msgpack 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+
@@ -1,5 +1,5 @@
1
1
  require 'mkmf'
2
2
  require './version.rb'
3
- $CFLAGS << %[ -I.. -Wall -O4 -DMESSAGEPACK_VERSION=\\"#{MessagePack::VERSION}\\"]
3
+ $CFLAGS << %[ -I.. -Wall -O4 -DMESSAGEPACK_VERSION=\\"#{MessagePack::VERSION}\\" -g]
4
4
  create_makefile('msgpack')
5
5
 
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
- // FIXME bignum
135
- if(RBIGNUM_SIGN(self)) { // positive
132
+ if(RBIGNUM_POSITIVE_P(self)) {
136
133
  msgpack_pack_uint64(out, rb_big2ull(self));
137
- } else { // negative
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
- msgpack_pack_array(out, RARRAY_LEN(self));
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
- msgpack_pack_map(out, RHASH_SIZE(self));
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
  }
@@ -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
  }
@@ -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 size;
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
- RERAISE;
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.size = 0;
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->size == 0) {
402
- size_t nsize = MSGPACK_UNPACKER_BUFFER_INIT_SIZE;
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 = ALLOC_N(char, nsize);
407
- buffer->ptr = tmp;
389
+ char* tmp = REALLOC_N(buffer->ptr, char, nsize);
408
390
  buffer->free = nsize;
409
- buffer->size = 0;
391
+ buffer->ptr = tmp;
410
392
  return;
411
393
  }
412
394
 
413
- if(buffer->size <= mp->user.offset) {
395
+ if(buffer->used <= mp->user.offset) {
414
396
  /* clear buffer and rewind offset */
415
- buffer->free += buffer->size;
416
- buffer->size = 0;
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->size + buffer->free) * 2;
407
+ size_t nsize = (buffer->used + buffer->free) * 2;
426
408
 
427
- if(mp->user.offset <= buffer->size / 2) {
409
+ if(mp->user.offset <= buffer->used / 2) {
428
410
  /* parsed less than half: realloc only */
429
- while(nsize < buffer->size + require) {
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->size;
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->size - mp->user.offset;
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 - buffer->size;
445
- buffer->size = not_parsed;
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 feed_buffer(msgpack_unpack_t* mp, const char* ptr, size_t len)
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(buffer->free < len) {
456
- reserve_buffer(mp, len);
442
+ if(csize <= mp->user.buffer_free_size) {
443
+ return;
457
444
  }
458
- memcpy(buffer->ptr + buffer->size, ptr, len);
459
- buffer->size += len;
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.size <= mp->user.offset) {
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.size,
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()* method before calling this method again.
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()* method before calling this method again.
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);