msgpack 0.4.3-x86-mingw32 → 0.4.4-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|