Add class 'SimpleDynamic' to base-writer, migrate AnimValue to use it
This commit is contained in:
@@ -9,95 +9,12 @@
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
|
||||
static const char *vtname(AnimValueType vt) {
|
||||
switch (vt) {
|
||||
case T_UNINITIALIZED: return "uninitialized";
|
||||
case T_BOOLEAN: return "boolean";
|
||||
case T_NUMBER: return "number";
|
||||
case T_STRING: return "string";
|
||||
case T_XYZ: return "xyz";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint64_t hash_encstep(uint64_t prev, std::string_view s) {
|
||||
return util::hash_string(util::HashValue(123, prev), s).first;
|
||||
}
|
||||
|
||||
void AnimValue::set_boolean(bool b) {
|
||||
type = T_BOOLEAN;
|
||||
str.clear();
|
||||
xyz = (b ? 1.0:0.0);
|
||||
}
|
||||
|
||||
void AnimValue::set_number(double n) {
|
||||
type = T_NUMBER;
|
||||
str.clear();
|
||||
xyz = util::DXYZ(n, 0, 0);
|
||||
}
|
||||
|
||||
void AnimValue::set_xyz(const util::DXYZ &v) {
|
||||
type = T_XYZ;
|
||||
str.clear();
|
||||
xyz = v;
|
||||
}
|
||||
|
||||
void AnimValue::set_string(std::string_view sv) {
|
||||
type = T_STRING;
|
||||
str = sv;
|
||||
xyz = 0.0;
|
||||
}
|
||||
|
||||
bool AnimValue::get_boolean() const {
|
||||
if (type != T_BOOLEAN) return false;
|
||||
return (xyz.x == 1.0);
|
||||
}
|
||||
|
||||
double AnimValue::get_number() const {
|
||||
if (type != T_NUMBER) return 0.0;
|
||||
return xyz.x;
|
||||
}
|
||||
|
||||
const util::DXYZ &AnimValue::get_xyz() const {
|
||||
static util::DXYZ zero;
|
||||
if (type != T_XYZ) return zero;
|
||||
return xyz;
|
||||
}
|
||||
|
||||
std::string_view AnimValue::get_string() const {
|
||||
if (type != T_STRING) return std::string_view("");
|
||||
return std::string_view(str);
|
||||
}
|
||||
|
||||
void AnimValue::copy_value(const AnimValue &other) {
|
||||
type = other.type;
|
||||
str = other.str;
|
||||
xyz = other.xyz;
|
||||
}
|
||||
|
||||
static void encode_value(StreamBuffer *sb, const AnimValue *v) {
|
||||
sb->write_uint8(uint8_t(v->type));
|
||||
switch(v->type) {
|
||||
case T_NUMBER: sb->write_double(v->xyz.x); break;
|
||||
case T_BOOLEAN: sb->write_bool(v->xyz.x == 1.0); break;
|
||||
case T_XYZ: sb->write_dxyz(v->xyz); break;
|
||||
case T_STRING: sb->write_string(v->str); break;
|
||||
default: assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_value(StreamBuffer *sb, AnimValue *v) {
|
||||
AnimValueType type = AnimValueType(sb->read_uint8());
|
||||
switch (type) {
|
||||
case T_NUMBER: v->set_number(sb->read_double()); break;
|
||||
case T_BOOLEAN: v->set_boolean(sb->read_bool()); break;
|
||||
case T_XYZ: v->set_xyz(sb->read_dxyz()); break;
|
||||
case T_STRING: v->set_string(sb->read_string()); break;
|
||||
default: assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse a value. This is meant for unit testing only. The
|
||||
// parser isn't powerful enough to express all possible values.
|
||||
static void parse_value(std::string_view vstr, AnimValue *v) {
|
||||
@@ -122,7 +39,7 @@ static void parse_value(std::string_view vstr, AnimValue *v) {
|
||||
double x = std::atof(parts[0].c_str());
|
||||
double y = std::atof(parts[1].c_str());
|
||||
double z = std::atof(parts[2].c_str());
|
||||
v->set_xyz(util::DXYZ(x,y,z));
|
||||
v->set_dxyz(util::DXYZ(x,y,z));
|
||||
return;
|
||||
}
|
||||
// If it doesn't parse as any of the above, it's a string.
|
||||
@@ -149,7 +66,7 @@ static AnimValue parse_anim_value(LuaCoreStack &LS, LuaSlot val, LuaSlot tmp) {
|
||||
LS.rawget(tmp, val, 3);
|
||||
if (!LS.isnumber(tmp)) return result;
|
||||
xyz.z = LS.cknumber(tmp);
|
||||
result.set_xyz(xyz);
|
||||
result.set_dxyz(xyz);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -158,32 +75,6 @@ void AnimState::set_persistent(const eng::string &name) {
|
||||
map_[name].persistent = true;
|
||||
}
|
||||
|
||||
bool AnimState::get_boolean(const eng::string &name) {
|
||||
auto iter = map_.find(name);
|
||||
if (iter == map_.end()) return false;
|
||||
return iter->second.get_boolean();
|
||||
}
|
||||
|
||||
double AnimState::get_number(const eng::string &name) {
|
||||
auto iter = map_.find(name);
|
||||
if (iter == map_.end()) return 0.0;
|
||||
return iter->second.get_number();
|
||||
}
|
||||
|
||||
util::DXYZ AnimState::get_xyz(const eng::string &name) {
|
||||
static util::DXYZ zero;
|
||||
auto iter = map_.find(name);
|
||||
if (iter == map_.end()) return zero;
|
||||
return iter->second.get_xyz();
|
||||
}
|
||||
|
||||
std::string_view AnimState::get_string(const eng::string &name) {
|
||||
auto iter = map_.find(name);
|
||||
if (iter == map_.end()) return std::string_view("");
|
||||
return iter->second.get_string();
|
||||
}
|
||||
|
||||
|
||||
void AnimState::set_boolean(const eng::string &name, bool v) {
|
||||
AnimValue &value = map_[name];
|
||||
value.set_boolean(v);
|
||||
@@ -194,9 +85,9 @@ void AnimState::set_number(const eng::string &name, double v) {
|
||||
value.set_number(v);
|
||||
}
|
||||
|
||||
void AnimState::set_xyz(const eng::string &name, const util::DXYZ &v) {
|
||||
void AnimState::set_dxyz(const eng::string &name, const util::DXYZ &v) {
|
||||
AnimValue &value = map_[name];
|
||||
value.set_xyz(v);
|
||||
value.set_dxyz(v);
|
||||
}
|
||||
|
||||
void AnimState::set_string(const eng::string &name, std::string_view v) {
|
||||
@@ -220,10 +111,10 @@ void AnimState::print_debug_string(eng::ostringstream &oss) {
|
||||
oss << ":";
|
||||
}
|
||||
switch (value.type) {
|
||||
case T_NUMBER: oss << value.xyz.x; break;
|
||||
case T_BOOLEAN: oss << ((value.xyz.x == 1.0) ? "true":"false"); break;
|
||||
case T_XYZ: oss << value.xyz; break;
|
||||
case T_STRING: oss << value.str; break;
|
||||
case SimpleDynamicTag::NUMBER: oss << value.x; break;
|
||||
case SimpleDynamicTag::BOOLEAN: oss << ((value.x == 1.0) ? "true":"false"); break;
|
||||
case SimpleDynamicTag::VECTOR: oss << value.x << "," << value.y << "," << value.z; break;
|
||||
case SimpleDynamicTag::STRING: oss << value.s; break;
|
||||
default: assert(false);
|
||||
}
|
||||
first = false;
|
||||
@@ -243,7 +134,7 @@ eng::string AnimState::encode() const {
|
||||
const AnimValue &value = pair.second;
|
||||
sb.write_string(name);
|
||||
sb.write_bool(value.persistent);
|
||||
encode_value(&sb, &value);
|
||||
sb.write_simple_dynamic(value);
|
||||
}
|
||||
return sb.read_entire_contents();
|
||||
}
|
||||
@@ -253,26 +144,25 @@ void AnimState::decode(std::string_view s) {
|
||||
StreamBuffer sb(s);
|
||||
while (!sb.empty()) {
|
||||
eng::string name = sb.read_string();
|
||||
bool persistent = sb.read_bool();
|
||||
AnimValue &value = map_[name];
|
||||
value.persistent = persistent;
|
||||
decode_value(&sb, &value);
|
||||
value.persistent = sb.read_bool();
|
||||
sb.read_simple_dynamic(&value);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimState::decode_persistent(std::string_view s) {
|
||||
map_.clear();
|
||||
StreamBuffer sb(s);
|
||||
AnimValue dummy;
|
||||
SimpleDynamic dummy;
|
||||
while (!sb.empty()) {
|
||||
eng::string name = sb.read_string();
|
||||
bool persistent = sb.read_bool();
|
||||
if (persistent) {
|
||||
AnimValue &value = map_[name];
|
||||
value.persistent = persistent;
|
||||
decode_value(&sb, &value);
|
||||
sb.read_simple_dynamic(&value);
|
||||
} else {
|
||||
decode_value(&sb, &dummy);
|
||||
sb.read_simple_dynamic(&dummy);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -280,7 +170,7 @@ void AnimState::decode_persistent(std::string_view s) {
|
||||
eng::string AnimState::add_default(const eng::string &name, const AnimValue &def, const AnimState *other) {
|
||||
AnimValue &value = map_[name];
|
||||
value.persistent = true;
|
||||
if (value.type == T_UNINITIALIZED) {
|
||||
if (value.type == SimpleDynamicTag::UNINITIALIZED) {
|
||||
if (other != nullptr) {
|
||||
auto otheriter = other->map_.find(name);
|
||||
if (otheriter != other->map_.end()) {
|
||||
@@ -294,7 +184,7 @@ eng::string AnimState::add_default(const eng::string &name, const AnimValue &def
|
||||
return "";
|
||||
}
|
||||
if (value.type != def.type) {
|
||||
return util::ss("Animation key ", name, " must be a ", vtname(def.type));
|
||||
return util::ss("Animation key ", name, " must be a ", def.type_name());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -303,7 +193,7 @@ eng::string AnimState::add_defaults(const AnimState *other) {
|
||||
eng::string err;
|
||||
AnimValue defval;
|
||||
|
||||
defval.set_xyz(util::DXYZ(0,0,0));
|
||||
defval.set_dxyz(util::DXYZ(0,0,0));
|
||||
err = add_default("xyz", defval, other);
|
||||
if (!err.empty()) return err;
|
||||
|
||||
@@ -341,13 +231,13 @@ eng::string AnimState::apply_lua(LuaCoreStack &LS0, LuaSlot tab, bool setpersist
|
||||
return "in animation key-value pairs, key must be a string.";
|
||||
}
|
||||
AnimValue parsedvalue = parse_anim_value(LS, val, tmp);
|
||||
if (parsedvalue.type == T_UNINITIALIZED) {
|
||||
if (parsedvalue.type == SimpleDynamicTag::UNINITIALIZED) {
|
||||
return "in animation key-value pairs, val must be number, string, boolean, or xyz";
|
||||
}
|
||||
eng::string name = LS.ckstring(key);
|
||||
AnimValue &mapentry = map_[name];
|
||||
if ((mapentry.type != T_UNINITIALIZED) && (mapentry.type != parsedvalue.type)) {
|
||||
return util::ss("animation '", name, "' must be a ", vtname(mapentry.type));
|
||||
if ((mapentry.type != SimpleDynamicTag::UNINITIALIZED) && (mapentry.type != parsedvalue.type)) {
|
||||
return util::ss("animation '", name, "' must be a ", mapentry.type_name());
|
||||
}
|
||||
mapentry.copy_value(parsedvalue);
|
||||
if (setpersist) mapentry.persistent = true;
|
||||
@@ -363,17 +253,17 @@ void AnimState::to_lua(LuaCoreStack &LS0, LuaSlot tab, bool persistent) {
|
||||
if (pair.second.persistent != persistent) continue;
|
||||
LS.set(name, pair.first);
|
||||
const AnimValue &value = pair.second;
|
||||
if (value.type == T_BOOLEAN) {
|
||||
LS.set(val, value.get_boolean());
|
||||
} else if (value.type == T_NUMBER) {
|
||||
LS.set(val, value.get_number());
|
||||
} else if (value.type == T_STRING) {
|
||||
LS.set(val, value.get_string());
|
||||
} else if (value.type == T_XYZ) {
|
||||
if (value.type == SimpleDynamicTag::BOOLEAN) {
|
||||
LS.set(val, (value.x == 1.0));
|
||||
} else if (value.type == SimpleDynamicTag::NUMBER) {
|
||||
LS.set(val, value.x);
|
||||
} else if (value.type == SimpleDynamicTag::STRING) {
|
||||
LS.set(val, std::string_view(value.s));
|
||||
} else if (value.type == SimpleDynamicTag::VECTOR) {
|
||||
LS.newtable(val);
|
||||
LS.rawset(val, 1, value.get_xyz().x);
|
||||
LS.rawset(val, 2, value.get_xyz().y);
|
||||
LS.rawset(val, 3, value.get_xyz().z);
|
||||
LS.rawset(val, 1, value.x);
|
||||
LS.rawset(val, 2, value.y);
|
||||
LS.rawset(val, 3, value.z);
|
||||
}
|
||||
LS.rawset(tab, name, val);
|
||||
}
|
||||
@@ -407,14 +297,14 @@ void AnimCoreState::decode(std::string_view s) {
|
||||
plane.clear();
|
||||
xyz = 0.0;
|
||||
StreamBuffer sb(s);
|
||||
AnimValue value;
|
||||
SimpleDynamic value;
|
||||
while (!sb.empty()) {
|
||||
eng::string name = sb.read_string();
|
||||
bool persistent = sb.read_bool();
|
||||
decode_value(&sb, &value);
|
||||
sb.read_simple_dynamic(&value);
|
||||
if (persistent) {
|
||||
if ((name == "xyz") && (value.type == T_XYZ)) xyz = value.xyz;
|
||||
if ((name == "plane") && (value.type == T_STRING)) plane = value.str;
|
||||
if ((name == "xyz") && (value.type == SimpleDynamicTag::VECTOR)) xyz = util::DXYZ(value.x, value.y, value.z);
|
||||
if ((name == "plane") && (value.type == SimpleDynamicTag::STRING)) plane = value.s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -642,28 +532,28 @@ LuaDefine(unittests_animqueue, "", "some unit tests") {
|
||||
|
||||
// Test AnimState simple setters.
|
||||
astate.set_string("color", "blue");
|
||||
astate.set_xyz("xyz", util::DXYZ(1,2,3));
|
||||
astate.set_dxyz("xyz", util::DXYZ(1,2,3));
|
||||
astate.set_number("half", 0.5);
|
||||
astate.set_boolean("nice", true);
|
||||
LuaAssertStrEq(L, astate.debug_string(), "color:blue half:0.5 nice:true xyz:1,2,3");
|
||||
|
||||
// Test AnimState simple getters.
|
||||
LuaAssert(L, astate.get_string("color") == "blue");
|
||||
LuaAssert(L, astate.get_xyz("xyz") == util::DXYZ(1,2,3));
|
||||
LuaAssert(L, astate.get_number("half") == 0.5);
|
||||
LuaAssert(L, astate.get_boolean("nice") == true);
|
||||
// // Test AnimState simple getters.
|
||||
// LuaAssert(L, astate.get_string("color") == "blue");
|
||||
// LuaAssert(L, astate.get_xyz("xyz") == util::DXYZ(1,2,3));
|
||||
// LuaAssert(L, astate.get_number("half") == 0.5);
|
||||
// LuaAssert(L, astate.get_boolean("nice") == true);
|
||||
|
||||
// Test AnimState simple getters on nonexistent data.
|
||||
LuaAssert(L, astate.get_string("q") == "");
|
||||
LuaAssert(L, astate.get_xyz("q") == util::DXYZ(0,0,0));
|
||||
LuaAssert(L, astate.get_number("q") == 0.0);
|
||||
LuaAssert(L, astate.get_boolean("q") == false);
|
||||
// // Test AnimState simple getters on nonexistent data.
|
||||
// LuaAssert(L, astate.get_string("q") == "");
|
||||
// LuaAssert(L, astate.get_xyz("q") == util::DXYZ(0,0,0));
|
||||
// LuaAssert(L, astate.get_number("q") == 0.0);
|
||||
// LuaAssert(L, astate.get_boolean("q") == false);
|
||||
|
||||
// Test AnimState simple getters on wrong-type data.
|
||||
LuaAssert(L, astate.get_string("half") == "");
|
||||
LuaAssert(L, astate.get_xyz("half") == util::DXYZ(0,0,0));
|
||||
LuaAssert(L, astate.get_number("color") == 0.0);
|
||||
LuaAssert(L, astate.get_boolean("color") == false);
|
||||
// // Test AnimState simple getters on wrong-type data.
|
||||
// LuaAssert(L, astate.get_string("half") == "");
|
||||
// LuaAssert(L, astate.get_xyz("half") == util::DXYZ(0,0,0));
|
||||
// LuaAssert(L, astate.get_number("color") == 0.0);
|
||||
// LuaAssert(L, astate.get_boolean("color") == false);
|
||||
|
||||
// Test AnimState persistence manipulation.
|
||||
astate.set_persistent("color");
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
#include "wrap-deque.hpp"
|
||||
#include "wrap-unordered-map.hpp"
|
||||
|
||||
#include "base-writer.hpp"
|
||||
#include "luastack.hpp"
|
||||
#include "streambuffer.hpp"
|
||||
#include "debugcollector.hpp"
|
||||
@@ -101,36 +102,15 @@
|
||||
#include <cassert>
|
||||
#include <ostream>
|
||||
|
||||
enum AnimValueType {
|
||||
T_STRING,
|
||||
T_NUMBER,
|
||||
T_BOOLEAN,
|
||||
T_XYZ,
|
||||
T_UNINITIALIZED
|
||||
};
|
||||
|
||||
struct AnimValue {
|
||||
AnimValue() : persistent(false), type(T_UNINITIALIZED) {}
|
||||
|
||||
struct AnimValue : public SimpleDynamic {
|
||||
bool persistent;
|
||||
AnimValueType type;
|
||||
eng::string str;
|
||||
util::DXYZ xyz;
|
||||
|
||||
// These set the type, str, and xyz fields in a consistent way.
|
||||
void set_boolean(bool b);
|
||||
void set_number(double n);
|
||||
void set_xyz(const util::DXYZ &xyz);
|
||||
void set_string(std::string_view s);
|
||||
AnimValue() { persistent = false; }
|
||||
|
||||
// The get the type, str, and xyz fields in a consistent way.
|
||||
bool get_boolean() const;
|
||||
double get_number() const;
|
||||
const util::DXYZ &get_xyz() const;
|
||||
std::string_view get_string() const;
|
||||
|
||||
// Copy the value from another animvalue. Don't copy the persistent flag.
|
||||
void copy_value(const AnimValue &other);
|
||||
void set_dxyz(const util::DXYZ &xyz) {
|
||||
type = SimpleDynamicTag::VECTOR;
|
||||
s.clear(); x = xyz.x; y = xyz.y; z = xyz.z;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -158,20 +138,12 @@ public:
|
||||
//
|
||||
bool contains(const eng::string &name) { return map_.find(name) != map_.end(); }
|
||||
|
||||
// Get the value of a specific variable.
|
||||
// If the variable isn't present, return a default value.
|
||||
//
|
||||
bool get_boolean(const eng::string &name);
|
||||
double get_number(const eng::string &name);
|
||||
util::DXYZ get_xyz(const eng::string &name);
|
||||
std::string_view get_string(const eng::string &name);
|
||||
|
||||
// Set a single variable to a value of a specified type.
|
||||
// If the variable isn't present, add it.
|
||||
//
|
||||
void set_boolean(const eng::string &name, bool v);
|
||||
void set_number(const eng::string &name, double v);
|
||||
void set_xyz(const eng::string &name, const util::DXYZ &value);
|
||||
void set_dxyz(const eng::string &name, const util::DXYZ &value);
|
||||
void set_string(const eng::string &name, std::string_view value);
|
||||
|
||||
// Print a debug string into the stringstream.
|
||||
|
||||
@@ -18,7 +18,7 @@ void World::tangible_clear_plane_and_xyz(int64_t id, const eng::string &plane, c
|
||||
assert(t != nullptr);
|
||||
AnimState state;
|
||||
state.set_string("plane", plane);
|
||||
state.set_xyz("xyz", xyz);
|
||||
state.set_dxyz("xyz", xyz);
|
||||
state.set_persistent("plane");
|
||||
state.set_persistent("xyz");
|
||||
t->anim_queue_.clear(state);
|
||||
@@ -30,7 +30,7 @@ void World::tangible_walkto(int64_t id, float x, float y) {
|
||||
assert(t != nullptr);
|
||||
AnimState state = t->anim_queue_.get_final_persistent();
|
||||
state.set_string("action", "walkto");
|
||||
state.set_xyz("xyz", util::DXYZ(x,y,0.0));
|
||||
state.set_dxyz("xyz", util::DXYZ(x,y,0.0));
|
||||
t->anim_queue_.add(state);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,90 @@
|
||||
#pragma once
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: This is a header-only library that is included
|
||||
// by the graphics engine as well. It cannot contain references
|
||||
// to anything else in the engine.
|
||||
//
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <string_view>
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SimpleDynamic
|
||||
//
|
||||
// A struct that holds a dynamically typed value.
|
||||
// This can hold a string, number, vector, or boolean.
|
||||
//
|
||||
// The type is stored in the 'type' field.
|
||||
//
|
||||
// If it's a STRING, the value is in the field s
|
||||
// If it's a NUMBER, the value is in the field x
|
||||
// If it's a BOOLEAN, it's true if (x==1.0)
|
||||
// If it's a VECTOR, the value is in x,y,z
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
enum class SimpleDynamicTag {
|
||||
UNINITIALIZED,
|
||||
STRING,
|
||||
NUMBER,
|
||||
BOOLEAN,
|
||||
VECTOR,
|
||||
};
|
||||
|
||||
struct SimpleDynamic {
|
||||
SimpleDynamicTag type;
|
||||
double x, y, z;
|
||||
std::string s;
|
||||
|
||||
SimpleDynamic() {
|
||||
type = SimpleDynamicTag::UNINITIALIZED;
|
||||
x=y=z=0;
|
||||
}
|
||||
|
||||
static const char *type_name_of(SimpleDynamicTag t) {
|
||||
switch (t) {
|
||||
case SimpleDynamicTag::UNINITIALIZED: return "uninitialized";
|
||||
case SimpleDynamicTag::BOOLEAN: return "boolean";
|
||||
case SimpleDynamicTag::NUMBER: return "number";
|
||||
case SimpleDynamicTag::STRING: return "string";
|
||||
case SimpleDynamicTag::VECTOR: return "vector";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char *type_name() const {
|
||||
return type_name_of(type);
|
||||
}
|
||||
|
||||
void set_string(std::string_view is) {
|
||||
type=SimpleDynamicTag::STRING; s=is; x=0; y=0; z=0;
|
||||
}
|
||||
|
||||
void set_number(double n) {
|
||||
type = SimpleDynamicTag::NUMBER; s.clear(); x=n; y=0; z=0;
|
||||
}
|
||||
|
||||
void set_boolean(bool b) {
|
||||
type = SimpleDynamicTag::BOOLEAN; s.clear(); x=(b?1:0); y=0; z=0;
|
||||
}
|
||||
|
||||
void set_vector(double ix, double iy, double iz) {
|
||||
type = SimpleDynamicTag::VECTOR; s.clear(); x=ix; y=iy; z=iz;
|
||||
}
|
||||
|
||||
void copy_value(const SimpleDynamic &other) {
|
||||
type = other.type;
|
||||
s=other.s; x=other.x; y=other.y; z=other.z;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BaseWriter
|
||||
@@ -30,6 +104,7 @@
|
||||
// void write_double(double data)
|
||||
// void write_length(size_t data)
|
||||
// void write_string(std::string_view data)
|
||||
// void write_simple_dynamic(const SimpleDynamic &sd);
|
||||
//
|
||||
// You should derive from BaseWriter using the CRTP pattern:
|
||||
//
|
||||
@@ -86,8 +161,20 @@ public:
|
||||
write_length(s.size());
|
||||
static_cast<Derived*>(this)->write_bytes(s.data(), s.size());
|
||||
}
|
||||
|
||||
void write_simple_dynamic(const SimpleDynamic &sd) {
|
||||
write_uint8(uint8_t(sd.type));
|
||||
switch(sd.type) {
|
||||
case SimpleDynamicTag::NUMBER: write_double(sd.x); break;
|
||||
case SimpleDynamicTag::BOOLEAN: write_bool(sd.x == 1.0); break;
|
||||
case SimpleDynamicTag::VECTOR: write_double(sd.x); write_double(sd.y); write_double(sd.z); break;
|
||||
case SimpleDynamicTag::STRING: write_string(sd.s); break;
|
||||
default: assert(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BaseReader
|
||||
@@ -109,6 +196,7 @@ public:
|
||||
// size_t read_length();
|
||||
// String read_string_limit(uint64_t size);
|
||||
// String read_string();
|
||||
// SimpleDynamic read_simple_dynamic();
|
||||
//
|
||||
// You should derive from BaseReader using the CRTP pattern:
|
||||
//
|
||||
@@ -184,5 +272,22 @@ public:
|
||||
}
|
||||
|
||||
auto read_string() { return read_string_limit(0x1000000); } // 16MB limit default
|
||||
|
||||
void read_simple_dynamic(SimpleDynamic *result) {
|
||||
SimpleDynamicTag type = SimpleDynamicTag(read_uint8());
|
||||
switch (type) {
|
||||
case SimpleDynamicTag::NUMBER: result->set_number(read_double()); break;
|
||||
case SimpleDynamicTag::BOOLEAN: result->set_boolean(read_bool()); break;
|
||||
case SimpleDynamicTag::VECTOR: {
|
||||
double x=read_double();
|
||||
double y=read_double();
|
||||
double z=read_double();
|
||||
result->set_vector(x,y,z);
|
||||
break;
|
||||
}
|
||||
case SimpleDynamicTag::STRING: result->set_string(read_string()); break;
|
||||
default: assert(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user