VBspeed / Language / UCase
VBspeed © 2000-10, updated: 09-Dec-2001
UCase


UCase
Visual Basic provides the UCase$ and LCase$ functions for changing case. These are smart functions that follow the rules and work correctly regardless of the language. Alas, with computers (and brains...), smart means slow. If you are a eurocentric ANSI kind of guy, the power of the native case changers is wasted on you. What you need is something fast!
Emulating UCase/LCase is straightforward stuff. If it weren't for the Stooges...
Use this function (VB5/6-compatible) to verify the correctness of your emulation code (ANSI UCase).
Code
UCase$ inline sRet = UCase$(sDum1)
UCase02
Public Function UCase02(ByRef sString As String) As String
' by Donald, donald@xbeat.net, 20011209
    Static saDst As SafeArray1D
    Static aDst%()
    Static pDst&, psaDst&
    Static init As Long
    Dim C As Long
    Dim lLen As Long
    Static iLUT(0 To 400) As Integer
    
    If init Then
    Else
        saDst.cDims = 1
        saDst.cbElements = 2
        saDst.cElements = &H7FFFFFFF
        
        pDst = VarPtr(saDst)
        psaDst = ArrPtr(aDst)
        
        ' init LUT
        For C = 0 To 255: iLUT(C) = AscW(UCase$(Chr$(C))): Next
        For C = 256 To 400: iLUT(C) = C: Next
        iLUT(353) = 352
        iLUT(339) = 338
        iLUT(382) = 381
        
        init = 1
    End If
    
    lLen = Len(sString)
    RtlMoveMemory ByVal VarPtr(UCase02), _
        SysAllocStringByteLen(StrPtr(sString), lLen + lLen), 4
    saDst.pvData = StrPtr(UCase02)
    RtlMoveMemory ByVal psaDst, pDst, 4
    
    For C = 0 To lLen - 1
      Select Case aDst(C)
      Case 97 To 382
        aDst(C) = iLUT(aDst(C))
      End Select
    Next
    
    RtlMoveMemory ByVal psaDst, 0&, 4
    
End Function
  
UCase03
Public Function UCase03(ByRef sString As String) As String
' by Donald, donald@xbeat.net, 20011209 (TLB-ed UCase02)
    Static saDst As BStrAPI.SafeArray1D
    Static aDst%()
    Static pDst&, psaDst&
    Static init As Long
    Dim C As Long
    Dim lLen As Long
    Static iLUT(0 To 400) As Integer
    
    If init Then
    Else
        saDst.cDims = 1
        saDst.cbElements = 2
        saDst.cElements1D = &H7FFFFFFF
        
        pDst = VarPtr(saDst)
        psaDst = ArrPtr(aDst)
        
        ' init LUT
        For C = 0 To 255: iLUT(C) = AscW(UCase$(Chr$(C))): Next
        For C = 256 To 400: iLUT(C) = C: Next
        iLUT(353) = 352
        iLUT(339) = 338
        iLUT(382) = 381
        
        init = 1
    End If
    
    lLen = Len(sString)
    UCase03 = BStrAPI.SysAllocStringLenPtr(ByVal StrPtr(sString), lLen)
    saDst.pvData = StrPtr(UCase03)
    FastString.RtlMoveMemory ByVal psaDst, pDst
    
    For C = 0 To lLen - 1
      Select Case aDst(C)
      Case 97 To 382
        aDst(C) = iLUT(aDst(C))
      End Select
    Next
    
    FastString.RtlMoveMemory ByVal psaDst, 0&
    
End Function
UCase04 UCase04/LCase04 is class-wrapped. Cinemascope here, preview here:

UCase05 UCase05/LCase05 is class-wrapped.
Find it inside the UCase04/LCase04 class above.
Update your TypeLibs: new FastString.
Calls
sRet = UCaseXX(sDum1)
1sDum1 = "hey"
2sDum1 = Replicate(50, "If any band epitomised the 70's, it was Sweet. ")
3sDum1 = "HEY"
4sDum1 = Replicate(50, "IF ANY BAND EPITOMISED THE 70'S, IT WAS SWEET. ")
Charts How to read all those numbers
 VB5 Charts
CodeAuthorDopingNotes
UCase$ inline VB  
UCase02 DonaldAPI 
UCase03 DonaldTLB 
UCase04 DonaldAPI,TLB 
UCase05 PaulAPI,TLB 
Call 1
53.173.904s
41.982.436s
31.591.955s
21.011.239s
11.001.231s
Call 2
58.02613s
42.16165s
32.05157s
21.2797s
11.0076s
Call 3
53.173.904s
41.942.388s
31.581.943s
21.011.239s
11.001.230s
Call 4
58.62661s
21.2092s
41.2999s
31.2696s
11.0077s
 VB6 Charts
CodeAuthorDopingNotes
UCase$ inline VB  
UCase02 DonaldAPI 
UCase03 DonaldTLB 
UCase04 DonaldAPI,TLB 
UCase05 PaulAPI,TLB 
Call 1
53.113.862s
42.242.790s
31.722.134s
21.161.436s
11.001.243s
Call 2
58.07614s
42.32177s
31.94148s
21.0782s
11.0076s
Call 3
53.203.858s
42.292.751s
31.792.154s
21.191.432s
11.001.204s
Call 4
58.29614s
41.78132s
31.3197s
21.1182s
11.0074s
Conclusions
...
NOTES
The Stooges.
A bunch of upper ANSI chars is handled by VB in a surprising manner. For example, Chr$(154) returns "". Now when you ask for Asc("") you get 154, so far so good. But AscW("") gives you 353: no zero in the upper unicode half! So VB internally translated 154 (hex 00 9A) into 353 (hex 01 61). You have to know this if you want to emulate ANSI UCase/LCase. Here is a list of ANSI chars with unicode twins, the stooges:
' UCase Stooges
'  154 / 353                138 / 352
'  156 / 339                140 / 338
'  158 / 382                142 / 381
'  255 / 255                159 / 376
' LCase Stooges
'  138 / 352                154 / 353
'  140 / 338                156 / 339
'  142 / 381                158 / 382
'  159 / 376                255 / 255
This function will print the above to your debug window:
Got comments?

top




VBspeed © 2000-10 by Donald Lessau