'\" t .\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "BSON_REFERENCE" "3" "Apr 02, 2024" "1.26.2" "libbson" .SH LIBBSON .sp A Cross Platform BSON Library for C .SS Introduction .sp libbson builds, parses, and iterates \fI\%BSON\fP documents, the native data format of MongoDB. It also converts BSON to and from JSON, and provides a platform compatibility layer for \fI\%the MongoDB C Driver\fP\&. .SS Tutorial .SS Using libbson In Your C Program .SS Include bson.h .sp All libbson\(aqs functions and types are available in one header file. Simply include \fBbson.h\fP: .sp hello_bson.c .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include int main (int argc, const char **argv) { bson_t *b; char *j; b = BCON_NEW (\(dqhello\(dq, BCON_UTF8 (\(dqbson!\(dq)); j = bson_as_canonical_extended_json (b, NULL); printf (\(dq%s\en\(dq, j); bson_free (j); bson_destroy (b); return 0; } .EE .UNINDENT .UNINDENT .SS CMake .sp The libbson installation includes a \fI\%CMake config\-file package\fP, so you can use CMake\(aqs \fI\%find_package\fP command to import libbson\(aqs CMake target and link to libbson (as a shared library): .sp CMakeLists.txt .INDENT 0.0 .INDENT 3.5 .sp .EX # Specify the minimum version you require. find_package (bson\-1.0 1.7 REQUIRED) # The \(dqhello_bson.c\(dq sample program is shared among four tests. add_executable (hello_bson ../../hello_bson.c) target_link_libraries (hello_bson PRIVATE mongo::bson_shared) .EE .UNINDENT .UNINDENT .sp You can also use libbson as a static library instead: Use the \fBmongo::bson_static\fP CMake target: .INDENT 0.0 .INDENT 3.5 .sp .EX # Specify the minimum version you require. find_package (bson\-1.0 1.7 REQUIRED) # The \(dqhello_bson.c\(dq sample program is shared among four tests. add_executable (hello_bson ../../hello_bson.c) target_link_libraries (hello_bson PRIVATE mongo::bson_static) .EE .UNINDENT .UNINDENT .SS pkg\-config .sp If you\(aqre not using CMake, use \fI\%pkg\-config\fP on the command line to set header and library paths: .INDENT 0.0 .INDENT 3.5 .sp .EX gcc \-o hello_bson hello_bson.c $(pkg\-config \-\-libs \-\-cflags libbson\-1.0) .EE .UNINDENT .UNINDENT .sp Or to statically link to libbson: .INDENT 0.0 .INDENT 3.5 .sp .EX gcc \-o hello_bson hello_bson.c $(pkg\-config \-\-libs \-\-cflags libbson\-static\-1.0) .EE .UNINDENT .UNINDENT .SS Creating a BSON Document .SS The bson_t structure .sp BSON documents are created using the \fI\%bson_t\fP structure. This structure encapsulates the necessary logic for encoding using the \fI\%BSON Specification\fP\&. At the core, \fI\%bson_t\fP is a buffer manager and set of encoding routines. .sp \fBTIP:\fP .INDENT 0.0 .INDENT 3.5 BSON documents can live on the stack or the heap based on the performance needs or preference of the consumer. .UNINDENT .UNINDENT .sp Let\(aqs start by creating a new BSON document on the stack. Whenever using libbson, make sure you \fB#include \fP\&. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t b; bson_init (&b); .EE .UNINDENT .UNINDENT .sp This creates an empty document. In JSON, this would be the same as \fB{}\fP\&. .sp We can now proceed to adding items to the BSON document. A variety of functions prefixed with \fBbson_append_\fP can be used based on the type of field you want to append. Let\(aqs append a UTF\-8 encoded string. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_append_utf8 (&b, \(dqkey\(dq, \-1, \(dqvalue\(dq, \-1); .EE .UNINDENT .UNINDENT .sp Notice the two \fB\-1\fP parameters. The first indicates that the length of \fBkey\fP in bytes should be determined with \fBstrlen()\fP\&. Alternatively, we could have passed the number \fB3\fP\&. The same goes for the second \fB\-1\fP, but for \fBvalue\fP\&. .sp Libbson provides macros to make this less tedious when using string literals. The following two appends are identical. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_append_utf8 (&b, \(dqkey\(dq, \-1, \(dqvalue\(dq, \-1); BSON_APPEND_UTF8 (&b, \(dqkey\(dq, \(dqvalue\(dq); .EE .UNINDENT .UNINDENT .sp Now let\(aqs take a look at an example that adds a few different field types to a BSON document. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t b = BSON_INITIALIZER; BSON_APPEND_INT32 (&b, \(dqa\(dq, 1); BSON_APPEND_UTF8 (&b, \(dqhello\(dq, \(dqworld\(dq); BSON_APPEND_BOOL (&b, \(dqbool\(dq, true); .EE .UNINDENT .UNINDENT .sp Notice that we omitted the call to \fI\%bson_init()\fP\&. By specifying \fBBSON_INITIALIZER\fP we can remove the need to initialize the structure to a base state. .SS Sub\-Documents and Sub\-Arrays .sp To simplify the creation of sub\-documents \fI\%bson_append_document_begin()\fP can be used to build a sub\-document using the parent\(aqs memory region as the destination buffer. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t parent = BSON_INITIALIZER; bson_t child; bson_append_document_begin (&parent, \(dqfoo\(dq, 3, &child); bson_append_int32 (&child, \(dqbaz\(dq, 3, 1); bson_append_document_end (&parent, &child); char *str = bson_as_relaxed_extended_json (&parent, NULL); printf (\(dq%s\en\(dq, str); // Prints: { \(dqfoo\(dq : { \(dqbaz\(dq : 1 } } bson_free (str); bson_destroy (&parent); .EE .UNINDENT .UNINDENT .sp To simplify the creation of sub\-arrays \fI\%bson_array_builder_t\fP can be used to build a sub\-array using the parent\(aqs memory region as the destination buffer. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t parent = BSON_INITIALIZER; bson_array_builder_t *bab; bson_append_array_builder_begin (&parent, \(dqfoo\(dq, 3, &bab); bson_array_builder_append_int32 (bab, 9); bson_array_builder_append_int32 (bab, 8); bson_array_builder_append_int32 (bab, 7); bson_append_array_builder_end (&parent, bab); char *str = bson_as_relaxed_extended_json (&parent, NULL); printf (\(dq%s\en\(dq, str); // Prints: { \(dqfoo\(dq : [ 9, 8, 7 ] } bson_free (str); bson_destroy (&parent); .EE .UNINDENT .UNINDENT .SS Simplified BSON C Object Notation .sp Creating BSON documents by hand can be tedious and time consuming. BCON, or BSON C Object Notation, was added to allow for the creation of BSON documents in a format that looks closer to the destination format. .sp The following example shows the use of BCON. Notice that values for fields are wrapped in the \fBBCON_*\fP macros. These are required for the variadic processor to determine the parameter type. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t *doc; doc = BCON_NEW (\(dqfoo\(dq, \(dq{\(dq, \(dqint\(dq, BCON_INT32 (1), \(dqarray\(dq, \(dq[\(dq, BCON_INT32 (100), \(dq{\(dq, \(dqsub\(dq, BCON_UTF8 (\(dqvalue\(dq), \(dq}\(dq, \(dq]\(dq, \(dq}\(dq); .EE .UNINDENT .UNINDENT .sp Creates the following document .INDENT 0.0 .INDENT 3.5 .sp .EX { \(dqfoo\(dq : { \(dqint\(dq : 1, \(dqarray\(dq : [ 100, { \(dqsub\(dq : \(dqvalue\(dq } ] } } .EE .UNINDENT .UNINDENT .SS Handling Errors .SS Description .sp Many libbson functions report errors by returning \fBNULL\fP or \-1 and filling out a \fI\%bson_error_t\fP structure with an error domain, error code, and message. .INDENT 0.0 .IP \(bu 2 \fBerror.domain\fP names the subsystem that generated the error. .IP \(bu 2 \fBerror.code\fP is a domain\-specific error type. .IP \(bu 2 \fBerror.message\fP describes the error. .UNINDENT .sp Some error codes overlap with others; always check both the domain and code to determine the type of error. .TS center; |l|l|l|. _ T{ \fBBSON_ERROR_JSON\fP T} T{ \fBBSON_JSON_ERROR_READ_CORRUPT_JS\fP \fBBSON_JSON_ERROR_READ_INVALID_PARAM\fP \fBBSON_JSON_ERROR_READ_CB_FAILURE\fP T} T{ \fI\%bson_json_reader_t\fP tried to parse invalid MongoDB Extended JSON. Tried to parse a valid JSON document that is invalid as MongoDBExtended JSON. An internal callback failure during JSON parsing. T} _ T{ \fBBSON_ERROR_READER\fP T} T{ \fBBSON_ERROR_READER_BADFD\fP T} T{ \fI\%bson_json_reader_new_from_file()\fP could not open the file. T} _ .TE .SS ObjectIDs .sp Libbson provides a simple way to generate ObjectIDs. It can be used in a single\-threaded or multi\-threaded manner depending on your requirements. .sp The \fI\%bson_oid_t\fP structure represents an \fBObjectID\fP in MongoDB. It is a 96\-bit identifier. .SS Composition .INDENT 0.0 .IP \(bu 2 4 bytes : The UNIX timestamp in big\-endian format. .IP \(bu 2 5 bytes : A random number. .IP \(bu 2 3 bytes : A 24\-bit monotonic counter incrementing from \fBrand()\fP in big\-endian. .UNINDENT .SS Sorting ObjectIDs .sp The typical way to sort in C is using \fBqsort()\fP\&. Therefore, Libbson provides a \fBqsort()\fP compatible callback function named \fI\%bson_oid_compare()\fP\&. It returns \fBless than 1\fP, \fBgreater than 1\fP, or \fB0\fP depending on the equality of two \fI\%bson_oid_t\fP structures. .SS Comparing Object IDs .sp If you simply want to compare two \fI\%bson_oid_t\fP structures for equality, use \fI\%bson_oid_equal()\fP\&. .SS Generating .sp To generate a \fI\%bson_oid_t\fP, you may use the following. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_oid_t oid; bson_oid_init (&oid, NULL); .EE .UNINDENT .UNINDENT .SS Parsing ObjectID Strings .sp You can also parse a string containing a \fI\%bson_oid_t\fP\&. The input string \fIMUST\fP be 24 characters or more in length. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_oid_t oid; bson_oid_init_from_string (&oid, \(dq123456789012345678901234\(dq); .EE .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX bson_oid_t oid; bson_oid_init_from_string_unsafe (&oid, \(dq123456789012345678901234\(dq); .EE .UNINDENT .UNINDENT .SS Hashing ObjectIDs .sp If you need to store items in a hashtable, you may want to use the \fI\%bson_oid_t\fP as the key. Libbson provides a hash function for just this purpose. It is based on DJB hash. .INDENT 0.0 .INDENT 3.5 .sp .EX unsigned hash; hash = bson_oid_hash (oid); .EE .UNINDENT .UNINDENT .SS Fetching ObjectID Creation Time .sp You can easily fetch the time that a \fI\%bson_oid_t\fP was generated using \fI\%bson_oid_get_time_t()\fP\&. .INDENT 0.0 .INDENT 3.5 .sp .EX time_t t; t = bson_oid_get_time_t (oid); printf (\(dqThe OID was generated at %u\en\(dq, (unsigned) t); .EE .UNINDENT .UNINDENT .SS Parsing and Iterating BSON Documents .SS Parsing .sp BSON documents are lazily parsed as necessary. To begin parsing a BSON document, use one of the provided Libbson functions to create a new \fI\%bson_t\fP from existing data such as \fI\%bson_new_from_data()\fP\&. This will make a copy of the data so that additional mutations may occur to the BSON document. .sp \fBTIP:\fP .INDENT 0.0 .INDENT 3.5 If you only want to parse a BSON document and have no need to mutate it, you may use \fI\%bson_init_static()\fP to avoid making a copy of the data. .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t *b; b = bson_new_from_data (my_data, my_data_len); if (!b) { fprintf (stderr, \(dqThe specified length embedded in did not match \(dq \(dq\en\(dq); return; } bson_destroy (b); .EE .UNINDENT .UNINDENT .sp Only two checks are performed when creating a new \fI\%bson_t\fP from an existing buffer. First, the document must begin with the buffer length, matching what was expected by the caller. Second, the document must end with the expected trailing \fB\e0\fP byte. .sp To parse the document further we use a \fI\%bson_iter_t\fP to iterate the elements within the document. Let\(aqs print all of the field names in the document. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t *b; bson_iter_t iter; if ((b = bson_new_from_data (my_data, my_data_len))) { if (bson_iter_init (&iter, b)) { while (bson_iter_next (&iter)) { printf (\(dqFound element key: \e\(dq%s\e\(dq\en\(dq, bson_iter_key (&iter)); } } bson_destroy (b); } .EE .UNINDENT .UNINDENT .sp Converting a document to JSON uses a \fI\%bson_iter_t\fP and \fI\%bson_visitor_t\fP to iterate all fields of a BSON document recursively and generate a UTF\-8 encoded JSON string. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t *b; char *json; if ((b = bson_new_from_data (my_data, my_data_len))) { if ((json = bson_as_canonical_extended_json (b, NULL))) { printf (\(dq%s\en\(dq, json); bson_free (json); } bson_destroy (b); } .EE .UNINDENT .UNINDENT .SS Recursing into Sub\-Documents .sp Libbson provides convenient sub\-iterators to dive down into a sub\-document or sub\-array. Below is an example that will dive into a sub\-document named \(dqfoo\(dq and print it\(aqs field names. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_iter_t iter; bson_iter_t child; char *json; if (bson_iter_init_find (&iter, doc, \(dqfoo\(dq) && BSON_ITER_HOLDS_DOCUMENT (&iter) && bson_iter_recurse (&iter, &child)) { while (bson_iter_next (&child)) { printf (\(dqFound sub\-key of \e\(dqfoo\e\(dq named \e\(dq%s\e\(dq\en\(dq, bson_iter_key (&child)); } } .EE .UNINDENT .UNINDENT .SS Finding Fields using Dot Notation .sp Using the \fI\%bson_iter_recurse()\fP function exemplified above, \fI\%bson_iter_find_descendant()\fP can find a field for you using the MongoDB style path notation such as \(dqfoo.bar.0.baz\(dq. .sp Let\(aqs create a document like \fB{\(dqfoo\(dq: {\(dqbar\(dq: [{\(dqbaz: 1}]}}\fP and locate the \fB\(dqbaz\(dq\fP field. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t *b; bson_iter_t iter; bson_iter_t baz; b = BCON_NEW (\(dqfoo\(dq, \(dq{\(dq, \(dqbar\(dq, \(dq[\(dq, \(dq{\(dq, \(dqbaz\(dq, BCON_INT32 (1), \(dq}\(dq, \(dq]\(dq, \(dq}\(dq); if (bson_iter_init (&iter, b) && bson_iter_find_descendant (&iter, \(dqfoo.bar.0.baz\(dq, &baz) && BSON_ITER_HOLDS_INT32 (&baz)) { printf (\(dqbaz = %d\en\(dq, bson_iter_int32 (&baz)); } bson_destroy (b); .EE .UNINDENT .UNINDENT .SS Validating a BSON Document .sp If all you want to do is validate that a BSON document is valid, you can use \fI\%bson_validate()\fP\&. .INDENT 0.0 .INDENT 3.5 .sp .EX size_t err_offset; if (!bson_validate (doc, BSON_VALIDATE_NONE, &err_offset)) { fprintf (stderr, \(dqThe document failed to validate at offset: %u\en\(dq, (unsigned) err_offset); } .EE .UNINDENT .UNINDENT .sp See the \fI\%bson_validate()\fP documentation for more information and examples. .SS UTF\-8 .SS Encoding .sp Libbson expects that you are always working with UTF\-8 encoded text. Anything else is \fBinvalid API use\fP\&. .sp If you should need to walk through UTF\-8 sequences, you can use the various UTF\-8 helper functions distributed with Libbson. .SS Validating a UTF\-8 Sequence .sp To validate the string contained in \fBmy_string\fP, use the following. You may pass \fB\-1\fP for the string length if you know the string is NULL\-terminated. .INDENT 0.0 .INDENT 3.5 .sp .EX if (!bson_utf8_validate (my_string, \-1, false)) { printf (\(dqValidation failed.\en\(dq); } .EE .UNINDENT .UNINDENT .sp If \fBmy_string\fP has NULL bytes within the string, you must provide the string length. Use the following format. Notice the \fBtrue\fP at the end indicating \fB\e0\fP is allowed. .INDENT 0.0 .INDENT 3.5 .sp .EX if (!bson_utf8_validate (my_string, my_string_len, true)) { printf (\(dqValidation failed.\en\(dq); } .EE .UNINDENT .UNINDENT .sp For more information see the API reference for \fI\%bson_utf8_validate()\fP\&. .SS Guides .SS Streaming BSON .sp \fI\%bson_reader_t\fP provides a streaming reader which can be initialized with a filedescriptor or memory region. \fI\%bson_writer_t\fP provides a streaming writer which can be initialized with a memory region. (Streaming BSON to a file descriptor is not yet supported.) .SS Reading from a BSON Stream .sp \fI\%bson_reader_t\fP provides a convenient API to read sequential BSON documents from a file\-descriptor or memory buffer. The \fI\%bson_reader_read()\fP function will read forward in the underlying stream and return a \fI\%bson_t\fP that can be inspected and iterated upon. .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include int main (int argc, char *argv[]) { bson_reader_t *reader; const bson_t *doc; bson_error_t error; bool eof; reader = bson_reader_new_from_file (\(dqmycollection.bson\(dq, &error); if (!reader) { fprintf (stderr, \(dqFailed to open file.\en\(dq); return 1; } while ((doc = bson_reader_read (reader, &eof))) { char *str = bson_as_canonical_extended_json (doc, NULL); printf (\(dq%s\en\(dq, str); bson_free (str); } if (!eof) { fprintf (stderr, \(dqcorrupted bson document found at %u\en\(dq, (unsigned) bson_reader_tell (reader)); } bson_reader_destroy (reader); return 0; } .EE .UNINDENT .UNINDENT .sp See \fI\%bson_reader_new_from_fd()\fP, \fI\%bson_reader_new_from_file()\fP, and \fI\%bson_reader_new_from_data()\fP for more information. .SS Writing a sequence of BSON Documents .sp \fI\%bson_writer_t\fP provides a convenient API to write a sequence of BSON documents to a memory buffer that can grow with \fBrealloc()\fP\&. The \fI\%bson_writer_begin()\fP and \fI\%bson_writer_end()\fP functions will manage the underlying buffer while building the sequence of documents. .sp This could also be useful if you want to write to a network packet while serializing the documents from a higher level language, (but do so just after the packets header). .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include #include int main (int argc, char *argv[]) { bson_writer_t *writer; bson_t *doc; uint8_t *buf = NULL; size_t buflen = 0; bool r; int i; writer = bson_writer_new (&buf, &buflen, 0, bson_realloc_ctx, NULL); for (i = 0; i < 10000; i++) { r = bson_writer_begin (writer, &doc); assert (r); r = BSON_APPEND_INT32 (doc, \(dqi\(dq, i); assert (r); bson_writer_end (writer); } bson_free (buf); return 0; } .EE .UNINDENT .UNINDENT .sp See \fI\%bson_writer_new()\fP for more information. .SS JSON .sp Libbson provides routines for converting to and from the JSON format. In particular, it supports the \fI\%MongoDB extended JSON\fP format. .SS Converting BSON to JSON .sp There are often times where you might want to convert a BSON document to JSON. It is convenient for debugging as well as an interchange format. To help with this, Libbson contains the functions \fI\%bson_as_canonical_extended_json()\fP and \fI\%bson_as_relaxed_extended_json()\fP\&. The canonical format preserves BSON type information for values that may have ambiguous representations in JSON (e.g. numeric types). .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t *b; size_t len; char *str; b = BCON_NEW (\(dqa\(dq, BCON_INT32 (1)); str = bson_as_canonical_extended_json (b, &len); printf (\(dq%s\en\(dq, str); bson_free (str); bson_destroy (b); .EE .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX { \(dqa\(dq : { \(dq$numberInt\(dq: \(dq1\(dq } } .EE .UNINDENT .UNINDENT .sp The relaxed format prefers JSON primitives for numeric values and may be used if type fidelity is not required. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t *b; size_t len; char *str; b = BCON_NEW (\(dqa\(dq, BCON_INT32 (1)); str = bson_as_relaxed_extended_json (b, &len); printf (\(dq%s\en\(dq, str); bson_free (str); bson_destroy (b); .EE .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX { \(dqa\(dq : 1 } .EE .UNINDENT .UNINDENT .SS Converting JSON to BSON .sp Converting back from JSON is also useful and common enough that we added \fI\%bson_init_from_json()\fP and \fI\%bson_new_from_json()\fP\&. .sp The following example creates a new \fI\%bson_t\fP from the JSON string \fB{\(dqa\(dq:1}\fP\&. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t *b; bson_error_t error; b = bson_new_from_json (\(dq{\e\(dqa\e\(dq:1}\(dq, \-1, &error); if (!b) { printf (\(dqError: %s\en\(dq, error.message); } else { bson_destroy (b); } .EE .UNINDENT .UNINDENT .SS Streaming JSON Parsing .sp Libbson provides \fI\%bson_json_reader_t\fP to allow for parsing a sequence of JSON documents into BSON. The interface is similar to \fI\%bson_reader_t\fP but expects the input to be in the \fI\%MongoDB extended JSON\fP format. .INDENT 0.0 .INDENT 3.5 .sp .EX /* * Copyright 2013 MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the \(dqLicense\(dq); * 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 \(dqAS IS\(dq 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. */ /* * This program will print each JSON document contained in the provided files * as a BSON string to STDOUT. */ #include #include #include int main (int argc, char *argv[]) { bson_json_reader_t *reader; bson_error_t error; const char *filename; bson_t doc = BSON_INITIALIZER; int i; int b; /* * Print program usage if no arguments are provided. */ if (argc == 1) { fprintf (stderr, \(dqusage: %s FILE...\en\(dq, argv[0]); return 1; } /* * Process command line arguments expecting each to be a filename. */ for (i = 1; i < argc; i++) { filename = argv[i]; /* * Open the filename provided in command line arguments. */ if (0 == strcmp (filename, \(dq\-\(dq)) { reader = bson_json_reader_new_from_fd (STDIN_FILENO, false); } else { if (!(reader = bson_json_reader_new_from_file (filename, &error))) { fprintf ( stderr, \(dqFailed to open \e\(dq%s\e\(dq: %s\en\(dq, filename, error.message); continue; } } /* * Convert each incoming document to BSON and print to stdout. */ while ((b = bson_json_reader_read (reader, &doc, &error))) { if (b < 0) { fprintf (stderr, \(dqError in json parsing:\en%s\en\(dq, error.message); abort (); } if (fwrite (bson_get_data (&doc), 1, doc.len, stdout) != doc.len) { fprintf (stderr, \(dqFailed to write to stdout, exiting.\en\(dq); exit (1); } bson_reinit (&doc); } bson_json_reader_destroy (reader); bson_destroy (&doc); } return 0; } .EE .UNINDENT .UNINDENT .SS Examples .sp The following example reads BSON documents from \fBstdin\fP and prints them to \fBstdout\fP as JSON. .INDENT 0.0 .INDENT 3.5 .sp .EX /* * Copyright 2013 MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the \(dqLicense\(dq); * 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 \(dqAS IS\(dq 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. */ /* * This program will print each BSON document contained in the provided files * as a JSON string to STDOUT. */ #include #include int main (int argc, char *argv[]) { bson_reader_t *reader; const bson_t *b; bson_error_t error; const char *filename; char *str; int i; /* * Print program usage if no arguments are provided. */ if (argc == 1) { fprintf (stderr, \(dqusage: %s [FILE | \-]...\enUse \- for STDIN.\en\(dq, argv[0]); return 1; } /* * Process command line arguments expecting each to be a filename. */ for (i = 1; i < argc; i++) { filename = argv[i]; if (strcmp (filename, \(dq\-\(dq) == 0) { reader = bson_reader_new_from_fd (STDIN_FILENO, false); } else { if (!(reader = bson_reader_new_from_file (filename, &error))) { fprintf ( stderr, \(dqFailed to open \e\(dq%s\e\(dq: %s\en\(dq, filename, error.message); continue; } } /* * Convert each incoming document to JSON and print to stdout. */ while ((b = bson_reader_read (reader, NULL))) { str = bson_as_canonical_extended_json (b, NULL); fprintf (stdout, \(dq%s\en\(dq, str); bson_free (str); } /* * Cleanup after our reader, which closes the file descriptor. */ bson_reader_destroy (reader); } return 0; } .EE .UNINDENT .UNINDENT .SS \fI\%bson_t\fP lifetimes .sp A \fI\%bson_t\fP may contain its data directly or may contain pointers to heap\-allocated memory. Overwriting an existing \fI\%bson_t\fP or allowing a stack\-allocated \fI\%bson_t\fP to go out of scope may cause a memory leak. A \fI\%bson_t\fP should always be destroyed with \fI\%bson_destroy()\fP\&. .SS \fI\%bson_t\fP out parameters .sp A \fI\%bson_t\fP pointer used as an out parameter must point to valid overwritable storage for a new \fI\%bson_t\fP which must be one of: .INDENT 0.0 .IP 1. 3 Uninitialized storage for a \fI\%bson_t\fP\&. .IP 2. 3 A zero\-initialized \fI\%bson_t\fP object. .IP 3. 3 A \fI\%bson_t\fP object initialized with \fBBSON_INITIALIZER\fP\&. .IP 4. 3 A \fI\%bson_t\fP object not created with \fI\%bson_new()\fP that was destroyed with \fI\%bson_destroy()\fP\&. .UNINDENT .sp This can be on the stack: .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t stack_doc = BSON_INITIALIZER; example_get_doc (&stack_doc); bson_destroy (&stack_doc); .EE .UNINDENT .UNINDENT .sp Or on the heap: .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t *heap_doc = bson_malloc (sizeof (bson_t)); example_get_doc (heap_doc); bson_destroy (heap_doc); bson_free (heap_doc); .EE .UNINDENT .UNINDENT .sp Omitting \fI\%bson_destroy()\fP in either case may cause memory leaks. .sp \fBWARNING:\fP .INDENT 0.0 .INDENT 3.5 Passing a \fI\%bson_t\fP pointer obtained from \fI\%bson_new()\fP as an out parameter will result in a leak of the \fI\%bson_t\fP struct. .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t *heap_doc = bson_new (); example_get_doc (heap_doc); bson_destroy (heap_doc); // Leaks the \(gabson_t\(ga struct! .EE .UNINDENT .UNINDENT .UNINDENT .UNINDENT .SS Cross Platform Notes .SS Endianness .sp The BSON specification dictates that the encoding format is in little\-endian. Many implementations simply ignore endianness altogether and expect that they are to be run on little\-endian. Libbson supports both Big and Little Endian systems. This means we use \fBmemcpy()\fP when appropriate instead of dereferencing and properly convert to and from the host endian format. We expect the compiler intrinsics to optimize it to a dereference when possible. .SS Threading .sp Libbson\(aqs data structures are \fINOT\fP thread\-safe. You are responsible for accessing and mutating these structures from one thread at a time. .sp Libbson requires POSIX threads (pthreads) on all UNIX\-like platforms. On Windows, the native threading interface is used. Libbson uses your system\(aqs threading library to safely generate unique \fI\%ObjectIds\fP, and to provide a fallback implementation for atomic operations on platforms without built\-in atomics. .SS API Reference .SS bson_t .sp BSON Document Abstraction .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX #include /** * bson_empty: * @b: a bson_t. * * Checks to see if @b is an empty BSON document. An empty BSON document is * a 5 byte document which contains the length (4 bytes) and a single NUL * byte indicating end of fields. */ #define bson_empty(b) /* ... */ /** * bson_empty0: * * Like bson_empty() but treats NULL the same as an empty bson_t document. */ #define bson_empty0(b) /* ... */ /** * bson_clear: * * Easily free a bson document and set it to NULL. Use like: * * bson_t *doc = bson_new(); * bson_clear (&doc); * BSON_ASSERT (doc == NULL); */ #define bson_clear(bptr) /* ... */ /** * BSON_MAX_SIZE: * * The maximum size in bytes of a BSON document. */ #define BSON_MAX_SIZE /* ... */ #define BSON_APPEND_ARRAY(b, key, val) \e bson_append_array (b, key, (int) strlen (key), val) #define BSON_APPEND_ARRAY_BEGIN(b, key, child) \e bson_append_array_begin (b, key, (int) strlen (key), child) #define BSON_APPEND_BINARY(b, key, subtype, val, len) \e bson_append_binary (b, key, (int) strlen (key), subtype, val, len) #define BSON_APPEND_BOOL(b, key, val) \e bson_append_bool (b, key, (int) strlen (key), val) #define BSON_APPEND_CODE(b, key, val) \e bson_append_code (b, key, (int) strlen (key), val) #define BSON_APPEND_CODE_WITH_SCOPE(b, key, val, scope) \e bson_append_code_with_scope (b, key, (int) strlen (key), val, scope) #define BSON_APPEND_DBPOINTER(b, key, coll, oid) \e bson_append_dbpointer (b, key, (int) strlen (key), coll, oid) #define BSON_APPEND_DOCUMENT_BEGIN(b, key, child) \e bson_append_document_begin (b, key, (int) strlen (key), child) #define BSON_APPEND_DOUBLE(b, key, val) \e bson_append_double (b, key, (int) strlen (key), val) #define BSON_APPEND_DOCUMENT(b, key, val) \e bson_append_document (b, key, (int) strlen (key), val) #define BSON_APPEND_INT32(b, key, val) \e bson_append_int32 (b, key, (int) strlen (key), val) #define BSON_APPEND_INT64(b, key, val) \e bson_append_int64 (b, key, (int) strlen (key), val) #define BSON_APPEND_MINKEY(b, key) \e bson_append_minkey (b, key, (int) strlen (key)) #define BSON_APPEND_DECIMAL128(b, key, val) \e bson_append_decimal128 (b, key, (int) strlen (key), val) #define BSON_APPEND_MAXKEY(b, key) \e bson_append_maxkey (b, key, (int) strlen (key)) #define BSON_APPEND_NULL(b, key) bson_append_null (b, key, (int) strlen (key)) #define BSON_APPEND_OID(b, key, val) \e bson_append_oid (b, key, (int) strlen (key), val) #define BSON_APPEND_REGEX(b, key, val, opt) \e bson_append_regex (b, key, (int) strlen (key), val, opt) #define BSON_APPEND_UTF8(b, key, val) \e bson_append_utf8 (b, key, (int) strlen (key), val, (int) strlen (val)) #define BSON_APPEND_SYMBOL(b, key, val) \e bson_append_symbol (b, key, (int) strlen (key), val, (int) strlen (val)) #define BSON_APPEND_TIME_T(b, key, val) \e bson_append_time_t (b, key, (int) strlen (key), val) #define BSON_APPEND_TIMEVAL(b, key, val) \e bson_append_timeval (b, key, (int) strlen (key), val) #define BSON_APPEND_DATE_TIME(b, key, val) \e bson_append_date_time (b, key, (int) strlen (key), val) #define BSON_APPEND_TIMESTAMP(b, key, val, inc) \e bson_append_timestamp (b, key, (int) strlen (key), val, inc) #define BSON_APPEND_UNDEFINED(b, key) \e bson_append_undefined (b, key, (int) strlen (key)) #define BSON_APPEND_VALUE(b, key, val) \e bson_append_value (b, key, (int) strlen (key), (val)) BSON_ALIGNED_BEGIN (128) typedef struct { uint32_t flags; /* Internal flags for the bson_t. */ uint32_t len; /* Length of BSON data. */ uint8_t padding[120]; /* Padding for stack allocation. */ } bson_t BSON_ALIGNED_END (128); .EE .UNINDENT .UNINDENT .SS Description .sp The \fI\%bson_t\fP structure represents a BSON document. This structure manages the underlying BSON encoded buffer. For mutable documents, it can append new data to the document. .SS Performance Notes .sp The \fI\%bson_t\fP structure attempts to use an inline allocation within the structure to speed up performance of small documents. When this internal buffer has been exhausted, a heap allocated buffer will be dynamically allocated. Therefore, it is essential to call \fI\%bson_destroy()\fP on allocated documents. .SS Duplicate Keys .sp The \fI\%BSON specification\fP allows BSON documents to have duplicate keys. Documents are stored as an ordered list of key\-value pairs. A \fI\%bson_t\fP may contain duplicate keys. Applications should refrain from generating such documents, because MongoDB server behavior is undefined when a BSON document contains duplicate keys. .SS Example .INDENT 0.0 .INDENT 3.5 .sp .EX static void create_on_heap (void) { bson_t *b = bson_new (); BSON_APPEND_INT32 (b, \(dqfoo\(dq, 123); BSON_APPEND_UTF8 (b, \(dqbar\(dq, \(dqfoo\(dq); BSON_APPEND_DOUBLE (b, \(dqbaz\(dq, 1.23f); bson_destroy (b); } .EE .UNINDENT .UNINDENT .SS bson_array_builder_t .INDENT 0.0 .INDENT 3.5 .sp .EX typedef struct _bson_array_builder_t bson_array_builder_t; .EE .UNINDENT .UNINDENT .sp \fBbson_array_builder_t\fP may be used to build BSON arrays. \fBbson_array_builder_t\fP internally tracks and uses the array index as a key (\(dq0\(dq, \(dq1\(dq, \(dq2\(dq, ...) when appending elements. .SS Appending an array value .INDENT 0.0 .INDENT 3.5 .sp .EX typedef struct _bson_array_builder_t bson_array_builder_t; bool bson_append_array_builder_begin (bson_t *bson, const char *key, int key_length, bson_array_builder_t **child); bool bson_append_array_builder_end (bson_t *bson, bson_array_builder_t *child); #define BSON_APPEND_ARRAY_BUILDER_BEGIN(b, key, child) \e bson_append_array_builder_begin (b, key, (int) strlen (key), child) .EE .UNINDENT .UNINDENT .sp \fBbson_append_array_builder_begin\fP may be used to append an array as a value. Example: .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t parent = BSON_INITIALIZER; bson_array_builder_t *bab; bson_append_array_builder_begin (&parent, \(dqfoo\(dq, 3, &bab); bson_array_builder_append_int32 (bab, 9); bson_array_builder_append_int32 (bab, 8); bson_array_builder_append_int32 (bab, 7); bson_append_array_builder_end (&parent, bab); char *str = bson_as_relaxed_extended_json (&parent, NULL); printf (\(dq%s\en\(dq, str); // Prints: { \(dqfoo\(dq : [ 9, 8, 7 ] } bson_free (str); bson_destroy (&parent); .EE .UNINDENT .UNINDENT .SS Creating a top\-level array .INDENT 0.0 .INDENT 3.5 .sp .EX bson_array_builder_t * bson_array_builder_new (void); bool bson_array_builder_build (bson_array_builder_t *bab, bson_t *out); BSON_EXPORT (void) bson_array_builder_destroy (bson_array_builder_t *bab); .EE .UNINDENT .UNINDENT .sp \fBbson_array_builder_new\fP and \fBbson_array_builder_build\fP may be used to build a top\-level BSON array. \fBbson_array_builder_build\fP initializes and moves BSON data to \fBout\fP\&. The \fBbson_array_builder_t\fP may be reused and will start appending a new array at index \(dq0\(dq: .sp Example: .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t out; bson_array_builder_t *bab = bson_array_builder_new (); bson_array_builder_append_int32 (bab, 9); bson_array_builder_append_int32 (bab, 8); bson_array_builder_append_int32 (bab, 7); bson_array_builder_build (bab, &out); char *str = bson_array_as_relaxed_extended_json (&out, NULL); printf (\(dq%s\en\(dq, str); // Prints: [ 9, 8, 7 ] bson_free (str); bson_array_builder_destroy (bab); .EE .UNINDENT .UNINDENT .SS Appending values to an array .sp \fBbson_array_builder_append_*\fP functions are provided to append values to a BSON array. The \fBbson_array_builder_append_*\fP functions internally use \fBbson_append_*\fP and provide the array index as a key: .INDENT 0.0 .INDENT 3.5 .sp .EX bool bson_array_builder_append_value (bson_array_builder_t *bab, const bson_value_t *value); bool bson_array_builder_append_array (bson_array_builder_t *bab, const bson_t *array); bool bson_array_builder_append_binary (bson_array_builder_t *bab, bson_subtype_t subtype, const uint8_t *binary, uint32_t length); bool bson_array_builder_append_bool (bson_array_builder_t *bab, bool value); bool bson_array_builder_append_code (bson_array_builder_t *bab, const char *javascript); bool bson_array_builder_append_code_with_scope (bson_array_builder_t *bab, const char *javascript, const bson_t *scope); bool bson_array_builder_append_dbpointer (bson_array_builder_t *bab, const char *collection, const bson_oid_t *oid); bool bson_array_builder_append_double (bson_array_builder_t *bab, double value); bool bson_array_builder_append_document (bson_array_builder_t *bab, const bson_t *value); bool bson_array_builder_append_document_begin (bson_array_builder_t *bab, bson_t *child); bool bson_array_builder_append_document_end (bson_array_builder_t *bab, bson_t *child); bool bson_array_builder_append_int32 (bson_array_builder_t *bab, int32_t value); bool bson_array_builder_append_int64 (bson_array_builder_t *bab, int64_t value); bool bson_array_builder_append_decimal128 (bson_array_builder_t *bab, const bson_decimal128_t *value); bool bson_array_builder_append_iter (bson_array_builder_t *bab, const bson_iter_t *iter); bool bson_array_builder_append_minkey (bson_array_builder_t *bab); bool bson_array_builder_append_maxkey (bson_array_builder_t *bab); bool bson_array_builder_append_null (bson_array_builder_t *bab); bool bson_array_builder_append_oid (bson_array_builder_t *bab, const bson_oid_t *oid); bool bson_array_builder_append_regex (bson_array_builder_t *bab, const char *regex, const char *options); bool bson_array_builder_append_regex_w_len (bson_array_builder_t *bab, const char *regex, int regex_length, const char *options); bool bson_array_builder_append_utf8 (bson_array_builder_t *bab, const char *value, int length); bool bson_array_builder_append_symbol (bson_array_builder_t *bab, const char *value, int length); bool bson_array_builder_append_time_t (bson_array_builder_t *bab, time_t value); bool bson_array_builder_append_timeval (bson_array_builder_t *bab, struct timeval *value); bool bson_array_builder_append_date_time (bson_array_builder_t *bab, int64_t value); bool bson_array_builder_append_now_utc (bson_array_builder_t *bab); bool bson_array_builder_append_timestamp (bson_array_builder_t *bab, uint32_t timestamp, uint32_t increment); bool bson_array_builder_append_undefined (bson_array_builder_t *bab); bool bson_array_builder_append_array_builder_begin (bson_array_builder_t *bab, bson_array_builder_t **child); bool bson_array_builder_append_array_builder_end (bson_array_builder_t *bab, bson_array_builder_t *child); .EE .UNINDENT .UNINDENT .SS bson_context_t .sp BSON OID Generation Context .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX #include typedef enum { BSON_CONTEXT_NONE = 0, BSON_CONTEXT_DISABLE_PID_CACHE = (1 << 2), } bson_context_flags_t; typedef struct _bson_context_t bson_context_t; bson_context_t * bson_context_get_default (void) BSON_GNUC_CONST; bson_context_t * bson_context_new (bson_context_flags_t flags); void bson_context_destroy (bson_context_t *context); .EE .UNINDENT .UNINDENT .SS Description .sp The \fI\%bson_context_t\fP structure is context for generation of BSON Object IDs. This context allows overriding behavior of generating ObjectIDs. The flags \fBBSON_CONTEXT_NONE\fP, \fBBSON_CONTEXT_THREAD_SAFE\fP, and \fBBSON_CONTEXT_DISABLE_PID_CACHE\fP are the only ones used. The others have no effect. .SS Example .INDENT 0.0 .INDENT 3.5 .sp .EX #include int main (int argc, char *argv[]) { bson_context_t *ctx = NULL; bson_oid_t oid; /* use default context, via bson_context_get_default() */ bson_oid_init (&oid, NULL); /* specify a local context for additional control */ ctx = bson_context_new (BSON_CONTEXT_NONE); bson_oid_init (&oid, ctx); bson_context_destroy (ctx); return 0; } .EE .UNINDENT .UNINDENT .SS bson_decimal128_t .sp BSON Decimal128 Abstraction .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX #include #define BSON_DECIMAL128_STRING 43 #define BSON_DECIMAL128_INF \(dqInfinity\(dq #define BSON_DECIMAL128_NAN \(dqNaN\(dq typedef struct { #if BSON_BYTE_ORDER == BSON_LITTLE_ENDIAN uint64_t low; uint64_t high; #elif BSON_BYTE_ORDER == BSON_BIG_ENDIAN uint64_t high; uint64_t low; #endif } bson_decimal128_t; .EE .UNINDENT .UNINDENT .SS Description .sp The \fI\%bson_decimal128_t\fP structure represents the IEEE\-754 Decimal128 data type. The type \fBbson_decimal128_t\fP is an aggregate that contains two \fBuint64_t\fPs, named \fBhigh\fP and \fBlow\fP\&. The declaration and layout order between them depends on the endian order of the target platform: \fBlow\fP will always correspond to the low\-order bits of the Decimal128 object, while \fBhigh\fP corresponds to the high\-order bits. The \fBbson_decimal128_t\fP always has a size of sixteen (\fB16\fP), and can be bit\-cast to/from a \fB_Decimal128\fP\&. .SS Example .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include int main (int argc, char *argv[]) { char string[BSON_DECIMAL128_STRING]; bson_decimal128_t decimal128; bson_decimal128_from_string (\(dq100.00\(dq, &decimal128); bson_decimal128_to_string (&decimal128, string); printf (\(dqDecimal128 value: %s\en\(dq, string); return 0; } .EE .UNINDENT .UNINDENT .SS bson_error_t .sp BSON Error Encapsulation .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX #include typedef struct { uint32_t domain; uint32_t code; char message[504]; } bson_error_t; .EE .UNINDENT .UNINDENT .SS Description .sp The \fI\%bson_error_t\fP structure is used as an out\-parameter to pass error information to the caller. It should be stack\-allocated and does not requiring freeing. .sp See \fI\%Handling Errors\fP\&. .SS Example .INDENT 0.0 .INDENT 3.5 .sp .EX bson_reader_t *reader; bson_error_t error; reader = bson_reader_new_from_file (\(dqdump.bson\(dq, &error); if (!reader) { fprintf ( stderr, \(dqERROR: %d.%d: %s\en\(dq, error.domain, error.code, error.message); } .EE .UNINDENT .UNINDENT .SS bson_iter_t .sp BSON Document Iterator .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX #include #define BSON_ITER_HOLDS_DOUBLE(iter) /* ... */ #define BSON_ITER_HOLDS_UTF8(iter) /* ... */ #define BSON_ITER_HOLDS_DOCUMENT(iter) /* ... */ #define BSON_ITER_HOLDS_ARRAY(iter) /* ... */ #define BSON_ITER_HOLDS_BINARY(iter) /* ... */ #define BSON_ITER_HOLDS_UNDEFINED(iter) /* ... */ #define BSON_ITER_HOLDS_OID(iter) /* ... */ #define BSON_ITER_HOLDS_BOOL(iter) /* ... */ #define BSON_ITER_HOLDS_DATE_TIME(iter) /* ... */ #define BSON_ITER_HOLDS_NULL(iter) /* ... */ #define BSON_ITER_HOLDS_REGEX(iter) /* ... */ #define BSON_ITER_HOLDS_DBPOINTER(iter) /* ... */ #define BSON_ITER_HOLDS_CODE(iter) /* ... */ #define BSON_ITER_HOLDS_SYMBOL(iter) /* ... */ #define BSON_ITER_HOLDS_CODEWSCOPE(iter) /* ... */ #define BSON_ITER_HOLDS_INT32(iter) /* ... */ #define BSON_ITER_HOLDS_TIMESTAMP(iter) /* ... */ #define BSON_ITER_HOLDS_INT64(iter) /* ... */ #define BSON_ITER_HOLDS_DECIMAL128(iter) /* ... */ #define BSON_ITER_HOLDS_MAXKEY(iter) /* ... */ #define BSON_ITER_HOLDS_MINKEY(iter) /* ... */ #define BSON_ITER_HOLDS_INT(iter) \e (BSON_ITER_HOLDS_INT32 (iter) || BSON_ITER_HOLDS_INT64 (iter)) #define BSON_ITER_HOLDS_NUMBER(iter) \e (BSON_ITER_HOLDS_INT (iter) || BSON_ITER_HOLDS_DOUBLE (iter)) #define BSON_ITER_IS_KEY(iter, key) \e (0 == strcmp ((key), bson_iter_key ((iter)))) typedef struct { /*< private >*/ } bson_iter_t; .EE .UNINDENT .UNINDENT .SS Description .sp \fI\%bson_iter_t\fP is a structure used to iterate through the elements of a \fI\%bson_t\fP\&. It is meant to be used on the stack and can be discarded at any time as it contains no external allocation. The contents of the structure should be considered private and may change between releases, however the structure size will not change. .sp The \fI\%bson_t\fP \fIMUST\fP be valid for the lifetime of the iter and it is an error to modify the \fI\%bson_t\fP while using the iter. .SS Examples .INDENT 0.0 .INDENT 3.5 .sp .EX bson_iter_t iter; if (bson_iter_init (&iter, my_bson_doc)) { while (bson_iter_next (&iter)) { printf (\(dqFound a field named: %s\en\(dq, bson_iter_key (&iter)); } } .EE .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX bson_iter_t iter; if (bson_iter_init (&iter, my_bson_doc) && bson_iter_find (&iter, \(dqmy_field\(dq)) { printf (\(dqFound the field named: %s\en\(dq, bson_iter_key (&iter)); } .EE .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX bson_iter_t iter; bson_iter_t sub_iter; if (bson_iter_init_find (&iter, my_bson_doc, \(dqmysubdoc\(dq) && (BSON_ITER_HOLDS_DOCUMENT (&iter) || BSON_ITER_HOLDS_ARRAY (&iter)) && bson_iter_recurse (&iter, &sub_iter)) { while (bson_iter_next (&sub_iter)) { printf (\(dqFound key \e\(dq%s\e\(dq in sub document.\en\(dq, bson_iter_key (&sub_iter)); } } .EE .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX bson_iter_t iter; if (bson_iter_init (&iter, my_doc) && bson_iter_find_descendant (&iter, \(dqa.b.c.d\(dq, &sub_iter)) { printf (\(dqThe type of a.b.c.d is: %d\en\(dq, (int) bson_iter_type (&sub_iter)); } .EE .UNINDENT .UNINDENT .SS bson_json_reader_t .sp Bulk JSON to BSON conversion .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX #include typedef struct _bson_json_reader_t bson_json_reader_t; typedef enum { BSON_JSON_ERROR_READ_CORRUPT_JS = 1, BSON_JSON_ERROR_READ_INVALID_PARAM, BSON_JSON_ERROR_READ_CB_FAILURE, } bson_json_error_code_t; .EE .UNINDENT .UNINDENT .SS Description .sp The \fI\%bson_json_reader_t\fP structure is used for reading a sequence of JSON documents and transforming them to \fI\%bson_t\fP documents. .sp This can often be useful if you want to perform bulk operations that are defined in a file containing JSON documents. .sp \fBTIP:\fP .INDENT 0.0 .INDENT 3.5 \fI\%bson_json_reader_t\fP works upon JSON documents formatted in \fI\%MongoDB extended JSON\fP format. .UNINDENT .UNINDENT .SS Example .INDENT 0.0 .INDENT 3.5 .sp .EX /* * Copyright 2013 MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the \(dqLicense\(dq); * 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 \(dqAS IS\(dq 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. */ /* * This program will print each JSON document contained in the provided files * as a BSON string to STDOUT. */ #include #include #include int main (int argc, char *argv[]) { bson_json_reader_t *reader; bson_error_t error; const char *filename; bson_t doc = BSON_INITIALIZER; int i; int b; /* * Print program usage if no arguments are provided. */ if (argc == 1) { fprintf (stderr, \(dqusage: %s FILE...\en\(dq, argv[0]); return 1; } /* * Process command line arguments expecting each to be a filename. */ for (i = 1; i < argc; i++) { filename = argv[i]; /* * Open the filename provided in command line arguments. */ if (0 == strcmp (filename, \(dq\-\(dq)) { reader = bson_json_reader_new_from_fd (STDIN_FILENO, false); } else { if (!(reader = bson_json_reader_new_from_file (filename, &error))) { fprintf ( stderr, \(dqFailed to open \e\(dq%s\e\(dq: %s\en\(dq, filename, error.message); continue; } } /* * Convert each incoming document to BSON and print to stdout. */ while ((b = bson_json_reader_read (reader, &doc, &error))) { if (b < 0) { fprintf (stderr, \(dqError in json parsing:\en%s\en\(dq, error.message); abort (); } if (fwrite (bson_get_data (&doc), 1, doc.len, stdout) != doc.len) { fprintf (stderr, \(dqFailed to write to stdout, exiting.\en\(dq); exit (1); } bson_reinit (&doc); } bson_json_reader_destroy (reader); bson_destroy (&doc); } return 0; } .EE .UNINDENT .UNINDENT .SS bson_oid_t .sp BSON ObjectID Abstraction .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX #include typedef struct { uint8_t bytes[12]; } bson_oid_t; .EE .UNINDENT .UNINDENT .SS Description .sp The \fI\%bson_oid_t\fP structure contains the 12\-byte ObjectId notation defined by the \fI\%BSON ObjectID specification\fP\&. .sp ObjectId is a 12\-byte BSON type, constructed using: .INDENT 0.0 .IP \(bu 2 a 4\-byte value representing the seconds since the Unix epoch (in Big Endian). .IP \(bu 2 a 5\-byte random value. .IP \(bu 2 a 3\-byte counter (Big Endian), starting with a random value. .UNINDENT .SS String Conversion .sp You can convert an Object ID to a string using \fI\%bson_oid_to_string()\fP and back with \fI\%bson_oid_init_from_string()\fP\&. .SS Hashing .sp A \fI\%bson_oid_t\fP can be used in hashtables using the function \fI\%bson_oid_hash()\fP and \fI\%bson_oid_equal()\fP\&. .SS Comparing .sp A \fI\%bson_oid_t\fP can be compared to another using \fI\%bson_oid_compare()\fP for \fBqsort()\fP style comparing and \fI\%bson_oid_equal()\fP for direct equality. .SS Validating .sp You can validate that a string containing a hex\-encoded ObjectID is valid using the function \fI\%bson_oid_is_valid()\fP\&. .SS Example .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include int main (int argc, char *argv[]) { bson_oid_t oid; char str[25]; bson_oid_init (&oid, NULL); bson_oid_to_string (&oid, str); printf (\(dq%s\en\(dq, str); if (bson_oid_is_valid (str, sizeof str)) { bson_oid_init_from_string (&oid, str); } printf (\(dqThe UNIX time was: %u\en\(dq, (unsigned) bson_oid_get_time_t (&oid)); return 0; } .EE .UNINDENT .UNINDENT .SS bson_reader_t .sp Streaming BSON Document Reader .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX #include typedef struct _bson_reader_t bson_reader_t; bson_reader_t * bson_reader_new_from_handle (void *handle, bson_reader_read_func_t rf, bson_reader_destroy_func_t df); bson_reader_t * bson_reader_new_from_fd (int fd, bool close_on_destroy); bson_reader_t * bson_reader_new_from_file (const char *path, bson_error_t *error); bson_reader_t * bson_reader_new_from_data (const uint8_t *data, size_t length); void bson_reader_destroy (bson_reader_t *reader); .EE .UNINDENT .UNINDENT .SS Description .sp \fI\%bson_reader_t\fP is a structure used for reading a sequence of BSON documents. The sequence can come from a file\-descriptor, memory region, or custom callbacks. .SS Example .INDENT 0.0 .INDENT 3.5 .sp .EX /* * Copyright 2013 MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the \(dqLicense\(dq); * 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 \(dqAS IS\(dq 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. */ /* * This program will print each BSON document contained in the provided files * as a JSON string to STDOUT. */ #include #include int main (int argc, char *argv[]) { bson_reader_t *reader; const bson_t *b; bson_error_t error; const char *filename; char *str; int i; /* * Print program usage if no arguments are provided. */ if (argc == 1) { fprintf (stderr, \(dqusage: %s [FILE | \-]...\enUse \- for STDIN.\en\(dq, argv[0]); return 1; } /* * Process command line arguments expecting each to be a filename. */ for (i = 1; i < argc; i++) { filename = argv[i]; if (strcmp (filename, \(dq\-\(dq) == 0) { reader = bson_reader_new_from_fd (STDIN_FILENO, false); } else { if (!(reader = bson_reader_new_from_file (filename, &error))) { fprintf ( stderr, \(dqFailed to open \e\(dq%s\e\(dq: %s\en\(dq, filename, error.message); continue; } } /* * Convert each incoming document to JSON and print to stdout. */ while ((b = bson_reader_read (reader, NULL))) { str = bson_as_canonical_extended_json (b, NULL); fprintf (stdout, \(dq%s\en\(dq, str); bson_free (str); } /* * Cleanup after our reader, which closes the file descriptor. */ bson_reader_destroy (reader); } return 0; } .EE .UNINDENT .UNINDENT .SS Character and String Routines .sp We provide a small number of character and string routines to substitute for those that are not available on all platforms, and routines to make UTF\-8 character manipulation convenient. .SS bson_string_t .sp String Building Abstraction .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX #include typedef struct { char *str; uint32_t len; uint32_t alloc; } bson_string_t; .EE .UNINDENT .UNINDENT .SS Description .sp \fI\%bson_string_t\fP is an abstraction for building strings. As chunks are added to the string, allocations are performed in powers of two. .sp This API is useful if you need to build UTF\-8 encoded strings. .SS Example .INDENT 0.0 .INDENT 3.5 .sp .EX bson_string_t *str; str = bson_string_new (NULL); bson_string_append_printf (str, \(dq%d %s %f\en\(dq, 0, \(dqsome string\(dq, 0.123); printf (\(dq%s\en\(dq, str\->str); bson_string_free (str, true); .EE .UNINDENT .UNINDENT .sp \fBTIP:\fP .INDENT 0.0 .INDENT 3.5 You can call \fI\%bson_string_free()\fP with \fBfalse\fP if you would like to take ownership of \fBstr\->str\fP\&. Some APIs that do this might call \fBreturn bson_string_free (str, false);\fP after building the string. .UNINDENT .UNINDENT .SS bson_subtype_t .sp Binary Field Subtype .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX #include typedef enum { BSON_SUBTYPE_BINARY = 0x00, BSON_SUBTYPE_FUNCTION = 0x01, BSON_SUBTYPE_BINARY_DEPRECATED = 0x02, BSON_SUBTYPE_UUID_DEPRECATED = 0x03, BSON_SUBTYPE_UUID = 0x04, BSON_SUBTYPE_MD5 = 0x05, BSON_SUBTYPE_COLUMN = 0x07, BSON_SUBTYPE_SENSITIVE = 0x08, BSON_SUBTYPE_USER = 0x80, } bson_subtype_t; .EE .UNINDENT .UNINDENT .SS Description .sp This enumeration contains the various subtypes that may be used in a binary field. See \fI\%http://bsonspec.org\fP for more information. .SS Example .INDENT 0.0 .INDENT 3.5 .sp .EX bson_t doc = BSON_INITIALIZER; BSON_APPEND_BINARY (&doc, \(dqbinary\(dq, BSON_SUBTYPE_BINARY, data, data_len); .EE .UNINDENT .UNINDENT .SS bson_type_t .sp BSON Type Enumeration .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX #include typedef enum { BSON_TYPE_EOD = 0x00, BSON_TYPE_DOUBLE = 0x01, BSON_TYPE_UTF8 = 0x02, BSON_TYPE_DOCUMENT = 0x03, BSON_TYPE_ARRAY = 0x04, BSON_TYPE_BINARY = 0x05, BSON_TYPE_UNDEFINED = 0x06, BSON_TYPE_OID = 0x07, BSON_TYPE_BOOL = 0x08, BSON_TYPE_DATE_TIME = 0x09, BSON_TYPE_NULL = 0x0A, BSON_TYPE_REGEX = 0x0B, BSON_TYPE_DBPOINTER = 0x0C, BSON_TYPE_CODE = 0x0D, BSON_TYPE_SYMBOL = 0x0E, BSON_TYPE_CODEWSCOPE = 0x0F, BSON_TYPE_INT32 = 0x10, BSON_TYPE_TIMESTAMP = 0x11, BSON_TYPE_INT64 = 0x12, BSON_TYPE_DECIMAL128 = 0x13, BSON_TYPE_MAXKEY = 0x7F, BSON_TYPE_MINKEY = 0xFF, } bson_type_t; .EE .UNINDENT .UNINDENT .SS Description .sp The \fI\%bson_type_t\fP enumeration contains all of the types from the \fI\%BSON Specification\fP\&. It can be used to determine the type of a field at runtime. .SS Example .INDENT 0.0 .INDENT 3.5 .sp .EX bson_iter_t iter; if (bson_iter_init_find (&iter, doc, \(dqfoo\(dq) && (BSON_TYPE_INT32 == bson_iter_type (&iter))) { printf (\(dq\(aqfoo\(aq is an int32.\en\(dq); } .EE .UNINDENT .UNINDENT .SS bson_unichar_t .sp Unicode Character Abstraction .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX typedef uint32_t bson_unichar_t; .EE .UNINDENT .UNINDENT .SS Description .sp \fI\%bson_unichar_t\fP provides an abstraction on a single unicode character. It is the 32\-bit representation of a character. As UTF\-8 can contain multi\-byte characters, this should be used when iterating through UTF\-8 text. .SS Example .INDENT 0.0 .INDENT 3.5 .sp .EX static void print_each_char (const char *str) { bson_unichar_t c; for (; *str; str = bson_utf8_next_char (str)) { c = bson_utf8_get_char (str); printf (\(dqThe numberic value is %u.\en\(dq, (unsigned) c); } } .EE .UNINDENT .UNINDENT .SS bson_value_t .sp BSON Boxed Container Type .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX #include typedef struct _bson_value_t { bson_type_t value_type; union { bson_oid_t v_oid; int64_t v_int64; int32_t v_int32; int8_t v_int8; double v_double; bool v_bool; int64_t v_datetime; struct { uint32_t timestamp; uint32_t increment; } v_timestamp; struct { uint32_t len; char *str; } v_utf8; struct { uint32_t data_len; uint8_t *data; } v_doc; struct { uint32_t data_len; uint8_t *data; bson_subtype_t subtype; } v_binary; struct { char *regex; char *options; } v_regex; struct { char *collection; uint32_t collection_len; bson_oid_t oid; } v_dbpointer; struct { uint32_t code_len; char *code; } v_code; struct { uint32_t code_len; char *code; uint32_t scope_len; uint8_t *scope_data; } v_codewscope; struct { uint32_t len; char *symbol; } v_symbol; bson_decimal128_t v_decimal128; } value; } bson_value_t; .EE .UNINDENT .UNINDENT .SS Description .sp The \fI\%bson_value_t\fP structure is a boxed type for encapsulating a runtime determined type. .SS Example .INDENT 0.0 .INDENT 3.5 .sp .EX const bson_value_t *value; value = bson_iter_value (&iter); if (value\->value_type == BSON_TYPE_INT32) { printf (\(dq%d\en\(dq, value\->value.v_int32); } .EE .UNINDENT .UNINDENT .SS bson_visitor_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX #include typedef struct { /* run before / after descending into a document */ bool (*visit_before) (const bson_iter_t *iter, const char *key, void *data); bool (*visit_after) (const bson_iter_t *iter, const char *key, void *data); /* corrupt BSON, or unsupported type and visit_unsupported_type not set */ void (*visit_corrupt) (const bson_iter_t *iter, void *data); /* normal bson field callbacks */ bool (*visit_double) (const bson_iter_t *iter, const char *key, double v_double, void *data); bool (*visit_utf8) (const bson_iter_t *iter, const char *key, size_t v_utf8_len, const char *v_utf8, void *data); bool (*visit_document) (const bson_iter_t *iter, const char *key, const bson_t *v_document, void *data); bool (*visit_array) (const bson_iter_t *iter, const char *key, const bson_t *v_array, void *data); bool (*visit_binary) (const bson_iter_t *iter, const char *key, bson_subtype_t v_subtype, size_t v_binary_len, const uint8_t *v_binary, void *data); /* normal field with deprecated \(dqUndefined\(dq BSON type */ bool (*visit_undefined) (const bson_iter_t *iter, const char *key, void *data); bool (*visit_oid) (const bson_iter_t *iter, const char *key, const bson_oid_t *v_oid, void *data); bool (*visit_bool) (const bson_iter_t *iter, const char *key, bool v_bool, void *data); bool (*visit_date_time) (const bson_iter_t *iter, const char *key, int64_t msec_since_epoch, void *data); bool (*visit_null) (const bson_iter_t *iter, const char *key, void *data); bool (*visit_regex) (const bson_iter_t *iter, const char *key, const char *v_regex, const char *v_options, void *data); bool (*visit_dbpointer) (const bson_iter_t *iter, const char *key, size_t v_collection_len, const char *v_collection, const bson_oid_t *v_oid, void *data); bool (*visit_code) (const bson_iter_t *iter, const char *key, size_t v_code_len, const char *v_code, void *data); bool (*visit_symbol) (const bson_iter_t *iter, const char *key, size_t v_symbol_len, const char *v_symbol, void *data); bool (*visit_codewscope) (const bson_iter_t *iter, const char *key, size_t v_code_len, const char *v_code, const bson_t *v_scope, void *data); bool (*visit_int32) (const bson_iter_t *iter, const char *key, int32_t v_int32, void *data); bool (*visit_timestamp) (const bson_iter_t *iter, const char *key, uint32_t v_timestamp, uint32_t v_increment, void *data); bool (*visit_int64) (const bson_iter_t *iter, const char *key, int64_t v_int64, void *data); bool (*visit_maxkey) (const bson_iter_t *iter, const char *key, void *data); bool (*visit_minkey) (const bson_iter_t *iter, const char *key, void *data); /* if set, called instead of visit_corrupt when an apparently valid BSON * includes an unrecognized field type (reading future version of BSON) */ void (*visit_unsupported_type) (const bson_iter_t *iter, const char *key, uint32_t type_code, void *data); bool (*visit_decimal128) (const bson_iter_t *iter, const char *key, const bson_decimal128_t *v_decimal128, void *data); void *padding[7]; } bson_visitor_t bson_visitor_t; .EE .UNINDENT .UNINDENT .SS Description .sp The \fI\%bson_visitor_t\fP structure provides a series of callbacks that can be called while iterating a BSON document. This may simplify the conversion of a \fI\%bson_t\fP to a higher level language structure. .sp If the optional callback \fBvisit_unsupported_type\fP is set, it is called instead of \fBvisit_corrupt\fP in the specific case of an unrecognized field type. (Parsing is aborted in either case.) Use this callback to report an error like \(dqunrecognized type\(dq instead of simply \(dqcorrupt BSON\(dq. This future\-proofs code that may use an older version of libbson to parse future BSON formats. .SS Basic Example .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include static bool my_visit_before (const bson_iter_t *iter, const char *key, void *data) { int *count = (int *) data; (*count)++; /* returning true stops further iteration of the document */ return false; } static void count_fields (bson_t *doc) { bson_visitor_t visitor = {0}; bson_iter_t iter; int count = 0; visitor.visit_before = my_visit_before; if (bson_iter_init (&iter, doc)) { bson_iter_visit_all (&iter, &visitor, &count); } printf (\(dqFound %d fields.\en\(dq, count); } .EE .UNINDENT .UNINDENT .sp The example below demonstrates how to set your own callbacks to provide information about the location of corrupt or unsupported BSON document entries. .SS Example Corruption Check .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include typedef struct { ssize_t *err_offset; } my_state_t; static void my_visit_corrupt (const bson_iter_t *iter, void *data) { *(((my_state_t *) data)\->err_offset) = iter\->off; } static void my_visit_unsupported_type (const bson_iter_t *iter, const char *key, uint32_t type_code, void *data) { *(((my_state_t *) data)\->err_offset) = iter\->off; } static void find_error_location (bson_t *doc) { bson_visitor_t visitors = {0}; bson_iter_t iter; my_state_t state; ssize_t err_offset = \-1; visitors.visit_corrupt = my_visit_corrupt; visitors.visit_unsupported_type = my_visit_unsupported_type; /* provide additional visitors as needed based on your requirements */ state.err_offset = &err_offset; if (!bson_iter_init (&iter, doc)) { printf (\(dqCould not initialize iterator!\(dq); exit (1); } if (bson_iter_visit_all (&iter, &visitors, &state) || err_offset != \-1) { printf (\(dqFound error at offset %d.\en\(dq, err_offset); } else { printf (\(dqBSON document had no errors.\en\(dq); } } .EE .UNINDENT .UNINDENT .sp The example below demonstrates how to use a visitor to validate a BSON document\(aqs maximum depth. .SS Example Custom Validation .sp bson\-check\-depth.c .INDENT 0.0 .INDENT 3.5 .sp .EX /* Reports the maximum nested depth of a BSON document. */ #include #include #include #include #include typedef struct { uint32_t depth; uint32_t max_depth; bool valid; } check_depth_t; bool _check_depth_document (const bson_iter_t *iter, const char *key, const bson_t *v_document, void *data); static const bson_visitor_t check_depth_funcs = { NULL, NULL, NULL, NULL, NULL, _check_depth_document, _check_depth_document, NULL, }; bool _check_depth_document (const bson_iter_t *iter, const char *key, const bson_t *v_document, void *data) { check_depth_t *state = (check_depth_t *) data; bson_iter_t child; BSON_UNUSED (iter); BSON_UNUSED (key); if (!bson_iter_init (&child, v_document)) { fprintf (stderr, \(dqcorrupt\en\(dq); return true; /* cancel */ } state\->depth++; if (state\->depth > state\->max_depth) { state\->valid = false; return true; /* cancel */ } bson_iter_visit_all (&child, &check_depth_funcs, state); state\->depth\-\-; return false; /* continue */ } void check_depth (const bson_t *bson, uint32_t max_depth) { bson_iter_t iter; check_depth_t state = {0}; if (!bson_iter_init (&iter, bson)) { fprintf (stderr, \(dqcorrupt\en\(dq); } state.valid = true; state.max_depth = max_depth; _check_depth_document (&iter, NULL, bson, &state); if (!state.valid) { printf (\(dqdocument exceeds maximum depth of %\(dq PRIu32 \(dq\en\(dq, state.max_depth); } else { char *as_json = bson_as_canonical_extended_json (bson, NULL); printf (\(dqdocument %s \(dq, as_json); printf (\(dqis valid\en\(dq); bson_free (as_json); } } int main (int argc, char **argv) { bson_reader_t *bson_reader; const bson_t *bson; bool reached_eof; bson_error_t error; if (argc != 3) { fprintf (stderr, \(dqusage: %s FILE MAX_DEPTH\en\(dq, argv[0]); fprintf (stderr, \(dqChecks that the depth of the BSON contained in FILE\en\(dq); fprintf (stderr, \(dqdoes not exceed MAX_DEPTH\en\(dq); } const char *const filename = argv[1]; const int max_depth = atoi (argv[2]); bson_reader = bson_reader_new_from_file (filename, &error); if (!bson_reader) { printf (\(dqcould not read %s: %s\en\(dq, filename, error.message); return 1; } BSON_ASSERT (bson_in_range_signed (uint32_t, max_depth)); while ((bson = bson_reader_read (bson_reader, &reached_eof))) { check_depth (bson, (uint32_t) max_depth); } if (!reached_eof) { printf (\(dqerror reading BSON\en\(dq); } bson_reader_destroy (bson_reader); return 0; } .EE .UNINDENT .UNINDENT .SS bson_writer_t .sp Bulk BSON serialization Abstraction .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX #include typedef struct _bson_writer_t bson_writer_t; bson_writer_t * bson_writer_new (uint8_t **buf, size_t *buflen, size_t offset, bson_realloc_func realloc_func, void *realloc_func_ctx); void bson_writer_destroy (bson_writer_t *writer); .EE .UNINDENT .UNINDENT .SS Description .sp The \fI\%bson_writer_t\fP API provides an abstraction for serializing many BSON documents to a single memory region. The memory region may be dynamically allocated and re\-allocated as more memory is demanded. This can be useful when building network packets from a high\-level language. For example, you can serialize a Python Dictionary directly to a single buffer destined for a TCP packet. .SS Example .INDENT 0.0 .INDENT 3.5 .sp .EX #include int main (int argc, char *argv[]) { bson_writer_t *writer; uint8_t *buf = NULL; size_t buflen = 0; bson_t *doc; writer = bson_writer_new (&buf, &buflen, 0, bson_realloc_ctx, NULL); for (i = 0; i < 1000; i++) { bson_writer_begin (writer, &doc); BSON_APPEND_INT32 (&doc, \(dqi\(dq, i); bson_writer_end (writer); } bson_writer_destroy (writer); bson_free (buf); return 0; } .EE .UNINDENT .UNINDENT .SS System Clock .sp BSON Clock Abstraction .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX int64_t bson_get_monotonic_time (void); int bson_gettimeofday (struct timeval *tv); .EE .UNINDENT .UNINDENT .SS Description .sp The clock abstraction in Libbson provides a cross\-platform way to handle timeouts within the BSON library. It abstracts the differences in implementations of \fBgettimeofday()\fP as well as providing a monotonic (incrementing only) clock in microseconds. .SS Memory Management .sp BSON Memory Abstraction. .SS Description .sp Libbson contains a lightweight memory abstraction to make portability to new platforms easier. Additionally, it helps us integrate with interesting higher\-level languages. One caveat, however, is that Libbson is not designed to deal with Out of Memory (OOM) situations. Doing so requires extreme diligence throughout the application stack that has rarely been implemented correctly. This may change in the future. As it stands now, Libbson will \fBabort()\fP under OOM situations. .sp To aid in language binding integration, Libbson allows for setting a custom memory allocator via \fI\%bson_mem_set_vtable()\fP\&. This allocation may be reversed via \fI\%bson_mem_restore_vtable()\fP\&. .SS Libbson Versioning .sp Versioning Macros and Functions .SS Macros .sp The following preprocessor macros can be used to perform various checks based on the version of the library you are compiling against. This may be useful if you only want to enable a feature on a certain version of the library. .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .EX #define BSON_CHECK_VERSION(major, minor, micro) #define BSON_MAJOR_VERSION (1) #define BSON_MINOR_VERSION (4) #define BSON_MICRO_VERSION (1) #define BSON_VERSION_S \(dq1.4.1\(dq #define BSON_VERSION_HEX \e (BSON_MAJOR_VERSION << 24 | BSON_MINOR_VERSION << 16 | \e BSON_MICRO_VERSION << 8) .EE .UNINDENT .UNINDENT .sp Only compile a block on Libbson 1.1.0 and newer. .INDENT 0.0 .INDENT 3.5 .sp .EX #if BSON_CHECK_VERSION(1, 1, 0) static void do_something (void) { } #endif .EE .UNINDENT .UNINDENT .SH AUTHOR MongoDB, Inc .SH COPYRIGHT 2017-present, MongoDB, Inc .\" Generated by docutils manpage writer. .