DECLARE SUB MyStringsGChSplitString (StringI AS STRING, ChSeparatorI AS STRING)
DECLARE FUNCTION MyStringsGJoin$ (SeparatorI AS STRING)
DECLARE SUB MyStringsGREDIMPRESERVE (NewUBoundI AS INTEGER)
DECLARE FUNCTION MyStringsGUBOUND% ()

   '----- MyStringsGChSplitString_TEST
   REDIM SHARED MyStringsG$(0)
   DIM iG


   MyStringsGChSplitString "", ","
   FOR iG = 0 TO UBOUND(MyStringsG$)
      IF iG > 0 THEN PRINT ";";
      PRINT MyStringsG$(iG);
   NEXT
   PRINT "<== ("; UBOUND(MyStringsG$); " fields )"

   MyStringsGChSplitString ",", ","
   PRINT MyStringsGJoin$(";"); "<== ("; MyStringsGUBOUND% + 1; " fields )"

   MyStringsGChSplitString ",,", ","
   PRINT MyStringsGJoin$(";"); "<== ("; MyStringsGUBOUND% + 1; " fields )"


   MyStringsGChSplitString "Red,Green,Blue", ","
   PRINT MyStringsGJoin$(";"); "<== ("; MyStringsGUBOUND% + 1; " fields )"
   PRINT


   '---------------


   MyStringsGChSplitString "a", ","
   PRINT MyStringsGJoin$(";"); "<== ("; MyStringsGUBOUND% + 1; " fields )"


   MyStringsGChSplitString "a,b", ","
   PRINT MyStringsGJoin$(";"); "<== ("; MyStringsGUBOUND% + 1; " fields )"


   MyStringsGChSplitString "a,b,c", ","
   PRINT MyStringsGJoin$(";"); "<== ("; MyStringsGUBOUND% + 1; " fields )"


   MyStringsGChSplitString ",b,c", ","
   PRINT MyStringsGJoin$(";"); "<== ("; MyStringsGUBOUND% + 1; " fields )"


   MyStringsGChSplitString "a,,c", ","
   PRINT MyStringsGJoin$(";"); "<== ("; MyStringsGUBOUND% + 1; " fields )"


   MyStringsGChSplitString "a,b,", ","
   PRINT MyStringsGJoin$(";"); "<== ("; MyStringsGUBOUND% + 1; " fields )"

'
'------------------------------------------------------------------------------
' This program toolbox
'------------------------------------------------------------------------------
'
'
'---------------
' MyStringsG$ (Array of String) routines
'---------------
' MyStringsGChSplitString
'---------------
'
'===== MyStringsGChSplitString
'
SUB MyStringsGChSplitString (StringI AS STRING, ChSeparatorI AS STRING)
   DIM FldCountL AS INTEGER

   DIM LenL AS INTEGER
   DIM FldBeginL AS INTEGER
   DIM FldAEndL AS INTEGER
   DIM FldLenL AS INTEGER

   REDIM MyStringsG$(0)
   FldCountL = 0

   LenL = LEN(StringI)
   FldBeginL = 1
   FldAEndL = 1
   FldLenL = 0

   '----- LOOP 1 , Search each field
   DO WHILE LenL <> 0

      '----- LOOP 2 , Search separator
      WHILE (LenL <> 0) AND (MID$(StringI, FldAEndL, 1) <> ChSeparatorI)
         LenL = LenL - 1
         FldAEndL = FldAEndL + 1
         FldLenL = FldLenL + 1
      WEND

      '----- If inside the string (separator found),...
      IF LenL <> 0 THEN
         '----- Add field
         FldCountL = FldCountL + 1
         MyStringsGREDIMPRESERVE (FldCountL - 1)
         MyStringsG$(FldCountL - 1) = MID$(StringI, FldBeginL, FldLenL)

         '----- Prepare next search
         LenL = LenL - 1
         FldAEndL = FldAEndL + 1
         FldBeginL = FldAEndL
         FldLenL = 0
      END IF
   LOOP

   '----- One more at the end...
   IF StringI <> "" THEN
      FldCountL = FldCountL + 1
      MyStringsGREDIMPRESERVE (FldCountL - 1)
      MyStringsG$(FldCountL - 1) = MID$(StringI, FldBeginL, FldLenL)
   END IF
END SUB

'
'------------------------------------------------------------------------------
' Small toolbox
'------------------------------------------------------------------------------
'
'
'---------------
' MyStringsG$ (Array of String) routines
'---------------
' MyStringsGJoin$
' MyStringsGREDIMPRESERVE
' MyStringsGUBOUND%
'---------------
'
'===== MyStringsGJoin$
'
FUNCTION MyStringsGJoin$ (SeparatorI AS STRING)
   DIM ResultL AS STRING
   DIM iL AS INTEGER

   ResultL = ""

   '----- LOOP , Concat items
   FOR iL = 0 TO UBOUND(MyStringsG$)
      IF iL > 0 THEN ResultL = ResultL + SeparatorI
      ResultL = ResultL + MyStringsG$(iL)
   NEXT

   MyStringsGJoin$ = ResultL
END FUNCTION

'
'===== MyStringsGREDIMPRESERVE
'
SUB MyStringsGREDIMPRESERVE (NewUBoundI AS INTEGER)
   REDIM SAVEArrayL$(0)
   DIM iL AS INTEGER

   IF NewUBoundI = -1 THEN
      REDIM MyStringsG$(0)
      MyStringsG$(0) = ""
      EXIT SUB
   END IF

   '----- Save current array values
   IF NewUBoundI < UBOUND(MyStringsG$) THEN
      REDIM SAVEArrayL$(NewUBoundI)
   ELSE
      REDIM SAVEArrayL$(UBOUND(MyStringsG$))
   END IF
   FOR iL = 0 TO UBOUND(SAVEArrayL$)
      SAVEArrayL$(iL) = MyStringsG$(iL)
   NEXT

   REDIM MyStringsG$(NewUBoundI)

   '----- Restore previously saved values
   FOR iL = 0 TO UBOUND(SAVEArrayL$)
      MyStringsG$(iL) = SAVEArrayL$(iL)
   NEXT
END SUB

'
'===== MyStringsGUBOUND%
'
FUNCTION MyStringsGUBOUND%
   IF UBOUND(MyStringsG$) = 0 THEN
      IF MyStringsG$(0) = "" THEN
         MyStringsGUBOUND% = -1
         EXIT FUNCTION
      END IF
   END IF

   MyStringsGUBOUND% = UBOUND(MyStringsG$)
END FUNCTION

