mongo_ext 0.18 → 0.18.1
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 +25 -7
- data/ext/cbson/buffer.c +135 -0
- data/ext/cbson/buffer.h +55 -0
- data/ext/cbson/cbson.c +127 -134
- data/ext/cbson/encoding_helpers.c +107 -0
- data/ext/cbson/encoding_helpers.h +22 -0
- data/ext/cbson/version.h +17 -0
- data/mongo-extensions.gemspec +5 -4
- metadata +10 -7
data/Rakefile
CHANGED
@@ -10,19 +10,37 @@ rescue LoadError
|
|
10
10
|
end
|
11
11
|
require 'rbconfig'
|
12
12
|
include Config
|
13
|
+
ENV['TEST_MODE'] = 'TRUE'
|
13
14
|
|
14
15
|
gem_command = "gem"
|
15
16
|
gem_command = "gem1.9" if $0.match(/1\.9$/) # use gem1.9 if we used rake1.9
|
16
17
|
|
17
|
-
# NOTE: the functional tests assume MongoDB is running.
|
18
18
|
desc "Test the MongoDB Ruby driver."
|
19
19
|
task :test do
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
puts "\nThis option has changed."
|
21
|
+
puts "\nTo test the driver with the c-extensions:\nrake test:c\n"
|
22
|
+
puts "To test the pure ruby driver: \nrake test:ruby"
|
23
23
|
end
|
24
24
|
|
25
|
-
namespace :test do
|
25
|
+
namespace :test do
|
26
|
+
|
27
|
+
desc "Test the driver with the c extension enabled."
|
28
|
+
task :c do
|
29
|
+
ENV['C_EXT'] = 'TRUE'
|
30
|
+
Rake::Task['test:unit'].invoke
|
31
|
+
Rake::Task['test:functional'].invoke
|
32
|
+
Rake::Task['test:pooled_threading'].invoke
|
33
|
+
ENV['C_EXT'] = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "Test the driver using pure ruby (no c extension)"
|
37
|
+
task :ruby do
|
38
|
+
ENV['C_EXT'] = nil
|
39
|
+
Rake::Task['test:unit'].invoke
|
40
|
+
Rake::Task['test:functional'].invoke
|
41
|
+
Rake::Task['test:pooled_threading'].invoke
|
42
|
+
end
|
43
|
+
|
26
44
|
Rake::TestTask.new(:unit) do |t|
|
27
45
|
t.test_files = FileList['test/unit/*_test.rb']
|
28
46
|
t.verbose = true
|
@@ -79,7 +97,7 @@ namespace :gem do
|
|
79
97
|
task :install do
|
80
98
|
sh <<EOS
|
81
99
|
#{gem_command} build mongo-ruby-driver.gemspec &&
|
82
|
-
|
100
|
+
#{gem_command} install mongo-*.gem &&
|
83
101
|
rm mongo-*.gem
|
84
102
|
EOS
|
85
103
|
end
|
@@ -88,7 +106,7 @@ EOS
|
|
88
106
|
task :install_extensions do
|
89
107
|
sh <<EOS
|
90
108
|
#{gem_command} build mongo-extensions.gemspec &&
|
91
|
-
|
109
|
+
#{gem_command} install mongo_ext-*.gem &&
|
92
110
|
rm mongo_ext-*.gem
|
93
111
|
EOS
|
94
112
|
end
|
data/ext/cbson/buffer.c
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2009 10gen, 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
|
+
|
17
|
+
#include <stdlib.h>
|
18
|
+
#include <string.h>
|
19
|
+
|
20
|
+
#include "buffer.h"
|
21
|
+
|
22
|
+
#define INITIAL_BUFFER_SIZE 256
|
23
|
+
|
24
|
+
struct buffer {
|
25
|
+
char* buffer;
|
26
|
+
int size;
|
27
|
+
int position;
|
28
|
+
};
|
29
|
+
|
30
|
+
/* Allocate and return a new buffer.
|
31
|
+
* Return NULL on allocation failure. */
|
32
|
+
buffer_t buffer_new(void) {
|
33
|
+
buffer_t buffer;
|
34
|
+
buffer = (buffer_t)malloc(sizeof(struct buffer));
|
35
|
+
if (buffer == NULL) {
|
36
|
+
return NULL;
|
37
|
+
}
|
38
|
+
|
39
|
+
buffer->size = INITIAL_BUFFER_SIZE;
|
40
|
+
buffer->position = 0;
|
41
|
+
buffer->buffer = (char*)malloc(sizeof(char) * INITIAL_BUFFER_SIZE);
|
42
|
+
if (buffer->buffer == NULL) {
|
43
|
+
free(buffer);
|
44
|
+
return NULL;
|
45
|
+
}
|
46
|
+
|
47
|
+
return buffer;
|
48
|
+
}
|
49
|
+
|
50
|
+
/* Free the memory allocated for `buffer`.
|
51
|
+
* Return non-zero on failure. */
|
52
|
+
int buffer_free(buffer_t buffer) {
|
53
|
+
if (buffer == NULL) {
|
54
|
+
return 1;
|
55
|
+
}
|
56
|
+
free(buffer->buffer);
|
57
|
+
free(buffer);
|
58
|
+
return 0;
|
59
|
+
}
|
60
|
+
|
61
|
+
/* Grow `buffer` to at least `min_length`.
|
62
|
+
* Return non-zero on allocation failure. */
|
63
|
+
static int buffer_grow(buffer_t buffer, int min_length) {
|
64
|
+
int size = buffer->size;
|
65
|
+
char* old_buffer = buffer->buffer;
|
66
|
+
if (size >= min_length) {
|
67
|
+
return 0;
|
68
|
+
}
|
69
|
+
while (size < min_length) {
|
70
|
+
size *= 2;
|
71
|
+
}
|
72
|
+
buffer->buffer = (char*)realloc(buffer->buffer, sizeof(char) * size);
|
73
|
+
if (buffer->buffer == NULL) {
|
74
|
+
free(old_buffer);
|
75
|
+
free(buffer);
|
76
|
+
return 1;
|
77
|
+
}
|
78
|
+
buffer->size = size;
|
79
|
+
return 0;
|
80
|
+
}
|
81
|
+
|
82
|
+
/* Assure that `buffer` has at least `size` free bytes (and grow if needed).
|
83
|
+
* Return non-zero on allocation failure. */
|
84
|
+
static int buffer_assure_space(buffer_t buffer, int size) {
|
85
|
+
if (buffer->position + size <= buffer->size) {
|
86
|
+
return 0;
|
87
|
+
}
|
88
|
+
return buffer_grow(buffer, buffer->position + size);
|
89
|
+
}
|
90
|
+
|
91
|
+
/* Save `size` bytes from the current position in `buffer` (and grow if needed).
|
92
|
+
* Return offset for writing, or -1 on allocation failure. */
|
93
|
+
buffer_position buffer_save_space(buffer_t buffer, int size) {
|
94
|
+
int position = buffer->position;
|
95
|
+
if (buffer_assure_space(buffer, size) != 0) {
|
96
|
+
return -1;
|
97
|
+
}
|
98
|
+
buffer->position += size;
|
99
|
+
return position;
|
100
|
+
}
|
101
|
+
|
102
|
+
/* Write `size` bytes from `data` to `buffer` (and grow if needed).
|
103
|
+
* Return non-zero on allocation failure. */
|
104
|
+
int buffer_write(buffer_t buffer, const char* data, int size) {
|
105
|
+
if (buffer_assure_space(buffer, size) != 0) {
|
106
|
+
return 1;
|
107
|
+
}
|
108
|
+
|
109
|
+
memcpy(buffer->buffer + buffer->position, data, size);
|
110
|
+
buffer->position += size;
|
111
|
+
return 0;
|
112
|
+
}
|
113
|
+
|
114
|
+
/* Write `size` bytes from `data` to `buffer` at position `position`.
|
115
|
+
* Does not change the internal position of `buffer`.
|
116
|
+
* Return non-zero if buffer isn't large enough for write. */
|
117
|
+
int buffer_write_at_position(buffer_t buffer, buffer_position position,
|
118
|
+
const char* data, int size) {
|
119
|
+
if (position + size > buffer->size) {
|
120
|
+
buffer_free(buffer);
|
121
|
+
return 1;
|
122
|
+
}
|
123
|
+
|
124
|
+
memcpy(buffer->buffer + position, data, size);
|
125
|
+
return 0;
|
126
|
+
}
|
127
|
+
|
128
|
+
|
129
|
+
int buffer_get_position(buffer_t buffer) {
|
130
|
+
return buffer->position;
|
131
|
+
}
|
132
|
+
|
133
|
+
char* buffer_get_buffer(buffer_t buffer) {
|
134
|
+
return buffer->buffer;
|
135
|
+
}
|
data/ext/cbson/buffer.h
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2009 10gen, 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
|
+
|
17
|
+
#ifndef BUFFER_H
|
18
|
+
#define BUFFER_H
|
19
|
+
|
20
|
+
/* Note: if any of these functions return a failure condition then the buffer
|
21
|
+
* has already been freed. */
|
22
|
+
|
23
|
+
/* A buffer */
|
24
|
+
typedef struct buffer* buffer_t;
|
25
|
+
/* A position in the buffer */
|
26
|
+
typedef int buffer_position;
|
27
|
+
|
28
|
+
/* Allocate and return a new buffer.
|
29
|
+
* Return NULL on allocation failure. */
|
30
|
+
buffer_t buffer_new(void);
|
31
|
+
|
32
|
+
/* Free the memory allocated for `buffer`.
|
33
|
+
* Return non-zero on failure. */
|
34
|
+
int buffer_free(buffer_t buffer);
|
35
|
+
|
36
|
+
/* Save `size` bytes from the current position in `buffer` (and grow if needed).
|
37
|
+
* Return offset for writing, or -1 on allocation failure. */
|
38
|
+
buffer_position buffer_save_space(buffer_t buffer, int size);
|
39
|
+
|
40
|
+
/* Write `size` bytes from `data` to `buffer` (and grow if needed).
|
41
|
+
* Return non-zero on allocation failure. */
|
42
|
+
int buffer_write(buffer_t buffer, const char* data, int size);
|
43
|
+
|
44
|
+
/* Write `size` bytes from `data` to `buffer` at position `position`.
|
45
|
+
* Does not change the internal position of `buffer`.
|
46
|
+
* Return non-zero if buffer isn't large enough for write. */
|
47
|
+
int buffer_write_at_position(buffer_t buffer, buffer_position position, const char* data, int size);
|
48
|
+
|
49
|
+
/* Getters for the internals of a buffer_t.
|
50
|
+
* Should try to avoid using these as much as possible
|
51
|
+
* since they break the abstraction. */
|
52
|
+
buffer_position buffer_get_position(buffer_t buffer);
|
53
|
+
char* buffer_get_buffer(buffer_t buffer);
|
54
|
+
|
55
|
+
#endif
|
data/ext/cbson/cbson.c
CHANGED
@@ -36,12 +36,23 @@
|
|
36
36
|
#include "regex.h"
|
37
37
|
#endif
|
38
38
|
|
39
|
-
#include <
|
39
|
+
#include <string.h>
|
40
40
|
#include <math.h>
|
41
41
|
#include <unistd.h>
|
42
42
|
#include <time.h>
|
43
43
|
|
44
|
-
#
|
44
|
+
#include "version.h"
|
45
|
+
#include "buffer.h"
|
46
|
+
#include "encoding_helpers.h"
|
47
|
+
|
48
|
+
#define SAFE_WRITE(buffer, data, size) \
|
49
|
+
if (buffer_write((buffer), (data), (size)) != 0) \
|
50
|
+
rb_raise(rb_eNoMemError, "failed to allocate memory in buffer.c")
|
51
|
+
|
52
|
+
#define SAFE_WRITE_AT_POS(buffer, position, data, size) \
|
53
|
+
if (buffer_write_at_position((buffer), (position), (data), (size)) != 0) \
|
54
|
+
rb_raise(rb_eNoMemError, "failed to allocate memory in buffer.c")
|
55
|
+
|
45
56
|
#define MAX_HOSTNAME_LENGTH 256
|
46
57
|
|
47
58
|
static VALUE Binary;
|
@@ -52,13 +63,28 @@ static VALUE Code;
|
|
52
63
|
static VALUE RegexpOfHolding;
|
53
64
|
static VALUE OrderedHash;
|
54
65
|
static VALUE InvalidName;
|
66
|
+
static VALUE InvalidStringEncoding;
|
55
67
|
static VALUE DigestMD5;
|
56
68
|
|
57
69
|
#if HAVE_RUBY_ENCODING_H
|
58
70
|
#include "ruby/encoding.h"
|
59
71
|
#define STR_NEW(p,n) rb_enc_str_new((p), (n), rb_utf8_encoding())
|
72
|
+
/* MUST call TO_UTF8 before calling write_utf8. */
|
73
|
+
#define TO_UTF8(string) rb_str_export_to_enc((string), rb_utf8_encoding())
|
74
|
+
static void write_utf8(buffer_t buffer, VALUE string) {
|
75
|
+
SAFE_WRITE(buffer, RSTRING_PTR(string), RSTRING_LEN(string));
|
76
|
+
}
|
60
77
|
#else
|
61
78
|
#define STR_NEW(p,n) rb_str_new((p), (n))
|
79
|
+
/* MUST call TO_UTF8 before calling write_utf8. */
|
80
|
+
#define TO_UTF8(string) (string)
|
81
|
+
static void write_utf8(buffer_t buffer, VALUE string) {
|
82
|
+
if (!is_legal_utf8_string(RSTRING_PTR(string), RSTRING_LEN(string))) {
|
83
|
+
buffer_free(buffer);
|
84
|
+
rb_raise(InvalidStringEncoding, "String not valid UTF-8");
|
85
|
+
}
|
86
|
+
SAFE_WRITE(buffer, RSTRING_PTR(string), RSTRING_LEN(string));
|
87
|
+
}
|
62
88
|
#endif
|
63
89
|
|
64
90
|
// this sucks. but for some reason these moved around between 1.8 and 1.9
|
@@ -91,12 +117,6 @@ static VALUE DigestMD5;
|
|
91
117
|
#define RREGEXP_SRC_LEN(r) RREGEXP(r)->len
|
92
118
|
#endif
|
93
119
|
|
94
|
-
typedef struct {
|
95
|
-
char* buffer;
|
96
|
-
int size;
|
97
|
-
int position;
|
98
|
-
} bson_buffer;
|
99
|
-
|
100
120
|
static char zero = 0;
|
101
121
|
static char one = 1;
|
102
122
|
|
@@ -104,78 +124,23 @@ static int cmp_char(const void* a, const void* b) {
|
|
104
124
|
return *(char*)a - *(char*)b;
|
105
125
|
}
|
106
126
|
|
107
|
-
static void write_doc(
|
127
|
+
static void write_doc(buffer_t buffer, VALUE hash, VALUE check_keys);
|
108
128
|
static int write_element(VALUE key, VALUE value, VALUE extra);
|
109
129
|
static VALUE elements_to_hash(const char* buffer, int max);
|
110
130
|
|
111
|
-
static
|
112
|
-
bson_buffer* buffer;
|
113
|
-
buffer = ALLOC(bson_buffer);
|
114
|
-
assert(buffer);
|
115
|
-
|
116
|
-
buffer->size = INITIAL_BUFFER_SIZE;
|
117
|
-
buffer->position = 0;
|
118
|
-
buffer->buffer = ALLOC_N(char, INITIAL_BUFFER_SIZE);
|
119
|
-
assert(buffer->buffer);
|
120
|
-
|
121
|
-
return buffer;
|
122
|
-
}
|
123
|
-
|
124
|
-
static void buffer_free(bson_buffer* buffer) {
|
125
|
-
assert(buffer);
|
126
|
-
assert(buffer->buffer);
|
127
|
-
|
128
|
-
free(buffer->buffer);
|
129
|
-
free(buffer);
|
130
|
-
}
|
131
|
-
|
132
|
-
static void buffer_resize(bson_buffer* buffer, int min_length) {
|
133
|
-
int size = buffer->size;
|
134
|
-
if (size >= min_length) {
|
135
|
-
return;
|
136
|
-
}
|
137
|
-
while (size < min_length) {
|
138
|
-
size *= 2;
|
139
|
-
}
|
140
|
-
buffer->buffer = REALLOC_N(buffer->buffer, char, size);
|
141
|
-
assert(buffer->buffer);
|
142
|
-
buffer->size = size;
|
143
|
-
}
|
144
|
-
|
145
|
-
static void buffer_assure_space(bson_buffer* buffer, int size) {
|
146
|
-
if (buffer->position + size <= buffer->size) {
|
147
|
-
return;
|
148
|
-
}
|
149
|
-
buffer_resize(buffer, buffer->position + size);
|
150
|
-
}
|
151
|
-
|
152
|
-
/* returns offset for writing */
|
153
|
-
static int buffer_save_bytes(bson_buffer* buffer, int size) {
|
154
|
-
int position = buffer->position;
|
155
|
-
buffer_assure_space(buffer, size);
|
156
|
-
buffer->position += size;
|
157
|
-
return position;
|
158
|
-
}
|
159
|
-
|
160
|
-
static void buffer_write_bytes(bson_buffer* buffer, const char* bytes, int size) {
|
161
|
-
buffer_assure_space(buffer, size);
|
162
|
-
|
163
|
-
memcpy(buffer->buffer + buffer->position, bytes, size);
|
164
|
-
buffer->position += size;
|
165
|
-
}
|
166
|
-
|
167
|
-
static VALUE pack_extra(bson_buffer* buffer, VALUE check_keys) {
|
131
|
+
static VALUE pack_extra(buffer_t buffer, VALUE check_keys) {
|
168
132
|
return rb_ary_new3(2, LL2NUM((long long)buffer), check_keys);
|
169
133
|
}
|
170
134
|
|
171
|
-
static void write_name_and_type(
|
172
|
-
|
173
|
-
|
174
|
-
|
135
|
+
static void write_name_and_type(buffer_t buffer, VALUE name, char type) {
|
136
|
+
SAFE_WRITE(buffer, &type, 1);
|
137
|
+
name = TO_UTF8(name);
|
138
|
+
write_utf8(buffer, name);
|
139
|
+
SAFE_WRITE(buffer, &zero, 1);
|
175
140
|
}
|
176
141
|
|
177
142
|
static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
178
|
-
|
143
|
+
buffer_t buffer = (buffer_t)NUM2LL(rb_ary_entry(extra, 0));
|
179
144
|
VALUE check_keys = rb_ary_entry(extra, 1);
|
180
145
|
|
181
146
|
if (TYPE(key) == T_SYMBOL) {
|
@@ -184,6 +149,7 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
184
149
|
}
|
185
150
|
|
186
151
|
if (TYPE(key) != T_STRING) {
|
152
|
+
buffer_free(buffer);
|
187
153
|
rb_raise(rb_eTypeError, "keys must be strings or symbols");
|
188
154
|
}
|
189
155
|
|
@@ -194,10 +160,12 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
194
160
|
if (check_keys == Qtrue) {
|
195
161
|
int i;
|
196
162
|
if (RSTRING_LEN(key) > 0 && RSTRING_PTR(key)[0] == '$') {
|
163
|
+
buffer_free(buffer);
|
197
164
|
rb_raise(InvalidName, "key must not start with '$'");
|
198
165
|
}
|
199
166
|
for (i = 0; i < RSTRING_LEN(key); i++) {
|
200
167
|
if (RSTRING_PTR(key)[i] == '.') {
|
168
|
+
buffer_free(buffer);
|
201
169
|
rb_raise(InvalidName, "key must not contain '.'");
|
202
170
|
}
|
203
171
|
}
|
@@ -209,6 +177,7 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
209
177
|
{
|
210
178
|
if (rb_funcall(value, rb_intern(">"), 1, LL2NUM(9223372036854775807LL)) == Qtrue ||
|
211
179
|
rb_funcall(value, rb_intern("<"), 1, LL2NUM(-9223372036854775808LL)) == Qtrue) {
|
180
|
+
buffer_free(buffer);
|
212
181
|
rb_raise(rb_eRangeError, "MongoDB can only handle 8-byte ints");
|
213
182
|
}
|
214
183
|
if (rb_funcall(value, rb_intern(">"), 1, INT2NUM(2147483647L)) == Qtrue ||
|
@@ -216,32 +185,32 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
216
185
|
long long ll_value;
|
217
186
|
write_name_and_type(buffer, key, 0x12);
|
218
187
|
ll_value = NUM2LL(value);
|
219
|
-
|
188
|
+
SAFE_WRITE(buffer, (char*)&ll_value, 8);
|
220
189
|
} else {
|
221
190
|
int int_value;
|
222
191
|
write_name_and_type(buffer, key, 0x10);
|
223
192
|
int_value = NUM2LL(value);
|
224
|
-
|
193
|
+
SAFE_WRITE(buffer, (char*)&int_value, 4);
|
225
194
|
}
|
226
195
|
break;
|
227
196
|
}
|
228
197
|
case T_TRUE:
|
229
198
|
{
|
230
199
|
write_name_and_type(buffer, key, 0x08);
|
231
|
-
|
200
|
+
SAFE_WRITE(buffer, &one, 1);
|
232
201
|
break;
|
233
202
|
}
|
234
203
|
case T_FALSE:
|
235
204
|
{
|
236
205
|
write_name_and_type(buffer, key, 0x08);
|
237
|
-
|
206
|
+
SAFE_WRITE(buffer, &zero, 1);
|
238
207
|
break;
|
239
208
|
}
|
240
209
|
case T_FLOAT:
|
241
210
|
{
|
242
211
|
double d = NUM2DBL(value);
|
243
212
|
write_name_and_type(buffer, key, 0x01);
|
244
|
-
|
213
|
+
SAFE_WRITE(buffer, (char*)&d, 8);
|
245
214
|
break;
|
246
215
|
}
|
247
216
|
case T_NIL:
|
@@ -257,14 +226,18 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
257
226
|
}
|
258
227
|
case T_ARRAY:
|
259
228
|
{
|
260
|
-
|
229
|
+
buffer_position length_location, start_position, obj_length;
|
230
|
+
int items, i;
|
261
231
|
VALUE* values;
|
262
232
|
|
263
233
|
write_name_and_type(buffer, key, 0x04);
|
264
|
-
start_position = buffer
|
234
|
+
start_position = buffer_get_position(buffer);
|
265
235
|
|
266
236
|
// save space for length
|
267
|
-
length_location =
|
237
|
+
length_location = buffer_save_space(buffer, 4);
|
238
|
+
if (length_location == -1) {
|
239
|
+
rb_raise(rb_eNoMemError, "failed to allocate memory in buffer.c");
|
240
|
+
}
|
268
241
|
|
269
242
|
items = RARRAY_LEN(value);
|
270
243
|
values = RARRAY_PTR(value);
|
@@ -278,37 +251,42 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
278
251
|
}
|
279
252
|
|
280
253
|
// write null byte and fill in length
|
281
|
-
|
282
|
-
obj_length = buffer
|
283
|
-
|
254
|
+
SAFE_WRITE(buffer, &zero, 1);
|
255
|
+
obj_length = buffer_get_position(buffer) - start_position;
|
256
|
+
SAFE_WRITE_AT_POS(buffer, length_location, (const char*)&obj_length, 4);
|
284
257
|
break;
|
285
258
|
}
|
286
259
|
case T_STRING:
|
287
260
|
{
|
288
261
|
if (strcmp(rb_class2name(RBASIC(value)->klass),
|
289
262
|
"Mongo::Code") == 0) {
|
290
|
-
|
263
|
+
buffer_position length_location, start_position, total_length;
|
264
|
+
int length;
|
291
265
|
write_name_and_type(buffer, key, 0x0F);
|
292
266
|
|
293
|
-
start_position = buffer
|
294
|
-
length_location =
|
267
|
+
start_position = buffer_get_position(buffer);
|
268
|
+
length_location = buffer_save_space(buffer, 4);
|
269
|
+
if (length_location == -1) {
|
270
|
+
rb_raise(rb_eNoMemError, "failed to allocate memory in buffer.c");
|
271
|
+
}
|
295
272
|
|
296
273
|
length = RSTRING_LEN(value) + 1;
|
297
|
-
|
298
|
-
|
299
|
-
|
274
|
+
SAFE_WRITE(buffer, (char*)&length, 4);
|
275
|
+
SAFE_WRITE(buffer, RSTRING_PTR(value), length - 1);
|
276
|
+
SAFE_WRITE(buffer, &zero, 1);
|
300
277
|
write_doc(buffer, rb_funcall(value, rb_intern("scope"), 0), Qfalse);
|
301
278
|
|
302
|
-
total_length = buffer
|
303
|
-
|
304
|
-
|
279
|
+
total_length = buffer_get_position(buffer) - start_position;
|
280
|
+
SAFE_WRITE_AT_POS(buffer, length_location, (const char*)&total_length, 4);
|
305
281
|
break;
|
306
282
|
} else {
|
307
|
-
int length
|
283
|
+
int length;
|
308
284
|
write_name_and_type(buffer, key, 0x02);
|
309
|
-
|
310
|
-
|
311
|
-
|
285
|
+
value = TO_UTF8(value);
|
286
|
+
length = RSTRING_LEN(value) + 1;
|
287
|
+
SAFE_WRITE(buffer, (char*)&length, 4);
|
288
|
+
write_utf8(buffer, value);
|
289
|
+
SAFE_WRITE(buffer, &zero, 1);
|
312
290
|
break;
|
313
291
|
}
|
314
292
|
}
|
@@ -317,8 +295,8 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
317
295
|
const char* str_value = rb_id2name(SYM2ID(value));
|
318
296
|
int length = strlen(str_value) + 1;
|
319
297
|
write_name_and_type(buffer, key, 0x0E);
|
320
|
-
|
321
|
-
|
298
|
+
SAFE_WRITE(buffer, (char*)&length, 4);
|
299
|
+
SAFE_WRITE(buffer, str_value, length);
|
322
300
|
break;
|
323
301
|
}
|
324
302
|
case T_OBJECT:
|
@@ -334,14 +312,14 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
334
312
|
write_name_and_type(buffer, key, 0x05);
|
335
313
|
if (subtype == 2) {
|
336
314
|
const int other_length = length + 4;
|
337
|
-
|
338
|
-
|
315
|
+
SAFE_WRITE(buffer, (const char*)&other_length, 4);
|
316
|
+
SAFE_WRITE(buffer, &subtype, 1);
|
339
317
|
}
|
340
|
-
|
318
|
+
SAFE_WRITE(buffer, (const char*)&length, 4);
|
341
319
|
if (subtype != 2) {
|
342
|
-
|
320
|
+
SAFE_WRITE(buffer, &subtype, 1);
|
343
321
|
}
|
344
|
-
|
322
|
+
SAFE_WRITE(buffer, RSTRING_PTR(string_data), length);
|
345
323
|
break;
|
346
324
|
}
|
347
325
|
if (strcmp(cls, "Mongo::ObjectID") == 0) {
|
@@ -350,19 +328,22 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
350
328
|
write_name_and_type(buffer, key, 0x07);
|
351
329
|
for (i = 0; i < 12; i++) {
|
352
330
|
char byte = (char)FIX2INT(RARRAY_PTR(as_array)[i]);
|
353
|
-
|
331
|
+
SAFE_WRITE(buffer, &byte, 1);
|
354
332
|
}
|
355
333
|
break;
|
356
334
|
}
|
357
335
|
if (strcmp(cls, "Mongo::DBRef") == 0) {
|
358
|
-
|
336
|
+
buffer_position length_location, start_position, obj_length;
|
359
337
|
VALUE ns, oid;
|
360
338
|
write_name_and_type(buffer, key, 0x03);
|
361
339
|
|
362
|
-
start_position = buffer
|
340
|
+
start_position = buffer_get_position(buffer);
|
363
341
|
|
364
342
|
// save space for length
|
365
|
-
length_location =
|
343
|
+
length_location = buffer_save_space(buffer, 4);
|
344
|
+
if (length_location == -1) {
|
345
|
+
rb_raise(rb_eNoMemError, "failed to allocate memory in buffer.c");
|
346
|
+
}
|
366
347
|
|
367
348
|
ns = rb_funcall(value, rb_intern("namespace"), 0);
|
368
349
|
write_element(rb_str_new2("$ref"), ns, pack_extra(buffer, Qfalse));
|
@@ -370,9 +351,9 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
370
351
|
write_element(rb_str_new2("$id"), oid, pack_extra(buffer, Qfalse));
|
371
352
|
|
372
353
|
// write null byte and fill in length
|
373
|
-
|
374
|
-
obj_length = buffer
|
375
|
-
|
354
|
+
SAFE_WRITE(buffer, &zero, 1);
|
355
|
+
obj_length = buffer_get_position(buffer) - start_position;
|
356
|
+
SAFE_WRITE_AT_POS(buffer, length_location, (const char*)&obj_length, 4);
|
376
357
|
break;
|
377
358
|
}
|
378
359
|
}
|
@@ -384,7 +365,7 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
384
365
|
double t = NUM2DBL(rb_funcall(value, rb_intern("to_f"), 0));
|
385
366
|
long long time_since_epoch = (long long)round(t * 1000);
|
386
367
|
write_name_and_type(buffer, key, 0x09);
|
387
|
-
|
368
|
+
SAFE_WRITE(buffer, (const char*)&time_since_epoch, 8);
|
388
369
|
break;
|
389
370
|
}
|
390
371
|
}
|
@@ -397,35 +378,36 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|
397
378
|
|
398
379
|
write_name_and_type(buffer, key, 0x0B);
|
399
380
|
|
400
|
-
|
401
|
-
|
381
|
+
SAFE_WRITE(buffer, pattern, length);
|
382
|
+
SAFE_WRITE(buffer, &zero, 1);
|
402
383
|
|
403
384
|
if (flags & IGNORECASE) {
|
404
385
|
char ignorecase = 'i';
|
405
|
-
|
386
|
+
SAFE_WRITE(buffer, &ignorecase, 1);
|
406
387
|
}
|
407
388
|
if (flags & MULTILINE) {
|
408
389
|
char multiline = 'm';
|
409
|
-
|
390
|
+
SAFE_WRITE(buffer, &multiline, 1);
|
410
391
|
}
|
411
392
|
if (flags & EXTENDED) {
|
412
393
|
char extended = 'x';
|
413
|
-
|
394
|
+
SAFE_WRITE(buffer, &extended, 1);
|
414
395
|
}
|
415
396
|
|
416
397
|
has_extra = rb_funcall(value, rb_intern("respond_to?"), 1, rb_str_new2("extra_options_str"));
|
417
398
|
if (TYPE(has_extra) == T_TRUE) {
|
418
399
|
VALUE extra = rb_funcall(value, rb_intern("extra_options_str"), 0);
|
419
|
-
|
420
|
-
|
421
|
-
qsort(buffer
|
400
|
+
buffer_position old_position = buffer_get_position(buffer);
|
401
|
+
SAFE_WRITE(buffer, RSTRING_PTR(extra), RSTRING_LEN(extra));
|
402
|
+
qsort(buffer_get_buffer(buffer) + old_position, RSTRING_LEN(extra), sizeof(char), cmp_char);
|
422
403
|
}
|
423
|
-
|
404
|
+
SAFE_WRITE(buffer, &zero, 1);
|
424
405
|
|
425
406
|
break;
|
426
407
|
}
|
427
408
|
default:
|
428
409
|
{
|
410
|
+
buffer_free(buffer);
|
429
411
|
rb_raise(rb_eTypeError, "no c encoder for this type yet (%d)", TYPE(value));
|
430
412
|
break;
|
431
413
|
}
|
@@ -437,13 +419,17 @@ static int write_element(VALUE key, VALUE value, VALUE extra) {
|
|
437
419
|
return write_element_allow_id(key, value, extra, 0);
|
438
420
|
}
|
439
421
|
|
440
|
-
static void write_doc(
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
422
|
+
static void write_doc(buffer_t buffer, VALUE hash, VALUE check_keys) {
|
423
|
+
buffer_position start_position = buffer_get_position(buffer);
|
424
|
+
buffer_position length_location = buffer_save_space(buffer, 4);
|
425
|
+
buffer_position length;
|
445
426
|
VALUE id_str = rb_str_new2("_id");
|
446
427
|
VALUE id_sym = ID2SYM(rb_intern("_id"));
|
428
|
+
|
429
|
+
if (length_location == -1) {
|
430
|
+
rb_raise(rb_eNoMemError, "failed to allocate memory in buffer.c");
|
431
|
+
}
|
432
|
+
|
447
433
|
if (rb_funcall(hash, rb_intern("has_key?"), 1, id_str) == Qtrue) {
|
448
434
|
VALUE id = rb_hash_aref(hash, id_str);
|
449
435
|
write_element_allow_id(id_str, id, pack_extra(buffer, check_keys), 1);
|
@@ -467,20 +453,24 @@ static void write_doc(bson_buffer* buffer, VALUE hash, VALUE check_keys) {
|
|
467
453
|
}
|
468
454
|
|
469
455
|
// write null byte and fill in length
|
470
|
-
|
471
|
-
length = buffer
|
472
|
-
|
456
|
+
SAFE_WRITE(buffer, &zero, 1);
|
457
|
+
length = buffer_get_position(buffer) - start_position;
|
458
|
+
SAFE_WRITE_AT_POS(buffer, length_location, &length, 4);
|
473
459
|
}
|
474
460
|
|
475
461
|
static VALUE method_serialize(VALUE self, VALUE doc, VALUE check_keys) {
|
476
462
|
VALUE result;
|
477
|
-
|
478
|
-
|
463
|
+
buffer_t buffer = buffer_new();
|
464
|
+
if (buffer == NULL) {
|
465
|
+
rb_raise(rb_eNoMemError, "failed to allocate memory in buffer.c");
|
466
|
+
}
|
479
467
|
|
480
468
|
write_doc(buffer, doc, check_keys);
|
481
469
|
|
482
|
-
result = rb_str_new(buffer
|
483
|
-
buffer_free(buffer)
|
470
|
+
result = rb_str_new(buffer_get_buffer(buffer), buffer_get_position(buffer));
|
471
|
+
if (buffer_free(buffer) != 0) {
|
472
|
+
rb_raise(rb_eRuntimeError, "failed to free buffer");
|
473
|
+
}
|
484
474
|
return result;
|
485
475
|
}
|
486
476
|
|
@@ -589,7 +579,7 @@ static VALUE get_value(const char* buffer, int* position, int type) {
|
|
589
579
|
long long millis;
|
590
580
|
VALUE seconds, microseconds;
|
591
581
|
memcpy(&millis, buffer + *position, 8);
|
592
|
-
seconds =
|
582
|
+
seconds = LL2NUM(millis / 1000);
|
593
583
|
microseconds = INT2NUM((millis % 1000) * 1000);
|
594
584
|
|
595
585
|
value = rb_funcall(Time, rb_intern("at"), 2, seconds, microseconds);
|
@@ -771,7 +761,7 @@ static VALUE objectid_generate(VALUE self)
|
|
771
761
|
t = htonl(time(NULL));
|
772
762
|
MEMCPY(&oid_bytes, &t, unsigned char, 4);
|
773
763
|
|
774
|
-
if (gethostname(
|
764
|
+
if (gethostname(hostname, MAX_HOSTNAME_LENGTH) != 0) {
|
775
765
|
rb_raise(rb_eRuntimeError, "failed to get hostname");
|
776
766
|
}
|
777
767
|
digest = rb_funcall(DigestMD5, rb_intern("digest"), 1, rb_str_new2(hostname));
|
@@ -792,7 +782,7 @@ static VALUE objectid_generate(VALUE self)
|
|
792
782
|
|
793
783
|
|
794
784
|
void Init_cbson() {
|
795
|
-
VALUE mongo, CBson, Digest;
|
785
|
+
VALUE mongo, CBson, Digest, ext_version;
|
796
786
|
Time = rb_const_get(rb_cObject, rb_intern("Time"));
|
797
787
|
|
798
788
|
mongo = rb_const_get(rb_cObject, rb_intern("Mongo"));
|
@@ -808,10 +798,13 @@ void Init_cbson() {
|
|
808
798
|
RegexpOfHolding = rb_const_get(mongo, rb_intern("RegexpOfHolding"));
|
809
799
|
rb_require("mongo/errors");
|
810
800
|
InvalidName = rb_const_get(mongo, rb_intern("InvalidName"));
|
801
|
+
InvalidStringEncoding = rb_const_get(mongo, rb_intern("InvalidStringEncoding"));
|
811
802
|
rb_require("mongo/util/ordered_hash");
|
812
803
|
OrderedHash = rb_const_get(rb_cObject, rb_intern("OrderedHash"));
|
813
804
|
|
814
805
|
CBson = rb_define_module("CBson");
|
806
|
+
ext_version = rb_str_new2(VERSION);
|
807
|
+
rb_define_const(CBson, "VERSION", ext_version);
|
815
808
|
rb_define_module_function(CBson, "serialize", method_serialize, 2);
|
816
809
|
rb_define_module_function(CBson, "deserialize", method_deserialize, 1);
|
817
810
|
|
@@ -0,0 +1,107 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2009 10gen, 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
|
+
|
17
|
+
/*
|
18
|
+
* Copyright 2001 Unicode, Inc.
|
19
|
+
*
|
20
|
+
* Disclaimer
|
21
|
+
*
|
22
|
+
* This source code is provided as is by Unicode, Inc. No claims are
|
23
|
+
* made as to fitness for any particular purpose. No warranties of any
|
24
|
+
* kind are expressed or implied. The recipient agrees to determine
|
25
|
+
* applicability of information provided. If this file has been
|
26
|
+
* purchased on magnetic or optical media from Unicode, Inc., the
|
27
|
+
* sole remedy for any claim will be exchange of defective media
|
28
|
+
* within 90 days of receipt.
|
29
|
+
*
|
30
|
+
* Limitations on Rights to Redistribute This Code
|
31
|
+
*
|
32
|
+
* Unicode, Inc. hereby grants the right to freely use the information
|
33
|
+
* supplied in this file in the creation of products supporting the
|
34
|
+
* Unicode Standard, and to make copies of this file in any form
|
35
|
+
* for internal or external distribution as long as this notice
|
36
|
+
* remains attached.
|
37
|
+
*/
|
38
|
+
|
39
|
+
/*
|
40
|
+
* Index into the table below with the first byte of a UTF-8 sequence to
|
41
|
+
* get the number of trailing bytes that are supposed to follow it.
|
42
|
+
*/
|
43
|
+
static const char trailingBytesForUTF8[256] = {
|
44
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
45
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
46
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
47
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
48
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
49
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
50
|
+
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
51
|
+
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
|
52
|
+
};
|
53
|
+
|
54
|
+
/* --------------------------------------------------------------------- */
|
55
|
+
|
56
|
+
/*
|
57
|
+
* Utility routine to tell whether a sequence of bytes is legal UTF-8.
|
58
|
+
* This must be called with the length pre-determined by the first byte.
|
59
|
+
* The length can be set by:
|
60
|
+
* length = trailingBytesForUTF8[*source]+1;
|
61
|
+
* and the sequence is illegal right away if there aren't that many bytes
|
62
|
+
* available.
|
63
|
+
* If presented with a length > 4, this returns 0. The Unicode
|
64
|
+
* definition of UTF-8 goes up to 4-byte sequences.
|
65
|
+
*/
|
66
|
+
static unsigned char isLegalUTF8(const unsigned char* source, int length) {
|
67
|
+
unsigned char a;
|
68
|
+
const unsigned char* srcptr = source + length;
|
69
|
+
switch (length) {
|
70
|
+
default: return 0;
|
71
|
+
/* Everything else falls through when "true"... */
|
72
|
+
case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
|
73
|
+
case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
|
74
|
+
case 2: if ((a = (*--srcptr)) > 0xBF) return 0;
|
75
|
+
switch (*source) {
|
76
|
+
/* no fall-through in this inner switch */
|
77
|
+
case 0xE0: if (a < 0xA0) return 0; break;
|
78
|
+
case 0xF0: if (a < 0x90) return 0; break;
|
79
|
+
case 0xF4: if (a > 0x8F) return 0; break;
|
80
|
+
default: if (a < 0x80) return 0;
|
81
|
+
}
|
82
|
+
case 1: if (*source >= 0x80 && *source < 0xC2) return 0;
|
83
|
+
if (*source > 0xF4) return 0;
|
84
|
+
}
|
85
|
+
return 1;
|
86
|
+
}
|
87
|
+
|
88
|
+
/* --------------------------------------------------------------------- */
|
89
|
+
|
90
|
+
/*
|
91
|
+
* Return whether a string containing UTF-8 is legal.
|
92
|
+
*/
|
93
|
+
unsigned char is_legal_utf8_string(const unsigned char* string, const int length) {
|
94
|
+
int position = 0;
|
95
|
+
|
96
|
+
while (position < length) {
|
97
|
+
int sequence_length = trailingBytesForUTF8[*(string + position)] + 1;
|
98
|
+
if ((position + sequence_length) > length) {
|
99
|
+
return 0;
|
100
|
+
}
|
101
|
+
if (!isLegalUTF8(string + position, sequence_length)) {
|
102
|
+
return 0;
|
103
|
+
}
|
104
|
+
position += sequence_length;
|
105
|
+
}
|
106
|
+
return 1;
|
107
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2009 10gen, 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
|
+
|
17
|
+
#ifndef ENCODING_HELPERS_H
|
18
|
+
#define ENCODING_HELPERS_H
|
19
|
+
|
20
|
+
unsigned char is_legal_utf8_string(const unsigned char* string, const int length);
|
21
|
+
|
22
|
+
#endif
|
data/ext/cbson/version.h
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2009 10gen, 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
|
+
|
17
|
+
#define VERSION "0.18.1"
|
data/mongo-extensions.gemspec
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
require 'lib/mongo'
|
2
|
-
|
2
|
+
VERSION_HEADER = File.open(File.join(File.dirname(__FILE__), 'ext', 'cbson', 'version.h'), "r")
|
3
|
+
VERSION = VERSION_HEADER.read.scan(/VERSION\s+"(\d+\.\d+(\.\d+)?)\"/)[0][0]
|
3
4
|
Gem::Specification.new do |s|
|
4
5
|
s.name = 'mongo_ext'
|
5
6
|
|
6
|
-
s.version
|
7
|
+
s.version = VERSION
|
7
8
|
s.platform = Gem::Platform::RUBY
|
8
|
-
s.summary
|
9
|
+
s.summary = 'C extensions for the MongoDB Ruby driver'
|
9
10
|
s.description = 'C extensions to accelerate the MongoDB Ruby driver. For more information about Mongo, see http://www.mongodb.org.'
|
10
11
|
|
11
12
|
s.require_paths = ['ext']
|
12
13
|
s.files = ['Rakefile', 'mongo-extensions.gemspec']
|
13
|
-
s.files += Dir['ext/**/*.rb'] + Dir['ext/**/*.c']
|
14
|
+
s.files += Dir['ext/**/*.rb'] + Dir['ext/**/*.c'] + Dir['ext/**/*.h']
|
14
15
|
s.test_files = []
|
15
16
|
|
16
17
|
s.has_rdoc = false
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongo_ext
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.18.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Dirolf
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-12-05 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -25,11 +25,14 @@ files:
|
|
25
25
|
- Rakefile
|
26
26
|
- mongo-extensions.gemspec
|
27
27
|
- ext/cbson/extconf.rb
|
28
|
+
- ext/cbson/buffer.c
|
28
29
|
- ext/cbson/cbson.c
|
29
|
-
|
30
|
+
- ext/cbson/encoding_helpers.c
|
31
|
+
- ext/cbson/buffer.h
|
32
|
+
- ext/cbson/encoding_helpers.h
|
33
|
+
- ext/cbson/version.h
|
34
|
+
has_rdoc: false
|
30
35
|
homepage: http://www.mongodb.org
|
31
|
-
licenses: []
|
32
|
-
|
33
36
|
post_install_message:
|
34
37
|
rdoc_options: []
|
35
38
|
|
@@ -50,9 +53,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
50
53
|
requirements: []
|
51
54
|
|
52
55
|
rubyforge_project:
|
53
|
-
rubygems_version: 1.3.
|
56
|
+
rubygems_version: 1.3.1
|
54
57
|
signing_key:
|
55
|
-
specification_version:
|
58
|
+
specification_version: 2
|
56
59
|
summary: C extensions for the MongoDB Ruby driver
|
57
60
|
test_files: []
|
58
61
|
|