aboutsummaryrefslogtreecommitdiff
path: root/apps/systemlib/bson
diff options
context:
space:
mode:
authorpx4dev <px4@purgatory.org>2012-08-19 01:30:17 -0700
committerpx4dev <px4@purgatory.org>2012-08-19 01:31:27 -0700
commita9dc84231e0e02abbbfd2f13e3500d193ebdb03b (patch)
tree1bdd070cd212a0a25a4d3343e2bf69805528f7d9 /apps/systemlib/bson
parent2c850752214ea0ce3a8bebe51d09e651d6d7706d (diff)
downloadpx4-firmware-a9dc84231e0e02abbbfd2f13e3500d193ebdb03b.tar.gz
px4-firmware-a9dc84231e0e02abbbfd2f13e3500d193ebdb03b.tar.bz2
px4-firmware-a9dc84231e0e02abbbfd2f13e3500d193ebdb03b.zip
Import of the Mongo C-BSON library with light modifications for PX4.
From https://github.com/mongodb/mongo-c-driver.git at 8ae2c57e95a3939850a77fb9329c129b2bcfcd1a
Diffstat (limited to 'apps/systemlib/bson')
-rw-r--r--apps/systemlib/bson/bcon.c427
-rw-r--r--apps/systemlib/bson/bcon.h420
-rw-r--r--apps/systemlib/bson/bson.c1049
-rw-r--r--apps/systemlib/bson/bson.h1044
4 files changed, 2940 insertions, 0 deletions
diff --git a/apps/systemlib/bson/bcon.c b/apps/systemlib/bson/bcon.c
new file mode 100644
index 000000000..8fa9a2c9d
--- /dev/null
+++ b/apps/systemlib/bson/bcon.c
@@ -0,0 +1,427 @@
+/* bcon.c */
+
+/* Copyright 2009-2012 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 <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+#include "bcon.h"
+
+/* PX4 */
+#include <debug.h>
+#define assert(_x) ASSERT(_x)
+
+#ifndef NOT_REACHED
+#define NOT_REACHED 0
+#endif
+
+#define ARRAY_INDEX_BUFFER_SIZE 9
+
+char *bcon_errstr[] = {
+ "OK",
+ "ERROR",
+ "bcon document or nesting incomplete",
+ "bson finish error"
+};
+
+int bcon_error(bson *b, const bcon *bc, size_t i, bcon_error_t err) {
+ b->err = err;
+ b->errstr = bcon_errstr[err];
+ return BCON_ERROR;
+}
+
+bcon_error_t bson_append_bcon_array(bson *b, const bcon *bc);
+
+bcon_token_t bcon_token(char *s) {
+ if (s == 0) return Token_EOD;
+ switch (s[0]) {
+ case ':': if (s[1] != '\0' && s[2] != '\0' && s[3] != '\0' && s[4] == '\0' &&
+ s[3] == ':' && (s[1] == '_' || s[1] == 'P' || s[1] == 'R'))
+ return Token_Typespec; break;
+ case '{': if (s[1] == '\0') return Token_OpenBrace; break;
+ case '}': if (s[1] == '\0') return Token_CloseBrace; break;
+ case '[': if (s[1] == '\0') return Token_OpenBracket; break;
+ case ']': if (s[1] == '\0') return Token_CloseBracket; break;
+ case '.': if (s[1] == '\0') return Token_End; break;
+ }
+ return Token_Default;
+}
+
+bcon_error_t bson_bcon_key_value(bson *b, const char *key, const char *typespec, const bcon bci) {
+ bcon_error_t ret = BCON_OK;
+ bson_oid_t oid;
+ char ptype = typespec ? typespec[1] : '_';
+ char utype = typespec ? typespec[2] : '_';
+ switch (ptype) {
+ case '_': /* kv(b, key, utype, bci) */
+ switch (utype) {
+ case '_': /* fall through */
+ case 's': bson_append_string( b, key, bci.s ); break; /* common case */
+ case 'f': bson_append_double( b, key, bci.f ); break;
+ case 'D':
+ bson_append_start_object( b, key );
+ ret = bson_append_bcon( b, bci.D );
+ bson_append_finish_object( b );
+ break;
+ case 'A':
+ bson_append_start_array( b, key );
+ ret = bson_append_bcon_array( b, bci.A );
+ bson_append_finish_array( b );
+ break;
+ case 'o': if (*bci.o == '\0') bson_oid_gen( &oid ); else bson_oid_from_string( &oid, bci.o ); bson_append_oid( b, key, &oid ); break;
+ case 'b': bson_append_bool( b, key, bci.b ); break;
+ case 't': bson_append_time_t( b, key, bci.t ); break;
+ case 'v': bson_append_null( b, key ); break; /* void */
+ case 'x': bson_append_symbol( b, key, bci.x ); break;
+ case 'i': bson_append_int( b, key, bci.i ); break;
+ case 'l': bson_append_long( b, key, bci.l ); break;
+ default: printf("\nptype:'%c' utype:'%c'\n", ptype, utype); assert(NOT_REACHED); break;
+ }
+ break;
+ case 'R': /* krv(b, key, utype, bci) */
+ switch (utype) {
+ case 'f': bson_append_double( b, key, *bci.Rf ); break;
+ case 's': bson_append_string( b, key, bci.Rs ); break;
+ case 'D':
+ bson_append_start_object( b, key );
+ ret = bson_append_bcon( b, bci.RD );
+ bson_append_finish_object( b );
+ break;
+ case 'A':
+ bson_append_start_array( b, key );
+ ret = bson_append_bcon_array( b, bci.RA );
+ bson_append_finish_array( b );
+ break;
+ case 'o': if (*bci.o == '\0') bson_oid_gen( &oid ); else bson_oid_from_string( &oid, bci.o ); bson_append_oid( b, key, &oid ); break;
+ case 'b': bson_append_bool( b, key, *bci.Rb ); break;
+ case 't': bson_append_time_t( b, key, *bci.Rt ); break;
+ case 'x': bson_append_symbol( b, key, bci.Rx ); break;
+ case 'i': bson_append_int( b, key, *bci.Ri ); break;
+ case 'l': bson_append_long( b, key, *bci.Rl ); break;
+ default: printf("\nptype:'%c' utype:'%c'\n", ptype, utype); assert(NOT_REACHED); break;
+ }
+ break;
+ case 'P': /* kpv(b, key, utype, bci) */
+ if (*bci.Pv != 0) {
+ switch (utype) {
+ case 'f': bson_append_double( b, key, **bci.Pf ); break;
+ case 's': bson_append_string( b, key, *bci.Ps ); break;
+ case 'D':
+ bson_append_start_object( b, key );
+ ret = bson_append_bcon( b, *bci.PD );
+ bson_append_finish_object( b );
+ break;
+ case 'A':
+ bson_append_start_array( b, key );
+ ret = bson_append_bcon_array( b, *bci.PA );
+ bson_append_finish_array( b );
+ break;
+ case 'o': if (**bci.Po == '\0') bson_oid_gen( &oid );
+ else bson_oid_from_string( &oid, *bci.Po );
+ bson_append_oid( b, key, &oid );
+ break;
+ case 'b': bson_append_bool( b, key, **bci.Pb ); break;
+ case 't': bson_append_time_t( b, key, **bci.Pt ); break;
+ case 'x': if (*bci.Px != 0) bson_append_symbol( b, key, *bci.Px ); break;
+ case 'i': bson_append_int( b, key, **bci.Pi ); break;
+ case 'l': bson_append_long( b, key, **bci.Pl ); break;
+ default: printf("\nptype:'%c' utype:'%c'\n", ptype, utype); assert(NOT_REACHED); break;
+ }
+ }
+ break;
+ default:
+ printf("\nptype:'%c' utype:'%c'\n", ptype, utype); assert(NOT_REACHED);
+ break;
+ }
+ return ret;
+}
+
+typedef enum bcon_state_t {
+ State_Element, State_DocSpecValue, State_DocValue,
+ State_ArraySpecValue, State_ArrayValue
+} bcon_state_t;
+
+#define DOC_STACK_SIZE 128
+#define ARRAY_INDEX_STACK_SIZE 128
+
+#define DOC_PUSH_STATE(return_state) ( doc_stack[doc_stack_pointer++] = (return_state) )
+#define DOC_POP_STATE ( state = doc_stack[--doc_stack_pointer] )
+#define ARRAY_PUSH_RESET_INDEX_STATE(return_state) ( array_index_stack[array_index_stack_pointer++] = array_index, array_index = 0, DOC_PUSH_STATE(return_state) )
+#define ARRAY_POP_INDEX_STATE ( array_index = array_index_stack[--array_index_stack_pointer], DOC_POP_STATE )
+
+#define ARRAY_KEY_STRING(l) (bson_numstr(array_index_buffer, (int)(l)), array_index_buffer)
+
+/*
+ * simplified FSM to parse BCON structure, uses stacks for sub-documents and sub-arrays
+ */
+bcon_error_t bson_append_bcon_with_state(bson *b, const bcon *bc, bcon_state_t start_state) {
+ bcon_error_t ret = BCON_OK;
+ bcon_state_t state = start_state;
+ char *key = 0;
+ char *typespec = 0;
+ unsigned char doc_stack[DOC_STACK_SIZE];
+ size_t doc_stack_pointer = 0;
+ size_t array_index = 0;
+ unsigned int array_index_stack[ARRAY_INDEX_STACK_SIZE];
+ size_t array_index_stack_pointer = 0;
+ char array_index_buffer[ARRAY_INDEX_BUFFER_SIZE]; /* max BSON size */
+ int end_of_data;
+ const bcon *bcp;
+ for (end_of_data = 0, bcp = bc; ret == BCON_OK && !end_of_data; bcp++) {
+ bcon bci = *bcp;
+ char *s = bci.s;
+ switch (state) {
+ case State_Element:
+ switch (bcon_token(s)) {
+ case Token_CloseBrace:
+ bson_append_finish_object( b );
+ DOC_POP_STATE; /* state = ...; */
+ break;
+ case Token_End:
+ end_of_data = 1;
+ break;
+ default:
+ key = s;
+ state = State_DocSpecValue;
+ break;
+ }
+ break;
+ case State_DocSpecValue:
+ switch (bcon_token(s)) {
+ case Token_Typespec:
+ typespec = s;
+ state = State_DocValue;
+ break;
+ case Token_OpenBrace:
+ bson_append_start_object( b, key );
+ DOC_PUSH_STATE(State_Element);
+ state = State_Element;
+ break;
+ case Token_OpenBracket:
+ bson_append_start_array( b, key );
+ ARRAY_PUSH_RESET_INDEX_STATE(State_Element);
+ state = State_ArraySpecValue;
+ break;
+ case Token_End:
+ end_of_data = 1;
+ break;
+ default:
+ ret = bson_bcon_key_value(b, key, typespec, bci);
+ state = State_Element;
+ break;
+ }
+ break;
+ case State_DocValue:
+ ret = bson_bcon_key_value(b, key, typespec, bci);
+ state = State_Element;
+ typespec = 0;
+ break;
+ case State_ArraySpecValue:
+ switch (bcon_token(s)) {
+ case Token_Typespec:
+ typespec = s;
+ state = State_ArrayValue;
+ break;
+ case Token_OpenBrace:
+ key = ARRAY_KEY_STRING(array_index++);
+ bson_append_start_object( b, key );
+ DOC_PUSH_STATE(State_ArraySpecValue);
+ state = State_Element;
+ break;
+ case Token_OpenBracket:
+ key = ARRAY_KEY_STRING(array_index++);
+ bson_append_start_array( b, key );
+ ARRAY_PUSH_RESET_INDEX_STATE(State_ArraySpecValue);
+ /* state = State_ArraySpecValue; */
+ break;
+ case Token_CloseBracket:
+ bson_append_finish_array( b );
+ ARRAY_POP_INDEX_STATE; /* state = ...; */
+ break;
+ case Token_End:
+ end_of_data = 1;
+ break;
+ default:
+ key = ARRAY_KEY_STRING(array_index++);
+ ret = bson_bcon_key_value(b, key, typespec, bci);
+ /* state = State_ArraySpecValue; */
+ break;
+ }
+ break;
+ case State_ArrayValue:
+ key = ARRAY_KEY_STRING(array_index++);
+ ret = bson_bcon_key_value(b, key, typespec, bci);
+ state = State_ArraySpecValue;
+ typespec = 0;
+ break;
+ default: assert(NOT_REACHED); break;
+ }
+ }
+ return state == start_state ? BCON_OK : BCON_DOCUMENT_INCOMPLETE;
+}
+
+bcon_error_t bson_append_bcon(bson *b, const bcon *bc) {
+ return bson_append_bcon_with_state(b, bc, State_Element);
+}
+
+bcon_error_t bson_append_bcon_array(bson *b, const bcon *bc) {
+ return bson_append_bcon_with_state(b, bc, State_ArraySpecValue);
+}
+
+/**
+ * Generate BSON from BCON
+ * @param b a BSON object
+ * @param bc a BCON object
+ * match with bson_destroy
+ */
+bcon_error_t bson_from_bcon(bson *b, const bcon *bc) {
+ bcon_error_t ret = BSON_OK;
+ bson_init( b );
+ ret = bson_append_bcon_with_state( b, bc, State_Element );
+ if (ret != BCON_OK) return ret;
+ ret = bson_finish( b );
+ return ( ret == BSON_OK ? BCON_OK : BCON_BSON_ERROR );
+}
+
+void bcon_print(const bcon *bc) { /* prints internal representation, not JSON */
+ char *typespec = 0;
+ char *delim = "";
+ int end_of_data;
+ bcon *bcp;
+ putchar('{');
+ for (end_of_data = 0, bcp = (bcon*)bc; !end_of_data; bcp++) {
+ bcon bci = *bcp;
+ char *typespec_next = 0;
+ if (typespec) {
+ switch (typespec[1]) {
+ case '_':
+ switch (typespec[2]) {
+ case 'f': printf("%s%f", delim, bci.f); break;
+ case 's': printf("%s\"%s\"", delim, bci.s); break;
+ case 'D': printf("%sPD(0x%lx,..)", delim, (unsigned long)bci.D); break;
+ case 'A': printf("%sPA(0x%lx,....)", delim, (unsigned long)bci.A); break;
+ case 'o': printf("%s\"%s\"", delim, bci.o); break;
+ case 'b': printf("%s%d", delim, bci.b); break;
+ case 't': printf("%s%ld", delim, (long)bci.t); break;
+ case 'v': printf("%s\"%s\"", delim, bci.v); break;
+ case 'x': printf("%s\"%s\"", delim, bci.x); break;
+ case 'i': printf("%s%d", delim, bci.i); break;
+ case 'l': printf("%s%ld", delim, bci.l); break;
+ default: printf("\ntypespec:\"%s\"\n", typespec); assert(NOT_REACHED); break;
+ }
+ break;
+ case 'R':
+ switch (typespec[2]) {
+ case 'f': printf("%sRf(0x%lx,%f)", delim, (unsigned long)bci.Rf, *bci.Rf); break;
+ case 's': printf("%sRs(0x%lx,\"%s\")", delim, (unsigned long)bci.Rs, bci.Rs); break;
+ case 'D': printf("%sRD(0x%lx,..)", delim, (unsigned long)bci.RD); break;
+ case 'A': printf("%sRA(0x%lx,....)", delim, (unsigned long)bci.RA); break;
+ case 'o': printf("%sRo(0x%lx,\"%s\")", delim, (unsigned long)bci.Ro, bci.Ro); break;
+ case 'b': printf("%sRb(0x%lx,%d)", delim, (unsigned long)bci.Rb, *bci.Rb); break;
+ case 't': printf("%sRt(0x%lx,%ld)", delim, (unsigned long)bci.Rt, (long)*bci.Rt); break;
+ case 'x': printf("%sRx(0x%lx,\"%s\")", delim, (unsigned long)bci.Rx, bci.Rx); break;
+ case 'i': printf("%sRi(0x%lx,%d)", delim, (unsigned long)bci.Ri, *bci.Ri); break;
+ case 'l': printf("%sRl(0x%lx,%ld)", delim, (unsigned long)bci.Rl, *bci.Rl); break;
+ default: printf("\ntypespec:\"%s\"\n", typespec); assert(NOT_REACHED); break;
+ }
+ break;
+ case 'P':
+ switch (typespec[2]) {
+ case 'f': printf("%sPf(0x%lx,0x%lx,%f)", delim, (unsigned long)bci.Pf, (unsigned long)(bci.Pf ? *bci.Pf : 0), bci.Pf && *bci.Pf ? **bci.Pf : 0.0); break;
+ case 's': printf("%sPs(0x%lx,0x%lx,\"%s\")", delim, (unsigned long)bci.Ps, (unsigned long)(bci.Ps ? *bci.Ps : 0), bci.Ps && *bci.Ps ? *bci.Ps : ""); break;
+ case 'D': printf("%sPD(0x%lx,0x%lx,..)", delim, (unsigned long)bci.PD, (unsigned long)(bci.PD ? *bci.PD : 0)); break;
+ case 'A': printf("%sPA(0x%lx,0x%lx,....)", delim, (unsigned long)bci.PA, (unsigned long)(bci.PA ? *bci.PA : 0)); break;
+ case 'o': printf("%sPo(0x%lx,0x%lx,\"%s\")", delim, (unsigned long)bci.Po, (unsigned long)(bci.Po ? *bci.Po : 0), bci.Po && *bci.Po ? *bci.Po : ""); break;
+ case 'b': printf("%sPb(0x%lx,0x%lx,%d)", delim, (unsigned long)bci.Pb, (unsigned long)(bci.Pb ? *bci.Pb : 0), bci.Pb && *bci.Pb ? **bci.Pb : 0); break;
+ case 't': printf("%sPt(0x%lx,0x%lx,%ld)", delim, (unsigned long)bci.Pt, (unsigned long)(bci.Pt ? *bci.Pt : 0), bci.Pt && *bci.Pt ? (long)**bci.Pt : 0); break;
+ case 'x': printf("%sPx(0x%lx,0x%lx,\"%s\")", delim, (unsigned long)bci.Px, (unsigned long)(bci.Px ? *bci.Px : 0), bci.Px && *bci.Px ? *bci.Px : ""); break;
+ case 'i': printf("%sPi(0x%lx,0x%lx,%d)", delim, (unsigned long)bci.Pi, (unsigned long)(bci.Pi ? *bci.Pi : 0), bci.Pi && *bci.Pi ? **bci.Pi : 0); break;
+ case 'l': printf("%sPl(0x%lx,0x%lx,%ld)", delim, (unsigned long)bci.Pl, (unsigned long)(bci.Pl ? *bci.Pl : 0), bci.Pl && *bci.Pl ? **bci.Pl : 0); break;
+
+ default: printf("\ntypespec:\"%s\"\n", typespec); assert(NOT_REACHED); break;
+ }
+ break;
+ default:
+ printf("\ntypespec:\"%s\"\n", typespec); assert(NOT_REACHED);
+ break;
+ }
+ }
+ else {
+ char *s = bci.s;
+ switch (s[0]) {
+ case '.':
+ end_of_data = (s[1] == '\0');
+ break;
+ case ':':
+ typespec_next = bcon_token(s) == Token_Typespec ? s : 0;
+ break;
+ }
+ printf("%s\"%s\"", delim, s);
+ }
+ typespec = typespec_next;
+ delim = ",";
+ }
+ putchar('}');
+}
+
+/* TODO - incomplete */
+void bcon_json_print(bcon *bc, int n) {
+ int t = 0;
+ int key_value_count = 0;
+ char *s;
+ int end_of_data;
+ bcon *bcp;
+ putchar('{');
+ for (end_of_data = 0, bcp = bc; !end_of_data; bcp++) {
+ bcon bci = *bcp;
+ switch (t) {
+ case 'l':
+ if (key_value_count & 0x1) putchar(':');
+ printf("%ld", bci.l);
+ t = 0;
+ key_value_count++;
+ break;
+ case 's': /* fall through */
+ default:
+ s = bci.s;
+ switch (*s) {
+ case ':':
+ ++s;
+ t = *++s;
+ break;
+ case '{':
+ if (key_value_count & 0x1) putchar(':');
+ putchar(*s);
+ key_value_count = 0;
+ break;
+ case '}':
+ putchar(*s);
+ key_value_count = 2;
+ break;
+ default:
+ if (key_value_count & 0x1) putchar(':');
+ else if (key_value_count > 1) putchar(',');
+ printf("\"%s\"", s);
+ t = 0;
+ key_value_count++;
+ break;
+ }
+ break;
+ }
+ }
+ putchar('}');
+}
diff --git a/apps/systemlib/bson/bcon.h b/apps/systemlib/bson/bcon.h
new file mode 100644
index 000000000..a4a32faac
--- /dev/null
+++ b/apps/systemlib/bson/bcon.h
@@ -0,0 +1,420 @@
+/**
+ * @file bcon.h
+ * @brief BCON (BSON C Object Notation) Declarations
+ */
+
+/* Copyright 2009-2012 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 BCON_H_
+#define BCON_H_
+
+#include "bson.h"
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+MONGO_EXTERN_C_START
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+/**
+ * BCON - BSON C Object Notation.
+ *
+ * Overview
+ * --------
+ * BCON provides for JSON-like (or BSON-like) initializers in C.
+ * Without this, BSON must be constructed by procedural coding via explicit function calls.
+ * With this, you now have concise, readable, and maintainable data-driven definition of BSON documents.
+ * Here are a couple of introductory examples.
+ *
+ * bcon hello[] = { "hello", "world", "." };
+ * bcon pi[] = { "pi", BF(3.14159), BEND };
+ *
+ * BCON is an array of bcon union elements with the default type of char* cstring.
+ * A BCON document must be terminated with a char* cstring containing a single dot, i.e., ".", or the macro equivalent BEND.
+ *
+ * Cstring literals in double quotes are used for keys as well as for string values.
+ * There is no explicit colon (':') separator between key and value, just a comma,
+ * however it must be explicit or C will quietly concatenate the key and value strings for you.
+ * Readability may be improved by using multiple lines with a key-value pair per line.
+ *
+ * Macros are used to enclose specific types, and an internal type-specifier string prefixes a typed value.
+ * Macros are also used to specify interpolation of values from references (or pointers to references) of specified types.
+ *
+ * Sub-documents are framed by "{" "}" string literals, and sub-arrays are framed by "[" "]" literals.
+ *
+ * All of this is needed because C arrays and initializers are mono-typed unlike dict/array types in modern languages.
+ * BCON attempts to be readable and JSON-like within the context and restrictions of the C language.
+ *
+ * Specification
+ * -------------
+ * This specification parallels the BSON specification ( http://bsonspec.org/#/specification ).
+ * The specific types and their corresponding macros are documented in the bcon (union bcon) structure.
+ * The base values use two-character macros starting with "B" for the simple initialization using static values.
+ *
+ * Examples
+ * --------
+ *
+ * bcon goodbye[] = { "hello", "world", "goodbye", "world", "." };
+ * bcon awesome[] = { "BSON", "[", "awesome", BF(5.05), BI(1986), "]", "." };
+ * bcon contact_info[] = {
+ * "firstName", "John",
+ * "lastName" , "Smith",
+ * "age" , BI(25),
+ * "address" ,
+ * "{",
+ * "streetAddress", "21 2nd Street",
+ * "city" , "New York",
+ * "state" , "NY",
+ * "postalCode" , "10021",
+ * "}",
+ * "phoneNumber",
+ * "[",
+ * "{",
+ * "type" , "home",
+ * "number", "212 555-1234",
+ * "}",
+ * "{",
+ * "type" , "fax",
+ * "number", "646 555-4567",
+ * "}",
+ * "]",
+ * BEND
+ * };
+ *
+ * Comparison
+ * ----------
+ *
+ * JSON:
+ * { "BSON" : [ "awesome", 5.05, 1986 ] }
+ *
+ * BCON:
+ * bcon awesome[] = { "BSON", "[", "awesome", BF(5.05), BI(1986), "]", BEND };
+ *
+ * C driver calls:
+ * bson_init( b );
+ * bson_append_start_array( b, "BSON" );
+ * bson_append_string( b, "0", "awesome" );
+ * bson_append_double( b, "1", 5.05 );
+ * bson_append_int( b, "2", 1986 );
+ * bson_append_finish_array( b );
+ * ret = bson_finish( b );
+ * bson_print( b );
+ * bson_destroy( b );
+ *
+ * Peformance
+ * ----------
+ * With compiler optimization -O3, BCON costs about 1.1 to 1.2 times as much
+ * as the equivalent bson function calls required to explicitly construct the document.
+ * This is significantly less than the cost of parsing JSON and constructing BSON,
+ * and BCON allows value interpolation via pointers.
+ *
+ * Reference Interpolation
+ * -----------------------
+ * Reference interpolation uses three-character macros starting with "BR" for simple dynamic values.
+ * You can change the referenced content and the new values will be interpolated when you generate BSON from BCON.
+ *
+ * bson b[1];
+ * char name[] = "pi";
+ * double value = 3.14159;
+ * bcon bc[] = { "name", BRS(name), "value", BRF(&value), BEND };
+ * bson_from_bcon( b, bc ); // generates { name: "pi", "value", 3.14159 }
+ * strcpy(name, "e");
+ * value = 2.71828;
+ * bson_from_bcon( b, bc ); // generates { name: "pi", "value", 3.14159 }
+ *
+ * Please remember that in C, the array type is anomalous in that an identifier is (already) a reference,
+ * therefore there is no ampersand '&' preceding the identifier for reference interpolation.
+ * This applies to BRS(cstring), BRD(doc), BRA(array), BRO(oid), and BRX(symbol).
+ * An ampersand '&' is needed for value types BRF(&double), BRB(&boolean), BRT(&time), BRI(&int), and BRL(&long).
+ * For completeness, BRS, BRD, BRA, BRO, and BRX are defined even though BS, BD, BA, BO, and BX are equivalent.
+ *
+ * Pointer Interpolation
+ * ---------------------
+ * Pointer(-to-reference) interpolation uses three-character macros starting with "BP" for _conditional_ dynamic values.
+ * You can change the pointer content and the new values will be interpolated when you generate BSON from BCON.
+ * If you set the pointer to null, the element will skipped and not inserted into the generated BSON document.
+ *
+ * bson b[1];
+ * char name[] = "pi";
+ * char new_name[] = "log(0)";
+ * char **pname = (char**)&name;
+ * double value = 3.14159;
+ * double *pvalue = &value;
+ * bcon bc[] = { "name", BPS(&pname), "value", BPF(&pvalue), BEND };
+ * bson_from_bcon( b, bc ); // generates { name: "pi", "value", 3.14159 }
+ * pname = (char**)&new_name;
+ * pvalue = 0;
+ * bson_from_bcon( b, bc ); // generates { name: "log(0)" }
+ *
+ * Pointer interpolation necessarily adds an extra level of indirection and complexity.
+ * All macro pointer arguments are preceded by '&'.
+ * Underlying pointer types are double-indirect (**) for array types and single-indirect (*) for value types.
+ * Char name[] is used above to highlight that the array reference is not assignable (in contrast to char *array).
+ * Please note the (char**)& cast-address sequence required to silence the "incompatible-pointer-types" warning.
+ *
+ * Additional Notes
+ * ----------------
+ * Use the BS macro or the ":_s:" type specifier for string to allow string values that collide with type specifiers, braces, or square brackets.
+ *
+ * bson b[1];
+ * bcon bc[] = { "spec", BS(":_s:"), BEND };
+ * bson_from_bcon( b, bc ); // generates { spec: ":_s:" }
+ *
+ * BCON does not yet support the following BSON types.
+ *
+ * 05 e_name binary Binary data
+ * 06 e_name undefined - deprecated
+ * 0B e_name cstring cstring Regular expression
+ * 0C e_name string (byte*12) DBPointer - Deprecated
+ * 0D e_name string JavaScript code
+ * 0F e_name code_w_s JavaScript code w/ scope
+ * 11 e_name int64 Timestamp
+ * FF e_name Min key
+ * 7F e_name Max key
+ *
+ */
+
+typedef union bcon {
+ char *s; /**< 02 e_name string Macro BS(v) - UTF-8 string */ /* must be first to be default */
+ char *Rs; /**< 02 e_name string Macro BRS(v) - UTF-8 string reference interpolation */
+ char **Ps; /**< 02 e_name string Macro BPS(v) - UTF-8 string pointer interpolation */
+ double f; /**< 01 e_name double Macro BF(v) - Floating point */
+ double *Rf; /**< 01 e_name double Macro BRF(v) - Floating point reference interpolation */
+ double **Pf; /**< 01 e_name double Macro BPF(v) - Floating point pointer interpolation */
+ union bcon *D; /**< 03 e_name document Macro BD(v) - Embedded document interpolation */
+ union bcon *RD; /**< 03 e_name document Macro BRD(v) - Embedded document reference interpolation */
+ union bcon **PD; /**< 03 e_name document Macro BPD(v) - Embedded document pointer interpolation */
+ union bcon *A; /**< 04 e_name document Macro BA(v) - Array interpolation */
+ union bcon *RA; /**< 04 e_name document Macro BRA(v) - Array reference interpolation */
+ union bcon **PA; /**< 04 e_name document Macro BPA(v) - Array pointer interpolation */
+ char *o; /**< 07 e_name (byte*12) Macro BO(v) - ObjectId */
+ char *Ro; /**< 07 e_name (byte*12) Macro BRO(v) - ObjectId reference interpolation */
+ char **Po; /**< 07 e_name (byte*12) Macro BPO(v) - ObjectId pointer interpolation */
+ bson_bool_t b; /**< 08 e_name 00 Macro BB(v) - Boolean "false"
+ 08 e_name 01 Macro BB(v) - Boolean "true" */
+ bson_bool_t *Rb; /**< 08 e_name 01 Macro BRB(v) - Boolean reference interpolation */
+ bson_bool_t **Pb;/**< 08 e_name 01 Macro BPB(v) - Boolean pointer interpolation */
+ time_t t; /**< 09 e_name int64 Macro BT(v) - UTC datetime */
+ time_t *Rt; /**< 09 e_name int64 Macro BRT(v) - UTC datetime reference interpolation */
+ time_t **Pt; /**< 09 e_name int64 Macro BPT(v) - UTC datetime pointer interpolation */
+ char *v; /**< 0A e_name Macro BNULL - Null value */
+ char *x; /**< 0E e_name string Macro BX(v) - Symbol */
+ char *Rx; /**< 0E e_name string Macro BRX(v) - Symbol reference interpolation */
+ char **Px; /**< 0E e_name string Macro BPX(v) - Symbol pointer interpolation */
+ int i; /**< 10 e_name int32 Macro BI(v) - 32-bit Integer */
+ int *Ri; /**< 10 e_name int32 Macro BRI(v) - 32-bit Integer reference interpolation */
+ int **Pi; /**< 10 e_name int32 Macro BPI(v) - 32-bit Integer pointer interpolation */
+ long l; /**< 12 e_name int64 Macro BL(v) - 64-bit Integer */
+ long *Rl; /**< 12 e_name int64 Macro BRL(v) - 64-bit Integer reference interpolation */
+ long **Pl; /**< 12 e_name int64 Macro BPL(v) - 64-bit Integer pointer interpolation */
+ void **Pv; /* generic pointer internal */
+ /* "{" "}" */ /* 03 e_name document Embedded document */
+ /* "[" "]" */ /* 04 e_name document Array */
+ /* 05 e_name binary Binary data */
+ /* 06 e_name undefined - deprecated */
+ /* 0B e_name cstring cstring Regular expression */
+ /* 0C e_name string (byte*12) DBPointer - Deprecated */
+ /* 0D e_name string JavaScript code */
+ /* 0F e_name code_w_s JavaScript code w/ scope */
+ /* 11 e_name int64 Timestamp */
+ /* FF e_name Min key */
+ /* 7F e_name Max key */
+} bcon;
+
+/** BCON document terminator */
+#define BEND "."
+
+/** BCON internal 01 double Floating point type-specifier */
+#define BTF ":_f:"
+/** BCON internal 02 char* string type-specifier */
+#define BTS ":_s:"
+/** BCON internal 03 union bcon* Embedded document interpolation type-specifier */
+#define BTD ":_D:"
+/** BCON internal 04 union bcon* Array interpolation type-specifier */
+#define BTA ":_A:"
+/** BCON internal 07 char* ObjectId type-specifier */
+#define BTO ":_o:"
+/** BCON internal 08 int Boolean type-specifier */
+#define BTB ":_b:"
+/** BCON internal 09 int64 UTC datetime type-specifier */
+#define BTT ":_t:"
+/** BCON internal 0A Null type-specifier */
+#define BTN ":_v:"
+/** BCON internal 0E char* Symbol type-specifier */
+#define BTX ":_x:"
+/** BCON internal 10 int32 64-bit Integer type-specifier */
+#define BTI ":_i:"
+/** BCON internal 12 int64 64-bit Integer type-specifier */
+#define BTL ":_l:"
+
+/** BCON internal 01 double* Floating point reference interpolation type-specifier */
+#define BTRF ":Rf:"
+/** BCON internal 02 char* string reference interpolation type-specifier */
+#define BTRS ":Rs:"
+/** BCON internal 03 union bcon* Embedded document reference interpolation type-specifier */
+#define BTRD ":RD:"
+/** BCON internal 04 union bcon* Array reference interpolation type-specifier */
+#define BTRA ":RA:"
+/** BCON internal 07 char* ObjectId reference interpolation type-specifier */
+#define BTRO ":Ro:"
+/** BCON internal 08 int* Boolean reference interpolation type-specifier */
+#define BTRB ":Rb:"
+/** BCON internal 09 int64* UTC datetime reference interpolation type-specifier */
+#define BTRT ":Rt:"
+/** BCON internal 0E char* Symbol reference interpolation type-specifier */
+#define BTRX ":Rx:"
+/** BCON internal 10 int32* 23-bit Integer reference interpolation type-specifier */
+#define BTRI ":Ri:"
+/** BCON internal 12 int64* 64-bit Integer reference interpolation type-specifier */
+#define BTRL ":Rl:"
+
+/** BCON internal 01 double** Floating point pointer interpolation type-specifier */
+#define BTPF ":Pf:"
+/** BCON internal 02 char** string pointer interpolation type-specifier */
+#define BTPS ":Ps:"
+/** BCON internal 03 union bcon** Embedded document pointer interpolation type-specifier */
+#define BTPD ":PD:"
+/** BCON internal 04 union bcon** Array pointer interpolation type-specifier */
+#define BTPA ":PA:"
+/** BCON internal 07 char** ObjectId pointer interpolation type-specifier */
+#define BTPO ":Po:"
+/** BCON internal 08 int** Boolean pointer interpolation type-specifier */
+#define BTPB ":Pb:"
+/** BCON internal 09 int64** UTC datetime pointer interpolation type-specifier */
+#define BTPT ":Pt:"
+/** BCON internal 0E char** Symbol pointer interpolation type-specifier */
+#define BTPX ":Px:"
+/** BCON internal 10 int32** 23-bit Integer pointer interpolation type-specifier */
+#define BTPI ":Pi:"
+/** BCON internal 12 int64** 64-bit Integer pointer interpolation type-specifier */
+#define BTPL ":Pl:"
+
+/** BCON 01 double Floating point value */
+#define BF(v) BTF, { .f = (v) }
+/** BCON 02 char* string value */
+#define BS(v) BTS, { .s = (v) }
+/** BCON 03 union bcon* Embedded document interpolation value */
+#define BD(v) BTD, { .D = (v) }
+/** BCON 04 union bcon* Array interpolation value */
+#define BA(v) BTA, { .A = (v) }
+/** BCON 07 char* ObjectId value */
+#define BO(v) BTO, { .o = (v) }
+/** BCON 08 int Boolean value */
+#define BB(v) BTB, { .b = (v) }
+/** BCON 09 int64 UTC datetime value */
+#define BT(v) BTT, { .t = (v) }
+/** BCON 0A Null value */
+#define BNULL BTN, { .v = ("") }
+/** BCON 0E char* Symbol value */
+#define BX(v) BTX, { .x = (v) }
+/** BCON 10 int32 32-bit Integer value */
+#define BI(v) BTI, { .i = (v) }
+/** BCON 12 int64 64-bit Integer value */
+#define BL(v) BTL, { .l = (v) }
+
+/** BCON 01 double* Floating point interpolation value */
+#define BRF(v) BTRF, { .Rf = (v) }
+/** BCON 02 char* string interpolation value */
+#define BRS(v) BTRS, { .Rs = (v) }
+/** BCON 03 union bcon* Embedded document interpolation value */
+#define BRD(v) BTRD, { .RD = (v) }
+/** BCON 04 union bcon* Array interpolation value */
+#define BRA(v) BTRA, { .RA = (v) }
+/** BCON 07 char* ObjectId interpolation value */
+#define BRO(v) BTRO, { .Ro = (v) }
+/** BCON 08 int* Boolean interpolation value */
+#define BRB(v) BTRB, { .Rb = (v) }
+/** BCON 09 int64* UTC datetime value */
+#define BRT(v) BTRT, { .Rt = (v) }
+/** BCON 0E char* Symbol interpolation value */
+#define BRX(v) BTRX, { .Rx = (v) }
+/** BCON 10 int32* 32-bit Integer interpolation value */
+#define BRI(v) BTRI, { .Ri = (v) }
+/** BCON 12 int64* 64-bit Integer interpolation value */
+#define BRL(v) BTRL, { .Rl = (v) }
+
+/** BCON 01 double** Floating point interpolation value */
+#define BPF(v) BTPF, { .Pf = (v) }
+/** BCON 02 char** string interpolation value */
+#define BPS(v) BTPS, { .Ps = ((char**)v) }
+/** BCON 03 union bcon** Embedded document interpolation value */
+#define BPD(v) BTPD, { .PD = ((union bcon **)v) }
+/** BCON 04 union bcon** Array interpolation value */
+#define BPA(v) BTPA, { .PA = ((union bcon **)v) }
+/** BCON 07 char** ObjectId interpolation value */
+#define BPO(v) BTPO, { .Po = ((char**)v) }
+/** BCON 08 int** Boolean interpolation value */
+#define BPB(v) BTPB, { .Pb = (v) }
+/** BCON 09 int64** UTC datetime value */
+#define BPT(v) BTPT, { .Pt = (v) }
+/** BCON 0E char** Symbol interpolation value */
+#define BPX(v) BTPX, { .Px = ((char**)v) }
+/** BCON 10 int32** 32-bit Integer interpolation value */
+#define BPI(v) BTPI, { .Pi = (v) }
+/** BCON 12 int64** 64-bit Integer interpolation value */
+#define BPL(v) BTPL, { .Pl = (v) }
+
+/*
+ * References on codes used for types
+ * http://en.wikipedia.org/wiki/Name_mangling
+ * http://www.agner.org/optimize/calling_conventions.pdf (page 25)
+ */
+
+typedef enum bcon_error_t {
+ BCON_OK = 0, /**< OK return code */
+ BCON_ERROR, /**< ERROR return code */
+ BCON_DOCUMENT_INCOMPLETE, /**< bcon document or nesting incomplete */
+ BCON_BSON_ERROR /**< bson finish error */
+} bcon_error_t;
+
+extern char *bcon_errstr[]; /**< bcon_error_t text messages */
+
+/**
+ * Append a BCON object to a BSON object.
+ *
+ * @param b a BSON object
+ * @param bc a BCON object
+ */
+MONGO_EXPORT bcon_error_t bson_append_bcon(bson *b, const bcon *bc);
+
+/**
+ * Generate a BSON object from a BCON object.
+ *
+ * @param b a BSON object
+ * @param bc a BCON object
+ */
+MONGO_EXPORT bcon_error_t bson_from_bcon( bson *b, const bcon *bc );
+
+/**
+ * Print a string representation of a BCON object.
+ *
+ * @param bc the BCON object to print.
+ */
+MONGO_EXPORT void bcon_print( const bcon *bc );
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+MONGO_EXTERN_C_END
+
+typedef enum bcon_token_t {
+ Token_Default, Token_End, Token_Typespec,
+ Token_OpenBrace, Token_CloseBrace, Token_OpenBracket, Token_CloseBracket,
+ Token_EOD
+} bcon_token_t;
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+#endif
diff --git a/apps/systemlib/bson/bson.c b/apps/systemlib/bson/bson.c
new file mode 100644
index 000000000..2cca3874d
--- /dev/null
+++ b/apps/systemlib/bson/bson.c
@@ -0,0 +1,1049 @@
+/* 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"
+#if 0 /* PX4 */
+#include "encoding.h"
+#else
+# define bson_check_field_name(_b, _s, _l) BSON_OK
+# define bson_check_string(_b, _s, _l) BSON_OK
+#endif
+
+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_func )( 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( void ) {
+ return (bson*)bson_malloc(sizeof(bson));
+}
+
+MONGO_EXPORT void bson_dispose(bson* b) {
+ bson_free(b);
+}
+
+MONGO_EXPORT 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->errstr = NULL;
+ obj->stackPos = 0;
+ return obj;
+}
+
+MONGO_EXPORT int bson_copy( bson *out, const bson *in ) {
+ if ( !out || !in ) 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);
+}
+
+
+MONGO_EXPORT const char *bson_data( const bson *b ) {
+ return (const char *)b->data;
+}
+
+static char hexbyte( char hex ) {
+ if (hex >= '0' && hex <= '9')
+ return (hex - '0');
+ else if (hex >= 'A' && hex <= 'F')
+ return (hex - 'A' + 10);
+ else if (hex >= 'a' && hex <= 'f')
+ return (hex - 'a' + 10);
+ else
+ return 0x0;
+}
+
+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';
+}
+
+MONGO_EXPORT void bson_set_oid_fuzz( int ( *func )( void ) ) {
+ oid_fuzz_func = func;
+}
+
+MONGO_EXPORT 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 );
+}
+
+MONGO_EXPORT time_t bson_oid_generated_time( bson_oid_t *oid ) {
+ time_t out;
+ bson_big_endian32( &out, &oid->ints[0] );
+
+ return out;
+}
+
+MONGO_EXPORT void bson_print( const bson *b ) {
+ bson_print_raw( b->data , 0 );
+}
+
+MONGO_EXPORT 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 ); */ /* review - stepped on by bson_iterator_code_scope? */
+ bson_iterator_code_scope( &i, &scope );
+ bson_printf( "\n\t SCOPE: " );
+ bson_print( &scope );
+ /* bson_destroy( &scope ); */ /* review - causes free error */
+ 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( void ) {
+ 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;
+}
+
+MONGO_EXPORT 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 );
+}
+
+MONGO_EXPORT 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;
+}
+
+MONGO_EXPORT 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;
+ }
+}
+
+MONGO_EXPORT 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 );
+}
+
+MONGO_EXPORT 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;
+
+}
+
+MONGO_EXPORT 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 );
+}
+
+MONGO_EXPORT 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 );
+}
+
+MONGO_EXPORT 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 );
+}
+
+MONGO_EXPORT 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 );
+}
+
+MONGO_EXPORT int bson_append_code_w_scope_n( bson *b, const char *name,
+ const char *code, int len, const bson *scope ) {
+
+ int sl, size;
+ if ( !scope ) return BSON_ERROR;
+ sl = len + 1;
+ 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;
+}
+
+MONGO_EXPORT 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 ) return BSON_ERROR;
+ 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;
+}
+
+MONGO_EXPORT 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;
+}
+
+MONGO_EXPORT 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;
+}
+
+MONGO_EXPORT 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;
+}
+
+MONGO_EXPORT 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;
+}
+
+MONGO_EXPORT void bson_free( void *ptr ) {
+ bson_free_func( ptr );
+}
+
+MONGO_EXPORT 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
+}
+
+
+#if 0 /* PX4 */
+/* 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 );
+}
+#else
+void bson_numstr( char *str, int i ) {
+ bson_sprintf( str,"%d", i );
+}
+#endif
+
+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/apps/systemlib/bson/bson.h b/apps/systemlib/bson/bson.h
new file mode 100644
index 000000000..d5168cfd0
--- /dev/null
+++ b/apps/systemlib/bson/bson.h
@@ -0,0 +1,1044 @@
+/**
+ * @file bson.h
+ * @brief BSON Declarations
+ */
+
+/* Copyright 2009-2012 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__
+ #if 0 /* PX4 */
+ #define MONGO_EXPORT
+ #else
+ #define MONGO_EXPORT __EXPORT
+ #endif
+#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_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; /**< Pointer to a block of data in this BSON object. */
+ char *cur; /**< Pointer to the current position. */
+ int dataSize; /**< The number of bytes allocated to char *data. */
+ bson_bool_t finished; /**< When finished, the BSON object can no longer be modified. */
+ int stack[32]; /**< A stack used to keep track of nested BSON elements. */
+ int stackPos; /**< Index of current stack position. */
+ 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( void );
+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.
+ */
+MONGO_EXPORT void bson_print( const bson *b );
+
+/**
+ * Return a pointer to the raw buffer stored by this bson object.
+ *
+ * @param b a BSON object
+ */
+MONGO_EXPORT const char *bson_data( const 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
+ */
+MONGO_EXPORT 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( void );
+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.
+ */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT void bson_set_oid_inc( int ( *func )( void ) );
+
+/**
+ * Get the time a bson_oid_t was created.
+ *
+ * @param oid the bson_oid_t.
+ */
+MONGO_EXPORT 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 */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT 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.
+ */
+MONGO_EXPORT 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_func )( 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;
+
+MONGO_EXPORT void bson_free( void *ptr );
+
+/**
+ * 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)
+ */
+MONGO_EXPORT 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