diff options
author | px4dev <px4@purgatory.org> | 2012-08-20 01:52:03 -0700 |
---|---|---|
committer | px4dev <px4@purgatory.org> | 2012-08-20 01:52:21 -0700 |
commit | 26c2c2d2cfc3f54eb0b2ff35cdebb2b0c93ab3c5 (patch) | |
tree | 8c1f7479c7ff5cf98560d9effb8e81500098fe2d | |
parent | a9dd3564ed3776b0a3f7a9b256a50c9876567f43 (diff) | |
download | px4-firmware-26c2c2d2cfc3f54eb0b2ff35cdebb2b0c93ab3c5.tar.gz px4-firmware-26c2c2d2cfc3f54eb0b2ff35cdebb2b0c93ab3c5.tar.bz2 px4-firmware-26c2c2d2cfc3f54eb0b2ff35cdebb2b0c93ab3c5.zip |
Goodbye to the Mongo BSON codec; too big. Hello to a really small SAX-style decoder and matching encoder.
-rw-r--r-- | apps/systemlib/Makefile | 3 | ||||
-rw-r--r-- | apps/systemlib/bson/bcon.c | 427 | ||||
-rw-r--r-- | apps/systemlib/bson/bcon.h | 420 | ||||
-rw-r--r-- | apps/systemlib/bson/bson.c | 1049 | ||||
-rw-r--r-- | apps/systemlib/bson/bson.h | 1044 | ||||
-rw-r--r-- | apps/systemlib/bson/tinybson.c | 313 | ||||
-rw-r--r-- | apps/systemlib/bson/tinybson.h | 169 |
7 files changed, 483 insertions, 2942 deletions
diff --git a/apps/systemlib/Makefile b/apps/systemlib/Makefile index d6b992286..0b3cb3c7b 100644 --- a/apps/systemlib/Makefile +++ b/apps/systemlib/Makefile @@ -39,8 +39,7 @@ CSRCS = err.c \ hx_stream.c \ perf_counter.c \ param/param.c \ - bson/bson.c \ - bson/bcon.c + bson/tinybson.c # # XXX this really should be a CONFIG_* test diff --git a/apps/systemlib/bson/bcon.c b/apps/systemlib/bson/bcon.c deleted file mode 100644 index 8fa9a2c9d..000000000 --- a/apps/systemlib/bson/bcon.c +++ /dev/null @@ -1,427 +0,0 @@ -/* 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 deleted file mode 100644 index a4a32faac..000000000 --- a/apps/systemlib/bson/bcon.h +++ /dev/null @@ -1,420 +0,0 @@ -/** - * @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 deleted file mode 100644 index 2cca3874d..000000000 --- a/apps/systemlib/bson/bson.c +++ /dev/null @@ -1,1049 +0,0 @@ -/* 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 deleted file mode 100644 index d5168cfd0..000000000 --- a/apps/systemlib/bson/bson.h +++ /dev/null @@ -1,1044 +0,0 @@ -/** - * @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 diff --git a/apps/systemlib/bson/tinybson.c b/apps/systemlib/bson/tinybson.c new file mode 100644 index 000000000..f2fa5b4df --- /dev/null +++ b/apps/systemlib/bson/tinybson.c @@ -0,0 +1,313 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file tinybson.c + * + * A simple subset SAX-style BSON parser and generator. + */ + +#include <unistd.h> +#include <string.h> +#include <err.h> + +#include "tinybson.h" + + +#if 1 +# define debug(fmt, args...) do { warnx("BSON:" fmt, ##args); } while(0) +#else +# define debug(fmt, args...) do { } while(0) +#endif + +#define CODER_CHECK(_c) do { if (_c->fd == -1) return -1; } while(0) +#define CODER_KILL(_c, _reason) do { debug("killed:%s", _reason); _c->fd = -1; return -1; } while(0) + +static int +read_int8(bson_decoder_t decoder, int8_t *b) +{ + return (read(decoder->fd, b, sizeof(*b)) == sizeof(*b)) ? 0 : -1; +} + +static int +read_int32(bson_decoder_t decoder, int32_t *i) +{ + return (read(decoder->fd, i, sizeof(*i)) == sizeof(*i)) ? 0 : -1; +} + +static int +read_double(bson_decoder_t decoder, double *d) +{ + return (read(decoder->fd, d, sizeof(*d)) == sizeof(*d)) ? 0 : -1; +} + +int +bson_decoder_init(bson_decoder_t decoder, int fd, bson_decoder_callback callback, void *private) +{ + int32_t junk; + + decoder->fd = fd; + decoder->callback = callback; + decoder->private = private; + decoder->nesting = 1; + decoder->pending = 0; + decoder->node.type = BSON_UNDEFINED; + + /* read and discard document size */ + if (read_int32(decoder, &junk)) + CODER_KILL(decoder, "failed reading length"); + + /* ready for decoding */ + return 0; +} + +int +bson_decoder_next(bson_decoder_t decoder) +{ + int8_t tbyte; + unsigned nlen; + + CODER_CHECK(decoder); + + /* if the previous node was EOO, pop a nesting level */ + if (decoder->node.type == BSON_EOO) { + if (decoder->nesting > 0) + decoder->nesting--; + + /* if the nesting level is now zero, the top-level document is done */ + if (decoder->nesting == 0) + CODER_KILL(decoder, "nesting is zero, document is done"); + } + + /* if there are unread bytes pending in the stream, discard them */ + while (decoder->pending != 0) { + if (read_int8(decoder, &tbyte)) + CODER_KILL(decoder, "read error discarding pending bytes"); + decoder->pending--; + } + + /* get the type byte */ + if (read_int8(decoder, &tbyte)) + CODER_KILL(decoder, "read error on type byte"); + decoder->node.type = tbyte; + decoder->pending = 0; + + /* get the node name */ + nlen = 0; + for (;;) { + if (nlen >= BSON_MAXNAME) + CODER_KILL(decoder, "node name overflow"); + if (read_int8(decoder, (int8_t *)&decoder->node.name[nlen])) + CODER_KILL(decoder, "read error on node name"); + if (decoder->node.name[nlen] == 0) + break; + nlen++; + } + + switch (decoder->node.type) { + case BSON_EOO: + /* nothing special to do here as we don't support nested objects yet */ + break; + case BSON_INT: + if (read_int32(decoder, &decoder->node.i)) { + CODER_KILL(decoder, "read error on BSON_INT"); + } + break; + case BSON_DOUBLE: + if (read_double(decoder, &decoder->node.d)) + CODER_KILL(decoder, "read error on BSON_DOUBLE"); + break; + case BSON_STRING: + if (read_int32(decoder, &decoder->pending)) + CODER_KILL(decoder, "read error on BSON_STRING length"); + break; + case BSON_BINDATA: + if (read_int32(decoder, &decoder->pending)) + CODER_KILL(decoder, "read error on BSON_BINDATA size"); + if (read_int8(decoder, &tbyte)) + CODER_KILL(decoder, "read error on BSON_BINDATA subtype"); + decoder->node.subtype = tbyte; + break; + + /* XXX currently not supporting other types */ + default: + CODER_KILL(decoder, "unsupported node type"); + } + + /* call the callback and pass its results back */ + return decoder->callback(decoder, decoder->private, &decoder->node); +} + +int +bson_decoder_copy_data(bson_decoder_t decoder, void *buf) +{ + int result; + + CODER_CHECK(decoder); + + /* if data already copied, return zero bytes */ + if (decoder->pending == 0) + return 0; + + /* copy bytes per the node size */ + result = read(decoder->fd, buf, decoder->pending); + if (result != decoder->pending) + CODER_KILL(decoder, "read error on copy_data"); + + /* pending count is discharged */ + decoder->pending = 0; + return 0; +} + +size_t +bson_decoder_data_pending(bson_decoder_t decoder) +{ + return decoder->pending; +} + +static int +write_int8(bson_encoder_t encoder, int8_t b) +{ + debug("write_int8 %d", b); + return (write(encoder->fd, &b, sizeof(b)) == sizeof(b)) ? 0 : -1; +} + +static int +write_int32(bson_encoder_t encoder, int32_t i) +{ + debug("write_int32 %d", i); + return (write(encoder->fd, &i, sizeof(i)) == sizeof(i)) ? 0 : -1; +} + +static int +write_double(bson_encoder_t encoder, double d) +{ + debug("write_double"); + return (write(encoder->fd, &d, sizeof(d)) == sizeof(d)) ? 0 : -1; +} + +static int +write_name(bson_encoder_t encoder, const char *name) +{ + size_t len = strlen(name); + + if (len > BSON_MAXNAME) + return -1; + debug("write name '%s' len %d", name, len); + return (write(encoder->fd, name, len + 1) == (int)(len + 1)) ? 0 : -1; +} + +int +bson_encoder_init(bson_encoder_t encoder, int fd) +{ + encoder->fd = fd; + + if (write_int32(encoder, 0)) + CODER_KILL(encoder, "write error on document length"); + + return 0; +} + +int +bson_encoder_fini(bson_encoder_t encoder) +{ + CODER_CHECK(encoder); + + if (write_int8(encoder, 0)) + CODER_KILL(encoder, "write error on document terminator"); + + return 0; +} + +int +bson_encoder_append_int(bson_encoder_t encoder, const char *name, int32_t value) +{ + CODER_CHECK(encoder); + + if (write_name(encoder, name)) + CODER_KILL(encoder, "write error on BSON_INT name"); + if (write_int32(encoder, value)) + CODER_KILL(encoder, "write error on BSON_INT value"); + + return 0; +} + +int +bson_encoder_append_double(bson_encoder_t encoder, const char *name, double value) +{ + CODER_CHECK(encoder); + + if (write_name(encoder, name)) + CODER_KILL(encoder, "write error on BSON_DOUBLE name"); + + if (write_double(encoder, value)) + CODER_KILL(encoder, "write error on BSON_DOUBLE value"); + + return 0; +} + +int +bson_encoder_append_string(bson_encoder_t encoder, const char *name, const char *string) +{ + size_t len; + + CODER_CHECK(encoder); + + if (write_name(encoder, name)) + CODER_KILL(encoder, "write error on BSON_STRING name"); + + len = strlen(string); + if (write_int32(encoder, len)) + CODER_KILL(encoder, "write error on BSON_STRING length"); + if (write(encoder->fd, name, len + 1) != (int)(len + 1)) + CODER_KILL(encoder, "write error on BSON_STRING data"); + return 0; +} + +int +bson_encoder_append_binary(bson_encoder_t encoder, const char *name, bson_binary_subtype_t subtype, size_t size, const void *data) +{ + CODER_CHECK(encoder); + + if (write_name(encoder, name)) + CODER_KILL(encoder, "write error on BSON_BINDATA name"); + if (write_int32(encoder, size)) + CODER_KILL(encoder, "write error on BSON_BINDATA size"); + if (write_int8(encoder, subtype)) + CODER_KILL(encoder, "write error on BSON_BINDATA subtype"); + if (write(encoder->fd, data, size) != (int)(size)) + CODER_KILL(encoder, "write error on BSON_BINDATA data"); + return 0; +} + + diff --git a/apps/systemlib/bson/tinybson.h b/apps/systemlib/bson/tinybson.h new file mode 100644 index 000000000..05bae007b --- /dev/null +++ b/apps/systemlib/bson/tinybson.h @@ -0,0 +1,169 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + + /** + * @file tinybson.h + * + * A simple subset SAX-style BSON parser and generator. + * + * Some types and defines taken from the standalone BSON parser/generator + * in the Mongo C connector. + */ + +#ifndef _TINYBSON_H +#define _TINYBSON_H + +#include <sys/types.h> +#include <stdint.h> +#include <stdbool.h> + +/** subset of the BSON node types we might care about */ +typedef enum { + BSON_EOO = 0, + BSON_DOUBLE = 1, + BSON_STRING = 2, + BSON_OBJECT = 3, + BSON_ARRAY = 4, + BSON_BINDATA = 5, + BSON_UNDEFINED = 6, + BSON_BOOL = 8, + BSON_DATE = 9, + BSON_NULL = 10, + BSON_INT = 16, + BSON_TIMESTAMP = 17, + BSON_LONG = 18 +} bson_type_t; + +typedef enum bson_binary_subtype { + BSON_BIN_BINARY = 0, + BSON_BIN_USER = 128 +} bson_binary_subtype_t; + +/** + * Maximum node name length. + */ +#define BSON_MAXNAME 32 + +/** + * Node structure passed to the callback. + */ +typedef struct bson_node_s +{ + char name[BSON_MAXNAME]; + bson_type_t type; + bson_binary_subtype_t subtype; + union { + int32_t i; + double d; + bool b; + }; +} *bson_node_t; + +typedef struct bson_decoder_s *bson_decoder_t; + +/** + * Node callback. + */ +typedef int (* bson_decoder_callback)(bson_decoder_t decoder, void *private, bson_node_t node); + +struct bson_decoder_s +{ + int fd; + bson_decoder_callback callback; + void *private; + unsigned nesting; + struct bson_node_s node; + int32_t pending; +}; + +/** + * Initialise the decoder. + */ +__EXPORT int bson_decoder_init(bson_decoder_t decoder, int fd, bson_decoder_callback callback, void *private); + +/** + * Process the next node from the stream and invoke the callback. + */ +__EXPORT int bson_decoder_next(bson_decoder_t decoder); + +/** + * Copy node data. + */ +__EXPORT int bson_decoder_copy_data(bson_decoder_t decoder, void *buf); + +/** + * Report copyable data size. + */ +__EXPORT size_t bson_decoder_data_pending(bson_decoder_t decoder); + +/** + * Encoder state structure. + */ +typedef struct bson_encoder_s +{ + int fd; + +} *bson_encoder_t; + +/** + * Initialze the encoder. + */ +__EXPORT int bson_encoder_init(bson_encoder_t encoder, int fd); + +/** + * Finalise the encoded stream. + */ +__EXPORT int bson_encoder_fini(bson_encoder_t encoder); + +/** + * Append an integer to the encoded stream. + */ +__EXPORT int bson_encoder_append_int(bson_encoder_t encoder, const char *name, int32_t value); + +/** + * Append a double to the encoded stream + */ +__EXPORT int bson_encoder_append_double(bson_encoder_t encoder, const char *name, double value); + +/** + * Append a string to the encoded stream. + */ +__EXPORT int bson_encoder_append_string(bson_encoder_t encoder, const char *name, const char *string); + +/** + * Append a binary blob to the encoded stream. + */ +__EXPORT int bson_encoder_append_binary(bson_encoder_t encoder, const char *name, bson_binary_subtype_t subtype, size_t size, const void *data); + + +#endif |