Re: Fast string
Posted: Fri Aug 11, 2017 11:51 am
+ 1
Code: Select all
DisableDebugger
Str.s
Dummy.s
#Text = "1234567890"
Time = ElapsedMilliseconds()
For i=1 To 100000
Dummy + #Text
If Len(Dummy) > 2048
Str + Dummy
Dummy = ""
EndIf
Next i
Str + Dummy
MessageRequester("", StrF((ElapsedMilliseconds()-Time)/1000, 3))
Code: Select all
EnableExplicit
Procedure StringAppend(*sb,string.s)
Protected size,*Offset
If *sb
size=MemorySize(*sb)
*Offset=size
EndIf
size+StringByteLength(string)
*sb=ReAllocateMemory(*sb,size,#PB_Memory_NoClear)
PokeS(*sb+*offset,string,-1,#PB_String_NoZero)
ProcedureReturn *sb
EndProcedure
Procedure.s SBToString(*sb)
ProcedureReturn PeekS(*sb,MemorySize(*sb)/SizeOf(Character))
EndProcedure
OpenConsole()
Define i
Define s.s="Lalala"
Define *sb=StringAppend(*sb,"Lalala")
#max=100000
Define start=ElapsedMilliseconds()
For i=1 To #max
s+"La"
Next
Define ende=ElapsedMilliseconds()
PrintN(Str(ende-start)+" - "+Len(s))
start=ElapsedMilliseconds()
For i=1 To #max
*sb=StringAppend(*sb,"La")
Next
ende=ElapsedMilliseconds()
PrintN(Str(ende-start)+" - "+Len(SBToString(*sb)))
Input()
CloseConsole()
Code: Select all
40733 - 200006
23 - 200006
I have an issue with extremely slow strings, that I posted about here:Cyllceaux wrote:Just a little fun code, to remember this is still a thing
Technically, no. But if we can write long blocks of code as a "workaround", then such workarounds need to become native.Shield wrote:This is not generally a PureBasic "problem"
Code: Select all
Debug "Please wait, speed testing..."
DisableDebugger
OpenWindow(0,200,200,200,100,"test",#PB_Window_Invisible)
ListIconGadget(0,10,10,180,80,"test",180)
; Prep the ListIconGadget with 505 KB of text:
items=5000
For a=1 To items
AddGadgetItem(0,-1,Str(a)+Space(100))
Next
; Build a 505 KB string directly from the gadget:
start.q=ElapsedMilliseconds()
For a=1 To items
one$+GetGadgetItemText(0,a)
Next
one.q=ElapsedMilliseconds()-start
; Build another 505 KB string using disk access:
start.q=ElapsedMilliseconds()
f$=GetTemporaryDirectory()+"string-speed-test"
If CreateFile(0,f$)
For a=1 To items
WriteString(0,GetGadgetItemText(0,a))
Next
CloseFile(0)
If ReadFile(0,f$)
two$=ReadString(0,#PB_File_IgnoreEOL)
CloseFile(0)
EndIf
DeleteFile(f$)
EndIf
two.q=ElapsedMilliseconds()-start
; The results:
EnableDebugger
Debug "Len(one$)="+Str(Len(one$))+" and took "+Str(one)+" ms" ; 8216 ms (8 seconds!)
Debug "Len(two$)="+Str(Len(two$))+" and took "+Str(two)+" ms" ; 22 ms (not even a quarter of a second!)
Dude wrote:22 ms (not even a quarter of a second!)
Code: Select all
DisableDebugger
Structure StringBuilderItem
item.s
size.i
EndStructure
Structure StringBuilder
size.i
count.i
List item.StringBuilderItem()
EndStructure
Procedure StringBuilder_Add(*sb.StringBuilder,itm$)
nSize = StringByteLength(itm$)
*sb\size = *sb\size + nSize
*sb\count = *sb\count + 1
AddElement(*sb\item())
*sb\item()\item = itm$
*sb\item()\size = nSize
EndProcedure
Procedure StringBuilder_Clear(*sb.StringBuilder)
ClearList(*sb\item())
*sb\count = 0
*sb\size = 0
EndProcedure
Procedure StringBuilder_Free(*sb.StringBuilder)
ClearList(*sb\item())
FreeStructure(*sb)
EndProcedure
Procedure.s StringBuilder_Get(*sb.StringBuilder,idx.i)
If idx > *sb\count - 1
ProcedureReturn ""
EndIf
SelectElement(*sb\item(),idx)
ProcedureReturn *sb\item()\item
EndProcedure
Procedure.s StringBuilder_GetChunk(*source,nSize)
*bfr = AllocateMemory(nSize + 4)
CopyMemory(*source,*bfr,nSize)
out$ = PeekS(*bfr)
FreeMemory(*bfr)
ProcedureReturn out$
EndProcedure
Procedure.i StringBuilder_GetLongest(*sb.StringBuilder)
nLongest = 0
ResetList(*sb\item())
While NextElement(*sb\item())
If *sb\item()\size > nLongest
nLongest = *sb\item()\size
EndIf
Wend
ProcedureReturn nLongest
EndProcedure
Procedure StringBuilder_Insert(*sb.StringBuilder,idx,val$)
If idx > *sb\count - 1 : ProcedureReturn : EndIf
SelectElement(*sb\item(),idx)
InsertElement(*sb\item())
nSize = StringByteLength(val$)
*sb\count = *sb\count + 1
*sb\size = *sb\size + nSize
*sb\item()\item = val$
*sb\item()\size = nSize
EndProcedure
Procedure.s StringBuilder_Join(*sb.StringBuilder,delim$="")
nSizeDelim = StringByteLength(delim$)
nAdder = ListSize(*sb\item()) * nSizeDelim
*bfr = AllocateMemory(*sb\size + nAdder + 4)
nLoops = 0
ResetList(*sb\item())
While NextElement(*sb\item())
PokeS(*bfr+nPos,*sb\item()\item,*sb\item()\size)
nPos = nPos + *sb\item()\size
nLoops = nLoops + 1
If nSizeDelim > 0 And nLoops < *sb\count
PokeS(*bfr+nPos,delim$,nSizeDelim)
nPos = nPos + nSizeDelim
EndIf
Wend
out$ = PeekS(*bfr,*sb\size)
FreeMemory(*bfr)
ProcedureReturn out$
EndProcedure
Procedure.i StringBuilder_New()
*s.StringBuilder = AllocateStructure(StringBuilder)
*s\count = 0
*s\size = 0
ProcedureReturn *s
EndProcedure
Procedure StringBuilder_Remove(*sb.StringBuilder,idx.i)
If idx > *sb\count - 1 : ProcedureReturn : EndIf
SelectElement(*sb\item(),idx)
*sb\count = *sb\count - 1
*sb\size = *sb\size - *sb\item()\size
DeleteElement(*sb\item())
EndProcedure
Procedure StringBuilder_Replace(*sb.StringBuilder,idx.i,val$)
If idx > *sb\count - 1 : ProcedureReturn : EndIf
SelectElement(*sb\item(),idx)
*sb\size = *sb\size - *sb\item()\size
nSize = StringByteLength(val$)
*sb\size = *sb\size + nSize
*sb\item()\item = val$
*sb\item()\size = nSize
EndProcedure
Procedure.i StringBuilder_Split(val$,delim$)
*sb = StringBuilder_New()
nSizeDel = StringByteLength(delim$)
nSizeVal = StringByteLength(val$)
If nSizeDel = 0 Or nSizeVal = 0
ProcedureReturn *sb
EndIf
nEnd = 0 : nLen = 0 : nStart = 0
While nEnd <= nSizeVal
If CompareMemory(@val$+nEnd,@delim$,nSizeDel)
StringBuilder_Add(*sb,StringBuilder_GetChunk(@val$+nStart,nLen))
nEnd = nEnd + nSizeDel
nStart = nEnd
nLen = 0
Else
nEnd = nEnd + 1
nLen = nLen + 1
EndIf
Wend
If nLen > 0
StringBuilder_Add(*sb,StringBuilder_GetChunk(@val$+nStart,nLen))
EndIf
ProcedureReturn *sb
EndProcedure
items=5000
joinstart.q=ElapsedMilliseconds()
*s.StringBuilder = StringBuilder_New()
For a=1 To items
StringBuilder_Add(*s,Str(a)+Space(100))
Next
s$=StringBuilder_Join(*s,"|")
joinend.q=ElapsedMilliseconds()-joinstart
splitstart.q=ElapsedMilliseconds()
*s1.StringBuilder = StringBuilder_Split(s$,"|")
splitend.q=ElapsedMilliseconds()-splitstart
EnableDebugger
Debug "Join: Len(s$)= "+Str(Len(s$))+" and took "+Str(joinend)+" ms"
Debug "Split: Elements(s$)= "+Str(*s1\count)+" and took "+Str(splitend)+" ms"
StringBuilder_Free(*s)
StringBuilder_Free(*s1)
s$ = "Probably the best sparkling wine in the world"
*s.StringBuilder = StringBuilder_Split(s$," ")
StringBuilder_Replace(*s,3,"malt")
StringBuilder_Remove(*s,4)
StringBuilder_Insert(*s,4,"vinegar")
Debug StringBuilder_Join(*s," ")
Code: Select all
For i=1 To 100000
Dummy + #Text
If Len(Dummy) > 2048
Str + Dummy
Dummy = ""
EndIf
Next i
Str + Dummy
Code: Select all
Procedure StringAppend(*sb,string.s)
Protected size,*Offset
If *sb
size=MemorySize(*sb)
*Offset=size
EndIf
size+StringByteLength(string)
*sb=ReAllocateMemory(*sb,size,#PB_Memory_NoClear)
PokeS(*sb+*offset,string,-1,#PB_String_NoZero)
ProcedureReturn *sb
EndProcedure
Procedure.s SBToString(*sb)
ProcedureReturn PeekS(*sb,MemorySize(*sb)/SizeOf(Character))
EndProcedure
Code: Select all
FreeMemory(*sb)
Code: Select all
Structure MyStringBuilder
*MyStringBuilderMemoryiD
MyStringBuilderSize.q
MyStringBuilderRemaining.q
MyStringBuilderPosition.q
EndStructure
Global Dim MyStringBuilder.MyStringBuilder(0)
Procedure.b initialiseStringBuilder(Taille.q)
If Taille.q <= 0
Taille.q = 1
EndIf
If ArraySize(MyStringBuilder(), 1) = -1
ProcedureReturn 0
EndIf
If MyStringBuilder.MyStringBuilder(0)\MyStringBuilderMemoryiD = 0
*MyStringBuilderMemoryiD = AllocateMemory(StringByteLength(Space(Taille.q), #PB_Unicode) + 2)
If *MyStringBuilderMemoryiD
MyStringBuilder.MyStringBuilder(0)\MyStringBuilderMemoryiD = *MyStringBuilderMemoryiD
MemorySize.q = MemorySize(MyStringBuilder.MyStringBuilder(0)\MyStringBuilderMemoryiD) / 2
MemorySize.q - 1
MyStringBuilder.MyStringBuilder(0)\MyStringBuilderRemaining = MemorySize.q
MyStringBuilder.MyStringBuilder(0)\MyStringBuilderSize = MemorySize.q
MyStringBuilder.MyStringBuilder(0)\MyStringBuilderPosition = 0
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure.b isStringBuilder(ElementiD.i)
ArraySize.i = ArraySize(MyStringBuilder(), 1)
If ArraySize.i = -1 Or ElementiD.i < 0 Or ElementiD.i > ArraySize.i
ProcedureReturn 0
EndIf
If MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD <> 0
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure.b StringBuilderAddElement(Taille.q)
ArraySize.i = ArraySize(MyStringBuilder(), 1)
If ArraySize.i = -1
ProcedureReturn 0
EndIf
ReDim MyStringBuilder.MyStringBuilder(ArraySize.i + 1)
*MyStringBuilderMemoryiD = AllocateMemory(StringByteLength(Space(Taille.q), #PB_Unicode) + 2)
If *MyStringBuilderMemoryiD
MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderMemoryiD = *MyStringBuilderMemoryiD
MemorySize.q = MemorySize(MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderMemoryiD) / 2
MemorySize.q - 1
MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderRemaining = MemorySize.q
MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderSize = MemorySize.q
MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderPosition = 0
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
ProcedureReturn ElementiD.i + 1
EndProcedure
Procedure.b StringBuilderClearString(ElementiD.i)
If Not isStringBuilder(ElementiD.i)
ProcedureReturn 0
EndIf
MemorySize.q = MemorySize(MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderMemoryiD) / 2
MemorySize.q - 1
FillMemory(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD, MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderSize, #Null , #PB_Unicode)
MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining = MemorySize.q
MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderSize = MemorySize.q
MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition = 0
ProcedureReturn 1
EndProcedure
Procedure.b StringBuilderReAllocate(ElementiD.i, Taille.q)
If Taille.q <= 0
Taille.q = 1
EndIf
If Not isStringBuilder(ElementiD.i)
ProcedureReturn 0
EndIf
*MyStringBuilderMemoryiD = ReAllocateMemory(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD, Taille.q)
If *MyStringBuilderMemoryiD
MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD = *MyStringBuilderMemoryiD
MemorySize.q = MemorySize(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD) / 2
MemorySize.q - 1
TailleActuel.q = MemorySize.q
NouvelleTaille.q = Taille.q
Restant.q = MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining
If TailleActuel.q > NouvelleTaille.q
Difference.q = TailleActuel.q - NouvelleTaille.q
Restant.q - Difference.q
If Restant.q < 0
MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition + Restant.q
Restant.q = 0
EndIf
MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining = Restant.q
MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderSize = Taille.q
ElseIf NouvelleTaille.q > TailleActuel.q
Difference.q = NouvelleTaille.q - TailleActuel.q
Restant.q + Difference.q
MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining = Restant.q
MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderSize = Taille.q
EndIf
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure.b StringBuilderAddString(ElementiD.i, String.s)
If Not String.s > ""
ProcedureReturn 0
EndIf
If isStringBuilder(ElementiD.i)
If Len(String.s) > MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining
*MyStringBuilderMemoryiD = ReAllocateMemory(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD, MemorySize(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD) + (StringByteLength(String.s) * 10))
If *MyStringBuilderMemoryiD
MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD = *MyStringBuilderMemoryiD
MemorySize.q = MemorySize(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD) / 2
MemorySize.q - 1
If PokeS(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD + (MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition * 2), String.s, -1, #PB_Unicode)
MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining = MemorySize.q - MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition - Len(String.s)
MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderSize = MemorySize.q
MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition + Len(String.s)
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
Else
ProcedureReturn 0
EndIf
Else
MemorySize.q = MemorySize(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD) / 2
MemorySize.q - 1
If PokeS(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD + (MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition * 2), String.s, -1, #PB_Unicode)
MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining = MemorySize.q - MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition - Len(String.s)
MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderSize = MemorySize.q
MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition + Len(String.s)
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndIf
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure.S StringBuilderGetString(ElementiD.i)
If isStringBuilder(ElementiD.i)
ProcedureReturn PeekS(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD, -1, #PB_Unicode)
Else
ProcedureReturn ""
EndIf
EndProcedure
Procedure.i StringBuilderGetMemoryiD(ElementiD.i)
If isStringBuilder(ElementiD.i)
ProcedureReturn MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure.i StringBuilderGetMemorySize(ElementiD.i)
If isStringBuilder(ElementiD.i)
ProcedureReturn MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderSize
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure.i StringBuilderGetMemoryRemaining(ElementiD.i)
If isStringBuilder(ElementiD.i)
ProcedureReturn MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure.i StringBuilderGetMemoryPosition(ElementiD.i)
If isStringBuilder(ElementiD.i)
ProcedureReturn MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition
Else
ProcedureReturn 0
EndIf
EndProcedure
;
; Procedure.i StringBuilderDeletteElement()
;
;
;
; EndProcedure
;
; Procedure.i StringBuilderCopyElement()
;
;
;
; EndProcedure
Abc$ = "Abcdefghijklmnopqrstuvwxyz"
If initialiseStringBuilder(0)
For MonStringBuilder1.i = 0 To 5
If isStringBuilder(MonStringBuilder1.i)
MessageRequester("StringBuilder initialisation...", "StringBuilderID = " + Str(MonStringBuilder1.i) + Chr(13) + Chr(10) +
"StringBuilder MemoryiD = " + Str(StringBuilderGetMemoryiD(MonStringBuilder1.i)) + Chr(13) + Chr(10) +
"StringBuilder Memory Size = " + Str(StringBuilderGetMemorySize(MonStringBuilder1.i)) + Chr(13) + Chr(10) +
"StringBuilder Memory Remaining = " + Str(StringBuilderGetMemoryRemaining(MonStringBuilder1.i)) + Chr(13) + Chr(10) +
"StringBuilder Memory Position = " + Str(StringBuilderGetMemoryPosition(MonStringBuilder1.i)))
Time1 = ElapsedMilliseconds()
For i = 1 To 255
Write.b = StringBuilderAddString(MonStringBuilder1.i, Abc$)
MemoryiD.q = StringBuilderGetMemoryiD(MonStringBuilder1.i)
MemorySize.q = StringBuilderGetMemorySize(MonStringBuilder1.i)
MemoryRemaining.q = StringBuilderGetMemoryRemaining(MonStringBuilder1.i)
MemoryPosition.q = StringBuilderGetMemoryPosition(MonStringBuilder1.i)
;
; Debug "MemoryiD: " + Str(MemoryiD.q)
; Debug "MemorySize: " + Str(MemorySize.q)
; Debug "MemoryRemaining: " + Str(MemoryRemaining.q)
; Debug "MemoryPosition: " + Str(MemoryPosition.q)
; Debug "Write: " + Str(Write.b)
; Debug "---------------------------"
;
Next
Time2 = ElapsedMilliseconds()
MessageRequester("StringBuilder Résultat...", "StringBuilderID = " + Str(MonStringBuilder1.i) + Chr(13) + Chr(10) +
"StringBuilder MemoryiD = " + Str(StringBuilderGetMemoryiD(MonStringBuilder1.i)) + Chr(13) + Chr(10) +
"StringBuilder Memory Size = " + Str(StringBuilderGetMemorySize(MonStringBuilder1.i)) + Chr(13) + Chr(10) +
"StringBuilder Memory Remaining = " + Str(StringBuilderGetMemoryRemaining(MonStringBuilder1.i)) + Chr(13) + Chr(10) +
"StringBuilder Memory Position = " + Str(StringBuilderGetMemoryPosition(MonStringBuilder1.i)) + Chr(13) + Chr(10) +
"Time Elapsed = " + Str(Time2 - Time1) + " Ms.")
If StringBuilderAddElement(1)
Else
Debug 0
EndIf
Else
MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder n°" + Str(MonStringBuilder1.i) + ", n'a pas put être initialisé !", 16)
EndIf
Next
Else
MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder n'a pas put être initialisé !", 16)
EndIf
For i = 0 To 5
Debug StringBuilderGetString(I)
Debug "----------"
Next
Code: Select all
Structure StructureMyStringBuilder
*MyStringBuilderMemoryID
MyStringBuilderSize.q
MyStringBuilderRemaining.q
MyStringBuilderPosition.q
EndStructure
Global NewMap MapMyStringBuilder.StructureMyStringBuilder()
; Crée un nouveau StringBuilder avec comme Nom: Nom$ et Taille (En caractères): Taille.q.
; Il est conseillé de mèttre une taille assez grande pour pouvoir ajouter par la suite la ou les nouvelles Chaines de sorte à se que le programme ne sois pas obligé
; de réalouer automatiquement une taille plus grande pour pouvoir y ajouter la nouvelle Chaine, puisque ceci ralentie beaucoup le programme.
; Si le Nom est vide ou que celui-ci existe déjà alors la fonction échoura.
; Si la Taille est inférieur ou égale à 0 alors Taille vaudra 1.
; La Taille du StringBuilder est toujours en caractères.
; Renvoie 1 si le StringBuilder a été créer ou sinon 0.
Procedure.b CreateAndInitialiseMyStringBuilder(Nom$, Taille.q = 1)
If Nom$ = "" Or FindMapElement(MapMyStringBuilder(), Nom$)
ProcedureReturn 0
EndIf
If Taille.q <= 0
Taille.q = 1
EndIf
If MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID = 0
*MyStringBuilderMemoryID = AllocateMemory(StringByteLength(Space(Taille.q + 1), #PB_Unicode))
If *MyStringBuilderMemoryID
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID = *MyStringBuilderMemoryID
MemorySize.q = MemorySize(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID) / 2
MemorySize.q - 1
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining = MemorySize.q
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize = MemorySize.q
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition = 1
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
Else
ProcedureReturn 0
EndIf
EndProcedure
; Vérifie que le StringBuilder existe avec comme Nom: Nom$.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction échoura.
; Renvoie 1 si le StringBuilder éxiste ou sinon 0.
Procedure.b IsMyStringBuilder(Nom$)
If Nom$ = "" Or Not FindMapElement(MapMyStringBuilder(), Nom$)
ProcedureReturn 0
Else
ProcedureReturn 1
EndIf
EndProcedure
; Ajoute une nouvelle chaine à la suite dans le StringBuilder avec comme Nom: Nom$ et Chaine: String.s.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction échoura.
; Si la Chaine à ajouter est vide alors la fonction échoura.
; Renvoie 1 si la Chaine a été ajouté ou sinon 0.
Procedure.b MyStringBuilderAddString(Nom$, String.s)
If IsMyStringBuilder(Nom$) And String.s > ""
If Len(String.s) > MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining
*MyStringBuilderMemoryID = ReAllocateMemory(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID, MemorySize(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID) + (StringByteLength(String.s) * 10))
If *MyStringBuilderMemoryID
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID = *MyStringBuilderMemoryID
MemorySize.q = MemorySize(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID) / 2
MemorySize.q - 1
If PokeS(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID + ((MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition - 1) * 2), String.s, -1, #PB_Unicode)
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining = (MemorySize.q - (MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition - 1) - Len(String.s))
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize = MemorySize.q
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition + Len(String.s)
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
Else
ProcedureReturn 0
EndIf
Else
MemorySize.q = MemorySize(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID) / 2
MemorySize.q - 1
If PokeS(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID + ((MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition - 1) * 2), String.s, -1, #PB_Unicode)
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining = (MemorySize.q - (MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition - 1) - Len(String.s))
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize = MemorySize.q
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition + Len(String.s)
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndIf
Else
ProcedureReturn 0
EndIf
EndProcedure
; Change la Taille (En caractères) d'allocation du StringBuilder avec comme Nom: Nom$ et Taille: Taille.q.
; Attention, si la Taille spécifié est plus petite que celle actuel, la Chaine du StringBuilder à la fin de celui-ci serra alors raccourcir et ainsi, les données serront alors supprimé définitivement.
; Si le Nom est vide ou que celui-ci n'éxiste pas alors la fonction échoura.
; Si la Taille est inférieur ou égale à 0 alors Taille vaudra 1.
; La Taille du StringBuilder est toujours en caractères.
; Renvoie 1 si la Taille du StringBuilder a été changé ou sinon 0.
Procedure.b MyStringBuilderReAllocate(Nom$, Taille.q = 1)
If IsMyStringBuilder(Nom$)
If Taille.q <= 0
Taille.q = 1
EndIf
AncienneTaille.q = MemorySize(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID) / 2
AncienneTaille.q - 1
*MyStringBuilderMemoryID = ReAllocateMemory(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID, StringByteLength(Space(Taille.q + 1)))
If *MyStringBuilderMemoryID
PokeS(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID + StringByteLength(Space(Taille.q)), Chr(#Null), -1, #PB_Unicode)
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID = *MyStringBuilderMemoryID
MemorySize.q = (MemorySize(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID)) / 2
MemorySize.q - 1
TailleActuel.q = AncienneTaille.q
NouvelleTaille.q = Taille.q
Restant.q = MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining
If TailleActuel.q > NouvelleTaille.q
Difference.q = TailleActuel.q - NouvelleTaille.q
Restant.q - Difference.q
If Restant.q < 0
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition + Restant.q
Restant.q = 0
EndIf
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining = Restant.q
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize = Taille.q
ElseIf NouvelleTaille.q > TailleActuel.q
Difference.q = NouvelleTaille.q - TailleActuel.q
Restant.q + Difference.q
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining = Restant.q
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize = Taille.q
EndIf
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
Else
ProcedureReturn 0
EndIf
EndProcedure
; Efface entièrement le StringBuilder avec comme Nom: Nom$.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction échoura.
; Seule la Chaine du StringBuilder est éffacé, ça taille restera quand à elle inchangé, ceci ne supprime pas le StringBuilder.
; Renvoie 1 si le StringBuilder a été éffacé ou sinon 0.
Procedure.b MyStringBuilderClearString(Nom$)
If IsMyStringBuilder(Nom$)
MemorySize.q = MemorySize(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID) / 2
MemorySize.q - 1
FillMemory(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID, MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize, #Null , #PB_Unicode)
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining = MemorySize.q
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize = MemorySize.q
MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition = 1
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndProcedure
; Supprime le StringBuilder avec comme Nom: Nom$.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction échoura.
; Attention, toutes les données du StringBuilder serront définitivement supprimé !
; Renvoie 1 si le StringBuilder a été supprimé ou sinon 0.
Procedure.b MyStringBuilderDeletteElement(Nom$)
If IsMyStringBuilder(Nom$)
DeleteMapElement(MapMyStringBuilder(), Nom$)
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndProcedure
; Renvoie la partie de la chaine désiré du StringBuilder avec comme Nom: Nom$.
; La Position de Depart commance à 1, si celle-ci est inférieur ou égale à 0 alors celle-ci vaudra 1.
; Si la Position de Depart est supérieur à la longueur de la chaine actuellement stoqué dans le StringBuilder, alors celle-ci vaudra la longueur de la chaine actuellement stoqué dans le StringBuilder.
; La Longueur commance à 1, si celle-ci est inférieur à -1 alors celle-ci vaudra -1.
; Si la Longueur vaud -1 alors toutes la chaine stoqué dans le StringBuilder serra renvoyé.
; Si la Longueur est supérieur à la longueur de la chaine actuellement stoqué dans le StringBuilder, alors celle-ci vaudra la longueur de la chaine actuellement stoqué dans le StringBuilder.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction renvéra une chaine vide.
Procedure.s MyStringBuilderGetString(Nom$, PositionDepart.q = 1, Longueur.q = -1)
If IsMyStringBuilder(Nom$)
If PositionDepart.q <= 1
PositionDepart.q = 1
EndIf
If PositionDepart.q > MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize
PositionDepart.q = MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize
EndIf
If Longueur.q < -1
Longueur.q = -1
EndIf
If Longueur.q > MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize
Longueur.q = (MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize)
EndIf
ProcedureReturn PeekS(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID + ((PositionDepart.q - 1) * 2), Longueur.q, #PB_Unicode)
Else
ProcedureReturn ""
EndIf
EndProcedure
; Renvoie l'adresse mémoire ou est stoqué la chaine dans le StringBuilder avec comme Nom: Nom$.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction renvéra 0.
Procedure.i MyStringBuilderGetMemoryID(Nom$)
If IsMyStringBuilder(Nom$)
ProcedureReturn MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID
Else
ProcedureReturn 0
EndIf
EndProcedure
; Renvoie la Taille en caractères du StringBuilder avec comme Nom: Nom$.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction renvéra 0.
Procedure.i MyStringBuilderGetSize(Nom$)
If IsMyStringBuilder(Nom$)
ProcedureReturn MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize
Else
ProcedureReturn 0
EndIf
EndProcedure
; Renvoie l'espace restant en caractères du StringBuilder avec comme Nom: Nom$.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction renvéra 0.
Procedure.i MyStringBuilderGetRemaining(Nom$)
If IsMyStringBuilder(Nom$)
ProcedureReturn MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining
Else
ProcedureReturn 0
EndIf
EndProcedure
; Renvoie la Position en caractères du StringBuilder avec comme Nom: Nom$.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction renvéra 0.
Procedure.i MyStringBuilderGetPosition(Nom$)
If IsMyStringBuilder(Nom$)
ProcedureReturn MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition
Else
ProcedureReturn 0
EndIf
EndProcedure
Chaine$ = "Abcdefghijklmnopqrstuvwxyz"
Chaine2$ = ""
MyStringBuilderName$ = "MyStringBuilder n°"
Time1 = ElapsedMilliseconds()
For I = 1 To 99
If CreateAndInitialiseMyStringBuilder(MyStringBuilderName$ + Str(I), 1)
If IsMyStringBuilder(MyStringBuilderName$ + Str(I))
; MessageRequester("StringBuilder initialisation...", "StringBuilder Name = " + MyStringBuilderName$ + Str(I) + Chr(13) + Chr(10) +
; "StringBuilder MemoryID = " + Str(MyStringBuilderGetMemoryID(MyStringBuilderName$ + Str(I))) + Chr(13) + Chr(10) +
; "StringBuilder Memory Size = " + Str(MyStringBuilderGetSize(MyStringBuilderName$ + Str(I))) + Chr(13) + Chr(10) +
; "StringBuilder Memory Remaining = " + Str(MyStringBuilderGetRemaining(MyStringBuilderName$ + Str(I))) + Chr(13) + Chr(10) +
; "StringBuilder Memory Position = " + Str(MyStringBuilderGetPosition(MyStringBuilderName$ + Str(I))))
; Time1 = ElapsedMilliseconds()
For J = 1 To 255
Write.b = MyStringBuilderAddString(MyStringBuilderName$ + Str(I), Str(I) + Chaine$ + Str(J))
MemoryID.q = MyStringBuilderGetMemoryID(MyStringBuilderName$ + Str(I))
MemorySize.q = MyStringBuilderGetSize(MyStringBuilderName$ + Str(I))
MemoryRemaining.q = MyStringBuilderGetRemaining(MyStringBuilderName$ + Str(I))
MemoryPosition.q = MyStringBuilderGetPosition(MyStringBuilderName$ + Str(I))
;
; Debug "MemoryID: " + Str(MemoryID.q)
; Debug "MemorySize: " + Str(MemorySize.q)
; Debug "MemoryRemaining: " + Str(MemoryRemaining.q)
; Debug "MemoryPosition: " + Str(MemoryPosition.q)
; Debug "Write: " + Str(Write.b)
; Debug "---------------------------"
;
Next
; Time2 = ElapsedMilliseconds()
; MessageRequester("StringBuilder Résultat...", "StringBuilder Name = " + MyStringBuilderName$ + Str(I) + Chr(13) + Chr(10) +
; "StringBuilder MemoryID = " + Str(MyStringBuilderGetMemoryID(MyStringBuilderName$ + Str(I))) + Chr(13) + Chr(10) +
; "StringBuilder Memory Size = " + Str(MyStringBuilderGetSize(MyStringBuilderName$ + Str(I))) + Chr(13) + Chr(10) +
; "StringBuilder Memory Remaining = " + Str(MyStringBuilderGetRemaining(MyStringBuilderName$ + Str(I))) + Chr(13) + Chr(10) +
; "StringBuilder Memory Position = " + Str(MyStringBuilderGetPosition(MyStringBuilderName$ + Str(I))) + Chr(13) + Chr(10) +
; "Time Elapsed = " + Str(Time2 - Time1) + " Ms.")
Else
MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder: " + MyStringBuilderName$ + Str(I) + ", n'est pas initialisé !", 16)
EndIf
Else
MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder: " + MyStringBuilderName$ + Str(I) + ", n'a pas put être crée !", 16)
EndIf
Next
Time2 = ElapsedMilliseconds()
For i = 1 To 99
Debug MyStringBuilderName$ + Str(I) + " = " + MyStringBuilderGetString(MyStringBuilderName$ + Str(I))
Debug "----------"
Next
Debug "Time Elapsed = " + Str(Time2 - Time1) + " Ms."
Time1 = ElapsedMilliseconds()
; Juste 5000 au lieux des 255 * 99 = 25245
; Mettez 25245 pour voir le temps réel
For J = 1 To 5000
Chaine2$ + Str(I) + Chaine$ + Str(J)
Next
Time2 = ElapsedMilliseconds()
Debug "Time Elapsed = " + Str(Time2 - Time1) + " Ms."
; ---------------------------------------------------------------------------------Exemple 2:---------------------------------------------------------------------------------------------------------------------------------------------------
; Chaine$ = "Abcdefghijklmnopqrstuvwxyz"
; Chaine2$ = ""
; MyStringBuilderName$ = "Mon StringBuilder"
;
; Debug "Temps passé avec façon Normale = " + Str(Time2 - Time1) + " Ms."
; Debug "---------------------------------"
;
; Time1 = ElapsedMilliseconds()
;
; If CreateAndInitialiseMyStringBuilder(MyStringBuilderName$)
;
; If IsMyStringBuilder(MyStringBuilderName$)
;
; For I = 1 To 10000
; MyStringBuilderAddString(MyStringBuilderName$, Chaine$ + Str(I))
;
; Next
;
; Else
; MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder: " + MyStringBuilderName$ + Str(I) + ", n'est pas initialisé !", 16)
;
; EndIf
;
; Else
; MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder: " + MyStringBuilderName$ + Str(I) + ", n'a pas put être crée !", 16)
;
; EndIf
;
; Time2 = ElapsedMilliseconds()
;
; Debug MyStringBuilderGetString(MyStringBuilderName$)
; Debug "Temps passé avec StringBuilder = " + Str(Time2 - Time1) + " Ms."
; Debug "---------------------------------"
;
; Time1 = ElapsedMilliseconds()
;
; ; Juste 5000 au lieux des 255 * 99 = 25245
; ; Mettez 25245 pour voir le temps réel
; For J = 1 To 5000
; Chaine2$ + Str(I) + Chaine$ + Str(J)
; Next
;
; Time2 = ElapsedMilliseconds()
;
; Debug "Time Elapsed = " + Str(Time2 - Time1) + " Ms."
;
; MessageRequester("Temps", "Temps passé avec StringBuilder = " + Str(Time2 - Time1) + " Ms.", 64)
;
; ---------------------------------------------------------------------------------Exemple 3:---------------------------------------------------------------------------------------------------------------------------------------------------
; Chaine$ = "Abcdefghijklmnopqrstuvwxyz"
; Chaine2$ = ""
; MyStringBuilderName$ = "Mon StringBuilder"
; ;
; ; Time1 = ElapsedMilliseconds()
; ;
; ; For J = 1 To 10000
; ; Chaine2$ + Str(I) + Chaine$ + Str(J)
; ; Next
; ;
; ; Time2 = ElapsedMilliseconds()
; ;
; ; Debug Chaine2$
; ; Debug "Temps passé avec façon normale = " + Str(Time2 - Time1) + " Ms."
; ; Debug "---------------------------------"
;
; Time1 = ElapsedMilliseconds()
;
; If CreateAndInitialiseMyStringBuilder(MyStringBuilderName$, 100000000)
;
; If IsMyStringBuilder(MyStringBuilderName$)
;
; For I = 1 To 1000000
; MyStringBuilderAddString(MyStringBuilderName$, Chaine$ + Str(I))
;
; Next
;
; Else
; MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder: " + MyStringBuilderName$ + Str(I) + ", n'est pas initialisé !", 16)
;
; EndIf
;
; Else
; MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder: " + MyStringBuilderName$ + Str(I) + ", n'a pas put être crée !", 16)
;
; EndIf
;
; Time2 = ElapsedMilliseconds()
;
; Debug MyStringBuilderGetString(MyStringBuilderName$)
; Debug "Temps passé avec StringBuilder = " + Str(Time2 - Time1) + " Ms."
; Debug "---------------------------------"
;
; MessageRequester("Temps", "Temps passé avec StringBuilder = " + Str(Time2 - Time1) + " Ms.", 64)