diff --git a/CMakeLists.txt b/CMakeLists.txt index c9ed1d8d..c9fe620b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0017 NEW) # need include() with .cmake project(pip) set(pip_MAJOR 2) -set(pip_MINOR 97) +set(pip_MINOR 98) set(pip_REVISION 0) set(pip_SUFFIX ) set(pip_COMPANY SHS) diff --git a/libs/main/core/piobject_macros.h b/libs/main/core/piobject_macros.h index ad3faf90..9fae4ec8 100644 --- a/libs/main/core/piobject_macros.h +++ b/libs/main/core/piobject_macros.h @@ -390,32 +390,32 @@ #define PIOBJECT(name) \ protected: \ - typedef name __PIObject__; \ + typedef name __PIObject__; \ public: \ - static const char * __classNameCC() {return #name;} \ - static uint __classNameIDS() {static uint ret = PIStringAscii(#name).hash(); return ret;} \ - virtual const char * className() const {return #name;} \ - virtual uint classNameID() const {static uint ret = PIStringAscii(#name).hash(); return ret;} \ + static const char * __classNameCC() {return #name;} \ + static uint __classNameIDS() {static uint ret = PIStringAscii(#name).hash(); return ret;} \ + const char * className() const override {return #name;} \ + uint classNameID() const override {static uint ret = PIStringAscii(#name).hash(); return ret;} \ private: \ - virtual int ptrOffset() const {name * o = (name*)100; return int(llong((PIObject*)o) - llong(o));} \ - class __BaseInitializer__ { \ - public: \ - __BaseInitializer__() { \ - uint pid = PIObject::__classNameIDS(); \ - if (pid == 0) return; \ - uint id = __classNameIDS(); \ - PIMutexLocker ml(__meta_mutex()); \ - if (__meta_data().contains(id)) return; \ - __meta_data()[pid]; \ - __meta_data()[id]; \ - __MetaData & ehp(__meta_data()[pid]); \ - __MetaData & eh(__meta_data()[id]); \ - eh.eh_set << ehp.eh_set; \ - eh.eh_func << ehp.eh_func; \ - eh.addScope(__classNameCC(), id); \ - } \ - }; \ - __BaseInitializer__ __base_init__; + int ptrOffset() const override {name * o = (name*)100; return int(llong((PIObject*)o) - llong(o));} \ + class __BaseInitializer__ { \ + public: \ + __BaseInitializer__() { \ + uint pid = PIObject::__classNameIDS(); \ + if (pid == 0) return; \ + uint id = __classNameIDS(); \ + PIMutexLocker ml(__meta_mutex()); \ + if (__meta_data().contains(id)) return; \ + __meta_data()[pid]; \ + __meta_data()[id]; \ + __MetaData & ehp(__meta_data()[pid]); \ + __MetaData & eh(__meta_data()[id]); \ + eh.eh_set << ehp.eh_set; \ + eh.eh_func << ehp.eh_func; \ + eh.addScope(__classNameCC(), id); \ + } \ + }; \ + __BaseInitializer__ __base_init__; #define PIOBJECT_PARENT(name) \ class __ParentInitializer__ { \ @@ -437,8 +437,8 @@ }; \ __ParentInitializer__ __parent_init__; \ public: \ - virtual const char * parentClassName() const {return #name;} \ - typedef name __Parent__; \ + const char * parentClassName() const override {return #name;} \ + typedef name __Parent__; \ private: #define PIOBJECT_SUBCLASS(name, parent) PIOBJECT(name) PIOBJECT_PARENT(parent) diff --git a/libs/main/core/pitextstream.h b/libs/main/core/pitextstream.h index c5f7bbc3..b4842be2 100644 --- a/libs/main/core/pitextstream.h +++ b/libs/main/core/pitextstream.h @@ -146,7 +146,7 @@ public: //! \~english Read character //! \~russian Читает символ - char takeChar(bool * rok) { + char readChar(bool * rok) { char ret; bool ok = s->binaryStreamTake(&ret, sizeof(ret)); if (!ok) is_end = true; @@ -156,11 +156,11 @@ public: //! \~english Read line //! \~russian Читает строку - PIString takeLine() { + PIString readLine() { PIByteArray ret; bool ok = true; for (;;) { - char b = takeChar(&ok); + char b = readChar(&ok); if (!ok || b == '\n') break; if (b != '\r') ret.append((uchar)b); @@ -170,16 +170,16 @@ public: //! \~english Read word, skip leading whitespaces, until next whitespace //! \~russian Читает слово, пропуская начальные пробельные символы, до следующего пробельного символа - PIString takeWord() { + PIString readWord() { static PIConstChars spaces(" \t\n\r"); - return takeUntil(spaces); + return readUntil(spaces); } //! \~english //! \~russian - PIString takeCWord() { + PIString readCWord() { static PIConstChars chars(" \t\n\r:;%$&#@!?~/*-+=.,\\\"'`[](){}<>"); - return takeUntil(chars); + return readUntil(chars); } private: @@ -190,7 +190,7 @@ private: } return PIString(); } - PIString takeUntil(const PIConstChars & chars) { + PIString readUntil(const PIConstChars & chars) { //static PIConstChars spaces(" \t\n\r"); bool ok = true; char c = skipWhile(chars, &ok); @@ -198,7 +198,7 @@ private: PIByteArray ret; ret.append((uchar)c); for (;;) { - c = takeChar(&ok); + c = readChar(&ok); if (!ok || chars.contains(c)) break; ret.append((uchar)c); } @@ -209,7 +209,7 @@ private: bool ok = true; char c = 0; for (;;) { - c = takeChar(&ok); + c = readChar(&ok); if (!ok || !chars.contains(c)) break; } if (rok) *rok = ok; @@ -291,51 +291,51 @@ template inline PITextStream

& operator <<(PITextStream

& s, c //! \~english Read word as bool //! \~russian Читает слово как логическое -template inline PITextStream

& operator >>(PITextStream

& s, bool & v) {v = s.takeWord().toBool(); return s;} +template inline PITextStream

& operator >>(PITextStream

& s, bool & v) {v = s.readWord().toBool(); return s;} //! \~english Read character //! \~russian Читает символ -template inline PITextStream

& operator >>(PITextStream

& s, char & v) {v = s.takeChar(); return s;} +template inline PITextStream

& operator >>(PITextStream

& s, char & v) {v = s.readChar(); return s;} //! \~english Read word as integer //! \~russian Читает слово как целое -template inline PITextStream

& operator >>(PITextStream

& s, uchar & v) {v = s.takeWord().toUInt(); return s;} +template inline PITextStream

& operator >>(PITextStream

& s, uchar & v) {v = s.readWord().toUInt(); return s;} //! \~english Read word as integer //! \~russian Читает слово как целое -template inline PITextStream

& operator >>(PITextStream

& s, short & v) {v = s.takeWord().toInt(); return s;} +template inline PITextStream

& operator >>(PITextStream

& s, short & v) {v = s.readWord().toInt(); return s;} //! \~english Read word as integer //! \~russian Читает слово как целое -template inline PITextStream

& operator >>(PITextStream

& s, ushort & v) {v = s.takeWord().toUInt(); return s;} +template inline PITextStream

& operator >>(PITextStream

& s, ushort & v) {v = s.readWord().toUInt(); return s;} //! \~english Read word as integer //! \~russian Читает слово как целое -template inline PITextStream

& operator >>(PITextStream

& s, int & v) {v = s.takeWord().toInt(); return s;} +template inline PITextStream

& operator >>(PITextStream

& s, int & v) {v = s.readWord().toInt(); return s;} //! \~english Read word as integer //! \~russian Читает слово как целое -template inline PITextStream

& operator >>(PITextStream

& s, uint & v) {v = s.takeWord().toUInt(); return s;} +template inline PITextStream

& operator >>(PITextStream

& s, uint & v) {v = s.readWord().toUInt(); return s;} //! \~english Read word as integer //! \~russian Читает слово как целое -template inline PITextStream

& operator >>(PITextStream

& s, llong & v) {v = s.takeWord().toLLong(); return s;} +template inline PITextStream

& operator >>(PITextStream

& s, llong & v) {v = s.readWord().toLLong(); return s;} //! \~english Read word as integer //! \~russian Читает слово как целое -template inline PITextStream

& operator >>(PITextStream

& s, ullong & v) {v = s.takeWord().toULLong(); return s;} +template inline PITextStream

& operator >>(PITextStream

& s, ullong & v) {v = s.readWord().toULLong(); return s;} //! \~english Read word as floating-point number //! \~russian Читает слово как число с плавающей точкой -template inline PITextStream

& operator >>(PITextStream

& s, float & v) {v = s.takeWord().toFloat(); return s;} +template inline PITextStream

& operator >>(PITextStream

& s, float & v) {v = s.readWord().toFloat(); return s;} //! \~english Read word as floating-point number //! \~russian Читает слово как число с плавающей точкой -template inline PITextStream

& operator >>(PITextStream

& s, double & v) {v = s.takeWord().toDouble(); return s;} +template inline PITextStream

& operator >>(PITextStream

& s, double & v) {v = s.readWord().toDouble(); return s;} //! \~english Read word //! \~russian Читает слово -template inline PITextStream

& operator >>(PITextStream

& s, PIString & v) {v = s.takeWord(); return s;} +template inline PITextStream

& operator >>(PITextStream

& s, PIString & v) {v = s.readWord(); return s;} #endif diff --git a/libs/main/io_devices/piconfig.cpp b/libs/main/io_devices/piconfig.cpp index 62212c01..476dcf01 100644 --- a/libs/main/io_devices/piconfig.cpp +++ b/libs/main/io_devices/piconfig.cpp @@ -267,33 +267,19 @@ void PIConfig::Entry::piCoutt(PICout s, const PIString & p) const { PIConfig::PIConfig(const PIString & path, PIIODevice::DeviceMode mode) { _init(); - own_dev = true; - dev = new PIFile(path, mode); - if (!dev->isOpened()) - dev->open(path, mode); - incdirs << PIFile::fileInfo(path).dir(); - parse(); + open(path, mode); } PIConfig::PIConfig(PIString * string, PIIODevice::DeviceMode mode) { _init(); - own_dev = true; - dev = new PIIOString(string, mode); - parse(); + open(string, mode); } PIConfig::PIConfig(PIIODevice * device, PIIODevice::DeviceMode mode) { _init(); - own_dev = false; - dev = device; - if (dev) { - dev->open(mode); - if (PIString(dev->className()) == "PIFile") - incdirs << PIFile::fileInfo(((PIFile*)dev)->path()).dir(); - } - parse(); + open(device, mode); } @@ -317,43 +303,57 @@ PIConfig::PIConfig(const PIString & path, PIStringList dirs) { dev = 0; return; } + _setupDev(); parse(); } PIConfig::~PIConfig() { root.deleteBranch(); - if (own_dev && dev) delete dev; - dev = 0; - piForeach (PIConfig * c, inc_devs) - delete c; - inc_devs.clear(); - includes.clear(); + _destroy(); } bool PIConfig::open(const PIString & path, PIIODevice::DeviceMode mode) { - if (own_dev && dev) delete dev; + _destroy(); + incdirs << PIFile::fileInfo(path).dir(); own_dev = true; dev = new PIFile(path, mode); if (!dev->isOpened()) dev->open(path, mode); + _setupDev(); parse(); return dev->isOpened(); } bool PIConfig::open(PIString * string, PIIODevice::DeviceMode mode) { - if (own_dev && dev) delete dev; + _destroy(); own_dev = true; dev = new PIIOString(string, mode); + _setupDev(); parse(); return true; } +bool PIConfig::open(PIIODevice * device, PIIODevice::DeviceMode mode) { + _destroy(); + own_dev = false; + dev = device; + if (dev) { + dev->open(mode); + if (dev->isTypeOf()) + incdirs << PIFile::fileInfo(((PIFile*)dev)->path()).dir(); + } + _setupDev(); + parse(); + if (device) return device->isOpened(); + return false; +} + + void PIConfig::_init() { - internal = false; delim = PIStringAscii("."); root.delim = delim; empty.delim = delim; @@ -361,6 +361,26 @@ void PIConfig::_init() { } +void PIConfig::_destroy() { + if (stream) { + delete stream; + stream = nullptr; + } + if (own_dev && dev) delete dev; + dev = nullptr; + piForeach (PIConfig * c, inc_devs) + delete c; + inc_devs.clear(); +} + + +void PIConfig::_setupDev() { + if (!dev) return; + stream = new PIIOTextStream(dev); + stream->setEncoding(PIIOTextStream::UTF8); +} + + void PIConfig::_clearDev() { if (!dev) return; if (PIString(dev->className()) == "PIFile") {((PIFile*)dev)->clear(); return;} @@ -375,10 +395,8 @@ void PIConfig::_flushDev() { bool PIConfig::_isEndDev() { - if (!dev) return true; - if (PIString(dev->className()) == "PIFile") {return ((PIFile*)dev)->isEnd();} - if (PIString(dev->className()) == "PIIOString") {return ((PIIOString*)dev)->isEnd();} - return true; + if (!stream) return true; + return stream->isEnd(); } @@ -390,19 +408,15 @@ void PIConfig::_seekToBeginDev() { PIString PIConfig::_readLineDev() { - if (!dev) return PIString(); - if (PIString(dev->className()) == "PIFile") {return ((PIFile*)dev)->readLine();} - if (PIString(dev->className()) == "PIIOString") {return ((PIIOString*)dev)->readLine();} - return PIString(); + if (!stream) return PIString(); + return stream->readLine(); } void PIConfig::_writeDev(const PIString & l) { //piCout << "write \"" << l << "\""; - if (!dev) return; - if (PIString(dev->className()) == "PIFile") {((PIFile*)dev)->write(l.toUTF8()); return;} - if (PIString(dev->className()) == "PIIOString") {((PIIOString*)dev)->writeString(l); return;} - dev->write(l.toByteArray()); + if (!stream) return; + stream->append(l); } @@ -799,7 +813,6 @@ void PIConfig::parse() { includes << iconf << iconf->includes; updateIncludes(); } - //piCout << "includes" << includes; other.back() = src; } else { name = tree.back(); diff --git a/libs/main/io_devices/piconfig.h b/libs/main/io_devices/piconfig.h index 6c415529..dc7dafde 100644 --- a/libs/main/io_devices/piconfig.h +++ b/libs/main/io_devices/piconfig.h @@ -27,6 +27,7 @@ #define PICONFIG_H #include "piiodevice.h" +#include "piiostream.h" #define PICONFIG_GET_VALUE \ Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) {return getValue(vname, PIString(def), exists);} \ @@ -68,7 +69,7 @@ public: PIConfig(PIString * string, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); //! Contructs and read configuration from custom device "device" in mode "mode" - PIConfig(PIIODevice * device = 0, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); + PIConfig(PIIODevice * device = nullptr, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); ~PIConfig(); @@ -328,12 +329,15 @@ public: }; - //! Read configuration file at path "path" in mode "mode" + //! Read configuration from file at path "path" in mode "mode" bool open(const PIString & path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); - //! Read configuration string "string" in mode "mode" + //! Read configuration from string "string" in mode "mode" bool open(PIString * string, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); + //! Read configuration from custom device "device" in mode "mode" + bool open(PIIODevice * device, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); + bool isOpened() const; //! Returns top-level entry with name "vname", if doesn`t exists return entry with value "def" and set *exist to false @@ -474,6 +478,8 @@ public: private: PIConfig(const PIString & path, PIStringList dirs); void _init(); + void _destroy(); + void _setupDev(); void _clearDev(); void _flushDev(); bool _isEndDev(); @@ -493,14 +499,15 @@ private: PIString parseLine(PIString v); void parse(); - bool own_dev, internal; + bool own_dev = false, internal = false; PIVector includes, inc_devs; Branch all_includes; - PIIODevice * dev; + PIIODevice * dev = nullptr; + PIIOTextStream * stream = nullptr; PIString delim; PIStringList incdirs; Entry root, empty; - uint lines; + uint lines = 0; PIStringList other; }; diff --git a/libs/main/io_devices/pifile.cpp b/libs/main/io_devices/pifile.cpp index b4d53be7..7e654c53 100644 --- a/libs/main/io_devices/pifile.cpp +++ b/libs/main/io_devices/pifile.cpp @@ -20,6 +20,7 @@ #include "piincludes_p.h" #include "pifile.h" #include "pidir.h" +#include "piiostream.h" #include "pitime_win.h" #ifdef WINDOWS # undef S_IFDIR @@ -229,24 +230,6 @@ bool PIFile::closeDevice() { } -PIString PIFile::readLine() { - PIByteArray str; - if (isClosed()) return str; - int cc; - while (!isEnd()) { - cc = fgetc(PRIVATE->fd); - if (char(cc) == '\n' || cc == EOF) break; - str.push_back(char(cc)); - } - str.push_back('\0'); - if (defaultCharset()) { - return PIString::fromCodepage((const char *)str.data(), defaultCharset()); - } - //cout << "readline: " << str << endl; - return PIString::fromUTF8(str); -} - - llong PIFile::readAll(void * data) { llong cp = pos(), s = size(), i = -1; seekToBegin(); @@ -371,7 +354,6 @@ void PIFile::_init() { PRIVATE->fd = 0; fdi = -1; _size = -1; - setPrecision(5); } @@ -405,7 +387,8 @@ void PIFile::seekToEnd() { void PIFile::seekToLine(llong line) { if (isClosed()) return; seekToBegin(); - piForTimes(line) readLine(); + PIIOTextStream ts(this); + piForTimes (line) ts.readLine(); clearerr(PRIVATE->fd); } @@ -444,13 +427,6 @@ bool PIFile::isEnd() const { } -void PIFile::setPrecision(int prec) { - prec_ = prec; - if (prec_ >= 0) prec_str = "." + PIString::fromNumber(prec_); - else prec_str = ""; -} - - PIFile & PIFile::put(const PIByteArray & v) { int sz = (int)v.size_s(); write(createMemoryBlock(&sz)); @@ -500,16 +476,6 @@ void PIFile::remove() { -const char * PIFile::defaultCharset() { - return PIInit::instance()->file_charset; -} - - -void PIFile::setDefaultCharset(const char * c) { - PIInit::instance()->setFileCharset(c); -} - - PIFile::FileInfo PIFile::fileInfo(const PIString & path) { FileInfo ret; diff --git a/libs/main/io_devices/pifile.h b/libs/main/io_devices/pifile.h index 9159bf64..93b92876 100644 --- a/libs/main/io_devices/pifile.h +++ b/libs/main/io_devices/pifile.h @@ -206,10 +206,7 @@ public: //! \~russian Читает один байт и возвращает его char readChar(); - //! \~english Read one text line and return it - //! \~russian Читает одну текстовую строку и возвращает её - PIString readLine(); - + //! \~english Read all file content to "data" and return readed bytes count. Position leaved unchanged //! \~russian Читает всё содержимое файла в "data" и возвращает количество прочитанных байт. Позиция остаётся неизменной llong readAll(void * data); @@ -228,7 +225,7 @@ public: llong size() const; ssize_t bytesAvailable() const override {return size() - pos();} - + //! \~english Returns read/write position //! \~russian Возвращает позицию чтения/записи llong pos() const; @@ -245,14 +242,6 @@ public: //! \~russian Возвращает \a PIFile::FileInfo текущего файла FileInfo fileInfo() const {return fileInfo(path());} - - //! \~english Returns float numbers write precision - //! \~russian Возвращает точность записи чисел с плавающей точкой - int precision() const {return prec_;} - - //! \~english Set float numbers write precision to "prec_" digits - //! \~russian Устанавливает точность записи чисел с плавающей точкой - void setPrecision(int prec); //! \~english Write size and content of "v" (serialize) //! \~russian Пишет в файл размер и содержимое "v" (сериализация) @@ -267,14 +256,7 @@ public: EVENT_HANDLER1(void, resize, llong, new_size) {resize(new_size, 0);} EVENT_HANDLER2(void, resize, llong, new_size, uchar, fill); - //! \~english - //! \~russian - static const char * defaultCharset(); - //! \~english - //! \~russian - static void setDefaultCharset(const char * c); - //! \~english Returns if file with path "path" exists //! \~russian Возвращает существует ли файл с путём "path" static bool isExists(const PIString & path); @@ -341,7 +323,7 @@ private: void _init(); PRIVATE_DECLARATION(PIP_EXPORT) - int ret, prec_, fdi; + int ret, fdi; llong _size; PIString prec_str; diff --git a/utils/resources_compiler/parser.cpp b/utils/resources_compiler/parser.cpp index b82c5d3f..a4419d84 100644 --- a/utils/resources_compiler/parser.cpp +++ b/utils/resources_compiler/parser.cpp @@ -1,5 +1,6 @@ #include "parser.h" #include "piconfig.h" +#include "piiostream.h" PIVector parse(const PIString & path) { @@ -32,9 +33,10 @@ ParserEntry makeEntry(PIString filename, const PIString & dir) { PIVector parseConf(PIFile & file, const PIString & dir) { PIVector ret; if (!file.isOpened()) return ret; + PIIOTextStream ts(&file); ParserSection ps; - while (!file.isEnd()) { - PIString line = file.readLine().trim(); + while (!ts.isEnd()) { + PIString line = ts.readLine().trim(); if (line.isEmpty()) continue; if (line.startsWith("[") && line.endsWith("]")) { if (!ps.files.isEmpty()) ret << ps; @@ -61,10 +63,11 @@ PIVector parseConf(PIFile & file, const PIString & dir) { PIVector parseQRC(PIFile & file, const PIString & dir) { PIVector ret; if (!file.isOpened()) return ret; + PIIOTextStream ts(&file); ParserSection ps; bool is_files = false; - while (!file.isEnd()) { - PIString line = file.readLine().trim(); + while (!ts.isEnd()) { + PIString line = ts.readLine().trim(); if (line.isEmpty()) continue; if (line.startsWith("