<page xmlns="http://projectmallard.org/1.0/"
      type="topic"
      id="parsing">
  <info><link type="guide" xref="index#intro"/></info>
  <title>Parsing and Iterating BSON Documents</title>

  <p>BSON documents are lazily parsed as necessary. To begin parsing a BSON document, use one of the provided Libbson functions to create a new <link xref="bson_t">bson_t</link> from existing data such as <link xref="bson_new_from_data">bson_new_from_data()</link>. This will make a copy of the data so that additional mutations may occur to the BSON document.</p>
  <note style="tip"><p>If you only want to parse a BSON document and have no need to mutate it, you may use <link xref="bson_init_static">bson_init_static()</link> to avoid making a copy of the data.</p></note>

  <example><code mime="text/x-csrc"><![CDATA[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);]]></code></example>

  <p>Only two checks are performed when creating a new <link xref="bson_t">bson_t</link> 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 <code>\0</code> byte.</p>
  <p>To parse the document further we use a <link xref="bson_iter_t">bson_iter_t</link> to iterate the elements within the document. Let's print all of the field names in the document.</p>

  <example><code mime="text/x-csrc"><![CDATA[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);
}]]></code></example>

  <p>Converting a document to JSON uses a <link xref="bson_iter_t">bson_iter_t</link> and <link xref="bson_visitor_t">bson_visitor_t</link> to iterate all fields of a BSON document recursively and generate a UTF-8 encoded JSON string.</p>

  <example><code mime="text/x-csrc"><![CDATA[bson_t *b;
char *json;

if ((b = bson_new_from_data (my_data, my_data_len))) {
   if ((json = bson_as_json (b, NULL))) {
      printf ("%s\n", json);
      bson_free (json);
   }
   bson_destroy (b);
}]]></code></example>

  <section id="recursing">
    <title>Recursing into Sub-Documents</title>
    <p>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.</p>
    <example><code mime="text/x-csrc"><![CDATA[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));
   }
}]]></code></example>
  </section>

  <section id="dotkey">
    <title>Finding Fields using Dot Notation</title>
    <p>Using the <link xref="bson_iter_recurse">bson_iter_recurse()</link> function exemplified above, <link xref="bson_iter_find_descendant">bson_iter_find_descendant()</link> can find a field for you using the MongoDB style path notation such as "foo.bar.0.baz".</p>
    <p>Let's create a document like <code mime="text/x-javascript">{"foo": {"bar": [{"baz: 1}]}}</code> and locate the <code>"baz"</code> field.</p>
    <example><code mime="text/x-csrc"><![CDATA[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);]]></code></example>
  </section>

  <section id="validating">
    <title>Validating a BSON Document</title>
    <p>If all you want to do is validate that a BSON document is valid, you can use <link xref="bson_validate">bson_validate()</link>.</p>
    <example><code mime="text/x-csrc"><![CDATA[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);
}]]></code></example>
    <p>See the <link xref="bson_validate">bson_validate()</link> documentation for more information and examples.</p>
  </section>

</page>
