msgpack 0.4.7 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/.gitignore +17 -0
  2. data/ChangeLog +47 -0
  3. data/README.rdoc +102 -0
  4. data/Rakefile +88 -0
  5. data/doclib/msgpack.rb +55 -0
  6. data/doclib/msgpack/buffer.rb +193 -0
  7. data/doclib/msgpack/core_ext.rb +101 -0
  8. data/doclib/msgpack/error.rb +14 -0
  9. data/doclib/msgpack/packer.rb +131 -0
  10. data/doclib/msgpack/unpacker.rb +130 -0
  11. data/ext/msgpack/buffer.c +679 -0
  12. data/ext/msgpack/buffer.h +442 -0
  13. data/ext/msgpack/buffer_class.c +507 -0
  14. data/ext/msgpack/buffer_class.h +32 -0
  15. data/ext/msgpack/compat.h +112 -0
  16. data/ext/msgpack/core_ext.c +129 -0
  17. data/ext/{pack.h → msgpack/core_ext.h} +7 -7
  18. data/ext/msgpack/extconf.rb +17 -0
  19. data/ext/msgpack/packer.c +137 -0
  20. data/ext/msgpack/packer.h +319 -0
  21. data/ext/msgpack/packer_class.c +285 -0
  22. data/ext/{unpack.h → msgpack/packer_class.h} +11 -7
  23. data/ext/msgpack/rbinit.c +33 -0
  24. data/ext/msgpack/rmem.c +110 -0
  25. data/ext/msgpack/rmem.h +100 -0
  26. data/ext/msgpack/sysdep.h +115 -0
  27. data/ext/msgpack/sysdep_endian.h +50 -0
  28. data/ext/msgpack/sysdep_types.h +46 -0
  29. data/ext/msgpack/unpacker.c +669 -0
  30. data/ext/msgpack/unpacker.h +112 -0
  31. data/ext/msgpack/unpacker_class.c +376 -0
  32. data/{msgpack/pack_define.h → ext/msgpack/unpacker_class.h} +12 -8
  33. data/lib/msgpack.rb +10 -0
  34. data/{ext → lib/msgpack}/version.rb +1 -1
  35. data/msgpack.gemspec +25 -0
  36. data/spec/buffer_io_spec.rb +237 -0
  37. data/spec/buffer_spec.rb +572 -0
  38. data/{test → spec}/cases.json +0 -0
  39. data/{test/cases.mpac → spec/cases.msg} +0 -0
  40. data/{test/cases_compact.mpac → spec/cases_compact.msg} +0 -0
  41. data/spec/cases_spec.rb +39 -0
  42. data/spec/format_spec.rb +225 -0
  43. data/spec/packer_spec.rb +127 -0
  44. data/spec/random_compat.rb +24 -0
  45. data/spec/spec_helper.rb +21 -0
  46. data/spec/unpacker_spec.rb +128 -0
  47. metadata +171 -34
  48. data/ext/compat.h +0 -99
  49. data/ext/extconf.rb +0 -7
  50. data/ext/pack.c +0 -314
  51. data/ext/rbinit.c +0 -66
  52. data/ext/unpack.c +0 -1001
  53. data/msgpack/pack_template.h +0 -771
  54. data/msgpack/sysdep.h +0 -195
  55. data/msgpack/unpack_define.h +0 -93
  56. data/msgpack/unpack_template.h +0 -413
  57. data/test/test_cases.rb +0 -46
  58. data/test/test_encoding.rb +0 -68
  59. data/test/test_helper.rb +0 -10
  60. data/test/test_pack_unpack.rb +0 -308
@@ -1,66 +0,0 @@
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
- #include "pack.h"
19
- #include "unpack.h"
20
- #include "compat.h"
21
-
22
- static VALUE mMessagePack;
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
-
31
- /**
32
- * Document-module: MessagePack
33
- *
34
- * MessagePack is a binary-based efficient object serialization library.
35
- * It enables to exchange structured objects between many languages like JSON.
36
- * But unlike JSON, it is very fast and small.
37
- *
38
- * You can install MessagePack with rubygems.
39
- *
40
- * gem install msgpack
41
- *
42
- * Simple usage is as follows:
43
- *
44
- * require 'msgpack'
45
- * msg = [1,2,3].to_msgpack #=> "\x93\x01\x02\x03"
46
- * MessagePack.unpack(msg) #=> [1,2,3]
47
- *
48
- * Use Unpacker class for streaming deserialization.
49
- *
50
- */
51
- void Init_msgpack(void)
52
- {
53
- mMessagePack = rb_define_module("MessagePack");
54
-
55
- rb_define_const(mMessagePack, "VERSION", rb_str_new2(MESSAGEPACK_VERSION));
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
-
64
- Init_msgpack_unpack(mMessagePack);
65
- Init_msgpack_pack(mMessagePack);
66
- }
@@ -1,1001 +0,0 @@
1
- /*
2
- * MessagePack for Ruby unpacking routine
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
- #include "ruby.h"
19
- #include "compat.h"
20
-
21
- #include "msgpack/unpack_define.h"
22
-
23
- static ID s_sysread;
24
- static ID s_readpartial;
25
-
26
- struct unpack_buffer {
27
- size_t used;
28
- size_t free;
29
- char* ptr;
30
- };
31
-
32
- typedef struct {
33
- int finished;
34
- VALUE source;
35
- size_t offset;
36
- struct unpack_buffer buffer;
37
- VALUE stream;
38
- VALUE streambuf;
39
- ID stream_append_method;
40
- size_t buffer_free_size;
41
- } unpack_user;
42
-
43
-
44
- #define msgpack_unpack_struct(name) \
45
- struct template ## name
46
-
47
- #define msgpack_unpack_func(ret, name) \
48
- ret template ## name
49
-
50
- #define msgpack_unpack_callback(name) \
51
- template_callback ## name
52
-
53
- #define msgpack_unpack_object VALUE
54
-
55
- #define msgpack_unpack_user unpack_user
56
-
57
-
58
- struct template_context;
59
- typedef struct template_context msgpack_unpack_t;
60
-
61
- static void template_init(msgpack_unpack_t* u);
62
-
63
- static VALUE template_data(msgpack_unpack_t* u);
64
-
65
- static int template_execute(msgpack_unpack_t* u,
66
- const char* data, size_t len, size_t* off);
67
-
68
-
69
- static inline VALUE template_callback_root(unpack_user* u)
70
- { return Qnil; }
71
-
72
- static inline int template_callback_uint8(unpack_user* u, uint8_t d, VALUE* o)
73
- { *o = INT2FIX(d); return 0; }
74
-
75
- static inline int template_callback_uint16(unpack_user* u, uint16_t d, VALUE* o)
76
- { *o = INT2FIX(d); return 0; }
77
-
78
- static inline int template_callback_uint32(unpack_user* u, uint32_t d, VALUE* o)
79
- { *o = UINT2NUM(d); return 0; }
80
-
81
- static inline int template_callback_uint64(unpack_user* u, uint64_t d, VALUE* o)
82
- { *o = rb_ull2inum(d); return 0; }
83
-
84
- static inline int template_callback_int8(unpack_user* u, int8_t d, VALUE* o)
85
- { *o = INT2FIX((long)d); return 0; }
86
-
87
- static inline int template_callback_int16(unpack_user* u, int16_t d, VALUE* o)
88
- { *o = INT2FIX((long)d); return 0; }
89
-
90
- static inline int template_callback_int32(unpack_user* u, int32_t d, VALUE* o)
91
- { *o = INT2NUM((long)d); return 0; }
92
-
93
- static inline int template_callback_int64(unpack_user* u, int64_t d, VALUE* o)
94
- { *o = rb_ll2inum(d); return 0; }
95
-
96
- static inline int template_callback_float(unpack_user* u, float d, VALUE* o)
97
- { *o = rb_float_new(d); return 0; }
98
-
99
- static inline int template_callback_double(unpack_user* u, double d, VALUE* o)
100
- { *o = rb_float_new(d); return 0; }
101
-
102
- static inline int template_callback_nil(unpack_user* u, VALUE* o)
103
- { *o = Qnil; return 0; }
104
-
105
- static inline int template_callback_true(unpack_user* u, VALUE* o)
106
- { *o = Qtrue; return 0; }
107
-
108
- static inline int template_callback_false(unpack_user* u, VALUE* o)
109
- { *o = Qfalse; return 0;}
110
-
111
- static inline int template_callback_array(unpack_user* u, unsigned int n, VALUE* o)
112
- { *o = rb_ary_new2(n); return 0; }
113
-
114
- static inline int template_callback_array_item(unpack_user* u, VALUE* c, VALUE o)
115
- { rb_ary_push(*c, o); return 0; }
116
-
117
- static inline int template_callback_map(unpack_user* u, unsigned int n, VALUE* o)
118
- { *o = rb_hash_new(); return 0; }
119
-
120
- static inline int template_callback_map_item(unpack_user* u, VALUE* c, VALUE k, VALUE v)
121
- { rb_hash_aset(*c, k, v); return 0; }
122
-
123
- #ifdef RSTRING_EMBED_LEN_MAX
124
- #define COW_MIN_SIZE RSTRING_EMBED_LEN_MAX
125
- #else
126
- #define COW_MIN_SIZE ((sizeof(VALUE)*3)/sizeof(char)-1)
127
- #endif
128
-
129
- static inline int template_callback_raw(unpack_user* u, const char* b, const char* p, unsigned int l, VALUE* o)
130
- {
131
- if(u->source == Qnil || l <= COW_MIN_SIZE) {
132
- *o = rb_str_new(p, l);
133
- } else {
134
- *o = rb_str_substr(u->source, p - b, l);
135
- }
136
- #ifdef COMPAT_HAVE_ENCODING
137
- ENCODING_SET(*o, s_enc_utf8);
138
- #endif
139
- return 0;
140
- }
141
-
142
-
143
- #include "msgpack/unpack_template.h"
144
-
145
-
146
- #define UNPACKER(from, name) \
147
- msgpack_unpack_t *name = NULL; \
148
- Data_Get_Struct(from, msgpack_unpack_t, name); \
149
- if(name == NULL) { \
150
- rb_raise(rb_eArgError, "NULL found for " # name " when shouldn't be."); \
151
- }
152
-
153
- #define CHECK_STRING_TYPE(value) \
154
- value = rb_check_string_type(value); \
155
- if( NIL_P(value) ) { \
156
- rb_raise(rb_eTypeError, "instance of String needed"); \
157
- }
158
-
159
-
160
- static VALUE template_execute_rescue(VALUE nouse)
161
- {
162
- rb_gc_enable();
163
- COMPAT_RERAISE;
164
- }
165
-
166
- static VALUE template_execute_do(VALUE argv)
167
- {
168
- VALUE* args = (VALUE*)argv;
169
-
170
- msgpack_unpack_t* mp = (msgpack_unpack_t*)args[0];
171
- char* dptr = (char*)args[1];
172
- size_t dlen = (size_t)args[2];
173
- size_t* from = (size_t*)args[3];
174
-
175
- int ret = template_execute(mp, dptr, dlen, from);
176
-
177
- return (VALUE)ret;
178
- }
179
-
180
- static int template_execute_wrap(msgpack_unpack_t* mp,
181
- VALUE str, size_t dlen, size_t* from)
182
- {
183
- VALUE args[4] = {
184
- (VALUE)mp,
185
- (VALUE)RSTRING_PTR(str),
186
- (VALUE)dlen,
187
- (VALUE)from,
188
- };
189
-
190
- // FIXME execute実行中はmp->topが更新されないのでGC markが機能しない
191
- rb_gc_disable();
192
-
193
- mp->user.source = str;
194
-
195
- int ret = (int)rb_rescue(template_execute_do, (VALUE)args,
196
- template_execute_rescue, Qnil);
197
-
198
- rb_gc_enable();
199
-
200
- return ret;
201
- }
202
-
203
- static int template_execute_wrap_each(msgpack_unpack_t* mp,
204
- const char* ptr, size_t dlen, size_t* from)
205
- {
206
- VALUE args[4] = {
207
- (VALUE)mp,
208
- (VALUE)ptr,
209
- (VALUE)dlen,
210
- (VALUE)from,
211
- };
212
-
213
- // FIXME execute実行中はmp->topが更新されないのでGC markが機能しない
214
- rb_gc_disable();
215
-
216
- mp->user.source = Qnil;
217
-
218
- int ret = (int)rb_rescue(template_execute_do, (VALUE)args,
219
- template_execute_rescue, Qnil);
220
-
221
- rb_gc_enable();
222
-
223
- return ret;
224
- }
225
-
226
-
227
- static VALUE cUnpacker;
228
-
229
-
230
- /**
231
- * Document-module: MessagePack::UnpackerError
232
- *
233
- */
234
- static VALUE eUnpackError;
235
-
236
-
237
- #ifndef MSGPACK_UNPACKER_BUFFER_INIT_SIZE
238
- #define MSGPACK_UNPACKER_BUFFER_INIT_SIZE (32*1024)
239
- #endif
240
-
241
- #ifndef MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE
242
- #define MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE (8*1024)
243
- #endif
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
-
252
- static void MessagePack_Unpacker_free(void* data)
253
- {
254
- if(data) {
255
- msgpack_unpack_t* mp = (msgpack_unpack_t*)data;
256
- free(mp->user.buffer.ptr);
257
- free(mp);
258
- }
259
- }
260
-
261
- static void MessagePack_Unpacker_mark(msgpack_unpack_t *mp)
262
- {
263
- unsigned int i;
264
- rb_gc_mark(mp->user.stream);
265
- rb_gc_mark(mp->user.streambuf);
266
- rb_gc_mark_maybe(template_data(mp));
267
- for(i=0; i < mp->top; ++i) {
268
- rb_gc_mark(mp->stack[i].obj);
269
- rb_gc_mark_maybe(mp->stack[i].map_key);
270
- }
271
- }
272
-
273
- static VALUE MessagePack_Unpacker_alloc(VALUE klass)
274
- {
275
- VALUE obj;
276
- msgpack_unpack_t* mp = ALLOC_N(msgpack_unpack_t, 1);
277
-
278
- // rb_gc_mark (not _maybe) is used for following member objects.
279
- mp->user.stream = Qnil;
280
- mp->user.streambuf = Qnil;
281
-
282
- mp->user.finished = 0;
283
- mp->user.offset = 0;
284
- mp->user.buffer.used = 0;
285
- mp->user.buffer.free = 0;
286
- mp->user.buffer.ptr = NULL;
287
-
288
- obj = Data_Wrap_Struct(klass, MessagePack_Unpacker_mark,
289
- MessagePack_Unpacker_free, mp);
290
- return obj;
291
- }
292
-
293
- static ID append_method_of(VALUE stream)
294
- {
295
- if(rb_respond_to(stream, s_sysread)) {
296
- return s_sysread;
297
- } else {
298
- return s_readpartial;
299
- }
300
- }
301
-
302
- /**
303
- * Document-method: MessagePack::Unpacker#initialize
304
- *
305
- * call-seq:
306
- * MessagePack::Unpacker.new(stream = nil)
307
- *
308
- * Creates instance of MessagePack::Unpacker.
309
- *
310
- * You can specify a _stream_ for input stream.
311
- * It is required to implement *sysread* or *readpartial* method.
312
- *
313
- * With the input stream, buffers will be feeded into the deserializer automatically.
314
- *
315
- * Without the input stream, use *feed* method manually. Or you can manage the buffer manually
316
- * with *execute*, *finished?*, *data* and *reset* methods.
317
- */
318
- static VALUE MessagePack_Unpacker_initialize(int argc, VALUE *argv, VALUE self)
319
- {
320
- VALUE stream;
321
- switch(argc) {
322
- case 0:
323
- stream = Qnil;
324
- break;
325
- case 1:
326
- stream = argv[0];
327
- break;
328
- default:
329
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
330
- }
331
-
332
- UNPACKER(self, mp);
333
- template_init(mp);
334
- mp->user.stream = stream;
335
- mp->user.streambuf = rb_str_buf_new(MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE);
336
- mp->user.stream_append_method = append_method_of(stream);
337
- mp->user.buffer_free_size = MSGPACK_BUFFER_FREE_SIZE;
338
-
339
- return self;
340
- }
341
-
342
-
343
- /**
344
- * Document-method: MessagePack::Unpacker#stream
345
- *
346
- * call-seq:
347
- * unpacker.stream
348
- *
349
- * Gets the input stream.
350
- */
351
- static VALUE MessagePack_Unpacker_stream_get(VALUE self)
352
- {
353
- UNPACKER(self, mp);
354
- return mp->user.stream;
355
- }
356
-
357
- /**
358
- * Document-method: MessagePack::Unpacker#stream=
359
- *
360
- * call-seq:
361
- * unpacker.stream = stream
362
- *
363
- * Resets the input stream. You can set nil not to use input stream.
364
- */
365
- static VALUE MessagePack_Unpacker_stream_set(VALUE self, VALUE val)
366
- {
367
- UNPACKER(self, mp);
368
- mp->user.stream = val;
369
- mp->user.stream_append_method = append_method_of(val);
370
- return val;
371
- }
372
-
373
-
374
- static void reserve_buffer(msgpack_unpack_t* mp, size_t require)
375
- {
376
- struct unpack_buffer* buffer = &mp->user.buffer;
377
-
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;
386
- while(nsize < require) {
387
- nsize *= 2;
388
- }
389
- char* tmp = REALLOC_N(buffer->ptr, char, nsize);
390
- buffer->free = nsize;
391
- buffer->ptr = tmp;
392
- return;
393
- }
394
-
395
- if(buffer->used <= mp->user.offset) {
396
- /* clear buffer and rewind offset */
397
- buffer->free += buffer->used;
398
- buffer->used = 0;
399
- mp->user.offset = 0;
400
- }
401
-
402
- if(require <= buffer->free) {
403
- /* enough free space */
404
- return;
405
- }
406
-
407
- size_t nsize = (buffer->used + buffer->free) * 2;
408
-
409
- if(mp->user.offset <= buffer->used / 2) {
410
- /* parsed less than half: realloc only */
411
- while(nsize < buffer->used + require) {
412
- nsize *= 2;
413
- }
414
- char* tmp = REALLOC_N(buffer->ptr, char, nsize);
415
- buffer->free = nsize - buffer->used;
416
- buffer->ptr = tmp;
417
-
418
- } else {
419
- /* parsed more than half: realloc and move */
420
- size_t not_parsed = buffer->used - mp->user.offset;
421
- while(nsize < not_parsed + require) {
422
- nsize *= 2;
423
- }
424
- char* tmp = REALLOC_N(buffer->ptr, char, nsize);
425
- memcpy(tmp, tmp + mp->user.offset, not_parsed);
426
- buffer->free = nsize - not_parsed;
427
- buffer->used = not_parsed;
428
- buffer->ptr = tmp;
429
- mp->user.offset = 0;
430
- }
431
- }
432
-
433
- static inline void try_free_buffer(msgpack_unpack_t* mp, size_t require)
434
- {
435
- if(mp->user.buffer_free_size == 0) {
436
- return;
437
- }
438
-
439
- struct unpack_buffer* buffer = &mp->user.buffer;
440
- size_t csize = buffer->used + buffer->free;
441
-
442
- if(csize <= mp->user.buffer_free_size) {
443
- return;
444
- }
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;
492
- buffer->free -= len;
493
- }
494
-
495
- /**
496
- * Document-method: MessagePack::Unpacker#feed
497
- *
498
- * call-seq:
499
- * unpacker.feed(data)
500
- *
501
- * Fills the internal buffer with the specified buffer.
502
- */
503
- static VALUE MessagePack_Unpacker_feed(VALUE self, VALUE data)
504
- {
505
- UNPACKER(self, mp);
506
- StringValue(data);
507
- feed_buffer(mp, RSTRING_PTR(data), RSTRING_LEN(data));
508
- return Qnil;
509
- }
510
-
511
- /**
512
- * Document-method: MessagePack::Unpacker#fill
513
- *
514
- * call-seq:
515
- * unpacker.fill -> length of read data
516
- *
517
- * Fills the internal buffer using the input stream.
518
- *
519
- * If the input stream is not specified, it returns nil.
520
- * You can set it on *initialize* or *stream=* methods.
521
- *
522
- * This methods raises exceptions that _stream.sysread_ or
523
- * _stream.readpartial_ method raises.
524
- */
525
- static VALUE MessagePack_Unpacker_fill(VALUE self)
526
- {
527
- UNPACKER(self, mp);
528
-
529
- if(mp->user.stream == Qnil) {
530
- return Qnil;
531
- }
532
-
533
- rb_funcall(mp->user.stream, mp->user.stream_append_method, 2,
534
- LONG2FIX(MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE),
535
- mp->user.streambuf);
536
-
537
- size_t len = RSTRING_LEN(mp->user.streambuf);
538
- feed_buffer(mp, RSTRING_PTR(mp->user.streambuf), len);
539
-
540
- return LONG2FIX(len);
541
- }
542
-
543
-
544
- /**
545
- * Document-method: MessagePack::Unpacker#each
546
- *
547
- * call-seq:
548
- * unpacker.each {|object| }
549
- *
550
- * Deserializes objects repeatedly. This calls *fill* method automatically.
551
- *
552
- * UnpackError is throw when parse error is occured.
553
- * This method raises exceptions that *fill* method raises.
554
- */
555
- static VALUE MessagePack_Unpacker_each(VALUE self)
556
- {
557
- UNPACKER(self, mp);
558
- int ret;
559
-
560
- #ifdef RETURN_ENUMERATOR
561
- RETURN_ENUMERATOR(self, 0, 0);
562
- #endif
563
-
564
- while(1) {
565
- if(mp->user.buffer.used <= mp->user.offset) {
566
- do_fill:
567
- {
568
- VALUE len = MessagePack_Unpacker_fill(self);
569
- if(len == Qnil || FIX2LONG(len) == 0) {
570
- break;
571
- }
572
- }
573
- }
574
-
575
- ret = template_execute_wrap_each(mp,
576
- mp->user.buffer.ptr, mp->user.buffer.used,
577
- &mp->user.offset);
578
-
579
- if(ret < 0) {
580
- rb_raise(eUnpackError, "parse error.");
581
-
582
- } else if(ret > 0) {
583
- VALUE data = template_data(mp);
584
- template_init(mp);
585
- rb_yield(data);
586
-
587
- } else {
588
- goto do_fill;
589
- }
590
- }
591
-
592
- try_free_buffer(mp, 0);
593
-
594
- return Qnil;
595
- }
596
-
597
- static VALUE feed_each_impl(VALUE args)
598
- {
599
- VALUE self = ((VALUE*)args)[0];
600
- VALUE data = ((VALUE*)args)[1];
601
- size_t* pconsumed = (size_t*)((VALUE*)args)[2];
602
-
603
- UNPACKER(self, mp);
604
- int ret;
605
- const char* ptr = RSTRING_PTR(data);
606
- size_t len = RSTRING_LEN(data);
607
-
608
- if(mp->user.buffer.used > 0) {
609
- while(1) {
610
- ret = template_execute_wrap_each(mp,
611
- mp->user.buffer.ptr, mp->user.buffer.used,
612
- &mp->user.offset);
613
-
614
- if(ret < 0) {
615
- rb_raise(eUnpackError, "parse error.");
616
-
617
- } else if(ret > 0) {
618
- VALUE data = template_data(mp);
619
- template_init(mp);
620
- rb_yield(data);
621
-
622
- } else {
623
- break;
624
- }
625
- }
626
- }
627
-
628
- if(len <= 0) {
629
- return Qnil;
630
- }
631
-
632
- if(mp->user.buffer.used <= mp->user.offset) {
633
- // wrap & execute & feed
634
- while(1) {
635
- ret = template_execute_wrap_each(mp,
636
- ptr, len, pconsumed);
637
-
638
- if(ret < 0) {
639
- rb_raise(eUnpackError, "parse error.");
640
-
641
- } else if(ret > 0) {
642
- VALUE data = template_data(mp);
643
- template_init(mp);
644
- rb_yield(data);
645
-
646
- } else {
647
- break;
648
- }
649
- }
650
-
651
- } else {
652
- // feed & execute
653
- feed_buffer(mp, ptr, len);
654
- *pconsumed = len;
655
-
656
- while(1) {
657
- ret = template_execute_wrap_each(mp,
658
- mp->user.buffer.ptr, mp->user.buffer.used,
659
- &mp->user.offset);
660
-
661
- if(ret < 0) {
662
- rb_raise(eUnpackError, "parse error.");
663
-
664
- } else if(ret > 0) {
665
- VALUE data = template_data(mp);
666
- template_init(mp);
667
- rb_yield(data);
668
-
669
- } else {
670
- break;
671
- }
672
- }
673
- }
674
-
675
- return Qnil;
676
- }
677
-
678
- static VALUE feed_each_ensure(VALUE args) {
679
- VALUE self = ((VALUE*)args)[0];
680
- VALUE data = ((VALUE*)args)[1];
681
- size_t* pconsumed = (size_t*)((VALUE*)args)[2];
682
-
683
- const char* dptr = RSTRING_PTR(data) + *pconsumed;
684
- size_t dlen = RSTRING_LEN(data) - *pconsumed;
685
-
686
- if(dlen > 0) {
687
- UNPACKER(self, mp);
688
- try_free_buffer(mp, dlen);
689
- feed_buffer(mp, dptr, dlen);
690
- }
691
-
692
- return Qnil;
693
- }
694
-
695
- /**
696
- * Document-method: MessagePack::Unpacker#feed_each
697
- *
698
- * call-seq:
699
- * unpacker.feed_each(data) {|object| }
700
- *
701
- * Same as feed(data) + each {|object| }, but tries to avoid copying of the buffer.
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
-
717
-
718
- static inline VALUE MessagePack_unpack_impl(VALUE self, VALUE data, unsigned long dlen)
719
- {
720
- msgpack_unpack_t mp;
721
- template_init(&mp);
722
-
723
- mp.user.finished = 0;
724
-
725
- size_t from = 0;
726
- int ret = template_execute_wrap(&mp, data, dlen, &from);
727
-
728
- if(ret < 0) {
729
- rb_raise(eUnpackError, "parse error.");
730
-
731
- } else if(ret == 0) {
732
- rb_raise(eUnpackError, "insufficient bytes.");
733
-
734
- } else {
735
- if(from < dlen) {
736
- rb_raise(eUnpackError, "extra bytes.");
737
- }
738
- return template_data(&mp);
739
- }
740
- }
741
-
742
- /**
743
- * Document-method: MessagePack::Unpacker.unpack_limit
744
- *
745
- * call-seq:
746
- * MessagePack::Unpacker.unpack_limit(data, limit) -> object
747
- *
748
- * Deserializes one object over the specified buffer upto _limit_ bytes.
749
- *
750
- * UnpackError is throw when parse error is occured, the buffer is insufficient
751
- * to deserialize one object or there are extra bytes.
752
- */
753
- static VALUE MessagePack_unpack_limit(VALUE self, VALUE data, VALUE limit)
754
- {
755
- CHECK_STRING_TYPE(data);
756
- return MessagePack_unpack_impl(self, data, NUM2ULONG(limit));
757
- }
758
-
759
- /**
760
- * Document-method: MessagePack::Unpacker.unpack
761
- *
762
- * call-seq:
763
- * MessagePack::Unpacker.unpack(data) -> object
764
- *
765
- * Deserializes one object over the specified buffer.
766
- *
767
- * UnpackError is throw when parse error is occured, the buffer is insufficient
768
- * to deserialize one object or there are extra bytes.
769
- */
770
- static VALUE MessagePack_unpack(VALUE self, VALUE data)
771
- {
772
- CHECK_STRING_TYPE(data);
773
- return MessagePack_unpack_impl(self, data, RSTRING_LEN(data));
774
- }
775
-
776
-
777
- static VALUE MessagePack_Unpacker_execute_impl(VALUE self, VALUE data,
778
- size_t from, size_t limit)
779
- {
780
- UNPACKER(self, mp);
781
-
782
- if(from >= limit) {
783
- rb_raise(eUnpackError, "offset is bigger than data buffer size.");
784
- }
785
-
786
- int ret = template_execute_wrap(mp, data, limit, &from);
787
-
788
- if(ret < 0) {
789
- rb_raise(eUnpackError, "parse error.");
790
- } else if(ret > 0) {
791
- mp->user.finished = 1;
792
- return ULONG2NUM(from);
793
- } else {
794
- mp->user.finished = 0;
795
- return ULONG2NUM(from);
796
- }
797
- }
798
-
799
- /**
800
- * Document-method: MessagePack::Unpacker#execute_limit
801
- *
802
- * call-seq:
803
- * unpacker.execute_limit(data, offset, limit) -> next offset
804
- *
805
- * Deserializes one object over the specified buffer from _offset_ bytes upto _limit_ bytes.
806
- *
807
- * This method doesn't use the internal buffer.
808
- *
809
- * Call *reset* method before calling this method again.
810
- *
811
- * UnpackError is throw when parse error is occured.
812
- */
813
- static VALUE MessagePack_Unpacker_execute_limit(VALUE self, VALUE data,
814
- VALUE off, VALUE limit)
815
- {
816
- CHECK_STRING_TYPE(data);
817
- return MessagePack_Unpacker_execute_impl(self, data,
818
- (size_t)NUM2ULONG(off), (size_t)NUM2ULONG(limit));
819
- }
820
-
821
- /**
822
- * Document-method: MessagePack::Unpacker#execute
823
- *
824
- * call-seq:
825
- * unpacker.execute(data, offset) -> next offset
826
- *
827
- * Deserializes one object over the specified buffer from _offset_ bytes.
828
- *
829
- * This method doesn't use the internal buffer.
830
- *
831
- * Call *reset* method before calling this method again.
832
- *
833
- * This returns offset that was parsed to.
834
- * Use *finished?* method to check an object is deserialized and call *data*
835
- * method if it returns true.
836
- *
837
- * UnpackError is throw when parse error is occured.
838
- */
839
- static VALUE MessagePack_Unpacker_execute(VALUE self, VALUE data, VALUE off)
840
- {
841
- CHECK_STRING_TYPE(data);
842
- return MessagePack_Unpacker_execute_impl(self, data,
843
- (size_t)NUM2ULONG(off), (size_t)RSTRING_LEN(data));
844
- }
845
-
846
- /**
847
- * Document-method: MessagePack::Unpacker#finished?
848
- *
849
- * call-seq:
850
- * unpacker.finished?
851
- *
852
- * Returns true if an object is ready to get with data method.
853
- *
854
- * Use this method with execute method.
855
- */
856
- static VALUE MessagePack_Unpacker_finished_p(VALUE self)
857
- {
858
- UNPACKER(self, mp);
859
- if(mp->user.finished) {
860
- return Qtrue;
861
- }
862
- return Qfalse;
863
- }
864
-
865
- /**
866
- * Document-method: MessagePack::Unpacker#data
867
- *
868
- * call-seq:
869
- * unpacker.data
870
- *
871
- * Gets the object deserialized by execute method.
872
- *
873
- * Use this method with execute method.
874
- */
875
- static VALUE MessagePack_Unpacker_data(VALUE self)
876
- {
877
- UNPACKER(self, mp);
878
- return template_data(mp);
879
- }
880
-
881
- /**
882
- * Document-method: MessagePack::Unpacker#reset
883
- *
884
- * call-seq:
885
- * unpacker.reset
886
- *
887
- * Resets the internal state of the unpacker.
888
- */
889
- static VALUE MessagePack_Unpacker_reset(VALUE self)
890
- {
891
- UNPACKER(self, mp);
892
- template_init(mp);
893
- mp->user.finished = 0;
894
- try_free_buffer(mp, 0);
895
- return self;
896
- }
897
-
898
-
899
- void Init_msgpack_unpack(VALUE mMessagePack)
900
- {
901
- s_sysread = rb_intern("sysread");
902
- s_readpartial = rb_intern("readpartial");
903
-
904
- eUnpackError = rb_define_class_under(mMessagePack, "UnpackError", rb_eStandardError);
905
- cUnpacker = rb_define_class_under(mMessagePack, "Unpacker", rb_cObject);
906
- rb_define_alloc_func(cUnpacker, MessagePack_Unpacker_alloc);
907
-
908
- rb_define_method(cUnpacker, "initialize", MessagePack_Unpacker_initialize, -1);
909
-
910
- /* Buffered API */
911
- rb_define_method(cUnpacker, "feed", MessagePack_Unpacker_feed, 1);
912
- rb_define_method(cUnpacker, "fill", MessagePack_Unpacker_fill, 0);
913
- rb_define_method(cUnpacker, "each", MessagePack_Unpacker_each, 0);
914
- rb_define_method(cUnpacker, "stream", MessagePack_Unpacker_stream_get, 0);
915
- rb_define_method(cUnpacker, "stream=", MessagePack_Unpacker_stream_set, 1);
916
- rb_define_method(cUnpacker, "feed_each", MessagePack_Unpacker_feed_each, 1);
917
-
918
- /* Unbuffered API */
919
- rb_define_method(cUnpacker, "execute", MessagePack_Unpacker_execute, 2);
920
- rb_define_method(cUnpacker, "execute_limit", MessagePack_Unpacker_execute_limit, 3);
921
- rb_define_method(cUnpacker, "finished?", MessagePack_Unpacker_finished_p, 0);
922
- rb_define_method(cUnpacker, "data", MessagePack_Unpacker_data, 0);
923
- rb_define_method(cUnpacker, "reset", MessagePack_Unpacker_reset, 0);
924
-
925
- /**
926
- * MessagePack module is defined in rbinit.c file.
927
- * mMessagePack = rb_define_module("MessagePack");
928
- */
929
- rb_define_module_function(mMessagePack, "unpack", MessagePack_unpack, 1);
930
- rb_define_module_function(mMessagePack, "unpack_limit", MessagePack_unpack_limit, 2);
931
- }
932
-
933
- /**
934
- * Document-module: MessagePack::Unpacker
935
- *
936
- * Deserializer class that includes Buffered API and Unbuffered API.
937
- *
938
- *
939
- * Buffered API uses the internal buffer of the Unpacker.
940
- * Following code uses Buffered API with an input stream:
941
- *
942
- * # create an unpacker with input stream.
943
- * pac = MessagePack::Unpacker.new(STDIN)
944
- *
945
- * # deserialize object one after another.
946
- * pac.each {|obj|
947
- * # ...
948
- * }
949
- *
950
- *
951
- * Following code doesn't use the input stream and feeds buffer
952
- * manually. This is useful to use special stream or with
953
- * event-driven I/O library.
954
- *
955
- * # create an unpacker without input stream.
956
- * pac = MessagePack::Unpacker.new()
957
- *
958
- * # feed buffer to the internal buffer.
959
- * pac.feed(input_bytes)
960
- *
961
- * # deserialize object one after another.
962
- * pac.each {|obj|
963
- * # ...
964
- * }
965
- *
966
- *
967
- * You can manage the buffer manually with the combination of
968
- * *execute*, *finished?*, *data* and *reset* method.
969
- *
970
- * # create an unpacker.
971
- * pac = MessagePack::Unpacker.new()
972
- *
973
- * # manage buffer and offset manually.
974
- * offset = 0
975
- * buffer = ''
976
- *
977
- * # read some data into the buffer.
978
- * buffer << [1,2,3].to_msgpack
979
- * buffer << [4,5,6].to_msgpack
980
- *
981
- * while true
982
- * offset = pac.execute(buffer, offset)
983
- *
984
- * if pac.finished?
985
- * obj = pac.data
986
- *
987
- * buffer.slice!(0, offset)
988
- * offset = 0
989
- * pac.reset
990
- *
991
- * # do something with the object
992
- * # ...
993
- *
994
- * # repeat execution if there are more data.
995
- * next unless buffer.empty?
996
- * end
997
- *
998
- * break
999
- * end
1000
- */
1001
-