diff --git a/src/db/db/dbBinarySerialize.h b/src/db/db/dbBinarySerialize.h index 731cc74bb..8482558e0 100644 --- a/src/db/db/dbBinarySerialize.h +++ b/src/db/db/dbBinarySerialize.h @@ -36,7 +36,7 @@ #include "dbTrans.h" #include "dbText.h" -#include "tlStream.h" +#include "tlBinaryStream.h" #include "tlException.h" namespace db diff --git a/src/db/db/gsiDeclDbPropertiesSupport.h b/src/db/db/gsiDeclDbPropertiesSupport.h index 8016117c5..cb7930772 100644 --- a/src/db/db/gsiDeclDbPropertiesSupport.h +++ b/src/db/db/gsiDeclDbPropertiesSupport.h @@ -251,7 +251,7 @@ static gsi::Methods properties_support_methods () "convenient than using the layout object and the properties ID to retrieve the property value. " ) + gsi::method ("to_s", (std::string (T::*) () const) &T::to_string, - "@brief Returns a string representing the polygon\n" + "@brief Returns a string representing the object\n" ) + gsi::method_ext ("properties", &get_properties_meth_impl, "@brief Gets the user properties\n" diff --git a/src/tl/tl/tl.pro b/src/tl/tl/tl.pro index b3386179b..51061b1b3 100644 --- a/src/tl/tl/tl.pro +++ b/src/tl/tl/tl.pro @@ -11,6 +11,7 @@ FORMS = SOURCES = \ tlAssert.cc \ tlBase64.cc \ + tlBinaryStream.cc \ tlColor.cc \ tlClassRegistry.cc \ tlCopyOnWrite.cc \ @@ -62,6 +63,7 @@ HEADERS = \ tlAlgorithm.h \ tlAssert.h \ tlBase64.h \ + tlBinaryStream.h \ tlColor.h \ tlClassRegistry.h \ tlCopyOnWrite.h \ diff --git a/src/tl/tl/tlBinaryStream.cc b/src/tl/tl/tlBinaryStream.cc index e69de29bb..4de710814 100644 --- a/src/tl/tl/tlBinaryStream.cc +++ b/src/tl/tl/tlBinaryStream.cc @@ -0,0 +1,691 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2026 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "tlBinaryStream.h" + +#include + +namespace tl +{ + +// --------------------------------------------------------------- +// Type codes for Variant serialization +// These type codes are intentionally separated from tl::Variant's +// type codes to allow a backward-compatible serialization scheme. + +enum VariantTypeCode +{ + var_type_nil = 0, + var_type_bool = 1, + var_type_char = 2, + var_type_schar = 3, + var_type_uchar = 4, + var_type_short = 5, + var_type_ushort = 6, + var_type_int = 7, + var_type_uint = 8, + var_type_long = 9, + var_type_ulong = 10, + var_type_longlong = 11, + var_type_ulonglong = 12, + var_type_id = 13, + var_type_float = 14, + var_type_double = 15, + var_type_string = 16, + var_type_bytes = 17, + var_type_list = 18, + var_type_array = 19, + + var_type_other = -1 +}; + +// --------------------------------------------------------------- + +class UnexpectedEndOfFileException + : public tl::Exception +{ +public: + UnexpectedEndOfFileException (const std::string &f) + : tl::Exception (tl::to_string (tr ("Unexpected end of file in: %s")), f) + { } +}; + +class InvalidVariantTypeCode + : public tl::Exception +{ +public: + InvalidVariantTypeCode (const std::string &f, int tc) + : tl::Exception (tl::to_string (tr ("Invalid variant type code %d in file: %s - maybe file is too new for this build?")), tc, f) + { } +}; + +// --------------------------------------------------------------- + +BinaryInputStream::BinaryInputStream (InputStream &stream) + : m_stream (stream) +{ + // .. nothing yet .. +} + +void +BinaryInputStream::reset () +{ + m_stream.reset (); +} + +BinaryInputStream & +BinaryInputStream::operator>> (std::string &v) +{ + uint64_t l = 0; + *this >> l; + + v.clear (); + v.reserve (l); + + size_t chunk_size = 1024, n = l; + while (n > 0) { + size_t chunk_len = std::min (n, chunk_size); + const char *chunk_data = m_stream.get (chunk_len); + if (! chunk_data) { + throw UnexpectedEndOfFileException (source ()); + } + v.append (chunk_data, chunk_len); + n -= chunk_len; + } + + return *this; +} + +BinaryInputStream & +BinaryInputStream::operator>> (std::vector &v) +{ + uint64_t l = 0; + *this >> l; + + v.clear (); + v.reserve (l); + + size_t chunk_size = 1024, n = l; + while (n > 0) { + size_t chunk_len = std::min (n, chunk_size); + const char *chunk_data = m_stream.get (chunk_len); + if (! chunk_data) { + throw UnexpectedEndOfFileException (source ()); + } + v.insert (v.end (), chunk_data, chunk_data + chunk_len); + n -= chunk_len; + } + + return *this; +} + +BinaryInputStream & +BinaryInputStream::operator>> (double &v) +{ + const char *chunk_data = m_stream.get (8); + if (! chunk_data) { + throw UnexpectedEndOfFileException (source ()); + } + // TODO: for now, we assume that file and memory layout are identical on all platforms + v = *reinterpret_cast (chunk_data); + + return *this; +} + +BinaryInputStream & +BinaryInputStream::operator>> (float &v) +{ + const char *chunk_data = m_stream.get (4); + if (! chunk_data) { + throw UnexpectedEndOfFileException (source ()); + } + // TODO: for now, we assume that file and memory layout are identical on all platforms + v = *reinterpret_cast (chunk_data); + + return *this; +} + +BinaryInputStream & +BinaryInputStream::operator>> (bool &v) +{ + const char *chunk_data = m_stream.get (1); + if (! chunk_data) { + throw UnexpectedEndOfFileException (source ()); + } + v = *chunk_data != 0; + + return *this; +} + +BinaryInputStream & +BinaryInputStream::operator>> (uint8_t &v) +{ + const char *chunk_data = m_stream.get (1); + if (! chunk_data) { + throw UnexpectedEndOfFileException (source ()); + } + v = (uint8_t) *chunk_data; + + return *this; +} + +BinaryInputStream & +BinaryInputStream::operator>> (int8_t &v) +{ + const char *chunk_data = m_stream.get (1); + if (! chunk_data) { + throw UnexpectedEndOfFileException (source ()); + } + v = (int8_t) *chunk_data; + + return *this; +} + +BinaryInputStream & +BinaryInputStream::operator>> (uint16_t &v) +{ + const char *chunk_data = m_stream.get (2); + if (! chunk_data) { + throw UnexpectedEndOfFileException (source ()); + } + // TODO: for now, we assume that file and memory layout are identical on all platforms + v = *reinterpret_cast (chunk_data); + + return *this; +} + +BinaryInputStream & +BinaryInputStream::operator>> (int16_t &v) +{ + const char *chunk_data = m_stream.get (2); + if (! chunk_data) { + throw UnexpectedEndOfFileException (source ()); + } + // TODO: for now, we assume that file and memory layout are identical on all platforms + v = *reinterpret_cast (chunk_data); + + return *this; +} + +BinaryInputStream & +BinaryInputStream::operator>> (uint32_t &v) +{ + const char *chunk_data = m_stream.get (4); + if (! chunk_data) { + throw UnexpectedEndOfFileException (source ()); + } + // TODO: for now, we assume that file and memory layout are identical on all platforms + v = *reinterpret_cast (chunk_data); + + return *this; +} + +BinaryInputStream & +BinaryInputStream::operator>> (int32_t &v) +{ + const char *chunk_data = m_stream.get (4); + if (! chunk_data) { + throw UnexpectedEndOfFileException (source ()); + } + // TODO: for now, we assume that file and memory layout are identical on all platforms + v = *reinterpret_cast (chunk_data); + + return *this; +} + +BinaryInputStream & +BinaryInputStream::operator>> (uint64_t &v) +{ + const char *chunk_data = m_stream.get (8); + if (! chunk_data) { + throw UnexpectedEndOfFileException (source ()); + } + // TODO: for now, we assume that file and memory layout are identical on all platforms + v = *reinterpret_cast (chunk_data); + + return *this; +} + +BinaryInputStream & +BinaryInputStream::operator>> (int64_t &v) +{ + const char *chunk_data = m_stream.get (8); + if (! chunk_data) { + throw UnexpectedEndOfFileException (source ()); + } + // TODO: for now, we assume that file and memory layout are identical on all platforms + v = *reinterpret_cast (chunk_data); + + return *this; +} + +BinaryInputStream & +BinaryInputStream::operator>> (tl::Variant &v) +{ + int16_t var_type = -1; + *this >> var_type; + + switch (var_type) { + case VariantTypeCode::var_type_nil: + v = tl::Variant (); + break; + case VariantTypeCode::var_type_bool: + { + bool f = false; + *this >> f; + v = tl::Variant (f); + } + break; + case VariantTypeCode::var_type_char: + { + uint8_t vv = 0; + *this >> vv; + v = tl::Variant ((char) vv); + } + break; + case VariantTypeCode::var_type_schar: + { + int8_t vv = 0; + *this >> vv; + v = tl::Variant ((signed char) vv); + } + break; + case VariantTypeCode::var_type_uchar: + { + uint8_t vv = 0; + *this >> vv; + v = tl::Variant ((unsigned char) vv); + } + break; + case VariantTypeCode::var_type_short: + { + int16_t vv = 0; + *this >> vv; + v = tl::Variant ((short) vv); + } + break; + case VariantTypeCode::var_type_ushort: + { + uint16_t vv = 0; + *this >> vv; + v = tl::Variant ((unsigned short) vv); + } + break; + case VariantTypeCode::var_type_int: + { + int32_t vv = 0; + *this >> vv; + v = tl::Variant ((int) vv); + } + break; + case VariantTypeCode::var_type_uint: + { + uint32_t vv = 0; + *this >> vv; + v = tl::Variant ((unsigned int) vv); + } + break; + case VariantTypeCode::var_type_long: + { + int64_t vv = 0; + *this >> vv; + if (vv >= (int64_t) std::numeric_limits::min () && vv <= (int64_t) std::numeric_limits::max ()) { + v = tl::Variant ((long) vv); + } else { + // Linux to Windows migration + v = tl::Variant ((long long) vv); + } + } + break; + case VariantTypeCode::var_type_ulong: + { + uint64_t vv = 0; + *this >> vv; + if (vv >= (uint64_t) std::numeric_limits::min () && vv <= (uint64_t) std::numeric_limits::max ()) { + v = tl::Variant ((unsigned long) vv); + } else { + // Linux to Windows migration + v = tl::Variant ((unsigned long long) vv); + } + } + break; + break; + case VariantTypeCode::var_type_longlong: + { + int64_t vv = 0; + *this >> vv; + v = tl::Variant ((long long) vv); + } + break; + case VariantTypeCode::var_type_ulonglong: + { + uint64_t vv = 0; + *this >> vv; + v = tl::Variant ((unsigned long long) vv); + } + break; + case VariantTypeCode::var_type_id: + { + uint64_t vv = 0; + *this >> vv; + v = tl::Variant ((size_t) vv, true /*as id*/); + } + break; + case VariantTypeCode::var_type_float: + { + float vv = 0; + *this >> vv; + v = tl::Variant (vv); + } + break; + case VariantTypeCode::var_type_double: + { + double vv = 0; + *this >> vv; + v = tl::Variant (vv); + } + break; + case VariantTypeCode::var_type_string: + { + std::string vv; + *this >> vv; + v = tl::Variant (std::move (vv)); + } + break; + case VariantTypeCode::var_type_bytes: + { + std::vector vv; + *this >> vv; + v = tl::Variant (std::move (vv)); + } + break; + case VariantTypeCode::var_type_list: + { + uint64_t n = 0; + *this >> n; + v = tl::Variant::empty_list (); + v.reserve (n); + while (n-- > 0) { + tl::Variant vv; + *this >> vv; + v.push (std::move (vv)); + } + } + break; + case VariantTypeCode::var_type_array: + { + uint64_t n = 0; + *this >> n; + v = tl::Variant::empty_array (); + while (n-- > 0) { + tl::Variant vk, vv; + *this >> vk; + *this >> vv; + v.insert (std::move (vk), std::move (vv)); + } + } + break; + case VariantTypeCode::var_type_other: + { + std::string s; + *this >> s; + tl::Extractor ex (s.c_str ()); + v = tl::Variant (); + ex.read (v); + } + break; + default: + throw InvalidVariantTypeCode (source (), int (var_type)); + } + + return *this; +} + +// --------------------------------------------------------------- +// BinaryOutputStream implementation + +BinaryOutputStream::BinaryOutputStream (OutputStreamBase &delegate) + : OutputStream (delegate, false) +{ + // .. nothing yet .. +} + +BinaryOutputStream::BinaryOutputStream (OutputStreamBase *delegate) + : OutputStream (delegate, false) +{ + // .. nothing yet .. +} + +BinaryOutputStream::BinaryOutputStream (const std::string &abstract_path, OutputStreamMode om, int keep_backups) + : OutputStream (abstract_path, om, false, keep_backups) +{ + // .. nothing yet .. +} + +void +BinaryOutputStream::put_native (const char *s, size_t n) +{ + // the native format for a string is a length field (uint64_t) and the bytes + // TODO: for now we assume that the memory layout is the same for all platforms + uint64_t len = uint64_t (n); + put_raw ((const char *) &len, 8); + put_raw (s, n); +} + +void +BinaryOutputStream::put_native (const std::string &s) +{ + // the native format for a string is a length field (uint64_t) and the bytes + // TODO: for now we assume that the memory layout is the same for all platforms + uint64_t len = uint64_t (s.size ()); + put_raw ((const char *) &len, 8); + put_raw (s.c_str (), s.size ()); +} + +void +BinaryOutputStream::put_native (double v) +{ + // TODO: for now we assume that the memory layout is the same for all platforms + put_raw ((const char *) &v, 8); +} + +void +BinaryOutputStream::put_native (float v) +{ + // TODO: for now we assume that the memory layout is the same for all platforms + put_raw ((const char *) &v, 4); +} + +void +BinaryOutputStream::put_native (bool v) +{ + char c = v ? 1 : 0; + put_raw (&c, 1); +} + +void +BinaryOutputStream::put_native (uint8_t v) +{ + put_raw ((const char *) &v, 1); +} + +void +BinaryOutputStream::put_native (int8_t v) +{ + put_raw ((const char *) &v, 1); +} + +void +BinaryOutputStream::put_native (uint16_t v) +{ + // TODO: for now we assume that the memory layout is the same for all platforms + put_raw ((const char *) &v, 2); +} + +void +BinaryOutputStream::put_native (int16_t v) +{ + // TODO: for now we assume that the memory layout is the same for all platforms + put_raw ((const char *) &v, 2); +} + +void +BinaryOutputStream::put_native (uint32_t v) +{ + // TODO: for now we assume that the memory layout is the same for all platforms + put_raw ((const char *) &v, 4); +} + +void +BinaryOutputStream::put_native (int32_t v) +{ + // TODO: for now we assume that the memory layout is the same for all platforms + put_raw ((const char *) &v, 4); +} + +void +BinaryOutputStream::put_native (uint64_t v) +{ + // TODO: for now we assume that the memory layout is the same for all platforms + put_raw ((const char *) &v, 8); +} + +void +BinaryOutputStream::put_native (int64_t v) +{ + // TODO: for now we assume that the memory layout is the same for all platforms + put_raw ((const char *) &v, 8); +} + +void +BinaryOutputStream::put_native (const tl::Variant &v) +{ + switch (v.type_code ()) { + case tl::Variant::t_nil: + put_native ((int16_t) VariantTypeCode::var_type_nil); + break; + case tl::Variant::t_bool: + put_native ((int16_t) VariantTypeCode::var_type_bool); + put_native (v.to_bool ()); + break; + case tl::Variant::t_char: + put_native ((int16_t) VariantTypeCode::var_type_char); + put_native ((uint8_t) v.to_char ()); + break; + case tl::Variant::t_schar: + put_native ((int16_t) VariantTypeCode::var_type_schar); + put_native ((int8_t) v.to_schar ()); + break; + case tl::Variant::t_uchar: + put_native ((int16_t) VariantTypeCode::var_type_uchar); + put_native ((uint8_t) v.to_uchar ()); + break; + case tl::Variant::t_short: + put_native ((int16_t) VariantTypeCode::var_type_short); + put_native ((int16_t) v.to_short ()); + break; + case tl::Variant::t_ushort: + put_native ((int16_t) VariantTypeCode::var_type_ushort); + put_native ((uint16_t) v.to_ushort ()); + break; + case tl::Variant::t_int: + put_native ((int16_t) VariantTypeCode::var_type_int); + put_native ((int32_t) v.to_int ()); + break; + case tl::Variant::t_uint: + put_native ((int16_t) VariantTypeCode::var_type_uint); + put_native ((uint32_t) v.to_uint ()); + break; + case tl::Variant::t_long: + put_native ((int16_t) VariantTypeCode::var_type_long); + // NOTE: "long" is always encoded as 64 bit for compatibility of Windows + Linux + put_native ((int64_t) v.to_long ()); + break; + case tl::Variant::t_ulong: + put_native ((int16_t) VariantTypeCode::var_type_ulong); + // NOTE: "ulong" is always encoded as 64 bit for compatibility of Windows + Linux + put_native ((uint64_t) v.to_ulong ()); + break; + case tl::Variant::t_longlong: + put_native ((int16_t) VariantTypeCode::var_type_longlong); + put_native ((int64_t) v.to_longlong ()); + break; + case tl::Variant::t_ulonglong: + put_native ((int16_t) VariantTypeCode::var_type_ulonglong); + put_native ((uint64_t) v.to_ulonglong ()); + break; + case tl::Variant::t_id: + put_native ((int16_t) VariantTypeCode::var_type_id); + // NOTE: "id" is always encoded as 64 bit + put_native ((uint64_t) v.to_id ()); + break; + case tl::Variant::t_float: + put_native ((int16_t) VariantTypeCode::var_type_float); + put_native (v.to_float ()); + break; + case tl::Variant::t_double: + put_native ((int16_t) VariantTypeCode::var_type_double); + put_native (v.to_double ()); + break; + case tl::Variant::t_string: + case tl::Variant::t_stdstring: + put_native ((int16_t) VariantTypeCode::var_type_string); + put_native (v.to_stdstring ()); + break; + case tl::Variant::t_bytearray: +#if defined(HAVE_QT) + case tl::Variant::t_qstring: + case tl::Variant::t_qbytearray: +#endif + { + put_native ((int16_t) VariantTypeCode::var_type_bytes); + std::vector bytes = v.to_bytearray (); + put_native (bytes.begin ().operator-> (), bytes.size ()); + } + break; + case tl::Variant::t_list: + { + put_native ((int16_t) VariantTypeCode::var_type_list); + put_native ((uint64_t) v.size ()); + for (auto i = v.begin (); i != v.end (); ++i) { + put_native (*i); + } + } + break; + case tl::Variant::t_array: + { + put_native ((int16_t) VariantTypeCode::var_type_array); + put_native ((uint64_t) v.array_size ()); + for (auto i = v.begin_array (); i != v.end_array (); ++i) { + put_native (i->first); + put_native (i->second); + } + } + break; + default: + put_native ((int16_t) VariantTypeCode::var_type_other); + put_native (v.to_parsable_string ()); + break; + } +} + +} diff --git a/src/tl/tl/tlBinaryStream.h b/src/tl/tl/tlBinaryStream.h index e69de29bb..4b6596ced 100644 --- a/src/tl/tl/tlBinaryStream.h +++ b/src/tl/tl/tlBinaryStream.h @@ -0,0 +1,207 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2026 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_tlBinaryStream +#define HDR_tlBinaryStream + +#include "tlCommon.h" +#include "tlStream.h" +#include "tlVariant.h" + +namespace tl +{ + +// --------------------------------------------------------------------------------- + +/** + * @brief An output stream specialized on binary representation + */ + +class TL_PUBLIC BinaryOutputStream + : public OutputStream +{ +public: + /** + * @brief Default constructor + * + * This constructor takes a delegate object. + */ + BinaryOutputStream (OutputStreamBase &delegate); + + /** + * @brief Default constructor + * + * This constructor takes a delegate object. The stream will own the delegate. + */ + BinaryOutputStream (OutputStreamBase *delegate); + + /** + * @brief Open an output stream with the given path and stream mode + * + * This will automatically create a delegate object and delete it later. + */ + BinaryOutputStream (const std::string &abstract_path, OutputStreamMode om = OM_Auto, int keep_backups = 0); + + /** + * @brief << operator: inserts character + */ + OutputStream &operator<< (char s) + { + put (&s, 1); + return *this; + } + + /** + * @brief << operator: inserts a character + */ + OutputStream &operator<< (unsigned char s) + { + put ((const char *) &s, 1); + return *this; + } + + /** + * @brief << operator: inserts a string + * + * In binary mode, the string is inserted as a length/data + * combination. That matches the extraction in BinaryInputStream. + */ + BinaryOutputStream &operator<< (const char *s) + { + put_native (s, strlen (s)); + return *this; + } + + /** + * @brief << operator: inserts a string + * + * In binary mode, the string is inserted as a length/data + * combination. That matches the extraction in BinaryInputStream. + */ + BinaryOutputStream &operator<< (const std::string &s) + { + put_native (s); + return *this; + } + + /** + * @brief << operator: inserts an object supported by "put_native". + */ + template + BinaryOutputStream &operator<< (const T &t) + { + put_native (t); + return *this; + } + +private: + void put_native (const std::string &s); + void put_native (const char *s, size_t n); + void put_native (double v); + void put_native (float v); + void put_native (bool v); + void put_native (uint8_t v); + void put_native (int8_t v); + void put_native (uint16_t v); + void put_native (int16_t v); + void put_native (uint32_t v); + void put_native (int32_t v); + void put_native (uint64_t v); + void put_native (int64_t v); + void put_native (const tl::Variant &v); + + void set_as_text (bool f); + + // No copying currently + BinaryOutputStream (const BinaryOutputStream &); + BinaryOutputStream &operator= (const BinaryOutputStream &); +}; + +// --------------------------------------------------------------------------------- + +/** + * @brief A binary input stream + * + * This class is put in front of a InputStream to retrieve binary primitives from the stream. + * The binary format corresponds to binary mode of OutputStream. + */ +class TL_PUBLIC BinaryInputStream +{ +public: + /** + * @brief Default constructor + * + * This constructor takes a delegate object. + */ + BinaryInputStream (InputStream &stream); + + /** + * @brief Gets the raw stream + */ + InputStream &raw_stream () + { + return m_stream; + } + + /** + * @brief Get the source specification + */ + std::string source () const + { + return m_stream.source (); + } + + /** + * @brief Gets a value of a specific type + */ + BinaryInputStream &operator>> (std::string &v); + BinaryInputStream &operator>> (std::vector &v); + BinaryInputStream &operator>> (double &v); + BinaryInputStream &operator>> (float &v); + BinaryInputStream &operator>> (bool &v); + BinaryInputStream &operator>> (uint8_t &v); + BinaryInputStream &operator>> (int8_t &v); + BinaryInputStream &operator>> (uint16_t &v); + BinaryInputStream &operator>> (int16_t &v); + BinaryInputStream &operator>> (uint32_t &v); + BinaryInputStream &operator>> (int32_t &v); + BinaryInputStream &operator>> (uint64_t &v); + BinaryInputStream &operator>> (int64_t &v); + BinaryInputStream &operator>> (tl::Variant &v); + + /** + * @brief Resets to the initial position + */ + void reset (); + +private: + InputStream &m_stream; + + // no copying + BinaryInputStream (const BinaryInputStream &); + BinaryInputStream &operator= (const BinaryInputStream &); +}; + +} + +#endif diff --git a/src/tl/tl/tlStream.cc b/src/tl/tl/tlStream.cc index ceb7c1008..fce7a43ae 100644 --- a/src/tl/tl/tlStream.cc +++ b/src/tl/tl/tlStream.cc @@ -20,8 +20,6 @@ */ - - #include #include #include @@ -133,15 +131,6 @@ public: { } }; -class UnexpectedEndOfFileException - : public tl::Exception -{ -public: - UnexpectedEndOfFileException (const std::string &f) - : tl::Exception (tl::to_string (tr ("Unexpected end of file: %s")), f) - { } -}; - // --------------------------------------------------------------- class ZLibFilePrivate @@ -929,183 +918,6 @@ TextInputStream::reset () } } -// --------------------------------------------------------------- - -BinaryInputStream::BinaryInputStream (InputStream &stream) - : m_stream (stream) -{ - // .. nothing yet .. -} - -void -BinaryInputStream::reset () -{ - m_stream.reset (); -} - -BinaryInputStream & -BinaryInputStream::operator>> (std::string &v) -{ - uint64_t l = 0; - *this >> l; - - v.clear (); - v.reserve (l); - - size_t chunk_size = 1024, n = l; - while (n > 0) { - size_t chunk_len = std::min (n, chunk_size); - const char *chunk_data = m_stream.get (chunk_len); - if (! chunk_data) { - throw UnexpectedEndOfFileException (source ()); - } - v.append (chunk_data, chunk_len); - n -= chunk_len; - } - - return *this; -} - -BinaryInputStream & -BinaryInputStream::operator>> (double &v) -{ - const char *chunk_data = m_stream.get (8); - if (! chunk_data) { - throw UnexpectedEndOfFileException (source ()); - } - // TODO: for now, we assume that file and memory layout are identical on all platforms - v = *reinterpret_cast (chunk_data); - - return *this; -} - -BinaryInputStream & -BinaryInputStream::operator>> (float &v) -{ - const char *chunk_data = m_stream.get (4); - if (! chunk_data) { - throw UnexpectedEndOfFileException (source ()); - } - // TODO: for now, we assume that file and memory layout are identical on all platforms - v = *reinterpret_cast (chunk_data); - - return *this; -} - -BinaryInputStream & -BinaryInputStream::operator>> (bool &v) -{ - const char *chunk_data = m_stream.get (1); - if (! chunk_data) { - throw UnexpectedEndOfFileException (source ()); - } - v = *chunk_data != 0; - - return *this; -} - -BinaryInputStream & -BinaryInputStream::operator>> (uint8_t &v) -{ - const char *chunk_data = m_stream.get (1); - if (! chunk_data) { - throw UnexpectedEndOfFileException (source ()); - } - v = (uint8_t) *chunk_data; - - return *this; -} - -BinaryInputStream & -BinaryInputStream::operator>> (int8_t &v) -{ - const char *chunk_data = m_stream.get (1); - if (! chunk_data) { - throw UnexpectedEndOfFileException (source ()); - } - v = (int8_t) *chunk_data; - - return *this; -} - -BinaryInputStream & -BinaryInputStream::operator>> (uint16_t &v) -{ - const char *chunk_data = m_stream.get (2); - if (! chunk_data) { - throw UnexpectedEndOfFileException (source ()); - } - // TODO: for now, we assume that file and memory layout are identical on all platforms - v = *reinterpret_cast (chunk_data); - - return *this; -} - -BinaryInputStream & -BinaryInputStream::operator>> (int16_t &v) -{ - const char *chunk_data = m_stream.get (2); - if (! chunk_data) { - throw UnexpectedEndOfFileException (source ()); - } - // TODO: for now, we assume that file and memory layout are identical on all platforms - v = *reinterpret_cast (chunk_data); - - return *this; -} - -BinaryInputStream & -BinaryInputStream::operator>> (uint32_t &v) -{ - const char *chunk_data = m_stream.get (4); - if (! chunk_data) { - throw UnexpectedEndOfFileException (source ()); - } - // TODO: for now, we assume that file and memory layout are identical on all platforms - v = *reinterpret_cast (chunk_data); - - return *this; -} - -BinaryInputStream & -BinaryInputStream::operator>> (int32_t &v) -{ - const char *chunk_data = m_stream.get (4); - if (! chunk_data) { - throw UnexpectedEndOfFileException (source ()); - } - // TODO: for now, we assume that file and memory layout are identical on all platforms - v = *reinterpret_cast (chunk_data); - - return *this; -} - -BinaryInputStream & -BinaryInputStream::operator>> (uint64_t &v) -{ - const char *chunk_data = m_stream.get (8); - if (! chunk_data) { - throw UnexpectedEndOfFileException (source ()); - } - // TODO: for now, we assume that file and memory layout are identical on all platforms - v = *reinterpret_cast (chunk_data); - - return *this; -} - -BinaryInputStream & -BinaryInputStream::operator>> (int64_t &v) -{ - const char *chunk_data = m_stream.get (8); - if (! chunk_data) { - throw UnexpectedEndOfFileException (source ()); - } - // TODO: for now, we assume that file and memory layout are identical on all platforms - v = *reinterpret_cast (chunk_data); - - return *this; -} - // --------------------------------------------------------------- // InputFile implementation @@ -1479,122 +1291,6 @@ OutputStream::seek (size_t pos) m_pos = pos; } -// --------------------------------------------------------------- -// BinaryOutputStream implementation - -BinaryOutputStream::BinaryOutputStream (OutputStreamBase &delegate) - : OutputStream (delegate, false) -{ - // .. nothing yet .. -} - -BinaryOutputStream::BinaryOutputStream (OutputStreamBase *delegate) - : OutputStream (delegate, false) -{ - // .. nothing yet .. -} - -BinaryOutputStream::BinaryOutputStream (const std::string &abstract_path, OutputStreamMode om, int keep_backups) - : OutputStream (abstract_path, om, false, keep_backups) -{ - // .. nothing yet .. -} - -void -BinaryOutputStream::put_native (const char *s, size_t n) -{ - // the native format for a string is a length field (uint64_t) and the bytes - // TODO: for now we assume that the memory layout is the same for all platforms - uint64_t len = uint64_t (n); - put_raw ((const char *) &len, 8); - put_raw (s, n); -} - -void -BinaryOutputStream::put_native (const std::string &s) -{ - // the native format for a string is a length field (uint64_t) and the bytes - // TODO: for now we assume that the memory layout is the same for all platforms - uint64_t len = uint64_t (s.size ()); - put_raw ((const char *) &len, 8); - put_raw (s.c_str (), s.size ()); -} - -void -BinaryOutputStream::put_native (double v) -{ - // TODO: for now we assume that the memory layout is the same for all platforms - put_raw ((const char *) &v, 8); -} - -void -BinaryOutputStream::put_native (float v) -{ - // TODO: for now we assume that the memory layout is the same for all platforms - put_raw ((const char *) &v, 4); -} - -void -BinaryOutputStream::put_native (bool v) -{ - char c = v ? 1 : 0; - put_raw (&c, 1); -} - -void -BinaryOutputStream::put_native (uint8_t v) -{ - put_raw ((const char *) &v, 1); -} - -void -BinaryOutputStream::put_native (int8_t v) -{ - put_raw ((const char *) &v, 1); -} - -void -BinaryOutputStream::put_native (uint16_t v) -{ - // TODO: for now we assume that the memory layout is the same for all platforms - put_raw ((const char *) &v, 2); -} - -void -BinaryOutputStream::put_native (int16_t v) -{ - // TODO: for now we assume that the memory layout is the same for all platforms - put_raw ((const char *) &v, 2); -} - -void -BinaryOutputStream::put_native (uint32_t v) -{ - // TODO: for now we assume that the memory layout is the same for all platforms - put_raw ((const char *) &v, 4); -} - -void -BinaryOutputStream::put_native (int32_t v) -{ - // TODO: for now we assume that the memory layout is the same for all platforms - put_raw ((const char *) &v, 4); -} - -void -BinaryOutputStream::put_native (uint64_t v) -{ - // TODO: for now we assume that the memory layout is the same for all platforms - put_raw ((const char *) &v, 8); -} - -void -BinaryOutputStream::put_native (int64_t v) -{ - // TODO: for now we assume that the memory layout is the same for all platforms - put_raw ((const char *) &v, 8); -} - // --------------------------------------------------------------- // OutputFileBase implementation diff --git a/src/tl/tl/tlStream.h b/src/tl/tl/tlStream.h index 0e8d65463..0b9764611 100644 --- a/src/tl/tl/tlStream.h +++ b/src/tl/tl/tlStream.h @@ -805,69 +805,6 @@ private: // --------------------------------------------------------------------------------- -/** - * @brief A binary input stream - * - * This class is put in front of a InputStream to retrieve binary primitives from the stream. - * The binary format corresponds to binary mode of OutputStream. - */ -class TL_PUBLIC BinaryInputStream -{ -public: - /** - * @brief Default constructor - * - * This constructor takes a delegate object. - */ - BinaryInputStream (InputStream &stream); - - /** - * @brief Gets the raw stream - */ - InputStream &raw_stream () - { - return m_stream; - } - - /** - * @brief Get the source specification - */ - std::string source () const - { - return m_stream.source (); - } - - /** - * @brief Gets a value of a specific type - */ - BinaryInputStream &operator>> (std::string &v); - BinaryInputStream &operator>> (double &v); - BinaryInputStream &operator>> (float &v); - BinaryInputStream &operator>> (bool &v); - BinaryInputStream &operator>> (uint8_t &v); - BinaryInputStream &operator>> (int8_t &v); - BinaryInputStream &operator>> (uint16_t &v); - BinaryInputStream &operator>> (int16_t &v); - BinaryInputStream &operator>> (uint32_t &v); - BinaryInputStream &operator>> (int32_t &v); - BinaryInputStream &operator>> (uint64_t &v); - BinaryInputStream &operator>> (int64_t &v); - - /** - * @brief Resets to the initial position - */ - void reset (); - -private: - InputStream &m_stream; - - // no copying - BinaryInputStream (const BinaryInputStream &); - BinaryInputStream &operator= (const BinaryInputStream &); -}; - -// --------------------------------------------------------------------------------- - /** * @brief The output stream delegate base class * @@ -1537,111 +1474,6 @@ private: OutputStream &operator= (const OutputStream &); }; -// --------------------------------------------------------------------------------- - -/** - * @brief An output stream specialized on binary representation - */ - -class TL_PUBLIC BinaryOutputStream - : public OutputStream -{ -public: - /** - * @brief Default constructor - * - * This constructor takes a delegate object. - */ - BinaryOutputStream (OutputStreamBase &delegate); - - /** - * @brief Default constructor - * - * This constructor takes a delegate object. The stream will own the delegate. - */ - BinaryOutputStream (OutputStreamBase *delegate); - - /** - * @brief Open an output stream with the given path and stream mode - * - * This will automatically create a delegate object and delete it later. - */ - BinaryOutputStream (const std::string &abstract_path, OutputStreamMode om = OM_Auto, int keep_backups = 0); - - /** - * @brief << operator: inserts character - */ - OutputStream &operator<< (char s) - { - put (&s, 1); - return *this; - } - - /** - * @brief << operator: inserts a character - */ - OutputStream &operator<< (unsigned char s) - { - put ((const char *) &s, 1); - return *this; - } - - /** - * @brief << operator: inserts a string - * - * In binary mode, the string is inserted as a length/data - * combination. That matches the extraction in BinaryInputStream. - */ - BinaryOutputStream &operator<< (const char *s) - { - put_native (s, strlen (s)); - return *this; - } - - /** - * @brief << operator: inserts a string - * - * In binary mode, the string is inserted as a length/data - * combination. That matches the extraction in BinaryInputStream. - */ - BinaryOutputStream &operator<< (const std::string &s) - { - put_native (s); - return *this; - } - - /** - * @brief << operator: inserts an object supported by "put_native". - */ - template - BinaryOutputStream &operator<< (const T &t) - { - put_native (t); - return *this; - } - -private: - void put_native (const std::string &s); - void put_native (const char *s, size_t n); - void put_native (double v); - void put_native (float v); - void put_native (bool v); - void put_native (uint8_t v); - void put_native (int8_t v); - void put_native (uint16_t v); - void put_native (int16_t v); - void put_native (uint32_t v); - void put_native (int32_t v); - void put_native (uint64_t v); - void put_native (int64_t v); - - void set_as_text (bool f); - - // No copying currently - BinaryOutputStream (const BinaryOutputStream &); - BinaryOutputStream &operator= (const BinaryOutputStream &); -}; - } #endif diff --git a/src/tl/tl/tlString.cc b/src/tl/tl/tlString.cc index 251568511..9242d99c7 100644 --- a/src/tl/tl/tlString.cc +++ b/src/tl/tl/tlString.cc @@ -651,7 +651,7 @@ to_quoted_string (const std::string &s) std::string r; r.reserve (s.size () + 2); r += '\''; - for (const char *c = s.c_str (); *c; ++c) { + for (auto c = s.begin (); c != s.end (); ++c) { if (*c == '\'' || *c == '\\') { r += '\\'; r += *c; diff --git a/src/tl/tl/tlVariant.cc b/src/tl/tl/tlVariant.cc index 3633ef37b..aef08085a 100644 --- a/src/tl/tl/tlVariant.cc +++ b/src/tl/tl/tlVariant.cc @@ -315,6 +315,12 @@ Variant::Variant (const std::vector &ba) m_var.m_bytearray = new std::vector (ba); } +Variant::Variant (std::vector &&ba) + : m_type (t_bytearray), m_string (0) +{ + m_var.m_bytearray = new std::vector (ba); +} + #if defined(HAVE_QT) Variant::Variant (const QByteArray &qba) @@ -530,7 +536,13 @@ Variant::Variant (const std::string &s) m_var.m_stdstring = new std::string (s); } -Variant::Variant (const char *s) +Variant::Variant (std::string &&s) + : m_type (t_stdstring), m_string (0) +{ + m_var.m_stdstring = new std::string (s); +} + +Variant::Variant (const char *s) : m_type (s != 0 ? t_string : t_nil) { if (s) { @@ -645,6 +657,12 @@ Variant::Variant (const Variant &v) operator= (v); } +Variant::Variant (Variant &&v) + : m_type (t_nil), m_string (0) +{ + swap (v); +} + Variant::~Variant () { reset (); @@ -713,6 +731,20 @@ Variant::operator= (const std::string &s) return *this; } +Variant & +Variant::operator= (std::string &&s) +{ + if (m_type == t_stdstring && &s == m_var.m_stdstring) { + // we are assigning to ourselves + } else { + std::string *snew = new std::string (s); + reset (); + m_type = t_stdstring; + m_var.m_stdstring = snew; + } + return *this; +} + Variant & Variant::operator= (const std::vector &s) { @@ -727,6 +759,20 @@ Variant::operator= (const std::vector &s) return *this; } +Variant & +Variant::operator= (std::vector &&s) +{ + if (m_type == t_bytearray && &s == m_var.m_bytearray) { + // we are assigning to ourselves + } else { + std::vector *snew = new std::vector (s); + reset (); + m_type = t_bytearray; + m_var.m_bytearray = snew; + } + return *this; +} + #if defined(HAVE_QT) Variant & @@ -900,6 +946,13 @@ Variant::operator= (__int128 l) } #endif +Variant & +Variant::operator= (Variant &&v) +{ + swap (v); + return *this; +} + Variant & Variant::operator= (const Variant &v) { @@ -1958,7 +2011,7 @@ Variant::to_string () const } else if (m_type == t_float) { r = tl::to_string (m_var.m_float, 7); } else if (m_type == t_char) { - r = tl::to_string ((int) m_var.m_char); + r += m_var.m_char; } else if (m_type == t_schar) { r = tl::to_string ((int) m_var.m_schar); } else if (m_type == t_uchar) { @@ -2602,12 +2655,10 @@ Variant::to_parsable_string () const return "nil"; } else if (is_stdstring ()) { return tl::to_quoted_string (*m_var.m_stdstring); -#if defined(HAVE_QT) - } else if (is_cstring () || is_qstring () || is_qbytearray () || is_bytearray ()) { -#else - } else if (is_cstring () || is_bytearray ()) { -#endif - return tl::to_quoted_string (to_string ()); + } else if (is_a_string ()) { + return tl::to_quoted_string (to_stdstring ()); + } else if (is_a_bytearray ()) { + return tl::to_quoted_string (to_stdstring ()) + "b"; } else if (is_list ()) { std::string r = "("; for (tl::Variant::const_iterator l = begin (); l != end (); ++l) { @@ -2630,6 +2681,10 @@ Variant::to_parsable_string () const } r += "}"; return r; + } else if (is_char ()) { + std::string s; + s += to_char (); + return tl::to_quoted_string (s) + "c"; } else if (is_id ()) { return "[id" + tl::to_string (m_var.m_id) + "]"; } else if (is_user ()) { @@ -3049,7 +3104,15 @@ TL_PUBLIC bool test_extractor_impl (tl::Extractor &ex, tl::Variant &v) } else if (ex.try_read_word_or_quoted (s)) { - v = tl::Variant (s); + if (ex.test ("c") || ex.test ("C")) { + v = s.empty () ? tl::Variant () : tl::Variant ((char) s.front ()); + } else if (ex.test ("b") || ex.test ("B")) { + std::vector cv (s.begin (), s.end ()); + v = tl::Variant (std::move (cv)); + } else { + v = tl::Variant (s); + } + return true; } else { diff --git a/src/tl/tl/tlVariant.h b/src/tl/tl/tlVariant.h index 5abaa1c45..0d2c28d96 100644 --- a/src/tl/tl/tlVariant.h +++ b/src/tl/tl/tlVariant.h @@ -205,11 +205,21 @@ public: */ Variant (const tl::Variant &d); + /** + * @brief Move ctor + */ + Variant (tl::Variant &&d); + /** * @brief Initialize the Variant with a std::vector */ Variant (const std::vector &s); + /** + * @brief Initialize the Variant with a std::vector (move semantics) + */ + Variant (std::vector &&s); + #if defined(HAVE_QT) /** * @brief Initialize the Variant with a QByteArray @@ -234,6 +244,11 @@ public: */ Variant (const std::string &s); + /** + * @brief Initialize the Variant with "string" (move semantics) + */ + Variant (std::string &&s); + /** * @brief Initialize the Variant with "string" */ @@ -466,6 +481,15 @@ public: m_var.m_list = new std::vector (list); } + /** + * @brief Initialize the Variant with an explicit vector of variants (move semantics) + */ + Variant (std::vector &&list) + : m_type (t_list), m_string (0) + { + m_var.m_list = new std::vector (list); + } + /** * @brief Initialize the Variant with an explicit map of variants */ @@ -475,6 +499,15 @@ public: m_var.m_array = new std::map (map); } + /** + * @brief Initialize the Variant with an explicit map of variants (move semantics) + */ + Variant (std::map &&map) + : m_type (t_array), m_string (0) + { + m_var.m_array = new std::map (map); + } + /** * @brief Initialize the Variant with a list */ @@ -546,6 +579,11 @@ public: */ Variant &operator= (const Variant &v); + /** + * @brief Assignment (move) + */ + Variant &operator= (Variant &&v); + /** * @brief Assignment of a string */ @@ -568,11 +606,21 @@ public: */ Variant &operator= (const std::string &v); + /** + * @brief Assignment of a string (move) + */ + Variant &operator= (std::string &&v); + /** * @brief Assignment of a STL byte array */ Variant &operator= (const std::vector &v); + /** + * @brief Assignment of a STL byte array (move) + */ + Variant &operator= (std::vector &&v); + /** * @brief Assignment of a double */ @@ -1173,6 +1221,15 @@ public: m_var.m_list->push_back (v); } + /** + * @brief Add a element to the list (move semantics) + */ + void push (tl::Variant &&v) + { + tl_assert (m_type == t_list); + m_var.m_list->push_back (v); + } + /** * @brief Get the back element of the list */ @@ -1280,6 +1337,15 @@ public: m_var.m_array->insert (std::make_pair (k, v)); } + /** + * @brief Insert an element into the array (move semantics) + */ + void insert (tl::Variant &&k, tl::Variant &&v) + { + tl_assert (m_type == t_array); + m_var.m_array->insert (std::make_pair (k, v)); + } + /** * @brief Returns the value for the given key or 0 if the variant is not an array or does not contain the key */ diff --git a/src/tl/unit_tests/tlBinaryStreamTests.cc b/src/tl/unit_tests/tlBinaryStreamTests.cc new file mode 100644 index 000000000..3a3c77779 --- /dev/null +++ b/src/tl/unit_tests/tlBinaryStreamTests.cc @@ -0,0 +1,425 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2026 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "tlBinaryStream.h" +#include "tlUnitTest.h" + +std::string s2string (tl::OutputMemoryStream &osm) +{ + std::string res; + size_t n = osm.size (); + const char *d = osm.data (); + for (size_t i = 0; i < n; ++i, ++d) { + if (i > 0) { + res += ","; + } + res += tl::sprintf ("0x%02x", int ((unsigned char) *d)); + } + return res; +} + +TEST(BinaryStreams1) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + os << (double) 0.17; + + os.flush (); + EXPECT_EQ (s2string (osm), "0xc3,0xf5,0x28,0x5c,0x8f,0xc2,0xc5,0x3f"); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + double x = 0.0; + bis >> x; + + EXPECT_EQ (tl::to_string (x), "0.17"); +} + +TEST(BinaryStreams2) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + os << (float) 0.17; + + os.flush (); + EXPECT_EQ (s2string (osm), "0x7b,0x14,0x2e,0x3e"); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + float x = 0.0; + bis >> x; + + EXPECT_EQ (tl::to_string (x), "0.17"); +} + +TEST(BinaryStreams3) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + os << std::string ("ABC"); + + os.flush (); + EXPECT_EQ (s2string (osm), "0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x42,0x43"); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + std::string x; + bis >> x; + + EXPECT_EQ (x, "ABC"); +} + +TEST(BinaryStreams4) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + os << "ABC"; + + os.flush (); + EXPECT_EQ (s2string (osm), "0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x42,0x43"); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + std::string x; + bis >> x; + + EXPECT_EQ (x, "ABC"); +} + +TEST(BinaryStreams5) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + os << uint8_t (17); + + os.flush (); + EXPECT_EQ (s2string (osm), "0x11"); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + uint8_t x; + bis >> x; + + EXPECT_EQ (x, 17); +} + +TEST(BinaryStreams6) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + os << int8_t (17); + + os.flush (); + EXPECT_EQ (s2string (osm), "0x11"); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + int8_t x; + bis >> x; + + EXPECT_EQ (x, 17); +} + +TEST(BinaryStreams7) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + os << uint16_t (1742); + + os.flush (); + EXPECT_EQ (s2string (osm), "0xce,0x06"); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + uint16_t x; + bis >> x; + + EXPECT_EQ (x, 1742); +} + +TEST(BinaryStreams8) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + os << int16_t (1742); + + os.flush (); + EXPECT_EQ (s2string (osm), "0xce,0x06"); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + int16_t x; + bis >> x; + + EXPECT_EQ (x, 1742); +} + +TEST(BinaryStreams9) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + os << uint32_t (17420000); + + os.flush (); + EXPECT_EQ (s2string (osm), "0xe0,0xce,0x09,0x01"); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + uint32_t x; + bis >> x; + + EXPECT_EQ (x, 17420000u); +} + +TEST(BinaryStreams10) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + os << int32_t (17420000); + + os.flush (); + EXPECT_EQ (s2string (osm), "0xe0,0xce,0x09,0x01"); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + int32_t x; + bis >> x; + + EXPECT_EQ (x, 17420000); +} + +TEST(BinaryStreams11) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + os << uint64_t (174200000000l); + + os.flush (); + EXPECT_EQ (s2string (osm), "0x00,0x0e,0x21,0x8f,0x28,0x00,0x00,0x00"); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + uint64_t x; + bis >> x; + + EXPECT_EQ (x, 174200000000lu); +} + +TEST(BinaryStreams12) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + os << int64_t (174200000000l); + + os.flush (); + EXPECT_EQ (s2string (osm), "0x00,0x0e,0x21,0x8f,0x28,0x00,0x00,0x00"); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + int64_t x; + bis >> x; + + EXPECT_EQ (x, 174200000000l); +} + +TEST(BinaryStreams13) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + os << true; + os << false; + + os.flush (); + EXPECT_EQ (s2string (osm), "0x01,0x00"); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + bool x = false, y = false; + bis >> x >> y; + + EXPECT_EQ (x, true); + EXPECT_EQ (y, false); +} + +TEST(BinaryStreamsCombined) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + os << "ABC" << 17.0 << "XUV" << (int32_t) 42; + + os.flush (); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + std::string a, c; + double b = 0.0; + int32_t d = 0; + + bis >> a >> b >> c >> d; + + EXPECT_EQ (a, "ABC"); + EXPECT_EQ (b, 17.0); + EXPECT_EQ (c, "XUV"); + EXPECT_EQ (d, 42); +} + +TEST(BinaryStreamsVariants) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + std::vector bytes = { 'X', 'U', 'V' }; + + os << tl::Variant ("ABC") + << tl::Variant () + << tl::Variant (bytes) + << tl::Variant ((float) 42.5) + << tl::Variant ((double) -17.5) + << tl::Variant ((char) 'x') + << tl::Variant ((unsigned char) 'u') + << tl::Variant ((signed char) 'v') + << tl::Variant ((short) 17) + << tl::Variant ((unsigned short) 42) + << tl::Variant ((int) 18) + << tl::Variant ((unsigned int) 43) + << tl::Variant ((long) 19) + << tl::Variant ((unsigned long) 44) + << tl::Variant ((long long) 20) + << tl::Variant ((unsigned long long) 45) + << tl::Variant ((size_t) 202, true /*id*/); + + os.flush (); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + tl::Variant v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17; + + bis >> v1 >> v2 >> v3 >> v4 >> v5 >> v6 >> v7 >> v8 >> v9 >> v10 >> v11 >> v12 >> v13 >> v14 >> v15 >> v16 >> v17; + + EXPECT_EQ (v1.to_parsable_string (), "'ABC'"); + EXPECT_EQ (v2.to_parsable_string (), "nil"); + EXPECT_EQ (v3.to_parsable_string (), "'XUV'b"); + EXPECT_EQ (v3.type_code (), tl::Variant::t_bytearray); + EXPECT_EQ (v4.to_parsable_string (), "##42.5"); + EXPECT_EQ (v5.to_parsable_string (), "##-17.5"); + EXPECT_EQ (v6.to_parsable_string (), "'x'c"); + EXPECT_EQ (v7.to_parsable_string (), "#u117"); + EXPECT_EQ (v8.to_parsable_string (), "#118"); + EXPECT_EQ (v9.to_parsable_string (), "#17"); + EXPECT_EQ (v10.to_parsable_string (), "#u42"); + EXPECT_EQ (v11.to_parsable_string (), "#18"); + EXPECT_EQ (v12.to_parsable_string (), "#u43"); + EXPECT_EQ (v13.to_parsable_string (), "#19"); + EXPECT_EQ (v14.to_parsable_string (), "#u44"); + EXPECT_EQ (v15.to_parsable_string (), "#l20"); + EXPECT_EQ (v16.to_parsable_string (), "#lu45"); + EXPECT_EQ (v17.to_parsable_string (), "[id202]"); +} + +TEST(BinaryStreamsVariantList) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + std::vector list = { 5.5, -17, "ABC" }; + + os << tl::Variant (list); + + os.flush (); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + tl::Variant v1; + + bis >> v1; + + EXPECT_EQ (v1.to_parsable_string (), "(##5.5,#-17,'ABC')"); +} + +TEST(BinaryStreamsVariantArray) +{ + tl::OutputMemoryStream osm; + tl::BinaryOutputStream os (osm); + + std::vector > a = { { 1, 5.5 }, { 2, -17 }, { "id", "ABC" } }; + + std::map array (a.begin (), a.end ()); + os << tl::Variant (array); + + os.flush (); + + tl::InputMemoryStream ism (osm.data (), osm.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + + tl::Variant v1; + + bis >> v1; + + EXPECT_EQ (v1.to_parsable_string (), "{#1=>##5.5,#2=>#-17,'id'=>'ABC'}"); +} diff --git a/src/tl/unit_tests/tlStreamTests.cc b/src/tl/unit_tests/tlStreamTests.cc index 881c4b098..71f85030e 100644 --- a/src/tl/unit_tests/tlStreamTests.cc +++ b/src/tl/unit_tests/tlStreamTests.cc @@ -624,304 +624,3 @@ TEST(MatchFormat) EXPECT_EQ (tl::match_filename_to_format ("abc.TEXT", "Text files (*.txt *.TXT)"), false); EXPECT_EQ (tl::match_filename_to_format ("abc.TEXT", "Text files (*)"), true); } - -std::string s2string (tl::OutputMemoryStream &osm) -{ - std::string res; - size_t n = osm.size (); - const char *d = osm.data (); - for (size_t i = 0; i < n; ++i, ++d) { - if (i > 0) { - res += ","; - } - res += tl::sprintf ("0x%02x", int ((unsigned char) *d)); - } - return res; -} - -TEST(BinaryStreams1) -{ - tl::OutputMemoryStream osm; - tl::BinaryOutputStream os (osm); - - os << (double) 0.17; - - os.flush (); - EXPECT_EQ (s2string (osm), "0xc3,0xf5,0x28,0x5c,0x8f,0xc2,0xc5,0x3f"); - - tl::InputMemoryStream ism (osm.data (), osm.size ()); - tl::InputStream is (ism); - tl::BinaryInputStream bis (is); - - double x = 0.0; - bis >> x; - - EXPECT_EQ (tl::to_string (x), "0.17"); -} - -TEST(BinaryStreams2) -{ - tl::OutputMemoryStream osm; - tl::BinaryOutputStream os (osm); - - os << (float) 0.17; - - os.flush (); - EXPECT_EQ (s2string (osm), "0x7b,0x14,0x2e,0x3e"); - - tl::InputMemoryStream ism (osm.data (), osm.size ()); - tl::InputStream is (ism); - tl::BinaryInputStream bis (is); - - float x = 0.0; - bis >> x; - - EXPECT_EQ (tl::to_string (x), "0.17"); -} - -TEST(BinaryStreams3) -{ - tl::OutputMemoryStream osm; - tl::BinaryOutputStream os (osm); - - os << std::string ("ABC"); - - os.flush (); - EXPECT_EQ (s2string (osm), "0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x42,0x43"); - - tl::InputMemoryStream ism (osm.data (), osm.size ()); - tl::InputStream is (ism); - tl::BinaryInputStream bis (is); - - std::string x; - bis >> x; - - EXPECT_EQ (x, "ABC"); -} - -TEST(BinaryStreams4) -{ - tl::OutputMemoryStream osm; - tl::BinaryOutputStream os (osm); - - os << "ABC"; - - os.flush (); - EXPECT_EQ (s2string (osm), "0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x42,0x43"); - - tl::InputMemoryStream ism (osm.data (), osm.size ()); - tl::InputStream is (ism); - tl::BinaryInputStream bis (is); - - std::string x; - bis >> x; - - EXPECT_EQ (x, "ABC"); -} - -TEST(BinaryStreams5) -{ - tl::OutputMemoryStream osm; - tl::BinaryOutputStream os (osm); - - os << uint8_t (17); - - os.flush (); - EXPECT_EQ (s2string (osm), "0x11"); - - tl::InputMemoryStream ism (osm.data (), osm.size ()); - tl::InputStream is (ism); - tl::BinaryInputStream bis (is); - - uint8_t x; - bis >> x; - - EXPECT_EQ (x, 17); -} - -TEST(BinaryStreams6) -{ - tl::OutputMemoryStream osm; - tl::BinaryOutputStream os (osm); - - os << int8_t (17); - - os.flush (); - EXPECT_EQ (s2string (osm), "0x11"); - - tl::InputMemoryStream ism (osm.data (), osm.size ()); - tl::InputStream is (ism); - tl::BinaryInputStream bis (is); - - int8_t x; - bis >> x; - - EXPECT_EQ (x, 17); -} - -TEST(BinaryStreams7) -{ - tl::OutputMemoryStream osm; - tl::BinaryOutputStream os (osm); - - os << uint16_t (1742); - - os.flush (); - EXPECT_EQ (s2string (osm), "0xce,0x06"); - - tl::InputMemoryStream ism (osm.data (), osm.size ()); - tl::InputStream is (ism); - tl::BinaryInputStream bis (is); - - uint16_t x; - bis >> x; - - EXPECT_EQ (x, 1742); -} - -TEST(BinaryStreams8) -{ - tl::OutputMemoryStream osm; - tl::BinaryOutputStream os (osm); - - os << int16_t (1742); - - os.flush (); - EXPECT_EQ (s2string (osm), "0xce,0x06"); - - tl::InputMemoryStream ism (osm.data (), osm.size ()); - tl::InputStream is (ism); - tl::BinaryInputStream bis (is); - - int16_t x; - bis >> x; - - EXPECT_EQ (x, 1742); -} - -TEST(BinaryStreams9) -{ - tl::OutputMemoryStream osm; - tl::BinaryOutputStream os (osm); - - os << uint32_t (17420000); - - os.flush (); - EXPECT_EQ (s2string (osm), "0xe0,0xce,0x09,0x01"); - - tl::InputMemoryStream ism (osm.data (), osm.size ()); - tl::InputStream is (ism); - tl::BinaryInputStream bis (is); - - uint32_t x; - bis >> x; - - EXPECT_EQ (x, 17420000u); -} - -TEST(BinaryStreams10) -{ - tl::OutputMemoryStream osm; - tl::BinaryOutputStream os (osm); - - os << int32_t (17420000); - - os.flush (); - EXPECT_EQ (s2string (osm), "0xe0,0xce,0x09,0x01"); - - tl::InputMemoryStream ism (osm.data (), osm.size ()); - tl::InputStream is (ism); - tl::BinaryInputStream bis (is); - - int32_t x; - bis >> x; - - EXPECT_EQ (x, 17420000); -} - -TEST(BinaryStreams11) -{ - tl::OutputMemoryStream osm; - tl::BinaryOutputStream os (osm); - - os << uint64_t (174200000000l); - - os.flush (); - EXPECT_EQ (s2string (osm), "0x00,0x0e,0x21,0x8f,0x28,0x00,0x00,0x00"); - - tl::InputMemoryStream ism (osm.data (), osm.size ()); - tl::InputStream is (ism); - tl::BinaryInputStream bis (is); - - uint64_t x; - bis >> x; - - EXPECT_EQ (x, 174200000000lu); -} - -TEST(BinaryStreams12) -{ - tl::OutputMemoryStream osm; - tl::BinaryOutputStream os (osm); - - os << int64_t (174200000000l); - - os.flush (); - EXPECT_EQ (s2string (osm), "0x00,0x0e,0x21,0x8f,0x28,0x00,0x00,0x00"); - - tl::InputMemoryStream ism (osm.data (), osm.size ()); - tl::InputStream is (ism); - tl::BinaryInputStream bis (is); - - int64_t x; - bis >> x; - - EXPECT_EQ (x, 174200000000l); -} - -TEST(BinaryStreams13) -{ - tl::OutputMemoryStream osm; - tl::BinaryOutputStream os (osm); - - os << true; - os << false; - - os.flush (); - EXPECT_EQ (s2string (osm), "0x01,0x00"); - - tl::InputMemoryStream ism (osm.data (), osm.size ()); - tl::InputStream is (ism); - tl::BinaryInputStream bis (is); - - bool x = false, y = false; - bis >> x >> y; - - EXPECT_EQ (x, true); - EXPECT_EQ (y, false); -} - -TEST(BinaryStreamsCombined) -{ - tl::OutputMemoryStream osm; - tl::BinaryOutputStream os (osm); - - os << "ABC" << 17.0 << "XUV" << (int32_t) 42; - - os.flush (); - - tl::InputMemoryStream ism (osm.data (), osm.size ()); - tl::InputStream is (ism); - tl::BinaryInputStream bis (is); - - std::string a, c; - double b = 0.0; - int32_t d = 0; - - bis >> a >> b >> c >> d; - - EXPECT_EQ (a, "ABC"); - EXPECT_EQ (b, 17.0); - EXPECT_EQ (c, "XUV"); - EXPECT_EQ (d, 42); -} diff --git a/src/tl/unit_tests/tlVariantTests.cc b/src/tl/unit_tests/tlVariantTests.cc index 28c71258c..15e354c7d 100644 --- a/src/tl/unit_tests/tlVariantTests.cc +++ b/src/tl/unit_tests/tlVariantTests.cc @@ -97,6 +97,7 @@ TEST(1) EXPECT_EQ (v.is_ulong (), false); EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is_double (), false); + EXPECT_EQ (v.to_string (), "nil"); EXPECT_EQ (v.to_parsable_string (), "nil"); vv = v; EXPECT_EQ (vv == v, true); @@ -109,6 +110,43 @@ TEST(1) EXPECT_EQ (vx == v, true); } + { + tl::Variant v ((char) '\033'); +#if defined(HAVE_QT) + EXPECT_EQ (tl::to_string (v.to_qvariant ().toString ()), "27"); +#endif + EXPECT_EQ (v.is_nil (), false); + EXPECT_EQ (v.is_list (), false); + EXPECT_EQ (v.is_cstring (), false); + EXPECT_EQ (v.is_id (), false); + EXPECT_EQ (v.is (), false); + EXPECT_EQ (v.is (), false); + EXPECT_EQ (v.is (), false); + EXPECT_EQ (v.is (), false); + EXPECT_EQ (v.is (), false); + EXPECT_EQ (v.is (), false); + EXPECT_EQ (v.is (), false); + EXPECT_EQ (v.is (), false); + EXPECT_EQ (v.is (), false); + EXPECT_EQ (v.is_char (), true); + EXPECT_EQ (v.is_long (), false); + EXPECT_EQ (v.is_longlong (), false); + EXPECT_EQ (v.is_ulong (), false); + EXPECT_EQ (v.is_ulonglong (), false); + EXPECT_EQ (v.is_double (), false); + EXPECT_EQ (v.to_string (), "\033"); + EXPECT_EQ (v.to_parsable_string (), "'\\033'c"); + vv = v; + EXPECT_EQ (vv == v, true); + EXPECT_EQ (vv != v, false); + tl::Variant vx; + std::string s (v.to_parsable_string ()); + tl::Extractor ex (s.c_str ()); + ex.read (vx); + ex.expect_end (); + EXPECT_EQ (vx == v, true); + } + { tl::Variant v (1ul); #if defined(HAVE_QT) @@ -123,6 +161,7 @@ TEST(1) EXPECT_EQ (v.is_long (), false); EXPECT_EQ (v.is_longlong (), false); EXPECT_EQ (v.is_double (), false); + EXPECT_EQ (v.to_string (), "1"); EXPECT_EQ (v.to_parsable_string (), "#u1"); EXPECT_EQ (v.to_long (), 1l); EXPECT_EQ (v.to_longlong (), 1l); @@ -161,6 +200,7 @@ TEST(1) EXPECT_EQ (v.is_longlong (), false); EXPECT_EQ (v.is_id (), false); EXPECT_EQ (v.is_double (), false); + EXPECT_EQ (v.to_string (), "2"); EXPECT_EQ (v.to_parsable_string (), "#u2"); EXPECT_EQ (v.to_long (), 2l); EXPECT_EQ (v.to_longlong (), 2l); @@ -196,6 +236,7 @@ TEST(1) EXPECT_EQ (v.is (), true); EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is_double (), false); + EXPECT_EQ (v.to_string (), "1"); EXPECT_EQ (v.to_parsable_string (), "#1"); EXPECT_EQ (v.to_long (), 1l); EXPECT_EQ (v.to_longlong (), 1l); @@ -236,6 +277,7 @@ TEST(1) EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is (), false); + EXPECT_EQ (v.to_string (), "2"); EXPECT_EQ (v.to_parsable_string (), "#2"); EXPECT_EQ (v.to_long (), 2l); EXPECT_EQ (v.to_longlong (), 2l); @@ -279,6 +321,7 @@ TEST(1) EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is_id (), false); + EXPECT_EQ (v.to_string (), "5"); EXPECT_EQ (v.to_parsable_string (), "##5"); EXPECT_EQ (v.to_double (), 5.0); EXPECT_EQ (v.to_float (), 5.0); @@ -327,6 +370,7 @@ TEST(1) EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is_id (), false); + EXPECT_EQ (v.to_string (), "5"); EXPECT_EQ (v.to_parsable_string (), "##5"); EXPECT_EQ (v.to_double (), 5.0); EXPECT_EQ (v.to_long (), 5); @@ -386,6 +430,7 @@ TEST(1) EXPECT_EQ (v.is_longlong (), false); EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is_double (), false); + EXPECT_EQ (v.to_string (), "2"); EXPECT_EQ (v.to_parsable_string (), "#2"); vv = v; EXPECT_EQ (vv == v, true); @@ -419,6 +464,8 @@ TEST(1) EXPECT_EQ (v.is_nil (), false); EXPECT_EQ (v.is_list (), false); EXPECT_EQ (v.is_cstring (), false); + EXPECT_EQ (v.is_bytearray (), false); + EXPECT_EQ (v.is_a_bytearray (), false); EXPECT_EQ (v.is_id (), false); EXPECT_EQ (v.is_char (), false); EXPECT_EQ (v.is_long (), false); @@ -432,6 +479,7 @@ TEST(1) EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is (), false); EXPECT_EQ (v.is (), false); + EXPECT_EQ (v.to_string (), "2"); EXPECT_EQ (v.to_parsable_string (), "#u2"); vv = v; EXPECT_EQ (vv == v, true); @@ -454,6 +502,39 @@ TEST(1) EXPECT_EQ (*(long *)v.native_ptr(), 2); } + { + std::vector bytes = { '"', 'h', 0, '\033', 'a', 'l', 'l', 'O', '"' }; + tl::Variant v (std::move (bytes)); +#if defined(HAVE_QT) + EXPECT_EQ (tl::Variant (v.to_qvariant ()).to_parsable_string (), "'\"h\\000\\033allO\"'b"); +#endif + EXPECT_EQ (v.is_nil (), false); + EXPECT_EQ (v.is_list (), false); + EXPECT_EQ (v.is_cstring (), false); + EXPECT_EQ (v.is_bytearray (), true); + EXPECT_EQ (v.is_a_bytearray (), true); + EXPECT_EQ (v.is_long (), false); + EXPECT_EQ (v.is_ulong (), false); + EXPECT_EQ (v.is_longlong (), false); + EXPECT_EQ (v.is_ulonglong (), false); + EXPECT_EQ (v.is_double (), false); + EXPECT_EQ (v.is_id (), false); + EXPECT_EQ (v.to_parsable_string (), "'\"h\\000\\033allO\"'b"); + EXPECT_EQ (v.to_stdstring (), std::string ("\"h\000\033allO\"", 9)); + EXPECT_EQ (vv == v, false); + EXPECT_EQ (vv != v, true); + vv = v; + EXPECT_EQ (vv == v, true); + EXPECT_EQ (vv != v, false); + tl::Variant vx; + std::string s (v.to_parsable_string ()); + tl::Extractor ex (s.c_str ()); + ex.read (vx); + ex.expect_end (); + EXPECT_EQ (vx.is_bytearray (), true); + EXPECT_EQ (vx == v, true); + } + { tl::Variant v ("hal'l\"o"); #if defined(HAVE_QT) @@ -534,6 +615,7 @@ TEST(1) EXPECT_EQ (v.is_id (), false); EXPECT_EQ (v.is_cstring (), false); EXPECT_EQ (v.is_double (), false); + EXPECT_EQ (v.to_string (), "(1,5,25)"); EXPECT_EQ (v.to_parsable_string (), "(#1,#5,#25)"); EXPECT_EQ (v.get_list ().size (), size_t (3)); EXPECT_EQ (v.begin ()->is_long (), true); @@ -571,6 +653,7 @@ TEST(1) EXPECT_EQ (v.is_ulonglong (), false); EXPECT_EQ (v.is_cstring (), false); EXPECT_EQ (v.is_double (), false); + EXPECT_EQ (v.to_string (), "17"); EXPECT_EQ (v.to_parsable_string (), "#l17"); tl::Variant vx; std::string s (v.to_parsable_string ()); @@ -595,6 +678,7 @@ TEST(1) EXPECT_EQ (v.is_longlong (), false); EXPECT_EQ (v.is_cstring (), false); EXPECT_EQ (v.is_double (), false); + EXPECT_EQ (v.to_string (), "17"); EXPECT_EQ (v.to_parsable_string (), "#lu17"); tl::Variant vx; std::string s (v.to_parsable_string ()); @@ -619,6 +703,7 @@ TEST(1) EXPECT_EQ (v.is_longlong (), false); EXPECT_EQ (v.is_cstring (), false); EXPECT_EQ (v.is_double (), false); + EXPECT_EQ (v.to_string (), "[id17]"); EXPECT_EQ (v.to_parsable_string (), "[id17]"); } @@ -642,6 +727,7 @@ TEST(1) v.insert (tl::Variant (1), tl::Variant ("A")); EXPECT_EQ (v.to_parsable_string (), "{#1=>\'A\'}"); v.insert (tl::Variant ("B"), tl::Variant (17)); + EXPECT_EQ (v.to_string (), "{1=>A,B=>17}"); EXPECT_EQ (v.to_parsable_string (), "{#1=>\'A\',\'B\'=>#17}"); #if defined(HAVE_QT) EXPECT_EQ (tl::Variant (v.to_qvariant ()).to_parsable_string (), "{\'1\'=>\'A\',\'B\'=>#17}"); @@ -1138,7 +1224,7 @@ TEST(8) v = tl::Variant (QByteArray ()); EXPECT_EQ (v.to_parsable_string (), "nil"); v = tl::Variant (QByteArray ("abc")); - EXPECT_EQ (v.to_parsable_string (), "'abc'"); + EXPECT_EQ (v.to_parsable_string (), "'abc'b"); v = QByteArray (); EXPECT_EQ (v.to_parsable_string (), "nil"); #endif diff --git a/src/tl/unit_tests/unit_tests.pro b/src/tl/unit_tests/unit_tests.pro index 3d8b06676..5ea1fe9cf 100644 --- a/src/tl/unit_tests/unit_tests.pro +++ b/src/tl/unit_tests/unit_tests.pro @@ -9,6 +9,7 @@ include($$PWD/../../lib_ut.pri) SOURCES = \ tlAlgorithmTests.cc \ tlBase64Tests.cc \ + tlBinaryStreamTests.cc \ tlClassRegistryTests.cc \ tlCommandLineParserTests.cc \ tlColorTests.cc \