Provided by: libbson-doc_1.9.2-1_all bug

NAME

       bson_tutorial - Tutorial

USING LIBBSON IN YOUR C PROGRAM

   Include bson.h
       All   libbson's   functions  and  types  are  available  in  one  header  file.  Simply  include  bson.h:
       hello_bson.c.INDENT 0.0

          #include <stdio.h>
          #include <bson.h>

          int
          main (int argc, const char **argv)
          {
             bson_t *b;
             char *j;

             b = BCON_NEW ("hello", BCON_UTF8 ("bson!"));
             j = bson_as_canonical_extended_json (b, NULL);
             printf ("%s\n", j);

             bson_free (j);
             bson_destroy (b);

             return 0;
          }

   CMake
       The libbson installation includes a CMake config-file  package,  so  you  can  use  CMake's  find_package
       command to find libbson's header and library paths and link to libbson: CMakeLists.txt.INDENT 0.0

          # Specify the minimum version you require.
          find_package (libbson-1.0 1.7 REQUIRED)

          message ("--   libbson found version \"${BSON_VERSION}\"")
          message ("--   libbson include path \"${BSON_INCLUDE_DIRS}\"")
          message ("--   libbson libraries \"${BSON_LIBRARIES}\"")

          # The "hello_bson.c" sample program is shared among four tests.
          add_executable (hello_bson ../../hello_bson.c)
          target_include_directories (hello_bson PRIVATE ${BSON_INCLUDE_DIRS})
          target_link_libraries (hello_bson PRIVATE ${BSON_LIBRARIES})
          target_compile_definitions (hello_bson PRIVATE ${BSON_DEFINITIONS})
libbson-static-1.0 config-file package and (on Unix) link to pthread:

          # Specify the minimum version you require.
          find_package (libbson-static-1.0 1.7 REQUIRED)

          message ("--   libbson-static found version \"${BSON_STATIC_VERSION}\"")
          message ("--   libbson-static include path \"${BSON_STATIC_INCLUDE_DIRS}\"")
          message ("--   libbson-static libraries \"${BSON_STATIC_LIBRARIES}\"")

          # The "hello_bson.c" sample program is shared among four tests.
          add_executable (hello_bson ../../hello_bson.c)
          target_include_directories (hello_bson PRIVATE ${BSON_STATIC_INCLUDE_DIRS})
          target_link_libraries (hello_bson PRIVATE ${BSON_STATIC_LIBRARIES})
          target_compile_definitions (hello_bson PRIVATE ${BSON_STATIC_DEFINITIONS})

   pkg-config
       If you're not using CMake, use pkg-config on the command line to set header and library paths:

          gcc -o hello_bson hello_bson.c $(pkg-config --libs --cflags libbson-1.0)

       Or to statically link to libbson:

          gcc -o hello_bson hello_bson.c $(pkg-config --libs --cflags libbson-static-1.0)

CREATING A BSON DOCUMENT

   The bson_t structure
       BSON documents are created using the bson_t structure. This structure encapsulates  the  necessary  logic
       for  encoding  using  the BSON Specification. At the core, bson_t is a buffer manager and set of encoding
       routines.

       TIP:
          BSON documents can live on the stack or the heap based on the performance needs or preference  of  the
          consumer.

       Let's  start by creating a new BSON document on the stack. Whenever using libbson, make sure you #include
       <bson.h>.

          bson_t b;

          bson_init (&b);

       This creates an empty document. In JSON, this would be the same as {}.

       We can now proceed to  adding  items  to  the  BSON  document.  A  variety  of  functions  prefixed  with
       bson_append_  can  be  used  based  on the type of field you want to append. Let's append a UTF-8 encoded
       string.

          bson_append_utf8 (&b, "key", -1, "value", -1);

       Notice the two -1 parameters. The first indicates that the length of key in bytes  should  be  determined
       with strlen(). Alternatively, we could have passed the number 3. The same goes for the second -1, but for
       value.

       Libbson provides macros to make this less tedious when using string literals. The following  two  appends
       are identical.

          bson_append_utf8 (&b, "key", -1, "value", -1);
          BSON_APPEND_UTF8 (&b, "key", "value");

       Now let's take a look at an example that adds a few different field types to a BSON document.

          bson_t b = BSON_INITIALIZER;

          BSON_APPEND_INT32 (&b, "a", 1);
          BSON_APPEND_UTF8 (&b, "hello", "world");
          BSON_APPEND_BOOL (&b, "bool", true);

       Notice  that we omitted the call to bson_init(). By specifying BSON_INITIALIZER we can remove the need to
       initialize the structure to a base state.

   Sub-Documents and Sub-Arrays
       To   simplify   the   creation   of   sub-documents   and   arrays,   bson_append_document_begin()    and
       bson_append_array_begin()  exist.  These  can  be used to build a sub-document using the parent documents
       memory region as the destination buffer.

          bson_t parent;
          bson_t child;
          char *str;

          bson_init (&parent);
          bson_append_document_begin (&parent, "foo", 3, &child);
          bson_append_int32 (&child, "baz", 3, 1);
          bson_append_document_end (&parent, &child);

          str = bson_as_canonical_extended_json (&parent, NULL);
          printf ("%s\n", str);
          bson_free (str);

          bson_destroy (&parent);

          { "foo" : { "baz" : 1 } }

   Simplified BSON C Object Notation
       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.

       The following example shows the use of BCON. Notice that values for fields  are  wrapped  in  the  BCON_*
       macros. These are required for the variadic processor to determine the parameter type.

          bson_t *doc;

          doc = BCON_NEW ("foo",
                          "{",
                          "int",
                          BCON_INT32 (1),
                          "array",
                          "[",
                          BCON_INT32 (100),
                          "{",
                          "sub",
                          BCON_UTF8 ("value"),
                          "}",
                          "]",
                          "}");

       Creates the following document

          { "foo" : { "int" : 1, "array" : [ 100, { "sub" : "value" } ] } }

HANDLING ERRORS

   Description
       Many  libbson  functions  report  errors by returning NULL or -1 and filling out a bson_error_t structure
       with an error domain, error code, and message.

       • error.domain names the subsystem that generated the error.

       • error.code is a domain-specific error type.

       • error.message describes the error.

       Some error codes overlap with others; always check both the domain and code  to  determine  the  type  of
       error.

               ┌──────────────────┬────────────────────────────────────┬────────────────────────────────┐
               │BSON_ERROR_JSONBSON_JSON_ERROR_READ_CORRUPT_JSbson_json_reader_t tried  to   │
               │                  │ BSON_JSON_ERROR_READ_INVALID_PARAM │ parse     invalid    MongoDB   │
               │                  │ BSON_JSON_ERROR_READ_CB_FAILURE    │ Extended  JSON.   Tried   to   │
               │                  │                                    │ parse  a valid JSON document   │
               │                  │                                    │ that    is    invalid     as   │
               │                  │                                    │ MongoDBExtended   JSON.   An   │
               │                  │                                    │ internal  callback   failure   │
               │                  │                                    │ during JSON parsing.           │
               ├──────────────────┼────────────────────────────────────┼────────────────────────────────┤
               │BSON_ERROR_READERBSON_ERROR_READER_BADFDbson_json_reader_new_from_file │
               │                  │                                    │ could not open the file.       │
               └──────────────────┴────────────────────────────────────┴────────────────────────────────┘

OBJECTIDS

       Libbson provides  a  simple  way  to  generate  ObjectIDs.  It  can  be  used  in  a  single-threaded  or
       multi-threaded manner depending on your requirements.

       The  bson_oid_t  structure  represents  an  ObjectID  in MongoDB. It is a 96-bit identifier that includes
       various information about the system generating the OID.

   Composition
       • 4 bytes : The UNIX timestamp in big-endian format.

       • 3 bytes : The first 3 bytes of MD5(hostname).

       • 2 bytes : The pid_t of the current process. Alternatively the task-id if configured.

       • 3 bytes : A 24-bit monotonic counter incrementing from rand() in big-endian.

   Sorting ObjectIDs
       The typical way to sort in C is using qsort(). Therefore, Libbson provides a qsort() compatible  callback
       function named bson_oid_compare(). It returns less than 1, greater than 1, or 0 depending on the equality
       of two bson_oid_t structures.

   Comparing Object IDs
       If you simply want to compare two bson_oid_t structures for equality, use bson_oid_equal().

   Generating
       To generate a bson_oid_t, you may use the following.

          bson_oid_t oid;

          bson_oid_init (&oid, NULL);

   Parsing ObjectID Strings
       You can also parse a string containing a bson_oid_t. The input string MUST be 24 characters  or  more  in
       length.

          bson_oid_t oid;

          bson_oid_init_from_string (&oid, "123456789012345678901234");

       If  you  need  to  parse  may  bson_oid_t  in  a tight loop and can guarantee the data is safe, you might
       consider using the inline variant. It will be inlined into your code and reduce the need  for  a  foreign
       function call.

          bson_oid_t oid;

          bson_oid_init_from_string_unsafe (&oid, "123456789012345678901234");

   Hashing ObjectIDs
       If  you  need  to  store  items  in  a  hashtable, you may want to use the bson_oid_t as the key. Libbson
       provides a hash function for just this purpose. It is based on DJB hash.

          unsigned hash;

          hash = bson_oid_hash (oid);

   Fetching ObjectID Creation Time
       You can easily fetch the time that a bson_oid_t was generated using bson_oid_get_time_t().

          time_t t;

          t = bson_oid_get_time_t (oid);
          printf ("The OID was generated at %u\n", (unsigned) t);

PARSING AND ITERATING BSON DOCUMENTS

   Parsing
       BSON documents are lazily parsed as necessary. To begin parsing a BSON document, use one of the  provided
       Libbson  functions to create a new bson_t from existing data such as bson_new_from_data(). This will make
       a copy of the data so that additional mutations may occur to the BSON document.

       TIP:
          If  you  only  want  to  parse  a  BSON  document  and  have  no  need  to  mutate  it,  you  may  use
          bson_init_static() to avoid making a copy of the data.

          bson_t *b;

          b = bson_new_from_data (my_data, my_data_len);
          if (!b) {
             fprintf (stderr, "The specified length embedded in <my_data> did not match "
                              "<my_data_len>\n");
             return;
          }

          bson_destroy (b);

       Only  two  checks  are  performed when creating a new bson_t 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 \0 byte.

       To  parse  the  document  further we use a bson_iter_t to iterate the elements within the document. Let's
       print all of the field names in the document.

          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 ("Found element key: \"%s\"\n", bson_iter_key (&iter));
                }
             }
             bson_destroy (b);
          }

       Converting a document to JSON uses a bson_iter_t and bson_visitor_t to  iterate  all  fields  of  a  BSON
       document recursively and generate a UTF-8 encoded JSON string.

          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 ("%s\n", json);
                bson_free (json);
             }
             bson_destroy (b);
          }

   Recursing into Sub-Documents
       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 "foo" and print it's field names.

          bson_iter_t iter;
          bson_iter_t *child;
          char *json;

          if (bson_iter_init_find (&iter, doc, "foo") &&
              BSON_ITER_HOLDS_DOCUMENT (&iter) && bson_iter_recurse (&iter, &child)) {
             while (bson_iter_next (&child)) {
                printf ("Found sub-key of \"foo\" named \"%s\"\n",
                        bson_iter_key (&child));
             }
          }

   Finding Fields using Dot Notation
       Using the bson_iter_recurse() function exemplified above, bson_iter_find_descendant() can  find  a  field
       for you using the MongoDB style path notation such as "foo.bar.0.baz".

       Let's create a document like {"foo": {"bar": [{"baz: 1}]}} and locate the "baz" field.

          bson_t *b;
          bson_iter_t iter;
          bson_iter_t baz;

          b =
             BCON_NEW ("foo", "{", "bar", "[", "{", "baz", BCON_INT32 (1), "}", "]", "}");

          if (bson_iter_init (&iter, b) &&
              bson_iter_find_descendant (&iter, "foo.bar.0.baz", &baz) &&
              BSON_ITER_HOLDS_INT32 (&baz)) {
             printf ("baz = %d\n", bson_iter_int32 (&baz));
          }

          bson_destroy (b);

   Validating a BSON Document
       If all you want to do is validate that a BSON document is valid, you can use bson_validate().

          size_t err_offset;

          if (!bson_validate (doc, BSON_VALIDATE_NONE, &err_offset)) {
             fprintf (stderr,
                      "The document failed to validate at offset: %u\n",
                      (unsigned) err_offset);
          }

       See the bson_validate() documentation for more information and examples.

UTF-8

   Encoding
       Libbson expects that you are always working with UTF-8 encoded text. Anything else is invalid API use.

       If  you  should  need  to  walk  through  UTF-8 sequences, you can use the various UTF-8 helper functions
       distributed with Libbson.

   Validating a UTF-8 Sequence
       To validate the string contained in my_string, use the following. You may pass -1 for the  string  length
       if you know the string is NULL-terminated.

          if (!bson_utf8_validate (my_string, -1, false)) {
             printf ("Validation failed.\n");
          }

       If  my_string  has  NULL  bytes  within the string, you must provide the string length. Use the following
       format. Notice the true at the end indicating \0 is allowed.

          if (!bson_utf8_validate (my_string, my_string_len, true)) {
             printf ("Validation failed.\n");
          }

       For more information see the API reference for bson_utf8_validate().

AUTHOR

       MongoDB, Inc

COPYRIGHT

       2018, MongoDB, Inc