1 Attachment(s)
clsBSTR - the ultimate string class
This is the first "full" release of this class. You've probably sometimes heard of StringBuilder classes or about cString class that offer a better performance for concatenating strings. This class does this, but it does it much better than other classes of this kind, being both easy to use and fast. Besides concatenation there are many more features included within this class.
Sample syntaxes:
Code:
Dim strTemp As New clsBSTR
strTemp = "Hello!"
MsgBox strTemp
' output: the obvious
MsgBox strTemp.SetValue("this line has LOTS OF STUFF!").PCase
' output: "This Line Has Lots Of Stuff!"
MsgBox strTemp.SetValue("One?").Replicate(5)
' output: "One?One?One?One?One?"
strTemp = "AAABCCC"
strTemp.Middle(0, 3) = "_"
strTemp.Middle(strTemp.Length - 3, 3) = "_"
MsgBox strTemp
' output: "_B_"
strTemp = "ABC"
strTemp.Middle(2, 0) = "[surprise!]"
strTemp.Middle(1, 0) = "[a big]"
MsgBox strTemp
' output: "A[a big]B[surprise!]C"
strTemp = "1|2|3|2|1|4|5|6|9|8|7|8|9"
MsgBox strTemp.Trim "123789|"
' output: "4|5|6"
This isn't a final release of the class: there is room for new features and for further optimizations, although at this point of performance the latter isn't just as important.
This thread is open for feature requests and generic feedback. If you wish to talk about the optimization tricks or you have ideas on what could be done better, check the thread over at Code It Better forum.
Re: clsBSTR - the ultimate string class
Just saw this in your signature not too long ago. I've been using a simple concatenation class I found (clsConcat) but I think I like yours better, especially since it has more features.
I especially like the .Middle method. :cool:
Re: clsBSTR - the ultimate string class
Quite a good job Merri :) I am sure i will find use for it sometime ;)
Re: clsBSTR - the ultimate string class
This is pretty ambitious, though it has a pretty contorted set of methods and properties.
Why do so many return a reference to the same object? Was this meant as some aid to packing in multiple operations per line of code? Sort of like building a String expression or something?
For my own use I find concatentation the main thing to worry about with String performance. I'm not so sure I would accept the tradeoff of something this complicated just to improve the rarer operations somewhat.
If I need a reasonably fast "string builder" in VB 6 I simply use the ADO Stream object with it's Type set to "text." Benchmarks can be clumsy because once we get past using String concatenation itself most methods involve some fairly small timings, and most timers you can benchmark with have fairly lousy resolution.
Here's an example timed using VB Watch 2 (attached).
Contrary to what some people seem to think, the overhead of VB's For loops isn't bad at all. Of course timings are imprecise at these small values.
Re: clsBSTR - the ultimate string class
I tested compiled code with all advanced optimizations and both are pretty much of the same speed... until I made clsBSTR allocate a bit more space with BufferAllocSize :)
Code:
Option Explicit
Dim STRADD As String
Dim Q As clsTime
Private Sub Command1_Click()
Dim strOut As New ADODB.Stream, lngA As Long, strResult As String
Q.Start
strOut.Open
strOut.Type = adTypeText
For lngA = 1 To 10000
strOut.WriteText STRADD
Next lngA
strOut.Position = 0
strResult = strOut.ReadText
strOut.Close
Command1.Caption = "ADODB: (" & Len(strResult) & ") " & Format$(Q.GetTime * 1000, "0.000000")
End Sub
Private Sub Command2_Click()
Dim strResult As New clsBSTR, lngA As Long
Q.Start
strResult.BufferAllocSize = 1000000
For lngA = 1 To 10000
strResult.Append STRADD
Next lngA
Command2.Caption = "clsBSTR: (" & Len(strResult) & ") " & Format$(Q.GetTime * 1000, "0.000000")
End Sub
Private Sub Form_Load()
Set Q = New clsTime
STRADD = Space$(100)
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set Q = Nothing
End Sub
Code:
'clsTime.cls
Option Explicit
Private m_Freq As Double
Private m_Start As Currency
Private m_Stop As Currency
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As Currency) As Long
Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As Currency) As Long
Public Function GetRemainingSeconds(ByVal CurrentValue As Long, ByVal EndVal As Long) As Currency
Dim dblCurrent As Double
If CurrentValue < 1 Then CurrentValue = 1
If EndVal > CurrentValue Then
QueryPerformanceCounter m_Stop
dblCurrent = (CDbl(m_Stop - m_Start) / m_Freq)
GetRemainingSeconds = CCur((dblCurrent / CurrentValue * EndVal) - dblCurrent)
End If
End Function
Public Function GetTime() As Double
QueryPerformanceCounter m_Stop
GetTime = CDbl(m_Stop - m_Start) / m_Freq
End Function
Public Sub Start()
QueryPerformanceCounter m_Start
End Sub
Private Sub Class_Initialize()
Dim curFreq As Currency
QueryPerformanceFrequency curFreq
m_Freq = CDbl(curFreq)
End Sub
The result for ADODB in compiled is roughly one second on my machine, same for clsBSTR without changing allocation size, but with changed allocation it goes down to 6 ms. Under IDE it is at 15 ms.
As for returning the object itself as a return value, it doesn't give too much performance loss, but it does give something that I personally consider useful (although concatenating short strings is faster to do with native strings).
You can compile the class and the module into a DLL and make a reference to it: you get faster concatenation than with ADODB and you don't need a reference to it (of course, if you're already using ADODB for something else then it doesn't matter so much). ADODB method requires many extra lines to get the job done (Open, Type, Position, Close), which is something I also wanted to avoid. You can make the class lightweight by removing the features you don't need.
Re: clsBSTR - the ultimate string class
How do you get operators in VB6 classes?
Re: clsBSTR - the ultimate string class
Does this class build a string from a byte array?
Re: clsBSTR - the ultimate string class
No. It holds data it in an Integer array, but it also keeps a custom String variable holding the information for fast access when required. For example there are no conversions done when you get the current data of the class:
Code:
' get string
Public Property Get Value() As String
Value = CharStr
End Property
A direct copypaste from the class.
The string variable (CharStr) is "faked" to point to the data Integer array holds. In the other hand, the Integer array has some extra buffer in both sides of the data, thus making Append and Prepend much faster, so there is less need for constant space allocation when adding data. BufferAllocSize controls how much space is reserved on both sides of the data when allocation must done.