diff --git a/geometry.cpp b/geometry.cpp index 849948c..bee9195 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -37,10 +37,12 @@ drawvec decode_geometry(FILE *meta, std::atomic *geompos, int z, unsi while (1) { draw d; - if (!deserialize_byte_io(meta, &d.op, geompos)) { + signed char op; + if (!deserialize_byte_io(meta, &op, geompos)) { fprintf(stderr, "Internal error: Unexpected end of file in geometry\n"); exit(EXIT_FAILURE); } + d.op = op & VT_CLOSEPATH; if (d.op == VT_END) { break; } @@ -77,6 +79,13 @@ drawvec decode_geometry(FILE *meta, std::atomic *geompos, int z, unsi d.x = wwx; d.y = wwy; + + if (op & VT_NODE_3D) { + deserialize_double_io(meta, &d.elevation, geompos); + } + if (op & VT_NODE_ATTRIB) { + deserialize_string_io(meta, d.attributes, geompos); + } } out.push_back(d); diff --git a/geometry.hpp b/geometry.hpp index c2e11df..3cb1d68 100644 --- a/geometry.hpp +++ b/geometry.hpp @@ -15,6 +15,9 @@ #define VT_LINETO 2 #define VT_CLOSEPATH 7 +#define VT_NODE_3D 8 +#define VT_NODE_ATTRIB 16 + // The bitfield is to make sizeof(draw) be 16 instead of 24 // at the cost, apparently, of a 0.7% increase in running time // for packing and unpacking. diff --git a/serial.cpp b/serial.cpp index 6047be4..c74861d 100644 --- a/serial.cpp +++ b/serial.cpp @@ -30,6 +30,11 @@ size_t fwrite_check(const void *ptr, size_t size, size_t nitems, FILE *stream, c return w; } +void serialize_double(FILE *out, double n, std::atomic *fpos, const char *fname) { + fwrite_check(&n, sizeof(double), 1, out, fname); + *fpos += sizeof(double); +} + void serialize_int(FILE *out, int n, std::atomic *fpos, const char *fname) { serialize_long_long(out, n, fpos, fname); } @@ -72,6 +77,12 @@ void serialize_uint(FILE *out, unsigned n, std::atomic *fpos, const c *fpos += sizeof(unsigned); } +void serialize_string(FILE *out, std::string const &s, std::atomic *fpos, const char *fname) { + serialize_ulong_long(out, s.size(), fpos, fname); + fwrite_check(s.c_str(), sizeof(char), s.size(), out, fname); + *fpos += s.size(); +} + void deserialize_int(char **f, int *n) { long long ll; deserialize_long_long(f, &ll); @@ -112,6 +123,27 @@ void deserialize_byte(char **f, signed char *n) { *f += sizeof(signed char); } +int deserialize_double_io(FILE *f, double *n, std::atomic *geompos) { + if (fread(n, sizeof(double), 1, f) == 1) { + *geompos += sizeof(double); + return 1; + } + return 0; +} + +int deserialize_string_io(FILE *f, std::string &s, std::atomic *geompos) { + unsigned long long len; + if (deserialize_ulong_long_io(f, &len, geompos)) { + char tmp[len]; + if (fread(tmp, sizeof(char), len, f) == len) { + *geompos += len; + s = std::string(tmp, len); + return 1; + } + } + return 0; +} + int deserialize_long_long_io(FILE *f, long long *n, std::atomic *geompos) { unsigned long long zigzag = 0; int ret = deserialize_ulong_long_io(f, &zigzag, geompos); @@ -171,9 +203,25 @@ int deserialize_byte_io(FILE *f, signed char *n, std::atomic *geompos static void write_geometry(drawvec const &dv, std::atomic *fpos, FILE *out, const char *fname, long long wx, long long wy) { for (size_t i = 0; i < dv.size(); i++) { if (dv[i].op == VT_MOVETO || dv[i].op == VT_LINETO) { - serialize_byte(out, dv[i].op, fpos, fname); + int op = dv[i].op; + if (!isnan(dv[i].elevation)) { + op |= VT_NODE_3D; + } + if (dv[i].attributes.size() != 0) { + op |= VT_NODE_ATTRIB; + } + + serialize_byte(out, op, fpos, fname); serialize_long_long(out, dv[i].x - wx, fpos, fname); serialize_long_long(out, dv[i].y - wy, fpos, fname); + + if (op & VT_NODE_3D) { + serialize_double(out, dv[i].elevation, fpos, fname); + } + if (op & VT_NODE_ATTRIB) { + serialize_string(out, dv[i].attributes, fpos, fname); + } + wx = dv[i].x; wy = dv[i].y; } else { diff --git a/serial.hpp b/serial.hpp index e52a6a8..233b390 100644 --- a/serial.hpp +++ b/serial.hpp @@ -16,21 +16,25 @@ size_t fwrite_check(const void *ptr, size_t size, size_t nitems, FILE *stream, c void serialize_int(FILE *out, int n, std::atomic *fpos, const char *fname); void serialize_long_long(FILE *out, long long n, std::atomic *fpos, const char *fname); void serialize_ulong_long(FILE *out, unsigned long long n, std::atomic *fpos, const char *fname); +void serialize_double(FILE *out, double n, std::atomic *fpos, const char *fname); void serialize_byte(FILE *out, signed char n, std::atomic *fpos, const char *fname); void serialize_uint(FILE *out, unsigned n, std::atomic *fpos, const char *fname); -void serialize_string(FILE *out, const char *s, std::atomic *fpos, const char *fname); +void serialize_string(FILE *out, std::string const &s, std::atomic *fpos, const char *fname); void deserialize_int(char **f, int *n); void deserialize_long_long(char **f, long long *n); void deserialize_ulong_long(char **f, unsigned long long *n); +void deserialize_double(char **f, double *n); void deserialize_uint(char **f, unsigned *n); void deserialize_byte(char **f, signed char *n); int deserialize_int_io(FILE *f, int *n, std::atomic *geompos); int deserialize_long_long_io(FILE *f, long long *n, std::atomic *geompos); int deserialize_ulong_long_io(FILE *f, unsigned long long *n, std::atomic *geompos); +int deserialize_double_io(FILE *f, double *n, std::atomic *geompos); int deserialize_uint_io(FILE *f, unsigned *n, std::atomic *geompos); int deserialize_byte_io(FILE *f, signed char *n, std::atomic *geompos); +int deserialize_string_io(FILE *f, std::string &s, std::atomic *geompos); struct serial_val { int type = 0;