// ------------------------------- // // -------- Start of File -------- // // ------------------------------- // // ----------------------------------------------------------- // // C++ Source Code File Name: strutil.cpp // Compiler Used: MSVC, BCC32, GCC, HPUX aCC, SOLARIS CC // Produced By: DataReel Software Development Team // File Creation Date: 12/16/1997 // Date Last Modified: 01/01/2009 // Copyright (c) 2001-2009 DataReel Software Development // ----------------------------------------------------------- // // ------------- Program Description and Details ------------- // // ----------------------------------------------------------- // /* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA The string utilities are a collection of data structures and standalone functions used to manipulate and parse null terminated ASCII and Unicode character strings. Changes: ============================================================== 07/10/2001: Added __AIX__ conditional directive for the IBM xlC C and C++ Compilers. This compiler does not define the strcasecmp() function. 09/28/2001: Added a string length parameter to the FindMatch() and IFindMatch() functions used to set the length of the string variable when the string is not null-terminated. 06/05/2002: Added standalone functions needed to work with both ASCII and Unicode strings 06/05/2002: Added conversion functions used with ASCII and Unicode string literals. 09/04/2002: Added Unicode versions of all strutil functions included with release 4.1. 09/04/2002: All versions of the CaseICmp() functions are no longer using compiler dependent string case insensitive functions. 09/04/2002: All versions of the StringCat() functions now use null pointers as the default arguments and will return a null string if no arguments are passed to the function from the caller. ============================================================== */ // ----------------------------------------------------------- // #include "gxdlcode.h" #include "strutil.h" #ifdef __BCC32__ #pragma warn -8080 #endif gxwchar::gxwchar(unsigned long wc) { UnPackBits(wc); } gxwchar::gxwchar(const gxwchar& wc) { memmove((void *)byte, (const void *)wc.byte, 4); } gxwchar& gxwchar::operator=(const gxwchar& wc) { if(this != &wc) { // Prevent self assignment memmove((void *)byte, (const void *)wc.byte, 4); } return *this; } gxwchar& gxwchar::operator=(const unsigned long wc) { UnPackBits(wc); return *this; } gxwchar::operator unsigned long() const { return PackBits(); } unsigned long gxwchar::PackBits() const { unsigned long a, b, c, d; a = (unsigned long)byte[0]; b = (unsigned long)byte[1]; c = (unsigned long)byte[2]; d = (unsigned long)byte[3]; a = a & 0xFF; b = (b<<8) & 0xFF00; c = (c<<16) & 0xFF0000; d = (d<<24) & 0xFF000000; return a + b + c + d; } void gxwchar::UnPackBits(unsigned long wc) { byte[0] = (unsigned char)(wc & 0xFF); byte[1] = (unsigned char)((wc & 0xFF00)>>8); byte[2] = (unsigned char)((wc & 0xFF0000)>>16); byte[3] = (unsigned char)((wc & 0xFF000000)>>24); } GXDLCODE_API gxwchar_t *gxstrcpy(gxwchar_t *to, const gxwchar_t *from) // Cross platform gxwchar_t string function used to copy a null terminated // gxwchar_t string. Redundantly returns a copy of the string. NOTE: This // function assumes that the caller has previously allocated enough memory // for the destination string plus room for the string's null terminator. { unsigned cs = sizeof(gxwchar_t); unsigned nchars = gxstrlen(from); // Cast to unsigned char * type so that the pointer will be // incremented one byte at a time. memmove((unsigned char *)to, (unsigned char *)from, (nchars*cs)); to[nchars] = (gxwchar_t)0; // Null terminate the string return to; } GXDLCODE_API unsigned gxstrlen(const gxwchar_t *s) // Cross platform gxwchar_t string function used calculate the string length // of a null terminated gxwchar_t string. NOTE: The string length of a string // refers to the number of characters in the string and not the number of // bytes the string occupies in memory. The number of bytes occupied by a // gxwchar_t string can be calculated by multiplying the string length by // sizeof(gxwchar_t). { gxwchar_t *p = (gxwchar_t *)s; unsigned i = 0; while(p[i++] != (gxwchar_t)0) ; return i - 1; // Return the length minus the null terminator } GXDLCODE_API gxwchar_t *gxstrcat(gxwchar_t *des, const gxwchar_t *src) // Cross compiler gxwchar_t string function used to append a null terminated // gxwchar_t string. Redundantly returns a copy of the string. NOTE: This // function assumes that the caller has previously allocated enough memory // for the destination string plus room for the string's null terminator. { unsigned cs = sizeof(gxwchar_t); unsigned nchars_d = gxstrlen(des); unsigned nchars_s = gxstrlen(src); // Cast to unsigned char * type so that the pointer will be // incremented one byte at a time. memmove((unsigned char *)des+(nchars_d*cs), (unsigned char *)src, (nchars_s*cs)); des[nchars_d+nchars_s] = (gxwchar_t)0; // Null terminate the string return des; } GXDLCODE_API int gxstrcmp(const gxwchar_t *a, const gxwchar_t *b) // Cross compiler gxwchar_t string function used to compare two null // terminated gxwchar_t strings. Returns -1 if a < b, 0 if a == b, // and 1 if a > b { unsigned cs = sizeof(gxwchar_t); unsigned nchars_a = gxstrlen(a); unsigned nchars_b = gxstrlen(b); return gxbyte_compare(a, (nchars_a*cs), b, (nchars_b*cs)); } GXDLCODE_API wchar_t *gxstrcpy(wchar_t *to, const wchar_t *from) // Cross compiler Unicode string function used to copy a null terminated // Unicode string. Redundantly returns a copy of the string. NOTE: This // function assumes that the caller has previously allocated enough memory // for the destination string plus room for the string's null terminator. { #if defined (__HAS_UNICODE__) return wcscpy(to, from); #else // Non-compiler specific Unicode string copy function unsigned cs = sizeof(wchar_t); unsigned nchars = gxstrlen(from); // Cast to unsigned char * type so that the pointer will be // incremented one byte at a time. memmove((unsigned char *)to, (unsigned char *)from, (nchars*cs)); to[nchars] = (wchar_t)0; // Null terminate the string return to; #endif // __HAS_UNICODE__ } GXDLCODE_API wchar_t *gxstrcat(wchar_t *des, const wchar_t *src) // Cross compiler Unicode string function used to append a null terminated // Unicode string. Redundantly returns a copy of the string. NOTE: This // function assumes that the caller has previously allocated enough memory // for the destination string plus room for the string's null terminator. { #if defined (__HAS_UNICODE__) return wcscat(des, src); #else // Non-compiler specific Unicode string cat function unsigned cs = sizeof(wchar_t); unsigned nchars_d = gxstrlen(des); unsigned nchars_s = gxstrlen(src); // Cast to unsigned char * type so that the pointer will be // incremented one byte at a time. memmove((unsigned char *)des+(nchars_d*cs), (unsigned char *)src, (nchars_s*cs)); des[nchars_d+nchars_s] = (wchar_t)0; // Null terminate the string return des; #endif // __HAS_UNICODE__ } GXDLCODE_API unsigned gxstrlen(const wchar_t *s) // Cross compiler Unicode string function used calculate the string length // of a null terminated Unicode string. NOTE: The string length of a string // refers to the number of characters in the string and not the number of // bytes the string occupies in memory. The number of bytes occupied by a // Unicode string can be calculated by multiplying the string length by // sizeof(wchar_t). { #if defined (__HAS_UNICODE__) return wcslen(s); #else // Non-compiler specific Unicode string function wchar_t *p = (wchar_t *)s; unsigned i = 0; while(p[i++] != (wchar_t)0) ; return i - 1; // Return the length minus the null terminator #endif // __HAS_UNICODE__ } GXDLCODE_API int gxstrcmp(const wchar_t *a, const wchar_t *b) // Cross compiler Unicode string function used to compare two null terminated // Unicode strings. Returns -1 if a < b, 0 if a == b, and 1 if a > b { #if defined (__HAS_UNICODE__) return wcscmp(a, b); #else // Non-compiler specific Unicode string function unsigned cs = sizeof(wchar_t); unsigned nchars_a = gxstrlen(a); unsigned nchars_b = gxstrlen(b); return gxbyte_compare(a, (nchars_a*cs), b, (nchars_b*cs)); #endif // __HAS_UNICODE__ } GXDLCODE_API int gxbyte_compare(const void *a, unsigned a_bytes, const void *b, unsigned b_bytes) // Function used to compare two memory buffers byte by byte. // Returns -1 if a < b, 0 if a == b, and 1 if a > b { unsigned sn = (a_bytes < b_bytes) ? a_bytes : b_bytes; char *ap = (char *)a; char *bp = (char *)b; for(unsigned i = 0; i < sn; i++) { if(*ap < *bp) return -1; if(*ap++ > *bp++) return 1; } if(a_bytes == b_bytes) return 0; if(a_bytes < b_bytes) return -1; return 1; } GXDLCODE_API int gxbyte_icompare(const void *a, unsigned a_bytes, const void *b, unsigned b_bytes, gxStringType st) // Returns -1 if a < b, 0 if a == b, and 1 if a > b without // regard for the case of any ASCII letters. { if(st == gxASCII_STRING) { unsigned sn = (a_bytes < b_bytes) ? a_bytes : b_bytes; char *ap = (char *)a; char *bp = (char *)b; for(unsigned i = 0; i < sn; i++) { if(tolower(*ap) < tolower(*bp)) return -1; if(tolower(*ap++) > tolower(*bp++)) return 1; } if(a_bytes == b_bytes) return 0; if(a_bytes < b_bytes) return -1; return 1; } else { unsigned cs = sizeof(wchar_t); unsigned a_nchars = a_bytes/cs; if(a_bytes % cs) a_nchars++; unsigned b_nchars = b_bytes/cs; if(b_bytes % cs) b_nchars++; unsigned sn = (a_nchars < b_nchars) ? a_nchars : b_nchars; wchar_t *ap = (wchar_t *)a; wchar_t *bp = (wchar_t *)b; for(unsigned i = 0; i < sn; i++) { #if defined (__HAS_UNICODE__) if(towlower(ap[i]) < towlower(bp[i])) return -1; if(towlower(ap[i]) > towlower(bp[i])) return 1; #else if(tolower(ap[i]) < tolower(bp[i])) return -1; if(tolower(ap[i]) > tolower(bp[i])) return 1; #endif // __HAS_UNICODE__ } if(a_bytes == b_bytes) return 0; if(a_bytes < b_bytes) return -1; return 1; } } GXDLCODE_API int gxfind_pattern(const void *src, unsigned s_bytes, const void *p, unsigned p_bytes, unsigned offset, gxStringType st, unsigned cs) // Returns index of first occurrence of pattern buffer *s // Returns -1 if the pattern is not found { if(st == gxASCII_STRING) { char *start = (char *)src + offset; // start of string data char *next = start; // next string element char *pattern = (char *)p; // next pattern element unsigned i = offset, j = 1; // String and pattern indexes while(i < s_bytes && j <= p_bytes) { if (*next == *pattern) { // Matching character if(j == p_bytes) return (int)i; // Entire match was found next++; pattern++; j++; } else { // Try next spot in string i++; start++; next = start; pattern = (char *)p; j = 1; } } } else { // Calculate the string and pattern indexes unsigned i = offset/cs; if(offset % cs) i++; unsigned nchars_p = p_bytes/cs; if(p_bytes % cs) nchars_p++; unsigned nchars_s = s_bytes/cs; if(s_bytes % cs) nchars_s++; unsigned j = 1; wchar_t *start = (wchar_t *)src + i; // start of string data wchar_t *next = start; // next string element wchar_t *pattern = (wchar_t *)p; // next pattern element while(i < nchars_s && j <= nchars_p) { if(*next == *pattern) { // Matching character if(j == nchars_p) return (int)i; // Entire match was found next++; pattern++; j++; } else { // Try next spot in string i++; start++; next = start; pattern = (wchar_t *)p; j = 1; } } } return (int)-1; // No match was found } GXDLCODE_API int gxifind_pattern(const void *src, unsigned s_bytes, const void *p, unsigned p_bytes, unsigned offset, gxStringType st, unsigned cs) // Returns index of first occurrence of pattern buffer *s starting at the // specified offset using a case insensitive compare. Returns -1 // if the pattern is not found. { if(st == gxASCII_STRING) { char *start = (char *)src + offset; // start of string data char *next = start; // next string element char *pattern = (char *)p; // next pattern element unsigned i = offset, j = 1; // String and pattern indexes while(i < s_bytes && j <= p_bytes) { if (tolower(*next) == tolower(*pattern)) { if(j == p_bytes) return (int)i; // Entire match was found next++; pattern++; j++; } else { // Try next spot in string i++; start++; next = start; pattern = (char *)p; j = 1; } } } else { // Calculate the string and pattern indexes unsigned i = offset/cs; if(offset % cs) i++; unsigned nchars_p = p_bytes/cs; if(p_bytes % cs) nchars_p++; unsigned nchars_s = s_bytes/cs; if(s_bytes % cs) nchars_s++; unsigned j = 1; wchar_t *start = (wchar_t *)src + i; // start of string data wchar_t *next = start; // next string element wchar_t *pattern = (wchar_t *)p; // next pattern element while(i < nchars_s && j <= nchars_p) { #if defined (__HAS_UNICODE__) if(towlower(*next) == towlower(*pattern)) { #else if(tolower(*next) == tolower(*pattern)) { #endif // __HAS_UNICODE__ if(j == nchars_p) return (int)i; // Entire match was found next++; pattern++; j++; } else { // Try next spot in string i++; start++; next = start; pattern = (wchar_t *)p; j = 1; } } } return (int)-1; // No match was found } GXDLCODE_API wchar_t *ASCII2Unicode(const char *s, unsigned nchars, wchar_t *nsptr) { if(!s) return 0; if(nchars == 0) nchars = gxstrlen(s); unsigned cs = sizeof(wchar_t); if(!nsptr) { nsptr = new wchar_t[nchars+1]; if(!nsptr) return 0; } memset(nsptr, 0, ((nchars*cs)+cs)); for(unsigned i = 0; i < nchars; i++) { // PC-lint 04/26/2005: Warning suspicious cast nsptr[i] = (wchar_t)s[i]; } return nsptr; } GXDLCODE_API char *Unicode2ASCII(const wchar_t *s, unsigned nchars, char *nsptr) { if(!s) return 0; if(nchars == 0) nchars = gxstrlen(s); if(!nsptr) { nsptr = new char[nchars+1]; if(!nsptr) return 0; } memset(nsptr, 0, (nchars+1)); for(unsigned i = 0; i < nchars; i++) nsptr[i] = (char)s[i]; return nsptr; } GXDLCODE_API wchar_t *gxwchar_t2Unicode(const gxwchar_t *s, unsigned nchars, wchar_t *nsptr) { if(!s) return 0; if(nchars == 0) nchars = gxstrlen(s); unsigned cs = sizeof(wchar_t); if(!nsptr) { nsptr = new wchar_t[nchars+1]; if(!nsptr) return 0; } memset(nsptr, 0, ((nchars*cs)+cs)); for(unsigned i = 0; i < nchars; i++) nsptr[i] = wchar_t((unsigned long)s[i]); return nsptr; } GXDLCODE_API char *gxwchar_t2ASCII(const gxwchar_t *s, unsigned nchars, char *nsptr) { if(!s) return 0; if(nchars == 0) nchars = gxstrlen(s); if(!nsptr) { nsptr = new char[nchars+1]; if(!nsptr) return 0; } memset(nsptr, 0, (nchars+1)); for(unsigned i = 0; i < nchars; i++) nsptr[i] = char((unsigned long)s[i]); return nsptr; } GXDLCODE_API gxwchar_t *ASCII2gxwchar_t(const char *s, unsigned nchars, gxwchar_t *nsptr) { if(!s) return 0; if(nchars == 0) nchars = gxstrlen(s); unsigned cs = sizeof(gxwchar_t); if(!nsptr) { nsptr = new gxwchar_t[nchars+1]; if(!nsptr) return 0; } memset(nsptr, 0, ((nchars*cs)+cs)); for(unsigned i = 0; i < nchars; i++) { // PC-lint 04/26/2005: Warning suspicious cast nsptr[i] = gxwchar_t((unsigned long)s[i]); } return nsptr; } GXDLCODE_API gxwchar_t *Unicode2gxwchar_t(const wchar_t *s, unsigned nchars, gxwchar_t *nsptr) { if(!s) return 0; if(nchars == 0) nchars = gxstrlen(s); unsigned cs = sizeof(gxwchar_t); if(!nsptr) { nsptr = new gxwchar_t[nchars+1]; if(!nsptr) return 0; } memset(nsptr, 0, ((nchars*cs)+cs)); for(unsigned i = 0; i < nchars; i++) nsptr[i] = gxwchar_t((unsigned long)s[i]); return nsptr; } GXDLCODE_API char *StringCat(const char *s1, const char *s2, const char *s3) { int len = 1; // Reserve one byte for the null terminator if(s1) len += gxstrlen(s1); if(s2) len += gxstrlen(s2); if(s3) len += gxstrlen(s3); char *comp = new char[len]; comp[len-1] = '\0'; // Null terminate the buffer if(s1) gxstrcpy(comp, s1); if(s2) gxstrcat(comp, s2); if(s3) gxstrcat(comp, s3); return comp; } GXDLCODE_API wchar_t *StringCat(const wchar_t *s1, const wchar_t *s2, const wchar_t *s3) { int len = 1; // Reserve one byte for the null terminator if(s1) len += gxstrlen(s1); if(s2) len += gxstrlen(s2); if(s3) len += gxstrlen(s3); wchar_t *comp = new wchar_t[len]; comp[len-1] = '\0'; // Null terminate the buffer if(s1) gxstrcpy(comp, s1); if(s2) gxstrcat(comp, s2); if(s3) gxstrcat(comp, s3); return comp; } GXDLCODE_API int parse(const wchar_t *str, wchar_t words[MAXWORDS][MAXWORDLENGTH], int *numwords, const wchar_t sepchar) // General purpose ASCII string parser { wchar_t *s = (wchar_t *)str; int i = 0; wchar_t newword[MAXWORDLENGTH]; *numwords = 0; const char space = ' '; const wchar_t wspace = (wchar_t)space; const wchar_t wnull = (wchar_t)0; while (1) { if (*s == wnull) return 0; if (*s != wspace) break; s++; } while(1) { // Check to see if there is room for another word in the array if(*numwords == MAXWORDS) return 1; i = 0; // PC-lint 04/26/2005: Possible access of out-of-bounds pointer while (i < (MAXWORDLENGTH-1)) { if(*s == 0 || *s == sepchar) break; newword[i] = *s; s++; i++; } newword[i] = wnull; // Ensure null termination gxstrcpy(words[*numwords], newword); // Install word into the array (*numwords)++; if(*s == wnull) break; s++; if(*s == wnull) break; } return 0; } GXDLCODE_API int parse(const char *str, char words[MAXWORDS][MAXWORDLENGTH], int *numwords, const char sepchar) // General purpose ASCII string parser { char *s = (char *)str; int i = 0; char newword[MAXWORDLENGTH]; *numwords = 0; while (1) { if (*s == '\0') return 0; if (*s != ' ') break; s++; } while(1) { // Check to see if there is room for another word in the array if(*numwords == MAXWORDS) return 1; i = 0; // PC-lint 04/26/2005: Possible access of out-of-bounds pointer while (i < (MAXWORDLENGTH-1)) { if(*s == 0 || *s == sepchar) break; newword[i] = *s; s++; i++; } newword[i] = 0; // Ensure null termination strcpy (words[*numwords], newword); // Install word into the array (*numwords)++; if(*s == 0) break; s++; if(*s == 0) break; } return 0; } GXDLCODE_API int CaseICmp(const wchar_t *a, const wchar_t *b) // Compare two strings without regard to the case of the letters { unsigned cs = sizeof(wchar_t); unsigned nchars_a = gxstrlen(a); unsigned nchars_b = gxstrlen(b); return gxbyte_icompare(a, (nchars_a*cs), b, (nchars_b*cs), gxUNICODE_STRING); } GXDLCODE_API int CaseICmp(const char *a, const char *b) // Compare two strings without regard to the case of the letters { unsigned nchars_a = gxstrlen(a); unsigned nchars_b = gxstrlen(b); return gxbyte_icompare(a, nchars_a, b, nchars_b, gxASCII_STRING); } GXDLCODE_API int FindMatch(const char *src, const char *p, unsigned offset, unsigned src_len, unsigned p_len) // Finds pattern "p" in string "src" starting at specified offset. // Returns index of first occurrence of matching pattern or -1 // if no match is found. If the "src_len" or "p_len" variables // equal zero it's assumed that that "src" and/or "p" are null- // terminated string(s). { if(src_len == 0) src_len = gxstrlen(src); if(p_len == 0) p_len = gxstrlen(p); return gxfind_pattern(src, src_len, p, p_len, offset, gxASCII_STRING, 1); } GXDLCODE_API int FindMatch(const wchar_t *src, const wchar_t *p, unsigned offset, unsigned src_len, unsigned p_len) // Finds pattern "p" in string "src" starting at specified offset. // Returns index of first occurrence of matching pattern or -1 // if no match is found. If the "src_len" or "p_len" variables // equal zero it's assumed that that "src" and/or "p" are null- // terminated string(s). { if(src_len == 0) src_len = gxstrlen(src); if(p_len == 0) p_len = gxstrlen(p); return gxfind_pattern(src, src_len, p, p_len, offset, gxUNICODE_STRING, sizeof(wchar_t)); } GXDLCODE_API int IFindMatch(const char *src, const char *p, unsigned offset, unsigned src_len, unsigned p_len) // Finds pattern "p" in string "src" starting at specified offset // using a case insensitive compare. Returns index of first occurrence // of matching pattern or -1 if no match is found. If the "src_len" or // "p_len" variables equal zero it's assumed that that "src" and/or "p" // are null-terminated string(s). { if(src_len == 0) src_len = gxstrlen(src); if(p_len == 0) p_len = gxstrlen(p); return gxifind_pattern(src, src_len, p, p_len, offset, gxASCII_STRING, 1); } GXDLCODE_API int IFindMatch(const wchar_t *src, const wchar_t *p, unsigned offset, unsigned src_len, unsigned p_len) // Finds pattern "p" in string "src" starting at specified offset // using a case insensitive compare. Returns index of first occurrence // of matching pattern or -1 if no match is found. If the "src_len" or // "p_len" variables equal zero it's assumed that that "src" and/or "p" // are null-terminated string(s). { if(src_len == 0) src_len = gxstrlen(src); if(p_len == 0) p_len = gxstrlen(p); return gxifind_pattern(src, src_len, p, p_len, offset, gxUNICODE_STRING, sizeof(wchar_t)); } GXDLCODE_API int test_for_null(const char *s, unsigned nchars) // General-purpose function used to test for null a terminator. // Returns true if a null terminator is found or false if no // null terminator is found. { char *p = (char *)s; for(unsigned i = 0; i < nchars; i++) { if(p[i] == 0) return 1; } return 0; } GXDLCODE_API int test_for_null(const gxwchar_t *s, unsigned nchars) // General-purpose function used to test for null a terminator. // Returns true if a null terminator is found or false if no // null terminator is found. { gxwchar_t *p = (gxwchar_t *)s; for(unsigned i = 0; i < nchars; i++) { if(p[i] == (gxwchar_t)0) return 1; } return 0; } GXDLCODE_API int StringANCompare(const char *a, const char *b, int check_case) // String compare function used to compare strings with alphanumeric content. // If the "check_case" variable is false a case insensitive compare will be // preformed on the non-numeric part of string 1 and 2. Returns 0 if the // strings are equal, 1 if string 1 is greater than string 2, or -1 if // string 1 is less than string 2. { unsigned long i; unsigned long a_bytes = gxstrlen(a); unsigned long b_bytes = gxstrlen(b); unsigned long sn = (a_bytes < b_bytes) ? a_bytes : b_bytes; char *ap = (char *)a; char *bp = (char *)b; unsigned long digit_pos1 = 0; unsigned long digit_pos2 = 0; char *dbuf1 = new char[sn+1]; // Digit buffer 1, collecting digits if(!dbuf1) return -1; char *dbuf2 = new char[sn+1]; // Digit buffer 2, collecting digits if(!dbuf2) { // PC-lint 04/26/2005: Prevent memory leak delete[] dbuf1; return -1; } memset(dbuf1, 0, (sn+1)); memset(dbuf2, 0, (sn+1)); unsigned long ibuf1, ibuf2; for(i = 0; i < sn; i++) { if((isdigit(*ap)) && (isdigit(*bp))) { if(a_bytes == b_bytes) { if((!isdigit(*ap+1)) && (!isdigit(*bp+1))) { if(*ap < *bp) { // PC-lint 04/26/2005: Avoid inappropriate de-allocation error, // but dbuf is not a user defined type so there is no destructor // to call for the array members. delete[] dbuf1; delete[] dbuf2; return -1; } if(*ap > *bp) { // PC-lint 04/26/2005: Avoid inappropriate de-allocation error, // but dbuf is not a user defined type so there is no destructor // to call for the array members. delete[] dbuf1; delete[] dbuf2; return 1; } } } dbuf1[digit_pos1++] = *ap++; dbuf2[digit_pos2++] = *bp++; } else { if((dbuf1[0] != 0) && (dbuf2[0] != 0)) { if((isdigit(*(ap)))) { dbuf1[digit_pos1] = *((ap)); } if((isdigit(*(bp)))) { dbuf2[digit_pos2] = *((bp)); } ibuf1 = StringToULWORD(dbuf1); ibuf2 = StringToULWORD(dbuf2); if(ibuf1 < ibuf2) { // PC-lint 04/26/2005: Avoid inappropriate de-allocation error, // but dbuf is not a user defined type so there is no destructor // to call for the array members. delete[] dbuf1; delete[] dbuf2; return -1; } if(ibuf1 > ibuf2) { // PC-lint 04/26/2005: Avoid inappropriate de-allocation error, // but dbuf is not a user defined type so there is no destructor // to call for the array members. delete[] dbuf1; delete[] dbuf2; return 1; } memset(dbuf1, 0, (sn+1)); memset(dbuf2, 0, (sn+1)); digit_pos1 = digit_pos2 = 0; } if(check_case) { if(*ap < *bp) { // PC-lint 04/26/2005: Avoid inappropriate de-allocation error, // but dbuf is not a user defined type so there is no destructor // to call for the array members. delete[] dbuf1; delete[] dbuf2; return -1; } if(*ap++ > *bp++) { // PC-lint 04/26/2005: Avoid inappropriate de-allocation error, // but dbuf is not a user defined type so there is no destructor // to call for the array members. delete[] dbuf1; delete[] dbuf2; return 1; } } else { if(tolower(*ap) < tolower(*bp)) { // PC-lint 04/26/2005: Avoid inappropriate de-allocation error, // but dbuf is not a user defined type so there is no destructor // to call for the array members. delete[] dbuf1; delete[] dbuf2; return -1; } if(tolower(*ap++) > tolower(*bp++)) { // PC-lint 04/26/2005: Avoid inappropriate de-allocation error, // but dbuf is not a user defined type so there is no destructor // to call for the array members. delete[] dbuf1; delete[] dbuf2; return 1; } } } } // Check for any remaining digits at the end of the string if((dbuf1[0] != 0) && (dbuf2[0] != 0)) { if(a_bytes > b_bytes) { if(isdigit(*(ap))) { dbuf1[digit_pos1] = *(ap); } } if(a_bytes < b_bytes) { if(isdigit(*(bp))) { dbuf2[digit_pos2] = *(bp); } } ibuf1 = StringToULWORD(dbuf1); ibuf2 = StringToULWORD(dbuf2); if(ibuf1 < ibuf2) { // PC-lint 04/26/2005: Avoid inappropriate de-allocation error, // but dbuf is not a user defined type so there is no destructor // to call for the array members. delete[] dbuf1; delete[] dbuf2; return -1; } if(ibuf1 > ibuf2) { // PC-lint 04/26/2005: Avoid inappropriate de-allocation error, // but dbuf is not a user defined type so there is no destructor // to call for the array members. delete[] dbuf1; delete[] dbuf2; return 1; } } // Tested all digits and letters so return the final result // based on the string lengths. if(a_bytes < b_bytes) { // PC-lint 04/26/2005: Avoid inappropriate de-allocation error, // but dbuf is not a user defined type so there is no destructor // to call for the array members. delete[] dbuf1; delete[] dbuf2; return -1; } if(a_bytes == b_bytes) { // PC-lint 04/26/2005: Avoid inappropriate de-allocation error, // but dbuf is not a user defined type so there is no destructor // to call for the array members. delete[] dbuf1; delete[] dbuf2; return 0; } // PC-lint 04/26/2005: Avoid inappropriate de-allocation error, // but dbuf is not a user defined type so there is no destructor // to call for the array members. delete[] dbuf1; delete[] dbuf2; return 1; } GXDLCODE_API unsigned long StringToULWORD(const char *str) { char *s = (char *)str; while(*s == ' ') ++s; int c = (int)(unsigned char)*s++; if(c == '-' || c == '+') c = (int)(unsigned char)*s++; unsigned long value = (unsigned long)0; while(isdigit(c)) { value = 10 * value + (c - '0'); c = (int)(unsigned char)*s++; } return value; } GXDLCODE_API unsigned long StringToULWORD(const wchar_t *str) { unsigned long i = (unsigned long)0; char *asbuf = Unicode2ASCII(str); if(!asbuf) return i; i = StringToULWORD(asbuf); delete asbuf; return i; } #if defined (__64_BIT_DATABASE_ENGINE__) || defined (__ENABLE_64_BIT_INTEGERS__) GXDLCODE_API wchar_t *ULLWORDToString(wchar_t *sbuf, __ULLWORD__ val, int radix) // Returns a null terminated string representing the specified // 64-bit value. NOTE: This function assumes that the proper // amount of memory has been allocated for the "sbuf" string // buffer. The string buffer "sbuf" is redundantly returned by // this function. { if(!sbuf) return 0; // Prevent a program crash if this is a null pointer char asbuf[255]; ULLWORDToString(asbuf, val, radix); wchar_t *wsbuf = ASCII2Unicode(asbuf); gxstrcpy(sbuf, wsbuf); delete wsbuf; return sbuf; } GXDLCODE_API char *ULLWORDToString(char *sbuf, __ULLWORD__ val, int radix) // Returns a null terminated string representing the specified // 64-bit value. NOTE: This function assumes that the proper // amount of memory has been allocated for the "sbuf" string // buffer. The string buffer "sbuf" is redundantly returned by // this function. { if(!sbuf) return 0; // Prevent a program crash if this is a null pointer char cbuf; unsigned value; char *s = sbuf; char *digit = s; do { // PC-lint 04/26/2005: Warning signed-unsigned mix with divide value = (unsigned)(val % radix); val /= radix; if(value > 9) *s++ = (char)(value - 10 + 'A'); else *s++ = (char)(value + '0'); } while(val > 0); *s-- = '\0'; do { cbuf = *s; *s = *digit; *digit = cbuf; --s; ++digit; } while(digit < s); return sbuf; } GXDLCODE_API wchar_t *LLWORDToString(wchar_t *sbuf, __ULLWORD__ val, int radix) // Returns a null terminated string representing the specified // 64-bit value. NOTE: This function assumes that the proper // amount of memory has been allocated for the "sbuf" string // buffer. The string buffer "sbuf" is redundantly returned by // this function. { if(!sbuf) return 0; // Prevent a program crash if this is a null pointer char asbuf[255]; LLWORDToString(asbuf, val, radix); wchar_t *wsbuf = ASCII2Unicode(asbuf); gxstrcpy(sbuf, wsbuf); delete wsbuf; return sbuf; } GXDLCODE_API char *LLWORDToString(char *sbuf, __ULLWORD__ val, int radix) // Returns a null terminated string representing the specified // 64-bit value. NOTE: This function assumes that the proper // amount of memory has been allocated for the "sbuf" string // buffer. The string buffer "sbuf" is redundantly returned by // this function. { if(!sbuf) return 0; // Prevent a program crash if this is a null pointer char cbuf; unsigned value; char *s = sbuf; if((radix == 10 && (__LLWORD__)val < 0)) { *s++ = '-'; } char *digit = s; do { // PC-lint 04/26/2005: Warning signed-unsigned mix with divide value = (unsigned)(val % radix); val /= radix; if(value > 9) *s++ = (char)(value - 10 + 'A'); else *s++ = (char)(value + '0'); } while(val > 0); *s-- = '\0'; do { cbuf = *s; *s = *digit; *digit = cbuf; --s; ++digit; } while(digit < s); return sbuf; } GXDLCODE_API __LLWORD__ StringToLLWORD(const wchar_t *str) { __LLWORD__ i = (__LLWORD__)0; char *asbuf = Unicode2ASCII(str); if(!asbuf) return i; i = StringToLLWORD(asbuf); delete asbuf; return i; } GXDLCODE_API __LLWORD__ StringToLLWORD(const char *str) { char *s = (char *)str; while(*s == ' ') ++s; int c = (int)(unsigned char)*s++; int sign = c; if(c == '-' || c == '+') c = (int)(unsigned char)*s++; __LLWORD__ value = (__LLWORD__)0; while(isdigit(c)) { value = 10 * value + (c - '0'); c = (int)(unsigned char)*s++; } if(sign == '-') return -value; else return value; } GXDLCODE_API __ULLWORD__ StringToULLWORD(const wchar_t *str) { __ULLWORD__ i = (__ULLWORD__)0; char *asbuf = Unicode2ASCII(str); if(!asbuf) return i; i = StringToULLWORD(asbuf); delete asbuf; return i; } GXDLCODE_API __ULLWORD__ StringToULLWORD(const char *str) { char *s = (char *)str; while(*s == ' ') ++s; int c = (int)(unsigned char)*s++; if(c == '-' || c == '+') c = (int)(unsigned char)*s++; __ULLWORD__ value = (__ULLWORD__)0; while(isdigit(c)) { value = 10 * value + (c - '0'); c = (int)(unsigned char)*s++; } return (__ULLWORD__)value; } #endif #ifdef __BCC32__ #pragma warn .8080 #endif // ----------------------------------------------------------- // // ------------------------------- // // --------- End of File --------- // // ------------------------------- //