hx_cbor 2021.8.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +30 -0
  3. data/.travis.yml +24 -0
  4. data/ChangeLog +106 -0
  5. data/Gemfile +11 -0
  6. data/README.rdoc +191 -0
  7. data/Rakefile +97 -0
  8. data/doclib/cbor.rb +80 -0
  9. data/doclib/cbor/buffer.rb +193 -0
  10. data/doclib/cbor/core_ext.rb +133 -0
  11. data/doclib/cbor/error.rb +14 -0
  12. data/doclib/cbor/packer.rb +133 -0
  13. data/doclib/cbor/simple.rb +15 -0
  14. data/doclib/cbor/tagged.rb +16 -0
  15. data/doclib/cbor/unpacker.rb +138 -0
  16. data/ext/cbor/3424.i.rb +29 -0
  17. data/ext/cbor/buffer.c +693 -0
  18. data/ext/cbor/buffer.h +484 -0
  19. data/ext/cbor/buffer_class.c +516 -0
  20. data/ext/cbor/buffer_class.h +41 -0
  21. data/ext/cbor/cbor.h +69 -0
  22. data/ext/cbor/compat.h +147 -0
  23. data/ext/cbor/core_ext.c +201 -0
  24. data/ext/cbor/core_ext.h +35 -0
  25. data/ext/cbor/example.rb +10 -0
  26. data/ext/cbor/extconf.rb +29 -0
  27. data/ext/cbor/install.sh +1 -0
  28. data/ext/cbor/packer.c +169 -0
  29. data/ext/cbor/packer.h +362 -0
  30. data/ext/cbor/packer_class.c +304 -0
  31. data/ext/cbor/packer_class.h +39 -0
  32. data/ext/cbor/rbinit.c +51 -0
  33. data/ext/cbor/renamer.h +56 -0
  34. data/ext/cbor/rmem.c +103 -0
  35. data/ext/cbor/rmem.h +118 -0
  36. data/ext/cbor/sysdep.h +139 -0
  37. data/ext/cbor/sysdep_endian.h +59 -0
  38. data/ext/cbor/sysdep_types.h +55 -0
  39. data/ext/cbor/unpacker.c +784 -0
  40. data/ext/cbor/unpacker.h +135 -0
  41. data/ext/cbor/unpacker_class.c +439 -0
  42. data/ext/cbor/unpacker_class.h +39 -0
  43. data/hx_cbor.gemspec +25 -0
  44. data/lib/cbor.rb +6 -0
  45. data/lib/cbor/version.rb +3 -0
  46. data/spec/buffer_io_spec.rb +260 -0
  47. data/spec/buffer_spec.rb +576 -0
  48. data/spec/cases.cbor +0 -0
  49. data/spec/cases.cbor_stream +0 -0
  50. data/spec/cases.json +1 -0
  51. data/spec/cases.msg +0 -0
  52. data/spec/cases_compact.msg +0 -0
  53. data/spec/cases_spec.rb +39 -0
  54. data/spec/format_spec.rb +540 -0
  55. data/spec/packer_spec.rb +127 -0
  56. data/spec/random_compat.rb +24 -0
  57. data/spec/spec_helper.rb +68 -0
  58. data/spec/unpacker_spec.rb +260 -0
  59. metadata +198 -0
@@ -0,0 +1,35 @@
1
+ /*
2
+ * CBOR for Ruby
3
+ *
4
+ * Copyright (C) 2013 Carsten Bormann
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License").
7
+ *
8
+ * Based on:
9
+ ***********/
10
+ /*
11
+ * MessagePack for Ruby
12
+ *
13
+ * Copyright (C) 2008-2013 Sadayuki Furuhashi
14
+ *
15
+ * Licensed under the Apache License, Version 2.0 (the "License");
16
+ * you may not use this file except in compliance with the License.
17
+ * You may obtain a copy of the License at
18
+ *
19
+ * http://www.apache.org/licenses/LICENSE-2.0
20
+ *
21
+ * Unless required by applicable law or agreed to in writing, software
22
+ * distributed under the License is distributed on an "AS IS" BASIS,
23
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
+ * See the License for the specific language governing permissions and
25
+ * limitations under the License.
26
+ */
27
+ #ifndef MSGPACK_RUBY_CORE_EXT_H__
28
+ #define MSGPACK_RUBY_CORE_EXT_H__
29
+
30
+ #include "compat.h"
31
+
32
+ void MessagePack_core_ext_module_init();
33
+
34
+ #endif
35
+
@@ -0,0 +1,10 @@
1
+ require 'cbor'
2
+ partCborFile = 'partly transferred cbor file' # 以 cbor 格式传输的文件,只成功传输了一部分。
3
+ partCborFileContent = File.read partCborFile
4
+ options = {:tolerant => true} # 要求解码过程中容错。
5
+ decoded = CBOR.decode(partCborFileContent, options)
6
+ #decoded = CBOR.decode partCborFileContent # 不加 tolerant 选项,遇到有问题的 cbor 会抛出异常。
7
+ puts decoded.class.name
8
+ # Hash
9
+ puts decoded.length
10
+ # 4
@@ -0,0 +1,29 @@
1
+ require 'mkmf'
2
+
3
+ have_header("ruby/st.h")
4
+ have_header("st.h")
5
+ have_func("rb_str_replace", ["ruby.h"])
6
+ have_func("rb_big_new", ["ruby.h"])
7
+ have_func("rb_intern_str", ["ruby.h"])
8
+ have_func("rb_sym2str", ["ruby.h"])
9
+ have_func("rb_str_intern", ["ruby.h"])
10
+ have_func("rb_integer_unpack", ["ruby.h"])
11
+
12
+ $CFLAGS << %[ -I.. -Wall -O3 -g -std=c99]
13
+ #$CFLAGS << %[ -DDISABLE_RMEM]
14
+ #$CFLAGS << %[ -DDISABLE_RMEM_REUSE_INTERNAL_FRAGMENT]
15
+ #$CFLAGS << %[ -DDISABLE_BUFFER_READ_REFERENCE_OPTIMIZE]
16
+ #$CFLAGS << %[ -DDISABLE_BUFFER_READ_TO_S_OPTIMIZE]
17
+
18
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
19
+ # msgpack-ruby doesn't modify data came from RSTRING_PTR(str)
20
+ $CFLAGS << %[ -DRSTRING_NOT_MODIFIED]
21
+ # Rubinius C extensions don't grab GVL while rmem is not thread safe
22
+ $CFLAGS << %[ -DDISABLE_RMEM]
23
+ end
24
+
25
+ if warnflags = CONFIG['warnflags']
26
+ warnflags.slice!(/ -Wdeclaration-after-statement/)
27
+ end
28
+
29
+ create_makefile('cbor/cbor')
@@ -0,0 +1 @@
1
+ gem install hx_cbor
data/ext/cbor/packer.c ADDED
@@ -0,0 +1,169 @@
1
+ /*
2
+ * CBOR for Ruby
3
+ *
4
+ * Copyright (C) 2013 Carsten Bormann
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License").
7
+ *
8
+ * Based on:
9
+ ***********/
10
+ /*
11
+ * MessagePack for Ruby
12
+ *
13
+ * Copyright (C) 2008-2013 Sadayuki Furuhashi
14
+ *
15
+ * Licensed under the Apache License, Version 2.0 (the "License");
16
+ * you may not use this file except in compliance with the License.
17
+ * You may obtain a copy of the License at
18
+ *
19
+ * http://www.apache.org/licenses/LICENSE-2.0
20
+ *
21
+ * Unless required by applicable law or agreed to in writing, software
22
+ * distributed under the License is distributed on an "AS IS" BASIS,
23
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
+ * See the License for the specific language governing permissions and
25
+ * limitations under the License.
26
+ */
27
+
28
+ #include "packer.h"
29
+
30
+ #ifdef RUBINIUS
31
+ static ID s_to_iter;
32
+ static ID s_next;
33
+ static ID s_key;
34
+ static ID s_value;
35
+ #endif
36
+
37
+ void msgpack_packer_static_init()
38
+ {
39
+ #ifdef RUBINIUS
40
+ s_to_iter = rb_intern("to_iter");
41
+ s_next = rb_intern("next");
42
+ s_key = rb_intern("key");
43
+ s_value = rb_intern("value");
44
+ #endif
45
+ }
46
+
47
+ void msgpack_packer_static_destroy()
48
+ { }
49
+
50
+ void msgpack_packer_init(msgpack_packer_t* pk)
51
+ {
52
+ memset(pk, 0, sizeof(msgpack_packer_t));
53
+
54
+ msgpack_buffer_init(PACKER_BUFFER_(pk));
55
+
56
+ pk->io = Qnil;
57
+ }
58
+
59
+ void msgpack_packer_destroy(msgpack_packer_t* pk)
60
+ {
61
+ msgpack_buffer_destroy(PACKER_BUFFER_(pk));
62
+ }
63
+
64
+ void msgpack_packer_mark(msgpack_packer_t* pk)
65
+ {
66
+ rb_gc_mark(pk->io);
67
+
68
+ /* See MessagePack_Buffer_wrap */
69
+ /* msgpack_buffer_mark(PACKER_BUFFER_(pk)); */
70
+ rb_gc_mark(pk->buffer_ref);
71
+ }
72
+
73
+ void msgpack_packer_reset(msgpack_packer_t* pk)
74
+ {
75
+ msgpack_buffer_clear(PACKER_BUFFER_(pk));
76
+
77
+ pk->io = Qnil;
78
+ pk->io_write_all_method = 0;
79
+ pk->buffer_ref = Qnil;
80
+ }
81
+
82
+
83
+ void msgpack_packer_write_array_value(msgpack_packer_t* pk, VALUE v)
84
+ {
85
+ /* actual return type of RARRAY_LEN is long */
86
+ unsigned long len = RARRAY_LEN(v);
87
+ msgpack_packer_write_array_header(pk, len);
88
+
89
+ unsigned long i;
90
+ for(i=0; i < len; ++i) {
91
+ VALUE e = rb_ary_entry(v, i);
92
+ msgpack_packer_write_value(pk, e);
93
+ }
94
+ }
95
+
96
+ static int write_hash_foreach(VALUE key, VALUE value, VALUE pk_value)
97
+ {
98
+ if (key == Qundef) {
99
+ return ST_CONTINUE;
100
+ }
101
+ msgpack_packer_t* pk = (msgpack_packer_t*) pk_value;
102
+ msgpack_packer_write_value(pk, key);
103
+ msgpack_packer_write_value(pk, value);
104
+ return ST_CONTINUE;
105
+ }
106
+
107
+ void msgpack_packer_write_hash_value(msgpack_packer_t* pk, VALUE v)
108
+ {
109
+ /* actual return type of RHASH_SIZE is long (if SIZEOF_LONG == SIZEOF_VOIDP
110
+ * or long long (if SIZEOF_LONG_LONG == SIZEOF_VOIDP. See st.h. */
111
+ unsigned long len = RHASH_SIZE(v);
112
+ msgpack_packer_write_map_header(pk, len);
113
+
114
+ #ifdef RUBINIUS
115
+ VALUE iter = rb_funcall(v, s_to_iter, 0);
116
+ VALUE entry = Qnil;
117
+ while(RTEST(entry = rb_funcall(iter, s_next, 1, entry))) {
118
+ VALUE key = rb_funcall(entry, s_key, 0);
119
+ VALUE val = rb_funcall(entry, s_value, 0);
120
+ write_hash_foreach(key, val, (VALUE) pk);
121
+ }
122
+ #else
123
+ rb_hash_foreach(v, write_hash_foreach, (VALUE) pk);
124
+ #endif
125
+ }
126
+
127
+ static void _msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
128
+ {
129
+ rb_funcall(v, pk->to_msgpack_method, 1, pk->to_msgpack_arg);
130
+ }
131
+
132
+ void msgpack_packer_write_value(msgpack_packer_t* pk, VALUE v)
133
+ {
134
+ switch(rb_type(v)) {
135
+ case T_NIL:
136
+ msgpack_packer_write_nil(pk);
137
+ break;
138
+ case T_TRUE:
139
+ msgpack_packer_write_true(pk);
140
+ break;
141
+ case T_FALSE:
142
+ msgpack_packer_write_false(pk);
143
+ break;
144
+ case T_FIXNUM:
145
+ msgpack_packer_write_fixnum_value(pk, v);
146
+ break;
147
+ case T_SYMBOL:
148
+ msgpack_packer_write_symbol_value(pk, v);
149
+ break;
150
+ case T_STRING:
151
+ msgpack_packer_write_string_value(pk, v);
152
+ break;
153
+ case T_ARRAY:
154
+ msgpack_packer_write_array_value(pk, v);
155
+ break;
156
+ case T_HASH:
157
+ msgpack_packer_write_hash_value(pk, v);
158
+ break;
159
+ case T_BIGNUM:
160
+ msgpack_packer_write_bignum_value(pk, v);
161
+ break;
162
+ case T_FLOAT:
163
+ msgpack_packer_write_float_value(pk, v);
164
+ break;
165
+ default:
166
+ _msgpack_packer_write_other_value(pk, v);
167
+ }
168
+ }
169
+
data/ext/cbor/packer.h ADDED
@@ -0,0 +1,362 @@
1
+ /*
2
+ * CBOR for Ruby
3
+ *
4
+ * Copyright (C) 2013 Carsten Bormann
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License").
7
+ *
8
+ * Based on:
9
+ ***********/
10
+ /*
11
+ * MessagePack for Ruby
12
+ *
13
+ * Copyright (C) 2008-2013 Sadayuki Furuhashi
14
+ *
15
+ * Licensed under the Apache License, Version 2.0 (the "License");
16
+ * you may not use this file except in compliance with the License.
17
+ * You may obtain a copy of the License at
18
+ *
19
+ * http://www.apache.org/licenses/LICENSE-2.0
20
+ *
21
+ * Unless required by applicable law or agreed to in writing, software
22
+ * distributed under the License is distributed on an "AS IS" BASIS,
23
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
+ * See the License for the specific language governing permissions and
25
+ * limitations under the License.
26
+ */
27
+ #ifndef MSGPACK_RUBY_PACKER_H__
28
+ #define MSGPACK_RUBY_PACKER_H__
29
+
30
+ #include "buffer.h"
31
+
32
+ #ifndef MSGPACK_PACKER_IO_FLUSH_THRESHOLD_TO_WRITE_STRING_BODY
33
+ #define MSGPACK_PACKER_IO_FLUSH_THRESHOLD_TO_WRITE_STRING_BODY (1024)
34
+ #endif
35
+
36
+ struct msgpack_packer_t;
37
+ typedef struct msgpack_packer_t msgpack_packer_t;
38
+
39
+ struct msgpack_packer_t {
40
+ msgpack_buffer_t buffer;
41
+
42
+ VALUE io;
43
+ ID io_write_all_method;
44
+
45
+ ID to_msgpack_method;
46
+ VALUE to_msgpack_arg;
47
+
48
+ VALUE buffer_ref;
49
+ };
50
+
51
+ #define PACKER_BUFFER_(pk) (&(pk)->buffer)
52
+
53
+ void msgpack_packer_static_init();
54
+
55
+ void msgpack_packer_static_destroy();
56
+
57
+ void msgpack_packer_init(msgpack_packer_t* pk);
58
+
59
+ void msgpack_packer_destroy(msgpack_packer_t* pk);
60
+
61
+ void msgpack_packer_mark(msgpack_packer_t* pk);
62
+
63
+ static inline void msgpack_packer_set_to_msgpack_method(msgpack_packer_t* pk,
64
+ ID to_msgpack_method, VALUE to_msgpack_arg)
65
+ {
66
+ pk->to_msgpack_method = to_msgpack_method;
67
+ pk->to_msgpack_arg = to_msgpack_arg;
68
+ }
69
+
70
+ static inline void msgpack_packer_set_io(msgpack_packer_t* pk, VALUE io, ID io_write_all_method)
71
+ {
72
+ pk->io = io;
73
+ pk->io_write_all_method = io_write_all_method;
74
+ }
75
+
76
+ void msgpack_packer_reset(msgpack_packer_t* pk);
77
+
78
+
79
+ static inline void cbor_encoder_write_head(msgpack_packer_t* pk, unsigned int ib, uint64_t n)
80
+ {
81
+ if (n < 24) {
82
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), 1);
83
+ msgpack_buffer_write_1(PACKER_BUFFER_(pk), ib + (int)n);
84
+ } else if (n < 256) {
85
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), 3);
86
+ msgpack_buffer_write_2(PACKER_BUFFER_(pk), ib + 24, n);
87
+ } else if (n < 65536) {
88
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), 3);
89
+ uint16_t be = _msgpack_be16(n);
90
+ msgpack_buffer_write_byte_and_data(PACKER_BUFFER_(pk), ib + 25, (const void*)&be, 2);
91
+ } else if (n < 0x100000000LU) {
92
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), 5);
93
+ uint32_t be = _msgpack_be32(n);
94
+ msgpack_buffer_write_byte_and_data(PACKER_BUFFER_(pk), ib + 26, (const void*)&be, 4);
95
+ } else {
96
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), 9);
97
+ uint64_t be = _msgpack_be64(n);
98
+ msgpack_buffer_write_byte_and_data(PACKER_BUFFER_(pk), ib + 27, (const void*)&be, 8);
99
+ }
100
+ }
101
+
102
+ static inline void msgpack_packer_write_nil(msgpack_packer_t* pk)
103
+ {
104
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), 1);
105
+ msgpack_buffer_write_1(PACKER_BUFFER_(pk), IB_NIL);
106
+ }
107
+
108
+ static inline void msgpack_packer_write_true(msgpack_packer_t* pk)
109
+ {
110
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), 1);
111
+ msgpack_buffer_write_1(PACKER_BUFFER_(pk), IB_TRUE);
112
+ }
113
+
114
+ static inline void msgpack_packer_write_false(msgpack_packer_t* pk)
115
+ {
116
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), 1);
117
+ msgpack_buffer_write_1(PACKER_BUFFER_(pk), IB_FALSE);
118
+ }
119
+
120
+ static inline void _msgpack_packer_write_long_long64(msgpack_packer_t* pk, long long v)
121
+ {
122
+ uint64_t ui = v >> 63; // extend sign to whole length
123
+ int mt = ui & IB_NEGFLAG; // extract major type
124
+ ui ^= v; // complement negatives
125
+ cbor_encoder_write_head(pk, mt, ui);
126
+ }
127
+
128
+ static inline void msgpack_packer_write_long(msgpack_packer_t* pk, long v)
129
+ {
130
+ _msgpack_packer_write_long_long64(pk, v);
131
+ }
132
+
133
+ static inline void msgpack_packer_write_u64(msgpack_packer_t* pk, uint64_t v)
134
+ {
135
+ cbor_encoder_write_head(pk, IB_UNSIGNED, v);
136
+ }
137
+
138
+ static inline void msgpack_packer_write_double(msgpack_packer_t* pk, double v)
139
+ {
140
+ float fv = v;
141
+ if (fv == v) { /* 32 bits is enough and we aren't NaN */
142
+ union {
143
+ float f;
144
+ uint32_t u32;
145
+ char mem[4];
146
+ } castbuf = { fv };
147
+ int b32 = castbuf.u32;
148
+ if ((b32 & 0x1FFF) == 0) { /* worth trying half */
149
+ int s16 = (b32 >> 16) & 0x8000;
150
+ int exp = (b32 >> 23) & 0xff;
151
+ int mant = b32 & 0x7fffff;
152
+ if (exp == 0 && mant == 0)
153
+ ; /* 0.0, -0.0 */
154
+ else if (exp >= 113 && exp <= 142) /* normalized */
155
+ s16 += ((exp - 112) << 10) + (mant >> 13);
156
+ else if (exp >= 103 && exp < 113) { /* denorm, exp16 = 0 */
157
+ if (mant & ((1 << (126 - exp)) - 1))
158
+ goto float32; /* loss of precision */
159
+ s16 += ((mant + 0x800000) >> (126 - exp));
160
+ } else if (exp == 255 && mant == 0) { /* Inf */
161
+ s16 += 0x7c00;
162
+ } else
163
+ goto float32; /* loss of range */
164
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), 3);
165
+ uint16_t be = _msgpack_be16(s16);
166
+ msgpack_buffer_write_byte_and_data(PACKER_BUFFER_(pk), IB_FLOAT2, (const void*)&be, 2);
167
+ return;
168
+ }
169
+ float32:
170
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), 5);
171
+ castbuf.u32 = _msgpack_be_float(castbuf.u32);
172
+ msgpack_buffer_write_byte_and_data(PACKER_BUFFER_(pk), IB_FLOAT4, castbuf.mem, 4);
173
+ } else if (v != v) { /* NaN */
174
+ cbor_encoder_write_head(pk, 0xe0, 0x7e00);
175
+ } else {
176
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), 9);
177
+ union {
178
+ double d;
179
+ uint64_t u64;
180
+ char mem[8];
181
+ } castbuf = { v };
182
+ castbuf.u64 = _msgpack_be_double(castbuf.u64);
183
+ msgpack_buffer_write_byte_and_data(PACKER_BUFFER_(pk), IB_FLOAT8, castbuf.mem, 8);
184
+ }
185
+ }
186
+
187
+ static inline void msgpack_packer_write_array_header(msgpack_packer_t* pk, uint64_t n)
188
+ {
189
+ cbor_encoder_write_head(pk, IB_ARRAY, n);
190
+ }
191
+
192
+ static inline void msgpack_packer_write_map_header(msgpack_packer_t* pk, uint64_t n)
193
+ {
194
+ cbor_encoder_write_head(pk, IB_MAP, n);
195
+ }
196
+
197
+
198
+ void _msgpack_packer_write_string_to_io(msgpack_packer_t* pk, VALUE string);
199
+
200
+ static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE v)
201
+ {
202
+ int mt = IB_TEXT; /* text string */
203
+ #ifdef COMPAT_HAVE_ENCODING
204
+ int enc = ENCODING_GET(v);
205
+ if (enc == s_enc_ascii8bit) {
206
+ mt = IB_BYTES;
207
+ } else if (enc != s_enc_utf8 && enc != s_enc_usascii) {
208
+ if(!ENC_CODERANGE_ASCIIONLY(v)) {
209
+ v = rb_str_encode(v, s_enc_utf8_value, 0, Qnil);
210
+ }
211
+ }
212
+ #endif
213
+ cbor_encoder_write_head(pk, mt, RSTRING_LEN(v));
214
+ msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
215
+ }
216
+
217
+ static inline void msgpack_packer_write_symbol_value(msgpack_packer_t* pk, VALUE v)
218
+ {
219
+ #ifdef HAVE_RB_SYM2STR
220
+ /* rb_sym2str is added since MRI 2.2.0 */
221
+ msgpack_packer_write_string_value(pk, rb_sym2str(v));
222
+ #else
223
+ const char* name = rb_id2name(SYM2ID(v));
224
+ /* actual return type of strlen is size_t */
225
+ unsigned long len = strlen(name);
226
+ if(len > 0xffffffffUL) {
227
+ // TODO rb_eArgError?
228
+ rb_raise(rb_eArgError, "size of symbol is too long to pack: %lu bytes should be <= %lu", len, 0xffffffffUL);
229
+ }
230
+ cbor_encoder_write_head(pk, IB_TEXT, len);
231
+ msgpack_buffer_append(PACKER_BUFFER_(pk), name, len);
232
+ #endif
233
+ }
234
+
235
+ static inline void msgpack_packer_write_fixnum_value(msgpack_packer_t* pk, VALUE v)
236
+ {
237
+ #ifdef JRUBY
238
+ msgpack_packer_write_long(pk, FIXNUM_P(v) ? FIX2LONG(v) : rb_num2ll(v));
239
+ #else
240
+ msgpack_packer_write_long(pk, FIX2LONG(v));
241
+ #endif
242
+ }
243
+
244
+ static inline void msgpack_packer_write_bignum_value(msgpack_packer_t* pk, VALUE v)
245
+ {
246
+ long len;
247
+ int ib = IB_UNSIGNED;
248
+ if (!RBIGNUM_POSITIVE_P(v)) {
249
+ v = rb_funcall(v, rb_intern("~"), 0); /* should be rb_big_neg(), but that is static. */
250
+ ib = IB_NEGATIVE;
251
+ }
252
+
253
+
254
+ #ifdef HAVE_RB_INTEGER_UNPACK
255
+ len = rb_absint_size(v, NULL);
256
+
257
+ if (len > SIZEOF_LONG_LONG) { /* i.e., need real bignum */
258
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), 1);
259
+ msgpack_buffer_write_1(PACKER_BUFFER_(pk), IB_BIGNUM + IB_NEGFLAG_AS_BIT(ib));
260
+ cbor_encoder_write_head(pk, IB_BYTES, len);
261
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), len);
262
+
263
+ char buf[len]; /* XXX */
264
+ if (rb_integer_pack(v, buf, len, 1, 0, INTEGER_PACK_BIG_ENDIAN) != 1)
265
+ rb_raise(rb_eRangeError, "cbor rb_integer_pack() error");
266
+
267
+ msgpack_buffer_append(PACKER_BUFFER_(pk), buf, len);
268
+
269
+ #else
270
+
271
+ len = RBIGNUM_LEN(v);
272
+ if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS) {
273
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), 1);
274
+ msgpack_buffer_write_1(PACKER_BUFFER_(pk), IB_BIGNUM + IB_NEGFLAG_AS_BIT(ib));
275
+ {
276
+ #ifndef CANT_DO_BIGNUMS_FAST_ON_THIS_PLATFORM
277
+ BDIGIT *dp = RBIGNUM_DIGITS(v);
278
+ BDIGIT *de = dp + len;
279
+ int nbyte = (len - 1) * SIZEOF_BDIGITS;
280
+ int nbmsdig = 0;
281
+ BDIGIT msdig;
282
+ int i;
283
+ if ((msdig = de[-1]) == 0) /* todo: check whether that occurs */
284
+ rb_raise(rb_eRangeError, "cbor writing unnormalized bignum");
285
+ while (msdig) { /* get number of significant bytes in msdig */
286
+ nbmsdig++;
287
+ msdig >>= 8;
288
+ }
289
+ nbyte += nbmsdig;
290
+ cbor_encoder_write_head(pk, IB_BYTES, nbyte);
291
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), nbyte);
292
+ /* first digit: */
293
+ msdig = de[-1];
294
+ while (nbmsdig) {
295
+ --nbmsdig;
296
+ msgpack_buffer_write_1(PACKER_BUFFER_(pk), msdig >> (nbmsdig << 3));
297
+ }
298
+ /* rest of the digits: */
299
+ for (i = 1; i < len; ++i) {
300
+ BDIGIT be = NTOHBDIGIT(de[-1-i]);
301
+ msgpack_buffer_append(PACKER_BUFFER_(pk), (const void*)&be, SIZEOF_BDIGITS);
302
+ }
303
+ #else
304
+ /* This is a slow workaround only... But a working one.*/
305
+ size_t nbyte;
306
+ VALUE hexval = rb_funcall(v, rb_intern("to_s"), 1, INT2FIX(16));
307
+ char *hp;
308
+ int i;
309
+ if (RSTRING_LEN(hexval) & 1)
310
+ rb_funcall(hexval, rb_intern("[]="), 3, INT2FIX(0), INT2FIX(0), rb_str_new("0", 1));
311
+ nbyte = RSTRING_LEN(hexval) >> 1;
312
+ hp = RSTRING_PTR(hexval);
313
+ cbor_encoder_write_head(pk, IB_BYTES, nbyte);
314
+ msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), nbyte);
315
+ for (i = 0; i < nbyte; i++) {
316
+ int c;
317
+ sscanf(hp, "%2x", &c);
318
+ hp += 2;
319
+ msgpack_buffer_write_1(PACKER_BUFFER_(pk), c);
320
+ }
321
+ #endif
322
+ }
323
+ #endif
324
+ } else {
325
+ cbor_encoder_write_head(pk, ib, rb_big2ull(v));
326
+ }
327
+
328
+ #ifdef RB_GC_GUARD
329
+ RB_GC_GUARD(v);
330
+ #endif
331
+ }
332
+
333
+ static inline void msgpack_packer_write_float_value(msgpack_packer_t* pk, VALUE v)
334
+ {
335
+ msgpack_packer_write_double(pk, rb_num2dbl(v));
336
+ }
337
+
338
+ static inline void msgpack_packer_write_simple_value(msgpack_packer_t* pk, VALUE v)
339
+ {
340
+ cbor_encoder_write_head(pk, IB_PRIM, FIX2LONG(rb_struct_aref(v, INT2FIX(0))));
341
+ }
342
+
343
+ void msgpack_packer_write_array_value(msgpack_packer_t* pk, VALUE v);
344
+
345
+ void msgpack_packer_write_hash_value(msgpack_packer_t* pk, VALUE v);
346
+
347
+ void msgpack_packer_write_value(msgpack_packer_t* pk, VALUE v);
348
+
349
+ static inline void msgpack_packer_write_tagged_value(msgpack_packer_t* pk, VALUE v)
350
+ {
351
+ cbor_encoder_write_head(pk, IB_TAG, rb_num2ulong(rb_struct_aref(v, INT2FIX(0))));
352
+ msgpack_packer_write_value(pk, rb_struct_aref(v, INT2FIX(1)));
353
+ }
354
+
355
+ static inline void msgpack_packer_write_processed_value(msgpack_packer_t* pk, VALUE v, ID method, int tag)
356
+ {
357
+ cbor_encoder_write_head(pk, IB_TAG, tag);
358
+ msgpack_packer_write_value(pk, rb_funcall(v, method, 0));
359
+ }
360
+
361
+ #endif
362
+