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 >
Assembly Source File  |  1998-06-17  |  7KB  |  282 lines

  1.         page    ,132
  2.         title   strnicmp - compare n chars of strings, ignore case
  3. ;***
  4. ;strnicmp.asm - compare n chars of strings, ignoring case
  5. ;
  6. ;       Copyright (c) 1986-1997, Microsoft Corporation. All rights reserved.
  7. ;
  8. ;Purpose:
  9. ;       defines _strnicmp() - Compares at most n characters of two strings,
  10. ;       without regard to case.
  11. ;
  12. ;*******************************************************************************
  13.  
  14.         .xlist
  15.         include cruntime.inc
  16.         .list
  17.  
  18.  
  19. ifdef _MT
  20.  
  21. ; Def and decls necessary to assert the lock for the LC_CTYPE locale category
  22.  
  23. _SETLOCALE_LOCK EQU     19
  24.  
  25. extrn   _lock:proc
  26. extrn   _unlock:proc
  27.  
  28. endif  ; _MT
  29.  
  30. ; Defs and decl necessary to test for the C locale.
  31.  
  32. _CLOCALEHANDLE  EQU     0
  33. LC_CTYPE        EQU     2 * 4
  34.  
  35.  
  36. extrn   __lc_handle:dword
  37.  
  38. ifdef _MT
  39. extrn   __setlc_active:dword
  40. extrn   __unguarded_readlc_active:dword
  41. endif  ; _MT
  42.  
  43.  
  44.  
  45. ifdef _MT
  46. crt_tolower EQU _tolower_lk
  47. else  ; _MT
  48. crt_tolower EQU tolower
  49. endif  ; _MT
  50.  
  51.  
  52. extrn   crt_tolower:proc
  53.  
  54.  
  55. page
  56. ;***
  57. ;int _strnicmp(first, last, count) - compares count char of strings, ignore case
  58. ;
  59. ;Purpose:
  60. ;       Compare the two strings for lexical order.  Stops the comparison
  61. ;       when the following occurs: (1) strings differ, (2) the end of the
  62. ;       strings is reached, or (3) count characters have been compared.
  63. ;       For the purposes of the comparison, upper case characters are
  64. ;       converted to lower case.
  65. ;
  66. ;       Algorithm:
  67. ;       int
  68. ;       _strncmpi (first, last, count)
  69. ;             char *first, *last;
  70. ;             unsigned int count;
  71. ;             {
  72. ;             int f,l;
  73. ;             int result = 0;
  74. ;
  75. ;             if (count) {
  76. ;                     do      {
  77. ;                             f = tolower(*first);
  78. ;                             l = tolower(*last);
  79. ;                             first++;
  80. ;                             last++;
  81. ;                             } while (--count && f && l && f == l);
  82. ;                     result = f - l;
  83. ;                     }
  84. ;             return(result);
  85. ;             }
  86. ;
  87. ;Entry:
  88. ;       char *first, *last - strings to compare
  89. ;       unsigned count - maximum number of characters to compare
  90. ;
  91. ;Exit:
  92. ;       returns <0 if first < last
  93. ;       returns 0 if first == last
  94. ;       returns >0 if first > last
  95. ;
  96. ;Uses:
  97. ;
  98. ;Exceptions:
  99. ;
  100. ;*******************************************************************************
  101.  
  102.         CODESEG
  103.  
  104.         public  _strnicmp
  105. _strnicmp proc \
  106.         uses edi esi ebx, \
  107.         first:ptr byte, \
  108.         last:ptr byte, \
  109.         count:IWORD
  110.  
  111.         mov     ecx,[count]     ; cx = byte count
  112.         or      ecx,ecx
  113.         jz      toend           ; if count = 0, we are done
  114.  
  115.         mov     esi,[first]     ; si = first string
  116.         mov     edi,[last]      ; di = last string
  117.  
  118.         ; test locale
  119.  
  120.         lea     eax,__lc_handle
  121.         cmp     [eax + LC_CTYPE],_CLOCALEHANDLE
  122.  
  123.         jne     notclocale
  124.  
  125.         ; C locale
  126.  
  127.         mov     bh,'A'
  128.         mov     bl,'Z'
  129.         mov     dh,'a'-'A'      ; add to cap to make lower
  130.  
  131.         align   4
  132.  
  133. lupe:
  134.         mov     ah,[esi]        ; *first
  135.  
  136.         or      ah,ah           ; see if *first is null
  137.  
  138.         mov     al,[edi]        ; *last
  139.  
  140.         jz      short eject     ;   jump if *first is null
  141.  
  142.         or      al,al           ; see if *last is null
  143.         jz      short eject     ;   jump if so
  144.  
  145.         inc     esi             ; first++
  146.         inc     edi             ; last++
  147.  
  148.         cmp     ah,bh           ; 'A'
  149.         jb      short skip1
  150.  
  151.         cmp     ah,bl           ; 'Z'
  152.         ja      short skip1
  153.  
  154.         add     ah,dh           ; make lower case
  155.  
  156. skip1:
  157.         cmp     al,bh           ; 'A'
  158.         jb      short skip2
  159.  
  160.         cmp     al,bl           ; 'Z'
  161.         ja      short skip2
  162.  
  163.         add     al,dh           ; make lower case
  164.  
  165. skip2:
  166.         cmp     ah,al           ; *first == *last ??
  167.         jne     short differ
  168.  
  169.         dec     ecx
  170.         jnz     short lupe
  171.  
  172. eject:
  173.         xor     ecx,ecx
  174.         cmp     ah,al           ; compare the (possibly) differing bytes
  175.         je      toend           ; both zero; return 0
  176.  
  177. differ:
  178.         mov     ecx,-1          ; assume last is bigger (* can't use 'or' *)
  179.         jb      toend           ; last is, in fact, bigger (return -1)
  180.         neg     ecx             ; first is bigger (return 1)
  181.  
  182.         jmp     toend
  183.  
  184. notclocale:
  185.  
  186.         ; Not the C locale. Must call tolower/_tolower_lk to convert chars
  187.         ; to lower case.
  188.  
  189. ifdef _MT
  190. lock    inc     __unguarded_readlc_active   ; bump unguarded locale read flag
  191.         cmp     __setlc_active,0            ; is setlocale() active?
  192.         jg      short do_lock               ; yes, go assert lock
  193.         push    0                           ; local lock flag is 0
  194.         jmp     short end_lock
  195. do_lock:
  196. lock    dec     __unguarded_readlc_active   ; restore flag
  197.         mov     ebx,ecx                     ; save count in ebx
  198.         push    _SETLOCALE_LOCK
  199.         call    _lock
  200.         mov     [esp],1                     ; local lock flag is 1
  201.         mov     ecx,ebx                     ; restore count to ecx
  202. end_lock:
  203. endif  ; _MT
  204.  
  205.         xor     eax,eax
  206.         xor     ebx,ebx
  207.  
  208.         align   4
  209.  
  210. lupe2:
  211.         mov     al,[esi]        ; *first
  212.  
  213.         or      eax,eax         ; see if *first is null
  214.  
  215.         mov     bl,[edi]        ; *last
  216.  
  217.         jz      short eject2    ;   jump if *first is null
  218.  
  219.         or      ebx,ebx         ; see if *last is null
  220.         jz      short eject2    ;   jump if so
  221.  
  222.         inc     esi
  223.         inc     edi
  224.  
  225.         push    ecx             ; save ecx (holds count)
  226.         push    eax
  227.         push    ebx
  228.  
  229.         call    crt_tolower     ; convert *last
  230.  
  231.         mov     ebx,eax
  232.         add     esp,4
  233.  
  234.         call    crt_tolower     ; convert *first
  235.  
  236.         add     esp,4
  237.  
  238.         pop     ecx             ; restore ecx (count)
  239.  
  240.         cmp     eax,ebx
  241.         jne     short differ2
  242.  
  243.         dec     ecx
  244.         jnz     short lupe2
  245.  
  246. eject2:
  247.         xor     ecx,ecx
  248.         cmp     eax,ebx
  249.         je      short toend2
  250.  
  251. differ2:
  252.         mov     ecx,-1
  253.         jb      short toend2
  254.  
  255.         neg     ecx
  256.  
  257. toend2:
  258.  
  259. ifdef _MT
  260.         pop     eax                         ; get local lock flag
  261.         or      eax,eax                     ; lock held?
  262.         jnz     short do_unlock             ; yes
  263. lock    dec     __unguarded_readlc_active   ; decrement unguarded locale
  264.                                             ; read flag
  265.         jmp     short end_unlock
  266. do_unlock:
  267.         mov     ebx,ecx                     ; save return value in ebx
  268.         push    _SETLOCALE_LOCK
  269.         call    _unlock
  270.         add     esp,4
  271.         mov     ecx,ebx                     ; restore return value to ecx
  272. end_unlock:
  273. endif  ; _MT
  274.  
  275. toend:
  276.         mov     eax,ecx
  277.  
  278.         ret                     ; _cdecl return
  279.  
  280. _strnicmp endp
  281.          end
  282.