Final refactor of basebuffer
This commit is contained in:
@@ -288,7 +288,7 @@ void UlxLuaCallLibrary::LuaCallArgument_string(UObject *context, const FString &
|
|||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
|
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
|
||||||
if (NotInitialized(sb)) return;
|
if (NotInitialized(sb)) return;
|
||||||
sb.write_simple_dynamic_tag(LuaValueType::STRING);
|
sb.write_lua_value_type(LuaValueType::STRING);
|
||||||
sb.write_string(pstring);
|
sb.write_string(pstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,7 +303,7 @@ void UlxLuaCallLibrary::LuaCallArgument_name(UObject *context, const FName &pnam
|
|||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
|
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
|
||||||
if (NotInitialized(sb)) return;
|
if (NotInitialized(sb)) return;
|
||||||
sb.write_simple_dynamic_tag(LuaValueType::TOKEN);
|
sb.write_lua_value_type(LuaValueType::TOKEN);
|
||||||
sb.write_string(namestr);
|
sb.write_string(namestr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +311,7 @@ void UlxLuaCallLibrary::LuaCallArgument_float(UObject *context, double pfloat) {
|
|||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
|
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
|
||||||
if (NotInitialized(sb)) return;
|
if (NotInitialized(sb)) return;
|
||||||
sb.write_simple_dynamic_tag(LuaValueType::NUMBER);
|
sb.write_lua_value_type(LuaValueType::NUMBER);
|
||||||
sb.write_double(pfloat);
|
sb.write_double(pfloat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,7 +319,7 @@ void UlxLuaCallLibrary::LuaCallArgument_int(UObject *context, int value) {
|
|||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
|
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
|
||||||
if (NotInitialized(sb)) return;
|
if (NotInitialized(sb)) return;
|
||||||
sb.write_simple_dynamic_tag(LuaValueType::NUMBER);
|
sb.write_lua_value_type(LuaValueType::NUMBER);
|
||||||
sb.write_double(value);
|
sb.write_double(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,7 +327,7 @@ void UlxLuaCallLibrary::LuaCallArgument_vector(UObject *context, const FVector &
|
|||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
|
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
|
||||||
if (NotInitialized(sb)) return;
|
if (NotInitialized(sb)) return;
|
||||||
sb.write_simple_dynamic_tag(LuaValueType::VECTOR);
|
sb.write_lua_value_type(LuaValueType::VECTOR);
|
||||||
sb.write_fvector(pvector);
|
sb.write_fvector(pvector);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,7 +335,7 @@ void UlxLuaCallLibrary::LuaCallArgument_vector2d(UObject *context, const FVector
|
|||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
|
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
|
||||||
if (NotInitialized(sb)) return;
|
if (NotInitialized(sb)) return;
|
||||||
sb.write_simple_dynamic_tag(LuaValueType::VECTOR);
|
sb.write_lua_value_type(LuaValueType::VECTOR);
|
||||||
sb.write_double(pvector.X);
|
sb.write_double(pvector.X);
|
||||||
sb.write_double(pvector.Y);
|
sb.write_double(pvector.Y);
|
||||||
sb.write_double(0.0);
|
sb.write_double(0.0);
|
||||||
@@ -345,7 +345,7 @@ void UlxLuaCallLibrary::LuaCallArgument_boolean(UObject *context, bool pbool) {
|
|||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
|
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
|
||||||
if (NotInitialized(sb)) return;
|
if (NotInitialized(sb)) return;
|
||||||
sb.write_simple_dynamic_tag(LuaValueType::BOOLEAN);
|
sb.write_lua_value_type(LuaValueType::BOOLEAN);
|
||||||
sb.write_bool(pbool);
|
sb.write_bool(pbool);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,7 +375,7 @@ bool UlxLuaValues::Initialize(std::string_view data)
|
|||||||
|
|
||||||
while (!Decoder.empty())
|
while (!Decoder.empty())
|
||||||
{
|
{
|
||||||
LuaValueType Tag = Decoder.read_simple_dynamic_tag();
|
LuaValueType Tag = Decoder.read_lua_value_type();
|
||||||
|
|
||||||
int64 Pos = Decoder.total_reads();
|
int64 Pos = Decoder.total_reads();
|
||||||
ElxLuaValueType Type;
|
ElxLuaValueType Type;
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ private:
|
|||||||
bool err_integer_truncated_;
|
bool err_integer_truncated_;
|
||||||
public:
|
public:
|
||||||
using string_type = std::string;
|
using string_type = std::string;
|
||||||
|
using fvector_type = FVector;
|
||||||
|
using dvector_type = FVector;
|
||||||
|
using luavalue_type = BaseLuaValue<std::string>;
|
||||||
void *basebuffer_malloc(size_t size) { return malloc(size); }
|
void *basebuffer_malloc(size_t size) { return malloc(size); }
|
||||||
void basebuffer_free(void *p) { free(p); }
|
void basebuffer_free(void *p) { free(p); }
|
||||||
void clear_error_flags() { err_eof_on_read_ = err_string_too_long_ = err_integer_truncated_ = false; }
|
void clear_error_flags() { err_eof_on_read_ = err_string_too_long_ = err_integer_truncated_ = false; }
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ eng::string AnimStepEditor::encode() const {
|
|||||||
const AnimValue &value = pair.second;
|
const AnimValue &value = pair.second;
|
||||||
sb.write_string(name);
|
sb.write_string(name);
|
||||||
sb.write_bool(value.persistent);
|
sb.write_bool(value.persistent);
|
||||||
sb.write_simple_dynamic(value);
|
sb.write_lua_value(value);
|
||||||
}
|
}
|
||||||
return eng::string(sb.view());
|
return eng::string(sb.view());
|
||||||
}
|
}
|
||||||
@@ -142,7 +142,7 @@ void AnimStepEditor::decode(std::string_view s) {
|
|||||||
eng::string name = sb.read_string();
|
eng::string name = sb.read_string();
|
||||||
AnimValue &value = map_[name];
|
AnimValue &value = map_[name];
|
||||||
value.persistent = sb.read_bool();
|
value.persistent = sb.read_bool();
|
||||||
sb.read_simple_dynamic(&value);
|
sb.read_lua_value(&value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,9 +156,9 @@ void AnimStepEditor::decode_persistent(std::string_view s) {
|
|||||||
if (persistent) {
|
if (persistent) {
|
||||||
AnimValue &value = map_[name];
|
AnimValue &value = map_[name];
|
||||||
value.persistent = persistent;
|
value.persistent = persistent;
|
||||||
sb.read_simple_dynamic(&value);
|
sb.read_lua_value(&value);
|
||||||
} else {
|
} else {
|
||||||
sb.read_simple_dynamic(&dummy);
|
sb.read_lua_value(&dummy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -349,7 +349,7 @@ void AnimCoreState::decode(std::string_view s) {
|
|||||||
while (!sb.empty()) {
|
while (!sb.empty()) {
|
||||||
eng::string name = sb.read_string();
|
eng::string name = sb.read_string();
|
||||||
bool persistent = sb.read_bool();
|
bool persistent = sb.read_bool();
|
||||||
sb.read_simple_dynamic(&value);
|
sb.read_lua_value(&value);
|
||||||
if (persistent) {
|
if (persistent) {
|
||||||
if ((name == "xyz") && (value.type == LuaValueType::VECTOR)) xyz = util::DXYZ(value.x, value.y, value.z);
|
if ((name == "xyz") && (value.type == LuaValueType::VECTOR)) xyz = util::DXYZ(value.x, value.y, value.z);
|
||||||
if ((name == "plane") && (value.type == LuaValueType::STRING)) plane = value.s;
|
if ((name == "plane") && (value.type == LuaValueType::STRING)) plane = value.s;
|
||||||
|
|||||||
@@ -79,7 +79,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_simple_dynamic(value)
|
// write_lua_value(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
|
||||||
|
|||||||
@@ -255,6 +255,7 @@ class ReplayLogfile : public std::ifstream {
|
|||||||
using std::ifstream::ifstream;
|
using std::ifstream::ifstream;
|
||||||
using DD = DataDeserializer<ReplayLogfile>;
|
using DD = DataDeserializer<ReplayLogfile>;
|
||||||
public:
|
public:
|
||||||
|
using string_type = std::string;
|
||||||
void read_bytes_into(char *n, size_t size) {
|
void read_bytes_into(char *n, size_t size) {
|
||||||
read(n, size);
|
read(n, size);
|
||||||
if (!good()) {
|
if (!good()) {
|
||||||
|
|||||||
@@ -248,6 +248,9 @@ using LuaValue = BaseLuaValue<eng::string>;
|
|||||||
class StreamBufferConfig {
|
class StreamBufferConfig {
|
||||||
public:
|
public:
|
||||||
using string_type = eng::string;
|
using string_type = eng::string;
|
||||||
|
using fvector_type = util::XYZ;
|
||||||
|
using dvector_type = util::DXYZ;
|
||||||
|
using luavalue_type = LuaValue;
|
||||||
void *basebuffer_malloc(size_t size) { return eng::malloc(size); }
|
void *basebuffer_malloc(size_t size) { return eng::malloc(size); }
|
||||||
void basebuffer_free(void *p) { eng::free(p); }
|
void basebuffer_free(void *p) { eng::free(p); }
|
||||||
void clear_error_flags() { }
|
void clear_error_flags() { }
|
||||||
@@ -260,50 +263,16 @@ class StreamBuffer : public eng::nevernew, public BaseBuffer<StreamBufferConfig>
|
|||||||
public:
|
public:
|
||||||
using BaseBuffer::BaseBuffer;
|
using BaseBuffer::BaseBuffer;
|
||||||
|
|
||||||
void write_xyz(const util::XYZ &xyz) {
|
|
||||||
write_float(xyz.x);
|
|
||||||
write_float(xyz.y);
|
|
||||||
write_float(xyz.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_dxyz(const util::DXYZ &xyz) {
|
|
||||||
write_double(xyz.x);
|
|
||||||
write_double(xyz.y);
|
|
||||||
write_double(xyz.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_hashvalue(const util::HashValue &h) {
|
void write_hashvalue(const util::HashValue &h) {
|
||||||
write_uint64(h.first);
|
write_uint64(h.first);
|
||||||
write_uint64(h.second);
|
write_uint64(h.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
util::XYZ read_xyz() {
|
|
||||||
float x = read_float();
|
|
||||||
float y = read_float();
|
|
||||||
float z = read_float();
|
|
||||||
return util::XYZ(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
util::DXYZ read_dxyz() {
|
|
||||||
double x = read_double();
|
|
||||||
double y = read_double();
|
|
||||||
double z = read_double();
|
|
||||||
return util::DXYZ(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
util::HashValue read_hashvalue() {
|
util::HashValue read_hashvalue() {
|
||||||
uint64_t f = read_uint64();
|
uint64_t f = read_uint64();
|
||||||
uint64_t s = read_uint64();
|
uint64_t s = read_uint64();
|
||||||
return util::HashValue(f, s);
|
return util::HashValue(f, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool contents_equal(const StreamBuffer *sb) {
|
|
||||||
return view() == sb->view();
|
|
||||||
}
|
|
||||||
|
|
||||||
void copy_into(StreamBuffer *sb) {
|
|
||||||
sb->write_bytes(view());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use a streambuffer as a lua_writer.
|
// Use a streambuffer as a lua_writer.
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
// Read a serialized LuaValue value from the
|
// Read a serialized LuaValue value from the
|
||||||
// streambuffer and push it onto the lua stack.
|
// streambuffer and push it onto the lua stack.
|
||||||
void push_simple_dynamic(lua_State *L, StreamBuffer *sb) {
|
void push_simple_dynamic(lua_State *L, StreamBuffer *sb) {
|
||||||
LuaValueType type = sb->read_simple_dynamic_tag();
|
LuaValueType type = sb->read_lua_value_type();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case LuaValueType::STRING: {
|
case LuaValueType::STRING: {
|
||||||
std::string_view s = sb->read_string_view();
|
std::string_view s = sb->read_string_view();
|
||||||
@@ -56,25 +56,25 @@ void push_simple_dynamic(lua_State *L, StreamBuffer *sb) {
|
|||||||
bool encode_simple_dynamic(LuaCoreStack &LS, LuaSlot &slot, StreamBuffer *sb) {
|
bool encode_simple_dynamic(LuaCoreStack &LS, LuaSlot &slot, StreamBuffer *sb) {
|
||||||
switch (LS.type(slot)) {
|
switch (LS.type(slot)) {
|
||||||
case LUA_TSTRING:
|
case LUA_TSTRING:
|
||||||
sb->write_simple_dynamic_tag(LuaValueType::STRING);
|
sb->write_lua_value_type(LuaValueType::STRING);
|
||||||
sb->write_string(LS.ckstringview(slot));
|
sb->write_string(LS.ckstringview(slot));
|
||||||
return true;
|
return true;
|
||||||
case LUA_TLIGHTUSERDATA:
|
case LUA_TLIGHTUSERDATA:
|
||||||
sb->write_simple_dynamic_tag(LuaValueType::TOKEN);
|
sb->write_lua_value_type(LuaValueType::TOKEN);
|
||||||
sb->write_string(LS.cktoken(slot).str());
|
sb->write_string(LS.cktoken(slot).str());
|
||||||
return true;
|
return true;
|
||||||
case LUA_TNUMBER:
|
case LUA_TNUMBER:
|
||||||
sb->write_simple_dynamic_tag(LuaValueType::NUMBER);
|
sb->write_lua_value_type(LuaValueType::NUMBER);
|
||||||
sb->write_double(LS.cknumber(slot));
|
sb->write_double(LS.cknumber(slot));
|
||||||
return true;
|
return true;
|
||||||
case LUA_TBOOLEAN:
|
case LUA_TBOOLEAN:
|
||||||
sb->write_simple_dynamic_tag(LuaValueType::BOOLEAN);
|
sb->write_lua_value_type(LuaValueType::BOOLEAN);
|
||||||
sb->write_bool(LS.ckboolean(slot));
|
sb->write_bool(LS.ckboolean(slot));
|
||||||
return true;
|
return true;
|
||||||
case LUA_TTABLE: {
|
case LUA_TTABLE: {
|
||||||
std::optional<util::DXYZ> xyz = LS.tryxyz(slot);
|
std::optional<util::DXYZ> xyz = LS.tryxyz(slot);
|
||||||
if (!xyz.has_value()) return false;
|
if (!xyz.has_value()) return false;
|
||||||
sb->write_simple_dynamic_tag(LuaValueType::VECTOR);
|
sb->write_lua_value_type(LuaValueType::VECTOR);
|
||||||
sb->write_dxyz(xyz.value());
|
sb->write_dxyz(xyz.value());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -480,7 +480,7 @@ void World::probe_lua_call(int64_t actor_id, int64_t place_id, std::string_view
|
|||||||
// return value of the function.
|
// return value of the function.
|
||||||
//
|
//
|
||||||
int64_t rv_base = retvals->total_writes();
|
int64_t rv_base = retvals->total_writes();
|
||||||
retvals->write_simple_dynamic_tag(LuaValueType::STRING);
|
retvals->write_lua_value_type(LuaValueType::STRING);
|
||||||
retvals->write_string(msg);
|
retvals->write_string(msg);
|
||||||
|
|
||||||
if (msg.empty()) {
|
if (msg.empty()) {
|
||||||
@@ -509,7 +509,7 @@ void World::probe_lua_call(int64_t actor_id, int64_t place_id, std::string_view
|
|||||||
if (!ok) {
|
if (!ok) {
|
||||||
msg = util::ss("Lua function ",classname,".",funcname," returned a non-serializable value");
|
msg = util::ss("Lua function ",classname,".",funcname," returned a non-serializable value");
|
||||||
retvals->unwrite_to(rv_base);
|
retvals->unwrite_to(rv_base);
|
||||||
retvals->write_simple_dynamic_tag(LuaValueType::STRING);
|
retvals->write_lua_value_type(LuaValueType::STRING);
|
||||||
retvals->write_string(msg);
|
retvals->write_string(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
@@ -109,12 +110,15 @@ struct BaseLuaValue {
|
|||||||
//
|
//
|
||||||
// To serialize, first construct a DataSerializer, passing
|
// To serialize, first construct a DataSerializer, passing
|
||||||
// in a pointer to an output device. An output device is
|
// in a pointer to an output device. An output device is
|
||||||
// any class that has these methods:
|
// any class that has these methods and type aliases:
|
||||||
//
|
|
||||||
// void write_bytes(char *data, size_t len);
|
|
||||||
//
|
//
|
||||||
|
// void write_bytes(const char *data, size_t len);
|
||||||
// void raise_integer_truncated();
|
// void raise_integer_truncated();
|
||||||
//
|
//
|
||||||
|
// using fvector_type = ...; // needed for write_xyz
|
||||||
|
// using dvector_type = ...; // needed for write_dxyz
|
||||||
|
// using luavalue_type = ...; // needed for write_lua_value
|
||||||
|
//
|
||||||
// After constructing the DataSerializer, call write_int,
|
// After constructing the DataSerializer, call write_int,
|
||||||
// write_float, write_string, or the like. The data will be
|
// write_float, write_string, or the like. The data will be
|
||||||
// written to the output device using write_bytes. If
|
// written to the output device using write_bytes. If
|
||||||
@@ -176,6 +180,44 @@ public:
|
|||||||
write_length(s.size());
|
write_length(s.size());
|
||||||
output_->write_bytes(s.data(), s.size());
|
output_->write_bytes(s.data(), s.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_lua_value_type(LuaValueType tag) {
|
||||||
|
write_uint8(uint8_t(tag));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FV>
|
||||||
|
void write_xyz(const FV &v) {
|
||||||
|
static_assert(std::is_same_v<FV, typename OutputDevice::fvector_type>);
|
||||||
|
if constexpr (requires { v.x; }) {
|
||||||
|
write_float(v.x); write_float(v.y); write_float(v.z);
|
||||||
|
} else {
|
||||||
|
write_float(v.X); write_float(v.Y); write_float(v.Z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class DV>
|
||||||
|
void write_dxyz(const DV &v) {
|
||||||
|
static_assert(std::is_same_v<DV, typename OutputDevice::dvector_type>);
|
||||||
|
if constexpr (requires { v.x; }) {
|
||||||
|
write_double(v.x); write_double(v.y); write_double(v.z);
|
||||||
|
} else {
|
||||||
|
write_double(v.X); write_double(v.Y); write_double(v.Z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class LV>
|
||||||
|
void write_lua_value(const LV &sd) {
|
||||||
|
static_assert(std::is_same_v<LV, typename OutputDevice::luavalue_type>);
|
||||||
|
write_lua_value_type(sd.type);
|
||||||
|
switch(sd.type) {
|
||||||
|
case LuaValueType::STRING: write_string(sd.s); break;
|
||||||
|
case LuaValueType::TOKEN: write_string(sd.s); break;
|
||||||
|
case LuaValueType::NUMBER: write_double(sd.x); break;
|
||||||
|
case LuaValueType::BOOLEAN: write_bool(sd.x == 1.0); break;
|
||||||
|
case LuaValueType::VECTOR: write_double(sd.x); write_double(sd.y); write_double(sd.z); break;
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -189,11 +231,16 @@ public:
|
|||||||
//
|
//
|
||||||
// To deserialize, first construct a DataDeserializer, passing
|
// To deserialize, first construct a DataDeserializer, passing
|
||||||
// in a pointer to an input device. An input device is
|
// in a pointer to an input device. An input device is
|
||||||
// any class that has these methods:
|
// any class that has these methods and type aliases:
|
||||||
//
|
//
|
||||||
// void read_bytes_into(char *data, size_t len);
|
// void read_bytes_into(char *data, size_t len);
|
||||||
// void raise_string_too_long();
|
// void raise_string_too_long();
|
||||||
//
|
//
|
||||||
|
// using string_type = ...; // needed for read_string
|
||||||
|
// using fvector_type = ...; // needed for read_xyz
|
||||||
|
// using dvector_type = ...; // needed for read_dxyz
|
||||||
|
// using luavalue_type = ...; // needed for read_lua_value
|
||||||
|
//
|
||||||
// After constructing the DataDeserializer, call read_int,
|
// After constructing the DataDeserializer, call read_int,
|
||||||
// read_float, read_string, or the like. The data will be
|
// read_float, read_string, or the like. The data will be
|
||||||
// read from the input device using read_bytes_into. If
|
// read from the input device using read_bytes_into. If
|
||||||
@@ -208,7 +255,7 @@ public:
|
|||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<class InputDevice, class StringType = std::string>
|
template<class InputDevice>
|
||||||
class DataDeserializer {
|
class DataDeserializer {
|
||||||
private:
|
private:
|
||||||
InputDevice *input_;
|
InputDevice *input_;
|
||||||
@@ -243,20 +290,57 @@ public:
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringType read_string_limit(uint64_t limit) {
|
auto read_string_limit(uint64_t limit) {
|
||||||
|
using ST = typename InputDevice::string_type;
|
||||||
size_t len = read_length();
|
size_t len = read_length();
|
||||||
if (len > limit) {
|
if (len > limit) {
|
||||||
input_->raise_string_too_long();
|
input_->raise_string_too_long();
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
StringType result(len, ' ');
|
ST result(len, ' ');
|
||||||
input_->read_bytes_into(&(result[0]), len);
|
input_->read_bytes_into(&(result[0]), len);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringType read_string() {
|
auto read_string() {
|
||||||
return read_string_limit(0x1000000); // 16MB limit default
|
return read_string_limit(0x1000000); // 16MB limit default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto read_xyz() {
|
||||||
|
using FV = typename InputDevice::fvector_type;
|
||||||
|
float x = read_float(), y = read_float(), z = read_float();
|
||||||
|
return FV(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto read_dxyz() {
|
||||||
|
using DV = typename InputDevice::dvector_type;
|
||||||
|
double x = read_double(), y = read_double(), z = read_double();
|
||||||
|
return DV(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
LuaValueType read_lua_value_type() {
|
||||||
|
return LuaValueType(read_uint8());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class LV>
|
||||||
|
void read_lua_value(LV *result) {
|
||||||
|
static_assert(std::is_same_v<LV, typename InputDevice::luavalue_type>);
|
||||||
|
LuaValueType type = read_lua_value_type();
|
||||||
|
switch (type) {
|
||||||
|
case LuaValueType::STRING: result->set_string(read_string()); break;
|
||||||
|
case LuaValueType::TOKEN: result->set_token(read_string()); break;
|
||||||
|
case LuaValueType::NUMBER: result->set_number(read_double()); break;
|
||||||
|
case LuaValueType::BOOLEAN: result->set_boolean(read_bool()); break;
|
||||||
|
case LuaValueType::VECTOR: {
|
||||||
|
double x=read_double();
|
||||||
|
double y=read_double();
|
||||||
|
double z=read_double();
|
||||||
|
result->set_vector(x,y,z);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: result->set_uninitialized(); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////
|
||||||
@@ -265,9 +349,13 @@ public:
|
|||||||
//
|
//
|
||||||
// You must supply a BaseBufferConfig which must define these:
|
// You must supply a BaseBufferConfig which must define these:
|
||||||
//
|
//
|
||||||
// using string_type = std::string; // or compatible
|
// using string_type = ...; // string type for read_string
|
||||||
|
// using fvector_type = ...; // vector type for read/write_xyz
|
||||||
|
// using dvector_type = ...; // vector type for read/write_dxyz
|
||||||
|
// using luavalue_type = ...; // lua value type for read/write_lua_value
|
||||||
// void *basebuffer_malloc(size_t size);
|
// void *basebuffer_malloc(size_t size);
|
||||||
// void basebuffer_free(void *data);
|
// void basebuffer_free(void *data);
|
||||||
|
// void clear_error_flags();
|
||||||
// void raise_eof_on_read();
|
// void raise_eof_on_read();
|
||||||
// void raise_string_too_long();
|
// void raise_string_too_long();
|
||||||
// void raise_integer_truncated();
|
// void raise_integer_truncated();
|
||||||
@@ -297,10 +385,13 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
using string_type = typename BaseBufferConfig::string_type;
|
using string_type = typename BaseBufferConfig::string_type;
|
||||||
|
using fvector_type = typename BaseBufferConfig::fvector_type;
|
||||||
|
using dvector_type = typename BaseBufferConfig::dvector_type;
|
||||||
|
using luavalue_type = typename BaseBufferConfig::luavalue_type;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using DS = DataSerializer<BaseBuffer<BaseBufferConfig>>;
|
using DS = DataSerializer<BaseBuffer<BaseBufferConfig>>;
|
||||||
using DD = DataDeserializer<BaseBuffer<BaseBufferConfig>, string_type>;
|
using DD = DataDeserializer<BaseBuffer<BaseBufferConfig>>;
|
||||||
|
|
||||||
void init(bool fixed, bool owned, char *buf, int64_t size) {
|
void init(bool fixed, bool owned, char *buf, int64_t size) {
|
||||||
BaseBufferConfig::clear_error_flags();
|
BaseBufferConfig::clear_error_flags();
|
||||||
@@ -442,45 +533,16 @@ public:
|
|||||||
write_bytes(s.data(), s.size());
|
write_bytes(s.data(), s.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write methods — delegate to DataSerializer.
|
// Copy the contents of this buffer into another buffer.
|
||||||
//
|
//
|
||||||
void write_uint8(uint64_t data) { DS(this).write_uint8(data); }
|
void copy_into(BaseBuffer *sb) {
|
||||||
void write_uint16(uint64_t data) { DS(this).write_uint16(data); }
|
sb->write_bytes(view());
|
||||||
void write_uint32(uint64_t data) { DS(this).write_uint32(data); }
|
|
||||||
void write_uint64(uint64_t data) { DS(this).write_uint64(data); }
|
|
||||||
void write_int8(int64_t data) { DS(this).write_int8(data); }
|
|
||||||
void write_int16(int64_t data) { DS(this).write_int16(data); }
|
|
||||||
void write_int32(int64_t data) { DS(this).write_int32(data); }
|
|
||||||
void write_int64(int64_t data) { DS(this).write_int64(data); }
|
|
||||||
void write_bool(bool b) { DS(this).write_bool(b); }
|
|
||||||
void write_char(char c) { DS(this).write_char(c); }
|
|
||||||
void write_float(float arg) { DS(this).write_float(arg); }
|
|
||||||
void write_double(double arg) { DS(this).write_double(arg); }
|
|
||||||
void write_length(size_t len) { DS(this).write_length(len); }
|
|
||||||
void write_string(std::string_view s) { DS(this).write_string(s); }
|
|
||||||
|
|
||||||
// Write a LuaValueType.
|
|
||||||
//
|
|
||||||
void write_simple_dynamic_tag(LuaValueType tag) {
|
|
||||||
write_uint8(uint8_t(tag));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a BaseLuaValue value.
|
// Check if the contents of this buffer are equal to another.
|
||||||
//
|
//
|
||||||
// This works regardless of what kind of data is present in the
|
bool contents_equal(const BaseBuffer *sb) const {
|
||||||
// BaseLuaValue.
|
return view() == sb->view();
|
||||||
//
|
|
||||||
template<class STRING>
|
|
||||||
void write_simple_dynamic(const BaseLuaValue<STRING> &sd) {
|
|
||||||
write_simple_dynamic_tag(sd.type);
|
|
||||||
switch(sd.type) {
|
|
||||||
case LuaValueType::STRING: write_string(sd.s); break;
|
|
||||||
case LuaValueType::TOKEN: write_string(sd.s); break;
|
|
||||||
case LuaValueType::NUMBER: write_double(sd.x); break;
|
|
||||||
case LuaValueType::BOOLEAN: write_bool(sd.x == 1.0); break;
|
|
||||||
case LuaValueType::VECTOR: write_double(sd.x); write_double(sd.y); write_double(sd.z); break;
|
|
||||||
default: assert(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read bytes into a caller-supplied buffer.
|
// Read bytes into a caller-supplied buffer.
|
||||||
@@ -517,6 +579,28 @@ public:
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Write methods — delegate to DataSerializer.
|
||||||
|
//
|
||||||
|
void write_uint8(uint64_t data) { DS(this).write_uint8(data); }
|
||||||
|
void write_uint16(uint64_t data) { DS(this).write_uint16(data); }
|
||||||
|
void write_uint32(uint64_t data) { DS(this).write_uint32(data); }
|
||||||
|
void write_uint64(uint64_t data) { DS(this).write_uint64(data); }
|
||||||
|
void write_int8(int64_t data) { DS(this).write_int8(data); }
|
||||||
|
void write_int16(int64_t data) { DS(this).write_int16(data); }
|
||||||
|
void write_int32(int64_t data) { DS(this).write_int32(data); }
|
||||||
|
void write_int64(int64_t data) { DS(this).write_int64(data); }
|
||||||
|
void write_bool(bool b) { DS(this).write_bool(b); }
|
||||||
|
void write_char(char c) { DS(this).write_char(c); }
|
||||||
|
void write_float(float arg) { DS(this).write_float(arg); }
|
||||||
|
void write_double(double arg) { DS(this).write_double(arg); }
|
||||||
|
void write_length(size_t len) { DS(this).write_length(len); }
|
||||||
|
void write_string(std::string_view s) { DS(this).write_string(s); }
|
||||||
|
void write_lua_value_type(LuaValueType tag) { DS(this).write_lua_value_type(tag); }
|
||||||
|
void write_xyz(const fvector_type &v) { DS(this).write_xyz(v); }
|
||||||
|
void write_dxyz(const dvector_type &v) { DS(this).write_dxyz(v); }
|
||||||
|
void write_lua_value(const luavalue_type &sd) { DS(this).write_lua_value(sd); }
|
||||||
|
|
||||||
// Read methods — delegate to DataDeserializer.
|
// Read methods — delegate to DataDeserializer.
|
||||||
//
|
//
|
||||||
uint8_t read_uint8() { return DD(this).read_uint8(); }
|
uint8_t read_uint8() { return DD(this).read_uint8(); }
|
||||||
@@ -534,6 +618,10 @@ public:
|
|||||||
size_t read_length() { return DD(this).read_length(); }
|
size_t read_length() { return DD(this).read_length(); }
|
||||||
string_type read_string_limit(uint64_t limit) { return DD(this).read_string_limit(limit); }
|
string_type read_string_limit(uint64_t limit) { return DD(this).read_string_limit(limit); }
|
||||||
string_type read_string() { return DD(this).read_string(); }
|
string_type read_string() { return DD(this).read_string(); }
|
||||||
|
LuaValueType read_lua_value_type() { return DD(this).read_lua_value_type(); }
|
||||||
|
fvector_type read_xyz() { return DD(this).read_xyz(); }
|
||||||
|
dvector_type read_dxyz() { return DD(this).read_dxyz(); }
|
||||||
|
void read_lua_value(luavalue_type *result) { DD(this).read_lua_value(result); }
|
||||||
|
|
||||||
// Read a string as a string_view.
|
// Read a string as a string_view.
|
||||||
//
|
//
|
||||||
@@ -562,33 +650,6 @@ public:
|
|||||||
return read_string_view_limit(0x1000000);
|
return read_string_view_limit(0x1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a LuaValueType
|
|
||||||
//
|
|
||||||
LuaValueType read_simple_dynamic_tag() {
|
|
||||||
return LuaValueType(read_uint8());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read a BaseLuaValue
|
|
||||||
//
|
|
||||||
template<class STRING>
|
|
||||||
void read_simple_dynamic(BaseLuaValue<STRING> *result) {
|
|
||||||
LuaValueType type = read_simple_dynamic_tag();
|
|
||||||
switch (type) {
|
|
||||||
case LuaValueType::STRING: result->set_string(read_string()); break;
|
|
||||||
case LuaValueType::TOKEN: result->set_token(read_string()); break;
|
|
||||||
case LuaValueType::NUMBER: result->set_number(read_double()); break;
|
|
||||||
case LuaValueType::BOOLEAN: result->set_boolean(read_bool()); break;
|
|
||||||
case LuaValueType::VECTOR: {
|
|
||||||
double x=read_double();
|
|
||||||
double y=read_double();
|
|
||||||
double z=read_double();
|
|
||||||
result->set_vector(x,y,z);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: result->set_uninitialized(); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to do a "readline". If there is no newline in
|
// Attempt to do a "readline". If there is no newline in
|
||||||
// the buffer, returns empty string. If there is a newline,
|
// the buffer, returns empty string. If there is a newline,
|
||||||
// returns a block of text that ends in newline.
|
// returns a block of text that ends in newline.
|
||||||
|
|||||||
Reference in New Issue
Block a user