diff --git a/libs/main/core/picout.cpp b/libs/main/core/picout.cpp index aa2a30fb..3fcd5e91 100644 --- a/libs/main/core/picout.cpp +++ b/libs/main/core/picout.cpp @@ -540,7 +540,7 @@ PICout & PICout::writePIString(const PIString & s) { buffer_->append(s); } else { if (PICout::isOutputDeviceActive(PICout::StdOut)) { - for (const PIChar & c: s) std::wcout.put(c.toWChar()); + for (PIChar c: s) std::wcout.put(c.toWChar()); } if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(s); } diff --git a/libs/main/core/pistring.cpp b/libs/main/core/pistring.cpp index 6e13226a..883e5ee2 100644 --- a/libs/main/core/pistring.cpp +++ b/libs/main/core/pistring.cpp @@ -28,12 +28,6 @@ # 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 //! \addtogroup Core //! \{ @@ -88,6 +82,8 @@ const float PIString::ElideLeft = 0.f; const float PIString::ElideCenter = .5f; const float PIString::ElideRight = 1.f; +static const char * _PIString_empty_cc = ""; + #ifndef CC_VC # define pisprintf(f, v) char ch[256]; memset(ch, 0, 256); sprintf(ch, f, v); return PIString(ch); @@ -235,14 +231,15 @@ void PIString::appendFromChars(const char * c, int s, const char * codepage) { return; //printf("request %d\n", sz); # else + mbstate_t state; + memset(&state, 0, sizeof(state)); wchar_t wc; - mbtowc(0,0,0); // reset mbtowc //qDebug() << "FromChars ..."; - while (s>0) { + while (sz = mbrtowc(&wc, c, s, &state) > 0) { //qDebug() << "0" << s; - sz = mbtowc(&wc, c, s); +// sz = mbrtowc(&wc, c, s, &state); //qDebug() << "1" << sz; - if (sz < 1) break; +// if (sz < 1) break; push_back(PIChar(wc)); c += sz; s -= sz; //qDebug() << "2" << c; @@ -254,37 +251,30 @@ void PIString::appendFromChars(const char * c, int s, const char * codepage) { PIString PIString::fromConsole(const char * s) { - int l = 0; - while (s[l] != '\0') ++l; PIString ret; - if (l > 0) ret.appendFromChars(s, l, __sysoemname__); + if (s[0] != '\0') ret.appendFromChars(s, strlen(s), __sysoemname__); return ret; } PIString PIString::fromSystem(const char * s) { - int l = 0; - while (s[l] != '\0') ++l; PIString ret; - if (l > 0) ret.appendFromChars(s, l, __syslocname__); + if (s[0] != '\0') ret.appendFromChars(s, strlen(s), __syslocname__); return ret; } PIString PIString::fromUTF8(const char * s) { - int l = 0; - while (s[l] != '\0') ++l; PIString ret; - if (l > 0) ret.appendFromChars(s, l, __utf8name__); + if (s[0] != '\0') ret.appendFromChars(s, strlen(s), __utf8name__); return ret; } PIString PIString::fromUTF8(const PIByteArray & ba) { PIString ret; - if (ba.isEmpty()) return ret; - ret.appendFromChars((const char*)ba.data(), ba.size(), __utf8name__); + if (ba.isNotEmpty()) ret.appendFromChars((const char*)ba.data(), ba.size(), __utf8name__); return ret; } @@ -296,19 +286,17 @@ PIString PIString::fromAscii(const char * s) { PIString PIString::fromAscii(const char * s, int len) { PIString ret; - ret.reserve(len); + ret.resize(len); for (int l = 0; l < len; ++l) { - ret.push_back(PIChar(s[l])); + ret[l] = s[l]; } return ret; } PIString PIString::fromCodepage(const char * s, const char * c) { - int l = 0; - while (s[l] != '\0') ++l; PIString ret; - if (l > 0) ret.appendFromChars(s, l + if (s[0] > '\0') ret.appendFromChars(s, strlen(s) #ifdef PIP_ICU , c #else @@ -342,7 +330,11 @@ PIString PIString::readableSize(llong bytes) { void PIString::buildData(const char * cp) const { - data_.clear(); + //data_.clear(); + if (data_) { + free(data_); + data_ = nullptr; + } int sz = 0; #ifdef PIP_ICU UErrorCode e((UErrorCode)0); @@ -371,29 +363,33 @@ void PIString::buildData(const char * cp) const { //printf("WideCharToMultiByte %d %d\n", (uint)(uintptr_t)cp, sz); if (sz <= 0) { //printf("WideCharToMultiByte erro %d\n", GetLastError()); - data_.push_back(uchar('\0')); + data_ = (char *)malloc(1); + data_[0] = '\0'; return; } - data_.resize(sz); - WideCharToMultiByte((uint)(uintptr_t)cp, 0, (LPCWCH)PIDeque::data(), PIDeque::size_s(), (LPSTR)data_.data(), data_.size_s(), NULL, NULL); - data_.push_back(uchar('\0')); + data_ = (char *)malloc(sz+1); + //data_.resize(sz); + WideCharToMultiByte((uint)(uintptr_t)cp, 0, (LPCWCH)PIDeque::data(), PIDeque::size_s(), (LPSTR)data_, sz, NULL, NULL); + data_[sz] = '\0'; return; # else wchar_t wc; - char tc[8]; - wctomb(0, 0); + //char tc[MB_CUR_MAX]; + mbstate_t state; + memset(&state, 0, sizeof(state)); + data_ = (char *)malloc(MB_CUR_MAX*size()+1); + char *p = data_; for (int i = 0; i < size_s(); ++i) { - if (at(i).isAscii()) { - data_.push_back(uchar(at(i).toAscii())); - continue; - } +// if (at(i).isAscii()) { +// data_.push_back(uchar(at(i).toAscii())); +// continue; +// } wc = at(i).toWChar(); - sz = wctomb(tc, wc); - for (int b = 0; b < sz; ++b) { - data_.push_back(uchar(tc[b])); - } + sz = wcrtomb(p, wc, &state); + if (sz < 0) break; + p += sz; } - data_.push_back(uchar('\0')); + p[0] = '\0'; # endif #endif } @@ -422,14 +418,14 @@ uint PIString::hash() const { PIByteArray PIString::toUTF8() const { - if (isEmpty()) return data_.resized(0); + if (isEmpty()) return PIByteArray(1,'\0'); buildData(__utf8name__); - return data_.resized(data_.size_s() - 1); + return PIByteArray(data_, strlen(data_)); } PIByteArray PIString::toCharset(const char * c) const { - if (isEmpty()) return data_.resized(0); + if (isEmpty()) return PIByteArray(1,'\0'); buildData( #ifdef PIP_ICU c @@ -439,19 +435,20 @@ PIByteArray PIString::toCharset(const char * c) const { # endif #endif ); - return data_.resized(data_.size_s() - 1); - + return PIByteArray(data_, strlen(data_)); } PIString & PIString::operator +=(const char * str) { if (!str) return *this; - int l = 0; - while (str[l] != '\0') ++l; - appendFromChars(str, l, __syslocname__); + appendFromChars(str, strlen(str), __syslocname__); return *this; } +PIString::~PIString() { + if(data_) free(data_); +} + PIString & PIString::operator +=(const wchar_t * str) { if (!str) return *this; @@ -1350,20 +1347,6 @@ PIString PIString::inBrackets(const PIChar start, const PIChar end) const { } -//! \~\details -//! \~english It`s equivalent length of char sequence returned by function \a data() - 1, without terminating null-char -//! \~russian Эквивалентно длине данных, возвращаемых \a data() - 1, без завершающего нулевого байта -//! \~\code -//! piCout << PIString("0123456789").lengthAscii(); // 10 -//! piCout << PIString("№1").lengthAscii(); // 3 -//! \endcode -//! \~\sa \a data() -int PIString::lengthAscii() const { - buildData(__syslocname__); - return data_.size_s() - 1; -} - - //! \~\details //! \~english //! This function fill internal buffer by sequence @@ -1380,8 +1363,9 @@ int PIString::lengthAscii() const { //! \endcode //! \~\sa \a dataConsole(), \a dataUTF8() const char * PIString::data() const { + if (isEmpty()) return _PIString_empty_cc; buildData(__syslocname__); - return (const char *)(data_.data()); + return data_; } @@ -1397,8 +1381,9 @@ const char * PIString::data() const { //! действителен до следующего вызова этого метода //! \~\sa \a data(), \a dataUTF8() const char * PIString::dataConsole() const { + if (isEmpty()) return _PIString_empty_cc; buildData(__sysoemname__ ); - return (const char *)(data_.data()); + return data_; } @@ -1414,8 +1399,9 @@ const char * PIString::dataConsole() const { //! действителен до следующего вызова этого метода //! \~\sa \a data(), \a dataConsole() const char * PIString::dataUTF8() const { + if (isEmpty()) return _PIString_empty_cc; buildData(__utf8name__); - return (const char *)(data_.data()); + return data_; } @@ -1431,12 +1417,17 @@ const char * PIString::dataUTF8() const { //! действителен до следующего вызова этого метода //! \~\sa \a dataConsole(), \a dataUTF8() const char * PIString::dataAscii() const { - data_.clear(); - for (int i = 0; i < size_s(); ++i) { - data_.push_back(uchar(at(i).ch)); + if (isEmpty()) return _PIString_empty_cc; + if (data_) { + free(data_); + data_ = nullptr; } - data_.push_back(uchar('\0')); - return (const char *)data_.data(); + data_ = (char*)malloc(size()+1); + for (int i = 0; i < size_s(); ++i) { + data_[i] = uchar(at(i).ch); + } + data_[size()] = '\0'; + return data_; } diff --git a/libs/main/core/pistring.h b/libs/main/core/pistring.h index 50a61b69..5afa1b01 100644 --- a/libs/main/core/pistring.h +++ b/libs/main/core/pistring.h @@ -39,7 +39,7 @@ class PIP_EXPORT PIString: public PIDeque public: //! \~english Contructs an empty string //! \~russian Создает пустую строку - PIString(): PIDeque() {} + PIString(): PIDeque() {data_ = nullptr;} //! \~english Value for elide at left //! \~russian Значение для пропуска слева @@ -62,18 +62,18 @@ public: //! \~english Contructs a copy of string //! \~russian Создает копию строки - PIString(const PIString & o): PIDeque(o) {} + PIString(const PIString & o): PIDeque(o) {data_ = nullptr;} - PIString(PIString && o): PIDeque(std::move(o)) {} + PIString(PIString && o): PIDeque(std::move(o)) {data_ = nullptr;} //! \~english Contructs string with single symbol "c" //! \~russian Создает строку из одного символа "c" - PIString(const PIChar c): PIDeque() {*this += c;} + PIString(const PIChar c): PIDeque() {data_ = nullptr; *this += c;} //! \~english Contructs string with single symbol "c" //! \~russian Создает строку из одного символа "c" - PIString(const char c): PIDeque() {*this += PIChar(c);} + PIString(const char c): PIDeque() {data_ = nullptr; *this += PIChar(c);} //! \~english Contructs string from C-string "str" (system codepage) //! \~russian Создает строку из C-строки "str" (кодировка системы) @@ -85,7 +85,7 @@ public: //! \~\code //! PIString s("string"); //! \endcode - PIString(const char * str): PIDeque() {*this += str;} + PIString(const char * str): PIDeque() {data_ = nullptr; *this += str;} //! \~english Contructs string from \c wchar_t C-string "str" //! \~russian Создает строку из \c wchar_t C-строки "str" @@ -97,15 +97,15 @@ public: //! \~\code //! PIString s(L"string"); //! \endcode - PIString(const wchar_t * str): PIDeque() {*this += str;} + PIString(const wchar_t * str): PIDeque() {data_ = nullptr; *this += str;} //! \~english Contructs string from byte array "ba" (as UTF-8) //! \~russian Создает строку из байтового массива "ba" (как UTF-8) - PIString(const PIByteArray & ba): PIDeque() {*this += ba;} + PIString(const PIByteArray & ba): PIDeque() {data_ = nullptr; *this += ba;} //! \~english Contructs string from "len" characters of buffer "str" //! \~russian Создает строку из "len" символов массива "str" - PIString(const PIChar * str, const int len): PIDeque(str, size_t(len)) {} + PIString(const PIChar * str, const int len): PIDeque(str, size_t(len)) {data_ = nullptr;} //! \~english Contructs string from "len" characters of buffer "str" (system codepage) //! \~russian Создает строку из "len" символов массива "str" (кодировка системы) @@ -113,7 +113,7 @@ public: //! \~\code //! PIString s("string", 3); // s = "str" //! \endcode - PIString(const char * str, const int len): PIDeque() {appendFromChars(str, len);} + PIString(const char * str, const int len): PIDeque() {data_ = nullptr; appendFromChars(str, len);} //! \~english Contructs string as sequence of characters "c" of buffer with length "len" //! \~russian Создает строку как последовательность длиной "len" символа "c" @@ -121,7 +121,7 @@ public: //! \~\code //! PIString s(5, 'p'); // s = "ppppp" //! \endcode - PIString(const int len, const char c): PIDeque() {for (int i = 0; i < len; ++i) PIDeque::push_back(PIChar(c));} + PIString(const int len, const char c): PIDeque() {data_ = nullptr; for (int i = 0; i < len; ++i) PIDeque::push_back(PIChar(c));} //! \~english Contructs string as sequence of symbols "c" of buffer with length "len" //! \~russian Создает строку как последовательность длиной "len" символа "c" @@ -129,9 +129,9 @@ public: //! \~\code //! PIString s(5, "№"); // s = "№№№№№" //! \endcode - PIString(const int len, const PIChar c): PIDeque() {for (int i = 0; i < len; ++i) PIDeque::push_back(c);} + PIString(const int len, const PIChar c): PIDeque() {data_ = nullptr; for (int i = 0; i < len; ++i) PIDeque::push_back(c);} - ~PIString() {} + ~PIString(); //! \~english Assign operator @@ -749,10 +749,6 @@ public: //! \~russian Возвращает строку между символами "start" и "end" с начала строки PIString inBrackets(const PIChar start, const PIChar end) const; - //! \~english Returns bytes count of this string in system codepage - //! \~russian Возвращает объем строки в системной кодировке - int lengthAscii() const; - //! \~english Returns \c char * representation of this string in system codepage //! \~russian Возвращает \c char * представление строки в системной кодировке const char * data() const; @@ -773,9 +769,9 @@ public: //! \~russian Возвращает хэш uint hash() const; - //! \~english Returns \a PIByteArray contains \a data() of this string without terminating null-char - //! \~russian Возвращает \a PIByteArray содержащий \a data() строки без завершающего нулевого байта - PIByteArray toByteArray() const {buildData(__utf8name__); return data_.resized(data_.size_s() - 1);} + //! \~english Same as \a toUTF8(). + //! \~russian Тоже самое, что \a toUTF8(). + PIByteArray toByteArray() const {return toUTF8();} //! \~english Returns \a PIByteArray contains \a dataUTF8() of this string without terminating null-char //! \~russian Возвращает \a PIByteArray содержащий \a dataUTF8() строки без завершающего нулевого байта @@ -1402,7 +1398,7 @@ private: void appendFromChars(const char * c, int s, const char * cp = __syslocname__); void buildData(const char * cp = __syslocname__) const; void trimsubstr(int &st, int &fn) const; - mutable PIByteArray data_; + mutable char * data_; }; diff --git a/libs/main/io_devices/piiostring.cpp b/libs/main/io_devices/piiostring.cpp index d2587cec..87be818f 100644 --- a/libs/main/io_devices/piiostring.cpp +++ b/libs/main/io_devices/piiostring.cpp @@ -67,8 +67,9 @@ int PIIOString::readDevice(void * read_to, int max_size) { PIString rs = str->mid(pos, max_size); pos += max_size; if (pos > str->size_s()) pos = str->size_s(); - int ret = rs.lengthAscii(); - memcpy(read_to, rs.data(), rs.lengthAscii()); + const char * cc = rs.data(); + int ret = strlen(cc); + memcpy(read_to, cc, ret); return ret; } @@ -81,7 +82,7 @@ int PIIOString::writeDevice(const void * data, int max_size) { if (rs.size_s() > max_size) rs.resize(max_size); str->insert(pos, rs); pos += rs.size_s(); - return rs.lengthAscii(); + return strlen((const char *)data); } @@ -90,7 +91,7 @@ int PIIOString::writeString(const PIString & string) { if (pos > str->size_s()) pos = str->size_s(); str->insert(pos, string); pos += string.size_s(); - return string.lengthAscii(); + return string.size_s(); } diff --git a/libs/main/system/piprocess.cpp b/libs/main/system/piprocess.cpp index a3e3f23b..d4d2e621 100644 --- a/libs/main/system/piprocess.cpp +++ b/libs/main/system/piprocess.cpp @@ -115,44 +115,37 @@ void PIProcess::startProc(bool detached) { //cout << "run" << endl; PIString str; /// arguments convertion -#ifdef WINDOWS int as = 0; - piForeachC (PIString & i, args) - as += i.lengthAscii() + 3; + const char * argscc[args.size()+1]; + int argsl[args.size()]; + for (int i = 0; i < args.size_s(); ++i) { + argscc[i] = args[i].data(); + argsl[i] = strlen(argscc[i]); + as += argsl[i] + 3; + } + argscc[args.size()] = 0; +#ifdef WINDOWS char * a = new char[as]; memset(a, ' ', as - 1); as = 0; for (int i = 0; i < args.size_s(); ++i) { str = args[i]; a[as] = '"'; - memcpy(&(a[as + 1]), str.data(), str.lengthAscii()); - a[as + str.lengthAscii() + 1] = '"'; - as += str.lengthAscii() + 3; + memcpy(&(a[as + 1]), argscc[i], argsl[i]); + a[as + argsl[i] + 1] = '"'; + as += argsl[i] + 3; } a[as - 1] = 0; //piCout << a; -#else - //piCout << "#" << args; - char * a[args.size_s() + 1]; - for (int i = 0; i < args.size_s(); ++i) { - str = args[i]; - //piCout << i << str << str.size() << str.lengthAscii() << str.lengthAscii() << str.lengthAscii(); - a[i] = new char[str.lengthAscii() + 1]; - memcpy(a[i], str.data(), str.lengthAscii()); - a[i][str.lengthAscii()] = 0; - } - a[args.size_s()] = 0; #endif +#ifndef WINDOWS /// environment convertion - char ** e = new char*[env.size_s() + 1]; + const char * envcc[env.size()+1]; + envcc[env.size_s()] = 0; for (int i = 0; i < env.size_s(); ++i) { - str = env[i]; - e[i] = new char[str.lengthAscii() + 1]; - memcpy(e[i], str.data(), str.lengthAscii()); - e[i][str.lengthAscii()] = 0; - //cout << e[i] << endl; + envcc[i] = env[i].data(); } - e[env.size_s()] = 0; +#endif /// files for stdin/out/err t_in = t_out = t_err = false; if (f_in.path().isEmpty()) { @@ -196,7 +189,7 @@ void PIProcess::startProc(bool detached) { 0, // Thread handle not inheritable false, // Set handle inheritance to FALSE detached ? DETACHED_PROCESS/*CREATE_NEW_CONSOLE*/ : 0, // Creation flags - 0,//e, // Use environment + 0,//envcc, // Use environment wd.isEmpty() ? 0 : wd.data(), // Use working directory &(PRIVATE->si), // Pointer to STARTUPINFO structure &(PRIVATE->pi))) // Pointer to PROCESS_INFORMATION structure @@ -209,7 +202,7 @@ void PIProcess::startProc(bool detached) { #else //cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl; - if (execve(str.data(), a, e) < 0) + if (execve(str.data(), argscc, envcc) < 0) piCoutObj << "\"execve" << str << args << "\" error :" << errorString(); } else { piMinSleep; @@ -224,14 +217,8 @@ void PIProcess::startProc(bool detached) { #endif if (!detached) execFinished(str, exit_code); is_exec = false; - for (int i = 0; i < env.size_s(); ++i) - delete e[i]; - delete[] e; #ifdef WINDOWS - delete a; -#else - for (int i = 0; i < args.size_s(); ++i) - delete a[i]; + delete[] a; #endif }