msgpack 0.6.0pre1-x64-mingw32
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.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.travis.yml +26 -0
- data/ChangeLog +117 -0
- data/Dockerfile +30 -0
- data/Gemfile +4 -0
- data/LICENSE +177 -0
- data/README.rdoc +129 -0
- data/Rakefile +114 -0
- data/bench/pack.rb +23 -0
- data/bench/pack_log.rb +33 -0
- data/bench/pack_log_long.rb +65 -0
- data/bench/run.sh +14 -0
- data/bench/run_long.sh +35 -0
- data/bench/unpack.rb +21 -0
- data/bench/unpack_log.rb +34 -0
- data/bench/unpack_log_long.rb +67 -0
- data/cross-build.sh +9 -0
- data/doclib/msgpack/buffer.rb +193 -0
- data/doclib/msgpack/core_ext.rb +101 -0
- data/doclib/msgpack/error.rb +14 -0
- data/doclib/msgpack/packer.rb +134 -0
- data/doclib/msgpack/unpacker.rb +146 -0
- data/doclib/msgpack.rb +77 -0
- data/ext/java/org/msgpack/jruby/Buffer.java +221 -0
- data/ext/java/org/msgpack/jruby/Decoder.java +201 -0
- data/ext/java/org/msgpack/jruby/Encoder.java +308 -0
- data/ext/java/org/msgpack/jruby/ExtensionValue.java +136 -0
- data/ext/java/org/msgpack/jruby/MessagePackLibrary.java +107 -0
- data/ext/java/org/msgpack/jruby/Packer.java +78 -0
- data/ext/java/org/msgpack/jruby/Types.java +37 -0
- data/ext/java/org/msgpack/jruby/Unpacker.java +170 -0
- data/ext/msgpack/buffer.c +695 -0
- data/ext/msgpack/buffer.h +447 -0
- data/ext/msgpack/buffer_class.c +507 -0
- data/ext/msgpack/buffer_class.h +32 -0
- data/ext/msgpack/compat.h +113 -0
- data/ext/msgpack/core_ext.c +129 -0
- data/ext/msgpack/core_ext.h +26 -0
- data/ext/msgpack/extconf.rb +28 -0
- data/ext/msgpack/packer.c +168 -0
- data/ext/msgpack/packer.h +441 -0
- data/ext/msgpack/packer_class.c +302 -0
- data/ext/msgpack/packer_class.h +30 -0
- data/ext/msgpack/rbinit.c +33 -0
- data/ext/msgpack/rmem.c +94 -0
- data/ext/msgpack/rmem.h +109 -0
- data/ext/msgpack/sysdep.h +115 -0
- data/ext/msgpack/sysdep_endian.h +50 -0
- data/ext/msgpack/sysdep_types.h +46 -0
- data/ext/msgpack/unpacker.c +771 -0
- data/ext/msgpack/unpacker.h +122 -0
- data/ext/msgpack/unpacker_class.c +405 -0
- data/ext/msgpack/unpacker_class.h +32 -0
- data/lib/msgpack/msgpack.so +0 -0
- data/lib/msgpack/version.rb +3 -0
- data/lib/msgpack.rb +13 -0
- data/msgpack.gemspec +31 -0
- data/msgpack.org.md +46 -0
- data/spec/cases.json +1 -0
- data/spec/cases.msg +0 -0
- data/spec/cases_compact.msg +0 -0
- data/spec/cases_spec.rb +39 -0
- data/spec/cruby/buffer_io_spec.rb +256 -0
- data/spec/cruby/buffer_packer.rb +29 -0
- data/spec/cruby/buffer_spec.rb +572 -0
- data/spec/cruby/buffer_unpacker.rb +19 -0
- data/spec/cruby/packer_spec.rb +120 -0
- data/spec/cruby/unpacker_spec.rb +305 -0
- data/spec/format_spec.rb +282 -0
- data/spec/jruby/benchmarks/shootout_bm.rb +73 -0
- data/spec/jruby/benchmarks/symbolize_keys_bm.rb +25 -0
- data/spec/jruby/msgpack/unpacker_spec.rb +290 -0
- data/spec/jruby/msgpack_spec.rb +142 -0
- data/spec/pack_spec.rb +67 -0
- data/spec/random_compat.rb +24 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/unpack_spec.rb +60 -0
- metadata +209 -0
@@ -0,0 +1,122 @@
|
|
1
|
+
/*
|
2
|
+
* MessagePack for Ruby
|
3
|
+
*
|
4
|
+
* Copyright (C) 2008-2013 Sadayuki Furuhashi
|
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 MSGPACK_RUBY_UNPACKER_H__
|
19
|
+
#define MSGPACK_RUBY_UNPACKER_H__
|
20
|
+
|
21
|
+
#include "buffer.h"
|
22
|
+
|
23
|
+
#ifndef MSGPACK_UNPACKER_STACK_CAPACITY
|
24
|
+
#define MSGPACK_UNPACKER_STACK_CAPACITY 128
|
25
|
+
#endif
|
26
|
+
|
27
|
+
struct msgpack_unpacker_t;
|
28
|
+
typedef struct msgpack_unpacker_t msgpack_unpacker_t;
|
29
|
+
|
30
|
+
enum stack_type_t {
|
31
|
+
STACK_TYPE_ARRAY,
|
32
|
+
STACK_TYPE_MAP_KEY,
|
33
|
+
STACK_TYPE_MAP_VALUE,
|
34
|
+
};
|
35
|
+
|
36
|
+
typedef struct {
|
37
|
+
size_t count;
|
38
|
+
enum stack_type_t type;
|
39
|
+
VALUE object;
|
40
|
+
VALUE key;
|
41
|
+
} msgpack_unpacker_stack_t;
|
42
|
+
|
43
|
+
#define MSGPACK_UNPACKER_STACK_SIZE (8+4+8+8) /* assumes size_t <= 64bit, enum <= 32bit, VALUE <= 64bit */
|
44
|
+
|
45
|
+
struct msgpack_unpacker_t {
|
46
|
+
msgpack_buffer_t buffer;
|
47
|
+
|
48
|
+
unsigned int head_byte;
|
49
|
+
|
50
|
+
msgpack_unpacker_stack_t* stack;
|
51
|
+
size_t stack_depth;
|
52
|
+
size_t stack_capacity;
|
53
|
+
|
54
|
+
VALUE last_object;
|
55
|
+
|
56
|
+
VALUE reading_raw;
|
57
|
+
size_t reading_raw_remaining;
|
58
|
+
|
59
|
+
VALUE buffer_ref;
|
60
|
+
|
61
|
+
/* options */
|
62
|
+
bool symbolize_keys;
|
63
|
+
};
|
64
|
+
|
65
|
+
#define UNPACKER_BUFFER_(uk) (&(uk)->buffer)
|
66
|
+
|
67
|
+
enum msgpack_unpacker_object_type {
|
68
|
+
TYPE_NIL = 0,
|
69
|
+
TYPE_BOOLEAN,
|
70
|
+
TYPE_INTEGER,
|
71
|
+
TYPE_FLOAT,
|
72
|
+
TYPE_RAW,
|
73
|
+
TYPE_ARRAY,
|
74
|
+
TYPE_MAP,
|
75
|
+
};
|
76
|
+
|
77
|
+
void msgpack_unpacker_static_init();
|
78
|
+
|
79
|
+
void msgpack_unpacker_static_destroy();
|
80
|
+
|
81
|
+
void _msgpack_unpacker_init(msgpack_unpacker_t* uk);
|
82
|
+
|
83
|
+
void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk);
|
84
|
+
|
85
|
+
void msgpack_unpacker_mark(msgpack_unpacker_t* uk);
|
86
|
+
|
87
|
+
void _msgpack_unpacker_reset(msgpack_unpacker_t* uk);
|
88
|
+
|
89
|
+
static inline void msgpack_unpacker_set_symbolized_keys(msgpack_unpacker_t* uk, bool enable)
|
90
|
+
{
|
91
|
+
uk->symbolize_keys = enable;
|
92
|
+
}
|
93
|
+
|
94
|
+
|
95
|
+
/* error codes */
|
96
|
+
#define PRIMITIVE_CONTAINER_START 1
|
97
|
+
#define PRIMITIVE_OBJECT_COMPLETE 0
|
98
|
+
#define PRIMITIVE_EOF -1
|
99
|
+
#define PRIMITIVE_INVALID_BYTE -2
|
100
|
+
#define PRIMITIVE_STACK_TOO_DEEP -3
|
101
|
+
#define PRIMITIVE_UNEXPECTED_TYPE -4
|
102
|
+
|
103
|
+
int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth);
|
104
|
+
|
105
|
+
int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth);
|
106
|
+
|
107
|
+
static inline VALUE msgpack_unpacker_get_last_object(msgpack_unpacker_t* uk)
|
108
|
+
{
|
109
|
+
return uk->last_object;
|
110
|
+
}
|
111
|
+
|
112
|
+
|
113
|
+
int msgpack_unpacker_peek_next_object_type(msgpack_unpacker_t* uk);
|
114
|
+
|
115
|
+
int msgpack_unpacker_skip_nil(msgpack_unpacker_t* uk);
|
116
|
+
|
117
|
+
int msgpack_unpacker_read_array_header(msgpack_unpacker_t* uk, uint32_t* result_size);
|
118
|
+
|
119
|
+
int msgpack_unpacker_read_map_header(msgpack_unpacker_t* uk, uint32_t* result_size);
|
120
|
+
|
121
|
+
#endif
|
122
|
+
|
@@ -0,0 +1,405 @@
|
|
1
|
+
/*
|
2
|
+
* MessagePack for Ruby
|
3
|
+
*
|
4
|
+
* Copyright (C) 2008-2013 Sadayuki Furuhashi
|
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
|
+
|
19
|
+
#include "unpacker.h"
|
20
|
+
#include "unpacker_class.h"
|
21
|
+
#include "buffer_class.h"
|
22
|
+
|
23
|
+
VALUE cMessagePack_Unpacker;
|
24
|
+
|
25
|
+
//static VALUE s_unpacker_value;
|
26
|
+
//static msgpack_unpacker_t* s_unpacker;
|
27
|
+
|
28
|
+
static VALUE eUnpackError;
|
29
|
+
static VALUE eMalformedFormatError;
|
30
|
+
static VALUE eStackError;
|
31
|
+
static VALUE eTypeError;
|
32
|
+
|
33
|
+
#define UNPACKER(from, name) \
|
34
|
+
msgpack_unpacker_t *name = NULL; \
|
35
|
+
Data_Get_Struct(from, msgpack_unpacker_t, name); \
|
36
|
+
if(name == NULL) { \
|
37
|
+
rb_raise(rb_eArgError, "NULL found for " # name " when shouldn't be."); \
|
38
|
+
}
|
39
|
+
|
40
|
+
static void Unpacker_free(msgpack_unpacker_t* uk)
|
41
|
+
{
|
42
|
+
if(uk == NULL) {
|
43
|
+
return;
|
44
|
+
}
|
45
|
+
_msgpack_unpacker_destroy(uk);
|
46
|
+
free(uk);
|
47
|
+
}
|
48
|
+
|
49
|
+
static VALUE Unpacker_alloc(VALUE klass)
|
50
|
+
{
|
51
|
+
msgpack_unpacker_t* uk = ALLOC_N(msgpack_unpacker_t, 1);
|
52
|
+
_msgpack_unpacker_init(uk);
|
53
|
+
|
54
|
+
VALUE self = Data_Wrap_Struct(klass, msgpack_unpacker_mark, Unpacker_free, uk);
|
55
|
+
|
56
|
+
uk->buffer_ref = MessagePack_Buffer_wrap(UNPACKER_BUFFER_(uk), self);
|
57
|
+
|
58
|
+
return self;
|
59
|
+
}
|
60
|
+
|
61
|
+
static VALUE Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
62
|
+
{
|
63
|
+
VALUE io = Qnil;
|
64
|
+
VALUE options = Qnil;
|
65
|
+
|
66
|
+
if(argc == 0 || (argc == 1 && argv[0] == Qnil)) {
|
67
|
+
/* Qnil */
|
68
|
+
|
69
|
+
} else if(argc == 1) {
|
70
|
+
VALUE v = argv[0];
|
71
|
+
if(rb_type(v) == T_HASH) {
|
72
|
+
options = v;
|
73
|
+
if(rb_type(options) != T_HASH) {
|
74
|
+
rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
|
75
|
+
}
|
76
|
+
} else {
|
77
|
+
io = v;
|
78
|
+
}
|
79
|
+
|
80
|
+
} else if(argc == 2) {
|
81
|
+
io = argv[0];
|
82
|
+
options = argv[1];
|
83
|
+
if(rb_type(options) != T_HASH) {
|
84
|
+
rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
|
85
|
+
}
|
86
|
+
|
87
|
+
} else {
|
88
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..2)", argc);
|
89
|
+
}
|
90
|
+
|
91
|
+
UNPACKER(self, uk);
|
92
|
+
|
93
|
+
MessagePack_Unpacker_initialize(uk, io, options);
|
94
|
+
|
95
|
+
return self;
|
96
|
+
}
|
97
|
+
|
98
|
+
void MessagePack_Unpacker_initialize(msgpack_unpacker_t* uk, VALUE io, VALUE options)
|
99
|
+
{
|
100
|
+
MessagePack_Buffer_initialize(UNPACKER_BUFFER_(uk), io, options);
|
101
|
+
|
102
|
+
if(options != Qnil) {
|
103
|
+
VALUE v;
|
104
|
+
|
105
|
+
v = rb_hash_aref(options, ID2SYM(rb_intern("symbolize_keys")));
|
106
|
+
msgpack_unpacker_set_symbolized_keys(uk, RTEST(v));
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
static void raise_unpacker_error(int r)
|
111
|
+
{
|
112
|
+
switch(r) {
|
113
|
+
case PRIMITIVE_EOF:
|
114
|
+
rb_raise(rb_eEOFError, "end of buffer reached");
|
115
|
+
case PRIMITIVE_INVALID_BYTE:
|
116
|
+
rb_raise(eMalformedFormatError, "invalid byte");
|
117
|
+
case PRIMITIVE_STACK_TOO_DEEP:
|
118
|
+
rb_raise(eStackError, "stack level too deep");
|
119
|
+
case PRIMITIVE_UNEXPECTED_TYPE:
|
120
|
+
rb_raise(eTypeError, "unexpected type");
|
121
|
+
default:
|
122
|
+
rb_raise(eUnpackError, "logically unknown error %d", r);
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
static VALUE Unpacker_buffer(VALUE self)
|
127
|
+
{
|
128
|
+
UNPACKER(self, uk);
|
129
|
+
return uk->buffer_ref;
|
130
|
+
}
|
131
|
+
|
132
|
+
static VALUE Unpacker_read(VALUE self)
|
133
|
+
{
|
134
|
+
UNPACKER(self, uk);
|
135
|
+
|
136
|
+
int r = msgpack_unpacker_read(uk, 0);
|
137
|
+
if(r < 0) {
|
138
|
+
raise_unpacker_error(r);
|
139
|
+
}
|
140
|
+
|
141
|
+
return msgpack_unpacker_get_last_object(uk);
|
142
|
+
}
|
143
|
+
|
144
|
+
static VALUE Unpacker_skip(VALUE self)
|
145
|
+
{
|
146
|
+
UNPACKER(self, uk);
|
147
|
+
|
148
|
+
int r = msgpack_unpacker_skip(uk, 0);
|
149
|
+
if(r < 0) {
|
150
|
+
raise_unpacker_error(r);
|
151
|
+
}
|
152
|
+
|
153
|
+
return Qnil;
|
154
|
+
}
|
155
|
+
|
156
|
+
static VALUE Unpacker_skip_nil(VALUE self)
|
157
|
+
{
|
158
|
+
UNPACKER(self, uk);
|
159
|
+
|
160
|
+
int r = msgpack_unpacker_skip_nil(uk);
|
161
|
+
if(r < 0) {
|
162
|
+
raise_unpacker_error(r);
|
163
|
+
}
|
164
|
+
|
165
|
+
if(r) {
|
166
|
+
return Qtrue;
|
167
|
+
}
|
168
|
+
return Qfalse;
|
169
|
+
}
|
170
|
+
|
171
|
+
static VALUE Unpacker_read_array_header(VALUE self)
|
172
|
+
{
|
173
|
+
UNPACKER(self, uk);
|
174
|
+
|
175
|
+
uint32_t size;
|
176
|
+
int r = msgpack_unpacker_read_array_header(uk, &size);
|
177
|
+
if(r < 0) {
|
178
|
+
raise_unpacker_error(r);
|
179
|
+
}
|
180
|
+
|
181
|
+
return ULONG2NUM(size);
|
182
|
+
}
|
183
|
+
|
184
|
+
static VALUE Unpacker_read_map_header(VALUE self)
|
185
|
+
{
|
186
|
+
UNPACKER(self, uk);
|
187
|
+
|
188
|
+
uint32_t size;
|
189
|
+
int r = msgpack_unpacker_read_map_header(uk, &size);
|
190
|
+
if(r < 0) {
|
191
|
+
raise_unpacker_error((int)r);
|
192
|
+
}
|
193
|
+
|
194
|
+
return ULONG2NUM(size);
|
195
|
+
}
|
196
|
+
|
197
|
+
static VALUE Unpacker_peek_next_type(VALUE self)
|
198
|
+
{
|
199
|
+
UNPACKER(self, uk);
|
200
|
+
|
201
|
+
int r = msgpack_unpacker_peek_next_object_type(uk);
|
202
|
+
if(r < 0) {
|
203
|
+
raise_unpacker_error(r);
|
204
|
+
}
|
205
|
+
|
206
|
+
switch((enum msgpack_unpacker_object_type) r) {
|
207
|
+
case TYPE_NIL:
|
208
|
+
return rb_intern("nil");
|
209
|
+
case TYPE_BOOLEAN:
|
210
|
+
return rb_intern("boolean");
|
211
|
+
case TYPE_INTEGER:
|
212
|
+
return rb_intern("integer");
|
213
|
+
case TYPE_FLOAT:
|
214
|
+
return rb_intern("float");
|
215
|
+
case TYPE_RAW:
|
216
|
+
return rb_intern("raw");
|
217
|
+
case TYPE_ARRAY:
|
218
|
+
return rb_intern("array");
|
219
|
+
case TYPE_MAP:
|
220
|
+
return rb_intern("map");
|
221
|
+
default:
|
222
|
+
rb_raise(eUnpackError, "logically unknown type %d", r);
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
226
|
+
static VALUE Unpacker_feed(VALUE self, VALUE data)
|
227
|
+
{
|
228
|
+
UNPACKER(self, uk);
|
229
|
+
|
230
|
+
StringValue(data);
|
231
|
+
|
232
|
+
msgpack_buffer_append_string(UNPACKER_BUFFER_(uk), data);
|
233
|
+
|
234
|
+
return self;
|
235
|
+
}
|
236
|
+
|
237
|
+
static VALUE Unpacker_each_impl(VALUE self)
|
238
|
+
{
|
239
|
+
UNPACKER(self, uk);
|
240
|
+
|
241
|
+
while(true) {
|
242
|
+
int r = msgpack_unpacker_read(uk, 0);
|
243
|
+
if(r < 0) {
|
244
|
+
if(r == PRIMITIVE_EOF) {
|
245
|
+
return Qnil;
|
246
|
+
}
|
247
|
+
raise_unpacker_error(r);
|
248
|
+
}
|
249
|
+
VALUE v = msgpack_unpacker_get_last_object(uk);
|
250
|
+
#ifdef JRUBY
|
251
|
+
/* TODO JRuby's rb_yield behaves differently from Ruby 1.9.3 or Rubinius. */
|
252
|
+
if(rb_type(v) == T_ARRAY) {
|
253
|
+
v = rb_ary_new3(1, v);
|
254
|
+
}
|
255
|
+
#endif
|
256
|
+
rb_yield(v);
|
257
|
+
}
|
258
|
+
}
|
259
|
+
|
260
|
+
static VALUE Unpacker_rescue_EOFError(VALUE self)
|
261
|
+
{
|
262
|
+
UNUSED(self);
|
263
|
+
return Qnil;
|
264
|
+
}
|
265
|
+
|
266
|
+
static VALUE Unpacker_each(VALUE self)
|
267
|
+
{
|
268
|
+
UNPACKER(self, uk);
|
269
|
+
|
270
|
+
#ifdef RETURN_ENUMERATOR
|
271
|
+
RETURN_ENUMERATOR(self, 0, 0);
|
272
|
+
#endif
|
273
|
+
|
274
|
+
if(msgpack_buffer_has_io(UNPACKER_BUFFER_(uk))) {
|
275
|
+
/* rescue EOFError only if io is set */
|
276
|
+
return rb_rescue2(Unpacker_each_impl, self,
|
277
|
+
Unpacker_rescue_EOFError, self,
|
278
|
+
rb_eEOFError, NULL);
|
279
|
+
} else {
|
280
|
+
return Unpacker_each_impl(self);
|
281
|
+
}
|
282
|
+
}
|
283
|
+
|
284
|
+
static VALUE Unpacker_feed_each(VALUE self, VALUE data)
|
285
|
+
{
|
286
|
+
// TODO optimize
|
287
|
+
Unpacker_feed(self, data);
|
288
|
+
return Unpacker_each(self);
|
289
|
+
}
|
290
|
+
|
291
|
+
static VALUE Unpacker_reset(VALUE self)
|
292
|
+
{
|
293
|
+
UNPACKER(self, uk);
|
294
|
+
|
295
|
+
_msgpack_unpacker_reset(uk);
|
296
|
+
|
297
|
+
return Qnil;
|
298
|
+
}
|
299
|
+
|
300
|
+
VALUE MessagePack_unpack(int argc, VALUE* argv)
|
301
|
+
{
|
302
|
+
VALUE src;
|
303
|
+
VALUE options = Qnil;
|
304
|
+
|
305
|
+
switch(argc) {
|
306
|
+
case 2:
|
307
|
+
options = argv[1];
|
308
|
+
if(rb_type(options) != T_HASH) {
|
309
|
+
rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
|
310
|
+
}
|
311
|
+
/* pass-through */
|
312
|
+
case 1:
|
313
|
+
src = argv[0];
|
314
|
+
break;
|
315
|
+
default:
|
316
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
|
317
|
+
}
|
318
|
+
|
319
|
+
VALUE self = Unpacker_alloc(cMessagePack_Unpacker);
|
320
|
+
UNPACKER(self, uk);
|
321
|
+
//_msgpack_unpacker_reset(s_unpacker);
|
322
|
+
//msgpack_buffer_reset_io(UNPACKER_BUFFER_(s_unpacker));
|
323
|
+
|
324
|
+
/* prefer reference than copying; see MessagePack_Unpacker_module_init */
|
325
|
+
msgpack_buffer_set_write_reference_threshold(UNPACKER_BUFFER_(uk), 0);
|
326
|
+
|
327
|
+
if(rb_type(src) == T_STRING) {
|
328
|
+
MessagePack_Unpacker_initialize(uk, Qnil, options);
|
329
|
+
msgpack_buffer_append_string(UNPACKER_BUFFER_(uk), src);
|
330
|
+
} else {
|
331
|
+
MessagePack_Unpacker_initialize(uk, src, options);
|
332
|
+
}
|
333
|
+
|
334
|
+
int r = msgpack_unpacker_read(uk, 0);
|
335
|
+
if(r < 0) {
|
336
|
+
raise_unpacker_error(r);
|
337
|
+
}
|
338
|
+
|
339
|
+
/* raise if extra bytes follow */
|
340
|
+
if(msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk)) > 0) {
|
341
|
+
rb_raise(eMalformedFormatError, "extra bytes follow after a deserialized object");
|
342
|
+
}
|
343
|
+
|
344
|
+
#ifdef RB_GC_GUARD
|
345
|
+
/* This prevents compilers from optimizing out the `self` variable
|
346
|
+
* from stack. Otherwise GC free()s it. */
|
347
|
+
RB_GC_GUARD(self);
|
348
|
+
#endif
|
349
|
+
|
350
|
+
return msgpack_unpacker_get_last_object(uk);
|
351
|
+
}
|
352
|
+
|
353
|
+
static VALUE MessagePack_load_module_method(int argc, VALUE* argv, VALUE mod)
|
354
|
+
{
|
355
|
+
UNUSED(mod);
|
356
|
+
return MessagePack_unpack(argc, argv);
|
357
|
+
}
|
358
|
+
|
359
|
+
static VALUE MessagePack_unpack_module_method(int argc, VALUE* argv, VALUE mod)
|
360
|
+
{
|
361
|
+
UNUSED(mod);
|
362
|
+
return MessagePack_unpack(argc, argv);
|
363
|
+
}
|
364
|
+
|
365
|
+
void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
366
|
+
{
|
367
|
+
msgpack_unpacker_static_init();
|
368
|
+
|
369
|
+
cMessagePack_Unpacker = rb_define_class_under(mMessagePack, "Unpacker", rb_cObject);
|
370
|
+
|
371
|
+
eUnpackError = rb_define_class_under(mMessagePack, "UnpackError", rb_eStandardError);
|
372
|
+
|
373
|
+
eMalformedFormatError = rb_define_class_under(mMessagePack, "MalformedFormatError", eUnpackError);
|
374
|
+
|
375
|
+
eStackError = rb_define_class_under(mMessagePack, "StackError", eUnpackError);
|
376
|
+
|
377
|
+
eTypeError = rb_define_class_under(mMessagePack, "TypeError", rb_eStandardError);
|
378
|
+
|
379
|
+
rb_define_alloc_func(cMessagePack_Unpacker, Unpacker_alloc);
|
380
|
+
|
381
|
+
rb_define_method(cMessagePack_Unpacker, "initialize", Unpacker_initialize, -1);
|
382
|
+
rb_define_method(cMessagePack_Unpacker, "buffer", Unpacker_buffer, 0);
|
383
|
+
rb_define_method(cMessagePack_Unpacker, "read", Unpacker_read, 0);
|
384
|
+
rb_define_alias(cMessagePack_Unpacker, "unpack", "read");
|
385
|
+
rb_define_method(cMessagePack_Unpacker, "skip", Unpacker_skip, 0);
|
386
|
+
rb_define_method(cMessagePack_Unpacker, "skip_nil", Unpacker_skip_nil, 0);
|
387
|
+
rb_define_method(cMessagePack_Unpacker, "read_array_header", Unpacker_read_array_header, 0);
|
388
|
+
rb_define_method(cMessagePack_Unpacker, "read_map_header", Unpacker_read_map_header, 0);
|
389
|
+
//rb_define_method(cMessagePack_Unpacker, "peek_next_type", Unpacker_peek_next_type, 0); // TODO
|
390
|
+
rb_define_method(cMessagePack_Unpacker, "feed", Unpacker_feed, 1);
|
391
|
+
rb_define_method(cMessagePack_Unpacker, "each", Unpacker_each, 0);
|
392
|
+
rb_define_method(cMessagePack_Unpacker, "feed_each", Unpacker_feed_each, 1);
|
393
|
+
rb_define_method(cMessagePack_Unpacker, "reset", Unpacker_reset, 0);
|
394
|
+
|
395
|
+
//s_unpacker_value = Unpacker_alloc(cMessagePack_Unpacker);
|
396
|
+
//rb_gc_register_address(&s_unpacker_value);
|
397
|
+
//Data_Get_Struct(s_unpacker_value, msgpack_unpacker_t, s_unpacker);
|
398
|
+
/* prefer reference than copying */
|
399
|
+
//msgpack_buffer_set_write_reference_threshold(UNPACKER_BUFFER_(s_unpacker), 0);
|
400
|
+
|
401
|
+
/* MessagePack.unpack(x) */
|
402
|
+
rb_define_module_function(mMessagePack, "load", MessagePack_load_module_method, -1);
|
403
|
+
rb_define_module_function(mMessagePack, "unpack", MessagePack_unpack_module_method, -1);
|
404
|
+
}
|
405
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
/*
|
2
|
+
* MessagePack for Ruby
|
3
|
+
*
|
4
|
+
* Copyright (C) 2008-2013 Sadayuki Furuhashi
|
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 MSGPACK_RUBY_UNPACKER_CLASS_H__
|
19
|
+
#define MSGPACK_RUBY_UNPACKER_CLASS_H__
|
20
|
+
|
21
|
+
#include "unpacker.h"
|
22
|
+
|
23
|
+
extern VALUE cMessagePack_Unpacker;
|
24
|
+
|
25
|
+
void MessagePack_Unpacker_module_init(VALUE mMessagePack);
|
26
|
+
|
27
|
+
VALUE MessagePack_unpack(int argc, VALUE* argv);
|
28
|
+
|
29
|
+
void MessagePack_Unpacker_initialize(msgpack_unpacker_t* uk, VALUE io, VALUE options);
|
30
|
+
|
31
|
+
#endif
|
32
|
+
|
Binary file
|
data/lib/msgpack.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "msgpack/version"
|
2
|
+
|
3
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby" # This is same with `/java/ =~ RUBY_VERSION`
|
4
|
+
require "java"
|
5
|
+
require "msgpack/msgpack.jar"
|
6
|
+
org.msgpack.jruby.MessagePackLibrary.new.load(JRuby.runtime, false)
|
7
|
+
else
|
8
|
+
begin
|
9
|
+
require "msgpack/#{RUBY_VERSION[/\d+.\d+/]}/msgpack"
|
10
|
+
rescue LoadError
|
11
|
+
require "msgpack/msgpack"
|
12
|
+
end
|
13
|
+
end
|
data/msgpack.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
$LOAD_PATH.push File.expand_path("../lib", __FILE__)
|
2
|
+
require 'msgpack/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "msgpack"
|
6
|
+
s.version = MessagePack::VERSION
|
7
|
+
s.summary = "MessagePack, a binary-based efficient data interchange format."
|
8
|
+
s.description = %q{MessagePack is a binary-based efficient object serialization library. It enables to exchange structured objects between many languages like JSON. But unlike JSON, it is very fast and small.}
|
9
|
+
s.authors = ["Sadayuki Furuhashi", "Theo Hultberg"]
|
10
|
+
s.email = ["frsyuki@gmail.com", "theo@iconara.net"]
|
11
|
+
s.license = "Apache 2.0"
|
12
|
+
s.homepage = "http://msgpack.org/"
|
13
|
+
s.rubyforge_project = "msgpack"
|
14
|
+
s.has_rdoc = false
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
if /java/ =~ RUBY_PLATFORM
|
17
|
+
s.files = Dir['lib/**/*.rb', 'lib/**/*.jar']
|
18
|
+
s.platform = Gem::Platform.new('java')
|
19
|
+
else
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.extensions = ["ext/msgpack/extconf.rb"]
|
22
|
+
end
|
23
|
+
s.test_files = `git ls-files -- {test,spec}/*`.split("\n")
|
24
|
+
|
25
|
+
s.add_development_dependency 'bundler', ['~> 1.0']
|
26
|
+
s.add_development_dependency 'rake', ['~> 0.9.2']
|
27
|
+
s.add_development_dependency 'rake-compiler', ['~> 0.8.3']
|
28
|
+
s.add_development_dependency 'rspec', ['~> 2.11']
|
29
|
+
s.add_development_dependency 'json', ['~> 1.7']
|
30
|
+
s.add_development_dependency 'yard', ['~> 0.8.2']
|
31
|
+
end
|
data/msgpack.org.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# MessagePack for Ruby
|
2
|
+
|
3
|
+
```
|
4
|
+
require 'msgpack'
|
5
|
+
msg = [1,2,3].to_msgpack #=> "\x93\x01\x02\x03"
|
6
|
+
MessagePack.unpack(msg) #=> [1,2,3]
|
7
|
+
```
|
8
|
+
|
9
|
+
## Install
|
10
|
+
|
11
|
+
```
|
12
|
+
gem install msgpack
|
13
|
+
```
|
14
|
+
|
15
|
+
## Use cases
|
16
|
+
|
17
|
+
* Create REST API returing MessagePack using Rails + [RABL](https://github.com/nesquena/rabl)
|
18
|
+
* Store objects efficiently in memcached or Redis
|
19
|
+
* Upload data in efficient format from mobile devices. See also MessagePack for [Objective-C](https://github.com/msgpack/msgpack-objectivec) and [Java](https://github.com/msgpack/msgpack-java)
|
20
|
+
|
21
|
+
## Links
|
22
|
+
|
23
|
+
* [Github](https://github.com/msgpack/msgpack-ruby)
|
24
|
+
* [API document](http://ruby.msgpack.org/)
|
25
|
+
|
26
|
+
## Streaming API
|
27
|
+
|
28
|
+
```
|
29
|
+
# serialize a 2-element array [e1, e2]
|
30
|
+
pk = MessagePack::Packer.new(io)
|
31
|
+
pk.write_array_header(2).write(e1).write(e2).flush
|
32
|
+
```
|
33
|
+
|
34
|
+
```
|
35
|
+
# deserialize objects from an IO
|
36
|
+
u = MessagePack::Unpacker.new(io)
|
37
|
+
u.each { |obj| ... }
|
38
|
+
```
|
39
|
+
|
40
|
+
```
|
41
|
+
# event-driven deserialization
|
42
|
+
def on_read(data)
|
43
|
+
@u ||= MessagePack::Unpacker.new
|
44
|
+
@u.feed_each(data) { |obj| ... }
|
45
|
+
end
|
46
|
+
```
|
data/spec/cases.json
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
[false,true,null,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,127,127,255,65535,4294967295,-32,-32,-128,-32768,-2147483648,0.0,-0.0,1.0,-1.0,"a","a","a","","","",[0],[0],[0],[],[],[],{},{},{},{"a":97},{"a":97},{"a":97},[[]],[["a"]]]
|
data/spec/cases.msg
ADDED
Binary file
|
Binary file
|
data/spec/cases_spec.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
describe MessagePack do
|
5
|
+
here = File.dirname(__FILE__)
|
6
|
+
CASES = File.read("#{here}/cases.msg")
|
7
|
+
CASES_JSON = File.read("#{here}/cases.json")
|
8
|
+
CASES_COMPACT = File.read("#{here}/cases_compact.msg")
|
9
|
+
|
10
|
+
it 'compare with json' do
|
11
|
+
ms = []
|
12
|
+
MessagePack::Unpacker.new.feed_each(CASES) {|m|
|
13
|
+
ms << m
|
14
|
+
}
|
15
|
+
|
16
|
+
js = JSON.load(CASES_JSON)
|
17
|
+
|
18
|
+
ms.zip(js) {|m,j|
|
19
|
+
m.should == j
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'compare with compat' do
|
24
|
+
ms = []
|
25
|
+
MessagePack::Unpacker.new.feed_each(CASES) {|m|
|
26
|
+
ms << m
|
27
|
+
}
|
28
|
+
|
29
|
+
cs = []
|
30
|
+
MessagePack::Unpacker.new.feed_each(CASES_COMPACT) {|c|
|
31
|
+
cs << c
|
32
|
+
}
|
33
|
+
|
34
|
+
ms.zip(cs) {|m,c|
|
35
|
+
m.should == c
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|