/* PIP - Platform Independent Primitives Unicode char Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru This program 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 3 of the License, or (at your option) any later version. This program 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 program. If not, see . */ #include "piincludes_p.h" #include "pistring.h" #ifdef PIP_ICU # define U_NOEXCEPT # include "unicode/ucnv.h" # include "unicode/ustring.h" #endif #ifdef WINDOWS # include # include #endif char * __syslocname__ = 0; char * __sysoemname__ = 0; char * __utf8name__ = 0; #ifdef BLACKBERRY # include #endif #include //! \class PIChar pichar.h //! \~\details //! \~english //! This class is wrapper around UTF16. //! There are many contructors and information functions //! //! \~russian //! %PIChar хранит один сивол в UTF16. Имеет много контрукторов, геттеров в различные //! кодировки (системную, консольную, UTF8) и информационных функций. //! ushort charFromCodepage(const char * c, int size, const char * codepage, int * taken = 0) { if (!c || size <= 0) return 0; if (uchar(c[0]) < 0x80) return c[0]; int ret; #ifdef PIP_ICU UErrorCode e((UErrorCode)0); UConverter * cc = ucnv_open(codepage, &e); if (cc) { UChar uc(0); e = (UErrorCode)0; ret = ucnv_toUChars(cc, &uc, 1, c, size, &e); //printf("PIChar %d -> %d\n", c[0], uc); if (taken) *taken = ret; ucnv_close(cc); return ushort(uc); } #else # ifdef WINDOWS wchar_t buffer; ret = MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, size, &buffer, 1); if (ret <= 0) return 0; if (taken) *taken = ret; return buffer; # else mbstate_t state; memset(&state, 0, sizeof(state)); wchar_t wc; ret = mbrtowc(&wc, c, size, &state); //printf("mbtowc = %d\n", ret); //piCout << errorString(); if (ret < 1) return 0; return ushort(wc); # endif #endif return ushort(c[0]); } int charCompare(const PIChar & f, const PIChar & s) { if (f.isAscii() && s.isAscii()) return strncmp(f.toCharPtr(), s.toCharPtr(), 1); return #ifdef PIP_ICU u_strCompare((const UChar*)f.toWCharPtr(), 1, (const UChar*)s.toWCharPtr(), 1, FALSE); #else # ifdef WINDOWS CompareStringW(LOCALE_USER_DEFAULT, 0, (PCNZWCH)f.toWCharPtr(), 1, (PCNZWCH)s.toWCharPtr(), 1) - 2; # else wcsncmp((const wchar_t *)f.toWCharPtr(), (const wchar_t *)s.toWCharPtr(), 1); # endif #endif } bool winIsCharType(const ushort * ch, int type) { #ifdef WINDOWS WORD attr = 0; if (GetStringTypeW(CT_CTYPE1, (LPCWCH)ch, 1, &attr) == 0) return false; return ((attr & type) == type); #endif return false; } PIChar::PIChar(const char * c, int * bytes) { ch = charFromCodepage(c, 4, __syslocname__, bytes); } PIChar PIChar::fromConsole(char c) { PIChar ret; ret.ch = charFromCodepage(&c, 1, __sysoemname__); return ret; } PIChar PIChar::fromSystem(char c) { PIChar ret; ret.ch = charFromCodepage(&c, 1, __syslocname__); return ret; } PIChar PIChar::fromUTF8(const char * c) { PIChar ret; int l = 0; while (c[l] != '\0') ++l; ret.ch = charFromCodepage(c, l, __utf8name__); return ret; } bool PIChar::operator ==(const PIChar & o) const { return ch == o.ch; } bool PIChar::operator >(const PIChar & o) const { return charCompare(*this, o) > 0; } bool PIChar::operator <(const PIChar & o) const { return charCompare(*this, o) < 0; } bool PIChar::operator >=(const PIChar & o) const { return charCompare(*this, o) >= 0; } bool PIChar::operator <=(const PIChar & o) const { return charCompare(*this, o) <= 0; } bool PIChar::isDigit() const { if (isAscii()) return isdigit(ch) != 0; #ifdef WINDOWS return winIsCharType(&ch, C1_DIGIT); #else return iswdigit(ch) != 0; #endif } bool PIChar::isHex() const { if (isAscii()) return isxdigit(ch) != 0; #ifdef WINDOWS return winIsCharType(&ch, C1_XDIGIT); #else return iswxdigit(ch) != 0; #endif } bool PIChar::isGraphical() const { if (isAscii()) return isgraph(ch) != 0; #ifdef WINDOWS return !winIsCharType(&ch, C1_CNTRL); #else return iswgraph(ch) != 0; #endif } bool PIChar::isControl() const { if (isAscii()) return iscntrl(ch) != 0; #ifdef WINDOWS return winIsCharType(&ch, C1_CNTRL); #else return iswcntrl(ch) != 0; #endif } bool PIChar::isLower() const { if (isAscii()) return islower(ch) != 0; #ifdef WINDOWS return winIsCharType(&ch, C1_LOWER); #else return iswlower(ch) != 0; #endif } bool PIChar::isUpper() const { if (isAscii()) return isupper(ch) != 0; #ifdef WINDOWS return winIsCharType(&ch, C1_UPPER); #else return iswupper(ch) != 0; #endif } bool PIChar::isPrint() const { if (isAscii()) return isprint(ch) != 0; #ifdef WINDOWS return !winIsCharType(&ch, C1_CNTRL); #else return iswprint(ch) != 0; #endif } bool PIChar::isSpace() const { if (isAscii()) return isspace(ch) != 0; #ifdef WINDOWS return winIsCharType(&ch, C1_SPACE); #else return iswspace(ch) != 0; #endif } bool PIChar::isAlpha() const { if (isAscii()) return isalpha(ch) != 0; #ifdef WINDOWS return winIsCharType(&ch, C1_ALPHA); #else return iswalpha(ch) != 0; #endif } bool PIChar::isAscii() const { return isascii(ch) != 0; } const wchar_t * PIChar::toWCharPtr() const { return reinterpret_cast(&ch); } const char * PIChar::toCharPtr() const { return reinterpret_cast(&ch); } wchar_t PIChar::toWChar() const { return wchar_t(ch); } char PIChar::toConsole1Byte() const { if (ch < 0x80) return ch; #ifdef PIP_ICU UErrorCode e((UErrorCode)0); UConverter * cc = ucnv_open(__sysoemname__, &e); if (cc) { char uc[8]; e = (UErrorCode)0; ucnv_fromUChars(cc, uc, 8, (const UChar*)(&ch), 1, &e); ucnv_close(cc); return uc[0]; } #endif #ifdef WINDOWS char ret[4] = {0,0,0,0}; WideCharToMultiByte(CP_OEMCP, 0, (LPCWCH)&ch, 1, ret, 4, NULL, NULL); return ret[0]; #endif return toAscii(); } char PIChar::toSystem() const { if (ch < 0x80) return ch; #ifdef PIP_ICU UErrorCode e((UErrorCode)0); UConverter * cc = ucnv_open(__syslocname__, &e); if (cc) { char uc[8]; e = (UErrorCode)0; ucnv_fromUChars(cc, uc, 8, (const UChar*)(&ch), 1, &e); ucnv_close(cc); return uc[0]; } #endif #ifdef WINDOWS char ret[4] = {0,0,0,0}; WideCharToMultiByte(CP_ACP, 0, (LPCWCH)&ch, 1, ret, 4, NULL, NULL); return ret[0]; #endif return toAscii(); } PIChar PIChar::toUpper() const { if (isAscii()) return PIChar((ushort)toupper(ch)); #ifdef PIP_ICU UChar c(0); UErrorCode e((UErrorCode)0); u_strToUpper(&c, 1, (const UChar*)(&ch), 1, 0, &e); return PIChar((ushort)c); #else # ifdef WINDOWS ushort wc = 0; if (LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE, (LPCWSTR)&ch, 1, (LPWSTR)&wc, 1) == 1) return PIChar(wc); # endif #endif return PIChar((ushort)towupper(ch)); } PIChar PIChar::toLower() const { if (isAscii()) return PIChar((ushort)tolower(ch)); #ifdef PIP_ICU UChar c(0); UErrorCode e((UErrorCode)0); u_strToLower(&c, 1, (const UChar*)(&ch), 1, 0, &e); return PIChar((ushort)c); #else # ifdef WINDOWS ushort wc = 0; if (LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, (LPCWSTR)&ch, 1, (LPWSTR)&wc, 1) == 1) return PIChar(wc); # endif #endif return PIChar((ushort)towlower(ch)); } PICout operator <<(PICout s, const PIChar & v) { s.space(); s.setControl(0, true); if (v.isAscii()) s << char(v.ch); else { #ifdef PIP_ICU UErrorCode e((UErrorCode)0); UConverter * cc = ucnv_open(__syslocname__, &e); if (cc) { char uc[8]; memset(uc, 0, 8); e = (UErrorCode)0; ucnv_fromUChars(cc, uc, 8, (const UChar*)(&v.ch), 1, &e); ucnv_close(cc); s << uc; } else #endif #ifdef WINDOWS s << v.toSystem(); #else s << PIString(v); #endif } s.restoreControl(); return s; }