libutil++  1.9.3
 All Classes Functions Variables
MessagePack.h
1 /*
2 ** libutil++
3 ** $Id: MessagePack.h 1653 2016-02-28 19:54:59Z sella $
4 ** Copyright (c) 2011-2016 Digital Genesis, LLC. All Rights Reserved.
5 ** Released under the LGPL Version 2.1 License.
6 ** http://www.digitalgenesis.com
7 */
8 
9 #ifndef __libutilxx__sella__util__MessagePack_H__
10 #define __libutilxx__sella__util__MessagePack_H__
11 
12 #include "../../common.h"
13 #include "CommonMacro.h"
14 
15 #include "MemoryException.h"
16 
17 #include <functional>
18 #include <map>
19 #include <string>
20 
21 namespace sella {
22  namespace util {
23  class MessagePack;
24 
25  typedef bool (mp_scan_callback(uint32_t i, uint32_t v, void * p));
26 
28  uint32_t index;
29  uint32_t value;
31 
33  MessagePack * instance;
34 
35  const char * index;
36  uint32_t bytes;
37 
38  uint32_t value;
40 
41  typedef struct mpack_table {
42  uint8_t bytes_base;
43  uint8_t bytes_mask;
44 
45  uint8_t count_mult;
46  uint8_t count_mask;
47 
48  uint32_t count_zero;
49  uint32_t bytes_zero;
50 
51  uint8_t type;
52  uint8_t shift_swap;
53  uint16_t zero;
54  } __attribute__((packed)) mpack_table_t;
55  }
56 }
57 
58 class sella::util::MessagePack {
59  public:
60  static const uint8_t TYPE_NULL = 0x00;
61  static const uint8_t TYPE_VECTOR = 0x01;
62  static const uint8_t TYPE_OBJECT = 0x02;
63  static const uint8_t TYPE_STRING = 0x03;
64  static const uint8_t TYPE_BOOLEAN = 0x04;
65  static const uint8_t TYPE_SIGNED = 0x05;
66  static const uint8_t TYPE_UNSIGNED = 0x06;
67  static const uint8_t TYPE_FLOAT = 0x07;
68  static const uint8_t TYPE_BINARY = 0x08;
69  static const uint8_t TYPE_EXTENSION = 0x09;
70  static const uint8_t TYPE_UNKNOWN = 0xff;
71 
72  MessagePack(uint8_t * & buffer, uint32_t & length, uint32_t offset = 0, uint32_t unused = 0, bool resizable = false) THROWS(MemoryException);
73 
74  uint32_t create(uint32_t offset) NO_EXCEPTIONS;
75  bool verify(void) NO_EXCEPTIONS;
76 
77  uint32_t create(uint32_t offset, const char * index) NO_EXCEPTIONS;
78  uint32_t create(uint32_t offset, const uint8_t * buffer, uint32_t length) NO_EXCEPTIONS;
79  uint32_t create(uint32_t offset, MessagePack & other, uint32_t length) NO_EXCEPTIONS;
80 
81  uint32_t select(uint32_t offset, MessagePack & other, uint32_t source) NO_EXCEPTIONS;
82  uint32_t select(uint32_t offset, const uint8_t * buffer, uint32_t length) NO_EXCEPTIONS;
83  uint32_t select(uint32_t offset, const char * index) NO_EXCEPTIONS;
84 
85  uint32_t remove(uint32_t offset, const char * index) NO_EXCEPTIONS;
86 
87  bool update(uint32_t offset, MessagePack & other, uint32_t source) NO_EXCEPTIONS;
88 
89  bool update(uint32_t offset, const char * value) NO_EXCEPTIONS;
90  bool update(uint32_t offset, const char * value, uint32_t length) NO_EXCEPTIONS;
91  bool update(uint32_t offset, const std::string & value) NO_EXCEPTIONS;
92  bool update(uint32_t offset, bool value) NO_EXCEPTIONS;
93  bool update(uint32_t offset, int64_t value) NO_EXCEPTIONS;
94  bool update(uint32_t offset, uint64_t value) NO_EXCEPTIONS;
95  bool update(uint32_t offset, double value) NO_EXCEPTIONS;
96  bool update(uint32_t offset) NO_EXCEPTIONS;
97 
98  bool decode(char * buffer, uint32_t length, uint32_t offset) NO_EXCEPTIONS;
99  bool decode(std::string & buffer, uint32_t offset) NO_EXCEPTIONS;
100  bool decode(bool & buffer, uint32_t offset) NO_EXCEPTIONS;
101  bool decode(int64_t & buffer, uint32_t offset) NO_EXCEPTIONS;
102  bool decode(uint64_t & buffer, uint32_t offset) NO_EXCEPTIONS;
103  bool decode(double & buffer, uint32_t offset) NO_EXCEPTIONS;
104 
105  uint32_t decode_first(uint32_t offset) NO_EXCEPTIONS;
106 
107  int compare(uint32_t offset, const char * value) NO_EXCEPTIONS;
108  int compare(uint32_t offset, const char * value, uint32_t length) NO_EXCEPTIONS;
109  int compare(uint32_t offset, const std::string & value) NO_EXCEPTIONS;
110  int compare(uint32_t offset, bool value) NO_EXCEPTIONS;
111  int compare(uint32_t offset, int64_t value) NO_EXCEPTIONS;
112  int compare(uint32_t offset, uint64_t value) NO_EXCEPTIONS;
113  int compare(uint32_t offset, double value) NO_EXCEPTIONS;
114 
115  void scan(uint32_t offset, std::function<bool (uint32_t i, uint32_t v)> callback);
116  void scan(uint32_t offset, mp_scan_callback callback, void * parameters);
117 
118  inline uint8_t typeof(uint32_t offset) NO_EXCEPTIONS {
119  if (UNLIKELY(offset == UINT32_MAX)) {
120  return MessagePack::TYPE_UNKNOWN;
121  }
122  return MessagePack::mpack_table[this->buffer_memory[this->buffer_offset + offset]].type;
123  }
124  void print(bool debug = false) NO_EXCEPTIONS;
125  std::string json(uint32_t offset = 0) NO_EXCEPTIONS;
126 
127  uint32_t append_object(uint32_t offset, uint32_t count) NO_EXCEPTIONS;
128  uint32_t append_vector(uint32_t offset, uint32_t count) NO_EXCEPTIONS;
129 
130  uint32_t memcpy(uint8_t * buffer, uint32_t length, uint32_t offset) NO_EXCEPTIONS;
131 
132  uint32_t append(uint32_t offset, const char * value) NO_EXCEPTIONS;
133  uint32_t append(uint32_t offset, const std::string & value) NO_EXCEPTIONS;
134  uint32_t append(uint32_t offset, bool value) NO_EXCEPTIONS;
135  uint32_t append(uint32_t offset, int64_t value) NO_EXCEPTIONS;
136  uint32_t append(uint32_t offset, uint64_t value) NO_EXCEPTIONS;
137  uint32_t append(uint32_t offset, double value) NO_EXCEPTIONS;
138  uint32_t append(uint32_t offset) NO_EXCEPTIONS;
139 
140  bool recast(uint32_t offset, uint32_t type) NO_EXCEPTIONS;
141  bool resize(uint32_t offset, uint32_t size) NO_EXCEPTIONS;
142 
143  uint32_t count(uint32_t offset) NO_EXCEPTIONS {
144  if (UNLIKELY(offset == UINT32_MAX)) {
145  return MessagePack::TYPE_UNKNOWN;
146  }
147  offset += this->buffer_offset;
148 
149  const mpack_table_t * index = &(MessagePack::mpack_table[this->buffer_memory[offset]]);
150  uint32_t value = __builtin_bswap32(*(reinterpret_cast<uint32_t *>(&(this->buffer_memory[offset + 1]))));
151 
152  return (this->buffer_memory[offset] & index->count_mask) + ((value & index->count_zero) >> index->shift_swap);
153  }
154 
155  uint32_t strlen(uint32_t offset) NO_EXCEPTIONS {
156  if (UNLIKELY(offset == UINT32_MAX)) {
157  return 0;
158  }
159  offset += this->buffer_offset;
160 
161  const mpack_table_t * index = &(MessagePack::mpack_table[this->buffer_memory[offset]]);
162  uint32_t value = __builtin_bswap32(*(reinterpret_cast<uint32_t *>(&(this->buffer_memory[offset + 1]))));
163 
164  return ((value & index->bytes_zero) >> index->shift_swap) + (this->buffer_memory[offset] & index->bytes_mask);
165  }
166 
167  uint32_t bytes(uint32_t offset) NO_EXCEPTIONS {
168  if (UNLIKELY(offset == UINT32_MAX)) {
169  return MessagePack::TYPE_UNKNOWN;
170  }
171  offset += this->buffer_offset;
172 
173  const mpack_table_t * index = &(MessagePack::mpack_table[this->buffer_memory[offset]]);
174 
175  uint32_t count = 1;
176  uint32_t bytes = 0;
177 
178  uint32_t value;
179  uint32_t n;
180 
181  while (count > 0) {
182  value = __builtin_bswap32(*(reinterpret_cast<uint32_t *>(&(this->buffer_memory[offset + 1]))));
183 
184  count -= 1;
185  count += ((this->buffer_memory[offset] & index->count_mask) + ((value & index->count_zero) >> index->shift_swap)) << index->count_mult;
186 
187  n = index->bytes_base + ((value & index->bytes_zero) >> index->shift_swap) + (this->buffer_memory[offset] & index->bytes_mask);
188 
189  offset += n;
190  bytes += n;
191 
192  index = &(MessagePack::mpack_table[this->buffer_memory[offset]]);
193  }
194  return bytes;
195  }
196 
197  uint32_t size(void) NO_EXCEPTIONS;
198  uint32_t length(void) NO_EXCEPTIONS;
199 
200  uint32_t next(uint32_t offset) NO_EXCEPTIONS; /* Next at same level */
201  uint32_t down(uint32_t offset) NO_EXCEPTIONS; /* Moves into the referenced object */
202 
203  uint32_t append_kv(uint32_t offset, const char * key, const char * value) NO_EXCEPTIONS;
204  uint32_t append_kv(uint32_t offset, const char * key, const std::string & value) NO_EXCEPTIONS;
205  uint32_t append_kv(uint32_t offset, const char * key, bool value) NO_EXCEPTIONS;
206  uint32_t append_kv(uint32_t offset, const char * key, int64_t value) NO_EXCEPTIONS;
207  uint32_t append_kv(uint32_t offset, const char * key, uint64_t value) NO_EXCEPTIONS;
208  uint32_t append_kv(uint32_t offset, const char * key, double value) NO_EXCEPTIONS;
209  uint32_t append_kv(uint32_t offset, const char * key) NO_EXCEPTIONS;
210 
211  uint32_t append_kv(uint32_t offset, const std::string & key, const char * value) NO_EXCEPTIONS;
212  uint32_t append_kv(uint32_t offset, const std::string & key, const std::string & value) NO_EXCEPTIONS;
213  uint32_t append_kv(uint32_t offset, const std::string & key, bool value) NO_EXCEPTIONS;
214  uint32_t append_kv(uint32_t offset, const std::string & key, int64_t value) NO_EXCEPTIONS;
215  uint32_t append_kv(uint32_t offset, const std::string & key, uint64_t value) NO_EXCEPTIONS;
216  uint32_t append_kv(uint32_t offset, const std::string & key, double value) NO_EXCEPTIONS;
217  uint32_t append_kv(uint32_t offset, const std::string & key) NO_EXCEPTIONS;
218 
219  protected:
220  static bool select_vector_callback(uint32_t i, uint32_t v, void * p);
221  static bool select_object_callback(uint32_t i, uint32_t v, void * p);
222 
223  uint32_t search(uint32_t offset, const char * index, uint32_t bytes, bool create) NO_EXCEPTIONS;
224 
225  uint32_t select(uint32_t offset, uint32_t index, bool create) NO_EXCEPTIONS;
226  uint32_t select(uint32_t offset, const char * index, uint32_t bytes, bool create) NO_EXCEPTIONS;
227 
228  uint32_t insert(uint32_t offset, const char * index) NO_EXCEPTIONS;
229  uint32_t insert(uint32_t offset, uint32_t index, uint32_t count) NO_EXCEPTIONS;
230 
231  void scan_vector(uint32_t length, uint32_t offset, std::function<bool (uint32_t i, uint32_t v)> callback);
232  void scan_vector(uint32_t length, uint32_t offset, mp_scan_callback callback, void * parameters);
233 
234  void scan_object(uint32_t length, uint32_t offset, std::function<bool (uint32_t i, uint32_t v)> callback);
235  void scan_object(uint32_t length, uint32_t offset, mp_scan_callback callback, void * parameters);
236 
237  bool expand(uint32_t offset, uint32_t length) NO_EXCEPTIONS;
238  bool reduce(uint32_t offset, uint32_t length) NO_EXCEPTIONS;
239 
240  double swap64(double value) NO_EXCEPTIONS;
241 
242  private:
243  static const mpack_table_t mpack_table[256];
244 
245  uint8_t * & buffer_memory;
246  uint32_t & buffer_length;
247 
248  uint32_t buffer_offset;
249  uint32_t buffer_unused;
250 
251  bool resizable;
252 };
253 
254 #endif
255 
256 /*
257 ** vim: noet ts=3 sw=3
258 */