#ifndef _HPROSE_TYPES_HPP_ #define _HPROSE_TYPES_HPP_ #include #include #include #include #include #include #include "hprose_ed.hpp" template struct StdFuncType { using type = void; }; template struct StdFuncType { using type = std::function; }; template struct StdFuncType { using type = std::function; }; template struct FunctionType { using type = typename StdFuncType::type; }; template struct FunctionType { using type = std::function; }; template struct FunctionType { using type = RET(CLASS::*)(ARGS...); }; template struct FunctionType { using type = RET(CLASS::*)(ARGS...) const; }; template struct IndexOfTypeHelper { static constexpr int32_t value = std::conditional_t::value, std::integral_constant, IndexOfTypeHelper>::value; }; template struct IndexOfTypeHelper { static constexpr int32_t value = std::conditional_t::value, std::integral_constant, std::integral_constant>::value; }; template struct IndexOfType { static constexpr int32_t value = IndexOfTypeHelper<0, T, ARGS...>::value; }; template struct IndexOfType { 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::quiet_NaN(); case Tags::Infinity: { auto t = r.ReadTag(); return (t == Tags::Pos) ? std::numeric_limits::infinity() : -std::numeric_limits::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 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 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 struct HproseValueHelperImpl { using type = HproseValueHelperStruct; }; template<> struct HproseValueHelperImpl { using type = HproseValueHelperInteger; }; template<> struct HproseValueHelperImpl { using type = HproseValueHelperError; }; template<> struct HproseValueHelperImpl { using type = HproseValueHelperBool; }; template<> struct HproseValueHelperImpl { using type = HproseValueHelperDouble; }; template<> struct HproseValueHelperImpl { using type = HproseValueHelperDouble; }; template<> struct HproseValueHelperImpl { using type = HproseValueHelperString; }; template<> struct HproseValueHelperImpl { using type = HproseValueHelperString; }; template<> struct HproseValueHelperImpl { using type = HproseValueHelperString; }; template using HproseValueHelper = typename HproseValueHelperImpl>>::type; template struct HproseValueHelperSlice { std::vector FromReader(HproseReader& reader) { std::vector ret; auto tag = reader.ReadTag(); switch(tag) { case Tags::List: { HproseValueHelper 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& value, HproseWriter& writer) { writer.WriteTag(Tags::Result); ToWriter(value, writer); return false; } void ToWriter(const std::vector& values, HproseWriter& writer) { HproseValueHelper 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 struct HproseValueHelperMap { MAP FromReader(HproseReader& reader) { MAP ret; auto tag = reader.ReadTag(); switch(tag) { case Tags::Map: { HproseValueHelper kvh; HproseValueHelper 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 kvh; HproseValueHelper 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 struct ErrorChecker { template bool IsError(T& val) { return !std::get(val).IsNull(); } template void WriteError(T& val, HproseWriter& writer) { HproseValueHelperError().ToWriterWithResultTag(std::get(val), writer); } }; template<> struct ErrorChecker<-1> { template bool IsError(T& val) { return false; } template void WriteError(T& val, HproseWriter& writer) {} }; template struct HproseValueHelperTuple { using helper_type = std::tuple...>; std::tuple FromReader(HproseReader& reader) { std::tuple 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{}); 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& value, helper_type& vhs, HproseReader& reader, int64_t count, std::index_sequence<>) {} template void FromReaderImpl(std::tuple& value, helper_type& vhs, HproseReader& reader, int64_t count, std::index_sequence) { if(I < (size_t)count) { std::get(value) = std::get(vhs).FromReader(reader); FromReaderImpl(value, vhs, reader, count, std::index_sequence{}); } } bool ToWriterWithResultTag(const std::tuple& value, HproseWriter& writer) { ErrorChecker::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& 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{}); writer.WriteTag(Tags::Closebrace); } void ToWriterImpl(const std::tuple& value, helper_type& vhs, HproseWriter& writer, std::index_sequence<>) {} template void ToWriterImpl(const std::tuple& value, helper_type& vhs, HproseWriter& writer, std::index_sequence) { std::get(vhs).ToWriter(std::get(value), writer); ToWriterImpl(value, vhs, writer, std::index_sequence{}); } }; template struct HproseValueHelperImpl> { using type = HproseValueHelperSlice; }; template struct HproseValueHelperImpl> { using type = HproseValueHelperMap>; }; template struct HproseValueHelperImpl> { using type = HproseValueHelperMap>; }; template struct HproseValueHelperImpl> { using type = HproseValueHelperTuple; }; 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 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().FromReader(r); } virtual void ToWriter(uintptr_t addr, HproseWriter& w) { T* ptr = (T*)(addr + offset); HproseValueHelper().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 void RegisterField(T* t, const std::string& fname) { auto reflector = new HproseReflectType((uintptr_t)t, fname); fields[fname] = std::unique_ptr(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> 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 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