DEFINITION MODULE DMStrings;
(*******************************************************************
Module DMStrings ('Dialog Machine' DM_V3.0)
Copyright (c) 1987-2006 by Andreas Fischlin and ETH Zurich.
Purpose Provides string handling as required
by the 'Dialog Machine'.
Remarks This module belongs to the 'Dialog Machine'.
Programming
o Design
Andreas Fischlin 17/03/1987
o Implementation
Andreas Fischlin 17/03/1987
ETH Zurich
Systems Ecology
CHN E 35.1
Universitaetstrasse 16
8092 Zurich
SWITZERLAND
URLs:
<mailto:RAMSES@env.ethz.ch>
<http://www.sysecol.ethz.ch>
<http://www.sysecol.ethz.ch/SimSoftware/RAMSES>
Last revision of definition: 30/01/1992 AF
*******************************************************************)
TYPE
String;
StringRelation = ( smaller, equal, greater );
VAR
notAllocatedStr: String;
(*
Read only variable which may be used for variables of type
String to denote that no memory has yet been allocated for
that string, i.e. NewString has never been called. It is a
good programming practice to assign this value to all string
variables during the initialization phase.
*)
ResourceStringsDone: BOOLEAN;
(*
Read only variable returning the success of the routines
LoadString, GetRString, and StoreString
*)
(**********************************)
(*##### Ordinary Strings #####*)
(**********************************)
(*----------------------*)
(*===== Basics =====*)
(*----------------------*)
PROCEDURE Length(VAR string: ARRAY OF CHAR): INTEGER;
(*VAR parameter only for speed-up reasons*)
(*-----------------------------------*)
(*===== Assignment, Copying =====*)
(*-----------------------------------*)
PROCEDURE AssignString(s: ARRAY OF CHAR; VAR d: ARRAY OF CHAR);
(*assign source string s to destination string d*)
PROCEDURE CopyString (VAR from: ARRAY OF CHAR; i1,nrChs: INTEGER;
VAR to: ARRAY OF CHAR; VAR i2: INTEGER);
(*
Efficient, versatile, general purpose string copying routine.
Copies the content of string 'from' beginning with position i1
into string 'to' by starting the writing process at position i2
in the destination string 'to'. String 'from' is passed as var
parameter only for speed-up reasons, otherwise it is left
untouched. In case that nrChs<0 then the copy process stops as
soon 0C is encountered in string 'from' or if 'from's upper
boundary is encountered. In case that nrChs>=0 the copy process
stops after nrChs characters have been copied or if 'from's
upper boundary is encountered. Whenever possible the
destination string 'to' is always properly terminated with a 0C
character (even if no copying should have taken place). After
the call i2 points to the char in string 'to' which contains
the termination char 0C (or beyond its range if the string 'to'
is too short to hold 0C). Hence this routine may be easily used
for string assignments or consecutive concatenations.
*)
PROCEDURE CopyStr( from: String; VAR to: String );
(*
Given 'from' does point to an existing string, this procedure
creates a new storage for this string in memory, copies the content
of the string 'from' to this new location, and returns the pointer
'to'. Otherwise the returned pointer 'to' points to an empty
string ('to' differs always from 'notAllocatedStr').
*)
PROCEDURE Copy(from: ARRAY OF CHAR; startIndex, nrOfChars: INTEGER;
VAR to: ARRAY OF CHAR);
(*
Copies nrOfChars characters from string from starting at index
position in from of value startIndex into the string to (Mainly
provided for IBM PC DM compatibility. See also CopyString).
*)
(*-------------------------*)
(*===== Appending =====*)
(*-------------------------*)
PROCEDURE Append(VAR dest: ARRAY OF CHAR; s: ARRAY OF CHAR);
(*append string s at end of destination string dest*)
PROCEDURE AppendCh(VAR dest: ARRAY OF CHAR; ch: CHAR);
(*append character ch at end of destination string dest*)
(*-----------------------------*)
(*===== Concatenation =====*)
(*-----------------------------*)
PROCEDURE Concatenate(first,second: ARRAY OF CHAR; VAR result: ARRAY OF CHAR);
(*Concatenates the strings first and second to the string result *)
(*-------------------------------------*)
(*===== Extracting Substrings =====*)
(*-------------------------------------*)
PROCEDURE ExtractSubString(VAR curPosInSrcS: INTEGER;
VAR srcS,destS: ARRAY OF CHAR;
delimiter: CHAR);
(*
Extracts string destS from source string srcS starting with char
position curPosInSrcS and stopping with extraction upon
encountering the delimiter. After a successful extraction
curPosInSrcS points on the first character after the delimiter
found. If no more strings can be extracted desS becomes the nul
string and curPosInSrcS returns the value atend (=MAX(INTEGER)).
A typical usage would be to extract in a sequence the sub
strings delimited by "|" from a source string srcS like
"Yes|No|Cancel". If no empty string elements are expected in
srcS, the termination condition of the extracting loop is
destS[0] = 0C. E.g. with the following code fragment:
i := 0; ExtractSubString(i,srcS,destS,"|");
WHILE destS[0]<>0C DO
Process(destS);
ExtractSubString(i,srcS,destS,"|");
END(*WHILE*);
However, if empty elements may be present it is better to test
for curPosInSrcS = atend. E.g. with the following code:
i := 0;
REPEAT
ExtractSubString(i,srcS,destS,"|");
Process(destS);
UNTIL i=atend;
*)
(*******************************************)
(*##### Dynamic String Management #####*)
(*******************************************)
(*-----------------------------*)
(*===== Instantiation =====*)
(*-----------------------------*)
(*strings are dynamically managed, i.e. stored in heap*)
PROCEDURE AllocateStr(VAR strRef: String; s: ARRAY OF CHAR);
(*
Allocate memory and store string s, a reference is returned
pointing to the string which is NIL if no more memory is
available.
*)
PROCEDURE NewString(VAR(*speed-up*) s: ARRAY OF CHAR): String;
(* same functionality as AllocateStr *)
PROCEDURE DeallocateStr(VAR strRef: String);
(*
Dispose of memory which has been allocated for string
storing.
*)
(*--------------------------*)
(*===== Assignment =====*)
(*--------------------------*)
PROCEDURE SetStr (VAR strRef: String; s: ARRAY OF CHAR);
(*
Overwrite string pointed at by strRef with new value s.
IMPORTANT NOTE: Since the previously allocated memory could
be insufficient in case that s is longer than what was held
by strRef, the value of strRef may change when calling
SetStr.
*)
PROCEDURE PutString(VAR strRef: String; VAR s: ARRAY OF CHAR);
(*-------------------------*)
(*===== Retrieval =====*)
(*-------------------------*)
PROCEDURE GetStr(strRef: String; VAR s: ARRAY OF CHAR);
(*retrieve string s pointed at by strRef*)
PROCEDURE StrLength(strRef: String): INTEGER;
PROCEDURE StrLevel(strRef: String): CARDINAL;
(*
Returns the level of the sub-program on which the string
strRef has been created. If the string does not exist
DMSystem.startUpLevel-1, i.e. 0 is returned.
*)
(*-------------------------*)
(*===== Appending =====*)
(*-------------------------*)
PROCEDURE AppendStr(VAR destStrRef: String; s: ARRAY OF CHAR);
(*append source string s at end of destination string destStrRef*)
PROCEDURE AppendChr(VAR destStrRef: String; ch: CHAR);
(*append character ch at end of destination string destStrRef*)
(**********************************)
(*##### String Relations #####*)
(**********************************)
PROCEDURE CompareStrings( s1,s2: ARRAY OF CHAR): StringRelation;
PROCEDURE CompVarStrings( VAR a, b: ARRAY OF CHAR): StringRelation;
PROCEDURE CompStr( VAR a: ARRAY OF CHAR; bS: String): StringRelation;
(*
All three procedures do basically the same, but differ in
respect to their parameters; e.g. CompVarStrings has VAR
parameters only to increase performance. The standard function
ORD(CHAR) is used to determine the relation and the comparison is
made case sensitive.
*)
(**********************************)
(*##### Substring Search #####*)
(**********************************)
PROCEDURE FindInString (VAR theString: ARRAY OF CHAR; searchStr: ARRAY OF CHAR;
VAR firstCh,lastCh: INTEGER): BOOLEAN;
(*
Finds in string theString (var paramater only for speed-up
reasons) the string searchStr. In case that firstCh=lastCh the
searching starts at this position else it starts by 1 position
after lastCh. After a successful search FindInString returns
TRUE and the values of firstCh and lastCh point to the begin
respectively the end position of the found substring within
theString. If the searchStr is empty or firstCh resp. lastCh
input values are such that the search process would start
outside of the boundaries of theString, FALSE is returned and
the values of firstCh and lastCh are left unmodified. If the
searchStr could not be found FALSE is returned and the values
of firstCh and lastCh are negative.
*)
(**********************************************)
(*##### Storing Strings in Resources #####*)
(**********************************************)
(* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
The following routines serve to store permamently on disk
media the values of strings in so-called resources. This serves
the need to save values from one use of an application to the
next usage at a later time.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = *)
PROCEDURE LoadString(fileName: ARRAY OF CHAR; stringID: INTEGER;
VAR string: ARRAY OF CHAR);
(*
LoadString retrieves a so-called predefined string from the
resource fork of the file "fileName". It may have been
stored there by means of procedure StoreString (see below).
LoadString may be used to read strings, or default values as
a Macintosh resource of type 'STR ' from permanent disk
storage. Hence, it becomes possible to modify such texts by
means of a resource editor (e.g.ResEdit) without having to
recompile the program.
The file specified by fileName is searched according to the
following default search strategy: First the file is
searched according to the pathes specified in the
User.Profile. Then the currently running application's
resource fork is searched, finally the System file. If
during this process neither a file with name fileName, nor
the running application, nor the System file could be found
which have a resource fork containing a resource of type 'STR
' with an IDÊ=ÊstringID, then the string returned is the
empty string (string[0] = 0C, ResourceStringsDone = FALSE).
HINT: When you generate a stand alone application
(With the MacMETH Linker Link using option /A), you should
copy all resources into your application (e.g. with the
program ResEdit). In this case the resources will be found
regardless of the fileName you have specified. However, once
you've finished your development, it is recommended to call
in your final program version LoadString with an empty
fileName or to call GetRString. This speeds-up the access to
the resources considerably.
*)
PROCEDURE GetRString(stringID: INTEGER; VAR str: ARRAY OF CHAR);
(*
Fast Access to String resources, which must reside in the
application's resource fork only. Otherwise same as LoadString.
*)
PROCEDURE StoreString(fileName: ARRAY OF CHAR;
VAR stringID: INTEGER;
string: ARRAY OF CHAR);
(*
This procedure offers a simple method to save parameters and
other values together with the program on the disk, which may
be read and reused when the program is executed the next
time. Write any string into the resource fork of the file
specified by filename.
Note the following behavior of StoreString: If a file with
name fileName exists, which has a resource fork containing a
string resource with the same stringID, then the latter's
value will be completely overwritten with the passed value in
parameter string. In case there couldn«t be found any string
resource with this stringID, but the file exists AND contains
a resource fork (regardless of its content), then StoreString
creates a new resource string of type 'STR ' and ID stringID.
The file with name fileName is searched according to the
following default search strategy: First the file is searched
according to the pathes specified in the User.Profile. If there
can't be found a file with this name AND with an already
existing resource fork, the resource will be stored in the
currently running application's resource fork, e.g. the MacMETH
resp. the RAMSES shell. Hence, it is unlikely that StoreString
fails completely, but often resources end up elsewhere than the
programer expects, which may lead to confusing and surprising
results.
NOTE: DMFiles.Lookup creates just a data fork only. To
create a resource fork for a file newly created by means of
DMFiles, use ResEdit or DMOpSys.CopyResourceFork.
*)
PROCEDURE SetRStringName (fileName: ARRAY OF CHAR; stringID: INTEGER;
name: ARRAY OF CHAR);
PROCEDURE GetRStringName (fileName: ARRAY OF CHAR; stringID: INTEGER;
VAR name: ARRAY OF CHAR);
(*
Strings stored as resources may have a name associated with
them (string with up to 255 characters). The above two
routines allow to set or get such a name. This allows for
easier identification of the resource if the utility ResEdit
or any other resource editor should be used to edit the
resource.
*)
END DMStrings.