home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Windows Gam…ming Gurus (2nd Edition)
/
Disc2.iso
/
vc98
/
crt
/
src
/
platform
/
strnicmp.asm
< prev
next >
Wrap
Assembly Source File
|
1998-06-17
|
7KB
|
282 lines
page ,132
title strnicmp - compare n chars of strings, ignore case
;***
;strnicmp.asm - compare n chars of strings, ignoring case
;
; Copyright (c) 1986-1997, Microsoft Corporation. All rights reserved.
;
;Purpose:
; defines _strnicmp() - Compares at most n characters of two strings,
; without regard to case.
;
;*******************************************************************************
.xlist
include cruntime.inc
.list
ifdef _MT
; Def and decls necessary to assert the lock for the LC_CTYPE locale category
_SETLOCALE_LOCK EQU 19
extrn _lock:proc
extrn _unlock:proc
endif ; _MT
; Defs and decl necessary to test for the C locale.
_CLOCALEHANDLE EQU 0
LC_CTYPE EQU 2 * 4
extrn __lc_handle:dword
ifdef _MT
extrn __setlc_active:dword
extrn __unguarded_readlc_active:dword
endif ; _MT
ifdef _MT
crt_tolower EQU _tolower_lk
else ; _MT
crt_tolower EQU tolower
endif ; _MT
extrn crt_tolower:proc
page
;***
;int _strnicmp(first, last, count) - compares count char of strings, ignore case
;
;Purpose:
; Compare the two strings for lexical order. Stops the comparison
; when the following occurs: (1) strings differ, (2) the end of the
; strings is reached, or (3) count characters have been compared.
; For the purposes of the comparison, upper case characters are
; converted to lower case.
;
; Algorithm:
; int
; _strncmpi (first, last, count)
; char *first, *last;
; unsigned int count;
; {
; int f,l;
; int result = 0;
;
; if (count) {
; do {
; f = tolower(*first);
; l = tolower(*last);
; first++;
; last++;
; } while (--count && f && l && f == l);
; result = f - l;
; }
; return(result);
; }
;
;Entry:
; char *first, *last - strings to compare
; unsigned count - maximum number of characters to compare
;
;Exit:
; returns <0 if first < last
; returns 0 if first == last
; returns >0 if first > last
;
;Uses:
;
;Exceptions:
;
;*******************************************************************************
CODESEG
public _strnicmp
_strnicmp proc \
uses edi esi ebx, \
first:ptr byte, \
last:ptr byte, \
count:IWORD
mov ecx,[count] ; cx = byte count
or ecx,ecx
jz toend ; if count = 0, we are done
mov esi,[first] ; si = first string
mov edi,[last] ; di = last string
; test locale
lea eax,__lc_handle
cmp [eax + LC_CTYPE],_CLOCALEHANDLE
jne notclocale
; C locale
mov bh,'A'
mov bl,'Z'
mov dh,'a'-'A' ; add to cap to make lower
align 4
lupe:
mov ah,[esi] ; *first
or ah,ah ; see if *first is null
mov al,[edi] ; *last
jz short eject ; jump if *first is null
or al,al ; see if *last is null
jz short eject ; jump if so
inc esi ; first++
inc edi ; last++
cmp ah,bh ; 'A'
jb short skip1
cmp ah,bl ; 'Z'
ja short skip1
add ah,dh ; make lower case
skip1:
cmp al,bh ; 'A'
jb short skip2
cmp al,bl ; 'Z'
ja short skip2
add al,dh ; make lower case
skip2:
cmp ah,al ; *first == *last ??
jne short differ
dec ecx
jnz short lupe
eject:
xor ecx,ecx
cmp ah,al ; compare the (possibly) differing bytes
je toend ; both zero; return 0
differ:
mov ecx,-1 ; assume last is bigger (* can't use 'or' *)
jb toend ; last is, in fact, bigger (return -1)
neg ecx ; first is bigger (return 1)
jmp toend
notclocale:
; Not the C locale. Must call tolower/_tolower_lk to convert chars
; to lower case.
ifdef _MT
lock inc __unguarded_readlc_active ; bump unguarded locale read flag
cmp __setlc_active,0 ; is setlocale() active?
jg short do_lock ; yes, go assert lock
push 0 ; local lock flag is 0
jmp short end_lock
do_lock:
lock dec __unguarded_readlc_active ; restore flag
mov ebx,ecx ; save count in ebx
push _SETLOCALE_LOCK
call _lock
mov [esp],1 ; local lock flag is 1
mov ecx,ebx ; restore count to ecx
end_lock:
endif ; _MT
xor eax,eax
xor ebx,ebx
align 4
lupe2:
mov al,[esi] ; *first
or eax,eax ; see if *first is null
mov bl,[edi] ; *last
jz short eject2 ; jump if *first is null
or ebx,ebx ; see if *last is null
jz short eject2 ; jump if so
inc esi
inc edi
push ecx ; save ecx (holds count)
push eax
push ebx
call crt_tolower ; convert *last
mov ebx,eax
add esp,4
call crt_tolower ; convert *first
add esp,4
pop ecx ; restore ecx (count)
cmp eax,ebx
jne short differ2
dec ecx
jnz short lupe2
eject2:
xor ecx,ecx
cmp eax,ebx
je short toend2
differ2:
mov ecx,-1
jb short toend2
neg ecx
toend2:
ifdef _MT
pop eax ; get local lock flag
or eax,eax ; lock held?
jnz short do_unlock ; yes
lock dec __unguarded_readlc_active ; decrement unguarded locale
; read flag
jmp short end_unlock
do_unlock:
mov ebx,ecx ; save return value in ebx
push _SETLOCALE_LOCK
call _unlock
add esp,4
mov ecx,ebx ; restore return value to ecx
end_unlock:
endif ; _MT
toend:
mov eax,ecx
ret ; _cdecl return
_strnicmp endp
end