DIRECTORY PS, Atom USING [MakeAtom], Rope USING [Fetch, Size]; PSStringImpl: CEDAR PROGRAM IMPORTS PS, Atom, Rope ~ BEGIN OPEN PS; StringCreate: PUBLIC PROC [size: INT] RETURNS [String] ~ { IF size<0 THEN ERROR Error[rangecheck]; IF size IN StringIndex THEN { ref: StringRef ~ NEW[TEXT[size]]; FOR i: StringIndex IN[0..ref.maxLength) DO ref[i] _ VAL[0] ENDLOOP; RETURN[[ val: [executable: FALSE, variant: string[access: unlimited, start: 0, length: size]], ref: ref ]]; } ELSE ERROR Error[limitcheck]; }; StringAccess: PUBLIC PROC [string: String] RETURNS [Access] ~ { RETURN [string.val.access]; }; StringLength: PUBLIC PROC [string: String] RETURNS [INT] ~ { RETURN [string.val.length]; }; StringGet: PUBLIC PROC [string: String, index: INT] RETURNS [CHAR] ~ { IF index NOT IN [0..string.val.length) THEN ERROR Error[rangecheck]; RETURN [string.ref[string.val.start+index]]; }; StringPut: PUBLIC PROC [string: String, index: INT, x: CHAR] ~ { IF index NOT IN[0..string.val.length) THEN ERROR Error[rangecheck]; string.ref[string.val.start+index] _ x; }; StringGetInterval: PUBLIC PROC [string: String, index, count: INT] RETURNS [String] ~ { IF index NOT IN [0..string.val.length] THEN ERROR Error[rangecheck]; IF count NOT IN [0..(string.val.length-index)] THEN ERROR Error[rangecheck]; RETURN[[ val: [executable: string.val.executable, variant: string[ access: string.val.access, start: string.val.start+index, length: count]], ref: string.ref ]]; }; StringPutInterval: PUBLIC PROC [string: String, index: INT, interval: String] ~ { substring: String ~ StringGetInterval[string, index, StringLength[interval]]; FOR i: INT IN[0..StringLength[substring]) DO StringPut[substring, i, StringGet[interval, i]]; ENDLOOP; }; StringCopy: PUBLIC PROC [string1, string2: String] RETURNS [String] ~ { substring2: String ~ StringGetInterval[string2, 0, StringLength[string1]]; StringPutInterval[substring2, 0, string1]; RETURN [substring2]; }; StringForAll: PUBLIC PROC [string: String, action: PROC [CHAR]] ~ { FOR index: INT IN [0..StringLength[string]) DO action[StringGet[string, index]]; ENDLOOP; }; StringEq: PUBLIC PROC [string1: String, string2: String] RETURNS [BOOL] ~ { IF StringLength[string1]#StringLength[string2] THEN RETURN [FALSE]; RETURN [StringCompare[string1, string2]=equal]; }; StringCompare: PUBLIC PROC [string1, string2: String] RETURNS [Comparison] ~ { length1: INT ~ StringLength[string1]; length2: INT ~ StringLength[string2]; FOR index: INT IN[0..MIN[length1, length2]) DO char1: CHAR ~ StringGet[string1, index]; char2: CHAR ~ StringGet[string2, index]; IF char1=char2 THEN NULL ELSE RETURN [IF char1 found _ TRUE; ENDLOOP; IF anchor THEN EXIT ELSE index _ index+1; ENDLOOP; }; StringFromRope: PUBLIC PROC [rope: ROPE, executable: BOOL] RETURNS [String] ~ { length: INT ~ Rope.Size[rope]; string: String ~ StringCreate[length]; FOR i: INT IN [0..length) DO StringPut[string, i, Rope.Fetch[rope, i]]; ENDLOOP; RETURN [string]; }; NameFromRope: PROC [rope: ROPE, executable: BOOL _ TRUE] RETURNS [Name] ~ { RETURN [[ val: [executable: executable, variant: name[]], ref: Atom.MakeAtom[rope] ]]; }; END. tPSStringImpl.mesa Copyright Σ 1986, 1987 by Xerox Corporation. All rights reserved. Doug Wyatt, May 13, 1987 12:50:28 pm PDT PostScript implementation: string, and name operations. Basic String operations MesaStringGet: PUBLIC PROC [string: String, index: INT] RETURNS [CHAR] ~ { IF index NOT IN [0..string.length) THEN ERROR Error[rangecheck]; RETURN [string.pointer[string.offset+index]]; }; MesaStringPut: PUBLIC PROC [string: String, index: INT, x: CHAR] ~ { IF index NOT IN[0..string.length) THEN ERROR Error[rangecheck]; string.pointer[string.offset+index] _ x; }; MesaStringGetInterval: PUBLIC PROC [string: String, index, count: INT] RETURNS [String] ~ { IF index NOT IN [0..string.length] THEN ERROR Error[rangecheck]; IF count NOT IN [0..(string.length-index)] THEN ERROR Error[rangecheck]; { byteOffset: StringLength ~ string.offset+index; RETURN[[ executable: string.executable, variant: string[ access: string.access, offset: byteOffset MOD bytesPerWord, length: count, pointer: string.pointer+byteOffset/bytesPerWord ] ]]; }; }; Other String operations ***** use ByteBlt here? ***** Name operations AtomFromString: PROC [string: String] RETURNS [atom: ATOM] ~ { scratch: REF TEXT ~ RefText.ObtainScratch[string.length]; text: REF TEXT _ scratch; text _ RefText.Append[to: text, from: string.base, start: string.start, len: string.length]; atom _ Atom.MakeAtomFromRefText[text]; RefText.ReleaseScratch[scratch]; }; NameFromString: PROC [string: String, executable: BOOL _ TRUE] RETURNS [Name] ~ { RETURN [[executable: executable, atom: AtomFromString[string]]]; }; NameToString: PROC [name: Name, string: String] RETURNS [String] ~ { rope: Rope.ROPE ~ Atom.GetPName[name.atom]; count: INT ~ Rope.Size[rope]; substring: String ~ StringGetInterval[string, 0, count]; FOR i: INT IN[0..count) DO substring.base[substring.start+i] _ Rope.Fetch[rope, i]; ENDLOOP; RETURN [substring]; }; ΚΈ˜codešœ™KšœB™BK™(—K˜K™7K™šΟk ˜ Kšœ˜Kšœœ ˜Kšœœ˜—K˜KšΟn œœ˜Kšœœ ˜Kšœœœœ˜head™š ž œœœœœ ˜:Kšœœœ˜'šœœ œ˜Kšœœœ˜!Kš œœœ œœ˜Cšœ˜Kšœœ?˜VKšœ˜Kšœ˜—K˜—Kšœœ˜K˜K˜—šž œœœœ ˜?Kšœ˜K˜K˜—š ž œœœœœ˜Kšœ œœ(™9Kšœœœ ™Kšœ\™\Kšœ&™&K™ K™K™—š žœœœœœ ™QKšœ:™@K™K™—š ž œœœœœœ ˜Kšœ˜ Kšœ/˜/Kšœ˜Kšœ˜—K˜K˜—šž œœœ ™DKšœ œ™+Kšœœ™Kšœ8™8šœœœ ™Kšœ8™8Kšœ™—Kšœ ™K™K™——J˜Jšœ˜—…—^Š