
Code: Select all
DisableDebugger
Interface IStringBuffer
add.i(String$)
addC.i(Character.c)
addUniC.i(Character.w)
clear.i()
get.s()
getMem.i()
copyToMem.i(*mem)
length.i()
;free object
delete()
EndInterface
Structure StringBufferElement
*next.StringBufferElement
*buffer
EndStructure
Structure OStringBuffer
;Address to the methods array
methodAddress.i
;Class Attributes
bufferSize.i
bufferOffset.i
*bufferList.StringBufferElement
*lastBuffer.StringBufferElement
length.i
EndStructure
Procedure.i StringBuffer_add(*this.IStringBuffer, String$)
If *this = #Null
ProcedureReturn #False
EndIf
*object.OStringBuffer = *this
*buffer.StringBufferElement = *object\lastBuffer
*in.CHARACTER = @String$
stringSize.i = StringByteLength(String$)
While *in - @String$ < stringSize
If *object\bufferSize <= *object\bufferOffset
*object\bufferOffset = 0
*newBuffer = #Null
While *newBuffer = #Null
*newBuffer = AllocateMemory(*object\bufferSize)
Wend
*newBufferElement = #Null
While *newBufferElement = #Null
*newBufferElement = AllocateMemory(*object\bufferSize)
Wend
*buffer\next = *newBufferElement
*buffer = *buffer\next
*buffer\buffer = *newBuffer
*object\lastBuffer = *buffer
EndIf
*out.WORD = *buffer\buffer + *object\bufferOffset
*out\w = *in\c
*object\bufferOffset + 2
*in + SizeOf(CHARACTER)
*object\length + 1
Wend
*object\lastBuffer = *buffer
ProcedureReturn #True
EndProcedure
Procedure.i StringBuffer_addC(*this.IStringBuffer, Character.c)
If *this = #Null
ProcedureReturn #False
EndIf
*object.OStringBuffer = *this
*buffer.StringBufferElement = *object\lastBuffer
If *object\bufferSize <= *object\bufferOffset
*object\bufferOffset = 0
*newBuffer = #Null
While *newBuffer = #Null
*newBuffer = AllocateMemory(*object\bufferSize)
Wend
*newBufferElement = #Null
While *newBufferElement = #Null
*newBufferElement = AllocateMemory(*object\bufferSize)
Wend
*buffer\next = *newBufferElement
*buffer = *buffer\next
*buffer\buffer = *newBuffer
*object\lastBuffer = *buffer
EndIf
*out.WORD = *buffer\buffer + *object\bufferOffset
*out\w = Character
*object\bufferOffset + 2
*object\length + 1
*object\lastBuffer = *buffer
ProcedureReturn #True
EndProcedure
Procedure.i StringBuffer_addUniC(*this.IStringBuffer, Character.w)
If *this = #Null
ProcedureReturn #False
EndIf
*object.OStringBuffer = *this
*buffer.StringBufferElement = *object\lastBuffer
If *object\bufferSize <= *object\bufferOffset
*object\bufferOffset = 0
*newBuffer = #Null
While *newBuffer = #Null
*newBuffer = AllocateMemory(*object\bufferSize)
Wend
*newBufferElement = #Null
While *newBufferElement = #Null
*newBufferElement = AllocateMemory(*object\bufferSize)
Wend
*buffer\next = *newBufferElement
*buffer = *buffer\next
*buffer\buffer = *newBuffer
*object\lastBuffer = *buffer
EndIf
*out.WORD = *buffer\buffer + *object\bufferOffset
*out\w = Character
*object\bufferOffset + 2
*object\length + 1
*object\lastBuffer = *buffer
ProcedureReturn #True
EndProcedure
Procedure.i StringBuffer_clear(*this.IStringBuffer)
If *this = #Null
ProcedureReturn #False
EndIf
*object.OStringBuffer = *this
*object\bufferOffset = 0
*object\lastBuffer = *object\bufferList
*buffer.StringBufferElement = *object\bufferList
If *buffer\next
*buffer = *buffer\next
Repeat
*nextBuffer = *buffer\next
FreeMemory(*buffer\buffer)
FreeMemory(*buffer)
*buffer = *nextBuffer
Until *buffer = #Null Or *buffer\next = #Null
EndIf
*object\bufferList\next = #Null
*object\length = 0
ProcedureReturn #True
EndProcedure
Procedure.s StringBuffer_get(*this.IStringBuffer)
If *this = #Null
ProcedureReturn ""
EndIf
*object.OStringBuffer = *this
*buffer.StringBufferElement = *object\bufferList
Result$ = ""
While *buffer\next
Result$ + PeekS(*buffer\buffer, *object\bufferSize >> 1, #PB_Unicode)
*buffer = *buffer\next
Wend
Result$ + PeekS(*buffer\buffer, *object\bufferOffset >> 1, #PB_Unicode)
ProcedureReturn Result$
EndProcedure
Procedure.i StringBuffer_getMem(*this.IStringBuffer)
If *this = #Null
ProcedureReturn #Null
EndIf
*object.OStringBuffer = *this
*result = AllocateMemory((*object\length + 1) * 2)
If *result = #Null
ProcedureReturn #Null
EndIf
If *this\copyToMem(*result) = #Null
ProcedureReturn #Null
EndIf
ProcedureReturn *result
EndProcedure
Procedure.i StringBuffer_copyToMem(*this.IStringBuffer, *mem)
If *this = #Null
ProcedureReturn 0
EndIf
*object.OStringBuffer = *this
If *mem = #Null
ProcedureReturn (*object\length + 1) * 2
EndIf
*buffer.StringBufferElement = *object\bufferList
While *buffer\next
CopyMemory(*buffer\buffer, *mem, *object\bufferSize)
*mem + *object\bufferSize
*buffer = *buffer\next
Wend
CopyMemory(*buffer\buffer, *mem, *object\bufferOffset)
ProcedureReturn (*object\length + 1) * 2
EndProcedure
Procedure.i StringBuffer_length(*this.IStringBuffer)
If *this = #Null
ProcedureReturn -1
EndIf
*object.OStringBuffer = *this
ProcedureReturn *object\length
EndProcedure
Procedure.i StringBuffer_delete(*this.IStringBuffer)
If *this = #Null
ProcedureReturn #False
EndIf
*this\clear()
*object.OStringBuffer = *this
FreeMemory(*object\bufferList\buffer)
FreeMemory(*object\bufferList)
FreeMemory(*object)
ProcedureReturn #True
EndProcedure
DataSection
OStringBuffer_methods:
Data.i @StringBuffer_add()
Data.i @StringBuffer_addC()
Data.i @StringBuffer_addUniC()
Data.i @StringBuffer_clear()
Data.i @StringBuffer_get()
Data.i @StringBuffer_getMem()
Data.i @StringBuffer_copyToMem()
Data.i @StringBuffer_length()
Data.i @StringBuffer_delete()
EndDataSection
Procedure.i newStringBuffer(bufferSize.i = 128) ;KB
If bufferSize < 1
ProcedureReturn #Null
EndIf
*object.OStringBuffer = AllocateMemory(SizeOf(OStringBuffer))
If *object = 0
ProcedureReturn #Null
EndIf
*object\methodAddress = ?OStringBuffer_methods
*object\bufferSize = bufferSize * 1024
*object\bufferOffset = 0
*object\bufferList = AllocateMemory(SizeOf(StringBufferElement))
If *object\bufferList = #Null
FreeMemory(*object)
ProcedureReturn #Null
EndIf
*object\bufferList\next = 0
*object\bufferList\buffer = AllocateMemory(*object\bufferSize)
If *object\bufferList\buffer = #Null
FreeMemory(*object\bufferList)
FreeMemory(*object)
ProcedureReturn #Null
EndIf
*object\lastBuffer = *object\bufferList
*object\length = 0
ProcedureReturn *object
EndProcedure
OpenConsole()
Buf$ = ""
t1 = ElapsedMilliseconds()
For i = 0 To 10230
Buf$ + "aaaaaaaaaa"
Next
t1 = ElapsedMilliseconds() - t1
l1 = Len(Buf$)
Buf$ = ""
b.IStringBuffer = newStringBuffer()
t2 = ElapsedMilliseconds()
For i = 0 To 10230
b\add("aaaaaaaaaa")
Next
Buf$ = b\get()
t2 = ElapsedMilliseconds() - t2
l2 = Len(Buf$)
b\delete()
Buf$ = ""
PrintN("PureBasic: " + Str(t1) + " ms (" + Str(l1) + " characters)")
PrintN("StringBuffer: " + Str(t2) + " ms (" + Str(l2) + " characters)")
Input()