home *** CD-ROM | disk | FTP | other *** search
- 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
-