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.904µs
41.982.436µs
31.591.955µs
21.011.239µs
11.001.231µs
Call 2
58.02613µs
42.16165µs
32.05157µs
21.2797µs
11.0076µs
Call 3
53.173.904µs
41.942.388µs
31.581.943µs
21.011.239µs
11.001.230µs
Call 4
58.62661µs
21.2092µs
41.2999µs
31.2696µs
11.0077µs
 VB6 Charts
CodeAuthorDopingNotes
UCase$ inline VB  
UCase02 DonaldAPI 
UCase03 DonaldTLB 
UCase04 DonaldAPI,TLB 
UCase05 PaulAPI,TLB 
Call 1
53.113.862µs
42.242.790µs
31.722.134µs
21.161.436µs
11.001.243µs
Call 2
58.07614µs
42.32177µs
31.94148µs
21.0782µs
11.0076µs
Call 3
53.203.858µs
42.292.751µs
31.792.154µs
21.191.432µs
11.001.204µs
Call 4
58.29614µs
41.78132µs
31.3197µs
21.1182µs
11.0074µs
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