line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#include "EXTERN.h" |
2
|
|
|
|
|
|
|
#include "perl.h" |
3
|
|
|
|
|
|
|
#include "XSUB.h" |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
#define NEED_newSVpvn_flags |
6
|
|
|
|
|
|
|
#define NEED_newRV_noinc |
7
|
|
|
|
|
|
|
#define NEED_sv_2pvbyte |
8
|
|
|
|
|
|
|
#define NEED_sv_2pv_flags |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
#include "ppport.h" |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
#ifndef MUTABLE_AV |
13
|
|
|
|
|
|
|
#define MUTABLE_AV(p) ((AV *)MUTABLE_PTR(p)) |
14
|
|
|
|
|
|
|
#endif |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
#ifndef MUTABLE_SV |
17
|
|
|
|
|
|
|
#define MUTABLE_SV(p) ((SV *)MUTABLE_PTR(p)) |
18
|
|
|
|
|
|
|
#endif |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
#ifndef MUTABLE_HV |
21
|
|
|
|
|
|
|
#define MUTABLE_HV(p) ((HV *)MUTABLE_PTR(p)) |
22
|
|
|
|
|
|
|
#endif |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
#include |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
#if !(IVSIZE == 8 || IVSIZE == 4 || IVSIZE == 2) |
27
|
|
|
|
|
|
|
#error "msgpack only supports IVSIZE = 8, 4 or 2" |
28
|
|
|
|
|
|
|
#endif |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
typedef struct |
31
|
|
|
|
|
|
|
{ |
32
|
|
|
|
|
|
|
int code; |
33
|
|
|
|
|
|
|
SV *message; |
34
|
|
|
|
|
|
|
const char *file; |
35
|
|
|
|
|
|
|
unsigned int line; |
36
|
|
|
|
|
|
|
} msgpack_raw_error; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
typedef struct |
39
|
|
|
|
|
|
|
{ |
40
|
|
|
|
|
|
|
msgpack_packer packer; |
41
|
|
|
|
|
|
|
SV *data; |
42
|
|
|
|
|
|
|
} msgpack_raw_packer; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
typedef struct |
45
|
|
|
|
|
|
|
{ |
46
|
|
|
|
|
|
|
msgpack_unpacker unpacker; |
47
|
|
|
|
|
|
|
} msgpack_raw_unpacker; |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
typedef msgpack_raw_packer *Packer; |
50
|
|
|
|
|
|
|
typedef msgpack_raw_unpacker *Unpacker; |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
#define MSGPACK_NEW_OBJ(rv, package, sv) \ |
53
|
|
|
|
|
|
|
STMT_START { \ |
54
|
|
|
|
|
|
|
(rv) = sv_setref_pv (newSV(0), package, sv); \ |
55
|
|
|
|
|
|
|
} STMT_END |
56
|
|
|
|
|
|
|
|
57
|
0
|
|
|
|
|
|
STATIC void *msgpack_sv_to_ptr (const char *type, SV *sv, const char *file, int line) |
58
|
|
|
|
|
|
|
{ |
59
|
0
|
|
|
|
|
|
SV *full_type = sv_2mortal (newSVpvf ("MsgPack::Raw::%s", type)); |
60
|
|
|
|
|
|
|
|
61
|
0
|
0
|
|
|
|
|
if (!(sv_isobject (sv) && sv_derived_from (sv, SvPV_nolen (full_type)))) |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
62
|
0
|
0
|
|
|
|
|
croak("Argument is not of type %s @ (%s:%d)\n", |
63
|
0
|
|
|
|
|
|
SvPV_nolen (full_type), file, line); |
64
|
|
|
|
|
|
|
|
65
|
0
|
0
|
|
|
|
|
return INT2PTR (void *, SvIV ((SV *) SvRV (sv))); |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
#define MSGPACK_SV_TO_PTR(type, sv) \ |
69
|
|
|
|
|
|
|
msgpack_sv_to_ptr(#type, sv, __FILE__, __LINE__) |
70
|
|
|
|
|
|
|
|
71
|
401
|
|
|
|
|
|
STATIC int msgpack_raw_packer_write(void *data, const char *buf, size_t len) |
72
|
|
|
|
|
|
|
{ |
73
|
401
|
|
|
|
|
|
msgpack_raw_packer *packer = (msgpack_raw_packer *)data; |
74
|
|
|
|
|
|
|
|
75
|
401
|
|
|
|
|
|
sv_catpvn (packer->data, buf, len); |
76
|
|
|
|
|
|
|
|
77
|
401
|
|
|
|
|
|
return 0; |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
366
|
|
|
|
|
|
STATIC void encode_msgpack (msgpack_raw_packer *packer, SV *sv) |
81
|
|
|
|
|
|
|
{ |
82
|
366
|
100
|
|
|
|
|
if (SvIOKp (sv)) |
83
|
|
|
|
|
|
|
{ |
84
|
35
|
50
|
|
|
|
|
if (SvUOK (sv)) |
85
|
|
|
|
|
|
|
{ |
86
|
|
|
|
|
|
|
#if IVSIZE == 8 |
87
|
0
|
|
|
|
|
|
msgpack_pack_uint64 (&packer->packer, SvUVX (sv)); |
88
|
|
|
|
|
|
|
#elif IVSIZE == 4 |
89
|
|
|
|
|
|
|
msgpack_pack_uint32 (&packer->packer, SvUVX (sv)); |
90
|
|
|
|
|
|
|
#elif IVSIZE == 2 |
91
|
|
|
|
|
|
|
msgpack_pack_uint16 (&packer->packer, SvUVX (sv)); |
92
|
|
|
|
|
|
|
#endif |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
else |
95
|
|
|
|
|
|
|
{ |
96
|
|
|
|
|
|
|
#if IVSIZE == 8 |
97
|
35
|
|
|
|
|
|
msgpack_pack_int64 (&packer->packer, SvIVX (sv)); |
98
|
|
|
|
|
|
|
#elif IVSIZE == 4 |
99
|
|
|
|
|
|
|
msgpack_pack_int32 (&packer->packer, SvIVX (sv)); |
100
|
|
|
|
|
|
|
#elif IVSIZE == 2 |
101
|
|
|
|
|
|
|
msgpack_pack_int16 (&packer->packer, SvIVX (sv)); |
102
|
|
|
|
|
|
|
#endif |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
} |
105
|
331
|
100
|
|
|
|
|
else if (SvPOKp (sv)) |
106
|
|
|
|
|
|
|
{ |
107
|
25
|
100
|
|
|
|
|
if (SvUTF8 (sv)) |
108
|
|
|
|
|
|
|
{ |
109
|
5
|
|
|
|
|
|
msgpack_pack_str (&packer->packer, SvCUR (sv)); |
110
|
5
|
|
|
|
|
|
msgpack_pack_str_body (&packer->packer, SvPVX_const (sv), SvCUR (sv)); |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
else |
113
|
|
|
|
|
|
|
{ |
114
|
20
|
|
|
|
|
|
msgpack_pack_bin (&packer->packer, SvCUR (sv)); |
115
|
25
|
|
|
|
|
|
msgpack_pack_bin_body (&packer->packer, SvPVX_const (sv), SvCUR (sv)); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
} |
118
|
306
|
100
|
|
|
|
|
else if (SvNOKp (sv)) |
119
|
|
|
|
|
|
|
{ |
120
|
1
|
|
|
|
|
|
msgpack_pack_double (&packer->packer, (double)SvNVX (sv)); |
121
|
|
|
|
|
|
|
} |
122
|
305
|
100
|
|
|
|
|
else if (SvROK (sv)) |
123
|
|
|
|
|
|
|
{ |
124
|
43
|
100
|
|
|
|
|
if (sv_isobject (sv) && sv_derived_from (sv, "MsgPack::Raw::Bool")) |
|
|
100
|
|
|
|
|
|
125
|
|
|
|
|
|
|
{ |
126
|
20
|
50
|
|
|
|
|
if (SvIV (SvRV (sv))) |
|
|
100
|
|
|
|
|
|
127
|
5
|
|
|
|
|
|
msgpack_pack_true (&packer->packer); |
128
|
|
|
|
|
|
|
else |
129
|
5
|
|
|
|
|
|
msgpack_pack_false (&packer->packer); |
130
|
|
|
|
|
|
|
} |
131
|
33
|
100
|
|
|
|
|
else if (sv_isobject (sv) && sv_derived_from (sv, "MsgPack::Raw::Ext")) |
|
|
50
|
|
|
|
|
|
132
|
43
|
|
|
|
|
|
{ |
133
|
10
|
|
|
|
|
|
HV *hash = MUTABLE_HV (SvRV (sv)); |
134
|
10
|
|
|
|
|
|
SV **type = hv_fetchs (hash, "type", 0); |
135
|
10
|
|
|
|
|
|
SV **data = hv_fetchs (hash, "data", 0); |
136
|
|
|
|
|
|
|
|
137
|
10
|
50
|
|
|
|
|
if (!type || !SvOK (*type)) |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
138
|
0
|
|
|
|
|
|
croak ("MsgPack::Raw::Ext object doesn't have a type member"); |
139
|
10
|
50
|
|
|
|
|
if (!data || !SvOK (*data)) |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
140
|
0
|
|
|
|
|
|
croak ("MsgPack::Raw::Ext object doesn't have a data member"); |
141
|
10
|
50
|
|
|
|
|
if (!SvIOK(*type) || SvIV(*type) < 0 || SvIV(*type)>255) |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
142
|
0
|
|
|
|
|
|
croak ("MsgPack::Raw::Ext type invalid"); |
143
|
|
|
|
|
|
|
|
144
|
10
|
50
|
|
|
|
|
msgpack_pack_ext (&packer->packer, SvCUR (*data), SvIV (*type)); |
145
|
10
|
|
|
|
|
|
msgpack_pack_ext_body (&packer->packer, SvPVX_const (*data), SvCUR (*data)); |
146
|
|
|
|
|
|
|
} |
147
|
23
|
100
|
|
|
|
|
else if (SvTYPE (SvRV (sv)) == SVt_PVHV) |
148
|
|
|
|
|
|
|
{ |
149
|
4
|
|
|
|
|
|
HV *hash = MUTABLE_HV (SvRV (sv)); |
150
|
4
|
|
|
|
|
|
I32 count = hv_iterinit (hash); |
151
|
|
|
|
|
|
|
HE *entry; |
152
|
|
|
|
|
|
|
|
153
|
4
|
|
|
|
|
|
msgpack_pack_map (&packer->packer, count); |
154
|
10
|
100
|
|
|
|
|
while ((entry = hv_iternext (hash))) |
155
|
|
|
|
|
|
|
{ |
156
|
6
|
|
|
|
|
|
encode_msgpack (packer, hv_iterkeysv (entry)); |
157
|
6
|
|
|
|
|
|
encode_msgpack (packer, hv_iterval (hash, entry)); |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
} |
160
|
19
|
50
|
|
|
|
|
else if (SvTYPE (SvRV (sv)) == SVt_PVAV) |
161
|
|
|
|
|
|
|
{ |
162
|
19
|
|
|
|
|
|
AV *list = MUTABLE_AV (SvRV (sv)); |
163
|
19
|
|
|
|
|
|
STRLEN i, size = av_len (list)+1; |
164
|
|
|
|
|
|
|
|
165
|
19
|
|
|
|
|
|
msgpack_pack_array (&packer->packer, size); |
166
|
313
|
100
|
|
|
|
|
for (i = 0; i < size; ++i) |
167
|
|
|
|
|
|
|
{ |
168
|
294
|
|
|
|
|
|
SV **value = av_fetch (list, i, 0); |
169
|
294
|
50
|
|
|
|
|
if (value && *value) |
|
|
50
|
|
|
|
|
|
170
|
294
|
|
|
|
|
|
encode_msgpack (packer, *value); |
171
|
|
|
|
|
|
|
else |
172
|
0
|
|
|
|
|
|
msgpack_pack_nil (&packer->packer); |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
else |
176
|
|
|
|
|
|
|
{ |
177
|
0
|
0
|
|
|
|
|
croak ("encountered object '%s', Data::MessagePack doesn't allow the object", |
178
|
0
|
|
|
|
|
|
SvPV_nolen(sv_2mortal(newRV_inc(sv)))); |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
} |
181
|
262
|
50
|
|
|
|
|
else if (!SvOK (sv)) |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
182
|
|
|
|
|
|
|
{ |
183
|
262
|
|
|
|
|
|
msgpack_pack_nil (&packer->packer); |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
else |
186
|
|
|
|
|
|
|
{ |
187
|
0
|
|
|
|
|
|
croak ("cannot pack type: %d\n", SvTYPE (sv)); |
188
|
|
|
|
|
|
|
} |
189
|
366
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
21
|
|
|
|
|
|
STATIC SV *decode_msgpack (msgpack_object *obj) |
192
|
|
|
|
|
|
|
{ |
193
|
21
|
|
|
|
|
|
switch (obj->type) |
194
|
|
|
|
|
|
|
{ |
195
|
|
|
|
|
|
|
// simple types |
196
|
0
|
|
|
|
|
|
case MSGPACK_OBJECT_NIL: return &PL_sv_undef; |
197
|
1
|
|
|
|
|
|
case MSGPACK_OBJECT_POSITIVE_INTEGER: return newSVuv (obj->via.u64); |
198
|
0
|
|
|
|
|
|
case MSGPACK_OBJECT_NEGATIVE_INTEGER: return newSViv (obj->via.i64); |
199
|
|
|
|
|
|
|
case MSGPACK_OBJECT_FLOAT32: // fall-through |
200
|
0
|
|
|
|
|
|
case MSGPACK_OBJECT_FLOAT64: return newSVnv (obj->via.f64); |
201
|
0
|
|
|
|
|
|
case MSGPACK_OBJECT_STR: return newSVpvn_utf8 (obj->via.str.ptr, obj->via.str.size, 1); |
202
|
10
|
|
|
|
|
|
case MSGPACK_OBJECT_BIN: return newSVpvn (obj->via.bin.ptr, obj->via.bin.size); |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
// complex types |
205
|
|
|
|
|
|
|
case MSGPACK_OBJECT_BOOLEAN: |
206
|
|
|
|
|
|
|
{ |
207
|
4
|
|
|
|
|
|
return sv_bless (newRV_noinc (newSViv (obj->via.boolean)), |
208
|
|
|
|
|
|
|
gv_stashpv ("MsgPack::Raw::Bool", 0)); |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
case MSGPACK_OBJECT_ARRAY: |
211
|
|
|
|
|
|
|
{ |
212
|
2
|
|
|
|
|
|
AV *list = MUTABLE_AV (sv_2mortal (MUTABLE_SV (newAV()))); |
213
|
2
|
|
|
|
|
|
msgpack_object *items = obj->via.array.ptr; |
214
|
2
|
|
|
|
|
|
uint32_t size = obj->via.array.size; |
215
|
|
|
|
|
|
|
|
216
|
6
|
100
|
|
|
|
|
while (size--) |
217
|
|
|
|
|
|
|
{ |
218
|
4
|
|
|
|
|
|
av_push (list, decode_msgpack (items++)); |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
|
221
|
2
|
|
|
|
|
|
return newRV_inc (MUTABLE_SV (list)); |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
case MSGPACK_OBJECT_MAP: |
224
|
|
|
|
|
|
|
{ |
225
|
2
|
|
|
|
|
|
HV *hash = MUTABLE_HV (sv_2mortal (MUTABLE_SV (newHV()))); |
226
|
2
|
|
|
|
|
|
msgpack_object_kv *items = obj->via.map.ptr; |
227
|
2
|
|
|
|
|
|
uint32_t size = obj->via.map.size; |
228
|
|
|
|
|
|
|
|
229
|
6
|
100
|
|
|
|
|
while (size--) |
230
|
|
|
|
|
|
|
{ |
231
|
4
|
|
|
|
|
|
SV *key = sv_2mortal (decode_msgpack (&items->key)); |
232
|
4
|
|
|
|
|
|
SV *value = sv_2mortal (decode_msgpack (&items->val)); |
233
|
|
|
|
|
|
|
|
234
|
4
|
|
|
|
|
|
hv_store (hash, SvPVX (key), SvCUR (key), value, 0); |
235
|
4
|
|
|
|
|
|
SvREFCNT_inc_NN (value); |
236
|
|
|
|
|
|
|
|
237
|
4
|
|
|
|
|
|
++items; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
|
240
|
2
|
|
|
|
|
|
return newRV_inc (MUTABLE_SV (hash)); |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
case MSGPACK_OBJECT_EXT: |
243
|
|
|
|
|
|
|
{ |
244
|
2
|
|
|
|
|
|
HV *hash = MUTABLE_HV (sv_2mortal (MUTABLE_SV (newHV()))); |
245
|
2
|
|
|
|
|
|
hv_stores (hash, "type", newSViv (obj->via.ext.type)); |
246
|
2
|
|
|
|
|
|
hv_stores (hash, "data", newSVpvn (obj->via.ext.ptr, obj->via.ext.size)); |
247
|
2
|
|
|
|
|
|
return sv_bless (newRV_inc (MUTABLE_SV (hash)), |
248
|
|
|
|
|
|
|
gv_stashpv ("MsgPack::Raw::Ext", 0)); |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
default: |
252
|
0
|
|
|
|
|
|
croak ("unknown object type: %d", obj->type); |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
// unreachable |
256
|
|
|
|
|
|
|
return &PL_sv_undef; |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
MODULE = MsgPack::Raw PACKAGE = MsgPack::Raw |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
INCLUDE: xs/Packer.xs |
262
|
|
|
|
|
|
|
INCLUDE: xs/Unpacker.xs |
263
|
|
|
|
|
|
|
|