/*! \file pitextstream.h * \ingroup Text * \~\brief * \~english Text serialization functionality over PIBinaryStream * \~russian Функциональность текстовой сериализации поверх PIBinaryStream */ /* PIP - Platform Independent Primitives Text serialization functionality over PIBinaryStream Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PITEXTSTREAM_H #define PITEXTSTREAM_H #include "pistring.h" //! \ingroup Text //! \~\brief //! \~english Text serialization functionality over PIBinaryStream. //! \~russian Функциональность текстовой сериализации поверх PIBinaryStream. template class PITextStream { public: //! \~english Floating-point numbers write format //! \~russian Формат записи чисел с плавающей точкой enum FloatFormat { DecimalFormat /** \~english Decimal format, "*.*" \~russian Десятичный формат, "*.*" */ = 'f', ExponentFormat /** \~english Exponential format, "*e+-" \~russian Экспонентный формат, "*e+-" */ = 'e' }; //! \~english String encoding //! \~russian Кодировка строк enum Encoding { System /** \~english System encoding \~russian Системная кодировка */, UTF8 /** \~english UTF-8 encoding \~russian Кодировка UTF-8 */, }; //! \~english Construct text stream binded to "stream_" //! \~russian Возвращает привязанный к "stream_" текстовый поток PITextStream(PIBinaryStream

* stream_) { setStream(stream_); } //! \~english Returns binded PIBinaryStream //! \~russian Возвращает привязанный PIBinaryStream PIBinaryStream

* stream() const { return s; } void setStream(PIBinaryStream

* stream_) { s = stream_; is_end = false; } //! \~english Returns if end of stream reached //! \~russian Возвращает достигнут ли конец потока bool isEnd() const { return is_end; } //! \~english Returns read/write encoding //! \~russian Возвращает кодировку чтения/записи Encoding encoding() const { return enc; } //! \~english Set read/write encoding, default UTF8 //! \~russian Устанавливает кодировку чтения/записи, по умолчанию UTF8 void setEncoding(Encoding e) { enc = e; } //! \~english Returns float numbers write format //! \~russian Возвращает формат записи чисел с плавающей точкой FloatFormat floatFormat() const { return format_; } //! \~english Set float numbers write format, default DecimalFormat //! \~russian Устанавливает формат записи чисел с плавающей точкой, по умолчанию DecimalFormat void setFloatFormat(FloatFormat format) { format_ = format; } //! \~english Returns float numbers write precision //! \~russian Возвращает точность записи чисел с плавающей точкой int floatPrecision() const { return prec_; } //! \~english Set float numbers write precision to "prec_" digits, default 5 //! \~russian Устанавливает точность записи чисел с плавающей точкой, по умолчанию 5 void setFloatPrecision(int prec) { prec_ = prec; } //! \~english Append space //! \~russian Добавляет пробел PITextStream

& space() { s->binaryStreamAppend(' '); return *this; } //! \~english Append new line //! \~russian Добавляет новую строку PITextStream

& newLine() { s->binaryStreamAppend('\n'); return *this; } //! \~english Append "v" string //! \~russian Добавляет строку "v" void append(const PIString & v) { if (v.isEmpty()) return; PIByteArray d; switch (enc) { case System: d = v.toSystem(); break; case UTF8: d = v.toUTF8(); break; } s->binaryStreamAppend(d.data(), d.size()); } //! \~english Append "v" as ASCII //! \~russian Добавляет "v" как ASCII void append(const PIConstChars & v) { if (!v.isEmpty()) s->binaryStreamAppend(v.data(), v.size()); } //! \~english Append "v" char as character //! \~russian Добавляет "v" как символ void append(char v) { s->binaryStreamAppend(v); } //! \~english Append "v" as ASCII //! \~russian Добавляет "v" как ASCII void append(const char * v) { append(PIConstChars(v)); } //! \~english Append boolean, "true" of "false" //! \~russian Добавляет логическое, "true" of "false" void append(bool v) { append(v ? "true" : "false"); } //! \~english Append integer //! \~russian Добавляет целое void append(int v) { append(PIString::fromNumber(v)); } //! \~english Append integer //! \~russian Добавляет целое void append(llong v) { append(PIString::fromNumber(v)); } //! \~english Append floating-point number, using \a floatFormat() and \a floatPrecision() //! \~russian Добавляет число с плавающей точкой, используя \a floatFormat() и \a floatPrecision() void append(float v) { append(PIString::fromNumber(v, (char)format_, prec_)); } //! \~english Append floating-point number, using \a floatFormat() and \a floatPrecision() //! \~russian Добавляет число с плавающей точкой, используя \a floatFormat() и \a floatPrecision() void append(double v) { append(PIString::fromNumber(v, (char)format_, prec_)); } //! \~english Read character //! \~russian Читает символ char readChar(bool * rok) { char ret; bool ok = s->binaryStreamTake(&ret, sizeof(ret)); if (!ok) is_end = true; if (rok) *rok = ok; return ret; } //! \~english Read line //! \~russian Читает строку PIString readLine() { PIByteArray ret; bool ok = true; for (;;) { char b = readChar(&ok); if (!ok || b == '\n') break; if (b != '\r') ret.append((uchar)b); } return fromBytes(ret); } //! \~english Read word, skip leading whitespaces, until next whitespace //! \~russian Читает слово, пропуская начальные пробельные символы, до следующего пробельного символа PIString readWord() { static PIConstChars spaces(" \t\n\r"); return readUntil(spaces); } //! \~english Read C-word, skip leading and until non C-identifier //! \~russian Читает C-слово, пропуская начальные и до следующих символов, не являющихся C-идентификаторами PIString readCWord() { static PIConstChars chars(" \t\n\r:;%$&#@!?~/*-+=.,\\\"'`[](){}<>"); return readUntil(chars); } private: PIString fromBytes(const PIByteArray & ba) { switch (enc) { case System: return PIString::fromSystem(ba); case UTF8: return PIString::fromUTF8(ba); } return PIString(); } PIString readUntil(const PIConstChars & chars) { // static PIConstChars spaces(" \t\n\r"); bool ok = true; char c = skipWhile(chars, &ok); if (!ok) return PIString(); PIByteArray ret; ret.append((uchar)c); for (;;) { c = readChar(&ok); if (!ok || chars.contains(c)) break; ret.append((uchar)c); } return fromBytes(ret); } // returns first non-"chars" char char skipWhile(const PIConstChars & chars, bool * rok) { bool ok = true; char c = 0; for (;;) { c = readChar(&ok); if (!ok || !chars.contains(c)) break; } if (rok) *rok = ok; return c; } PIBinaryStream

* s; Encoding enc = UTF8; FloatFormat format_ = DecimalFormat; bool is_end = false; int prec_ = 5; }; //! \~english Returns PITextStream for binary stream "stream" //! \~russian Возвращает PITextStream для бинарного потока "stream" template inline PITextStream

createPITextStream(PIBinaryStream

* stream) { return PITextStream

(stream); } //! \~english Append boolean //! \~russian Добавляет логическое template inline PITextStream

& operator<<(PITextStream

& s, bool v) { s.append(v); return s; } //! \~english Append character //! \~russian Добавляет символ template inline PITextStream

& operator<<(PITextStream

& s, char v) { s.append(v); return s; } //! \~english Append integer //! \~russian Добавляет целое template inline PITextStream

& operator<<(PITextStream

& s, uchar v) { s.append((int)v); return s; } //! \~english Append integer //! \~russian Добавляет целое template inline PITextStream

& operator<<(PITextStream

& s, short v) { s.append((int)v); return s; } //! \~english Append integer //! \~russian Добавляет целое template inline PITextStream

& operator<<(PITextStream

& s, ushort v) { s.append((int)v); return s; } //! \~english Append integer //! \~russian Добавляет целое template inline PITextStream

& operator<<(PITextStream

& s, int v) { s.append((int)v); return s; } //! \~english Append integer //! \~russian Добавляет целое template inline PITextStream

& operator<<(PITextStream

& s, uint v) { s.append((int)v); return s; } //! \~english Append integer //! \~russian Добавляет целое template inline PITextStream

& operator<<(PITextStream

& s, llong v) { s.append((llong)v); return s; } //! \~english Append integer //! \~russian Добавляет целое template inline PITextStream

& operator<<(PITextStream

& s, ullong v) { s.append((llong)v); return s; } //! \~english Append floating-point number //! \~russian Добавляет число с плавающей точкой template inline PITextStream

& operator<<(PITextStream

& s, float v) { s.append(v); return s; } //! \~english Append floating-point number //! \~russian Добавляет число с плавающей точкой template inline PITextStream

& operator<<(PITextStream

& s, double v) { s.append(v); return s; } //! \~english Append string //! \~russian Добавляет строку template inline PITextStream

& operator<<(PITextStream

& s, const char * v) { s.append(v); return s; } //! \~english Append string //! \~russian Добавляет строку template inline PITextStream

& operator<<(PITextStream

& s, const PIConstChars & v) { s.append(v); return s; } //! \~english Append string //! \~russian Добавляет строку template inline PITextStream

& operator<<(PITextStream

& s, const PIString & v) { s.append(v); return s; } //! \~english Read word as bool //! \~russian Читает слово как логическое 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.readChar(); return s; } //! \~english Read word as integer //! \~russian Читает слово как целое 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.readWord().toInt(); return s; } //! \~english Read word as integer //! \~russian Читает слово как целое 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.readWord().toInt(); return s; } //! \~english Read word as integer //! \~russian Читает слово как целое 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, long & v) { v = s.readWord().toLong(); return s; } //! \~english Read word as integer //! \~russian Читает слово как целое template inline PITextStream

& operator>>(PITextStream

& s, ulong & v) { v = s.readWord().toULong(); return s; } //! \~english Read word as integer //! \~russian Читает слово как целое 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.readWord().toULLong(); return s; } //! \~english Read word as floating-point number //! \~russian Читает слово как число с плавающей точкой 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.readWord().toDouble(); return s; } //! \~english Read word //! \~russian Читает слово template inline PITextStream

& operator>>(PITextStream

& s, PIString & v) { v = s.readWord(); return s; } #endif