aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar djsollen@google.com <djsollen@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-13 18:22:09 +0000
committerGravatar djsollen@google.com <djsollen@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-13 18:22:09 +0000
commitb2c16472f6ebb134f46d63af2265b9d741f5748e (patch)
tree41643b05f09c0dcd559c8c44f7531b248f9a1792
parentaba0e3b6bc91ae6b95bca2325933c5893070ac99 (diff)
Add BSON implementation to third_party
Review URL: https://codereview.appspot.com/6267044 git-svn-id: http://skia.googlecode.com/svn/trunk@4252 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--third_party/bson_c/APACHE-2.0.txt202
-rw-r--r--third_party/bson_c/src/bson.c1063
-rw-r--r--third_party/bson_c/src/bson.h1036
-rw-r--r--third_party/bson_c/src/encoding.c148
-rw-r--r--third_party/bson_c/src/encoding.h54
-rw-r--r--third_party/bson_c/src/numbers.c127
-rw-r--r--third_party/bson_c/test/bson_subobject_test.c50
-rw-r--r--third_party/bson_c/test/bson_test.c259
8 files changed, 2939 insertions, 0 deletions
diff --git a/third_party/bson_c/APACHE-2.0.txt b/third_party/bson_c/APACHE-2.0.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/third_party/bson_c/APACHE-2.0.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/third_party/bson_c/src/bson.c b/third_party/bson_c/src/bson.c
new file mode 100644
index 0000000000..788bc2fefc
--- /dev/null
+++ b/third_party/bson_c/src/bson.c
@@ -0,0 +1,1063 @@
+/* bson.c */
+
+/* Copyright 2009, 2010 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+#include <limits.h>
+
+#include "bson.h"
+#include "encoding.h"
+
+const int initialBufferSize = 128;
+
+/* only need one of these */
+static const int zero = 0;
+
+/* Custom standard function pointers. */
+void *( *bson_malloc_func )( size_t ) = malloc;
+void *( *bson_realloc_func )( void *, size_t ) = realloc;
+void ( *bson_free )( void * ) = free;
+#ifdef R_SAFETY_NET
+bson_printf_func bson_printf;
+#else
+bson_printf_func bson_printf = printf;
+#endif
+bson_fprintf_func bson_fprintf = fprintf;
+bson_sprintf_func bson_sprintf = sprintf;
+
+static int _bson_errprintf( const char *, ... );
+bson_printf_func bson_errprintf = _bson_errprintf;
+
+/* ObjectId fuzz functions. */
+static int ( *oid_fuzz_func )( void ) = NULL;
+static int ( *oid_inc_func )( void ) = NULL;
+
+/* ----------------------------
+ READING
+ ------------------------------ */
+
+MONGO_EXPORT bson* bson_create() {
+ return (bson*)bson_malloc(sizeof(bson));
+}
+
+MONGO_EXPORT void bson_dispose(bson* b) {
+ bson_free(b);
+}
+
+bson *bson_empty( bson *obj ) {
+ static char *data = "\005\0\0\0\0";
+ bson_init_data( obj, data );
+ obj->finished = 1;
+ obj->err = 0;
+ obj->stackPos = 0;
+ return obj;
+}
+
+MONGO_EXPORT int bson_copy( bson *out, const bson *in ) {
+ if ( !out ) return BSON_ERROR;
+ if ( !in->finished ) return BSON_ERROR;
+ bson_init_size( out, bson_size( in ) );
+ memcpy( out->data, in->data, bson_size( in ) );
+ out->finished = 1;
+
+ return BSON_OK;
+}
+
+int bson_init_data( bson *b, char *data ) {
+ b->data = data;
+ return BSON_OK;
+}
+
+int bson_init_finished_data( bson *b, char *data ) {
+ bson_init_data( b, data );
+ b->finished = 1;
+ return BSON_OK;
+}
+
+static void _bson_reset( bson *b ) {
+ b->finished = 0;
+ b->stackPos = 0;
+ b->err = 0;
+ b->errstr = NULL;
+}
+
+MONGO_EXPORT int bson_size( const bson *b ) {
+ int i;
+ if ( ! b || ! b->data )
+ return 0;
+ bson_little_endian32( &i, b->data );
+ return i;
+}
+
+MONGO_EXPORT int bson_buffer_size( const bson *b ) {
+ return (b->cur - b->data + 1);
+}
+
+
+const char *bson_data( bson *b ) {
+ return (const char *)b->data;
+}
+
+static char hexbyte( char hex ) {
+ switch ( hex ) {
+ case '0':
+ return 0x0;
+ case '1':
+ return 0x1;
+ case '2':
+ return 0x2;
+ case '3':
+ return 0x3;
+ case '4':
+ return 0x4;
+ case '5':
+ return 0x5;
+ case '6':
+ return 0x6;
+ case '7':
+ return 0x7;
+ case '8':
+ return 0x8;
+ case '9':
+ return 0x9;
+ case 'a':
+ case 'A':
+ return 0xa;
+ case 'b':
+ case 'B':
+ return 0xb;
+ case 'c':
+ case 'C':
+ return 0xc;
+ case 'd':
+ case 'D':
+ return 0xd;
+ case 'e':
+ case 'E':
+ return 0xe;
+ case 'f':
+ case 'F':
+ return 0xf;
+ default:
+ return 0x0; /* something smarter? */
+ }
+}
+
+MONGO_EXPORT void bson_oid_from_string( bson_oid_t *oid, const char *str ) {
+ int i;
+ for ( i=0; i<12; i++ ) {
+ oid->bytes[i] = ( hexbyte( str[2*i] ) << 4 ) | hexbyte( str[2*i + 1] );
+ }
+}
+
+MONGO_EXPORT void bson_oid_to_string( const bson_oid_t *oid, char *str ) {
+ static const char hex[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+ int i;
+ for ( i=0; i<12; i++ ) {
+ str[2*i] = hex[( oid->bytes[i] & 0xf0 ) >> 4];
+ str[2*i + 1] = hex[ oid->bytes[i] & 0x0f ];
+ }
+ str[24] = '\0';
+}
+
+void bson_set_oid_fuzz( int ( *func )( void ) ) {
+ oid_fuzz_func = func;
+}
+
+void bson_set_oid_inc( int ( *func )( void ) ) {
+ oid_inc_func = func;
+}
+
+MONGO_EXPORT void bson_oid_gen( bson_oid_t *oid ) {
+ static int incr = 0;
+ static int fuzz = 0;
+ int i;
+ int t = time( NULL );
+
+ if( oid_inc_func )
+ i = oid_inc_func();
+ else
+ i = incr++;
+
+ if ( !fuzz ) {
+ if ( oid_fuzz_func )
+ fuzz = oid_fuzz_func();
+ else {
+ srand( t );
+ fuzz = rand();
+ }
+ }
+
+ bson_big_endian32( &oid->ints[0], &t );
+ oid->ints[1] = fuzz;
+ bson_big_endian32( &oid->ints[2], &i );
+}
+
+time_t bson_oid_generated_time( bson_oid_t *oid ) {
+ time_t out;
+ bson_big_endian32( &out, &oid->ints[0] );
+
+ return out;
+}
+
+void bson_print( bson *b ) {
+ bson_print_raw( b->data , 0 );
+}
+
+void bson_print_raw( const char *data , int depth ) {
+ bson_iterator i;
+ const char *key;
+ int temp;
+ bson_timestamp_t ts;
+ char oidhex[25];
+ bson scope;
+ bson_iterator_from_buffer( &i, data );
+
+ while ( bson_iterator_next( &i ) ) {
+ bson_type t = bson_iterator_type( &i );
+ if ( t == 0 )
+ break;
+ key = bson_iterator_key( &i );
+
+ for ( temp=0; temp<=depth; temp++ )
+ bson_printf( "\t" );
+ bson_printf( "%s : %d \t " , key , t );
+ switch ( t ) {
+ case BSON_DOUBLE:
+ bson_printf( "%f" , bson_iterator_double( &i ) );
+ break;
+ case BSON_STRING:
+ bson_printf( "%s" , bson_iterator_string( &i ) );
+ break;
+ case BSON_SYMBOL:
+ bson_printf( "SYMBOL: %s" , bson_iterator_string( &i ) );
+ break;
+ case BSON_OID:
+ bson_oid_to_string( bson_iterator_oid( &i ), oidhex );
+ bson_printf( "%s" , oidhex );
+ break;
+ case BSON_BOOL:
+ bson_printf( "%s" , bson_iterator_bool( &i ) ? "true" : "false" );
+ break;
+ case BSON_DATE:
+ bson_printf( "%ld" , ( long int )bson_iterator_date( &i ) );
+ break;
+ case BSON_BINDATA:
+ bson_printf( "BSON_BINDATA" );
+ break;
+ case BSON_UNDEFINED:
+ bson_printf( "BSON_UNDEFINED" );
+ break;
+ case BSON_NULL:
+ bson_printf( "BSON_NULL" );
+ break;
+ case BSON_REGEX:
+ bson_printf( "BSON_REGEX: %s", bson_iterator_regex( &i ) );
+ break;
+ case BSON_CODE:
+ bson_printf( "BSON_CODE: %s", bson_iterator_code( &i ) );
+ break;
+ case BSON_CODEWSCOPE:
+ bson_printf( "BSON_CODE_W_SCOPE: %s", bson_iterator_code( &i ) );
+ bson_init( &scope );
+ bson_iterator_code_scope( &i, &scope );
+ bson_printf( "\n\t SCOPE: " );
+ bson_print( &scope );
+ break;
+ case BSON_INT:
+ bson_printf( "%d" , bson_iterator_int( &i ) );
+ break;
+ case BSON_LONG:
+ bson_printf( "%lld" , ( uint64_t )bson_iterator_long( &i ) );
+ break;
+ case BSON_TIMESTAMP:
+ ts = bson_iterator_timestamp( &i );
+ bson_printf( "i: %d, t: %d", ts.i, ts.t );
+ break;
+ case BSON_OBJECT:
+ case BSON_ARRAY:
+ bson_printf( "\n" );
+ bson_print_raw( bson_iterator_value( &i ) , depth + 1 );
+ break;
+ default:
+ bson_errprintf( "can't print type : %d\n" , t );
+ }
+ bson_printf( "\n" );
+ }
+}
+
+/* ----------------------------
+ ITERATOR
+ ------------------------------ */
+
+MONGO_EXPORT bson_iterator* bson_iterator_create() {
+ return (bson_iterator*)malloc(sizeof(bson_iterator*));
+}
+
+MONGO_EXPORT void bson_iterator_dispose(bson_iterator* i) {
+ free(i);
+}
+
+MONGO_EXPORT void bson_iterator_init( bson_iterator *i, const bson *b ) {
+ i->cur = b->data + 4;
+ i->first = 1;
+}
+
+void bson_iterator_from_buffer( bson_iterator *i, const char *buffer ) {
+ i->cur = buffer + 4;
+ i->first = 1;
+}
+
+MONGO_EXPORT bson_type bson_find( bson_iterator *it, const bson *obj, const char *name ) {
+ bson_iterator_init( it, (bson *)obj );
+ while( bson_iterator_next( it ) ) {
+ if ( strcmp( name, bson_iterator_key( it ) ) == 0 )
+ break;
+ }
+ return bson_iterator_type( it );
+}
+
+bson_bool_t bson_iterator_more( const bson_iterator *i ) {
+ return *( i->cur );
+}
+
+MONGO_EXPORT bson_type bson_iterator_next( bson_iterator *i ) {
+ int ds;
+
+ if ( i->first ) {
+ i->first = 0;
+ return ( bson_type )( *i->cur );
+ }
+
+ switch ( bson_iterator_type( i ) ) {
+ case BSON_EOO:
+ return BSON_EOO; /* don't advance */
+ case BSON_UNDEFINED:
+ case BSON_NULL:
+ ds = 0;
+ break;
+ case BSON_BOOL:
+ ds = 1;
+ break;
+ case BSON_INT:
+ ds = 4;
+ break;
+ case BSON_LONG:
+ case BSON_DOUBLE:
+ case BSON_TIMESTAMP:
+ case BSON_DATE:
+ ds = 8;
+ break;
+ case BSON_OID:
+ ds = 12;
+ break;
+ case BSON_STRING:
+ case BSON_SYMBOL:
+ case BSON_CODE:
+ ds = 4 + bson_iterator_int_raw( i );
+ break;
+ case BSON_BINDATA:
+ ds = 5 + bson_iterator_int_raw( i );
+ break;
+ case BSON_OBJECT:
+ case BSON_ARRAY:
+ case BSON_CODEWSCOPE:
+ ds = bson_iterator_int_raw( i );
+ break;
+ case BSON_DBREF:
+ ds = 4+12 + bson_iterator_int_raw( i );
+ break;
+ case BSON_REGEX: {
+ const char *s = bson_iterator_value( i );
+ const char *p = s;
+ p += strlen( p )+1;
+ p += strlen( p )+1;
+ ds = p-s;
+ break;
+ }
+
+ default: {
+ char msg[] = "unknown type: 000000000000";
+ bson_numstr( msg+14, ( unsigned )( i->cur[0] ) );
+ bson_fatal_msg( 0, msg );
+ return 0;
+ }
+ }
+
+ i->cur += 1 + strlen( i->cur + 1 ) + 1 + ds;
+
+ return ( bson_type )( *i->cur );
+}
+
+MONGO_EXPORT bson_type bson_iterator_type( const bson_iterator *i ) {
+ return ( bson_type )i->cur[0];
+}
+
+MONGO_EXPORT const char *bson_iterator_key( const bson_iterator *i ) {
+ return i->cur + 1;
+}
+
+const char *bson_iterator_value( const bson_iterator *i ) {
+ const char *t = i->cur + 1;
+ t += strlen( t ) + 1;
+ return t;
+}
+
+/* types */
+
+int bson_iterator_int_raw( const bson_iterator *i ) {
+ int out;
+ bson_little_endian32( &out, bson_iterator_value( i ) );
+ return out;
+}
+
+double bson_iterator_double_raw( const bson_iterator *i ) {
+ double out;
+ bson_little_endian64( &out, bson_iterator_value( i ) );
+ return out;
+}
+
+int64_t bson_iterator_long_raw( const bson_iterator *i ) {
+ int64_t out;
+ bson_little_endian64( &out, bson_iterator_value( i ) );
+ return out;
+}
+
+bson_bool_t bson_iterator_bool_raw( const bson_iterator *i ) {
+ return bson_iterator_value( i )[0];
+}
+
+MONGO_EXPORT bson_oid_t *bson_iterator_oid( const bson_iterator *i ) {
+ return ( bson_oid_t * )bson_iterator_value( i );
+}
+
+MONGO_EXPORT int bson_iterator_int( const bson_iterator *i ) {
+ switch ( bson_iterator_type( i ) ) {
+ case BSON_INT:
+ return bson_iterator_int_raw( i );
+ case BSON_LONG:
+ return bson_iterator_long_raw( i );
+ case BSON_DOUBLE:
+ return bson_iterator_double_raw( i );
+ default:
+ return 0;
+ }
+}
+
+MONGO_EXPORT double bson_iterator_double( const bson_iterator *i ) {
+ switch ( bson_iterator_type( i ) ) {
+ case BSON_INT:
+ return bson_iterator_int_raw( i );
+ case BSON_LONG:
+ return bson_iterator_long_raw( i );
+ case BSON_DOUBLE:
+ return bson_iterator_double_raw( i );
+ default:
+ return 0;
+ }
+}
+
+MONGO_EXPORT int64_t bson_iterator_long( const bson_iterator *i ) {
+ switch ( bson_iterator_type( i ) ) {
+ case BSON_INT:
+ return bson_iterator_int_raw( i );
+ case BSON_LONG:
+ return bson_iterator_long_raw( i );
+ case BSON_DOUBLE:
+ return bson_iterator_double_raw( i );
+ default:
+ return 0;
+ }
+}
+
+bson_timestamp_t bson_iterator_timestamp( const bson_iterator *i ) {
+ bson_timestamp_t ts;
+ bson_little_endian32( &( ts.i ), bson_iterator_value( i ) );
+ bson_little_endian32( &( ts.t ), bson_iterator_value( i ) + 4 );
+ return ts;
+}
+
+
+MONGO_EXPORT int bson_iterator_timestamp_time( const bson_iterator *i ) {
+ int time;
+ bson_little_endian32( &time, bson_iterator_value( i ) + 4 );
+ return time;
+}
+
+
+MONGO_EXPORT int bson_iterator_timestamp_increment( const bson_iterator *i ) {
+ int increment;
+ bson_little_endian32( &increment, bson_iterator_value( i ) );
+ return increment;
+}
+
+
+MONGO_EXPORT bson_bool_t bson_iterator_bool( const bson_iterator *i ) {
+ switch ( bson_iterator_type( i ) ) {
+ case BSON_BOOL:
+ return bson_iterator_bool_raw( i );
+ case BSON_INT:
+ return bson_iterator_int_raw( i ) != 0;
+ case BSON_LONG:
+ return bson_iterator_long_raw( i ) != 0;
+ case BSON_DOUBLE:
+ return bson_iterator_double_raw( i ) != 0;
+ case BSON_EOO:
+ case BSON_NULL:
+ return 0;
+ default:
+ return 1;
+ }
+}
+
+MONGO_EXPORT const char *bson_iterator_string( const bson_iterator *i ) {
+ switch ( bson_iterator_type( i ) ) {
+ case BSON_STRING:
+ case BSON_SYMBOL:
+ return bson_iterator_value( i ) + 4;
+ default:
+ return "";
+ }
+}
+
+int bson_iterator_string_len( const bson_iterator *i ) {
+ return bson_iterator_int_raw( i );
+}
+
+MONGO_EXPORT const char *bson_iterator_code( const bson_iterator *i ) {
+ switch ( bson_iterator_type( i ) ) {
+ case BSON_STRING:
+ case BSON_CODE:
+ return bson_iterator_value( i ) + 4;
+ case BSON_CODEWSCOPE:
+ return bson_iterator_value( i ) + 8;
+ default:
+ return NULL;
+ }
+}
+
+MONGO_EXPORT void bson_iterator_code_scope( const bson_iterator *i, bson *scope ) {
+ if ( bson_iterator_type( i ) == BSON_CODEWSCOPE ) {
+ int code_len;
+ bson_little_endian32( &code_len, bson_iterator_value( i )+4 );
+ bson_init_data( scope, ( void * )( bson_iterator_value( i )+8+code_len ) );
+ _bson_reset( scope );
+ scope->finished = 1;
+ } else {
+ bson_empty( scope );
+ }
+}
+
+MONGO_EXPORT bson_date_t bson_iterator_date( const bson_iterator *i ) {
+ return bson_iterator_long_raw( i );
+}
+
+time_t bson_iterator_time_t( const bson_iterator *i ) {
+ return bson_iterator_date( i ) / 1000;
+}
+
+MONGO_EXPORT int bson_iterator_bin_len( const bson_iterator *i ) {
+ return ( bson_iterator_bin_type( i ) == BSON_BIN_BINARY_OLD )
+ ? bson_iterator_int_raw( i ) - 4
+ : bson_iterator_int_raw( i );
+}
+
+MONGO_EXPORT char bson_iterator_bin_type( const bson_iterator *i ) {
+ return bson_iterator_value( i )[4];
+}
+
+MONGO_EXPORT const char *bson_iterator_bin_data( const bson_iterator *i ) {
+ return ( bson_iterator_bin_type( i ) == BSON_BIN_BINARY_OLD )
+ ? bson_iterator_value( i ) + 9
+ : bson_iterator_value( i ) + 5;
+}
+
+MONGO_EXPORT const char *bson_iterator_regex( const bson_iterator *i ) {
+ return bson_iterator_value( i );
+}
+
+MONGO_EXPORT const char *bson_iterator_regex_opts( const bson_iterator *i ) {
+ const char *p = bson_iterator_value( i );
+ return p + strlen( p ) + 1;
+
+}
+
+void bson_iterator_subobject( const bson_iterator *i, bson *sub ) {
+ bson_init_data( sub, ( char * )bson_iterator_value( i ) );
+ _bson_reset( sub );
+ sub->finished = 1;
+}
+
+MONGO_EXPORT void bson_iterator_subiterator( const bson_iterator *i, bson_iterator *sub ) {
+ bson_iterator_from_buffer( sub, bson_iterator_value( i ) );
+}
+
+/* ----------------------------
+ BUILDING
+ ------------------------------ */
+
+static void _bson_init_size( bson *b, int size ) {
+ if( size == 0 )
+ b->data = NULL;
+ else
+ b->data = ( char * )bson_malloc( size );
+ b->dataSize = size;
+ b->cur = b->data + 4;
+ _bson_reset( b );
+}
+
+MONGO_EXPORT void bson_init( bson *b ) {
+ _bson_init_size( b, initialBufferSize );
+}
+
+void bson_init_size( bson *b, int size ) {
+ _bson_init_size( b, size );
+}
+
+void bson_append_byte( bson *b, char c ) {
+ b->cur[0] = c;
+ b->cur++;
+}
+
+void bson_append( bson *b, const void *data, int len ) {
+ memcpy( b->cur , data , len );
+ b->cur += len;
+}
+
+void bson_append32( bson *b, const void *data ) {
+ bson_little_endian32( b->cur, data );
+ b->cur += 4;
+}
+
+void bson_append64( bson *b, const void *data ) {
+ bson_little_endian64( b->cur, data );
+ b->cur += 8;
+}
+
+int bson_ensure_space( bson *b, const int bytesNeeded ) {
+ int pos = b->cur - b->data;
+ char *orig = b->data;
+ int new_size;
+
+ if ( pos + bytesNeeded <= b->dataSize )
+ return BSON_OK;
+
+ new_size = 1.5 * ( b->dataSize + bytesNeeded );
+
+ if( new_size < b->dataSize ) {
+ if( ( b->dataSize + bytesNeeded ) < INT_MAX )
+ new_size = INT_MAX;
+ else {
+ b->err = BSON_SIZE_OVERFLOW;
+ return BSON_ERROR;
+ }
+ }
+
+ b->data = bson_realloc( b->data, new_size );
+ if ( !b->data )
+ bson_fatal_msg( !!b->data, "realloc() failed" );
+
+ b->dataSize = new_size;
+ b->cur += b->data - orig;
+
+ return BSON_OK;
+}
+
+MONGO_EXPORT int bson_finish( bson *b ) {
+ int i;
+
+ if( b->err & BSON_NOT_UTF8 )
+ return BSON_ERROR;
+
+ if ( ! b->finished ) {
+ if ( bson_ensure_space( b, 1 ) == BSON_ERROR ) return BSON_ERROR;
+ bson_append_byte( b, 0 );
+ i = b->cur - b->data;
+ bson_little_endian32( b->data, &i );
+ b->finished = 1;
+ }
+
+ return BSON_OK;
+}
+
+MONGO_EXPORT void bson_destroy( bson *b ) {
+ if (b) {
+ bson_free( b->data );
+ b->err = 0;
+ b->data = 0;
+ b->cur = 0;
+ b->finished = 1;
+ }
+}
+
+static int bson_append_estart( bson *b, int type, const char *name, const int dataSize ) {
+ const int len = strlen( name ) + 1;
+
+ if ( b->finished ) {
+ b->err |= BSON_ALREADY_FINISHED;
+ return BSON_ERROR;
+ }
+
+ if ( bson_ensure_space( b, 1 + len + dataSize ) == BSON_ERROR ) {
+ return BSON_ERROR;
+ }
+
+ if( bson_check_field_name( b, ( const char * )name, len - 1 ) == BSON_ERROR ) {
+ bson_builder_error( b );
+ return BSON_ERROR;
+ }
+
+ bson_append_byte( b, ( char )type );
+ bson_append( b, name, len );
+ return BSON_OK;
+}
+
+/* ----------------------------
+ BUILDING TYPES
+ ------------------------------ */
+
+MONGO_EXPORT int bson_append_int( bson *b, const char *name, const int i ) {
+ if ( bson_append_estart( b, BSON_INT, name, 4 ) == BSON_ERROR )
+ return BSON_ERROR;
+ bson_append32( b , &i );
+ return BSON_OK;
+}
+
+MONGO_EXPORT int bson_append_long( bson *b, const char *name, const int64_t i ) {
+ if ( bson_append_estart( b , BSON_LONG, name, 8 ) == BSON_ERROR )
+ return BSON_ERROR;
+ bson_append64( b , &i );
+ return BSON_OK;
+}
+
+MONGO_EXPORT int bson_append_double( bson *b, const char *name, const double d ) {
+ if ( bson_append_estart( b, BSON_DOUBLE, name, 8 ) == BSON_ERROR )
+ return BSON_ERROR;
+ bson_append64( b , &d );
+ return BSON_OK;
+}
+
+MONGO_EXPORT int bson_append_bool( bson *b, const char *name, const bson_bool_t i ) {
+ if ( bson_append_estart( b, BSON_BOOL, name, 1 ) == BSON_ERROR )
+ return BSON_ERROR;
+ bson_append_byte( b , i != 0 );
+ return BSON_OK;
+}
+
+MONGO_EXPORT int bson_append_null( bson *b, const char *name ) {
+ if ( bson_append_estart( b , BSON_NULL, name, 0 ) == BSON_ERROR )
+ return BSON_ERROR;
+ return BSON_OK;
+}
+
+MONGO_EXPORT int bson_append_undefined( bson *b, const char *name ) {
+ if ( bson_append_estart( b, BSON_UNDEFINED, name, 0 ) == BSON_ERROR )
+ return BSON_ERROR;
+ return BSON_OK;
+}
+
+int bson_append_string_base( bson *b, const char *name,
+ const char *value, int len, bson_type type ) {
+
+ int sl = len + 1;
+ if ( bson_check_string( b, ( const char * )value, sl - 1 ) == BSON_ERROR )
+ return BSON_ERROR;
+ if ( bson_append_estart( b, type, name, 4 + sl ) == BSON_ERROR ) {
+ return BSON_ERROR;
+ }
+ bson_append32( b , &sl );
+ bson_append( b , value , sl - 1 );
+ bson_append( b , "\0" , 1 );
+ return BSON_OK;
+}
+
+MONGO_EXPORT int bson_append_string( bson *b, const char *name, const char *value ) {
+ return bson_append_string_base( b, name, value, strlen ( value ), BSON_STRING );
+}
+
+MONGO_EXPORT int bson_append_symbol( bson *b, const char *name, const char *value ) {
+ return bson_append_string_base( b, name, value, strlen ( value ), BSON_SYMBOL );
+}
+
+MONGO_EXPORT int bson_append_code( bson *b, const char *name, const char *value ) {
+ return bson_append_string_base( b, name, value, strlen ( value ), BSON_CODE );
+}
+
+int bson_append_string_n( bson *b, const char *name, const char *value, int len ) {
+ return bson_append_string_base( b, name, value, len, BSON_STRING );
+}
+
+int bson_append_symbol_n( bson *b, const char *name, const char *value, int len ) {
+ return bson_append_string_base( b, name, value, len, BSON_SYMBOL );
+}
+
+int bson_append_code_n( bson *b, const char *name, const char *value, int len ) {
+ return bson_append_string_base( b, name, value, len, BSON_CODE );
+}
+
+int bson_append_code_w_scope_n( bson *b, const char *name,
+ const char *code, int len, const bson *scope ) {
+
+ int sl = len + 1;
+ int size = 4 + 4 + sl + bson_size( scope );
+ if ( bson_append_estart( b, BSON_CODEWSCOPE, name, size ) == BSON_ERROR )
+ return BSON_ERROR;
+ bson_append32( b, &size );
+ bson_append32( b, &sl );
+ bson_append( b, code, sl );
+ bson_append( b, scope->data, bson_size( scope ) );
+ return BSON_OK;
+}
+
+MONGO_EXPORT int bson_append_code_w_scope( bson *b, const char *name, const char *code, const bson *scope ) {
+ return bson_append_code_w_scope_n( b, name, code, strlen ( code ), scope );
+}
+
+MONGO_EXPORT int bson_append_binary( bson *b, const char *name, char type, const char *str, int len ) {
+ if ( type == BSON_BIN_BINARY_OLD ) {
+ int subtwolen = len + 4;
+ if ( bson_append_estart( b, BSON_BINDATA, name, 4+1+4+len ) == BSON_ERROR )
+ return BSON_ERROR;
+ bson_append32( b, &subtwolen );
+ bson_append_byte( b, type );
+ bson_append32( b, &len );
+ bson_append( b, str, len );
+ } else {
+ if ( bson_append_estart( b, BSON_BINDATA, name, 4+1+len ) == BSON_ERROR )
+ return BSON_ERROR;
+ bson_append32( b, &len );
+ bson_append_byte( b, type );
+ bson_append( b, str, len );
+ }
+ return BSON_OK;
+}
+
+MONGO_EXPORT int bson_append_oid( bson *b, const char *name, const bson_oid_t *oid ) {
+ if ( bson_append_estart( b, BSON_OID, name, 12 ) == BSON_ERROR )
+ return BSON_ERROR;
+ bson_append( b , oid , 12 );
+ return BSON_OK;
+}
+
+int bson_append_new_oid( bson *b, const char *name ) {
+ bson_oid_t oid;
+ bson_oid_gen( &oid );
+ return bson_append_oid( b, name, &oid );
+}
+
+MONGO_EXPORT int bson_append_regex( bson *b, const char *name, const char *pattern, const char *opts ) {
+ const int plen = strlen( pattern )+1;
+ const int olen = strlen( opts )+1;
+ if ( bson_append_estart( b, BSON_REGEX, name, plen + olen ) == BSON_ERROR )
+ return BSON_ERROR;
+ if ( bson_check_string( b, pattern, plen - 1 ) == BSON_ERROR )
+ return BSON_ERROR;
+ bson_append( b , pattern , plen );
+ bson_append( b , opts , olen );
+ return BSON_OK;
+}
+
+MONGO_EXPORT int bson_append_bson( bson *b, const char *name, const bson *bson ) {
+ if ( bson_append_estart( b, BSON_OBJECT, name, bson_size( bson ) ) == BSON_ERROR )
+ return BSON_ERROR;
+ bson_append( b , bson->data , bson_size( bson ) );
+ return BSON_OK;
+}
+
+int bson_append_element( bson *b, const char *name_or_null, const bson_iterator *elem ) {
+ bson_iterator next = *elem;
+ int size;
+
+ bson_iterator_next( &next );
+ size = next.cur - elem->cur;
+
+ if ( name_or_null == NULL ) {
+ if( bson_ensure_space( b, size ) == BSON_ERROR )
+ return BSON_ERROR;
+ bson_append( b, elem->cur, size );
+ } else {
+ int data_size = size - 2 - strlen( bson_iterator_key( elem ) );
+ bson_append_estart( b, elem->cur[0], name_or_null, data_size );
+ bson_append( b, bson_iterator_value( elem ), data_size );
+ }
+
+ return BSON_OK;
+}
+
+int bson_append_timestamp( bson *b, const char *name, bson_timestamp_t *ts ) {
+ if ( bson_append_estart( b, BSON_TIMESTAMP, name, 8 ) == BSON_ERROR ) return BSON_ERROR;
+
+ bson_append32( b , &( ts->i ) );
+ bson_append32( b , &( ts->t ) );
+
+ return BSON_OK;
+}
+
+MONGO_EXPORT int bson_append_timestamp2( bson *b, const char *name, int time, int increment ) {
+ if ( bson_append_estart( b, BSON_TIMESTAMP, name, 8 ) == BSON_ERROR ) return BSON_ERROR;
+
+ bson_append32( b , &increment );
+ bson_append32( b , &time );
+ return BSON_OK;
+}
+
+MONGO_EXPORT int bson_append_date( bson *b, const char *name, bson_date_t millis ) {
+ if ( bson_append_estart( b, BSON_DATE, name, 8 ) == BSON_ERROR ) return BSON_ERROR;
+ bson_append64( b , &millis );
+ return BSON_OK;
+}
+
+int bson_append_time_t( bson *b, const char *name, time_t secs ) {
+ return bson_append_date( b, name, ( bson_date_t )secs * 1000 );
+}
+
+MONGO_EXPORT int bson_append_start_object( bson *b, const char *name ) {
+ if ( bson_append_estart( b, BSON_OBJECT, name, 5 ) == BSON_ERROR ) return BSON_ERROR;
+ b->stack[ b->stackPos++ ] = b->cur - b->data;
+ bson_append32( b , &zero );
+ return BSON_OK;
+}
+
+MONGO_EXPORT int bson_append_start_array( bson *b, const char *name ) {
+ if ( bson_append_estart( b, BSON_ARRAY, name, 5 ) == BSON_ERROR ) return BSON_ERROR;
+ b->stack[ b->stackPos++ ] = b->cur - b->data;
+ bson_append32( b , &zero );
+ return BSON_OK;
+}
+
+MONGO_EXPORT int bson_append_finish_object( bson *b ) {
+ char *start;
+ int i;
+ if ( bson_ensure_space( b, 1 ) == BSON_ERROR ) return BSON_ERROR;
+ bson_append_byte( b , 0 );
+
+ start = b->data + b->stack[ --b->stackPos ];
+ i = b->cur - start;
+ bson_little_endian32( start, &i );
+
+ return BSON_OK;
+}
+
+MONGO_EXPORT double bson_int64_to_double( int64_t i64 ) {
+ return (double)i64;
+}
+
+int bson_append_finish_array( bson *b ) {
+ return bson_append_finish_object( b );
+}
+
+/* Error handling and allocators. */
+
+static bson_err_handler err_handler = NULL;
+
+MONGO_EXPORT bson_err_handler set_bson_err_handler( bson_err_handler func ) {
+ bson_err_handler old = err_handler;
+ err_handler = func;
+ return old;
+}
+
+void *bson_malloc( int size ) {
+ void *p;
+ p = bson_malloc_func( size );
+ bson_fatal_msg( !!p, "malloc() failed" );
+ return p;
+}
+
+void *bson_realloc( void *ptr, int size ) {
+ void *p;
+ p = bson_realloc_func( ptr, size );
+ bson_fatal_msg( !!p, "realloc() failed" );
+ return p;
+}
+
+int _bson_errprintf( const char *format, ... ) {
+ va_list ap;
+ int ret;
+ va_start( ap, format );
+#ifndef R_SAFETY_NET
+ ret = vfprintf( stderr, format, ap );
+#endif
+ va_end( ap );
+
+ return ret;
+}
+
+/**
+ * This method is invoked when a non-fatal bson error is encountered.
+ * Calls the error handler if available.
+ *
+ * @param
+ */
+void bson_builder_error( bson *b ) {
+ if( err_handler )
+ err_handler( "BSON error." );
+}
+
+void bson_fatal( int ok ) {
+ bson_fatal_msg( ok, "" );
+}
+
+void bson_fatal_msg( int ok , const char *msg ) {
+ if ( ok )
+ return;
+
+ if ( err_handler ) {
+ err_handler( msg );
+ }
+#ifndef R_SAFETY_NET
+ bson_errprintf( "error: %s\n" , msg );
+ exit( -5 );
+#endif
+}
+
+
+/* Efficiently copy an integer to a string. */
+extern const char bson_numstrs[1000][4];
+
+void bson_numstr( char *str, int i ) {
+ if( i < 1000 )
+ memcpy( str, bson_numstrs[i], 4 );
+ else
+ bson_sprintf( str,"%d", i );
+}
+
+MONGO_EXPORT void bson_swap_endian64( void *outp, const void *inp ) {
+ const char *in = ( const char * )inp;
+ char *out = ( char * )outp;
+
+ out[0] = in[7];
+ out[1] = in[6];
+ out[2] = in[5];
+ out[3] = in[4];
+ out[4] = in[3];
+ out[5] = in[2];
+ out[6] = in[1];
+ out[7] = in[0];
+
+}
+
+MONGO_EXPORT void bson_swap_endian32( void *outp, const void *inp ) {
+ const char *in = ( const char * )inp;
+ char *out = ( char * )outp;
+
+ out[0] = in[3];
+ out[1] = in[2];
+ out[2] = in[1];
+ out[3] = in[0];
+}
diff --git a/third_party/bson_c/src/bson.h b/third_party/bson_c/src/bson.h
new file mode 100644
index 0000000000..b8c5ba2340
--- /dev/null
+++ b/third_party/bson_c/src/bson.h
@@ -0,0 +1,1036 @@
+/**
+ * @file bson.h
+ * @brief BSON Declarations
+ */
+
+/* Copyright 2009-2011 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BSON_H_
+#define BSON_H_
+
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef __GNUC__
+ #define MONGO_INLINE static __inline__
+ #define MONGO_EXPORT
+#else
+ #define MONGO_INLINE static
+ #ifdef MONGO_STATIC_BUILD
+ #define MONGO_EXPORT
+ #elif defined(MONGO_DLL_BUILD)
+ #define MONGO_EXPORT __declspec(dllexport)
+ #else
+ #define MONGO_EXPORT __declspec(dllimport)
+ #endif
+#endif
+
+#ifdef __cplusplus
+#define MONGO_EXTERN_C_START extern "C" {
+#define MONGO_EXTERN_C_END }
+#else
+#define MONGO_EXTERN_C_START
+#define MONGO_EXTERN_C_END
+#endif
+
+#if defined(MONGO_HAVE_STDINT) || __STDC_VERSION__ >= 199901L
+#include <stdint.h>
+#elif defined(MONGO_HAVE_UNISTD)
+#include <unistd.h>
+#elif defined(MONGO_USE__INT64)
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#elif defined(MONGO_USE_LONG_LONG_INT)
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#else
+#error Must compile with c99 or define MONGO_HAVE_STDINT, MONGO_HAVE_UNISTD, MONGO_USE__INT64, or MONGO_USE_LONG_INT.
+#endif
+
+#ifdef MONGO_BIG_ENDIAN
+#define bson_little_endian64(out, in) ( bson_swap_endian64(out, in) )
+#define bson_little_endian32(out, in) ( bson_swap_endian32(out, in) )
+#define bson_big_endian64(out, in) ( memcpy(out, in, 8) )
+#define bson_big_endian32(out, in) ( memcpy(out, in, 4) )
+#else
+#define bson_little_endian64(out, in) ( memcpy(out, in, 8) )
+#define bson_little_endian32(out, in) ( memcpy(out, in, 4) )
+#define bson_big_endian64(out, in) ( bson_swap_endian64(out, in) )
+#define bson_big_endian32(out, in) ( bson_swap_endian32(out, in) )
+#endif
+
+MONGO_EXTERN_C_START
+
+#define BSON_OK 0
+#define BSON_ERROR -1
+
+enum bson_error_t {
+ BSON_SIZE_OVERFLOW = 1 /**< Trying to create a BSON object larger than INT_MAX. */
+};
+
+enum bson_validity_t {
+ BSON_VALID = 0, /**< BSON is valid and UTF-8 compliant. */
+ BSON_NOT_UTF8 = ( 1<<1 ), /**< A key or a string is not valid UTF-8. */
+ BSON_FIELD_HAS_DOT = ( 1<<2 ), /**< Warning: key contains '.' character. */
+ BSON_FIELD_INIT_DOLLAR = ( 1<<3 ), /**< Warning: key starts with '$' character. */
+ BSON_ALREADY_FINISHED = ( 1<<4 ) /**< Trying to modify a finished BSON object. */
+};
+
+enum bson_binary_subtype_t {
+ BSON_BIN_BINARY = 0,
+ BSON_BIN_FUNC = 1,
+ BSON_BIN_BINARY_OLD = 2,
+ BSON_BIN_UUID = 3,
+ BSON_BIN_MD5 = 5,
+ BSON_BIN_USER = 128
+};
+
+typedef enum {
+ BSON_EOO = 0,
+ BSON_DOUBLE = 1,
+ BSON_STRING = 2,
+ BSON_OBJECT = 3,
+ BSON_ARRAY = 4,
+ BSON_BINDATA = 5,
+ BSON_UNDEFINED = 6,
+ BSON_OID = 7,
+ BSON_BOOL = 8,
+ BSON_DATE = 9,
+ BSON_NULL = 10,
+ BSON_REGEX = 11,
+ BSON_DBREF = 12, /**< Deprecated. */
+ BSON_CODE = 13,
+ BSON_SYMBOL = 14,
+ BSON_CODEWSCOPE = 15,
+ BSON_INT = 16,
+ BSON_TIMESTAMP = 17,
+ BSON_LONG = 18
+} bson_type;
+
+typedef int bson_bool_t;
+
+typedef struct {
+ const char *cur;
+ bson_bool_t first;
+} bson_iterator;
+
+typedef struct {
+ char *data;
+ char *cur;
+ int dataSize;
+ bson_bool_t finished;
+ int stack[32];
+ int stackPos;
+ int err; /**< Bitfield representing errors or warnings on this buffer */
+ char *errstr; /**< A string representation of the most recent error or warning. */
+} bson;
+
+#pragma pack(1)
+typedef union {
+ char bytes[12];
+ int ints[3];
+} bson_oid_t;
+#pragma pack()
+
+typedef int64_t bson_date_t; /* milliseconds since epoch UTC */
+
+typedef struct {
+ int i; /* increment */
+ int t; /* time in seconds */
+} bson_timestamp_t;
+
+/* ----------------------------
+ READING
+ ------------------------------ */
+
+MONGO_EXPORT bson* bson_create();
+MONGO_EXPORT void bson_dispose(bson* b);
+/**
+ * Size of a BSON object.
+ *
+ * @param b the BSON object.
+ *
+ * @return the size.
+ */
+MONGO_EXPORT int bson_size( const bson *b );
+MONGO_EXPORT int bson_buffer_size( const bson *b );
+
+/**
+ * Print a string representation of a BSON object.
+ *
+ * @param b the BSON object to print.
+ */
+void bson_print( bson *b );
+
+/**
+ * Return a pointer to the raw buffer stored by this bson object.
+ *
+ * @param b a BSON object
+ */
+const char *bson_data( bson *b );
+
+/**
+ * Print a string representation of a BSON object.
+ *
+ * @param bson the raw data to print.
+ * @param depth the depth to recurse the object.x
+ */
+void bson_print_raw( const char *bson , int depth );
+
+/**
+ * Advance a bson_iterator to the named field.
+ *
+ * @param it the bson_iterator to use.
+ * @param obj the BSON object to use.
+ * @param name the name of the field to find.
+ *
+ * @return the type of the found object or BSON_EOO if it is not found.
+ */
+MONGO_EXPORT bson_type bson_find( bson_iterator *it, const bson *obj, const char *name );
+
+
+MONGO_EXPORT bson_iterator* bson_iterator_create();
+MONGO_EXPORT void bson_iterator_dispose(bson_iterator*);
+/**
+ * Initialize a bson_iterator.
+ *
+ * @param i the bson_iterator to initialize.
+ * @param bson the BSON object to associate with the iterator.
+ */
+MONGO_EXPORT void bson_iterator_init( bson_iterator *i , const bson *b );
+
+/**
+ * Initialize a bson iterator from a const char* buffer. Note
+ * that this is mostly used internally.
+ *
+ * @param i the bson_iterator to initialize.
+ * @param buffer the buffer to point to.
+ */
+void bson_iterator_from_buffer( bson_iterator *i, const char *buffer );
+
+/* more returns true for eoo. best to loop with bson_iterator_next(&it) */
+/**
+ * Check to see if the bson_iterator has more data.
+ *
+ * @param i the iterator.
+ *
+ * @return returns true if there is more data.
+ */
+bson_bool_t bson_iterator_more( const bson_iterator *i );
+
+/**
+ * Point the iterator at the next BSON object.
+ *
+ * @param i the bson_iterator.
+ *
+ * @return the type of the next BSON object.
+ */
+MONGO_EXPORT bson_type bson_iterator_next( bson_iterator *i );
+
+/**
+ * Get the type of the BSON object currently pointed to by the iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the type of the current BSON object.
+ */
+MONGO_EXPORT bson_type bson_iterator_type( const bson_iterator *i );
+
+/**
+ * Get the key of the BSON object currently pointed to by the iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the key of the current BSON object.
+ */
+MONGO_EXPORT const char *bson_iterator_key( const bson_iterator *i );
+
+/**
+ * Get the value of the BSON object currently pointed to by the iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the value of the current BSON object.
+ */
+const char *bson_iterator_value( const bson_iterator *i );
+
+/* these convert to the right type (return 0 if non-numeric) */
+/**
+ * Get the double value of the BSON object currently pointed to by the
+ * iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the value of the current BSON object.
+ */
+MONGO_EXPORT double bson_iterator_double( const bson_iterator *i );
+
+/**
+ * Get the int value of the BSON object currently pointed to by the iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the value of the current BSON object.
+ */
+MONGO_EXPORT int bson_iterator_int( const bson_iterator *i );
+
+/**
+ * Get the long value of the BSON object currently pointed to by the iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the value of the current BSON object.
+ */
+MONGO_EXPORT int64_t bson_iterator_long( const bson_iterator *i );
+
+/* return the bson timestamp as a whole or in parts */
+/**
+ * Get the timestamp value of the BSON object currently pointed to by
+ * the iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the value of the current BSON object.
+ */
+bson_timestamp_t bson_iterator_timestamp( const bson_iterator *i );
+MONGO_EXPORT int bson_iterator_timestamp_time( const bson_iterator *i );
+MONGO_EXPORT int bson_iterator_timestamp_increment( const bson_iterator *i );
+
+/**
+ * Get the boolean value of the BSON object currently pointed to by
+ * the iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the value of the current BSON object.
+ */
+/* false: boolean false, 0 in any type, or null */
+/* true: anything else (even empty strings and objects) */
+MONGO_EXPORT bson_bool_t bson_iterator_bool( const bson_iterator *i );
+
+/**
+ * Get the double value of the BSON object currently pointed to by the
+ * iterator. Assumes the correct type is used.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the value of the current BSON object.
+ */
+/* these assume you are using the right type */
+double bson_iterator_double_raw( const bson_iterator *i );
+
+/**
+ * Get the int value of the BSON object currently pointed to by the
+ * iterator. Assumes the correct type is used.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the value of the current BSON object.
+ */
+int bson_iterator_int_raw( const bson_iterator *i );
+
+/**
+ * Get the long value of the BSON object currently pointed to by the
+ * iterator. Assumes the correct type is used.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the value of the current BSON object.
+ */
+int64_t bson_iterator_long_raw( const bson_iterator *i );
+
+/**
+ * Get the bson_bool_t value of the BSON object currently pointed to by the
+ * iterator. Assumes the correct type is used.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the value of the current BSON object.
+ */
+bson_bool_t bson_iterator_bool_raw( const bson_iterator *i );
+
+/**
+ * Get the bson_oid_t value of the BSON object currently pointed to by the
+ * iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the value of the current BSON object.
+ */
+MONGO_EXPORT bson_oid_t *bson_iterator_oid( const bson_iterator *i );
+
+/**
+ * Get the string value of the BSON object currently pointed to by the
+ * iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the value of the current BSON object.
+ */
+/* these can also be used with bson_code and bson_symbol*/
+MONGO_EXPORT const char *bson_iterator_string( const bson_iterator *i );
+
+/**
+ * Get the string length of the BSON object currently pointed to by the
+ * iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the length of the current BSON object.
+ */
+int bson_iterator_string_len( const bson_iterator *i );
+
+/**
+ * Get the code value of the BSON object currently pointed to by the
+ * iterator. Works with bson_code, bson_codewscope, and BSON_STRING
+ * returns NULL for everything else.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the code value of the current BSON object.
+ */
+/* works with bson_code, bson_codewscope, and BSON_STRING */
+/* returns NULL for everything else */
+MONGO_EXPORT const char *bson_iterator_code( const bson_iterator *i );
+
+/**
+ * Calls bson_empty on scope if not a bson_codewscope
+ *
+ * @param i the bson_iterator.
+ * @param scope the bson scope.
+ */
+/* calls bson_empty on scope if not a bson_codewscope */
+MONGO_EXPORT void bson_iterator_code_scope( const bson_iterator *i, bson *scope );
+
+/**
+ * Get the date value of the BSON object currently pointed to by the
+ * iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the date value of the current BSON object.
+ */
+/* both of these only work with bson_date */
+MONGO_EXPORT bson_date_t bson_iterator_date( const bson_iterator *i );
+
+/**
+ * Get the time value of the BSON object currently pointed to by the
+ * iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the time value of the current BSON object.
+ */
+time_t bson_iterator_time_t( const bson_iterator *i );
+
+/**
+ * Get the length of the BSON binary object currently pointed to by the
+ * iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the length of the current BSON binary object.
+ */
+MONGO_EXPORT int bson_iterator_bin_len( const bson_iterator *i );
+
+/**
+ * Get the type of the BSON binary object currently pointed to by the
+ * iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the type of the current BSON binary object.
+ */
+MONGO_EXPORT char bson_iterator_bin_type( const bson_iterator *i );
+
+/**
+ * Get the value of the BSON binary object currently pointed to by the
+ * iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the value of the current BSON binary object.
+ */
+MONGO_EXPORT const char *bson_iterator_bin_data( const bson_iterator *i );
+
+/**
+ * Get the value of the BSON regex object currently pointed to by the
+ * iterator.
+ *
+ * @param i the bson_iterator
+ *
+ * @return the value of the current BSON regex object.
+ */
+MONGO_EXPORT const char *bson_iterator_regex( const bson_iterator *i );
+
+/**
+ * Get the options of the BSON regex object currently pointed to by the
+ * iterator.
+ *
+ * @param i the bson_iterator.
+ *
+ * @return the options of the current BSON regex object.
+ */
+MONGO_EXPORT const char *bson_iterator_regex_opts( const bson_iterator *i );
+
+/* these work with BSON_OBJECT and BSON_ARRAY */
+/**
+ * Get the BSON subobject currently pointed to by the
+ * iterator.
+ *
+ * @param i the bson_iterator.
+ * @param sub the BSON subobject destination.
+ */
+void bson_iterator_subobject( const bson_iterator *i, bson *sub );
+
+/**
+ * Get a bson_iterator that on the BSON subobject.
+ *
+ * @param i the bson_iterator.
+ * @param sub the iterator to point at the BSON subobject.
+ */
+MONGO_EXPORT void bson_iterator_subiterator( const bson_iterator *i, bson_iterator *sub );
+
+/* str must be at least 24 hex chars + null byte */
+/**
+ * Create a bson_oid_t from a string.
+ *
+ * @param oid the bson_oid_t destination.
+ * @param str a null terminated string comprised of at least 24 hex chars.
+ */
+MONGO_EXPORT void bson_oid_from_string( bson_oid_t *oid, const char *str );
+
+/**
+ * Create a string representation of the bson_oid_t.
+ *
+ * @param oid the bson_oid_t source.
+ * @param str the string representation destination.
+ */
+MONGO_EXPORT void bson_oid_to_string( const bson_oid_t *oid, char *str );
+
+/**
+ * Create a bson_oid object.
+ *
+ * @param oid the destination for the newly created bson_oid_t.
+ */
+MONGO_EXPORT void bson_oid_gen( bson_oid_t *oid );
+
+/**
+ * Set a function to be used to generate the second four bytes
+ * of an object id.
+ *
+ * @param func a pointer to a function that returns an int.
+ */
+void bson_set_oid_fuzz( int ( *func )( void ) );
+
+/**
+ * Set a function to be used to generate the incrementing part
+ * of an object id (last four bytes). If you need thread-safety
+ * in generating object ids, you should set this function.
+ *
+ * @param func a pointer to a function that returns an int.
+ */
+void bson_set_oid_inc( int ( *func )( void ) );
+
+/**
+ * Get the time a bson_oid_t was created.
+ *
+ * @param oid the bson_oid_t.
+ */
+time_t bson_oid_generated_time( bson_oid_t *oid ); /* Gives the time the OID was created */
+
+/* ----------------------------
+ BUILDING
+ ------------------------------ */
+
+/**
+ * Initialize a new bson object. If not created
+ * with bson_new, you must initialize each new bson
+ * object using this function.
+ *
+ * @note When finished, you must pass the bson object to
+ * bson_destroy( ).
+ */
+MONGO_EXPORT void bson_init( bson *b );
+
+/**
+ * Initialize a BSON object, and point its data
+ * pointer to the provided char*.
+ *
+ * @param b the BSON object to initialize.
+ * @param data the raw BSON data.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+int bson_init_data( bson *b , char *data );
+int bson_init_finished_data( bson *b, char *data ) ;
+
+/**
+ * Initialize a BSON object, and set its
+ * buffer to the given size.
+ *
+ * @param b the BSON object to initialize.
+ * @param size the initial size of the buffer.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+void bson_init_size( bson *b, int size );
+
+/**
+ * Grow a bson object.
+ *
+ * @param b the bson to grow.
+ * @param bytesNeeded the additional number of bytes needed.
+ *
+ * @return BSON_OK or BSON_ERROR with the bson error object set.
+ * Exits if allocation fails.
+ */
+int bson_ensure_space( bson *b, const int bytesNeeded );
+
+/**
+ * Finalize a bson object.
+ *
+ * @param b the bson object to finalize.
+ *
+ * @return the standard error code. To deallocate memory,
+ * call bson_destroy on the bson object.
+ */
+MONGO_EXPORT int bson_finish( bson *b );
+
+/**
+ * Destroy a bson object.
+ *
+ * @param b the bson object to destroy.
+ *
+ */
+MONGO_EXPORT void bson_destroy( bson *b );
+
+/**
+ * Returns a pointer to a static empty BSON object.
+ *
+ * @param obj the BSON object to initialize.
+ *
+ * @return the empty initialized BSON object.
+ */
+/* returns pointer to static empty bson object */
+bson *bson_empty( bson *obj );
+
+/**
+ * Make a complete copy of the a BSON object.
+ * The source bson object must be in a finished
+ * state; otherwise, the copy will fail.
+ *
+ * @param out the copy destination BSON object.
+ * @param in the copy source BSON object.
+ */
+MONGO_EXPORT int bson_copy( bson *out, const bson *in ); /* puts data in new buffer. NOOP if out==NULL */
+
+/**
+ * Append a previously created bson_oid_t to a bson object.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the bson_oid_t.
+ * @param oid the bson_oid_t to append.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_oid( bson *b, const char *name, const bson_oid_t *oid );
+
+/**
+ * Append a bson_oid_t to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the bson_oid_t.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+int bson_append_new_oid( bson *b, const char *name );
+
+/**
+ * Append an int to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the int.
+ * @param i the int to append.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_int( bson *b, const char *name, const int i );
+
+/**
+ * Append an long to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the long.
+ * @param i the long to append.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_long( bson *b, const char *name, const int64_t i );
+
+/**
+ * Append an double to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the double.
+ * @param d the double to append.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_double( bson *b, const char *name, const double d );
+
+/**
+ * Append a string to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the string.
+ * @param str the string to append.
+ *
+ * @return BSON_OK or BSON_ERROR.
+*/
+MONGO_EXPORT int bson_append_string( bson *b, const char *name, const char *str );
+
+/**
+ * Append len bytes of a string to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the string.
+ * @param str the string to append.
+ * @param len the number of bytes from str to append.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+int bson_append_string_n( bson *b, const char *name, const char *str, int len );
+
+/**
+ * Append a symbol to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the symbol.
+ * @param str the symbol to append.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_symbol( bson *b, const char *name, const char *str );
+
+/**
+ * Append len bytes of a symbol to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the symbol.
+ * @param str the symbol to append.
+ * @param len the number of bytes from str to append.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+int bson_append_symbol_n( bson *b, const char *name, const char *str, int len );
+
+/**
+ * Append code to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the code.
+ * @param str the code to append.
+ * @param len the number of bytes from str to append.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_code( bson *b, const char *name, const char *str );
+
+/**
+ * Append len bytes of code to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the code.
+ * @param str the code to append.
+ * @param len the number of bytes from str to append.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+int bson_append_code_n( bson *b, const char *name, const char *str, int len );
+
+/**
+ * Append code to a bson with scope.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the code.
+ * @param str the string to append.
+ * @param scope a BSON object containing the scope.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_code_w_scope( bson *b, const char *name, const char *code, const bson *scope );
+
+/**
+ * Append len bytes of code to a bson with scope.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the code.
+ * @param str the string to append.
+ * @param len the number of bytes from str to append.
+ * @param scope a BSON object containing the scope.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+int bson_append_code_w_scope_n( bson *b, const char *name, const char *code, int size, const bson *scope );
+
+/**
+ * Append binary data to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the data.
+ * @param type the binary data type.
+ * @param str the binary data.
+ * @param len the length of the data.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_binary( bson *b, const char *name, char type, const char *str, int len );
+
+/**
+ * Append a bson_bool_t to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the boolean value.
+ * @param v the bson_bool_t to append.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_bool( bson *b, const char *name, const bson_bool_t v );
+
+/**
+ * Append a null value to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the null value.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_null( bson *b, const char *name );
+
+/**
+ * Append an undefined value to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the undefined value.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_undefined( bson *b, const char *name );
+
+/**
+ * Append a regex value to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the regex value.
+ * @param pattern the regex pattern to append.
+ * @param the regex options.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_regex( bson *b, const char *name, const char *pattern, const char *opts );
+
+/**
+ * Append bson data to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the bson data.
+ * @param bson the bson object to append.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_bson( bson *b, const char *name, const bson *bson );
+
+/**
+ * Append a BSON element to a bson from the current point of an iterator.
+ *
+ * @param b the bson to append to.
+ * @param name_or_null the key for the BSON element, or NULL.
+ * @param elem the bson_iterator.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+int bson_append_element( bson *b, const char *name_or_null, const bson_iterator *elem );
+
+/**
+ * Append a bson_timestamp_t value to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the timestampe value.
+ * @param ts the bson_timestamp_t value to append.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+int bson_append_timestamp( bson *b, const char *name, bson_timestamp_t *ts );
+MONGO_EXPORT int bson_append_timestamp2( bson *b, const char *name, int time, int increment );
+
+/* these both append a bson_date */
+/**
+ * Append a bson_date_t value to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the date value.
+ * @param millis the bson_date_t to append.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_date( bson *b, const char *name, bson_date_t millis );
+
+/**
+ * Append a time_t value to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the key for the date value.
+ * @param secs the time_t to append.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+int bson_append_time_t( bson *b, const char *name, time_t secs );
+
+/**
+ * Start appending a new object to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the name of the new object.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_start_object( bson *b, const char *name );
+
+/**
+ * Start appending a new array to a bson.
+ *
+ * @param b the bson to append to.
+ * @param name the name of the new array.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_start_array( bson *b, const char *name );
+
+/**
+ * Finish appending a new object or array to a bson.
+ *
+ * @param b the bson to append to.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+MONGO_EXPORT int bson_append_finish_object( bson *b );
+
+/**
+ * Finish appending a new object or array to a bson. This
+ * is simply an alias for bson_append_finish_object.
+ *
+ * @param b the bson to append to.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+int bson_append_finish_array( bson *b );
+
+void bson_numstr( char *str, int i );
+
+void bson_incnumstr( char *str );
+
+/* Error handling and standard library function over-riding. */
+/* -------------------------------------------------------- */
+
+/* bson_err_handlers shouldn't return!!! */
+typedef void( *bson_err_handler )( const char *errmsg );
+
+typedef int (*bson_printf_func)( const char *, ... );
+typedef int (*bson_fprintf_func)( FILE *, const char *, ... );
+typedef int (*bson_sprintf_func)( char *, const char *, ... );
+
+extern void *( *bson_malloc_func )( size_t );
+extern void *( *bson_realloc_func )( void *, size_t );
+extern void ( *bson_free )( void * );
+
+extern bson_printf_func bson_printf;
+extern bson_fprintf_func bson_fprintf;
+extern bson_sprintf_func bson_sprintf;
+
+extern bson_printf_func bson_errprintf;
+
+/**
+ * Allocates memory and checks return value, exiting fatally if malloc() fails.
+ *
+ * @param size bytes to allocate.
+ *
+ * @return a pointer to the allocated memory.
+ *
+ * @sa malloc(3)
+ */
+void *bson_malloc( int size );
+
+/**
+ * Changes the size of allocated memory and checks return value,
+ * exiting fatally if realloc() fails.
+ *
+ * @param ptr pointer to the space to reallocate.
+ * @param size bytes to allocate.
+ *
+ * @return a pointer to the allocated memory.
+ *
+ * @sa realloc()
+ */
+void *bson_realloc( void *ptr, int size );
+
+/**
+ * Set a function for error handling.
+ *
+ * @param func a bson_err_handler function.
+ *
+ * @return the old error handling function, or NULL.
+ */
+MONGO_EXPORT bson_err_handler set_bson_err_handler( bson_err_handler func );
+
+/* does nothing if ok != 0 */
+/**
+ * Exit fatally.
+ *
+ * @param ok exits if ok is equal to 0.
+ */
+void bson_fatal( int ok );
+
+/**
+ * Exit fatally with an error message.
+ *
+ * @param ok exits if ok is equal to 0.
+ * @param msg prints to stderr before exiting.
+ */
+void bson_fatal_msg( int ok, const char *msg );
+
+/**
+ * Invoke the error handler, but do not exit.
+ *
+ * @param b the buffer object.
+ */
+void bson_builder_error( bson *b );
+
+/**
+ * Cast an int64_t to double. This is necessary for embedding in
+ * certain environments.
+ *
+ */
+MONGO_EXPORT double bson_int64_to_double( int64_t i64 );
+
+MONGO_EXPORT void bson_swap_endian32( void *outp, const void *inp );
+MONGO_EXPORT void bson_swap_endian64( void *outp, const void *inp );
+
+MONGO_EXTERN_C_END
+#endif
diff --git a/third_party/bson_c/src/encoding.c b/third_party/bson_c/src/encoding.c
new file mode 100644
index 0000000000..8d2da1502f
--- /dev/null
+++ b/third_party/bson_c/src/encoding.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2009-2011 10gen, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Portions Copyright 2001 Unicode, Inc.
+ *
+ * Disclaimer
+ *
+ * This source code is provided as is by Unicode, Inc. No claims are
+ * made as to fitness for any particular purpose. No warranties of any
+ * kind are expressed or implied. The recipient agrees to determine
+ * applicability of information provided. If this file has been
+ * purchased on magnetic or optical media from Unicode, Inc., the
+ * sole remedy for any claim will be exchange of defective media
+ * within 90 days of receipt.
+ *
+ * Limitations on Rights to Redistribute This Code
+ *
+ * Unicode, Inc. hereby grants the right to freely use the information
+ * supplied in this file in the creation of products supporting the
+ * Unicode Standard, and to make copies of this file in any form
+ * for internal or external distribution as long as this notice
+ * remains attached.
+ */
+
+
+#include "bson.h"
+#include "encoding.h"
+
+/*
+ * Index into the table below with the first byte of a UTF-8 sequence to
+ * get the number of trailing bytes that are supposed to follow it.
+ */
+static const char trailingBytesForUTF8[256] = {
+ 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,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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
+};
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Utility routine to tell whether a sequence of bytes is legal UTF-8.
+ * This must be called with the length pre-determined by the first byte.
+ * The length can be set by:
+ * length = trailingBytesForUTF8[*source]+1;
+ * and the sequence is illegal right away if there aren't that many bytes
+ * available.
+ * If presented with a length > 4, this returns 0. The Unicode
+ * definition of UTF-8 goes up to 4-byte sequences.
+ */
+static int isLegalUTF8( const unsigned char *source, int length ) {
+ unsigned char a;
+ const unsigned char *srcptr = source + length;
+ switch ( length ) {
+ default:
+ return 0;
+ /* Everything else falls through when "true"... */
+ case 4:
+ if ( ( a = ( *--srcptr ) ) < 0x80 || a > 0xBF ) return 0;
+ case 3:
+ if ( ( a = ( *--srcptr ) ) < 0x80 || a > 0xBF ) return 0;
+ case 2:
+ if ( ( a = ( *--srcptr ) ) > 0xBF ) return 0;
+ switch ( *source ) {
+ /* no fall-through in this inner switch */
+ case 0xE0:
+ if ( a < 0xA0 ) return 0;
+ break;
+ case 0xF0:
+ if ( a < 0x90 ) return 0;
+ break;
+ case 0xF4:
+ if ( a > 0x8F ) return 0;
+ break;
+ default:
+ if ( a < 0x80 ) return 0;
+ }
+ case 1:
+ if ( *source >= 0x80 && *source < 0xC2 ) return 0;
+ if ( *source > 0xF4 ) return 0;
+ }
+ return 1;
+}
+
+static int bson_validate_string( bson *b, const unsigned char *string,
+ const int length, const char check_utf8, const char check_dot,
+ const char check_dollar ) {
+
+ int position = 0;
+ int sequence_length = 1;
+
+ if( check_dollar && string[0] == '$' ) {
+ b->err |= BSON_FIELD_INIT_DOLLAR;
+ }
+
+ while ( position < length ) {
+ if ( check_dot && *( string + position ) == '.' ) {
+ b->err |= BSON_FIELD_HAS_DOT;
+ }
+
+ if ( check_utf8 ) {
+ sequence_length = trailingBytesForUTF8[*( string + position )] + 1;
+ if ( ( position + sequence_length ) > length ) {
+ b->err |= BSON_NOT_UTF8;
+ return BSON_ERROR;
+ }
+ if ( !isLegalUTF8( string + position, sequence_length ) ) {
+ b->err |= BSON_NOT_UTF8;
+ return BSON_ERROR;
+ }
+ }
+ position += sequence_length;
+ }
+
+ return BSON_OK;
+}
+
+
+int bson_check_string( bson *b, const char *string,
+ const int length ) {
+
+ return bson_validate_string( b, ( const unsigned char * )string, length, 1, 0, 0 );
+}
+
+int bson_check_field_name( bson *b, const char *string,
+ const int length ) {
+
+ return bson_validate_string( b, ( const unsigned char * )string, length, 1, 1, 1 );
+}
diff --git a/third_party/bson_c/src/encoding.h b/third_party/bson_c/src/encoding.h
new file mode 100644
index 0000000000..86d5e8ea9a
--- /dev/null
+++ b/third_party/bson_c/src/encoding.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2009-2011 10gen, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BSON_ENCODING_H_
+#define BSON_ENCODING_H_
+
+MONGO_EXTERN_C_START
+
+/**
+ * Check that a field name is valid UTF8, does not start with a '$',
+ * and contains no '.' characters. Set bson bit field appropriately.
+ * Note that we don't need to check for '\0' because we're using
+ * strlen(3), which stops at '\0'.
+ *
+ * @param b The bson object to which field name will be appended.
+ * @param string The field name as char*.
+ * @param length The length of the field name.
+ *
+ * @return BSON_OK if valid UTF8 and BSON_ERROR if not. All BSON strings must be
+ * valid UTF8. This function will also check whether the string
+ * contains '.' or starts with '$', since the validity of this depends on context.
+ * Set the value of b->err appropriately.
+ */
+int bson_check_field_name( bson *b, const char *string,
+ const int length );
+
+/**
+ * Check that a string is valid UTF8. Sets the buffer bit field appropriately.
+ *
+ * @param b The bson object to which string will be appended.
+ * @param string The string to check.
+ * @param length The length of the string.
+ *
+ * @return BSON_OK if valid UTF-8; otherwise, BSON_ERROR.
+ * Sets b->err on error.
+ */
+bson_bool_t bson_check_string( bson *b, const char *string,
+ const int length );
+
+MONGO_EXTERN_C_END
+#endif
diff --git a/third_party/bson_c/src/numbers.c b/third_party/bson_c/src/numbers.c
new file mode 100644
index 0000000000..a63e3d73f9
--- /dev/null
+++ b/third_party/bson_c/src/numbers.c
@@ -0,0 +1,127 @@
+/* Copyright 2009-2011 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* all the numbers that fit in a 4 byte string */
+const char bson_numstrs[1000][4] = {
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+ "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
+ "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
+ "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
+ "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
+ "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
+ "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
+ "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
+ "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
+ "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
+
+ "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
+ "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
+ "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
+ "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
+ "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
+ "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
+ "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
+ "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
+ "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
+ "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
+
+ "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
+ "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
+ "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
+ "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
+ "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
+ "250", "251", "252", "253", "254", "255", "256", "257", "258", "259",
+ "260", "261", "262", "263", "264", "265", "266", "267", "268", "269",
+ "270", "271", "272", "273", "274", "275", "276", "277", "278", "279",
+ "280", "281", "282", "283", "284", "285", "286", "287", "288", "289",
+ "290", "291", "292", "293", "294", "295", "296", "297", "298", "299",
+
+ "300", "301", "302", "303", "304", "305", "306", "307", "308", "309",
+ "310", "311", "312", "313", "314", "315", "316", "317", "318", "319",
+ "320", "321", "322", "323", "324", "325", "326", "327", "328", "329",
+ "330", "331", "332", "333", "334", "335", "336", "337", "338", "339",
+ "340", "341", "342", "343", "344", "345", "346", "347", "348", "349",
+ "350", "351", "352", "353", "354", "355", "356", "357", "358", "359",
+ "360", "361", "362", "363", "364", "365", "366", "367", "368", "369",
+ "370", "371", "372", "373", "374", "375", "376", "377", "378", "379",
+ "380", "381", "382", "383", "384", "385", "386", "387", "388", "389",
+ "390", "391", "392", "393", "394", "395", "396", "397", "398", "399",
+
+ "400", "401", "402", "403", "404", "405", "406", "407", "408", "409",
+ "410", "411", "412", "413", "414", "415", "416", "417", "418", "419",
+ "420", "421", "422", "423", "424", "425", "426", "427", "428", "429",
+ "430", "431", "432", "433", "434", "435", "436", "437", "438", "439",
+ "440", "441", "442", "443", "444", "445", "446", "447", "448", "449",
+ "450", "451", "452", "453", "454", "455", "456", "457", "458", "459",
+ "460", "461", "462", "463", "464", "465", "466", "467", "468", "469",
+ "470", "471", "472", "473", "474", "475", "476", "477", "478", "479",
+ "480", "481", "482", "483", "484", "485", "486", "487", "488", "489",
+ "490", "491", "492", "493", "494", "495", "496", "497", "498", "499",
+
+ "500", "501", "502", "503", "504", "505", "506", "507", "508", "509",
+ "510", "511", "512", "513", "514", "515", "516", "517", "518", "519",
+ "520", "521", "522", "523", "524", "525", "526", "527", "528", "529",
+ "530", "531", "532", "533", "534", "535", "536", "537", "538", "539",
+ "540", "541", "542", "543", "544", "545", "546", "547", "548", "549",
+ "550", "551", "552", "553", "554", "555", "556", "557", "558", "559",
+ "560", "561", "562", "563", "564", "565", "566", "567", "568", "569",
+ "570", "571", "572", "573", "574", "575", "576", "577", "578", "579",
+ "580", "581", "582", "583", "584", "585", "586", "587", "588", "589",
+ "590", "591", "592", "593", "594", "595", "596", "597", "598", "599",
+
+ "600", "601", "602", "603", "604", "605", "606", "607", "608", "609",
+ "610", "611", "612", "613", "614", "615", "616", "617", "618", "619",
+ "620", "621", "622", "623", "624", "625", "626", "627", "628", "629",
+ "630", "631", "632", "633", "634", "635", "636", "637", "638", "639",
+ "640", "641", "642", "643", "644", "645", "646", "647", "648", "649",
+ "650", "651", "652", "653", "654", "655", "656", "657", "658", "659",
+ "660", "661", "662", "663", "664", "665", "666", "667", "668", "669",
+ "670", "671", "672", "673", "674", "675", "676", "677", "678", "679",
+ "680", "681", "682", "683", "684", "685", "686", "687", "688", "689",
+ "690", "691", "692", "693", "694", "695", "696", "697", "698", "699",
+
+ "700", "701", "702", "703", "704", "705", "706", "707", "708", "709",
+ "710", "711", "712", "713", "714", "715", "716", "717", "718", "719",
+ "720", "721", "722", "723", "724", "725", "726", "727", "728", "729",
+ "730", "731", "732", "733", "734", "735", "736", "737", "738", "739",
+ "740", "741", "742", "743", "744", "745", "746", "747", "748", "749",
+ "750", "751", "752", "753", "754", "755", "756", "757", "758", "759",
+ "760", "761", "762", "763", "764", "765", "766", "767", "768", "769",
+ "770", "771", "772", "773", "774", "775", "776", "777", "778", "779",
+ "780", "781", "782", "783", "784", "785", "786", "787", "788", "789",
+ "790", "791", "792", "793", "794", "795", "796", "797", "798", "799",
+
+ "800", "801", "802", "803", "804", "805", "806", "807", "808", "809",
+ "810", "811", "812", "813", "814", "815", "816", "817", "818", "819",
+ "820", "821", "822", "823", "824", "825", "826", "827", "828", "829",
+ "830", "831", "832", "833", "834", "835", "836", "837", "838", "839",
+ "840", "841", "842", "843", "844", "845", "846", "847", "848", "849",
+ "850", "851", "852", "853", "854", "855", "856", "857", "858", "859",
+ "860", "861", "862", "863", "864", "865", "866", "867", "868", "869",
+ "870", "871", "872", "873", "874", "875", "876", "877", "878", "879",
+ "880", "881", "882", "883", "884", "885", "886", "887", "888", "889",
+ "890", "891", "892", "893", "894", "895", "896", "897", "898", "899",
+
+ "900", "901", "902", "903", "904", "905", "906", "907", "908", "909",
+ "910", "911", "912", "913", "914", "915", "916", "917", "918", "919",
+ "920", "921", "922", "923", "924", "925", "926", "927", "928", "929",
+ "930", "931", "932", "933", "934", "935", "936", "937", "938", "939",
+ "940", "941", "942", "943", "944", "945", "946", "947", "948", "949",
+ "950", "951", "952", "953", "954", "955", "956", "957", "958", "959",
+ "960", "961", "962", "963", "964", "965", "966", "967", "968", "969",
+ "970", "971", "972", "973", "974", "975", "976", "977", "978", "979",
+ "980", "981", "982", "983", "984", "985", "986", "987", "988", "989",
+ "990", "991", "992", "993", "994", "995", "996", "997", "998", "999",
+};
diff --git a/third_party/bson_c/test/bson_subobject_test.c b/third_party/bson_c/test/bson_subobject_test.c
new file mode 100644
index 0000000000..06d49c9460
--- /dev/null
+++ b/third_party/bson_c/test/bson_subobject_test.c
@@ -0,0 +1,50 @@
+#include "test.h"
+#include "bson.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+int main() {
+ bson_iterator it[1], it2[1];
+ bson b[1];
+ bson sub[1];
+ bson copy[1];
+ bson_type type;
+
+ bson_init( b );
+ bson_append_string( b, "foo", "hello" );
+
+ {
+ bson_append_start_object( b, "o" );
+ bson_append_string( b, "bar", "goodbye" );
+ bson_append_finish_object( b );
+ }
+
+ bson_iterator_init( it, b );
+
+ bson_iterator_next( it );
+ type = bson_iterator_next( it );
+
+ ASSERT( BSON_OBJECT == type );
+
+ bson_iterator_subobject( it, sub );
+ ASSERT( sub->finished == 1 );
+
+ bson_iterator_init( it2, sub );
+
+ type = bson_iterator_next( it2 );
+ ASSERT( BSON_STRING == type );
+ type = bson_iterator_next( it2 );
+ ASSERT( BSON_EOO == type );
+
+ bson_copy( copy, sub );
+
+ ASSERT( 1 == copy->finished );
+ ASSERT( 0 == copy->stackPos );
+ ASSERT( 0 == copy->err );
+
+ bson_destroy( b );
+
+ return 0;
+}
+
diff --git a/third_party/bson_c/test/bson_test.c b/third_party/bson_c/test/bson_test.c
new file mode 100644
index 0000000000..f0687a1542
--- /dev/null
+++ b/third_party/bson_c/test/bson_test.c
@@ -0,0 +1,259 @@
+#include "test.h"
+#include "bson.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+int test_bson_generic() {
+
+ bson_iterator it, it2, it3;
+ bson_oid_t oid;
+ bson_timestamp_t ts;
+ bson_timestamp_t ts_result;
+ bson b[1];
+ bson copy[1];
+ bson scope[1];
+
+ ts.i = 1;
+ ts.t = 2;
+
+ bson_init( b );
+ bson_append_double( b, "d", 3.14 );
+ bson_append_string( b, "s", "hello" );
+ bson_append_string_n( b, "s_n", "goodbye cruel world", 7 );
+
+ {
+ bson_append_start_object( b, "o" );
+ bson_append_start_array( b, "a" );
+ bson_append_binary( b, "0", 8, "w\0rld", 5 );
+ bson_append_finish_object( b );
+ bson_append_finish_object( b );
+ }
+
+ bson_append_undefined( b, "u" );
+
+ bson_oid_from_string( &oid, "010203040506070809101112" );
+ ASSERT( !memcmp( oid.bytes, "\x001\x002\x003\x004\x005\x006\x007\x008\x009\x010\x011\x012", 12 ) );
+ bson_append_oid( b, "oid", &oid );
+
+ bson_append_bool( b, "b", 1 );
+ bson_append_date( b, "date", 0x0102030405060708 );
+ bson_append_null( b, "n" );
+ bson_append_regex( b, "r", "^asdf", "imx" );
+ /* no dbref test (deprecated) */
+ bson_append_code( b, "c", "function(){}" );
+ bson_append_code_n( b, "c_n", "function(){}garbage", 12 );
+ bson_append_symbol( b, "symbol", "symbol" );
+ bson_append_symbol_n( b, "symbol_n", "symbol and garbage", 6 );
+
+ {
+ bson_init( scope );
+ bson_append_int( scope, "i", 123 );
+ bson_finish( scope );
+
+ bson_append_code_w_scope( b, "cws", "function(){return i}", scope );
+ bson_destroy( scope );
+ }
+
+ bson_append_timestamp( b, "timestamp", &ts );
+ bson_append_long( b, "l", 0x1122334455667788 );
+
+ /* Ensure that we can't copy a non-finished object. */
+ ASSERT( bson_copy( copy, b ) == BSON_ERROR );
+
+ bson_finish( b );
+
+ ASSERT( b->err == BSON_VALID );
+
+ /* Test append after finish. */
+ ASSERT( bson_append_string( b, "foo", "bar" ) == BSON_ERROR );
+ ASSERT( b->err & BSON_ALREADY_FINISHED );
+
+ ASSERT( bson_copy( copy, b ) == BSON_OK );
+
+ ASSERT( 1 == copy->finished );
+ ASSERT( 0 == copy->err );
+
+ bson_print( b );
+
+ bson_iterator_init( &it, b );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_DOUBLE );
+ ASSERT( bson_iterator_type( &it ) == BSON_DOUBLE );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "d" ) );
+ ASSERT( bson_iterator_double( &it ) == 3.14 );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_STRING );
+ ASSERT( bson_iterator_type( &it ) == BSON_STRING );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "s" ) );
+ ASSERT( !strcmp( bson_iterator_string( &it ), "hello" ) );
+ ASSERT( strcmp( bson_iterator_string( &it ), "" ) );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_STRING );
+ ASSERT( bson_iterator_type( &it ) == BSON_STRING );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "s_n" ) );
+ ASSERT( !strcmp( bson_iterator_string( &it ), "goodbye" ) );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_OBJECT );
+ ASSERT( bson_iterator_type( &it ) == BSON_OBJECT );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "o" ) );
+ bson_iterator_subiterator( &it, &it2 );
+
+ ASSERT( bson_iterator_more( &it2 ) );
+ ASSERT( bson_iterator_next( &it2 ) == BSON_ARRAY );
+ ASSERT( bson_iterator_type( &it2 ) == BSON_ARRAY );
+ ASSERT( !strcmp( bson_iterator_key( &it2 ), "a" ) );
+ bson_iterator_subiterator( &it2, &it3 );
+
+ ASSERT( bson_iterator_more( &it3 ) );
+ ASSERT( bson_iterator_next( &it3 ) == BSON_BINDATA );
+ ASSERT( bson_iterator_type( &it3 ) == BSON_BINDATA );
+ ASSERT( !strcmp( bson_iterator_key( &it3 ), "0" ) );
+ ASSERT( bson_iterator_bin_type( &it3 ) == 8 );
+ ASSERT( bson_iterator_bin_len( &it3 ) == 5 );
+ ASSERT( !memcmp( bson_iterator_bin_data( &it3 ), "w\0rld", 5 ) );
+
+ ASSERT( bson_iterator_more( &it3 ) );
+ ASSERT( bson_iterator_next( &it3 ) == BSON_EOO );
+ ASSERT( bson_iterator_type( &it3 ) == BSON_EOO );
+ ASSERT( !bson_iterator_more( &it3 ) );
+
+ ASSERT( bson_iterator_more( &it2 ) );
+ ASSERT( bson_iterator_next( &it2 ) == BSON_EOO );
+ ASSERT( bson_iterator_type( &it2 ) == BSON_EOO );
+ ASSERT( !bson_iterator_more( &it2 ) );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_UNDEFINED );
+ ASSERT( bson_iterator_type( &it ) == BSON_UNDEFINED );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "u" ) );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_OID );
+ ASSERT( bson_iterator_type( &it ) == BSON_OID );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "oid" ) );
+ ASSERT( !memcmp( bson_iterator_oid( &it )->bytes, "\x001\x002\x003\x004\x005\x006\x007\x008\x009\x010\x011\x012", 12 ) );
+ ASSERT( bson_iterator_oid( &it )->ints[0] == oid.ints[0] );
+ ASSERT( bson_iterator_oid( &it )->ints[1] == oid.ints[1] );
+ ASSERT( bson_iterator_oid( &it )->ints[2] == oid.ints[2] );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_BOOL );
+ ASSERT( bson_iterator_type( &it ) == BSON_BOOL );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "b" ) );
+ ASSERT( bson_iterator_bool( &it ) == 1 );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_DATE );
+ ASSERT( bson_iterator_type( &it ) == BSON_DATE );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "date" ) );
+ ASSERT( bson_iterator_date( &it ) == 0x0102030405060708 );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_NULL );
+ ASSERT( bson_iterator_type( &it ) == BSON_NULL );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "n" ) );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_REGEX );
+ ASSERT( bson_iterator_type( &it ) == BSON_REGEX );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "r" ) );
+ ASSERT( !strcmp( bson_iterator_regex( &it ), "^asdf" ) );
+ ASSERT( !strcmp( bson_iterator_regex_opts( &it ), "imx" ) );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_CODE );
+ ASSERT( bson_iterator_type( &it ) == BSON_CODE );
+ ASSERT( !strcmp( bson_iterator_code(&it), "function(){}") );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "c" ) );
+ ASSERT( !strcmp( bson_iterator_string( &it ), "" ) );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_CODE );
+ ASSERT( bson_iterator_type( &it ) == BSON_CODE );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "c_n" ) );
+ ASSERT( !strcmp( bson_iterator_string( &it ), "" ) );
+ ASSERT( !strcmp( bson_iterator_code( &it ), "function(){}" ) );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_SYMBOL );
+ ASSERT( bson_iterator_type( &it ) == BSON_SYMBOL );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "symbol" ) );
+ ASSERT( !strcmp( bson_iterator_string( &it ), "symbol" ) );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_SYMBOL );
+ ASSERT( bson_iterator_type( &it ) == BSON_SYMBOL );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "symbol_n" ) );
+ ASSERT( !strcmp( bson_iterator_string( &it ), "symbol" ) );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_CODEWSCOPE );
+ ASSERT( bson_iterator_type( &it ) == BSON_CODEWSCOPE );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "cws" ) );
+ ASSERT( !strcmp( bson_iterator_code( &it ), "function(){return i}" ) );
+
+ {
+ bson scope;
+ bson_iterator_code_scope( &it, &scope );
+ bson_iterator_init( &it2, &scope );
+
+ ASSERT( bson_iterator_more( &it2 ) );
+ ASSERT( bson_iterator_next( &it2 ) == BSON_INT );
+ ASSERT( bson_iterator_type( &it2 ) == BSON_INT );
+ ASSERT( !strcmp( bson_iterator_key( &it2 ), "i" ) );
+ ASSERT( bson_iterator_int( &it2 ) == 123 );
+
+ ASSERT( bson_iterator_more( &it2 ) );
+ ASSERT( bson_iterator_next( &it2 ) == BSON_EOO );
+ ASSERT( bson_iterator_type( &it2 ) == BSON_EOO );
+ ASSERT( !bson_iterator_more( &it2 ) );
+ }
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_TIMESTAMP );
+ ASSERT( bson_iterator_type( &it ) == BSON_TIMESTAMP );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "timestamp" ) );
+ ts_result = bson_iterator_timestamp( &it );
+ ASSERT( ts_result.i == 1 );
+ ASSERT( ts_result.t == 2 );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_LONG );
+ ASSERT( bson_iterator_type( &it ) == BSON_LONG );
+ ASSERT( !strcmp( bson_iterator_key( &it ), "l" ) );
+ ASSERT( bson_iterator_long( &it ) == 0x1122334455667788 );
+
+ ASSERT( bson_iterator_more( &it ) );
+ ASSERT( bson_iterator_next( &it ) == BSON_EOO );
+ ASSERT( bson_iterator_type( &it ) == BSON_EOO );
+ ASSERT( !bson_iterator_more( &it ) );
+
+ bson_destroy( b );
+}
+
+int test_bson_iterator() {
+ bson b[1];
+ bson_iterator i[1];
+
+ bson_iterator_init( i, bson_empty( b ) );
+ bson_iterator_next( i );
+ bson_iterator_type( i );
+
+ bson_find( i, bson_empty( b ), "foo" );
+
+ return 0;
+}
+
+int main() {
+
+ test_bson_generic();
+ test_bson_iterator();
+
+ return 0;
+}
+