It is currently Sat Mar 06, 2021 3:23 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 13 posts ] 
Author Message
 Post subject: String Builder?
PostPosted: Wed Oct 06, 2004 12:26 am 
Offline
Addict
Addict
User avatar

Joined: Thu Jul 01, 2004 2:51 am
Posts: 898
Location: Tacoma, WA
Is there such a thing in Purebasic as a string builder? Or some way to concatenate a lot of strings together? I know VB and C++ have some string builder classes that make appending strings very fast - is there a PB equivalent?


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Oct 06, 2004 3:10 am 
Offline
Moderator
Moderator

Joined: Sat Dec 27, 2003 3:55 am
Posts: 3321
Location: Great Southern Land
Not sure is this is what you mean:

Code:
w.s="ABC"
x.s="XYZ"
y.s="NOP"

z.s=w+" : "+x+" concat using plus sign "+y
Debug z


Using the + (plus) sign. If off track here, my apologies.

_________________
@}--`--,-- A rose by any other name ..


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Oct 06, 2004 4:24 am 
Offline
Addict
Addict
User avatar

Joined: Thu Jul 01, 2004 2:51 am
Posts: 898
Location: Tacoma, WA
No, no. Of course I know that one. I'm talking about fast string concatenation. For example, in VB, you could add strings together with the "&" symbol just fine but with several hundred additions it was slow. String builder classes could append the strings together very quickly for you. You'd create a new instance of the string builder class and usually calls sHold.Append and then when you were done, sHold.ToString (VB6).

Does this make any sense?


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Oct 06, 2004 5:46 am 
Offline
Moderator
Moderator

Joined: Sat Dec 27, 2003 3:55 am
Posts: 3321
Location: Great Southern Land
Oops. Sorry Xombie. :) Yes it makes sense. I am unaware of anything like this for PB.

Maybe someone else?

_________________
@}--`--,-- A rose by any other name ..


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Oct 06, 2004 5:54 am 
Offline
User
User
User avatar

Joined: Mon May 12, 2003 6:04 am
Posts: 39
Location: the far west
is the speed of string concatenation (x.s + y.s) in PureBasic even an issue? I haven't compared this to other languages anyone else?


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Oct 06, 2004 6:39 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sat Jun 28, 2003 12:01 am
Posts: 531
Dare2 wrote:
Oops. Sorry Xombie. :) Yes it makes sense. I am unaware of anything like this for PB.


Hello all,

First VB: It only makes sense to use string builder classes in VB, when you have to concatenate a lot of strings. Because if you do this in VB it always reallocates the string memory. I once wrote an stringbuilder class for VBScript ... it just adds the string parts to a string array (the array is not redimensioned with every new string, but in steps of 50/100 ...) ... and if you need the whole string the join() command is used to concatenate all strings. This is much ... much ... much faster than adding all string parts to one big string. If you only have to concatenate some few strings, than it makes no sense to use a string builder class.

PureBasic: I do not know how fast the realocation of strings is in PureBasic. Maybe someone can test if it would make sense to write some special concatenation functions.

cu, helpy


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Oct 06, 2004 6:48 am 
Offline
Moderator
Moderator

Joined: Sat Dec 27, 2003 3:55 am
Posts: 3321
Location: Great Southern Land
Hi helpy :)

Further on this (hopefully this is still on topic) has anyone successfully used StrCat and similar calls, either via PB: StrCat_( or through the dll:
Code:
#_shlwapi = 11
If OpenLibrary(#_shlwapi,"shlwapi.dll")
  Debug "---"
  Debug IsFunction(#_shlwapi, "StrCat") ; says no ?
  Debug IsFunction(#_shlwapi, "StrCatA") ; says no ?
  Debug IsFunction(#_shlwapi, "StrCatW") ; says YES !
  Debug IsFunction(#_shlwapi, "StringCbCat") ; says no ?
  Debug IsFunction(#_shlwapi, "StringCbCatEx") ; says no ?
; push it a bit  :)
  Debug IsFunction(#_shlwapi, "StringCbCatA") ; says no ?
  Debug IsFunction(#_shlwapi, "StringCbCatW") ; says no ?
  Debug IsFunction(#_shlwapi, "StringCbCatAEx") ; says no ?
  Debug IsFunction(#_shlwapi, "StringCbCatWEx") ; says no ?
  Debug IsFunction(#_shlwapi, "StringCbCatExA") ; says no ?
  Debug IsFunction(#_shlwapi, "StringCbCatExW") ; says no ?
  Debug "---"
  CloseLibrary(#_shlwapi)
EndIf

?

When string handling becomes bulky, important (or possibly leaky) I now use memory.


Edit:

Forgot to post what I started out to post :oops:

Helpy's post reminded me of this, by Wilbert. Maybe useful?

http://forums.purebasic.com/english/vie ... highlight=

_________________
@}--`--,-- A rose by any other name ..


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Oct 06, 2004 8:31 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sat Jun 28, 2003 12:01 am
Posts: 531
Hi all,

I tested it with own StringBuilder functions:
Code:
; Speed test of string concatenation
; and the use of StringBuilder functions
Structure StringBuilder
  pString.l
  StringSize.l
  MemSize.l
  BlockSize.l
  InitDone.l
EndStructure

Procedure StringBuilder_Info()
  Static sbInfo.StringBuilder
  ProcedureReturn @sbInfo
EndProcedure

Procedure StringBuilder_Init(BlockSize)
  Protected *sbInfo.StringBuilder
  *sbInfo = StringBuilder_Info()
  If *sbInfo\InitDone : FreeMemory(*sbInfo\pString) : EndIf
  ; BlockSize min. 1024 ($400) Byte
  If BlockSize < $400 : BlockSize = $400 : EndIf
  ; BlockSize max. 1 MByte ($100000) Byte
  If BlockSize > $100000 : BlockSize = $100000 : EndIf
  If BlockSize <> (BlockSize & $FC00):
    BlockSize = (BlockSize & $FC00) + 1024
  EndIf
  *sbInfo\BlockSize = BlockSize
  *sbInfo\StringSize = 0
  *sbInfo\pString = AllocateMemory(BlockSize)
  If *sbInfo\pString <> 0
    *sbInfo\InitDone = #True
    *sbInfo\MemSize = *sbInfo\BlockSize
  Else
    *sbInfo\InitDone = #False
    *sbInfo\MemSize = 0
  EndIf
  ProcedureReturn *sbInfo\InitDone
EndProcedure
Procedure StringBuilder_Clear()
  Protected *sbInfo.StringBuilder
  *sbInfo=StringBuilder_Info()
  If *sbInfo\InitDone
    FreeMemory(*sbInfo\pString)
    *sbInfo\pString = 0
    *sbInfo\StringSize = 0
    *sbInfo\BlockSize = 0
    *sbInfo\InitDone = #False
    *sbInfo\MemSize = 0
  EndIf
EndProcedure
Procedure StringBuilder_Add(pAddString.l)
  Protected *sbInfo.StringBuilder
  Protected StrLen
  Protected pNewString, NewMemSize, NewStringSize
  *sbInfo = StringBuilder_Info()
  StrLen = MemoryStringLength(pAddString)
  NewStringSize = StrLen + *sbInfo\StringSize
 
  If NewStringSize + 1 > *sbInfo\MemSize
    NewMemSize = *sbInfo\MemSize+*sbInfo\BlockSize
    pNewString=AllocateMemory(NewMemSize)
    If pNewString = 0 : ProcedureReturn #False : EndIf
    CopyMemory(*sbInfo\pString,pNewString,*sbInfo\StringSize)
    FreeMemory(*sbInfo\pString)
    *sbInfo\pString=pNewString
    *sbInfo\MemSize=NewMemSize
  EndIf
  CopyMemory(pAddString,*sbInfo\pString+*sbInfo\StringSize,StrLen)
  *sbInfo\StringSize = NewStringSize
EndProcedure
Procedure.s StringBuilder_GetString()
  Protected *sbInfo.StringBuilder
  Protected WholeString.s
  *sbInfo=StringBuilder_Info()
  WholeString = PeekS(*sbInfo\pString)
  ProcedureReturn WholeString
EndProcedure

#TestLoop=1024*64

t=GetTickCount_()
For i = 1 To #TestLoop
  s1.s+"+"
Next
time1=GetTickCount_()-t
MessageRequester("StringTest", "StringFunctions: " + Str(time1) + " ms")

t=GetTickCount_()
If StringBuilder_Init(2048)
  sAdd.s="+"
  For i = 1 To #TestLoop
    StringBuilder_Add(@sAdd)
  Next
  s2.s = StringBuilder_GetString()
  StringBuilder_Clear()
  time2=GetTickCount_()-t
  MessageRequester("StringTest", "StringFunctions: " + Str(time1) + " ms" + #CRLF$ + "StringBuilder: " + Str(time2) + " ms")
 
  If CompareMemoryString(s1,s2,0) <> 0
    MessageRequester("StringTest", "Strings sind nicht identisch!")
  Else
    MessageRequester("StringTest", "Strings sind identisch!")
  EndIf
Else
  MessageRequester("StringTest", "StringBuilder konnte nicht initialisiert werden!")
EndIf

Test: 64.000 times the character "+" is added to a string. with normal PB-String functions it takes about 11s at my PC. With the StringBuilder functions it takes 16ms.

So if you have to concatenate much strings, it makes sense to use own concatenation functions:

ATTENTION: The above functions are written only for testing. It is not possible to handel two or more strings at the same time, because there is only ONE string buffer. It would be possible to rewrite the functions to use more stringbuffers. AND the above functions does not handel the string limitations of PureBasic ... so the StringBuilder_GetString() could fail if the concatenated string is too big (at the moment a PB-String can have a maximum of 70508 characters ... tested with PB 3.91).

cu, helpy


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Oct 06, 2004 9:06 am 
Offline
Administrator
Administrator

Joined: Fri May 17, 2002 4:39 pm
Posts: 14181
Location: France
You can use a combination of AllocateMemory() and CopyMemoryString() which should be the fastest way to concatenate a lot of strings. See the help for CopyMemoryString() for a quick example.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Oct 09, 2004 1:02 am 
Offline
Addict
Addict
User avatar

Joined: Thu Jul 01, 2004 2:51 am
Posts: 898
Location: Tacoma, WA
helpy - that code works great. Thanks a lot for sharing. I do wish it could be used (easily) more than once at a time but I can always adapt it as I need it.

Thanks again.


Top
 Profile  
Reply with quote  
 Post subject: Re:
PostPosted: Sun Oct 09, 2016 5:52 am 
Offline
Addict
Addict

Joined: Mon Feb 16, 2015 2:49 pm
Posts: 1907
Fred wrote:
You can use a combination of AllocateMemory() and CopyMemoryString() which should be the fastest way to concatenate a lot of strings. See the help for CopyMemoryString() for a quick example.

I've been trying to do this (for fast string building, concatenation or joining) but I can't work it out. :( Here's what I want to achieve:

Code:
one$="111"
two$="222"

m=AllocateMemory(Len(one$)+Len(two$))
CopyMemoryString(@two$,@m)

Debug one$ ; Should output 111222


Top
 Profile  
Reply with quote  
 Post subject: Re: String Builder?
PostPosted: Sun Oct 09, 2016 7:25 am 
Offline
PureBasic Bullfrog
PureBasic Bullfrog
User avatar

Joined: Wed Jul 06, 2005 5:42 am
Posts: 8149
Location: Fort Nelson, BC, Canada
Just a couple things to keep in mind, Len won't do for calculating memory required, StringBytelength is needed. In PB 5.50, Len is returning 3 for one$, where we know 6 bytes are needed. Also, you can't use the actual address as destination because CopyMemoryString is going to update the pointer each time it writes, adding to it the number of bytes it just wrote. So you need to set a new var to the value of your destination pointer and pass the new one to the command. Also note that after the first write no more address is needed as the command now knows where to write:

Code:
one$="111"
two$="222"

*m=AllocateMemory(StringByteLength(one$)+StringByteLength(two$)+SizeOf(Character))
*writeloc = *m

CopyMemoryString(one$, @*writeloc)
CopyMemoryString(two$)

Debug PeekS(*m) ; Should output 111222


Quite a cleverly conceived command, actually. Both lightning fast and simple to code once you grasp the concept.

_________________
BERISHEET


Top
 Profile  
Reply with quote  
 Post subject: Re: String Builder?
PostPosted: Sun Oct 09, 2016 11:51 am 
Offline
Addict
Addict

Joined: Mon Feb 16, 2015 2:49 pm
Posts: 1907
Thanks netmaestro! 8)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 44 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye