hproselet/hprose_types.hpp

697 lines
22 KiB
C++
Raw Permalink Normal View History

2022-12-15 02:05:06 +00:00
#ifndef _HPROSE_TYPES_HPP_
#define _HPROSE_TYPES_HPP_
#include <vector>
#include <functional>
#include <cmath>
#include <map>
#include <unordered_map>
#include <atomic>
#include "hprose_ed.hpp"
template<typename T>
struct StdFuncType { using type = void; };
template<typename RET, typename CLASS, typename... ARGS>
struct StdFuncType<RET(CLASS::*)(ARGS...) const> { using type = std::function<RET(ARGS...)>; };
template<typename RET, typename CLASS, typename... ARGS>
struct StdFuncType<RET(CLASS::*)(ARGS...)> { using type = std::function<RET(ARGS...)>; };
template<typename HANDLER>
struct FunctionType { using type = typename StdFuncType<decltype(&HANDLER::operator())>::type; };
template<typename RET, typename... ARGS>
struct FunctionType<RET(*)(ARGS...)> { using type = std::function<RET(ARGS...)>; };
template<typename RET, typename CLASS, typename... ARGS>
struct FunctionType<RET(CLASS::*)(ARGS...)> { using type = RET(CLASS::*)(ARGS...); };
template<typename RET, typename CLASS, typename... ARGS>
struct FunctionType<RET(CLASS::*)(ARGS...) const> { using type = RET(CLASS::*)(ARGS...) const; };
template<int32_t INDEX, typename TYPE, typename FIRST, typename... REST>
struct IndexOfTypeHelper {
static constexpr int32_t value = std::conditional_t<std::is_same<TYPE, FIRST>::value, std::integral_constant<int32_t, INDEX>, IndexOfTypeHelper<INDEX + 1, TYPE, REST...>>::value;
};
template<int32_t INDEX, typename TYPE, typename ARG>
struct IndexOfTypeHelper<INDEX, TYPE, ARG> {
static constexpr int32_t value = std::conditional_t<std::is_same<TYPE, ARG>::value, std::integral_constant<int32_t, INDEX>, std::integral_constant<int32_t, -1>>::value;
};
template<typename T, typename... ARGS>
struct IndexOfType { static constexpr int32_t value = IndexOfTypeHelper<0, T, ARGS...>::value; };
template<typename T>
struct IndexOfType<T> { static constexpr int32_t value = -1; };
class HproseError {
public:
HproseError() : is_null(true) {}
HproseError(const std::string& msg) : is_null(false), errmsg(msg) {}
HproseError(std::string&& msg) : is_null(false), errmsg(std::move(msg)) {}
bool IsNull() const { return is_null; }
const std::string& Message() const { return errmsg; }
operator bool () { return !is_null; }
protected:
bool is_null;
std::string errmsg;
};
struct HproseValueHelperError {
HproseError FromReader(HproseReader& reader) {
reader.CheckTag(Tags::Null, true);
return HproseError();
}
bool ToWriterWithResultTag(const HproseError& err, HproseWriter& writer) {
if(err.IsNull())
writer.WriteTag(Tags::Result);
else
writer.WriteTag(Tags::Error);
ToWriter(err, writer);
return !err.IsNull();
}
void ToWriter(const HproseError& err, HproseWriter& writer) {
if(err.IsNull())
writer.WriteTag(Tags::Null);
else {
const std::string& errmsg = err.Message();
writer.WriteTag(Tags::String);
writer.WriteLength(errmsg.length());
writer.WriteTag(Tags::Quote);
writer.WriteString(errmsg);
writer.WriteTag(Tags::Quote);
}
}
};
struct HproseValueHelperNull {
bool ToWriterWithResultTag(HproseWriter& writer) {
writer.WriteTag(Tags::Result);
writer.WriteTag(Tags::Null);
return false;
}
void ToWriter(HproseWriter& writer) {
writer.WriteTag(Tags::Null);
}
};
struct HproseValueHelperInteger {
int64_t FromReader(HproseReader& r) {
auto tag = r.ReadTag();
switch(tag) {
case Tags::Null: return 0;
case Tags::Empty: return 0;
case Tags::Num0: return 0;
case Tags::Num1: return 1;
case Tags::Num2: return 2;
case Tags::Num3: return 3;
case Tags::Num4: return 4;
case Tags::Num5: return 5;
case Tags::Num6: return 6;
case Tags::Num7: return 7;
case Tags::Num8: return 8;
case Tags::Num9: return 9;
case Tags::False: return 0;
case Tags::True: return 1;
case Tags::NaN: return 0;
case Tags::Infinity: {
r.ReadTag();
return 0;
}
case Tags::Integer:
case Tags::Long: { // golang use big.int to decode Long
return r.ReadInt64Raw(Tags::Semicolon);
}
case Tags::Double: {
return int64_t(strtod(r.ReadUntilAsString(Tags::Semicolon).data(), nullptr));
}
case Tags::UTF8Char: {
return strtoll(r.ReadUTF8String(1).data(), nullptr, 10);
}
case Tags::String: {
return strtoll(r.ReadUTF8String(r.ReadInt64Raw(Tags::Quote)).data(), nullptr, 10);
}
case Tags::Bytes: {
return strtoll(r.ReadBytesAsString(r.ReadInt64Raw(Tags::Quote)).data(), nullptr, 10);
}
default: {
r.SkipValue(tag);
return 0;
}
}
}
bool ToWriterWithResultTag(int64_t value, HproseWriter& writer) {
writer.WriteTag(Tags::Result);
ToWriter(value, writer);
return false;
}
void ToWriter(int64_t value, HproseWriter& writer) {
if(value >= 0 && value <= 9) {
writer.WriteByte(value + '0');
return;
}
if(value >= -0xffffffff && value <= 0xffffffff)
writer.WriteTag(Tags::Integer);
else
writer.WriteTag(Tags::Long);
writer.WriteInteger(value);
writer.WriteTag(Tags::Semicolon);
}
};
struct HproseValueHelperBool {
bool FromReader(HproseReader& r) {
auto tag = r.ReadTag();
switch(tag) {
case Tags::Null:
case Tags::Empty:
case Tags::Num0: return false;
case Tags::Num1:
case Tags::Num2:
case Tags::Num3:
case Tags::Num4:
case Tags::Num5:
case Tags::Num6:
case Tags::Num7:
case Tags::Num8:
case Tags::Num9: return true;
case Tags::False: return false;
case Tags::True: return true;
case Tags::NaN: return false;
case Tags::Infinity: {
r.ReadTag();
return true;
}
case Tags::Integer:
case Tags::Long: {
return r.ReadInt64Raw(Tags::Semicolon) != 0;
}
case Tags::Double: {
return strtod(r.ReadUntilAsString(Tags::Semicolon).data(), nullptr) != 0.0;
}
case Tags::UTF8Char: {
return r.ReadUTF8String(1) != "0";
}
case Tags::String: {
return CheckString(r.ReadUTF8String(r.ReadInt64Raw(Tags::Quote)));
}
case Tags::Bytes: {
return CheckString(r.ReadBytesAsString(r.ReadInt64Raw(Tags::Quote)));
}
default: {
r.SkipValue(tag);
return false;
}
}
}
bool CheckString(const std::string& str) {
return str != "";
}
bool ToWriterWithResultTag(bool value, HproseWriter& writer) {
writer.WriteTag(Tags::Result);
ToWriter(value, writer);
return false;
}
void ToWriter(bool value, HproseWriter& writer) {
writer.WriteTag(value ? Tags::True : Tags::False);
}
};
struct HproseValueHelperDouble {
double FromReader(HproseReader& r) {
auto tag = r.ReadTag();
switch(tag) {
case Tags::Null: return 0.0;
case Tags::Empty: return 0.0;
case Tags::Num0: return 0.0;
case Tags::Num1: return 1.0;
case Tags::Num2: return 2.0;
case Tags::Num3: return 3.0;
case Tags::Num4: return 4.0;
case Tags::Num5: return 5.0;
case Tags::Num6: return 6.0;
case Tags::Num7: return 7.0;
case Tags::Num8: return 8.0;
case Tags::Num9: return 9.0;
case Tags::False: return 0.0;
case Tags::True: return 1.0;
case Tags::NaN: return std::numeric_limits<double>::quiet_NaN();
case Tags::Infinity: {
auto t = r.ReadTag();
return (t == Tags::Pos) ? std::numeric_limits<double>::infinity() : -std::numeric_limits<double>::infinity();
}
case Tags::Integer:
case Tags::Long: {
return double(r.ReadInt64Raw(Tags::Semicolon));
}
case Tags::Double: {
return strtod(r.ReadUntilAsString(Tags::Semicolon).data(), nullptr);
}
case Tags::UTF8Char: {
return strtod(r.ReadUTF8String(1).data(), nullptr);
}
case Tags::String: {
return strtod(r.ReadUTF8String(r.ReadInt64Raw(Tags::Quote)).data(), nullptr);
}
case Tags::Bytes: {
return strtod(r.ReadBytesAsString(r.ReadInt64Raw(Tags::Quote)).data(), nullptr);
}
default: {
r.SkipValue(tag);
return 0.0;
}
}
}
bool ToWriterWithResultTag(double value, HproseWriter& writer) {
writer.WriteTag(Tags::Result);
ToWriter(value, writer);
return false;
}
void ToWriter(double value, HproseWriter& writer) {
if(std::isnan(value)) {
writer.WriteTag(Tags::NaN);
return;
}
if(std::isinf(value)) {
writer.WriteTag(Tags::Infinity);
writer.WriteTag(value > 0 ? Tags::Pos : Tags::Neg);
return;
}
writer.WriteTag(Tags::Double);
writer.WriteDouble(value);
writer.WriteTag(Tags::Semicolon);
}
};
struct HproseValueHelperString {
std::string FromReader(HproseReader& r) {
auto tag = r.ReadTag();
switch(tag) {
case Tags::Null: return "";
case Tags::Empty: return "";
case Tags::Num0: return "0";
case Tags::Num1: return "1";
case Tags::Num2: return "2";
case Tags::Num3: return "3";
case Tags::Num4: return "4";
case Tags::Num5: return "5";
case Tags::Num6: return "6";
case Tags::Num7: return "7";
case Tags::Num8: return "8";
case Tags::Num9: return "9";
case Tags::False: return "false";
case Tags::True: return "true";
case Tags::NaN: return "nan";
case Tags::Infinity: {
auto t = r.ReadTag();
return (t == Tags::Pos) ? "+inf" : "-inf";
}
case Tags::Integer:
case Tags::Long:
case Tags::Double: {
return r.ReadUntilAsString(Tags::Semicolon);
}
case Tags::UTF8Char: {
return r.ReadUTF8String(1);
}
case Tags::String: {
return r.ReadUTF8String(r.ReadInt64Raw(Tags::Quote));
}
case Tags::Bytes: {
return r.ReadBytesAsString(r.ReadInt64Raw(Tags::Quote));
}
default: {
r.SkipValue(tag);
return "";
}
}
}
bool ToWriterWithResultTag(const std::string& value, HproseWriter& writer) {
writer.WriteTag(Tags::Result);
ToWriter(value, writer);
return false;
}
void ToWriter(const std::string& value, HproseWriter& writer) {
if(value.empty()) {
writer.WriteTag(Tags::Empty);
return;
}
if(value.length() == 1) {
writer.WriteTag(Tags::UTF8Char);
writer.WriteByte(value[0]);
return;
}
writer.WriteTag(Tags::String);
writer.WriteLength(value.length());
writer.WriteTag(Tags::Quote);
writer.WriteString(value);
writer.WriteTag(Tags::Quote);
}
std::string FromReaderRaw(HproseReader& r) {
return r.ReadUTF8String(r.ReadInt64Raw(Tags::Quote));
}
void ToWriterRaw(const std::string& value, HproseWriter& writer, bool with_tag) {
if(with_tag)
writer.WriteTag(Tags::String);
writer.WriteLength(value.length());
writer.WriteTag(Tags::Quote);
writer.WriteString(value);
writer.WriteTag(Tags::Quote);
}
};
template<typename T>
struct HproseValueHelperStruct {
T FromReader(HproseReader& reader) {
T val;
auto tag = reader.ReadTag();
switch(tag) {
case Tags::Class: {
HproseValueHelperString().FromReaderRaw(reader);
int32_t count = reader.ReadInt64Raw(Tags::Openbrace);
std::vector<std::string> fields;
for(int32_t i = 0; i < count; ++i)
fields.emplace_back(HproseValueHelperString().FromReader(reader));
reader.PushFieldRefs(std::move(fields));
reader.CheckTag(Tags::Closebrace, true);
reader.CheckTag(Tags::Object, true);
}
case Tags::Object: {
int32_t index = reader.ReadInt64Raw(Tags::Openbrace);
auto& fields = reader.GetFieldRefs(index);
auto& refmap = val.GetFieldMaps();
for(size_t i = 0; i < fields.size(); ++i)
refmap.ReadField((uintptr_t)&val, fields[i], reader);
reader.CheckTag(Tags::Closebrace, true);
return val;
}
default: {
reader.SkipValue(tag);
return val;
}
}
}
bool ToWriterWithResultTag(const T& val, HproseWriter& writer) {
writer.WriteTag(Tags::Result);
val.GetFieldMaps().ToWriter((uintptr_t)&val, writer);
return false;
}
void ToWriter(const T& val, HproseWriter& writer) {
val.GetFieldMaps().ToWriter((uintptr_t)&val, writer);
}
};
template<typename T> struct HproseValueHelperImpl { using type = HproseValueHelperStruct<T>; };
template<> struct HproseValueHelperImpl<int> { using type = HproseValueHelperInteger; };
template<> struct HproseValueHelperImpl<HproseError> { using type = HproseValueHelperError; };
template<> struct HproseValueHelperImpl<bool> { using type = HproseValueHelperBool; };
template<> struct HproseValueHelperImpl<float> { using type = HproseValueHelperDouble; };
template<> struct HproseValueHelperImpl<double> { using type = HproseValueHelperDouble; };
template<> struct HproseValueHelperImpl<char*> { using type = HproseValueHelperString; };
template<> struct HproseValueHelperImpl<const char*> { using type = HproseValueHelperString; };
template<> struct HproseValueHelperImpl<std::string> { using type = HproseValueHelperString; };
template<typename T>
using HproseValueHelper = typename HproseValueHelperImpl<std::remove_cv_t<std::remove_reference_t<T>>>::type;
template<typename T>
struct HproseValueHelperSlice {
std::vector<T> FromReader(HproseReader& reader) {
std::vector<T> ret;
auto tag = reader.ReadTag();
switch(tag) {
case Tags::List: {
HproseValueHelper<T> vh;
int64_t count = reader.ReadInt64Raw(Tags::Openbrace);
for(int64_t i = 0; i < count; ++i)
ret.push_back(vh.FromReader(reader));
reader.CheckTag(Tags::Closebrace, true);
return ret;
}
default: {
reader.SkipValue(tag);
return ret;
}
}
}
bool ToWriterWithResultTag(const std::vector<T>& value, HproseWriter& writer) {
writer.WriteTag(Tags::Result);
ToWriter(value, writer);
return false;
}
void ToWriter(const std::vector<T>& values, HproseWriter& writer) {
HproseValueHelper<T> vh;
writer.WriteTag(Tags::List);
writer.WriteLength(values.size());
writer.WriteTag(Tags::Openbrace);
for(auto& v : values)
vh.ToWriter(v, writer);
writer.WriteTag(Tags::Closebrace);
}
};
template<typename K, typename V, typename MAP>
struct HproseValueHelperMap {
MAP FromReader(HproseReader& reader) {
MAP ret;
auto tag = reader.ReadTag();
switch(tag) {
case Tags::Map: {
HproseValueHelper<K> kvh;
HproseValueHelper<V> vvh;
int64_t count = reader.ReadInt64Raw(Tags::Openbrace);
for(int64_t i = 0; i < count; ++i) {
auto k = kvh.FromReader(reader);
auto v = vvh.FromReader(reader);
ret[k] = v;
}
reader.CheckTag(Tags::Closebrace, true);
return ret;
}
default: {
reader.SkipValue(tag);
return ret;
}
}
}
bool ToWriterWithResultTag(const MAP& value, HproseWriter& writer) {
writer.WriteTag(Tags::Result);
ToWriter(value, writer);
return false;
}
void ToWriter(const MAP& value, HproseWriter& writer) {
HproseValueHelper<K> kvh;
HproseValueHelper<V> vvh;
writer.WriteTag(Tags::Map);
writer.WriteLength(value.size());
writer.WriteTag(Tags::Openbrace);
for(auto& iter : value) {
kvh.ToWriter(iter.first, writer);
vvh.ToWriter(iter.second, writer);
}
writer.WriteTag(Tags::Closebrace);
}
};
template<int32_t INDEX>
struct ErrorChecker {
template<typename T>
bool IsError(T& val) {
return !std::get<INDEX>(val).IsNull();
}
template<typename T>
void WriteError(T& val, HproseWriter& writer) {
HproseValueHelperError().ToWriterWithResultTag(std::get<INDEX>(val), writer);
}
};
template<>
struct ErrorChecker<-1> {
template<typename T>
bool IsError(T& val) { return false; }
template<typename T>
void WriteError(T& val, HproseWriter& writer) {}
};
template<typename ... ARGS>
struct HproseValueHelperTuple {
using helper_type = std::tuple<HproseValueHelper<ARGS>...>;
std::tuple<ARGS...> FromReader(HproseReader& reader) {
std::tuple<ARGS...> ret;
auto tag = reader.ReadTag();
switch(tag) {
case Tags::List: {
helper_type vhs;
int64_t count = reader.ReadInt64Raw(Tags::Openbrace);
FromReaderImpl(ret, vhs, reader, count, std::make_index_sequence<sizeof...(ARGS)>{});
for(int32_t i = sizeof...(ARGS); i < count; ++i)
reader.SkipValue();
reader.CheckTag(Tags::Closebrace, true);
return ret;
}
default: {
reader.SkipValue(tag);
return ret;
}
}
}
void FromReaderImpl(std::tuple<ARGS...>& value, helper_type& vhs, HproseReader& reader, int64_t count, std::index_sequence<>) {}
template<size_t I, size_t... R>
void FromReaderImpl(std::tuple<ARGS...>& value, helper_type& vhs, HproseReader& reader, int64_t count, std::index_sequence<I, R...>) {
if(I < (size_t)count) {
std::get<I>(value) = std::get<I>(vhs).FromReader(reader);
FromReaderImpl(value, vhs, reader, count, std::index_sequence<R...>{});
}
}
bool ToWriterWithResultTag(const std::tuple<ARGS...>& value, HproseWriter& writer) {
ErrorChecker<IndexOfType<HproseError, ARGS...>::value> checker;
bool has_error = checker.IsError(value);
if(has_error) {
checker.WriteError(value, writer);
} else {
writer.WriteTag(Tags::Result);
ToWriter(value, writer);
}
return has_error;
}
void ToWriter(const std::tuple<ARGS...>& value, HproseWriter& writer) {
helper_type vhs;
writer.WriteTag(Tags::List);
writer.WriteLength(sizeof...(ARGS));
writer.WriteTag(Tags::Openbrace);
ToWriterImpl(value, vhs, writer, std::make_index_sequence<sizeof...(ARGS)>{});
writer.WriteTag(Tags::Closebrace);
}
void ToWriterImpl(const std::tuple<ARGS...>& value, helper_type& vhs, HproseWriter& writer, std::index_sequence<>) {}
template<size_t I, size_t... R>
void ToWriterImpl(const std::tuple<ARGS...>& value, helper_type& vhs, HproseWriter& writer, std::index_sequence<I, R...>) {
std::get<I>(vhs).ToWriter(std::get<I>(value), writer);
ToWriterImpl(value, vhs, writer, std::index_sequence<R...>{});
}
};
template<typename T>
struct HproseValueHelperImpl<std::vector<T>> { using type = HproseValueHelperSlice<T>; };
template<typename K, typename V>
struct HproseValueHelperImpl<std::map<K, V>> { using type = HproseValueHelperMap<K, V, std::map<K, V>>; };
template<typename K, typename V>
struct HproseValueHelperImpl<std::unordered_map<K, V>> { using type = HproseValueHelperMap<K, V, std::unordered_map<K, V>>; };
template<typename ... ARGS>
struct HproseValueHelperImpl<std::tuple<ARGS...>> { using type = HproseValueHelperTuple<ARGS...>; };
struct HproseReflector {
virtual void FromReader(uintptr_t addr, HproseReader& r) = 0;
virtual void ToWriter(uintptr_t addr, HproseWriter& w) = 0;
virtual const std::string& GetName() = 0;
virtual ~HproseReflector() {}
};
template<typename T>
struct HproseReflectType : public HproseReflector {
HproseReflectType(uintptr_t off, const std::string& n) : offset(off), name(n) {}
virtual void FromReader(uintptr_t addr, HproseReader& r) {
T* ptr = (T*)(addr + offset);
*ptr = HproseValueHelper<T>().FromReader(r);
}
virtual void ToWriter(uintptr_t addr, HproseWriter& w) {
T* ptr = (T*)(addr + offset);
HproseValueHelper<T>().ToWriter(*ptr, w);
}
virtual const std::string& GetName() {
return name;
}
uintptr_t offset;
std::string name;
};
struct HproseReflectMap {
bool IsInited() { return inited; }
void Init(const std::string& name) {
struct_name = name;
inited = true;
}
template<typename T>
void RegisterField(T* t, const std::string& fname) {
auto reflector = new HproseReflectType<T>((uintptr_t)t, fname);
fields[fname] = std::unique_ptr<HproseReflector>(reflector);
}
void ReadField(uintptr_t struct_ptr, const std::string& name, HproseReader& reader) {
auto iter = fields.find(name);
if(iter == fields.end()) {
reader.SkipValue();
return;
}
iter->second->FromReader(struct_ptr, reader);
}
void ToWriter(uintptr_t struct_ptr, HproseWriter& writer) const {
auto idx = writer.GetStructFieldsIndex(struct_name);
if(idx == -1) {
idx = writer.PushFieldRefs(struct_name);
WriteFields(writer);
}
writer.WriteTag(Tags::Object);
HproseValueHelperInteger().ToWriter(idx, writer);
writer.WriteTag(Tags::Openbrace);
for(auto& iter : fields)
iter.second->ToWriter(struct_ptr, writer);
writer.WriteTag(Tags::Closebrace);
}
void WriteFields(HproseWriter& writer) const {
writer.WriteTag(Tags::Class);
HproseValueHelperString().ToWriterRaw(struct_name, writer, false);
HproseValueHelperInteger().ToWriter(fields.size(), writer);
writer.WriteTag(Tags::Openbrace);
for(auto& iter : fields)
HproseValueHelperString().ToWriterRaw(iter.first, writer, true);
writer.WriteTag(Tags::Closebrace);
}
bool inited = false;
std::string struct_name;
std::map<std::string, std::unique_ptr<HproseReflector>> fields;
};
#define FE_1(FUN, FIELD) FUN(FIELD)
#define FE_2(FUN, FIELD, ...) FUN(FIELD)FE_1(FUN, __VA_ARGS__)
#define FE_3(FUN, FIELD, ...) FUN(FIELD)FE_2(FUN, __VA_ARGS__)
#define FE_4(FUN, FIELD, ...) FUN(FIELD)FE_3(FUN, __VA_ARGS__)
#define FE_5(FUN, FIELD, ...) FUN(FIELD)FE_4(FUN, __VA_ARGS__)
#define FE_6(FUN, FIELD, ...) FUN(FIELD)FE_5(FUN, __VA_ARGS__)
#define FE_7(FUN, FIELD, ...) FUN(FIELD)FE_6(FUN, __VA_ARGS__)
#define FE_8(FUN, FIELD, ...) FUN(FIELD)FE_7(FUN, __VA_ARGS__)
#define GET_MACRO(_1,_2,_3,_4,_5,_6,_7,_8,NAME,...) NAME
#define FOR_EACH(action,...) GET_MACRO(__VA_ARGS__,FE_8,FE_7,FE_6,FE_5,FE_4,FE_3,FE_2,FE_1)(action,__VA_ARGS__)
#define PUSH_FIELD(FIELD) ref_map.RegisterField(&ptr->FIELD, #FIELD);
#define HPROSE_REFLECT(struct_type, ...) \
public:\
static HproseReflectMap& GetFieldMaps() {\
static HproseReflectMap ref_map;\
if(ref_map.IsInited())\
return ref_map;\
static std::atomic<bool> inited(false);\
bool expected = false;\
if(inited.compare_exchange_strong(expected, true)) {\
struct_type* ptr = nullptr;\
FOR_EACH(PUSH_FIELD, __VA_ARGS__)\
ref_map.Init(#struct_type);\
} else {\
while(!ref_map.IsInited());\
}\
return ref_map;\
}
#endif