benchmark silo added
[c11concurrency-benchmarks.git] / silo / masstree / msgpack.cc
1 #include "msgpack.hh"
2 namespace msgpack {
3
4 namespace {
5 const uint8_t nbytes[] = {
6     /* 0xC0-0xC3 */ 0, 0, 0, 0,
7     /* 0xC4-0xC6 fbin8-fbin32 */ 2, 3, 5,
8     /* 0xC7-0xC9 fext */ 0, 0, 0,
9     /* 0xCA ffloat32 */ 5,
10     /* 0xCB ffloat64 */ 9,
11     /* 0xCC-0xD3 ints */ 2, 3, 5, 9, 2, 3, 5, 9,
12     /* 0xD4-0xD8 ffixext */ 0, 0, 0, 0, 0,
13     /* 0xD9-0xDB fstr8-fstr32 */ 2, 3, 5,
14     /* 0xDC-0xDD farray16-farray32 */ 3, 5,
15     /* 0xDE-0xDF fmap16-fmap32 */ 3, 5
16 };
17 }
18
19 const uint8_t* streaming_parser::consume(const uint8_t* first,
20                                          const uint8_t* last,
21                                          const String& str) {
22     using std::swap;
23     Json* jx;
24     int n = 0;
25
26     if (state_ < 0)
27         return first;
28     if (state_ == st_partial || state_ == st_string) {
29         int nneed;
30         if (state_ == st_partial)
31             nneed = nbytes[str_.udata()[0] - 0xC0];
32         else
33             nneed = stack_.back().size;
34         const uint8_t* next;
35         if (last - first < nneed - str_.length())
36             next = last;
37         else
38             next = first + (nneed - str_.length());
39         str_.append(first, next);
40         if (str_.length() != nneed)
41             return next;
42         first = next;
43         if (state_ == st_string) {
44             stack_.pop_back();
45             jx = stack_.empty() ? &json_ : stack_.back().jp;
46             *jx = str_;
47             goto next;
48         } else {
49             state_ = st_normal;
50             consume(str_.ubegin(), str_.uend(), str_);
51             if (state_ != st_normal)
52                 return next;
53         }
54     }
55
56     while (first != last) {
57         jx = stack_.empty() ? &json_ : stack_.back().jp;
58
59         if (format::is_fixint(*first)) {
60             *jx = int(int8_t(*first));
61             ++first;
62         } else if (*first == format::fnull) {
63             *jx = Json();
64             ++first;
65         } else if (format::is_bool(*first)) {
66             *jx = bool(*first - format::ffalse);
67             ++first;
68         } else if (format::is_fixmap(*first)) {
69             n = *first - format::ffixmap;
70             ++first;
71         map:
72             if (jx->is_o())
73                 jx->clear();
74             else
75                 *jx = Json::make_object();
76         } else if (format::is_fixarray(*first)) {
77             n = *first - format::ffixarray;
78             ++first;
79         array:
80             if (!jx->is_a())
81                 *jx = Json::make_array_reserve(n);
82             jx->resize(n);
83         } else if (format::is_fixstr(*first)) {
84             n = *first - format::ffixstr;
85             ++first;
86         raw:
87             if (last - first < n) {
88                 str_ = String(first, last);
89                 stack_.push_back(selem{0, n});
90                 state_ = st_string;
91                 return last;
92             }
93             if (first < str.ubegin() || first + n >= str.uend())
94                 *jx = String(first, n);
95             else {
96                 const char* s = reinterpret_cast<const char*>(first);
97                 *jx = str.fast_substring(s, s + n);
98             }
99             first += n;
100         } else {
101             uint8_t type = *first - format::fnull;
102             if (!nbytes[type])
103                 goto error;
104             if (last - first < nbytes[type]) {
105                 str_ = String(first, last);
106                 state_ = st_partial;
107                 return last;
108             }
109             first += nbytes[type];
110             switch (type) {
111             case format::ffloat32 - format::fnull:
112                 *jx = read_in_net_order<float>(first - 4);
113                 break;
114             case format::ffloat64 - format::fnull:
115                 *jx = read_in_net_order<double>(first - 8);
116                 break;
117             case format::fuint8 - format::fnull:
118                 *jx = int(first[-1]);
119                 break;
120             case format::fuint16 - format::fnull:
121                 *jx = read_in_net_order<uint16_t>(first - 2);
122                 break;
123             case format::fuint32 - format::fnull:
124                 *jx = read_in_net_order<uint32_t>(first - 4);
125                 break;
126             case format::fuint64 - format::fnull:
127                 *jx = read_in_net_order<uint64_t>(first - 8);
128                 break;
129             case format::fint8 - format::fnull:
130                 *jx = int8_t(first[-1]);
131                 break;
132             case format::fint16 - format::fnull:
133                 *jx = read_in_net_order<int16_t>(first - 2);
134                 break;
135             case format::fint32 - format::fnull:
136                 *jx = read_in_net_order<int32_t>(first - 4);
137                 break;
138             case format::fint64 - format::fnull:
139                 *jx = read_in_net_order<int64_t>(first - 8);
140                 break;
141             case format::fbin8 - format::fnull:
142             case format::fstr8 - format::fnull:
143                 n = first[-1];
144                 goto raw;
145             case format::fbin16 - format::fnull:
146             case format::fstr16 - format::fnull:
147                 n = read_in_net_order<uint16_t>(first - 2);
148                 goto raw;
149             case format::fbin32 - format::fnull:
150             case format::fstr32 - format::fnull:
151                 n = read_in_net_order<uint32_t>(first - 4);
152                 goto raw;
153             case format::farray16 - format::fnull:
154                 n = read_in_net_order<uint16_t>(first - 2);
155                 goto array;
156             case format::farray32 - format::fnull:
157                 n = read_in_net_order<uint32_t>(first - 4);
158                 goto array;
159             case format::fmap16 - format::fnull:
160                 n = read_in_net_order<uint16_t>(first - 2);
161                 goto map;
162             case format::fmap32 - format::fnull:
163                 n = read_in_net_order<uint32_t>(first - 4);
164                 goto map;
165             }
166         }
167
168         // Add it
169     next:
170         if (jx == &jokey_) {
171             // Reading a key for some object Json
172             if (!jx->is_s() && !jx->is_i())
173                 goto error;
174             selem* top = &stack_.back();
175             Json* jo = (top == stack_.begin() ? &json_ : top[-1].jp);
176             top->jp = &jo->get_insert(jx->to_s());
177             continue;
178         }
179
180         if (jx->is_a() && n != 0)
181             stack_.push_back(selem{&jx->at_insert(0), n - 1});
182         else if (jx->is_o() && n != 0)
183             stack_.push_back(selem{&jokey_, n - 1});
184         else {
185             while (!stack_.empty() && stack_.back().size == 0)
186                 stack_.pop_back();
187             if (stack_.empty()) {
188                 state_ = st_final;
189                 return first;
190             }
191             selem* top = &stack_.back();
192             --top->size;
193             Json* jo = (top == stack_.begin() ? &json_ : top[-1].jp);
194             if (jo->is_a())
195                 ++top->jp;
196             else
197                 top->jp = &jokey_;
198         }
199     }
200
201     state_ = st_normal;
202     return first;
203
204  error:
205     state_ = st_error;
206     return first;
207 }
208
209 parser& parser::operator>>(Str& x) {
210     uint32_t len;
211     if ((uint32_t) *s_ - format::ffixstr < format::nfixstr) {
212         len = *s_ - format::ffixstr;
213         ++s_;
214     } else if (*s_ == format::fbin8 || *s_ == format::fstr8) {
215         len = s_[1];
216         s_ += 2;
217     } else if (*s_ == format::fbin16 || *s_ == format::fstr16) {
218         len = read_in_net_order<uint16_t>(s_ + 1);
219         s_ += 3;
220     } else {
221         assert(*s_ == format::fbin32 || *s_ == format::fstr32);
222         len = read_in_net_order<uint32_t>(s_ + 1);
223         s_ += 5;
224     }
225     x.assign(reinterpret_cast<const char*>(s_), len);
226     s_ += len;
227     return *this;
228 }
229
230 parser& parser::operator>>(String& x) {
231     Str s;
232     *this >> s;
233     if (str_)
234         x = str_.substring(s.begin(), s.end());
235     else
236         x.assign(s.begin(), s.end());
237     return *this;
238 }
239
240 } // namespace msgpack