/* ========================================================================== * ÀÛ ¼º ÀÚ : À̼ø±Ô * ÀÛ ¼º ÀÏ : 2006.09.12 * ³» ¿ë : std::char_traits¸¦ °¨½Ñ ¹®ÀÚ Æ¯¼º ÅÛÇø´ * ÁÖÀÇ»çÇ× : *===========================================================================*/ #pragma once #pragma warning( push ) //#pragma warning( disable: 4996 ) #pragma warning( disable: 4267 ) #include #include #include #include #include #include using namespace std; /// ´ÜÇ× »©±â ¿¬»êÀÚ°¡ ºÎÈ£ ¾ø´Â Çü½Ä¿¡ Àû¿ëµÇ¾ú½À´Ï´Ù. #pragma warning(disable: 4146) /// Çüº¯È¯Çϸ鼭 µ¥ÀÌÅͰ¡ ¼Õ½ÇµÉ ¼ö ÀÖ½À´Ï´Ù. #pragma warning(disable: 4244) /// ÇÔ¼ö°¡ deprecated·Î ¼±¾ðµÇ¾ú½À´Ï´Ù. //#pragma warning(disable: 4996) /// ¹®ÀÚ Æ¯¼º template class tCharTraits { }; template<> class tCharTraits : public char_traits { public: /// ¹®ÀÚ¿­ s0°ú ¹®ÀÚ¿­ s1À» ºñ±³ static int Compare( const char* s0, const char* s1 ) { while( *s0 == *s1 ) { if( *s0 == 0 ) { return 0; } s0++; s1++; } return *s0 - *s1; } /// ¹®ÀÚ¿­ s0°ú ¹®ÀÚ¿­ s1À» ±æÀÌ n¸¸Å­ ºñ±³ static int Compare( const char* s0, const char* s1, unsigned int n ) { return ::memcmp( s0, s1, n ); } /// ¹®ÀÚ¿­ÀÇ ±æÀ̸¦ ¸®ÅÏ static unsigned int GetLength( const char* s ) { return ::strlen( s ); } /// ¼ýÀÚ·Î º¯È¯ static long ToLong( const char*nptr, char**endptr, int base ) { /// ¿øº» //const char*s = nptr; //unsigned long acc; //int c; //unsigned long cutoff; //int neg = 0, any, cutlim; ///* //* Skip white space and pick up leading +/- sign if any. //* If base is 0, allow 0x for hex and 0 for octal, else //* assume decimal; if base is already 16, allow 0x. //*/ //do{ // c = *s++; //} while(::isspace(c)); //if(c == '-') //{ // neg = 1; // c = *s++; //} //else if(c == '+') // c = *s++; //if((base == 0 || base == 16) && // c == '0' && (*s == 'x' || *s == 'X')) //{ // c = s[1]; // s += 2; // base = 16; //} //if(base == 0) // base = c == '0' ? 8 : 10; ///* //* Compute the cutoff value between legal numbers and illegal //* numbers. That is the largest legal value, divided by the //* base. An input number that is greater than this value, if //* followed by a legal input character, is too big. One that //* is equal to this value may be valid or not; the limit //* between valid and invalid numbers is then based on the last //* digit. For instance, if the range for longs is //* [-2147483648..2147483647] and the input base is 10, //* cutoff will be set to 214748364 and cutlim to either //* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated //* a value > 214748364, or equal but the next digit is > 7 (or 8), //* the number is too big, and we will return a range error. //* //* Set any if any `digits' consumed; make it negative to indicate //* overflow. //*/ //cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; //cutlim = cutoff % (unsigned long)base; //cutoff /= (unsigned long)base; //for(acc = 0, any = 0;; c = *s++) //{ // if( ::isdigit(c) ) // c -= '0'; // else if( ::isalpha(c) ) // c -= ::isupper(c) ? 'A' - 10 : 'a' - 10; // else // break; // if(c >= base) // break; // if(any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) // any = -1; // else // { // any = 1; // acc *= base; // acc += c; // } //} //if(any < 0) //{ // acc = neg ? LONG_MIN : LONG_MAX; //} //else if(neg) // acc = -acc; //if(endptr != 0) // *endptr = any ? (char*)s - 1 : (char*)nptr; //return acc; const char*s = nptr; unsigned long acc; int c; unsigned long cutoff; int neg = 0, any, cutlim; /* * Skip white space and pick up leading +/- sign if any. * If base is 0, allow 0x for hex and 0 for octal, else * assume decimal; if base is already 16, allow 0x. */ do{ c = *s++; } while(::isspace(c)); if(c == '-') { neg = 1; c = *s++; } else if(c == '+') c = *s++; if((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; s += 2; base = 16; } if(base == 0) base = c == '0' ? 8 : 10; /* * Compute the cutoff value between legal numbers and illegal * numbers. That is the largest legal value, divided by the * base. An input number that is greater than this value, if * followed by a legal input character, is too big. One that * is equal to this value may be valid or not; the limit * between valid and invalid numbers is then based on the last * digit. For instance, if the range for longs is * [-2147483648..2147483647] and the input base is 10, * cutoff will be set to 214748364 and cutlim to either * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated * a value > 214748364, or equal but the next digit is > 7 (or 8), * the number is too big, and we will return a range error. * * Set any if any `digits' consumed; make it negative to indicate * overflow. */ if( neg == 1 ) { cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; cutlim = cutoff % (unsigned long)base; cutoff /= (unsigned long)base; for(acc = 0, any = 0;; c = *s++) { if( ::isdigit(c) ) c -= '0'; else if( ::isalpha(c) ) c -= ::isupper(c) ? 'A' - 10 : 'a' - 10; else break; if(c >= base) break; if(any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { assert(NULL); /// ¼öÄ¡ Ãʰú any = -1; } else { any = 1; acc *= base; acc += c; } } if(any < 0) { acc = neg ? LONG_MIN : LONG_MAX; } else if(neg) acc = -acc; if(endptr != 0) *endptr = any ? (char*)s - 1 : (char*)nptr; return acc; } else { /// unsigned ÃÖ´ë°ªÀ» ULONG_MAX(41¾ï...) °ªÀ¸·Î ³õ°í Àоî¿Â´Ù. cutoff = ULONG_MAX; cutlim = cutoff % (unsigned long)base; cutoff /= (unsigned long)base; for(acc = 0, any = 0;; c = *s++) { if( ::isdigit(c) ) c -= '0'; else if( ::isalpha(c) ) c -= ::isupper(c) ? 'A' - 10 : 'a' - 10; else break; if(c >= base) break; if(any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { assert(NULL); /// ¼öÄ¡ Ãʰú any = -1; } else { any = 1; acc *= base; acc += c; } } if(any < 0) { acc = ULONG_MAX; } if(endptr != 0) *endptr = any ? (char*)s - 1 : (char*)nptr; return acc; } } static double ToDouble( const char*s, char**sret ) { long double r; /* result */ int e; /* exponent */ long double d; /* scale */ int sign; /* +- 1.0 */ int esign; int i; int flags=0; r = 0.0; sign = 1; e = 0; esign = 1; while((*s == ' ') || (*s == '\t')) s++; if(*s == '+') s++; else if(*s == '-') { sign = -1; s++; } while((*s >= '0') && (*s <= '9')) { flags |= 1; r *= 10.0; r += *s - '0'; s++; } if(*s == '.') { d = 0.1L; s++; while((*s >= '0') && (*s <= '9')) { flags |= 2; r += d * (*s - '0'); s++; d *= 0.1L; } } if(flags == 0) { if(sret) *sret = (char*)s; return 0; } if((*s == 'e') || (*s == 'E')) { s++; if(*s == '+') s++; else if(*s == '-') { s++; esign = -1; } if((*s < '0') || (*s > '9')) { if(sret) *sret = (char*)s; return r; } while((*s >= '0') && (*s <= '9')) { e *= 10; e += *s - '0'; s++; } } if(esign < 0) for(i = 1; i <= e; i++) r *= 0.1L; else for(i = 1; i <= e; i++) r *= 10.0; if(sret) *sret = (char*)s; return r * sign; } static int ToInt( const char* s ) { return (int)ToLong( s, 0, 10 ); } static float ToFloat( const char* s ) { return (float)ToDouble( s, 0 ); } /// ¼Ò¹®ÀÚ¸¦ ´ë¹®ÀÚ·Î º¯È¯ static char ToUpper( char c ) { return ::toupper( c ); } /// ¹®ÀÚ¿­¾ÈÀÇ ¼Ò¹®ÀÚ¸¦ ´ë¹®ÀÚ·Î º¯È¯ static void ToUpper( char* s ) { for( ; *s; ++s ) { *s = ::toupper( *s ); } } /// ¹®ÀÚ¿­¾ÈÀÇ ´ë¹®ÀÚ¸¦ ¼Ò¹®ÀÚ·Î º¯È¯ static char ToLower( char c ) { return ::tolower( c ); } /// ¹®ÀÚ¿­¾ÈÀÇ ´ë¹®ÀÚ¸¦ ¼Ò¹®ÀÚ·Î º¯È¯ static void ToLower( char* s ) { for( ; *s; ++s ) { *s = ::tolower( *s ); } } /// ¹®ÀÚ static unsigned int GetHashCode( const char* str ) { unsigned long h = 0; for( ; *str; ++str ) { h = 5 * h + *str; } return unsigned int( h ); } /// °ø¹é ¹®ÀÚ°¡ ¾Æ´Ï¸é ÂüÀ» ¸®ÅÏ static bool IsNotSpace( char c ) { return ::isspace(c) == false; }; /// °¡º¯ ÀÎÀڷκÎÅÍ Çü½ÄÈ­ ÀÔ·Â static int _vsnprintf( char* buffer, unsigned int count, const char* format, va_list argptr ) { return ::_vsnprintf_s( buffer, count, _TRUNCATE, format, argptr ); } }; template<> class tCharTraits : public char_traits { public: /// ¹®ÀÚ¿­ s0°ú ¹®ÀÚ¿­ s1À» ºñ±³ static int Compare( const wchar_t* s0, const wchar_t* s1 ) { while( *s0 == *s1 ) { if( *s0 == 0 ) { return 0; } s0++; s1++; } return *s0 - *s1; } /// ¹®ÀÚ¿­ s0°ú ¹®ÀÚ¿­ s1À» ±æÀÌ n¸¸Å­ ºñ±³ static int Compare( const wchar_t* s0, const wchar_t* s1, unsigned int n ) { return ::memcmp( s0, s1, n*sizeof(wchar_t) ); } /// ¹®ÀÚ¿­ÀÇ ±æÀ̸¦ ¸®ÅÏ static unsigned int GetLength( const wchar_t* s ) { return ::wcslen( s ); } /// ¼ýÀÚ·Î º¯È¯ static long ToLong( const wchar_t* nptr, const wchar_t** endptr, int base ) { const wchar_t* s = nptr; unsigned long acc; int c; unsigned long cutoff; int neg = 0, any, cutlim; /* * Skip white space and pick up leading +/- sign if any. * If base is 0, allow 0x for hex and 0 for octal, else * assume decimal; if base is already 16, allow 0x. */ do{ c = *s++; } while( ::iswspace(c) ); if(c == L'-') { neg = 1; c = *s++; } else if(c == L'+') c = *s++; if((base == 0 || base == 16) && c == L'0' && (*s == L'x' || *s == L'X')) { c = s[1]; s += 2; base = 16; } if(base == 0) base = c == '0' ? 8 : 10; /* * Compute the cutoff value between legal numbers and illegal * numbers. That is the largest legal value, divided by the * base. An input number that is greater than this value, if * followed by a legal input character, is too big. One that * is equal to this value may be valid or not; the limit * between valid and invalid numbers is then based on the last * digit. For instance, if the range for longs is * [-2147483648..2147483647] and the input base is 10, * cutoff will be set to 214748364 and cutlim to either * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated * a value > 214748364, or equal but the next digit is > 7 (or 8), * the number is too big, and we will return a range error. * * Set any if any `digits' consumed; make it negative to indicate * overflow. */ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; cutlim = cutoff % (unsigned long)base; cutoff /= (unsigned long)base; for(acc = 0, any = 0;; c = *s++) { if( ::iswdigit(c) ) c -= L'0'; else if( ::iswalpha(c) ) c -= ::iswupper(c) ? L'A' - 10 : L'a' - 10; else break; if(c >= base) break; if(any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) any = -1; else { any = 1; acc *= base; acc += c; } } if(any < 0) { acc = neg ? LONG_MIN : LONG_MAX; } else if(neg) acc = -acc; if(endptr != 0) *endptr = any ? (wchar_t*)s - 1 : (wchar_t*)nptr; return acc; } static double ToDouble( const wchar_t* s, const wchar_t** sret ) { long double r; /* result */ int e; /* exponent */ long double d; /* scale */ int sign; /* +- 1.0 */ int esign; int i; int flags=0; r = 0.0; sign = 1; e = 0; esign = 1; while((*s == L' ') || (*s == L'\t')) s++; if(*s == L'+') s++; else if(*s == L'-') { sign = -1; s++; } while((*s >= L'0') && (*s <= L'9')) { flags |= 1; r *= 10.0; r += *s - L'0'; s++; } if(*s == L'.') { d = 0.1L; s++; while((*s >= L'0') && (*s <= L'9')) { flags |= 2; r += d * (*s - L'0'); s++; d *= 0.1L; } } if(flags == 0) { if(sret) *sret = (wchar_t*)s; return 0; } if((*s == L'e') || (*s == L'E')) { s++; if(*s == L'+') s++; else if(*s == L'-') { s++; esign = -1; } if((*s < L'0') || (*s > L'9')) { if(sret) *sret = (wchar_t*)s; return r; } while((*s >= L'0') && (*s <= L'9')) { e *= 10; e += *s - L'0'; s++; } } if(esign < 0) for(i = 1; i <= e; i++) r *= 0.1L; else for(i = 1; i <= e; i++) r *= 10.0; if(sret) *sret = (wchar_t*)s; return r * sign; } static int ToInt( const wchar_t* s ) { return (int)ToLong( s, 0, 10 ); } static float ToFloat( const wchar_t* s ) { return (float)ToDouble( s, 0 ); } /// ¼Ò¹®ÀÚ¸¦ ´ë¹®ÀÚ·Î º¯È¯ static wchar_t ToUpper( wchar_t c ) { return ::towupper( c ); } /// ¹®ÀÚ¿­¾ÈÀÇ ¼Ò¹®ÀÚ¸¦ ´ë¹®ÀÚ·Î º¯È¯ static void ToUpper( wchar_t* s ) { for( ; *s; ++s ) { *s = ::towupper( *s ); } } /// ¹®ÀÚ¿­¾ÈÀÇ ´ë¹®ÀÚ¸¦ ¼Ò¹®ÀÚ·Î º¯È¯ static wchar_t ToLower( wchar_t c ) { return ::towlower( c ); } /// ¹®ÀÚ¿­¾ÈÀÇ ´ë¹®ÀÚ¸¦ ¼Ò¹®ÀÚ·Î º¯È¯ static void ToLower( wchar_t* s ) { for( ; *s; ++s ) { *s = ::towlower( *s ); } } /// ¹®ÀÚ static unsigned int GetHashCode( const wchar_t* str ) { unsigned long h = 0; for( ; *str; ++str ) { h = 5 * h + *str; } return unsigned int( h ); } /// °ø¹é ¹®ÀÚ°¡ ¾Æ´Ï¸é ÂüÀ» ¸®ÅÏ static bool IsNotSpace( wchar_t c ) { return ::iswspace(c) == false; }; /// °¡º¯ ÀÎÀڷκÎÅÍ Çü½ÄÈ­ ÀÔ·Â static int _vsnprintf( wchar_t* buffer, unsigned int count, const wchar_t* format, va_list argptr ) { return ::_vsnwprintf_s( buffer, count, _TRUNCATE, format, argptr ); } }; /// ¹®ÀÚ¿­ Àü¿ª ÇÔ¼ö typedef tCharTraits cStr; typedef tCharTraits cStrW; #pragma warning( pop )