1BSON_TUTORIAL(3)                    Libbson                   BSON_TUTORIAL(3)
2
3
4

NAME

6       bson_tutorial - Tutorial
7

USING LIBBSON IN YOUR C PROGRAM

9   Include bson.h
10       All  libbson's  functions  and  types are available in one header file.
11       Simply include bson.h: hello_bson.c.INDENT 0.0
12
13          #include <stdio.h>
14          #include <bson/bson.h>
15
16          int
17          main (int argc, const char **argv)
18          {
19             bson_t *b;
20             char *j;
21
22             b = BCON_NEW ("hello", BCON_UTF8 ("bson!"));
23             j = bson_as_canonical_extended_json (b, NULL);
24             printf ("%s\n", j);
25
26             bson_free (j);
27             bson_destroy (b);
28
29             return 0;
30          }
31
32
33   CMake
34       The libbson installation includes a CMake config-file package,  so  you
35       can  use  CMake's  find_package  command  to  find libbson's header and
36       library paths and link to libbson: CMakeLists.txt.INDENT 0.0
37
38          # Specify the minimum version you require.
39          find_package (libbson-1.0 1.7 REQUIRED)
40
41          message ("--   libbson found version \"${BSON_VERSION}\"")
42          message ("--   libbson include path \"${BSON_INCLUDE_DIRS}\"")
43          message ("--   libbson libraries \"${BSON_LIBRARIES}\"")
44
45          # The "hello_bson.c" sample program is shared among four tests.
46          add_executable (hello_bson ../../hello_bson.c)
47          target_include_directories (hello_bson PRIVATE ${BSON_INCLUDE_DIRS})
48          target_link_libraries (hello_bson PRIVATE ${BSON_LIBRARIES})
49          target_compile_definitions (hello_bson PRIVATE ${BSON_DEFINITIONS})
50
51
52By default, libbson is dynamically linked. You can use  libbson  as  a  static
53library  instead:  Use the included libbson-static-1.0 config-file package and
54(on Unix) link to pthread:
55
56          # Specify the minimum version you require.
57          find_package (libbson-static-1.0 1.7 REQUIRED)
58
59          message ("--   libbson-static found version \"${BSON_STATIC_VERSION}\"")
60          message ("--   libbson-static include path \"${BSON_STATIC_INCLUDE_DIRS}\"")
61          message ("--   libbson-static libraries \"${BSON_STATIC_LIBRARIES}\"")
62
63          # The "hello_bson.c" sample program is shared among four tests.
64          add_executable (hello_bson ../../hello_bson.c)
65          target_include_directories (hello_bson PRIVATE ${BSON_STATIC_INCLUDE_DIRS})
66          target_link_libraries (hello_bson PRIVATE ${BSON_STATIC_LIBRARIES})
67          target_compile_definitions (hello_bson PRIVATE ${BSON_STATIC_DEFINITIONS})
68
69
70   pkg-config
71       If you're not using CMake, use pkg-config on the command  line  to  set
72       header and library paths:
73
74          gcc -o hello_bson hello_bson.c $(pkg-config --libs --cflags libbson-1.0)
75
76
77       Or to statically link to libbson:
78
79          gcc -o hello_bson hello_bson.c $(pkg-config --libs --cflags libbson-static-1.0)
80
81

CREATING A BSON DOCUMENT

83   The bson_t structure
84       BSON  documents  are created using the bson_t structure. This structure
85       encapsulates the necessary logic for encoding using the BSON Specifica‐
86       tion.  At the core, bson_t is a buffer manager and set of encoding rou‐
87       tines.
88
89       TIP:
90          BSON documents can live on the stack or the heap based on  the  per‐
91          formance needs or preference of the consumer.
92
93       Let's  start  by  creating  a  new BSON document on the stack. Whenever
94       using libbson, make sure you #include <bson/bson.h>.
95
96          bson_t b;
97
98          bson_init (&b);
99
100       This creates an empty document. In JSON, this would be the same as {}.
101
102       We can now proceed to adding items to the BSON document. A  variety  of
103       functions  prefixed  with bson_append_ can be used based on the type of
104       field you want to append. Let's append a UTF-8 encoded string.
105
106          bson_append_utf8 (&b, "key", -1, "value", -1);
107
108       Notice the two -1 parameters. The first indicates that  the  length  of
109       key  in  bytes  should  be  determined with strlen(). Alternatively, we
110       could have passed the number 3. The same goes for the  second  -1,  but
111       for value.
112
113       Libbson  provides  macros  to  make this less tedious when using string
114       literals. The following two appends are identical.
115
116          bson_append_utf8 (&b, "key", -1, "value", -1);
117          BSON_APPEND_UTF8 (&b, "key", "value");
118
119       Now let's take a look at an example that adds  a  few  different  field
120       types to a BSON document.
121
122          bson_t b = BSON_INITIALIZER;
123
124          BSON_APPEND_INT32 (&b, "a", 1);
125          BSON_APPEND_UTF8 (&b, "hello", "world");
126          BSON_APPEND_BOOL (&b, "bool", true);
127
128       Notice that we omitted the call to bson_init(). By specifying BSON_INI‐
129       TIALIZER we can remove the need to initialize the structure to  a  base
130       state.
131
132   Sub-Documents and Sub-Arrays
133       To simplify the creation of sub-documents and arrays, bson_append_docu‐
134       ment_begin() and bson_append_array_begin() exist. These can be used  to
135       build  a  sub-document  using the parent documents memory region as the
136       destination buffer.
137
138          bson_t parent;
139          bson_t child;
140          char *str;
141
142          bson_init (&parent);
143          bson_append_document_begin (&parent, "foo", 3, &child);
144          bson_append_int32 (&child, "baz", 3, 1);
145          bson_append_document_end (&parent, &child);
146
147          str = bson_as_canonical_extended_json (&parent, NULL);
148          printf ("%s\n", str);
149          bson_free (str);
150
151          bson_destroy (&parent);
152
153          { "foo" : { "baz" : 1 } }
154
155   Simplified BSON C Object Notation
156       Creating BSON documents by hand can  be  tedious  and  time  consuming.
157       BCON, or BSON C Object Notation, was added to allow for the creation of
158       BSON documents in a format that looks closer to the destination format.
159
160       The following example shows the use of BCON.  Notice  that  values  for
161       fields  are  wrapped  in  the BCON_* macros. These are required for the
162       variadic processor to determine the parameter type.
163
164          bson_t *doc;
165
166          doc = BCON_NEW ("foo",
167                          "{",
168                          "int",
169                          BCON_INT32 (1),
170                          "array",
171                          "[",
172                          BCON_INT32 (100),
173                          "{",
174                          "sub",
175                          BCON_UTF8 ("value"),
176                          "}",
177                          "]",
178                          "}");
179
180       Creates the following document
181
182          { "foo" : { "int" : 1, "array" : [ 100, { "sub" : "value" } ] } }
183

HANDLING ERRORS

185   Description
186       Many libbson functions report errors by returning NULL or -1 and  fill‐
187       ing  out a bson_error_t structure with an error domain, error code, and
188       message.
189
190       · error.domain names the subsystem that generated the error.
191
192       · error.code is a domain-specific error type.
193
194       · error.message describes the error.
195
196       Some error codes overlap with others; always check both the domain  and
197       code to determine the type of error.
198
199
200
201
202
203┌──────────────────┬────────────────────────────────────┬────────────────────────────────┐
204BSON_ERROR_JSON   BSON_JSON_ERROR_READ_COR‐          bson_json_reader_t             
205│                  │ RUPT_JS                            │ tried   to    parse            │
206│                  │ BSON_JSON_ERROR_READ_INVALID_PARAM │ invalid     MongoDB            │
207│                  │ BSON_JSON_ERROR_READ_CB_FAIL‐      │ Extended      JSON.            │
208│                  │ URE                                │ Tried  to  parse  a            │
209│                  │                                    │ valid JSON document            │
210│                  │                                    │ that  is invalid as            │
211│                  │                                    │ MongoDBExtended                │
212│                  │                                    │ JSON.   An internal            │
213│                  │                                    │ callback    failure            │
214│                  │                                    │ during  JSON  pars‐            │
215│                  │                                    │ ing.                           │
216├──────────────────┼────────────────────────────────────┼────────────────────────────────┤
217BSON_ERROR_READER BSON_ERROR_READER_BADFD            bson_json_reader_new_from_file 
218│                  │                                    │ could  not open the            │
219│                  │                                    │ file.                          │
220└──────────────────┴────────────────────────────────────┴────────────────────────────────┘
221

OBJECTIDS

223       Libbson provides a simple way to generate ObjectIDs. It can be used  in
224       a  single-threaded  or multi-threaded manner depending on your require‐
225       ments.
226
227       The bson_oid_t structure represents an ObjectID in  MongoDB.  It  is  a
228       96-bit  identifier  that  includes various information about the system
229       generating the OID.
230
231   Composition
232       · 4 bytes : The UNIX timestamp in big-endian format.
233
234       · 3 bytes : A hash of the hostname.
235
236       · 2 bytes : The pid_t of the current process. Alternatively the task-id
237         if configured.
238
239       · 3  bytes  :  A  24-bit  monotonic counter incrementing from rand() in
240         big-endian.
241
242   Sorting ObjectIDs
243       The typical way to sort in C is using qsort(). Therefore, Libbson  pro‐
244       vides  a qsort() compatible callback function named bson_oid_compare().
245       It returns less than 1, greater than 1, or 0 depending on the  equality
246       of two bson_oid_t structures.
247
248   Comparing Object IDs
249       If  you  simply want to compare two bson_oid_t structures for equality,
250       use bson_oid_equal().
251
252   Generating
253       To generate a bson_oid_t, you may use the following.
254
255          bson_oid_t oid;
256
257          bson_oid_init (&oid, NULL);
258
259   Parsing ObjectID Strings
260       You can also parse a string containing a bson_oid_t. The  input  string
261       MUST be 24 characters or more in length.
262
263          bson_oid_t oid;
264
265          bson_oid_init_from_string (&oid, "123456789012345678901234");
266
267       If  you  need to parse may bson_oid_t in a tight loop and can guarantee
268       the data is safe, you might consider using the inline variant. It  will
269       be  inlined  into  your code and reduce the need for a foreign function
270       call.
271
272          bson_oid_t oid;
273
274          bson_oid_init_from_string_unsafe (&oid, "123456789012345678901234");
275
276   Hashing ObjectIDs
277       If you need to store items in a hashtable, you  may  want  to  use  the
278       bson_oid_t  as  the key. Libbson provides a hash function for just this
279       purpose. It is based on DJB hash.
280
281          unsigned hash;
282
283          hash = bson_oid_hash (oid);
284
285   Fetching ObjectID Creation Time
286       You can easily fetch the time that a  bson_oid_t  was  generated  using
287       bson_oid_get_time_t().
288
289          time_t t;
290
291          t = bson_oid_get_time_t (oid);
292          printf ("The OID was generated at %u\n", (unsigned) t);
293

PARSING AND ITERATING BSON DOCUMENTS

295   Parsing
296       BSON  documents are lazily parsed as necessary. To begin parsing a BSON
297       document, use one of the provided Libbson functions  to  create  a  new
298       bson_t  from existing data such as bson_new_from_data(). This will make
299       a copy of the data so that additional mutations may occur to  the  BSON
300       document.
301
302       TIP:
303          If you only want to parse a BSON document and have no need to mutate
304          it, you may use bson_init_static() to avoid making  a  copy  of  the
305          data.
306
307          bson_t *b;
308
309          b = bson_new_from_data (my_data, my_data_len);
310          if (!b) {
311             fprintf (stderr, "The specified length embedded in <my_data> did not match "
312                              "<my_data_len>\n");
313             return;
314          }
315
316          bson_destroy (b);
317
318       Only two checks are performed when creating a new bson_t from an exist‐
319       ing buffer. First, the document must  begin  with  the  buffer  length,
320       matching what was expected by the caller. Second, the document must end
321       with the expected trailing \0 byte.
322
323       To parse the document further we use a bson_iter_t to iterate the  ele‐
324       ments  within  the  document. Let's print all of the field names in the
325       document.
326
327          bson_t *b;
328          bson_iter_t iter;
329
330          if ((b = bson_new_from_data (my_data, my_data_len))) {
331             if (bson_iter_init (&iter, b)) {
332                while (bson_iter_next (&iter)) {
333                   printf ("Found element key: \"%s\"\n", bson_iter_key (&iter));
334                }
335             }
336             bson_destroy (b);
337          }
338
339       Converting a document to JSON uses a bson_iter_t and bson_visitor_t  to
340       iterate  all fields of a BSON document recursively and generate a UTF-8
341       encoded JSON string.
342
343          bson_t *b;
344          char *json;
345
346          if ((b = bson_new_from_data (my_data, my_data_len))) {
347             if ((json = bson_as_canonical_extended_json (b, NULL))) {
348                printf ("%s\n", json);
349                bson_free (json);
350             }
351             bson_destroy (b);
352          }
353
354   Recursing into Sub-Documents
355       Libbson provides convenient sub-iterators to dive down into a sub-docu‐
356       ment  or sub-array. Below is an example that will dive into a sub-docu‐
357       ment named "foo" and print it's field names.
358
359          bson_iter_t iter;
360          bson_iter_t child;
361          char *json;
362
363          if (bson_iter_init_find (&iter, doc, "foo") &&
364              BSON_ITER_HOLDS_DOCUMENT (&iter) && bson_iter_recurse (&iter, &child)) {
365             while (bson_iter_next (&child)) {
366                printf ("Found sub-key of \"foo\" named \"%s\"\n",
367                        bson_iter_key (&child));
368             }
369          }
370
371   Finding Fields using Dot Notation
372       Using   the    bson_iter_recurse()    function    exemplified    above,
373       bson_iter_find_descendant()  can find a field for you using the MongoDB
374       style path notation such as "foo.bar.0.baz".
375
376       Let's create a document like {"foo": {"bar": [{"baz: 1}]}}  and  locate
377       the "baz" field.
378
379          bson_t *b;
380          bson_iter_t iter;
381          bson_iter_t baz;
382
383          b =
384             BCON_NEW ("foo", "{", "bar", "[", "{", "baz", BCON_INT32 (1), "}", "]", "}");
385
386          if (bson_iter_init (&iter, b) &&
387              bson_iter_find_descendant (&iter, "foo.bar.0.baz", &baz) &&
388              BSON_ITER_HOLDS_INT32 (&baz)) {
389             printf ("baz = %d\n", bson_iter_int32 (&baz));
390          }
391
392          bson_destroy (b);
393
394   Validating a BSON Document
395       If  all  you  want to do is validate that a BSON document is valid, you
396       can use bson_validate().
397
398          size_t err_offset;
399
400          if (!bson_validate (doc, BSON_VALIDATE_NONE, &err_offset)) {
401             fprintf (stderr,
402                      "The document failed to validate at offset: %u\n",
403                      (unsigned) err_offset);
404          }
405
406       See the bson_validate() documentation for more  information  and  exam‐
407       ples.
408

UTF-8

410   Encoding
411       Libbson  expects  that  you are always working with UTF-8 encoded text.
412       Anything else is invalid API use.
413
414       If you should need to walk through UTF-8 sequences,  you  can  use  the
415       various UTF-8 helper functions distributed with Libbson.
416
417   Validating a UTF-8 Sequence
418       To  validate  the string contained in my_string, use the following. You
419       may pass -1 for the string length if you know the string is NULL-termi‐
420       nated.
421
422          if (!bson_utf8_validate (my_string, -1, false)) {
423             printf ("Validation failed.\n");
424          }
425
426       If  my_string  has  NULL  bytes within the string, you must provide the
427       string length. Use the following format. Notice the  true  at  the  end
428       indicating \0 is allowed.
429
430          if (!bson_utf8_validate (my_string, my_string_len, true)) {
431             printf ("Validation failed.\n");
432          }
433
434       For more information see the API reference for bson_utf8_validate().
435

AUTHOR

437       MongoDB, Inc
438
440       2017-present, MongoDB, Inc
441
442
443
444
4451.13.1                           Jan 24, 2019                 BSON_TUTORIAL(3)
Impressum