faststep 0.0.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/.gitignore +6 -0
- data/Gemfile +4 -0
- data/Rakefile +15 -0
- data/bench/standard_benchmark +178 -0
- data/ext/faststep/bson.c +687 -0
- data/ext/faststep/bson.h +225 -0
- data/ext/faststep/bson_ruby_conversion.c +44 -0
- data/ext/faststep/bson_ruby_conversion.h +10 -0
- data/ext/faststep/collection.c +187 -0
- data/ext/faststep/collection.h +24 -0
- data/ext/faststep/connection.c +85 -0
- data/ext/faststep/connection.h +17 -0
- data/ext/faststep/cursor.c +61 -0
- data/ext/faststep/cursor.h +10 -0
- data/ext/faststep/db.c +56 -0
- data/ext/faststep/db.h +8 -0
- data/ext/faststep/exceptions.c +7 -0
- data/ext/faststep/exceptions.h +5 -0
- data/ext/faststep/extconf.rb +3 -0
- data/ext/faststep/faststep.c +30 -0
- data/ext/faststep/faststep.h +4 -0
- data/ext/faststep/faststep_defines.h +11 -0
- data/ext/faststep/gridfs.c +799 -0
- data/ext/faststep/gridfs.h +278 -0
- data/ext/faststep/md5.c +381 -0
- data/ext/faststep/md5.h +91 -0
- data/ext/faststep/mongo.c +801 -0
- data/ext/faststep/mongo.h +188 -0
- data/ext/faststep/mongo_except.h +143 -0
- data/ext/faststep/numbers.c +127 -0
- data/ext/faststep/platform_hacks.h +93 -0
- data/ext/faststep/support.c +21 -0
- data/ext/faststep/support.h +6 -0
- data/faststep.gemspec +26 -0
- data/lib/faststep/collection.rb +21 -0
- data/lib/faststep/connection.rb +13 -0
- data/lib/faststep/cursor.rb +7 -0
- data/lib/faststep/db.rb +25 -0
- data/lib/faststep/version.rb +3 -0
- data/lib/faststep.rb +10 -0
- data/spec/collection_spec.rb +116 -0
- data/spec/connection_spec.rb +34 -0
- data/spec/cursor_spec.rb +24 -0
- data/spec/db_spec.rb +28 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support_spec.rb +14 -0
- metadata +181 -0
data/ext/faststep/bson.c
ADDED
@@ -0,0 +1,687 @@
|
|
1
|
+
/* bson.c */
|
2
|
+
|
3
|
+
/* Copyright 2009, 2010 10gen Inc.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#include "bson.h"
|
19
|
+
#include <stdlib.h>
|
20
|
+
#include <string.h>
|
21
|
+
#include <stdio.h>
|
22
|
+
#include <time.h>
|
23
|
+
|
24
|
+
const int initialBufferSize = 128;
|
25
|
+
|
26
|
+
/* only need one of these */
|
27
|
+
static const int zero = 0;
|
28
|
+
|
29
|
+
/* ----------------------------
|
30
|
+
READING
|
31
|
+
------------------------------ */
|
32
|
+
|
33
|
+
bson * bson_empty(bson * obj){
|
34
|
+
static char * data = "\005\0\0\0\0";
|
35
|
+
return bson_init(obj, data, 0);
|
36
|
+
}
|
37
|
+
|
38
|
+
void bson_copy(bson* out, const bson* in){
|
39
|
+
if (!out) return;
|
40
|
+
out->data = bson_malloc(bson_size(in));
|
41
|
+
out->owned = 1;
|
42
|
+
memcpy(out->data, in->data, bson_size(in));
|
43
|
+
}
|
44
|
+
|
45
|
+
bson * bson_from_buffer(bson * b, bson_buffer * buf){
|
46
|
+
return bson_init(b, bson_buffer_finish(buf), 1);
|
47
|
+
}
|
48
|
+
|
49
|
+
bson * bson_init( bson * b , char * data , bson_bool_t mine ){
|
50
|
+
b->data = data;
|
51
|
+
b->owned = mine;
|
52
|
+
return b;
|
53
|
+
}
|
54
|
+
int bson_size(const bson * b ){
|
55
|
+
int i;
|
56
|
+
if ( ! b || ! b->data )
|
57
|
+
return 0;
|
58
|
+
bson_little_endian32(&i, b->data);
|
59
|
+
return i;
|
60
|
+
}
|
61
|
+
void bson_destroy( bson * b ){
|
62
|
+
if ( b->owned && b->data )
|
63
|
+
free( b->data );
|
64
|
+
b->data = 0;
|
65
|
+
b->owned = 0;
|
66
|
+
}
|
67
|
+
|
68
|
+
static char hexbyte(char hex){
|
69
|
+
switch (hex){
|
70
|
+
case '0': return 0x0;
|
71
|
+
case '1': return 0x1;
|
72
|
+
case '2': return 0x2;
|
73
|
+
case '3': return 0x3;
|
74
|
+
case '4': return 0x4;
|
75
|
+
case '5': return 0x5;
|
76
|
+
case '6': return 0x6;
|
77
|
+
case '7': return 0x7;
|
78
|
+
case '8': return 0x8;
|
79
|
+
case '9': return 0x9;
|
80
|
+
case 'a':
|
81
|
+
case 'A': return 0xa;
|
82
|
+
case 'b':
|
83
|
+
case 'B': return 0xb;
|
84
|
+
case 'c':
|
85
|
+
case 'C': return 0xc;
|
86
|
+
case 'd':
|
87
|
+
case 'D': return 0xd;
|
88
|
+
case 'e':
|
89
|
+
case 'E': return 0xe;
|
90
|
+
case 'f':
|
91
|
+
case 'F': return 0xf;
|
92
|
+
default: return 0x0; /* something smarter? */
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
void bson_oid_from_string(bson_oid_t* oid, const char* str){
|
97
|
+
int i;
|
98
|
+
for (i=0; i<12; i++){
|
99
|
+
oid->bytes[i] = (hexbyte(str[2*i]) << 4) | hexbyte(str[2*i + 1]);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
void bson_oid_to_string(const bson_oid_t* oid, char* str){
|
103
|
+
static const char hex[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
|
104
|
+
int i;
|
105
|
+
for (i=0; i<12; i++){
|
106
|
+
str[2*i] = hex[(oid->bytes[i] & 0xf0) >> 4];
|
107
|
+
str[2*i + 1] = hex[ oid->bytes[i] & 0x0f ];
|
108
|
+
}
|
109
|
+
str[24] = '\0';
|
110
|
+
}
|
111
|
+
void bson_oid_gen(bson_oid_t* oid){
|
112
|
+
static int incr = 0;
|
113
|
+
static int fuzz = 0;
|
114
|
+
int i = incr++; /*TODO make atomic*/
|
115
|
+
int t = time(NULL);
|
116
|
+
|
117
|
+
/* TODO rand sucks. find something better */
|
118
|
+
if (!fuzz){
|
119
|
+
srand(t);
|
120
|
+
fuzz = rand();
|
121
|
+
}
|
122
|
+
|
123
|
+
bson_big_endian32(&oid->ints[0], &t);
|
124
|
+
oid->ints[1] = fuzz;
|
125
|
+
bson_big_endian32(&oid->ints[2], &i);
|
126
|
+
}
|
127
|
+
|
128
|
+
time_t bson_oid_generated_time(bson_oid_t* oid){
|
129
|
+
time_t out;
|
130
|
+
bson_big_endian32(&out, &oid->ints[0]);
|
131
|
+
return out;
|
132
|
+
|
133
|
+
}
|
134
|
+
void bson_print( bson * b ){
|
135
|
+
bson_print_raw( b->data , 0 );
|
136
|
+
}
|
137
|
+
|
138
|
+
void bson_print_raw( const char * data , int depth ){
|
139
|
+
bson_iterator i;
|
140
|
+
const char * key;
|
141
|
+
int temp;
|
142
|
+
bson_timestamp_t ts;
|
143
|
+
char oidhex[25];
|
144
|
+
bson_iterator_init( &i , data );
|
145
|
+
|
146
|
+
while ( bson_iterator_next( &i ) ){
|
147
|
+
bson_type t = bson_iterator_type( &i );
|
148
|
+
if ( t == 0 )
|
149
|
+
break;
|
150
|
+
key = bson_iterator_key( &i );
|
151
|
+
|
152
|
+
for ( temp=0; temp<=depth; temp++ )
|
153
|
+
printf( "\t" );
|
154
|
+
printf( "%s : %d \t " , key , t );
|
155
|
+
switch ( t ){
|
156
|
+
case bson_int: printf( "%d" , bson_iterator_int( &i ) ); break;
|
157
|
+
case bson_double: printf( "%f" , bson_iterator_double( &i ) ); break;
|
158
|
+
case bson_bool: printf( "%s" , bson_iterator_bool( &i ) ? "true" : "false" ); break;
|
159
|
+
case bson_string: printf( "%s" , bson_iterator_string( &i ) ); break;
|
160
|
+
case bson_null: printf( "null" ); break;
|
161
|
+
case bson_oid: bson_oid_to_string(bson_iterator_oid(&i), oidhex); printf( "%s" , oidhex ); break;
|
162
|
+
case bson_timestamp:
|
163
|
+
ts = bson_iterator_timestamp( &i );
|
164
|
+
printf("i: %d, t: %d", ts.i, ts.t);
|
165
|
+
break;
|
166
|
+
case bson_object:
|
167
|
+
case bson_array:
|
168
|
+
printf( "\n" );
|
169
|
+
bson_print_raw( bson_iterator_value( &i ) , depth + 1 );
|
170
|
+
break;
|
171
|
+
default:
|
172
|
+
fprintf( stderr , "can't print type : %d\n" , t );
|
173
|
+
}
|
174
|
+
printf( "\n" );
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
/* ----------------------------
|
179
|
+
ITERATOR
|
180
|
+
------------------------------ */
|
181
|
+
|
182
|
+
void bson_iterator_init( bson_iterator * i , const char * bson ){
|
183
|
+
i->cur = bson + 4;
|
184
|
+
i->first = 1;
|
185
|
+
}
|
186
|
+
|
187
|
+
bson_type bson_find(bson_iterator* it, const bson* obj, const char* name){
|
188
|
+
bson_iterator_init(it, obj->data);
|
189
|
+
while(bson_iterator_next(it)){
|
190
|
+
if (strcmp(name, bson_iterator_key(it)) == 0)
|
191
|
+
break;
|
192
|
+
}
|
193
|
+
return bson_iterator_type(it);
|
194
|
+
}
|
195
|
+
|
196
|
+
bson_bool_t bson_iterator_more( const bson_iterator * i ){
|
197
|
+
return *(i->cur);
|
198
|
+
}
|
199
|
+
|
200
|
+
bson_type bson_iterator_next( bson_iterator * i ){
|
201
|
+
int ds;
|
202
|
+
|
203
|
+
if ( i->first ){
|
204
|
+
i->first = 0;
|
205
|
+
return (bson_type)(*i->cur);
|
206
|
+
}
|
207
|
+
|
208
|
+
switch ( bson_iterator_type(i) ){
|
209
|
+
case bson_eoo: return bson_eoo; /* don't advance */
|
210
|
+
case bson_undefined:
|
211
|
+
case bson_null: ds = 0; break;
|
212
|
+
case bson_bool: ds = 1; break;
|
213
|
+
case bson_int: ds = 4; break;
|
214
|
+
case bson_long:
|
215
|
+
case bson_double:
|
216
|
+
case bson_timestamp:
|
217
|
+
case bson_date: ds = 8; break;
|
218
|
+
case bson_oid: ds = 12; break;
|
219
|
+
case bson_string:
|
220
|
+
case bson_symbol:
|
221
|
+
case bson_code: ds = 4 + bson_iterator_int_raw(i); break;
|
222
|
+
case bson_bindata: ds = 5 + bson_iterator_int_raw(i); break;
|
223
|
+
case bson_object:
|
224
|
+
case bson_array:
|
225
|
+
case bson_codewscope: ds = bson_iterator_int_raw(i); break;
|
226
|
+
case bson_dbref: ds = 4+12 + bson_iterator_int_raw(i); break;
|
227
|
+
case bson_regex:
|
228
|
+
{
|
229
|
+
const char * s = bson_iterator_value(i);
|
230
|
+
const char * p = s;
|
231
|
+
p += strlen(p)+1;
|
232
|
+
p += strlen(p)+1;
|
233
|
+
ds = p-s;
|
234
|
+
break;
|
235
|
+
}
|
236
|
+
|
237
|
+
default:
|
238
|
+
{
|
239
|
+
char msg[] = "unknown type: 000000000000";
|
240
|
+
bson_numstr(msg+14, (unsigned)(i->cur[0]));
|
241
|
+
bson_fatal_msg(0, msg);
|
242
|
+
return 0;
|
243
|
+
}
|
244
|
+
}
|
245
|
+
|
246
|
+
i->cur += 1 + strlen( i->cur + 1 ) + 1 + ds;
|
247
|
+
|
248
|
+
return (bson_type)(*i->cur);
|
249
|
+
}
|
250
|
+
|
251
|
+
bson_type bson_iterator_type( const bson_iterator * i ){
|
252
|
+
return (bson_type)i->cur[0];
|
253
|
+
}
|
254
|
+
const char * bson_iterator_key( const bson_iterator * i ){
|
255
|
+
return i->cur + 1;
|
256
|
+
}
|
257
|
+
const char * bson_iterator_value( const bson_iterator * i ){
|
258
|
+
const char * t = i->cur + 1;
|
259
|
+
t += strlen( t ) + 1;
|
260
|
+
return t;
|
261
|
+
}
|
262
|
+
|
263
|
+
/* types */
|
264
|
+
|
265
|
+
int bson_iterator_int_raw( const bson_iterator * i ){
|
266
|
+
int out;
|
267
|
+
bson_little_endian32(&out, bson_iterator_value( i ));
|
268
|
+
return out;
|
269
|
+
}
|
270
|
+
double bson_iterator_double_raw( const bson_iterator * i ){
|
271
|
+
double out;
|
272
|
+
bson_little_endian64(&out, bson_iterator_value( i ));
|
273
|
+
return out;
|
274
|
+
}
|
275
|
+
int64_t bson_iterator_long_raw( const bson_iterator * i ){
|
276
|
+
int64_t out;
|
277
|
+
bson_little_endian64(&out, bson_iterator_value( i ));
|
278
|
+
return out;
|
279
|
+
}
|
280
|
+
|
281
|
+
bson_bool_t bson_iterator_bool_raw( const bson_iterator * i ){
|
282
|
+
return bson_iterator_value( i )[0];
|
283
|
+
}
|
284
|
+
|
285
|
+
bson_oid_t * bson_iterator_oid( const bson_iterator * i ){
|
286
|
+
return (bson_oid_t*)bson_iterator_value(i);
|
287
|
+
}
|
288
|
+
|
289
|
+
int bson_iterator_int( const bson_iterator * i ){
|
290
|
+
switch (bson_iterator_type(i)){
|
291
|
+
case bson_int: return bson_iterator_int_raw(i);
|
292
|
+
case bson_long: return bson_iterator_long_raw(i);
|
293
|
+
case bson_double: return bson_iterator_double_raw(i);
|
294
|
+
default: return 0;
|
295
|
+
}
|
296
|
+
}
|
297
|
+
double bson_iterator_double( const bson_iterator * i ){
|
298
|
+
switch (bson_iterator_type(i)){
|
299
|
+
case bson_int: return bson_iterator_int_raw(i);
|
300
|
+
case bson_long: return bson_iterator_long_raw(i);
|
301
|
+
case bson_double: return bson_iterator_double_raw(i);
|
302
|
+
default: return 0;
|
303
|
+
}
|
304
|
+
}
|
305
|
+
int64_t bson_iterator_long( const bson_iterator * i ){
|
306
|
+
switch (bson_iterator_type(i)){
|
307
|
+
case bson_int: return bson_iterator_int_raw(i);
|
308
|
+
case bson_long: return bson_iterator_long_raw(i);
|
309
|
+
case bson_double: return bson_iterator_double_raw(i);
|
310
|
+
default: return 0;
|
311
|
+
}
|
312
|
+
}
|
313
|
+
|
314
|
+
bson_timestamp_t bson_iterator_timestamp( const bson_iterator * i){
|
315
|
+
bson_timestamp_t ts;
|
316
|
+
bson_little_endian32(&(ts.i), bson_iterator_value(i));
|
317
|
+
bson_little_endian32(&(ts.t), bson_iterator_value(i) + 4);
|
318
|
+
return ts;
|
319
|
+
}
|
320
|
+
|
321
|
+
bson_bool_t bson_iterator_bool( const bson_iterator * i ){
|
322
|
+
switch (bson_iterator_type(i)){
|
323
|
+
case bson_bool: return bson_iterator_bool_raw(i);
|
324
|
+
case bson_int: return bson_iterator_int_raw(i) != 0;
|
325
|
+
case bson_long: return bson_iterator_long_raw(i) != 0;
|
326
|
+
case bson_double: return bson_iterator_double_raw(i) != 0;
|
327
|
+
case bson_eoo:
|
328
|
+
case bson_null: return 0;
|
329
|
+
default: return 1;
|
330
|
+
}
|
331
|
+
}
|
332
|
+
|
333
|
+
const char * bson_iterator_string( const bson_iterator * i ){
|
334
|
+
return bson_iterator_value( i ) + 4;
|
335
|
+
}
|
336
|
+
int bson_iterator_string_len( const bson_iterator * i ){
|
337
|
+
return bson_iterator_int_raw( i );
|
338
|
+
}
|
339
|
+
|
340
|
+
const char * bson_iterator_code( const bson_iterator * i ){
|
341
|
+
switch (bson_iterator_type(i)){
|
342
|
+
case bson_string:
|
343
|
+
case bson_code: return bson_iterator_value(i) + 4;
|
344
|
+
case bson_codewscope: return bson_iterator_value(i) + 8;
|
345
|
+
default: return NULL;
|
346
|
+
}
|
347
|
+
}
|
348
|
+
|
349
|
+
void bson_iterator_code_scope(const bson_iterator * i, bson * scope){
|
350
|
+
if (bson_iterator_type(i) == bson_codewscope){
|
351
|
+
int code_len;
|
352
|
+
bson_little_endian32(&code_len, bson_iterator_value(i)+4);
|
353
|
+
bson_init(scope, (void*)(bson_iterator_value(i)+8+code_len), 0);
|
354
|
+
}else{
|
355
|
+
bson_empty(scope);
|
356
|
+
}
|
357
|
+
}
|
358
|
+
|
359
|
+
bson_date_t bson_iterator_date(const bson_iterator * i){
|
360
|
+
return bson_iterator_long_raw(i);
|
361
|
+
}
|
362
|
+
|
363
|
+
time_t bson_iterator_time_t(const bson_iterator * i){
|
364
|
+
return bson_iterator_date(i) / 1000;
|
365
|
+
}
|
366
|
+
|
367
|
+
int bson_iterator_bin_len( const bson_iterator * i ){
|
368
|
+
return (bson_iterator_bin_type(i) == 2)
|
369
|
+
? bson_iterator_int_raw( i ) - 4
|
370
|
+
: bson_iterator_int_raw( i );
|
371
|
+
}
|
372
|
+
|
373
|
+
char bson_iterator_bin_type( const bson_iterator * i ){
|
374
|
+
return bson_iterator_value(i)[4];
|
375
|
+
}
|
376
|
+
const char * bson_iterator_bin_data( const bson_iterator * i ){
|
377
|
+
return (bson_iterator_bin_type( i ) == 2)
|
378
|
+
? bson_iterator_value( i ) + 9
|
379
|
+
: bson_iterator_value( i ) + 5;
|
380
|
+
}
|
381
|
+
|
382
|
+
const char * bson_iterator_regex( const bson_iterator * i ){
|
383
|
+
return bson_iterator_value( i );
|
384
|
+
}
|
385
|
+
const char * bson_iterator_regex_opts( const bson_iterator * i ){
|
386
|
+
const char* p = bson_iterator_value( i );
|
387
|
+
return p + strlen(p) + 1;
|
388
|
+
|
389
|
+
}
|
390
|
+
|
391
|
+
void bson_iterator_subobject(const bson_iterator * i, bson * sub){
|
392
|
+
bson_init(sub, (char*)bson_iterator_value(i), 0);
|
393
|
+
}
|
394
|
+
void bson_iterator_subiterator(const bson_iterator * i, bson_iterator * sub){
|
395
|
+
bson_iterator_init(sub, bson_iterator_value(i));
|
396
|
+
}
|
397
|
+
|
398
|
+
/* ----------------------------
|
399
|
+
BUILDING
|
400
|
+
------------------------------ */
|
401
|
+
|
402
|
+
bson_buffer * bson_buffer_init( bson_buffer * b ){
|
403
|
+
b->buf = (char*)bson_malloc( initialBufferSize );
|
404
|
+
b->bufSize = initialBufferSize;
|
405
|
+
b->cur = b->buf + 4;
|
406
|
+
b->finished = 0;
|
407
|
+
b->stackPos = 0;
|
408
|
+
return b;
|
409
|
+
}
|
410
|
+
|
411
|
+
void bson_append_byte( bson_buffer * b , char c ){
|
412
|
+
b->cur[0] = c;
|
413
|
+
b->cur++;
|
414
|
+
}
|
415
|
+
void bson_append( bson_buffer * b , const void * data , int len ){
|
416
|
+
memcpy( b->cur , data , len );
|
417
|
+
b->cur += len;
|
418
|
+
}
|
419
|
+
void bson_append32(bson_buffer * b, const void * data){
|
420
|
+
bson_little_endian32(b->cur, data);
|
421
|
+
b->cur += 4;
|
422
|
+
}
|
423
|
+
void bson_append64(bson_buffer * b, const void * data){
|
424
|
+
bson_little_endian64(b->cur, data);
|
425
|
+
b->cur += 8;
|
426
|
+
}
|
427
|
+
|
428
|
+
bson_buffer * bson_ensure_space( bson_buffer * b , const int bytesNeeded ){
|
429
|
+
int pos = b->cur - b->buf;
|
430
|
+
char * orig = b->buf;
|
431
|
+
int new_size;
|
432
|
+
|
433
|
+
if (b->finished)
|
434
|
+
bson_fatal_msg(!!b->buf, "trying to append to finished buffer");
|
435
|
+
|
436
|
+
if (pos + bytesNeeded <= b->bufSize)
|
437
|
+
return b;
|
438
|
+
|
439
|
+
new_size = 1.5 * (b->bufSize + bytesNeeded);
|
440
|
+
b->buf = realloc(b->buf, new_size);
|
441
|
+
if (!b->buf)
|
442
|
+
bson_fatal_msg(!!b->buf, "realloc() failed");
|
443
|
+
|
444
|
+
b->bufSize = new_size;
|
445
|
+
b->cur += b->buf - orig;
|
446
|
+
|
447
|
+
return b;
|
448
|
+
}
|
449
|
+
|
450
|
+
char * bson_buffer_finish( bson_buffer * b ){
|
451
|
+
int i;
|
452
|
+
if ( ! b->finished ){
|
453
|
+
if ( ! bson_ensure_space( b , 1 ) ) return 0;
|
454
|
+
bson_append_byte( b , 0 );
|
455
|
+
i = b->cur - b->buf;
|
456
|
+
bson_little_endian32(b->buf, &i);
|
457
|
+
b->finished = 1;
|
458
|
+
}
|
459
|
+
return b->buf;
|
460
|
+
}
|
461
|
+
|
462
|
+
void bson_buffer_destroy( bson_buffer * b ){
|
463
|
+
free( b->buf );
|
464
|
+
b->buf = 0;
|
465
|
+
b->cur = 0;
|
466
|
+
b->finished = 1;
|
467
|
+
}
|
468
|
+
|
469
|
+
static bson_buffer * bson_append_estart( bson_buffer * b , int type , const char * name , const int dataSize ){
|
470
|
+
const int sl = strlen(name) + 1;
|
471
|
+
if ( ! bson_ensure_space( b , 1 + sl + dataSize ) )
|
472
|
+
return 0;
|
473
|
+
bson_append_byte( b , (char)type );
|
474
|
+
bson_append( b , name , sl );
|
475
|
+
return b;
|
476
|
+
}
|
477
|
+
|
478
|
+
/* ----------------------------
|
479
|
+
BUILDING TYPES
|
480
|
+
------------------------------ */
|
481
|
+
|
482
|
+
bson_buffer * bson_append_int( bson_buffer * b , const char * name , const int i ){
|
483
|
+
if ( ! bson_append_estart( b , bson_int , name , 4 ) ) return 0;
|
484
|
+
bson_append32( b , &i );
|
485
|
+
return b;
|
486
|
+
}
|
487
|
+
bson_buffer * bson_append_long( bson_buffer * b , const char * name , const int64_t i ){
|
488
|
+
if ( ! bson_append_estart( b , bson_long , name , 8 ) ) return 0;
|
489
|
+
bson_append64( b , &i );
|
490
|
+
return b;
|
491
|
+
}
|
492
|
+
bson_buffer * bson_append_double( bson_buffer * b , const char * name , const double d ){
|
493
|
+
if ( ! bson_append_estart( b , bson_double , name , 8 ) ) return 0;
|
494
|
+
bson_append64( b , &d );
|
495
|
+
return b;
|
496
|
+
}
|
497
|
+
bson_buffer * bson_append_bool( bson_buffer * b , const char * name , const bson_bool_t i ){
|
498
|
+
if ( ! bson_append_estart( b , bson_bool , name , 1 ) ) return 0;
|
499
|
+
bson_append_byte( b , i != 0 );
|
500
|
+
return b;
|
501
|
+
}
|
502
|
+
bson_buffer * bson_append_null( bson_buffer * b , const char * name ){
|
503
|
+
if ( ! bson_append_estart( b , bson_null , name , 0 ) ) return 0;
|
504
|
+
return b;
|
505
|
+
}
|
506
|
+
bson_buffer * bson_append_undefined( bson_buffer * b , const char * name ){
|
507
|
+
if ( ! bson_append_estart( b , bson_undefined , name , 0 ) ) return 0;
|
508
|
+
return b;
|
509
|
+
}
|
510
|
+
bson_buffer * bson_append_string_base( bson_buffer * b , const char * name , const char * value , bson_type type){
|
511
|
+
int sl = strlen( value ) + 1;
|
512
|
+
if ( ! bson_append_estart( b , type , name , 4 + sl ) ) return 0;
|
513
|
+
bson_append32( b , &sl);
|
514
|
+
bson_append( b , value , sl );
|
515
|
+
return b;
|
516
|
+
}
|
517
|
+
bson_buffer * bson_append_string( bson_buffer * b , const char * name , const char * value ){
|
518
|
+
return bson_append_string_base(b, name, value, bson_string);
|
519
|
+
}
|
520
|
+
bson_buffer * bson_append_symbol( bson_buffer * b , const char * name , const char * value ){
|
521
|
+
return bson_append_string_base(b, name, value, bson_symbol);
|
522
|
+
}
|
523
|
+
bson_buffer * bson_append_code( bson_buffer * b , const char * name , const char * value ){
|
524
|
+
return bson_append_string_base(b, name, value, bson_code);
|
525
|
+
}
|
526
|
+
|
527
|
+
bson_buffer * bson_append_code_w_scope( bson_buffer * b , const char * name , const char * code , const bson * scope){
|
528
|
+
int sl = strlen(code) + 1;
|
529
|
+
int size = 4 + 4 + sl + bson_size(scope);
|
530
|
+
if (!bson_append_estart(b, bson_codewscope, name, size)) return 0;
|
531
|
+
bson_append32(b, &size);
|
532
|
+
bson_append32(b, &sl);
|
533
|
+
bson_append(b, code, sl);
|
534
|
+
bson_append(b, scope->data, bson_size(scope));
|
535
|
+
return b;
|
536
|
+
}
|
537
|
+
|
538
|
+
bson_buffer * bson_append_binary( bson_buffer * b, const char * name, char type, const char * str, int len ){
|
539
|
+
if ( type == 2 ){
|
540
|
+
int subtwolen = len + 4;
|
541
|
+
if ( ! bson_append_estart( b , bson_bindata , name , 4+1+4+len ) ) return 0;
|
542
|
+
bson_append32(b, &subtwolen);
|
543
|
+
bson_append_byte(b, type);
|
544
|
+
bson_append32(b, &len);
|
545
|
+
bson_append(b, str, len);
|
546
|
+
}else{
|
547
|
+
if ( ! bson_append_estart( b , bson_bindata , name , 4+1+len ) ) return 0;
|
548
|
+
bson_append32(b, &len);
|
549
|
+
bson_append_byte(b, type);
|
550
|
+
bson_append(b, str, len);
|
551
|
+
}
|
552
|
+
return b;
|
553
|
+
}
|
554
|
+
bson_buffer * bson_append_oid( bson_buffer * b , const char * name , const bson_oid_t * oid ){
|
555
|
+
if ( ! bson_append_estart( b , bson_oid , name , 12 ) ) return 0;
|
556
|
+
bson_append( b , oid , 12 );
|
557
|
+
return b;
|
558
|
+
}
|
559
|
+
bson_buffer * bson_append_new_oid( bson_buffer * b , const char * name ){
|
560
|
+
bson_oid_t oid;
|
561
|
+
bson_oid_gen(&oid);
|
562
|
+
return bson_append_oid(b, name, &oid);
|
563
|
+
}
|
564
|
+
|
565
|
+
bson_buffer * bson_append_regex( bson_buffer * b , const char * name , const char * pattern, const char * opts ){
|
566
|
+
const int plen = strlen(pattern)+1;
|
567
|
+
const int olen = strlen(opts)+1;
|
568
|
+
if ( ! bson_append_estart( b , bson_regex , name , plen + olen ) ) return 0;
|
569
|
+
bson_append( b , pattern , plen );
|
570
|
+
bson_append( b , opts , olen );
|
571
|
+
return b;
|
572
|
+
}
|
573
|
+
|
574
|
+
bson_buffer * bson_append_bson( bson_buffer * b , const char * name , const bson* bson){
|
575
|
+
if ( ! bson_append_estart( b , bson_object , name , bson_size(bson) ) ) return 0;
|
576
|
+
bson_append( b , bson->data , bson_size(bson) );
|
577
|
+
return b;
|
578
|
+
}
|
579
|
+
|
580
|
+
bson_buffer * bson_append_element( bson_buffer * b, const char * name_or_null, const bson_iterator* elem){
|
581
|
+
bson_iterator next = *elem;
|
582
|
+
int size;
|
583
|
+
|
584
|
+
bson_iterator_next(&next);
|
585
|
+
size = next.cur - elem->cur;
|
586
|
+
|
587
|
+
if (name_or_null == NULL){
|
588
|
+
bson_ensure_space(b, size);
|
589
|
+
bson_append(b, elem->cur, size);
|
590
|
+
}else{
|
591
|
+
int data_size = size - 2 - strlen(bson_iterator_key(elem));
|
592
|
+
bson_append_estart(b, elem->cur[0], name_or_null, data_size);
|
593
|
+
bson_append(b, bson_iterator_value(elem), data_size);
|
594
|
+
}
|
595
|
+
|
596
|
+
return b;
|
597
|
+
}
|
598
|
+
|
599
|
+
bson_buffer * bson_append_timestamp( bson_buffer * b, const char * name, bson_timestamp_t * ts ){
|
600
|
+
if ( ! bson_append_estart( b , bson_timestamp , name , 8 ) ) return 0;
|
601
|
+
|
602
|
+
bson_append32( b , &(ts->i) );
|
603
|
+
bson_append32( b , &(ts->t) );
|
604
|
+
|
605
|
+
return b;
|
606
|
+
}
|
607
|
+
|
608
|
+
bson_buffer * bson_append_date( bson_buffer * b , const char * name , bson_date_t millis ){
|
609
|
+
if ( ! bson_append_estart( b , bson_date , name , 8 ) ) return 0;
|
610
|
+
bson_append64( b , &millis );
|
611
|
+
return b;
|
612
|
+
}
|
613
|
+
|
614
|
+
bson_buffer * bson_append_time_t( bson_buffer * b , const char * name , time_t secs){
|
615
|
+
return bson_append_date(b, name, (bson_date_t)secs * 1000);
|
616
|
+
}
|
617
|
+
|
618
|
+
bson_buffer * bson_append_start_object( bson_buffer * b , const char * name ){
|
619
|
+
if ( ! bson_append_estart( b , bson_object , name , 5 ) ) return 0;
|
620
|
+
b->stack[ b->stackPos++ ] = b->cur - b->buf;
|
621
|
+
bson_append32( b , &zero );
|
622
|
+
return b;
|
623
|
+
}
|
624
|
+
|
625
|
+
bson_buffer * bson_append_start_array( bson_buffer * b , const char * name ){
|
626
|
+
if ( ! bson_append_estart( b , bson_array , name , 5 ) ) return 0;
|
627
|
+
b->stack[ b->stackPos++ ] = b->cur - b->buf;
|
628
|
+
bson_append32( b , &zero );
|
629
|
+
return b;
|
630
|
+
}
|
631
|
+
|
632
|
+
bson_buffer * bson_append_finish_object( bson_buffer * b ){
|
633
|
+
char * start;
|
634
|
+
int i;
|
635
|
+
if ( ! bson_ensure_space( b , 1 ) ) return 0;
|
636
|
+
bson_append_byte( b , 0 );
|
637
|
+
|
638
|
+
start = b->buf + b->stack[ --b->stackPos ];
|
639
|
+
i = b->cur - start;
|
640
|
+
bson_little_endian32(start, &i);
|
641
|
+
|
642
|
+
return b;
|
643
|
+
}
|
644
|
+
|
645
|
+
void* bson_malloc(int size){
|
646
|
+
void* p = malloc(size);
|
647
|
+
bson_fatal_msg(!!p, "malloc() failed");
|
648
|
+
return p;
|
649
|
+
}
|
650
|
+
|
651
|
+
void* bson_realloc(void* ptr, int size){
|
652
|
+
void* p = realloc(ptr, size);
|
653
|
+
bson_fatal_msg(!!p, "realloc() failed");
|
654
|
+
return p;
|
655
|
+
}
|
656
|
+
|
657
|
+
static bson_err_handler err_handler = NULL;
|
658
|
+
|
659
|
+
bson_err_handler set_bson_err_handler(bson_err_handler func){
|
660
|
+
bson_err_handler old = err_handler;
|
661
|
+
err_handler = func;
|
662
|
+
return old;
|
663
|
+
}
|
664
|
+
|
665
|
+
void bson_fatal( int ok ){
|
666
|
+
bson_fatal_msg(ok, "");
|
667
|
+
}
|
668
|
+
|
669
|
+
void bson_fatal_msg( int ok , const char* msg){
|
670
|
+
if (ok)
|
671
|
+
return;
|
672
|
+
|
673
|
+
if (err_handler){
|
674
|
+
err_handler(msg);
|
675
|
+
}
|
676
|
+
|
677
|
+
fprintf( stderr , "error: %s\n" , msg );
|
678
|
+
exit(-5);
|
679
|
+
}
|
680
|
+
|
681
|
+
extern const char bson_numstrs[1000][4];
|
682
|
+
void bson_numstr(char* str, int i){
|
683
|
+
if(i < 1000)
|
684
|
+
memcpy(str, bson_numstrs[i], 4);
|
685
|
+
else
|
686
|
+
sprintf(str,"%d", i);
|
687
|
+
}
|