Chars

This module provides common character oriented tests.

InRange
Check to see if a character, c, is in an inclusive range from a lower to upper character.
IsUpper
Check to see if a character is upper case
IsLower
Check to see if a character is lower case
IsAlpha
Check to see if a character is alphabetic, i.e. in the range of “a” to “z” or “A” to “Z”.
IsDigit
Check to see if a character is a digit, i.e. in range of “0” to “9”
IsAlphaNum
Check to see if a character is alpha or a digit
IsSpace
Check to see if a character is a space, tab, carriage return or line feed
AppendChar
Append a single char to the end of an ARRAY OF CHAR adjusting the terminating null character and return TRUE on success or FALSE otherwise.
AppendChars
Append an ARRAY OF CHAR to another the destination ARRAY OF CHAR.
Equal
Compares two ARRAY OF CHAR and returns TRUE if they match, FALSE otherwise
Clear
Sets all cells in an ARRAY OF CHAR to 0X.
TrimSpace
Trim the leading and trailing space characters from an ARRAY OF CHAR
TrimLeftSpace
Trim the leading space characters from an ARRAY OF CHAR
TrimRightSpace
Trim the trailing space characters from an ARRAY OF CHAR
StartsWith
Checks to see if a prefix ARRAY OF CHAR matches a target ARRAY OF CHAR return TRUE if found, FALSE otherwise
EndsWith
Checks to see if a suffix ARRAY OF CHAR matches a target ARRAY OF CHAR return TRUE if found, FALSE otherwise
TrimPrefix
Trim a prefix ARRAY OF CHAR from a target ARRAY OF CHAR
TrimSuffix
Trim a suffix ARRAY OF CHAR from a target ARRAY OF CHAR

Source code for Chars.Mod

MODULE Chars;

IMPORT Strings;

CONST
    MAXSTR* = 1024; (* or whatever *)
    (* byte constants *)
    LF* = 10;
    CR* = 13;
    (* Character constants *)
    ENDSTR* = 0X;
    NEWLINE* = 10X;
    TAB* = 9X;
    SPACE* = " ";
    DASH* = "-";
    CARET* = "^";
    TILDE* = "~";
    QUOTE* = CHR(34);

(* InRange -- given a character to check and an inclusive range of
characters in the ASCII character set. Compare the ordinal values
for inclusively. Return TRUE if in range FALSE otherwise. *)
PROCEDURE InRange* (c, lower, upper : CHAR) : BOOLEAN;
VAR inrange : BOOLEAN;
BEGIN
  IF (ORD(c) >= ORD(lower)) & (ORD(c) <= ORD(upper)) THEN
    inrange := TRUE;
  ELSE
    inrange := FALSE;
  END;
  RETURN inrange
END InRange;

(* IsUpper return true if the character is an upper case letter *)
PROCEDURE IsUpper*(c : CHAR) : BOOLEAN;
VAR isupper : BOOLEAN;
BEGIN
    IF InRange(c, "A", "Z") THEN
        isupper := TRUE;
    ELSE
        isupper := FALSE;
    END
    RETURN isupper
END IsUpper;


(* IsLower return true if the character is a lower case letter *)
PROCEDURE IsLower*(c : CHAR) : BOOLEAN;
VAR islower : BOOLEAN;
BEGIN
    IF InRange(c, "a", "a") THEN
        islower := TRUE;
    ELSE
        islower := FALSE;
    END
    RETURN islower
END IsLower;

(* IsDigit return true if the character in the range of "0" to "9" *)
PROCEDURE IsDigit*(c : CHAR) : BOOLEAN;
VAR isdigit : BOOLEAN;
BEGIN
    IF InRange(c, "0", "9") THEN
        isdigit := TRUE;
    ELSE
        isdigit := FALSE;
    END;
    RETURN isdigit
END IsDigit;

(* IsAlpha return true is character is either upper or lower case letter *)
PROCEDURE IsAlpha*(c : CHAR) : BOOLEAN;
VAR isalpha : BOOLEAN;
BEGIN
    IF IsUpper(c) OR IsLower(c) THEN
        isalpha := TRUE;
    ELSE
        isalpha := FALSE;
    END;
    RETURN isalpha
END IsAlpha;

(* IsAlphaNum return true is IsAlpha or IsDigit *)
PROCEDURE IsAlphaNum* (c : CHAR) : BOOLEAN;
VAR isalphanum : BOOLEAN;
BEGIN
    IF IsAlpha(c) OR IsDigit(c) THEN
        isalphanum := TRUE;
    ELSE
        isalphanum := FALSE;
    END;
    RETURN isalphanum
END IsAlphaNum;

(* IsSpace returns TRUE if the char is a space, tab, carriage return or line feed *)
PROCEDURE IsSpace*(c : CHAR) : BOOLEAN;
VAR isSpace : BOOLEAN;
BEGIN
    isSpace := FALSE;
    IF (c = SPACE) OR (c = TAB) OR (ORD(c) = CR) OR (ORD(c) = LF) THEN
        isSpace := TRUE;
    END;
    RETURN isSpace
END IsSpace;

(* AppendChar - this copies the char and appends it to
   the destination. Returns FALSE if append fails. *)
PROCEDURE AppendChar*(c : CHAR; VAR dest : ARRAY OF CHAR) : BOOLEAN;
VAR res : BOOLEAN; l : INTEGER;
BEGIN
  l := Strings.Length(dest);
  (* NOTE: we need to account for a trailing 0X to end
     the string. *)
  IF l < (LEN(dest) - 1) THEN
    dest[l] := c;
    dest[l + 1] := 0X;
    res := TRUE;
  ELSE
    res := FALSE;
  END;
  RETURN res
END AppendChar;

(* AppendChars - copy the contents of src ARRAY OF CHAR to end of
   dest ARRAY OF CHAR *)
PROCEDURE AppendChars*(src : ARRAY OF CHAR; VAR dest : ARRAY OF CHAR);
VAR i, j : INTEGER;
BEGIN
  i := 0;
  WHILE (i < LEN(dest)) & (dest[i] # 0X) DO
    i := i + 1;
  END;
  j := 0;
  WHILE (i < LEN(dest)) & (j < Strings.Length(src)) DO
    dest[i] := src[j];
    i := i + 1;
    j := j + 1;
  END;
  WHILE i < LEN(dest) DO
    dest[i] := 0X;
    i := i + 1;
  END;
END AppendChars;

(* Equal - compares two ARRAY OF CHAR and returns TRUE
if the characters match up to the end of string, FALSE otherwise. *)
PROCEDURE Equal*(a : ARRAY OF CHAR; b : ARRAY OF CHAR) : BOOLEAN;
VAR isSame : BOOLEAN; i : INTEGER;
BEGIN
  isSame := (Strings.Length(a) = Strings.Length(b));
  i := 0;
  WHILE isSame & (i < Strings.Length(a)) DO
    IF a[i] # b[i] THEN
      isSame := FALSE;
    END;
    i := i + 1;
  END;
  RETURN isSame
END Equal;


(* StartsWith - check to see of a prefix starts an ARRAY OF CHAR *)
PROCEDURE StartsWith*(prefix : ARRAY OF CHAR; VAR src : ARRAY OF CHAR) : BOOLEAN;
VAR startsWith : BOOLEAN; i: INTEGER;
BEGIN
    startsWith := FALSE;
    IF Strings.Length(prefix) <= Strings.Length(src) THEN
        startsWith := TRUE;
        i := 0;
        WHILE (i < Strings.Length(prefix)) & startsWith DO
            IF prefix[i] # src[i] THEN
                startsWith := FALSE;
            END;
            i := i + 1;
        END;
    END;    
    RETURN startsWith
END StartsWith;

(* EndsWith - check to see of a prefix starts an ARRAY OF CHAR *)
PROCEDURE EndsWith*(suffix : ARRAY OF CHAR; VAR src : ARRAY OF CHAR) : BOOLEAN;
VAR endsWith : BOOLEAN; i, j : INTEGER;
BEGIN
    endsWith := FALSE;
    IF Strings.Length(suffix) <= Strings.Length(src) THEN
        endsWith := TRUE;
        i := 0;
        j := Strings.Length(src) - Strings.Length(suffix);
        WHILE (i < Strings.Length(suffix)) & endsWith DO
            IF suffix[i] # src[j] THEN
                endsWith := FALSE;
            END;
            i := i + 1;
            j := j + 1;
        END;
    END;
    RETURN endsWith
END EndsWith;


(* Clear - resets all cells of an ARRAY OF CHAR to 0X *)
PROCEDURE Clear*(VAR a : ARRAY OF CHAR);
VAR i : INTEGER;
BEGIN
  FOR i := 0 TO (LEN(a) - 1) DO
    a[i] := 0X;
  END;
END Clear;

(* Shift returns the first character of an ARRAY OF CHAR and shifts the
remaining elements left appending an extra 0X if necessary *)
PROCEDURE Shift*(VAR src : ARRAY OF CHAR) : CHAR;
VAR i, last : INTEGER; c : CHAR;
BEGIN
    i := 0;
    c := src[i];
    Strings.Delete(src, 0, 1);
    last := Strings.Length(src) - 1;
    FOR i := last TO (LEN(src) - 1) DO
        src[i] := 0X;
    END;
    RETURN c
END Shift;

(* Pop returns the last non-OX element of an ARRAY OF CHAR replacing
   it with an OX *)
PROCEDURE Pop*(VAR src : ARRAY OF CHAR) : CHAR;
VAR i, last : INTEGER; c : CHAR;
BEGIN
    (* Move to the last non-0X cell *)
    i := 0;
    last := LEN(src);
    WHILE (i < last) & (src[i] # 0X) DO
       i := i + 1;
    END;
    IF i > 0 THEN
        i := i - 1;
    ELSE
        i := 0;
    END;
    c := src[i];
    WHILE (i < last) DO
        src[i] := 0X;
        i := i + 1;
    END;
    RETURN c
END Pop;

(* TrimLeftSpace - remove leading spaces from an ARRAY OF CHAR *)
PROCEDURE TrimLeftSpace*(VAR src : ARRAY OF CHAR);
VAR i : INTEGER;
BEGIN
    (* find the first non-space or end of the string *)
    i := 0;
    WHILE (i < LEN(src)) & IsSpace(src[i]) DO
        i := i + 1;
    END;
    (* Trims the beginning of the string *)
    IF i > 0 THEN
        Strings.Delete(src, 0, i);
    END;
END TrimLeftSpace;

(* TrimRightSpace - remove the trailing spaces from an ARRAY OF CHAR *)
PROCEDURE TrimRightSpace*(VAR src : ARRAY OF CHAR);
VAR i, l : INTEGER; 
BEGIN
    (* Find the first 0X, end of string *)
    l := Strings.Length(src);
    i := l - 1;
    (* Find the start of the trailing space sequence *)
    WHILE (i > 0) & IsSpace(src[i]) DO
        i := i - 1;
    END;
    (* Delete the trailing spaces *)
    Strings.Delete(src, i + 1, l - i);
END TrimRightSpace;

(* TrimSpace - remove leading and trailing space CHARS from an ARRAY OF CHAR *)
PROCEDURE TrimSpace*(VAR src : ARRAY OF CHAR);
BEGIN
    TrimLeftSpace(src);
    TrimRightSpace(src);    
END TrimSpace;    
    

(* TrimPrefix - remove a prefix ARRAY OF CHAR from a target ARRAY OF CHAR *)
PROCEDURE TrimPrefix*(prefix : ARRAY OF CHAR; VAR src : ARRAY OF CHAR);
VAR l : INTEGER;
BEGIN
    IF StartsWith(prefix, src) THEN
         l := Strings.Length(prefix);
         Strings.Delete(src, 0, l);
    END;
END TrimPrefix;

(* TrimSuffix - remove a suffix ARRAY OF CHAR from a target ARRAY OF CHAR *)
PROCEDURE TrimSuffix*(suffix : ARRAY OF CHAR; VAR src : ARRAY OF CHAR);
VAR i, l : INTEGER;
BEGIN
    IF EndsWith(suffix, src) THEN
        l := Strings.Length(src) - 1;
        FOR i := ((l - Strings.Length(suffix)) + 1) TO l DO
            src[i] := 0X;
        END;
    END;
END TrimSuffix;


END Chars.