packsnap 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.gitignore +17 -0
  2. data/ChangeLog +29 -0
  3. data/README.rdoc +26 -0
  4. data/Rakefile +150 -0
  5. data/doclib/msgpack.rb +54 -0
  6. data/doclib/packsnap/buffer.rb +177 -0
  7. data/doclib/packsnap/error.rb +14 -0
  8. data/doclib/packsnap/packer.rb +131 -0
  9. data/doclib/packsnap/unpacker.rb +130 -0
  10. data/ext/packsnap/buffer.cc +684 -0
  11. data/ext/packsnap/buffer.hh +439 -0
  12. data/ext/packsnap/buffer_class.cc +490 -0
  13. data/ext/packsnap/buffer_class.hh +32 -0
  14. data/ext/packsnap/compat.h +128 -0
  15. data/ext/packsnap/extconf.rb +94 -0
  16. data/ext/packsnap/packer.cc +137 -0
  17. data/ext/packsnap/packer.h +334 -0
  18. data/ext/packsnap/packer_class.cc +288 -0
  19. data/ext/packsnap/packer_class.hh +32 -0
  20. data/ext/packsnap/packsnap.h +4 -0
  21. data/ext/packsnap/rbinit.cc +52 -0
  22. data/ext/packsnap/rmem.cc +110 -0
  23. data/ext/packsnap/rmem.h +100 -0
  24. data/ext/packsnap/sysdep.h +112 -0
  25. data/ext/packsnap/sysdep_endian.h +50 -0
  26. data/ext/packsnap/sysdep_types.h +46 -0
  27. data/ext/packsnap/unpacker.cc +654 -0
  28. data/ext/packsnap/unpacker.hh +108 -0
  29. data/ext/packsnap/unpacker_class.cc +392 -0
  30. data/ext/packsnap/unpacker_class.hh +32 -0
  31. data/lib/packsnap.rb +12 -0
  32. data/lib/packsnap/version.rb +3 -0
  33. data/packsnap.gemspec +23 -0
  34. data/spec/buffer_io_spec.rb +228 -0
  35. data/spec/buffer_spec.rb +572 -0
  36. data/spec/cases.json +1 -0
  37. data/spec/cases.msg +0 -0
  38. data/spec/cases_compact.msg +0 -0
  39. data/spec/cases_spec.rb +39 -0
  40. data/spec/format_spec.rb +225 -0
  41. data/spec/packer_spec.rb +127 -0
  42. data/spec/random_compat.rb +24 -0
  43. data/spec/spec_helper.rb +21 -0
  44. data/spec/unpacker_spec.rb +128 -0
  45. metadata +183 -0
@@ -0,0 +1,100 @@
1
+ /*
2
+ * MessagePack for Ruby
3
+ *
4
+ * Copyright (C) 2008-2012 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 MSGPACK_RUBY_RMEM_H__
19
+ #define MSGPACK_RUBY_RMEM_H__
20
+
21
+ #include "compat.h"
22
+ #include "sysdep.h"
23
+
24
+ #ifndef MSGPACK_RMEM_PAGE_SIZE
25
+ #define MSGPACK_RMEM_PAGE_SIZE (4*1024)
26
+ #endif
27
+
28
+ struct msgpack_rmem_t;
29
+ typedef struct msgpack_rmem_t msgpack_rmem_t;
30
+
31
+ struct msgpack_rmem_chunk_t;
32
+ typedef struct msgpack_rmem_chunk_t msgpack_rmem_chunk_t;
33
+
34
+ /*
35
+ * a chunk contains 32 pages.
36
+ * size of each buffer is MSGPACK_RMEM_PAGE_SIZE bytes.
37
+ */
38
+ struct msgpack_rmem_chunk_t {
39
+ unsigned int mask;
40
+ char* pages;
41
+ };
42
+
43
+ struct msgpack_rmem_t {
44
+ msgpack_rmem_chunk_t head;
45
+ msgpack_rmem_chunk_t* array_first;
46
+ msgpack_rmem_chunk_t* array_last;
47
+ msgpack_rmem_chunk_t* array_end;
48
+ };
49
+
50
+ /* assert MSGPACK_RMEM_PAGE_SIZE % sysconf(_SC_PAGE_SIZE) == 0 */
51
+ void msgpack_rmem_init(msgpack_rmem_t* pm);
52
+
53
+ void msgpack_rmem_destroy(msgpack_rmem_t* pm);
54
+
55
+ void* _msgpack_rmem_alloc2(msgpack_rmem_t* pm);
56
+
57
+ #define _msgpack_rmem_chunk_available(c) ((c)->mask != 0)
58
+
59
+ static inline void* _msgpack_rmem_chunk_alloc(msgpack_rmem_chunk_t* c)
60
+ {
61
+ _msgpack_bsp32(pos, c->mask);
62
+ (c)->mask &= ~(1 << pos);
63
+ return ((char*)(c)->pages) + (pos * (MSGPACK_RMEM_PAGE_SIZE));
64
+ }
65
+
66
+ static inline bool _msgpack_rmem_chunk_try_free(msgpack_rmem_chunk_t* c, void* mem)
67
+ {
68
+ ptrdiff_t pdiff = ((char*)(mem)) - ((char*)(c)->pages);
69
+ if(0 <= pdiff && pdiff < MSGPACK_RMEM_PAGE_SIZE * 32) {
70
+ size_t pos = pdiff / MSGPACK_RMEM_PAGE_SIZE;
71
+ (c)->mask |= (1 << pos);
72
+ return true;
73
+ }
74
+ return false;
75
+ }
76
+
77
+ static inline void* msgpack_rmem_alloc(msgpack_rmem_t* pm)
78
+ {
79
+ if(_msgpack_rmem_chunk_available(&pm->head)) {
80
+ return _msgpack_rmem_chunk_alloc(&pm->head);
81
+ }
82
+ return _msgpack_rmem_alloc2(pm);
83
+ }
84
+
85
+ bool _msgpack_rmem_free2(msgpack_rmem_t* pm, void* mem);
86
+
87
+ static inline bool msgpack_rmem_free(msgpack_rmem_t* pm, void* mem)
88
+ {
89
+ if(_msgpack_rmem_chunk_try_free(&pm->head, mem)) {
90
+ return true;
91
+ }
92
+ if(pm->array_last == pm->array_end) {
93
+ return false;
94
+ }
95
+ return _msgpack_rmem_free2(pm, mem);
96
+ }
97
+
98
+
99
+ #endif
100
+
@@ -0,0 +1,112 @@
1
+ /*
2
+ * MessagePack for Ruby
3
+ *
4
+ * Copyright (C) 2008-2012 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 MSGPACK_RUBY_SYSDEP_H__
19
+ #define MSGPACK_RUBY_SYSDEP_H__
20
+
21
+ #include "sysdep_types.h"
22
+ #include "sysdep_endian.h"
23
+
24
+
25
+ #define UNUSED(var) ((void)var)
26
+
27
+
28
+ #ifdef __LITTLE_ENDIAN__
29
+
30
+ /* _msgpack_be16 */
31
+ #ifdef _WIN32
32
+ # if defined(ntohs)
33
+ # define _msgpack_be16(x) ntohs(x)
34
+ # elif defined(_byteswap_ushort) || (defined(_MSC_VER) && _MSC_VER >= 1400)
35
+ # define _msgpack_be16(x) ((uint16_t)_byteswap_ushort((unsigned short)x))
36
+ # else
37
+ # define _msgpack_be16(x) ( \
38
+ ((((uint16_t)x) << 8) ) | \
39
+ ((((uint16_t)x) >> 8) ) )
40
+ # endif
41
+ #else
42
+ # define _msgpack_be16(x) ntohs(x)
43
+ #endif
44
+
45
+ /* _msgpack_be32 */
46
+ #ifdef _WIN32
47
+ # if defined(ntohl)
48
+ # define _msgpack_be32(x) ntohl(x)
49
+ # elif defined(_byteswap_ulong) || (defined(_MSC_VER) && _MSC_VER >= 1400)
50
+ # define _msgpack_be32(x) ((uint32_t)_byteswap_ulong((unsigned long)x))
51
+ # else
52
+ # define _msgpack_be32(x) \
53
+ ( ((((uint32_t)x) << 24) ) | \
54
+ ((((uint32_t)x) << 8) & 0x00ff0000U ) | \
55
+ ((((uint32_t)x) >> 8) & 0x0000ff00U ) | \
56
+ ((((uint32_t)x) >> 24) ) )
57
+ # endif
58
+ #else
59
+ # define _msgpack_be32(x) ntohl(x)
60
+ #endif
61
+
62
+ /* _msgpack_be64 */
63
+ #if defined(_byteswap_uint64) || (defined(_MSC_VER) && _MSC_VER >= 1400)
64
+ # define _msgpack_be64(x) (_byteswap_uint64(x))
65
+ #elif defined(bswap_64)
66
+ # define _msgpack_be64(x) bswap_64(x)
67
+ #elif defined(__DARWIN_OSSwapInt64)
68
+ # define _msgpack_be64(x) __DARWIN_OSSwapInt64(x)
69
+ #else
70
+ #define _msgpack_be64(x) \
71
+ ( ((((uint64_t)x) << 56) ) | \
72
+ ((((uint64_t)x) << 40) & 0x00ff000000000000ULL ) | \
73
+ ((((uint64_t)x) << 24) & 0x0000ff0000000000ULL ) | \
74
+ ((((uint64_t)x) << 8) & 0x000000ff00000000ULL ) | \
75
+ ((((uint64_t)x) >> 8) & 0x00000000ff000000ULL ) | \
76
+ ((((uint64_t)x) >> 24) & 0x0000000000ff0000ULL ) | \
77
+ ((((uint64_t)x) >> 40) & 0x000000000000ff00ULL ) | \
78
+ ((((uint64_t)x) >> 56) ) )
79
+ #endif
80
+
81
+ #else /* big endian */
82
+ #define _msgpack_be16(x) (x)
83
+ #define _msgpack_be32(x) (x)
84
+ #define _msgpack_be64(x) (x)
85
+
86
+ #endif
87
+
88
+
89
+ #define _msgpack_be_float(x) _msgpack_be32(x)
90
+
91
+ #if defined(__arm__) && !(__ARM_EABI__)
92
+ /* ARM OABI */
93
+ #define _msgpack_be_double(x) \
94
+ ( (((x) & 0xFFFFFFFFUL) << 32UL) | ((x) >> 32UL) )
95
+ #else
96
+ #define _msgpack_be_double(x) _msgpack_be64(x)
97
+ #endif
98
+
99
+ /* _msgpack_bsp32 */
100
+ #if defined(_MSC_VER)
101
+ #define _msgpack_bsp32(name, val) \
102
+ long name; \
103
+ _BitScanForward(&name, val)
104
+ #else
105
+ #define _msgpack_bsp32(name, val) \
106
+ int name = __builtin_ctz(val)
107
+ /* TODO default impl */
108
+ #endif
109
+
110
+
111
+ #endif
112
+
@@ -0,0 +1,50 @@
1
+ /*
2
+ * MessagePack for Ruby
3
+ *
4
+ * Copyright (C) 2008-2012 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 MSGPACK_RUBY_SYSDEP_ENDIAN_H__
19
+ #define MSGPACK_RUBY_SYSDEP_ENDIAN_H__
20
+
21
+ /* including arpa/inet.h requires an extra dll on win32 */
22
+ #ifndef _WIN32
23
+ #include <arpa/inet.h> /* __BYTE_ORDER */
24
+ #endif
25
+
26
+ /*
27
+ * Use following command to add consitions here:
28
+ * cpp -dM `echo "#include <arpa/inet.h>" > test.c; echo test.c` | grep ENDIAN
29
+ */
30
+ #if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) /* Mac OS X */
31
+ # if defined(_LITTLE_ENDIAN) \
32
+ || ( defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) \
33
+ && __BYTE_ORDER == __LITTLE_ENDIAN ) /* Linux */ \
34
+ || ( defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) \
35
+ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) /* Solaris */
36
+ # define __LITTLE_ENDIAN__
37
+ # elif defined(_BIG_ENDIAN) \
38
+ || (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) \
39
+ && __BYTE_ORDER == __BIG_ENDIAN) /* Linux */ \
40
+ || (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) \
41
+ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) /* Solaris */
42
+ # define __BIG_ENDIAN__
43
+ # elif defined(_WIN32) /* Win32 */
44
+ # define __LITTLE_ENDIAN__
45
+ # endif
46
+ #endif
47
+
48
+
49
+ #endif
50
+
@@ -0,0 +1,46 @@
1
+ /*
2
+ * MessagePack for Ruby
3
+ *
4
+ * Copyright (C) 2008-2012 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 MSGPACK_RUBY_SYSDEP_TYPES_H__
19
+ #define MSGPACK_RUBY_SYSDEP_TYPES_H__
20
+
21
+ #include <string.h>
22
+ #include <stdlib.h>
23
+
24
+ #include <stddef.h>
25
+
26
+ #if defined(_MSC_VER) && _MSC_VER < 1600
27
+ typedef __int8 int8_t;
28
+ typedef unsigned __int8 uint8_t;
29
+ typedef __int16 int16_t;
30
+ typedef unsigned __int16 uint16_t;
31
+ typedef __int32 int32_t;
32
+ typedef unsigned __int32 uint32_t;
33
+ typedef __int64 int64_t;
34
+ typedef unsigned __int64 uint64_t;
35
+
36
+ #elif defined(_MSC_VER) // && _MSC_VER >= 1600
37
+ #include <stdint.h>
38
+
39
+ #else
40
+ #include <stdint.h>
41
+ #include <stdbool.h>
42
+ #endif
43
+
44
+
45
+ #endif
46
+
@@ -0,0 +1,654 @@
1
+ /*
2
+ * MessagePack for Ruby
3
+ *
4
+ * Copyright (C) 2008-2012 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
+
19
+ #include "unpacker.hh"
20
+
21
+ #define HEAD_BYTE_REQUIRED 0xc6
22
+
23
+ void msgpack_unpacker_init(msgpack_unpacker_t* uk)
24
+ {
25
+ memset(uk, 0, sizeof(msgpack_unpacker_t));
26
+
27
+ msgpack_buffer_init(UNPACKER_BUFFER_(uk));
28
+
29
+ uk->head_byte = HEAD_BYTE_REQUIRED;
30
+
31
+ uk->last_object = Qnil;
32
+ uk->reading_raw = Qnil;
33
+
34
+ uk->stack = (msgpack_unpacker_stack_t*)calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_t));
35
+ uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
36
+ }
37
+
38
+ void msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
39
+ {
40
+ free(uk->stack);
41
+ msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
42
+ }
43
+
44
+ void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
45
+ {
46
+ rb_gc_mark(uk->last_object);
47
+ rb_gc_mark(uk->reading_raw);
48
+
49
+ msgpack_unpacker_stack_t* s = uk->stack;
50
+ msgpack_unpacker_stack_t* send = uk->stack + uk->stack_depth;
51
+ for(; s < send; s++) {
52
+ rb_gc_mark(s->object);
53
+ rb_gc_mark(s->key);
54
+ }
55
+
56
+ /* See MessagePack_Buffer_wrap */
57
+ /* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
58
+ rb_gc_mark(uk->buffer_ref);
59
+ }
60
+
61
+ void msgpack_unpacker_reset(msgpack_unpacker_t* uk)
62
+ {
63
+ msgpack_buffer_clear(UNPACKER_BUFFER_(uk));
64
+
65
+ uk->head_byte = HEAD_BYTE_REQUIRED;
66
+
67
+ memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack_depth);
68
+ uk->stack_depth = 0;
69
+
70
+ uk->last_object = Qnil;
71
+ uk->reading_raw = Qnil;
72
+ uk->reading_raw_remaining = 0;
73
+ uk->buffer_ref = Qnil;
74
+ }
75
+
76
+
77
+ /* head byte functions */
78
+ static int read_head_byte(msgpack_unpacker_t* uk)
79
+ {
80
+ //printf("%lu\n", msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk)));
81
+ int r = msgpack_buffer_read_1(UNPACKER_BUFFER_(uk));
82
+ if(r == -1) {
83
+ return PRIMITIVE_EOF;
84
+ }
85
+ return uk->head_byte = r;
86
+ }
87
+
88
+ static inline int get_head_byte(msgpack_unpacker_t* uk)
89
+ {
90
+ int b = uk->head_byte;
91
+ if(b == HEAD_BYTE_REQUIRED) {
92
+ b = read_head_byte(uk);
93
+ }
94
+ return b;
95
+ }
96
+
97
+ static inline void reset_head_byte(msgpack_unpacker_t* uk)
98
+ {
99
+ uk->head_byte = HEAD_BYTE_REQUIRED;
100
+ }
101
+
102
+ static inline int object_complete(msgpack_unpacker_t* uk, VALUE object)
103
+ {
104
+ uk->last_object = object;
105
+ reset_head_byte(uk);
106
+ return PRIMITIVE_OBJECT_COMPLETE;
107
+ }
108
+
109
+ /* stack funcs */
110
+ static inline msgpack_unpacker_stack_t* _msgpack_unpacker_stack_top(msgpack_unpacker_t* uk)
111
+ {
112
+ return &uk->stack[uk->stack_depth-1];
113
+ }
114
+
115
+ static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
116
+ {
117
+ reset_head_byte(uk);
118
+
119
+ if(uk->stack_capacity - uk->stack_depth <= 0) {
120
+ return PRIMITIVE_STACK_TOO_DEEP;
121
+ }
122
+
123
+ msgpack_unpacker_stack_t* next = &uk->stack[uk->stack_depth];
124
+ next->count = count;
125
+ next->type = type;
126
+ next->object = object;
127
+ next->key = Qnil;
128
+
129
+ //printf("push count: %d depth:%d type:%d\n", count, uk->stack_depth, type);
130
+ uk->stack_depth++;
131
+ return PRIMITIVE_CONTAINER_START;
132
+ }
133
+
134
+ static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
135
+ {
136
+ return --uk->stack_depth;
137
+ }
138
+
139
+ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
140
+ {
141
+ return uk->stack_depth == 0;
142
+ }
143
+
144
+ #ifdef USE_CASE_RANGE
145
+
146
+ #define SWITCH_RANGE_BEGIN(BYTE) { switch(BYTE) {
147
+ #define SWITCH_RANGE(BYTE, FROM, TO) } case FROM ... TO: {
148
+ #define SWITCH_RANGE_DEFAULT } default: {
149
+ #define SWITCH_RANGE_END } }
150
+
151
+ #else
152
+
153
+ #define SWITCH_RANGE_BEGIN(BYTE) { if(0) {
154
+ #define SWITCH_RANGE(BYTE, FROM, TO) } else if(FROM <= (BYTE) && (BYTE) <= TO) {
155
+ #define SWITCH_RANGE_DEFAULT } else {
156
+ #define SWITCH_RANGE_END } }
157
+
158
+ #endif
159
+
160
+
161
+ #define READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, n) \
162
+ union msgpack_buffer_cast_block_t* cb = msgpack_buffer_read_cast_block(UNPACKER_BUFFER_(uk), n); \
163
+ if(cb == NULL) { \
164
+ return PRIMITIVE_EOF; \
165
+ }
166
+
167
+ static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
168
+ {
169
+ if(uk->stack_depth > 0) {
170
+ msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
171
+ if(top->type == STACK_TYPE_MAP_KEY) {
172
+ return true;
173
+ }
174
+ }
175
+ return false;
176
+ }
177
+
178
+ static int read_raw_body_cont(msgpack_unpacker_t* uk)
179
+ {
180
+ size_t length = uk->reading_raw_remaining;
181
+
182
+ if(uk->reading_raw == Qnil) {
183
+ uk->reading_raw = rb_str_buf_new(length);
184
+ }
185
+
186
+ do {
187
+ size_t n = msgpack_buffer_read_to_string(UNPACKER_BUFFER_(uk), uk->reading_raw, length);
188
+ if(n == 0) {
189
+ return PRIMITIVE_EOF;
190
+ }
191
+ /* update reading_raw_remaining everytime because
192
+ * msgpack_buffer_read_to_string raises IOError */
193
+ uk->reading_raw_remaining = length = length - n;
194
+ } while(length > 0);
195
+
196
+ object_complete(uk, uk->reading_raw);
197
+ uk->reading_raw = Qnil;
198
+ return PRIMITIVE_OBJECT_COMPLETE;
199
+ }
200
+
201
+ static inline int read_raw_body_begin(msgpack_unpacker_t* uk)
202
+ {
203
+ /* assuming uk->reading_raw == Qnil */
204
+
205
+ /* try optimized read */
206
+ size_t length = uk->reading_raw_remaining;
207
+ if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
208
+ /* don't use zerocopy for hash keys because
209
+ * rb_hash_aset freezes keys and causes copying */
210
+ bool suppress_reference = is_reading_map_key(uk);
211
+ VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, suppress_reference);
212
+ object_complete(uk, string);
213
+ uk->reading_raw_remaining = 0;
214
+ return PRIMITIVE_OBJECT_COMPLETE;
215
+ }
216
+
217
+ return read_raw_body_cont(uk);
218
+ }
219
+
220
+ static int read_primitive(msgpack_unpacker_t* uk)
221
+ {
222
+ if(uk->reading_raw_remaining > 0) {
223
+ return read_raw_body_cont(uk);
224
+ }
225
+
226
+ int b = get_head_byte(uk);
227
+ if(b < 0) {
228
+ return b;
229
+ }
230
+
231
+ SWITCH_RANGE_BEGIN(b)
232
+ SWITCH_RANGE(b, 0x00, 0x7f) // Positive Fixnum
233
+ return object_complete(uk, INT2FIX(b));
234
+
235
+ SWITCH_RANGE(b, 0xe0, 0xff) // Negative Fixnum
236
+ return object_complete(uk, INT2FIX((int8_t)b));
237
+
238
+ SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw
239
+ int count = b & 0x1f;
240
+ if(count == 0) {
241
+ return object_complete(uk, rb_str_buf_new(0));
242
+ }
243
+ //uk->reading_raw = rb_str_buf_new(count);
244
+ uk->reading_raw_remaining = count;
245
+ return read_raw_body_begin(uk);
246
+
247
+ SWITCH_RANGE(b, 0x90, 0x9f) // FixArray
248
+ int count = b & 0x0f;
249
+ if(count == 0) {
250
+ return object_complete(uk, rb_ary_new());
251
+ }
252
+ //printf("fix array %d\n", count);
253
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
254
+
255
+ SWITCH_RANGE(b, 0x80, 0x8f) // FixMap
256
+ int count = b & 0x0f;
257
+ if(count == 0) {
258
+ return object_complete(uk, rb_hash_new());
259
+ }
260
+ //printf("fix map %d %x\n", count, b);
261
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
262
+
263
+ SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
264
+ switch(b) {
265
+ case 0xc0: // nil
266
+ return object_complete(uk, Qnil);
267
+
268
+ //case 0xc1: // string
269
+
270
+ case 0xc2: // false
271
+ return object_complete(uk, Qfalse);
272
+
273
+ case 0xc3: // true
274
+ return object_complete(uk, Qtrue);
275
+
276
+ //case 0xc4:
277
+ //case 0xc5:
278
+ //case 0xc6:
279
+ //case 0xc7:
280
+ //case 0xc8:
281
+ //case 0xc9:
282
+
283
+ case 0xca: // float
284
+ {
285
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
286
+ cb->u32 = _msgpack_be_float(cb->u32);
287
+ return object_complete(uk, rb_float_new(cb->f));
288
+ }
289
+
290
+ case 0xcb: // double
291
+ {
292
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
293
+ cb->u64 = _msgpack_be_double(cb->u64);
294
+ return object_complete(uk, rb_float_new(cb->d));
295
+ }
296
+
297
+ //int n = 1 << (((unsigned int)*p) & 0x03)
298
+ case 0xcc: // unsigned int 8
299
+ {
300
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
301
+ uint8_t u8 = cb->u8;
302
+ return object_complete(uk, INT2FIX((int)u8));
303
+ }
304
+
305
+ case 0xcd: // unsigned int 16
306
+ {
307
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
308
+ uint16_t u16 = _msgpack_be16(cb->u16);
309
+ return object_complete(uk, INT2FIX((int)u16));
310
+ }
311
+
312
+ case 0xce: // unsigned int 32
313
+ {
314
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
315
+ uint32_t u32 = _msgpack_be32(cb->u32);
316
+ return object_complete(uk, ULONG2NUM((unsigned long)u32));
317
+ }
318
+
319
+ case 0xcf: // unsigned int 64
320
+ {
321
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
322
+ uint64_t u64 = _msgpack_be64(cb->u64);
323
+ return object_complete(uk, rb_ull2inum(u64));
324
+ }
325
+
326
+ case 0xd0: // signed int 8
327
+ {
328
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
329
+ int8_t i8 = cb->i8;
330
+ return object_complete(uk, INT2FIX((int)i8));
331
+ }
332
+
333
+ case 0xd1: // signed int 16
334
+ {
335
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
336
+ int16_t i16 = _msgpack_be16(cb->i16);
337
+ return object_complete(uk, INT2FIX((int)i16));
338
+ }
339
+
340
+ case 0xd2: // signed int 32
341
+ {
342
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
343
+ int32_t i32 = _msgpack_be32(cb->i32);
344
+ return object_complete(uk, LONG2FIX((long)i32));
345
+ }
346
+
347
+ case 0xd3: // signed int 64
348
+ {
349
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
350
+ int64_t i64 = _msgpack_be64(cb->i64);
351
+ return object_complete(uk, rb_ll2inum(i64));
352
+ }
353
+
354
+ //case 0xd4:
355
+ //case 0xd5:
356
+ //case 0xd6: // big integer 16
357
+ //case 0xd7: // big integer 32
358
+ //case 0xd8: // big float 16
359
+ //case 0xd9: // big float 32
360
+
361
+ //int n = 2 << (((unsigned int)*p) & 0x01);
362
+ case 0xda: // raw 16
363
+ {
364
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
365
+ uint16_t count = _msgpack_be16(cb->u16);
366
+ if(count == 0) {
367
+ return object_complete(uk, rb_str_buf_new(0));
368
+ }
369
+ //uk->reading_raw = rb_str_buf_new(count);
370
+ uk->reading_raw_remaining = count;
371
+ return read_raw_body_begin(uk);
372
+ }
373
+
374
+ case 0xdb: // raw 32
375
+ {
376
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
377
+ uint32_t count = _msgpack_be32(cb->u32);
378
+ if(count == 0) {
379
+ return object_complete(uk, rb_str_buf_new(0));
380
+ }
381
+ //uk->reading_raw = rb_str_buf_new(count);
382
+ uk->reading_raw_remaining = count;
383
+ return read_raw_body_begin(uk);
384
+ }
385
+
386
+ case 0xdc: // array 16
387
+ {
388
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
389
+ uint16_t count = _msgpack_be16(cb->u16);
390
+ if(count == 0) {
391
+ return object_complete(uk, rb_ary_new());
392
+ }
393
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
394
+ }
395
+
396
+ case 0xdd: // array 32
397
+ {
398
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
399
+ uint32_t count = _msgpack_be32(cb->u32);
400
+ if(count == 0) {
401
+ return object_complete(uk, rb_ary_new());
402
+ }
403
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
404
+ }
405
+
406
+ case 0xde: // map 16
407
+ {
408
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
409
+ uint16_t count = _msgpack_be16(cb->u16);
410
+ if(count == 0) {
411
+ return object_complete(uk, rb_hash_new());
412
+ }
413
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
414
+ }
415
+
416
+ case 0xdf: // map 32
417
+ {
418
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
419
+ uint32_t count = _msgpack_be32(cb->u32);
420
+ if(count == 0) {
421
+ return object_complete(uk, rb_hash_new());
422
+ }
423
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
424
+ }
425
+
426
+ default:
427
+ //printf("invalid byte: %x\n", b);
428
+ return PRIMITIVE_INVALID_BYTE;
429
+ }
430
+
431
+ SWITCH_RANGE_DEFAULT
432
+ //printf("invalid byte: %x\n", b);
433
+ return PRIMITIVE_INVALID_BYTE;
434
+
435
+ SWITCH_RANGE_END
436
+ }
437
+
438
+ int msgpack_unpacker_read_array_header(msgpack_unpacker_t* uk, uint32_t* result_size)
439
+ {
440
+ int b = get_head_byte(uk);
441
+ if(b < 0) {
442
+ return b;
443
+ }
444
+
445
+ if(0x90 < b && b < 0x9f) {
446
+ *result_size = b & 0x0f;
447
+
448
+ } else if(b == 0xdc) {
449
+ /* array 16 */
450
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
451
+ *result_size = _msgpack_be16(cb->u16);
452
+
453
+ } else if(b == 0xdd) {
454
+ /* array 32 */
455
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
456
+ *result_size = _msgpack_be32(cb->u32);
457
+
458
+ } else {
459
+ return PRIMITIVE_UNEXPECTED_TYPE;
460
+ }
461
+
462
+ return 0;
463
+ }
464
+
465
+ int msgpack_unpacker_read_map_header(msgpack_unpacker_t* uk, uint32_t* result_size)
466
+ {
467
+ int b = get_head_byte(uk);
468
+ if(b < 0) {
469
+ return b;
470
+ }
471
+
472
+ if(0x80 < b && b < 0x8f) {
473
+ *result_size = b & 0x0f;
474
+
475
+ } else if(b == 0xde) {
476
+ /* map 16 */
477
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
478
+ *result_size = _msgpack_be16(cb->u16);
479
+
480
+ } else if(b == 0xdf) {
481
+ /* map 32 */
482
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
483
+ *result_size = _msgpack_be32(cb->u32);
484
+
485
+ } else {
486
+ return PRIMITIVE_UNEXPECTED_TYPE;
487
+ }
488
+
489
+ return 0;
490
+ }
491
+
492
+ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
493
+ {
494
+ while(true) {
495
+ int r = read_primitive(uk);
496
+ if(r < 0) {
497
+ return r;
498
+ }
499
+ if(r == PRIMITIVE_CONTAINER_START) {
500
+ //printf("container start count=%lu\n", _msgpack_unpacker_stack_top(uk)->count);
501
+ continue;
502
+ }
503
+ /* PRIMITIVE_OBJECT_COMPLETE */
504
+
505
+ if(msgpack_unpacker_stack_is_empty(uk)) {
506
+ return PRIMITIVE_OBJECT_COMPLETE;
507
+ }
508
+
509
+ container_completed:
510
+ {
511
+ msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
512
+ switch(top->type) {
513
+ case STACK_TYPE_ARRAY:
514
+ rb_ary_push(top->object, uk->last_object);
515
+ break;
516
+ case STACK_TYPE_MAP_KEY:
517
+ top->key = uk->last_object;
518
+ top->type = STACK_TYPE_MAP_VALUE;
519
+ break;
520
+ case STACK_TYPE_MAP_VALUE:
521
+ rb_hash_aset(top->object, top->key, uk->last_object);
522
+ top->type = STACK_TYPE_MAP_KEY;
523
+ break;
524
+ }
525
+ size_t count = --top->count;
526
+ //printf("calc count: %lu depth=%lu\n", count, uk->stack_depth);
527
+
528
+ if(count == 0) {
529
+ object_complete(uk, top->object);
530
+ if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
531
+ return PRIMITIVE_OBJECT_COMPLETE;
532
+ }
533
+ goto container_completed;
534
+ }
535
+ }
536
+ }
537
+ }
538
+
539
+ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
540
+ {
541
+ while(true) {
542
+ int r = read_primitive(uk);
543
+ if(r < 0) {
544
+ return r;
545
+ }
546
+ if(r == PRIMITIVE_CONTAINER_START) {
547
+ continue;
548
+ }
549
+ /* PRIMITIVE_OBJECT_COMPLETE */
550
+
551
+ if(msgpack_unpacker_stack_is_empty(uk)) {
552
+ return PRIMITIVE_OBJECT_COMPLETE;
553
+ }
554
+
555
+ container_completed:
556
+ {
557
+ msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
558
+ /* deleted section */
559
+ /* TODO optimize: #define SKIP and #include unpacker_incl.h */
560
+ size_t count = --top->count;
561
+
562
+ if(count == 0) {
563
+ object_complete(uk, Qnil);
564
+ if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
565
+ return PRIMITIVE_OBJECT_COMPLETE;
566
+ }
567
+ goto container_completed;
568
+ }
569
+ }
570
+ }
571
+ }
572
+
573
+ int msgpack_unpacker_peek_next_object_type(msgpack_unpacker_t* uk)
574
+ {
575
+ int b = get_head_byte(uk);
576
+ if(b < 0) {
577
+ return b;
578
+ }
579
+
580
+ SWITCH_RANGE_BEGIN(b)
581
+ SWITCH_RANGE(b, 0x00, 0x7f) // Positive Fixnum
582
+ return TYPE_INTEGER;
583
+
584
+ SWITCH_RANGE(b, 0xe0, 0xff) // Negative Fixnum
585
+ return TYPE_INTEGER;
586
+
587
+ SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw
588
+ return TYPE_RAW;
589
+
590
+ SWITCH_RANGE(b, 0x90, 0x9f) // FixArray
591
+ return TYPE_ARRAY;
592
+
593
+ SWITCH_RANGE(b, 0x80, 0x8f) // FixMap
594
+ return TYPE_MAP;
595
+
596
+ SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
597
+ switch(b) {
598
+ case 0xc0: // nil
599
+ return TYPE_NIL;
600
+
601
+ case 0xc2: // false
602
+ case 0xc3: // true
603
+ return TYPE_BOOLEAN;
604
+
605
+ case 0xca: // float
606
+ case 0xcb: // double
607
+ return TYPE_FLOAT;
608
+
609
+ case 0xcc: // unsigned int 8
610
+ case 0xcd: // unsigned int 16
611
+ case 0xce: // unsigned int 32
612
+ case 0xcf: // unsigned int 64
613
+ return TYPE_INTEGER;
614
+
615
+ case 0xd0: // signed int 8
616
+ case 0xd1: // signed int 16
617
+ case 0xd2: // signed int 32
618
+ case 0xd3: // signed int 64
619
+ return TYPE_INTEGER;
620
+
621
+ case 0xda: // raw 16
622
+ case 0xdb: // raw 32
623
+ return TYPE_RAW;
624
+
625
+ case 0xdc: // array 16
626
+ case 0xdd: // array 32
627
+ return TYPE_ARRAY;
628
+
629
+ case 0xde: // map 16
630
+ case 0xdf: // map 32
631
+ return TYPE_MAP;
632
+
633
+ default:
634
+ return PRIMITIVE_INVALID_BYTE;
635
+ }
636
+
637
+ SWITCH_RANGE_DEFAULT
638
+ return PRIMITIVE_INVALID_BYTE;
639
+
640
+ SWITCH_RANGE_END
641
+ }
642
+
643
+ int msgpack_unpacker_skip_nil(msgpack_unpacker_t* uk)
644
+ {
645
+ int b = get_head_byte(uk);
646
+ if(b < 0) {
647
+ return b;
648
+ }
649
+ if(b == 0xc0) {
650
+ return 1;
651
+ }
652
+ return 0;
653
+ }
654
+