PSStringImpl.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Doug Wyatt, May 13, 1987 12:50:28 pm PDT
Basic String operations
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
]];
};
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
StringPutInterval:
PUBLIC
PROC [string: String, index:
INT, interval: String] ~ {
substring: String ~ StringGetInterval[string, index, StringLength[interval]];
***** use ByteBlt here? *****
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<char2 THEN less ELSE greater];
ENDLOOP;
IF length1=length2 THEN RETURN [equal]
ELSE RETURN [IF length1<length2 THEN less ELSE greater];
};
StringSearch:
PUBLIC
PROC [string, seek: String, anchor:
BOOL]
RETURNS [found:
BOOL ←
FALSE, index:
INT ← 0] ~ {
stringLength: INT ~ StringLength[string];
seekLength: INT ~ StringLength[seek];
UNTIL found
OR (stringLength-index)<seekLength
DO
FOR i:
INT
IN[0..seekLength)
DO
char1: CHAR ~ StringGet[string, index+i];
char2: CHAR ~ StringGet[seek, i];
IF char1#char2 THEN EXIT;
REPEAT FINISHED => 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];
};
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]]];
};
NameFromRope:
PROC [rope:
ROPE, executable:
BOOL ←
TRUE]
RETURNS [Name] ~ {
RETURN [[
val: [executable: executable, variant: name[]],
ref: Atom.MakeAtom[rope]
]];
};
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];
};