home *** CD-ROM | disk | FTP | other *** search
- /***
- *a_cmp.c - A version of CompareString.
- *
- * Copyright (c) 1993-1997, Microsoft Corporation. All rights reserved.
- *
- *Purpose:
- * Use either CompareStringA or CompareStringW depending on which is
- * available
- *
- *******************************************************************************/
-
- #include <cruntime.h>
- #include <internal.h>
- #include <dbgint.h>
- #include <stdlib.h>
- #include <setlocal.h>
- #include <awint.h>
- #include <dbgint.h>
-
- #define USE_W 1
- #define USE_A 2
-
- /***
- *int __cdecl strncnt - count characters in a string, up to n.
- *
- *Purpose:
- * Internal local support function. Counts characters in string before NULL.
- * If NULL not found in n chars, then return n.
- *
- *Entry:
- * const char *string - start of string
- * int n - byte count
- *
- *Exit:
- * returns number of bytes from start of string to
- * NULL (exclusive), up to n.
- *
- *Exceptions:
- *
- *******************************************************************************/
-
- static int __cdecl strncnt (
- const char *string,
- int cnt
- )
- {
- int n = cnt;
- char *cp = (char *)string;
-
- while (n-- && *cp)
- cp++;
-
- if (!*cp)
- return cp - string;
- return cnt;
- }
-
- /***
- *int __cdecl __crtCompareStringA - Get type information about an ANSI string.
- *
- *Purpose:
- * Internal support function. Assumes info in ANSI string format. Tries
- * to use NLS API call CompareStringA if available and uses CompareStringW
- * if it must. If neither are available it fails and returns 0.
- *
- *Entry:
- * LCID Locale - locale context for the comparison.
- * DWORD dwCmpFlags - see NT\Chicago docs
- * LPCSTR lpStringn - multibyte string to be compared
- * int cchCountn - char (byte) count (NOT including NULL)
- * (-1 if NULL terminated)
- * int code_page - for MB/WC conversion. If 0, use __lc_codepage
- *
- *Exit:
- * Success: 1 - if lpString1 < lpString2
- * 2 - if lpString1 == lpString2
- * 3 - if lpString1 > lpString2
- * Failure: 0
- *
- *Exceptions:
- *
- *******************************************************************************/
-
- int __cdecl __crtCompareStringA(
- LCID Locale,
- DWORD dwCmpFlags,
- LPCSTR lpString1,
- int cchCount1,
- LPCSTR lpString2,
- int cchCount2,
- int code_page
- )
- {
- static int f_use = 0;
-
- /*
- * Look for unstubbed 'preferred' flavor. Otherwise use available flavor.
- * Must actually call the function to ensure it's not a stub.
- * (Always try wide version first so WinNT can process codepage correctly.)
- */
-
- if (0 == f_use)
- {
- if (0 != CompareStringW(0, 0, L"\0", 1, L"\0", 1))
- f_use = USE_W;
-
- else if (0 != CompareStringA(0, 0, "\0", 1, "\0", 1))
- f_use = USE_A;
-
- else
- return 0;
- }
-
- /*
- * CompareString will compare past NULL. Must find NULL if in string
- * before cchCountn chars.
- */
-
- if (cchCount1 > 0)
- cchCount1 = strncnt(lpString1, cchCount1);
- if (cchCount2 > 0)
- cchCount2 = strncnt(lpString2, cchCount2);
-
- /* Use "A" version */
-
- if (USE_A == f_use)
- {
- return CompareStringA( Locale,
- dwCmpFlags,
- lpString1,
- cchCount1,
- lpString2,
- cchCount2 );
- }
-
- /* Use "W" version */
-
- if (USE_W == f_use)
- {
- int buff_size1;
- int buff_size2;
- wchar_t *wbuffer1;
- wchar_t *wbuffer2;
-
- /*
- * Use __lc_codepage for conversion if code_page not specified
- */
-
- if (0 == code_page)
- code_page = __lc_codepage;
-
- /*
- * Special case: at least one count is zero
- */
-
- if (!cchCount1 || !cchCount2)
- {
- unsigned char *cp; // char pointer
- CPINFO lpCPInfo; // struct for use with GetCPInfo
-
- /* both strings zero */
- if (cchCount1 == cchCount2)
- return 2;
-
- /* string 1 greater */
- if (cchCount2 > 1)
- return 1;
-
- /* string 2 greater */
- if (cchCount1 > 1)
- return 3;
-
- /*
- * one has zero count, the other has a count of one
- * - if the one count is a naked lead byte, the strings are equal
- * - otherwise it is a single character and they are unequal
- */
-
- if (GetCPInfo(code_page, &lpCPInfo) == FALSE)
- return 0;
-
- _ASSERTE(cchCount1==0 && cchCount2==1 || cchCount1==1 && cchCount2==0);
-
- /* string 1 has count of 1 */
- if (cchCount1 > 0)
- {
- if (lpCPInfo.MaxCharSize < 2)
- return 3;
-
- for ( cp = (unsigned char *)lpCPInfo.LeadByte ;
- cp[0] && cp[1] ;
- cp += 2 )
- if ( (*(unsigned char *)lpString1 >= cp[0]) &&
- (*(unsigned char *)lpString1 <= cp[1]) )
- return 2;
-
- return 3;
- }
-
- /* string 2 has count of 1 */
- if (cchCount2 > 0)
- {
- if (lpCPInfo.MaxCharSize < 2)
- return 1;
-
- for ( cp = (unsigned char *)lpCPInfo.LeadByte ;
- cp[0] && cp[1] ;
- cp += 2 )
- if ( (*(unsigned char *)lpString2 >= cp[0]) &&
- (*(unsigned char *)lpString2 <= cp[1]) )
- return 2;
-
- return 1;
- }
- }
-
- /*
- * Convert strings and return the requested information.
- */
-
- /* find out how big a buffer we need (includes NULL if any) */
- if ( 0 == (buff_size1 = MultiByteToWideChar( code_page,
- MB_PRECOMPOSED |
- MB_ERR_INVALID_CHARS,
- lpString1,
- cchCount1,
- NULL,
- 0 )) )
- return 0;
-
- /* allocate enough space for chars */
- __try {
- wbuffer1 = (wchar_t *)_alloca( buff_size1 * sizeof(wchar_t) );
- }
- __except( EXCEPTION_EXECUTE_HANDLER ) {
- wbuffer1 = NULL;
- }
-
- if ( wbuffer1 == NULL )
- return 0;
-
- /* do the conversion */
- if ( 0 == MultiByteToWideChar( code_page,
- MB_PRECOMPOSED,
- lpString1,
- cchCount1,
- wbuffer1,
- buff_size1 ) )
- return 0;
-
- /* find out how big a buffer we need (includes NULL if any) */
- if ( 0 == (buff_size2 = MultiByteToWideChar( code_page,
- MB_PRECOMPOSED |
- MB_ERR_INVALID_CHARS,
- lpString2,
- cchCount2,
- NULL,
- 0 )) )
- return 0;
-
- /* allocate enough space for chars */
- __try {
- wbuffer2 = (wchar_t *)_alloca( buff_size2 * sizeof(wchar_t) );
- }
- __except( EXCEPTION_EXECUTE_HANDLER ) {
- wbuffer2 = NULL;
- }
-
- if ( wbuffer2 == NULL )
- return 0;
-
- /* do the conversion */
- if ( 0 == MultiByteToWideChar( code_page,
- MB_PRECOMPOSED,
- lpString2,
- cchCount2,
- wbuffer2,
- buff_size2 ) )
- return 0;
-
- return CompareStringW( Locale,
- dwCmpFlags,
- wbuffer1,
- buff_size1,
- wbuffer2,
- buff_size2 );
- }
- else /* f_use is neither USE_A nor USE_W */
- return 0;
- }
-