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; ROPE: TYPE ~ Rope.ROPE; 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]}; 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]}; 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] = {}; 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]}; 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; StringFromMesaString: PUBLIC PROC [s: MesaString] RETURNS [String] = {RETURN[s]}; AppendToMesaString: PUBLIC PROC [to: MesaString, from: String] = {[] _ RefText.Append[to, from]}; ValidAsMesaString: PUBLIC PROC [s: String] RETURNS [BOOLEAN] = {RETURN[TRUE]}; 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; StringBoundsFault: PUBLIC SIGNAL [old: String, increaseBy: CARDINAL] RETURNS [new: String] = CODE; END. -- of NSString 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. `NSStringImpl.mesa Copyright c 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 -- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- TYPES : -- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- 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 : -- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- BASIC STRING OPERATIONS: Delete the specified SubString from its parent string STRING ALLOCATION/DEALLOCATION CHARACTER ACCESS ROUTINES FOR DEALING WITH TRUNCATED STRINGS ROUTINES FOR INTERCONVERTING Strings AND Numbers ROUTINES FOR INTERCONVERTING NSStrings AND MesaStrings 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. COURIER DESCRIPTIONS 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 : -- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- The string has an invalid format. Overflow: ERROR; ++ this is defined as a SIGNAL in String.mesa, but isn't raised by anyone. 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.) Κ »˜codešœ™Kšœ Οmœ1™-Y