bson_ext 1.3.1 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|