Skip to content

CDRIVER-504 add bson_array_builder_t #1344

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/libbson/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ if (ENABLE_EXAMPLES)
add_example (bson-validate examples/bson-validate.c)
add_example (json-to-bson examples/json-to-bson.c)
add_example (bson-check-depth examples/bson-check-depth.c)
add_example (creating examples/creating.c)
endif () # ENABLE_EXAMPLES

set (BSON_HEADER_INSTALL_DIR
Expand Down
1 change: 1 addition & 0 deletions src/libbson/doc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ API Reference
:maxdepth: 2

bson_t
bson_array_builder_t
bson_context_t
bson_decimal128_t
bson_error_t
Expand Down
4 changes: 4 additions & 0 deletions src/libbson/doc/bson_append_array.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ Returns
-------

Returns ``true`` if the operation was applied successfully. The function fails if appending the array grows ``bson`` larger than INT32_MAX.

.. seealso::

| :symbol:`bson_array_builder_t`
6 changes: 6 additions & 0 deletions src/libbson/doc/bson_append_array_begin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,14 @@ The :symbol:`bson_append_array_begin()` function shall begin appending an array

For generating array element keys, see :symbol:`bson_uint32_to_string`.

Consider using :symbol:`bson_array_builder_t` to append an array without needing to generate array element keys.

Returns
-------

Returns ``true`` if the operation was applied successfully. The function will fail if appending the array grows ``bson`` larger than INT32_MAX.

.. seealso::

| :symbol:`bson_array_builder_t`

4 changes: 4 additions & 0 deletions src/libbson/doc/bson_append_array_end.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ Returns
-------

Returns ``true`` if successful.

.. seealso::

| :symbol:`bson_array_builder_t`
212 changes: 212 additions & 0 deletions src/libbson/doc/bson_array_builder_t.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
:man_page: bson_array_builder_t

bson_array_builder_t
====================

.. code-block:: c

typedef struct _bson_array_builder_t bson_array_builder_t;

``bson_array_builder_t`` may be used to build BSON arrays. ``bson_array_builder_t`` internally tracks and uses the array index as a key ("0", "1", "2", ...) when appending elements.

Appending an array value
------------------------

.. code-block:: c

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) \
bson_append_array_builder_begin (b, key, (int) strlen (key), child)

``bson_append_array_builder_begin`` may be used to append an array as a value. Example:

.. literalinclude:: ../examples/creating.c
:language: c
:start-after: // bson_array_builder_t example ... begin
:end-before: // bson_array_builder_t example ... end
:dedent: 6

Creating a top-level array
--------------------------

.. code-block:: c

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);

``bson_array_builder_new`` and ``bson_array_builder_build`` may be used to build a top-level BSON array. ``bson_array_builder_build`` initializes and moves BSON data to ``out``. The ``bson_array_builder_t`` may be reused and will start appending a new array at index "0":

Example:

.. literalinclude:: ../examples/creating.c
:language: c
:start-after: // bson_array_builder_t top-level example ... begin
:end-before: // bson_array_builder_t top-level example ... end
:dedent: 6

Appending values to an array
----------------------------

``bson_array_builder_append_*`` functions are provided to append values to a BSON array. The ``bson_array_builder_append_*`` functions internally use ``bson_append_*`` and provide the array index as a key:

.. code-block:: c

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);
31 changes: 12 additions & 19 deletions src/libbson/doc/creating.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,28 +52,21 @@ Notice that we omitted the call to :symbol:`bson_init()`. By specifying ``BSON_I
Sub-Documents and Sub-Arrays
----------------------------

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

.. code-block:: c

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);
.. literalinclude:: ../examples/creating.c
:language: c
:start-after: // bson_append_document_begin example ... begin
:end-before: // bson_append_document_begin example ... end
:dedent: 6

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

bson_destroy (&parent);

.. code-block:: none
To simplify the creation of sub-arrays :symbol:`bson_array_builder_t` can be used to build a sub-array using the parent's memory region as the destination buffer.

{ "foo" : { "baz" : 1 } }
.. literalinclude:: ../examples/creating.c
:language: c
:start-after: // bson_array_builder_t example ... begin
:end-before: // bson_array_builder_t example ... end
:dedent: 6

Simplified BSON C Object Notation
---------------------------------
Expand Down
77 changes: 77 additions & 0 deletions src/libbson/examples/creating.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/* Copyright 2017 MongoDB Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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 "AS IS" 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.
*/

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

int
main (int argc, const char **argv)
{
{
// bson_append_document_begin example ... begin
bson_t parent = BSON_INITIALIZER;
bson_t child;

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

char *str = bson_as_relaxed_extended_json (&parent, NULL);
printf ("%s\n", str); // Prints: { "foo" : { "baz" : 1 } }
bson_free (str);

bson_destroy (&parent);
// bson_append_document_begin example ... end
}

{
// bson_array_builder_t example ... begin
bson_t parent = BSON_INITIALIZER;
bson_array_builder_t *bab;

bson_append_array_builder_begin (&parent, "foo", 3, &bab);
bson_array_builder_append_int32 (bab, 1);
bson_array_builder_append_int32 (bab, 2);
bson_array_builder_append_int32 (bab, 3);
bson_append_array_builder_end (&parent, bab);

char *str = bson_as_relaxed_extended_json (&parent, NULL);
printf ("%s\n", str); // Prints: { "foo" : [ 1, 2, 3 ] }
bson_free (str);

bson_destroy (&parent);
// bson_array_builder_t example ... end
}

{
// bson_array_builder_t top-level example ... begin
bson_t out;
bson_array_builder_t *bab = bson_array_builder_new ();

bson_array_builder_append_int32 (bab, 1);
bson_array_builder_append_int32 (bab, 2);
bson_array_builder_append_int32 (bab, 3);
bson_array_builder_build (bab, &out);

char *str = bson_array_as_relaxed_extended_json (&out, NULL);
printf ("%s\n", str); // Prints: [ 1, 2, 3 ]
bson_free (str);

bson_array_builder_destroy (bab);
// bson_array_builder_t top-level example ... end
}

return 0;
}
5 changes: 4 additions & 1 deletion src/libbson/src/bson/bson-keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,10 @@ static const char *gUint32Strs[] = {
* @size: Size of @str.
*
* Returns:
* The number of bytes in the resulting string.
* The number of bytes in the resulting string excluding the NULL
* terminator. If the output requires more than @size bytes, then @size
* bytes are written and the result is the number of bytes required
* (excluding the NULL terminator)
*
* Side effects:
* None.
Expand Down
Loading