StringField with support for whole string delimiters

Share your advanced PureBasic knowledge/code with the community.
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

StringField with support for whole string delimiters

Post by Mistrel »

PureBasic's current implementation only supports character delimiters. Here is an improved version which supports whole string delimiters.

Code: Select all

Procedure.s StringField_(StringToSearch.s, Index.i, Delimiter.s)
  Protected StartPos.i=0
  Protected EndPos.i=0
  
  ;/ To prevent an infinite loop
  If Index<1
    ProcedureReturn StringToSearch
  EndIf
  
  ;/ Parameters strings cannot be blank
  If StringToSearch="" Or Delimiter=""
    ProcedureReturn StringToSearch;
  EndIf
  
  ;/ Find the string index of previous to the next occurrence of the
  ;/ delimiter
  For i=1 To Index-1
    StartPos=FindString(StringToSearch,Delimiter,StartPos+1)
  Next i
  
  ;/ If the starting match is at the first character and the index is 1 then
  ;/ Return an empty string
  If Index=1 And StartPos=1
    ProcedureReturn ""
  EndIf
  
  ;/ Find the string index of the Next occurrence of the delimiter
  EndPos=FindString(StringToSearch,Delimiter,StartPos+1)
  
  ;/ If no start position was found (no search was made for (1 to 0) but an
  ;/ end position was found then set the start position to the first character
  If Not StartPos And EndPos
    StartPos=1
  EndIf
  
  ;/ If no End field is found then set it To the length of the search
  ;/ string. For fields other than the first And the last endPos is negated
  ;/ 1 To account For findString starting from 1 instead of 0.
  If Not EndPos
    EndPos=Len(StringToSearch)
  Else
    endPos-1
  EndIf
  
  ;/ If no fields are found then Return the original search string
  If Not StartPos And EndPos=Len(StringToSearch)
     ProcedureReturn StringToSearch
  EndIf
  
  ;/ If a field is found but the startPos is 0 then the string field index
  ;/ is beyond the final match. Return a blank string To identify that there
  ;/ are no more fields
  If StartPos=0
    ProcedureReturn ""
  EndIf
  
  If Index=1
    ProcedureReturn Mid(StringToSearch,1,EndPos)
  EndIf
  
  ProcedureReturn Mid(StringToSearch,StartPos+Len(Delimiter),EndPos-StartPos-Len(Delimiter)+1)
EndProcedure
User avatar
skywalk
Addict
Addict
Posts: 4221
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: StringField with support for whole string delimiters

Post by skywalk »

Cool, but why return the whole StringToSearch when Delimiter does not exist?
I prefer it to return "" or empty.

Code: Select all

Debug StringField_("1,;2,;3,;4,;5" , 0, " ,,")
Debug StringField_("1,;2,;3,;4,;5" , 10, " ,,")
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Re: StringField with support for whole string delimiters

Post by Mistrel »

A blank string is a valid result where two delimiters are adjacent. Returning the whole string is the only way to determine if no delimiter exists.

PureBasic's StringField() does the same when using index 1 but returns a blank string for indices greater than 1 which is inconsistent either way.

If you don't like the behavior you're more than welcome to change it for your own purposes. My implementation is guaranteed and and I rely upon this.
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Re: StringField with support for whole string delimiters

Post by GedB »

Mistrel,

If the delimiter isn't present, then StringField only returns the full string for an index of 1. For a higher index it returns a blank string.

This makes sense if you think of the String is a list of delimited items. If the list has only one item then there will be no delimiter.

The following code shows that the behaviour of 3 and 4 differ between StringField and StringField_ given the same parameters.

Code: Select all

Debug "1. Should be foo - "+StringField_("foo", 1,  "|")
Debug "2. Should be foo - "+StringField("foo", 1, "|")
Debug "3. Should be Blank - "+StringField_("foo", 2,  "|") ;Fails
Debug "4. Should be Blank - "+StringField("foo", 2, "|")
Debug "5. Should be bar - "+StringField_("foo|bar", 2 , "|")
Debug "6. Should be bar - "+StringField("foo|bar", 2 , "|")
Regards,


Ged
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Re: StringField with support for whole string delimiters

Post by Mistrel »

With my implementation it's possible to perform a loop where the end condition is where the result is equal to the input string. If the result is a blank string then it's not possible to evaluate this condition.

Returning a blank string doesn't make any sense because a blank string also suggests two adjacent delimiters.
If the delimiter isn't present, then StringField only returns the full string for an index of 1. For a higher index it returns a blank string.
My implementation fulfills my requirements. It was based upon and designed to improve the behavior of StringField not to duplicate it.
Post Reply