sq_detailed_metrics 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/extconf.rb +26 -0
- data/include/half.hpp +4575 -0
- data/include/msgpack.h +24 -0
- data/include/msgpack/fbuffer.h +42 -0
- data/include/msgpack/gcc_atomic.h +25 -0
- data/include/msgpack/object.h +118 -0
- data/include/msgpack/pack.h +174 -0
- data/include/msgpack/pack_define.h +18 -0
- data/include/msgpack/pack_template.h +952 -0
- data/include/msgpack/sbuffer.h +115 -0
- data/include/msgpack/sysdep.h +221 -0
- data/include/msgpack/timestamp.h +58 -0
- data/include/msgpack/unpack.h +281 -0
- data/include/msgpack/unpack_define.h +89 -0
- data/include/msgpack/unpack_template.h +471 -0
- data/include/msgpack/util.h +15 -0
- data/include/msgpack/version.h +38 -0
- data/include/msgpack/version_master.h +3 -0
- data/include/msgpack/vrefbuffer.h +144 -0
- data/include/msgpack/zbuffer.h +205 -0
- data/include/msgpack/zone.h +163 -0
- data/include/rapidjson/allocators.h +271 -0
- data/include/rapidjson/document.h +2575 -0
- data/include/rapidjson/encodedstream.h +299 -0
- data/include/rapidjson/encodings.h +716 -0
- data/include/rapidjson/error/en.h +74 -0
- data/include/rapidjson/error/error.h +155 -0
- data/include/rapidjson/filereadstream.h +99 -0
- data/include/rapidjson/filewritestream.h +104 -0
- data/include/rapidjson/fwd.h +151 -0
- data/include/rapidjson/internal/biginteger.h +290 -0
- data/include/rapidjson/internal/diyfp.h +258 -0
- data/include/rapidjson/internal/dtoa.h +245 -0
- data/include/rapidjson/internal/ieee754.h +78 -0
- data/include/rapidjson/internal/itoa.h +304 -0
- data/include/rapidjson/internal/meta.h +181 -0
- data/include/rapidjson/internal/pow10.h +55 -0
- data/include/rapidjson/internal/regex.h +701 -0
- data/include/rapidjson/internal/stack.h +230 -0
- data/include/rapidjson/internal/strfunc.h +55 -0
- data/include/rapidjson/internal/strtod.h +269 -0
- data/include/rapidjson/internal/swap.h +46 -0
- data/include/rapidjson/istreamwrapper.h +115 -0
- data/include/rapidjson/memorybuffer.h +70 -0
- data/include/rapidjson/memorystream.h +71 -0
- data/include/rapidjson/msinttypes/inttypes.h +316 -0
- data/include/rapidjson/msinttypes/stdint.h +300 -0
- data/include/rapidjson/ostreamwrapper.h +81 -0
- data/include/rapidjson/pointer.h +1358 -0
- data/include/rapidjson/prettywriter.h +255 -0
- data/include/rapidjson/rapidjson.h +615 -0
- data/include/rapidjson/reader.h +1879 -0
- data/include/rapidjson/schema.h +2006 -0
- data/include/rapidjson/stream.h +179 -0
- data/include/rapidjson/stringbuffer.h +117 -0
- data/include/rapidjson/writer.h +610 -0
- data/include/xxhash.h +328 -0
- data/json_conv.cpp +284 -0
- data/json_conv.hpp +17 -0
- data/metrics.cpp +239 -0
- data/metrics.hpp +84 -0
- data/msgpack/objectc.c +482 -0
- data/msgpack/unpack.c +703 -0
- data/msgpack/version.c +22 -0
- data/msgpack/vrefbuffer.c +250 -0
- data/msgpack/zone.c +222 -0
- data/sq_detailed_metrics.cpp +248 -0
- metadata +199 -0
data/json_conv.hpp
ADDED
@@ -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
|
data/metrics.cpp
ADDED
@@ -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
|
+
}
|
data/metrics.hpp
ADDED
@@ -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
|
data/msgpack/objectc.c
ADDED
@@ -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
|
+
}
|