1BSON_VISITOR_T(3)                   libbson                  BSON_VISITOR_T(3)
2
3
4

SYNOPSIS

6          #include <bson/bson.h>
7
8          typedef struct {
9             /* run before / after descending into a document */
10             bool (*visit_before) (const bson_iter_t *iter, const char *key, void *data);
11             bool (*visit_after) (const bson_iter_t *iter, const char *key, void *data);
12             /* corrupt BSON, or unsupported type and visit_unsupported_type not set */
13             void (*visit_corrupt) (const bson_iter_t *iter, void *data);
14             /* normal bson field callbacks */
15             bool (*visit_double) (const bson_iter_t *iter,
16                                   const char *key,
17                                   double v_double,
18                                   void *data);
19             bool (*visit_utf8) (const bson_iter_t *iter,
20                                 const char *key,
21                                 size_t v_utf8_len,
22                                 const char *v_utf8,
23                                 void *data);
24             bool (*visit_document) (const bson_iter_t *iter,
25                                     const char *key,
26                                     const bson_t *v_document,
27                                     void *data);
28             bool (*visit_array) (const bson_iter_t *iter,
29                                  const char *key,
30                                  const bson_t *v_array,
31                                  void *data);
32             bool (*visit_binary) (const bson_iter_t *iter,
33                                   const char *key,
34                                   bson_subtype_t v_subtype,
35                                   size_t v_binary_len,
36                                   const uint8_t *v_binary,
37                                   void *data);
38             /* normal field with deprecated "Undefined" BSON type */
39             bool (*visit_undefined) (const bson_iter_t *iter,
40                                      const char *key,
41                                      void *data);
42             bool (*visit_oid) (const bson_iter_t *iter,
43                                const char *key,
44                                const bson_oid_t *v_oid,
45                                void *data);
46             bool (*visit_bool) (const bson_iter_t *iter,
47                                 const char *key,
48                                 bool v_bool,
49                                 void *data);
50             bool (*visit_date_time) (const bson_iter_t *iter,
51                                      const char *key,
52                                      int64_t msec_since_epoch,
53                                      void *data);
54             bool (*visit_null) (const bson_iter_t *iter, const char *key, void *data);
55             bool (*visit_regex) (const bson_iter_t *iter,
56                                  const char *key,
57                                  const char *v_regex,
58                                  const char *v_options,
59                                  void *data);
60             bool (*visit_dbpointer) (const bson_iter_t *iter,
61                                      const char *key,
62                                      size_t v_collection_len,
63                                      const char *v_collection,
64                                      const bson_oid_t *v_oid,
65                                      void *data);
66             bool (*visit_code) (const bson_iter_t *iter,
67                                 const char *key,
68                                 size_t v_code_len,
69                                 const char *v_code,
70                                 void *data);
71             bool (*visit_symbol) (const bson_iter_t *iter,
72                                   const char *key,
73                                   size_t v_symbol_len,
74                                   const char *v_symbol,
75                                   void *data);
76             bool (*visit_codewscope) (const bson_iter_t *iter,
77                                       const char *key,
78                                       size_t v_code_len,
79                                       const char *v_code,
80                                       const bson_t *v_scope,
81                                       void *data);
82             bool (*visit_int32) (const bson_iter_t *iter,
83                                  const char *key,
84                                  int32_t v_int32,
85                                  void *data);
86             bool (*visit_timestamp) (const bson_iter_t *iter,
87                                      const char *key,
88                                      uint32_t v_timestamp,
89                                      uint32_t v_increment,
90                                      void *data);
91             bool (*visit_int64) (const bson_iter_t *iter,
92                                  const char *key,
93                                  int64_t v_int64,
94                                  void *data);
95             bool (*visit_maxkey) (const bson_iter_t *iter, const char *key, void *data);
96             bool (*visit_minkey) (const bson_iter_t *iter, const char *key, void *data);
97             /* if set, called instead of visit_corrupt when an apparently valid BSON
98              * includes an unrecognized field type (reading future version of BSON) */
99             void (*visit_unsupported_type) (const bson_iter_t *iter,
100                                             const char *key,
101                                             uint32_t type_code,
102                                             void *data);
103             bool (*visit_decimal128) (const bson_iter_t *iter,
104                                       const char *key,
105                                       const bson_decimal128_t *v_decimal128,
106                                       void *data);
107
108             void *padding[7];
109          } bson_visitor_t bson_visitor_t;
110

DESCRIPTION

112       The bson_visitor_t structure provides a series of callbacks that can be
113       called while iterating a BSON document. This may simplify  the  converā€
114       sion of a bson_t to a higher level language structure.
115
116       If  the  optional  callback visit_unsupported_type is set, it is called
117       instead of visit_corrupt in the specific case of an unrecognized  field
118       type.  (Parsing is aborted in either case.) Use this callback to report
119       an error like "unrecognized type" instead  of  simply  "corrupt  BSON".
120       This  future-proofs  code  that  may use an older version of libbson to
121       parse future BSON formats.
122

BASIC EXAMPLE

124          #include <bson/bson.h>
125          #include <stdio.h>
126
127          static bool
128          my_visit_before (const bson_iter_t *iter, const char *key, void *data)
129          {
130             int *count = (int *) data;
131
132             (*count)++;
133
134             /* returning true stops further iteration of the document */
135
136             return false;
137          }
138
139          static void
140          count_fields (bson_t *doc)
141          {
142             bson_visitor_t visitor = {0};
143             bson_iter_t iter;
144             int count = 0;
145
146             visitor.visit_before = my_visit_before;
147
148             if (bson_iter_init (&iter, doc)) {
149                bson_iter_visit_all (&iter, &visitor, &count);
150             }
151
152             printf ("Found %d fields.\n", count);
153          }
154
155       The example below demonstrates how to set your own callbacks to provide
156       information  about the location of corrupt or unsupported BSON document
157       entries.
158

EXAMPLE CORRUPTION CHECK

160          #include <bson/bson.h>
161          #include <stdio.h>
162
163          typedef struct {
164             ssize_t *err_offset;
165          } my_state_t;
166
167          static void
168          my_visit_corrupt (const bson_iter_t *iter, void *data)
169          {
170             *(((my_state_t *) data)->err_offset) = iter->off;
171          }
172
173          static void
174          my_visit_unsupported_type (const bson_iter_t *iter,
175                                     const char *key,
176                                     uint32_t type_code,
177                                     void *data)
178          {
179             *(((my_state_t *) data)->err_offset) = iter->off;
180          }
181
182          static void
183          find_error_location (bson_t *doc)
184          {
185             bson_visitor_t visitors = {0};
186             bson_iter_t iter;
187             my_state_t state;
188             ssize_t err_offset = -1;
189
190             visitors.visit_corrupt = my_visit_corrupt;
191             visitors.visit_unsupported_type = my_visit_unsupported_type;
192             /* provide additional visitors as needed based on your requirements */
193             state.err_offset = &err_offset;
194
195             if (!bson_iter_init (&iter, doc)) {
196                printf ("Could not initialize iterator!");
197                exit (1);
198             }
199
200             if (bson_iter_visit_all (&iter, &visitors, &state) ||
201                 err_offset != -1) {
202                printf ("Found error at offset %d.\n", err_offset);
203             } else {
204                printf ("BSON document had no errors.\n");
205             }
206          }
207
208       The example below demonstrates how to use a visitor to validate a  BSON
209       document's maximum depth.
210

EXAMPLE CUSTOM VALIDATION

212       bson-check-depth.c
213
214          /* Reports the maximum nested depth of a BSON document. */
215          #include <bson/bson.h>
216
217          #include <assert.h>
218          #include <inttypes.h>
219          #include <stdio.h>
220          #include <stdlib.h>
221
222          typedef struct {
223             uint32_t depth;
224             uint32_t max_depth;
225             bool valid;
226          } check_depth_t;
227
228          bool
229          _check_depth_document (const bson_iter_t *iter,
230                                 const char *key,
231                                 const bson_t *v_document,
232                                 void *data);
233
234          static const bson_visitor_t check_depth_funcs = {
235             NULL,
236             NULL,
237             NULL,
238             NULL,
239             NULL,
240             _check_depth_document,
241             _check_depth_document,
242             NULL,
243          };
244
245          bool
246          _check_depth_document (const bson_iter_t *iter,
247                                 const char *key,
248                                 const bson_t *v_document,
249                                 void *data)
250          {
251             check_depth_t *state = (check_depth_t *) data;
252             bson_iter_t child;
253
254             BSON_UNUSED (iter);
255             BSON_UNUSED (key);
256
257             if (!bson_iter_init (&child, v_document)) {
258                fprintf (stderr, "corrupt\n");
259                return true; /* cancel */
260             }
261
262             state->depth++;
263             if (state->depth > state->max_depth) {
264                state->valid = false;
265                return true; /* cancel */
266             }
267
268             bson_iter_visit_all (&child, &check_depth_funcs, state);
269             state->depth--;
270             return false; /* continue */
271          }
272
273          void
274          check_depth (const bson_t *bson, uint32_t max_depth)
275          {
276             bson_iter_t iter;
277             check_depth_t state = {0};
278
279             if (!bson_iter_init (&iter, bson)) {
280                fprintf (stderr, "corrupt\n");
281             }
282
283             state.valid = true;
284             state.max_depth = max_depth;
285             _check_depth_document (&iter, NULL, bson, &state);
286             if (!state.valid) {
287                printf ("document exceeds maximum depth of %" PRIu32 "\n",
288                        state.max_depth);
289             } else {
290                char *as_json = bson_as_canonical_extended_json (bson, NULL);
291                printf ("document %s ", as_json);
292                printf ("is valid\n");
293                bson_free (as_json);
294             }
295          }
296
297          int
298          main (int argc, char **argv)
299          {
300             bson_reader_t *bson_reader;
301             const bson_t *bson;
302             bool reached_eof;
303             bson_error_t error;
304
305             if (argc != 3) {
306                fprintf (stderr, "usage: %s FILE MAX_DEPTH\n", argv[0]);
307                fprintf (stderr, "Checks that the depth of the BSON contained in FILE\n");
308                fprintf (stderr, "does not exceed MAX_DEPTH\n");
309             }
310
311             const char *const filename = argv[1];
312             const int max_depth = atoi (argv[2]);
313
314             bson_reader = bson_reader_new_from_file (filename, &error);
315             if (!bson_reader) {
316                printf ("could not read %s: %s\n", filename, error.message);
317                return 1;
318             }
319
320             BSON_ASSERT (bson_in_range_signed (uint32_t, max_depth));
321
322             while ((bson = bson_reader_read (bson_reader, &reached_eof))) {
323                check_depth (bson, (uint32_t) max_depth);
324             }
325
326             if (!reached_eof) {
327                printf ("error reading BSON\n");
328             }
329
330             bson_reader_destroy (bson_reader);
331             return 0;
332          }
333
334

AUTHOR

336       MongoDB, Inc
337
339       2017-present, MongoDB, Inc
340
341
342
343
3441.25.1                           Nov 08, 2023                BSON_VISITOR_T(3)
Impressum