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})
the included 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       │
       │                  │ BSON_JSON_ERROR_READ_INVALID_PARAM │ to 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