(******************************************************************************) (* TopSpeed compatible string library *) (* (C) 2009..2010 Steffen Solyga *) (******************************************************************************) IMPLEMENTATION MODULE Str; IMPORT Strings, NumConv; CONST baseMin = 2; baseMax = 16; VAR cnvStr: ARRAY [ 0 .. 15 ] OF CHAR; forceSign: BOOLEAN; PROCEDURE Caps( VAR s: ARRAY OF CHAR ); BEGIN Strings.CAPS( s ); END Caps; PROCEDURE Lows( VAR s: ARRAY OF CHAR ); VAR i: CARDINAL; c: CHAR; BEGIN FOR i := 0 TO HIGH( s ) DO c := s[ i ]; IF ( c >= 'A' ) & ( c <= 'Z' ) THEN s[ i ] := CHR( ORD(c) + ORD('a') - ORD('A') ); END; END; END Lows; PROCEDURE Compare( VAR s,t: ARRAY OF CHAR ): INTEGER; BEGIN RETURN Strings.compare( s, t ); END Compare; PROCEDURE Length( VAR s: ARRAY OF CHAR ): CARDINAL; BEGIN RETURN Strings.Length( s ); END Length; PROCEDURE Delete( VAR s: ARRAY OF CHAR; p, l: CARDINAL ); BEGIN Strings.Delete( s, p, l ); END Delete; PROCEDURE Copy( VAR d,s: ARRAY OF CHAR ); BEGIN Strings.Copy( s, 0, Length(s), d ); END Copy; PROCEDURE ChkBase( VAR b: CARDINAL ); BEGIN IF b < baseMin THEN b := baseMin END; IF b > baseMax THEN b := baseMax END; END ChkBase; PROCEDURE Reverse( VAR s: ARRAY OF CHAR; l,h: CARDINAL ); VAR c: CHAR; BEGIN WHILE l < h DO c := s[l]; s[l] := s[h]; s[h] := c; INC( l ); DEC( h ); END; END Reverse; PROCEDURE Card2Str( x: LONGCARD; VAR s: ARRAY OF CHAR; b: CARDINAL; VAR ok: BOOLEAN; pc: CHAR ); VAR i,i0: CARDINAL; BEGIN ok := TRUE; ChkBase( b ); IF pc = 0C THEN i0 := 0; ELSE s[ 0 ] := pc; i0 := 1; END; i := i0; REPEAT IF i > HIGH( s ) THEN ok := FALSE; RETURN END; s[ i ] := cnvStr[ x MOD b ]; INC( i ); x := x DIV b; UNTIL x <= 0; IF i <= HIGH( s ) THEN s[ i ] := 0C END; Reverse( s, i0, i-1 ); END Card2Str; PROCEDURE CardToStr( x: LONGCARD; VAR s: ARRAY OF CHAR; b: CARDINAL; VAR ok: BOOLEAN ); BEGIN Card2Str( x, s, b, ok, 0C ); END CardToStr; PROCEDURE IntToStr( x: LONGINT; VAR s: ARRAY OF CHAR; b: CARDINAL; VAR ok: BOOLEAN ); % norange VAR c: CHAR; v: LONGCARD; BEGIN (* code requires cast by value *) IF x < 0 THEN c := '-'; v := -x; (* MIN(LONGINT) support => no range check allowed here *) ELSIF forceSign THEN c := '+'; v := x; ELSE c := 0C; v := x; END; Card2Str( v, s, b, ok, c ); END IntToStr; PROCEDURE Str2Card( VAR s: ARRAY OF CHAR; b: CARDINAL; VAR ok: BOOLEAN ): LONGCARD; VAR i,i0: CARDINAL; x: LONGCARD; d: CARDINAL; BEGIN ok := TRUE; ChkBase( b ); i0 := 0; IF ( s[0] = '+' ) OR ( s[0] = '-' ) THEN i0 := 1 END; i := i0; x := 0; WHILE ( i <= HIGH(s) ) & ( s[i] # 0C ) DO CASE s[ i ] OF | '0'..'9': d := ORD( s[i] ) - ORD( '0' ); | 'A'..'F': d := ORD( s[i] ) - ORD( 'A' ) + 10; ELSE d := baseMax + 1; END; IF ( d >= b ) OR ( x > (MAX(LONGCARD)-d) DIV b ) THEN ok := FALSE; RETURN 0 END; x := x * b + LONGCARD( d ); INC( i ); END; IF i = i0 THEN ok := FALSE END; RETURN x; END Str2Card; PROCEDURE StrToCard( VAR s: ARRAY OF CHAR; b: CARDINAL; VAR ok: BOOLEAN ): LONGCARD; VAR x: LONGCARD; BEGIN x := Str2Card( s, b, ok ); IF s[ 0 ] = '-' THEN ok := FALSE; x := 0 END; RETURN x; END StrToCard; PROCEDURE StrToInt( VAR s: ARRAY OF CHAR; b: CARDINAL; VAR ok: BOOLEAN ): LONGINT; VAR x: LONGCARD; BEGIN x := Str2Card( s, b, ok ); (* code requires cast by value *) IF x <= MAX( LONGINT ) THEN IF s[ 0 ] = '-' THEN RETURN -LONGINT( x ); ELSE RETURN LONGINT( x ); END; ELSE (* MIN(LONGINT) support (unlike TS) *) IF ( x = LONGCARD( MAX(LONGINT) ) + 1 ) & ( s[ 0 ] = '-' ) THEN RETURN MIN( LONGINT ); ELSE ok := FALSE; RETURN 0; END; END; END StrToInt; BEGIN cnvStr := '0123456789ABCDEF'; forceSign := FALSE; END Str.