benchmark silo added
[c11concurrency-benchmarks.git] / silo / masstree / msgpack.hh
diff --git a/silo/masstree/msgpack.hh b/silo/masstree/msgpack.hh
new file mode 100644 (file)
index 0000000..f4bc4dc
--- /dev/null
@@ -0,0 +1,692 @@
+#ifndef GSTORE_MSGPACK_HH
+#define GSTORE_MSGPACK_HH
+#include "json.hh"
+#include "local_vector.hh"
+#include "straccum.hh"
+#include <vector>
+namespace msgpack {
+using lcdf::Json;
+using lcdf::Str;
+using lcdf::String;
+using lcdf::StringAccum;
+
+namespace format {
+enum {
+    ffixuint = 0x00, nfixuint = 0x80,
+    ffixmap = 0x80, nfixmap = 0x10,
+    ffixarray = 0x90, nfixarray = 0x10,
+    ffixstr = 0xA0, nfixstr = 0x20,
+    fnull = 0xC0,
+    ffalse = 0xC2, ftrue = 0xC3,
+    fbin8 = 0xC4, fbin16 = 0xC5, fbin32 = 0xC6,
+    fext8 = 0xC7, fext16 = 0xC8, fext32 = 0xC9,
+    ffloat32 = 0xCA, ffloat64 = 0xCB,
+    fuint8 = 0xCC, fuint16 = 0xCD, fuint32 = 0xCE, fuint64 = 0xCF,
+    fint8 = 0xD0, fint16 = 0xD1, fint32 = 0xD2, fint64 = 0xD3,
+    ffixext1 = 0xD4, ffixext2 = 0xD5, ffixext4 = 0xD6,
+    ffixext8 = 0xD7, ffixext16 = 0xD8,
+    fstr8 = 0xD9, fstr16 = 0xDA, fstr32 = 0xDB,
+    farray16 = 0xDC, farray32 = 0xDD,
+    fmap16 = 0xDE, fmap32 = 0xDF,
+    ffixnegint = 0xE0, nfixnegint = 0x20,
+    nfixint = nfixuint + nfixnegint
+};
+
+inline bool in_range(uint8_t x, unsigned low, unsigned n) {
+    return (unsigned) x - low < n;
+}
+inline bool in_wrapped_range(uint8_t x, unsigned low, unsigned n) {
+    return (unsigned) (int8_t) x - low < n;
+}
+
+inline bool is_fixint(uint8_t x) {
+    return in_wrapped_range(x, -nfixnegint, nfixint);
+}
+inline bool is_null_or_bool(uint8_t x) {
+    return in_range(x, fnull, 4);
+}
+inline bool is_bool(uint8_t x) {
+    return in_range(x, ffalse, 2);
+}
+inline bool is_fixstr(uint8_t x) {
+    return in_range(x, ffixstr, nfixstr);
+}
+inline bool is_fixarray(uint8_t x) {
+    return in_range(x, ffixarray, nfixarray);
+}
+inline bool is_fixmap(uint8_t x) {
+    return in_range(x, ffixmap, nfixmap);
+}
+
+inline char* write_null(char* s) {
+    *s++ = fnull;
+    return s;
+}
+inline char* write_bool(char* s, bool x) {
+    *s++ = ffalse + x;
+    return s;
+}
+
+template <size_t s> struct sized_writer {};
+template <> struct sized_writer<4> {
+    static inline char* write_unsigned(char* s, uint32_t x) {
+        if (x < nfixuint)
+            *s++ = x;
+        else if (x < 256) {
+            *s++ = fuint8;
+            *s++ = x;
+        } else if (x < 65536) {
+            *s++ = fuint16;
+            s = write_in_net_order<uint16_t>(s, (uint16_t) x);
+        } else {
+            *s++ = fuint32;
+            s = write_in_net_order<uint32_t>(s, x);
+        }
+        return s;
+    }
+    static inline char* write_signed(char* s, int32_t x) {
+        if ((uint32_t) x + nfixnegint < nfixint)
+            *s++ = x;
+        else if ((uint32_t) x + 128 < 256) {
+            *s++ = fint8;
+            *s++ = x;
+        } else if ((uint32_t) x + 32768 < 65536) {
+            *s++ = fint16;
+            s = write_in_net_order<int16_t>(s, (int16_t) x);
+        } else {
+            *s++ = fint32;
+            s = write_in_net_order<int32_t>(s, x);
+        }
+        return s;
+    }
+};
+template <> struct sized_writer<8> {
+    static inline char* write_unsigned(char* s, uint64_t x) {
+        if (x < 4294967296ULL)
+            return sized_writer<4>::write_unsigned(s, (uint32_t) x);
+        else {
+            *s++ = fuint64;
+            return write_in_net_order<uint64_t>(s, x);
+        }
+    }
+    static inline char* write_signed(char* s, int64_t x) {
+        if (x + 2147483648ULL < 4294967296ULL)
+            return sized_writer<4>::write_signed(s, (int32_t) x);
+        else {
+            *s++ = fint64;
+            return write_in_net_order<int64_t>(s, x);
+        }
+    }
+};
+inline char* write_int(char* s, int x) {
+    return sized_writer<sizeof(x)>::write_signed(s, x);
+}
+inline char* write_int(char* s, unsigned x) {
+    return sized_writer<sizeof(x)>::write_unsigned(s, x);
+}
+inline char* write_int(char* s, long x) {
+    return sized_writer<sizeof(x)>::write_signed(s, x);
+}
+inline char* write_int(char* s, unsigned long x) {
+    return sized_writer<sizeof(x)>::write_unsigned(s, x);
+}
+#if HAVE_LONG_LONG && SIZEOF_LONG_LONG <= 8
+inline char* write_int(char* s, long long x) {
+    return sized_writer<sizeof(x)>::write_signed(s, x);
+}
+inline char* write_int(char* s, unsigned long long x) {
+    return sized_writer<sizeof(x)>::write_unsigned(s, x);
+}
+#endif
+inline char* write_wide_int64(char* s, uint64_t x) {
+    *s++ = fuint64;
+    return write_in_net_order<uint64_t>(s, x);
+}
+inline char* write_wide_int64(char* s, int64_t x) {
+    *s++ = fint64;
+    return write_in_net_order<int64_t>(s, x);
+}
+inline char* write_float(char* s, float x) {
+    *s++ = ffloat32;
+    return write_in_net_order<float>(s, x);
+}
+inline char* write_double(char* s, double x) {
+    *s++ = ffloat64;
+    return write_in_net_order<double>(s, x);
+}
+inline char* write_string(char* s, const char *data, int len) {
+    if (len < nfixstr)
+        *s++ = 0xA0 + len;
+    else if (len < 256) {
+        *s++ = fstr8;
+        *s++ = len;
+    } else if (len < 65536) {
+        *s++ = fstr16;
+        s = write_in_net_order<uint16_t>(s, (uint16_t) len);
+    } else {
+        *s++ = fstr32;
+        s = write_in_net_order<uint32_t>(s, len);
+    }
+    memcpy(s, data, len);
+    return s + len;
+}
+inline char* write_string(char* s, Str x) {
+    return write_string(s, x.data(), x.length());
+}
+template <typename T>
+inline char* write_string(char* s, const lcdf::String_base<T>& x) {
+    return write_string(s, x.data(), x.length());
+}
+inline char* write_array_header(char* s, uint32_t size) {
+    if (size < nfixarray) {
+        *s++ = ffixarray + size;
+        return s;
+    } else if (size < 65536) {
+        *s++ = farray16;
+        return write_in_net_order<uint16_t>(s, (uint16_t) size);
+    } else {
+        *s++ = farray32;
+        return write_in_net_order<uint32_t>(s, (uint32_t) size);
+    }
+}
+inline char* write_map_header(char* s, uint32_t size) {
+    if (size < nfixmap) {
+        *s++ = ffixmap + size;
+        return s;
+    } else if (size < 65536) {
+        *s++ = fmap16;
+        return write_in_net_order<uint16_t>(s, (uint16_t) size);
+    } else {
+        *s++ = fmap32;
+        return write_in_net_order<uint32_t>(s, (uint32_t) size);
+    }
+}
+} // namespace format
+
+struct array_t {
+    uint32_t size;
+    array_t(uint32_t s)
+        : size(s) {
+    }
+};
+
+inline array_t array(uint32_t size) {
+    return array_t(size);
+}
+
+struct object_t {
+    uint32_t size;
+    object_t(uint32_t s)
+        : size(s) {
+    }
+};
+
+inline object_t object(uint32_t size) {
+    return object_t(size);
+}
+
+template <typename T>
+class unparser {
+  public:
+    inline unparser(T& base)
+        : base_(base) {
+    }
+    template <typename X>
+    inline unparser(T& base, const X& x)
+        : base_(base) {
+        *this << x;
+    }
+
+    inline void clear() {
+        base_.clear();
+    }
+
+    inline unparser<T>& null() {
+        base_.append((char) format::fnull);
+        return *this;
+    }
+    inline unparser<T>& operator<<(const Json::null_t&) {
+        return null();
+    }
+    inline unparser<T>& operator<<(int x) {
+        char* s = base_.reserve(sizeof(x) + 1);
+        base_.set_end(format::write_int(s, x));
+        return *this;
+    }
+    inline unparser<T>& operator<<(unsigned x) {
+        char* s = base_.reserve(sizeof(x) + 1);
+        base_.set_end(format::write_int(s, x));
+        return *this;
+    }
+    inline unparser<T>& operator<<(long x) {
+        char* s = base_.reserve(sizeof(x) + 1);
+        base_.set_end(format::write_int(s, x));
+        return *this;
+    }
+    inline unparser<T>& operator<<(unsigned long x) {
+        char* s = base_.reserve(sizeof(x) + 1);
+        base_.set_end(format::write_int(s, x));
+        return *this;
+    }
+#if HAVE_LONG_LONG && SIZEOF_LONG_LONG <= 8
+    inline unparser<T>& operator<<(long long x) {
+        char* s = base_.reserve(sizeof(x) + 1);
+        base_.set_end(format::write_int(s, x));
+        return *this;
+    }
+    inline unparser<T>& operator<<(unsigned long long x) {
+        char* s = base_.reserve(sizeof(x) + 1);
+        base_.set_end(format::write_int(s, x));
+        return *this;
+    }
+#endif
+    inline unparser<T>& write_wide(int64_t x) {
+        char* s = base_.reserve(sizeof(x) + 1);
+        base_.set_end(format::write_wide_int64(s, x));
+        return *this;
+    }
+    inline unparser<T>& write_wide(uint64_t x) {
+        char* s = base_.reserve(sizeof(x) + 1);
+        base_.set_end(format::write_wide_int64(s, x));
+        return *this;
+    }
+    inline unparser<T>& operator<<(float x) {
+        char* s = base_.reserve(sizeof(x) + 1);
+        base_.set_end(format::write_float(s, x));
+        return *this;
+    }
+    inline unparser<T>& operator<<(double x) {
+        char* s = base_.reserve(sizeof(x) + 1);
+        base_.set_end(format::write_double(s, x));
+        return *this;
+    }
+    inline unparser<T>& operator<<(Str x) {
+        char* s = base_.reserve(5 + x.length());
+        base_.set_end(format::write_string(s, x.data(), x.length()));
+        return *this;
+    }
+    template <typename X>
+    inline unparser<T>& operator<<(const lcdf::String_base<X>& x) {
+        char* s = base_.reserve(5 + x.length());
+        base_.set_end(format::write_string(s, x.data(), x.length()));
+        return *this;
+    }
+    inline unparser<T>& operator<<(array_t x) {
+        char* s = base_.reserve(5);
+        base_.set_end(format::write_array_header(s, x.size));
+        return *this;
+    }
+    inline unparser<T>& write_array_header(uint32_t size) {
+        char* s = base_.reserve(5);
+        base_.set_end(format::write_array_header(s, size));
+        return *this;
+    }
+    inline unparser<T>& operator<<(object_t x) {
+        char* s = base_.reserve(5);
+        base_.set_end(format::write_map_header(s, x.size));
+        return *this;
+    }
+    unparser<T>& operator<<(const Json& j);
+    template <typename X>
+    inline unparser<T>& write(const X& x) {
+        return *this << x;
+    }
+
+  private:
+    T& base_;
+};
+
+class streaming_parser {
+  public:
+    inline streaming_parser();
+    inline void reset();
+
+    inline bool empty() const;
+    inline bool done() const;
+    inline bool success() const;
+    inline bool error() const;
+
+    inline size_t consume(const char* first, size_t length,
+                          const String& str = String());
+    inline const char* consume(const char* first, const char* last,
+                               const String& str = String());
+    const uint8_t* consume(const uint8_t* first, const uint8_t* last,
+                           const String& str = String());
+
+    inline Json& result();
+    inline const Json& result() const;
+
+  private:
+    enum {
+        st_final = -2, st_error = -1, st_normal = 0, st_partial = 1,
+        st_string = 2
+    };
+    struct selem {
+        Json* jp;
+        int size;
+    };
+    int state_;
+    local_vector<selem, 2> stack_;
+    String str_;
+    Json json_;
+    Json jokey_;
+};
+
+class parser {
+  public:
+    explicit inline parser(const char* s)
+        : s_(reinterpret_cast<const unsigned char*>(s)), str_() {
+    }
+    explicit inline parser(const unsigned char* s)
+        : s_(s), str_() {
+    }
+    explicit inline parser(const String& str)
+        : s_(reinterpret_cast<const uint8_t*>(str.begin())), str_(str) {
+    }
+    inline const char* position() const {
+        return reinterpret_cast<const char*>(s_);
+    }
+
+    inline bool try_read_null() {
+        if (*s_ == format::fnull) {
+            ++s_;
+            return true;
+        } else
+            return false;
+    }
+    inline int read_tiny_int() {
+        assert(format::is_fixint(*s_));
+        return (int8_t) *s_++;
+    }
+    inline parser& read_tiny_int(int& x) {
+        x = read_tiny_int();
+        return *this;
+    }
+    template <typename T>
+    inline parser& read_int(T& x) {
+        if (format::is_fixint(*s_)) {
+            x = (int8_t) *s_;
+            ++s_;
+        } else {
+            assert((uint32_t) *s_ - format::fuint8 < 8);
+            hard_read_int(x);
+        }
+        return *this;
+    }
+    inline parser& operator>>(int& x) {
+        return read_int(x);
+    }
+    inline parser& operator>>(long& x) {
+        return read_int(x);
+    }
+    inline parser& operator>>(long long& x) {
+        return read_int(x);
+    }
+    inline parser& operator>>(unsigned& x) {
+        return read_int(x);
+    }
+    inline parser& operator>>(unsigned long& x) {
+        return read_int(x);
+    }
+    inline parser& operator>>(unsigned long long& x) {
+        return read_int(x);
+    }
+    inline parser& operator>>(bool& x) {
+        assert(format::is_bool(*s_));
+        x = *s_ - format::ffalse;
+        ++s_;
+        return *this;
+    }
+    inline parser& operator>>(double& x) {
+        assert(*s_ == format::ffloat64);
+        x = read_in_net_order<double>(s_ + 1);
+        s_ += 9;
+        return *this;
+    }
+    parser& operator>>(Str& x);
+    parser& operator>>(String& x);
+    inline parser& read_array_header(unsigned& size) {
+        if (format::is_fixarray(*s_)) {
+            size = *s_ - format::ffixarray;
+            s_ += 1;
+        } else if (*s_ == format::farray16) {
+            size = read_in_net_order<uint16_t>(s_ + 1);
+            s_ += 3;
+        } else {
+            assert(*s_ == format::farray32);
+            size = read_in_net_order<uint32_t>(s_ + 1);
+            s_ += 5;
+        }
+        return *this;
+    }
+    template <typename T> parser& operator>>(::std::vector<T>& x);
+    inline parser& operator>>(Json& j);
+
+    inline parser& skip_primitives(unsigned n) {
+        for (; n != 0; --n) {
+            if (format::is_fixint(*s_) || format::is_null_or_bool(*s_))
+                s_ += 1;
+            else if (format::is_fixstr(*s_))
+                s_ += 1 + (*s_ - format::ffixstr);
+            else if (*s_ == format::fuint8 || *s_ == format::fint8)
+                s_ += 2;
+            else if (*s_ == format::fuint16 || *s_ == format::fint16)
+                s_ += 3;
+            else if (*s_ == format::fuint32 || *s_ == format::fint32
+                     || *s_ == format::ffloat32)
+                s_ += 5;
+            else if (*s_ == format::fstr8 || *s_ == format::fbin8)
+                s_ += 2 + s_[1];
+            else if (*s_ == format::fstr16 || *s_ == format::fbin16)
+                s_ += 3 + read_in_net_order<uint16_t>(s_ + 1);
+            else if (*s_ == format::fstr32 || *s_ == format::fbin32)
+                s_ += 5 + read_in_net_order<uint32_t>(s_ + 1);
+        }
+        return *this;
+    }
+    inline parser& skip_primitive() {
+        return skip_primitives(1);
+    }
+    inline parser& skip_array_size() {
+        if (format::is_fixarray(*s_))
+            s_ += 1;
+        else if (*s_ == format::farray16)
+            s_ += 3;
+        else {
+            assert(*s_ == format::farray32);
+            s_ += 5;
+        }
+        return *this;
+    }
+  private:
+    const uint8_t* s_;
+    String str_;
+    template <typename T> void hard_read_int(T& x);
+};
+
+template <typename T>
+void parser::hard_read_int(T& x) {
+    switch (*s_) {
+    case format::fuint8:
+        x = s_[1];
+        s_ += 2;
+        break;
+    case format::fuint16:
+        x = read_in_net_order<uint16_t>(s_ + 1);
+        s_ += 3;
+        break;
+    case format::fuint32:
+        x = read_in_net_order<uint32_t>(s_ + 1);
+        s_ += 5;
+        break;
+    case format::fuint64:
+        x = read_in_net_order<uint64_t>(s_ + 1);
+        s_ += 9;
+        break;
+    case format::fint8:
+        x = (int8_t) s_[1];
+        s_ += 2;
+        break;
+    case format::fint16:
+        x = read_in_net_order<int16_t>(s_ + 1);
+        s_ += 3;
+        break;
+    case format::fint32:
+        x = read_in_net_order<int32_t>(s_ + 1);
+        s_ += 5;
+        break;
+    case format::fint64:
+        x = read_in_net_order<int64_t>(s_ + 1);
+        s_ += 9;
+        break;
+    }
+}
+
+template <typename T>
+unparser<T>& unparser<T>::operator<<(const Json& j) {
+    if (j.is_null())
+        base_.append(char(format::fnull));
+    else if (j.is_b())
+        base_.append(char(format::ffalse + j.as_b()));
+    else if (j.is_u()) {
+        char* x = base_.reserve(9);
+        base_.set_end(format::write_int(x, j.as_u()));
+    } else if (j.is_i()) {
+        char* x = base_.reserve(9);
+        base_.set_end(format::write_int(x, j.as_i()));
+    } else if (j.is_d()) {
+        char* x = base_.reserve(9);
+        base_.set_end(format::write_double(x, j.as_d()));
+    } else if (j.is_s()) {
+        char* x = base_.reserve(j.as_s().length() + 5);
+        base_.set_end(format::write_string(x, j.as_s()));
+    } else if (j.is_a()) {
+        char* x = base_.reserve(5);
+        base_.set_end(format::write_array_header(x, j.size()));
+        for (auto it = j.cabegin(); it != j.caend(); ++it)
+            *this << *it;
+    } else if (j.is_o()) {
+        char* x = base_.reserve(5);
+        base_.set_end(format::write_map_header(x, j.size()));
+        for (auto it = j.cobegin(); it != j.coend(); ++it) {
+            char* x = base_.reserve(it.key().length() + 5);
+            base_.set_end(format::write_string(x, it.key()));
+            *this << it.value();
+        }
+    } else
+        base_.append(char(format::fnull));
+    return *this;
+}
+
+inline String unparse(const Json& j) {
+    StringAccum sa;
+    unparser<StringAccum>(sa, j);
+    return sa.take_string();
+}
+template <typename T, typename X>
+inline T& unparse(T& s, const X& x) {
+    unparser<T>(s) << x;
+    return s;
+}
+template <typename T, typename X>
+inline T& unparse_wide(T& s, const X& x) {
+    unparser<T>(s).write_wide(x);
+    return s;
+}
+
+template <typename T>
+parser& parser::operator>>(::std::vector<T>& x) {
+    uint32_t sz;
+    if ((uint32_t) *s_ - format::ffixarray < format::nfixarray) {
+        sz = *s_ - format::ffixarray;
+        ++s_;
+    } else if (*s_ == format::farray16) {
+        sz = read_in_net_order<uint16_t>(s_ + 1);
+        s_ += 3;
+    } else {
+        assert(*s_ == format::farray32);
+        sz = read_in_net_order<uint32_t>(s_ + 1);
+        s_ += 5;
+    }
+    for (; sz != 0; --sz) {
+        x.push_back(T());
+        parse(x.back());
+    }
+    return *this;
+}
+
+inline streaming_parser::streaming_parser()
+    : state_(st_normal) {
+}
+
+inline void streaming_parser::reset() {
+    state_ = st_normal;
+    stack_.clear();
+}
+
+inline bool streaming_parser::empty() const {
+    return state_ == st_normal && stack_.empty();
+}
+
+inline bool streaming_parser::done() const {
+    return state_ < 0;
+}
+
+inline bool streaming_parser::success() const {
+    return state_ == st_final;
+}
+
+inline bool streaming_parser::error() const {
+    return state_ == st_error;
+}
+
+inline const char* streaming_parser::consume(const char* first,
+                                             const char* last,
+                                             const String& str) {
+    return reinterpret_cast<const char*>
+        (consume(reinterpret_cast<const uint8_t*>(first),
+                 reinterpret_cast<const uint8_t*>(last), str));
+}
+
+inline size_t streaming_parser::consume(const char* first, size_t length,
+                                        const String& str) {
+    const uint8_t* ufirst = reinterpret_cast<const uint8_t*>(first);
+    return consume(ufirst, ufirst + length, str) - ufirst;
+}
+
+inline Json& streaming_parser::result() {
+    return json_;
+}
+
+inline const Json& streaming_parser::result() const {
+    return json_;
+}
+
+inline parser& parser::operator>>(Json& j)  {
+    using std::swap;
+    streaming_parser sp;
+    while (!sp.done())
+        s_ = sp.consume(s_, s_ + 4096, str_);
+    if (sp.success())
+        swap(j, sp.result());
+    return *this;
+}
+
+inline Json parse(const char* first, const char* last) {
+    streaming_parser sp;
+    first = sp.consume(first, last, String());
+    if (sp.success())
+        return sp.result();
+    return Json();
+}
+
+inline Json parse(const String& str) {
+    streaming_parser sp;
+    sp.consume(str.begin(), str.end(), str);
+    if (sp.success())
+        return sp.result();
+    return Json();
+}
+
+} // namespace msgpack
+#endif