From 30c1e6255826658f9bc1f9e87cf9c1f9273b0663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B5=D0=BB=D0=B8=D0=BF=D0=B5=D0=BD=D0=BA=D0=BE=20?= =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD?= Date: Tue, 14 Apr 2015 10:23:13 +0000 Subject: [PATCH] 0.5.1_alpha ICU support git-svn-id: svn://db.shs.com.ru/pip@91 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5 --- CMakeLists.txt | 11 +++++ main.cpp | 19 +++++++++ src/console/piscreen.cpp | 3 +- src/core/pichar.h | 75 ++++++++++++++++----------------- src/core/piinit.cpp | 38 +++++++++++++++++ src/core/pistring.cpp | 89 ++++++++++++++++++++++++++++++++++++--- src/core/pistring.h | 6 +-- src/io/pifiletransfer.cpp | 1 + src/piversion.h | 4 +- 9 files changed, 196 insertions(+), 50 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f27f5880..6c9435d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,17 @@ else () endif () +# Check if ICU used for PIString and PIChar +if (DEFINED ICU) + message(STATUS "Building with ICU") + unset(ICU) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPIP_ICU") + list(APPEND LIBS icuuc) +else () + message(STATUS "Building without ICU, attention!") +endif () + + # Add library if (${WIN32}) list(APPEND LIBS ws2_32 Iphlpapi Psapi) diff --git a/main.cpp b/main.cpp index 156baa77..db2f86ae 100644 --- a/main.cpp +++ b/main.cpp @@ -216,7 +216,26 @@ inline PICout operator <<(PICout s, const FixedPoint & v) { //#include "mpint.h" +#include "unicode/utypes.h" +#include "unicode/stringpiece.h" +#include "unicode/utf8.h" +#include "unicode/ucnv.h" +#include "unicode/uchar.h" + int main (int argc, char * argv[]) { + //char uc[] = "←↑→↓АБВ"; + char uc[] = "←↑→↓АБВ"; + + PIString us(uc); + + //piForeachC (PIChar & c, us) + // piCout << PICoutManipulators::Hex << PIByteArray(&c, 4); + piCout << uc; + std::cout << uc << "\n"; + printf("%s\n", uc); + //piCout << us.toByteArray() << us.size_s(); + return 0; + /*FixedPoint<16, long long> a, b; a = 10; b = 3; diff --git a/src/console/piscreen.cpp b/src/console/piscreen.cpp index c01d1daa..adb99d55 100644 --- a/src/console/piscreen.cpp +++ b/src/console/piscreen.cpp @@ -200,7 +200,8 @@ void PIScreen::SystemConsole::print() { int k = j * dw + i; Cell & c(cells[j + dy0][i + dx0]); PRIVATE->chars[k].Char.UnicodeChar = 0; - PRIVATE->chars[k].Char.AsciiChar = c.symbol.toAscii(); + PRIVATE->chars[k].Char.AsciiChar = c.symbol.toConcole1Byte(); + //PRIVATE->chars[k].Char.UnicodeChar = c.symbol.toInt(); PRIVATE->chars[k].Attributes = attributes(c); } //PRIVATE->bc.X = dx0; diff --git a/src/core/pichar.h b/src/core/pichar.h index d8f22efe..202f487d 100755 --- a/src/core/pichar.h +++ b/src/core/pichar.h @@ -24,10 +24,12 @@ #define PICHAR_H #include "pibytearray.h" -/*! \brief Unicode char - * \details This class is wrapper around \c "uint". - * There are many contructors and information functions - */ + +#ifdef PIP_ICU +extern char * __syslocname__; +extern char * __sysoemname__; +#endif + class PIP_EXPORT PIChar { friend class PIString; @@ -38,7 +40,7 @@ public: PIChar(const char c) {ch = c; ch &= 0xFF;} //! Contructs 2-bytes symbol - PIChar(const short c) {ch = c; ch &= 0xFFFF;} + PIChar(const short c) {ch = c;} //! Contructs 4-bytes symbol PIChar(const int c) {ch = c;} @@ -47,13 +49,13 @@ public: PIChar(const uchar c) {ch = c; ch &= 0xFF;} //! Contructs 2-bytes symbol - PIChar(const ushort c) {ch = c; ch &= 0xFFFF;} + PIChar(const ushort c) {ch = c;} //! Default constructor. Contructs 4-bytes symbol PIChar(const uint c = 0) {ch = c;} //! Contructs symbol from no more than 4 bytes of string - PIChar(const char * c) {ch = *reinterpret_cast(c);} + PIChar(const char * c); //inline operator const int() {return static_cast(ch);} //inline operator const char() {return toAscii();} @@ -67,7 +69,7 @@ public: inline PIChar & operator =(const uint v) {ch = v; return *this;}*/ //! Compare operator - bool operator ==(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) == 0;} + bool operator ==(const PIChar & o) const; /*inline bool operator ==(const PIChar & o) const {if (o.isAscii() ^ isAscii()) return false; if (isAscii()) return (o.toAscii() == toAscii()); return (o.toInt() == toInt());} @@ -88,87 +90,82 @@ public: inline bool operator !=(const uint o) const {return (PIChar(o) != *this);}*/ //! Compare operator - bool operator >(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) < 0;} + bool operator >(const PIChar & o) const; //! Compare operator - bool operator <(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) > 0;} + bool operator <(const PIChar & o) const; //! Compare operator - bool operator >=(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) <= 0;} + bool operator >=(const PIChar & o) const; //! Compare operator - bool operator <=(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) >= 0;} + bool operator <=(const PIChar & o) const; //! Return \b true if symbol is digit ('0' to '9') - bool isDigit() const {return isdigit(ch) != 0;} + bool isDigit() const; //! Return \b true if symbol is HEX digit ('0' to '9', 'a' to 'f', 'A' to 'F') - bool isHex() const {return isxdigit(ch) != 0;} + bool isHex() const; //! Return \b true if symbol is drawable (without space) - bool isGraphical() const {return isgraph(ch) != 0;} + bool isGraphical() const; //! Return \b true if symbol is control byte (< 32 or 127) - bool isControl() const {return iscntrl(ch) != 0;} + bool isControl() const; //! Return \b true if symbol is in lower case - bool isLower() const {return islower(ch) != 0;} + bool isLower() const; //! Return \b true if symbol is in upper case - bool isUpper() const {return isupper(ch) != 0;} + bool isUpper() const; //! Return \b true if symbol is printable (with space) - bool isPrint() const {return isprint(ch) != 0;} + bool isPrint() const; //! Return \b true if symbol is space or tab - bool isSpace() const {return isspace(ch) != 0;} + bool isSpace() const; //! Return \b true if symbol is alphabetical letter - bool isAlpha() const {return isalpha(ch) != 0;} + bool isAlpha() const; //! Return \b true if symbol is ascii (< 128) - bool isAscii() const {return isascii(ch) != 0;} + bool isAscii() const; - int toInt() const {return int(ch);} - const wchar_t * toWCharPtr() const {return reinterpret_cast(&ch);} + const wchar_t * toWCharPtr() const; //! Return as "char * " string - const char * toCharPtr() const {return reinterpret_cast(&ch);} + const char * toCharPtr() const; - wchar_t toWChar() const {return wchar_t(ch);} + wchar_t toWChar() const; char toAscii() const {return ch % 256;} - int unicode16Code() const {wchar_t wc; if (mbtowc(&wc, toCharPtr(), 4) > 0) return wc; return 0;} -//#ifdef WINDOWS -// inline PIChar toUpper() const __attribute__ ((optimize(0))) {return PIChar(toupper(ch));} -// inline PIChar toLower() const __attribute__ ((optimize(0))) {return PIChar(tolower(ch));} -//#else + char toConcole1Byte() const; + ushort unicode16Code() const {return ch;} //! Return symbol in upper case - PIChar toUpper() const {return PIChar(toupper(ch));} + PIChar toUpper() const; //! Return symbol in lower case - PIChar toLower() const {return PIChar(tolower(ch));} -//#endif + PIChar toLower() const; private: - uint ch; + ushort ch; }; __PICONTAINERS_SIMPLE_TYPE__(PIChar) //! Output operator to \c std::ostream -inline std::ostream & operator <<(std::ostream & s, const PIChar & v) {s << v.toCharPtr(); return s;} +std::ostream & operator <<(std::ostream & s, const PIChar & v); //! Output operator to \a PICout -inline PICout operator <<(PICout s, const PIChar & v) {s.space(); s.setControl(0, true); s << v.toCharPtr(); s.restoreControl(); return s;} +PICout operator <<(PICout s, const PIChar & v); //! Write operator to \c PIByteArray -inline PIByteArray & operator <<(PIByteArray & s, const PIChar & v) {s << uint(v.ch); return s;} +inline PIByteArray & operator <<(PIByteArray & s, const PIChar & v) {s << v.ch; return s;} //! Read operator from \c PIByteArray -inline PIByteArray & operator >>(PIByteArray & s, PIChar & v) {uint i; s >> i; v.ch = wchar_t(i); return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIChar & v) {s >> v.ch; return s;} //! Compare operator diff --git a/src/core/piinit.cpp b/src/core/piinit.cpp index 1e3ae4e2..883fff74 100644 --- a/src/core/piinit.cpp +++ b/src/core/piinit.cpp @@ -40,6 +40,9 @@ //# include extern clock_serv_t __pi_mac_clock; #endif +#ifdef PIP_ICU +# include +#endif /* #ifdef WINDOWS # include @@ -125,6 +128,37 @@ PIInit::PIInit() { setlocale(LC_NUMERIC, "C"); # endif #endif +#ifdef PIP_ICU + __syslocname__ = new char[256]; + memset(__syslocname__, 0, 256); +# ifdef WINDOWS + CPINFOEX cpinfo; + GetCPInfoEx(CP_ACP, 0, &cpinfo); + int l = 0; + for (l = 0; l < MAX_PATH; ++l) + if (cpinfo.CodePageName[l] == '\0' || cpinfo.CodePageName[l] == ' ') + break; + memcpy(__syslocname__, "windows-", 8); + memcpy(&(__syslocname__[8]), cpinfo.CodePageName, l); + GetCPInfoEx(CP_OEMCP, 0, &cpinfo); + for (l = 0; l < MAX_PATH; ++l) + if (cpinfo.CodePageName[l] == '\0' || cpinfo.CodePageName[l] == ' ') + break; + __sysoemname__ = new char[256]; + memset(__sysoemname__, 0, 256); + memcpy(__sysoemname__, "ibm-", 4); + memcpy(&(__sysoemname__[4]), cpinfo.CodePageName, l); + //piCout << cpinfo.CodePageName; +# else + PIString en(getenv("LANG")); + if (!en.isEmpty()) + en = en.mid(en.find(".") + 1); + PIByteArray enba = en.toByteArray(); + memcpy(__syslocname__, enba.data(), enba.size_s()); +# endif + piCout << __syslocname__; + piCout << __sysoemname__; +#endif #ifdef MAC_OS host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &__pi_mac_clock); #endif @@ -200,6 +234,10 @@ PIInit::~PIInit() { #endif #ifdef MAC_OS mach_port_deallocate(mach_task_self(), __pi_mac_clock); +#endif +#ifdef PIP_ICU + if (__syslocname__) delete __syslocname__; + if (__sysoemname__) delete __sysoemname__; #endif //if (currentLocale_t != 0) freelocale(currentLocale_t); } diff --git a/src/core/pistring.cpp b/src/core/pistring.cpp index 068fc3d9..2d62a97c 100755 --- a/src/core/pistring.cpp +++ b/src/core/pistring.cpp @@ -18,7 +18,9 @@ */ #include "pistring.h" - +#ifdef PIP_ICU +# include "unicode/ucnv.h" +#endif /*! \class PIString * \brief String class @@ -96,6 +98,23 @@ PIString PIString::dtos(const double num) {pisprintf("%.8f", num); return PIStri void PIString::appendFromChars(const char * c, int s) { + if (s <= 0) return; +#ifdef PIP_ICU + UErrorCode e((UErrorCode)0); + UConverter * cc = ucnv_open(__syslocname__, &e); + if (cc) { + UChar * ucs = new UChar[s]; + memset(ucs, 0, s * sizeof(UChar)); + e = (UErrorCode)0; + int rs = ucnv_toUChars(cc, ucs, s, c, s, &e); + //printf("appendFromChars %d -> %d\n", s, rs); + for (int i = 0; i < rs; ++i) + push_back(PIChar(ucs[i])); + delete ucs; + ucnv_close(cc); + return; + } +#endif int sz; wchar_t wc; for (int i = 0; i < s; ++i) { @@ -129,15 +148,38 @@ void PIString::appendFromChars(const char * c, int s) { void PIString::buildData() const { data_.clear(); +#ifdef PIP_ICU + UErrorCode e((UErrorCode)0); + UConverter * cc = ucnv_open(__syslocname__, &e); + if (cc) { + int rs = 0;//, ol = UCNV_GET_MAX_BYTES_FOR_STRING(size_s(), ucnv_getMaxCharSize(cc)); + char uc[8]; + for (int i = 0; i < size_s(); ++i) { + if (at(i).isAscii()) + data_.push_back(uchar(at(i).unicode16Code())); + else { + e = (UErrorCode)0; + rs = ucnv_fromUChars(cc, uc, 8, (const UChar*)(PIDeque::data(i)), 1, &e); + //printf("conv %d\n", rs); + for (int j = 0; j < rs; ++j) + data_.push_back(uc[j]); + } + } + //printf("buildData %d -> %d\n", size_s(), data_.size_s()); + ucnv_close(cc); + data_.push_back('\0'); + return; + } +#endif uint wc; uchar tc; //printf("PIString::data %d\n", size_s()); for (int i = 0, j = 0; i < size_s(); ++i) { - wc = uint(at(i).toInt()); + wc = uint(at(i).unicode16Code()); //printf("__%d_%d\n", i, wc); tc = wc & 0xFF; while (tc) { - data_ << uchar(tc); ++j; + data_.push_back(uchar(tc)); ++j; wc >>= 8; tc = wc & 0xFF; //printf("____%d\n", wc); @@ -149,7 +191,7 @@ void PIString::buildData() const { data_.push_back((at(i).toCharPtr()[1])); }*/ } - data_ << uchar('\0'); + data_.push_back(uchar('\0')); } @@ -658,7 +700,7 @@ std::string PIString::convertToStd() const { uchar tc; if (size() > 0) { for (int i = 0; i < length(); ++i) { - wc = uint(at(i).toInt()); + wc = uint(at(i).unicode16Code()); while (tc = wc & 0xFF, tc) { s.push_back(char(tc)); wc >>= 8; @@ -764,6 +806,43 @@ inline char chrLwr(char c) { } +PICout operator <<(PICout s, const PIString & v) { + s.space(); + s.quote(); + s.setControl(0, true); +#ifdef PIP_ICU + if (__sysoemname__) { + PIByteArray oba; + UErrorCode e((UErrorCode)0); + UConverter * cc = ucnv_open(__sysoemname__, &e); + if (cc) { + int rs = 0; + char uc[8]; + for (int i = 0; i < v.size_s(); ++i) { + if (v[i].isAscii()) + oba.push_back(uchar(v[i].unicode16Code())); + else { + e = (UErrorCode)0; + rs = ucnv_fromUChars(cc, uc, 8, (const UChar*)(((PIDeque*)(&v))->data(i)), 1, &e); + //printf("conv %d\n", rs); + for (int j = 0; j < rs; ++j) + oba.push_back(uc[j]); + } + } + ucnv_close(cc); + oba.push_back('\0'); + s << (const char *)oba.data(); + } else + s << v.data(); + } else +#endif + s << v.data(); + s.restoreControl(); + s.quote(); + return s; +} + + PIStringList& PIStringList::removeDuplicates() { PIStringList l; diff --git a/src/core/pistring.h b/src/core/pistring.h index 003d8645..a882ecb6 100755 --- a/src/core/pistring.h +++ b/src/core/pistring.h @@ -800,14 +800,14 @@ inline std::ostream & operator <<(std::ostream & s, const PIString & v) {for (in inline std::istream & operator >>(std::istream & s, PIString & v) {std::string ss; s >> ss; v << PIString(ss); return s;} //! \relatesalso PIString \relatesalso PICout \brief Output operator to PICout -inline PICout operator <<(PICout s, const PIString & v) {s.space(); s.quote(); s.setControl(0, true); for (int i = 0; i < v.length(); ++i) s << v[i]; s.restoreControl(); s.quote(); return s;} +PICout operator <<(PICout s, const PIString & v); //! \relatesalso PIString \relatesalso PIByteArray \brief Output operator to PIByteArray -inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {s << v.toByteArray(); return s;} +inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {s << *(PIDeque*)&v; return s;} //! \relatesalso PIString \relatesalso PIByteArray \brief Input operator from PIByteArray -inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {PIByteArray sc; s >> sc; v.clear(); v.appendFromChars((const char *)sc.data(), sc.size_s()); return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {s >> *(PIDeque*)&v; return s;} //! \relatesalso PIString \brief Return concatenated string diff --git a/src/io/pifiletransfer.cpp b/src/io/pifiletransfer.cpp index f8c1f5b3..c7afb9c0 100644 --- a/src/io/pifiletransfer.cpp +++ b/src/io/pifiletransfer.cpp @@ -126,6 +126,7 @@ void PIFileTransfer::processFile(int id, ullong start, PIByteArray & data) { stopReceive(); return; } + PIFile::applyFileInfo(path, fi); if (work_file.size() > fi.size) { // piCoutObj << "error size" << work_file.size() << fi.size; work_file.clear(); diff --git a/src/piversion.h b/src/piversion.h index 9d8954ab..6cf4665a 100644 --- a/src/piversion.h +++ b/src/piversion.h @@ -4,7 +4,7 @@ #define PIP_VERSION_MAJOR 0 #define PIP_VERSION_MINOR 5 -#define PIP_VERSION_REVISION 0 -#define PIP_VERSION_SUFFIX "_beta" +#define PIP_VERSION_REVISION 1 +#define PIP_VERSION_SUFFIX "_alpha" #endif // PIVERSION_H