This class is intended to be used for better performance when lots of strings need to be concatenated.
The test concatenates a string of 26 characters (all lower case of the ASCII alphabet) 25000 times. Without the StringBuffer, this takes approximately 10 seconds on my laptop, with the StringBuffer less than 1 second.
Methods
init(sz)
Initializes the string buffer and pre-allocates sz characters
append(txt)
Appends txt to the current text. Resizes the string if the current preallocation is too small
value
Returns the value of the string currently stored in the buffer. This is the default method, thus .value is not technically required to appear in the source code.
Basic usage
The following simple snippet demonstrates how the string buffer is used:
First, it needs to be created (new) and
initialized to the initial size of the buffer (.init …).
Then, strings can be appended by calling .append
Finally, when all pieces are added, the value of the string can be queried with .value or the class's default member.
The class automatically extends the internal buffer when its size becomes too small.
dim strBuf as new StringBuffer
strBuf.init 10000 ' Set initial buffer size
strBuf.append "text"
strBuf.append "more text"
strBuf.append "even more text"
msgBox strBuf.value
msgBox strBuf ' Alternatively, use class's default member.
Source code
' vi: ft=vb
'
' V0.3
option explicit
private buf as string
private cur_len as long
public sub init(size as long) ' {
buf = space$(size)
cur_len = 0
end sub ' }
public sub append(text as string) ' {
dim next_len as long
next_len = cur_len + len(text)
if len(buf) < next_len then
dim cur_text as string
cur_text = value
buf = space$(next_len*2)
mid(buf, 1, next_len) = cur_text & text
cur_len = next_len
exit sub
end if
mid$(buf, 1+cur_len, next_len) = text
cur_len = next_len
end sub ' }
public function value as string ' {
attribute value.vb_UserMemId = 0
value = mid$(buf, 1, cur_len)
end function ' }
option explicit
sub testStringBuffer () ' {
dim sb as new StringBuffer : sb.init 5
sb.append "foo"
sb.append ", bar"
if sb <> "foo, bar" then
msgBox "Expected foo, bar, but got: " & sb
end if
sb.append " and baz. And quite a lot more!"
if sb.value <> "foo, bar and baz. And quite a lot more!" then ' {
msgBox sb.value
end if ' }
'
' StringBuffer V0.2: test default attribute:
'
if sb <> "foo, bar and baz. And quite a lot more!" then ' {
msgBox "Accessing default attribute did not succeed"
end if ' }
sb.append("<")
if sb <> "foo, bar and baz. And quite a lot more!<" then ' {
msgBox "trailing < not found"
end if ' }
timeIt
end sub ' }
private sub timeIt ' {
dim t0 as double
t0 = timer
dim i as long
dim str as string
for i = 1 to 25000
str = str & "abcdefghijklmnopqrstuvwxzy"
next i
debug.print "time string : " & format((timer - t0) / 86400, "hh:mm:ss")
t0 = timer
dim strBuf as new stringBuffer : strBuf.init (10000& * 26)
for i = 1 to 25000
strBuf.append "abcdefghijklmnopqrstuvwxzy"
next i
debug.print "time stringBuffer: " & format((timer - t0) / 86400, "hh:mm:ss")
if str <> strBuf.value then
msgBox "str <> strBuf.value"
end if
end sub ' }