bson 4.5.0 → 4.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.md +7 -5
- data/ext/bson/{native-endian.h → bson-endian.h} +5 -99
- data/ext/bson/bson-native.h +112 -0
- data/ext/bson/bytebuf.c +133 -0
- data/ext/bson/endian.c +116 -0
- data/ext/bson/init.c +289 -0
- data/ext/bson/libbson-utf8.c +230 -0
- data/ext/bson/read.c +294 -0
- data/ext/bson/util.c +55 -0
- data/ext/bson/write.c +637 -0
- data/lib/bson/document.rb +43 -1
- data/lib/bson/hash.rb +11 -2
- data/lib/bson/int32.rb +19 -13
- data/lib/bson/int64.rb +19 -13
- data/lib/bson/version.rb +1 -1
- data/spec/bson/byte_buffer_read_spec.rb +141 -0
- data/spec/bson/byte_buffer_spec.rb +14 -451
- data/spec/bson/byte_buffer_write_spec.rb +758 -0
- data/spec/bson/corpus_spec.rb +8 -5
- data/spec/bson/document_spec.rb +29 -29
- data/spec/bson/hash_spec.rb +65 -0
- data/spec/bson/int32_spec.rb +21 -3
- data/spec/bson/int64_spec.rb +22 -3
- data/spec/bson/string_spec.rb +18 -0
- data/spec/support/corpus-tests/array.json +8 -2
- data/spec/support/shared_examples.rb +2 -4
- data/spec/support/utils.rb +10 -0
- metadata +74 -55
- metadata.gz.sig +0 -0
- data/ext/bson/bson_native.c +0 -1344
metadata.gz.sig
CHANGED
Binary file
|
data/ext/bson/bson_native.c
DELETED
@@ -1,1344 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* Copyright (C) 2009-2019 MongoDB Inc.
|
3
|
-
*
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
-
* you may not use this file except in compliance with the License.
|
6
|
-
* You may obtain a copy of the License at
|
7
|
-
*
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
-
*
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
-
* See the License for the specific language governing permissions and
|
14
|
-
* limitations under the License.
|
15
|
-
*/
|
16
|
-
#include <ruby.h>
|
17
|
-
#include <ruby/encoding.h>
|
18
|
-
#include <stdbool.h>
|
19
|
-
#include <time.h>
|
20
|
-
#include <unistd.h>
|
21
|
-
#include "native-endian.h"
|
22
|
-
|
23
|
-
#define BSON_BYTE_BUFFER_SIZE 1024
|
24
|
-
|
25
|
-
#ifndef HOST_NAME_HASH_MAX
|
26
|
-
#define HOST_NAME_HASH_MAX 256
|
27
|
-
#endif
|
28
|
-
|
29
|
-
#define BSON_TYPE_DOUBLE 1
|
30
|
-
#define BSON_TYPE_STRING 2
|
31
|
-
#define BSON_TYPE_OBJECT 3
|
32
|
-
#define BSON_TYPE_ARRAY 4
|
33
|
-
#define BSON_TYPE_INT32 16
|
34
|
-
#define BSON_TYPE_INT64 18
|
35
|
-
#define BSON_TYPE_BOOLEAN 8
|
36
|
-
|
37
|
-
typedef struct {
|
38
|
-
size_t size;
|
39
|
-
size_t write_position;
|
40
|
-
size_t read_position;
|
41
|
-
char buffer[BSON_BYTE_BUFFER_SIZE];
|
42
|
-
char *b_ptr;
|
43
|
-
} byte_buffer_t;
|
44
|
-
|
45
|
-
#define READ_PTR(byte_buffer_ptr) \
|
46
|
-
(byte_buffer_ptr->b_ptr + byte_buffer_ptr->read_position)
|
47
|
-
|
48
|
-
#define READ_SIZE(byte_buffer_ptr) \
|
49
|
-
(byte_buffer_ptr->write_position - byte_buffer_ptr->read_position)
|
50
|
-
|
51
|
-
#define WRITE_PTR(byte_buffer_ptr) \
|
52
|
-
(byte_buffer_ptr->b_ptr + byte_buffer_ptr->write_position)
|
53
|
-
|
54
|
-
#define ENSURE_BSON_WRITE(buffer_ptr, length) \
|
55
|
-
{ if (buffer_ptr->write_position + length > buffer_ptr->size) rb_bson_expand_buffer(buffer_ptr, length); }
|
56
|
-
|
57
|
-
#define ENSURE_BSON_READ(buffer_ptr, length) \
|
58
|
-
{ if (buffer_ptr->read_position + length > buffer_ptr->write_position) \
|
59
|
-
rb_raise(rb_eRangeError, "Attempted to read %zu bytes, but only %zu bytes remain", (size_t)length, READ_SIZE(buffer_ptr)); }
|
60
|
-
|
61
|
-
static VALUE rb_bson_byte_buffer_allocate(VALUE klass);
|
62
|
-
static VALUE rb_bson_byte_buffer_initialize(int argc, VALUE *argv, VALUE self);
|
63
|
-
static VALUE rb_bson_byte_buffer_length(VALUE self);
|
64
|
-
static VALUE rb_bson_byte_buffer_get_byte(VALUE self);
|
65
|
-
static VALUE rb_bson_byte_buffer_get_bytes(VALUE self, VALUE i);
|
66
|
-
static VALUE rb_bson_byte_buffer_get_cstring(VALUE self);
|
67
|
-
static VALUE rb_bson_byte_buffer_get_decimal128_bytes(VALUE self);
|
68
|
-
static VALUE rb_bson_byte_buffer_get_double(VALUE self);
|
69
|
-
static VALUE rb_bson_byte_buffer_get_int32(VALUE self);
|
70
|
-
static VALUE rb_bson_byte_buffer_get_int64(VALUE self);
|
71
|
-
static VALUE rb_bson_byte_buffer_get_string(VALUE self);
|
72
|
-
static VALUE rb_bson_byte_buffer_get_hash(VALUE self);
|
73
|
-
static VALUE rb_bson_byte_buffer_get_array(VALUE self);
|
74
|
-
static VALUE rb_bson_byte_buffer_put_byte(VALUE self, VALUE byte);
|
75
|
-
static VALUE rb_bson_byte_buffer_put_bytes(VALUE self, VALUE bytes);
|
76
|
-
static VALUE rb_bson_byte_buffer_put_bson_partial_string(VALUE self, const char *str, int32_t length);
|
77
|
-
static VALUE rb_bson_byte_buffer_put_cstring(VALUE self, VALUE string);
|
78
|
-
static VALUE rb_bson_byte_buffer_put_decimal128(VALUE self, VALUE low, VALUE high);
|
79
|
-
static VALUE rb_bson_byte_buffer_put_double(VALUE self, VALUE f);
|
80
|
-
static VALUE rb_bson_byte_buffer_put_int32(VALUE self, VALUE i);
|
81
|
-
static VALUE rb_bson_byte_buffer_put_int64(VALUE self, VALUE i);
|
82
|
-
static VALUE rb_bson_byte_buffer_put_bson_string(VALUE self, const char *str, int32_t length);
|
83
|
-
static VALUE rb_bson_byte_buffer_put_string(VALUE self, VALUE string);
|
84
|
-
static VALUE rb_bson_byte_buffer_put_symbol(VALUE self, VALUE symbol);
|
85
|
-
static VALUE rb_bson_byte_buffer_put_hash(VALUE self, VALUE hash, VALUE validating_keys);
|
86
|
-
static VALUE rb_bson_byte_buffer_put_array(VALUE self, VALUE array, VALUE validating_keys);
|
87
|
-
static VALUE rb_bson_byte_buffer_read_position(VALUE self);
|
88
|
-
static VALUE rb_bson_byte_buffer_replace_int32(VALUE self, VALUE index, VALUE i);
|
89
|
-
static VALUE rb_bson_byte_buffer_rewind(VALUE self);
|
90
|
-
static VALUE rb_bson_byte_buffer_write_position(VALUE self);
|
91
|
-
static VALUE rb_bson_byte_buffer_to_s(VALUE self);
|
92
|
-
static VALUE rb_bson_object_id_generator_next(int argc, VALUE* args, VALUE self);
|
93
|
-
|
94
|
-
static size_t rb_bson_byte_buffer_memsize(const void *ptr);
|
95
|
-
static void rb_bson_byte_buffer_free(void *ptr);
|
96
|
-
static void rb_bson_expand_buffer(byte_buffer_t* buffer_ptr, size_t length);
|
97
|
-
static void rb_bson_generate_machine_id(VALUE rb_md5_class, char *rb_bson_machine_id);
|
98
|
-
static bool rb_bson_utf8_validate(const char *utf8, size_t utf8_len, bool allow_null);
|
99
|
-
|
100
|
-
static const rb_data_type_t rb_byte_buffer_data_type = {
|
101
|
-
"bson/byte_buffer",
|
102
|
-
{ NULL, rb_bson_byte_buffer_free, rb_bson_byte_buffer_memsize }
|
103
|
-
};
|
104
|
-
|
105
|
-
static uint8_t pvt_get_type_byte(byte_buffer_t *b);
|
106
|
-
static VALUE pvt_get_int32(byte_buffer_t *b);
|
107
|
-
static VALUE pvt_get_int64(byte_buffer_t *b);
|
108
|
-
static VALUE pvt_get_double(byte_buffer_t *b);
|
109
|
-
static VALUE pvt_get_string(byte_buffer_t *b);
|
110
|
-
static VALUE pvt_get_boolean(byte_buffer_t *b);
|
111
|
-
|
112
|
-
|
113
|
-
static VALUE pvt_read_field(byte_buffer_t *b, VALUE rb_buffer, uint8_t type);
|
114
|
-
static void pvt_replace_int32(byte_buffer_t *b, int32_t position, int32_t newval);
|
115
|
-
static void pvt_skip_cstring(byte_buffer_t *b);
|
116
|
-
static void pvt_validate_length(byte_buffer_t *b);
|
117
|
-
|
118
|
-
|
119
|
-
static void pvt_put_field(byte_buffer_t *b, VALUE rb_buffer, VALUE val, VALUE validating_keys);
|
120
|
-
static void pvt_put_byte(byte_buffer_t *b, const char byte);
|
121
|
-
static void pvt_put_int32(byte_buffer_t *b, const int32_t i32);
|
122
|
-
static void pvt_put_int64(byte_buffer_t *b, const int64_t i);
|
123
|
-
static void pvt_put_double(byte_buffer_t *b, double f);
|
124
|
-
static void pvt_put_cstring(byte_buffer_t *b, const char *str, int32_t length);
|
125
|
-
static void pvt_put_bson_key(byte_buffer_t *b, VALUE string, VALUE validating_keys);
|
126
|
-
|
127
|
-
/**
|
128
|
-
* Holds the machine id hash for object id generation.
|
129
|
-
*/
|
130
|
-
static char rb_bson_machine_id_hash[HOST_NAME_HASH_MAX];
|
131
|
-
|
132
|
-
/**
|
133
|
-
* The counter for incrementing object ids.
|
134
|
-
*/
|
135
|
-
static uint32_t rb_bson_object_id_counter;
|
136
|
-
|
137
|
-
|
138
|
-
static VALUE rb_bson_registry;
|
139
|
-
|
140
|
-
static VALUE rb_bson_illegal_key;
|
141
|
-
/**
|
142
|
-
* Initialize the bson_native extension.
|
143
|
-
*/
|
144
|
-
void Init_bson_native()
|
145
|
-
{
|
146
|
-
char rb_bson_machine_id[256];
|
147
|
-
|
148
|
-
VALUE rb_bson_module = rb_define_module("BSON");
|
149
|
-
VALUE rb_byte_buffer_class = rb_define_class_under(rb_bson_module, "ByteBuffer", rb_cObject);
|
150
|
-
VALUE rb_bson_object_id_class = rb_const_get(rb_bson_module, rb_intern("ObjectId"));
|
151
|
-
VALUE rb_bson_object_id_generator_class = rb_const_get(rb_bson_object_id_class, rb_intern("Generator"));
|
152
|
-
VALUE rb_digest_class = rb_const_get(rb_cObject, rb_intern("Digest"));
|
153
|
-
VALUE rb_md5_class = rb_const_get(rb_digest_class, rb_intern("MD5"));
|
154
|
-
|
155
|
-
rb_bson_illegal_key = rb_const_get(rb_const_get(rb_bson_module, rb_intern("String")),rb_intern("IllegalKey"));
|
156
|
-
|
157
|
-
rb_define_alloc_func(rb_byte_buffer_class, rb_bson_byte_buffer_allocate);
|
158
|
-
rb_define_method(rb_byte_buffer_class, "initialize", rb_bson_byte_buffer_initialize, -1);
|
159
|
-
rb_define_method(rb_byte_buffer_class, "length", rb_bson_byte_buffer_length, 0);
|
160
|
-
rb_define_method(rb_byte_buffer_class, "get_byte", rb_bson_byte_buffer_get_byte, 0);
|
161
|
-
rb_define_method(rb_byte_buffer_class, "get_bytes", rb_bson_byte_buffer_get_bytes, 1);
|
162
|
-
rb_define_method(rb_byte_buffer_class, "get_cstring", rb_bson_byte_buffer_get_cstring, 0);
|
163
|
-
rb_define_method(rb_byte_buffer_class, "get_decimal128_bytes", rb_bson_byte_buffer_get_decimal128_bytes, 0);
|
164
|
-
rb_define_method(rb_byte_buffer_class, "get_double", rb_bson_byte_buffer_get_double, 0);
|
165
|
-
rb_define_method(rb_byte_buffer_class, "get_hash", rb_bson_byte_buffer_get_hash, 0);
|
166
|
-
rb_define_method(rb_byte_buffer_class, "get_array", rb_bson_byte_buffer_get_array, 0);
|
167
|
-
|
168
|
-
rb_define_method(rb_byte_buffer_class, "get_int32", rb_bson_byte_buffer_get_int32, 0);
|
169
|
-
rb_define_method(rb_byte_buffer_class, "get_int64", rb_bson_byte_buffer_get_int64, 0);
|
170
|
-
rb_define_method(rb_byte_buffer_class, "get_string", rb_bson_byte_buffer_get_string, 0);
|
171
|
-
rb_define_method(rb_byte_buffer_class, "put_byte", rb_bson_byte_buffer_put_byte, 1);
|
172
|
-
rb_define_method(rb_byte_buffer_class, "put_bytes", rb_bson_byte_buffer_put_bytes, 1);
|
173
|
-
rb_define_method(rb_byte_buffer_class, "put_cstring", rb_bson_byte_buffer_put_cstring, 1);
|
174
|
-
rb_define_method(rb_byte_buffer_class, "put_decimal128", rb_bson_byte_buffer_put_decimal128, 2);
|
175
|
-
rb_define_method(rb_byte_buffer_class, "put_double", rb_bson_byte_buffer_put_double, 1);
|
176
|
-
rb_define_method(rb_byte_buffer_class, "put_int32", rb_bson_byte_buffer_put_int32, 1);
|
177
|
-
rb_define_method(rb_byte_buffer_class, "put_int64", rb_bson_byte_buffer_put_int64, 1);
|
178
|
-
rb_define_method(rb_byte_buffer_class, "put_string", rb_bson_byte_buffer_put_string, 1);
|
179
|
-
rb_define_method(rb_byte_buffer_class, "put_symbol", rb_bson_byte_buffer_put_symbol, 1);
|
180
|
-
rb_define_method(rb_byte_buffer_class, "read_position", rb_bson_byte_buffer_read_position, 0);
|
181
|
-
rb_define_method(rb_byte_buffer_class, "replace_int32", rb_bson_byte_buffer_replace_int32, 2);
|
182
|
-
rb_define_method(rb_byte_buffer_class, "rewind!", rb_bson_byte_buffer_rewind, 0);
|
183
|
-
rb_define_method(rb_byte_buffer_class, "write_position", rb_bson_byte_buffer_write_position, 0);
|
184
|
-
rb_define_method(rb_byte_buffer_class, "to_s", rb_bson_byte_buffer_to_s, 0);
|
185
|
-
rb_define_method(rb_bson_object_id_generator_class, "next_object_id", rb_bson_object_id_generator_next, -1);
|
186
|
-
|
187
|
-
rb_define_method(rb_byte_buffer_class, "put_hash", rb_bson_byte_buffer_put_hash, 2);
|
188
|
-
rb_define_method(rb_byte_buffer_class, "put_array", rb_bson_byte_buffer_put_array, 2);
|
189
|
-
|
190
|
-
// Get the object id machine id and hash it.
|
191
|
-
rb_require("digest/md5");
|
192
|
-
gethostname(rb_bson_machine_id, sizeof(rb_bson_machine_id));
|
193
|
-
rb_bson_machine_id[255] = '\0';
|
194
|
-
rb_bson_generate_machine_id(rb_md5_class, rb_bson_machine_id);
|
195
|
-
|
196
|
-
// Set the object id counter to a random number
|
197
|
-
rb_bson_object_id_counter = FIX2INT(rb_funcall(rb_mKernel, rb_intern("rand"), 1, INT2FIX(0x1000000)));
|
198
|
-
|
199
|
-
rb_bson_registry = rb_const_get(rb_bson_module, rb_intern("Registry"));
|
200
|
-
}
|
201
|
-
|
202
|
-
void rb_bson_generate_machine_id(VALUE rb_md5_class, char *rb_bson_machine_id)
|
203
|
-
{
|
204
|
-
VALUE digest = rb_funcall(rb_md5_class, rb_intern("digest"), 1, rb_str_new2(rb_bson_machine_id));
|
205
|
-
memcpy(rb_bson_machine_id_hash, RSTRING_PTR(digest), RSTRING_LEN(digest));
|
206
|
-
}
|
207
|
-
|
208
|
-
/**
|
209
|
-
* Allocates a bson byte buffer that wraps a byte_buffer_t.
|
210
|
-
*/
|
211
|
-
VALUE rb_bson_byte_buffer_allocate(VALUE klass)
|
212
|
-
{
|
213
|
-
byte_buffer_t *b;
|
214
|
-
VALUE obj = TypedData_Make_Struct(klass, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
215
|
-
b->b_ptr = b->buffer;
|
216
|
-
b->size = BSON_BYTE_BUFFER_SIZE;
|
217
|
-
return obj;
|
218
|
-
}
|
219
|
-
|
220
|
-
/**
|
221
|
-
* Initialize a byte buffer.
|
222
|
-
*/
|
223
|
-
VALUE rb_bson_byte_buffer_initialize(int argc, VALUE *argv, VALUE self)
|
224
|
-
{
|
225
|
-
VALUE bytes;
|
226
|
-
rb_scan_args(argc, argv, "01", &bytes);
|
227
|
-
|
228
|
-
if (!NIL_P(bytes)) {
|
229
|
-
rb_bson_byte_buffer_put_bytes(self, bytes);
|
230
|
-
}
|
231
|
-
|
232
|
-
return self;
|
233
|
-
}
|
234
|
-
|
235
|
-
static int fits_int32(int64_t i64){
|
236
|
-
return i64 >= INT32_MIN && i64 <= INT32_MAX;
|
237
|
-
}
|
238
|
-
|
239
|
-
/* write the byte denoting the BSON type for the passed object*/
|
240
|
-
void pvt_put_type_byte(byte_buffer_t *b, VALUE val){
|
241
|
-
switch(TYPE(val)){
|
242
|
-
case T_BIGNUM:
|
243
|
-
case T_FIXNUM:
|
244
|
-
if(fits_int32(NUM2LL(val))){
|
245
|
-
pvt_put_byte(b, BSON_TYPE_INT32);
|
246
|
-
}else{
|
247
|
-
pvt_put_byte(b, BSON_TYPE_INT64);
|
248
|
-
}
|
249
|
-
break;
|
250
|
-
case T_STRING:
|
251
|
-
pvt_put_byte(b, BSON_TYPE_STRING);
|
252
|
-
break;
|
253
|
-
case T_ARRAY:
|
254
|
-
pvt_put_byte(b, BSON_TYPE_ARRAY);
|
255
|
-
break;
|
256
|
-
case T_TRUE:
|
257
|
-
case T_FALSE:
|
258
|
-
pvt_put_byte(b, BSON_TYPE_BOOLEAN);
|
259
|
-
break;
|
260
|
-
case T_HASH:
|
261
|
-
pvt_put_byte(b, BSON_TYPE_OBJECT);
|
262
|
-
break;
|
263
|
-
case T_FLOAT:
|
264
|
-
pvt_put_byte(b, BSON_TYPE_DOUBLE);
|
265
|
-
break;
|
266
|
-
default:{
|
267
|
-
VALUE type = rb_funcall(val, rb_intern("bson_type"),0);
|
268
|
-
pvt_put_byte(b, *RSTRING_PTR(type));
|
269
|
-
break;
|
270
|
-
}
|
271
|
-
}
|
272
|
-
}
|
273
|
-
|
274
|
-
void pvt_put_field(byte_buffer_t *b, VALUE rb_buffer, VALUE val, VALUE validating_keys){
|
275
|
-
switch(TYPE(val)){
|
276
|
-
case T_BIGNUM:
|
277
|
-
case T_FIXNUM:{
|
278
|
-
int64_t i64= NUM2LL(val);
|
279
|
-
if(fits_int32(i64)){
|
280
|
-
pvt_put_int32(b, (int32_t)i64);
|
281
|
-
}else{
|
282
|
-
pvt_put_int64(b, i64);
|
283
|
-
}
|
284
|
-
break;
|
285
|
-
}
|
286
|
-
case T_FLOAT:
|
287
|
-
pvt_put_double(b, NUM2DBL(val));
|
288
|
-
break;
|
289
|
-
case T_ARRAY:
|
290
|
-
rb_bson_byte_buffer_put_array(rb_buffer, val, validating_keys);
|
291
|
-
break;
|
292
|
-
case T_TRUE:
|
293
|
-
pvt_put_byte(b, 1);
|
294
|
-
break;
|
295
|
-
case T_FALSE:
|
296
|
-
pvt_put_byte(b, 0);
|
297
|
-
break;
|
298
|
-
case T_HASH:
|
299
|
-
rb_bson_byte_buffer_put_hash(rb_buffer, val, validating_keys);
|
300
|
-
break;
|
301
|
-
default:{
|
302
|
-
rb_funcall(val, rb_intern("to_bson"), 2, rb_buffer, validating_keys);
|
303
|
-
break;
|
304
|
-
}
|
305
|
-
}
|
306
|
-
}
|
307
|
-
|
308
|
-
typedef struct{
|
309
|
-
byte_buffer_t *b;
|
310
|
-
VALUE buffer;
|
311
|
-
VALUE validating_keys;
|
312
|
-
} put_hash_context;
|
313
|
-
|
314
|
-
static int put_hash_callback(VALUE key, VALUE val, VALUE context){
|
315
|
-
VALUE buffer = ((put_hash_context*)context)->buffer;
|
316
|
-
VALUE validating_keys = ((put_hash_context*)context)->validating_keys;
|
317
|
-
byte_buffer_t *b = ((put_hash_context*)context)->b;
|
318
|
-
|
319
|
-
pvt_put_type_byte(b, val);
|
320
|
-
|
321
|
-
switch(TYPE(key)){
|
322
|
-
case T_STRING:
|
323
|
-
pvt_put_bson_key(b, key, validating_keys);
|
324
|
-
break;
|
325
|
-
case T_SYMBOL:
|
326
|
-
pvt_put_bson_key(b, rb_sym_to_s(key), validating_keys);
|
327
|
-
break;
|
328
|
-
default:
|
329
|
-
rb_bson_byte_buffer_put_cstring(buffer, rb_funcall(key, rb_intern("to_bson_key"), 1, validating_keys));
|
330
|
-
}
|
331
|
-
|
332
|
-
pvt_put_field(b, buffer, val, validating_keys);
|
333
|
-
return ST_CONTINUE;
|
334
|
-
}
|
335
|
-
|
336
|
-
/**
|
337
|
-
* serializes a hash into the byte buffer
|
338
|
-
*/
|
339
|
-
VALUE rb_bson_byte_buffer_put_hash(VALUE self, VALUE hash, VALUE validating_keys){
|
340
|
-
byte_buffer_t *b = NULL;
|
341
|
-
put_hash_context context = {0};
|
342
|
-
size_t position = 0;
|
343
|
-
size_t new_position = 0;
|
344
|
-
int32_t new_length = 0;
|
345
|
-
|
346
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
347
|
-
Check_Type(hash, T_HASH);
|
348
|
-
|
349
|
-
position = READ_SIZE(b);
|
350
|
-
|
351
|
-
/* insert length placeholder */
|
352
|
-
pvt_put_int32(b, 0);
|
353
|
-
context.buffer = self;
|
354
|
-
context.validating_keys = validating_keys;
|
355
|
-
context.b = b;
|
356
|
-
|
357
|
-
rb_hash_foreach(hash, put_hash_callback, (VALUE)&context);
|
358
|
-
pvt_put_byte(b, 0);
|
359
|
-
|
360
|
-
/* update length placeholder with actual value */
|
361
|
-
new_position = READ_SIZE(b);
|
362
|
-
new_length = new_position - position;
|
363
|
-
pvt_replace_int32(b, position, new_length);
|
364
|
-
|
365
|
-
return self;
|
366
|
-
}
|
367
|
-
|
368
|
-
static const char *index_strings[] = {
|
369
|
-
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
|
370
|
-
"11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21",
|
371
|
-
"22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32",
|
372
|
-
"33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43",
|
373
|
-
"44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54",
|
374
|
-
"55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65",
|
375
|
-
"66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76",
|
376
|
-
"77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87",
|
377
|
-
"88", "89", "90", "91", "92", "93", "94", "95", "96", "97", "98",
|
378
|
-
"99", "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
|
379
|
-
"110", "111", "112", "113", "114", "115", "116", "117", "118", "119", "120",
|
380
|
-
"121", "122", "123", "124", "125", "126", "127", "128", "129", "130", "131",
|
381
|
-
"132", "133", "134", "135", "136", "137", "138", "139", "140", "141", "142",
|
382
|
-
"143", "144", "145", "146", "147", "148", "149", "150", "151", "152", "153",
|
383
|
-
"154", "155", "156", "157", "158", "159", "160", "161", "162", "163", "164",
|
384
|
-
"165", "166", "167", "168", "169", "170", "171", "172", "173", "174", "175",
|
385
|
-
"176", "177", "178", "179", "180", "181", "182", "183", "184", "185", "186",
|
386
|
-
"187", "188", "189", "190", "191", "192", "193", "194", "195", "196", "197",
|
387
|
-
"198", "199", "200", "201", "202", "203", "204", "205", "206", "207", "208",
|
388
|
-
"209", "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
|
389
|
-
"220", "221", "222", "223", "224", "225", "226", "227", "228", "229", "230",
|
390
|
-
"231", "232", "233", "234", "235", "236", "237", "238", "239", "240", "241",
|
391
|
-
"242", "243", "244", "245", "246", "247", "248", "249", "250", "251", "252",
|
392
|
-
"253", "254", "255", "256", "257", "258", "259", "260", "261", "262", "263",
|
393
|
-
"264", "265", "266", "267", "268", "269", "270", "271", "272", "273", "274",
|
394
|
-
"275", "276", "277", "278", "279", "280", "281", "282", "283", "284", "285",
|
395
|
-
"286", "287", "288", "289", "290", "291", "292", "293", "294", "295", "296",
|
396
|
-
"297", "298", "299", "300", "301", "302", "303", "304", "305", "306", "307",
|
397
|
-
"308", "309", "310", "311", "312", "313", "314", "315", "316", "317", "318",
|
398
|
-
"319", "320", "321", "322", "323", "324", "325", "326", "327", "328", "329",
|
399
|
-
"330", "331", "332", "333", "334", "335", "336", "337", "338", "339", "340",
|
400
|
-
"341", "342", "343", "344", "345", "346", "347", "348", "349", "350", "351",
|
401
|
-
"352", "353", "354", "355", "356", "357", "358", "359", "360", "361", "362",
|
402
|
-
"363", "364", "365", "366", "367", "368", "369", "370", "371", "372", "373",
|
403
|
-
"374", "375", "376", "377", "378", "379", "380", "381", "382", "383", "384",
|
404
|
-
"385", "386", "387", "388", "389", "390", "391", "392", "393", "394", "395",
|
405
|
-
"396", "397", "398", "399", "400", "401", "402", "403", "404", "405", "406",
|
406
|
-
"407", "408", "409", "410", "411", "412", "413", "414", "415", "416", "417",
|
407
|
-
"418", "419", "420", "421", "422", "423", "424", "425", "426", "427", "428",
|
408
|
-
"429", "430", "431", "432", "433", "434", "435", "436", "437", "438", "439",
|
409
|
-
"440", "441", "442", "443", "444", "445", "446", "447", "448", "449", "450",
|
410
|
-
"451", "452", "453", "454", "455", "456", "457", "458", "459", "460", "461",
|
411
|
-
"462", "463", "464", "465", "466", "467", "468", "469", "470", "471", "472",
|
412
|
-
"473", "474", "475", "476", "477", "478", "479", "480", "481", "482", "483",
|
413
|
-
"484", "485", "486", "487", "488", "489", "490", "491", "492", "493", "494",
|
414
|
-
"495", "496", "497", "498", "499", "500", "501", "502", "503", "504", "505",
|
415
|
-
"506", "507", "508", "509", "510", "511", "512", "513", "514", "515", "516",
|
416
|
-
"517", "518", "519", "520", "521", "522", "523", "524", "525", "526", "527",
|
417
|
-
"528", "529", "530", "531", "532", "533", "534", "535", "536", "537", "538",
|
418
|
-
"539", "540", "541", "542", "543", "544", "545", "546", "547", "548", "549",
|
419
|
-
"550", "551", "552", "553", "554", "555", "556", "557", "558", "559", "560",
|
420
|
-
"561", "562", "563", "564", "565", "566", "567", "568", "569", "570", "571",
|
421
|
-
"572", "573", "574", "575", "576", "577", "578", "579", "580", "581", "582",
|
422
|
-
"583", "584", "585", "586", "587", "588", "589", "590", "591", "592", "593",
|
423
|
-
"594", "595", "596", "597", "598", "599", "600", "601", "602", "603", "604",
|
424
|
-
"605", "606", "607", "608", "609", "610", "611", "612", "613", "614", "615",
|
425
|
-
"616", "617", "618", "619", "620", "621", "622", "623", "624", "625", "626",
|
426
|
-
"627", "628", "629", "630", "631", "632", "633", "634", "635", "636", "637",
|
427
|
-
"638", "639", "640", "641", "642", "643", "644", "645", "646", "647", "648",
|
428
|
-
"649", "650", "651", "652", "653", "654", "655", "656", "657", "658", "659",
|
429
|
-
"660", "661", "662", "663", "664", "665", "666", "667", "668", "669", "670",
|
430
|
-
"671", "672", "673", "674", "675", "676", "677", "678", "679", "680", "681",
|
431
|
-
"682", "683", "684", "685", "686", "687", "688", "689", "690", "691", "692",
|
432
|
-
"693", "694", "695", "696", "697", "698", "699", "700", "701", "702", "703",
|
433
|
-
"704", "705", "706", "707", "708", "709", "710", "711", "712", "713", "714",
|
434
|
-
"715", "716", "717", "718", "719", "720", "721", "722", "723", "724", "725",
|
435
|
-
"726", "727", "728", "729", "730", "731", "732", "733", "734", "735", "736",
|
436
|
-
"737", "738", "739", "740", "741", "742", "743", "744", "745", "746", "747",
|
437
|
-
"748", "749", "750", "751", "752", "753", "754", "755", "756", "757", "758",
|
438
|
-
"759", "760", "761", "762", "763", "764", "765", "766", "767", "768", "769",
|
439
|
-
"770", "771", "772", "773", "774", "775", "776", "777", "778", "779", "780",
|
440
|
-
"781", "782", "783", "784", "785", "786", "787", "788", "789", "790", "791",
|
441
|
-
"792", "793", "794", "795", "796", "797", "798", "799", "800", "801", "802",
|
442
|
-
"803", "804", "805", "806", "807", "808", "809", "810", "811", "812", "813",
|
443
|
-
"814", "815", "816", "817", "818", "819", "820", "821", "822", "823", "824",
|
444
|
-
"825", "826", "827", "828", "829", "830", "831", "832", "833", "834", "835",
|
445
|
-
"836", "837", "838", "839", "840", "841", "842", "843", "844", "845", "846",
|
446
|
-
"847", "848", "849", "850", "851", "852", "853", "854", "855", "856", "857",
|
447
|
-
"858", "859", "860", "861", "862", "863", "864", "865", "866", "867", "868",
|
448
|
-
"869", "870", "871", "872", "873", "874", "875", "876", "877", "878", "879",
|
449
|
-
"880", "881", "882", "883", "884", "885", "886", "887", "888", "889", "890",
|
450
|
-
"891", "892", "893", "894", "895", "896", "897", "898", "899", "900", "901",
|
451
|
-
"902", "903", "904", "905", "906", "907", "908", "909", "910", "911", "912",
|
452
|
-
"913", "914", "915", "916", "917", "918", "919", "920", "921", "922", "923",
|
453
|
-
"924", "925", "926", "927", "928", "929", "930", "931", "932", "933", "934",
|
454
|
-
"935", "936", "937", "938", "939", "940", "941", "942", "943", "944", "945",
|
455
|
-
"946", "947", "948", "949", "950", "951", "952", "953", "954", "955", "956",
|
456
|
-
"957", "958", "959", "960", "961", "962", "963", "964", "965", "966", "967",
|
457
|
-
"968", "969", "970", "971", "972", "973", "974", "975", "976", "977", "978",
|
458
|
-
"979", "980", "981", "982", "983", "984", "985", "986", "987", "988", "989",
|
459
|
-
"990", "991", "992", "993", "994", "995", "996", "997", "998", "999"};
|
460
|
-
|
461
|
-
/**
|
462
|
-
* Writes an array index to the byte buffer.
|
463
|
-
*/
|
464
|
-
void pvt_put_array_index(byte_buffer_t *b, int32_t index)
|
465
|
-
{
|
466
|
-
char buffer[16];
|
467
|
-
const char *c_str = NULL;
|
468
|
-
size_t length;
|
469
|
-
|
470
|
-
if (index < 1000) {
|
471
|
-
c_str = index_strings[index];
|
472
|
-
} else {
|
473
|
-
c_str = buffer;
|
474
|
-
snprintf(buffer, sizeof(buffer), "%d", index);
|
475
|
-
}
|
476
|
-
length = strlen(c_str) + 1;
|
477
|
-
ENSURE_BSON_WRITE(b, length);
|
478
|
-
memcpy(WRITE_PTR(b), c_str, length);
|
479
|
-
b->write_position += length;
|
480
|
-
}
|
481
|
-
|
482
|
-
/**
|
483
|
-
* serializes an array into the byte buffer
|
484
|
-
*/
|
485
|
-
VALUE rb_bson_byte_buffer_put_array(VALUE self, VALUE array, VALUE validating_keys){
|
486
|
-
byte_buffer_t *b = NULL;
|
487
|
-
size_t new_position = 0;
|
488
|
-
int32_t new_length = 0;
|
489
|
-
size_t position = 0;
|
490
|
-
VALUE *array_element = NULL;
|
491
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
492
|
-
Check_Type(array, T_ARRAY);
|
493
|
-
|
494
|
-
position = READ_SIZE(b);
|
495
|
-
/* insert length placeholder */
|
496
|
-
pvt_put_int32(b, 0);
|
497
|
-
|
498
|
-
array_element = RARRAY_PTR(array);
|
499
|
-
|
500
|
-
for(int32_t index=0; index < RARRAY_LEN(array); index++, array_element++){
|
501
|
-
pvt_put_type_byte(b, *array_element);
|
502
|
-
pvt_put_array_index(b,index);
|
503
|
-
pvt_put_field(b, self, *array_element, validating_keys);
|
504
|
-
}
|
505
|
-
pvt_put_byte(b, 0);
|
506
|
-
|
507
|
-
/* update length placeholder */
|
508
|
-
new_position = READ_SIZE(b);
|
509
|
-
new_length = new_position - position;
|
510
|
-
pvt_replace_int32(b, position, new_length);
|
511
|
-
|
512
|
-
return self;
|
513
|
-
}
|
514
|
-
|
515
|
-
/**
|
516
|
-
* Get the length of the buffer.
|
517
|
-
*/
|
518
|
-
VALUE rb_bson_byte_buffer_length(VALUE self)
|
519
|
-
{
|
520
|
-
byte_buffer_t *b;
|
521
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
522
|
-
return UINT2NUM(READ_SIZE(b));
|
523
|
-
}
|
524
|
-
|
525
|
-
/**
|
526
|
-
* Get a single byte from the buffer.
|
527
|
-
*/
|
528
|
-
VALUE rb_bson_byte_buffer_get_byte(VALUE self)
|
529
|
-
{
|
530
|
-
byte_buffer_t *b;
|
531
|
-
VALUE byte;
|
532
|
-
|
533
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
534
|
-
ENSURE_BSON_READ(b, 1);
|
535
|
-
byte = rb_str_new(READ_PTR(b), 1);
|
536
|
-
b->read_position += 1;
|
537
|
-
return byte;
|
538
|
-
}
|
539
|
-
|
540
|
-
uint8_t pvt_get_type_byte(byte_buffer_t *b){
|
541
|
-
int8_t byte;
|
542
|
-
ENSURE_BSON_READ(b, 1);
|
543
|
-
byte = *READ_PTR(b);
|
544
|
-
b->read_position += 1;
|
545
|
-
return (uint8_t)byte;
|
546
|
-
}
|
547
|
-
|
548
|
-
/**
|
549
|
-
* Get bytes from the buffer.
|
550
|
-
*/
|
551
|
-
VALUE rb_bson_byte_buffer_get_bytes(VALUE self, VALUE i)
|
552
|
-
{
|
553
|
-
byte_buffer_t *b;
|
554
|
-
VALUE bytes;
|
555
|
-
const uint32_t length = FIX2LONG(i);
|
556
|
-
|
557
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
558
|
-
ENSURE_BSON_READ(b, length);
|
559
|
-
bytes = rb_str_new(READ_PTR(b), length);
|
560
|
-
b->read_position += length;
|
561
|
-
return bytes;
|
562
|
-
}
|
563
|
-
|
564
|
-
VALUE pvt_get_boolean(byte_buffer_t *b){
|
565
|
-
VALUE result = Qnil;
|
566
|
-
ENSURE_BSON_READ(b, 1);
|
567
|
-
result = *READ_PTR(b) == 1 ? Qtrue: Qfalse;
|
568
|
-
b->read_position += 1;
|
569
|
-
return result;
|
570
|
-
}
|
571
|
-
|
572
|
-
/**
|
573
|
-
* Get a cstring from the buffer.
|
574
|
-
*/
|
575
|
-
VALUE rb_bson_byte_buffer_get_cstring(VALUE self)
|
576
|
-
{
|
577
|
-
byte_buffer_t *b;
|
578
|
-
VALUE string;
|
579
|
-
int length;
|
580
|
-
|
581
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
582
|
-
length = (int)strlen(READ_PTR(b));
|
583
|
-
ENSURE_BSON_READ(b, length);
|
584
|
-
string = rb_enc_str_new(READ_PTR(b), length, rb_utf8_encoding());
|
585
|
-
b->read_position += length + 1;
|
586
|
-
return string;
|
587
|
-
}
|
588
|
-
|
589
|
-
/**
|
590
|
-
* Reads but does not return a cstring from the buffer.
|
591
|
-
*/
|
592
|
-
void pvt_skip_cstring(byte_buffer_t *b)
|
593
|
-
{
|
594
|
-
int length;
|
595
|
-
length = (int)strlen(READ_PTR(b));
|
596
|
-
ENSURE_BSON_READ(b, length);
|
597
|
-
b->read_position += length + 1;
|
598
|
-
}
|
599
|
-
|
600
|
-
/**
|
601
|
-
* Get the 16 bytes representing the decimal128 from the buffer.
|
602
|
-
*/
|
603
|
-
VALUE rb_bson_byte_buffer_get_decimal128_bytes(VALUE self)
|
604
|
-
{
|
605
|
-
byte_buffer_t *b;
|
606
|
-
VALUE bytes;
|
607
|
-
|
608
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
609
|
-
ENSURE_BSON_READ(b, 16);
|
610
|
-
bytes = rb_str_new(READ_PTR(b), 16);
|
611
|
-
b->read_position += 16;
|
612
|
-
return bytes;
|
613
|
-
}
|
614
|
-
|
615
|
-
/**
|
616
|
-
* Get a double from the buffer.
|
617
|
-
*/
|
618
|
-
VALUE rb_bson_byte_buffer_get_double(VALUE self)
|
619
|
-
{
|
620
|
-
byte_buffer_t *b;
|
621
|
-
|
622
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
623
|
-
return pvt_get_double(b);
|
624
|
-
}
|
625
|
-
|
626
|
-
VALUE pvt_get_double(byte_buffer_t *b)
|
627
|
-
{
|
628
|
-
double d;
|
629
|
-
|
630
|
-
ENSURE_BSON_READ(b, 8);
|
631
|
-
memcpy(&d, READ_PTR(b), 8);
|
632
|
-
b->read_position += 8;
|
633
|
-
return DBL2NUM(BSON_DOUBLE_FROM_LE(d));
|
634
|
-
}
|
635
|
-
|
636
|
-
/**
|
637
|
-
* Get a int32 from the buffer.
|
638
|
-
*/
|
639
|
-
VALUE rb_bson_byte_buffer_get_int32(VALUE self)
|
640
|
-
{
|
641
|
-
byte_buffer_t *b;
|
642
|
-
|
643
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
644
|
-
return pvt_get_int32(b);
|
645
|
-
}
|
646
|
-
|
647
|
-
VALUE pvt_get_int32(byte_buffer_t *b)
|
648
|
-
{
|
649
|
-
int32_t i32;
|
650
|
-
|
651
|
-
ENSURE_BSON_READ(b, 4);
|
652
|
-
memcpy(&i32, READ_PTR(b), 4);
|
653
|
-
b->read_position += 4;
|
654
|
-
return INT2NUM(BSON_UINT32_FROM_LE(i32));
|
655
|
-
}
|
656
|
-
|
657
|
-
/**
|
658
|
-
* Get a int64 from the buffer.
|
659
|
-
*/
|
660
|
-
VALUE rb_bson_byte_buffer_get_int64(VALUE self)
|
661
|
-
{
|
662
|
-
byte_buffer_t *b;
|
663
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
664
|
-
return pvt_get_int64(b);
|
665
|
-
}
|
666
|
-
|
667
|
-
VALUE pvt_get_int64(byte_buffer_t *b)
|
668
|
-
{
|
669
|
-
int64_t i64;
|
670
|
-
|
671
|
-
ENSURE_BSON_READ(b, 8);
|
672
|
-
memcpy(&i64, READ_PTR(b), 8);
|
673
|
-
b->read_position += 8;
|
674
|
-
return LL2NUM(BSON_UINT64_FROM_LE(i64));
|
675
|
-
}
|
676
|
-
|
677
|
-
/**
|
678
|
-
* Get a string from the buffer.
|
679
|
-
*/
|
680
|
-
VALUE rb_bson_byte_buffer_get_string(VALUE self)
|
681
|
-
{
|
682
|
-
byte_buffer_t *b;
|
683
|
-
|
684
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
685
|
-
return pvt_get_string(b);
|
686
|
-
}
|
687
|
-
|
688
|
-
VALUE pvt_get_string(byte_buffer_t *b)
|
689
|
-
{
|
690
|
-
int32_t length;
|
691
|
-
int32_t length_le;
|
692
|
-
VALUE string;
|
693
|
-
|
694
|
-
ENSURE_BSON_READ(b, 4);
|
695
|
-
memcpy(&length, READ_PTR(b), 4);
|
696
|
-
length_le = BSON_UINT32_FROM_LE(length);
|
697
|
-
b->read_position += 4;
|
698
|
-
ENSURE_BSON_READ(b, length_le);
|
699
|
-
string = rb_enc_str_new(READ_PTR(b), length_le - 1, rb_utf8_encoding());
|
700
|
-
b->read_position += length_le;
|
701
|
-
return string;
|
702
|
-
}
|
703
|
-
|
704
|
-
|
705
|
-
VALUE rb_bson_byte_buffer_get_hash(VALUE self){
|
706
|
-
VALUE doc = Qnil;
|
707
|
-
byte_buffer_t *b=NULL;
|
708
|
-
uint8_t type;
|
709
|
-
VALUE cDocument = rb_const_get(rb_const_get(rb_cObject, rb_intern("BSON")), rb_intern("Document"));
|
710
|
-
|
711
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
712
|
-
|
713
|
-
pvt_validate_length(b);
|
714
|
-
|
715
|
-
doc = rb_funcall(cDocument, rb_intern("allocate"),0);
|
716
|
-
|
717
|
-
while((type = pvt_get_type_byte(b)) != 0){
|
718
|
-
VALUE field = rb_bson_byte_buffer_get_cstring(self);
|
719
|
-
rb_hash_aset(doc, field, pvt_read_field(b, self, type));
|
720
|
-
}
|
721
|
-
return doc;
|
722
|
-
}
|
723
|
-
|
724
|
-
VALUE rb_bson_byte_buffer_get_array(VALUE self){
|
725
|
-
byte_buffer_t *b;
|
726
|
-
VALUE array = Qnil;
|
727
|
-
uint8_t type;
|
728
|
-
|
729
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
730
|
-
|
731
|
-
pvt_validate_length(b);
|
732
|
-
|
733
|
-
array = rb_ary_new();
|
734
|
-
while((type = pvt_get_type_byte(b)) != 0){
|
735
|
-
pvt_skip_cstring(b);
|
736
|
-
rb_ary_push(array, pvt_read_field(b, self, type));
|
737
|
-
}
|
738
|
-
return array;
|
739
|
-
}
|
740
|
-
|
741
|
-
/**
|
742
|
-
* Read a single field from a hash or array
|
743
|
-
*/
|
744
|
-
VALUE pvt_read_field(byte_buffer_t *b, VALUE rb_buffer, uint8_t type){
|
745
|
-
switch(type) {
|
746
|
-
case BSON_TYPE_INT32: return pvt_get_int32(b);
|
747
|
-
case BSON_TYPE_INT64: return pvt_get_int64(b);
|
748
|
-
case BSON_TYPE_DOUBLE: return pvt_get_double(b);
|
749
|
-
case BSON_TYPE_STRING: return pvt_get_string(b);
|
750
|
-
case BSON_TYPE_ARRAY: return rb_bson_byte_buffer_get_array(rb_buffer);
|
751
|
-
case BSON_TYPE_OBJECT: return rb_bson_byte_buffer_get_hash(rb_buffer);
|
752
|
-
case BSON_TYPE_BOOLEAN: return pvt_get_boolean(b);
|
753
|
-
default:
|
754
|
-
{
|
755
|
-
VALUE klass = rb_funcall(rb_bson_registry,rb_intern("get"),1, INT2FIX(type));
|
756
|
-
VALUE value = rb_funcall(klass, rb_intern("from_bson"),1, rb_buffer);
|
757
|
-
return value;
|
758
|
-
}
|
759
|
-
}
|
760
|
-
}
|
761
|
-
|
762
|
-
/**
|
763
|
-
* Writes a byte to the byte buffer.
|
764
|
-
*/
|
765
|
-
VALUE rb_bson_byte_buffer_put_byte(VALUE self, VALUE byte)
|
766
|
-
{
|
767
|
-
byte_buffer_t *b;
|
768
|
-
const char *str;
|
769
|
-
|
770
|
-
if (!RB_TYPE_P(byte, T_STRING))
|
771
|
-
rb_raise(rb_eArgError, "Invalid input");
|
772
|
-
|
773
|
-
str = RSTRING_PTR(byte);
|
774
|
-
|
775
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
776
|
-
ENSURE_BSON_WRITE(b, 1);
|
777
|
-
memcpy(WRITE_PTR(b), str, 1);
|
778
|
-
b->write_position += 1;
|
779
|
-
|
780
|
-
return self;
|
781
|
-
}
|
782
|
-
|
783
|
-
void pvt_put_byte( byte_buffer_t *b, const char byte)
|
784
|
-
{
|
785
|
-
ENSURE_BSON_WRITE(b, 1);
|
786
|
-
*WRITE_PTR(b) = byte;
|
787
|
-
b->write_position += 1;
|
788
|
-
|
789
|
-
}
|
790
|
-
/**
|
791
|
-
* Writes bytes to the byte buffer.
|
792
|
-
*/
|
793
|
-
VALUE rb_bson_byte_buffer_put_bytes(VALUE self, VALUE bytes)
|
794
|
-
{
|
795
|
-
byte_buffer_t *b;
|
796
|
-
const char *str;
|
797
|
-
size_t length;
|
798
|
-
|
799
|
-
if (!RB_TYPE_P(bytes, T_STRING) && !RB_TYPE_P(bytes, RUBY_T_DATA))
|
800
|
-
rb_raise(rb_eArgError, "Invalid input");
|
801
|
-
|
802
|
-
str = RSTRING_PTR(bytes);
|
803
|
-
length = RSTRING_LEN(bytes);
|
804
|
-
|
805
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
806
|
-
ENSURE_BSON_WRITE(b, length);
|
807
|
-
memcpy(WRITE_PTR(b), str, length);
|
808
|
-
b->write_position += length;
|
809
|
-
return self;
|
810
|
-
}
|
811
|
-
|
812
|
-
/**
|
813
|
-
* Writes a string (which may form part of a BSON object) to the byte buffer.
|
814
|
-
* length does not include the null terminator.
|
815
|
-
*/
|
816
|
-
VALUE rb_bson_byte_buffer_put_bson_partial_string(VALUE self, const char *str, int32_t length)
|
817
|
-
{
|
818
|
-
byte_buffer_t *b;
|
819
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
820
|
-
pvt_put_cstring(b, str, length);
|
821
|
-
return self;
|
822
|
-
}
|
823
|
-
|
824
|
-
/**
|
825
|
-
* length does not include the null terminator.
|
826
|
-
*/
|
827
|
-
void pvt_put_cstring(byte_buffer_t *b, const char *str, int32_t length)
|
828
|
-
{
|
829
|
-
int bytes_to_write;
|
830
|
-
if (!rb_bson_utf8_validate(str, length, false)) {
|
831
|
-
rb_raise(rb_eArgError, "String %s is not a valid UTF-8 CString.", str);
|
832
|
-
}
|
833
|
-
bytes_to_write = length + 1;
|
834
|
-
ENSURE_BSON_WRITE(b, bytes_to_write);
|
835
|
-
memcpy(WRITE_PTR(b), str, bytes_to_write);
|
836
|
-
b->write_position += bytes_to_write;
|
837
|
-
}
|
838
|
-
|
839
|
-
/**
|
840
|
-
* Write a hash key to the byte buffer, validating it if requested
|
841
|
-
*/
|
842
|
-
void pvt_put_bson_key(byte_buffer_t *b, VALUE string, VALUE validating_keys){
|
843
|
-
char *c_str = RSTRING_PTR(string);
|
844
|
-
size_t length = RSTRING_LEN(string);
|
845
|
-
|
846
|
-
if (RTEST(validating_keys)) {
|
847
|
-
if (length > 0 && (c_str[0] == '$' || memchr(c_str, '.', length))) {
|
848
|
-
rb_exc_raise(rb_funcall(rb_bson_illegal_key, rb_intern("new"), 1, string));
|
849
|
-
}
|
850
|
-
}
|
851
|
-
|
852
|
-
pvt_put_cstring(b, c_str, length);
|
853
|
-
}
|
854
|
-
|
855
|
-
/**
|
856
|
-
* Writes a cstring to the byte buffer.
|
857
|
-
* This magically supports both Ruby symbols and strings.
|
858
|
-
*/
|
859
|
-
VALUE rb_bson_byte_buffer_put_cstring(VALUE self, VALUE string)
|
860
|
-
{
|
861
|
-
int32_t length;
|
862
|
-
|
863
|
-
if (TYPE(string) == T_SYMBOL) {
|
864
|
-
const char *sym = rb_id2name(SYM2ID(string));
|
865
|
-
length = strlen(sym);
|
866
|
-
|
867
|
-
return rb_bson_byte_buffer_put_bson_partial_string(self, sym, length);
|
868
|
-
} else if (TYPE(string) == T_STRING) {
|
869
|
-
const char *str = RSTRING_PTR(string);
|
870
|
-
length = RSTRING_LEN(string);
|
871
|
-
|
872
|
-
return rb_bson_byte_buffer_put_bson_partial_string(self, str, length);
|
873
|
-
} else if (TYPE(string) == T_FIXNUM) {
|
874
|
-
const char *str = RSTRING_PTR(rb_fix2str(string, 10));
|
875
|
-
length = strlen(str);
|
876
|
-
|
877
|
-
return rb_bson_byte_buffer_put_bson_partial_string(self, str, length);
|
878
|
-
} else {
|
879
|
-
rb_raise(rb_eTypeError, "Invalid type for string");
|
880
|
-
}
|
881
|
-
}
|
882
|
-
|
883
|
-
/**
|
884
|
-
* Writes a 128 bit decimal to the byte buffer.
|
885
|
-
*/
|
886
|
-
VALUE rb_bson_byte_buffer_put_decimal128(VALUE self, VALUE low, VALUE high)
|
887
|
-
{
|
888
|
-
byte_buffer_t *b;
|
889
|
-
const int64_t low64 = BSON_UINT64_TO_LE(NUM2ULL(low));
|
890
|
-
const int64_t high64 = BSON_UINT64_TO_LE(NUM2ULL(high));
|
891
|
-
|
892
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
893
|
-
ENSURE_BSON_WRITE(b, 8);
|
894
|
-
memcpy(WRITE_PTR(b), &low64, 8);
|
895
|
-
b->write_position += 8;
|
896
|
-
|
897
|
-
ENSURE_BSON_WRITE(b, 8);
|
898
|
-
memcpy(WRITE_PTR(b), &high64, 8);
|
899
|
-
b->write_position += 8;
|
900
|
-
|
901
|
-
return self;
|
902
|
-
}
|
903
|
-
|
904
|
-
/**
|
905
|
-
* Writes a 64 bit double to the buffer.
|
906
|
-
*/
|
907
|
-
VALUE rb_bson_byte_buffer_put_double(VALUE self, VALUE f)
|
908
|
-
{
|
909
|
-
byte_buffer_t *b;
|
910
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
911
|
-
pvt_put_double(b,NUM2DBL(f));
|
912
|
-
|
913
|
-
return self;
|
914
|
-
}
|
915
|
-
|
916
|
-
void pvt_put_double(byte_buffer_t *b, double f)
|
917
|
-
{
|
918
|
-
const double d = BSON_DOUBLE_TO_LE(f);
|
919
|
-
ENSURE_BSON_WRITE(b, 8);
|
920
|
-
memcpy(WRITE_PTR(b), &d, 8);
|
921
|
-
b->write_position += 8;
|
922
|
-
}
|
923
|
-
|
924
|
-
/**
|
925
|
-
* Writes a 32 bit integer to the byte buffer.
|
926
|
-
*/
|
927
|
-
VALUE rb_bson_byte_buffer_put_int32(VALUE self, VALUE i)
|
928
|
-
{
|
929
|
-
byte_buffer_t *b;
|
930
|
-
const int32_t i32 = NUM2INT(i);
|
931
|
-
|
932
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
933
|
-
pvt_put_int32(b, i32);
|
934
|
-
return self;
|
935
|
-
}
|
936
|
-
|
937
|
-
void pvt_put_int32(byte_buffer_t *b, const int32_t i)
|
938
|
-
{
|
939
|
-
const int32_t i32 = BSON_UINT32_TO_LE(i);
|
940
|
-
ENSURE_BSON_WRITE(b, 4);
|
941
|
-
memcpy(WRITE_PTR(b), &i32, 4);
|
942
|
-
b->write_position += 4;
|
943
|
-
}
|
944
|
-
|
945
|
-
/**
|
946
|
-
* Writes a 64 bit integer to the byte buffer.
|
947
|
-
*/
|
948
|
-
VALUE rb_bson_byte_buffer_put_int64(VALUE self, VALUE i)
|
949
|
-
{
|
950
|
-
byte_buffer_t *b;
|
951
|
-
const int64_t i64 = NUM2LL(i);
|
952
|
-
|
953
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
954
|
-
pvt_put_int64(b, i64);
|
955
|
-
|
956
|
-
return self;
|
957
|
-
}
|
958
|
-
|
959
|
-
void pvt_put_int64(byte_buffer_t *b, const int64_t i)
|
960
|
-
{
|
961
|
-
const int64_t i64 = BSON_UINT64_TO_LE(i);
|
962
|
-
|
963
|
-
ENSURE_BSON_WRITE(b, 8);
|
964
|
-
memcpy(WRITE_PTR(b), &i64, 8);
|
965
|
-
b->write_position += 8;
|
966
|
-
|
967
|
-
}
|
968
|
-
|
969
|
-
/**
|
970
|
-
* validate the buffer contains the amount of bytes the array / hash claimns
|
971
|
-
* and that it is null terminated
|
972
|
-
*/
|
973
|
-
void pvt_validate_length(byte_buffer_t *b)
|
974
|
-
{
|
975
|
-
int32_t length;
|
976
|
-
|
977
|
-
ENSURE_BSON_READ(b, 4);
|
978
|
-
memcpy(&length, READ_PTR(b), 4);
|
979
|
-
length = BSON_UINT32_TO_LE(length);
|
980
|
-
|
981
|
-
/* minimum valid length is 4 (byte count) + 1 (terminating byte) */
|
982
|
-
if(length >= 5){
|
983
|
-
ENSURE_BSON_READ(b, length);
|
984
|
-
|
985
|
-
/* The last byte should be a null byte: it should be at length - 1 */
|
986
|
-
if( *(READ_PTR(b) + length - 1) != 0 ){
|
987
|
-
rb_raise(rb_eRangeError, "Buffer should have contained null terminator at %zu but contained %d", b->read_position + (size_t)length, (int)*(READ_PTR(b) + length));
|
988
|
-
}
|
989
|
-
b->read_position += 4;
|
990
|
-
}
|
991
|
-
else{
|
992
|
-
rb_raise(rb_eRangeError, "Buffer contained invalid length %d at %zu", length, b->read_position);
|
993
|
-
}
|
994
|
-
}
|
995
|
-
|
996
|
-
/**
|
997
|
-
* Write BSON string to byte buffer given a C string.
|
998
|
-
* length is inclusive of the NULL terminator in the C string.
|
999
|
-
*/
|
1000
|
-
static VALUE rb_bson_byte_buffer_put_bson_string(VALUE self, const char *str, int32_t length)
|
1001
|
-
{
|
1002
|
-
byte_buffer_t *b;
|
1003
|
-
int32_t length_le;
|
1004
|
-
|
1005
|
-
if (length <= 0) {
|
1006
|
-
rb_raise(rb_eArgError, "The length must include the NULL terminator, and thus be at least 1");
|
1007
|
-
}
|
1008
|
-
|
1009
|
-
length_le = BSON_UINT32_TO_LE(length);
|
1010
|
-
|
1011
|
-
if (!rb_bson_utf8_validate(str, length - 1, true)) {
|
1012
|
-
rb_raise(rb_eArgError, "String %s is not valid UTF-8.", str);
|
1013
|
-
}
|
1014
|
-
|
1015
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
1016
|
-
ENSURE_BSON_WRITE(b, length + 4);
|
1017
|
-
memcpy(WRITE_PTR(b), &length_le, 4);
|
1018
|
-
b->write_position += 4;
|
1019
|
-
memcpy(WRITE_PTR(b), str, length);
|
1020
|
-
b->write_position += length;
|
1021
|
-
|
1022
|
-
return self;
|
1023
|
-
}
|
1024
|
-
|
1025
|
-
/**
|
1026
|
-
* Writes a string to the byte buffer.
|
1027
|
-
*/
|
1028
|
-
VALUE rb_bson_byte_buffer_put_string(VALUE self, VALUE string)
|
1029
|
-
{
|
1030
|
-
const char *str = RSTRING_PTR(string);
|
1031
|
-
const int32_t length = RSTRING_LEN(string) + 1;
|
1032
|
-
|
1033
|
-
return rb_bson_byte_buffer_put_bson_string(self, str, length);
|
1034
|
-
}
|
1035
|
-
|
1036
|
-
/**
|
1037
|
-
* Writes a symbol to the byte buffer.
|
1038
|
-
*/
|
1039
|
-
VALUE rb_bson_byte_buffer_put_symbol(VALUE self, VALUE symbol)
|
1040
|
-
{
|
1041
|
-
const char *sym = rb_id2name(SYM2ID(symbol));
|
1042
|
-
const int32_t length = strlen(sym) + 1;
|
1043
|
-
|
1044
|
-
return rb_bson_byte_buffer_put_bson_string(self, sym, length);
|
1045
|
-
}
|
1046
|
-
|
1047
|
-
/**
|
1048
|
-
* Get the read position.
|
1049
|
-
*/
|
1050
|
-
VALUE rb_bson_byte_buffer_read_position(VALUE self)
|
1051
|
-
{
|
1052
|
-
byte_buffer_t *b;
|
1053
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
1054
|
-
return INT2NUM(b->read_position);
|
1055
|
-
}
|
1056
|
-
|
1057
|
-
/**
|
1058
|
-
* Replace a 32 bit integer int the byte buffer.
|
1059
|
-
*/
|
1060
|
-
VALUE rb_bson_byte_buffer_replace_int32(VALUE self, VALUE index, VALUE i)
|
1061
|
-
{
|
1062
|
-
byte_buffer_t *b;
|
1063
|
-
|
1064
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
1065
|
-
pvt_replace_int32(b, NUM2LONG(index), NUM2LONG(i));
|
1066
|
-
|
1067
|
-
return self;
|
1068
|
-
}
|
1069
|
-
|
1070
|
-
void pvt_replace_int32(byte_buffer_t *b, int32_t position, int32_t newval)
|
1071
|
-
{
|
1072
|
-
const int32_t i32 = BSON_UINT32_TO_LE(newval);
|
1073
|
-
memcpy(READ_PTR(b) + position, &i32, 4);
|
1074
|
-
}
|
1075
|
-
|
1076
|
-
/**
|
1077
|
-
* Reset the read position to the beginning of the byte buffer.
|
1078
|
-
*/
|
1079
|
-
VALUE rb_bson_byte_buffer_rewind(VALUE self)
|
1080
|
-
{
|
1081
|
-
byte_buffer_t *b;
|
1082
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
1083
|
-
b->read_position = 0;
|
1084
|
-
|
1085
|
-
return self;
|
1086
|
-
}
|
1087
|
-
|
1088
|
-
/**
|
1089
|
-
* Get the write position.
|
1090
|
-
*/
|
1091
|
-
VALUE rb_bson_byte_buffer_write_position(VALUE self)
|
1092
|
-
{
|
1093
|
-
byte_buffer_t *b;
|
1094
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
1095
|
-
return INT2NUM(b->write_position);
|
1096
|
-
}
|
1097
|
-
|
1098
|
-
/**
|
1099
|
-
* Convert the buffer to a string.
|
1100
|
-
*/
|
1101
|
-
VALUE rb_bson_byte_buffer_to_s(VALUE self)
|
1102
|
-
{
|
1103
|
-
byte_buffer_t *b;
|
1104
|
-
TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
|
1105
|
-
return rb_str_new(READ_PTR(b), READ_SIZE(b));
|
1106
|
-
}
|
1107
|
-
|
1108
|
-
/**
|
1109
|
-
* Get the size of the byte_buffer_t in memory.
|
1110
|
-
*/
|
1111
|
-
size_t rb_bson_byte_buffer_memsize(const void *ptr)
|
1112
|
-
{
|
1113
|
-
return ptr ? sizeof(byte_buffer_t) : 0;
|
1114
|
-
}
|
1115
|
-
|
1116
|
-
/**
|
1117
|
-
* Free the memory for the byte buffer.
|
1118
|
-
*/
|
1119
|
-
void rb_bson_byte_buffer_free(void *ptr)
|
1120
|
-
{
|
1121
|
-
byte_buffer_t *b = ptr;
|
1122
|
-
if (b->b_ptr != b->buffer) {
|
1123
|
-
xfree(b->b_ptr);
|
1124
|
-
}
|
1125
|
-
xfree(b);
|
1126
|
-
}
|
1127
|
-
|
1128
|
-
/**
|
1129
|
-
* Expand the byte buffer linearly.
|
1130
|
-
*/
|
1131
|
-
void rb_bson_expand_buffer(byte_buffer_t* buffer_ptr, size_t length)
|
1132
|
-
{
|
1133
|
-
const size_t required_size = buffer_ptr->write_position - buffer_ptr->read_position + length;
|
1134
|
-
if (required_size <= buffer_ptr->size) {
|
1135
|
-
memmove(buffer_ptr->b_ptr, READ_PTR(buffer_ptr), READ_SIZE(buffer_ptr));
|
1136
|
-
buffer_ptr->write_position -= buffer_ptr->read_position;
|
1137
|
-
buffer_ptr->read_position = 0;
|
1138
|
-
} else {
|
1139
|
-
char *new_b_ptr;
|
1140
|
-
const size_t new_size = required_size * 2;
|
1141
|
-
new_b_ptr = ALLOC_N(char, new_size);
|
1142
|
-
memcpy(new_b_ptr, READ_PTR(buffer_ptr), READ_SIZE(buffer_ptr));
|
1143
|
-
if (buffer_ptr->b_ptr != buffer_ptr->buffer) {
|
1144
|
-
xfree(buffer_ptr->b_ptr);
|
1145
|
-
}
|
1146
|
-
buffer_ptr->b_ptr = new_b_ptr;
|
1147
|
-
buffer_ptr->size = new_size;
|
1148
|
-
buffer_ptr->write_position -= buffer_ptr->read_position;
|
1149
|
-
buffer_ptr->read_position = 0;
|
1150
|
-
}
|
1151
|
-
}
|
1152
|
-
|
1153
|
-
/**
|
1154
|
-
* Generate the next object id.
|
1155
|
-
*/
|
1156
|
-
VALUE rb_bson_object_id_generator_next(int argc, VALUE* args, VALUE self)
|
1157
|
-
{
|
1158
|
-
char bytes[12];
|
1159
|
-
uint32_t t;
|
1160
|
-
uint32_t c;
|
1161
|
-
uint16_t pid = BSON_UINT16_TO_BE(getpid());
|
1162
|
-
|
1163
|
-
if (argc == 0 || (argc == 1 && *args == Qnil)) {
|
1164
|
-
t = BSON_UINT32_TO_BE((int) time(NULL));
|
1165
|
-
}
|
1166
|
-
else {
|
1167
|
-
t = BSON_UINT32_TO_BE(NUM2ULONG(rb_funcall(*args, rb_intern("to_i"), 0)));
|
1168
|
-
}
|
1169
|
-
|
1170
|
-
c = BSON_UINT32_TO_BE(rb_bson_object_id_counter << 8);
|
1171
|
-
|
1172
|
-
memcpy(&bytes, &t, 4);
|
1173
|
-
memcpy(&bytes[4], rb_bson_machine_id_hash, 3);
|
1174
|
-
memcpy(&bytes[7], &pid, 2);
|
1175
|
-
memcpy(&bytes[9], &c, 3);
|
1176
|
-
rb_bson_object_id_counter++;
|
1177
|
-
return rb_str_new(bytes, 12);
|
1178
|
-
}
|
1179
|
-
|
1180
|
-
/**
|
1181
|
-
* Taken from libbson.
|
1182
|
-
*/
|
1183
|
-
static void _bson_utf8_get_sequence(const char *utf8, uint8_t *seq_length, uint8_t *first_mask)
|
1184
|
-
{
|
1185
|
-
unsigned char c = *(const unsigned char *)utf8;
|
1186
|
-
uint8_t m;
|
1187
|
-
uint8_t n;
|
1188
|
-
|
1189
|
-
/*
|
1190
|
-
* See the following[1] for a description of what the given multi-byte
|
1191
|
-
* sequences will be based on the bits set of the first byte. We also need
|
1192
|
-
* to mask the first byte based on that. All subsequent bytes are masked
|
1193
|
-
* against 0x3F.
|
1194
|
-
*
|
1195
|
-
* [1] http://www.joelonsoftware.com/articles/Unicode.html
|
1196
|
-
*/
|
1197
|
-
|
1198
|
-
if ((c & 0x80) == 0) {
|
1199
|
-
n = 1;
|
1200
|
-
m = 0x7F;
|
1201
|
-
} else if ((c & 0xE0) == 0xC0) {
|
1202
|
-
n = 2;
|
1203
|
-
m = 0x1F;
|
1204
|
-
} else if ((c & 0xF0) == 0xE0) {
|
1205
|
-
n = 3;
|
1206
|
-
m = 0x0F;
|
1207
|
-
} else if ((c & 0xF8) == 0xF0) {
|
1208
|
-
n = 4;
|
1209
|
-
m = 0x07;
|
1210
|
-
} else if ((c & 0xFC) == 0xF8) {
|
1211
|
-
n = 5;
|
1212
|
-
m = 0x03;
|
1213
|
-
} else if ((c & 0xFE) == 0xFC) {
|
1214
|
-
n = 6;
|
1215
|
-
m = 0x01;
|
1216
|
-
} else {
|
1217
|
-
n = 0;
|
1218
|
-
m = 0;
|
1219
|
-
}
|
1220
|
-
|
1221
|
-
*seq_length = n;
|
1222
|
-
*first_mask = m;
|
1223
|
-
}
|
1224
|
-
|
1225
|
-
/**
|
1226
|
-
* Taken from libbson.
|
1227
|
-
*/
|
1228
|
-
bool rb_bson_utf8_validate(const char *utf8, size_t utf8_len, bool allow_null)
|
1229
|
-
{
|
1230
|
-
uint32_t c;
|
1231
|
-
uint8_t first_mask;
|
1232
|
-
uint8_t seq_length;
|
1233
|
-
unsigned i;
|
1234
|
-
unsigned j;
|
1235
|
-
|
1236
|
-
if (!utf8) {
|
1237
|
-
return false;
|
1238
|
-
}
|
1239
|
-
|
1240
|
-
for (i = 0; i < utf8_len; i += seq_length) {
|
1241
|
-
_bson_utf8_get_sequence(&utf8[i], &seq_length, &first_mask);
|
1242
|
-
|
1243
|
-
/*
|
1244
|
-
* Ensure we have a valid multi-byte sequence length.
|
1245
|
-
*/
|
1246
|
-
if (!seq_length) {
|
1247
|
-
return false;
|
1248
|
-
}
|
1249
|
-
|
1250
|
-
/*
|
1251
|
-
* Ensure we have enough bytes left.
|
1252
|
-
*/
|
1253
|
-
if ((utf8_len - i) < seq_length) {
|
1254
|
-
return false;
|
1255
|
-
}
|
1256
|
-
|
1257
|
-
/*
|
1258
|
-
* Also calculate the next char as a unichar so we can
|
1259
|
-
* check code ranges for non-shortest form.
|
1260
|
-
*/
|
1261
|
-
c = utf8 [i] & first_mask;
|
1262
|
-
|
1263
|
-
/*
|
1264
|
-
* Check the high-bits for each additional sequence byte.
|
1265
|
-
*/
|
1266
|
-
for (j = i + 1; j < (i + seq_length); j++) {
|
1267
|
-
c = (c << 6) | (utf8 [j] & 0x3F);
|
1268
|
-
if ((utf8[j] & 0xC0) != 0x80) {
|
1269
|
-
return false;
|
1270
|
-
}
|
1271
|
-
}
|
1272
|
-
|
1273
|
-
/*
|
1274
|
-
* Check for NULL bytes afterwards.
|
1275
|
-
*
|
1276
|
-
* Hint: if you want to optimize this function, starting here to do
|
1277
|
-
* this in the same pass as the data above would probably be a good
|
1278
|
-
* idea. You would add a branch into the inner loop, but save possibly
|
1279
|
-
* on cache-line bouncing on larger strings. Just a thought.
|
1280
|
-
*/
|
1281
|
-
if (!allow_null) {
|
1282
|
-
for (j = 0; j < seq_length; j++) {
|
1283
|
-
if (((i + j) > utf8_len) || !utf8[i + j]) {
|
1284
|
-
return false;
|
1285
|
-
}
|
1286
|
-
}
|
1287
|
-
}
|
1288
|
-
|
1289
|
-
/*
|
1290
|
-
* Code point wont fit in utf-16, not allowed.
|
1291
|
-
*/
|
1292
|
-
if (c > 0x0010FFFF) {
|
1293
|
-
return false;
|
1294
|
-
}
|
1295
|
-
|
1296
|
-
/*
|
1297
|
-
* Byte is in reserved range for UTF-16 high-marks
|
1298
|
-
* for surrogate pairs.
|
1299
|
-
*/
|
1300
|
-
if ((c & 0xFFFFF800) == 0xD800) {
|
1301
|
-
return false;
|
1302
|
-
}
|
1303
|
-
|
1304
|
-
/*
|
1305
|
-
* Check non-shortest form unicode.
|
1306
|
-
*/
|
1307
|
-
switch (seq_length) {
|
1308
|
-
case 1:
|
1309
|
-
if (c <= 0x007F) {
|
1310
|
-
continue;
|
1311
|
-
}
|
1312
|
-
return false;
|
1313
|
-
|
1314
|
-
case 2:
|
1315
|
-
if ((c >= 0x0080) && (c <= 0x07FF)) {
|
1316
|
-
continue;
|
1317
|
-
} else if (c == 0) {
|
1318
|
-
/* Two-byte representation for NULL. */
|
1319
|
-
continue;
|
1320
|
-
}
|
1321
|
-
return false;
|
1322
|
-
|
1323
|
-
case 3:
|
1324
|
-
if (((c >= 0x0800) && (c <= 0x0FFF)) ||
|
1325
|
-
((c >= 0x1000) && (c <= 0xFFFF))) {
|
1326
|
-
continue;
|
1327
|
-
}
|
1328
|
-
return false;
|
1329
|
-
|
1330
|
-
case 4:
|
1331
|
-
if (((c >= 0x10000) && (c <= 0x3FFFF)) ||
|
1332
|
-
((c >= 0x40000) && (c <= 0xFFFFF)) ||
|
1333
|
-
((c >= 0x100000) && (c <= 0x10FFFF))) {
|
1334
|
-
continue;
|
1335
|
-
}
|
1336
|
-
return false;
|
1337
|
-
|
1338
|
-
default:
|
1339
|
-
return false;
|
1340
|
-
}
|
1341
|
-
}
|
1342
|
-
|
1343
|
-
return true;
|
1344
|
-
}
|