Can now pass tokens as values in animation steps

This commit is contained in:
2025-02-05 15:45:48 -05:00
parent 22644c64fa
commit 07dbec4bef
8 changed files with 111 additions and 103 deletions

View File

@@ -41,6 +41,13 @@ static bool SetProperty(const FString& prefix, UObject* obj, const FlxAnimationF
*pptr = FString(field.S.size(), (const UTF8CHAR*)field.S.data()); *pptr = FString(field.S.size(), (const UTF8CHAR*)field.S.data());
return true; return true;
} }
case SimpleDynamicTag::TOKEN: {
FNameProperty* fprop = FindFProperty<FNameProperty>(uclass, nname);
if (fprop == nullptr) return false;
FName* pptr = fprop->ContainerPtrToValuePtr<FName>(obj);
*pptr = FName(field.S.size(), (const UTF8CHAR*)field.S.data(), FNAME_Add);
return true;
}
case SimpleDynamicTag::NUMBER: { case SimpleDynamicTag::NUMBER: {
FDoubleProperty* fprop = FindFProperty<FDoubleProperty>(uclass, nname); FDoubleProperty* fprop = FindFProperty<FDoubleProperty>(uclass, nname);
if (fprop == nullptr) return false; if (fprop == nullptr) return false;
@@ -206,6 +213,12 @@ FString UlxAnimationStepLibrary::AnimationStepGetString(const FlxAnimationStep&
return FString(field.S.size(), (const UTF8CHAR*)(field.S.data())); return FString(field.S.size(), (const UTF8CHAR*)(field.S.data()));
} }
FName UlxAnimationStepLibrary::AnimationStepGetName(const FlxAnimationStep& step, const FString& name) {
FlxAnimationField field = FindAnimationField(step, name);
if (field.Type != SimpleDynamicTag::TOKEN) return FName();
return FName(field.S.size(), (const UTF8CHAR*)(field.S.data()), FNAME_Add);
}
bool UlxAnimationStepLibrary::AnimationStepGetBool(const FlxAnimationStep& step, const FString& name) { bool UlxAnimationStepLibrary::AnimationStepGetBool(const FlxAnimationStep& step, const FString& name) {
FlxAnimationField field = FindAnimationField(step, name); FlxAnimationField field = FindAnimationField(step, name);
if (field.Type != SimpleDynamicTag::BOOLEAN) return false; if (field.Type != SimpleDynamicTag::BOOLEAN) return false;
@@ -223,6 +236,10 @@ FlxAnimationField FlxAnimationStepDecoder::ReadField() {
result.S = Decoder.read_string_view(); result.S = Decoder.read_string_view();
break; break;
} }
case SimpleDynamicTag::TOKEN: {
result.S = Decoder.read_string_view();
break;
}
case SimpleDynamicTag::NUMBER: { case SimpleDynamicTag::NUMBER: {
result.X = Decoder.read_double(); result.X = Decoder.read_double();
break; break;
@@ -263,6 +280,9 @@ FString FlxAnimationStepDecoder::DebugString(bool injectidle, bool persistentonl
case SimpleDynamicTag::STRING: case SimpleDynamicTag::STRING:
result.Append(FString(field.S.size(), (const UTF8CHAR*)field.S.data())); result.Append(FString(field.S.size(), (const UTF8CHAR*)field.S.data()));
break; break;
case SimpleDynamicTag::TOKEN:
result.Appendf(TEXT("[%s]"), *FString(field.S.size(), (const UTF8CHAR*)field.S.data()));
break;
case SimpleDynamicTag::NUMBER: case SimpleDynamicTag::NUMBER:
result.Appendf(TEXT("%lf"), field.X); result.Appendf(TEXT("%lf"), field.X);
break; break;

View File

@@ -106,6 +106,9 @@ public:
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Animation Step") UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Animation Step")
static FString AnimationStepGetString(const FlxAnimationStep& step, const FString& name); static FString AnimationStepGetString(const FlxAnimationStep& step, const FString& name);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Animation Step")
static FName AnimationStepGetName(const FlxAnimationStep& step, const FString& name);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Animation Step") UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Animation Step")
static bool AnimationStepGetBool(const FlxAnimationStep& step, const FString& name); static bool AnimationStepGetBool(const FlxAnimationStep& step, const FString& name);
}; };

View File

@@ -55,33 +55,31 @@ static void parse_value(std::string_view vstr, AnimValue *v) {
} }
static AnimValue parse_anim_value(LuaCoreStack &LS, LuaSlot val, LuaSlot tmp) { static AnimValue parse_anim_value(LuaCoreStack &LS, LuaSlot val) {
AnimValue result; AnimValue result;
auto tboolean = LS.tryboolean(val); int type = LS.type(val);
if (tboolean) { switch (type) {
result.set_boolean(*tboolean); case LUA_TBOOLEAN: {
return result; auto tbool = LS.tryboolean(val);
if (tbool) result.set_boolean(*tbool);
} }
auto tnumber = LS.trynumber(val); case LUA_TNUMBER: {
if (tnumber) { auto tnum = LS.trynumber(val);
result.set_number(*tnumber); if (tnum) result.set_number(*tnum);
return result;
} }
auto tstring = LS.trystringview(val); case LUA_TSTRING: {
if (tstring) { auto tstr = LS.trystringview(val);
result.set_string(*tstring); if (tstr) result.set_string(*tstr);
return result;
} }
case LUA_TTABLE: {
auto txyz = LS.tryxyz(val); auto txyz = LS.tryxyz(val);
if (txyz) { if (txyz) result.set_dxyz(*txyz);
result.set_dxyz(*txyz); }
return result; case LUA_TLIGHTUSERDATA: {
auto ttoken = LS.trytoken(val);
if (ttoken) result.set_token(*ttoken);
} }
if (LS.rawequal(val, LuaToken("auto"))) {
result.set_auto();
return result;
} }
result.set_uninitialized();
return result; return result;
} }
@@ -89,26 +87,6 @@ void AnimState::set_persistent(const eng::string &name) {
map_[name].persistent = true; map_[name].persistent = true;
} }
void AnimState::set_boolean(const eng::string &name, bool v) {
AnimValue &value = map_[name];
value.set_boolean(v);
}
void AnimState::set_number(const eng::string &name, double v) {
AnimValue &value = map_[name];
value.set_number(v);
}
void AnimState::set_dxyz(const eng::string &name, const util::DXYZ &v) {
AnimValue &value = map_[name];
value.set_dxyz(v);
}
void AnimState::set_string(const eng::string &name, std::string_view v) {
AnimValue &value = map_[name];
value.set_string(v);
}
void AnimState::print_debug_string(eng::ostringstream &oss) { void AnimState::print_debug_string(eng::ostringstream &oss) {
bool first = true; bool first = true;
if (map_.empty()) { if (map_.empty()) {
@@ -126,11 +104,11 @@ void AnimState::print_debug_string(eng::ostringstream &oss) {
} }
switch (value.type) { switch (value.type) {
case SimpleDynamicTag::UNINITIALIZED: oss << "UNINITIALIZED"; break; case SimpleDynamicTag::UNINITIALIZED: oss << "UNINITIALIZED"; break;
case SimpleDynamicTag::AUTO: oss << "AUTO"; break; case SimpleDynamicTag::STRING: oss << value.s; break;
case SimpleDynamicTag::TOKEN: oss << "[" << value.s << "]"; break;
case SimpleDynamicTag::NUMBER: oss << value.x; break; case SimpleDynamicTag::NUMBER: oss << value.x; break;
case SimpleDynamicTag::BOOLEAN: oss << ((value.x == 1.0) ? "true":"false"); 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::VECTOR: oss << value.x << "," << value.y << "," << value.z; break;
case SimpleDynamicTag::STRING: oss << value.s; break;
default: assert(false); default: assert(false);
} }
first = false; first = false;
@@ -230,8 +208,8 @@ eng::string AnimState::add_defaults(const AnimState *other) {
eng::string AnimState::from_lua(LuaCoreStack &LS0, LuaSlot tab, bool persistent, bool allowauto) { eng::string AnimState::from_lua(LuaCoreStack &LS0, LuaSlot tab, bool persistent, bool allowauto) {
LuaVar key, val, tmp; LuaVar key, val;
LuaExtStack LS(LS0.state(), key, val, tmp); LuaExtStack LS(LS0.state(), key, val);
util::DXYZ xyz; util::DXYZ xyz;
clear(); clear();
@@ -247,12 +225,12 @@ eng::string AnimState::from_lua(LuaCoreStack &LS0, LuaSlot tab, bool persistent,
if (!sv::is_lua_id(name)) { if (!sv::is_lua_id(name)) {
return "in animation key-value pairs, key must be a valid lua identifier."; return "in animation key-value pairs, key must be a valid lua identifier.";
} }
AnimValue parsedvalue = parse_anim_value(LS, val, tmp); AnimValue parsedvalue = parse_anim_value(LS, val);
if (parsedvalue.type == SimpleDynamicTag::UNINITIALIZED) { if (parsedvalue.type == SimpleDynamicTag::UNINITIALIZED) {
return "in animation key-value pairs, value must be number, string, boolean, or xyz"; return "in animation key-value pairs, value must be string, token, number, boolean, or xyz";
} }
if ((parsedvalue.type == SimpleDynamicTag::AUTO) && !allowauto) { if (parsedvalue.is_token("auto") && !allowauto) {
return "in animation key-value pairs, value must not be AUTO here."; return "in animation key-value pairs, value must not be [auto] here.";
} }
AnimValue &mapentry = map_[name]; AnimValue &mapentry = map_[name];
mapentry.copy_value(parsedvalue); mapentry.copy_value(parsedvalue);
@@ -271,7 +249,7 @@ eng::string AnimState::merge(const AnimState &previous, const AnimState &update)
const AnimValue &src = pair.second; const AnimValue &src = pair.second;
// Handle autocalculation rules. // Handle autocalculation rules.
if (src.type == SimpleDynamicTag::AUTO) { if (src.is_token("auto")) {
if (name == "facing") { if (name == "facing") {
if (!dst.persistent || dst.type != SimpleDynamicTag::NUMBER) { if (!dst.persistent || dst.type != SimpleDynamicTag::NUMBER) {
return "Cannot auto-calculate facing because facing has not been specified as a persistent number"; return "Cannot auto-calculate facing because facing has not been specified as a persistent number";
@@ -306,12 +284,16 @@ eng::string AnimState::merge(const AnimState &previous, const AnimState &update)
} }
void AnimState::to_lua(LuaCoreStack &LS0, LuaSlot tab, bool persistent) { void AnimState::to_lua(LuaCoreStack &LS0, LuaSlot tab, bool transient, bool persistent) {
LuaVar name, val; LuaVar name, val;
LuaExtStack LS(LS0.state(), name, val); LuaExtStack LS(LS0.state(), name, val);
LS.newtable(tab); LS.newtable(tab);
for (const auto &pair : map_) { for (const auto &pair : map_) {
if (pair.second.persistent != persistent) continue; if (pair.second.persistent) {
if (!persistent) continue;
} else {
if (!transient) continue;
}
LS.set(name, pair.first); LS.set(name, pair.first);
const AnimValue &value = pair.second; const AnimValue &value = pair.second;
if (value.type == SimpleDynamicTag::BOOLEAN) { if (value.type == SimpleDynamicTag::BOOLEAN) {
@@ -320,6 +302,8 @@ void AnimState::to_lua(LuaCoreStack &LS0, LuaSlot tab, bool persistent) {
LS.set(val, value.x); LS.set(val, value.x);
} else if (value.type == SimpleDynamicTag::STRING) { } else if (value.type == SimpleDynamicTag::STRING) {
LS.set(val, std::string_view(value.s)); LS.set(val, std::string_view(value.s));
} else if (value.type == SimpleDynamicTag::TOKEN) {
LS.set(val, LuaToken(value.s));
} else if (value.type == SimpleDynamicTag::VECTOR) { } else if (value.type == SimpleDynamicTag::VECTOR) {
LS.newtable(val); LS.newtable(val);
LS.rawset(val, 1, value.x); LS.rawset(val, 1, value.x);

View File

@@ -52,12 +52,7 @@
// for all key-value pairs do: // for all key-value pairs do:
// write_string(key) // write_string(key)
// write_bool(persistent) // write_bool(persistent)
// write_uint8(type) // T_STRING, T_NUMBER, T_BOOL, or T_XYZ // write_simple_dynamic(value)
// switch type:
// T_STRING: write_string(value)
// T_NUMBER: write_double(value)
// T_BOOL: write_bool(value)
// T_XYZ: write_xyz(value)
// //
// The encoded string produced by the loop above is called an "encstep". // The encoded string produced by the loop above is called an "encstep".
// That's short for "encoded animation step". The encstep has a hash // That's short for "encoded animation step". The encstep has a hash
@@ -107,10 +102,19 @@ struct AnimValue : public SimpleDynamicValue {
AnimValue() { persistent = false; } AnimValue() { persistent = false; }
void set_token(LuaToken token) {
type = SimpleDynamicTag::TOKEN;
s=token.str(); x=y=z=0;
}
void set_dxyz(const util::DXYZ &xyz) { void set_dxyz(const util::DXYZ &xyz) {
type = SimpleDynamicTag::VECTOR; type = SimpleDynamicTag::VECTOR;
s.clear(); x = xyz.x; y = xyz.y; z = xyz.z; s.clear(); x = xyz.x; y = xyz.y; z = xyz.z;
} }
bool is_token(const char *t) const {
return (type == SimpleDynamicTag::TOKEN) && (s == t);
}
}; };
@@ -141,10 +145,11 @@ public:
// Set a single variable to a value of a specified type. // Set a single variable to a value of a specified type.
// If the variable isn't present, add it. // If the variable isn't present, add it.
// //
void set_boolean(const eng::string &name, bool v); void set_string(const eng::string &name, std::string_view v) { map_[name].set_string(v); }
void set_number(const eng::string &name, double v); void set_token(const eng::string &name, LuaToken v) { map_[name].set_token(v); }
void set_dxyz(const eng::string &name, const util::DXYZ &value); void set_number(const eng::string &name, double v) { map_[name].set_number(v); }
void set_string(const eng::string &name, std::string_view value); void set_boolean(const eng::string &name, bool v) { map_[name].set_boolean(v); }
void set_dxyz(const eng::string &name, const util::DXYZ &v) { map_[name].set_dxyz(v); }
// Print a debug string into the stringstream. // Print a debug string into the stringstream.
// //
@@ -217,10 +222,10 @@ public:
// Convert an animstate to a lua table. // Convert an animstate to a lua table.
// //
// You can either convert the persistent key-value pairs, or the // You can specify whether you want to include the transient values, the
// nonpersistent. So you'll need two lua tables to store both. // persistent values, or both.
// //
void to_lua(LuaCoreStack &LS, LuaSlot tab, bool persistent); void to_lua(LuaCoreStack &LS, LuaSlot tab, bool transient, bool persistent);
// Parse a string, for unit testing. // Parse a string, for unit testing.
// //

View File

@@ -409,15 +409,14 @@ enum LuaTableType {
struct LuaToken { struct LuaToken {
private: private:
// Convert a base36 number into a token. If the base36 number is // Convert a base36 number into a token. If the base36 number is
// not valid, or if it exceeds 64 bits, then return maxint, ie, // not valid, or if it exceeds 64 bits, then return zero.
// the invalid token.
// //
static constexpr uint64_t parse(std::string_view str) { static constexpr uint64_t parse(std::string_view str) {
uint64_t result = 0; uint64_t result = 0;
uint64_t maxint = uint64_t(-1); uint64_t maxint = uint64_t(-1);
// Leading zeros are not allowed. // Leading zeros are not allowed.
if ((!str.empty()) && (str[0]=='0')) return maxint; if ((!str.empty()) && (str[0]=='0')) return 0;
for (int i = 0; i < int(str.size()); i++) { for (int i = 0; i < int(str.size()); i++) {
char c = str[i]; char c = str[i];
@@ -433,9 +432,9 @@ private:
} }
// Multiply existing number by 36, then add the digit. // Multiply existing number by 36, then add the digit.
// We have two checks to prevent integer overflow. // We have two checks to prevent integer overflow.
if (result > (maxint / 36)) return maxint; if (result > (maxint / 36)) return 0;
result *= 36; result *= 36;
if (digit > (maxint - result)) return maxint; if (digit > (maxint - result)) return 0;
result += digit; result += digit;
} }
return result; return result;
@@ -451,20 +450,21 @@ public:
// Construct a token from a string. // Construct a token from a string.
// //
// If the string is not a valid token, then this initializes the // If the string is not a valid base36 number, then this
// token to the invalid token. // initializes the token to the empty token (zero)
// //
LuaToken(std::string_view s) : value(parse(s)) {} LuaToken(std::string_view s) : value(parse(s)) {}
LuaToken(const eng::string &s) : value(parse(s)) {}
// Construct a token from a compile-time constant string. // Construct a token from a compile-time constant string.
// //
// It appears that the code below throws an exception if the // It appears that the code below throws an exception if the
// string is invalid. But in reality, since this function is // string not parseable. But in reality, since this function is
// consteval (evaluated at compile time), the error is // consteval (evaluated at compile time), the error is
// generated during the compilation. // generated during the compilation.
// //
consteval LuaToken(const char *s) : value(parse(s)) { consteval LuaToken(const char *s) : value(parse(s)) {
if (is_invalid()) throw "Invalid token"; if (empty()) throw "cannot parse token";
} }
// Construct a token from an int64. // Construct a token from an int64.
@@ -482,9 +482,9 @@ public:
// Assignment operator. // Assignment operator.
void operator =(const LuaToken &other) { value = other.value; } void operator =(const LuaToken &other) { value = other.value; }
// Empty: return true if the token is all zero bytes. // Empty: return true if the token is zero.
// //
bool empty() const { return value == 0; } constexpr bool empty() const { return value == 0; }
// Compare two tokens for equality. // Compare two tokens for equality.
// //
@@ -494,19 +494,12 @@ public:
// //
void *voidvalue() const { return (void*)value; } void *voidvalue() const { return (void*)value; }
// Return true if it's the invalid token.
//
constexpr bool is_invalid() { return value == uint64_t(-1); }
// Convert the token to a string. // Convert the token to a string.
// //
// The conversion to string consists of expressing the value // The conversion to string consists of expressing the value
// in base 36. The value 0 is expressed as the empty string. // in base 36.
// //
eng::string str() const; eng::string str() const;
public:
}; };
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@@ -4,6 +4,8 @@
#include "serializelua.hpp" #include "serializelua.hpp"
#include <cmath> #include <cmath>
LuaTokenConstant(tangible_auto, "auto", "");
static void tangible_getall(LuaCoreStack &LS0, LuaSlot list, const util::IdVector &idv) { static void tangible_getall(LuaCoreStack &LS0, LuaSlot list, const util::IdVector &idv) {
LuaVar tangibles, tan; LuaVar tangibles, tan;
LuaExtStack LS(LS0.state(), tangibles, tan); LuaExtStack LS(LS0.state(), tangibles, tan);
@@ -73,7 +75,7 @@ LuaDefine(tangible_animfinal, "tan",
World *w = World::fetch_global_pointer(L); World *w = World::fetch_global_pointer(L);
Tangible *tan = w->tangible_get(LS, tanobj, false); Tangible *tan = w->tangible_get(LS, tanobj, false);
AnimState state = tan->anim_queue_.get_final_everything(); AnimState state = tan->anim_queue_.get_final_everything();
state.to_lua(LS, result, true); state.to_lua(LS, result, true, true);
return LS.result(); return LS.result();
} }

View File

@@ -275,7 +275,7 @@ static std::vector<std::string> parse_control_lst(std::string_view ctrl) {
static std::string read_file(const std::filesystem::path &fn, std::string &err) { static std::string read_file(const std::filesystem::path &fn, std::string &err) {
std::ifstream t(fn); std::ifstream t(fn);
if (t.fail()) { if (t.fail()) {
err = std::string("Could not open ") + fn.u8string(); err = std::string("Could not open ") + fn.string();
return ""; return "";
} }
t.seekg(0, std::ios::end); t.seekg(0, std::ios::end);
@@ -284,7 +284,7 @@ static std::string read_file(const std::filesystem::path &fn, std::string &err)
t.seekg(0); t.seekg(0);
t.read(&result[0], size); t.read(&result[0], size);
if ((t.fail()) || (size_t(t.tellg()) != size)) { if ((t.fail()) || (size_t(t.tellg()) != size)) {
err = std::string("Could not read ") + fn.u8string(); err = std::string("Could not read ") + fn.string();
return ""; return "";
} }
err = ""; err = "";
@@ -347,7 +347,7 @@ std::string package_lua_source(const std::filesystem::path &base, std::ostream *
sbwrite_string(s, names[i]); sbwrite_string(s, names[i]);
std::filesystem::path lfn = base / "lua" / names[i]; std::filesystem::path lfn = base / "lua" / names[i];
if (!sbwrite_file(s, lfn)) { if (!sbwrite_file(s, lfn)) {
return std::string("Cannot read source file: ") + lfn.u8string(); return std::string("Cannot read source file: ") + lfn.string();
} }
} }
return ""; return "";

View File

@@ -33,8 +33,8 @@
enum class SimpleDynamicTag { enum class SimpleDynamicTag {
UNINITIALIZED, UNINITIALIZED,
AUTO,
STRING, STRING,
TOKEN,
NUMBER, NUMBER,
BOOLEAN, BOOLEAN,
VECTOR, VECTOR,
@@ -55,9 +55,10 @@ struct SimpleDynamic {
static const char *type_name_of(SimpleDynamicTag t) { static const char *type_name_of(SimpleDynamicTag t) {
switch (t) { switch (t) {
case SimpleDynamicTag::UNINITIALIZED: return "uninitialized"; case SimpleDynamicTag::UNINITIALIZED: return "uninitialized";
case SimpleDynamicTag::STRING: return "string";
case SimpleDynamicTag::TOKEN: return "token";
case SimpleDynamicTag::BOOLEAN: return "boolean"; case SimpleDynamicTag::BOOLEAN: return "boolean";
case SimpleDynamicTag::NUMBER: return "number"; case SimpleDynamicTag::NUMBER: return "number";
case SimpleDynamicTag::STRING: return "string";
case SimpleDynamicTag::VECTOR: return "vector"; case SimpleDynamicTag::VECTOR: return "vector";
default: return "unknown"; default: return "unknown";
} }
@@ -71,14 +72,14 @@ struct SimpleDynamic {
type=SimpleDynamicTag::UNINITIALIZED; s.clear(); x=y=z=0; type=SimpleDynamicTag::UNINITIALIZED; s.clear(); x=y=z=0;
} }
void set_auto() {
type=SimpleDynamicTag::AUTO; s.clear(); x=y=z=0;
}
void set_string(std::string_view is) { void set_string(std::string_view is) {
type=SimpleDynamicTag::STRING; s=is; x=y=z=0; type=SimpleDynamicTag::STRING; s=is; x=y=z=0;
} }
void set_token(std::string_view is) {
type=SimpleDynamicTag::TOKEN; s=is; x=y=z=0;
}
void set_number(double n) { void set_number(double n) {
type = SimpleDynamicTag::NUMBER; s.clear(); x=n; y=z=0; type = SimpleDynamicTag::NUMBER; s.clear(); x=n; y=z=0;
} }
@@ -116,7 +117,6 @@ struct SimpleDynamic {
// void write_double(double data) // void write_double(double data)
// void write_length(size_t data) // void write_length(size_t data)
// void write_string(std::string_view data) // void write_string(std::string_view data)
// void write_simple_dynamic(const SimpleDynamic &sd);
// //
// You should derive from BaseWriter using the CRTP pattern: // You should derive from BaseWriter using the CRTP pattern:
// //
@@ -197,7 +197,6 @@ public:
// size_t read_length(); // size_t read_length();
// String read_string_limit(uint64_t size); // String read_string_limit(uint64_t size);
// String read_string(); // String read_string();
// SimpleDynamic read_simple_dynamic();
// //
// You should derive from BaseReader using the CRTP pattern: // You should derive from BaseReader using the CRTP pattern:
// //
@@ -501,17 +500,18 @@ public:
// Write a SimpleDynamic value. // Write a SimpleDynamic value.
// //
// This works regardless of what kind of string is present in the // This works regardless of what kind of data is present in the
// SimpleDynamic. // SimpleDynamic.
// //
template<class STRING> template<class STRING>
void write_simple_dynamic(const SimpleDynamic<STRING> &sd) { void write_simple_dynamic(const SimpleDynamic<STRING> &sd) {
write_simple_dynamic_tag(sd.type); write_simple_dynamic_tag(sd.type);
switch(sd.type) { switch(sd.type) {
case SimpleDynamicTag::STRING: write_string(sd.s); break;
case SimpleDynamicTag::TOKEN: write_string(sd.s); break;
case SimpleDynamicTag::NUMBER: write_double(sd.x); break; case SimpleDynamicTag::NUMBER: write_double(sd.x); break;
case SimpleDynamicTag::BOOLEAN: write_bool(sd.x == 1.0); 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::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); default: assert(false);
} }
} }
@@ -628,6 +628,8 @@ public:
void read_simple_dynamic(SimpleDynamic<STRING> *result) { void read_simple_dynamic(SimpleDynamic<STRING> *result) {
SimpleDynamicTag type = read_simple_dynamic_tag(); SimpleDynamicTag type = read_simple_dynamic_tag();
switch (type) { switch (type) {
case SimpleDynamicTag::STRING: result->set_string(read_string()); break;
case SimpleDynamicTag::TOKEN: result->set_token(read_string()); break;
case SimpleDynamicTag::NUMBER: result->set_number(read_double()); break; case SimpleDynamicTag::NUMBER: result->set_number(read_double()); break;
case SimpleDynamicTag::BOOLEAN: result->set_boolean(read_bool()); break; case SimpleDynamicTag::BOOLEAN: result->set_boolean(read_bool()); break;
case SimpleDynamicTag::VECTOR: { case SimpleDynamicTag::VECTOR: {
@@ -637,7 +639,6 @@ public:
result->set_vector(x,y,z); result->set_vector(x,y,z);
break; break;
} }
case SimpleDynamicTag::STRING: result->set_string(read_string()); break;
default: result->set_uninitialized(); break; default: result->set_uninitialized(); break;
} }
} }