mongo_ext 0.18 → 0.18.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|