PROGRAM   ChSptP72 ;
{$IFDEF VER70}{$IFDEF WINDOWS}   USES   WinCRT ;   {$ENDIF}{$ENDIF}
{$IFDEF VER80}   USES   WinCRT ;   {$ENDIF}      {--- Delphi1 }
{$IFDEF WIN32}   {$APPTYPE CONSOLE}   {$ENDIF}      {--- Delphi2,... }

{
!------------------------------------------------------------------------------
! Small toolbox
!------------------------------------------------------------------------------
}

{$IFDEF MSDOS}{$IFNDEF VER70}
TYPE
   PChar = ^Char ;
{$ENDIF}{$ENDIF}

{
!---------------
! G_MyStrings routines
!---------------
! G_MyStrings_Add
!---------------
}
VAR
   G_MyStrings : RECORD
      Count : Integer ;
      Items : ARRAY[0..99] of String[100];
   END;

{===== G_MyStrings_Add }

PROCEDURE   G_MyStrings_Add   ( {$IFDEF VER70}Const{$ENDIF} I_String : String );
BEGIN
   Inc ( G_MyStrings.Count );
   G_MyStrings.Items[G_MyStrings.Count-1] := I_String ;
END;

{
!------------------------------------------------------------------------------
! This program toolbox
!------------------------------------------------------------------------------
}
{
!---------------
! G_MyStrings routines
!---------------
! G_MyStrings_ChSplitPChar
!---------------
}
{===== G_MyStrings_ChSplitPChar }

PROCEDURE   G_MyStrings_ChSplitPChar   ( I_PChar : PChar
                                       ; I_ChSeparator : Char );
VAR
   L_FldBegin : PChar ;
   L_FldAEnd  : PChar ;
   L_i_String : String ;
   L_PLast : PChar ;
BEGIN
   G_MyStrings.Count := 0 ;

   L_FldBegin := I_PChar ;
   L_FldAEnd  := I_PChar ;

   {----- LOOP 1 , Search each field }
   WHILE L_FldAEnd^ <> #0 DO BEGIN

      {----- LOOP 2 , Search separator }
      WHILE (L_FldAEnd^ <> #0) and (L_FldAEnd^ <> I_ChSeparator)
      DO Inc ( Longint(L_FldAEnd) );

      {----- Add field }
      L_i_String[0] := Char( Longint(L_FldAEnd) - Longint(L_FldBegin) );
      Move ( L_FldBegin^ , L_i_String[1] , Length(L_i_String) );
      G_MyStrings_Add ( L_i_String );

      {----- If inside the string (separator found),... }
      IF L_FldAEnd^ <> #0
      THEN BEGIN
         {----- Prepare next search }
         Inc ( Longint(L_FldAEnd) );
         L_FldBegin := L_FldAEnd ;
      END;
   END;{while}

   {----- One more at the end... }
   IF I_PChar^ <> #0 THEN BEGIN
      Longint(L_PLast) := Longint(L_FldAEnd) - 1 ;
      IF L_PLast^ = I_ChSeparator THEN BEGIN
         G_MyStrings_Add ( '' );
      END;
   END;
END;


{===============}


FUNCTION   G_MyStrings_Join   ( I_Separator : String ) : String ;
VAR
   L_Result : String ;
   L_i : Integer ;
BEGIN
   L_Result := '' ;

   {----- LOOP , Concat items }
   FOR L_i := 0 TO G_MyStrings.Count -1 DO BEGIN
      IF L_i > 0 THEN L_Result := L_Result  +  I_Separator ;
      L_Result := L_Result  +  G_MyStrings.Items[L_i];
   END;{for}

   G_MyStrings_Join := L_Result ;
END;

{===== Test Speed variables }
LABEL
   G_TEST_SPEED ;
VAR
   G_SPEED_LoopMax  : Longint ;
   G_SPEED_String1  : String ;
   G_SPEED_i        : Longint ;
   G_SPEED_DummyStr : String ;

   GI_SPEED_TmpStr : String ;
   G_SPEED_ErrPos  : Integer ;

VAR
   G_MyString : String ;

   G_i : Integer ;

BEGIN
   G_MyStrings.Count := 0 ;



   IF ParamStr(1) = 'TestSpeed' THEN GOTO G_TEST_SPEED ;      {--- Test speed ?  }



   G_MyString := #0 ;
   G_MyStrings_ChSplitPChar ( @G_MyString[1] , ',' );
   FOR G_i := 0 TO G_MyStrings.Count -1 DO BEGIN
      IF G_i > 0 THEN Write (   ';'   );
      Write (   G_MyStrings.Items[G_i]   );
   END;{i}
   WriteLn (   '<== ( '  ,  G_MyStrings.Count  ,  '  fields )'   );


   G_MyString := ',' + #0 ;
   G_MyStrings_ChSplitPChar ( @G_MyString[1] , ',' );
   WriteLn (   G_MyStrings_Join(';')  ,  '<== ( '  ,  G_MyStrings.Count  ,  '  fields )'   );


   G_MyString := ',,' + #0 ;
   G_MyStrings_ChSplitPChar ( @G_MyString[1] , ',' );
   WriteLn (   G_MyStrings_Join(';')  ,  '<== ( '  ,  G_MyStrings.Count  ,  '  fields )'   );


   G_MyString := 'Red,Green,Blue' + #0 ;
   G_MyStrings_ChSplitPChar ( @G_MyString[1] , ',' );
   WriteLn (   G_MyStrings_Join(';')  ,  '<== ( '  ,  G_MyStrings.Count  ,  '  fields )'   );
   WriteLn ;


   {---------------}


   G_MyString := 'a' + #0 ;
   G_MyStrings_ChSplitPChar ( @G_MyString[1] , ',' );
   WriteLn (   G_MyStrings_Join(';')  ,  '<== ( '  ,  G_MyStrings.Count  ,  '  fields )'   );


   G_MyString := 'a,b' + #0 ;
   G_MyStrings_ChSplitPChar ( @G_MyString[1] , ',' );
   WriteLn (   G_MyStrings_Join(';')  ,  '<== ( '  ,  G_MyStrings.Count  ,  '  fields )'   );


   G_MyString := 'a,b,c' + #0 ;
   G_MyStrings_ChSplitPChar ( @G_MyString[1] , ',' );
   WriteLn (   G_MyStrings_Join(';')  ,  '<== ( '  ,  G_MyStrings.Count  ,  '  fields )'   );


   G_MyString := ',b,c' + #0 ;
   G_MyStrings_ChSplitPChar ( @G_MyString[1] , ',' );
   WriteLn (   G_MyStrings_Join(';')  ,  '<== ( '  ,  G_MyStrings.Count  ,  '  fields )'   );


   G_MyString := 'a,,c' + #0 ;
   G_MyStrings_ChSplitPChar ( @G_MyString[1] , ',' );
   WriteLn (   G_MyStrings_Join(';')  ,  '<== ( '  ,  G_MyStrings.Count  ,  '  fields )'   );


   G_MyString := 'a,b,' + #0 ;
   G_MyStrings_ChSplitPChar ( @G_MyString[1] , ',' );
   WriteLn (   G_MyStrings_Join(';')  ,  '<== ( '  ,  G_MyStrings.Count  ,  '  fields )'   );



   {***************  TEST SPEED  ***************}
  G_TEST_SPEED:

   {----- Get Parameter 2  ( optional ) : Loop max }
   G_SPEED_LoopMax := 10 ;      {--- Default value }
   GI_SPEED_TmpStr := ParamStr(2);
   IF GI_SPEED_TmpStr <> '' THEN BEGIN
      Val ( GI_SPEED_TmpStr , G_SPEED_LoopMax , G_SPEED_ErrPos );
      IF G_SPEED_ErrPos <> 0 THEN BEGIN
         WriteLn (   'ERROR: '  ,  'Number expected  ( Parameter 2 ).'   );
         HALT ( 1 );
      END;
   END;

   G_SPEED_String1 := 'Red,Green,Blue,Red,,..........,Green..........,Blue..........,,Red,Green,Blue,,,' + #0 ;
                      {12345678901234567890123456789012345678901234567890123456789012345678901234567890}

   {----- LOOP , Call a split }
   FOR G_SPEED_i := 1 TO G_SPEED_LoopMax DO BEGIN
      G_MyStrings_ChSplitPChar ( @G_SPEED_String1[1] , ',' );
   END;{i}
END.
