msgpack 0.4.3-mswin32 → 0.4.4-mswin32
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.
- data/ext/compat.h +77 -0
- data/ext/extconf.rb +1 -1
- data/ext/pack.c +20 -9
- data/ext/rbinit.c +15 -0
- data/ext/unpack.c +219 -67
- data/ext/version.rb +1 -1
- data/lib/1.8/msgpack.so +0 -0
- data/lib/1.9/msgpack.so +0 -0
- data/msgpack/pack_template.h +32 -32
- data/msgpack/sysdep.h +6 -4
- data/test/test_cases.rbc +1152 -0
- data/test/test_encoding.rb +68 -0
- data/test/test_helper.rb +3 -1
- data/test/test_helper.rbc +227 -0
- data/test/test_pack_unpack.rb +15 -10
- data/test/test_pack_unpack.rbc +5863 -0
- metadata +15 -5
data/ext/compat.h
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
/*
|
2
|
+
* MessagePack for Ruby
|
3
|
+
*
|
4
|
+
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
|
5
|
+
*
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
* you may not use this file except in compliance with the License.
|
8
|
+
* You may obtain a copy of the License at
|
9
|
+
*
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
*
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
* See the License for the specific language governing permissions and
|
16
|
+
* limitations under the License.
|
17
|
+
*/
|
18
|
+
#ifndef COMPAT_H__
|
19
|
+
#define COMPAT_H__
|
20
|
+
|
21
|
+
|
22
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
23
|
+
#include "ruby/encoding.h"
|
24
|
+
#define COMPAT_HAVE_ENCODING
|
25
|
+
extern int s_enc_utf8;
|
26
|
+
extern int s_enc_ascii8bit;
|
27
|
+
extern int s_enc_usascii;
|
28
|
+
extern VALUE s_enc_utf8_value;
|
29
|
+
#endif
|
30
|
+
|
31
|
+
#ifdef RUBY_VM
|
32
|
+
#define COMPAT_RERAISE rb_exc_raise(rb_errinfo())
|
33
|
+
#else
|
34
|
+
#define COMPAT_RERAISE rb_exc_raise(ruby_errinfo)
|
35
|
+
#endif
|
36
|
+
|
37
|
+
|
38
|
+
/* ruby 1.8 and Rubinius */
|
39
|
+
#ifndef RBIGNUM_POSITIVE_P
|
40
|
+
# ifdef RUBINIUS
|
41
|
+
# define RBIGNUM_POSITIVE_P(b) (rb_funcall(b, rb_intern(">="), 1, INT2FIX(0)) == Qtrue)
|
42
|
+
# else
|
43
|
+
# define RBIGNUM_POSITIVE_P(b) (RBIGNUM(b)->sign)
|
44
|
+
# endif
|
45
|
+
#endif
|
46
|
+
|
47
|
+
|
48
|
+
/* Rubinius */
|
49
|
+
#ifdef RUBINIUS
|
50
|
+
static inline void rb_gc_enable() { return; }
|
51
|
+
static inline void rb_gc_disable() { return; }
|
52
|
+
#endif
|
53
|
+
|
54
|
+
|
55
|
+
/* ruby 1.8.5 */
|
56
|
+
#ifndef RSTRING_PTR
|
57
|
+
#define RSTRING_PTR(s) (RSTRING(s)->ptr)
|
58
|
+
#endif
|
59
|
+
|
60
|
+
/* ruby 1.8.5 */
|
61
|
+
#ifndef RSTRING_LEN
|
62
|
+
#define RSTRING_LEN(s) (RSTRING(s)->len)
|
63
|
+
#endif
|
64
|
+
|
65
|
+
/* ruby 1.8.5 */
|
66
|
+
#ifndef RARRAY_PTR
|
67
|
+
#define RARRAY_PTR(s) (RARRAY(s)->ptr)
|
68
|
+
#endif
|
69
|
+
|
70
|
+
/* ruby 1.8.5 */
|
71
|
+
#ifndef RARRAY_LEN
|
72
|
+
#define RARRAY_LEN(s) (RARRAY(s)->len)
|
73
|
+
#endif
|
74
|
+
|
75
|
+
|
76
|
+
#endif /* compat.h */
|
77
|
+
|
data/ext/extconf.rb
CHANGED
data/ext/pack.c
CHANGED
@@ -16,6 +16,8 @@
|
|
16
16
|
* limitations under the License.
|
17
17
|
*/
|
18
18
|
#include "ruby.h"
|
19
|
+
#include "compat.h"
|
20
|
+
|
19
21
|
#include "msgpack/pack_define.h"
|
20
22
|
|
21
23
|
static ID s_to_msgpack;
|
@@ -116,10 +118,6 @@ static VALUE MessagePack_Fixnum_to_msgpack(int argc, VALUE *argv, VALUE self)
|
|
116
118
|
}
|
117
119
|
|
118
120
|
|
119
|
-
#ifndef RBIGNUM_SIGN // Ruby 1.8
|
120
|
-
#define RBIGNUM_SIGN(b) (RBIGNUM(b)->sign)
|
121
|
-
#endif
|
122
|
-
|
123
121
|
/*
|
124
122
|
* Document-method: Bignum#to_msgpack
|
125
123
|
*
|
@@ -131,10 +129,9 @@ static VALUE MessagePack_Fixnum_to_msgpack(int argc, VALUE *argv, VALUE self)
|
|
131
129
|
static VALUE MessagePack_Bignum_to_msgpack(int argc, VALUE *argv, VALUE self)
|
132
130
|
{
|
133
131
|
ARG_BUFFER(out, argc, argv);
|
134
|
-
|
135
|
-
if(RBIGNUM_SIGN(self)) { // positive
|
132
|
+
if(RBIGNUM_POSITIVE_P(self)) {
|
136
133
|
msgpack_pack_uint64(out, rb_big2ull(self));
|
137
|
-
} else {
|
134
|
+
} else {
|
138
135
|
msgpack_pack_int64(out, rb_big2ll(self));
|
139
136
|
}
|
140
137
|
return out;
|
@@ -168,6 +165,14 @@ static VALUE MessagePack_Float_to_msgpack(int argc, VALUE *argv, VALUE self)
|
|
168
165
|
static VALUE MessagePack_String_to_msgpack(int argc, VALUE *argv, VALUE self)
|
169
166
|
{
|
170
167
|
ARG_BUFFER(out, argc, argv);
|
168
|
+
#ifdef COMPAT_HAVE_ENCODING
|
169
|
+
int enc = ENCODING_GET(self);
|
170
|
+
if(enc != s_enc_utf8 && enc != s_enc_ascii8bit && enc != s_enc_usascii) {
|
171
|
+
if(!ENC_CODERANGE_ASCIIONLY(self)) {
|
172
|
+
self = rb_str_encode(self, s_enc_utf8_value, 0, Qnil);
|
173
|
+
}
|
174
|
+
}
|
175
|
+
#endif
|
171
176
|
msgpack_pack_raw(out, RSTRING_LEN(self));
|
172
177
|
msgpack_pack_raw_body(out, RSTRING_PTR(self), RSTRING_LEN(self));
|
173
178
|
return out;
|
@@ -184,12 +189,16 @@ static VALUE MessagePack_String_to_msgpack(int argc, VALUE *argv, VALUE self)
|
|
184
189
|
*/
|
185
190
|
static VALUE MessagePack_Symbol_to_msgpack(int argc, VALUE *argv, VALUE self)
|
186
191
|
{
|
192
|
+
#ifdef COMPAT_HAVE_ENCODING
|
193
|
+
return MessagePack_String_to_msgpack(argc, argv, rb_id2str(SYM2ID(self)));
|
194
|
+
#else
|
187
195
|
ARG_BUFFER(out, argc, argv);
|
188
196
|
const char* name = rb_id2name(SYM2ID(self));
|
189
197
|
size_t len = strlen(name);
|
190
198
|
msgpack_pack_raw(out, len);
|
191
199
|
msgpack_pack_raw_body(out, name, len);
|
192
200
|
return out;
|
201
|
+
#endif
|
193
202
|
}
|
194
203
|
|
195
204
|
|
@@ -205,7 +214,8 @@ static VALUE MessagePack_Symbol_to_msgpack(int argc, VALUE *argv, VALUE self)
|
|
205
214
|
static VALUE MessagePack_Array_to_msgpack(int argc, VALUE *argv, VALUE self)
|
206
215
|
{
|
207
216
|
ARG_BUFFER(out, argc, argv);
|
208
|
-
|
217
|
+
// FIXME check sizeof(long) > sizeof(unsigned int) && RARRAY_LEN(self) > UINT_MAX
|
218
|
+
msgpack_pack_array(out, (unsigned int)RARRAY_LEN(self));
|
209
219
|
VALUE* p = RARRAY_PTR(self);
|
210
220
|
VALUE* const pend = p + RARRAY_LEN(self);
|
211
221
|
for(;p != pend; ++p) {
|
@@ -239,7 +249,8 @@ static int MessagePack_Hash_to_msgpack_foreach(VALUE key, VALUE value, VALUE out
|
|
239
249
|
static VALUE MessagePack_Hash_to_msgpack(int argc, VALUE *argv, VALUE self)
|
240
250
|
{
|
241
251
|
ARG_BUFFER(out, argc, argv);
|
242
|
-
|
252
|
+
// FIXME check sizeof(st_index_t) > sizeof(unsigned int) && RARRAY_LEN(self) > UINT_MAX
|
253
|
+
msgpack_pack_map(out, (unsigned int)RHASH_SIZE(self));
|
243
254
|
rb_hash_foreach(self, MessagePack_Hash_to_msgpack_foreach, out);
|
244
255
|
return out;
|
245
256
|
}
|
data/ext/rbinit.c
CHANGED
@@ -17,9 +17,17 @@
|
|
17
17
|
*/
|
18
18
|
#include "pack.h"
|
19
19
|
#include "unpack.h"
|
20
|
+
#include "compat.h"
|
20
21
|
|
21
22
|
static VALUE mMessagePack;
|
22
23
|
|
24
|
+
#ifdef COMPAT_HAVE_ENCODING
|
25
|
+
int s_enc_utf8;
|
26
|
+
int s_enc_ascii8bit;
|
27
|
+
int s_enc_usascii;
|
28
|
+
VALUE s_enc_utf8_value;
|
29
|
+
#endif
|
30
|
+
|
23
31
|
/**
|
24
32
|
* Document-module: MessagePack
|
25
33
|
*
|
@@ -46,6 +54,13 @@ void Init_msgpack(void)
|
|
46
54
|
|
47
55
|
rb_define_const(mMessagePack, "VERSION", rb_str_new2(MESSAGEPACK_VERSION));
|
48
56
|
|
57
|
+
#ifdef COMPAT_HAVE_ENCODING
|
58
|
+
s_enc_ascii8bit = rb_ascii8bit_encindex();
|
59
|
+
s_enc_utf8 = rb_utf8_encindex();
|
60
|
+
s_enc_usascii = rb_usascii_encindex();
|
61
|
+
s_enc_utf8_value = rb_enc_from_encoding(rb_utf8_encoding());
|
62
|
+
#endif
|
63
|
+
|
49
64
|
Init_msgpack_unpack(mMessagePack);
|
50
65
|
Init_msgpack_pack(mMessagePack);
|
51
66
|
}
|
data/ext/unpack.c
CHANGED
@@ -16,19 +16,15 @@
|
|
16
16
|
* limitations under the License.
|
17
17
|
*/
|
18
18
|
#include "ruby.h"
|
19
|
+
#include "compat.h"
|
19
20
|
|
20
21
|
#include "msgpack/unpack_define.h"
|
21
22
|
|
22
23
|
static ID s_sysread;
|
23
24
|
static ID s_readpartial;
|
24
25
|
|
25
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
26
|
-
#include "ruby/encoding.h"
|
27
|
-
int s_ascii_8bit;
|
28
|
-
#endif
|
29
|
-
|
30
26
|
struct unpack_buffer {
|
31
|
-
size_t
|
27
|
+
size_t used;
|
32
28
|
size_t free;
|
33
29
|
char* ptr;
|
34
30
|
};
|
@@ -41,6 +37,7 @@ typedef struct {
|
|
41
37
|
VALUE stream;
|
42
38
|
VALUE streambuf;
|
43
39
|
ID stream_append_method;
|
40
|
+
size_t buffer_free_size;
|
44
41
|
} unpack_user;
|
45
42
|
|
46
43
|
|
@@ -136,6 +133,9 @@ static inline int template_callback_raw(unpack_user* u, const char* b, const cha
|
|
136
133
|
} else {
|
137
134
|
*o = rb_str_substr(u->source, p - b, l);
|
138
135
|
}
|
136
|
+
#ifdef COMPAT_HAVE_ENCODING
|
137
|
+
ENCODING_SET(*o, s_enc_utf8);
|
138
|
+
#endif
|
139
139
|
return 0;
|
140
140
|
}
|
141
141
|
|
@@ -156,27 +156,11 @@ static inline int template_callback_raw(unpack_user* u, const char* b, const cha
|
|
156
156
|
rb_raise(rb_eTypeError, "instance of String needed"); \
|
157
157
|
}
|
158
158
|
|
159
|
-
#ifdef RUBY_VM
|
160
|
-
#define RERAISE rb_exc_raise(rb_errinfo())
|
161
|
-
#else
|
162
|
-
#define RERAISE rb_exc_raise(ruby_errinfo)
|
163
|
-
#endif
|
164
|
-
|
165
|
-
|
166
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
167
|
-
static VALUE template_execute_rescue_enc(VALUE data)
|
168
|
-
{
|
169
|
-
rb_gc_enable();
|
170
|
-
VALUE* resc = (VALUE*)data;
|
171
|
-
rb_enc_set_index(resc[0], (int)resc[1]);
|
172
|
-
RERAISE;
|
173
|
-
}
|
174
|
-
#endif
|
175
159
|
|
176
160
|
static VALUE template_execute_rescue(VALUE nouse)
|
177
161
|
{
|
178
162
|
rb_gc_enable();
|
179
|
-
|
163
|
+
COMPAT_RERAISE;
|
180
164
|
}
|
181
165
|
|
182
166
|
static VALUE template_execute_do(VALUE argv)
|
@@ -203,31 +187,16 @@ static int template_execute_wrap(msgpack_unpack_t* mp,
|
|
203
187
|
(VALUE)from,
|
204
188
|
};
|
205
189
|
|
206
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
207
|
-
int enc_orig = rb_enc_get_index(str);
|
208
|
-
rb_enc_set_index(str, s_ascii_8bit);
|
209
|
-
#endif
|
210
|
-
|
211
190
|
// FIXME execute実行中はmp->topが更新されないのでGC markが機能しない
|
212
191
|
rb_gc_disable();
|
213
192
|
|
214
193
|
mp->user.source = str;
|
215
194
|
|
216
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
217
|
-
VALUE resc[2] = {str, enc_orig};
|
218
|
-
int ret = (int)rb_rescue(template_execute_do, (VALUE)args,
|
219
|
-
template_execute_rescue_enc, (VALUE)resc);
|
220
|
-
#else
|
221
195
|
int ret = (int)rb_rescue(template_execute_do, (VALUE)args,
|
222
196
|
template_execute_rescue, Qnil);
|
223
|
-
#endif
|
224
197
|
|
225
198
|
rb_gc_enable();
|
226
199
|
|
227
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
228
|
-
rb_enc_set_index(str, enc_orig);
|
229
|
-
#endif
|
230
|
-
|
231
200
|
return ret;
|
232
201
|
}
|
233
202
|
|
@@ -273,6 +242,13 @@ static VALUE eUnpackError;
|
|
273
242
|
#define MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE (8*1024)
|
274
243
|
#endif
|
275
244
|
|
245
|
+
/*
|
246
|
+
#ifndef MSGPACK_BUFFER_FREE_SIZE
|
247
|
+
#define MSGPACK_BUFFER_FREE_SIZE (1024*1024)
|
248
|
+
#endif
|
249
|
+
*/
|
250
|
+
#define MSGPACK_BUFFER_FREE_SIZE 0
|
251
|
+
|
276
252
|
static void MessagePack_Unpacker_free(void* data)
|
277
253
|
{
|
278
254
|
if(data) {
|
@@ -305,7 +281,7 @@ static VALUE MessagePack_Unpacker_alloc(VALUE klass)
|
|
305
281
|
|
306
282
|
mp->user.finished = 0;
|
307
283
|
mp->user.offset = 0;
|
308
|
-
mp->user.buffer.
|
284
|
+
mp->user.buffer.used = 0;
|
309
285
|
mp->user.buffer.free = 0;
|
310
286
|
mp->user.buffer.ptr = NULL;
|
311
287
|
|
@@ -358,6 +334,7 @@ static VALUE MessagePack_Unpacker_initialize(int argc, VALUE *argv, VALUE self)
|
|
358
334
|
mp->user.stream = stream;
|
359
335
|
mp->user.streambuf = rb_str_buf_new(MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE);
|
360
336
|
mp->user.stream_append_method = append_method_of(stream);
|
337
|
+
mp->user.buffer_free_size = MSGPACK_BUFFER_FREE_SIZE;
|
361
338
|
|
362
339
|
return self;
|
363
340
|
}
|
@@ -398,22 +375,27 @@ static void reserve_buffer(msgpack_unpack_t* mp, size_t require)
|
|
398
375
|
{
|
399
376
|
struct unpack_buffer* buffer = &mp->user.buffer;
|
400
377
|
|
401
|
-
if(buffer->
|
402
|
-
|
378
|
+
if(buffer->used == 0) {
|
379
|
+
if(require <= buffer->free) {
|
380
|
+
/* enough free space */
|
381
|
+
return;
|
382
|
+
}
|
383
|
+
/* no used buffer: realloc only */
|
384
|
+
size_t nsize = buffer->free == 0 ?
|
385
|
+
MSGPACK_UNPACKER_BUFFER_INIT_SIZE : buffer->free*2;
|
403
386
|
while(nsize < require) {
|
404
387
|
nsize *= 2;
|
405
388
|
}
|
406
|
-
char* tmp =
|
407
|
-
buffer->ptr = tmp;
|
389
|
+
char* tmp = REALLOC_N(buffer->ptr, char, nsize);
|
408
390
|
buffer->free = nsize;
|
409
|
-
buffer->
|
391
|
+
buffer->ptr = tmp;
|
410
392
|
return;
|
411
393
|
}
|
412
394
|
|
413
|
-
if(buffer->
|
395
|
+
if(buffer->used <= mp->user.offset) {
|
414
396
|
/* clear buffer and rewind offset */
|
415
|
-
buffer->free += buffer->
|
416
|
-
buffer->
|
397
|
+
buffer->free += buffer->used;
|
398
|
+
buffer->used = 0;
|
417
399
|
mp->user.offset = 0;
|
418
400
|
}
|
419
401
|
|
@@ -422,41 +404,91 @@ static void reserve_buffer(msgpack_unpack_t* mp, size_t require)
|
|
422
404
|
return;
|
423
405
|
}
|
424
406
|
|
425
|
-
size_t nsize = (buffer->
|
407
|
+
size_t nsize = (buffer->used + buffer->free) * 2;
|
426
408
|
|
427
|
-
if(mp->user.offset <= buffer->
|
409
|
+
if(mp->user.offset <= buffer->used / 2) {
|
428
410
|
/* parsed less than half: realloc only */
|
429
|
-
while(nsize < buffer->
|
411
|
+
while(nsize < buffer->used + require) {
|
430
412
|
nsize *= 2;
|
431
413
|
}
|
432
414
|
char* tmp = REALLOC_N(buffer->ptr, char, nsize);
|
433
|
-
buffer->free = nsize - buffer->
|
415
|
+
buffer->free = nsize - buffer->used;
|
434
416
|
buffer->ptr = tmp;
|
435
417
|
|
436
418
|
} else {
|
437
419
|
/* parsed more than half: realloc and move */
|
438
|
-
size_t not_parsed = buffer->
|
420
|
+
size_t not_parsed = buffer->used - mp->user.offset;
|
439
421
|
while(nsize < not_parsed + require) {
|
440
422
|
nsize *= 2;
|
441
423
|
}
|
442
424
|
char* tmp = REALLOC_N(buffer->ptr, char, nsize);
|
443
425
|
memcpy(tmp, tmp + mp->user.offset, not_parsed);
|
444
|
-
buffer->free = nsize -
|
445
|
-
buffer->
|
426
|
+
buffer->free = nsize - not_parsed;
|
427
|
+
buffer->used = not_parsed;
|
446
428
|
buffer->ptr = tmp;
|
447
429
|
mp->user.offset = 0;
|
448
430
|
}
|
449
431
|
}
|
450
432
|
|
451
|
-
static inline void
|
433
|
+
static inline void try_free_buffer(msgpack_unpack_t* mp, size_t require)
|
452
434
|
{
|
435
|
+
if(mp->user.buffer_free_size == 0) {
|
436
|
+
return;
|
437
|
+
}
|
438
|
+
|
453
439
|
struct unpack_buffer* buffer = &mp->user.buffer;
|
440
|
+
size_t csize = buffer->used + buffer->free;
|
454
441
|
|
455
|
-
if(
|
456
|
-
|
442
|
+
if(csize <= mp->user.buffer_free_size) {
|
443
|
+
return;
|
457
444
|
}
|
458
|
-
|
459
|
-
buffer->
|
445
|
+
|
446
|
+
if(mp->user.offset <= buffer->used / 2) {
|
447
|
+
/* parsed less than half: do nothing */
|
448
|
+
|
449
|
+
} else if(mp->user.offset < buffer->used) {
|
450
|
+
/* parsed more than half but not all: realloc and move */
|
451
|
+
size_t nsize = MSGPACK_UNPACKER_BUFFER_INIT_SIZE;
|
452
|
+
size_t not_parsed = buffer->used - mp->user.offset;
|
453
|
+
while(nsize < not_parsed + require) {
|
454
|
+
nsize *= 2;
|
455
|
+
}
|
456
|
+
|
457
|
+
if(nsize >= csize) {
|
458
|
+
return;
|
459
|
+
}
|
460
|
+
|
461
|
+
char* tmp;
|
462
|
+
if(mp->user.offset == 0) {
|
463
|
+
tmp = ALLOC_N(char, nsize);
|
464
|
+
memcpy(tmp, buffer->ptr + mp->user.offset, not_parsed);
|
465
|
+
free(buffer->ptr);
|
466
|
+
} else {
|
467
|
+
tmp = REALLOC_N(buffer->ptr, char, nsize);
|
468
|
+
}
|
469
|
+
buffer->free = nsize - not_parsed;
|
470
|
+
buffer->used = not_parsed;
|
471
|
+
buffer->ptr = tmp;
|
472
|
+
mp->user.offset = 0;
|
473
|
+
|
474
|
+
} else {
|
475
|
+
/* all parsed: free all */
|
476
|
+
free(buffer->ptr);
|
477
|
+
buffer->free = 0;
|
478
|
+
buffer->used = 0;
|
479
|
+
buffer->ptr = NULL;
|
480
|
+
mp->user.offset = 0;
|
481
|
+
}
|
482
|
+
}
|
483
|
+
|
484
|
+
static void feed_buffer(msgpack_unpack_t* mp, const char* ptr, size_t len)
|
485
|
+
{
|
486
|
+
struct unpack_buffer* buffer = &mp->user.buffer;
|
487
|
+
|
488
|
+
reserve_buffer(mp, len);
|
489
|
+
|
490
|
+
memcpy(buffer->ptr + buffer->used, ptr, len);
|
491
|
+
buffer->used += len;
|
460
492
|
buffer->free -= len;
|
461
493
|
}
|
462
494
|
|
@@ -530,7 +562,7 @@ static VALUE MessagePack_Unpacker_each(VALUE self)
|
|
530
562
|
#endif
|
531
563
|
|
532
564
|
while(1) {
|
533
|
-
if(mp->user.buffer.
|
565
|
+
if(mp->user.buffer.used <= mp->user.offset) {
|
534
566
|
do_fill:
|
535
567
|
{
|
536
568
|
VALUE len = MessagePack_Unpacker_fill(self);
|
@@ -541,7 +573,7 @@ static VALUE MessagePack_Unpacker_each(VALUE self)
|
|
541
573
|
}
|
542
574
|
|
543
575
|
ret = template_execute_wrap_each(mp,
|
544
|
-
mp->user.buffer.ptr, mp->user.buffer.
|
576
|
+
mp->user.buffer.ptr, mp->user.buffer.used,
|
545
577
|
&mp->user.offset);
|
546
578
|
|
547
579
|
if(ret < 0) {
|
@@ -557,9 +589,131 @@ static VALUE MessagePack_Unpacker_each(VALUE self)
|
|
557
589
|
}
|
558
590
|
}
|
559
591
|
|
592
|
+
try_free_buffer(mp, 0);
|
593
|
+
|
560
594
|
return Qnil;
|
561
595
|
}
|
562
596
|
|
597
|
+
/**
|
598
|
+
* Document-method: MessagePack::Unpacker#feed_each
|
599
|
+
*
|
600
|
+
* call-seq:
|
601
|
+
* unpacker.feed_each(data) {|object| }
|
602
|
+
*
|
603
|
+
* Same as feed(data) + each {|object| }, but tries to avoid copying of the buffer.
|
604
|
+
*/
|
605
|
+
static VALUE feed_each_impl(VALUE args)
|
606
|
+
{
|
607
|
+
VALUE self = ((VALUE*)args)[0];
|
608
|
+
VALUE data = ((VALUE*)args)[1];
|
609
|
+
size_t* pconsumed = (size_t*)((VALUE*)args)[2];
|
610
|
+
|
611
|
+
UNPACKER(self, mp);
|
612
|
+
int ret;
|
613
|
+
const char* ptr = RSTRING_PTR(data);
|
614
|
+
size_t len = RSTRING_LEN(data);
|
615
|
+
|
616
|
+
if(mp->user.buffer.used > 0) {
|
617
|
+
while(1) {
|
618
|
+
ret = template_execute_wrap_each(mp,
|
619
|
+
mp->user.buffer.ptr, mp->user.buffer.used,
|
620
|
+
&mp->user.offset);
|
621
|
+
|
622
|
+
if(ret < 0) {
|
623
|
+
rb_raise(eUnpackError, "parse error.");
|
624
|
+
|
625
|
+
} else if(ret > 0) {
|
626
|
+
VALUE data = template_data(mp);
|
627
|
+
template_init(mp);
|
628
|
+
rb_yield(data);
|
629
|
+
|
630
|
+
} else {
|
631
|
+
break;
|
632
|
+
}
|
633
|
+
}
|
634
|
+
}
|
635
|
+
|
636
|
+
if(len <= 0) {
|
637
|
+
return Qnil;
|
638
|
+
}
|
639
|
+
|
640
|
+
if(mp->user.buffer.used <= mp->user.offset) {
|
641
|
+
// wrap & execute & feed
|
642
|
+
while(1) {
|
643
|
+
ret = template_execute_wrap_each(mp,
|
644
|
+
ptr, len, pconsumed);
|
645
|
+
|
646
|
+
if(ret < 0) {
|
647
|
+
rb_raise(eUnpackError, "parse error.");
|
648
|
+
|
649
|
+
} else if(ret > 0) {
|
650
|
+
VALUE data = template_data(mp);
|
651
|
+
template_init(mp);
|
652
|
+
rb_yield(data);
|
653
|
+
|
654
|
+
} else {
|
655
|
+
break;
|
656
|
+
}
|
657
|
+
}
|
658
|
+
|
659
|
+
} else {
|
660
|
+
// feed & execute
|
661
|
+
feed_buffer(mp, ptr, len);
|
662
|
+
*pconsumed = len;
|
663
|
+
|
664
|
+
while(1) {
|
665
|
+
ret = template_execute_wrap_each(mp,
|
666
|
+
mp->user.buffer.ptr, mp->user.buffer.used,
|
667
|
+
&mp->user.offset);
|
668
|
+
|
669
|
+
if(ret < 0) {
|
670
|
+
rb_raise(eUnpackError, "parse error.");
|
671
|
+
|
672
|
+
} else if(ret > 0) {
|
673
|
+
VALUE data = template_data(mp);
|
674
|
+
template_init(mp);
|
675
|
+
rb_yield(data);
|
676
|
+
|
677
|
+
} else {
|
678
|
+
break;
|
679
|
+
}
|
680
|
+
}
|
681
|
+
}
|
682
|
+
|
683
|
+
return Qnil;
|
684
|
+
}
|
685
|
+
|
686
|
+
static VALUE feed_each_ensure(VALUE args) {
|
687
|
+
VALUE self = ((VALUE*)args)[0];
|
688
|
+
VALUE data = ((VALUE*)args)[1];
|
689
|
+
size_t* pconsumed = (size_t*)((VALUE*)args)[2];
|
690
|
+
|
691
|
+
const char* dptr = RSTRING_PTR(data) + *pconsumed;
|
692
|
+
size_t dlen = RSTRING_LEN(data) - *pconsumed;
|
693
|
+
|
694
|
+
if(dlen > 0) {
|
695
|
+
UNPACKER(self, mp);
|
696
|
+
try_free_buffer(mp, dlen);
|
697
|
+
feed_buffer(mp, dptr, dlen);
|
698
|
+
}
|
699
|
+
|
700
|
+
return Qnil;
|
701
|
+
}
|
702
|
+
|
703
|
+
static VALUE MessagePack_Unpacker_feed_each(VALUE self, VALUE data)
|
704
|
+
{
|
705
|
+
size_t consumed = 0;
|
706
|
+
StringValue(data);
|
707
|
+
|
708
|
+
VALUE args[3];
|
709
|
+
args[0] = self;
|
710
|
+
args[1] = data;
|
711
|
+
args[2] = (VALUE)&consumed;
|
712
|
+
|
713
|
+
return rb_ensure(feed_each_impl, (VALUE)args,
|
714
|
+
feed_each_ensure, (VALUE)args);
|
715
|
+
}
|
716
|
+
|
563
717
|
|
564
718
|
static inline VALUE MessagePack_unpack_impl(VALUE self, VALUE data, unsigned long dlen)
|
565
719
|
{
|
@@ -652,7 +806,7 @@ static VALUE MessagePack_Unpacker_execute_impl(VALUE self, VALUE data,
|
|
652
806
|
*
|
653
807
|
* This method doesn't use the internal buffer.
|
654
808
|
*
|
655
|
-
* Call *reset
|
809
|
+
* Call *reset* method before calling this method again.
|
656
810
|
*
|
657
811
|
* UnpackError is throw when parse error is occured.
|
658
812
|
*/
|
@@ -674,7 +828,7 @@ static VALUE MessagePack_Unpacker_execute_limit(VALUE self, VALUE data,
|
|
674
828
|
*
|
675
829
|
* This method doesn't use the internal buffer.
|
676
830
|
*
|
677
|
-
* Call *reset
|
831
|
+
* Call *reset* method before calling this method again.
|
678
832
|
*
|
679
833
|
* This returns offset that was parsed to.
|
680
834
|
* Use *finished?* method to check an object is deserialized and call *data*
|
@@ -737,6 +891,7 @@ static VALUE MessagePack_Unpacker_reset(VALUE self)
|
|
737
891
|
UNPACKER(self, mp);
|
738
892
|
template_init(mp);
|
739
893
|
mp->user.finished = 0;
|
894
|
+
try_free_buffer(mp, 0);
|
740
895
|
return self;
|
741
896
|
}
|
742
897
|
|
@@ -746,10 +901,6 @@ void Init_msgpack_unpack(VALUE mMessagePack)
|
|
746
901
|
s_sysread = rb_intern("sysread");
|
747
902
|
s_readpartial = rb_intern("readpartial");
|
748
903
|
|
749
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
750
|
-
s_ascii_8bit = rb_enc_find_index("ASCII-8BIT");
|
751
|
-
#endif
|
752
|
-
|
753
904
|
eUnpackError = rb_define_class_under(mMessagePack, "UnpackError", rb_eStandardError);
|
754
905
|
cUnpacker = rb_define_class_under(mMessagePack, "Unpacker", rb_cObject);
|
755
906
|
rb_define_alloc_func(cUnpacker, MessagePack_Unpacker_alloc);
|
@@ -762,6 +913,7 @@ void Init_msgpack_unpack(VALUE mMessagePack)
|
|
762
913
|
rb_define_method(cUnpacker, "each", MessagePack_Unpacker_each, 0);
|
763
914
|
rb_define_method(cUnpacker, "stream", MessagePack_Unpacker_stream_get, 0);
|
764
915
|
rb_define_method(cUnpacker, "stream=", MessagePack_Unpacker_stream_set, 1);
|
916
|
+
rb_define_method(cUnpacker, "feed_each", MessagePack_Unpacker_feed_each, 1);
|
765
917
|
|
766
918
|
/* Unbuffered API */
|
767
919
|
rb_define_method(cUnpacker, "execute", MessagePack_Unpacker_execute, 2);
|