cbor 0.5.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.travis.yml +5 -0
- data/ChangeLog +87 -0
- data/README.rdoc +180 -0
- data/Rakefile +94 -0
- data/cbor.gemspec +26 -0
- data/doclib/cbor.rb +80 -0
- data/doclib/cbor/buffer.rb +193 -0
- data/doclib/cbor/core_ext.rb +133 -0
- data/doclib/cbor/error.rb +14 -0
- data/doclib/cbor/packer.rb +133 -0
- data/doclib/cbor/simple.rb +15 -0
- data/doclib/cbor/tagged.rb +16 -0
- data/doclib/cbor/unpacker.rb +138 -0
- data/ext/cbor/buffer.c +693 -0
- data/ext/cbor/buffer.h +469 -0
- data/ext/cbor/buffer_class.c +516 -0
- data/ext/cbor/buffer_class.h +41 -0
- data/ext/cbor/cbor.h +69 -0
- data/ext/cbor/compat.h +136 -0
- data/ext/cbor/core_ext.c +181 -0
- data/ext/cbor/core_ext.h +35 -0
- data/ext/cbor/extconf.rb +25 -0
- data/ext/cbor/packer.c +169 -0
- data/ext/cbor/packer.h +337 -0
- data/ext/cbor/packer_class.c +304 -0
- data/ext/cbor/packer_class.h +39 -0
- data/ext/cbor/rbinit.c +51 -0
- data/ext/cbor/renamer.h +56 -0
- data/ext/cbor/rmem.c +103 -0
- data/ext/cbor/rmem.h +118 -0
- data/ext/cbor/sysdep.h +135 -0
- data/ext/cbor/sysdep_endian.h +59 -0
- data/ext/cbor/sysdep_types.h +55 -0
- data/ext/cbor/unpacker.c +735 -0
- data/ext/cbor/unpacker.h +133 -0
- data/ext/cbor/unpacker_class.c +417 -0
- data/ext/cbor/unpacker_class.h +39 -0
- data/lib/cbor.rb +9 -0
- data/lib/cbor/version.rb +3 -0
- data/spec/buffer_io_spec.rb +260 -0
- data/spec/buffer_spec.rb +576 -0
- data/spec/cases.cbor +0 -0
- data/spec/cases.cbor_stream +0 -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/format_spec.rb +445 -0
- data/spec/packer_spec.rb +127 -0
- data/spec/random_compat.rb +24 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/unpacker_spec.rb +238 -0
- metadata +196 -0
data/ext/cbor/extconf.rb
ADDED
@@ -0,0 +1,25 @@
|
|
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
|
+
|
8
|
+
$CFLAGS << %[ -I.. -Wall -O3 -g -std=c99]
|
9
|
+
#$CFLAGS << %[ -DDISABLE_RMEM]
|
10
|
+
#$CFLAGS << %[ -DDISABLE_RMEM_REUSE_INTERNAL_FRAGMENT]
|
11
|
+
#$CFLAGS << %[ -DDISABLE_BUFFER_READ_REFERENCE_OPTIMIZE]
|
12
|
+
#$CFLAGS << %[ -DDISABLE_BUFFER_READ_TO_S_OPTIMIZE]
|
13
|
+
|
14
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
15
|
+
# msgpack-ruby doesn't modify data came from RSTRING_PTR(str)
|
16
|
+
$CFLAGS << %[ -DRSTRING_NOT_MODIFIED]
|
17
|
+
# Rubinius C extensions don't grab GVL while rmem is not thread safe
|
18
|
+
$CFLAGS << %[ -DDISABLE_RMEM]
|
19
|
+
end
|
20
|
+
|
21
|
+
if warnflags = CONFIG['warnflags']
|
22
|
+
warnflags.slice!(/ -Wdeclaration-after-statement/)
|
23
|
+
end
|
24
|
+
|
25
|
+
create_makefile('cbor/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,337 @@
|
|
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 + 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, 0xfe00);
|
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
|
+
const char* name = rb_id2name(SYM2ID(v));
|
220
|
+
/* actual return type of strlen is size_t */
|
221
|
+
unsigned long len = strlen(name);
|
222
|
+
if(len > 0xffffffffUL) {
|
223
|
+
// TODO rb_eArgError?
|
224
|
+
rb_raise(rb_eArgError, "size of symbol is too long to pack: %lu bytes should be <= %lu", len, 0xffffffffUL);
|
225
|
+
}
|
226
|
+
cbor_encoder_write_head(pk, IB_TEXT, len);
|
227
|
+
msgpack_buffer_append(PACKER_BUFFER_(pk), name, len);
|
228
|
+
}
|
229
|
+
|
230
|
+
static inline void msgpack_packer_write_fixnum_value(msgpack_packer_t* pk, VALUE v)
|
231
|
+
{
|
232
|
+
#ifdef JRUBY
|
233
|
+
msgpack_packer_write_long(pk, FIXNUM_P(v) ? FIX2LONG(v) : rb_num2ll(v));
|
234
|
+
#else
|
235
|
+
msgpack_packer_write_long(pk, FIX2LONG(v));
|
236
|
+
#endif
|
237
|
+
}
|
238
|
+
|
239
|
+
static inline void msgpack_packer_write_bignum_value(msgpack_packer_t* pk, VALUE v)
|
240
|
+
{
|
241
|
+
long len;
|
242
|
+
int ib = IB_UNSIGNED;
|
243
|
+
if (!RBIGNUM_POSITIVE_P(v)) {
|
244
|
+
v = rb_funcall(v, rb_intern("~"), 0); /* should be rb_big_neg(), but that is static. */
|
245
|
+
ib = IB_NEGATIVE;
|
246
|
+
}
|
247
|
+
len = RBIGNUM_LEN(v); /* This API is broken in Rubinius 2.1.1, #2742 */
|
248
|
+
if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS) {
|
249
|
+
msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), 1);
|
250
|
+
msgpack_buffer_write_1(PACKER_BUFFER_(pk), IB_BIGNUM + IB_NEGFLAG_AS_BIT(ib));
|
251
|
+
{
|
252
|
+
#ifndef CANT_DO_BIGNUMS_FAST_ON_THIS_PLATFORM
|
253
|
+
BDIGIT *dp = RBIGNUM_DIGITS(v);
|
254
|
+
BDIGIT *de = dp + len;
|
255
|
+
int nbyte = (len - 1) * SIZEOF_BDIGITS;
|
256
|
+
int nbmsdig = 0;
|
257
|
+
BDIGIT msdig;
|
258
|
+
int i;
|
259
|
+
if ((msdig = de[-1]) == 0) /* todo: check whether that occurs */
|
260
|
+
rb_raise(rb_eRangeError, "cbor writing unnormalized bignum");
|
261
|
+
while (msdig) { /* get number of significant bytes in msdig */
|
262
|
+
nbmsdig++;
|
263
|
+
msdig >>= 8;
|
264
|
+
}
|
265
|
+
nbyte += nbmsdig;
|
266
|
+
cbor_encoder_write_head(pk, IB_BYTES, nbyte);
|
267
|
+
msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), nbyte);
|
268
|
+
/* first digit: */
|
269
|
+
msdig = de[-1];
|
270
|
+
while (nbmsdig) {
|
271
|
+
--nbmsdig;
|
272
|
+
msgpack_buffer_write_1(PACKER_BUFFER_(pk), msdig >> (nbmsdig << 3));
|
273
|
+
}
|
274
|
+
/* rest of the digits: */
|
275
|
+
for (i = 1; i < len; ++i) {
|
276
|
+
BDIGIT be = NTOHBDIGIT(de[-1-i]);
|
277
|
+
msgpack_buffer_append(PACKER_BUFFER_(pk), (const void*)&be, SIZEOF_BDIGITS);
|
278
|
+
}
|
279
|
+
#else
|
280
|
+
/* This is a slow workaround only... But a working one.*/
|
281
|
+
size_t nbyte;
|
282
|
+
VALUE hexval = rb_funcall(v, rb_intern("to_s"), 1, INT2FIX(16));
|
283
|
+
char *hp;
|
284
|
+
int i;
|
285
|
+
if (RSTRING_LEN(hexval) & 1)
|
286
|
+
rb_funcall(hexval, rb_intern("[]="), 3, INT2FIX(0), INT2FIX(0), rb_str_new("0", 1));
|
287
|
+
nbyte = RSTRING_LEN(hexval) >> 1;
|
288
|
+
hp = RSTRING_PTR(hexval);
|
289
|
+
cbor_encoder_write_head(pk, IB_BYTES, nbyte);
|
290
|
+
msgpack_buffer_ensure_writable(PACKER_BUFFER_(pk), nbyte);
|
291
|
+
for (i = 0; i < nbyte; i++) {
|
292
|
+
int c;
|
293
|
+
sscanf(hp, "%2x", &c);
|
294
|
+
hp += 2;
|
295
|
+
msgpack_buffer_write_1(PACKER_BUFFER_(pk), c);
|
296
|
+
}
|
297
|
+
#endif
|
298
|
+
}
|
299
|
+
} else {
|
300
|
+
cbor_encoder_write_head(pk, ib, rb_big2ull(v));
|
301
|
+
}
|
302
|
+
|
303
|
+
#ifdef RB_GC_GUARD
|
304
|
+
RB_GC_GUARD(v);
|
305
|
+
#endif
|
306
|
+
}
|
307
|
+
|
308
|
+
static inline void msgpack_packer_write_float_value(msgpack_packer_t* pk, VALUE v)
|
309
|
+
{
|
310
|
+
msgpack_packer_write_double(pk, rb_num2dbl(v));
|
311
|
+
}
|
312
|
+
|
313
|
+
static inline void msgpack_packer_write_simple_value(msgpack_packer_t* pk, VALUE v)
|
314
|
+
{
|
315
|
+
cbor_encoder_write_head(pk, IB_PRIM, FIX2LONG(rb_struct_aref(v, INT2FIX(0))));
|
316
|
+
}
|
317
|
+
|
318
|
+
void msgpack_packer_write_array_value(msgpack_packer_t* pk, VALUE v);
|
319
|
+
|
320
|
+
void msgpack_packer_write_hash_value(msgpack_packer_t* pk, VALUE v);
|
321
|
+
|
322
|
+
void msgpack_packer_write_value(msgpack_packer_t* pk, VALUE v);
|
323
|
+
|
324
|
+
static inline void msgpack_packer_write_tagged_value(msgpack_packer_t* pk, VALUE v)
|
325
|
+
{
|
326
|
+
cbor_encoder_write_head(pk, IB_TAG, FIX2LONG(rb_struct_aref(v, INT2FIX(0))));
|
327
|
+
msgpack_packer_write_value(pk, rb_struct_aref(v, INT2FIX(1)));
|
328
|
+
}
|
329
|
+
|
330
|
+
static inline void msgpack_packer_write_processed_value(msgpack_packer_t* pk, VALUE v, ID method, int tag)
|
331
|
+
{
|
332
|
+
cbor_encoder_write_head(pk, IB_TAG, tag);
|
333
|
+
msgpack_packer_write_value(pk, rb_funcall(v, method, 0));
|
334
|
+
}
|
335
|
+
|
336
|
+
#endif
|
337
|
+
|