NSStringImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Revised by Kiser: 22-Sep-82 21:00:23
Overview: Definitions for the international network string format.
Tim Diebert: November 24, 1986 2:50:11 pm PST
Ruseli Binsol: November 18, 1986 4:27:01 pm PST
DIRECTORY
Ascii USING [Lower, Upper],
Convert USING [AppendCard, AppendInt, Error, IntFromRope],
NSString,
RefText USING [Append, AppendChar, Compare, Length, TrustTextAsRope],
Rope USING [Compare, Index, ROPE, Substr];
NSStringImpl:
CEDAR
PROGRAM
IMPORTS Ascii, Convert, RefText, Rope
EXPORTS NSString = BEGIN OPEN NSString;
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
TYPES :
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
ROPE: TYPE ~ Rope.ROPE;
Character: TYPE = MACHINE DEPENDENT RECORD [chset, code: Basics.BYTE];
Characters: TYPE = REF CharactersRef;
CharactersRef: TYPE = RECORD [data: SEQUENCE length: CARDINAL OF Character];
String: TYPE = REF TEXT;
StringRep: TYPE ~ TEXT;
Handle to network string.
SubString: TYPE = REF SubStringDescriptor;
SubStringDescriptor: TYPE = RECORD [base: String, offset, length: CARDINAL];
offset and length are in logical characters, not bytes.
Relation: TYPE = {less, equal, greater};
MesaString: TYPE = REF TEXT;
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
CONSTANTS :
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
nullString: String = NIL;
Null value of String.
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
OPERATIONS :
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
LogicalLength: PUBLIC PROC [s: String] RETURNS [CARDINAL] = {RETURN [RefText.Length[s]]};
WordsForString: PUBLIC PROC [bytes: CARDINAL] RETURNS [CARDINAL] = {RETURN[bytes/2+1]};
AppendCharacter:
PUBLIC
PROC [to: String, from: Character]
RETURNS [String] = {
RETURN[RefText.AppendChar[to, LOOPHOLE[from.code]]]};
AppendString:
PUBLIC
PROC [to: String, from: String]
RETURNS [String] = {
RETURN[RefText.Append[to, from]]};
AppendSubString:
PUBLIC
PROC [to: String, from: SubString]
RETURNS [String] =
BEGIN
wk: String ← to;
IF from = NIL OR from.length = 0 OR from.base = NIL OR from.base.length = 0 THEN RETURN [to];
IF from.offset > from.base.length THEN RETURN[to];
IF wk.length + from.length > wk.maxLength
THEN
wk ← NEW[TEXT[wk.length + from.length]];
FOR i:
CARDINAL
IN [from.offset .. from.offset + from.length)
DO
wk[i] ← from.base[from.offset + i];
ENDLOOP;
RETURN[wk];
END;
CompareStrings:
PUBLIC
PROC [s1, s2: String, ignoreCase:
BOOLEAN ←
TRUE]
RETURNS [Relation] = {
RETURN[RefText.Compare[s1, s2, ~ignoreCase]]};
CompareSubStrings:
PUBLIC
PROC [s1, s2: SubString, ignoreCase:
BOOLEAN ←
TRUE]
RETURNS [Relation] =
BEGIN
r1: ROPE = Rope.Substr[RefText.TrustTextAsRope[s1.base], s1.offset, s1.length];
r2: ROPE = Rope.Substr[RefText.TrustTextAsRope[s2.base], s2.offset, s2.length];
RETURN[Rope.Compare[r1, r2, ~ignoreCase]];
END;
DeleteSubString:
PUBLIC
PROC [s: SubString]
RETURNS [String] = {
RETURN[s.base]};
Delete the specified SubString from its parent string
EqualCharacter:
PUBLIC
PROC [c: Character, s: String, index:
CARDINAL]
RETURNS [
BOOLEAN] = {
RETURN[s[index] = LOOPHOLE[c.code]]};
ScanForCharacter:
PUBLIC
PROC [c: Character, s: String, start:
CARDINAL ← 0]
RETURNS [
CARDINAL] =
BEGIN
t: REF TEXT ← NEW[TEXT[1]];
i: INT; ardc: CARDINAL;
t[0] ← LOOPHOLE[c.code];
i ← Rope.Index[RefText.TrustTextAsRope[s], start, RefText.TrustTextAsRope[t]];
IF i < 0
THEN ardc ← LAST[CARDINAL]
ELSE {IF i > LAST[CARDINAL] THEN ardc ← LAST[CARDINAL] ELSE ardc ← i};
RETURN[ardc];
END;
UpperCase: PUBLIC PROC [c: Character] RETURNS [Character] =
{RETURN[[0, LOOPHOLE[Ascii.Upper[LOOPHOLE[c.code]]]]]};
LowerCase: PUBLIC PROC [c: Character] RETURNS [Character] =
{RETURN[[0, LOOPHOLE[Ascii.Lower[LOOPHOLE[c.code]]]]]};
WellFormed: PUBLIC PROC [s: String] RETURNS [BOOLEAN] = {RETURN[s#NIL]};
STRING ALLOCATION/DEALLOCATION
MakeString: PUBLIC PROC [bytes: CARDINAL] RETURNS [String] = {RETURN[NEW[TEXT[bytes]]]};
FreeString: PUBLIC PROC [s: String] = {};
CopyString:
PUBLIC
PROC [s: String]
RETURNS [String] =
BEGIN
ns: REF TEXT;
IF s = NIL THEN RETURN [NIL];
ns ← NEW[TEXT[s.length]];
FOR i: CARDINAL IN [0 .. s.length) DO ns[i] ← s[i]; ENDLOOP;
RETURN[ns];
END;
ExpandString:
PUBLIC
PROCEDURE [s: String]
RETURNS [Characters] =
BEGIN
c: Characters;
IF s = NIL THEN RETURN [NIL];
c ← NEW[CharactersRep[s.length]];
FOR i:
CARDINAL
IN [0 .. s.length)
DO
c.data[i] ← [0, LOOPHOLE[s[i]]];
ENDLOOP;
RETURN[c];
END;
FreeCharacters: PUBLIC PROCEDURE [c: Characters] = {};
ROUTINES FOR DEALING WITH TRUNCATED STRINGS
TruncateString:
PUBLIC
PROC [s: String, bytes:
CARDINAL]
RETURNS [String] =
BEGIN
s.length ← MIN[s.length, bytes];
RETURN[s];
END;
CompareStringsAndStems: PUBLIC PROC [s1, s2: String, ignoreCase: BOOLEAN ← TRUE]
RETURNS [relation: Relation, equalStems: BOOLEAN] = {RETURN[equal, TRUE]};
CompareStringsTruncated: PUBLIC PROC [s1, s2: String, trunc1, trunc2: BOOLEAN ← FALSE, ignoreCase: BOOLEAN ← TRUE] RETURNS [Relation] = {RETURN[equal]};
ROUTINES FOR INTERCONVERTING Strings AND Numbers
AppendDecimal:
PUBLIC
PROC [s: String, n:
INTEGER]
RETURNS [String] =
BEGIN
IF s= NIL THEN s ← NEW[TEXT[100]];
RETURN[Convert.AppendInt[s, n]];
END;
AppendOctal:
PUBLIC
PROC [s: String, n:
UNSPECIFIED]
RETURNS [String] =
BEGIN
IF s= NIL THEN s ← NEW[TEXT[100]];
RETURN[Convert.AppendCard[s, n, 8]];
END;
AppendLongNumber:
PUBLIC
PROC [s: String, n:
LONG
UNSPECIFIED, radix:
CARDINAL ← 10]
RETURNS [String] =
BEGIN
IF s= NIL THEN s ← NEW[TEXT[100]];
RETURN[Convert.AppendCard[s, n, LOOPHOLE[radix]]];
END;
AppendLongDecimal:
PUBLIC
PROC [s: String, n:
LONG
INTEGER]
RETURNS [String] =
BEGIN
IF s= NIL THEN s ← NEW[TEXT[100]];
RETURN[Convert.AppendCard[s, n]];
END;
AppendNumber:
PUBLIC
PROC [s: String, n:
UNSPECIFIED, radix:
CARDINAL ← 10]
RETURNS [String] =
BEGIN
IF s= NIL THEN s ← NEW[TEXT[100]];
RETURN[Convert.AppendCard[s, n, LOOPHOLE[radix]]];
END;
StringToNumber:
PUBLIC
PROC [s: String, radix:
CARDINAL ← 10]
RETURNS [
UNSPECIFIED] =
BEGIN
ENABLE Convert.Error => ERROR InvalidNumber;
i: INTEGER;
IF s=NIL THEN RETURN[0];
i ← Convert.IntFromRope[RefText.TrustTextAsRope[s], LOOPHOLE[radix]];
RETURN[LOOPHOLE[i]];
END;
ROUTINES FOR INTERCONVERTING NSStrings AND MesaStrings
StringFromMesaString:
PUBLIC
PROC [s: MesaString]
RETURNS [String] = {
RETURN[s]};
Return a String which contains the same bytes as are in the Mesa string. Note that the data is not copied; the validity of the String depends on the continued existence of the Mesa string.
AppendToMesaString: PUBLIC PROC [to: MesaString, from: String] = {[] ← RefText.Append[to, from]};
ValidAsMesaString: PUBLIC PROC [s: String] RETURNS [BOOLEAN] = {RETURN[TRUE]};
DescribeString: Courier.Description;
Caveat: When deserializing a String, the maxlength may not be set to the correct value. It is only guaranteed to have a value >= the length of the string. The maxlength field may, of course, be set by the client after deserialization to match the length field.
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
SIGNALS AND ERRORS :
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
InvalidNumber: PUBLIC ERROR = CODE; -- raised by StringToDecimal if the characters do not represent a decimal number. This is a SIGNAL is String.mesa
InvalidString:
PUBLIC
ERROR =
CODE;
The string has an invalid format.
Overflow: ERROR; ++ this is defined as a SIGNAL in String.mesa, but isn't raised by anyone.
StringBoundsFault:
PUBLIC
SIGNAL [old: String, increaseBy:
CARDINAL]
RETURNS [new: String] =
CODE;
The string is too small by increaseBy bytes; if desired, continue with a new one, after copying into it all old characters which were in the old string BEFORE the start of the operation raising StringBoundsFault. (See note before AppendCharacter.)
LOG ( date - person - action )
February 26, 1981 - Kabcenell - Creation.
- - - -
FILING 5.0 - - - -
1-Mar-82 14:07:59 - Hamilton - Add SubString and StringToDecimal stuff.
19-Apr-82 15:59:12 - Hamilton - Add remaining ops that String.mesa has and NSString.mesa doesn't.
August 2, 1982 - Hanzel - Define Characters, ExpandString, and Freecharacters in support of character-level access.
August 5, 1982 - Kiser - Added increaseBy to StringBoundsFault.
5-Aug-82 19:18:52 - Kabcenell - Changed order of arguments in ExpandString and FreeCharacters; made Characters a LONG DESCRIPTOR.
2-Sep-82 15:50:35 - Kiser - Made internal structure of Character visible; added DescribeString.
22-Sep-82 21:00:195 - Kiser - Changed NOTE comment: StringBoundsFault always leaves a well-formed string.