Page 1 of 1

Parse a string to ArgC/ArgV pair

Posted: Tue Jul 26, 2011 10:10 pm
by Mistrel
This only works with ascii strings.

h.ParseStringToArgV.pb

Code: Select all

Structure Priv_ParseStringToArgV_Char
  c.c[0]
EndStructure

Declare ParseStringToArgV(String.s, *ArgC.Integer, *ArgV.Integer)
Declare ParseStringToArgV_Free(ArgC, *ArgV)

EnableExplicit
XIncludeFile #PB_Compiler_File+"\..\"+"lib.ParseStringToArgV.pb"
DisableExplicit
lib.ParseStringToArgV.pb

Code: Select all

Procedure ParseStringToArgV(String.s, *ArgC.Integer, *ArgV.Integer)
  Protected *String
  Protected InQuotes=#False
  Protected ArgCount
  Protected Length
  Protected *CString.Priv_ParseStringToArgV_Char
  Protected Char.c
  Protected *Mem
  Protected *MemString
  Protected i
  
  NewList StringList.i()
  
  *String=@String.s
  
  If Not *String Or Not *ArgC Or Not *ArgV
    ProcedureReturn #False
  EndIf
  
  Length=Len(PeekS(*String))
  *CString=*String
  
  If Length<1
    ProcedureReturn #False
  EndIf
  
  For i=0 To Length-1
    Char.c=*CString\c[i]
    
    If InQuotes
      If Char.c=34
        InQuotes=#False
        *CString\c[i]=0
      EndIf
      
      Continue
    EndIf
    
    If (Char.c=32 Or Char.c=34 Or i=0) And Not InQuotes
      If Char.c=32 And *CString\c[i+1]=32
        *CString\c[i]=0
        Continue
      EndIf
      
      If Char.c=34 Or (Char.c=32 And *CString\c[i+1]=34)
        InQuotes=#True
        
        If Char.c=32 And *CString\c[i+1]=34
          i+1
        EndIf
      EndIf
      
      If Char.c=32 And Not InQuotes
        *CString\c[i]=0
      EndIf
      
      If Not i=0 Or Char.c=34
        i+1
      EndIf
      
      AddElement(StringList())
      StringList()=*String+i
      
      ArgCount+1
    EndIf
  Next i
  
  If ArgCount
    *Mem=AllocateMemory(SizeOf(Integer)*ArgCount)
    
    i=0
    ForEach StringList()
      *MemString=AllocateMemory(Len(PeekS(StringList()))+1)
      PokeS(*MemString,PeekS(StringList()))
      
      PokeI(*Mem+(i*SizeOf(Integer)),*MemString)
      i+1
    Next
  EndIf
  
  *ArgC\i=ArgCount
  *ArgV\i=*Mem
  
  ProcedureReturn #True
EndProcedure

Procedure ParseStringToArgV_Free(ArgC, *ArgV)
  Protected i
  
  If Not ArgC
    ProcedureReturn
  EndIf
  
  For i=0 To ArgC-1
    FreeMemory(PeekI(*ArgV+(i*SizeOf(Integer))))
  Next i
  
  FreeMemory(*ArgV)
EndProcedure
Example:

Code: Select all

;/ Example
String1.s="argstring     "+#DQUOTE$+"some whole string"+#DQUOTE$+"     a b c     d"
String2.s=#DQUOTE$+"some whole string"+#DQUOTE$+"      a b c     d"

ParseStringToArgV(String1.s,@ArgC,@ArgV)
For i=0 To ArgC-1
  Debug PeekS(PeekI(ArgV+(i*SizeOf(Integer))))
Next i
ParseStringToArgV_Free(ArgC,ArgV)
Debug ""

ParseStringToArgV(String2.s,@ArgC,@ArgV)
For i=0 To ArgC-1
  Debug PeekS(PeekI(ArgV+(i*SizeOf(Integer))))
Next i
ParseStringToArgV_Free(ArgC,ArgV)
Debug ""

Re: Parse a string to ArgC/ArgV pair

Posted: Fri Jul 29, 2011 11:45 pm
by idle
thanks could be useful