DIRECTORY RefText, Rope, UXStrings; UXStringsImpl: CEDAR MONITOR IMPORTS RefText, Rope EXPORTS UXStrings ~ BEGIN OPEN UXStrings; ToRope: PUBLIC PROC [from: CString, maxLength: INT ¬ LAST[INT]] RETURNS [r: Rope.ROPE] = TRUSTED { len, pos: INT ¬ 0; PerChar: PROC RETURNS [c: CHAR] = TRUSTED { c ¬ from­[pos]; pos ¬ pos+1; }; IF from=NIL THEN RETURN[NIL]; WHILE from­[len]#'\000 AND len < maxLength DO len ¬ len + 1 ENDLOOP; IF len = 0 THEN RETURN[NIL]; RETURN [Rope.FromProc[len, PerChar]]; }; CharSequence: TYPE ~ RECORD[ seq: PACKED SEQUENCE COMPUTED CARD OF CHAR ]; Create: PUBLIC PROC [from: REF] RETURNS [string: CString] = { WITH from SELECT FROM r: Rope.ROPE => { len: INT ¬ Rope.Length[r]; rtn: REF CharSequence ¬ NEW[CharSequence[len+1]]; TRUSTED { FOR i: INT IN [0..len) DO rtn[i] ¬ r.Fetch[i] ENDLOOP; rtn[len] ¬ '\000; }; string ¬ LOOPHOLE[rtn]; }; r: REF TEXT => { len: INT ¬ RefText.Length[r]; rtn: REF CharSequence ¬ NEW[CharSequence[len+1]]; TRUSTED { FOR i: INT IN [0..len) DO rtn[i] ¬ r[i] ENDLOOP; rtn[len] ¬ '\000; }; string ¬ LOOPHOLE[rtn]; }; ENDCASE => IF from=NIL THEN TRUSTED { rtn: REF CharSequence ¬ NEW[CharSequence[1]]; rtn[0] ¬ '\000; string ¬ LOOPHOLE[rtn]; } ELSE ERROR; --not implemented type }; CreateSpace: PUBLIC PROC [size: INT] RETURNS [string: CString] ~ { rtn: REF CharSequence ¬ NEW[CharSequence[size+1]]; string ¬ LOOPHOLE[rtn]; }; CopyRefToString: PUBLIC UNSAFE PROC [ref: REF, string: CString] ~ UNCHECKED { rtn: REF CharSequence ¬ LOOPHOLE[string]; WITH ref SELECT FROM r: Rope.ROPE => { len: INT ¬ Rope.Length[r]; TRUSTED { FOR i: INT IN [0..len) DO rtn[i] ¬ r.Fetch[i] ENDLOOP; rtn[len] ¬ '\000; }; }; r: REF TEXT => { len: INT ¬ RefText.Length[r]; TRUSTED { FOR i: INT IN [0..len) DO rtn[i] ¬ r[i] ENDLOOP; rtn[len] ¬ '\000; }; }; ENDCASE => IF ref=NIL THEN TRUSTED { rtn[0] ¬ '\000; } ELSE ERROR; --not implemented type }; ViewRefText: PUBLIC UNSAFE PROC [from: REF TEXT] RETURNS [string: CString] ~ { RETURN[ LOOPHOLE[LOOPHOLE[from, CARD]+UNITS[TEXT[0]]]] }; StringIndex: TYPE = [0..1]; StringMaxLength: ARRAY StringIndex OF INT = [100, 512]; NStringsToAllocate: ARRAY StringIndex OF NAT = [8, 2]; available: ARRAY StringIndex OF LIST OF CString ¬ ALL[NIL]; reserved: ARRAY StringIndex OF LIST OF CString ¬ ALL[NIL]; InterestingQuantity: TYPE = {obtainCalled, nCharsTooLarge, availEmpty}; Counts: ARRAY InterestingQuantity OF INT ¬ ALL[0]; Bump: INTERNAL PROC [q: InterestingQuantity] = INLINE { Counts[q] ¬ Counts[q] + 1 }; Error: PUBLIC ERROR [ec: ErrorCode] = CODE; CreateScratch: PUBLIC PROC [from: REF] RETURNS [string: CString] ~ { WITH from SELECT FROM r: Rope.ROPE => { len: INT ¬ Rope.Length[r]; rtn: POINTER TO CharSequence ¬ LOOPHOLE[ObtainScratch[len]]; TRUSTED { FOR i: INT IN [0..len) DO rtn[i] ¬ r.Fetch[i] ENDLOOP; rtn[len] ¬ '\000; }; string ¬ LOOPHOLE[rtn]; }; r: REF TEXT => { len: INT ¬ RefText.Length[r]; rtn: POINTER TO CharSequence ¬ LOOPHOLE[ObtainScratch[len]]; TRUSTED { FOR i: INT IN [0..len) DO rtn[i] ¬ r[i] ENDLOOP; rtn[len] ¬ '\000; }; string ¬ LOOPHOLE[rtn]; }; ENDCASE => IF from=NIL THEN TRUSTED { rtn: POINTER TO CharSequence ¬ LOOPHOLE[ObtainScratch[0]]; rtn[0] ¬ '\000; string ¬ LOOPHOLE[rtn]; } ELSE ERROR; --not implemented type }; ObtainScratch: PUBLIC ENTRY PROC [nChars: INT] RETURNS [CString] = TRUSTED { i: StringIndex ¬ 0; avail: LIST OF CString; Bump[obtainCalled]; FOR i IN [0 .. LAST[StringIndex]] DO IF nChars <= StringMaxLength[i] THEN EXIT; REPEAT FINISHED => { Bump[nCharsTooLarge]; RETURN [CreateSpace[nChars]]; }; ENDLOOP; IF (avail ¬ available[i].rest) = NIL THEN { r: LIST OF CString; Bump[availEmpty]; r ¬ reserved[i]; UNTIL r.rest.rest = NIL DO r ¬ r.rest ENDLOOP; avail ¬ r.rest; r.rest ¬ NIL; avail.first ¬ CreateSpace[StringMaxLength[i]] }; available[i].rest ¬ avail.rest; avail.rest ¬ reserved[i].rest; reserved[i].rest ¬ avail; IF avail.first[0] # '\000 THEN RETURN WITH ERROR Error[clientModifiedReleasedString]; RETURN [avail.first]; }; ReleaseScratch: PUBLIC ENTRY PROC [s: CString] = TRUSTED { i: StringIndex ¬ 0; r, l: LIST OF CString; IF s = NIL THEN RETURN; FOR i IN [0 .. LAST[StringIndex]] DO r ¬ reserved[i]; WHILE (l ¬ r.rest) # NIL DO IF l.first = s THEN { r.rest ¬ l.rest; l.rest ¬ available[i].rest; available[i].rest ¬ l; s[0] ¬ '\000; RETURN; }; r ¬ l; ENDLOOP; ENDLOOP; }; InitializeScratchPool: ENTRY PROC [] = { FOR i: StringIndex IN StringIndex DO reserved[i] ¬ CONS[NIL, NIL]; FOR j: NAT IN [0..NStringsToAllocate[i]] DO available[i] ¬ CONS[NIL, available[i]]; ENDLOOP; ENDLOOP; FOR i: StringIndex IN StringIndex DO l: LIST OF CString ¬ available[i].rest; WHILE l # NIL DO l.first ¬ CreateSpace[StringMaxLength[i]]; l ¬ l.rest; ENDLOOP; ENDLOOP; }; InitializeScratchPool[]; END.   UXStringsImpl.mesa Copyright Σ 1988, 1989, 1991 by Xerox Corporation. All rights reserved. Created by Christian Jacobi, March 31, 1988 12:19:45 pm PST Christian Jacobi, March 31, 1988 5:40:20 pm PST Carl Hauser, February 16, 1989 3:09:31 pm PST Chauser, April 26, 1990 4:26 pm PDT Willie-s, August 8, 1991 5:41 pm PDT Monitored global variables: too large for pool Give last element of reserved[i] to the collector, allocate a new one, and put it in avail. Move first element of available[i] to front of reserved[i]. construct a list of NStringsToAllocate[i]+1 nodes. allocate a string of length StringMaxLength[i] for each node but the first. CHauser February 16, 1989: reworked interface and impl to make returned values from Create and CreateSpace legitimate object pointers, eliminating the need for clients to hold onto another value to keep the string pointers valid. CHauser April 26, 1990: added scratch pool. Κ S–(cedarcode) style•NewlineDelimiter ™šœ™Icodešœ Οeœ=™HK™;K™/K™-K™#K™$—K˜šΟk ˜ Kšœ˜Kšœ˜Kšœ ˜ K˜—šΠbl œžœž˜Kšžœ˜Kšžœ ˜—šœž œ ˜K˜—šΟnœžœžœžœžœžœžœ žœžœ˜bKšœ žœ˜š  œžœžœžœžœ˜+Kšœ˜Kšœ˜—Kš žœžœžœžœžœ˜Kšžœžœžœžœ˜DKšžœ žœžœžœ˜Kšžœ˜%K˜—K˜šœžœžœ˜Kš œžœžœžœžœžœž˜*K˜K˜—š  œžœžœžœžœ˜=šžœžœž˜šœžœ˜Kšœžœ˜Kšœžœžœ˜1šžœ˜ Kš žœžœžœ žœžœ˜6K˜K˜—Kšœ žœ˜K˜—šœžœžœ˜Kšœžœ˜Kšœžœžœ˜1šžœ˜ Kš žœžœžœ žœžœ˜0K˜K˜—Kšœ žœ˜Kšœ˜—šžœ˜ šžœžœ˜ šžœžœ˜Kšœžœžœ˜-K˜Kšœ žœ˜Kšœ˜—KšžœžœΟc˜#———K˜K˜—š   œžœžœžœžœ˜BKšœžœžœ˜2Kšœ žœ˜K˜—K˜š  œžœžœžœžœž œ˜MKšœžœžœ ˜)šžœžœž˜šœžœ˜Kšœžœ˜šžœ˜ Kš žœžœžœ žœžœ˜6K˜K˜—K˜—šœžœžœ˜Kšœžœ˜šžœ˜ Kš žœžœžœ žœžœ˜0K˜K˜—Kšœ˜—šžœ˜ šžœžœ˜ šžœžœ˜K˜Kšœ˜—Kšžœžœ‘˜#———K˜K˜—š  œžœžœžœžœžœžœ˜NKš žœžœžœžœžœžœ˜6K˜—K˜K™Kšœ žœ ˜Kš œžœ žœžœ˜7Kšœžœ žœžœ ˜6Kš œ žœ žœžœžœ žœžœ˜;Kš œ žœ žœžœžœ žœžœ˜:K˜Kšœžœ.˜GKš œžœžœžœžœ˜2K˜Kš œžœžœžœ˜TK˜Kš œžœžœžœ˜+K˜š   œžœžœžœžœ˜Dšžœžœž˜šœžœ˜Kšœžœ˜Kšœžœžœžœ˜<šžœ˜ Kš žœžœžœ žœžœ˜6K˜K˜—Kšœ žœ˜K˜—šœžœžœ˜Kšœžœ˜Kšœžœžœžœ˜<šžœ˜ Kš žœžœžœ žœžœ˜0K˜K˜—Kšœ žœ˜Kšœ˜—šžœ˜ šžœžœ˜ šžœžœ˜Kšœžœžœžœ˜:K˜Kšœ žœ˜Kšœ˜—Kšžœžœ‘˜#———Kšœ˜K™—š  œžœžœžœ žœžœ žœ˜LKšœ˜Kšœžœžœ ˜K˜šžœžœžœž˜$Kšžœžœžœ˜*šžœžœ˜Kšœ™Kšœ˜Kšžœ˜Kšœ˜—Kšžœ˜—šžœžœžœ˜+Kšœ[™[Kšœžœžœ ˜K˜K˜Kšžœžœžœ žœ˜.Kšœžœ3˜Q—Kšœ;™;K˜K˜9Kš žœžœžœžœžœ%˜UKšžœ˜Kšœ˜K˜—š  œžœžœžœžœ˜:K˜Kšœžœžœ ˜Kšžœžœžœžœ˜šžœžœžœž˜$K˜šžœžœž˜šžœ žœ˜K˜K˜3K˜ Kšžœ˜Kšœ˜—K˜Kšžœ˜—Kšžœ˜—K˜K˜—š œž œ˜(šžœžœ ž˜$Kšœžœžœžœ˜Kšœ2™2šžœžœžœž˜+Kšœžœžœ˜'Kšžœ˜—Kšžœ˜—šžœžœ ž˜$KšœK™KKšœžœžœžœ˜'šžœžœž˜Kšœ*˜*K˜ Kšžœ˜—Kšžœ˜—K˜K˜—Kšœ˜Kšžœ˜K˜Kšœε™εK™+—…—†y