sq_detailed_metrics 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/extconf.rb +26 -0
  3. data/include/half.hpp +4575 -0
  4. data/include/msgpack.h +24 -0
  5. data/include/msgpack/fbuffer.h +42 -0
  6. data/include/msgpack/gcc_atomic.h +25 -0
  7. data/include/msgpack/object.h +118 -0
  8. data/include/msgpack/pack.h +174 -0
  9. data/include/msgpack/pack_define.h +18 -0
  10. data/include/msgpack/pack_template.h +952 -0
  11. data/include/msgpack/sbuffer.h +115 -0
  12. data/include/msgpack/sysdep.h +221 -0
  13. data/include/msgpack/timestamp.h +58 -0
  14. data/include/msgpack/unpack.h +281 -0
  15. data/include/msgpack/unpack_define.h +89 -0
  16. data/include/msgpack/unpack_template.h +471 -0
  17. data/include/msgpack/util.h +15 -0
  18. data/include/msgpack/version.h +38 -0
  19. data/include/msgpack/version_master.h +3 -0
  20. data/include/msgpack/vrefbuffer.h +144 -0
  21. data/include/msgpack/zbuffer.h +205 -0
  22. data/include/msgpack/zone.h +163 -0
  23. data/include/rapidjson/allocators.h +271 -0
  24. data/include/rapidjson/document.h +2575 -0
  25. data/include/rapidjson/encodedstream.h +299 -0
  26. data/include/rapidjson/encodings.h +716 -0
  27. data/include/rapidjson/error/en.h +74 -0
  28. data/include/rapidjson/error/error.h +155 -0
  29. data/include/rapidjson/filereadstream.h +99 -0
  30. data/include/rapidjson/filewritestream.h +104 -0
  31. data/include/rapidjson/fwd.h +151 -0
  32. data/include/rapidjson/internal/biginteger.h +290 -0
  33. data/include/rapidjson/internal/diyfp.h +258 -0
  34. data/include/rapidjson/internal/dtoa.h +245 -0
  35. data/include/rapidjson/internal/ieee754.h +78 -0
  36. data/include/rapidjson/internal/itoa.h +304 -0
  37. data/include/rapidjson/internal/meta.h +181 -0
  38. data/include/rapidjson/internal/pow10.h +55 -0
  39. data/include/rapidjson/internal/regex.h +701 -0
  40. data/include/rapidjson/internal/stack.h +230 -0
  41. data/include/rapidjson/internal/strfunc.h +55 -0
  42. data/include/rapidjson/internal/strtod.h +269 -0
  43. data/include/rapidjson/internal/swap.h +46 -0
  44. data/include/rapidjson/istreamwrapper.h +115 -0
  45. data/include/rapidjson/memorybuffer.h +70 -0
  46. data/include/rapidjson/memorystream.h +71 -0
  47. data/include/rapidjson/msinttypes/inttypes.h +316 -0
  48. data/include/rapidjson/msinttypes/stdint.h +300 -0
  49. data/include/rapidjson/ostreamwrapper.h +81 -0
  50. data/include/rapidjson/pointer.h +1358 -0
  51. data/include/rapidjson/prettywriter.h +255 -0
  52. data/include/rapidjson/rapidjson.h +615 -0
  53. data/include/rapidjson/reader.h +1879 -0
  54. data/include/rapidjson/schema.h +2006 -0
  55. data/include/rapidjson/stream.h +179 -0
  56. data/include/rapidjson/stringbuffer.h +117 -0
  57. data/include/rapidjson/writer.h +610 -0
  58. data/include/xxhash.h +328 -0
  59. data/json_conv.cpp +284 -0
  60. data/json_conv.hpp +17 -0
  61. data/metrics.cpp +239 -0
  62. data/metrics.hpp +84 -0
  63. data/msgpack/objectc.c +482 -0
  64. data/msgpack/unpack.c +703 -0
  65. data/msgpack/version.c +22 -0
  66. data/msgpack/vrefbuffer.c +250 -0
  67. data/msgpack/zone.c +222 -0
  68. data/sq_detailed_metrics.cpp +248 -0
  69. metadata +199 -0
@@ -0,0 +1,17 @@
1
+ #ifndef JSON_CONV_HPP
2
+ #define JSON_CONV_HPP
3
+
4
+ #include <iostream>
5
+
6
+ namespace sq_detailed_metrics
7
+ {
8
+ class JsonConv {
9
+ std::ostream& os;
10
+ public:
11
+ JsonConv(std::ostream& os_) : os(os_) {}
12
+
13
+ void parse(const char *src, size_t size);
14
+ };
15
+ }
16
+
17
+ #endif // JSON_CONV_HPP
@@ -0,0 +1,239 @@
1
+ #include "metrics.hpp"
2
+ #include <msgpack.h>
3
+ #define LZ4LIB_VISIBILITY
4
+
5
+ namespace sq_detailed_metrics {
6
+
7
+ struct MsgpackPacker
8
+ {
9
+ MsgpackPacker() {
10
+ msgpack_packer_init(&packer, &output, &MsgpackPacker::std_string_write);
11
+ }
12
+
13
+ void start_map(size_t num_keys) {
14
+ msgpack_pack_map(&packer, num_keys);
15
+ }
16
+
17
+ void start_array(size_t num_elements) {
18
+ msgpack_pack_array(&packer, num_elements);
19
+ }
20
+
21
+ void start_bin(size_t size) {
22
+ msgpack_pack_bin(&packer, size);
23
+ }
24
+
25
+ void add_bin_portion(const char *data, size_t size) {
26
+ msgpack_pack_bin_body(&packer, data, size);
27
+ }
28
+
29
+ MsgpackPacker& operator<<(const std::string& str) {
30
+ const char *c_str = str.c_str();
31
+ msgpack_pack_str_with_body(&packer, c_str, str.size());
32
+ return *this;
33
+ }
34
+
35
+ MsgpackPacker& operator<<(index_t value) {
36
+ msgpack_pack_uint8(&packer, value);
37
+ return *this;
38
+ }
39
+
40
+ MsgpackPacker& operator<<(uint16_t value) {
41
+ msgpack_pack_uint16(&packer, value);
42
+ return *this;
43
+ }
44
+
45
+ MsgpackPacker& operator<<(half_float::half& value) {
46
+ msgpack_pack_fix_uint16(&packer, *reinterpret_cast<uint16_t *>(&value));
47
+ return *this;
48
+ }
49
+
50
+ std::string move_output() {
51
+ return std::move(output);
52
+ }
53
+
54
+ MsgpackPacker(const MsgpackPacker&) = delete;
55
+ MsgpackPacker& operator=(const MsgpackPacker&) = delete;
56
+ private:
57
+ // must be of type msgpack_packer_write
58
+ static int std_string_write(void* data, const char* buf, size_t len) {
59
+ std::string *str = static_cast<std::string*>(data);
60
+ try {
61
+ str->append(buf, len);
62
+ } catch (std::bad_alloc&) {
63
+ return -1;
64
+ }
65
+ return 0;
66
+ }
67
+
68
+ std::string output;
69
+ msgpack_packer packer;
70
+ };
71
+
72
+ struct MetricsIndex {
73
+ index_t index_of(const std::string& meas_type) {
74
+ lock_guard lock_guard(m);
75
+
76
+ index_t& t = meas_type_index[meas_type];
77
+ if (t == undef_index_t) {
78
+ t = next;
79
+ if (next < max_index_t) {
80
+ next++;
81
+ }
82
+ }
83
+ return t;
84
+ }
85
+
86
+ void serialize(MsgpackPacker& packer, const index_t_set& used_meas) {
87
+ lock_guard lock_guard(m);
88
+
89
+ // indexes 0 (undefined) and 255 (others) are not sent
90
+ packer.start_map(used_meas.count() -
91
+ (used_meas[undef_index_t] ? 1 : 0) -
92
+ (used_meas[max_index_t] ? 1 : 0));
93
+
94
+ std::for_each(meas_type_index.begin(), meas_type_index.end(),
95
+ [&packer, &used_meas](std::pair<std::string, index_t> entry) {
96
+ index_t i = entry.second;
97
+ if (i == max_index_t || i == undef_index_t || !used_meas[i]) {
98
+ return;
99
+ }
100
+ packer << i << entry.first; // index, string
101
+ });
102
+ }
103
+
104
+ MetricsIndex() {}
105
+ ~MetricsIndex() = default;
106
+ MetricsIndex(const MetricsIndex&) = delete;
107
+ MetricsIndex& operator= (const MetricsIndex&) = delete;
108
+
109
+ private:
110
+ std::map<std::string, index_t> meas_type_index;
111
+ index_t next = 1;
112
+ std::mutex m;
113
+ };
114
+
115
+
116
+ void Request::set_overtime_cb(const std::string& cb) {
117
+ if (cb.size() != 0) {
118
+ overtime_cb = metrics_index->index_of(cb);
119
+ } else {
120
+ overtime_cb = undef_index_t;
121
+ }
122
+ }
123
+
124
+ void Request::add(const std::string& meas_type, double value) {
125
+ index_t t = metrics_index->index_of(meas_type);
126
+ // the max half float is only 65504. Since we're storing
127
+ // ms, this is about 65 s. While this is a large quantity,
128
+ // larger ones have been seen in practice. Extend this range
129
+ // to almost 9 minutes by diving by 8. The minumum (normal)
130
+ // value becomes about 0.5 us, which is still good enough
131
+ float fval = static_cast<float>(value) / 8.0f;
132
+ half_float::half val{fval};
133
+
134
+ measurements.push_back(meas_entry_t{t, val});
135
+ }
136
+
137
+ void Request::mark_used_meas_types(index_t_set& bitset) const {
138
+ bitset[this->overtime_cb] = true;
139
+ for (const meas_entry_t& m: measurements) {
140
+ index_t i = m.first;
141
+ bitset[i] = true;
142
+ }
143
+ }
144
+
145
+ void Request::serialize(MsgpackPacker& packer,
146
+ req_index_t idx,
147
+ std::map<std::string, req_index_t>& prev_routes) const {
148
+ packer.start_array(3);
149
+
150
+ auto route_prev_idx_it = prev_routes.find(route);
151
+ if (route_prev_idx_it == prev_routes.end()) {
152
+ packer << route;
153
+ prev_routes[route] = idx;
154
+ } else {
155
+ req_index_t prev_idx = route_prev_idx_it->second;
156
+ packer << prev_idx;
157
+ }
158
+
159
+ packer << overtime_cb;
160
+
161
+ // encode as binary to encode pairs in 3 bytes
162
+ packer.start_bin(measurements.size() *
163
+ (sizeof(index_t) + sizeof(half_float::half)));
164
+ std::for_each(measurements.begin(), measurements.end(),
165
+ [&packer](meas_entry_t entry) {
166
+ packer.add_bin_portion(
167
+ reinterpret_cast<const char *>(&entry.first),
168
+ sizeof(index_t));
169
+ packer.add_bin_portion(
170
+ reinterpret_cast<const char *>(&entry.second),
171
+ sizeof(half_float::half));
172
+ });
173
+ }
174
+
175
+ size_t Request::mem_size() const {
176
+ return sizeof(Request) + route.length() +
177
+ sizeof(meas_entry_t) * this->measurements.size();
178
+ }
179
+
180
+ void RequestCollection::operator<<(Request request) {
181
+ lock_guard lock_guard{m};
182
+
183
+ if (completed_requests.size() == max_req_per_coll) {
184
+ return;
185
+ }
186
+
187
+ completed_requests.push_back(std::move(request));
188
+ }
189
+
190
+ bool RequestCollection::flush(std::string& out) {
191
+ std::list<Request> requests;
192
+ {
193
+ lock_guard lock_guard{m};
194
+ std::swap(requests, completed_requests);
195
+ }
196
+
197
+ if (requests.size() == 0) {
198
+ return false;
199
+ }
200
+
201
+ MsgpackPacker packer;
202
+
203
+ packer.start_array(2);
204
+ index_t_set meas_types_used;
205
+ for (const Request& req: requests) {
206
+ req.mark_used_meas_types(meas_types_used);
207
+ }
208
+ metrics_index->serialize(packer, meas_types_used);
209
+
210
+ packer.start_array(requests.size());
211
+ {
212
+ std::map<std::string, req_index_t> seen_routes;
213
+ req_index_t i = 0;
214
+ for (const Request &r: requests) {
215
+ r.serialize(packer, i, seen_routes);
216
+ i++;
217
+ }
218
+ }
219
+
220
+ out = packer.move_output(); // should select move assignment
221
+
222
+ return true;
223
+ }
224
+
225
+ size_t RequestCollection::mem_size() const {
226
+ size_t size = sizeof(RequestCollection);
227
+ for (const Request& req: completed_requests) {
228
+ size += req.mem_size();
229
+ }
230
+ return size;
231
+ }
232
+
233
+ MetricsIndex *MetricsIndex_create() {
234
+ return new MetricsIndex();
235
+ }
236
+ void MetricsIndex_free(MetricsIndex *idx) {
237
+ delete idx;
238
+ }
239
+ }
@@ -0,0 +1,84 @@
1
+ #ifndef METRICS_HPP
2
+ #define METRICS_HPP
3
+
4
+ #include <memory>
5
+ #include <map>
6
+ #include <set>
7
+ #include <string>
8
+ #include <list>
9
+ #include <mutex>
10
+ #include <bitset>
11
+ #include <half.hpp>
12
+ #include <limits>
13
+
14
+ #include <memory>
15
+ namespace sq_detailed_metrics
16
+ {
17
+ struct MetricsIndex;
18
+ MetricsIndex *MetricsIndex_create();
19
+ void MetricsIndex_free(MetricsIndex *idx);
20
+
21
+ extern MetricsIndex *metrics_index;
22
+
23
+ using index_t = uint8_t;
24
+ constexpr index_t max_index_t = std::numeric_limits<index_t>::max();
25
+ constexpr index_t undef_index_t = 0; // must be 0
26
+ using index_t_set = std::bitset<max_index_t - 0 /* min */ + 1>;
27
+ using lock_guard = std::lock_guard<std::mutex>;
28
+ typedef std::pair<index_t, half_float::half> meas_entry_t;
29
+
30
+ using req_index_t = uint16_t;
31
+ constexpr auto max_req_per_coll = std::numeric_limits<req_index_t>::max();
32
+
33
+ struct MsgpackPacker;
34
+
35
+ // XXX: we require here that Request objects be modified only
36
+ // in one thread and that this be the thread that submits them to
37
+ // the request collection. This holds for Ruby, but may not hold
38
+ // e.g. for Java.
39
+ struct Request {
40
+ public:
41
+ void add(const std::string& meas_type, double value);
42
+ void set_route(std::string route_arg) {
43
+ this->route = std::move(route_arg);
44
+ }
45
+ void set_overtime_cb(const std::string& cb);
46
+
47
+ void mark_used_meas_types(index_t_set& set) const;
48
+
49
+ /*
50
+ * ["route"/<prev req index>, "overtime callback", b"<metric index 1><measurement 1>..."]]
51
+ */
52
+ void serialize(MsgpackPacker& packer,
53
+ req_index_t idx,
54
+ std::map<std::string, req_index_t>& prev_routes) const;
55
+
56
+ size_t mem_size() const;
57
+
58
+ Request() = default;
59
+ Request(const Request&) = delete;
60
+ Request(Request&&) = default;
61
+ Request& operator=(const Request&) = delete;
62
+
63
+ private:
64
+ std::string route;
65
+ index_t overtime_cb = undef_index_t;
66
+ std::list<meas_entry_t> measurements;
67
+ };
68
+
69
+ class RequestCollection {
70
+ public:
71
+ void operator<<(Request request);
72
+ bool flush(std::string& out);
73
+ size_t mem_size() const;
74
+
75
+ RequestCollection() = default;
76
+ RequestCollection(const RequestCollection&) = delete;
77
+ RequestCollection& operator=(const RequestCollection&) = delete;
78
+ private:
79
+ std::mutex m;
80
+ std::list<Request> completed_requests;
81
+ };
82
+ }
83
+
84
+ #endif // METRICS_HPP
@@ -0,0 +1,482 @@
1
+ /*
2
+ * MessagePack for C dynamic typing routine
3
+ *
4
+ * Copyright (C) 2008-2009 FURUHASHI Sadayuki
5
+ *
6
+ * Distributed under the Boost Software License, Version 1.0.
7
+ * (See accompanying file LICENSE_1_0.txt or copy at
8
+ * http://www.boost.org/LICENSE_1_0.txt)
9
+ */
10
+ #if defined(_KERNEL_MODE)
11
+ # undef _NO_CRT_STDIO_INLINE
12
+ # define _NO_CRT_STDIO_INLINE
13
+ #endif
14
+
15
+ #include "msgpack/object.h"
16
+ #include "msgpack/pack.h"
17
+ #include <ctype.h>
18
+
19
+ #include <stdio.h>
20
+ #include <string.h>
21
+
22
+ #if defined(_MSC_VER)
23
+ #if _MSC_VER >= 1800
24
+ #include <inttypes.h>
25
+ #else
26
+ #define PRIu64 "I64u"
27
+ #define PRIi64 "I64i"
28
+ #define PRIi8 "i"
29
+ #endif
30
+ #else
31
+ #include <inttypes.h>
32
+ #endif
33
+
34
+ #if defined(_KERNEL_MODE)
35
+ # undef snprintf
36
+ # define snprintf _snprintf
37
+ #endif
38
+
39
+ int msgpack_pack_object(msgpack_packer* pk, msgpack_object d)
40
+ {
41
+ switch(d.type) {
42
+ case MSGPACK_OBJECT_NIL:
43
+ return msgpack_pack_nil(pk);
44
+
45
+ case MSGPACK_OBJECT_BOOLEAN:
46
+ if(d.via.boolean) {
47
+ return msgpack_pack_true(pk);
48
+ } else {
49
+ return msgpack_pack_false(pk);
50
+ }
51
+
52
+ case MSGPACK_OBJECT_POSITIVE_INTEGER:
53
+ return msgpack_pack_uint64(pk, d.via.u64);
54
+
55
+ case MSGPACK_OBJECT_NEGATIVE_INTEGER:
56
+ return msgpack_pack_int64(pk, d.via.i64);
57
+
58
+ case MSGPACK_OBJECT_FLOAT32:
59
+ return msgpack_pack_float(pk, (float)d.via.f64);
60
+
61
+ case MSGPACK_OBJECT_FLOAT64:
62
+ return msgpack_pack_double(pk, d.via.f64);
63
+
64
+ case MSGPACK_OBJECT_STR:
65
+ {
66
+ int ret = msgpack_pack_str(pk, d.via.str.size);
67
+ if(ret < 0) { return ret; }
68
+ return msgpack_pack_str_body(pk, d.via.str.ptr, d.via.str.size);
69
+ }
70
+
71
+ case MSGPACK_OBJECT_BIN:
72
+ {
73
+ int ret = msgpack_pack_bin(pk, d.via.bin.size);
74
+ if(ret < 0) { return ret; }
75
+ return msgpack_pack_bin_body(pk, d.via.bin.ptr, d.via.bin.size);
76
+ }
77
+
78
+ case MSGPACK_OBJECT_EXT:
79
+ {
80
+ int ret = msgpack_pack_ext(pk, d.via.ext.size, d.via.ext.type);
81
+ if(ret < 0) { return ret; }
82
+ return msgpack_pack_ext_body(pk, d.via.ext.ptr, d.via.ext.size);
83
+ }
84
+
85
+ case MSGPACK_OBJECT_ARRAY:
86
+ {
87
+ int ret = msgpack_pack_array(pk, d.via.array.size);
88
+ if(ret < 0) {
89
+ return ret;
90
+ }
91
+ else {
92
+ msgpack_object* o = d.via.array.ptr;
93
+ msgpack_object* const oend = d.via.array.ptr + d.via.array.size;
94
+ for(; o != oend; ++o) {
95
+ ret = msgpack_pack_object(pk, *o);
96
+ if(ret < 0) { return ret; }
97
+ }
98
+
99
+ return 0;
100
+ }
101
+ }
102
+
103
+ case MSGPACK_OBJECT_MAP:
104
+ {
105
+ int ret = msgpack_pack_map(pk, d.via.map.size);
106
+ if(ret < 0) {
107
+ return ret;
108
+ }
109
+ else {
110
+ msgpack_object_kv* kv = d.via.map.ptr;
111
+ msgpack_object_kv* const kvend = d.via.map.ptr + d.via.map.size;
112
+ for(; kv != kvend; ++kv) {
113
+ ret = msgpack_pack_object(pk, kv->key);
114
+ if(ret < 0) { return ret; }
115
+ ret = msgpack_pack_object(pk, kv->val);
116
+ if(ret < 0) { return ret; }
117
+ }
118
+
119
+ return 0;
120
+ }
121
+ }
122
+
123
+ default:
124
+ return -1;
125
+ }
126
+ }
127
+
128
+ #if !defined(_KERNEL_MODE)
129
+
130
+ static void msgpack_object_bin_print(FILE* out, const char *ptr, size_t size)
131
+ {
132
+ size_t i;
133
+ for (i = 0; i < size; ++i) {
134
+ if (ptr[i] == '"') {
135
+ fputs("\\\"", out);
136
+ } else if (isprint((unsigned char)ptr[i])) {
137
+ fputc(ptr[i], out);
138
+ } else {
139
+ fprintf(out, "\\x%02x", (unsigned char)ptr[i]);
140
+ }
141
+ }
142
+ }
143
+
144
+ void msgpack_object_print(FILE* out, msgpack_object o)
145
+ {
146
+ switch(o.type) {
147
+ case MSGPACK_OBJECT_NIL:
148
+ fprintf(out, "nil");
149
+ break;
150
+
151
+ case MSGPACK_OBJECT_BOOLEAN:
152
+ fprintf(out, (o.via.boolean ? "true" : "false"));
153
+ break;
154
+
155
+ case MSGPACK_OBJECT_POSITIVE_INTEGER:
156
+ #if defined(PRIu64)
157
+ fprintf(out, "%" PRIu64, o.via.u64);
158
+ #else
159
+ if (o.via.u64 > ULONG_MAX)
160
+ fprintf(out, "over 4294967295");
161
+ else
162
+ fprintf(out, "%lu", (unsigned long)o.via.u64);
163
+ #endif
164
+ break;
165
+
166
+ case MSGPACK_OBJECT_NEGATIVE_INTEGER:
167
+ #if defined(PRIi64)
168
+ fprintf(out, "%" PRIi64, o.via.i64);
169
+ #else
170
+ if (o.via.i64 > LONG_MAX)
171
+ fprintf(out, "over +2147483647");
172
+ else if (o.via.i64 < LONG_MIN)
173
+ fprintf(out, "under -2147483648");
174
+ else
175
+ fprintf(out, "%ld", (signed long)o.via.i64);
176
+ #endif
177
+ break;
178
+
179
+ case MSGPACK_OBJECT_FLOAT32:
180
+ case MSGPACK_OBJECT_FLOAT64:
181
+ fprintf(out, "%f", o.via.f64);
182
+ break;
183
+
184
+ case MSGPACK_OBJECT_STR:
185
+ fprintf(out, "\"");
186
+ fwrite(o.via.str.ptr, o.via.str.size, 1, out);
187
+ fprintf(out, "\"");
188
+ break;
189
+
190
+ case MSGPACK_OBJECT_BIN:
191
+ fprintf(out, "\"");
192
+ msgpack_object_bin_print(out, o.via.bin.ptr, o.via.bin.size);
193
+ fprintf(out, "\"");
194
+ break;
195
+
196
+ case MSGPACK_OBJECT_EXT:
197
+ #if defined(PRIi8)
198
+ fprintf(out, "(ext: %" PRIi8 ")", o.via.ext.type);
199
+ #else
200
+ fprintf(out, "(ext: %d)", (int)o.via.ext.type);
201
+ #endif
202
+ fprintf(out, "\"");
203
+ msgpack_object_bin_print(out, o.via.ext.ptr, o.via.ext.size);
204
+ fprintf(out, "\"");
205
+ break;
206
+
207
+ case MSGPACK_OBJECT_ARRAY:
208
+ fprintf(out, "[");
209
+ if(o.via.array.size != 0) {
210
+ msgpack_object* p = o.via.array.ptr;
211
+ msgpack_object* const pend = o.via.array.ptr + o.via.array.size;
212
+ msgpack_object_print(out, *p);
213
+ ++p;
214
+ for(; p < pend; ++p) {
215
+ fprintf(out, ", ");
216
+ msgpack_object_print(out, *p);
217
+ }
218
+ }
219
+ fprintf(out, "]");
220
+ break;
221
+
222
+ case MSGPACK_OBJECT_MAP:
223
+ fprintf(out, "{");
224
+ if(o.via.map.size != 0) {
225
+ msgpack_object_kv* p = o.via.map.ptr;
226
+ msgpack_object_kv* const pend = o.via.map.ptr + o.via.map.size;
227
+ msgpack_object_print(out, p->key);
228
+ fprintf(out, "=>");
229
+ msgpack_object_print(out, p->val);
230
+ ++p;
231
+ for(; p < pend; ++p) {
232
+ fprintf(out, ", ");
233
+ msgpack_object_print(out, p->key);
234
+ fprintf(out, "=>");
235
+ msgpack_object_print(out, p->val);
236
+ }
237
+ }
238
+ fprintf(out, "}");
239
+ break;
240
+
241
+ default:
242
+ // FIXME
243
+ #if defined(PRIu64)
244
+ fprintf(out, "#<UNKNOWN %i %" PRIu64 ">", o.type, o.via.u64);
245
+ #else
246
+ if (o.via.u64 > ULONG_MAX)
247
+ fprintf(out, "#<UNKNOWN %i over 4294967295>", o.type);
248
+ else
249
+ fprintf(out, "#<UNKNOWN %i %lu>", o.type, (unsigned long)o.via.u64);
250
+ #endif
251
+
252
+ }
253
+ }
254
+
255
+ #endif
256
+
257
+ #define MSGPACK_CHECKED_CALL(ret, func, aux_buffer, aux_buffer_size, ...) \
258
+ ret = func(aux_buffer, aux_buffer_size, __VA_ARGS__); \
259
+ if (ret <= 0 || ret >= (int)aux_buffer_size) return 0; \
260
+ aux_buffer = aux_buffer + ret; \
261
+ aux_buffer_size = aux_buffer_size - ret \
262
+
263
+ static int msgpack_object_bin_print_buffer(char *buffer, size_t buffer_size, const char *ptr, size_t size)
264
+ {
265
+ size_t i;
266
+ char *aux_buffer = buffer;
267
+ size_t aux_buffer_size = buffer_size;
268
+ int ret;
269
+
270
+ for (i = 0; i < size; ++i) {
271
+ if (ptr[i] == '"') {
272
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\\\"");
273
+ } else if (isprint((unsigned char)ptr[i])) {
274
+ if (aux_buffer_size > 0) {
275
+ memcpy(aux_buffer, ptr + i, 1);
276
+ aux_buffer = aux_buffer + 1;
277
+ aux_buffer_size = aux_buffer_size - 1;
278
+ }
279
+ } else {
280
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\\x%02x", (unsigned char)ptr[i]);
281
+ }
282
+ }
283
+
284
+ return (int)(buffer_size - aux_buffer_size);
285
+ }
286
+
287
+ int msgpack_object_print_buffer(char *buffer, size_t buffer_size, msgpack_object o)
288
+ {
289
+ char *aux_buffer = buffer;
290
+ size_t aux_buffer_size = buffer_size;
291
+ int ret;
292
+ switch(o.type) {
293
+ case MSGPACK_OBJECT_NIL:
294
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "nil");
295
+ break;
296
+
297
+ case MSGPACK_OBJECT_BOOLEAN:
298
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, (o.via.boolean ? "true" : "false"));
299
+ break;
300
+
301
+ case MSGPACK_OBJECT_POSITIVE_INTEGER:
302
+ #if defined(PRIu64)
303
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%" PRIu64, o.via.u64);
304
+ #else
305
+ if (o.via.u64 > ULONG_MAX) {
306
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "over 4294967295");
307
+ } else {
308
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%lu", (unsigned long)o.via.u64);
309
+ }
310
+ #endif
311
+ break;
312
+
313
+ case MSGPACK_OBJECT_NEGATIVE_INTEGER:
314
+ #if defined(PRIi64)
315
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%" PRIi64, o.via.i64);
316
+ #else
317
+ if (o.via.i64 > LONG_MAX) {
318
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "over +2147483647");
319
+ } else if (o.via.i64 < LONG_MIN) {
320
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "under -2147483648");
321
+ } else {
322
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%ld", (signed long)o.via.i64);
323
+ }
324
+ #endif
325
+ break;
326
+
327
+ case MSGPACK_OBJECT_FLOAT32:
328
+ case MSGPACK_OBJECT_FLOAT64:
329
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%f", o.via.f64);
330
+ break;
331
+
332
+ case MSGPACK_OBJECT_STR:
333
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
334
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%.*s", (int)o.via.str.size, o.via.str.ptr);
335
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
336
+ break;
337
+
338
+ case MSGPACK_OBJECT_BIN:
339
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
340
+ MSGPACK_CHECKED_CALL(ret, msgpack_object_bin_print_buffer, aux_buffer, aux_buffer_size, o.via.bin.ptr, o.via.bin.size);
341
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
342
+ break;
343
+
344
+ case MSGPACK_OBJECT_EXT:
345
+ #if defined(PRIi8)
346
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "(ext: %" PRIi8 ")", o.via.ext.type);
347
+ #else
348
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "(ext: %d)", (int)o.via.ext.type);
349
+ #endif
350
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
351
+ MSGPACK_CHECKED_CALL(ret, msgpack_object_bin_print_buffer, aux_buffer, aux_buffer_size, o.via.ext.ptr, o.via.ext.size);
352
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
353
+ break;
354
+
355
+ case MSGPACK_OBJECT_ARRAY:
356
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "[");
357
+ if(o.via.array.size != 0) {
358
+ msgpack_object* p = o.via.array.ptr;
359
+ msgpack_object* const pend = o.via.array.ptr + o.via.array.size;
360
+ MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, *p);
361
+ ++p;
362
+ for(; p < pend; ++p) {
363
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, ", ");
364
+ MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, *p);
365
+ }
366
+ }
367
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "]");
368
+ break;
369
+
370
+ case MSGPACK_OBJECT_MAP:
371
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "{");
372
+ if(o.via.map.size != 0) {
373
+ msgpack_object_kv* p = o.via.map.ptr;
374
+ msgpack_object_kv* const pend = o.via.map.ptr + o.via.map.size;
375
+ MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, p->key);
376
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "=>");
377
+ MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, p->val);
378
+ ++p;
379
+ for(; p < pend; ++p) {
380
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, ", ");
381
+ MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, p->key);
382
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "=>");
383
+ MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, p->val);
384
+ }
385
+ }
386
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "}");
387
+ break;
388
+
389
+ default:
390
+ // FIXME
391
+ #if defined(PRIu64)
392
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "#<UNKNOWN %i %" PRIu64 ">", o.type, o.via.u64);
393
+ #else
394
+ if (o.via.u64 > ULONG_MAX) {
395
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "#<UNKNOWN %i over 4294967295>", o.type);
396
+ } else {
397
+ MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "#<UNKNOWN %i %lu>", o.type, (unsigned long)o.via.u64);
398
+ }
399
+ #endif
400
+ }
401
+
402
+ return (int)(buffer_size - aux_buffer_size);
403
+ }
404
+
405
+ #undef MSGPACK_CHECKED_CALL
406
+
407
+ bool msgpack_object_equal(const msgpack_object x, const msgpack_object y)
408
+ {
409
+ if(x.type != y.type) { return false; }
410
+
411
+ switch(x.type) {
412
+ case MSGPACK_OBJECT_NIL:
413
+ return true;
414
+
415
+ case MSGPACK_OBJECT_BOOLEAN:
416
+ return x.via.boolean == y.via.boolean;
417
+
418
+ case MSGPACK_OBJECT_POSITIVE_INTEGER:
419
+ return x.via.u64 == y.via.u64;
420
+
421
+ case MSGPACK_OBJECT_NEGATIVE_INTEGER:
422
+ return x.via.i64 == y.via.i64;
423
+
424
+ case MSGPACK_OBJECT_FLOAT32:
425
+ case MSGPACK_OBJECT_FLOAT64:
426
+ return x.via.f64 == y.via.f64;
427
+
428
+ case MSGPACK_OBJECT_STR:
429
+ return x.via.str.size == y.via.str.size &&
430
+ memcmp(x.via.str.ptr, y.via.str.ptr, x.via.str.size) == 0;
431
+
432
+ case MSGPACK_OBJECT_BIN:
433
+ return x.via.bin.size == y.via.bin.size &&
434
+ memcmp(x.via.bin.ptr, y.via.bin.ptr, x.via.bin.size) == 0;
435
+
436
+ case MSGPACK_OBJECT_EXT:
437
+ return x.via.ext.size == y.via.ext.size &&
438
+ x.via.ext.type == y.via.ext.type &&
439
+ memcmp(x.via.ext.ptr, y.via.ext.ptr, x.via.ext.size) == 0;
440
+
441
+ case MSGPACK_OBJECT_ARRAY:
442
+ if(x.via.array.size != y.via.array.size) {
443
+ return false;
444
+ } else if(x.via.array.size == 0) {
445
+ return true;
446
+ } else {
447
+ msgpack_object* px = x.via.array.ptr;
448
+ msgpack_object* const pxend = x.via.array.ptr + x.via.array.size;
449
+ msgpack_object* py = y.via.array.ptr;
450
+ do {
451
+ if(!msgpack_object_equal(*px, *py)) {
452
+ return false;
453
+ }
454
+ ++px;
455
+ ++py;
456
+ } while(px < pxend);
457
+ return true;
458
+ }
459
+
460
+ case MSGPACK_OBJECT_MAP:
461
+ if(x.via.map.size != y.via.map.size) {
462
+ return false;
463
+ } else if(x.via.map.size == 0) {
464
+ return true;
465
+ } else {
466
+ msgpack_object_kv* px = x.via.map.ptr;
467
+ msgpack_object_kv* const pxend = x.via.map.ptr + x.via.map.size;
468
+ msgpack_object_kv* py = y.via.map.ptr;
469
+ do {
470
+ if(!msgpack_object_equal(px->key, py->key) || !msgpack_object_equal(px->val, py->val)) {
471
+ return false;
472
+ }
473
+ ++px;
474
+ ++py;
475
+ } while(px < pxend);
476
+ return true;
477
+ }
478
+
479
+ default:
480
+ return false;
481
+ }
482
+ }