First implementation of to_bytes/from_bytes for Vector,Point,Box,Polygon,SimplePolygon,Trans,CplxTrans,Text,Path,Edge,EdgePair and variants

This commit is contained in:
Matthias Koefferlein 2026-05-02 23:21:35 +02:00
parent 5ccf6260f1
commit fdaa93d234
28 changed files with 1658 additions and 36 deletions

View File

@ -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 \

View File

@ -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 ..
}

View File

@ -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<class C>
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<class C>
tl::OutputStream &write_binary (tl::OutputStream &s, const db::point<C> &pt)
{
return write_coord (write_coord (s, pt.x ()), pt.y ());
}
template<class C>
tl::OutputStream &write_binary (tl::OutputStream &s, const db::vector<C> &v)
{
return write_coord (write_coord (s, v.x ()), v.y ());
}
template<class C>
tl::OutputStream &operator<< (tl::OutputStream &s, const db::point<C> &pt)
{
s << (uint16_t) 1; // version
return write_binary (s, pt);
}
template<class C>
tl::OutputStream &operator<< (tl::OutputStream &s, const db::vector<C> &v)
{
s << (uint16_t) 1; // version
return write_binary (s, v);
}
template<class C>
tl::OutputStream &write_binary (tl::OutputStream &s, const db::edge<C> &e)
{
write_binary (s, e.p1 ());
write_binary (s, e.p2 ());
return s;
}
template<class C>
tl::OutputStream &operator<< (tl::OutputStream &s, const db::edge<C> &e)
{
s << (uint16_t) 1; // version
return write_binary (s, e);
}
template<class C>
tl::OutputStream &operator<< (tl::OutputStream &s, const db::box<C> &b)
{
s << (uint16_t) 1; // version
write_binary (s, b.p1 ());
write_binary (s, b.p2 ());
return s;
}
template<class C>
tl::OutputStream &operator<< (tl::OutputStream &s, const db::edge_pair<C> &ep)
{
s << (uint16_t) 1; // version
write_binary (s, ep.first ());
write_binary (s, ep.second ());
return s;
}
template<class C>
tl::OutputStream &write_binary (tl::OutputStream &s, const db::polygon_contour<C> &c)
{
s << (uint64_t) c.size ();
for (auto i = c.begin (); i != c.end (); ++i) {
s << *i;
}
return s;
}
template<class C>
tl::OutputStream &operator<< (tl::OutputStream &s, const db::polygon<C> &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<class C>
tl::OutputStream &operator<< (tl::OutputStream &s, const db::simple_polygon<C> &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<class C>
tl::OutputStream &operator<< (tl::OutputStream &s, const db::unit_trans<C> &)
{
s << (uint16_t) 1; // version
return s;
}
template<class C>
tl::OutputStream &operator<< (tl::OutputStream &s, const db::disp_trans<C> &t)
{
s << (uint16_t) 1; // version
write_binary (s, t.disp ());
return s;
}
template<class C>
tl::OutputStream &write_binary (tl::OutputStream &s, const db::simple_trans<C> &t)
{
s << (uint16_t) t.rot ();
write_binary (s, t.disp ());
return s;
}
template<class C>
tl::OutputStream &operator<< (tl::OutputStream &s, const db::simple_trans<C> &t)
{
s << (uint16_t) 1; // version
return write_binary (s, t);
}
template<class C, class D, class R>
tl::OutputStream &operator<< (tl::OutputStream &s, const db::complex_trans<C, D, R> &t)
{
s << (uint16_t) 1; // version
write_binary (s, t.disp ());
return s << (double) t.msin () << (double) t.mcos () << (double) t.mag ();
}
template<class C>
tl::OutputStream &operator<< (tl::OutputStream &s, const db::text<C> &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<class C>
tl::OutputStream &operator<< (tl::OutputStream &s, const db::path<C> &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<class C>
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<class C>
tl::BinaryInputStream &read_binary (tl::BinaryInputStream &s, db::point<C> &pt)
{
C x = 0, y = 0;
read_coord (s, x);
read_coord (s, y);
pt = db::point<C> (x, y);
return s;
}
template<class C>
tl::BinaryInputStream &read_binary (tl::BinaryInputStream &s, db::vector<C> &v)
{
C x = 0, y = 0;
read_coord (s, x);
read_coord (s, y);
v = db::vector<C> (x, y);
return s;
}
template<class C>
tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::point<C> &pt)
{
uint16_t fmt = 0;
s >> fmt;
if (fmt > 1) {
throw FutureBinarySerializationFormatException ();
}
return read_binary (s, pt);
}
template<class C>
tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::vector<C> &v)
{
uint16_t fmt = 0;
s >> fmt;
if (fmt > 1) {
throw FutureBinarySerializationFormatException ();
}
return read_binary (s, v);
}
template<class C>
tl::BinaryInputStream &read_binary (tl::BinaryInputStream &s, db::edge<C> &v)
{
db::point<C> p1, p2;
read_binary (s, p1);
read_binary (s, p2);
v = db::edge<C> (p1, p2);
return s;
}
template<class C>
tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::edge<C> &e)
{
uint16_t fmt = 0;
s >> fmt;
if (fmt > 1) {
throw FutureBinarySerializationFormatException ();
}
return read_binary (s, e);
}
template<class C>
tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::box<C> &b)
{
uint16_t fmt = 0;
s >> fmt;
if (fmt > 1) {
throw FutureBinarySerializationFormatException ();
}
db::point<C> p1, p2;
read_binary (s, p1);
read_binary (s, p2);
b = db::box<C> (p1, p2);
return s;
}
template<class C>
tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::edge_pair<C> &ep)
{
uint16_t fmt = 0;
s >> fmt;
if (fmt > 1) {
throw FutureBinarySerializationFormatException ();
}
db::edge<C> e1, e2;
read_binary (s, e1);
read_binary (s, e2);
ep = db::edge_pair<C> (e1, e2);
return s;
}
template<class C>
tl::BinaryInputStream &read_binary (tl::BinaryInputStream &s, db::polygon_contour<C> &c)
{
uint64_t n = 0;
s >> n;
std::vector<db::point<C> > pts;
pts.reserve (n);
while (n-- > 0) {
pts.push_back (db::point<C> ());
read_binary (s, pts.back ());
}
// NOTE: not normalization or modification is applied
c.assign (pts.begin (), pts.end (), false, false, false);
return s;
}
template<class C>
tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::polygon<C> &p)
{
uint16_t fmt = 0;
s >> fmt;
if (fmt > 1) {
throw FutureBinarySerializationFormatException ();
}
uint64_t n = 0;
s >> n;
p = db::polygon<C> ();
db::polygon_contour<C> 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<class C>
tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::simple_polygon<C> &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<C> ctr;
read_binary (s, ctr);
p.assign_hull (ctr);
return s;
}
template<class C>
tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::unit_trans<C> &)
{
uint16_t fmt = 0;
s >> fmt;
if (fmt > 1) {
throw FutureBinarySerializationFormatException ();
}
return s;
}
template<class C>
tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::disp_trans<C> &t)
{
uint16_t fmt = 0;
s >> fmt;
if (fmt > 1) {
throw FutureBinarySerializationFormatException ();
}
db::vector<C> d;
read_binary (s, d);
t = db::disp_trans (d);
return s;
}
template<class C>
tl::BinaryInputStream &read_binary (tl::BinaryInputStream &s, db::simple_trans<C> &t)
{
uint16_t r = 0;
s >> r;
db::vector<C> d;
read_binary (s, d);
t = db::simple_trans (r, d);
return s;
}
template<class C>
tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::simple_trans<C> &t)
{
uint16_t fmt = 0;
s >> fmt;
if (fmt > 1) {
throw FutureBinarySerializationFormatException ();
}
return read_binary (s, t);
}
template<class C, class D, class R>
tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::complex_trans<C, D, R> &t)
{
uint16_t fmt = 0;
s >> fmt;
if (fmt > 1) {
throw FutureBinarySerializationFormatException ();
}
db::vector<R> d;
read_binary (s, d);
double asin, acos, mag;
s >> asin >> acos >> mag;
t = db::complex_trans<C, D, R> (d, asin, acos, mag);
return s;
}
template<class C>
tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::text<C> &t)
{
uint16_t fmt = 0;
s >> fmt;
if (fmt > 1) {
throw FutureBinarySerializationFormatException ();
}
std::string txt;
s >> txt;
db::simple_trans<C> 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<class C>
tl::BinaryInputStream &operator>> (tl::BinaryInputStream &s, db::path<C> &p)
{
uint16_t fmt = 0;
s >> fmt;
if (fmt > 1) {
throw FutureBinarySerializationFormatException ();
}
uint64_t n = 0;
s >> n;
std::vector<db::point<C> > pts;
pts.reserve (n);
while (n-- > 0) {
pts.push_back (db::point<C> ());
read_binary (s, pts.back ());
}
C width, bgn_ext, end_ext;
s >> width >> bgn_ext >> end_ext;
bool round;
s >> round;
p = db::path<C> (pts.begin (), pts.end (), width, bgn_ext, end_ext, round);
return s;
}
// -----------------------------------------------------------------------------------------
// Converters of objects to a binary string
template<class T>
std::vector<char> to_bytes (const T &t)
{
tl::OutputMemoryStream osm;
{
tl::OutputStream os (osm, false /*binary*/);
os << t;
}
return std::vector<char> (osm.data (), osm.data () + osm.size ());
}
template<class T>
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<class T>
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<class T>
void from_bytes (const std::vector<char> &s, T &t)
{
tl::InputMemoryStream ism (s.begin ().operator-> (), s.size ());
tl::InputStream is (ism);
tl::BinaryInputStream bis (is);
bis >> t;
}
}
#endif

View File

@ -1625,6 +1625,17 @@ public:
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<R> &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
*

View File

@ -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<char> &s)
{
std::unique_ptr<C> c (new C ());
db::from_bytes (s, *c);
return c.release ();
}
static std::vector<char> 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"
);
}
};

View File

@ -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<char> &s)
{
std::unique_ptr<C> c (new C ());
db::from_bytes (s, *c);
return c.release ();
}
static std::vector<char> 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"

View File

@ -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<char> &s)
{
std::unique_ptr<C> c (new C ());
db::from_bytes (s, *c);
return c.release ();
}
static std::vector<char> 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"
) +

View File

@ -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<char> &s)
{
std::unique_ptr<C> c (new C ());
db::from_bytes (s, *c);
return c.release ();
}
static std::vector<char> 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 "

View File

@ -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<char> &s)
{
std::unique_ptr<C> c (new C ());
db::from_bytes (s, *c);
return c.release ();
}
static std::vector<char> 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"
);
}

View File

@ -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<char> &s)
{
std::unique_ptr<C> c (new C ());
db::from_bytes (s, *c);
return c.release ();
}
static std::vector<char> 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<char> &s)
{
std::unique_ptr<C> c (new C ());
db::from_bytes (s, *c);
return c.release ();
}
static std::vector<char> 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"

View File

@ -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<char> &s)
{
std::unique_ptr<C> c (new C ());
db::from_bytes (s, *c);
return c.release ();
}
static std::vector<char> 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"
);
}
};

View File

@ -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<char> &s)
{
std::unique_ptr<C> c (new C ());
db::from_bytes (s, *c);
return c.release ();
}
static std::vector<char> 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<char> &s)
{
std::unique_ptr<C> c (new C ());
db::from_bytes (s, *c);
return c.release ();
}
static std::vector<char> 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"
) +

View File

@ -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<char> &s)
{
std::unique_ptr<C> c (new C ());
db::from_bytes (s, *c);
return c.release ();
}
static std::vector<char> 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"
);
}

View File

@ -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;

View File

View File

View File

@ -133,6 +133,15 @@ public:
{ }
};
class UnexpectedEndOfFileException
: public tl::Exception
{
public:
UnexpectedEndOfFileException (const std::string &f)
: tl::Exception (tl::to_string (tr ("Unexpected end of file: %s")), f)
{ }
};
// ---------------------------------------------------------------
class ZLibFilePrivate
@ -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<const double *> (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<const float *> (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<const uint16_t *> (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<const int16_t *> (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<const uint32_t *> (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<const int32_t *> (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<const uint64_t *> (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<const int64_t *> (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)
{

View File

@ -730,7 +730,7 @@ public:
}
/**
* @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 @@ public:
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 @@ public:
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 @@ public:
}
/**
* @brief Get the current line number
* @brief Gets the current line number
*/
size_t line_number ()
{
@ -780,7 +780,7 @@ public:
}
/**
* @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 @@ public:
}
/**
* @brief Reset to the initial position
* @brief Resets to the initial position
*/
void reset ();
@ -805,6 +805,69 @@ private:
// ---------------------------------------------------------------------------------
/**
* @brief A binary input stream
*
* This class is put in front of a InputStream to retrieve binary primitives from the stream.
* The binary format corresponds to binary mode of OutputStream.
*/
class TL_PUBLIC BinaryInputStream
{
public:
/**
* @brief Default constructor
*
* This constructor takes a delegate object.
*/
BinaryInputStream (InputStream &stream);
/**
* @brief Gets the raw stream
*/
InputStream &raw_stream ()
{
return m_stream;
}
/**
* @brief Get the source specification
*/
std::string source () const
{
return m_stream.source ();
}
/**
* @brief Gets a value of a specific type
*/
BinaryInputStream &operator>> (std::string &v);
BinaryInputStream &operator>> (double &v);
BinaryInputStream &operator>> (float &v);
BinaryInputStream &operator>> (bool &v);
BinaryInputStream &operator>> (uint8_t &v);
BinaryInputStream &operator>> (int8_t &v);
BinaryInputStream &operator>> (uint16_t &v);
BinaryInputStream &operator>> (int16_t &v);
BinaryInputStream &operator>> (uint32_t &v);
BinaryInputStream &operator>> (int32_t &v);
BinaryInputStream &operator>> (uint64_t &v);
BinaryInputStream &operator>> (int64_t &v);
/**
* @brief Resets to the initial position
*/
void reset ();
private:
InputStream &m_stream;
// no copying
BinaryInputStream (const BinaryInputStream &);
BinaryInputStream &operator= (const BinaryInputStream &);
};
// ---------------------------------------------------------------------------------
/**
* @brief The output stream delegate base class
*
@ -880,9 +943,9 @@ public:
/**
* @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 @@ public:
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 @@ public:
}
/**
* @brief << operator
* @brief << operator: inserts character
*/
OutputStream &operator<< (char s)
{
@ -1345,7 +1415,7 @@ public:
}
/**
* @brief << operator
* @brief << operator: inserts a character
*/
OutputStream &operator<< (unsigned char s)
{
@ -1354,30 +1424,48 @@ public:
}
/**
* @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 <class T>
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 @@ private:
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 &);

View File

@ -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);
}

View File

@ -41,6 +41,7 @@ class DBBox_TestClass < TestBase
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 @@ class DBBox_TestClass < TestBase
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

View File

@ -40,6 +40,9 @@ class DBEdgePair_TestClass < TestBase
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 @@ class DBEdgePair_TestClass < TestBase
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

View File

@ -36,6 +36,7 @@ class DBEdge_TestClass < TestBase
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 @@ class DBEdge_TestClass < TestBase
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)" )

View File

@ -33,6 +33,7 @@ class DBPath_TestClass < TestBase
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 @@ class DBPath_TestClass < TestBase
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 @@ class DBPath_TestClass < TestBase
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 @@ class DBPath_TestClass < TestBase
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 @@ class DBPath_TestClass < TestBase
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 @@ class DBPath_TestClass < TestBase
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

View File

@ -34,6 +34,7 @@ class DBPoint_TestClass < TestBase
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 @@ class DBPoint_TestClass < TestBase
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" )

View File

@ -31,6 +31,7 @@ class DBPolygon_TestClass < TestBase
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 @@ class DBPolygon_TestClass < TestBase
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 @@ class DBPolygon_TestClass < TestBase
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 @@ class DBPolygon_TestClass < TestBase
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 @@ class DBPolygon_TestClass < TestBase
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 @@ class DBPolygon_TestClass < TestBase
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 )

View File

@ -30,10 +30,12 @@ class DBText_TestClass < TestBase
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 @@ class DBText_TestClass < TestBase
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 @@ class DBText_TestClass < TestBase
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 )

View File

@ -38,6 +38,7 @@ class DBTrans_TestClass < TestBase
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 @@ class DBTrans_TestClass < TestBase
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 @@ class DBTrans_TestClass < TestBase
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 @@ class DBTrans_TestClass < TestBase
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 @@ class DBTrans_TestClass < TestBase
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 @@ class DBTrans_TestClass < TestBase
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 @@ class DBTrans_TestClass < TestBase
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 @@ class DBTrans_TestClass < TestBase
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 @@ class DBTrans_TestClass < TestBase
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)

View File

@ -34,6 +34,7 @@ class DBVector_TestClass < TestBase
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 @@ class DBVector_TestClass < TestBase
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" )