line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
/* |
2
|
|
|
|
|
|
|
* code is written by tokuhirom. |
3
|
|
|
|
|
|
|
* buffer alocation technique is taken from JSON::XS. thanks to mlehmann. |
4
|
|
|
|
|
|
|
*/ |
5
|
|
|
|
|
|
|
#include "xshelper.h" |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
#include "msgpack/pack_define.h" |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
#define msgpack_pack_inline_func(name) \ |
10
|
|
|
|
|
|
|
static inline void msgpack_pack ## name |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
#define msgpack_pack_inline_func_cint(name) \ |
13
|
|
|
|
|
|
|
static inline void msgpack_pack ## name |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
// serialization context |
16
|
|
|
|
|
|
|
typedef struct { |
17
|
|
|
|
|
|
|
char *cur; /* SvPVX (sv) + current output position */ |
18
|
|
|
|
|
|
|
const char *end; /* SvEND (sv) */ |
19
|
|
|
|
|
|
|
SV *sv; /* result scalar */ |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
bool prefer_int; |
22
|
|
|
|
|
|
|
bool canonical; |
23
|
|
|
|
|
|
|
} enc_t; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
STATIC_INLINE void |
26
|
7367
|
|
|
|
|
|
dmp_append_buf(enc_t* const enc, const void* const buf, STRLEN const len) |
27
|
|
|
|
|
|
|
{ |
28
|
7367
|
100
|
|
|
|
|
if (enc->cur + len >= enc->end) { |
29
|
|
|
|
|
|
|
dTHX; |
30
|
393
|
|
|
|
|
|
STRLEN const cur = enc->cur - SvPVX_const(enc->sv); |
31
|
393
|
|
|
|
|
|
sv_grow (enc->sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1); |
32
|
393
|
|
|
|
|
|
enc->cur = SvPVX_mutable(enc->sv) + cur; |
33
|
393
|
|
|
|
|
|
enc->end = SvPVX_const(enc->sv) + SvLEN (enc->sv) - 1; |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
|
36
|
7367
|
|
|
|
|
|
memcpy(enc->cur, buf, len); |
37
|
7367
|
|
|
|
|
|
enc->cur += len; |
38
|
7367
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
#define msgpack_pack_user enc_t* |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
#define msgpack_pack_append_buffer(enc, buf, len) \ |
43
|
|
|
|
|
|
|
dmp_append_buf(enc, buf, len) |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
#include "msgpack/pack_template.h" |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
#define INIT_SIZE 32 /* initial scalar size to be allocated */ |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
#if IVSIZE == 8 |
50
|
|
|
|
|
|
|
# define PACK_IV msgpack_pack_int64 |
51
|
|
|
|
|
|
|
# define PACK_UV msgpack_pack_uint64 |
52
|
|
|
|
|
|
|
#elif IVSIZE == 4 |
53
|
|
|
|
|
|
|
# define PACK_IV msgpack_pack_int32 |
54
|
|
|
|
|
|
|
# define PACK_UV msgpack_pack_uint32 |
55
|
|
|
|
|
|
|
#elif IVSIZE == 2 |
56
|
|
|
|
|
|
|
# define PACK_IV msgpack_pack_int16 |
57
|
|
|
|
|
|
|
# define PACK_UV msgpack_pack_uint16 |
58
|
|
|
|
|
|
|
#else |
59
|
|
|
|
|
|
|
# error "msgpack only supports IVSIZE = 8,4,2 environment." |
60
|
|
|
|
|
|
|
#endif |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
#define ERR_NESTING_EXCEEDED "perl structure exceeds maximum nesting level (max_depth set too low?)" |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
#define DMP_PREF_INT "PreferInteger" |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
/* interpreter global variables */ |
67
|
|
|
|
|
|
|
#define MY_CXT_KEY "Data::MessagePack::_pack_guts" XS_VERSION |
68
|
|
|
|
|
|
|
typedef struct { |
69
|
|
|
|
|
|
|
bool prefer_int; |
70
|
|
|
|
|
|
|
bool canonical; |
71
|
|
|
|
|
|
|
} my_cxt_t; |
72
|
|
|
|
|
|
|
START_MY_CXT |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
|
75
|
89
|
|
|
|
|
|
static int dmp_config_set(pTHX_ SV* sv, MAGIC* mg) { |
76
|
|
|
|
|
|
|
dMY_CXT; |
77
|
|
|
|
|
|
|
assert(mg->mg_ptr); |
78
|
89
|
50
|
|
|
|
|
if(strEQ(mg->mg_ptr, DMP_PREF_INT)) { |
79
|
89
|
50
|
|
|
|
|
MY_CXT.prefer_int = SvTRUE(sv) ? true : false; |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
else { |
82
|
|
|
|
|
|
|
assert(0); |
83
|
|
|
|
|
|
|
} |
84
|
89
|
|
|
|
|
|
return 0; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
MGVTBL dmp_config_vtbl = { |
88
|
|
|
|
|
|
|
NULL, |
89
|
|
|
|
|
|
|
dmp_config_set, |
90
|
|
|
|
|
|
|
NULL, |
91
|
|
|
|
|
|
|
NULL, |
92
|
|
|
|
|
|
|
NULL, |
93
|
|
|
|
|
|
|
NULL, |
94
|
|
|
|
|
|
|
NULL, |
95
|
|
|
|
|
|
|
#ifdef MGf_LOCAL |
96
|
|
|
|
|
|
|
NULL, |
97
|
|
|
|
|
|
|
#endif |
98
|
|
|
|
|
|
|
}; |
99
|
|
|
|
|
|
|
|
100
|
25
|
|
|
|
|
|
void init_Data__MessagePack_pack(pTHX_ bool const cloning) { |
101
|
25
|
50
|
|
|
|
|
if(!cloning) { |
102
|
|
|
|
|
|
|
MY_CXT_INIT; |
103
|
25
|
|
|
|
|
|
MY_CXT.prefer_int = false; |
104
|
25
|
|
|
|
|
|
MY_CXT.canonical = false; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
else { |
107
|
|
|
|
|
|
|
MY_CXT_CLONE; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
25
|
|
|
|
|
|
SV* var = get_sv("Data::MessagePack::" DMP_PREF_INT, GV_ADDMULTI); |
111
|
25
|
|
|
|
|
|
sv_magicext(var, NULL, PERL_MAGIC_ext, &dmp_config_vtbl, |
112
|
|
|
|
|
|
|
DMP_PREF_INT, 0); |
113
|
25
|
50
|
|
|
|
|
SvSETMAGIC(var); |
114
|
25
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
|
117
|
35
|
|
|
|
|
|
STATIC_INLINE int try_int(enc_t* enc, const char *p, size_t len) { |
118
|
|
|
|
|
|
|
int negative = 0; |
119
|
35
|
|
|
|
|
|
const char* pe = p + len; |
120
|
|
|
|
|
|
|
uint64_t num = 0; |
121
|
|
|
|
|
|
|
|
122
|
35
|
100
|
|
|
|
|
if (len == 0) { return 0; } |
123
|
|
|
|
|
|
|
|
124
|
34
|
100
|
|
|
|
|
if (*p == '-') { |
125
|
|
|
|
|
|
|
/* length(-0x80000000) == 11 */ |
126
|
12
|
100
|
|
|
|
|
if (len <= 1 || len > 11) { return 0; } |
127
|
|
|
|
|
|
|
negative = 1; |
128
|
4
|
|
|
|
|
|
++p; |
129
|
|
|
|
|
|
|
} else { |
130
|
|
|
|
|
|
|
/* length(0xFFFFFFFF) == 10 */ |
131
|
26
|
100
|
|
|
|
|
if (len > 10) { return 0; } |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
#if '9'=='8'+1 && '8'=='7'+1 && '7'=='6'+1 && '6'=='5'+1 && '5'=='4'+1 \ |
135
|
|
|
|
|
|
|
&& '4'=='3'+1 && '3'=='2'+1 && '2'=='1'+1 && '1'=='0'+1 |
136
|
|
|
|
|
|
|
do { |
137
|
66
|
|
|
|
|
|
unsigned int c = ((int)*(p++)) - '0'; |
138
|
66
|
100
|
|
|
|
|
if (c > 9) { return 0; } |
139
|
61
|
|
|
|
|
|
num = num * 10 + c; |
140
|
61
|
100
|
|
|
|
|
} while(p < pe); |
141
|
|
|
|
|
|
|
#else |
142
|
|
|
|
|
|
|
do { |
143
|
|
|
|
|
|
|
switch (*(p++)) { |
144
|
|
|
|
|
|
|
case '0': num = num * 10 + 0; break; |
145
|
|
|
|
|
|
|
case '1': num = num * 10 + 1; break; |
146
|
|
|
|
|
|
|
case '2': num = num * 10 + 2; break; |
147
|
|
|
|
|
|
|
case '3': num = num * 10 + 3; break; |
148
|
|
|
|
|
|
|
case '4': num = num * 10 + 4; break; |
149
|
|
|
|
|
|
|
case '5': num = num * 10 + 5; break; |
150
|
|
|
|
|
|
|
case '6': num = num * 10 + 6; break; |
151
|
|
|
|
|
|
|
case '7': num = num * 10 + 7; break; |
152
|
|
|
|
|
|
|
case '8': num = num * 10 + 8; break; |
153
|
|
|
|
|
|
|
case '9': num = num * 10 + 9; break; |
154
|
|
|
|
|
|
|
default: return 0; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
} while(p < pe); |
157
|
|
|
|
|
|
|
#endif |
158
|
|
|
|
|
|
|
|
159
|
17
|
100
|
|
|
|
|
if (negative) { |
160
|
4
|
50
|
|
|
|
|
if (num > 0x80000000) { return 0; } |
161
|
4
|
|
|
|
|
|
msgpack_pack_int32(enc, ((int32_t)-num)); |
162
|
|
|
|
|
|
|
} else { |
163
|
13
|
50
|
|
|
|
|
if (num > 0xFFFFFFFF) { return 0; } |
164
|
13
|
|
|
|
|
|
msgpack_pack_uint32(enc, (uint32_t)num); |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
return 1; |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
STATIC_INLINE void _msgpack_pack_rv(pTHX_ enc_t *enc, SV* sv, int depth, bool utf8); |
172
|
|
|
|
|
|
|
|
173
|
5719
|
|
|
|
|
|
STATIC_INLINE void _msgpack_pack_sv(pTHX_ enc_t* const enc, SV* const sv, int const depth, bool utf8) { |
174
|
|
|
|
|
|
|
assert(sv); |
175
|
5719
|
100
|
|
|
|
|
if (UNLIKELY(depth <= 0)) Perl_croak(aTHX_ ERR_NESTING_EXCEEDED); |
176
|
5715
|
100
|
|
|
|
|
SvGETMAGIC(sv); |
177
|
|
|
|
|
|
|
|
178
|
5715
|
100
|
|
|
|
|
if (SvPOKp(sv)) { |
179
|
1669
|
|
|
|
|
|
STRLEN const len = SvCUR(sv); |
180
|
1669
|
|
|
|
|
|
const char* const pv = SvPVX_const(sv); |
181
|
|
|
|
|
|
|
|
182
|
1669
|
100
|
|
|
|
|
if (enc->prefer_int && try_int(enc, pv, len)) { |
|
|
100
|
|
|
|
|
|
183
|
|
|
|
|
|
|
return; |
184
|
|
|
|
|
|
|
} else { |
185
|
1652
|
100
|
|
|
|
|
if (utf8) { |
186
|
26
|
|
|
|
|
|
msgpack_pack_str(enc, len); |
187
|
|
|
|
|
|
|
msgpack_pack_str_body(enc, pv, len); |
188
|
|
|
|
|
|
|
} else { |
189
|
1626
|
|
|
|
|
|
msgpack_pack_bin(enc, len); |
190
|
|
|
|
|
|
|
msgpack_pack_bin_body(enc, pv, len); |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
} |
193
|
4046
|
100
|
|
|
|
|
} else if (SvNOKp(sv)) { |
194
|
27
|
|
|
|
|
|
msgpack_pack_double(enc, (double)SvNVX(sv)); |
195
|
4019
|
100
|
|
|
|
|
} else if (SvIOKp(sv)) { |
196
|
1249
|
50
|
|
|
|
|
if(SvUOK(sv)) { |
197
|
0
|
|
|
|
|
|
PACK_UV(enc, SvUVX(sv)); |
198
|
|
|
|
|
|
|
} else { |
199
|
1249
|
|
|
|
|
|
PACK_IV(enc, SvIVX(sv)); |
200
|
|
|
|
|
|
|
} |
201
|
2770
|
100
|
|
|
|
|
} else if (SvROK(sv)) { |
202
|
1972
|
|
|
|
|
|
_msgpack_pack_rv(aTHX_ enc, SvRV(sv), depth-1, utf8); |
203
|
798
|
50
|
|
|
|
|
} else if (!SvOK(sv)) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
204
|
|
|
|
|
|
|
msgpack_pack_nil(enc); |
205
|
0
|
0
|
|
|
|
|
} else if (isGV(sv)) { |
206
|
0
|
|
|
|
|
|
Perl_croak(aTHX_ "msgpack cannot pack the GV\n"); |
207
|
|
|
|
|
|
|
} else { |
208
|
0
|
|
|
|
|
|
sv_dump(sv); |
209
|
0
|
|
|
|
|
|
Perl_croak(aTHX_ "msgpack for perl doesn't supported this type: %d\n", SvTYPE(sv)); |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
STATIC_INLINE |
214
|
787
|
|
|
|
|
|
void _msgpack_pack_he(pTHX_ enc_t* enc, HV* hv, HE* he, int depth, bool utf8) { |
215
|
787
|
|
|
|
|
|
_msgpack_pack_sv(aTHX_ enc, hv_iterkeysv(he), depth, utf8); |
216
|
787
|
|
|
|
|
|
_msgpack_pack_sv(aTHX_ enc, hv_iterval(hv, he), depth, utf8); |
217
|
787
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
1972
|
|
|
|
|
|
STATIC_INLINE void _msgpack_pack_rv(pTHX_ enc_t *enc, SV* sv, int depth, bool utf8) { |
220
|
|
|
|
|
|
|
svtype svt; |
221
|
|
|
|
|
|
|
assert(sv); |
222
|
1972
|
50
|
|
|
|
|
SvGETMAGIC(sv); |
223
|
1972
|
|
|
|
|
|
svt = SvTYPE(sv); |
224
|
|
|
|
|
|
|
|
225
|
1972
|
100
|
|
|
|
|
if (SvOBJECT (sv)) { |
226
|
62
|
|
|
|
|
|
HV *stash = gv_stashpv ("Data::MessagePack::Boolean", 1); // TODO: cache? |
227
|
62
|
50
|
|
|
|
|
if (SvSTASH (sv) == stash) { |
228
|
62
|
50
|
|
|
|
|
if (SvIV(sv)) { |
|
|
100
|
|
|
|
|
|
229
|
|
|
|
|
|
|
msgpack_pack_true(enc); |
230
|
|
|
|
|
|
|
} else { |
231
|
|
|
|
|
|
|
msgpack_pack_false(enc); |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
} else { |
234
|
0
|
0
|
|
|
|
|
croak ("encountered object '%s', Data::MessagePack doesn't allow the object", |
235
|
0
|
|
|
|
|
|
SvPV_nolen(sv_2mortal(newRV_inc(sv)))); |
236
|
|
|
|
|
|
|
} |
237
|
1910
|
100
|
|
|
|
|
} else if (svt == SVt_PVHV) { |
238
|
|
|
|
|
|
|
HV* hval = (HV*)sv; |
239
|
754
|
|
|
|
|
|
int count = hv_iterinit(hval); |
240
|
|
|
|
|
|
|
HE* he; |
241
|
|
|
|
|
|
|
|
242
|
754
|
100
|
|
|
|
|
if (SvTIED_mg(sv,PERL_MAGIC_tied)) { |
|
|
50
|
|
|
|
|
|
243
|
|
|
|
|
|
|
count = 0; |
244
|
8
|
100
|
|
|
|
|
while (hv_iternext (hval)) |
245
|
6
|
|
|
|
|
|
++count; |
246
|
2
|
|
|
|
|
|
hv_iterinit (hval); |
247
|
|
|
|
|
|
|
} |
248
|
754
|
|
|
|
|
|
msgpack_pack_map(enc, count); |
249
|
|
|
|
|
|
|
|
250
|
754
|
100
|
|
|
|
|
if (enc->canonical) { |
251
|
11
|
|
|
|
|
|
AV* const keys = newAV(); |
252
|
11
|
|
|
|
|
|
sv_2mortal((SV*)keys); |
253
|
11
|
|
|
|
|
|
av_extend(keys, count); |
254
|
|
|
|
|
|
|
|
255
|
53
|
100
|
|
|
|
|
while ((he = hv_iternext(hval))) { |
256
|
84
|
|
|
|
|
|
av_push(keys, SvREFCNT_inc(hv_iterkeysv(he))); |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
|
259
|
11
|
|
|
|
|
|
int const len = av_len(keys) + 1; |
260
|
11
|
|
|
|
|
|
sortsv(AvARRAY(keys), len, Perl_sv_cmp); |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
int i; |
263
|
53
|
100
|
|
|
|
|
for (i=0; i
|
264
|
42
|
|
|
|
|
|
SV* sv = *av_fetch(keys, i, TRUE); |
265
|
42
|
|
|
|
|
|
he = hv_fetch_ent(hval, sv, FALSE, 0U); |
266
|
42
|
|
|
|
|
|
_msgpack_pack_he(aTHX_ enc, hval, he, depth, utf8); |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
} else { |
269
|
1488
|
100
|
|
|
|
|
while ((he = hv_iternext(hval))) { |
270
|
745
|
|
|
|
|
|
_msgpack_pack_he(aTHX_ enc, hval, he, depth, utf8); |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
} |
273
|
1156
|
50
|
|
|
|
|
} else if (svt == SVt_PVAV) { |
274
|
|
|
|
|
|
|
AV* ary = (AV*)sv; |
275
|
1156
|
|
|
|
|
|
int len = av_len(ary) + 1; |
276
|
|
|
|
|
|
|
int i; |
277
|
1156
|
|
|
|
|
|
msgpack_pack_array(enc, len); |
278
|
3998
|
100
|
|
|
|
|
for (i=0; i
|
279
|
3868
|
|
|
|
|
|
SV** svp = av_fetch(ary, i, 0); |
280
|
3868
|
50
|
|
|
|
|
if (svp) { |
281
|
3868
|
|
|
|
|
|
_msgpack_pack_sv(aTHX_ enc, *svp, depth, utf8); |
282
|
|
|
|
|
|
|
} else { |
283
|
|
|
|
|
|
|
msgpack_pack_nil(enc); |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
} |
286
|
0
|
0
|
|
|
|
|
} else if (svt < SVt_PVAV) { |
287
|
0
|
|
|
|
|
|
STRLEN len = 0; |
288
|
0
|
0
|
|
|
|
|
char *pv = svt ? SvPV (sv, len) : 0; |
|
|
0
|
|
|
|
|
|
289
|
|
|
|
|
|
|
|
290
|
0
|
0
|
|
|
|
|
if (len == 1 && *pv == '1') |
|
|
0
|
|
|
|
|
|
291
|
|
|
|
|
|
|
msgpack_pack_true(enc); |
292
|
0
|
0
|
|
|
|
|
else if (len == 1 && *pv == '0') |
|
|
0
|
|
|
|
|
|
293
|
|
|
|
|
|
|
msgpack_pack_false(enc); |
294
|
|
|
|
|
|
|
else { |
295
|
|
|
|
|
|
|
//sv_dump(sv); |
296
|
0
|
0
|
|
|
|
|
croak("cannot encode reference to scalar '%s' unless the scalar is 0 or 1", |
297
|
0
|
|
|
|
|
|
SvPV_nolen (sv_2mortal (newRV_inc (sv)))); |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
} else { |
300
|
0
|
0
|
|
|
|
|
croak ("encountered %s, but msgpack can only represent references to arrays or hashes", |
301
|
0
|
|
|
|
|
|
SvPV_nolen (sv_2mortal (newRV_inc (sv)))); |
302
|
|
|
|
|
|
|
} |
303
|
946
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
|
305
|
277
|
|
|
|
|
|
XS(xs_pack) { |
306
|
554
|
|
|
|
|
|
dXSARGS; |
307
|
277
|
50
|
|
|
|
|
if (items < 2) { |
308
|
0
|
|
|
|
|
|
Perl_croak(aTHX_ "Usage: Data::MessagePack->pack($dat [,$max_depth])"); |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
277
|
|
|
|
|
|
SV* self = ST(0); |
312
|
277
|
|
|
|
|
|
SV* val = ST(1); |
313
|
|
|
|
|
|
|
int depth = 512; |
314
|
|
|
|
|
|
|
bool utf8 = false; |
315
|
277
|
100
|
|
|
|
|
if (items >= 3) depth = SvIVx(ST(2)); |
|
|
50
|
|
|
|
|
|
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
enc_t enc; |
318
|
277
|
|
|
|
|
|
enc.sv = sv_2mortal(newSV(INIT_SIZE)); |
319
|
277
|
|
|
|
|
|
enc.cur = SvPVX(enc.sv); |
320
|
277
|
|
|
|
|
|
enc.end = SvEND(enc.sv); |
321
|
277
|
|
|
|
|
|
SvPOK_only(enc.sv); |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
// setup configuration |
324
|
|
|
|
|
|
|
dMY_CXT; |
325
|
277
|
|
|
|
|
|
enc.prefer_int = MY_CXT.prefer_int; // back compat |
326
|
277
|
100
|
|
|
|
|
if(SvROK(self) && SvTYPE(SvRV(self)) == SVt_PVHV) { |
|
|
50
|
|
|
|
|
|
327
|
|
|
|
|
|
|
HV* const hv = (HV*)SvRV(self); |
328
|
|
|
|
|
|
|
SV** svp; |
329
|
|
|
|
|
|
|
|
330
|
44
|
|
|
|
|
|
svp = hv_fetchs(hv, "prefer_integer", FALSE); |
331
|
44
|
100
|
|
|
|
|
if(svp) { |
332
|
14
|
50
|
|
|
|
|
enc.prefer_int = SvTRUE(*svp) ? true : false; |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
44
|
|
|
|
|
|
svp = hv_fetchs(hv, "canonical", FALSE); |
336
|
44
|
100
|
|
|
|
|
if(svp) { |
337
|
11
|
50
|
|
|
|
|
enc.canonical = SvTRUE(*svp) ? true : false; |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
|
340
|
44
|
|
|
|
|
|
svp = hv_fetchs(hv, "utf8", FALSE); |
341
|
44
|
100
|
|
|
|
|
if (svp) { |
342
|
24
|
50
|
|
|
|
|
utf8 = SvTRUE(*svp) ? true : false; |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
|
346
|
277
|
|
|
|
|
|
_msgpack_pack_sv(aTHX_ &enc, val, depth, utf8); |
347
|
|
|
|
|
|
|
|
348
|
273
|
|
|
|
|
|
SvCUR_set(enc.sv, enc.cur - SvPVX (enc.sv)); |
349
|
273
|
|
|
|
|
|
*SvEND (enc.sv) = 0; /* many xs functions expect a trailing 0 for text strings */ |
350
|
|
|
|
|
|
|
|
351
|
273
|
|
|
|
|
|
ST(0) = enc.sv; |
352
|
273
|
|
|
|
|
|
XSRETURN(1); |
353
|
|
|
|
|
|
|
} |