It is currently Sun Jan 17, 2021 10:25 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 1 post ] 
Author Message
 Post subject: String Builder "Class"
PostPosted: Wed Nov 03, 2004 5:24 am 
Offline
Addict
Addict
User avatar

Joined: Thu Jul 01, 2004 2:51 am
Posts: 898
Location: Tacoma, WA
Code updated For 5.20+

I've been using helpy's code for string building (http://forums.purebasic.com/english/viewtopic.php?t=12696&highlight=) but finally got frustrated when I could only call it once at a time. So I just ran myself through a quick course in pointers and, using froggerprogger's queue library as reference, created these string builder procedures that should allow you to use it any number of times. I also added a simple Length procedure.

Code:
    Structure StringBuilder
      pString.i
      StringSize.i
      MemSize.i
      BlockSize.i
      InitDone.i
      ; Initialized to 0 (FALSE) at creation.  Means by default
      ; we have not initialized the structure/class.
    EndStructure

    Procedure sbCreate(BlockSize)
       ;
       Protected *sbClass.StringBuilder
       ;
       *sbClass = AllocateMemory(SizeOf(StringBuilder))
       ;
       If *sbClass\InitDone : FreeMemory(*sbClass\pString) : EndIf
       ; If the stringbuilder is already initialized, free the memory of the string.
       ; 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
       ;
       *sbClass\BlockSize = BlockSize
       *sbClass\StringSize = 0
       *sbClass\pString = AllocateMemory(BlockSize)
       ; Allocate the memory needed for our string
       If *sbClass\pString <> 0
          ; Allocation went fine, let the structure know we initialized everything fine.
          *sbClass\InitDone = #True
          *sbClass\MemSize = *sbClass\BlockSize
          ; Set our memory size used to the size of the block.
       Else
          ; Problem with allocation - let it know we did not initialize
          *sbClass\InitDone = #False
          *sbClass\MemSize = 0
       EndIf
       ;
       ProcedureReturn *sbClass
       ; Return the pointer to our new stringbuilder class.
    EndProcedure

    Procedure sbClear(*inSBClass.StringBuilder)
       ;
       If *inSBClass\InitDone
          FreeMemory(*inSBClass\pString)
          *inSBClass\pString = 0
          *inSBClass\StringSize = 0
          *inSBClass\BlockSize = 0
          *inSBClass\InitDone = #False
          *inSBClass\MemSize = 0
       EndIf
       ;
    EndProcedure

    Procedure sbDestroy(*inSBClass.StringBuilder)
       ;
       If *inSBClass\InitDone
          FreeMemory(*inSBClass\pString)
          *inSBClass\pString = 0
          *inSBClass\StringSize = 0
          *inSBClass\BlockSize = 0
          *inSBClass\InitDone = #False
          *inSBClass\MemSize = 0
       EndIf
       ;
       FreeMemory(*inSBClass)
       ;
    EndProcedure

    Procedure sbAdd(*inSBClass.StringBuilder, inString)
       ;
       Protected StrLen
       Protected pNewString
       Protected NewMemSize
       Protected NewStringSize
       ;
       StrLen = MemoryStringLength(inString)
       ;
       NewStringSize = StrLen + *inSBClass\StringSize
       ;
       If NewStringSize + 1 > *inSBClass\MemSize
          NewMemSize = *inSBClass\MemSize + *inSBClass\BlockSize
          pNewString=AllocateMemory(NewMemSize)
          If pNewString = 0 : ProcedureReturn #False : EndIf
          CopyMemory(*inSBClass\pString, pNewString, *inSBClass\StringSize)
          FreeMemory(*inSBClass\pString)
          *inSBClass\pString = pNewString
          *inSBClass\MemSize = NewMemSize
       EndIf
       ;
       CopyMemory(inString, *inSBClass\pString + *inSBClass\StringSize, StrLen)
       *inSBClass\StringSize = NewStringSize
       ;
    EndProcedure

    Procedure sbAddLiteral(*inSBClass.StringBuilder, inString.s)
       ;
       Protected sAddress
       Protected StrLen
       Protected pNewString
       Protected NewMemSize
       Protected NewStringSize
       ;
       sAddress = @inString
       StrLen = MemoryStringLength(sAddress)
       ;
       NewStringSize = StrLen + *inSBClass\StringSize
       ;
       If NewStringSize + 1 > *inSBClass\MemSize
          NewMemSize = *inSBClass\MemSize + *inSBClass\BlockSize
          pNewString=AllocateMemory(NewMemSize)
          If pNewString = 0 : ProcedureReturn #False : EndIf
          CopyMemory(*inSBClass\pString, pNewString, *inSBClass\StringSize)
          FreeMemory(*inSBClass\pString)
          *inSBClass\pString = pNewString
          *inSBClass\MemSize = NewMemSize
       EndIf
       ;
       CopyMemory(sAddress, *inSBClass\pString + *inSBClass\StringSize, StrLen)
       *inSBClass\StringSize = NewStringSize
       ;
    EndProcedure

    Procedure.s sbGetString(*inSBClass.StringBuilder)
       ;
       Protected WholeString.s
       ;
       WholeString = PeekS(*inSBClass\pString)
       ;
       ProcedureReturn WholeString
       ;
    EndProcedure

    Procedure.s sbGetStringAndDestroy(*inSBClass.StringBuilder)
       ;
       Protected WholeString.s
       ;
       WholeString = PeekS(*inSBClass\pString)
       sbDestroy(*inSBClass)
       ;
       ProcedureReturn WholeString
       ;
    EndProcedure

    Procedure sbLength(*inSBClass.StringBuilder)
      Protected iLength
      iLength = *inSBClass\StringSize
      ProcedureReturn iLength
    EndProcedure


    sHold.s = "1"
    sDelimiter.s = ","
    q = sbCreate(2048)
    ; Create a new string builder with a blocksize of 2048.  You can create as many as you like.  Just use a new long variable and pass it as a reference to the various functions.
    sbAdd(q, @sHold)
    ; Add a string by the address of the string variable
    sbAdd(q, @sDelimiter)
    sbAddLiteral(q, "Hi!")
    ; Add by string rather than string address.
    Debug sbGetString(q)
    ; Return the string itself
    Debug "Length: "+Str(sbLength(q))
    ; Return the character count - 1 based. So "Hi" will return 2.  Our example here should return 5.
    sbDestroy(q)
    ; Destroy the string builder and clean up the used memory.


So you should be able to create and use as many string builders as you want. It'd be great if anyone could spot any way to update the code and make it faster or better. In fact, I'd appreciate if people could give it a shot. I'm just starting with pointers memory functions so I'm sure I messed something up.

And thanks to helpy and froggerprogger for the code and examples :D

[Edit: I snuck in a "sbGetStringAndDestroy" procedure that will return the string and destroy the string builder. I'm not sure others will find this useful but I often need to return the built string as a procedurereturn so it's useful for me to return the string without setting the string builder to a string, destroying it and then returning the string]


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

All times are UTC + 1 hour


Who is online

Users browsing this forum: Amitris_de and 28 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