Here's also an ASM version you can try
Code: Select all
EnableExplicit
Global Inc.l, FirstTick, Word.s, EventId.l, TicksTaken.l
Procedure.s MakeLowerCase(*String)
Dim buffer.c(MemoryStringLength(*String) << 1 + 1)
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
!mov ecx, [p.p_String]
!mov edx, [p.a_buffer]
!lcase_translation_loop:
CompilerIf #PB_Compiler_Unicode
!movzx eax, word [ecx]
!add ecx, 2
!test ah, ah
!jnz lcase_translation_cont1
!mov ax, [lcase_translation_table + eax * 2]
!test ah, ah
!jz lcase_translation_cont2
!mov [edx], al
!mov [edx + 2], ah
!add edx, 4
!jmp lcase_translation_loop
!lcase_translation_cont1:
!mov [edx], ax
!add edx, 2
!jmp lcase_translation_loop
!lcase_translation_cont2:
!mov [edx], al
!add edx, 2
CompilerElse
!movzx eax, byte [ecx]
!inc ecx
!mov ax, [lcase_translation_table + eax * 2]
!mov [edx], ax
!neg ah
!adc edx, 1
CompilerEndIf
CompilerElse
!lea r8, [lcase_translation_table]
!mov rcx, [p.p_String]
!mov rdx, [p.a_buffer]
!lcase_translation_loop:
CompilerIf #PB_Compiler_Unicode
!movzx eax, word [rcx]
!add rcx, 2
!test ah, ah
!jnz lcase_translation_cont1
!mov ax, [r8 + rax * 2]
!test ah, ah
!jz lcase_translation_cont2
!mov [rdx], al
!mov [rdx + 2], ah
!add rdx, 4
!jmp lcase_translation_loop
!lcase_translation_cont1:
!mov [rdx], ax
!add rdx, 2
!jmp lcase_translation_loop
!lcase_translation_cont2:
!mov [rdx], al
!add rdx, 2
CompilerElse
!movzx eax, byte [rcx]
!inc rcx
!mov ax, [r8 + rax * 2]
!mov [rdx], ax
!neg ah
!adc rdx, 1
CompilerEndIf
CompilerEndIf
!test al, al
!jnz lcase_translation_loop
ProcedureReturn PeekS(@buffer())
!align 16
!lcase_translation_table:
!dw 0x00,0x01,0x02,0x03,0x04,0x05,0x06 ,0x07,0x08,0x09,0x0A,0x0B,0x0C ,0x0D,0x0E,0x0F
!dw 0x10,0x11,0x12,0x13,0x14,0x15,0x16 ,0x17,0x18,0x19,0x1A,0x1B,0x1C ,0x1D,0x1E,0x1F
!dw 0x20,0x21,0x22,0x23,0x24,0x25,0x26 ,0x27,0x28,0x29,0x2A,0x2B,0x2C ,0x20,0x2E,0x2F
!dw 0x30,0x31,0x32,0x33,0x34,0x35,0x36 ,0x37,0x38,0x39,0x3A,0x3B,0x3C ,0x3D,0x3E,0x3F
!dw 0x40,0x61,0x62,0x63,0x64,0x65,0x66 ,0x67,0x68,0x69,0x6A,0x6B,0x6C ,0x6D,0x6E,0x6F
!dw 0x70,0x71,0x72,0x73,0x74,0x75,0x76 ,0x77,0x78,0x79,0x7A,0x5B,0x5C ,0x5D,0x5E,0x5F
!dw 0x60,0x61,0x62,0x63,0x64,0x65,0x66 ,0x67,0x68,0x69,0x6A,0x6B,0x6C ,0x6D,0x6E,0x6F
!dw 0x70,0x71,0x72,0x73,0x74,0x75,0x76 ,0x77,0x78,0x79,0x7A,0x7B,0x7C ,0x7D,0x7E,0x7F
!dw 0x80,0x81,0x82,0x83,0x84,0x85,0x86 ,0x87,0x88,0x89,0x73,0x8B,0x656F,0x8D,0x7A,0x8F
!dw 0x90,0x27,0x27,0x22,0x22,0x95,0x96 ,0x97,0x98,0x99,0x73,0x9B,0x656F,0x9D,0x7A,0x79
!dw 0x20,0xA1,0xA2,0xA3,0xA4,0x79,0xA6 ,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC ,0xAD,0xAE,0xAF
!dw 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6 ,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC ,0xBD,0xBE,0xBF
!dw 0x61,0x61,0x61,0x61,0x61,0x61,0x6561,0x63,0x65,0x65,0x65,0x65,0x69 ,0x69,0x69,0x69
!dw 0x64,0x6E,0x6F,0x6F,0x6F,0x6F,0x6F ,0xD7,0x6F,0x75,0x75,0x75,0x75 ,0x79,0xDE,0x7373
!dw 0x61,0x61,0x61,0x61,0x61,0x61,0x6561,0x63,0x65,0x65,0x65,0x65,0x69 ,0x69,0x69,0x69
!dw 0xF0,0x6E,0x6F,0x6F,0x6F,0x6F,0x6F ,0xF7,0x6F,0x75,0x75,0x75,0x75 ,0x79,0xFE,0x79
EndProcedure
Word = "ÆXAMPLE ßTRING"
If OpenWindow(0, 20, 20, 400, 300, "Lower Case")
TextGadget(0, 20, 20, 250, 18, "Original String: " + Word)
TextGadget(1, 20, 40, 250, 18, "Lower case String: " + MakeLowerCase(@Word))
TextGadget(2, 20, 60, 250, 18, "")
FirstTick = GetTickCount_()
For Inc = 1 To 1000000
MakeLowerCase(@Word)
Next
TicksTaken = GetTickCount_() - FirstTick
SetGadgetText(2, "Time Taken: " + Str(TicksTaken))
Repeat
EventId = WaitWindowEvent()
Until EventId = #PB_Event_CloseWindow
CloseWindow(0)
EndIf
Here's a version with a static buffer that can be used if the source string has less than 16384 characters.
Code: Select all
EnableExplicit
Global Inc.l, FirstTick, Word.s, EventId.l, TicksTaken.l
Procedure.s MakeLowerCase_S(*String)
Static Dim buffer.c(16384)
Protected *buffer = @buffer()
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
!mov ecx, [p.p_String]
!mov edx, [p.p_buffer]
!lcase_s_translation_loop:
CompilerIf #PB_Compiler_Unicode
!movzx eax, word [ecx]
!add ecx, 2
!test ah, ah
!jnz lcase_s_translation_cont1
!mov ax, [lcase_s_translation_table + eax * 2]
!test ah, ah
!jz lcase_s_translation_cont2
!shl eax, 8
!shr ax, 8
!mov [edx], eax
!add edx, 4
!jmp lcase_s_translation_loop
!lcase_s_translation_cont1:
!mov [edx], ax
!add edx, 2
!jmp lcase_s_translation_loop
!lcase_s_translation_cont2:
!mov [edx], ax
!add edx, 2
CompilerElse
!movzx eax, byte [ecx]
!inc ecx
!mov ax, [lcase_s_translation_table + eax * 2]
!mov [edx], ax
!neg ah
!adc edx, 1
CompilerEndIf
CompilerElse
!lea r8, [lcase_s_translation_table]
!mov rcx, [p.p_String]
!mov rdx, [p.p_buffer]
!lcase_s_translation_loop:
CompilerIf #PB_Compiler_Unicode
!movzx eax, word [rcx]
!add rcx, 2
!test ah, ah
!jnz lcase_s_translation_cont1
!mov ax, [r8 + rax * 2]
!test ah, ah
!jz lcase_s_translation_cont2
!shl eax, 8
!shr ax, 8
!mov [rdx], eax
!add rdx, 4
!jmp lcase_s_translation_loop
!lcase_s_translation_cont1:
!mov [rdx], ax
!add rdx, 2
!jmp lcase_s_translation_loop
!lcase_s_translation_cont2:
!mov [rdx], ax
!add rdx, 2
CompilerElse
!movzx eax, byte [rcx]
!inc rcx
!mov ax, [r8 + rax * 2]
!mov [rdx], ax
!neg ah
!adc rdx, 1
CompilerEndIf
CompilerEndIf
!test al, al
!jnz lcase_s_translation_loop
ProcedureReturn PeekS(@buffer())
!align 16
!lcase_s_translation_table:
!dw 0x00,0x01,0x02,0x03,0x04,0x05,0x06 ,0x07,0x08,0x09,0x0A,0x0B,0x0C ,0x0D,0x0E,0x0F
!dw 0x10,0x11,0x12,0x13,0x14,0x15,0x16 ,0x17,0x18,0x19,0x1A,0x1B,0x1C ,0x1D,0x1E,0x1F
!dw 0x20,0x21,0x22,0x23,0x24,0x25,0x26 ,0x27,0x28,0x29,0x2A,0x2B,0x2C ,0x20,0x2E,0x2F
!dw 0x30,0x31,0x32,0x33,0x34,0x35,0x36 ,0x37,0x38,0x39,0x3A,0x3B,0x3C ,0x3D,0x3E,0x3F
!dw 0x40,0x61,0x62,0x63,0x64,0x65,0x66 ,0x67,0x68,0x69,0x6A,0x6B,0x6C ,0x6D,0x6E,0x6F
!dw 0x70,0x71,0x72,0x73,0x74,0x75,0x76 ,0x77,0x78,0x79,0x7A,0x5B,0x5C ,0x5D,0x5E,0x5F
!dw 0x60,0x61,0x62,0x63,0x64,0x65,0x66 ,0x67,0x68,0x69,0x6A,0x6B,0x6C ,0x6D,0x6E,0x6F
!dw 0x70,0x71,0x72,0x73,0x74,0x75,0x76 ,0x77,0x78,0x79,0x7A,0x7B,0x7C ,0x7D,0x7E,0x7F
!dw 0x80,0x81,0x82,0x83,0x84,0x85,0x86 ,0x87,0x88,0x89,0x73,0x8B,0x656F,0x8D,0x7A,0x8F
!dw 0x90,0x27,0x27,0x22,0x22,0x95,0x96 ,0x97,0x98,0x99,0x73,0x9B,0x656F,0x9D,0x7A,0x79
!dw 0x20,0xA1,0xA2,0xA3,0xA4,0x79,0xA6 ,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC ,0xAD,0xAE,0xAF
!dw 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6 ,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC ,0xBD,0xBE,0xBF
!dw 0x61,0x61,0x61,0x61,0x61,0x61,0x6561,0x63,0x65,0x65,0x65,0x65,0x69 ,0x69,0x69,0x69
!dw 0x64,0x6E,0x6F,0x6F,0x6F,0x6F,0x6F ,0xD7,0x6F,0x75,0x75,0x75,0x75 ,0x79,0xDE,0x7373
!dw 0x61,0x61,0x61,0x61,0x61,0x61,0x6561,0x63,0x65,0x65,0x65,0x65,0x69 ,0x69,0x69,0x69
!dw 0xF0,0x6E,0x6F,0x6F,0x6F,0x6F,0x6F ,0xF7,0x6F,0x75,0x75,0x75,0x75 ,0x79,0xFE,0x79
EndProcedure
Word = "ÆXAMPLE ßTRING"
If OpenWindow(0, 20, 20, 400, 300, "Lower Case")
TextGadget(0, 20, 20, 250, 18, "Original String: " + Word)
TextGadget(1, 20, 40, 250, 18, "Lower case String: " + MakeLowerCase_S(@Word))
TextGadget(2, 20, 60, 250, 18, "")
FirstTick = GetTickCount_()
For Inc = 1 To 1000000
MakeLowerCase_S(@Word)
Next
TicksTaken = GetTickCount_() - FirstTick
SetGadgetText(2, "Time Taken: " + Str(TicksTaken))
Repeat
EventId = WaitWindowEvent()
Until EventId = #PB_Event_CloseWindow
CloseWindow(0)
EndIf