With integrated search - sort and other functions.
It is extreme fast
You can easily test this.
Load and convert (automatically) a photo as sample with the new BaseU_BF function or the other data functions.
The normal versions uses StringField() PB, the HighSpeed versions uses StringFields_BF.
Converting a large photo with the normal versions takes one or more minutes,
with the HighSpeed versions only a fraction of a second.
viewtopic.php?f=12&t=77374
viewtopic.php?f=12&t=77248
viewtopic.php?f=12&t=77295
The BF function reads in all fields up to the given index.
The fields are already stored in an internal list.
This list then contains every field found.
Empty fields can be skipped automatically when the function is called.
Each field contained in the list can then be retrieved with a function call.
The list can be sorted as desired and also searched automatically.
The function StringFields_BF(string$, ..) can also be changed in seconds,
so that a pointer to a string can be passed StringFields_BF(*string, ..)
Have fun with it
Code: Select all
DeclareModule StringFields_BF
EnableExplicit
; Main function - Call firstly
; mode = 0 - Add a virtual separator at the first and start the search there
; 1 - Start the search with the first separator found
; 2 - Add a virtual separator at the end and include it in the search
; 3 - Add a virtual separator at the first and the end and include both in the search
Declare StringFields_BF(string$, ; String to parse - For speed up you can replace with *string
separator$, ; Separator
mode=1, ; Mode
ignore_empty_fields=1, ; Ignore empty fields
start_index.q=1, ; Set the start index
end_index.q=-1) ; Set the end index / -1 = full string size
Declare.s GetStringFields_BF(field) ; Get a selected StringField
Declare GetAmountStringFields_BF() ; Get the StringFields amount
Declare GetEmptyStringFields_BF() ; Get the empty StringFields amount
Declare CountSeparators_BF(string$, separator$) ; Count the separators in a string
Declare FreeAllStringFields_BF() ; Free the actual cached StringField list
Declare SortStringFields_BF(flags.a=0, ; Flags - (optional) - #PB_Sort_Ascending, #PB_Sort_Descending, #PB_Sort_NoCase
start_field=-1, ; Start field for sort - Ignore with -1
end_field=-1) ; End field for sort - Ignore with -1
; Find a string in a StringField
; This function give back the Stringfield number or 0
Declare FindStringFields_BF(find_string$, ; Search string
start_position=1, ; Startposition inside a StringField
flag.a=#PB_String_CaseSensitive, ; Flag - #PB_String_CaseSensitive (preset), #PB_String_NoCase
start_field=-1, ; Ignore with -1
end_field=-1) ; Ignore with -1
EndDeclareModule
Module StringFields_BF
; By Saki - Unicode - This code is free for using and enhancing
Global NewList index(), NewList indexes.s(), empty_fields.q
Procedure StringFields_BF(string$, separator$, mode=1, ignore_empty_fields=1, start_index.q=1, end_index.q=-1)
Select mode
Case 0 : Protected add_first=1 : Case 2 : Protected add_last=1 : Case 3 : add_first=1 : add_last=1
EndSelect
Protected skip_first : If start_index<1 : start_index=1 : EndIf : empty_fields.q=0
Protected i, ii, iii, iiii, pos_1, pos_2, length_result, comp, count_index, amount_indexes
Protected len_separator=StringByteLength(separator$), skip_last, *string=@string$
Protected *separator=@separator$, *pointer.word, byte_pos_last, result$ : If end_index=-1 : end_index=1e18 : EndIf
If start_index>end_index : start_index=end_index+1 : EndIf : If Not PeekW(*string) : ProcedureReturn 0 : EndIf
ClearList(index()) : AddElement(index()) : ClearList(indexes()) : AddElement(indexes())
If comp=CompareMemory(*string, *separator, len_separator) : end_index+1 : count_index+1 : skip_first=1 : EndIf
If add_first
If skip_first And start_index : start_index-2 : end_index-1 : EndIf
Else
If skip_first And start_index : start_index-1 : EndIf
EndIf
i=-2
Repeat
i+2 : comp=CompareMemory(*string+i, *separator, len_separator)
If comp
iii=i : count_index+1 : ii+1 : i+len_separator-2 : amount_indexes+1 : AddElement(index()) : index()=i+2
EndIf
*pointer=*string+i+len_separator
Until count_index>end_index Or Not *pointer\w
iiii=i : byte_pos_last=iii+len_separator
If comp=CompareMemory(*string+i-len_separator-1, *separator, len_separator) : skip_last=1 : EndIf
If end_index>count_index : end_index=count_index : EndIf : amount_indexes=ii : i=skip_first
If start_index>amount_indexes : start_index=amount_indexes-1 : EndIf : i+start_index+skip_first+skip_last
If skip_first : i-1 : EndIf : If skip_last : i-1 : EndIf
If amount_indexes
Repeat
If ListSize(index())>i : SelectElement(index(), i) : pos_1=index() : EndIf
If ListSize(index())>i+1 : SelectElement(index(), i+1) : pos_2=index() : EndIf
length_result=(pos_2-pos_1-len_separator)>>1
If pos_2-pos_1>0
If length_result>0
result$=PeekS(*string+pos_1, length_result) : AddElement(indexes()) : indexes()=result$
Else
empty_fields+1
If ignore_empty_fields : result$=#Null$ : Else : result$="" : AddElement(indexes()) : EndIf
EndIf
EndIf
i+1
Until i>end_index Or i=amount_indexes
If add_last And skip_last
result$=PeekS(*string+byte_pos_last, (iiii-byte_pos_last+len_separator)>>1)
AddElement(indexes()) : indexes()=result$
EndIf
EndIf
ProcedureReturn 1
EndProcedure
Procedure.s GetStringFields_BF(field)
If field <1 : ProcedureReturn "" : EndIf : SelectElement(indexes(), field)
If field<ListSize(indexes()) : ProcedureReturn indexes() : EndIf
EndProcedure
Procedure GetAmountStringFields_BF() : ProcedureReturn ListSize(indexes())-1 : EndProcedure
Procedure GetEmptyStringFields_BF() : ProcedureReturn empty_fields : EndProcedure
Procedure CountSeparators_BF(string$, separator$) : ProcedureReturn CountString(string$, separator$) : EndProcedure
Procedure FreeAllStringFields_BF()
ClearList(index()) : AddElement(index()) : ClearList(indexes()) : AddElement(indexes()) : ProcedureReturn 1
EndProcedure
Procedure SortStringFields_BF(flags.a=0, start_field=-1, end_field=-1)
If start_field>0 And end_field>1 And end_field<=ListSize(indexes())
SortList(indexes(), flags, start_field, end_field-1) : ProcedureReturn 2
Else
SortList(indexes(), flags) : ProcedureReturn 1
EndIf
EndProcedure
Procedure FindStringFields_BF(find_string$,
start_position=1,
flag.a=#PB_String_CaseSensitive,
start_field=-1,
end_field=-1)
Protected i, result$
If end_field>ListSize(indexes()) : end_field=ListSize(indexes()) : EndIf
If start_field>0 And end_field>1 : end_field-1
For i=start_field To end_field
SelectElement(indexes(), i) : result$=indexes()
If FindString(result$, find_string$, start_position, flag) : ProcedureReturn i : EndIf
Next
EndIf
ProcedureReturn 0
EndProcedure
EndModule
UseModule StringFields_BF
; #################### Demo part #######################
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
Define separator$=" "
Define i, index, result$
Define string$=" Hello i am a splitted String, i am StringFields_BF "
Define multiplier=1 ; Enlarge the Teststring - 15 is about 1.7mb (20=54mb) - Deactivate the debugger for large values
If multiplier>1 : For i=1 To multiplier : string$+string$ : Next i : EndIf
Define len_string=Len(string$)
; mode = 0 - Add a virtual separator at the first and start the search there
; 1 - Start the search with the first separator found
; 2 - Add a virtual separator at the end and include it in the search
; 3 - Add a virtual separator at the first and the end and include both in the search
Define mode=1
Define start_index=1
Define end_index=-1 ; Index up to which is searched (Last separator) -1 = full string size, all
Debug "Mode : "+mode
Debug "End Index : "+end_index
Define ignore_empty_fields=1
Define time=ElapsedMilliseconds()
Define parsing_time=ElapsedMilliseconds()
Define amount_fields=StringFields_BF(string$, separator$, mode, ignore_empty_fields, start_index, end_index)
Define parsing_time=ElapsedMilliseconds()-parsing_time
Debug "String parsing time : "+parsing_time
Debug "String length : "+Len(string$)
Debug "StringFields found : "+GetAmountStringFields_BF()
Debug "Empty StringFields found : "+GetEmptyStringFields_BF()
Debug "=============================="
Debug "I only display the first nine StringFields here"
Debug "=============================="
; Sort the StringFields
; Define flags.a=#PB_Sort_Ascending|#PB_Sort_NoCase
; Define start_field=1
; Define end_field=9
; flags (optional) - #PB_Sort_Ascending, #PB_Sort_Descending, #PB_Sort_NoCase
; SortStringFields_BF(flags.a, start_field, end_field)
For index=1 To 9
result$=GetStringFields_BF(index)
Debug result$
Next
; Find a string in a StringField
Define find_string$="am"
Define start_position=1
Define flags.a=#PB_Sort_Ascending ; #PB_Sort_NoCase
Define start_field=1
Define end_field=9 ; GetAmountStringFields_BF()
Define found
Debug "=============================="
Debug "I only search the first nine StringFields here"
Debug "=============================="
Debug "Search for : "+find_string$
For i=1 To end_field
found=FindStringFields_BF(find_string$, start_position, flags.a, start_field, end_field)
If found
start_field=found+1
Debug "Found in StringField : "+found
EndIf
Next
MessageRequester("Deactivate the Debugger",
"String parsing time : "+parsing_time+#LF$+
"String length : "+Len(string$)+#LF$+
"StringFields found : "+GetAmountStringFields_BF()+#LF$+
"Empty StringFields found : "+GetEmptyStringFields_BF())
CompilerEndIf