Skip to content

Commit 9affd70

Browse files
CDRIVER-504 add bson_array_builder_t (#1344)
* document and test `bson_uint32_to_string` behavior when input buffer is too small. * add `ASSERT_BSON_EQUAL_BSON` test macro * add `bson_array_builder_t` * add `bson_array_builder_append_*` functions * use `bson_array_builder_t` Replace existing use of `bson_append_array_begin`. bcon-speed.c was deliberately not modified to use `bson_array_builder_append_array_begin` to avoid changing performance. * move tutorial `Appending BSON` example code to separate file * add doc page for `bson_array_builder_t` and update doc examples * link to `bson_array_builder_t` doc page * colocate `BSON_APPEND_*` macros with functions Intends to make it easier to spot if a macro is missing. * add `BSON_APPEND_ITER` and `BSON_APPEND_NOW_UTC` * colocate `bson_append_*` with `bson_array_builder_append_*` functions Intends to make it easier to spot if a function is missing. --------- Co-authored-by: Adrian Dole <[email protected]>
1 parent ba5ab6d commit 9affd70

31 files changed

+1536
-261
lines changed

src/libbson/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ if (ENABLE_EXAMPLES)
378378
add_example (bson-validate examples/bson-validate.c)
379379
add_example (json-to-bson examples/json-to-bson.c)
380380
add_example (bson-check-depth examples/bson-check-depth.c)
381+
add_example (creating examples/creating.c)
381382
endif () # ENABLE_EXAMPLES
382383

383384
set (BSON_HEADER_INSTALL_DIR

src/libbson/doc/api.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ API Reference
66
:maxdepth: 2
77

88
bson_t
9+
bson_array_builder_t
910
bson_context_t
1011
bson_decimal128_t
1112
bson_error_t

src/libbson/doc/bson_append_array.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,7 @@ Returns
3434
-------
3535

3636
Returns ``true`` if the operation was applied successfully. The function fails if appending the array grows ``bson`` larger than INT32_MAX.
37+
38+
.. seealso::
39+
40+
| :symbol:`bson_array_builder_t`

src/libbson/doc/bson_append_array_begin.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,14 @@ The :symbol:`bson_append_array_begin()` function shall begin appending an array
3232

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

35+
Consider using :symbol:`bson_array_builder_t` to append an array without needing to generate array element keys.
36+
3537
Returns
3638
-------
3739

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

42+
.. seealso::
43+
44+
| :symbol:`bson_array_builder_t`
45+

src/libbson/doc/bson_append_array_end.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,7 @@ Returns
2626
-------
2727

2828
Returns ``true`` if successful.
29+
30+
.. seealso::
31+
32+
| :symbol:`bson_array_builder_t`
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
:man_page: bson_array_builder_t
2+
3+
bson_array_builder_t
4+
====================
5+
6+
.. code-block:: c
7+
8+
typedef struct _bson_array_builder_t bson_array_builder_t;
9+
10+
``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.
11+
12+
Appending an array value
13+
------------------------
14+
15+
.. code-block:: c
16+
17+
typedef struct _bson_array_builder_t bson_array_builder_t;
18+
19+
bool
20+
bson_append_array_builder_begin (bson_t *bson,
21+
const char *key,
22+
int key_length,
23+
bson_array_builder_t **child);
24+
25+
bool
26+
bson_append_array_builder_end (bson_t *bson, bson_array_builder_t *child);
27+
28+
#define BSON_APPEND_ARRAY_BUILDER_BEGIN(b, key, child) \
29+
bson_append_array_builder_begin (b, key, (int) strlen (key), child)
30+
31+
``bson_append_array_builder_begin`` may be used to append an array as a value. Example:
32+
33+
.. literalinclude:: ../examples/creating.c
34+
:language: c
35+
:start-after: // bson_array_builder_t example ... begin
36+
:end-before: // bson_array_builder_t example ... end
37+
:dedent: 6
38+
39+
Creating a top-level array
40+
--------------------------
41+
42+
.. code-block:: c
43+
44+
bson_array_builder_t * bson_array_builder_new (void);
45+
46+
bool
47+
bson_array_builder_build (bson_array_builder_t *bab, bson_t *out);
48+
49+
BSON_EXPORT (void)
50+
bson_array_builder_destroy (bson_array_builder_t *bab);
51+
52+
``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":
53+
54+
Example:
55+
56+
.. literalinclude:: ../examples/creating.c
57+
:language: c
58+
:start-after: // bson_array_builder_t top-level example ... begin
59+
:end-before: // bson_array_builder_t top-level example ... end
60+
:dedent: 6
61+
62+
Appending values to an array
63+
----------------------------
64+
65+
``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:
66+
67+
.. code-block:: c
68+
69+
bool
70+
bson_array_builder_append_value (bson_array_builder_t *bab,
71+
const bson_value_t *value);
72+
73+
74+
bool
75+
bson_array_builder_append_array (bson_array_builder_t *bab,
76+
const bson_t *array);
77+
78+
79+
bool
80+
bson_array_builder_append_binary (bson_array_builder_t *bab,
81+
bson_subtype_t subtype,
82+
const uint8_t *binary,
83+
uint32_t length);
84+
85+
bool
86+
bson_array_builder_append_bool (bson_array_builder_t *bab, bool value);
87+
88+
89+
bool
90+
bson_array_builder_append_code (bson_array_builder_t *bab,
91+
const char *javascript);
92+
93+
94+
bool
95+
bson_array_builder_append_code_with_scope (bson_array_builder_t *bab,
96+
const char *javascript,
97+
const bson_t *scope);
98+
99+
100+
bool
101+
bson_array_builder_append_dbpointer (bson_array_builder_t *bab,
102+
const char *collection,
103+
const bson_oid_t *oid);
104+
105+
106+
bool
107+
bson_array_builder_append_double (bson_array_builder_t *bab, double value);
108+
109+
110+
bool
111+
bson_array_builder_append_document (bson_array_builder_t *bab,
112+
const bson_t *value);
113+
114+
115+
bool
116+
bson_array_builder_append_document_begin (bson_array_builder_t *bab,
117+
bson_t *child);
118+
119+
120+
bool
121+
bson_array_builder_append_document_end (bson_array_builder_t *bab,
122+
bson_t *child);
123+
124+
bool
125+
bson_array_builder_append_int32 (bson_array_builder_t *bab, int32_t value);
126+
127+
128+
bool
129+
bson_array_builder_append_int64 (bson_array_builder_t *bab, int64_t value);
130+
131+
132+
bool
133+
bson_array_builder_append_decimal128 (bson_array_builder_t *bab,
134+
const bson_decimal128_t *value);
135+
136+
137+
bool
138+
bson_array_builder_append_iter (bson_array_builder_t *bab,
139+
const bson_iter_t *iter);
140+
141+
142+
bool
143+
bson_array_builder_append_minkey (bson_array_builder_t *bab);
144+
145+
146+
bool
147+
bson_array_builder_append_maxkey (bson_array_builder_t *bab);
148+
149+
150+
bool
151+
bson_array_builder_append_null (bson_array_builder_t *bab);
152+
153+
154+
bool
155+
bson_array_builder_append_oid (bson_array_builder_t *bab,
156+
const bson_oid_t *oid);
157+
158+
159+
bool
160+
bson_array_builder_append_regex (bson_array_builder_t *bab,
161+
const char *regex,
162+
const char *options);
163+
164+
165+
bool
166+
bson_array_builder_append_regex_w_len (bson_array_builder_t *bab,
167+
const char *regex,
168+
int regex_length,
169+
const char *options);
170+
171+
bool
172+
bson_array_builder_append_utf8 (bson_array_builder_t *bab,
173+
const char *value,
174+
int length);
175+
176+
bool
177+
bson_array_builder_append_symbol (bson_array_builder_t *bab,
178+
const char *value,
179+
int length);
180+
181+
bool
182+
bson_array_builder_append_time_t (bson_array_builder_t *bab, time_t value);
183+
184+
185+
bool
186+
bson_array_builder_append_timeval (bson_array_builder_t *bab,
187+
struct timeval *value);
188+
189+
190+
bool
191+
bson_array_builder_append_date_time (bson_array_builder_t *bab, int64_t value);
192+
193+
194+
bool
195+
bson_array_builder_append_now_utc (bson_array_builder_t *bab);
196+
197+
198+
bool
199+
bson_array_builder_append_timestamp (bson_array_builder_t *bab,
200+
uint32_t timestamp,
201+
uint32_t increment);
202+
203+
bool
204+
bson_array_builder_append_undefined (bson_array_builder_t *bab);
205+
206+
bool
207+
bson_array_builder_append_array_builder_begin (bson_array_builder_t *bab,
208+
bson_array_builder_t **child);
209+
210+
bool
211+
bson_array_builder_append_array_builder_end (bson_array_builder_t *bab,
212+
bson_array_builder_t *child);

src/libbson/doc/creating.rst

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,28 +52,21 @@ Notice that we omitted the call to :symbol:`bson_init()`. By specifying ``BSON_I
5252
Sub-Documents and Sub-Arrays
5353
----------------------------
5454

55-
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.
55+
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.
5656

57-
.. code-block:: c
58-
59-
bson_t parent;
60-
bson_t child;
61-
char *str;
62-
63-
bson_init (&parent);
64-
bson_append_document_begin (&parent, "foo", 3, &child);
65-
bson_append_int32 (&child, "baz", 3, 1);
66-
bson_append_document_end (&parent, &child);
57+
.. literalinclude:: ../examples/creating.c
58+
:language: c
59+
:start-after: // bson_append_document_begin example ... begin
60+
:end-before: // bson_append_document_begin example ... end
61+
:dedent: 6
6762

68-
str = bson_as_canonical_extended_json (&parent, NULL);
69-
printf ("%s\n", str);
70-
bson_free (str);
71-
72-
bson_destroy (&parent);
73-
74-
.. code-block:: none
63+
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.
7564

76-
{ "foo" : { "baz" : 1 } }
65+
.. literalinclude:: ../examples/creating.c
66+
:language: c
67+
:start-after: // bson_array_builder_t example ... begin
68+
:end-before: // bson_array_builder_t example ... end
69+
:dedent: 6
7770

7871
Simplified BSON C Object Notation
7972
---------------------------------

src/libbson/examples/creating.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/* Copyright 2017 MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
#include <stdio.h>
17+
#include <bson/bson.h>
18+
19+
int
20+
main (int argc, const char **argv)
21+
{
22+
{
23+
// bson_append_document_begin example ... begin
24+
bson_t parent = BSON_INITIALIZER;
25+
bson_t child;
26+
27+
bson_append_document_begin (&parent, "foo", 3, &child);
28+
bson_append_int32 (&child, "baz", 3, 1);
29+
bson_append_document_end (&parent, &child);
30+
31+
char *str = bson_as_relaxed_extended_json (&parent, NULL);
32+
printf ("%s\n", str); // Prints: { "foo" : { "baz" : 1 } }
33+
bson_free (str);
34+
35+
bson_destroy (&parent);
36+
// bson_append_document_begin example ... end
37+
}
38+
39+
{
40+
// bson_array_builder_t example ... begin
41+
bson_t parent = BSON_INITIALIZER;
42+
bson_array_builder_t *bab;
43+
44+
bson_append_array_builder_begin (&parent, "foo", 3, &bab);
45+
bson_array_builder_append_int32 (bab, 9);
46+
bson_array_builder_append_int32 (bab, 8);
47+
bson_array_builder_append_int32 (bab, 7);
48+
bson_append_array_builder_end (&parent, bab);
49+
50+
char *str = bson_as_relaxed_extended_json (&parent, NULL);
51+
printf ("%s\n", str); // Prints: { "foo" : [ 9, 8, 7 ] }
52+
bson_free (str);
53+
54+
bson_destroy (&parent);
55+
// bson_array_builder_t example ... end
56+
}
57+
58+
{
59+
// bson_array_builder_t top-level example ... begin
60+
bson_t out;
61+
bson_array_builder_t *bab = bson_array_builder_new ();
62+
63+
bson_array_builder_append_int32 (bab, 9);
64+
bson_array_builder_append_int32 (bab, 8);
65+
bson_array_builder_append_int32 (bab, 7);
66+
bson_array_builder_build (bab, &out);
67+
68+
char *str = bson_array_as_relaxed_extended_json (&out, NULL);
69+
printf ("%s\n", str); // Prints: [ 9, 8, 7 ]
70+
bson_free (str);
71+
72+
bson_array_builder_destroy (bab);
73+
// bson_array_builder_t top-level example ... end
74+
}
75+
76+
return 0;
77+
}

src/libbson/src/bson/bson-keys.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,10 @@ static const char *gUint32Strs[] = {
138138
* @size: Size of @str.
139139
*
140140
* Returns:
141-
* The number of bytes in the resulting string.
141+
* The number of bytes in the resulting string excluding the NULL
142+
* terminator. If the output requires more than @size bytes, then @size
143+
* bytes are written and the result is the number of bytes required
144+
* (excluding the NULL terminator)
142145
*
143146
* Side effects:
144147
* None.

0 commit comments

Comments
 (0)