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


LCase
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 LCase).
Code
LCase$ inline sRet = LCase$(sDum1)
LCase02
Public Function LCase02(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(LCase$(Chr$(c))): Next
        For c = 256 To 400: iLUT(c) = c: Next
        iLUT(352) = 353
        iLUT(338) = 339
        iLUT(381) = 382
        iLUT(376) = 255
        
        init = 1
    End If
    
    lLen = Len(sString)
    RtlMoveMemory ByVal VarPtr(LCase02), _
        SysAllocStringByteLen(StrPtr(sString), lLen + lLen), 4
    saDst.pvData = StrPtr(LCase02)
    RtlMoveMemory ByVal psaDst, pDst, 4
    
    For c = 0 To lLen - 1
      Select Case aDst(c)
      Case 65 To 381
        aDst(c) = iLUT(aDst(c))
      End Select
    Next
    
    RtlMoveMemory ByVal psaDst, 0&, 4
    
End Function
  
LCase03
Public Function LCase03(ByRef sString As String) As String
' by Donald, donald@xbeat.net, 20011209 (TLB-ed LCase02)
    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(LCase$(Chr$(c))): Next
        For c = 256 To 400: iLUT(c) = c: Next
        iLUT(352) = 353
        iLUT(338) = 339
        iLUT(381) = 382
        iLUT(376) = 255
        
        init = 1
    End If
    
    lLen = Len(sString)
    LCase03 = BStrAPI.SysAllocStringLenPtr(ByVal StrPtr(sString), lLen)
    saDst.pvData = StrPtr(LCase03)
    FastString.RtlMoveMemory ByVal psaDst, pDst
    
    For c = 0 To lLen - 1
      Select Case aDst(c)
      Case 65 To 381
        aDst(c) = iLUT(aDst(c))
      End Select
    Next
    
    FastString.RtlMoveMemory ByVal psaDst, 0&
    
End Function
LCase04 UCase04/LCase04 is class-wrapped. Cinemascope here, preview here:

LCase05 UCase05/LCase05 is class-wrapped.
Find it inside the UCase04/LCase04 class above.
Update your TypeLibs: new FastString.
Calls
sRet = LCaseXX(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
LCase$ inline VB  
LCase02 DonaldAPI 
LCase03 DonaldTLB 
LCase04 DonaldAPI,TLB 
LCase05 PaulAPI,TLB 
Call 1
52.993.622µs
41.942.353µs
31.581.914µs
21.061.281µs
11.001.213µs
Call 2
58.48641µs
31.73131µs
42.00151µs
21.1285µs
11.0076µs
Call 3
53.023.587µs
41.972.340µs
31.631.935µs
21.071.276µs
11.001.188µs
Call 4
58.19640µs
31.68132µs
41.95153µs
21.0884µs
11.0078µs
 VB6 Charts
CodeAuthorDopingNotes
LCase$ inline VB  
LCase02 DonaldAPI 
LCase03 DonaldTLB 
LCase04 DonaldAPI,TLB 
LCase05 PaulAPI,TLB 
Call 1
53.053.814µs
42.402.995µs
31.762.197µs
21.121.404µs
11.001.250µs
Call 2
58.36639µs
31.77135µs
41.97151µs
21.0983µs
11.0076µs
Call 3
53.103.778µs
42.432.960µs
31.812.201µs
21.101.334µs
11.001.217µs
Call 4
58.55639µs
31.79134µs
42.00149µs
21.1183µs
11.0075µ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