From fdaa93d2349c8f801c24eb25eb13dbc261e755df Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 2 May 2026 23:21:35 +0200 Subject: [PATCH 1/6] First implementation of to_bytes/from_bytes for Vector,Point,Box,Polygon,SimplePolygon,Trans,CplxTrans,Text,Path,Edge,EdgePair and variants --- src/db/db/db.pro | 2 + src/db/db/dbBinarySerialize.cc | 31 ++ src/db/db/dbBinarySerialize.h | 573 +++++++++++++++++++++++++++++ src/db/db/dbTrans.h | 11 + src/db/db/gsiDeclDbBox.cc | 26 ++ src/db/db/gsiDeclDbEdge.cc | 26 ++ src/db/db/gsiDeclDbEdgePair.cc | 26 ++ src/db/db/gsiDeclDbPath.cc | 26 ++ src/db/db/gsiDeclDbPoint.cc | 26 ++ src/db/db/gsiDeclDbPolygon.cc | 51 +++ src/db/db/gsiDeclDbText.cc | 26 ++ src/db/db/gsiDeclDbTrans.cc | 51 +++ src/db/db/gsiDeclDbVector.cc | 26 ++ src/laybasic/laybasic/layBitmap.cc | 2 +- src/tl/tl/tlBinaryStream.cc | 0 src/tl/tl/tlBinaryStream.h | 0 src/tl/tl/tlStream.cc | 281 ++++++++++++++ src/tl/tl/tlStream.h | 142 +++++-- src/tl/unit_tests/tlStreamTests.cc | 329 ++++++++++++++++- testdata/ruby/dbBoxTest.rb | 2 + testdata/ruby/dbEdgePairTest.rb | 6 + testdata/ruby/dbEdgeTest.rb | 2 + testdata/ruby/dbPathTest.rb | 6 + testdata/ruby/dbPointTest.rb | 2 + testdata/ruby/dbPolygonTest.rb | 6 + testdata/ruby/dbTextTest.rb | 4 + testdata/ruby/dbTransTest.rb | 9 + testdata/ruby/dbVectorTest.rb | 2 + 28 files changed, 1658 insertions(+), 36 deletions(-) create mode 100644 src/db/db/dbBinarySerialize.cc create mode 100644 src/db/db/dbBinarySerialize.h create mode 100644 src/tl/tl/tlBinaryStream.cc create mode 100644 src/tl/tl/tlBinaryStream.h diff --git a/src/db/db/db.pro b/src/db/db/db.pro index bcae249bfb..d316c1c603 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -8,6 +8,7 @@ DEFINES += MAKE_DB_LIBRARY SOURCES = \ dbArray.cc \ + dbBinarySerialize.cc \ dbBox.cc \ dbBoxConvert.cc \ dbBoxScanner.cc \ @@ -248,6 +249,7 @@ SOURCES = \ HEADERS = \ dbArray.h \ + dbBinarySerialize.h \ dbBoxConvert.h \ dbBox.h \ dbBoxScanner.h \ diff --git a/src/db/db/dbBinarySerialize.cc b/src/db/db/dbBinarySerialize.cc new file mode 100644 index 0000000000..ea92b8ac4e --- /dev/null +++ b/src/db/db/dbBinarySerialize.cc @@ -0,0 +1,31 @@ + +/* + + 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 "dbBinarySerialize.h" + +namespace db +{ + + // .. nothing yet .. + +} diff --git a/src/db/db/dbBinarySerialize.h b/src/db/db/dbBinarySerialize.h new file mode 100644 index 0000000000..93c55505cb --- /dev/null +++ b/src/db/db/dbBinarySerialize.h @@ -0,0 +1,573 @@ + +/* + + 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_dbBinarySerialize +#define HDR_dbBinarySerialize + +#include "dbCommon.h" + +#include "dbPoint.h" +#include "dbVector.h" +#include "dbEdge.h" +#include "dbEdgePair.h" +#include "dbPolygon.h" +#include "dbBox.h" +#include "dbPath.h" +#include "dbTrans.h" +#include "dbText.h" + +#include "tlStream.h" +#include "tlException.h" + +namespace db +{ + +// ----------------------------------------------------------------------------------------- +// Stream inserters + +template +tl::OutputStream &write_coord (tl::OutputStream &s, C c) +{ + return s << c; +} + +inline tl::OutputStream &write_coord (tl::OutputStream &s, db::Coord c) +{ + // NOTE: for compatibility across different builds we use 64 bit coordinates always + return s << (int64_t) c; +} + +template +tl::OutputStream &write_binary (tl::OutputStream &s, const db::point &pt) +{ + return write_coord (write_coord (s, pt.x ()), pt.y ()); +} + +template +tl::OutputStream &write_binary (tl::OutputStream &s, const db::vector &v) +{ + return write_coord (write_coord (s, v.x ()), v.y ()); +} + +template +tl::OutputStream &operator<< (tl::OutputStream &s, const db::point &pt) +{ + s << (uint16_t) 1; // version + return write_binary (s, pt); +} + +template +tl::OutputStream &operator<< (tl::OutputStream &s, const db::vector &v) +{ + s << (uint16_t) 1; // version + return write_binary (s, v); +} + +template +tl::OutputStream &write_binary (tl::OutputStream &s, const db::edge &e) +{ + write_binary (s, e.p1 ()); + write_binary (s, e.p2 ()); + return s; +} + +template +tl::OutputStream &operator<< (tl::OutputStream &s, const db::edge &e) +{ + s << (uint16_t) 1; // version + return write_binary (s, e); +} + +template +tl::OutputStream &operator<< (tl::OutputStream &s, const db::box &b) +{ + s << (uint16_t) 1; // version + write_binary (s, b.p1 ()); + write_binary (s, b.p2 ()); + return s; +} + +template +tl::OutputStream &operator<< (tl::OutputStream &s, const db::edge_pair &ep) +{ + s << (uint16_t) 1; // version + write_binary (s, ep.first ()); + write_binary (s, ep.second ()); + return s; +} + +template +tl::OutputStream &write_binary (tl::OutputStream &s, const db::polygon_contour &c) +{ + s << (uint64_t) c.size (); + for (auto i = c.begin (); i != c.end (); ++i) { + s << *i; + } + return s; +} + +template +tl::OutputStream &operator<< (tl::OutputStream &s, const db::polygon &p) +{ + s << (uint16_t) 1; // version + s << (uint64_t) (p.holes () + 1); + for (size_t h = 0; h < p.holes () + 1; ++h) { + write_binary (s, p.contour (h)); + } + return s; +} + +template +tl::OutputStream &operator<< (tl::OutputStream &s, const db::simple_polygon &p) +{ + // NOTE: the format of polygon and simple polygon are compatible + s << (uint16_t) 1; // version + s << (uint64_t) 1; // number of contours + write_binary (s, p.hull ()); + return s; +} + +template +tl::OutputStream &operator<< (tl::OutputStream &s, const db::unit_trans &) +{ + s << (uint16_t) 1; // version + return s; +} + +template +tl::OutputStream &operator<< (tl::OutputStream &s, const db::disp_trans &t) +{ + s << (uint16_t) 1; // version + write_binary (s, t.disp ()); + return s; +} + +template +tl::OutputStream &write_binary (tl::OutputStream &s, const db::simple_trans &t) +{ + s << (uint16_t) t.rot (); + write_binary (s, t.disp ()); + return s; +} + +template +tl::OutputStream &operator<< (tl::OutputStream &s, const db::simple_trans &t) +{ + s << (uint16_t) 1; // version + return write_binary (s, t); +} + +template +tl::OutputStream &operator<< (tl::OutputStream &s, const db::complex_trans &t) +{ + s << (uint16_t) 1; // version + write_binary (s, t.disp ()); + return s << (double) t.msin () << (double) t.mcos () << (double) t.mag (); +} + +template +tl::OutputStream &operator<< (tl::OutputStream &s, const db::text &t) +{ + s << (uint16_t) 1; // version + s << t.string (); + write_binary (s, t.trans ()); + write_coord (s, t.size ()); + return s << (int32_t) t.font () << (int32_t) t.halign () << (int32_t) t.valign (); +} + +template +tl::OutputStream &operator<< (tl::OutputStream &s, const db::path &p) +{ + s << (uint16_t) 1; // version + s << (uint64_t) p.points (); + for (auto i = p.begin (); i != p.end (); ++i) { + write_binary (s, *i); + } + write_coord (s, p.width ()); + write_coord (s, p.bgn_ext ()); + write_coord (s, p.end_ext ()); + write_coord (s, p.round ()); + return s; +} + +// ----------------------------------------------------------------------------------------- +// Stream extractors + +class FutureBinarySerializationFormatException + : public tl::Exception +{ +public: + FutureBinarySerializationFormatException () + : tl::Exception (tl::to_string (tr ("Binary serialization format version is too new for this build"))) + { } +}; + +template +tl::BinaryInputStream &read_coord (tl::BinaryInputStream &s, C &c) +{ + return s >> c; +} + +inline tl::BinaryInputStream &read_coord (tl::BinaryInputStream &s, db::Coord &c) +{ + // NOTE: for compatibility across different builds we use 64 bit coordinates always + int64_t cc = 0; + s >> cc; + c = cc; + return s; +} + +template +tl::BinaryInputStream &read_binary (tl::BinaryInputStream &s, db::point &pt) +{ + C x = 0, y = 0; + read_coord (s, x); + read_coord (s, y); + pt = db::point (x, y); + return s; +} + +template +tl::BinaryInputStream &read_binary (tl::BinaryInputStream &s, db::vector &v) +{ + C x = 0, y = 0; + read_coord (s, x); + read_coord (s, y); + v = db::vector (x, y); + return s; +} + +template +tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::point &pt) +{ + uint16_t fmt = 0; + s >> fmt; + if (fmt > 1) { + throw FutureBinarySerializationFormatException (); + } + return read_binary (s, pt); +} + +template +tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::vector &v) +{ + uint16_t fmt = 0; + s >> fmt; + if (fmt > 1) { + throw FutureBinarySerializationFormatException (); + } + return read_binary (s, v); +} + +template +tl::BinaryInputStream &read_binary (tl::BinaryInputStream &s, db::edge &v) +{ + db::point p1, p2; + read_binary (s, p1); + read_binary (s, p2); + v = db::edge (p1, p2); + return s; +} + +template +tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::edge &e) +{ + uint16_t fmt = 0; + s >> fmt; + if (fmt > 1) { + throw FutureBinarySerializationFormatException (); + } + return read_binary (s, e); +} + +template +tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::box &b) +{ + uint16_t fmt = 0; + s >> fmt; + if (fmt > 1) { + throw FutureBinarySerializationFormatException (); + } + + db::point p1, p2; + read_binary (s, p1); + read_binary (s, p2); + b = db::box (p1, p2); + return s; +} + +template +tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::edge_pair &ep) +{ + uint16_t fmt = 0; + s >> fmt; + if (fmt > 1) { + throw FutureBinarySerializationFormatException (); + } + + db::edge e1, e2; + read_binary (s, e1); + read_binary (s, e2); + ep = db::edge_pair (e1, e2); + return s; +} + +template +tl::BinaryInputStream &read_binary (tl::BinaryInputStream &s, db::polygon_contour &c) +{ + uint64_t n = 0; + s >> n; + + std::vector > pts; + pts.reserve (n); + while (n-- > 0) { + pts.push_back (db::point ()); + read_binary (s, pts.back ()); + } + + // NOTE: not normalization or modification is applied + c.assign (pts.begin (), pts.end (), false, false, false); + + return s; +} + +template +tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::polygon &p) +{ + uint16_t fmt = 0; + s >> fmt; + if (fmt > 1) { + throw FutureBinarySerializationFormatException (); + } + + uint64_t n = 0; + s >> n; + + p = db::polygon (); + + db::polygon_contour ctr; + for (uint64_t h = 0; h < n; ++h) { + read_binary (s, ctr); + if (h == 0) { + p.assign_hull (ctr); + } else { + p.insert_hole (ctr); + } + } + + return s; +} + +template +tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::simple_polygon &p) +{ + uint16_t fmt = 0; + s >> fmt; + if (fmt > 1) { + throw FutureBinarySerializationFormatException (); + } + + uint64_t n = 0; + s >> n; + tl_assert (n == (uint64_t) 1); + + db::polygon_contour ctr; + read_binary (s, ctr); + p.assign_hull (ctr); + + return s; +} + +template +tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::unit_trans &) +{ + uint16_t fmt = 0; + s >> fmt; + if (fmt > 1) { + throw FutureBinarySerializationFormatException (); + } + + return s; +} + +template +tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::disp_trans &t) +{ + uint16_t fmt = 0; + s >> fmt; + if (fmt > 1) { + throw FutureBinarySerializationFormatException (); + } + + db::vector d; + read_binary (s, d); + t = db::disp_trans (d); + + return s; +} + +template +tl::BinaryInputStream &read_binary (tl::BinaryInputStream &s, db::simple_trans &t) +{ + uint16_t r = 0; + s >> r; + + db::vector d; + read_binary (s, d); + + t = db::simple_trans (r, d); + return s; +} + +template +tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::simple_trans &t) +{ + uint16_t fmt = 0; + s >> fmt; + if (fmt > 1) { + throw FutureBinarySerializationFormatException (); + } + + return read_binary (s, t); +} + +template +tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::complex_trans &t) +{ + uint16_t fmt = 0; + s >> fmt; + if (fmt > 1) { + throw FutureBinarySerializationFormatException (); + } + + db::vector d; + read_binary (s, d); + + double asin, acos, mag; + s >> asin >> acos >> mag; + + t = db::complex_trans (d, asin, acos, mag); + + return s; +} + +template +tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::text &t) +{ + uint16_t fmt = 0; + s >> fmt; + if (fmt > 1) { + throw FutureBinarySerializationFormatException (); + } + + std::string txt; + s >> txt; + + db::simple_trans tr; + read_binary (s, tr); + + C size; + read_coord (s, size); + + int32_t font, halign, valign; + s >> font >> halign >> valign; + + t = db::text (txt, tr, size, db::Font (font), db::HAlign (halign), db::VAlign (valign)); + return s; +} + +template +tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::path &p) +{ + uint16_t fmt = 0; + s >> fmt; + if (fmt > 1) { + throw FutureBinarySerializationFormatException (); + } + + uint64_t n = 0; + s >> n; + + std::vector > pts; + pts.reserve (n); + while (n-- > 0) { + pts.push_back (db::point ()); + read_binary (s, pts.back ()); + } + + C width, bgn_ext, end_ext; + s >> width >> bgn_ext >> end_ext; + + bool round; + s >> round; + + p = db::path (pts.begin (), pts.end (), width, bgn_ext, end_ext, round); + return s; +} + +// ----------------------------------------------------------------------------------------- +// Converters of objects to a binary string + +template +std::vector to_bytes (const T &t) +{ + tl::OutputMemoryStream osm; + { + tl::OutputStream os (osm, false /*binary*/); + os << t; + } + return std::vector (osm.data (), osm.data () + osm.size ()); +} + +template +std::string to_bytes_str (const T &t) +{ + tl::OutputMemoryStream osm; + { + tl::OutputStream os (osm, false /*binary*/); + os << t; + } + return std::string (osm.data (), osm.size ()); +} + +template +void from_bytes (const char *data, size_t n, T &t) +{ + tl::InputMemoryStream ism (data, n); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + bis >> t; +} + +template +void from_bytes (const std::vector &s, T &t) +{ + tl::InputMemoryStream ism (s.begin ().operator-> (), s.size ()); + tl::InputStream is (ism); + tl::BinaryInputStream bis (is); + bis >> t; +} + +} + +#endif diff --git a/src/db/db/dbTrans.h b/src/db/db/dbTrans.h index 9c93a54bce..cf50a7cb4e 100644 --- a/src/db/db/dbTrans.h +++ b/src/db/db/dbTrans.h @@ -1625,6 +1625,17 @@ class DB_PUBLIC_TEMPLATE complex_trans m_mag = s.is_mirror () ? -1.0 : 1.0; } + /** + * @brief Native constructor + * + * This constructor creates the objects from the native parameters (max, acos, asin and displacement) + */ + complex_trans (const vector &disp, R asin, R acos, R mag) + : m_u (disp), m_sin (asin), m_cos (acos), m_mag (mag) + { + // .. nothing yet .. + } + /** * @brief Migration constructor from a simple transformation to a complex transformation * diff --git a/src/db/db/gsiDeclDbBox.cc b/src/db/db/gsiDeclDbBox.cc index 80e3bdfbb6..f5572fa161 100644 --- a/src/db/db/gsiDeclDbBox.cc +++ b/src/db/db/gsiDeclDbBox.cc @@ -26,6 +26,7 @@ #include "dbPoint.h" #include "dbBox.h" #include "dbHash.h" +#include "dbBinarySerialize.h" namespace gsi { @@ -50,6 +51,18 @@ struct box_defs return c.release (); } + static C *from_bytes (const std::vector &s) + { + std::unique_ptr c (new C ()); + db::from_bytes (s, *c); + return c.release (); + } + + static std::vector to_bytes (const C *c) + { + return db::to_bytes (*c); + } + static C world () { return C::world (); @@ -533,6 +546,19 @@ struct box_defs "If a DBU is given, the output units will be micrometers.\n" "\n" "The DBU argument has been added in version 0.27.6.\n" + ) + + constructor ("from_bytes", &from_bytes, gsi::arg ("s"), + "@brief Creates a box object from a binary serialization\n" + "Creates the object from a binary representation (as returned by \\to_bytes)\n" + "\n" + "This method has been added in version 0.30.9.\n" + ) + + method_ext ("to_bytes", &to_bytes, + "@brief Returns a binary string representing this box\n" + "\n" + "This string can be turned into a box again by using \\from_bytes\n. " + "\n" + "This method has been added in version 0.30.9.\n" ); } }; diff --git a/src/db/db/gsiDeclDbEdge.cc b/src/db/db/gsiDeclDbEdge.cc index c7b348f69c..5b25f4073f 100644 --- a/src/db/db/gsiDeclDbEdge.cc +++ b/src/db/db/gsiDeclDbEdge.cc @@ -26,6 +26,7 @@ #include "dbPoint.h" #include "dbEdge.h" #include "dbHash.h" +#include "dbBinarySerialize.h" namespace gsi { @@ -53,6 +54,18 @@ struct edge_defs return c.release (); } + static C *from_bytes (const std::vector &s) + { + std::unique_ptr c (new C ()); + db::from_bytes (s, *c); + return c.release (); + } + + static std::vector to_bytes (const C *c) + { + return db::to_bytes (*c); + } + static C *new_v () { return new C (); @@ -446,6 +459,19 @@ struct edge_defs "\n" "The DBU argument has been added in version 0.27.6.\n" ) + + constructor ("from_bytes", &from_bytes, gsi::arg ("s"), + "@brief Creates an edge object from a binary serialization\n" + "Creates the object from a binary representation (as returned by \\to_bytes)\n" + "\n" + "This method has been added in version 0.30.9.\n" + ) + + method_ext ("to_bytes", &to_bytes, + "@brief Returns a binary string representing this edge\n" + "\n" + "This string can be turned into an edge again by using \\from_bytes\n. " + "\n" + "This method has been added in version 0.30.9.\n" + ); method ("is_parallel?", &C::parallel, gsi::arg ("e"), "@brief Test for being parallel\n" "\n" diff --git a/src/db/db/gsiDeclDbEdgePair.cc b/src/db/db/gsiDeclDbEdgePair.cc index 2d9e7a86ca..c1953db26f 100644 --- a/src/db/db/gsiDeclDbEdgePair.cc +++ b/src/db/db/gsiDeclDbEdgePair.cc @@ -26,6 +26,7 @@ #include "dbEdgePair.h" #include "dbHash.h" +#include "dbBinarySerialize.h" namespace gsi { @@ -50,6 +51,18 @@ struct edge_pair_defs return c.release (); } + static C *from_bytes (const std::vector &s) + { + std::unique_ptr c (new C ()); + db::from_bytes (s, *c); + return c.release (); + } + + static std::vector to_bytes (const C *c) + { + return db::to_bytes (*c); + } + static C *new_v () { return new C (); @@ -167,6 +180,19 @@ struct edge_pair_defs "\n" "The DBU argument has been added in version 0.27.6.\n" ) + + constructor ("from_bytes", &from_bytes, gsi::arg ("s"), + "@brief Creates an edge pair object from a binary serialization\n" + "Creates the object from a binary representation (as returned by \\to_bytes)\n" + "\n" + "This method has been added in version 0.30.9.\n" + ) + + method_ext ("to_bytes", &to_bytes, + "@brief Returns a binary string representing this edge pair\n" + "\n" + "This string can be turned into an edge pair again by using \\from_bytes\n. " + "\n" + "This method has been added in version 0.30.9.\n" + ); method ("bbox", &C::bbox, "@brief Gets the bounding box of the edge pair\n" ) + diff --git a/src/db/db/gsiDeclDbPath.cc b/src/db/db/gsiDeclDbPath.cc index b2b6dae33b..8cef53f973 100644 --- a/src/db/db/gsiDeclDbPath.cc +++ b/src/db/db/gsiDeclDbPath.cc @@ -26,6 +26,7 @@ #include "dbPoint.h" #include "dbPath.h" #include "dbHash.h" +#include "dbBinarySerialize.h" namespace gsi { @@ -59,6 +60,18 @@ struct path_defs return c.release (); } + static C *from_bytes (const std::vector &s) + { + std::unique_ptr c (new C ()); + db::from_bytes (s, *c); + return c.release (); + } + + static std::vector to_bytes (const C *c) + { + return db::to_bytes (*c); + } + static C *new_v () { return new C (); @@ -284,6 +297,19 @@ struct path_defs method ("to_s", (std::string (C::*) () const) &C::to_string, "@brief Convert to a string\n" ) + + constructor ("from_bytes", &from_bytes, gsi::arg ("s"), + "@brief Creates a path object from a binary serialization\n" + "Creates the object from a binary representation (as returned by \\to_bytes)\n" + "\n" + "This method has been added in version 0.30.9.\n" + ) + + method_ext ("to_bytes", &to_bytes, + "@brief Returns a binary string representing this path\n" + "\n" + "This string can be turned into a path again by using \\from_bytes\n. " + "\n" + "This method has been added in version 0.30.9.\n" + ); method ("simple_polygon", &C::simple_polygon, "@brief Convert the path to a simple polygon\n" "The returned polygon is not guaranteed to be non-selfoverlapping. This may happen if the path overlaps " diff --git a/src/db/db/gsiDeclDbPoint.cc b/src/db/db/gsiDeclDbPoint.cc index 80b65c4b1e..de391726c1 100644 --- a/src/db/db/gsiDeclDbPoint.cc +++ b/src/db/db/gsiDeclDbPoint.cc @@ -25,6 +25,7 @@ #include "dbPoint.h" #include "dbBox.h" #include "dbHash.h" +#include "dbBinarySerialize.h" namespace gsi { @@ -46,6 +47,18 @@ struct point_defs return c.release (); } + static C *from_bytes (const std::vector &s) + { + std::unique_ptr c (new C ()); + db::from_bytes (s, *c); + return c.release (); + } + + static std::vector to_bytes (const C *c) + { + return db::to_bytes (*c); + } + static C *new_v () { return new C (); @@ -320,6 +333,19 @@ struct point_defs "If a DBU is given, the output units will be micrometers.\n" "\n" "The DBU argument has been added in version 0.27.6.\n" + ) + + constructor ("from_bytes", &from_bytes, gsi::arg ("s"), + "@brief Creates a point object from a binary serialization\n" + "Creates the object from a binary representation (as returned by \\to_bytes)\n" + "\n" + "This method has been added in version 0.30.9.\n" + ) + + method_ext ("to_bytes", &to_bytes, + "@brief Returns a binary string representing this point\n" + "\n" + "This string can be turned into a point again by using \\from_bytes\n. " + "\n" + "This method has been added in version 0.30.9.\n" ); } diff --git a/src/db/db/gsiDeclDbPolygon.cc b/src/db/db/gsiDeclDbPolygon.cc index 41b6b205a7..be2023eb46 100644 --- a/src/db/db/gsiDeclDbPolygon.cc +++ b/src/db/db/gsiDeclDbPolygon.cc @@ -30,6 +30,7 @@ #include "dbHash.h" #include "dbPLCTriangulation.h" #include "dbPLCConvexDecomposition.h" +#include "dbBinarySerialize.h" namespace gsi { @@ -307,6 +308,18 @@ struct simple_polygon_defs return c.release (); } + static C *from_bytes (const std::vector &s) + { + std::unique_ptr c (new C ()); + db::from_bytes (s, *c); + return c.release (); + } + + static std::vector to_bytes (const C *c) + { + return db::to_bytes (*c); + } + static C *new_v () { return new C; @@ -702,6 +715,19 @@ struct simple_polygon_defs method ("to_s", (std::string (C::*) () const) &C::to_string, "@brief Returns a string representing the polygon\n" ) + + constructor ("from_bytes", &from_bytes, gsi::arg ("s"), + "@brief Creates a polygon object from a binary serialization\n" + "Creates the object from a binary representation (as returned by \\to_bytes)\n" + "\n" + "This method has been added in version 0.30.9.\n" + ) + + method_ext ("to_bytes", &to_bytes, + "@brief Returns a binary string representing this polygon\n" + "\n" + "This string can be turned into a polygon again by using \\from_bytes\n. " + "\n" + "This method has been added in version 0.30.9.\n" + ); method_ext ("round_corners", &round_corners, gsi::arg ("rinner"), gsi::arg ("router"), gsi::arg ("n"), "@brief Rounds the corners of the polygon\n" "\n" @@ -1298,6 +1324,18 @@ struct polygon_defs return c.release (); } + static C *from_bytes (const std::vector &s) + { + std::unique_ptr c (new C ()); + db::from_bytes (s, *c); + return c.release (); + } + + static std::vector to_bytes (const C *c) + { + return db::to_bytes (*c); + } + static C *new_v () { return new C; @@ -1854,6 +1892,19 @@ struct polygon_defs method ("to_s", (std::string (C::*) () const) &C::to_string, "@brief Returns a string representing the polygon\n" ) + + constructor ("from_bytes", &from_bytes, gsi::arg ("s"), + "@brief Creates a polygon object from a binary serialization\n" + "Creates the object from a binary representation (as returned by \\to_bytes)\n" + "\n" + "This method has been added in version 0.30.9.\n" + ) + + method_ext ("to_bytes", &to_bytes, + "@brief Returns a binary string representing this polygon\n" + "\n" + "This string can be turned into a polygon again by using \\from_bytes\n. " + "\n" + "This method has been added in version 0.30.9.\n" + ); method_ext ("round_corners", &round_corners, gsi::arg ("rinner"), gsi::arg ("router"), gsi::arg ("n"), "@brief Rounds the corners of the polygon\n" "\n" diff --git a/src/db/db/gsiDeclDbText.cc b/src/db/db/gsiDeclDbText.cc index 118e7474c9..7f88d763ec 100644 --- a/src/db/db/gsiDeclDbText.cc +++ b/src/db/db/gsiDeclDbText.cc @@ -27,6 +27,7 @@ #include "dbPoint.h" #include "dbText.h" #include "dbHash.h" +#include "dbBinarySerialize.h" namespace gsi { @@ -52,6 +53,18 @@ struct text_defs return c.release (); } + static C *from_bytes (const std::vector &s) + { + std::unique_ptr c (new C ()); + db::from_bytes (s, *c); + return c.release (); + } + + static std::vector to_bytes (const C *c) + { + return db::to_bytes (*c); + } + static C *new_v () { return new C (); @@ -397,6 +410,19 @@ struct text_defs "If a DBU is given, the output units will be micrometers.\n" "\n" "The DBU argument has been added in version 0.27.6.\n" + ) + + constructor ("from_bytes", &from_bytes, gsi::arg ("s"), + "@brief Creates a text object from a binary serialization\n" + "Creates the object from a binary representation (as returned by \\to_bytes)\n" + "\n" + "This method has been added in version 0.30.9.\n" + ) + + method_ext ("to_bytes", &to_bytes, + "@brief Returns a binary string representing this text object\n" + "\n" + "This string can be turned into a text object again by using \\from_bytes\n. " + "\n" + "This method has been added in version 0.30.9.\n" ); } }; diff --git a/src/db/db/gsiDeclDbTrans.cc b/src/db/db/gsiDeclDbTrans.cc index 917fa60fe7..213fdd5124 100644 --- a/src/db/db/gsiDeclDbTrans.cc +++ b/src/db/db/gsiDeclDbTrans.cc @@ -29,6 +29,7 @@ #include "dbPath.h" #include "dbText.h" #include "dbHash.h" +#include "dbBinarySerialize.h" namespace gsi { @@ -98,6 +99,18 @@ struct trans_defs return c.release (); } + static C *from_bytes (const std::vector &s) + { + std::unique_ptr c (new C ()); + db::from_bytes (s, *c); + return c.release (); + } + + static std::vector to_bytes (const C *c) + { + return db::to_bytes (*c); + } + static C *new_v () { return new C (); @@ -518,6 +531,19 @@ struct trans_defs "\n" "The DBU argument has been added in version 0.27.6.\n" ) + + constructor ("from_bytes", &from_bytes, gsi::arg ("s"), + "@brief Creates an object from a binary serialization\n" + "Creates the object from a binary representation (as returned by \\to_bytes)\n" + "\n" + "This method has been added in version 0.30.9.\n" + ) + + method_ext ("to_bytes", &to_bytes, + "@brief Returns a binary string representing this object\n" + "\n" + "This string can be turned into an object again by using \\from_bytes\n. " + "\n" + "This method has been added in version 0.30.9.\n" + ); method ("disp", (const vector_type &(C::*) () const) &C::disp, "@brief Gets to the displacement vector\n" "\n" @@ -736,6 +762,18 @@ struct cplx_trans_defs return c.release (); } + static C *from_bytes (const std::vector &s) + { + std::unique_ptr c (new C ()); + db::from_bytes (s, *c); + return c.release (); + } + + static std::vector to_bytes (const C *c) + { + return db::to_bytes (*c); + } + static C *new_v () { return new C (); @@ -1139,6 +1177,19 @@ struct cplx_trans_defs "\n" "The lazy and DBU arguments have been added in version 0.27.6.\n" ) + + constructor ("from_bytes", &from_bytes, gsi::arg ("s"), + "@brief Creates an object from a binary serialization\n" + "Creates the object from a binary representation (as returned by \\to_bytes)\n" + "\n" + "This method has been added in version 0.30.9.\n" + ) + + method_ext ("to_bytes", &to_bytes, + "@brief Returns a binary string representing this object\n" + "\n" + "This string can be turned into an object again by using \\from_bytes\n. " + "\n" + "This method has been added in version 0.30.9.\n" + ); method ("disp", (displacement_type (C::*)() const) &C::disp, "@brief Gets the displacement\n" ) + diff --git a/src/db/db/gsiDeclDbVector.cc b/src/db/db/gsiDeclDbVector.cc index 6946f5ac8b..25b22fd4dc 100644 --- a/src/db/db/gsiDeclDbVector.cc +++ b/src/db/db/gsiDeclDbVector.cc @@ -25,6 +25,7 @@ #include "dbVector.h" #include "dbPoint.h" #include "dbHash.h" +#include "dbBinarySerialize.h" namespace gsi { @@ -45,6 +46,18 @@ struct vector_defs return c.release (); } + static C *from_bytes (const std::vector &s) + { + std::unique_ptr c (new C ()); + db::from_bytes (s, *c); + return c.release (); + } + + static std::vector to_bytes (const C *c) + { + return db::to_bytes (*c); + } + static C *new_v () { return new C (); @@ -275,6 +288,19 @@ struct vector_defs "If a DBU is given, the output units will be micrometers.\n" "\n" "The DBU argument has been added in version 0.27.6.\n" + ) + + constructor ("from_bytes", &from_bytes, gsi::arg ("s"), + "@brief Creates a vector object from a binary serialization\n" + "Creates the object from a binary representation (as returned by \\to_bytes)\n" + "\n" + "This method has been added in version 0.30.9.\n" + ) + + method_ext ("to_bytes", &to_bytes, + "@brief Returns a binary string representing this vector\n" + "\n" + "This string can be turned into a vector again by using \\from_bytes\n. " + "\n" + "This method has been added in version 0.30.9.\n" ); } diff --git a/src/laybasic/laybasic/layBitmap.cc b/src/laybasic/laybasic/layBitmap.cc index c17ffda7e7..d919bd0b2e 100644 --- a/src/laybasic/laybasic/layBitmap.cc +++ b/src/laybasic/laybasic/layBitmap.cc @@ -298,7 +298,7 @@ Bitmap::fill_pattern (int y, int x, const uint32_t *pp, unsigned int stride, uns uint32_t p = *pp; int x1 = x + s * 32; - if (x1 <= -32 || x1 >= m_width) { + if (x1 <= -32 || x1 >= (int)m_width) { continue; } else if (x1 < 0) { p >>= (unsigned int)-x1; diff --git a/src/tl/tl/tlBinaryStream.cc b/src/tl/tl/tlBinaryStream.cc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/tl/tl/tlBinaryStream.h b/src/tl/tl/tlBinaryStream.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/tl/tl/tlStream.cc b/src/tl/tl/tlStream.cc index 4e52db055f..214e5914a4 100644 --- a/src/tl/tl/tlStream.cc +++ b/src/tl/tl/tlStream.cc @@ -133,6 +133,15 @@ class FilePWriteErrorException { } }; +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 @@ -920,6 +929,183 @@ 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 @@ -1282,6 +1468,101 @@ OutputStream::put_raw (const char *b, size_t n) } } +void +OutputStream::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 +OutputStream::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 +OutputStream::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 +OutputStream::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 +OutputStream::put_native (bool v) +{ + char c = v ? 1 : 0; + put_raw (&c, 1); +} + +void +OutputStream::put_native (uint8_t v) +{ + put_raw ((const char *) &v, 1); +} + +void +OutputStream::put_native (int8_t v) +{ + put_raw ((const char *) &v, 1); +} + +void +OutputStream::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 +OutputStream::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 +OutputStream::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 +OutputStream::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 +OutputStream::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 +OutputStream::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 OutputStream::seek (size_t pos) { diff --git a/src/tl/tl/tlStream.h b/src/tl/tl/tlStream.h index 70fac833c1..05285de142 100644 --- a/src/tl/tl/tlStream.h +++ b/src/tl/tl/tlStream.h @@ -730,7 +730,7 @@ class TL_PUBLIC TextInputStream } /** - * @brief Get a single line (presumably UTF8 encoded) + * @brief Gets a single line (presumably UTF8 encoded) */ const std::string &get_line (); @@ -747,7 +747,7 @@ class TL_PUBLIC TextInputStream std::string read_all (size_t max_count); /** - * @brief Get a single character + * @brief Gets a single character */ char get_char (); @@ -757,14 +757,14 @@ class TL_PUBLIC TextInputStream char peek_char (); /** - * @brief Skip blanks, newlines etc. + * @brief Skips blanks, newlines etc. * * Returns the following character without getting it. */ char skip (); /** - * @brief Get the source specification + * @brief Gets the source specification */ std::string source () const { @@ -772,7 +772,7 @@ class TL_PUBLIC TextInputStream } /** - * @brief Get the current line number + * @brief Gets the current line number */ size_t line_number () { @@ -780,7 +780,7 @@ class TL_PUBLIC TextInputStream } /** - * @brief Return false, if no more characters can be obtained + * @brief Returns false, if no more characters can be obtained */ bool at_end () const { @@ -788,7 +788,7 @@ class TL_PUBLIC TextInputStream } /** - * @brief Reset to the initial position + * @brief Resets to the initial position */ void reset (); @@ -805,6 +805,69 @@ class TL_PUBLIC TextInputStream // --------------------------------------------------------------------------------- +/** + * @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 * @@ -880,9 +943,9 @@ class TL_PUBLIC OutputMemoryStream /** * @brief Create a string writer */ - OutputMemoryStream () + OutputMemoryStream (size_t initial_alloc = 65536) { - m_buffer.reserve (65336); + m_buffer.reserve (initial_alloc); } /** @@ -1312,13 +1375,20 @@ class TL_PUBLIC OutputStream void close (); /** - * @brief This is the outer write method to call + * @brief Puts a string into the stream * - * This implementation writes data through the - * protected write call. + * In text mode, this handles line separator conversion. + * In binary mode, this method is equivalent to "put_raw". */ void put (const char *b, size_t n); + /** + * @brief Puts the raw bytes into the stream + * + * This method bypasses the line feed translation. + */ + void put_raw (const char *b, size_t n); + /** * @brief Puts a C string (UTF-8) to the output */ @@ -1336,7 +1406,7 @@ class TL_PUBLIC OutputStream } /** - * @brief << operator + * @brief << operator: inserts character */ OutputStream &operator<< (char s) { @@ -1345,7 +1415,7 @@ class TL_PUBLIC OutputStream } /** - * @brief << operator + * @brief << operator: inserts a character */ OutputStream &operator<< (unsigned char s) { @@ -1354,30 +1424,48 @@ class TL_PUBLIC OutputStream } /** - * @brief << operator + * @brief << operator: inserts a string + * + * In binary mode, the string is inserted as a length/data + * combination. That matches the extraction in BinaryInputStream. */ OutputStream &operator<< (const char *s) { - put (s); + if (m_as_text) { + put (s, strlen (s)); + } else { + put_native (s, strlen (s)); + } return *this; } /** - * @brief << operator + * @brief << operator: inserts a string + * + * In binary mode, the string is inserted as a length/data + * combination. That matches the extraction in BinaryInputStream. */ OutputStream &operator<< (const std::string &s) { - put (s); + if (m_as_text) { + put (s); + } else { + put_native (s); + } return *this; } /** - * @brief << operator + * @brief << operator: inserts an object supported by "put_native". */ template OutputStream &operator<< (const T &t) { - put (tl::to_string (t)); + if (m_as_text) { + put (tl::to_string (t)); + } else { + put_native (t); + } return *this; } @@ -1456,7 +1544,19 @@ class TL_PUBLIC OutputStream size_t m_buffer_capacity, m_buffer_pos; std::string m_path; - void put_raw (const char *b, size_t n); + 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); // No copying currently OutputStream (const OutputStream &); diff --git a/src/tl/unit_tests/tlStreamTests.cc b/src/tl/unit_tests/tlStreamTests.cc index 4396a102f3..490814a7a2 100644 --- a/src/tl/unit_tests/tlStreamTests.cc +++ b/src/tl/unit_tests/tlStreamTests.cc @@ -66,7 +66,7 @@ TEST(OutputPipe1) { tl::OutputPipe pipe ("cat >" + tf); tl::OutputStream str (pipe); - str << "Hello, world!"; + str.put ("Hello, world!"); } { @@ -82,7 +82,7 @@ TEST(TextOutputStream) { tl::OutputStream os (fn, tl::OutputStream::OM_Auto, false); - os << "Hello, world!\nWith another line\n\r\r\nseparated by a LFCR and CRLF."; + os.put ("Hello, world!\nWith another line\n\r\r\nseparated by a LFCR and CRLF."); } { @@ -140,7 +140,7 @@ TEST(TextInputStream) { tl::OutputStream os (fn, tl::OutputStream::OM_Auto, false); - os << "Hello, world!\nWith another line\n\r\r\nseparated by a LFCR and CRLF."; + os.put ("Hello, world!\nWith another line\n\r\r\nseparated by a LFCR and CRLF."); } { @@ -242,7 +242,7 @@ TEST(SafeOutput) { tl::OutputStream os (tp); - os << "blabla\n"; + os.put ("blabla\n"); } EXPECT_EQ (tl::file_exists (tp + ".~backup"), false); @@ -252,7 +252,7 @@ TEST(SafeOutput) tl::OutputStream os (tp); EXPECT_EQ (tl::file_exists (tp + ".~backup"), true); EXPECT_EQ (tl::file_exists (tp), true); - os << "Hello, world!\n"; + os.put ("Hello, world!\n"); } EXPECT_EQ (tl::file_exists (tp + ".~backup"), false); @@ -268,7 +268,7 @@ TEST(SafeOutput) tl::OutputStream os (broken); EXPECT_EQ (tl::file_exists (tp + ".~backup"), true); EXPECT_EQ (tl::file_exists (tp), true); - os << "Hi!\n"; + os.put ("Hi!\n"); os.flush (); // raises the exception EXPECT_EQ (true, false); } catch (...) { @@ -291,7 +291,7 @@ TEST(SafeOutput) tl::OutputStream os (broken); EXPECT_EQ (tl::file_exists (tp + ".~backup"), true); EXPECT_EQ (tl::file_exists (tp), true); - os << "Hi!\n"; + os.put ("Hi!\n"); os.flush (); // raises the exception EXPECT_EQ (true, false); } catch (...) { @@ -323,7 +323,7 @@ TEST(SafeOutput2) { tl::OutputStream os (tp); - os << "blabla\n"; + os.put ("blabla\n"); } EXPECT_EQ (tl::file_exists (tp + ".~backup"), false); @@ -333,7 +333,7 @@ TEST(SafeOutput2) tl::OutputStream os (tp); EXPECT_EQ (tl::file_exists (tp + ".~backup"), true); EXPECT_EQ (tl::file_exists (tp), true); - os << "Hello, world!\n"; + os.put ("Hello, world!\n"); } EXPECT_EQ (tl::file_exists (tp + ".~backup"), false); @@ -358,7 +358,7 @@ TEST(Backups) { tl::OutputStream os (tp, tl::OutputStream::OM_Auto, false, 2); - os << "1\n"; + os.put ("1\n"); } EXPECT_EQ (tl::file_exists (tp + ".~backup"), false); @@ -376,7 +376,7 @@ TEST(Backups) tl::OutputStream os (tp, tl::OutputStream::OM_Auto, false, 2); EXPECT_EQ (tl::file_exists (tp + ".~backup"), true); EXPECT_EQ (tl::file_exists (tp), true); - os << "2\n"; + os.put ("2\n"); } EXPECT_EQ (tl::file_exists (tp + ".~backup"), false); @@ -399,7 +399,7 @@ TEST(Backups) tl::OutputStream os (tp, tl::OutputStream::OM_Auto, false, 2); EXPECT_EQ (tl::file_exists (tp + ".~backup"), true); EXPECT_EQ (tl::file_exists (tp), true); - os << "3\n"; + os.put ("3\n"); } EXPECT_EQ (tl::file_exists (tp + ".~backup"), false); @@ -427,7 +427,7 @@ TEST(Backups) tl::OutputStream os (tp, tl::OutputStream::OM_Auto, false, 2); EXPECT_EQ (tl::file_exists (tp + ".~backup"), true); EXPECT_EQ (tl::file_exists (tp), true); - os << "4\n"; + os.put ("4\n"); } EXPECT_EQ (tl::file_exists (tp + ".~backup"), false); @@ -456,7 +456,7 @@ TEST(Backups) tl::OutputStream os (broken); EXPECT_EQ (tl::file_exists (tp + ".~backup"), true); EXPECT_EQ (tl::file_exists (tp), true); - os << "5!\n"; + os.put ("5!\n"); os.flush (); // raises the exception EXPECT_EQ (true, false); } catch (...) { @@ -624,3 +624,304 @@ 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::OutputStream os (osm, false /*binary*/); + + 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::OutputStream os (osm, false /*binary*/); + + 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::OutputStream os (osm, false /*binary*/); + + 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::OutputStream os (osm, false /*binary*/); + + 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::OutputStream os (osm, false /*binary*/); + + 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::OutputStream os (osm, false /*binary*/); + + 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::OutputStream os (osm, false /*binary*/); + + 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::OutputStream os (osm, false /*binary*/); + + 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::OutputStream os (osm, false /*binary*/); + + 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::OutputStream os (osm, false /*binary*/); + + 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::OutputStream os (osm, false /*binary*/); + + 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::OutputStream os (osm, false /*binary*/); + + 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::OutputStream os (osm, false /*binary*/); + + 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::OutputStream os (osm, false /*binary*/); + + 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/testdata/ruby/dbBoxTest.rb b/testdata/ruby/dbBoxTest.rb index 537c8c0479..5c440098a3 100644 --- a/testdata/ruby/dbBoxTest.rb +++ b/testdata/ruby/dbBoxTest.rb @@ -41,6 +41,7 @@ def test_1_DBox a = RBA::DBox::new( -10, 21, 11, 17 ) assert_equal( a.to_s, "(-10,17;11,21)" ) assert_equal( RBA::DBox::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::DBox::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( (a*0.5).to_s, "(-5,8.5;5.5,10.5)" ) b = a @@ -263,6 +264,7 @@ def test_1_Box a = RBA::Box::new( -10, 21, 11, 17 ) assert_equal( a.to_s, "(-10,17;11,21)" ) assert_equal( RBA::Box::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::Box::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( (a*2).to_s, "(-20,34;22,42)" ) b = a diff --git a/testdata/ruby/dbEdgePairTest.rb b/testdata/ruby/dbEdgePairTest.rb index 2a02a05ad4..bfcfbe5b4d 100644 --- a/testdata/ruby/dbEdgePairTest.rb +++ b/testdata/ruby/dbEdgePairTest.rb @@ -40,6 +40,9 @@ def test_1 assert_equal(ep.to_s, "(0,0;10,20)/(-10,0;-10,30)") assert_equal(ep.bbox.to_s, "(-10,0;10,30)") + assert_equal(RBA::EdgePair::from_s(ep.to_s).to_s, ep.to_s) + assert_equal(RBA::EdgePair::from_bytes(ep.to_bytes).to_s, ep.to_s) + assert_equal(RBA::EdgePair::new(ep.first, ep.second).to_s, "(0,0;10,20)/(-10,0;-10,30)") ep2 = RBA::EdgePair::new @@ -91,6 +94,9 @@ def test_2 assert_equal(ep.to_s, "(0,0;10,20)/(-10,0;-10,30)") assert_equal(ep.bbox.to_s, "(-10,0;10,30)") + assert_equal(RBA::DEdgePair::from_s(ep.to_s).to_s, ep.to_s) + assert_equal(RBA::DEdgePair::from_bytes(ep.to_bytes).to_s, ep.to_s) + assert_equal(RBA::DEdgePair::new(ep.first, ep.second).to_s, "(0,0;10,20)/(-10,0;-10,30)") ep2 = RBA::DEdgePair::new diff --git a/testdata/ruby/dbEdgeTest.rb b/testdata/ruby/dbEdgeTest.rb index 09623dce33..3e6c8271cd 100644 --- a/testdata/ruby/dbEdgeTest.rb +++ b/testdata/ruby/dbEdgeTest.rb @@ -36,6 +36,7 @@ def test_1_DEdge a = RBA::DEdge::new( -1, 2, 15, -7 ) assert_equal( a.to_s, "(-1,2;15,-7)" ) assert_equal( RBA::DEdge::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::DEdge::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( (a*0.5).to_s, "(-0.5,1;7.5,-3.5)" ) d = RBA::Edge::new( a ) assert_equal( d.to_s, "(-1,2;15,-7)" ) @@ -156,6 +157,7 @@ def test_1_Edge a = RBA::Edge::new( RBA::Point::new( -1, 2 ), RBA::Point::new( 15, -7 ) ) assert_equal( a.to_s, "(-1,2;15,-7)" ) assert_equal( RBA::Edge::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::Edge::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( (a*2).to_s, "(-2,4;30,-14)" ) d = RBA::DEdge::new( a ) assert_equal( d.to_s, "(-1,2;15,-7)" ) diff --git a/testdata/ruby/dbPathTest.rb b/testdata/ruby/dbPathTest.rb index 199d808b29..f3bd55e976 100644 --- a/testdata/ruby/dbPathTest.rb +++ b/testdata/ruby/dbPathTest.rb @@ -33,6 +33,7 @@ def test_1_DPath assert_equal( a.area.to_s, "0.0" ) assert_equal( a.length.to_s, "0.0" ) assert_equal( RBA::DPath::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::DPath::from_bytes(a.to_bytes).to_s, a.to_s ) b = a.dup a = RBA::DPath::new( [ RBA::DPoint::new( 0, 1 ), RBA::DPoint::new( 1, 5 ) ], 2.5 ) @@ -40,6 +41,7 @@ def test_1_DPath assert_equal( "%.3f" % a.area, "10.308" ) assert_equal( "%.3f" % a.length, "4.123" ) assert_equal( RBA::DPath::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::DPath::from_bytes(a.to_bytes).to_s, a.to_s ) c = a.dup assert_equal( a == b, false ) @@ -55,6 +57,7 @@ def test_1_DPath a = RBA::DPath::new( [ RBA::DPoint::new( 0, 1 ), RBA::DPoint::new( 1, 5 ) ], 2.5, -0.5, 1.5 ) assert_equal( a.to_s, "(0,1;1,5) w=2.5 bx=-0.5 ex=1.5 r=false" ) assert_equal( RBA::DPath::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::DPath::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( "%.3f" % a.length, "5.123" ) assert_equal( RBA::Path::new(a).to_s, "(0,1;1,5) w=3 bx=-1 ex=2 r=false" ) @@ -122,6 +125,7 @@ def test_1_Path assert_equal( a.area.to_f.to_s, "0.0" ) assert_equal( a.length.to_s, "0" ) assert_equal( RBA::Path::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::Path::from_bytes(a.to_bytes).to_s, a.to_s ) b = a.dup a = RBA::Path::new( [ RBA::Point::new( 0, 10 ), RBA::Point::new( 10, 50 ) ], 25 ) @@ -129,6 +133,7 @@ def test_1_Path assert_equal( a.area.to_f.to_s, "1025.0" ) assert_equal( a.length.to_s, "41" ) assert_equal( RBA::Path::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::Path::from_bytes(a.to_bytes).to_s, a.to_s ) c = a.dup assert_equal( a == b, false ) @@ -144,6 +149,7 @@ def test_1_Path assert_equal( a.to_s, "(0,10;10,50) w=25 bx=-5 ex=15 r=false" ) assert_equal( a.length.to_s, "51" ) assert_equal( RBA::Path::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::Path::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( RBA::DPath::new(a).to_s, "(0,10;10,50) w=25 bx=-5 ex=15 r=false" ) a.bgn_ext = 5 diff --git a/testdata/ruby/dbPointTest.rb b/testdata/ruby/dbPointTest.rb index 2aeea8a61d..030475706a 100644 --- a/testdata/ruby/dbPointTest.rb +++ b/testdata/ruby/dbPointTest.rb @@ -34,6 +34,7 @@ def test_1_DPoint assert_equal( a.to_s, "1,-17" ) assert_equal( RBA::DPoint::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::DPoint::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( (-a).to_s, "-1,17" ) assert_equal( b.to_s, "0,0" ) assert_equal( c.to_s, "5,11" ) @@ -84,6 +85,7 @@ def test_1_Point assert_equal( a.to_s, "1,-17" ) assert_equal( RBA::Point::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::Point::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( (-a).to_s, "-1,17" ) assert_equal( b.to_s, "0,0" ) assert_equal( c.to_s, "5,11" ) diff --git a/testdata/ruby/dbPolygonTest.rb b/testdata/ruby/dbPolygonTest.rb index e3ed29a83f..4749f832ca 100644 --- a/testdata/ruby/dbPolygonTest.rb +++ b/testdata/ruby/dbPolygonTest.rb @@ -31,6 +31,7 @@ def test_1_DPolygon a = RBA::DPolygon::new assert_equal( a.to_s, "()" ) assert_equal( RBA::DPolygon::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::DPolygon::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( a.is_box?, false ) assert_equal( a.is_empty?, true ) assert_equal( a.is_rectilinear?, false ) @@ -41,6 +42,7 @@ def test_1_DPolygon assert_equal( a.to_s, "(0,1;1,5;5,5)" ) assert_equal( (a * 2).to_s, "(0,2;2,10;10,10)" ) assert_equal( RBA::DPolygon::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::DPolygon::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( a.is_box?, false ) assert_equal( a.num_points_hull, 3 ) assert_equal( a.is_empty?, false ) @@ -101,6 +103,7 @@ def test_1_DPolygon a.insert_hole( [ RBA::DPoint::new( 1, 2 ), RBA::DPoint::new( 2, 2 ), RBA::DPoint::new( 2, 6 ) ] ) assert_equal( a.to_s, "(0,1;1,5;1,1/1,2;2,2;2,6)" ) assert_equal( RBA::DPolygon::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::DPolygon::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( a.area, 0 ) assert_equal( a.num_points_hole(0), 3 ) assert_equal( a.holes, 1 ) @@ -172,6 +175,7 @@ def test_1_Polygon a = RBA::Polygon::new assert_equal( a.to_s, "()" ) assert_equal( RBA::Polygon::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::Polygon::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( a.is_box?, false ) b = a.dup @@ -179,6 +183,7 @@ def test_1_Polygon assert_equal( a.to_s, "(0,1;1,5;5,5)" ) assert_equal( (a * 2).to_s, "(0,2;2,10;10,10)" ) assert_equal( RBA::Polygon::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::Polygon::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( a.num_points_hull, 3 ) c = a.dup @@ -226,6 +231,7 @@ def test_1_Polygon a.insert_hole( [ RBA::Point::new( 1, 2 ), RBA::Point::new( 2, 2 ), RBA::Point::new( 2, 6 ) ] ) assert_equal( a.to_s, "(0,1;1,5;1,1/1,2;2,2;2,6)" ) assert_equal( RBA::Polygon::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::Polygon::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( a.area, 0 ) assert_equal( a.num_points_hole(0), 3 ) assert_equal( a.holes, 1 ) diff --git a/testdata/ruby/dbTextTest.rb b/testdata/ruby/dbTextTest.rb index ac4ca0c387..a05494ecd3 100644 --- a/testdata/ruby/dbTextTest.rb +++ b/testdata/ruby/dbTextTest.rb @@ -30,10 +30,12 @@ def test_1_DText a = RBA::DText::new( "hallo", 10.0, -15.0 ) assert_equal( RBA::DText::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::DText::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( a.to_s, "('hallo',r0 10,-15)" ) a = RBA::DText::new( RBA::Text::new( "itext", RBA::Trans::new( RBA::Trans::R270, RBA::Point::new( 100, -150 )))) assert_equal( RBA::DText::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::DText::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( a.to_s, "('itext',r270 100,-150)" ) a = RBA::DText::new @@ -124,6 +126,7 @@ def test_1_Text a = RBA::Text::new( "hallo", 10, -15 ) assert_equal( RBA::Text::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::Text::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( a.to_s, "('hallo',r0 10,-15)" ) a = RBA::Text::new( RBA::DText::new( "dtext", RBA::DTrans::new( RBA::DTrans::R270, RBA::DPoint::new( 100.0, -150.0 )))) @@ -136,6 +139,7 @@ def test_1_Text a = RBA::Text::new( "hallo", RBA::Trans::new( RBA::Trans::R90, RBA::Point::new( 10, -15 ))) assert_equal( a.to_s, "('hallo',r90 10,-15)" ) assert_equal( RBA::Text::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::Text::from_bytes(a.to_bytes).to_s, a.to_s ) c = a.dup assert_equal( a == b, false ) diff --git a/testdata/ruby/dbTransTest.rb b/testdata/ruby/dbTransTest.rb index 71bc4d780e..8385ddd9be 100644 --- a/testdata/ruby/dbTransTest.rb +++ b/testdata/ruby/dbTransTest.rb @@ -38,6 +38,7 @@ def test_1_DTrans assert_equal( a.to_s, "r0 0,0" ) assert_equal( RBA::DTrans::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::DTrans::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( b.to_s, "m135 17,5" ) assert_equal( c.to_s, "m135 17,5" ) assert_equal( d.to_s, "r0 17,5" ) @@ -47,6 +48,7 @@ def test_1_DTrans assert_equal( RBA::DTrans::new( RBA::Trans::M135, RBA::DPoint::new( 1.2, 0.25 )).to_itype(0.001).to_s, "m135 1200,250" ) assert_equal( RBA::Trans::new( RBA::Trans::M135, RBA::Point::new( 1200, 250 )).to_dtype(0.001).to_s, "m135 1.2,0.25" ) assert_equal( RBA::DTrans::from_s(f.to_s).to_s, f.to_s ) + assert_equal( RBA::DTrans::from_bytes(f.to_bytes).to_s, f.to_s ) assert_equal( b.trans( RBA::DPoint::new( 1, 0 )).to_s, "17,4" ) @@ -139,6 +141,7 @@ def test_2_DTrans assert_equal( i.to_s, "m135 *0.5 2.5,8.5" ) assert_equal( RBA::DCplxTrans::from_s(i.to_s).to_s, i.to_s ) + assert_equal( RBA::DCplxTrans::from_bytes(i.to_bytes).to_s, i.to_s ) assert_equal( i * mb == u, true ) assert_equal( mb * i == u, true ) @@ -244,6 +247,7 @@ def test_1_Trans assert_equal( a.to_s, "r0 0,0" ) assert_equal( RBA::Trans::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::Trans::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( b.to_s, "m135 17,5" ) assert_equal( c.to_s, "m135 17,5" ) assert_equal( d.to_s, "r0 17,5" ) @@ -251,6 +255,7 @@ def test_1_Trans assert_equal( e2.to_s, "m135 0,0" ) assert_equal( f.to_s, "m135 17,5" ) assert_equal( RBA::Trans::from_s(f.to_s).to_s, f.to_s ) + assert_equal( RBA::Trans::from_bytes(f.to_bytes).to_s, f.to_s ) assert_equal( b.trans( RBA::Point::new( 1, 0 )).to_s, "17,4" ) @@ -340,6 +345,7 @@ def test_3_Trans c = RBA::CplxTrans::new( 5, -7 ) assert_equal( c.to_s, "r0 *1 5,-7" ) assert_equal( RBA::CplxTrans::from_s(c.to_s).to_s, c.to_s ) + assert_equal( RBA::CplxTrans::from_bytes(c.to_bytes).to_s, c.to_s ) c = RBA::CplxTrans::new( RBA::CplxTrans::M135 ) assert_equal( c.to_s, "m135 *1 0,0" ) @@ -367,6 +373,7 @@ def test_3_Trans c = RBA::CplxTrans::new( 0.75, 45, true, 2.5, -12.5 ) assert_equal( c.to_s, "m22.5 *0.75 2.5,-12.5" ) assert_equal( RBA::CplxTrans::from_s(c.to_s).to_s, c.to_s ) + assert_equal( RBA::CplxTrans::from_bytes(c.to_bytes).to_s, c.to_s ) c = RBA::CplxTrans::new( 0.75, 45, true, RBA::DPoint::new( 2.5, -12.5 ) ) assert_equal( c.to_s, "m22.5 *0.75 2.5,-12.5" ) assert_equal( c.is_unity?, false ) @@ -436,6 +443,7 @@ def test_4_Trans assert_equal( m.to_s, "r0 *1.1 0,0" ) assert_equal( RBA::DCplxTrans::from_s(m.to_s).to_s, m.to_s ) + assert_equal( RBA::DCplxTrans::from_bytes(m.to_bytes).to_s, m.to_s ) assert_equal( m.trans( RBA::Point::new( 5, -7 )).to_s, "5.5,-7.7" ) im = RBA::ICplxTrans::new( a, 0.5 ) @@ -443,6 +451,7 @@ def test_4_Trans assert_equal( im.to_s, "r0 *0.5 0,0" ) assert_equal( RBA::ICplxTrans::from_s(im.to_s).to_s, im.to_s ) + assert_equal( RBA::ICplxTrans::from_bytes(im.to_bytes).to_s, im.to_s ) assert_equal( im.trans( RBA::Point::new( 5, -7 )).to_s, "3,-4" ) im = RBA::ICplxTrans::new(m) diff --git a/testdata/ruby/dbVectorTest.rb b/testdata/ruby/dbVectorTest.rb index d279cb2bc8..34bce36272 100644 --- a/testdata/ruby/dbVectorTest.rb +++ b/testdata/ruby/dbVectorTest.rb @@ -34,6 +34,7 @@ def test_1_DVector assert_equal( a.to_s, "1,-17" ) assert_equal( RBA::DVector::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::DVector::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( (-a).to_s, "-1,17" ) assert_equal( b.to_s, "0,0" ) assert_equal( c.to_s, "5,11" ) @@ -88,6 +89,7 @@ def test_1_Vector assert_equal( a.to_s, "1,-17" ) assert_equal( RBA::Vector::from_s(a.to_s).to_s, a.to_s ) + assert_equal( RBA::Vector::from_bytes(a.to_bytes).to_s, a.to_s ) assert_equal( (-a).to_s, "-1,17" ) assert_equal( b.to_s, "0,0" ) assert_equal( c.to_s, "5,11" ) From 7f6071db3121b6f0af05ad917ce7af360c8d8aeb Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 3 May 2026 00:15:47 +0200 Subject: [PATCH 2/6] Some refactoring, bug fixes --- src/db/db/dbBinarySerialize.h | 65 +++++++++-------- src/db/db/gsiDeclDbEdge.cc | 2 +- src/db/db/gsiDeclDbEdgePair.cc | 2 +- src/db/db/gsiDeclDbPath.cc | 2 +- src/db/db/gsiDeclDbPolygon.cc | 4 +- src/db/db/gsiDeclDbTrans.cc | 4 +- src/tl/tl/tlStream.cc | 69 ++++++++++++------ src/tl/tl/tlStream.h | 113 ++++++++++++++++++++++++----- src/tl/unit_tests/tlStreamTests.cc | 28 +++---- 9 files changed, 197 insertions(+), 92 deletions(-) diff --git a/src/db/db/dbBinarySerialize.h b/src/db/db/dbBinarySerialize.h index 93c55505cb..731cc74bbc 100644 --- a/src/db/db/dbBinarySerialize.h +++ b/src/db/db/dbBinarySerialize.h @@ -46,45 +46,45 @@ namespace db // Stream inserters template -tl::OutputStream &write_coord (tl::OutputStream &s, C c) +tl::BinaryOutputStream &write_coord (tl::BinaryOutputStream &s, C c) { return s << c; } -inline tl::OutputStream &write_coord (tl::OutputStream &s, db::Coord c) +inline tl::BinaryOutputStream &write_coord (tl::BinaryOutputStream &s, db::Coord c) { // NOTE: for compatibility across different builds we use 64 bit coordinates always return s << (int64_t) c; } template -tl::OutputStream &write_binary (tl::OutputStream &s, const db::point &pt) +tl::BinaryOutputStream &write_binary (tl::BinaryOutputStream &s, const db::point &pt) { return write_coord (write_coord (s, pt.x ()), pt.y ()); } template -tl::OutputStream &write_binary (tl::OutputStream &s, const db::vector &v) +tl::BinaryOutputStream &write_binary (tl::BinaryOutputStream &s, const db::vector &v) { return write_coord (write_coord (s, v.x ()), v.y ()); } template -tl::OutputStream &operator<< (tl::OutputStream &s, const db::point &pt) +tl::BinaryOutputStream &operator<< (tl::BinaryOutputStream &s, const db::point &pt) { s << (uint16_t) 1; // version return write_binary (s, pt); } template -tl::OutputStream &operator<< (tl::OutputStream &s, const db::vector &v) +tl::BinaryOutputStream &operator<< (tl::BinaryOutputStream &s, const db::vector &v) { s << (uint16_t) 1; // version return write_binary (s, v); } template -tl::OutputStream &write_binary (tl::OutputStream &s, const db::edge &e) +tl::BinaryOutputStream &write_binary (tl::BinaryOutputStream &s, const db::edge &e) { write_binary (s, e.p1 ()); write_binary (s, e.p2 ()); @@ -92,14 +92,14 @@ tl::OutputStream &write_binary (tl::OutputStream &s, const db::edge &e) } template -tl::OutputStream &operator<< (tl::OutputStream &s, const db::edge &e) +tl::BinaryOutputStream &operator<< (tl::BinaryOutputStream &s, const db::edge &e) { s << (uint16_t) 1; // version return write_binary (s, e); } template -tl::OutputStream &operator<< (tl::OutputStream &s, const db::box &b) +tl::BinaryOutputStream &operator<< (tl::BinaryOutputStream &s, const db::box &b) { s << (uint16_t) 1; // version write_binary (s, b.p1 ()); @@ -108,7 +108,7 @@ tl::OutputStream &operator<< (tl::OutputStream &s, const db::box &b) } template -tl::OutputStream &operator<< (tl::OutputStream &s, const db::edge_pair &ep) +tl::BinaryOutputStream &operator<< (tl::BinaryOutputStream &s, const db::edge_pair &ep) { s << (uint16_t) 1; // version write_binary (s, ep.first ()); @@ -117,17 +117,17 @@ tl::OutputStream &operator<< (tl::OutputStream &s, const db::edge_pair &ep) } template -tl::OutputStream &write_binary (tl::OutputStream &s, const db::polygon_contour &c) +tl::BinaryOutputStream &write_binary (tl::BinaryOutputStream &s, const db::polygon_contour &c) { s << (uint64_t) c.size (); for (auto i = c.begin (); i != c.end (); ++i) { - s << *i; + write_binary (s, *i); } return s; } template -tl::OutputStream &operator<< (tl::OutputStream &s, const db::polygon &p) +tl::BinaryOutputStream &operator<< (tl::BinaryOutputStream &s, const db::polygon &p) { s << (uint16_t) 1; // version s << (uint64_t) (p.holes () + 1); @@ -138,7 +138,7 @@ tl::OutputStream &operator<< (tl::OutputStream &s, const db::polygon &p) } template -tl::OutputStream &operator<< (tl::OutputStream &s, const db::simple_polygon &p) +tl::BinaryOutputStream &operator<< (tl::BinaryOutputStream &s, const db::simple_polygon &p) { // NOTE: the format of polygon and simple polygon are compatible s << (uint16_t) 1; // version @@ -148,14 +148,14 @@ tl::OutputStream &operator<< (tl::OutputStream &s, const db::simple_polygon & } template -tl::OutputStream &operator<< (tl::OutputStream &s, const db::unit_trans &) +tl::BinaryOutputStream &operator<< (tl::BinaryOutputStream &s, const db::unit_trans &) { s << (uint16_t) 1; // version return s; } template -tl::OutputStream &operator<< (tl::OutputStream &s, const db::disp_trans &t) +tl::BinaryOutputStream &operator<< (tl::BinaryOutputStream &s, const db::disp_trans &t) { s << (uint16_t) 1; // version write_binary (s, t.disp ()); @@ -163,7 +163,7 @@ tl::OutputStream &operator<< (tl::OutputStream &s, const db::disp_trans &t) } template -tl::OutputStream &write_binary (tl::OutputStream &s, const db::simple_trans &t) +tl::BinaryOutputStream &write_binary (tl::BinaryOutputStream &s, const db::simple_trans &t) { s << (uint16_t) t.rot (); write_binary (s, t.disp ()); @@ -171,22 +171,22 @@ tl::OutputStream &write_binary (tl::OutputStream &s, const db::simple_trans & } template -tl::OutputStream &operator<< (tl::OutputStream &s, const db::simple_trans &t) +tl::BinaryOutputStream &operator<< (tl::BinaryOutputStream &s, const db::simple_trans &t) { s << (uint16_t) 1; // version return write_binary (s, t); } template -tl::OutputStream &operator<< (tl::OutputStream &s, const db::complex_trans &t) +tl::BinaryOutputStream &operator<< (tl::BinaryOutputStream &s, const db::complex_trans &t) { s << (uint16_t) 1; // version write_binary (s, t.disp ()); - return s << (double) t.msin () << (double) t.mcos () << (double) t.mag (); + return s << (double) t.msin () << (double) t.mcos () << (double) (t.is_mirror () ? -t.mag () : t.mag ()); } template -tl::OutputStream &operator<< (tl::OutputStream &s, const db::text &t) +tl::BinaryOutputStream &operator<< (tl::BinaryOutputStream &s, const db::text &t) { s << (uint16_t) 1; // version s << t.string (); @@ -196,7 +196,7 @@ tl::OutputStream &operator<< (tl::OutputStream &s, const db::text &t) } template -tl::OutputStream &operator<< (tl::OutputStream &s, const db::path &p) +tl::BinaryOutputStream &operator<< (tl::BinaryOutputStream &s, const db::path &p) { s << (uint16_t) 1; // version s << (uint64_t) p.points (); @@ -206,7 +206,7 @@ tl::OutputStream &operator<< (tl::OutputStream &s, const db::path &p) write_coord (s, p.width ()); write_coord (s, p.bgn_ext ()); write_coord (s, p.end_ext ()); - write_coord (s, p.round ()); + s << p.round (); return s; } @@ -333,7 +333,7 @@ tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::edge_pair &e } template -tl::BinaryInputStream &read_binary (tl::BinaryInputStream &s, db::polygon_contour &c) +tl::BinaryInputStream &read_binary (tl::BinaryInputStream &s, db::polygon_contour &c, bool hole) { uint64_t n = 0; s >> n; @@ -346,7 +346,7 @@ tl::BinaryInputStream &read_binary (tl::BinaryInputStream &s, db::polygon_contou } // NOTE: not normalization or modification is applied - c.assign (pts.begin (), pts.end (), false, false, false); + c.assign (pts.begin (), pts.end (), hole, false, false, false); return s; } @@ -364,10 +364,13 @@ tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::polygon &p) s >> n; p = db::polygon (); + if (n > 0) { + p.reserve_holes (n - 1); + } db::polygon_contour ctr; for (uint64_t h = 0; h < n; ++h) { - read_binary (s, ctr); + read_binary (s, ctr, h > 0); if (h == 0) { p.assign_hull (ctr); } else { @@ -392,7 +395,7 @@ tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::simple_polygon< tl_assert (n == (uint64_t) 1); db::polygon_contour ctr; - read_binary (s, ctr); + read_binary (s, ctr, false); p.assign_hull (ctr); return s; @@ -516,7 +519,9 @@ tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::path &p) } C width, bgn_ext, end_ext; - s >> width >> bgn_ext >> end_ext; + read_coord (s, width); + read_coord (s, bgn_ext); + read_coord (s, end_ext); bool round; s >> round; @@ -533,7 +538,7 @@ std::vector to_bytes (const T &t) { tl::OutputMemoryStream osm; { - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << t; } return std::vector (osm.data (), osm.data () + osm.size ()); @@ -544,7 +549,7 @@ std::string to_bytes_str (const T &t) { tl::OutputMemoryStream osm; { - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << t; } return std::string (osm.data (), osm.size ()); diff --git a/src/db/db/gsiDeclDbEdge.cc b/src/db/db/gsiDeclDbEdge.cc index 5b25f4073f..c3387a5c42 100644 --- a/src/db/db/gsiDeclDbEdge.cc +++ b/src/db/db/gsiDeclDbEdge.cc @@ -471,7 +471,7 @@ struct edge_defs "This string can be turned into an edge again by using \\from_bytes\n. " "\n" "This method has been added in version 0.30.9.\n" - ); + ) + method ("is_parallel?", &C::parallel, gsi::arg ("e"), "@brief Test for being parallel\n" "\n" diff --git a/src/db/db/gsiDeclDbEdgePair.cc b/src/db/db/gsiDeclDbEdgePair.cc index c1953db26f..8c7ac65959 100644 --- a/src/db/db/gsiDeclDbEdgePair.cc +++ b/src/db/db/gsiDeclDbEdgePair.cc @@ -192,7 +192,7 @@ struct edge_pair_defs "This string can be turned into an edge pair again by using \\from_bytes\n. " "\n" "This method has been added in version 0.30.9.\n" - ); + ) + method ("bbox", &C::bbox, "@brief Gets the bounding box of the edge pair\n" ) + diff --git a/src/db/db/gsiDeclDbPath.cc b/src/db/db/gsiDeclDbPath.cc index 8cef53f973..e804e16af1 100644 --- a/src/db/db/gsiDeclDbPath.cc +++ b/src/db/db/gsiDeclDbPath.cc @@ -309,7 +309,7 @@ struct path_defs "This string can be turned into a path again by using \\from_bytes\n. " "\n" "This method has been added in version 0.30.9.\n" - ); + ) + method ("simple_polygon", &C::simple_polygon, "@brief Convert the path to a simple polygon\n" "The returned polygon is not guaranteed to be non-selfoverlapping. This may happen if the path overlaps " diff --git a/src/db/db/gsiDeclDbPolygon.cc b/src/db/db/gsiDeclDbPolygon.cc index be2023eb46..5894f9393f 100644 --- a/src/db/db/gsiDeclDbPolygon.cc +++ b/src/db/db/gsiDeclDbPolygon.cc @@ -727,7 +727,7 @@ struct simple_polygon_defs "This string can be turned into a polygon again by using \\from_bytes\n. " "\n" "This method has been added in version 0.30.9.\n" - ); + ) + method_ext ("round_corners", &round_corners, gsi::arg ("rinner"), gsi::arg ("router"), gsi::arg ("n"), "@brief Rounds the corners of the polygon\n" "\n" @@ -1904,7 +1904,7 @@ struct polygon_defs "This string can be turned into a polygon again by using \\from_bytes\n. " "\n" "This method has been added in version 0.30.9.\n" - ); + ) + method_ext ("round_corners", &round_corners, gsi::arg ("rinner"), gsi::arg ("router"), gsi::arg ("n"), "@brief Rounds the corners of the polygon\n" "\n" diff --git a/src/db/db/gsiDeclDbTrans.cc b/src/db/db/gsiDeclDbTrans.cc index 213fdd5124..7e07d6739d 100644 --- a/src/db/db/gsiDeclDbTrans.cc +++ b/src/db/db/gsiDeclDbTrans.cc @@ -543,7 +543,7 @@ struct trans_defs "This string can be turned into an object again by using \\from_bytes\n. " "\n" "This method has been added in version 0.30.9.\n" - ); + ) + method ("disp", (const vector_type &(C::*) () const) &C::disp, "@brief Gets to the displacement vector\n" "\n" @@ -1189,7 +1189,7 @@ struct cplx_trans_defs "This string can be turned into an object again by using \\from_bytes\n. " "\n" "This method has been added in version 0.30.9.\n" - ); + ) + method ("disp", (displacement_type (C::*)() const) &C::disp, "@brief Gets the displacement\n" ) + diff --git a/src/tl/tl/tlStream.cc b/src/tl/tl/tlStream.cc index 214e5914a4..ceb7c10080 100644 --- a/src/tl/tl/tlStream.cc +++ b/src/tl/tl/tlStream.cc @@ -1469,7 +1469,39 @@ OutputStream::put_raw (const char *b, size_t n) } void -OutputStream::put_native (const char *s, size_t n) +OutputStream::seek (size_t pos) +{ + flush (); + + if (mp_delegate) { + mp_delegate->seek (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 @@ -1479,7 +1511,7 @@ OutputStream::put_native (const char *s, size_t n) } void -OutputStream::put_native (const std::string &s) +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 @@ -1489,91 +1521,80 @@ OutputStream::put_native (const std::string &s) } void -OutputStream::put_native (double v) +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 -OutputStream::put_native (float v) +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 -OutputStream::put_native (bool v) +BinaryOutputStream::put_native (bool v) { char c = v ? 1 : 0; put_raw (&c, 1); } void -OutputStream::put_native (uint8_t v) +BinaryOutputStream::put_native (uint8_t v) { put_raw ((const char *) &v, 1); } void -OutputStream::put_native (int8_t v) +BinaryOutputStream::put_native (int8_t v) { put_raw ((const char *) &v, 1); } void -OutputStream::put_native (uint16_t v) +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 -OutputStream::put_native (int16_t v) +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 -OutputStream::put_native (uint32_t v) +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 -OutputStream::put_native (int32_t v) +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 -OutputStream::put_native (uint64_t v) +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 -OutputStream::put_native (int64_t v) +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 -OutputStream::seek (size_t pos) -{ - flush (); - - if (mp_delegate) { - mp_delegate->seek (pos); - } - m_pos = pos; -} - // --------------------------------------------------------------- // OutputFileBase implementation diff --git a/src/tl/tl/tlStream.h b/src/tl/tl/tlStream.h index 05285de142..0e8d654634 100644 --- a/src/tl/tl/tlStream.h +++ b/src/tl/tl/tlStream.h @@ -1431,11 +1431,7 @@ class TL_PUBLIC OutputStream */ OutputStream &operator<< (const char *s) { - if (m_as_text) { - put (s, strlen (s)); - } else { - put_native (s, strlen (s)); - } + put (s, strlen (s)); return *this; } @@ -1447,11 +1443,7 @@ class TL_PUBLIC OutputStream */ OutputStream &operator<< (const std::string &s) { - if (m_as_text) { - put (s); - } else { - put_native (s); - } + put (s); return *this; } @@ -1461,11 +1453,7 @@ class TL_PUBLIC OutputStream template OutputStream &operator<< (const T &t) { - if (m_as_text) { - put (tl::to_string (t)); - } else { - put_native (t); - } + put (tl::to_string (t)); return *this; } @@ -1544,6 +1532,95 @@ class TL_PUBLIC OutputStream size_t m_buffer_capacity, m_buffer_pos; std::string m_path; + // No copying currently + OutputStream (const OutputStream &); + 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); @@ -1558,9 +1635,11 @@ class TL_PUBLIC OutputStream void put_native (uint64_t v); void put_native (int64_t v); + void set_as_text (bool f); + // No copying currently - OutputStream (const OutputStream &); - OutputStream &operator= (const OutputStream &); + BinaryOutputStream (const BinaryOutputStream &); + BinaryOutputStream &operator= (const BinaryOutputStream &); }; } diff --git a/src/tl/unit_tests/tlStreamTests.cc b/src/tl/unit_tests/tlStreamTests.cc index 490814a7a2..881c4b0988 100644 --- a/src/tl/unit_tests/tlStreamTests.cc +++ b/src/tl/unit_tests/tlStreamTests.cc @@ -642,7 +642,7 @@ std::string s2string (tl::OutputMemoryStream &osm) TEST(BinaryStreams1) { tl::OutputMemoryStream osm; - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << (double) 0.17; @@ -662,7 +662,7 @@ TEST(BinaryStreams1) TEST(BinaryStreams2) { tl::OutputMemoryStream osm; - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << (float) 0.17; @@ -682,7 +682,7 @@ TEST(BinaryStreams2) TEST(BinaryStreams3) { tl::OutputMemoryStream osm; - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << std::string ("ABC"); @@ -702,7 +702,7 @@ TEST(BinaryStreams3) TEST(BinaryStreams4) { tl::OutputMemoryStream osm; - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << "ABC"; @@ -722,7 +722,7 @@ TEST(BinaryStreams4) TEST(BinaryStreams5) { tl::OutputMemoryStream osm; - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << uint8_t (17); @@ -742,7 +742,7 @@ TEST(BinaryStreams5) TEST(BinaryStreams6) { tl::OutputMemoryStream osm; - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << int8_t (17); @@ -762,7 +762,7 @@ TEST(BinaryStreams6) TEST(BinaryStreams7) { tl::OutputMemoryStream osm; - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << uint16_t (1742); @@ -782,7 +782,7 @@ TEST(BinaryStreams7) TEST(BinaryStreams8) { tl::OutputMemoryStream osm; - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << int16_t (1742); @@ -802,7 +802,7 @@ TEST(BinaryStreams8) TEST(BinaryStreams9) { tl::OutputMemoryStream osm; - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << uint32_t (17420000); @@ -822,7 +822,7 @@ TEST(BinaryStreams9) TEST(BinaryStreams10) { tl::OutputMemoryStream osm; - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << int32_t (17420000); @@ -842,7 +842,7 @@ TEST(BinaryStreams10) TEST(BinaryStreams11) { tl::OutputMemoryStream osm; - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << uint64_t (174200000000l); @@ -862,7 +862,7 @@ TEST(BinaryStreams11) TEST(BinaryStreams12) { tl::OutputMemoryStream osm; - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << int64_t (174200000000l); @@ -882,7 +882,7 @@ TEST(BinaryStreams12) TEST(BinaryStreams13) { tl::OutputMemoryStream osm; - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << true; os << false; @@ -904,7 +904,7 @@ TEST(BinaryStreams13) TEST(BinaryStreamsCombined) { tl::OutputMemoryStream osm; - tl::OutputStream os (osm, false /*binary*/); + tl::BinaryOutputStream os (osm); os << "ABC" << 17.0 << "XUV" << (int32_t) 42; From 1de28f2d6b518d2972fd40c1eca4779b375ebe7d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 3 May 2026 16:24:14 +0200 Subject: [PATCH 3/6] Refactoring, some enhancements to tl::Variant - Split binary and regular streams - Binary serialization of tl::Variant - Fixing tl::Variant parsable string representation for byte arrays and char (Format is '...'b for byte arrays and '.'c for chars). - tl::to_quoted_string now allows 0 characters in the string (escapes to '\000') --- src/db/db/dbBinarySerialize.h | 2 +- src/db/db/gsiDeclDbPropertiesSupport.h | 2 +- src/tl/tl/tl.pro | 2 + src/tl/tl/tlBinaryStream.cc | 691 +++++++++++++++++++++++ src/tl/tl/tlBinaryStream.h | 207 +++++++ src/tl/tl/tlStream.cc | 304 ---------- src/tl/tl/tlStream.h | 168 ------ src/tl/tl/tlString.cc | 2 +- src/tl/tl/tlVariant.cc | 81 ++- src/tl/tl/tlVariant.h | 66 +++ src/tl/unit_tests/tlBinaryStreamTests.cc | 425 ++++++++++++++ src/tl/unit_tests/tlStreamTests.cc | 301 ---------- src/tl/unit_tests/tlVariantTests.cc | 88 ++- src/tl/unit_tests/unit_tests.pro | 1 + 14 files changed, 1554 insertions(+), 786 deletions(-) create mode 100644 src/tl/unit_tests/tlBinaryStreamTests.cc diff --git a/src/db/db/dbBinarySerialize.h b/src/db/db/dbBinarySerialize.h index 731cc74bbc..8482558e0c 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 8016117c54..cb7930772b 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 b3386179be..51061b1b37 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 e69de29bb2..4de7108149 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 e69de29bb2..4b6596ced1 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 ceb7c10080..fce7a43aed 100644 --- a/src/tl/tl/tlStream.cc +++ b/src/tl/tl/tlStream.cc @@ -20,8 +20,6 @@ */ - - #include #include #include @@ -133,15 +131,6 @@ class FilePWriteErrorException { } }; -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 0e8d654634..0b9764611a 100644 --- a/src/tl/tl/tlStream.h +++ b/src/tl/tl/tlStream.h @@ -805,69 +805,6 @@ class TL_PUBLIC TextInputStream // --------------------------------------------------------------------------------- -/** - * @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 @@ class TL_PUBLIC OutputStream 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 2515685113..9242d99c75 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 3633ef37b2..aef08085ad 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 5abaa1c453..0d2c28d967 100644 --- a/src/tl/tl/tlVariant.h +++ b/src/tl/tl/tlVariant.h @@ -205,11 +205,21 @@ class TL_PUBLIC Variant */ 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 @@ class TL_PUBLIC Variant */ 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 @@ class TL_PUBLIC Variant 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 @@ class TL_PUBLIC Variant 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 @@ class TL_PUBLIC Variant */ Variant &operator= (const Variant &v); + /** + * @brief Assignment (move) + */ + Variant &operator= (Variant &&v); + /** * @brief Assignment of a string */ @@ -568,11 +606,21 @@ class TL_PUBLIC Variant */ 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 @@ class TL_PUBLIC Variant 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 @@ class TL_PUBLIC Variant 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 0000000000..3a3c77779f --- /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 881c4b0988..71f85030ed 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 28c71258cf..15e354c7d1 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 3d8b066765..5ea1fe9cfd 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 \ From 77fb74e0727ca9f13f963dfa1a3e02b866dbbb95 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 3 May 2026 18:10:00 +0200 Subject: [PATCH 4/6] Supporting to_bytes and from_bytes also for the ..WithProperties types --- src/db/db/dbBinarySerialize.h | 45 ++++++++++++++++++++++++++ src/db/db/gsiDeclDbPropertiesSupport.h | 28 ++++++++++++++++ testdata/ruby/dbBoxTest.rb | 14 ++++++++ testdata/ruby/dbPolygonTest.rb | 18 +++++++++++ 4 files changed, 105 insertions(+) diff --git a/src/db/db/dbBinarySerialize.h b/src/db/db/dbBinarySerialize.h index 8482558e0c..2898420efd 100644 --- a/src/db/db/dbBinarySerialize.h +++ b/src/db/db/dbBinarySerialize.h @@ -35,6 +35,7 @@ #include "dbPath.h" #include "dbTrans.h" #include "dbText.h" +#include "dbObjectWithProperties.h" #include "tlBinaryStream.h" #include "tlException.h" @@ -210,6 +211,23 @@ tl::BinaryOutputStream &operator<< (tl::BinaryOutputStream &s, const db::path return s; } +template +tl::BinaryOutputStream &operator<< (tl::BinaryOutputStream &s, const db::object_with_properties &o) +{ + s << (uint16_t) 1; // version + + s << (const T &) o; + + const auto &ps = db::properties (o.properties_id ()); + + s << (uint64_t) ps.size (); + for (auto i = ps.begin (); i != ps.end (); ++i) { + s << db::property_name (i->first) << db::property_value (i->second); + } + + return s; +} + // ----------------------------------------------------------------------------------------- // Stream extractors @@ -530,6 +548,33 @@ tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::path &p) return s; } +template +tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::object_with_properties &o) +{ + uint16_t fmt = 0; + s >> fmt; + if (fmt > 1) { + throw FutureBinarySerializationFormatException (); + } + + s >> (T &) o; + + uint64_t n = 0; + s >> n; + + db::PropertiesSet ps; + + while (n-- > 0) { + tl::Variant name, value; + s >> name >> value; + ps.insert (name, value); + } + + o.properties_id (db::properties_id (ps)); + + return s; +} + // ----------------------------------------------------------------------------------------- // Converters of objects to a binary string diff --git a/src/db/db/gsiDeclDbPropertiesSupport.h b/src/db/db/gsiDeclDbPropertiesSupport.h index cb7930772b..2dbf2d1aeb 100644 --- a/src/db/db/gsiDeclDbPropertiesSupport.h +++ b/src/db/db/gsiDeclDbPropertiesSupport.h @@ -27,12 +27,27 @@ #include "tlTypeTraits.h" #include "dbPropertiesRepository.h" #include "dbObjectWithProperties.h" +#include "dbBinarySerialize.h" #include "dbTrans.h" #include "dbEdge.h" namespace gsi { +template +static T *from_bytes (const std::vector &s) +{ + std::unique_ptr t (new T ()); + db::from_bytes (s, *t); + return t.release (); +} + +template +static std::vector to_bytes (const T *t) +{ + return db::to_bytes (*t); +} + template static void delete_property_meth_impl (T *s, const tl::Variant &key) { @@ -253,6 +268,19 @@ static gsi::Methods properties_support_methods () gsi::method ("to_s", (std::string (T::*) () const) &T::to_string, "@brief Returns a string representing the object\n" ) + + gsi::constructor ("from_bytes", &from_bytes, gsi::arg ("s"), + "@brief Creates an object from a binary serialization\n" + "Creates the object from a binary representation (as returned by \\to_bytes)\n" + "\n" + "This method has been added in version 0.30.9.\n" + ) + + gsi::method_ext ("to_bytes", &to_bytes, + "@brief Returns a binary string representing this object\n" + "\n" + "This string can be turned into an object again by using \\from_bytes\n. " + "\n" + "This method has been added in version 0.30.9.\n" + ) + gsi::method_ext ("properties", &get_properties_meth_impl, "@brief Gets the user properties\n" "This method is a convenience method that gets the properties of the shape as a single hash.\n" diff --git a/testdata/ruby/dbBoxTest.rb b/testdata/ruby/dbBoxTest.rb index 5c440098a3..40c11e141f 100644 --- a/testdata/ruby/dbBoxTest.rb +++ b/testdata/ruby/dbBoxTest.rb @@ -552,6 +552,20 @@ def test_boxWithProperties assert_equal(s.to_s, "(0,0;100,200) props={}") assert_equal(s.property(1), nil) + # binary serialization + + s = RBA::BoxWithProperties::new(RBA::Box::new(0, 0, 100, 200), {}) + assert_equal(RBA::BoxWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) + + s = RBA::BoxWithProperties::new(RBA::Box::new(0, 0, 100, 200), { 1 => "one", "key" => 17 }) + assert_equal(RBA::BoxWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) + + s = RBA::DBoxWithProperties::new(RBA::DBox::new(0, 0, 100, 200), {}) + assert_equal(RBA::DBoxWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) + + s = RBA::DBoxWithProperties::new(RBA::DBox::new(0, 0, 100, 200), { 1 => "one", "key" => 17 }) + assert_equal(RBA::DBoxWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) + end end diff --git a/testdata/ruby/dbPolygonTest.rb b/testdata/ruby/dbPolygonTest.rb index 4749f832ca..422e32a49f 100644 --- a/testdata/ruby/dbPolygonTest.rb +++ b/testdata/ruby/dbPolygonTest.rb @@ -990,6 +990,24 @@ def test_polygonWithProperties assert_equal(s.class.to_s, "RBA::DSimplePolygonWithProperties") assert_equal(s.downcast.class.to_s, "RBA::DSimplePolygon") + # binary serialization + s = RBA::PolygonWithProperties::new(RBA::Box::new(0, 0, 100, 200), {}) + assert_equal(RBA::PolygonWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) + s = RBA::PolygonWithProperties::new(RBA::Box::new(0, 0, 100, 200), { 1 => "one", "key" => 17 }) + assert_equal(RBA::PolygonWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) + s = RBA::DPolygonWithProperties::new(RBA::DBox::new(0, 0, 100, 200), {}) + assert_equal(RBA::DPolygonWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) + s = RBA::DPolygonWithProperties::new(RBA::DBox::new(0, 0, 100, 200), { 1 => "one", "key" => 17 }) + assert_equal(RBA::DPolygonWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) + s = RBA::SimplePolygonWithProperties::new(RBA::Box::new(0, 0, 100, 200), {}) + assert_equal(RBA::SimplePolygonWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) + s = RBA::SimplePolygonWithProperties::new(RBA::Box::new(0, 0, 100, 200), { 1 => "one", "key" => 17 }) + assert_equal(RBA::SimplePolygonWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) + s = RBA::DSimplePolygonWithProperties::new(RBA::DBox::new(0, 0, 100, 200), {}) + assert_equal(RBA::DSimplePolygonWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) + s = RBA::DSimplePolygonWithProperties::new(RBA::DBox::new(0, 0, 100, 200), { 1 => "one", "key" => 17 }) + assert_equal(RBA::DSimplePolygonWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) + end def test_triangulation From c85be6bce523fea3281232c1df0147355b674280 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 3 May 2026 20:27:15 +0200 Subject: [PATCH 5/6] Adding string serialization "from_s" for objects with properties (CAUTION: side effect!) Problem was that "to_s" did not deliver a parsable string for the properties. This is fixed, but the format of the properties part of the string changes. --- src/db/db/dbObjectWithProperties.h | 2 +- src/db/db/gsiDeclDbPropertiesSupport.h | 15 + .../unit_tests/dbObjectWithPropertiesTests.cc | 6 +- src/db/unit_tests/dbRegionProcessorTests.cc | 2 +- src/db/unit_tests/dbRegionTests.cc | 4 +- testdata/python/dbEdgeNeighborhoodWithNets.py | 308 +++++++++--------- testdata/ruby/dbBoxTest.rb | 30 +- testdata/ruby/dbEdgeNeighborhood.rb | 12 +- testdata/ruby/dbEdgePairTest.rb | 16 +- testdata/ruby/dbEdgePairsTest.rb | 4 +- testdata/ruby/dbEdgeTest.rb | 52 +-- testdata/ruby/dbEdgesTest.rb | 8 +- testdata/ruby/dbPathTest.rb | 16 +- testdata/ruby/dbPolygonNeighborhood.rb | 4 +- testdata/ruby/dbPolygonTest.rb | 50 ++- testdata/ruby/dbRegionTest.rb | 10 +- testdata/ruby/dbTextTest.rb | 16 +- testdata/ruby/dbTextsTest.rb | 4 +- 18 files changed, 299 insertions(+), 260 deletions(-) diff --git a/src/db/db/dbObjectWithProperties.h b/src/db/db/dbObjectWithProperties.h index 8b2cd1baf8..d19bce192d 100644 --- a/src/db/db/dbObjectWithProperties.h +++ b/src/db/db/dbObjectWithProperties.h @@ -271,7 +271,7 @@ class object_with_properties { std::string s = Obj::to_string (); s += " props="; - s += db::properties (properties_id ()).to_dict_var ().to_string (); + s += db::properties (properties_id ()).to_dict_var ().to_parsable_string (); return s; } diff --git a/src/db/db/gsiDeclDbPropertiesSupport.h b/src/db/db/gsiDeclDbPropertiesSupport.h index 2dbf2d1aeb..9abebee9ce 100644 --- a/src/db/db/gsiDeclDbPropertiesSupport.h +++ b/src/db/db/gsiDeclDbPropertiesSupport.h @@ -34,6 +34,15 @@ namespace gsi { +template +static T *from_string (const std::string &s) +{ + tl::Extractor ex (s); + std::unique_ptr t (new T ()); + ex.read (*t.get ()); + return t.release (); +} + template static T *from_bytes (const std::vector &s) { @@ -265,6 +274,12 @@ static gsi::Methods properties_support_methods () "If no property with that key does not exist, it will return nil. Using that method is more " "convenient than using the layout object and the properties ID to retrieve the property value. " ) + + gsi::constructor ("from_s", &from_string, gsi::arg ("s"), + "@brief Creates an object from a binary serialization\n" + "Creates the object from a binary representation (as returned by \\to_bytes)\n" + "\n" + "This method has been added in version 0.30.9.\n" + ) + gsi::method ("to_s", (std::string (T::*) () const) &T::to_string, "@brief Returns a string representing the object\n" ) + diff --git a/src/db/unit_tests/dbObjectWithPropertiesTests.cc b/src/db/unit_tests/dbObjectWithPropertiesTests.cc index 751b1f34e4..187cfe7f3e 100644 --- a/src/db/unit_tests/dbObjectWithPropertiesTests.cc +++ b/src/db/unit_tests/dbObjectWithPropertiesTests.cc @@ -34,7 +34,7 @@ TEST(1) db::PolygonWithProperties pwp (db::Polygon (db::Box (0, 0, 100, 200)), db::properties_id (ps)); - EXPECT_EQ (pwp.to_string (), "(0,0;0,200;100,200;100,0) props={1=>one,key=>42}"); + EXPECT_EQ (pwp.to_string (), "(0,0;0,200;100,200;100,0) props={#1=>'one','key'=>##42}"); db::PolygonWithProperties pwp2; @@ -43,11 +43,11 @@ TEST(1) EXPECT_EQ (ex.try_read (pwp2), false); - s = " (0,0;0,200;100,200;100,0) props= {1 => \"one\", key => 42} "; + s = " (0,0;0,200;100,200;100,0) props= {#1 => \"one\", 'key' => ##42} "; ex = tl::Extractor (s.c_str ()); EXPECT_EQ (ex.try_read (pwp2), true); - EXPECT_EQ (pwp2.to_string (), "(0,0;0,200;100,200;100,0) props={1=>one,key=>42}"); + EXPECT_EQ (pwp2.to_string (), "(0,0;0,200;100,200;100,0) props={#1=>'one','key'=>##42}"); } } diff --git a/src/db/unit_tests/dbRegionProcessorTests.cc b/src/db/unit_tests/dbRegionProcessorTests.cc index c0e9cfb402..fcf6a3a2ea 100644 --- a/src/db/unit_tests/dbRegionProcessorTests.cc +++ b/src/db/unit_tests/dbRegionProcessorTests.cc @@ -84,5 +84,5 @@ TEST(1_RegionToEdgesProcessor) result.clear (); db::PolygonToEdgeProcessor (db::PolygonToEdgeProcessor::StepIn).process (poly, result); - EXPECT_EQ (tl::join (result.begin (), result.end (), ";"), "(0,1000;1000,1000) props={net=>17};(2000,2000;2000,1000) props={net=>17}"); + EXPECT_EQ (tl::join (result.begin (), result.end (), ";"), "(0,1000;1000,1000) props={'net'=>#17};(2000,2000;2000,1000) props={'net'=>#17}"); } diff --git a/src/db/unit_tests/dbRegionTests.cc b/src/db/unit_tests/dbRegionTests.cc index fb114a32b4..e6730cc59b 100644 --- a/src/db/unit_tests/dbRegionTests.cc +++ b/src/db/unit_tests/dbRegionTests.cc @@ -2253,7 +2253,7 @@ TEST(52_PropertiesDeep) EXPECT_EQ (s.at_end (), false); // polygons are merged with "maximum" property value - EXPECT_EQ (db::PolygonWithProperties (*s, s.prop_id ()).to_string (), "(0,0;0,200;1,200;1,202;10,202;10,220;110,220;110,212;111,212;111,12;101,12;101,2;100,2;100,0) props={id=>42}"); + EXPECT_EQ (db::PolygonWithProperties (*s, s.prop_id ()).to_string (), "(0,0;0,200;1,200;1,202;10,202;10,220;110,220;110,212;111,212;111,12;101,12;101,2;100,2;100,0) props={'id'=>#42}"); ++s; EXPECT_EQ (s.at_end (), true); @@ -2395,7 +2395,7 @@ TEST(53_PropertiesDeepFromLayout) EXPECT_EQ (s.at_end (), false); // polygons are merged with "maximum" property value - EXPECT_EQ (db::PolygonWithProperties (*s, s.prop_id ()).to_string (), "(0,0;0,200;1,200;1,202;10,202;10,220;110,220;110,212;111,212;111,12;101,12;101,2;100,2;100,0) props={VALUE=>42}"); + EXPECT_EQ (db::PolygonWithProperties (*s, s.prop_id ()).to_string (), "(0,0;0,200;1,200;1,202;10,202;10,220;110,220;110,212;111,212;111,12;101,12;101,2;100,2;100,0) props={'VALUE'=>#42}"); ++s; EXPECT_EQ (s.at_end (), true); diff --git a/testdata/python/dbEdgeNeighborhoodWithNets.py b/testdata/python/dbEdgeNeighborhoodWithNets.py index ddd4a37a44..758ec0b759 100644 --- a/testdata/python/dbEdgeNeighborhoodWithNets.py +++ b/testdata/python/dbEdgeNeighborhoodWithNets.py @@ -147,160 +147,160 @@ def test_1_Basic(self): self.maxDiff = None self.assertEqual("\n" + visitor.dump(), """ -Polygon: (-14000,0;-14000,15000;-11000,15000;-11000,0) props={net=>net1} - Edge: (-11000,0;-14000,0) props={net=>net1} - 0.0,3000.0 -> 0: (0,-11;0,0;3000,0;3000,-11) props={net=>net1} - Edge: (-11000,15000;-11000,0) props={net=>net1} - 0.0,500.0 -> 0: (0,-11;0,0;500,0;500,-11) props={net=>net1} - 0.0,500.0 -> 1: (0,1500;0,6001;500,6001;500,1500) props={net=>net1} - 0.0,500.0 -> 3: (0,-11;0,4500;500,4500;500,-11) props={net=>net1} - 500.0,2500.0 -> 0: (500,-11;500,0;2500,0;2500,-11) props={net=>net1} - 500.0,2500.0 -> 1: (500,1500;500,6001;2500,6001;2500,1500) props={net=>net1} - 500.0,2500.0 -> 2: (500,2000;500,4000;2500,4000;2500,2000) props={net=>net1} - 500.0,2500.0 -> 3: (500,-11;500,4500;2500,4500;2500,-11) props={net=>net1} - 2500.0,3000.0 -> 0: (2500,-11;2500,0;3000,0;3000,-11) props={net=>net1} - 2500.0,3000.0 -> 1: (2500,1500;2500,6001;3000,6001;3000,1500) props={net=>net1} - 2500.0,3000.0 -> 3: (2500,-11;2500,4500;3000,4500;3000,-11) props={net=>net1} - 3000.0,8500.0 -> 0: (3000,-11;3000,0;8500,0;8500,-11) props={net=>net1} - 3000.0,8500.0 -> 1: (3000,1500;3000,4500;8500,4500;8500,1500) props={net=>net1}/(3000,6000;3000,6001;8500,6001;8500,6000) props={net=>net1} - 3000.0,8500.0 -> 3: (3000,-11;3000,0;8500,0;8500,-11) props={net=>net1} - 8500.0,15000.0 -> 0: (8500,-11;8500,0;15000,0;15000,-11) props={net=>net1} - 8500.0,15000.0 -> 1: (8500,1500;8500,4500;15000,4500;15000,1500) props={net=>net1}/(8500,6000;8500,6001;15000,6001;15000,6000) props={net=>net1} - Edge: (-14000,0;-14000,15000) props={net=>net1} - 0.0,6500.0 -> 0: (0,-11;0,0;6500,0;6500,-11) props={net=>net1} - 6500.0,15000.0 -> 0: (6500,-11;6500,0;15000,0;15000,-11) props={net=>net1} - 6500.0,15000.0 -> 3: (6500,-11;6500,0;15000,0;15000,-11) props={net=>net1} - Edge: (-14000,15000;-11000,15000) props={net=>net1} - 0.0,3000.0 -> 0: (0,-11;0,0;3000,0;3000,-11) props={net=>net1} - 0.0,3000.0 -> 1: (0,1500;0,5000;3000,5000;3000,1500) props={net=>net3} - 0.0,3000.0 -> 3: (0,-11;0,0;3000,0;3000,-11) props={net=>net1} - 3000.0,3001.0 -> 1: (3000,1500;3000,5000;3001,5000;3001,1500) props={net=>net3} - 3000.0,3001.0 -> 3: (3000,-11;3000,0;3001,0;3001,-11) props={net=>net1} -Polygon: (-14000,16500;-14000,20000;0,20000;0,16500) props={net=>net3} - Edge: (-14000,16500;-14000,20000) props={net=>net3} - 0.0,3500.0 -> 0: (0,-11;0,0;3500,0;3500,-11) props={net=>net3} - Edge: (-14000,20000;0,20000) props={net=>net3} - 0.0,7000.0 -> 0: (0,-11;0,0;7000,0;7000,-11) props={net=>net3} - 7000.0,14000.0 -> 0: (7000,-11;7000,0;14000,0;14000,-11) props={net=>net3} - 7000.0,14000.0 -> 3: (7000,-11;7000,0;14000,0;14000,-11) props={net=>net2} - 14000.0,14001.0 -> 3: (14000,-11;14000,0;14001,0;14001,-11) props={net=>net2} - Edge: (0,16500;-14000,16500) props={net=>net3} - -1.0,0.0 -> 3: (-1,-11;-1,0;0,0;0,-11) props={net=>net2} - 0.0,5000.0 -> 0: (0,-11;0,0;5000,0;5000,-11) props={net=>net3} - 0.0,5000.0 -> 1: (0,1500;0,6001;5000,6001;5000,1500) props={net=>net1} - 0.0,5000.0 -> 3: (0,-11;0,0;5000,0;5000,-11) props={net=>net2} - 5000.0,6500.0 -> 0: (5000,-11;5000,0;6500,0;6500,-11) props={net=>net3} - 5000.0,6500.0 -> 1: (5000,1500;5000,4500;6500,4500;6500,1500) props={net=>net1} - 5000.0,6500.0 -> 3: (5000,-11;5000,0;6500,0;6500,-11) props={net=>net2} - 6500.0,7000.0 -> 0: (6500,-11;6500,0;7000,0;7000,-11) props={net=>net3} - 6500.0,7000.0 -> 1: (6500,1500;6500,6001;7000,6001;7000,1500) props={net=>net1} - 6500.0,7000.0 -> 3: (6500,-11;6500,0;7000,0;7000,-11) props={net=>net2}/(6500,1500;6500,4500;7000,4500;7000,1500) props={net=>net1} - 7000.0,9000.0 -> 0: (7000,-11;7000,0;9000,0;9000,-11) props={net=>net3} - 7000.0,9000.0 -> 1: (7000,1500;7000,6001;9000,6001;9000,1500) props={net=>net1} - 7000.0,9000.0 -> 2: (7000,2000;7000,4000;9000,4000;9000,2000) props={net=>net1} - 7000.0,9000.0 -> 3: (7000,1500;7000,4500;9000,4500;9000,1500) props={net=>net1} - 9000.0,9500.0 -> 0: (9000,-11;9000,0;9500,0;9500,-11) props={net=>net3} - 9000.0,9500.0 -> 1: (9000,1500;9000,6001;9500,6001;9500,1500) props={net=>net1} - 9000.0,9500.0 -> 3: (9000,1500;9000,4500;9500,4500;9500,1500) props={net=>net1} - 9500.0,11000.0 -> 0: (9500,-11;9500,0;11000,0;11000,-11) props={net=>net3} - 9500.0,11000.0 -> 3: (9500,1500;9500,4500;11000,4500;11000,1500) props={net=>net1} - 11000.0,11500.0 -> 0: (11000,-11;11000,0;11500,0;11500,-11) props={net=>net3} - 11000.0,11500.0 -> 1: (11000,1500;11000,6001;11500,6001;11500,1500) props={net=>net1} - 11000.0,11500.0 -> 3: (11000,1500;11000,6001;11500,6001;11500,1500) props={net=>net1} - 11500.0,13500.0 -> 0: (11500,-11;11500,0;13500,0;13500,-11) props={net=>net3} - 11500.0,13500.0 -> 1: (11500,1500;11500,6001;13500,6001;13500,1500) props={net=>net1} - 11500.0,13500.0 -> 2: (11500,2000;11500,4000;13500,4000;13500,2000) props={net=>net1} - 11500.0,13500.0 -> 3: (11500,1500;11500,6001;13500,6001;13500,1500) props={net=>net1} - 13500.0,14000.0 -> 0: (13500,-11;13500,0;14000,0;14000,-11) props={net=>net3} - 13500.0,14000.0 -> 1: (13500,1500;13500,6001;14000,6001;14000,1500) props={net=>net1} - 13500.0,14000.0 -> 3: (13500,1500;13500,6001;14000,6001;14000,1500) props={net=>net1} - Edge: (0,20000;0,16500) props={net=>net3} - 0.0,3500.0 -> 0: (0,-11;0,0;3500,0;3500,-11) props={net=>net3} - 0.0,3500.0 -> 3: (0,-11;0,4500;3500,4500;3500,-11) props={net=>net2} - 3500.0,3501.0 -> 3: (3500,1500;3500,4500;3501,4500;3501,1500) props={net=>net2} -Polygon: (-9500,-5500;-9500,-1500;5000,-1500;5000,-5500) props={net=>net2} - Edge: (-9500,-1500;5000,-1500) props={net=>net2} - 0.0,3000.0 -> 0: (0,-11;0,0;3000,0;3000,-11) props={net=>net2} - 0.0,3000.0 -> 1: (0,1500;0,6001;3000,6001;3000,1500) props={net=>net1} - 3000.0,4500.0 -> 0: (3000,-11;3000,0;4500,0;4500,-11) props={net=>net2} - 4500.0,9500.0 -> 0: (4500,-11;4500,0;9500,0;9500,-11) props={net=>net2} - 4500.0,9500.0 -> 1: (4500,1500;4500,6001;9500,6001;9500,1500) props={net=>net1} - 9500.0,11000.0 -> 0: (9500,-11;9500,0;11000,0;11000,-11) props={net=>net2} - 11000.0,14000.0 -> 0: (11000,-11;11000,0;14000,0;14000,-11) props={net=>net2} - 11000.0,14000.0 -> 3: (11000,-11;11000,6001;14000,6001;14000,-11) props={net=>net2} - 14000.0,14500.0 -> 0: (14000,-11;14000,0;14500,0;14500,-11) props={net=>net2} - Edge: (-9500,-5500;-9500,-1500) props={net=>net2} - 0.0,4000.0 -> 0: (0,-11;0,0;4000,0;4000,-11) props={net=>net2} - Edge: (5000,-1500;5000,-5500) props={net=>net2} - 0.0,4000.0 -> 0: (0,-11;0,0;4000,0;4000,-11) props={net=>net2} - Edge: (5000,-5500;-9500,-5500) props={net=>net2} - 0.0,14500.0 -> 0: (0,-11;0,0;14500,0;14500,-11) props={net=>net2} -Polygon: (-9500,0;-9500,15000;0,15000;0,0;-5000,0;-5000,12000;-6500,12000;-6500,0) props={net=>net1} - Edge: (-5000,0;-5000,12000) props={net=>net1} - 0.0,6500.0 -> 0: (0,-11;0,0;6500,0;6500,-11) props={net=>net1}/(0,1500;0,4500;6500,4500;6500,1500) props={net=>net1} - 0.0,6500.0 -> 1: (0,6000;0,6001;6500,6001;6500,6000) props={net=>net1} - 6500.0,12000.0 -> 0: (6500,-11;6500,0;12000,0;12000,-11) props={net=>net1}/(6500,1500;6500,4500;12000,4500;12000,1500) props={net=>net1} - 6500.0,12000.0 -> 1: (6500,6000;6500,6001;12000,6001;12000,6000) props={net=>net1} - 6500.0,12000.0 -> 3: (6500,6000;6500,6001;12000,6001;12000,6000) props={net=>net1} - 12000.0,12001.0 -> 0: (12000,-11;12000,4500;12001,4500;12001,-11) props={net=>net1} - 12000.0,12001.0 -> 1: (12000,6000;12000,6001;12001,6001;12001,6000) props={net=>net1} - 12000.0,12001.0 -> 3: (12000,1500;12000,6001;12001,6001;12001,1500) props={net=>net1} - Edge: (-5000,12000;-6500,12000) props={net=>net1} - -1.0,0.0 -> 0: (-1,-11;-1,6001;0,6001;0,-11) props={net=>net1} - 0.0,1500.0 -> 0: (0,-11;0,0;1500,0;1500,-11) props={net=>net1} - 1500.0,1501.0 -> 0: (1500,-11;1500,6001;1501,6001;1501,-11) props={net=>net1} - 1500.0,1501.0 -> 3: (1500,-11;1500,0;1501,0;1501,-11) props={net=>net1} - Edge: (-6500,0;-9500,0) props={net=>net1} - -1.0,0.0 -> 1: (-1,1500;-1,5500;0,5500;0,1500) props={net=>net2} - 0.0,3000.0 -> 0: (0,-11;0,0;3000,0;3000,-11) props={net=>net1} - 0.0,3000.0 -> 1: (0,1500;0,5500;3000,5500;3000,1500) props={net=>net2} - Edge: (-6500,12000;-6500,0) props={net=>net1} - -1.0,0.0 -> 0: (-1,-11;-1,6001;0,6001;0,-11) props={net=>net1} - -1.0,0.0 -> 3: (-1,-11;-1,0;0,0;0,-11) props={net=>net1} - 0.0,12000.0 -> 0: (0,-11;0,0;12000,0;12000,-11) props={net=>net1}/(0,1500;0,6001;12000,6001;12000,1500) props={net=>net1} - Edge: (-9500,0;-9500,15000) props={net=>net1} - 0.0,6500.0 -> 0: (0,-11;0,0;6500,0;6500,-11) props={net=>net1} - 0.0,6500.0 -> 1: (0,1500;0,4500;6500,4500;6500,1500) props={net=>net1} - 6500.0,12000.0 -> 0: (6500,-11;6500,0;12000,0;12000,-11) props={net=>net1} - 6500.0,12000.0 -> 1: (6500,1500;6500,4500;12000,4500;12000,1500) props={net=>net1} - 6500.0,12000.0 -> 3: (6500,1500;6500,4500;12000,4500;12000,1500) props={net=>net1} - 12000.0,12500.0 -> 0: (12000,-11;12000,0;12500,0;12500,-11) props={net=>net1} - 12000.0,12500.0 -> 1: (12000,1500;12000,4500;12500,4500;12500,1500) props={net=>net1} - 12000.0,12500.0 -> 3: (12000,-11;12000,4500;12500,4500;12500,-11) props={net=>net1} - 12500.0,14500.0 -> 0: (12500,-11;12500,0;14500,0;14500,-11) props={net=>net1} - 12500.0,14500.0 -> 1: (12500,1500;12500,4500;14500,4500;14500,1500) props={net=>net1} - 12500.0,14500.0 -> 2: (12500,2000;12500,4000;14500,4000;14500,2000) props={net=>net1} - 12500.0,14500.0 -> 3: (12500,-11;12500,4500;14500,4500;14500,-11) props={net=>net1} - 14500.0,15000.0 -> 0: (14500,-11;14500,0;15000,0;15000,-11) props={net=>net1} - 14500.0,15000.0 -> 1: (14500,1500;14500,4500;15000,4500;15000,1500) props={net=>net1} - 14500.0,15000.0 -> 3: (14500,-11;14500,4500;15000,4500;15000,-11) props={net=>net1} - Edge: (-9500,15000;0,15000) props={net=>net1} - -1.0,0.0 -> 1: (-1,1500;-1,5000;0,5000;0,1500) props={net=>net3} - -1.0,0.0 -> 3: (-1,-11;-1,0;0,0;0,-11) props={net=>net1} - 0.0,2500.0 -> 0: (0,-11;0,0;2500,0;2500,-11) props={net=>net1} - 0.0,2500.0 -> 1: (0,1500;0,5000;2500,5000;2500,1500) props={net=>net3} - 0.0,2500.0 -> 3: (0,-11;0,0;2500,0;2500,-11) props={net=>net1} - 2500.0,3000.0 -> 0: (2500,-11;2500,0;3000,0;3000,-11) props={net=>net1} - 2500.0,3000.0 -> 1: (2500,1500;2500,5000;3000,5000;3000,1500) props={net=>net3} - 2500.0,3000.0 -> 3: (2500,-11;2500,0;3000,0;3000,-11) props={net=>net1}/(2500,1500;2500,5000;3000,5000;3000,1500) props={net=>net2} - 3000.0,9500.0 -> 0: (3000,-11;3000,0;9500,0;9500,-11) props={net=>net1} - 3000.0,9500.0 -> 1: (3000,1500;3000,5000;9500,5000;9500,1500) props={net=>net3} - 3000.0,9500.0 -> 3: (3000,1500;3000,5000;9500,5000;9500,1500) props={net=>net2} - 9500.0,9501.0 -> 3: (9500,1500;9500,5000;9501,5000;9501,1500) props={net=>net2} - Edge: (0,0;-5000,0) props={net=>net1} - -1.0,0.0 -> 1: (-1,1500;-1,5500;0,5500;0,1500) props={net=>net2} - -1.0,0.0 -> 3: (-1,2000;-1,5000;0,5000;0,2000) props={net=>net2} - 0.0,3000.0 -> 0: (0,-11;0,0;3000,0;3000,-11) props={net=>net1} - 0.0,3000.0 -> 1: (0,1500;0,5500;3000,5500;3000,1500) props={net=>net2} - 0.0,3000.0 -> 3: (0,2000;0,5000;3000,5000;3000,2000) props={net=>net2} - 3000.0,5000.0 -> 0: (3000,-11;3000,0;5000,0;5000,-11) props={net=>net1} - 3000.0,5000.0 -> 1: (3000,1500;3000,5500;5000,5500;5000,1500) props={net=>net2} - 5000.0,5001.0 -> 1: (5000,1500;5000,5500;5001,5500;5001,1500) props={net=>net2} - Edge: (0,15000;0,0) props={net=>net1} - -1.0,0.0 -> 3: (-1,1500;-1,4500;0,4500;0,1500) props={net=>net2} - 0.0,15000.0 -> 0: (0,-11;0,0;15000,0;15000,-11) props={net=>net1} - 0.0,15000.0 -> 3: (0,1500;0,4500;15000,4500;15000,1500) props={net=>net2} - 15000.0,15001.0 -> 3: (15000,1500;15000,4500;15001,4500;15001,1500) props={net=>net2} +Polygon: (-14000,0;-14000,15000;-11000,15000;-11000,0) props={'net'=>'net1'} + Edge: (-11000,0;-14000,0) props={'net'=>'net1'} + 0.0,3000.0 -> 0: (0,-11;0,0;3000,0;3000,-11) props={'net'=>'net1'} + Edge: (-11000,15000;-11000,0) props={'net'=>'net1'} + 0.0,500.0 -> 0: (0,-11;0,0;500,0;500,-11) props={'net'=>'net1'} + 0.0,500.0 -> 1: (0,1500;0,6001;500,6001;500,1500) props={'net'=>'net1'} + 0.0,500.0 -> 3: (0,-11;0,4500;500,4500;500,-11) props={'net'=>'net1'} + 500.0,2500.0 -> 0: (500,-11;500,0;2500,0;2500,-11) props={'net'=>'net1'} + 500.0,2500.0 -> 1: (500,1500;500,6001;2500,6001;2500,1500) props={'net'=>'net1'} + 500.0,2500.0 -> 2: (500,2000;500,4000;2500,4000;2500,2000) props={'net'=>'net1'} + 500.0,2500.0 -> 3: (500,-11;500,4500;2500,4500;2500,-11) props={'net'=>'net1'} + 2500.0,3000.0 -> 0: (2500,-11;2500,0;3000,0;3000,-11) props={'net'=>'net1'} + 2500.0,3000.0 -> 1: (2500,1500;2500,6001;3000,6001;3000,1500) props={'net'=>'net1'} + 2500.0,3000.0 -> 3: (2500,-11;2500,4500;3000,4500;3000,-11) props={'net'=>'net1'} + 3000.0,8500.0 -> 0: (3000,-11;3000,0;8500,0;8500,-11) props={'net'=>'net1'} + 3000.0,8500.0 -> 1: (3000,1500;3000,4500;8500,4500;8500,1500) props={'net'=>'net1'}/(3000,6000;3000,6001;8500,6001;8500,6000) props={'net'=>'net1'} + 3000.0,8500.0 -> 3: (3000,-11;3000,0;8500,0;8500,-11) props={'net'=>'net1'} + 8500.0,15000.0 -> 0: (8500,-11;8500,0;15000,0;15000,-11) props={'net'=>'net1'} + 8500.0,15000.0 -> 1: (8500,1500;8500,4500;15000,4500;15000,1500) props={'net'=>'net1'}/(8500,6000;8500,6001;15000,6001;15000,6000) props={'net'=>'net1'} + Edge: (-14000,0;-14000,15000) props={'net'=>'net1'} + 0.0,6500.0 -> 0: (0,-11;0,0;6500,0;6500,-11) props={'net'=>'net1'} + 6500.0,15000.0 -> 0: (6500,-11;6500,0;15000,0;15000,-11) props={'net'=>'net1'} + 6500.0,15000.0 -> 3: (6500,-11;6500,0;15000,0;15000,-11) props={'net'=>'net1'} + Edge: (-14000,15000;-11000,15000) props={'net'=>'net1'} + 0.0,3000.0 -> 0: (0,-11;0,0;3000,0;3000,-11) props={'net'=>'net1'} + 0.0,3000.0 -> 1: (0,1500;0,5000;3000,5000;3000,1500) props={'net'=>'net3'} + 0.0,3000.0 -> 3: (0,-11;0,0;3000,0;3000,-11) props={'net'=>'net1'} + 3000.0,3001.0 -> 1: (3000,1500;3000,5000;3001,5000;3001,1500) props={'net'=>'net3'} + 3000.0,3001.0 -> 3: (3000,-11;3000,0;3001,0;3001,-11) props={'net'=>'net1'} +Polygon: (-14000,16500;-14000,20000;0,20000;0,16500) props={'net'=>'net3'} + Edge: (-14000,16500;-14000,20000) props={'net'=>'net3'} + 0.0,3500.0 -> 0: (0,-11;0,0;3500,0;3500,-11) props={'net'=>'net3'} + Edge: (-14000,20000;0,20000) props={'net'=>'net3'} + 0.0,7000.0 -> 0: (0,-11;0,0;7000,0;7000,-11) props={'net'=>'net3'} + 7000.0,14000.0 -> 0: (7000,-11;7000,0;14000,0;14000,-11) props={'net'=>'net3'} + 7000.0,14000.0 -> 3: (7000,-11;7000,0;14000,0;14000,-11) props={'net'=>'net2'} + 14000.0,14001.0 -> 3: (14000,-11;14000,0;14001,0;14001,-11) props={'net'=>'net2'} + Edge: (0,16500;-14000,16500) props={'net'=>'net3'} + -1.0,0.0 -> 3: (-1,-11;-1,0;0,0;0,-11) props={'net'=>'net2'} + 0.0,5000.0 -> 0: (0,-11;0,0;5000,0;5000,-11) props={'net'=>'net3'} + 0.0,5000.0 -> 1: (0,1500;0,6001;5000,6001;5000,1500) props={'net'=>'net1'} + 0.0,5000.0 -> 3: (0,-11;0,0;5000,0;5000,-11) props={'net'=>'net2'} + 5000.0,6500.0 -> 0: (5000,-11;5000,0;6500,0;6500,-11) props={'net'=>'net3'} + 5000.0,6500.0 -> 1: (5000,1500;5000,4500;6500,4500;6500,1500) props={'net'=>'net1'} + 5000.0,6500.0 -> 3: (5000,-11;5000,0;6500,0;6500,-11) props={'net'=>'net2'} + 6500.0,7000.0 -> 0: (6500,-11;6500,0;7000,0;7000,-11) props={'net'=>'net3'} + 6500.0,7000.0 -> 1: (6500,1500;6500,6001;7000,6001;7000,1500) props={'net'=>'net1'} + 6500.0,7000.0 -> 3: (6500,-11;6500,0;7000,0;7000,-11) props={'net'=>'net2'}/(6500,1500;6500,4500;7000,4500;7000,1500) props={'net'=>'net1'} + 7000.0,9000.0 -> 0: (7000,-11;7000,0;9000,0;9000,-11) props={'net'=>'net3'} + 7000.0,9000.0 -> 1: (7000,1500;7000,6001;9000,6001;9000,1500) props={'net'=>'net1'} + 7000.0,9000.0 -> 2: (7000,2000;7000,4000;9000,4000;9000,2000) props={'net'=>'net1'} + 7000.0,9000.0 -> 3: (7000,1500;7000,4500;9000,4500;9000,1500) props={'net'=>'net1'} + 9000.0,9500.0 -> 0: (9000,-11;9000,0;9500,0;9500,-11) props={'net'=>'net3'} + 9000.0,9500.0 -> 1: (9000,1500;9000,6001;9500,6001;9500,1500) props={'net'=>'net1'} + 9000.0,9500.0 -> 3: (9000,1500;9000,4500;9500,4500;9500,1500) props={'net'=>'net1'} + 9500.0,11000.0 -> 0: (9500,-11;9500,0;11000,0;11000,-11) props={'net'=>'net3'} + 9500.0,11000.0 -> 3: (9500,1500;9500,4500;11000,4500;11000,1500) props={'net'=>'net1'} + 11000.0,11500.0 -> 0: (11000,-11;11000,0;11500,0;11500,-11) props={'net'=>'net3'} + 11000.0,11500.0 -> 1: (11000,1500;11000,6001;11500,6001;11500,1500) props={'net'=>'net1'} + 11000.0,11500.0 -> 3: (11000,1500;11000,6001;11500,6001;11500,1500) props={'net'=>'net1'} + 11500.0,13500.0 -> 0: (11500,-11;11500,0;13500,0;13500,-11) props={'net'=>'net3'} + 11500.0,13500.0 -> 1: (11500,1500;11500,6001;13500,6001;13500,1500) props={'net'=>'net1'} + 11500.0,13500.0 -> 2: (11500,2000;11500,4000;13500,4000;13500,2000) props={'net'=>'net1'} + 11500.0,13500.0 -> 3: (11500,1500;11500,6001;13500,6001;13500,1500) props={'net'=>'net1'} + 13500.0,14000.0 -> 0: (13500,-11;13500,0;14000,0;14000,-11) props={'net'=>'net3'} + 13500.0,14000.0 -> 1: (13500,1500;13500,6001;14000,6001;14000,1500) props={'net'=>'net1'} + 13500.0,14000.0 -> 3: (13500,1500;13500,6001;14000,6001;14000,1500) props={'net'=>'net1'} + Edge: (0,20000;0,16500) props={'net'=>'net3'} + 0.0,3500.0 -> 0: (0,-11;0,0;3500,0;3500,-11) props={'net'=>'net3'} + 0.0,3500.0 -> 3: (0,-11;0,4500;3500,4500;3500,-11) props={'net'=>'net2'} + 3500.0,3501.0 -> 3: (3500,1500;3500,4500;3501,4500;3501,1500) props={'net'=>'net2'} +Polygon: (-9500,-5500;-9500,-1500;5000,-1500;5000,-5500) props={'net'=>'net2'} + Edge: (-9500,-1500;5000,-1500) props={'net'=>'net2'} + 0.0,3000.0 -> 0: (0,-11;0,0;3000,0;3000,-11) props={'net'=>'net2'} + 0.0,3000.0 -> 1: (0,1500;0,6001;3000,6001;3000,1500) props={'net'=>'net1'} + 3000.0,4500.0 -> 0: (3000,-11;3000,0;4500,0;4500,-11) props={'net'=>'net2'} + 4500.0,9500.0 -> 0: (4500,-11;4500,0;9500,0;9500,-11) props={'net'=>'net2'} + 4500.0,9500.0 -> 1: (4500,1500;4500,6001;9500,6001;9500,1500) props={'net'=>'net1'} + 9500.0,11000.0 -> 0: (9500,-11;9500,0;11000,0;11000,-11) props={'net'=>'net2'} + 11000.0,14000.0 -> 0: (11000,-11;11000,0;14000,0;14000,-11) props={'net'=>'net2'} + 11000.0,14000.0 -> 3: (11000,-11;11000,6001;14000,6001;14000,-11) props={'net'=>'net2'} + 14000.0,14500.0 -> 0: (14000,-11;14000,0;14500,0;14500,-11) props={'net'=>'net2'} + Edge: (-9500,-5500;-9500,-1500) props={'net'=>'net2'} + 0.0,4000.0 -> 0: (0,-11;0,0;4000,0;4000,-11) props={'net'=>'net2'} + Edge: (5000,-1500;5000,-5500) props={'net'=>'net2'} + 0.0,4000.0 -> 0: (0,-11;0,0;4000,0;4000,-11) props={'net'=>'net2'} + Edge: (5000,-5500;-9500,-5500) props={'net'=>'net2'} + 0.0,14500.0 -> 0: (0,-11;0,0;14500,0;14500,-11) props={'net'=>'net2'} +Polygon: (-9500,0;-9500,15000;0,15000;0,0;-5000,0;-5000,12000;-6500,12000;-6500,0) props={'net'=>'net1'} + Edge: (-5000,0;-5000,12000) props={'net'=>'net1'} + 0.0,6500.0 -> 0: (0,-11;0,0;6500,0;6500,-11) props={'net'=>'net1'}/(0,1500;0,4500;6500,4500;6500,1500) props={'net'=>'net1'} + 0.0,6500.0 -> 1: (0,6000;0,6001;6500,6001;6500,6000) props={'net'=>'net1'} + 6500.0,12000.0 -> 0: (6500,-11;6500,0;12000,0;12000,-11) props={'net'=>'net1'}/(6500,1500;6500,4500;12000,4500;12000,1500) props={'net'=>'net1'} + 6500.0,12000.0 -> 1: (6500,6000;6500,6001;12000,6001;12000,6000) props={'net'=>'net1'} + 6500.0,12000.0 -> 3: (6500,6000;6500,6001;12000,6001;12000,6000) props={'net'=>'net1'} + 12000.0,12001.0 -> 0: (12000,-11;12000,4500;12001,4500;12001,-11) props={'net'=>'net1'} + 12000.0,12001.0 -> 1: (12000,6000;12000,6001;12001,6001;12001,6000) props={'net'=>'net1'} + 12000.0,12001.0 -> 3: (12000,1500;12000,6001;12001,6001;12001,1500) props={'net'=>'net1'} + Edge: (-5000,12000;-6500,12000) props={'net'=>'net1'} + -1.0,0.0 -> 0: (-1,-11;-1,6001;0,6001;0,-11) props={'net'=>'net1'} + 0.0,1500.0 -> 0: (0,-11;0,0;1500,0;1500,-11) props={'net'=>'net1'} + 1500.0,1501.0 -> 0: (1500,-11;1500,6001;1501,6001;1501,-11) props={'net'=>'net1'} + 1500.0,1501.0 -> 3: (1500,-11;1500,0;1501,0;1501,-11) props={'net'=>'net1'} + Edge: (-6500,0;-9500,0) props={'net'=>'net1'} + -1.0,0.0 -> 1: (-1,1500;-1,5500;0,5500;0,1500) props={'net'=>'net2'} + 0.0,3000.0 -> 0: (0,-11;0,0;3000,0;3000,-11) props={'net'=>'net1'} + 0.0,3000.0 -> 1: (0,1500;0,5500;3000,5500;3000,1500) props={'net'=>'net2'} + Edge: (-6500,12000;-6500,0) props={'net'=>'net1'} + -1.0,0.0 -> 0: (-1,-11;-1,6001;0,6001;0,-11) props={'net'=>'net1'} + -1.0,0.0 -> 3: (-1,-11;-1,0;0,0;0,-11) props={'net'=>'net1'} + 0.0,12000.0 -> 0: (0,-11;0,0;12000,0;12000,-11) props={'net'=>'net1'}/(0,1500;0,6001;12000,6001;12000,1500) props={'net'=>'net1'} + Edge: (-9500,0;-9500,15000) props={'net'=>'net1'} + 0.0,6500.0 -> 0: (0,-11;0,0;6500,0;6500,-11) props={'net'=>'net1'} + 0.0,6500.0 -> 1: (0,1500;0,4500;6500,4500;6500,1500) props={'net'=>'net1'} + 6500.0,12000.0 -> 0: (6500,-11;6500,0;12000,0;12000,-11) props={'net'=>'net1'} + 6500.0,12000.0 -> 1: (6500,1500;6500,4500;12000,4500;12000,1500) props={'net'=>'net1'} + 6500.0,12000.0 -> 3: (6500,1500;6500,4500;12000,4500;12000,1500) props={'net'=>'net1'} + 12000.0,12500.0 -> 0: (12000,-11;12000,0;12500,0;12500,-11) props={'net'=>'net1'} + 12000.0,12500.0 -> 1: (12000,1500;12000,4500;12500,4500;12500,1500) props={'net'=>'net1'} + 12000.0,12500.0 -> 3: (12000,-11;12000,4500;12500,4500;12500,-11) props={'net'=>'net1'} + 12500.0,14500.0 -> 0: (12500,-11;12500,0;14500,0;14500,-11) props={'net'=>'net1'} + 12500.0,14500.0 -> 1: (12500,1500;12500,4500;14500,4500;14500,1500) props={'net'=>'net1'} + 12500.0,14500.0 -> 2: (12500,2000;12500,4000;14500,4000;14500,2000) props={'net'=>'net1'} + 12500.0,14500.0 -> 3: (12500,-11;12500,4500;14500,4500;14500,-11) props={'net'=>'net1'} + 14500.0,15000.0 -> 0: (14500,-11;14500,0;15000,0;15000,-11) props={'net'=>'net1'} + 14500.0,15000.0 -> 1: (14500,1500;14500,4500;15000,4500;15000,1500) props={'net'=>'net1'} + 14500.0,15000.0 -> 3: (14500,-11;14500,4500;15000,4500;15000,-11) props={'net'=>'net1'} + Edge: (-9500,15000;0,15000) props={'net'=>'net1'} + -1.0,0.0 -> 1: (-1,1500;-1,5000;0,5000;0,1500) props={'net'=>'net3'} + -1.0,0.0 -> 3: (-1,-11;-1,0;0,0;0,-11) props={'net'=>'net1'} + 0.0,2500.0 -> 0: (0,-11;0,0;2500,0;2500,-11) props={'net'=>'net1'} + 0.0,2500.0 -> 1: (0,1500;0,5000;2500,5000;2500,1500) props={'net'=>'net3'} + 0.0,2500.0 -> 3: (0,-11;0,0;2500,0;2500,-11) props={'net'=>'net1'} + 2500.0,3000.0 -> 0: (2500,-11;2500,0;3000,0;3000,-11) props={'net'=>'net1'} + 2500.0,3000.0 -> 1: (2500,1500;2500,5000;3000,5000;3000,1500) props={'net'=>'net3'} + 2500.0,3000.0 -> 3: (2500,-11;2500,0;3000,0;3000,-11) props={'net'=>'net1'}/(2500,1500;2500,5000;3000,5000;3000,1500) props={'net'=>'net2'} + 3000.0,9500.0 -> 0: (3000,-11;3000,0;9500,0;9500,-11) props={'net'=>'net1'} + 3000.0,9500.0 -> 1: (3000,1500;3000,5000;9500,5000;9500,1500) props={'net'=>'net3'} + 3000.0,9500.0 -> 3: (3000,1500;3000,5000;9500,5000;9500,1500) props={'net'=>'net2'} + 9500.0,9501.0 -> 3: (9500,1500;9500,5000;9501,5000;9501,1500) props={'net'=>'net2'} + Edge: (0,0;-5000,0) props={'net'=>'net1'} + -1.0,0.0 -> 1: (-1,1500;-1,5500;0,5500;0,1500) props={'net'=>'net2'} + -1.0,0.0 -> 3: (-1,2000;-1,5000;0,5000;0,2000) props={'net'=>'net2'} + 0.0,3000.0 -> 0: (0,-11;0,0;3000,0;3000,-11) props={'net'=>'net1'} + 0.0,3000.0 -> 1: (0,1500;0,5500;3000,5500;3000,1500) props={'net'=>'net2'} + 0.0,3000.0 -> 3: (0,2000;0,5000;3000,5000;3000,2000) props={'net'=>'net2'} + 3000.0,5000.0 -> 0: (3000,-11;3000,0;5000,0;5000,-11) props={'net'=>'net1'} + 3000.0,5000.0 -> 1: (3000,1500;3000,5500;5000,5500;5000,1500) props={'net'=>'net2'} + 5000.0,5001.0 -> 1: (5000,1500;5000,5500;5001,5500;5001,1500) props={'net'=>'net2'} + Edge: (0,15000;0,0) props={'net'=>'net1'} + -1.0,0.0 -> 3: (-1,1500;-1,4500;0,4500;0,1500) props={'net'=>'net2'} + 0.0,15000.0 -> 0: (0,-11;0,0;15000,0;15000,-11) props={'net'=>'net1'} + 0.0,15000.0 -> 3: (0,1500;0,4500;15000,4500;15000,1500) props={'net'=>'net2'} + 15000.0,15001.0 -> 3: (15000,1500;15000,4500;15001,4500;15001,1500) props={'net'=>'net2'} """) diff --git a/testdata/ruby/dbBoxTest.rb b/testdata/ruby/dbBoxTest.rb index 40c11e141f..3a4e023a2b 100644 --- a/testdata/ruby/dbBoxTest.rb +++ b/testdata/ruby/dbBoxTest.rb @@ -520,16 +520,16 @@ def test_boxWithProperties assert_equal(s.to_s, "() props={}") s = RBA::BoxWithProperties::new(RBA::Box::new(0, 0, 100, 200), { 1 => "one" }) - assert_equal(s.to_s, "(0,0;100,200) props={1=>one}") + assert_equal(s.to_s, "(0,0;100,200) props={#1=>'one'}") pid = RBA::Layout::properties_id({ 1 => "one" }) s = RBA::BoxWithProperties::new(RBA::Box::new(0, 0, 100, 200), pid) - assert_equal(s.to_s, "(0,0;100,200) props={1=>one}") - assert_equal((RBA::CplxTrans::new(0.001) * s).to_s, "(0,0;0.1,0.2) props={1=>one}") + assert_equal(s.to_s, "(0,0;100,200) props={#1=>'one'}") + assert_equal((RBA::CplxTrans::new(0.001) * s).to_s, "(0,0;0.1,0.2) props={#1=>'one'}") assert_equal(s.property(1), "one") assert_equal(s.properties, { 1 => "one" }) s.set_property(1, "xxx") - assert_equal(s.to_s, "(0,0;100,200) props={1=>xxx}") + assert_equal(s.to_s, "(0,0;100,200) props={#1=>'xxx'}") s.delete_property(1) assert_equal(s.to_s, "(0,0;100,200) props={}") assert_equal(s.property(1), nil) @@ -538,34 +538,40 @@ def test_boxWithProperties assert_equal(s.to_s, "() props={}") s = RBA::DBoxWithProperties::new(RBA::DBox::new(0, 0, 100, 200), { 1 => "one" }) - assert_equal(s.to_s, "(0,0;100,200) props={1=>one}") + assert_equal(s.to_s, "(0,0;100,200) props={#1=>'one'}") pid = RBA::Layout::properties_id({ 1 => "one" }) s = RBA::DBoxWithProperties::new(RBA::DBox::new(0, 0, 100, 200), pid) - assert_equal(s.to_s, "(0,0;100,200) props={1=>one}") - assert_equal((RBA::VCplxTrans::new(2.5) * s).to_s, "(0,0;250,500) props={1=>one}") + assert_equal(s.to_s, "(0,0;100,200) props={#1=>'one'}") + assert_equal((RBA::VCplxTrans::new(2.5) * s).to_s, "(0,0;250,500) props={#1=>'one'}") assert_equal(s.property(1), "one") assert_equal(s.properties, { 1 => "one" }) s.set_property(1, "xxx") - assert_equal(s.to_s, "(0,0;100,200) props={1=>xxx}") + assert_equal(s.to_s, "(0,0;100,200) props={#1=>'xxx'}") s.delete_property(1) assert_equal(s.to_s, "(0,0;100,200) props={}") assert_equal(s.property(1), nil) # binary serialization - s = RBA::BoxWithProperties::new(RBA::Box::new(0, 0, 100, 200), {}) assert_equal(RBA::BoxWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) - s = RBA::BoxWithProperties::new(RBA::Box::new(0, 0, 100, 200), { 1 => "one", "key" => 17 }) assert_equal(RBA::BoxWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) - s = RBA::DBoxWithProperties::new(RBA::DBox::new(0, 0, 100, 200), {}) assert_equal(RBA::DBoxWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) - s = RBA::DBoxWithProperties::new(RBA::DBox::new(0, 0, 100, 200), { 1 => "one", "key" => 17 }) assert_equal(RBA::DBoxWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) + # string serialization + s = RBA::BoxWithProperties::new(RBA::Box::new(0, 0, 100, 200), {}) + assert_equal(RBA::BoxWithProperties::from_s(s.to_s).to_s, s.to_s) + s = RBA::BoxWithProperties::new(RBA::Box::new(0, 0, 100, 200), { 1 => "one", "key" => 17 }) + assert_equal(RBA::BoxWithProperties::from_s(s.to_s).to_s, s.to_s) + s = RBA::DBoxWithProperties::new(RBA::DBox::new(0, 0, 100, 200), {}) + assert_equal(RBA::DBoxWithProperties::from_s(s.to_s).to_s, s.to_s) + s = RBA::DBoxWithProperties::new(RBA::DBox::new(0, 0, 100, 200), { 1 => "one", "key" => 17 }) + assert_equal(RBA::DBoxWithProperties::from_s(s.to_s).to_s, s.to_s) + end end diff --git a/testdata/ruby/dbEdgeNeighborhood.rb b/testdata/ruby/dbEdgeNeighborhood.rb index 33255bdfca..da05a0b08e 100644 --- a/testdata/ruby/dbEdgeNeighborhood.rb +++ b/testdata/ruby/dbEdgeNeighborhood.rb @@ -123,15 +123,15 @@ def test_1 "edge = (-1100,0;-1100,1000) props={}\n" + "edge = (-1100,1000;-100,1000) props={}\n" + "edge = (-100,1000;-100,0) props={}\n" + - " 0.0,1000.0 -> 0: (0,100;0,101;1000,101;1000,100) props={1=>one}\n" + + " 0.0,1000.0 -> 0: (0,100;0,101;1000,101;1000,100) props={#1=>'one'}\n" + "edge = (-100,0;-1100,0) props={}\n" + "/Polygon\n" + - "Polygon: (0,0;0,1000;1000,1000;1000,0) props={1=>one}\n" + - "edge = (0,0;0,1000) props={1=>one}\n" + + "Polygon: (0,0;0,1000;1000,1000;1000,0) props={#1=>'one'}\n" + + "edge = (0,0;0,1000) props={#1=>'one'}\n" + " 0.0,1000.0 -> 0: (0,100;0,101;1000,101;1000,100) props={}\n" + - "edge = (0,1000;1000,1000) props={1=>one}\n" + - "edge = (1000,1000;1000,0) props={1=>one}\n" + - "edge = (1000,0;0,0) props={1=>one}\n" + + "edge = (0,1000;1000,1000) props={#1=>'one'}\n" + + "edge = (1000,1000;1000,0) props={#1=>'one'}\n" + + "edge = (1000,0;0,0) props={#1=>'one'}\n" + "/Polygon\n" ) diff --git a/testdata/ruby/dbEdgePairTest.rb b/testdata/ruby/dbEdgePairTest.rb index bfcfbe5b4d..71ee628287 100644 --- a/testdata/ruby/dbEdgePairTest.rb +++ b/testdata/ruby/dbEdgePairTest.rb @@ -258,16 +258,16 @@ def test_edgePairWithProperties assert_equal(s.to_s, "(0,0;0,0)/(0,0;0,0) props={}") s = RBA::EdgePairWithProperties::new(RBA::EdgePair::new(RBA::Edge::new(0, 0, 100, 200), RBA::Edge::new(10, 10, 110, 210)), { 1 => "one" }) - assert_equal(s.to_s, "(0,0;100,200)/(10,10;110,210) props={1=>one}") + assert_equal(s.to_s, "(0,0;100,200)/(10,10;110,210) props={#1=>'one'}") pid = RBA::Layout::properties_id({ 1 => "one" }) s = RBA::EdgePairWithProperties::new(RBA::EdgePair::new(RBA::Edge::new(0, 0, 100, 200), RBA::Edge::new(10, 10, 110, 210)), pid) - assert_equal(s.to_s, "(0,0;100,200)/(10,10;110,210) props={1=>one}") - assert_equal((RBA::CplxTrans::new(0.001) * s).to_s, "(0,0;0.1,0.2)/(0.01,0.01;0.11,0.21) props={1=>one}") + assert_equal(s.to_s, "(0,0;100,200)/(10,10;110,210) props={#1=>'one'}") + assert_equal((RBA::CplxTrans::new(0.001) * s).to_s, "(0,0;0.1,0.2)/(0.01,0.01;0.11,0.21) props={#1=>'one'}") assert_equal(s.property(1), "one") assert_equal(s.properties, { 1 => "one" }) s.set_property(1, "xxx") - assert_equal(s.to_s, "(0,0;100,200)/(10,10;110,210) props={1=>xxx}") + assert_equal(s.to_s, "(0,0;100,200)/(10,10;110,210) props={#1=>'xxx'}") s.delete_property(1) assert_equal(s.to_s, "(0,0;100,200)/(10,10;110,210) props={}") assert_equal(s.property(1), nil) @@ -276,16 +276,16 @@ def test_edgePairWithProperties assert_equal(s.to_s, "(0,0;0,0)/(0,0;0,0) props={}") s = RBA::DEdgePairWithProperties::new(RBA::DEdgePair::new(RBA::DEdge::new(0, 0, 100, 200), RBA::DEdge::new(10, 10, 110, 210)), { 1 => "one" }) - assert_equal(s.to_s, "(0,0;100,200)/(10,10;110,210) props={1=>one}") + assert_equal(s.to_s, "(0,0;100,200)/(10,10;110,210) props={#1=>'one'}") pid = RBA::Layout::properties_id({ 1 => "one" }) s = RBA::DEdgePairWithProperties::new(RBA::DEdgePair::new(RBA::DEdge::new(0, 0, 100, 200), RBA::DEdge::new(10, 10, 110, 210)), pid) - assert_equal(s.to_s, "(0,0;100,200)/(10,10;110,210) props={1=>one}") - assert_equal((RBA::VCplxTrans::new(2.5) * s).to_s, "(0,0;250,500)/(25,25;275,525) props={1=>one}") + assert_equal(s.to_s, "(0,0;100,200)/(10,10;110,210) props={#1=>'one'}") + assert_equal((RBA::VCplxTrans::new(2.5) * s).to_s, "(0,0;250,500)/(25,25;275,525) props={#1=>'one'}") assert_equal(s.property(1), "one") assert_equal(s.properties, { 1 => "one" }) s.set_property(1, "xxx") - assert_equal(s.to_s, "(0,0;100,200)/(10,10;110,210) props={1=>xxx}") + assert_equal(s.to_s, "(0,0;100,200)/(10,10;110,210) props={#1=>'xxx'}") s.delete_property(1) assert_equal(s.to_s, "(0,0;100,200)/(10,10;110,210) props={}") assert_equal(s.property(1), nil) diff --git a/testdata/ruby/dbEdgePairsTest.rb b/testdata/ruby/dbEdgePairsTest.rb index 36dd8f40e9..53e1b8a654 100644 --- a/testdata/ruby/dbEdgePairsTest.rb +++ b/testdata/ruby/dbEdgePairsTest.rb @@ -622,7 +622,7 @@ def test_props r = RBA::EdgePairs::new([ RBA::EdgePairWithProperties::new(RBA::EdgePair::new(RBA::Edge::new(0, 0, 100, 100), RBA::Edge::new(200, 300, 200, 500)), { 1 => "one" }) ]) assert_equal(r.to_s, "(0,0;100,100)/(200,300;200,500){1=>one}") - assert_equal(r[0].to_s, "(0,0;100,100)/(200,300;200,500) props={1=>one}") + assert_equal(r[0].to_s, "(0,0;100,100)/(200,300;200,500) props={#1=>'one'}") r = RBA::EdgePairs::new([]) assert_equal(r.to_s, "") @@ -638,7 +638,7 @@ def test_props r.insert(RBA::EdgePairWithProperties::new(RBA::EdgePair::new(RBA::Edge::new(0, 0, 100, 100), RBA::Edge::new(200, 300, 200, 500)), { 1 => "one" })) r.insert(RBA::EdgePair::new(RBA::Edge::new(0, 10, 100, 110), RBA::Edge::new(220, 300, 220, 500))) s = r.each.collect(&:to_s).join(";") - assert_equal(s, "(0,10;100,110)/(220,300;220,500) props={};(0,0;100,100)/(200,300;200,500) props={1=>one}") + assert_equal(s, "(0,10;100,110)/(220,300;220,500) props={};(0,0;100,100)/(200,300;200,500) props={#1=>'one'}") end diff --git a/testdata/ruby/dbEdgeTest.rb b/testdata/ruby/dbEdgeTest.rb index 3e6c8271cd..f229bac1a7 100644 --- a/testdata/ruby/dbEdgeTest.rb +++ b/testdata/ruby/dbEdgeTest.rb @@ -341,31 +341,31 @@ def test_edgeWithProperties assert_equal(s.to_s, "(0,0;0,0) props={}") s = RBA::EdgeWithProperties::new(RBA::Edge::new(0, 0, 100, 200), { 1 => "one" }) - assert_equal(s.to_s, "(0,0;100,200) props={1=>one}") + assert_equal(s.to_s, "(0,0;100,200) props={#1=>'one'}") pid = RBA::Layout::properties_id({ 1 => "one" }) s = RBA::EdgeWithProperties::new(RBA::Edge::new(0, 0, 100, 200), pid) - assert_equal(s.to_s, "(0,0;100,200) props={1=>one}") - assert_equal((RBA::CplxTrans::new(0.001) * s).to_s, "(0,0;0.1,0.2) props={1=>one}") - assert_equal(s.transformed(RBA::CplxTrans::new(0.001)).to_s, "(0,0;0.1,0.2) props={1=>one}") - assert_equal(s.transformed(RBA::ICplxTrans::new(2.5)).to_s, "(0,0;250,500) props={1=>one}") - assert_equal(s.transformed(RBA::Trans::R90).to_s, "(0,0;-200,100) props={1=>one}") + assert_equal(s.to_s, "(0,0;100,200) props={#1=>'one'}") + assert_equal((RBA::CplxTrans::new(0.001) * s).to_s, "(0,0;0.1,0.2) props={#1=>'one'}") + assert_equal(s.transformed(RBA::CplxTrans::new(0.001)).to_s, "(0,0;0.1,0.2) props={#1=>'one'}") + assert_equal(s.transformed(RBA::ICplxTrans::new(2.5)).to_s, "(0,0;250,500) props={#1=>'one'}") + assert_equal(s.transformed(RBA::Trans::R90).to_s, "(0,0;-200,100) props={#1=>'one'}") s2 = s.dup s2.transform(RBA::Trans::R90) - assert_equal(s2.to_s, "(0,0;-200,100) props={1=>one}") - assert_equal((s * 0.001).to_s, "(0,0;0.1,0.2) props={1=>one}") - assert_equal(s.moved(10, 20).to_s, "(10,20;110,220) props={1=>one}") - assert_equal(s.moved(RBA::Vector::new(10, 20)).to_s, "(10,20;110,220) props={1=>one}") + assert_equal(s2.to_s, "(0,0;-200,100) props={#1=>'one'}") + assert_equal((s * 0.001).to_s, "(0,0;0.1,0.2) props={#1=>'one'}") + assert_equal(s.moved(10, 20).to_s, "(10,20;110,220) props={#1=>'one'}") + assert_equal(s.moved(RBA::Vector::new(10, 20)).to_s, "(10,20;110,220) props={#1=>'one'}") s2 = s.dup s2.move(10, 20) - assert_equal(s2.to_s, "(10,20;110,220) props={1=>one}") + assert_equal(s2.to_s, "(10,20;110,220) props={#1=>'one'}") s2 = s.dup s2.move(RBA::Vector::new(10, 20)) - assert_equal(s2.to_s, "(10,20;110,220) props={1=>one}") + assert_equal(s2.to_s, "(10,20;110,220) props={#1=>'one'}") assert_equal(s.property(1), "one") assert_equal(s.properties, { 1 => "one" }) s.set_property(1, "xxx") - assert_equal(s.to_s, "(0,0;100,200) props={1=>xxx}") + assert_equal(s.to_s, "(0,0;100,200) props={#1=>'xxx'}") s.delete_property(1) assert_equal(s.to_s, "(0,0;100,200) props={}") assert_equal(s.property(1), nil) @@ -374,31 +374,31 @@ def test_edgeWithProperties assert_equal(s.to_s, "(0,0;0,0) props={}") s = RBA::DEdgeWithProperties::new(RBA::DEdge::new(0, 0, 100, 200), { 1 => "one" }) - assert_equal(s.to_s, "(0,0;100,200) props={1=>one}") + assert_equal(s.to_s, "(0,0;100,200) props={#1=>'one'}") pid = RBA::Layout::properties_id({ 1 => "one" }) s = RBA::DEdgeWithProperties::new(RBA::DEdge::new(0, 0, 100, 200), pid) - assert_equal(s.to_s, "(0,0;100,200) props={1=>one}") - assert_equal((RBA::VCplxTrans::new(2.5) * s).to_s, "(0,0;250,500) props={1=>one}") - assert_equal(s.transformed(RBA::DCplxTrans::new(0.001)).to_s, "(0,0;0.1,0.2) props={1=>one}") - assert_equal(s.transformed(RBA::VCplxTrans::new(2.5)).to_s, "(0,0;250,500) props={1=>one}") - assert_equal(s.transformed(RBA::DTrans::R90).to_s, "(0,0;-200,100) props={1=>one}") + assert_equal(s.to_s, "(0,0;100,200) props={#1=>'one'}") + assert_equal((RBA::VCplxTrans::new(2.5) * s).to_s, "(0,0;250,500) props={#1=>'one'}") + assert_equal(s.transformed(RBA::DCplxTrans::new(0.001)).to_s, "(0,0;0.1,0.2) props={#1=>'one'}") + assert_equal(s.transformed(RBA::VCplxTrans::new(2.5)).to_s, "(0,0;250,500) props={#1=>'one'}") + assert_equal(s.transformed(RBA::DTrans::R90).to_s, "(0,0;-200,100) props={#1=>'one'}") s2 = s.dup s2.transform(RBA::DTrans::R90) - assert_equal(s2.to_s, "(0,0;-200,100) props={1=>one}") - assert_equal((s * 0.001).to_s, "(0,0;0.1,0.2) props={1=>one}") - assert_equal(s.moved(10, 20).to_s, "(10,20;110,220) props={1=>one}") - assert_equal(s.moved(RBA::DVector::new(10, 20)).to_s, "(10,20;110,220) props={1=>one}") + assert_equal(s2.to_s, "(0,0;-200,100) props={#1=>'one'}") + assert_equal((s * 0.001).to_s, "(0,0;0.1,0.2) props={#1=>'one'}") + assert_equal(s.moved(10, 20).to_s, "(10,20;110,220) props={#1=>'one'}") + assert_equal(s.moved(RBA::DVector::new(10, 20)).to_s, "(10,20;110,220) props={#1=>'one'}") s2 = s.dup s2.move(10, 20) - assert_equal(s2.to_s, "(10,20;110,220) props={1=>one}") + assert_equal(s2.to_s, "(10,20;110,220) props={#1=>'one'}") s2 = s.dup s2.move(RBA::DVector::new(10, 20)) - assert_equal(s2.to_s, "(10,20;110,220) props={1=>one}") + assert_equal(s2.to_s, "(10,20;110,220) props={#1=>'one'}") assert_equal(s.property(1), "one") assert_equal(s.properties, { 1 => "one" }) s.set_property(1, "xxx") - assert_equal(s.to_s, "(0,0;100,200) props={1=>xxx}") + assert_equal(s.to_s, "(0,0;100,200) props={#1=>'xxx'}") s.delete_property(1) assert_equal(s.to_s, "(0,0;100,200) props={}") assert_equal(s.property(1), nil) diff --git a/testdata/ruby/dbEdgesTest.rb b/testdata/ruby/dbEdgesTest.rb index 47ccf01df1..50112c5cec 100644 --- a/testdata/ruby/dbEdgesTest.rb +++ b/testdata/ruby/dbEdgesTest.rb @@ -970,7 +970,7 @@ def test_props r = RBA::Edges::new([ RBA::EdgeWithProperties::new(RBA::Edge::new(0, 0, 100, 100), { 1 => "one" }) ]) assert_equal(r.to_s, "(0,0;100,100){1=>one}") - assert_equal(r[0].to_s, "(0,0;100,100) props={1=>one}") + assert_equal(r[0].to_s, "(0,0;100,100) props={#1=>'one'}") r = RBA::Edges::new([]) assert_equal(r.to_s, "") @@ -1040,15 +1040,15 @@ def test_props r.insert(RBA::EdgeWithProperties::new(RBA::Edge::new(0, 0, 100, 0), { 1 => "one" })) r.insert(RBA::Edge::new(10, 0, 110, 0)) s = r.each.collect(&:to_s).join(";") - assert_equal(s, "(10,0;110,0) props={};(0,0;100,0) props={1=>one}") + assert_equal(s, "(10,0;110,0) props={};(0,0;100,0) props={#1=>'one'}") s = r.each_merged.collect(&:to_s).join(";") - assert_equal(s, "(10,0;110,0) props={};(0,0;100,0) props={1=>one}") + assert_equal(s, "(10,0;110,0) props={};(0,0;100,0) props={#1=>'one'}") r = RBA::Edges::new r.insert(RBA::EdgeWithProperties::new(RBA::Edge::new(0, 0, 100, 0), { 1 => "one" })) r.insert(RBA::EdgeWithProperties::new(RBA::Edge::new(10, 0, 110, 0), { 1 => "one" })) s = r.each_merged.collect(&:to_s).join(";") - assert_equal(s, "(0,0;110,0) props={1=>one}") + assert_equal(s, "(0,0;110,0) props={#1=>'one'}") end diff --git a/testdata/ruby/dbPathTest.rb b/testdata/ruby/dbPathTest.rb index f3bd55e976..6d66860a8b 100644 --- a/testdata/ruby/dbPathTest.rb +++ b/testdata/ruby/dbPathTest.rb @@ -341,16 +341,16 @@ def test_pathWithProperties assert_equal(s.to_s, "() w=0 bx=0 ex=0 r=false props={}") s = RBA::PathWithProperties::new(RBA::Path::new([ [0,0], [100, 0] ], 100), { 1 => "one" }) - assert_equal(s.to_s, "(0,0;100,0) w=100 bx=0 ex=0 r=false props={1=>one}") + assert_equal(s.to_s, "(0,0;100,0) w=100 bx=0 ex=0 r=false props={#1=>'one'}") pid = RBA::Layout::properties_id({ 1 => "one" }) s = RBA::PathWithProperties::new(RBA::Path::new([ [0,0], [100, 0] ], 100), pid) - assert_equal(s.to_s, "(0,0;100,0) w=100 bx=0 ex=0 r=false props={1=>one}") - assert_equal((RBA::CplxTrans::new(0.001) * s).to_s, "(0,0;0.1,0) w=0.1 bx=0 ex=0 r=false props={1=>one}") + assert_equal(s.to_s, "(0,0;100,0) w=100 bx=0 ex=0 r=false props={#1=>'one'}") + assert_equal((RBA::CplxTrans::new(0.001) * s).to_s, "(0,0;0.1,0) w=0.1 bx=0 ex=0 r=false props={#1=>'one'}") assert_equal(s.property(1), "one") assert_equal(s.properties, { 1 => "one" }) s.set_property(1, "xxx") - assert_equal(s.to_s, "(0,0;100,0) w=100 bx=0 ex=0 r=false props={1=>xxx}") + assert_equal(s.to_s, "(0,0;100,0) w=100 bx=0 ex=0 r=false props={#1=>'xxx'}") s.delete_property(1) assert_equal(s.to_s, "(0,0;100,0) w=100 bx=0 ex=0 r=false props={}") assert_equal(s.property(1), nil) @@ -359,16 +359,16 @@ def test_pathWithProperties assert_equal(s.to_s, "() w=0 bx=0 ex=0 r=false props={}") s = RBA::DPathWithProperties::new(RBA::DPath::new([ [0,0], [100, 0] ], 100), { 1 => "one" }) - assert_equal(s.to_s, "(0,0;100,0) w=100 bx=0 ex=0 r=false props={1=>one}") + assert_equal(s.to_s, "(0,0;100,0) w=100 bx=0 ex=0 r=false props={#1=>'one'}") pid = RBA::Layout::properties_id({ 1 => "one" }) s = RBA::DPathWithProperties::new(RBA::DPath::new([ [0,0], [100, 0] ], 100), pid) - assert_equal(s.to_s, "(0,0;100,0) w=100 bx=0 ex=0 r=false props={1=>one}") - assert_equal((RBA::VCplxTrans::new(2.5) * s).to_s, "(0,0;250,0) w=250 bx=0 ex=0 r=false props={1=>one}") + assert_equal(s.to_s, "(0,0;100,0) w=100 bx=0 ex=0 r=false props={#1=>'one'}") + assert_equal((RBA::VCplxTrans::new(2.5) * s).to_s, "(0,0;250,0) w=250 bx=0 ex=0 r=false props={#1=>'one'}") assert_equal(s.property(1), "one") assert_equal(s.properties, { 1 => "one" }) s.set_property(1, "xxx") - assert_equal(s.to_s, "(0,0;100,0) w=100 bx=0 ex=0 r=false props={1=>xxx}") + assert_equal(s.to_s, "(0,0;100,0) w=100 bx=0 ex=0 r=false props={#1=>'xxx'}") s.delete_property(1) assert_equal(s.to_s, "(0,0;100,0) w=100 bx=0 ex=0 r=false props={}") assert_equal(s.property(1), nil) diff --git a/testdata/ruby/dbPolygonNeighborhood.rb b/testdata/ruby/dbPolygonNeighborhood.rb index 27f944f7ce..527a605440 100644 --- a/testdata/ruby/dbPolygonNeighborhood.rb +++ b/testdata/ruby/dbPolygonNeighborhood.rb @@ -122,8 +122,8 @@ def test_1 assert_equal(visitor.log, "Polygon: (-1100,0;-1100,1000;-100,1000;-100,0) props={}\n" + - " 0: (0,0;0,1000;1000,1000;1000,0) props={1=>one}\n" + - "Polygon: (0,0;0,1000;1000,1000;1000,0) props={1=>one}\n" + + " 0: (0,0;0,1000;1000,1000;1000,0) props={#1=>'one'}\n" + + "Polygon: (0,0;0,1000;1000,1000;1000,0) props={#1=>'one'}\n" + " 0: (-1100,0;-1100,1000;-100,1000;-100,0) props={}\n" ) diff --git a/testdata/ruby/dbPolygonTest.rb b/testdata/ruby/dbPolygonTest.rb index 422e32a49f..14e6f19833 100644 --- a/testdata/ruby/dbPolygonTest.rb +++ b/testdata/ruby/dbPolygonTest.rb @@ -906,16 +906,16 @@ def test_polygonWithProperties assert_equal(s.to_s, "() props={}") s = RBA::PolygonWithProperties::new(RBA::Polygon::new(RBA::Box::new(0, 0, 100, 200)), { 1 => "one" }) - assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={1=>one}") + assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={#1=>'one'}") pid = RBA::Layout::properties_id({ 1 => "one" }) s = RBA::PolygonWithProperties::new(RBA::Polygon::new(RBA::Box::new(0, 0, 100, 200)), pid) - assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={1=>one}") - assert_equal((RBA::CplxTrans::new(0.001) * s).to_s, "(0,0;0,0.2;0.1,0.2;0.1,0) props={1=>one}") + assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={#1=>'one'}") + assert_equal((RBA::CplxTrans::new(0.001) * s).to_s, "(0,0;0,0.2;0.1,0.2;0.1,0) props={#1=>'one'}") assert_equal(s.property(1), "one") assert_equal(s.properties, { 1 => "one" }) s.set_property(1, "xxx") - assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={1=>xxx}") + assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={#1=>'xxx'}") s.delete_property(1) assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={}") assert_equal(s.property(1), nil) @@ -928,16 +928,16 @@ def test_polygonWithProperties assert_equal(s.to_s, "() props={}") s = RBA::DPolygonWithProperties::new(RBA::DPolygon::new(RBA::DBox::new(0, 0, 100, 200)), { 1 => "one" }) - assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={1=>one}") + assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={#1=>'one'}") pid = RBA::Layout::properties_id({ 1 => "one" }) s = RBA::DPolygonWithProperties::new(RBA::DPolygon::new(RBA::DBox::new(0, 0, 100, 200)), pid) - assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={1=>one}") - assert_equal((RBA::VCplxTrans::new(2.5) * s).to_s, "(0,0;0,500;250,500;250,0) props={1=>one}") + assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={#1=>'one'}") + assert_equal((RBA::VCplxTrans::new(2.5) * s).to_s, "(0,0;0,500;250,500;250,0) props={#1=>'one'}") assert_equal(s.property(1), "one") assert_equal(s.properties, { 1 => "one" }) s.set_property(1, "xxx") - assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={1=>xxx}") + assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={#1=>'xxx'}") s.delete_property(1) assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={}") assert_equal(s.property(1), nil) @@ -950,16 +950,16 @@ def test_polygonWithProperties assert_equal(s.to_s, "() props={}") s = RBA::SimplePolygonWithProperties::new(RBA::SimplePolygon::new(RBA::Box::new(0, 0, 100, 200)), { 1 => "one" }) - assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={1=>one}") + assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={#1=>'one'}") pid = RBA::Layout::properties_id({ 1 => "one" }) s = RBA::SimplePolygonWithProperties::new(RBA::SimplePolygon::new(RBA::Box::new(0, 0, 100, 200)), pid) - assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={1=>one}") - assert_equal((RBA::CplxTrans::new(0.001) * s).to_s, "(0,0;0,0.2;0.1,0.2;0.1,0) props={1=>one}") + assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={#1=>'one'}") + assert_equal((RBA::CplxTrans::new(0.001) * s).to_s, "(0,0;0,0.2;0.1,0.2;0.1,0) props={#1=>'one'}") assert_equal(s.property(1), "one") assert_equal(s.properties, { 1 => "one" }) s.set_property(1, "xxx") - assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={1=>xxx}") + assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={#1=>'xxx'}") s.delete_property(1) assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={}") assert_equal(s.property(1), nil) @@ -972,16 +972,16 @@ def test_polygonWithProperties assert_equal(s.to_s, "() props={}") s = RBA::DSimplePolygonWithProperties::new(RBA::DSimplePolygon::new(RBA::DBox::new(0, 0, 100, 200)), { 1 => "one" }) - assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={1=>one}") + assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={#1=>'one'}") pid = RBA::Layout::properties_id({ 1 => "one" }) s = RBA::DSimplePolygonWithProperties::new(RBA::DSimplePolygon::new(RBA::DBox::new(0, 0, 100, 200)), pid) - assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={1=>one}") - assert_equal((RBA::VCplxTrans::new(2.5) * s).to_s, "(0,0;0,500;250,500;250,0) props={1=>one}") + assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={#1=>'one'}") + assert_equal((RBA::VCplxTrans::new(2.5) * s).to_s, "(0,0;0,500;250,500;250,0) props={#1=>'one'}") assert_equal(s.property(1), "one") assert_equal(s.properties, { 1 => "one" }) s.set_property(1, "xxx") - assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={1=>xxx}") + assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={#1=>'xxx'}") s.delete_property(1) assert_equal(s.to_s, "(0,0;0,200;100,200;100,0) props={}") assert_equal(s.property(1), nil) @@ -1008,6 +1008,24 @@ def test_polygonWithProperties s = RBA::DSimplePolygonWithProperties::new(RBA::DBox::new(0, 0, 100, 200), { 1 => "one", "key" => 17 }) assert_equal(RBA::DSimplePolygonWithProperties::from_bytes(s.to_bytes).to_s, s.to_s) + # string serialization + s = RBA::PolygonWithProperties::new(RBA::Box::new(0, 0, 100, 200), {}) + assert_equal(RBA::PolygonWithProperties::from_s(s.to_s).to_s, s.to_s) + s = RBA::PolygonWithProperties::new(RBA::Box::new(0, 0, 100, 200), { 1 => "one", "key" => 17 }) + assert_equal(RBA::PolygonWithProperties::from_s(s.to_s).to_s, s.to_s) + s = RBA::DPolygonWithProperties::new(RBA::DBox::new(0, 0, 100, 200), {}) + assert_equal(RBA::DPolygonWithProperties::from_s(s.to_s).to_s, s.to_s) + s = RBA::DPolygonWithProperties::new(RBA::DBox::new(0, 0, 100, 200), { 1 => "one", "key" => 17 }) + assert_equal(RBA::DPolygonWithProperties::from_s(s.to_s).to_s, s.to_s) + s = RBA::SimplePolygonWithProperties::new(RBA::Box::new(0, 0, 100, 200), {}) + assert_equal(RBA::SimplePolygonWithProperties::from_s(s.to_s).to_s, s.to_s) + s = RBA::SimplePolygonWithProperties::new(RBA::Box::new(0, 0, 100, 200), { 1 => "one", "key" => 17 }) + assert_equal(RBA::SimplePolygonWithProperties::from_s(s.to_s).to_s, s.to_s) + s = RBA::DSimplePolygonWithProperties::new(RBA::DBox::new(0, 0, 100, 200), {}) + assert_equal(RBA::DSimplePolygonWithProperties::from_s(s.to_s).to_s, s.to_s) + s = RBA::DSimplePolygonWithProperties::new(RBA::DBox::new(0, 0, 100, 200), { 1 => "one", "key" => 17 }) + assert_equal(RBA::DSimplePolygonWithProperties::from_s(s.to_s).to_s, s.to_s) + end def test_triangulation diff --git a/testdata/ruby/dbRegionTest.rb b/testdata/ruby/dbRegionTest.rb index 4324292572..9a76b89dba 100644 --- a/testdata/ruby/dbRegionTest.rb +++ b/testdata/ruby/dbRegionTest.rb @@ -235,7 +235,7 @@ def test_1 r.insert(RBA::PolygonWithProperties::new(RBA::Box::new(0, 0, 10, 20), { 1 => 'value' })) r.insert(RBA::Box::new(1, 2, 11, 22)) assert_equal(r[0].to_s, "(1,2;1,22;11,22;11,2) props={}") - assert_equal(r[1].to_s, "(0,0;0,20;10,20;10,0) props={1=>value}") + assert_equal(r[1].to_s, "(0,0;0,20;10,20;10,0) props={#1=>'value'}") r = RBA::Region::new(ly.begin_shapes(c1.cell_index, l2), "*") assert_equal(csort(r.to_s), csort("(-11,-21;-11,-19;-9,-19;-9,-21);(9,19;9,21;11,21;11,19);(-11,79;-11,81;-9,81;-9,79);(9,119;9,121;11,121;11,119);(189,79;189,81;191,81;191,79);(209,119;209,121;211,121;211,119)")) @@ -1635,20 +1635,20 @@ def test_props r.insert(RBA::BoxWithProperties::new(RBA::Box::new(0, 0, 100, 200), { 1 => "one" })) r.insert(RBA::Box::new(10, 20, 110, 220)) s = r.each.collect(&:to_s).join(";") - assert_equal(s, "(10,20;10,220;110,220;110,20) props={};(0,0;0,200;100,200;100,0) props={1=>one}") + assert_equal(s, "(10,20;10,220;110,220;110,20) props={};(0,0;0,200;100,200;100,0) props={#1=>'one'}") rr = r.dup rr.join_properties_on_merge = true assert_equal(rr.join_properties_on_merge, true) s = rr.each_merged.collect(&:to_s).join(";") - assert_equal(s, "(0,0;0,200;10,200;10,220;110,220;110,20;100,20;100,0) props={1=>one}") + assert_equal(s, "(0,0;0,200;10,200;10,220;110,220;110,20;100,20;100,0) props={#1=>'one'}") s = r.each_merged.collect(&:to_s).join(";") - assert_equal(s, "(10,20;10,220;110,220;110,20) props={};(0,0;0,200;100,200;100,0) props={1=>one}") + assert_equal(s, "(10,20;10,220;110,220;110,20) props={};(0,0;0,200;100,200;100,0) props={#1=>'one'}") r = RBA::Region::new r.insert(RBA::BoxWithProperties::new(RBA::Box::new(0, 0, 100, 200), { 1 => "one" })) r.insert(RBA::BoxWithProperties::new(RBA::Box::new(10, 20, 110, 220), { 1 => "one" })) s = r.each_merged.collect(&:to_s).join(";") - assert_equal(s, "(0,0;0,200;10,200;10,220;110,220;110,20;100,20;100,0) props={1=>one}") + assert_equal(s, "(0,0;0,200;10,200;10,220;110,220;110,20;100,20;100,0) props={#1=>'one'}") end diff --git a/testdata/ruby/dbTextTest.rb b/testdata/ruby/dbTextTest.rb index a05494ecd3..a253ab67c6 100644 --- a/testdata/ruby/dbTextTest.rb +++ b/testdata/ruby/dbTextTest.rb @@ -264,16 +264,16 @@ def test_textWithProperties assert_equal(s.to_s, "('',r0 0,0) props={}") s = RBA::TextWithProperties::new(RBA::Text::new("text", RBA::Trans::R90), { 1 => "one" }) - assert_equal(s.to_s, "('text',r90 0,0) props={1=>one}") + assert_equal(s.to_s, "('text',r90 0,0) props={#1=>'one'}") pid = RBA::Layout::properties_id({ 1 => "one" }) s = RBA::TextWithProperties::new(RBA::Text::new("text", RBA::Trans::R90), pid) - assert_equal(s.to_s, "('text',r90 0,0) props={1=>one}") - assert_equal((RBA::CplxTrans::new(0.001) * s).to_s, "('text',r90 0,0) props={1=>one}") + assert_equal(s.to_s, "('text',r90 0,0) props={#1=>'one'}") + assert_equal((RBA::CplxTrans::new(0.001) * s).to_s, "('text',r90 0,0) props={#1=>'one'}") assert_equal(s.property(1), "one") assert_equal(s.properties, { 1 => "one" }) s.set_property(1, "xxx") - assert_equal(s.to_s, "('text',r90 0,0) props={1=>xxx}") + assert_equal(s.to_s, "('text',r90 0,0) props={#1=>'xxx'}") s.delete_property(1) assert_equal(s.to_s, "('text',r90 0,0) props={}") assert_equal(s.property(1), nil) @@ -282,16 +282,16 @@ def test_textWithProperties assert_equal(s.to_s, "('',r0 0,0) props={}") s = RBA::DTextWithProperties::new(RBA::DText::new("text", RBA::Trans::R90), { 1 => "one" }) - assert_equal(s.to_s, "('text',r90 0,0) props={1=>one}") + assert_equal(s.to_s, "('text',r90 0,0) props={#1=>'one'}") pid = RBA::Layout::properties_id({ 1 => "one" }) s = RBA::DTextWithProperties::new(RBA::DText::new("text", RBA::Trans::R90), pid) - assert_equal(s.to_s, "('text',r90 0,0) props={1=>one}") - assert_equal((RBA::VCplxTrans::new(2.5) * s).to_s, "('text',r90 0,0) props={1=>one}") + assert_equal(s.to_s, "('text',r90 0,0) props={#1=>'one'}") + assert_equal((RBA::VCplxTrans::new(2.5) * s).to_s, "('text',r90 0,0) props={#1=>'one'}") assert_equal(s.property(1), "one") assert_equal(s.properties, { 1 => "one" }) s.set_property(1, "xxx") - assert_equal(s.to_s, "('text',r90 0,0) props={1=>xxx}") + assert_equal(s.to_s, "('text',r90 0,0) props={#1=>'xxx'}") s.delete_property(1) assert_equal(s.to_s, "('text',r90 0,0) props={}") assert_equal(s.property(1), nil) diff --git a/testdata/ruby/dbTextsTest.rb b/testdata/ruby/dbTextsTest.rb index 9c5eb20643..5a93366567 100644 --- a/testdata/ruby/dbTextsTest.rb +++ b/testdata/ruby/dbTextsTest.rb @@ -229,7 +229,7 @@ def test_3 r = RBA::Texts::new r.insert(RBA::TextWithProperties::new(RBA::Text::new("string", RBA::Trans::new), { 1 => "value" })) - assert_equal(r[0].to_s, "('string',r0 0,0) props={1=>value}") + assert_equal(r[0].to_s, "('string',r0 0,0) props={#1=>'value'}") dss = RBA::DeepShapeStore::new r = RBA::Texts::new(ly.begin_shapes(c1.cell_index, l1), dss) @@ -477,7 +477,7 @@ def test_props r.insert(RBA::TextWithProperties::new(RBA::Text::new("abc", RBA::Trans::new), { 1 => "one" })) r.insert(RBA::Text::new("xuv", RBA::Trans::new)) s = r.each.collect(&:to_s).join(";") - assert_equal(s, "('xuv',r0 0,0) props={};('abc',r0 0,0) props={1=>one}") + assert_equal(s, "('xuv',r0 0,0) props={};('abc',r0 0,0) props={#1=>'one'}") end From 485ec8a4135f1cf20c801c462913266fd9746775 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 7 May 2026 00:11:39 +0200 Subject: [PATCH 6/6] Fixing builds --- src/db/db/dbBinarySerialize.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/db/db/dbBinarySerialize.h b/src/db/db/dbBinarySerialize.h index 2898420efd..5512228eac 100644 --- a/src/db/db/dbBinarySerialize.h +++ b/src/db/db/dbBinarySerialize.h @@ -442,7 +442,7 @@ tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::disp_trans & db::vector d; read_binary (s, d); - t = db::disp_trans (d); + t = db::disp_trans (d); return s; } @@ -456,7 +456,7 @@ tl::BinaryInputStream &read_binary (tl::BinaryInputStream &s, db::simple_trans d; read_binary (s, d); - t = db::simple_trans (r, d); + t = db::simple_trans (r, d); return s; } @@ -513,7 +513,7 @@ tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::text &t) int32_t font, halign, valign; s >> font >> halign >> valign; - t = db::text (txt, tr, size, db::Font (font), db::HAlign (halign), db::VAlign (valign)); + t = db::text (txt, tr, size, db::Font (font), db::HAlign (halign), db::VAlign (valign)); return s; }