diff --git a/CMakeLists.txt b/CMakeLists.txt index 615ecd8c..225a8279 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0017 NEW) # need include() with .cmake project(PIP) set(PIP_MAJOR 3) -set(PIP_MINOR 16) -set(PIP_REVISION 1) +set(PIP_MINOR 17) +set(PIP_REVISION 0) set(PIP_SUFFIX ) set(PIP_COMPANY SHS) set(PIP_DOMAIN org.SHS) diff --git a/libs/main/io_devices/piiostring.cpp b/libs/main/io_devices/piiostring.cpp index 2cec7c73..52226865 100644 --- a/libs/main/io_devices/piiostring.cpp +++ b/libs/main/io_devices/piiostring.cpp @@ -41,7 +41,18 @@ PIIOString::PIIOString(const PIString & string) { } +void PIIOString::clear() { + if (str) str->clear(); + pos = 0; +} + + bool PIIOString::open(PIString * string, PIIODevice::DeviceMode mode) { + if (mode == PIIODevice::ReadWrite) { + piCoutObj << "Error: ReadWrite mode not supported, use WriteOnly or ReadOnly"; + str = nullptr; + return false; + } str = string; return PIIODevice::open(mode); } @@ -53,26 +64,57 @@ bool PIIOString::open(const PIString & string) { } +bool PIIOString::isEnd() const { + if (!str) return true; + if (mode_ == PIIODevice::WriteOnly) + return pos >= str->size_s(); + else { + str->dataUTF8(); + return pos >= static_cast(str->lastDataSize()); + } +} + + +void PIIOString::seekToBegin() { + if (!str) return; + pos = 0; +} + + +void PIIOString::seekToEnd() { + if (!str) return; + if (mode_ == PIIODevice::WriteOnly) + pos = str->size_s(); + else { + str->dataUTF8(); + pos = str->lastDataSize(); + } +} + + PIString PIIOString::readLine() { if (!canRead() || !str) return PIString(); - int np = pos; - while (++np < str->size_s()) { - if ((*str)[np] == '\n') break; + auto utf8_data = str->dataUTF8(); + ssize_t utf8_size = str->lastDataSize(); + int pp = pos; + while (++pp < utf8_size) { + if (utf8_data[pp] == '\n') break; } - PIString ret = str->mid(pos, np - pos); - pos = piMini(np + 1, str->size_s()); + PIString ret = PIString::fromUTF8(&(utf8_data[pos]), pp - pos); + pos = piMini(pp + 1, utf8_size); return ret; } ssize_t PIIOString::readDevice(void * read_to, ssize_t max_size) { if (!canRead() || !str || max_size <= 0) return -1; - PIString rs = str->mid(pos, max_size); - pos += max_size; - if (pos > str->size_s()) pos = str->size_s(); - const char * cc = rs.data(); - int ret = strlen(cc); - memcpy(read_to, cc, ret); + auto utf8_data = str->dataUTF8(); + ssize_t utf8_size = str->lastDataSize(); + if (pos >= utf8_size) return 0; + int ret = piMini(max_size, utf8_size - pos); + if (ret <= 0) return 0; + memcpy(read_to, &(utf8_data[pos]), ret); + pos += ret; return ret; } @@ -98,6 +140,12 @@ int PIIOString::writeString(const PIString & string) { } +ssize_t PIIOString::bytesAvailable() const { + if (!str) return 0; + return str->size() - pos; +} + + bool PIIOString::openDevice() { pos = 0; return (str != 0); diff --git a/libs/main/io_devices/piiostring.h b/libs/main/io_devices/piiostring.h index b24033b9..cc7473c7 100644 --- a/libs/main/io_devices/piiostring.h +++ b/libs/main/io_devices/piiostring.h @@ -39,7 +39,7 @@ class PIP_EXPORT PIIOString: public PIIODevice { public: //! \~english Contructs %PIIOString with "string" content and "mode" open mode //! \~russian Создает %PIIOString с содержимым "string" и режимом открытия "mode" - explicit PIIOString(PIString * string = 0, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); + explicit PIIOString(PIString * string = 0, PIIODevice::DeviceMode mode = PIIODevice::ReadOnly); //! \~english Contructs %PIIOString with "string" content only for read //! \~russian Создает %PIIOString с содержимым "string" только для чтения @@ -51,10 +51,7 @@ public: //! \~english Clear content string //! \~russian Очищает содержимое строки - void clear() { - if (str) str->clear(); - pos = 0; - } + void clear(); //! \~english Open "string" content with "mode" open mode //! \~russian Открывает содержимое "string" с режимом открытия "mode" @@ -66,10 +63,7 @@ public: //! \~english Returns if position is at the end of content //! \~russian Возвращает в конце содержимого ли позиция - bool isEnd() const { - if (!str) return true; - return pos >= str->size_s(); - } + bool isEnd() const; //! \~english Move read/write position to "position" @@ -78,15 +72,11 @@ public: //! \~english Move read/write position to the beginning of the string //! \~russian Перемещает позицию чтения/записи на начало строки - void seekToBegin() { - if (str) pos = 0; - } + void seekToBegin(); //! \~english Move read/write position to the end of the string //! \~russian Перемещает позицию чтения/записи на конец строки - void seekToEnd() { - if (str) pos = str->size_s(); - } + void seekToEnd(); //! \~english Read one text line and return it @@ -97,12 +87,7 @@ public: //! \~russian Вставляет строку "string" в содержимое буфера в текущую позицию int writeString(const PIString & string); - ssize_t bytesAvailable() const override { - if (str) - return str->size() - pos; - else - return 0; - } + ssize_t bytesAvailable() const override; protected: bool openDevice() override; diff --git a/libs/main/io_devices/piserial.cpp b/libs/main/io_devices/piserial.cpp index faf606ad..cee0b931 100644 --- a/libs/main/io_devices/piserial.cpp +++ b/libs/main/io_devices/piserial.cpp @@ -770,8 +770,8 @@ void PISerial::applySettings() { GetCommMask(PRIVATE->hCom, &PRIVATE->mask); SetCommMask(PRIVATE->hCom, EV_RXCHAR); GetCommState(PRIVATE->hCom, &PRIVATE->sdesc); - piCoutObj << PRIVATE->sdesc.fBinary << PRIVATE->sdesc.fAbortOnError << PRIVATE->sdesc.fDsrSensitivity << PRIVATE->sdesc.fDtrControl - << PRIVATE->sdesc.fDummy2 << PRIVATE->sdesc.fErrorChar; + // piCoutObj << PRIVATE->sdesc.fBinary << PRIVATE->sdesc.fAbortOnError << PRIVATE->sdesc.fDsrSensitivity << PRIVATE->sdesc.fDtrControl + // << PRIVATE->sdesc.fDummy2 << PRIVATE->sdesc.fErrorChar; PRIVATE->desc = PRIVATE->sdesc; PRIVATE->desc.DCBlength = sizeof(PRIVATE->desc); PRIVATE->desc.BaudRate = convertSpeed(outSpeed()); diff --git a/libs/main/text/pistring.cpp b/libs/main/text/pistring.cpp index 02200269..af33c8b5 100644 --- a/libs/main/text/pistring.cpp +++ b/libs/main/text/pistring.cpp @@ -324,6 +324,7 @@ void PIString::appendFromChars(const char * c, int s, const char * codepage) { ucs2.copy((char16_t *)d.data(old_sz), ucs2.size()); # endif #endif + changed_ = true; } @@ -455,6 +456,9 @@ PIString PIString::readableSize(llong bytes) { void PIString::buildData(const char * cp) const { + if (!changed_ && (last_loc_ == cp) && data_) return; + last_loc_ = cp; + changed_ = false; deleteData(); #ifdef PIP_ICU UErrorCode e((UErrorCode)0); @@ -464,7 +468,8 @@ void PIString::buildData(const char * cp) const { data_ = (char *)malloc(len); int sz = ucnv_fromUChars(cc, data_, len, (const UChar *)(d.data()), d.size_s(), &e); ucnv_close(cc); - data_[sz] = '\0'; + data_[sz] = '\0'; + data_size_ = sz; return; } #else @@ -477,13 +482,15 @@ void PIString::buildData(const char * cp) const { } data_ = (char *)malloc(sz + 1); WideCharToMultiByte((uint)(uintptr_t)cp, 0, (LPCWCH)d.data(), d.size_s(), (LPSTR)data_, sz, NULL, NULL); - data_[sz] = '\0'; + data_[sz] = '\0'; + data_size_ = sz; return; # else std::wstring_convert, char16_t> ucs2conv; std::string u8str = ucs2conv.to_bytes((char16_t *)d.data(), (char16_t *)d.data() + d.size()); data_ = (char *)malloc(u8str.size() + 1); strcpy(data_, u8str.c_str()); + data_size_ = u8str.size(); # endif #endif } @@ -492,7 +499,8 @@ void PIString::buildData(const char * cp) const { void PIString::deleteData() const { if (!data_) return; free(data_); - data_ = nullptr; + data_ = nullptr; + data_size_ = 0; } @@ -594,6 +602,7 @@ PIString & PIString::operator+=(const wchar_t * str) { while (str[++i]) { d.push_back(PIChar(str[i])); } + changed_ = true; return *this; } @@ -604,12 +613,14 @@ PIString & PIString::operator+=(const char16_t * str) { while (str[++i]) { d.push_back(PIChar(str[i])); } + changed_ = true; return *this; } PIString & PIString::operator+=(const PIString & str) { d.append(str.d); + changed_ = true; return *this; } @@ -622,6 +633,7 @@ PIString & PIString::operator+=(const PIConstChars & str) { d[os + l] = str[l]; } } + changed_ = true; return *this; } @@ -729,6 +741,7 @@ PIString & PIString::cutMid(int start, int len) { if (len > length() - start) len = length() - start; d.remove(start, len); } + changed_ = true; return *this; } @@ -781,6 +794,7 @@ PIString & PIString::replace(int from, int count, const PIString & with) { d.remove(from, count); d.insert(from, with.d); } + changed_ = true; return *this; } @@ -837,6 +851,7 @@ PIString & PIString::replaceAll(const PIString & what, const PIString & with) { i += dl; } } + changed_ = true; return *this; } @@ -863,6 +878,7 @@ PIString & PIString::replaceAll(const PIString & what, const char with) { if (dl > 0) d.remove(i, dl); d[i] = PIChar(with); } + changed_ = true; return *this; } @@ -879,6 +895,7 @@ PIString & PIString::replaceAll(const char what, const char with) { for (int i = 0; i < l; ++i) { if (at(i) == what) d[i] = with; } + changed_ = true; return *this; } @@ -898,12 +915,14 @@ PIString & PIString::removeAll(const PIString & str) { d.remove(i, l); i -= l; } + changed_ = true; return *this; } PIString & PIString::insert(int index, const PIString & str) { d.insert(index, str.d); + changed_ = true; return *this; } @@ -920,6 +939,7 @@ PIString & PIString::elide(int size, float pos) { int ls = piRoundf(ns * pos); d.remove(ls, length() - ns); d.insert(ls, s_dotdot.d); + changed_ = true; return *this; } diff --git a/libs/main/text/pistring.h b/libs/main/text/pistring.h index ed0727f5..94170853 100644 --- a/libs/main/text/pistring.h +++ b/libs/main/text/pistring.h @@ -71,10 +71,12 @@ public: PIString & operator+=(const PIChar & c) { d.push_back(c); + changed_ = true; return *this; } PIString & operator+=(const char c) { d.push_back(PIChar(c)); + changed_ = true; return *this; } PIString & operator+=(const char * str); @@ -105,11 +107,17 @@ public: //! \~english Contructs a copy of string. //! \~russian Создает копию строки. - PIString(const PIString & o) { d = o.d; } + PIString(const PIString & o) { + d = o.d; + changed_ = true; + } //! \~english Move constructor. //! \~russian Перемещающий конструктор. - PIString(PIString && o): d(std::move(o.d)) { piSwap(data_, o.data_); } + PIString(PIString && o): d(std::move(o.d)) { + piSwap(data_, o.data_); + changed_ = true; + } //! \~english Contructs string with single character "c". //! \~russian Создает строку из одного символа "c". @@ -197,7 +205,8 @@ public: //! \~russian Оператор присваивания. PIString & operator=(const PIString & o) { if (this == &o) return *this; - d = o.d; + d = o.d; + changed_ = true; return *this; } @@ -206,6 +215,7 @@ public: PIString & operator=(PIString && o) { d.swap(o.d); piSwap(data_, o.data_); + changed_ = true; return *this; } @@ -367,7 +377,10 @@ public: //! \~russian Индекс элемента считается от `0`. //! Индекс символа должен лежать в пределах от `0` до `size()-1`. //! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти. - inline PIChar & operator[](size_t index) { return d[index]; } + inline PIChar & operator[](size_t index) { + changed_ = true; + return d[index]; + } inline PIChar operator[](size_t index) const { return d[index]; } //! \~english Read only access to character by `index`. @@ -383,10 +396,16 @@ public: //! \~english Returns the last character of the string. //! \~russian Возвращает последний символ строки. - inline PIChar & back() { return d.back(); } + inline PIChar & back() { + changed_ = true; + return d.back(); + } inline PIChar back() const { return d.back(); } - inline PIChar & front() { return d.front(); } + inline PIChar & front() { + changed_ = true; + return d.front(); + } inline PIChar front() const { return d.front(); } //! \~english Sets size of the string, new characters are copied from `c`. @@ -402,6 +421,7 @@ public: //! \~\sa \a size(), \a clear() inline PIString & resize(size_t new_size, PIChar c = PIChar()) { d.resize(new_size, c); + changed_ = true; return *this; } @@ -409,6 +429,7 @@ public: //! \~russian Удаляет один символ с конца строки. inline PIString & pop_back() { d.pop_back(); + changed_ = true; return *this; } @@ -416,6 +437,7 @@ public: //! \~russian Удаляет один символ с начала строки. inline PIString & pop_front() { d.pop_front(); + changed_ = true; return *this; } @@ -423,6 +445,7 @@ public: //! \~russian Удаляет символы из строки, начиная с позиции `index` в количестве `count`. inline PIString & remove(size_t index, size_t count = 1) { d.remove(index, count); + changed_ = true; return *this; } @@ -430,6 +453,7 @@ public: //! \~russian Заполняет всю строку символами `c`. inline PIString & fill(PIChar c = PIChar()) { d.fill(c); + changed_ = true; return *this; } @@ -444,6 +468,7 @@ public: //! \~russian Вставляет "str" в начало строки. PIString & prepend(const PIString & str) { d.prepend(str.d); + changed_ = true; return *this; } @@ -451,6 +476,7 @@ public: //! \~russian Вставляет символ `c` в начало строки. PIString & prepend(const PIChar c) { d.prepend(c); + changed_ = true; return *this; } @@ -458,6 +484,7 @@ public: //! \~russian Вставляет символ `c` в начало строки. PIString & prepend(const char c) { d.prepend(PIChar(c)); + changed_ = true; return *this; } @@ -465,6 +492,7 @@ public: //! \~russian Вставляет "str" в начало строки. PIString & push_front(const char * str) { insert(0, str); + changed_ = true; return *this; } @@ -479,6 +507,7 @@ public: //! \~russian Вставляет "str" в начало строки. PIString & push_front(const PIString & str) { d.push_front(str.d); + changed_ = true; return *this; } @@ -486,6 +515,7 @@ public: //! \~russian Вставляет символ `c` в начало строки. PIString & push_front(const PIChar c) { d.push_front(c); + changed_ = true; return *this; } @@ -493,6 +523,7 @@ public: //! \~russian Вставляет символ `c` в начало строки. PIString & push_front(const char c) { d.push_front(PIChar(c)); + changed_ = true; return *this; } @@ -514,6 +545,7 @@ public: //! \~russian Вставляет "str" в конец строки. PIString & append(const PIString & str) { d.append(str.d); + changed_ = true; return *this; } @@ -526,6 +558,7 @@ public: //! \~russian Вставляет символ `c` в конец строки. PIString & append(const PIChar c) { d.append(c); + changed_ = true; return *this; } @@ -533,6 +566,7 @@ public: //! \~russian Вставляет символ `c` в конец строки. PIString & append(const char c) { d.append(PIChar(c)); + changed_ = true; return *this; } @@ -547,6 +581,7 @@ public: //! \~russian Вставляет "str" в конец строки. PIString & push_back(const PIString & str) { d.push_back(str.d); + changed_ = true; return *this; } @@ -559,6 +594,7 @@ public: //! \~russian Вставляет символ `c` в конец строки. PIString & push_back(const PIChar c) { d.push_back(c); + changed_ = true; return *this; } @@ -566,6 +602,7 @@ public: //! \~russian Вставляет символ `c` в конец строки. PIString & push_back(const char c) { d.push_back(PIChar(c)); + changed_ = true; return *this; } @@ -741,6 +778,7 @@ public: //! \~russian Удаляет все найденные символы "what", возвращает эту строку. PIString & removeAll(char c) { d.removeAll(PIChar(c)); + changed_ = true; return *this; } @@ -757,6 +795,7 @@ public: PIString ss(*this); times--; piForTimes(times) * this += ss; + changed_ = true; return *this; } @@ -784,6 +823,7 @@ public: //! \endcode PIString & insert(const int index, const PIChar c) { d.insert(index, c); + changed_ = true; return *this; } @@ -840,6 +880,7 @@ public: //! \~\sa \a expandLeftTo(), \a expandedRightTo(), \a expandedLeftTo() PIString & expandRightTo(const int len, const PIChar c) { if (len > d.size_s()) d.resize(len, c); + changed_ = true; return *this; } @@ -856,6 +897,7 @@ public: //! \~\sa \a expandRightTo(), \a expandedRightTo(), \a expandedLeftTo() PIString & expandLeftTo(const int len, const PIChar c) { if (len > d.size_s()) insert(0, PIString(len - d.size_s(), c)); + changed_ = true; return *this; } @@ -893,6 +935,7 @@ public: PIString & quote(PIChar c = PIChar('"')) { d.prepend(c); d.append(c); + changed_ = true; return *this; } @@ -918,6 +961,7 @@ public: //! \~\sa \a reversed() PIString & reverse() { d.reverse(); + changed_ = true; return *this; } @@ -1051,6 +1095,10 @@ public: //! \~russian Возвращает \c char * представление строки в кодировке ASCII. const char * dataAscii() const; + //! \~english Returns data size of last data*() call. + //! \~russian Возвращает размер данных последнего вызова data*(). + const size_t lastDataSize() const { return data_size_; } + //! \~english Returns hash of string //! \~russian Возвращает хэш строки uint hash() const; @@ -1279,7 +1327,10 @@ public: //! \~english Reserved memory will not be released. //! \~russian Зарезервированная память не освободится. //! \~\sa \a resize() - void clear() { d.clear(); } + void clear() { + d.clear(); + changed_ = true; + } //! \~english Returns \c true if string equal "true", "yes", "on" or positive not null numeric value. //! \~russian Возвращает \c true если строка равна "true", "yes", "on" или числу > 0. @@ -1804,7 +1855,10 @@ private: void trimsubstr(int & st, int & fn) const; PIDeque d; - mutable char * data_ = nullptr; + mutable bool changed_ = true; + mutable const char * last_loc_ = nullptr; + mutable char * data_ = nullptr; + mutable size_t data_size_ = 0; }; //! \relatesalso PIBinaryStream @@ -1820,6 +1874,7 @@ BINARY_STREAM_WRITE(PIString) { //! \~russian Оператор извлечения. BINARY_STREAM_READ(PIString) { s >> v.d; + v.changed_ = true; if (s.wasReadError()) v.clear(); return s; }