/*! \file pichar.h * \brief Unicode char */ /* PIP - Platform Independent Primitives Unicode char Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "piincludes_p.h" #include "pibytearray.h" #ifdef PIP_ICU # define U_NOEXCEPT # include "unicode/ucnv.h" # include "unicode/ustring.h" #endif #ifdef WINDOWS # include #endif char * __syslocname__ = 0; char * __sysoemname__ = 0; char * __utf8name__ = 0; #ifdef BLACKBERRY # include #endif #include #ifdef ANDROID # if __ANDROID_API__ < 21 # define wctomb(s, wc) wcrtomb(s, wc, NULL) # define mbtowc(pwc, s, n) mbrtowc(pwc, s, n, NULL) # endif #endif /*! \class PIChar * \brief Unicode char * \details This class is wrapper around \c "uint". * There are many contructors and information functions */ 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; //printf("request %d\n", sz); # endif #endif wchar_t wc(0); mbtowc(0, 0, 0); // reset mbtowc ret = mbtowc(&wc, c, size); printf("mbtowc = %d\n", ret); if (ret < 1) return 0; return ushort(int(wc)); } 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 #ifdef PIP_ICU u_strCompare((const UChar*)&(ch), 1, (const UChar*)&(o.ch), 1, FALSE) > 0; #else strcmp(toCharPtr(), o.toCharPtr()) > 0; #endif } bool PIChar::operator <(const PIChar & o) const { return #ifdef PIP_ICU u_strCompare((const UChar*)&(ch), 1, (const UChar*)&(o.ch), 1, FALSE) < 0; #else strcmp(toCharPtr(), o.toCharPtr()) < 0; #endif } bool PIChar::operator >=(const PIChar & o) const { return #ifdef PIP_ICU u_strCompare((const UChar*)&(ch), 1, (const UChar*)&(o.ch), 1, FALSE) >= 0; #else strcmp(toCharPtr(), o.toCharPtr()) >= 0; #endif } bool PIChar::operator <=(const PIChar & o) const { return #ifdef PIP_ICU u_strCompare((const UChar*)&(ch), 1, (const UChar*)&(o.ch), 1, FALSE) <= 0; #else strcmp(toCharPtr(), o.toCharPtr()) <= 0; #endif } bool PIChar::isDigit() const { return isdigit(ch) != 0; } bool PIChar::isHex() const { return isxdigit(ch) != 0; } bool PIChar::isGraphical() const { return isgraph(ch) != 0; } bool PIChar::isControl() const { return iscntrl(ch) != 0; } bool PIChar::isLower() const { return islower(ch) != 0; } bool PIChar::isUpper() const { return isupper(ch) != 0; } bool PIChar::isPrint() const { return isprint(ch) != 0; } bool PIChar::isSpace() const { return isspace(ch) != 0; } bool PIChar::isAlpha() const { return isalpha(ch) != 0; } 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 { #ifdef PIP_ICU UChar c(0); UErrorCode e((UErrorCode)0); u_strToUpper(&c, 1, (const UChar*)(&ch), 1, 0, &e); return PIChar(c); #else return PIChar(toupper(ch)); #endif } PIChar PIChar::toLower() const { #ifdef PIP_ICU UChar c(0); UErrorCode e((UErrorCode)0); u_strToLower(&c, 1, (const UChar*)(&ch), 1, 0, &e); return PIChar(c); #else return PIChar(tolower(ch)); #endif } PICout operator <<(PICout s, const PIChar & v) { s.space(); s.setControl(0, true); #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 //if (PICout::isBufferActive()) s << v.toSystem(); //else // s << v.toConsole1Byte(); #else s << v.toCharPtr(); #endif s.restoreControl(); return s; }