Commit 64520831 authored by Matthias Wittgen's avatar Matthias Wittgen
Browse files

Merge branch 'devel' into 'master'

template msgpack code

See merge request !1
parents 39eec2ee 134d4065
......@@ -2,7 +2,6 @@
#define __MEMORY_BUFFER_HPP__
#include <vector>
#include <variant.hpp>
#include <stdint.h>
......@@ -26,7 +25,7 @@ public:
_pos+=sizeof(T);
}
const char *getBytes(std::size_t n) {
if((_pos+n)>=_len) throw;
if((_pos+n)>_len) throw;
const char*p=(const char*)&_buf[_pos];
_pos+=n;
return p;
......
......@@ -89,17 +89,16 @@ namespace msgpack {
{ typeid(int64_t) , INT_64 }
};
template <typename V>
class Reader {
public:
Reader(MemoryReadBuffer &mem,variant &var,bool toDouble): _mem(mem),_var(var),_toDouble(toDouble) {
Reader(MemoryReadBuffer &mem,V &var,bool toDouble=false): _mem(mem),_var(var),_toDouble(toDouble) {
_var=readToken();
}
private:
bool _toDouble;
variant readToken() {
variant v;
V readToken() {
V v;
uint8_t token;
_mem.get(token);
switch(token) {
......@@ -114,20 +113,36 @@ namespace msgpack {
case EXT_16: readExt<uint16_t>(); break;
case EXT_32: readExt<uint32_t>(); break;
case FLOAT_32:
if(_toDouble)
v=readValue<float,double>();
if constexpr (std::is_same_v<V,variant64>) {
if(_toDouble)
v=readValue<float,double>();
else
v=readValue<float>();
}
else
v=readValue<float>();
break;
case FLOAT_64: v=readValue<double>(); break;
case FLOAT_64:
if constexpr (std::is_same_v<V,variant64>)
v=readValue<double>();
else throw;
break;
case UINT_8: v=readValue<uint8_t>(); break;
case UINT_16: v=readValue<uint16_t>(); break;
case UINT_32: v=readValue<uint32_t>(); break;
case UINT_64: v=readValue<uint64_t>(); break;
case UINT_64:
if constexpr (std::is_same_v<V,variant64>)
v=readValue<uint64_t>();
else throw;
break;
case INT_8: v=readValue<int8_t>();break;
case INT_16: v=readValue<int16_t>();break;
case INT_32: v=readValue<int32_t>();break;
case INT_64: v=readValue<int64_t>();break;
case INT_32: v=readValue<int32_t>();break;
case INT_64:
if constexpr (std::is_same_v<V,variant64>)
v=readValue<int64_t>();
else throw;
break;
case FIXEXT_1: readFixExt<1>();break;
case FIXEXT_2: readFixExt<2>();break;
case FIXEXT_4: readFixExt<6>();break;
......@@ -155,14 +170,14 @@ namespace msgpack {
return v;
}
template<typename T,typename N=T> variant readValue() {
template<typename T,typename N=T> V readValue() {
T val;
_mem.get(val);
return variant(N(val));
return V(N(val));
}
template<typename T> variant readStr(uint8_t token=0) {
return variant(readString<T>(token));
template<typename T> V readStr(uint8_t token=0) {
return V(readString<T>(token));
}
std::string readKey() {
......@@ -186,19 +201,19 @@ namespace msgpack {
}
variant readBool(uint8_t val) {
V readBool(uint8_t val) {
bool b=(val==0xc3);
return variant(b);
return V(b);
}
variant readPosFixInt(uint8_t val) {
return variant(val);
V readPosFixInt(uint8_t val) {
return V(val);
}
variant readNegFixInt(uint8_t val) {
return variant(int8_t(val));
V readNegFixInt(uint8_t val) {
return V(int8_t(val));
}
variant readNull() {
return variant();
V readNull() {
return V();
}
// byte array
......@@ -224,8 +239,8 @@ namespace msgpack {
_mem.getBytes(len);
// handle types
}
template <typename T> variant readMap(uint8_t token=0) {
variant result;
template <typename T> V readMap(uint8_t token=0) {
V result;
T len;
if(token==0) _mem.get(len); else len=token;
for(std::size_t i=0;i<len;i++) {
......@@ -235,12 +250,15 @@ namespace msgpack {
return result;
}
bool readTypedArray(variant &var,std::size_t len) {
bool readTypedArray(V &var,std::size_t len) {
uint8_t last;
uint8_t tok;
_mem.peek(tok,0);
if(tok>=FLOAT_32 && tok<=INT_64) {
std::size_t offset=(len-1)*(1+typesize_map[tok]);
std::size_t sz=typesize_map[tok];
if constexpr (std::is_same_v<V,variant32>)
if(sz>4) throw;
std::size_t offset=(len-1)*(1+sz);
_mem.peek(last,offset);
if(tok!=last) return false;
}
......@@ -249,21 +267,39 @@ namespace msgpack {
case UINT_8: return readTypedArray<uint8_t>(var,len); break;
case UINT_16: return readTypedArray<uint16_t>(var,len); break;
case UINT_32: return readTypedArray<uint32_t>(var,len); break;
case UINT_64: return readTypedArray<uint64_t>(var,len); break;
case UINT_64:
if constexpr (std::is_same_v<V,variant64>)
return readTypedArray<uint64_t>(var,len);
else throw;
break;
case INT_8: return readTypedArray<int8_t>(var,len); break;
case INT_16: return readTypedArray<int16_t>(var,len); break;
case INT_32: return readTypedArray<int32_t>(var,len); break;
case INT_64: return readTypedArray<int64_t>(var,len); break;
case FLOAT_32: if(_toDouble) return readTypedArray<float,double>(var,len);
else return readTypedArray<float>(var,len); break;
case FLOAT_64: return readTypedArray<double>(var,len); break;
case INT_64:
if constexpr (std::is_same_v<V,variant64>)
return readTypedArray<int64_t>(var,len);
else throw;
break;
case FLOAT_32:
if constexpr (std::is_same_v<V,variant64>) {
if(_toDouble) return readTypedArray<float,double>(var,len);
else return readTypedArray<float>(var,len);
}
else
return readTypedArray<float>(var,len);
break;
case FLOAT_64:
if constexpr (std::is_same_v<V,variant64>)
return readTypedArray<double>(var,len);
else throw;
break;
default:
break;
}
return false;
}
template <typename T,typename N=T> bool readTypedArray(variant &var,std::size_t len) {
template <typename T,typename N=T> bool readTypedArray(V &var,std::size_t len) {
std::vector<N> result;
// std::size_t pos=_mem.pos();
uint8_t token=typeid_map[typeid(T)];
......@@ -279,13 +315,13 @@ namespace msgpack {
offset+=sz+1;
result.push_back(val);
}
var=variant(result);
var=V(result);
_mem.advance(offset);
return true;
}
template <typename T> variant readArray(uint8_t token=0) {
variant result(variant::Type::array);
template <typename T> V readArray(uint8_t token=0) {
V result(V::Type::array);
T len;
if(token==0) _mem.get(len); else len=token;
bool is_typed_array=readTypedArray(result,len);
......@@ -295,12 +331,12 @@ namespace msgpack {
}
MemoryReadBuffer &_mem;
variant &_var;
V &_var;
};
template <typename V>
class Writer {
public:
Writer(MemoryWriteBuffer &mem,const variant &var):_mem(mem),_var(var) {
Writer(MemoryWriteBuffer &mem,const V &var):_mem(mem),_var(var) {
writeValue(var);
}
......@@ -311,10 +347,10 @@ namespace msgpack {
else if(n>4) {_mem.put(uint8_t(0xdc)); _mem.put(uint16_t(length)); }
else _mem.put(uint8_t(0x90|length));
}
template <typename T> void writeTypedArray(const variant &var) const {
const std::vector<T> &ar=*get_v<ValPtr<T>>(var.value);
template <typename T> void writeTypedArray(const V &var) const {
const std::vector<T> &ar=(const std::vector<T>) var;
_writeArrayHeader(ar.size());
for(auto a:ar) {
_mem.put(typeid_map[typeid(T)]);
......@@ -322,12 +358,12 @@ namespace msgpack {
}
}
void writeArray(const array_t &ar) {
void writeArray(const typename V::array_t &ar) {
_writeArrayHeader(ar.size());
for(auto a:ar) writeValue(a);
}
void writeObject(const object_t &obj) {
void writeObject(const typename V::object_t &obj) {
uint64_t len=obj.size();
uint64_t n=bit_width(len);
if(n>32) throw;
......@@ -349,25 +385,25 @@ namespace msgpack {
}
template <typename T> void writeScalar(const variant &v) {
template <typename T> void writeScalar(const V &v) {
T val=get_v<T>(v.value);
_mem.put(typeid_map[typeid(T)]);
_mem.put(val);
}
void writeUint8(const variant &v) {
void writeUint8(const V &v) {
uint8_t val=get_v<uint8_t>(v.value);
if(val>127)
_mem.put(typeid_map[typeid(uint8_t)]);
_mem.put(val);
}
void writeInt8(const variant &v) {
void writeInt8(const V &v) {
uint8_t val=get_v<int8_t>(v.value);
if(val<-32)
_mem.put(typeid_map[typeid(uint8_t)]);
_mem.put(val);
}
void writeBool(const variant &v) {
void writeBool(const V &v) {
bool b=get_v<bool>(v.value);
uint8_t op=FALSE;
if(b) op=TRUE;
......@@ -375,46 +411,71 @@ namespace msgpack {
}
void writeNull() { _mem.put(NIL);}
void writeValue(const variant &v) {
if(v.is_object()) writeObject(*get_v<ObjPtr>(v.value));
else if(v.is_array()) writeArray(*get_v<ArrayPtr>(v.value));
else if(v.is_string()) writeStr(*get_v<StrPtr>(v.value));
void writeValue(const V &v) {
if(v.is_object()) writeObject(*get_v<typename V::ObjPtr>(v.value));
else if(v.is_array()) writeArray(*get_v<typename V::ArrayPtr>(v.value));
else if(v.is_string()) writeStr(*get_v<typename V::StrPtr>(v.value));
else if(v.is_bool()) writeBool(v);
else if(v.is_null()) writeNull();
else switch(v.index()) {
case variant::Type::uint64: writeScalar<uint64_t>(v); break;
case variant::Type::uint32: writeScalar<uint32_t>(v); break;
case variant::Type::uint16: writeScalar<uint16_t>(v); break;
case variant::Type::uint8: writeUint8(v); break;
case variant::Type::int64: writeScalar<int64_t>(v); break;
case variant::Type::int32: writeScalar<int32_t>(v); break;
case variant::Type::int16: writeScalar<int16_t>(v); break;
case variant::Type::int8: writeInt8(v); break;
case variant::Type::float32: writeScalar<float>(v); break;
case variant::Type::float64: writeScalar<double>(v); break;
case variant::Type::array_uint64: writeTypedArray<uint64_t>(v); break;
case variant::Type::array_uint32: writeTypedArray<uint32_t>(v); break;
case variant::Type::array_uint16: writeTypedArray<uint16_t>(v); break;
case variant::Type::array_uint8: writeTypedArray<uint8_t>(v); break;
case variant::Type::array_int64: writeTypedArray<int64_t>(v); break;
case variant::Type::array_int32: writeTypedArray<int32_t>(v); break;
case variant::Type::array_int16: writeTypedArray<int16_t>(v); break;
case variant::Type::array_int8: writeTypedArray<int8_t>(v); break;
case variant::Type::array_float: writeTypedArray<float>(v); break;
case variant::Type::array_double: writeTypedArray<double>(v); break;
else switch(v.index()) {
case V::Type::uint64:
if constexpr (std::is_same_v<V,variant64>)
writeScalar<uint64_t>(v);
else throw;
break;
case V::Type::uint32: writeScalar<uint32_t>(v); break;
case V::Type::uint16: writeScalar<uint16_t>(v); break;
case V::Type::uint8: writeUint8(v); break;
case V::Type::int64:
if constexpr (std::is_same_v<V,variant64>)
writeScalar<int64_t>(v);
else throw;
break;
case V::Type::int32: writeScalar<int32_t>(v); break;
case V::Type::int16: writeScalar<int16_t>(v); break;
case V::Type::int8: writeInt8(v); break;
case V::Type::float32: writeScalar<float>(v); break;
case V::Type::float64:
if constexpr (std::is_same_v<V,variant64>)
writeScalar<double>(v);
else throw;
break;
case V::Type::array_uint64:
if constexpr (std::is_same_v<V,variant64>)
writeTypedArray<uint64_t>(v);
else throw;
break;
case V::Type::array_uint32: writeTypedArray<uint32_t>(v); break;
case V::Type::array_uint16: writeTypedArray<uint16_t>(v); break;
case V::Type::array_uint8: writeTypedArray<uint8_t>(v); break;
case V::Type::array_int64:
if constexpr (std::is_same_v<V,variant32>)
writeTypedArray<int64_t>(v);
else throw;
break;
case V::Type::array_int32: writeTypedArray<int32_t>(v); break;
case V::Type::array_int16: writeTypedArray<int16_t>(v); break;
case V::Type::array_int8: writeTypedArray<int8_t>(v); break;
case V::Type::array_float: writeTypedArray<float>(v); break;
case V::Type::array_double:
if constexpr (std::is_same_v<V,variant64>)
writeTypedArray<double>(v);
else throw;
break;
}
}
private:
MemoryWriteBuffer &_mem;
const variant &_var;
const V &_var;
inline uint32_t bit_width(uint64_t arg) const {
return sizeof(arg)*8 - __builtin_clzl(arg);
}
};
using Writer64=Writer<variant64>;
using Writer32=Writer<variant32>;
using Reader64=Reader<variant64>;
using Reader32=Reader<variant32>;
}
......
......@@ -75,6 +75,7 @@ template<template<typename...> class Ref, typename... Args>
struct is_specialization<Ref<Args...>, Ref>: std::true_type {};
template <typename U64=uint64_t,typename I64=int64_t,typename DBL=double>
class variant {
public:
using array_t=std::vector<variant>;
using string_t=std::string;
using size_type=std::size_t;
......@@ -83,7 +84,7 @@ class ArrayPtr : public DeepPtr<array_t> { using DeepPtr<array_t>::DeepPtr ; } ;
class ObjPtr : public DeepPtr<object_t> { using DeepPtr<object_t>::DeepPtr ; } ;
class StrPtr : public DeepPtr<string_t> { using DeepPtr<string_t>::DeepPtr ; } ;
template <typename T,typename A=std::vector<T>> class ValPtr : public DeepPtr<A> { using DeepPtr<A>::DeepPtr ; } ;
private:
template <typename... T> using variant_t=std::variant<T...>;
......@@ -304,9 +305,10 @@ public:
void dump() {
void dump() const {
rapidjson::StringBuffer buffer;
toJson(buffer);
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
dump(writer);
std::cout << buffer.GetString() << std::endl;
}
......@@ -369,24 +371,9 @@ void fromJson(const char *json) {
template<class T> operator T() const {
if constexpr(std::is_arithmetic<T>{}) {
return get_v<T>(value);
}// else return *get_v<T>(value);
}
#if 0
template<class T,typename std::enable_if<
std::is_arithmetic<T>{},int>::type = 0>
operator const T&() {
return get_v<T>(value);
} //else return *get_v<T>(value);
}
template<class T,
typename std::enable_if<
std::is_arithmetic<T>{},
int>::type = 0>
operator T() {
return get_v<T>(value);
}
#endif
template <typename T> const std::vector<T> &get() const {
return *get_v<ValPtr<T>>(value);
......@@ -399,6 +386,14 @@ void fromJson(const char *json) {
return *get_v<ValPtr<T>>(value);
}
operator const std::string &() {
return *get_v<StrPtr>(value);
}
operator const std::string &() const {
return *get_v<StrPtr>(value);
}
reference operator [] (const typename object_t::key_type &key) {
if(is_null() ) {
......
......@@ -3,8 +3,10 @@ const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n
int main(int argc,char *argv[]){
variant32 v,w;
v["test"]= {
{"a",20} , {"b",40}
{"a",20} , {"b",40}, {"string","mystring"}
};
const std::string &s= v["test"]["string"];
std::cout << "s=" << s << std::endl;
v.dump();
w=v;
w["test"]["a"]=25;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment