IMPLEMENTATION MODULE SplitV1;

IMPORT Strings;
FROM InOut IMPORT Write, WriteString, WriteCard, WriteLn;

VAR
  j : CARDINAL;
  
PROCEDURE Ltrim (VAR src : ARRAY OF CHAR; separator : CHAR  );

VAR
  longueur : CARDINAL;
  
  BEGIN
    REPEAT
      longueur := LENGTH(src);
      IF src[0] = separator THEN
      	(*PROCEDURE Delete (VAR stringVar: ARRAY OF CHAR; startIndex, numberToDelete:CARDINAL);*)
        (* Deletes at most numberToDelete characters from stringVar, starting at position startIndex.*)
        Strings.Delete(src,0,1);
      END;  
    UNTIL (src[0] # separator) OR (longueur = 0)
  END Ltrim;     
  
PROCEDURE Rtrim ( VAR src : ARRAY OF CHAR ; separator : CHAR );

VAR
  longueur : CARDINAL;
  
  BEGIN
    longueur := LENGTH(src);
    REPEAT
      longueur := LENGTH(src);
      IF src[longueur - 1] = separator THEN
      	(*PROCEDURE Delete (VAR stringVar: ARRAY OF CHAR; startIndex, numberToDelete:CARDINAL);*)
        (* Deletes at most numberToDelete characters from stringVar, starting at position startIndex.*)
        Strings.Delete(src,longueur - 1,1);
      END;  
      longueur := LENGTH(src);
    UNTIL (src[longueur - 1] # separator) OR (longueur =0 ) 
   END Rtrim;  
  
PROCEDURE removeDuplicate ( VAR src : ARRAY OF CHAR ; separator : CHAR );             

VAR
  longueur : CARDINAL;
  pos      : CARDINAL;
  
  BEGIN
    pos := 0;
    longueur := LENGTH(src);
    LOOP
      IF (longueur = 0 ) OR (pos = longueur ) THEN
        RETURN
      END;
      (*Write(src[pos]);Write(" ");*)
      IF src[pos] = separator THEN 
        pos := pos + 1;
        WHILE src[pos] = separator DO 
          Strings.Delete(src,pos,1);
        END; 
      ELSE 
        INC(pos) 
      END;  
      longueur := LENGTH(src);
    END; (* end loop*)
  END removeDuplicate;   
  
PROCEDURE SplitStr(s : ARRAY OF CHAR; separator : CHAR; VAR out : Structure) ;

(*
  There are several cases to take account for :
  - standard case : s begin with an element and end with an element
  - s begins with a separator and end with an element
  - s begins with a separator and ends with a separators
  - there are consecutive separators inside s
  - there are consecutive separators at the beginning
  - there are consecutive separators at the end
*)

VAR 
  i : CARDINAL;
  indice : CARDINAL;
  longueur : CARDINAL;
  resultat : ARRAY[0..255] OF CHAR;
  deja : BOOLEAN;
  c : CHAR;
  
  BEGIN
    indice := 0; 
    (* modes de fonctionnement *)
    (*  trimMode    : BOOLEAN;
        allTrimMode : BOOLEAN;
        noDupMode   : BOOLEAN;
        rtrim       : BOOLEAN;
        ltrim       : BOOLEAN;*)
    IF trimMode THEN
      Rtrim ( s, separator);
      Ltrim ( s, separator);
    END;
    
    IF ltrim THEN
      Ltrim ( s, separator);
    END;
    
    IF rtrim THEN
      Rtrim ( s, separator);
    END;    
    
    IF noDupMode THEN
      removeDuplicate ( s, separator);
    END;
    
    IF allTrimMode THEN
      Rtrim ( s, separator);
      Ltrim ( s, separator);
      removeDuplicate ( s, separator);
    END;  
    
    longueur := LENGTH(s);
    resultat := "";
    deja := FALSE;
    FOR i := 0 TO longueur -1 DO
      c := s[i]; 						(* the first character of the string s *)
      IF c # separator THEN 					(* the character belongs to an element *)
         Strings.Append(Strings.String1(c),resultat);
      ELSE
        out[indice].element := resultat;
        resultat := ""; 
        INC(indice);
      END;
      out[indice].element := resultat;
    END;
    FOR i := indice + 1 TO HIGH(out) DO 
      out[i].pos := MAX(CARDINAL);
    END;
  END SplitStr;

PROCEDURE InitStructure ( VAR out : Structure);

VAR 
  i : CARDINAL;
  
BEGIN 
  FOR i := 0 TO HIGH(out)   DO
    out[i].pos := i;
    out[i].element := "";
  END;
END InitStructure;

BEGIN 
  trimMode    := FALSE;
  allTrimMode := FALSE;
  noDupMode   := FALSE;
  ltrim       := FALSE;
  rtrim       := FALSE; 
END SplitV1. 
