bson_ext 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +3 -4
- data/ext/cbson/{buffer.c → bson_buffer.c} +30 -14
- data/ext/cbson/{buffer.h → bson_buffer.h} +16 -12
- data/ext/cbson/cbson.c +61 -56
- data/ext/cbson/version.h +1 -1
- data/ext/cmongo/c-driver/src/bson.c +699 -0
- data/ext/cmongo/c-driver/src/bson.h +229 -0
- data/ext/cmongo/c-driver/src/gridfs.c +799 -0
- data/ext/cmongo/c-driver/src/gridfs.h +278 -0
- data/ext/cmongo/c-driver/src/md5.c +381 -0
- data/ext/cmongo/c-driver/src/md5.h +91 -0
- data/ext/cmongo/c-driver/src/mongo.c +1020 -0
- data/ext/cmongo/c-driver/src/mongo.h +260 -0
- data/ext/cmongo/c-driver/src/mongo_except.h +143 -0
- data/ext/cmongo/c-driver/src/numbers.c +127 -0
- data/ext/cmongo/c-driver/src/platform_hacks.h +93 -0
- data/ext/cmongo/c-driver/test/all_types.c +223 -0
- data/ext/cmongo/c-driver/test/auth.c +28 -0
- data/ext/cmongo/c-driver/test/benchmark.c +434 -0
- data/ext/cmongo/c-driver/test/count_delete.c +64 -0
- data/ext/cmongo/c-driver/test/endian_swap.c +31 -0
- data/ext/cmongo/c-driver/test/errors.c +71 -0
- data/ext/cmongo/c-driver/test/examples.c +75 -0
- data/ext/cmongo/c-driver/test/gridfs.c +217 -0
- data/ext/cmongo/c-driver/test/json.c +169 -0
- data/ext/cmongo/c-driver/test/pair.c +41 -0
- data/ext/cmongo/c-driver/test/replica_set.c +81 -0
- data/ext/cmongo/c-driver/test/resize.c +35 -0
- data/ext/cmongo/c-driver/test/simple.c +110 -0
- data/ext/cmongo/c-driver/test/sizes.c +22 -0
- data/ext/cmongo/c-driver/test/test.h +19 -0
- data/ext/cmongo/c-driver/test/update.c +107 -0
- metadata +61 -29
data/Rakefile
CHANGED
@@ -22,12 +22,11 @@ namespace :build do
|
|
22
22
|
jar_dir = File.join(java_dir, 'jar')
|
23
23
|
|
24
24
|
jruby_jar = File.join(jar_dir, 'jruby.jar')
|
25
|
-
mongo_jar = File.join(jar_dir, 'mongo-2.
|
26
|
-
bson_jar = File.join(jar_dir, 'bson-2.2.jar')
|
25
|
+
mongo_jar = File.join(jar_dir, 'mongo-2.6.5.jar')
|
27
26
|
|
28
27
|
src_base = File.join(java_dir, 'src')
|
29
28
|
|
30
|
-
system("javac -Xlint:unchecked -classpath #{jruby_jar}:#{mongo_jar}
|
29
|
+
system("javac -Xlint:deprecation -Xlint:unchecked -classpath #{jruby_jar}:#{mongo_jar} #{File.join(src_base, 'org', 'jbson', '*.java')}")
|
31
30
|
system("cd #{src_base} && jar cf #{File.join(jar_dir, 'jbson.jar')} #{File.join('.', 'org', 'jbson', '*.class')}")
|
32
31
|
end
|
33
32
|
end
|
@@ -142,7 +141,7 @@ task :ydoc do
|
|
142
141
|
require File.join(File.dirname(__FILE__), 'lib', 'mongo')
|
143
142
|
out = File.join('ydoc', Mongo::VERSION)
|
144
143
|
FileUtils.rm_rf('ydoc')
|
145
|
-
system "yardoc lib/**/*.rb lib/mongo/**/*.rb lib/bson/**/*.rb -e yard/yard_ext.rb -p yard/templates -o #{out} --title MongoRuby-#{Mongo::VERSION} --files docs/TUTORIAL.md,docs/GridFS.md,docs/FAQ.md,docs/REPLICA_SETS.md,docs/WRITE_CONCERN.md,docs/HISTORY.md,docs/CREDITS.md,docs/RELEASES.md"
|
144
|
+
system "yardoc lib/**/*.rb lib/mongo/**/*.rb lib/bson/**/*.rb -e ./yard/yard_ext.rb -p yard/templates -o #{out} --title MongoRuby-#{Mongo::VERSION} --files docs/TUTORIAL.md,docs/GridFS.md,docs/FAQ.md,docs/REPLICA_SETS.md,docs/WRITE_CONCERN.md,docs/READ_PREFERENCE.md,docs/HISTORY.md,docs/CREDITS.md,docs/RELEASES.md,docs/CREDITS.md,docs/TAILABLE_CURSORS.md"
|
146
145
|
end
|
147
146
|
|
148
147
|
namespace :bamboo do
|
@@ -17,21 +17,23 @@
|
|
17
17
|
#include <stdlib.h>
|
18
18
|
#include <string.h>
|
19
19
|
|
20
|
-
#include "
|
20
|
+
#include "bson_buffer.h"
|
21
21
|
|
22
22
|
#define INITIAL_BUFFER_SIZE 256
|
23
|
+
#define DEFAULT_MAX_SIZE 4 * 1024 * 1024
|
23
24
|
|
24
|
-
struct
|
25
|
+
struct bson_buffer {
|
25
26
|
char* buffer;
|
26
27
|
int size;
|
27
28
|
int position;
|
29
|
+
int max_size;
|
28
30
|
};
|
29
31
|
|
30
32
|
/* Allocate and return a new buffer.
|
31
33
|
* Return NULL on allocation failure. */
|
32
|
-
|
33
|
-
|
34
|
-
buffer = (
|
34
|
+
bson_buffer_t bson_buffer_new(void) {
|
35
|
+
bson_buffer_t buffer;
|
36
|
+
buffer = (bson_buffer_t)malloc(sizeof(struct bson_buffer));
|
35
37
|
if (buffer == NULL) {
|
36
38
|
return NULL;
|
37
39
|
}
|
@@ -43,13 +45,22 @@ buffer_t buffer_new(void) {
|
|
43
45
|
free(buffer);
|
44
46
|
return NULL;
|
45
47
|
}
|
48
|
+
buffer->max_size = DEFAULT_MAX_SIZE;
|
46
49
|
|
47
50
|
return buffer;
|
48
51
|
}
|
49
52
|
|
53
|
+
void bson_buffer_set_max_size(bson_buffer_t buffer, int max_size) {
|
54
|
+
buffer->max_size = max_size;
|
55
|
+
}
|
56
|
+
|
57
|
+
int bson_buffer_get_max_size(bson_buffer_t buffer) {
|
58
|
+
return buffer->max_size;
|
59
|
+
}
|
60
|
+
|
50
61
|
/* Free the memory allocated for `buffer`.
|
51
62
|
* Return non-zero on failure. */
|
52
|
-
int
|
63
|
+
int bson_buffer_free(bson_buffer_t buffer) {
|
53
64
|
if (buffer == NULL) {
|
54
65
|
return 1;
|
55
66
|
}
|
@@ -60,14 +71,19 @@ int buffer_free(buffer_t buffer) {
|
|
60
71
|
|
61
72
|
/* Grow `buffer` to at least `min_length`.
|
62
73
|
* Return non-zero on allocation failure. */
|
63
|
-
static int buffer_grow(
|
74
|
+
static int buffer_grow(bson_buffer_t buffer, int min_length) {
|
64
75
|
int size = buffer->size;
|
76
|
+
int old_size;
|
65
77
|
char* old_buffer = buffer->buffer;
|
66
78
|
if (size >= min_length) {
|
67
79
|
return 0;
|
68
80
|
}
|
69
81
|
while (size < min_length) {
|
82
|
+
old_size = size;
|
70
83
|
size *= 2;
|
84
|
+
/* Prevent potential overflow. */
|
85
|
+
if( size < old_size )
|
86
|
+
size = min_length;
|
71
87
|
}
|
72
88
|
buffer->buffer = (char*)realloc(buffer->buffer, sizeof(char) * size);
|
73
89
|
if (buffer->buffer == NULL) {
|
@@ -81,7 +97,7 @@ static int buffer_grow(buffer_t buffer, int min_length) {
|
|
81
97
|
|
82
98
|
/* Assure that `buffer` has at least `size` free bytes (and grow if needed).
|
83
99
|
* Return non-zero on allocation failure. */
|
84
|
-
static int buffer_assure_space(
|
100
|
+
static int buffer_assure_space(bson_buffer_t buffer, int size) {
|
85
101
|
if (buffer->position + size <= buffer->size) {
|
86
102
|
return 0;
|
87
103
|
}
|
@@ -90,7 +106,7 @@ static int buffer_assure_space(buffer_t buffer, int size) {
|
|
90
106
|
|
91
107
|
/* Save `size` bytes from the current position in `buffer` (and grow if needed).
|
92
108
|
* Return offset for writing, or -1 on allocation failure. */
|
93
|
-
|
109
|
+
bson_buffer_position bson_buffer_save_space(bson_buffer_t buffer, int size) {
|
94
110
|
int position = buffer->position;
|
95
111
|
if (buffer_assure_space(buffer, size) != 0) {
|
96
112
|
return -1;
|
@@ -101,7 +117,7 @@ buffer_position buffer_save_space(buffer_t buffer, int size) {
|
|
101
117
|
|
102
118
|
/* Write `size` bytes from `data` to `buffer` (and grow if needed).
|
103
119
|
* Return non-zero on allocation failure. */
|
104
|
-
int
|
120
|
+
int bson_buffer_write(bson_buffer_t buffer, const char* data, int size) {
|
105
121
|
if (buffer_assure_space(buffer, size) != 0) {
|
106
122
|
return 1;
|
107
123
|
}
|
@@ -114,10 +130,10 @@ int buffer_write(buffer_t buffer, const char* data, int size) {
|
|
114
130
|
/* Write `size` bytes from `data` to `buffer` at position `position`.
|
115
131
|
* Does not change the internal position of `buffer`.
|
116
132
|
* Return non-zero if buffer isn't large enough for write. */
|
117
|
-
int
|
133
|
+
int bson_buffer_write_at_position(bson_buffer_t buffer, bson_buffer_position position,
|
118
134
|
const char* data, int size) {
|
119
135
|
if (position + size > buffer->size) {
|
120
|
-
|
136
|
+
bson_buffer_free(buffer);
|
121
137
|
return 1;
|
122
138
|
}
|
123
139
|
|
@@ -126,10 +142,10 @@ int buffer_write_at_position(buffer_t buffer, buffer_position position,
|
|
126
142
|
}
|
127
143
|
|
128
144
|
|
129
|
-
int
|
145
|
+
int bson_buffer_get_position(bson_buffer_t buffer) {
|
130
146
|
return buffer->position;
|
131
147
|
}
|
132
148
|
|
133
|
-
char*
|
149
|
+
char* bson_buffer_get_buffer(bson_buffer_t buffer) {
|
134
150
|
return buffer->buffer;
|
135
151
|
}
|
@@ -14,42 +14,46 @@
|
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
16
|
|
17
|
-
#ifndef
|
18
|
-
#define
|
17
|
+
#ifndef _BSON_BUFFER_H
|
18
|
+
#define _BSON_BUFFER_H
|
19
19
|
|
20
20
|
/* Note: if any of these functions return a failure condition then the buffer
|
21
21
|
* has already been freed. */
|
22
22
|
|
23
23
|
/* A buffer */
|
24
|
-
typedef struct
|
24
|
+
typedef struct bson_buffer* bson_buffer_t;
|
25
25
|
/* A position in the buffer */
|
26
|
-
typedef int
|
26
|
+
typedef int bson_buffer_position;
|
27
27
|
|
28
28
|
/* Allocate and return a new buffer.
|
29
29
|
* Return NULL on allocation failure. */
|
30
|
-
|
30
|
+
bson_buffer_t bson_buffer_new(void);
|
31
|
+
|
32
|
+
/* Set the max size for this buffer.
|
33
|
+
* Note: this is not a hard limit. */
|
34
|
+
void bson_buffer_set_max_size(bson_buffer_t buffer, int max_size);
|
31
35
|
|
32
36
|
/* Free the memory allocated for `buffer`.
|
33
37
|
* Return non-zero on failure. */
|
34
|
-
int
|
38
|
+
int bson_buffer_free(bson_buffer_t buffer);
|
35
39
|
|
36
40
|
/* Save `size` bytes from the current position in `buffer` (and grow if needed).
|
37
41
|
* Return offset for writing, or -1 on allocation failure. */
|
38
|
-
|
42
|
+
bson_buffer_position bson_buffer_save_space(bson_buffer_t buffer, int size);
|
39
43
|
|
40
44
|
/* Write `size` bytes from `data` to `buffer` (and grow if needed).
|
41
45
|
* Return non-zero on allocation failure. */
|
42
|
-
int
|
46
|
+
int bson_buffer_write(bson_buffer_t buffer, const char* data, int size);
|
43
47
|
|
44
48
|
/* Write `size` bytes from `data` to `buffer` at position `position`.
|
45
49
|
* Does not change the internal position of `buffer`.
|
46
50
|
* Return non-zero if buffer isn't large enough for write. */
|
47
|
-
int
|
51
|
+
int bson_buffer_write_at_position(bson_buffer_t buffer, bson_buffer_position position, const char* data, int size);
|
48
52
|
|
49
|
-
/* Getters for the internals of a
|
53
|
+
/* Getters for the internals of a bson_buffer_t.
|
50
54
|
* Should try to avoid using these as much as possible
|
51
55
|
* since they break the abstraction. */
|
52
|
-
|
53
|
-
char*
|
56
|
+
bson_buffer_position bson_buffer_get_position(bson_buffer_t buffer);
|
57
|
+
char* bson_buffer_get_buffer(bson_buffer_t buffer);
|
54
58
|
|
55
59
|
#endif
|
data/ext/cbson/cbson.c
CHANGED
@@ -61,16 +61,16 @@
|
|
61
61
|
#include <time.h>
|
62
62
|
|
63
63
|
#include "version.h"
|
64
|
-
#include "
|
64
|
+
#include "bson_buffer.h"
|
65
65
|
#include "encoding_helpers.h"
|
66
66
|
|
67
67
|
#define SAFE_WRITE(buffer, data, size) \
|
68
|
-
if (
|
69
|
-
rb_raise(rb_eNoMemError, "failed to allocate memory in
|
68
|
+
if (bson_buffer_write((buffer), (data), (size)) != 0) \
|
69
|
+
rb_raise(rb_eNoMemError, "failed to allocate memory in bson_buffer.c")
|
70
70
|
|
71
71
|
#define SAFE_WRITE_AT_POS(buffer, position, data, size) \
|
72
|
-
if (
|
73
|
-
rb_raise(rb_eRuntimeError, "invalid write at position in
|
72
|
+
if (bson_buffer_write_at_position((buffer), (position), (data), (size)) != 0) \
|
73
|
+
rb_raise(rb_eRuntimeError, "invalid write at position in bson_buffer.c")
|
74
74
|
|
75
75
|
#define MAX_HOSTNAME_LENGTH 256
|
76
76
|
|
@@ -114,14 +114,14 @@ static int max_bson_size;
|
|
114
114
|
#define TO_UTF8(string) (string)
|
115
115
|
#endif
|
116
116
|
|
117
|
-
static void write_utf8(
|
117
|
+
static void write_utf8(bson_buffer_t buffer, VALUE string, char check_null) {
|
118
118
|
result_t status = check_string(RSTRING_PTR(string), RSTRING_LEN(string),
|
119
119
|
1, check_null);
|
120
120
|
if (status == HAS_NULL) {
|
121
|
-
|
121
|
+
bson_buffer_free(buffer);
|
122
122
|
rb_raise(InvalidDocument, "Key names / regex patterns must not contain the NULL byte");
|
123
123
|
} else if (status == NOT_UTF_8) {
|
124
|
-
|
124
|
+
bson_buffer_free(buffer);
|
125
125
|
rb_raise(InvalidStringEncoding, "String not valid UTF-8");
|
126
126
|
}
|
127
127
|
string = TO_UTF8(string);
|
@@ -192,23 +192,23 @@ static int cmp_char(const void* a, const void* b) {
|
|
192
192
|
return *(char*)a - *(char*)b;
|
193
193
|
}
|
194
194
|
|
195
|
-
static void write_doc(
|
195
|
+
static void write_doc(bson_buffer_t buffer, VALUE hash, VALUE check_keys, VALUE move_id);
|
196
196
|
static int write_element_with_id(VALUE key, VALUE value, VALUE extra);
|
197
197
|
static int write_element_without_id(VALUE key, VALUE value, VALUE extra);
|
198
198
|
static VALUE elements_to_hash(const char* buffer, int max);
|
199
199
|
|
200
|
-
static VALUE pack_extra(
|
200
|
+
static VALUE pack_extra(bson_buffer_t buffer, VALUE check_keys) {
|
201
201
|
return rb_ary_new3(2, LL2NUM((long long)buffer), check_keys);
|
202
202
|
}
|
203
203
|
|
204
|
-
static void write_name_and_type(
|
204
|
+
static void write_name_and_type(bson_buffer_t buffer, VALUE name, char type) {
|
205
205
|
SAFE_WRITE(buffer, &type, 1);
|
206
206
|
write_utf8(buffer, name, 1);
|
207
207
|
SAFE_WRITE(buffer, &zero, 1);
|
208
208
|
}
|
209
209
|
|
210
210
|
static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
211
|
-
|
211
|
+
bson_buffer_t buffer = (bson_buffer_t)NUM2LL(rb_ary_entry(extra, 0));
|
212
212
|
VALUE check_keys = rb_ary_entry(extra, 1);
|
213
213
|
|
214
214
|
if (TYPE(key) == T_SYMBOL) {
|
@@ -217,7 +217,7 @@ static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
|
217
217
|
}
|
218
218
|
|
219
219
|
if (TYPE(key) != T_STRING) {
|
220
|
-
|
220
|
+
bson_buffer_free(buffer);
|
221
221
|
rb_raise(rb_eTypeError, "keys must be strings or symbols");
|
222
222
|
}
|
223
223
|
|
@@ -228,12 +228,12 @@ static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
|
228
228
|
if (check_keys == Qtrue) {
|
229
229
|
int i;
|
230
230
|
if (RSTRING_LEN(key) > 0 && RSTRING_PTR(key)[0] == '$') {
|
231
|
-
|
231
|
+
bson_buffer_free(buffer);
|
232
232
|
rb_raise(InvalidKeyName, "%s - key must not start with '$'", RSTRING_PTR(key));
|
233
233
|
}
|
234
234
|
for (i = 0; i < RSTRING_LEN(key); i++) {
|
235
235
|
if (RSTRING_PTR(key)[i] == '.') {
|
236
|
-
|
236
|
+
bson_buffer_free(buffer);
|
237
237
|
rb_raise(InvalidKeyName, "%s - key must not contain '.'", RSTRING_PTR(key));
|
238
238
|
}
|
239
239
|
}
|
@@ -244,7 +244,7 @@ static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
|
244
244
|
{
|
245
245
|
if (rb_funcall(value, gt_operator, 1, LL2NUM(9223372036854775807LL)) == Qtrue ||
|
246
246
|
rb_funcall(value, lt_operator, 1, LL2NUM(-9223372036854775808ULL)) == Qtrue) {
|
247
|
-
|
247
|
+
bson_buffer_free(buffer);
|
248
248
|
rb_raise(rb_eRangeError, "MongoDB can only handle 8-byte ints");
|
249
249
|
}
|
250
250
|
}
|
@@ -298,15 +298,15 @@ static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
|
298
298
|
}
|
299
299
|
case T_ARRAY:
|
300
300
|
{
|
301
|
-
|
301
|
+
bson_buffer_position length_location, start_position, obj_length;
|
302
302
|
int items, i;
|
303
303
|
VALUE* values;
|
304
304
|
|
305
305
|
write_name_and_type(buffer, key, 0x04);
|
306
|
-
start_position =
|
306
|
+
start_position = bson_buffer_get_position(buffer);
|
307
307
|
|
308
308
|
// save space for length
|
309
|
-
length_location =
|
309
|
+
length_location = bson_buffer_save_space(buffer, 4);
|
310
310
|
if (length_location == -1) {
|
311
311
|
rb_raise(rb_eNoMemError, "failed to allocate memory in buffer.c");
|
312
312
|
}
|
@@ -323,7 +323,7 @@ static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
|
323
323
|
|
324
324
|
// write null byte and fill in length
|
325
325
|
SAFE_WRITE(buffer, &zero, 1);
|
326
|
-
obj_length =
|
326
|
+
obj_length = bson_buffer_get_position(buffer) - start_position;
|
327
327
|
SAFE_WRITE_AT_POS(buffer, length_location, (const char*)&obj_length, 4);
|
328
328
|
break;
|
329
329
|
}
|
@@ -380,14 +380,14 @@ static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
|
380
380
|
break;
|
381
381
|
}
|
382
382
|
if (strcmp(cls, "BSON::DBRef") == 0) {
|
383
|
-
|
383
|
+
bson_buffer_position length_location, start_position, obj_length;
|
384
384
|
VALUE ns, oid;
|
385
385
|
write_name_and_type(buffer, key, 0x03);
|
386
386
|
|
387
|
-
start_position =
|
387
|
+
start_position = bson_buffer_get_position(buffer);
|
388
388
|
|
389
389
|
// save space for length
|
390
|
-
length_location =
|
390
|
+
length_location = bson_buffer_save_space(buffer, 4);
|
391
391
|
if (length_location == -1) {
|
392
392
|
rb_raise(rb_eNoMemError, "failed to allocate memory in buffer.c");
|
393
393
|
}
|
@@ -399,18 +399,18 @@ static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
|
399
399
|
|
400
400
|
// write null byte and fill in length
|
401
401
|
SAFE_WRITE(buffer, &zero, 1);
|
402
|
-
obj_length =
|
402
|
+
obj_length = bson_buffer_get_position(buffer) - start_position;
|
403
403
|
SAFE_WRITE_AT_POS(buffer, length_location, (const char*)&obj_length, 4);
|
404
404
|
break;
|
405
405
|
}
|
406
406
|
if (strcmp(cls, "BSON::Code") == 0) {
|
407
|
-
|
407
|
+
bson_buffer_position length_location, start_position, total_length;
|
408
408
|
int length;
|
409
409
|
VALUE code_str;
|
410
410
|
write_name_and_type(buffer, key, 0x0F);
|
411
411
|
|
412
|
-
start_position =
|
413
|
-
length_location =
|
412
|
+
start_position = bson_buffer_get_position(buffer);
|
413
|
+
length_location = bson_buffer_save_space(buffer, 4);
|
414
414
|
if (length_location == -1) {
|
415
415
|
rb_raise(rb_eNoMemError, "failed to allocate memory in buffer.c");
|
416
416
|
}
|
@@ -422,7 +422,7 @@ static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
|
422
422
|
SAFE_WRITE(buffer, &zero, 1);
|
423
423
|
write_doc(buffer, rb_funcall(value, rb_intern("scope"), 0), Qfalse, Qfalse);
|
424
424
|
|
425
|
-
total_length =
|
425
|
+
total_length = bson_buffer_get_position(buffer) - start_position;
|
426
426
|
SAFE_WRITE_AT_POS(buffer, length_location, (const char*)&total_length, 4);
|
427
427
|
break;
|
428
428
|
}
|
@@ -436,9 +436,9 @@ static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
|
436
436
|
}
|
437
437
|
if (strcmp(cls, "BSON::Timestamp") == 0) {
|
438
438
|
write_name_and_type(buffer, key, 0x11);
|
439
|
-
int seconds =
|
439
|
+
unsigned int seconds = NUM2UINT(
|
440
440
|
rb_funcall(value, rb_intern("seconds"), 0));
|
441
|
-
int increment =
|
441
|
+
unsigned int increment = NUM2UINT(
|
442
442
|
rb_funcall(value, rb_intern("increment"), 0));
|
443
443
|
|
444
444
|
SAFE_WRITE(buffer, (const char*)&increment, 4);
|
@@ -446,16 +446,16 @@ static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
|
446
446
|
break;
|
447
447
|
}
|
448
448
|
if (strcmp(cls, "DateTime") == 0 || strcmp(cls, "Date") == 0 || strcmp(cls, "ActiveSupport::TimeWithZone") == 0) {
|
449
|
-
|
449
|
+
bson_buffer_free(buffer);
|
450
450
|
rb_raise(InvalidDocument, "%s is not currently supported; use a UTC Time instance instead.", cls);
|
451
451
|
break;
|
452
452
|
}
|
453
453
|
if(strcmp(cls, "Complex") == 0 || strcmp(cls, "Rational") == 0 || strcmp(cls, "BigDecimal") == 0) {
|
454
|
-
|
454
|
+
bson_buffer_free(buffer);
|
455
455
|
rb_raise(InvalidDocument, "Cannot serialize the Numeric type %s as BSON; only Bignum, Fixnum, and Float are supported.", cls);
|
456
456
|
break;
|
457
457
|
}
|
458
|
-
|
458
|
+
bson_buffer_free(buffer);
|
459
459
|
rb_raise(InvalidDocument, "Cannot serialize an object of class %s into BSON.", cls);
|
460
460
|
break;
|
461
461
|
}
|
@@ -470,11 +470,11 @@ static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
|
470
470
|
break;
|
471
471
|
}
|
472
472
|
if(strcmp(cls, "BigDecimal") == 0) {
|
473
|
-
|
473
|
+
bson_buffer_free(buffer);
|
474
474
|
rb_raise(InvalidDocument, "Cannot serialize the Numeric type %s as BSON; only Bignum, Fixnum, and Float are supported.", cls);
|
475
475
|
break;
|
476
476
|
}
|
477
|
-
|
477
|
+
bson_buffer_free(buffer);
|
478
478
|
rb_raise(InvalidDocument, "Cannot serialize an object of class %s into BSON.", cls);
|
479
479
|
break;
|
480
480
|
}
|
@@ -507,9 +507,9 @@ static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
|
507
507
|
has_extra = rb_funcall(value, rb_intern("respond_to?"), 1, rb_str_new2("extra_options_str"));
|
508
508
|
if (TYPE(has_extra) == T_TRUE) {
|
509
509
|
VALUE extra = rb_funcall(value, rb_intern("extra_options_str"), 0);
|
510
|
-
|
510
|
+
bson_buffer_position old_position = bson_buffer_get_position(buffer);
|
511
511
|
SAFE_WRITE(buffer, RSTRING_PTR(extra), RSTRING_LENINT(extra));
|
512
|
-
qsort(
|
512
|
+
qsort(bson_buffer_get_buffer(buffer) + old_position, RSTRING_LEN(extra), sizeof(char), cmp_char);
|
513
513
|
}
|
514
514
|
SAFE_WRITE(buffer, &zero, 1);
|
515
515
|
|
@@ -518,7 +518,7 @@ static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
|
518
518
|
default:
|
519
519
|
{
|
520
520
|
const char* cls = rb_obj_classname(value);
|
521
|
-
|
521
|
+
bson_buffer_free(buffer);
|
522
522
|
rb_raise(InvalidDocument, "Cannot serialize an object of class %s (type %d) into BSON.", cls, TYPE(value));
|
523
523
|
break;
|
524
524
|
}
|
@@ -534,10 +534,10 @@ static int write_element_with_id(VALUE key, VALUE value, VALUE extra) {
|
|
534
534
|
return write_element(key, value, extra, 1);
|
535
535
|
}
|
536
536
|
|
537
|
-
static void write_doc(
|
538
|
-
|
539
|
-
|
540
|
-
|
537
|
+
static void write_doc(bson_buffer_t buffer, VALUE hash, VALUE check_keys, VALUE move_id) {
|
538
|
+
bson_buffer_position start_position = bson_buffer_get_position(buffer);
|
539
|
+
bson_buffer_position length_location = bson_buffer_save_space(buffer, 4);
|
540
|
+
bson_buffer_position length;
|
541
541
|
int allow_id;
|
542
542
|
int (*write_function)(VALUE, VALUE, VALUE) = NULL;
|
543
543
|
VALUE id_str = rb_str_new2("_id");
|
@@ -590,34 +590,39 @@ static void write_doc(buffer_t buffer, VALUE hash, VALUE check_keys, VALUE move_
|
|
590
590
|
} else if (rb_obj_is_kind_of(hash, RB_HASH) == Qtrue) {
|
591
591
|
rb_hash_foreach(hash, write_function, pack_extra(buffer, check_keys));
|
592
592
|
} else {
|
593
|
-
|
593
|
+
bson_buffer_free(buffer);
|
594
594
|
rb_raise(InvalidDocument, "BSON.serialize takes a Hash but got a %s", rb_obj_classname(hash));
|
595
595
|
}
|
596
596
|
|
597
597
|
// write null byte and fill in length
|
598
598
|
SAFE_WRITE(buffer, &zero, 1);
|
599
|
-
length =
|
599
|
+
length = bson_buffer_get_position(buffer) - start_position;
|
600
600
|
|
601
601
|
// make sure that length doesn't exceed 4MB
|
602
|
-
if (length >
|
603
|
-
|
604
|
-
rb_raise(InvalidDocument,
|
602
|
+
if (length > bson_buffer_get_max_size(buffer)) {
|
603
|
+
bson_buffer_free(buffer);
|
604
|
+
rb_raise(InvalidDocument,
|
605
|
+
"Document too large: This BSON documents is limited to %d bytes.",
|
606
|
+
bson_buffer_get_max_size(buffer));
|
605
607
|
return;
|
606
608
|
}
|
607
609
|
SAFE_WRITE_AT_POS(buffer, length_location, (const char*)&length, 4);
|
608
610
|
}
|
609
611
|
|
610
|
-
static VALUE method_serialize(VALUE self, VALUE doc, VALUE check_keys,
|
612
|
+
static VALUE method_serialize(VALUE self, VALUE doc, VALUE check_keys,
|
613
|
+
VALUE move_id, VALUE max_size) {
|
614
|
+
|
611
615
|
VALUE result;
|
612
|
-
|
616
|
+
bson_buffer_t buffer = bson_buffer_new();
|
617
|
+
bson_buffer_set_max_size(buffer, FIX2INT(max_size));
|
613
618
|
if (buffer == NULL) {
|
614
619
|
rb_raise(rb_eNoMemError, "failed to allocate memory in buffer.c");
|
615
620
|
}
|
616
621
|
|
617
622
|
write_doc(buffer, doc, check_keys, move_id);
|
618
623
|
|
619
|
-
result = rb_str_new(
|
620
|
-
if (
|
624
|
+
result = rb_str_new(bson_buffer_get_buffer(buffer), bson_buffer_get_position(buffer));
|
625
|
+
if (bson_buffer_free(buffer) != 0) {
|
621
626
|
rb_raise(rb_eRuntimeError, "failed to free buffer");
|
622
627
|
}
|
623
628
|
return result;
|
@@ -830,12 +835,12 @@ static VALUE get_value(const char* buffer, int* position, int type) {
|
|
830
835
|
}
|
831
836
|
case 17:
|
832
837
|
{
|
833
|
-
int sec, inc;
|
838
|
+
unsigned int sec, inc;
|
834
839
|
VALUE argv[2];
|
835
840
|
memcpy(&inc, buffer + *position, 4);
|
836
841
|
memcpy(&sec, buffer + *position + 4, 4);
|
837
|
-
argv[0] =
|
838
|
-
argv[1] =
|
842
|
+
argv[0] = UINT2NUM(sec);
|
843
|
+
argv[1] = UINT2NUM(inc);
|
839
844
|
value = rb_class_new_instance(2, argv, Timestamp);
|
840
845
|
*position += 8;
|
841
846
|
break;
|
@@ -899,7 +904,7 @@ static VALUE objectid_generate(int argc, VALUE* args, VALUE self)
|
|
899
904
|
if(argc == 0 || (argc == 1 && *args == Qnil)) {
|
900
905
|
t = htonl((int)time(NULL));
|
901
906
|
} else {
|
902
|
-
t = htonl(
|
907
|
+
t = htonl(NUM2UINT(rb_funcall(*args, rb_intern("to_i"), 0)));
|
903
908
|
}
|
904
909
|
MEMCPY(&oid_bytes, &t, unsigned char, 4);
|
905
910
|
|
@@ -973,7 +978,7 @@ void Init_cbson() {
|
|
973
978
|
CBson = rb_define_module("CBson");
|
974
979
|
ext_version = rb_str_new2(VERSION);
|
975
980
|
rb_define_const(CBson, "VERSION", ext_version);
|
976
|
-
rb_define_module_function(CBson, "serialize", method_serialize,
|
981
|
+
rb_define_module_function(CBson, "serialize", method_serialize, 4);
|
977
982
|
rb_define_module_function(CBson, "deserialize", method_deserialize, 1);
|
978
983
|
rb_define_module_function(CBson, "max_bson_size", method_max_bson_size, 0);
|
979
984
|
rb_define_module_function(CBson, "update_max_bson_size", method_update_max_bson_size, 1);
|