File Coverage

bson/bson.c
Criterion Covered Total %
statement 409 1070 38.2
branch 161 556 28.9
condition n/a
subroutine n/a
pod n/a
total 570 1626 35.0


line stmt bran cond sub pod time code
1             /*
2             * Copyright 2013 MongoDB, Inc.
3             *
4             * Licensed under the Apache License, Version 2.0 (the "License");
5             * you may not use this file except in compliance with the License.
6             * You may obtain a copy of the License at
7             *
8             * http://www.apache.org/licenses/LICENSE-2.0
9             *
10             * Unless required by applicable law or agreed to in writing, software
11             * distributed under the License is distributed on an "AS IS" BASIS,
12             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13             * See the License for the specific language governing permissions and
14             * limitations under the License.
15             */
16              
17              
18             #include "bson.h"
19             #include "bson-config.h"
20             #include "b64_ntop.h"
21             #include "bson-private.h"
22             #include "bson-string.h"
23              
24             #include
25             #include
26             #include
27              
28              
29             #ifndef BSON_MAX_RECURSION
30             # define BSON_MAX_RECURSION 100
31             #endif
32              
33              
34             typedef enum {
35             BSON_VALIDATE_PHASE_START,
36             BSON_VALIDATE_PHASE_TOP,
37             BSON_VALIDATE_PHASE_LF_REF_KEY,
38             BSON_VALIDATE_PHASE_LF_REF_UTF8,
39             BSON_VALIDATE_PHASE_LF_ID_KEY,
40             BSON_VALIDATE_PHASE_LF_DB_KEY,
41             BSON_VALIDATE_PHASE_LF_DB_UTF8,
42             BSON_VALIDATE_PHASE_NOT_DBREF,
43             } bson_validate_phase_t;
44              
45              
46             /*
47             * Structures.
48             */
49             typedef struct
50             {
51             bson_validate_flags_t flags;
52             ssize_t err_offset;
53             bson_validate_phase_t phase;
54             const char * invalid_key;
55             uint32_t invalid_type;
56             } bson_validate_state_t;
57              
58              
59             typedef struct
60             {
61             uint32_t count;
62             bool keys;
63             uint32_t depth;
64             bson_string_t *str;
65             } bson_json_state_t;
66              
67              
68             /*
69             * Forward declarations.
70             */
71             static bool _bson_as_json_visit_array (const bson_iter_t *iter,
72             const char *key,
73             const bson_t *v_array,
74             void *data);
75             static bool _bson_as_json_visit_document (const bson_iter_t *iter,
76             const char *key,
77             const bson_t *v_document,
78             void *data);
79              
80              
81             /*
82             * Globals.
83             */
84             static const uint8_t gZero;
85              
86              
87             /*
88             *--------------------------------------------------------------------------
89             *
90             * _bson_impl_inline_grow --
91             *
92             * Document growth implementation for documents that currently
93             * contain stack based buffers. The document may be switched to
94             * a malloc based buffer.
95             *
96             * Returns:
97             * true if successful; otherwise false indicating INT_MAX overflow.
98             *
99             * Side effects:
100             * None.
101             *
102             *--------------------------------------------------------------------------
103             */
104              
105             static bool
106 1992           _bson_impl_inline_grow (bson_impl_inline_t *impl, /* IN */
107             size_t size) /* IN */
108             {
109 1992           bson_impl_alloc_t *alloc = (bson_impl_alloc_t *)impl;
110             uint8_t *data;
111             size_t req;
112              
113 1992 100         if (((size_t)impl->len + size) <= sizeof impl->data) {
114 1926           return true;
115             }
116              
117 66           req = bson_next_power_of_two (impl->len + size);
118              
119 66 50         if (req <= INT32_MAX) {
120 66           data = bson_malloc (req);
121              
122 66           memcpy (data, impl->data, impl->len);
123 66           alloc->flags &= ~BSON_FLAG_INLINE;
124 66           alloc->parent = NULL;
125 66           alloc->depth = 0;
126 66           alloc->buf = &alloc->alloc;
127 66           alloc->buflen = &alloc->alloclen;
128 66           alloc->offset = 0;
129 66           alloc->alloc = data;
130 66           alloc->alloclen = req;
131 66           alloc->realloc = bson_realloc_ctx;
132 66           alloc->realloc_func_ctx = NULL;
133              
134 66           return true;
135             }
136              
137 0           return false;
138             }
139              
140              
141             /*
142             *--------------------------------------------------------------------------
143             *
144             * _bson_impl_alloc_grow --
145             *
146             * Document growth implementation for documents containing malloc
147             * based buffers.
148             *
149             * Returns:
150             * true if successful; otherwise false indicating INT_MAX overflow.
151             *
152             * Side effects:
153             * None.
154             *
155             *--------------------------------------------------------------------------
156             */
157              
158             static bool
159 1191           _bson_impl_alloc_grow (bson_impl_alloc_t *impl, /* IN */
160             size_t size) /* IN */
161             {
162             size_t req;
163              
164             /*
165             * Determine how many bytes we need for this document in the buffer
166             * including necessary trailing bytes for parent documents.
167             */
168 1191           req = (impl->offset + impl->len + size + impl->depth);
169              
170 1191 100         if (req <= *impl->buflen) {
171 1167           return true;
172             }
173              
174 24           req = bson_next_power_of_two (req);
175              
176 24 50         if ((req <= INT32_MAX) && impl->realloc) {
    50          
177 24           *impl->buf = impl->realloc (*impl->buf, req, impl->realloc_func_ctx);
178 24           *impl->buflen = req;
179 24           return true;
180             }
181              
182 0           return false;
183             }
184              
185              
186             /*
187             *--------------------------------------------------------------------------
188             *
189             * _bson_grow --
190             *
191             * Grows the bson_t structure to be large enough to contain @size
192             * bytes.
193             *
194             * Returns:
195             * true if successful, false if the size would overflow.
196             *
197             * Side effects:
198             * None.
199             *
200             *--------------------------------------------------------------------------
201             */
202              
203             static bool
204 3183           _bson_grow (bson_t *bson, /* IN */
205             uint32_t size) /* IN */
206             {
207 3183 100         if ((bson->flags & BSON_FLAG_INLINE)) {
208 1992           return _bson_impl_inline_grow ((bson_impl_inline_t *)bson, size);
209             }
210              
211 1191           return _bson_impl_alloc_grow ((bson_impl_alloc_t *)bson, size);
212             }
213              
214              
215             /*
216             *--------------------------------------------------------------------------
217             *
218             * _bson_data --
219             *
220             * A helper function to return the contents of the bson document
221             * taking into account the polymorphic nature of bson_t.
222             *
223             * Returns:
224             * A buffer which should not be modified or freed.
225             *
226             * Side effects:
227             * None.
228             *
229             *--------------------------------------------------------------------------
230             */
231              
232             static BSON_INLINE uint8_t *
233 15036           _bson_data (const bson_t *bson) /* IN */
234             {
235 15036 100         if ((bson->flags & BSON_FLAG_INLINE)) {
236 5974           return ((bson_impl_inline_t *)bson)->data;
237             } else {
238 9062           bson_impl_alloc_t *impl = (bson_impl_alloc_t *)bson;
239 9062           return (*impl->buf) + impl->offset;
240             }
241             }
242              
243              
244             /*
245             *--------------------------------------------------------------------------
246             *
247             * _bson_encode_length --
248             *
249             * Helper to encode the length of the bson_t in the first 4 bytes
250             * of the bson document. Little endian format is used as specified
251             * by bsonspec.
252             *
253             * Returns:
254             * None.
255             *
256             * Side effects:
257             * None.
258             *
259             *--------------------------------------------------------------------------
260             */
261              
262             static BSON_INLINE void
263 3878           _bson_encode_length (bson_t *bson) /* IN */
264             {
265             #if BSON_BYTE_ORDER == BSON_LITTLE_ENDIAN
266 3878           memcpy (_bson_data (bson), &bson->len, sizeof (bson->len));
267             #else
268             uint32_t length_le = BSON_UINT32_TO_LE (bson->len);
269             memcpy (_bson_data (bson), &length_le, sizeof (length_le));
270             #endif
271 3878           }
272              
273              
274             /*
275             *--------------------------------------------------------------------------
276             *
277             * _bson_append_va --
278             *
279             * Appends the length,buffer pairs to the bson_t. @n_bytes is an
280             * optimization to perform one array growth rather than many small
281             * growths.
282             *
283             * @bson: A bson_t
284             * @n_bytes: The number of bytes to append to the document.
285             * @n_pairs: The number of length,buffer pairs.
286             * @first_len: Length of first buffer.
287             * @first_data: First buffer.
288             * @args: va_list of additional tuples.
289             *
290             * Returns:
291             * true if the bytes were appended successfully.
292             * false if it bson would overflow INT_MAX.
293             *
294             * Side effects:
295             * None.
296             *
297             *--------------------------------------------------------------------------
298             */
299              
300             static BSON_INLINE bool
301 3121           _bson_append_va (bson_t *bson, /* IN */
302             uint32_t n_bytes, /* IN */
303             uint32_t n_pairs, /* IN */
304             uint32_t first_len, /* IN */
305             const uint8_t *first_data, /* IN */
306             va_list args) /* IN */
307             {
308             const uint8_t *data;
309             uint32_t data_len;
310             uint8_t *buf;
311              
312 3121 50         BSON_ASSERT (!(bson->flags & BSON_FLAG_IN_CHILD));
313 3121 50         BSON_ASSERT (!(bson->flags & BSON_FLAG_RDONLY));
314              
315 3121 50         if (BSON_UNLIKELY (!_bson_grow (bson, n_bytes))) {
316 0           return false;
317             }
318              
319 3121           data = first_data;
320 3121           data_len = first_len;
321              
322 3121           buf = _bson_data (bson) + bson->len - 1;
323              
324             do {
325 12832           n_pairs--;
326 12832           memcpy (buf, data, data_len);
327 12832           bson->len += data_len;
328 12832           buf += data_len;
329              
330 12832 100         if (n_pairs) {
331 9711 100         data_len = va_arg (args, uint32_t);
332 9711 50         data = va_arg (args, const uint8_t *);
333             }
334 12832 100         } while (n_pairs);
335              
336 3121           _bson_encode_length (bson);
337              
338 3121           *buf = '\0';
339              
340 3121           return true;
341             }
342              
343              
344             /*
345             *--------------------------------------------------------------------------
346             *
347             * _bson_append --
348             *
349             * Variadic function to append length,buffer pairs to a bson_t. If the
350             * append would cause the bson_t to overflow a 32-bit length, it will
351             * return false and no append will have occurred.
352             *
353             * Parameters:
354             * @bson: A bson_t.
355             * @n_pairs: Number of length,buffer pairs.
356             * @n_bytes: the total number of bytes being appended.
357             * @first_len: Length of first buffer.
358             * @first_data: First buffer.
359             *
360             * Returns:
361             * true if successful; otherwise false indicating INT_MAX overflow.
362             *
363             * Side effects:
364             * None.
365             *
366             *--------------------------------------------------------------------------
367             */
368              
369             static bool
370 3121           _bson_append (bson_t *bson, /* IN */
371             uint32_t n_pairs, /* IN */
372             uint32_t n_bytes, /* IN */
373             uint32_t first_len, /* IN */
374             const uint8_t *first_data, /* IN */
375             ...)
376             {
377             va_list args;
378             bool ok;
379              
380 3121 50         BSON_ASSERT (n_pairs);
381 3121 50         BSON_ASSERT (first_len);
382 3121 50         BSON_ASSERT (first_data);
383              
384             /*
385             * Check to see if this append would overflow 32-bit signed integer. I know
386             * what you're thinking. BSON uses a signed 32-bit length field? Yeah. It
387             * does.
388             */
389 3121 50         if (BSON_UNLIKELY (n_bytes > (BSON_MAX_SIZE - bson->len))) {
390 0           return false;
391             }
392              
393 3121           va_start (args, first_data);
394 3121           ok = _bson_append_va (bson, n_bytes, n_pairs, first_len, first_data, args);
395 3121           va_end (args);
396              
397 3121           return ok;
398             }
399              
400              
401             /*
402             *--------------------------------------------------------------------------
403             *
404             * _bson_append_bson_begin --
405             *
406             * Begin appending a subdocument or subarray to the document using
407             * the key provided by @key.
408             *
409             * If @key_length is < 0, then strlen() will be called on @key
410             * to determine the length.
411             *
412             * @key_type MUST be either BSON_TYPE_DOCUMENT or BSON_TYPE_ARRAY.
413             *
414             * Returns:
415             * true if successful; otherwise false indicating INT_MAX overflow.
416             *
417             * Side effects:
418             * @child is initialized if true is returned.
419             *
420             *--------------------------------------------------------------------------
421             */
422              
423             static bool
424 963           _bson_append_bson_begin (bson_t *bson, /* IN */
425             const char *key, /* IN */
426             int key_length, /* IN */
427             bson_type_t child_type, /* IN */
428             bson_t *child) /* OUT */
429             {
430 963           const uint8_t type = child_type;
431 963           const uint8_t empty[5] = { 5 };
432 963           bson_impl_alloc_t *aparent = (bson_impl_alloc_t *)bson;
433 963           bson_impl_alloc_t *achild = (bson_impl_alloc_t *)child;
434              
435 963 50         BSON_ASSERT (!(bson->flags & BSON_FLAG_RDONLY));
436 963 50         BSON_ASSERT (!(bson->flags & BSON_FLAG_IN_CHILD));
437 963 50         BSON_ASSERT (key);
438 963 100         BSON_ASSERT ((child_type == BSON_TYPE_DOCUMENT) ||
    50          
439             (child_type == BSON_TYPE_ARRAY));
440 963 50         BSON_ASSERT (child);
441              
442 963 50         if (key_length < 0) {
443 963           key_length = (int)strlen (key);
444             }
445              
446             /*
447             * If the parent is an inline bson_t, then we need to convert
448             * it to a heap allocated buffer. This makes extending buffers
449             * of child bson documents much simpler logic, as they can just
450             * realloc the *buf pointer.
451             */
452 963 100         if ((bson->flags & BSON_FLAG_INLINE)) {
453 62 50         BSON_ASSERT (bson->len <= 120);
454 62 50         if (!_bson_grow (bson, 128 - bson->len)) {
455 0           return false;
456             }
457 62 50         BSON_ASSERT (!(bson->flags & BSON_FLAG_INLINE));
458             }
459              
460             /*
461             * Append the type and key for the field.
462             */
463 963 50         if (!_bson_append (bson, 4,
464 963           (1 + key_length + 1 + 5),
465             1, &type,
466             key_length, key,
467             1, &gZero,
468             5, empty)) {
469 0           return false;
470             }
471              
472             /*
473             * Mark the document as working on a child document so that no
474             * further modifications can happen until the caller has called
475             * bson_append_{document,array}_end().
476             */
477 963           bson->flags |= BSON_FLAG_IN_CHILD;
478              
479             /*
480             * Initialize the child bson_t structure and point it at the parents
481             * buffers. This allows us to realloc directly from the child without
482             * walking up to the parent bson_t.
483             */
484 963           achild->flags = (BSON_FLAG_CHILD | BSON_FLAG_NO_FREE | BSON_FLAG_STATIC);
485              
486 963 100         if ((bson->flags & BSON_FLAG_CHILD)) {
487 895           achild->depth = ((bson_impl_alloc_t *)bson)->depth + 1;
488             } else {
489 68           achild->depth = 1;
490             }
491              
492 963           achild->parent = bson;
493 963           achild->buf = aparent->buf;
494 963           achild->buflen = aparent->buflen;
495 963           achild->offset = aparent->offset + aparent->len - 1 - 5;
496 963           achild->len = 5;
497 963           achild->alloc = NULL;
498 963           achild->alloclen = 0;
499 963           achild->realloc = aparent->realloc;
500 963           achild->realloc_func_ctx = aparent->realloc_func_ctx;
501              
502 963           return true;
503             }
504              
505              
506             /*
507             *--------------------------------------------------------------------------
508             *
509             * _bson_append_bson_end --
510             *
511             * Complete a call to _bson_append_bson_begin.
512             *
513             * Returns:
514             * true if successful; otherwise false indicating INT_MAX overflow.
515             *
516             * Side effects:
517             * @child is destroyed and no longer valid after calling this
518             * function.
519             *
520             *--------------------------------------------------------------------------
521             */
522              
523             static bool
524 757           _bson_append_bson_end (bson_t *bson, /* IN */
525             bson_t *child) /* IN */
526             {
527 757 50         BSON_ASSERT (bson);
528 757 50         BSON_ASSERT ((bson->flags & BSON_FLAG_IN_CHILD));
529 757 50         BSON_ASSERT (!(child->flags & BSON_FLAG_IN_CHILD));
530              
531             /*
532             * Unmark the IN_CHILD flag.
533             */
534 757           bson->flags &= ~BSON_FLAG_IN_CHILD;
535              
536             /*
537             * Now that we are done building the sub-document, add the size to the
538             * parent, not including the default 5 byte empty document already added.
539             */
540 757           bson->len = (bson->len + child->len - 5);
541              
542             /*
543             * Ensure we have a \0 byte at the end and proper length encoded at
544             * the beginning of the document.
545             */
546 757           _bson_data (bson)[bson->len - 1] = '\0';
547 757           _bson_encode_length (bson);
548              
549 757           return true;
550             }
551              
552              
553             /*
554             *--------------------------------------------------------------------------
555             *
556             * bson_append_array_begin --
557             *
558             * Start appending a new array.
559             *
560             * Use @child to append to the data area for the given field.
561             *
562             * It is a programming error to call any other bson function on
563             * @bson until bson_append_array_end() has been called. It is
564             * valid to call bson_append*() functions on @child.
565             *
566             * This function is useful to allow building nested documents using
567             * a single buffer owned by the top-level bson document.
568             *
569             * Returns:
570             * true if successful; otherwise false and @child is invalid.
571             *
572             * Side effects:
573             * @child is initialized if true is returned.
574             *
575             *--------------------------------------------------------------------------
576             */
577              
578             bool
579 17           bson_append_array_begin (bson_t *bson, /* IN */
580             const char *key, /* IN */
581             int key_length, /* IN */
582             bson_t *child) /* IN */
583             {
584 17 50         BSON_ASSERT (bson);
585 17 50         BSON_ASSERT (key);
586 17 50         BSON_ASSERT (child);
587              
588 17           return _bson_append_bson_begin (bson, key, key_length, BSON_TYPE_ARRAY,
589             child);
590             }
591              
592              
593             /*
594             *--------------------------------------------------------------------------
595             *
596             * bson_append_array_end --
597             *
598             * Complete a call to bson_append_array_begin().
599             *
600             * It is safe to append other fields to @bson after calling this
601             * function.
602             *
603             * Returns:
604             * true if successful; otherwise false indicating INT_MAX overflow.
605             *
606             * Side effects:
607             * @child is invalid after calling this function.
608             *
609             *--------------------------------------------------------------------------
610             */
611              
612             bool
613 16           bson_append_array_end (bson_t *bson, /* IN */
614             bson_t *child) /* IN */
615             {
616 16 50         BSON_ASSERT (bson);
617 16 50         BSON_ASSERT (child);
618              
619 16           return _bson_append_bson_end (bson, child);
620             }
621              
622              
623             /*
624             *--------------------------------------------------------------------------
625             *
626             * bson_append_document_begin --
627             *
628             * Start appending a new document.
629             *
630             * Use @child to append to the data area for the given field.
631             *
632             * It is a programming error to call any other bson function on
633             * @bson until bson_append_document_end() has been called. It is
634             * valid to call bson_append*() functions on @child.
635             *
636             * This function is useful to allow building nested documents using
637             * a single buffer owned by the top-level bson document.
638             *
639             * Returns:
640             * true if successful; otherwise false and @child is invalid.
641             *
642             * Side effects:
643             * @child is initialized if true is returned.
644             *
645             *--------------------------------------------------------------------------
646             */
647             bool
648 946           bson_append_document_begin (bson_t *bson, /* IN */
649             const char *key, /* IN */
650             int key_length, /* IN */
651             bson_t *child) /* IN */
652             {
653 946 50         BSON_ASSERT (bson);
654 946 50         BSON_ASSERT (key);
655 946 50         BSON_ASSERT (child);
656              
657 946           return _bson_append_bson_begin (bson, key, key_length, BSON_TYPE_DOCUMENT,
658             child);
659             }
660              
661              
662             /*
663             *--------------------------------------------------------------------------
664             *
665             * bson_append_document_end --
666             *
667             * Complete a call to bson_append_document_begin().
668             *
669             * It is safe to append new fields to @bson after calling this
670             * function, if true is returned.
671             *
672             * Returns:
673             * true if successful; otherwise false indicating INT_MAX overflow.
674             *
675             * Side effects:
676             * @child is destroyed and invalid after calling this function.
677             *
678             *--------------------------------------------------------------------------
679             */
680              
681             bool
682 741           bson_append_document_end (bson_t *bson, /* IN */
683             bson_t *child) /* IN */
684             {
685 741 50         BSON_ASSERT (bson);
686 741 50         BSON_ASSERT (child);
687              
688 741           return _bson_append_bson_end (bson, child);
689             }
690              
691              
692             /*
693             *--------------------------------------------------------------------------
694             *
695             * bson_append_array --
696             *
697             * Append an array to @bson.
698             *
699             * Generally, bson_append_array_begin() will result in faster code
700             * since few buffers need to be malloced.
701             *
702             * Returns:
703             * true if successful; otherwise false indicating INT_MAX overflow.
704             *
705             * Side effects:
706             * None.
707             *
708             *--------------------------------------------------------------------------
709             */
710              
711             bool
712 0           bson_append_array (bson_t *bson, /* IN */
713             const char *key, /* IN */
714             int key_length, /* IN */
715             const bson_t *array) /* IN */
716             {
717             static const uint8_t type = BSON_TYPE_ARRAY;
718              
719 0 0         BSON_ASSERT (bson);
720 0 0         BSON_ASSERT (key);
721 0 0         BSON_ASSERT (array);
722              
723 0 0         if (key_length < 0) {
724 0           key_length = (int)strlen (key);
725             }
726              
727             /*
728             * Let's be a bit pedantic and ensure the array has properly formatted key
729             * names. We will verify this simply by checking the first element for "0"
730             * if the array is non-empty.
731             */
732 0 0         if (array && !bson_empty (array)) {
    0          
    0          
733             bson_iter_t iter;
734              
735 0 0         if (bson_iter_init (&iter, array) && bson_iter_next (&iter)) {
    0          
736 0 0         if (0 != strcmp ("0", bson_iter_key (&iter))) {
737 0           fprintf (stderr,
738             "%s(): invalid array detected. first element of array "
739             "parameter is not \"0\".\n",
740             BSON_FUNC);
741             }
742             }
743             }
744              
745 0           return _bson_append (bson, 4,
746 0           (1 + key_length + 1 + array->len),
747             1, &type,
748             key_length, key,
749             1, &gZero,
750             array->len, _bson_data (array));
751             }
752              
753              
754             /*
755             *--------------------------------------------------------------------------
756             *
757             * bson_append_binary --
758             *
759             * Append binary data to @bson. The field will have the
760             * BSON_TYPE_BINARY type.
761             *
762             * Parameters:
763             * @subtype: the BSON Binary Subtype. See bsonspec.org for more
764             * information.
765             * @binary: a pointer to the raw binary data.
766             * @length: the size of @binary in bytes.
767             *
768             * Returns:
769             * true if successful; otherwise false.
770             *
771             * Side effects:
772             * None.
773             *
774             *--------------------------------------------------------------------------
775             */
776              
777             bool
778 28           bson_append_binary (bson_t *bson, /* IN */
779             const char *key, /* IN */
780             int key_length, /* IN */
781             bson_subtype_t subtype, /* IN */
782             const uint8_t *binary, /* IN */
783             uint32_t length) /* IN */
784             {
785             static const uint8_t type = BSON_TYPE_BINARY;
786             uint32_t length_le;
787             uint32_t deprecated_length_le;
788 28           uint8_t subtype8 = 0;
789              
790 28 50         BSON_ASSERT (bson);
791 28 50         BSON_ASSERT (key);
792 28 50         BSON_ASSERT (binary);
793              
794 28 50         if (key_length < 0) {
795 28           key_length = (int)strlen (key);
796             }
797              
798 28           subtype8 = subtype;
799              
800 28 100         if (subtype == BSON_SUBTYPE_BINARY_DEPRECATED) {
801 2           length_le = BSON_UINT32_TO_LE (length + 4);
802 2           deprecated_length_le = BSON_UINT32_TO_LE (length);
803              
804 2           return _bson_append (bson, 7,
805 2           (1 + key_length + 1 + 4 + 1 + 4 + length),
806             1, &type,
807             key_length, key,
808             1, &gZero,
809             4, &length_le,
810             1, &subtype8,
811             4, &deprecated_length_le,
812             length, binary);
813             } else {
814 26           length_le = BSON_UINT32_TO_LE (length);
815              
816 28           return _bson_append (bson, 6,
817 26           (1 + key_length + 1 + 4 + 1 + length),
818             1, &type,
819             key_length, key,
820             1, &gZero,
821             4, &length_le,
822             1, &subtype8,
823             length, binary);
824             }
825             }
826              
827              
828             /*
829             *--------------------------------------------------------------------------
830             *
831             * bson_append_bool --
832             *
833             * Append a new field to @bson with the name @key. The value is
834             * a boolean indicated by @value.
835             *
836             * Returns:
837             * true if succesful; otherwise false.
838             *
839             * Side effects:
840             * None.
841             *
842             *--------------------------------------------------------------------------
843             */
844              
845             bool
846 18           bson_append_bool (bson_t *bson, /* IN */
847             const char *key, /* IN */
848             int key_length, /* IN */
849             bool value) /* IN */
850             {
851             static const uint8_t type = BSON_TYPE_BOOL;
852 18           uint8_t abyte = !!value;
853              
854 18 50         BSON_ASSERT (bson);
855 18 50         BSON_ASSERT (key);
856              
857 18 50         if (key_length < 0) {
858 18           key_length = (int)strlen (key);
859             }
860              
861 18           return _bson_append (bson, 4,
862 18           (1 + key_length + 1 + 1),
863             1, &type,
864             key_length, key,
865             1, &gZero,
866             1, &abyte);
867             }
868              
869              
870             /*
871             *--------------------------------------------------------------------------
872             *
873             * bson_append_code --
874             *
875             * Append a new field to @bson containing javascript code.
876             *
877             * @javascript MUST be a zero terminated UTF-8 string. It MUST NOT
878             * containing embedded \0 characters.
879             *
880             * Returns:
881             * true if successful; otherwise false.
882             *
883             * Side effects:
884             * None.
885             *
886             * See also:
887             * bson_append_code_with_scope().
888             *
889             *--------------------------------------------------------------------------
890             */
891              
892             bool
893 10           bson_append_code (bson_t *bson, /* IN */
894             const char *key, /* IN */
895             int key_length, /* IN */
896             const char *javascript) /* IN */
897             {
898             static const uint8_t type = BSON_TYPE_CODE;
899             uint32_t length;
900             uint32_t length_le;
901              
902 10 50         BSON_ASSERT (bson);
903 10 50         BSON_ASSERT (key);
904 10 50         BSON_ASSERT (javascript);
905              
906 10 50         if (key_length < 0) {
907 10           key_length = (int)strlen (key);
908             }
909              
910 10           length = (int)strlen (javascript) + 1;
911 10           length_le = BSON_UINT32_TO_LE (length);
912              
913 10           return _bson_append (bson, 5,
914 10           (1 + key_length + 1 + 4 + length),
915             1, &type,
916             key_length, key,
917             1, &gZero,
918             4, &length_le,
919             length, javascript);
920             }
921              
922              
923             /*
924             *--------------------------------------------------------------------------
925             *
926             * bson_append_code_with_scope --
927             *
928             * Append a new field to @bson containing javascript code with
929             * supplied scope.
930             *
931             * Returns:
932             * true if successful; otherwise false.
933             *
934             * Side effects:
935             * None.
936             *
937             *--------------------------------------------------------------------------
938             */
939              
940             bool
941 14           bson_append_code_with_scope (bson_t *bson, /* IN */
942             const char *key, /* IN */
943             int key_length, /* IN */
944             const char *javascript, /* IN */
945             uint32_t js_length, /* IN */
946             const bson_t *scope) /* IN */
947             {
948             static const uint8_t type = BSON_TYPE_CODEWSCOPE;
949             uint32_t codews_length_le;
950             uint32_t codews_length;
951             uint32_t js_length_le;
952              
953 14 50         BSON_ASSERT (bson);
954 14 50         BSON_ASSERT (key);
955 14 50         BSON_ASSERT (javascript);
956              
957 14 50         if (key_length < 0) {
958 14           key_length = (int)strlen (key);
959             }
960              
961 14           js_length++; /* must include null in length */
962 14           js_length_le = BSON_UINT32_TO_LE (js_length);
963              
964 14           codews_length = 4 + 4 + js_length + scope->len;
965 14           codews_length_le = BSON_UINT32_TO_LE (codews_length);
966              
967 14           return _bson_append (bson, 7,
968 14           (1 + key_length + 1 + 4 + 4 + js_length + scope->len),
969             1, &type,
970             key_length, key,
971             1, &gZero,
972             4, &codews_length_le,
973             4, &js_length_le,
974             js_length, javascript,
975             scope->len, _bson_data (scope));
976             }
977              
978              
979             /*
980             *--------------------------------------------------------------------------
981             *
982             * bson_append_dbpointer --
983             *
984             * This BSON data type is DEPRECATED.
985             *
986             * Append a BSON dbpointer field to @bson.
987             *
988             * Returns:
989             * true if successful; otherwise false.
990             *
991             * Side effects:
992             * None.
993             *
994             *--------------------------------------------------------------------------
995             */
996              
997             bool
998 0           bson_append_dbpointer (bson_t *bson, /* IN */
999             const char *key, /* IN */
1000             int key_length, /* IN */
1001             const char *collection, /* IN */
1002             const bson_oid_t *oid)
1003             {
1004             static const uint8_t type = BSON_TYPE_DBPOINTER;
1005             uint32_t length;
1006             uint32_t length_le;
1007              
1008 0 0         BSON_ASSERT (bson);
1009 0 0         BSON_ASSERT (key);
1010 0 0         BSON_ASSERT (collection);
1011 0 0         BSON_ASSERT (oid);
1012              
1013 0 0         if (key_length < 0) {
1014 0           key_length = (int)strlen (key);
1015             }
1016              
1017 0           length = (int)strlen (collection) + 1;
1018 0           length_le = BSON_UINT32_TO_LE (length);
1019              
1020 0           return _bson_append (bson, 6,
1021 0           (1 + key_length + 1 + 4 + length + 12),
1022             1, &type,
1023             key_length, key,
1024             1, &gZero,
1025             4, &length_le,
1026             length, collection,
1027             12, oid);
1028             }
1029              
1030              
1031             /*
1032             *--------------------------------------------------------------------------
1033             *
1034             * bson_append_document --
1035             *
1036             * Append a new field to @bson containing a BSON document.
1037             *
1038             * In general, using bson_append_document_begin() results in faster
1039             * code and less memory fragmentation.
1040             *
1041             * Returns:
1042             * true if successful; otherwise false.
1043             *
1044             * Side effects:
1045             * None.
1046             *
1047             * See also:
1048             * bson_append_document_begin().
1049             *
1050             *--------------------------------------------------------------------------
1051             */
1052              
1053             bool
1054 104           bson_append_document (bson_t *bson, /* IN */
1055             const char *key, /* IN */
1056             int key_length, /* IN */
1057             const bson_t *value) /* IN */
1058             {
1059             static const uint8_t type = BSON_TYPE_DOCUMENT;
1060              
1061 104 50         BSON_ASSERT (bson);
1062 104 50         BSON_ASSERT (key);
1063 104 50         BSON_ASSERT (value);
1064              
1065 104 50         if (key_length < 0) {
1066 104           key_length = (int)strlen (key);
1067             }
1068              
1069 104           return _bson_append (bson, 4,
1070 104           (1 + key_length + 1 + value->len),
1071             1, &type,
1072             key_length, key,
1073             1, &gZero,
1074             value->len, _bson_data (value));
1075             }
1076              
1077              
1078             bool
1079 46           bson_append_double (bson_t *bson,
1080             const char *key,
1081             int key_length,
1082             double value)
1083             {
1084             static const uint8_t type = BSON_TYPE_DOUBLE;
1085              
1086 46 50         BSON_ASSERT (bson);
1087 46 50         BSON_ASSERT (key);
1088              
1089 46 50         if (key_length < 0) {
1090 46           key_length = (int)strlen (key);
1091             }
1092              
1093             #if BSON_BYTE_ORDER == BSON_BIG_ENDIAN
1094             value = BSON_DOUBLE_TO_LE (value);
1095             #endif
1096              
1097 46           return _bson_append (bson, 4,
1098 46           (1 + key_length + 1 + 8),
1099             1, &type,
1100             key_length, key,
1101             1, &gZero,
1102             8, &value);
1103             }
1104              
1105              
1106             bool
1107 168           bson_append_int32 (bson_t *bson,
1108             const char *key,
1109             int key_length,
1110             int32_t value)
1111             {
1112             static const uint8_t type = BSON_TYPE_INT32;
1113             uint32_t value_le;
1114              
1115 168 50         BSON_ASSERT (bson);
1116 168 50         BSON_ASSERT (key);
1117              
1118 168 50         if (key_length < 0) {
1119 168           key_length = (int)strlen (key);
1120             }
1121              
1122 168           value_le = BSON_UINT32_TO_LE (value);
1123              
1124 168           return _bson_append (bson, 4,
1125 168           (1 + key_length + 1 + 4),
1126             1, &type,
1127             key_length, key,
1128             1, &gZero,
1129             4, &value_le);
1130             }
1131              
1132              
1133             bool
1134 20           bson_append_int64 (bson_t *bson,
1135             const char *key,
1136             int key_length,
1137             int64_t value)
1138             {
1139             static const uint8_t type = BSON_TYPE_INT64;
1140             uint64_t value_le;
1141              
1142 20 50         BSON_ASSERT (bson);
1143 20 50         BSON_ASSERT (key);
1144              
1145 20 50         if (key_length < 0) {
1146 20           key_length = (int)strlen (key);
1147             }
1148              
1149 20           value_le = BSON_UINT64_TO_LE (value);
1150              
1151 20           return _bson_append (bson, 4,
1152 20           (1 + key_length + 1 + 8),
1153             1, &type,
1154             key_length, key,
1155             1, &gZero,
1156             8, &value_le);
1157             }
1158              
1159              
1160             bool
1161 1512           bson_append_decimal128 (bson_t *bson,
1162             const char *key,
1163             int key_length,
1164             const bson_decimal128_t *value)
1165             {
1166             static const uint8_t type = BSON_TYPE_DECIMAL128;
1167             uint64_t value_le[2];
1168              
1169 1512 50         BSON_ASSERT (bson);
1170 1512 50         BSON_ASSERT (key);
1171 1512 50         BSON_ASSERT (value);
1172              
1173 1512 50         if (key_length < 0) {
1174 1512           key_length = (int)strlen (key);
1175             }
1176              
1177 1512           value_le[0] = BSON_UINT64_TO_LE (value->low);
1178 1512           value_le[1] = BSON_UINT64_TO_LE (value->high);
1179              
1180 1512           return _bson_append (bson, 4,
1181 1512           (1 + key_length + 1 + 16),
1182             1, &type,
1183             key_length, key,
1184             1, &gZero,
1185             16, value_le);
1186             }
1187              
1188              
1189             bool
1190 0           bson_append_iter (bson_t *bson,
1191             const char *key,
1192             int key_length,
1193             const bson_iter_t *iter)
1194             {
1195 0           bool ret = false;
1196              
1197 0 0         BSON_ASSERT (bson);
1198 0 0         BSON_ASSERT (iter);
1199              
1200 0 0         if (!key) {
1201 0           key = bson_iter_key (iter);
1202 0           key_length = -1;
1203             }
1204              
1205 0           switch (bson_iter_type_unsafe (iter)) {
1206             case BSON_TYPE_EOD:
1207 0           return false;
1208             case BSON_TYPE_DOUBLE:
1209 0           ret = bson_append_double (bson, key, key_length, bson_iter_double (iter));
1210 0           break;
1211             case BSON_TYPE_UTF8:
1212             {
1213 0           uint32_t len = 0;
1214             const char *str;
1215              
1216 0           str = bson_iter_utf8 (iter, &len);
1217 0           ret = bson_append_utf8 (bson, key, key_length, str, len);
1218             }
1219 0           break;
1220             case BSON_TYPE_DOCUMENT:
1221             {
1222 0           const uint8_t *buf = NULL;
1223 0           uint32_t len = 0;
1224             bson_t doc;
1225              
1226 0           bson_iter_document (iter, &len, &buf);
1227              
1228 0 0         if (bson_init_static (&doc, buf, len)) {
1229 0           ret = bson_append_document (bson, key, key_length, &doc);
1230 0           bson_destroy (&doc);
1231             }
1232             }
1233 0           break;
1234             case BSON_TYPE_ARRAY:
1235             {
1236 0           const uint8_t *buf = NULL;
1237 0           uint32_t len = 0;
1238             bson_t doc;
1239              
1240 0           bson_iter_array (iter, &len, &buf);
1241              
1242 0 0         if (bson_init_static (&doc, buf, len)) {
1243 0           ret = bson_append_array (bson, key, key_length, &doc);
1244 0           bson_destroy (&doc);
1245             }
1246             }
1247 0           break;
1248             case BSON_TYPE_BINARY:
1249             {
1250 0           const uint8_t *binary = NULL;
1251 0           bson_subtype_t subtype = BSON_SUBTYPE_BINARY;
1252 0           uint32_t len = 0;
1253              
1254 0           bson_iter_binary (iter, &subtype, &len, &binary);
1255 0           ret = bson_append_binary (bson, key, key_length,
1256             subtype, binary, len);
1257             }
1258 0           break;
1259             case BSON_TYPE_UNDEFINED:
1260 0           ret = bson_append_undefined (bson, key, key_length);
1261 0           break;
1262             case BSON_TYPE_OID:
1263 0           ret = bson_append_oid (bson, key, key_length, bson_iter_oid (iter));
1264 0           break;
1265             case BSON_TYPE_BOOL:
1266 0           ret = bson_append_bool (bson, key, key_length, bson_iter_bool (iter));
1267 0           break;
1268             case BSON_TYPE_DATE_TIME:
1269 0           ret = bson_append_date_time (bson, key, key_length,
1270             bson_iter_date_time (iter));
1271 0           break;
1272             case BSON_TYPE_NULL:
1273 0           ret = bson_append_null (bson, key, key_length);
1274 0           break;
1275             case BSON_TYPE_REGEX:
1276             {
1277             const char *regex;
1278             const char *options;
1279              
1280 0           regex = bson_iter_regex (iter, &options);
1281 0           ret = bson_append_regex (bson, key, key_length, regex, options);
1282             }
1283 0           break;
1284             case BSON_TYPE_DBPOINTER:
1285             {
1286             const bson_oid_t *oid;
1287             uint32_t len;
1288             const char *collection;
1289              
1290 0           bson_iter_dbpointer (iter, &len, &collection, &oid);
1291 0           ret = bson_append_dbpointer (bson, key, key_length, collection, oid);
1292             }
1293 0           break;
1294             case BSON_TYPE_CODE:
1295             {
1296             uint32_t len;
1297             const char *code;
1298              
1299 0           code = bson_iter_code (iter, &len);
1300 0           ret = bson_append_code (bson, key, key_length, code);
1301             }
1302 0           break;
1303             case BSON_TYPE_SYMBOL:
1304             {
1305             uint32_t len;
1306             const char *symbol;
1307              
1308 0           symbol = bson_iter_symbol (iter, &len);
1309 0           ret = bson_append_symbol (bson, key, key_length, symbol, len);
1310             }
1311 0           break;
1312             case BSON_TYPE_CODEWSCOPE:
1313             {
1314 0           const uint8_t *scope = NULL;
1315 0           uint32_t scope_len = 0;
1316 0           uint32_t len = 0;
1317 0           const char *javascript = NULL;
1318             bson_t doc;
1319              
1320 0           javascript = bson_iter_codewscope (iter, &len, &scope_len, &scope);
1321              
1322 0 0         if (bson_init_static (&doc, scope, scope_len)) {
1323 0           ret = bson_append_code_with_scope (bson, key, key_length,
1324             javascript, len, &doc);
1325 0           bson_destroy (&doc);
1326             }
1327             }
1328 0           break;
1329             case BSON_TYPE_INT32:
1330 0           ret = bson_append_int32 (bson, key, key_length, bson_iter_int32 (iter));
1331 0           break;
1332             case BSON_TYPE_TIMESTAMP:
1333             {
1334             uint32_t ts;
1335             uint32_t inc;
1336              
1337 0           bson_iter_timestamp (iter, &ts, &inc);
1338 0           ret = bson_append_timestamp (bson, key, key_length, ts, inc);
1339             }
1340 0           break;
1341             case BSON_TYPE_INT64:
1342 0           ret = bson_append_int64 (bson, key, key_length, bson_iter_int64 (iter));
1343 0           break;
1344             case BSON_TYPE_DECIMAL128:
1345             {
1346             bson_decimal128_t dec;
1347              
1348 0 0         if (!bson_iter_decimal128 (iter, &dec)) {
1349 0           return false;
1350             }
1351              
1352 0           ret = bson_append_decimal128 (bson, key, key_length, &dec);
1353             }
1354 0           break;
1355             case BSON_TYPE_MAXKEY:
1356 0           ret = bson_append_maxkey (bson, key, key_length);
1357 0           break;
1358             case BSON_TYPE_MINKEY:
1359 0           ret = bson_append_minkey (bson, key, key_length);
1360 0           break;
1361             default:
1362 0           break;
1363             }
1364              
1365 0           return ret;
1366             }
1367              
1368              
1369             bool
1370 6           bson_append_maxkey (bson_t *bson,
1371             const char *key,
1372             int key_length)
1373             {
1374             static const uint8_t type = BSON_TYPE_MAXKEY;
1375              
1376 6 50         BSON_ASSERT (bson);
1377 6 50         BSON_ASSERT (key);
1378              
1379 6 50         if (key_length < 0) {
1380 6           key_length = (int)strlen (key);
1381             }
1382              
1383 6           return _bson_append (bson, 3,
1384 6           (1 + key_length + 1),
1385             1, &type,
1386             key_length, key,
1387             1, &gZero);
1388             }
1389              
1390              
1391             bool
1392 6           bson_append_minkey (bson_t *bson,
1393             const char *key,
1394             int key_length)
1395             {
1396             static const uint8_t type = BSON_TYPE_MINKEY;
1397              
1398 6 50         BSON_ASSERT (bson);
1399 6 50         BSON_ASSERT (key);
1400              
1401 6 50         if (key_length < 0) {
1402 6           key_length = (int)strlen (key);
1403             }
1404              
1405 6           return _bson_append (bson, 3,
1406 6           (1 + key_length + 1),
1407             1, &type,
1408             key_length, key,
1409             1, &gZero);
1410             }
1411              
1412              
1413             bool
1414 16           bson_append_null (bson_t *bson,
1415             const char *key,
1416             int key_length)
1417             {
1418             static const uint8_t type = BSON_TYPE_NULL;
1419              
1420 16 50         BSON_ASSERT (bson);
1421 16 50         BSON_ASSERT (key);
1422              
1423 16 50         if (key_length < 0) {
1424 16           key_length = (int)strlen (key);
1425             }
1426              
1427 16           return _bson_append (bson, 3,
1428 16           (1 + key_length + 1),
1429             1, &type,
1430             key_length, key,
1431             1, &gZero);
1432             }
1433              
1434              
1435             bool
1436 28           bson_append_oid (bson_t *bson,
1437             const char *key,
1438             int key_length,
1439             const bson_oid_t *value)
1440             {
1441             static const uint8_t type = BSON_TYPE_OID;
1442              
1443 28 50         BSON_ASSERT (bson);
1444 28 50         BSON_ASSERT (key);
1445 28 50         BSON_ASSERT (value);
1446              
1447 28 50         if (key_length < 0) {
1448 28           key_length = (int)strlen (key);
1449             }
1450              
1451 28           return _bson_append (bson, 4,
1452 28           (1 + key_length + 1 + 12),
1453             1, &type,
1454             key_length, key,
1455             1, &gZero,
1456             12, value);
1457             }
1458              
1459              
1460             bool
1461 26           bson_append_regex (bson_t *bson,
1462             const char *key,
1463             int key_length,
1464             const char *regex,
1465             const char *options)
1466             {
1467             static const uint8_t type = BSON_TYPE_REGEX;
1468             uint32_t regex_len;
1469             uint32_t options_len;
1470              
1471 26 50         BSON_ASSERT (bson);
1472 26 50         BSON_ASSERT (key);
1473              
1474 26 50         if (key_length < 0) {
1475 26           key_length = (int)strlen (key);
1476             }
1477              
1478 26 50         if (!regex) {
1479 0           regex = "";
1480             }
1481              
1482 26 50         if (!options) {
1483 0           options = "";
1484             }
1485              
1486 26           regex_len = (int)strlen (regex) + 1;
1487 26           options_len = (int)strlen (options) + 1;
1488              
1489 26           return _bson_append (bson, 5,
1490 26           (1 + key_length + 1 + regex_len + options_len),
1491             1, &type,
1492             key_length, key,
1493             1, &gZero,
1494             regex_len, regex,
1495             options_len, options);
1496             }
1497              
1498              
1499             bool
1500 123           bson_append_utf8 (bson_t *bson,
1501             const char *key,
1502             int key_length,
1503             const char *value,
1504             int length)
1505             {
1506             static const uint8_t type = BSON_TYPE_UTF8;
1507             uint32_t length_le;
1508              
1509 123 50         BSON_ASSERT (bson);
1510 123 50         BSON_ASSERT (key);
1511              
1512 123 50         if (BSON_UNLIKELY (!value)) {
1513 0           return bson_append_null (bson, key, key_length);
1514             }
1515              
1516 123 50         if (BSON_UNLIKELY (key_length < 0)) {
1517 123           key_length = (int)strlen (key);
1518             }
1519              
1520 123 50         if (BSON_UNLIKELY (length < 0)) {
1521 0           length = (int)strlen (value);
1522             }
1523              
1524 123           length_le = BSON_UINT32_TO_LE (length + 1);
1525              
1526 123           return _bson_append (bson, 6,
1527 123           (1 + key_length + 1 + 4 + length + 1),
1528             1, &type,
1529             key_length, key,
1530             1, &gZero,
1531             4, &length_le,
1532             length, value,
1533             1, &gZero);
1534             }
1535              
1536              
1537             bool
1538 0           bson_append_symbol (bson_t *bson,
1539             const char *key,
1540             int key_length,
1541             const char *value,
1542             int length)
1543             {
1544             static const uint8_t type = BSON_TYPE_SYMBOL;
1545             uint32_t length_le;
1546              
1547 0 0         BSON_ASSERT (bson);
1548 0 0         BSON_ASSERT (key);
1549              
1550 0 0         if (!value) {
1551 0           return bson_append_null (bson, key, key_length);
1552             }
1553              
1554 0 0         if (key_length < 0) {
1555 0           key_length = (int)strlen (key);
1556             }
1557              
1558 0 0         if (length < 0) {
1559 0           length =(int)strlen (value);
1560             }
1561              
1562 0           length_le = BSON_UINT32_TO_LE (length + 1);
1563              
1564 0           return _bson_append (bson, 6,
1565 0           (1 + key_length + 1 + 4 + length + 1),
1566             1, &type,
1567             key_length, key,
1568             1, &gZero,
1569             4, &length_le,
1570             length, value,
1571             1, &gZero);
1572             }
1573              
1574              
1575             bool
1576 0           bson_append_time_t (bson_t *bson,
1577             const char *key,
1578             int key_length,
1579             time_t value)
1580             {
1581             #ifdef BSON_OS_WIN32
1582             struct timeval tv = { (long)value, 0 };
1583             #else
1584 0           struct timeval tv = { value, 0 };
1585             #endif
1586              
1587 0 0         BSON_ASSERT (bson);
1588 0 0         BSON_ASSERT (key);
1589              
1590 0           return bson_append_timeval (bson, key, key_length, &tv);
1591             }
1592              
1593              
1594             bool
1595 11           bson_append_timestamp (bson_t *bson,
1596             const char *key,
1597             int key_length,
1598             uint32_t timestamp,
1599             uint32_t increment)
1600             {
1601             static const uint8_t type = BSON_TYPE_TIMESTAMP;
1602             uint64_t value;
1603              
1604 11 50         BSON_ASSERT (bson);
1605 11 50         BSON_ASSERT (key);
1606              
1607 11 50         if (key_length < 0) {
1608 11           key_length =(int)strlen (key);
1609             }
1610              
1611 11           value = ((((uint64_t)timestamp) << 32) | ((uint64_t)increment));
1612 11           value = BSON_UINT64_TO_LE (value);
1613              
1614 11           return _bson_append (bson, 4,
1615 11           (1 + key_length + 1 + 8),
1616             1, &type,
1617             key_length, key,
1618             1, &gZero,
1619             8, &value);
1620             }
1621              
1622              
1623             bool
1624 0           bson_append_now_utc (bson_t *bson,
1625             const char *key,
1626             int key_length)
1627             {
1628 0 0         BSON_ASSERT (bson);
1629 0 0         BSON_ASSERT (key);
1630 0 0         BSON_ASSERT (key_length >= -1);
1631              
1632 0           return bson_append_time_t (bson, key, key_length, time (NULL));
1633             }
1634              
1635              
1636             bool
1637 20           bson_append_date_time (bson_t *bson,
1638             const char *key,
1639             int key_length,
1640             int64_t value)
1641             {
1642             static const uint8_t type = BSON_TYPE_DATE_TIME;
1643             uint64_t value_le;
1644              
1645 20 50         BSON_ASSERT (bson);
1646 20 50         BSON_ASSERT (key);
1647              
1648 20 50         if (key_length < 0) {
1649 20           key_length =(int)strlen (key);
1650             }
1651              
1652 20           value_le = BSON_UINT64_TO_LE (value);
1653              
1654 20           return _bson_append (bson, 4,
1655 20           (1 + key_length + 1 + 8),
1656             1, &type,
1657             key_length, key,
1658             1, &gZero,
1659             8, &value_le);
1660             }
1661              
1662              
1663             bool
1664 0           bson_append_timeval (bson_t *bson,
1665             const char *key,
1666             int key_length,
1667             struct timeval *value)
1668             {
1669             uint64_t unix_msec;
1670              
1671 0 0         BSON_ASSERT (bson);
1672 0 0         BSON_ASSERT (key);
1673 0 0         BSON_ASSERT (value);
1674              
1675 0           unix_msec = (((uint64_t)value->tv_sec) * 1000UL) +
1676 0           (value->tv_usec / 1000UL);
1677 0           return bson_append_date_time (bson, key, key_length, unix_msec);
1678             }
1679              
1680              
1681             bool
1682 0           bson_append_undefined (bson_t *bson,
1683             const char *key,
1684             int key_length)
1685             {
1686             static const uint8_t type = BSON_TYPE_UNDEFINED;
1687              
1688 0 0         BSON_ASSERT (bson);
1689 0 0         BSON_ASSERT (key);
1690              
1691 0 0         if (key_length < 0) {
1692 0           key_length =(int)strlen (key);
1693             }
1694              
1695 0           return _bson_append (bson, 3,
1696 0           (1 + key_length + 1),
1697             1, &type,
1698             key_length, key,
1699             1, &gZero);
1700             }
1701              
1702              
1703             bool
1704 0           bson_append_value (bson_t *bson,
1705             const char *key,
1706             int key_length,
1707             const bson_value_t *value)
1708             {
1709             bson_t local;
1710 0           bool ret = false;
1711              
1712 0 0         BSON_ASSERT (bson);
1713 0 0         BSON_ASSERT (key);
1714 0 0         BSON_ASSERT (value);
1715              
1716 0           switch (value->value_type) {
1717             case BSON_TYPE_DOUBLE:
1718 0           ret = bson_append_double (bson, key, key_length,
1719             value->value.v_double);
1720 0           break;
1721             case BSON_TYPE_UTF8:
1722 0           ret = bson_append_utf8 (bson, key, key_length,
1723 0           value->value.v_utf8.str,
1724 0           value->value.v_utf8.len);
1725 0           break;
1726             case BSON_TYPE_DOCUMENT:
1727 0 0         if (bson_init_static (&local,
1728 0           value->value.v_doc.data,
1729 0           value->value.v_doc.data_len)) {
1730 0           ret = bson_append_document (bson, key, key_length, &local);
1731 0           bson_destroy (&local);
1732             }
1733 0           break;
1734             case BSON_TYPE_ARRAY:
1735 0 0         if (bson_init_static (&local,
1736 0           value->value.v_doc.data,
1737 0           value->value.v_doc.data_len)) {
1738 0           ret = bson_append_array (bson, key, key_length, &local);
1739 0           bson_destroy (&local);
1740             }
1741 0           break;
1742             case BSON_TYPE_BINARY:
1743 0           ret = bson_append_binary (bson, key, key_length,
1744             value->value.v_binary.subtype,
1745 0           value->value.v_binary.data,
1746             value->value.v_binary.data_len);
1747 0           break;
1748             case BSON_TYPE_UNDEFINED:
1749 0           ret = bson_append_undefined (bson, key, key_length);
1750 0           break;
1751             case BSON_TYPE_OID:
1752 0           ret = bson_append_oid (bson, key, key_length, &value->value.v_oid);
1753 0           break;
1754             case BSON_TYPE_BOOL:
1755 0           ret = bson_append_bool (bson, key, key_length, value->value.v_bool);
1756 0           break;
1757             case BSON_TYPE_DATE_TIME:
1758 0           ret = bson_append_date_time (bson, key, key_length,
1759             value->value.v_datetime);
1760 0           break;
1761             case BSON_TYPE_NULL:
1762 0           ret = bson_append_null (bson, key, key_length);
1763 0           break;
1764             case BSON_TYPE_REGEX:
1765 0           ret = bson_append_regex (bson, key, key_length,
1766 0           value->value.v_regex.regex,
1767 0           value->value.v_regex.options);
1768 0           break;
1769             case BSON_TYPE_DBPOINTER:
1770 0           ret = bson_append_dbpointer (bson, key, key_length,
1771 0           value->value.v_dbpointer.collection,
1772             &value->value.v_dbpointer.oid);
1773 0           break;
1774             case BSON_TYPE_CODE:
1775 0           ret = bson_append_code (bson, key, key_length,
1776 0           value->value.v_code.code);
1777 0           break;
1778             case BSON_TYPE_SYMBOL:
1779 0           ret = bson_append_symbol (bson, key, key_length,
1780 0           value->value.v_symbol.symbol,
1781 0           value->value.v_symbol.len);
1782 0           break;
1783             case BSON_TYPE_CODEWSCOPE:
1784 0 0         if (bson_init_static (&local,
1785 0           value->value.v_codewscope.scope_data,
1786 0           value->value.v_codewscope.scope_len)) {
1787 0           ret = bson_append_code_with_scope (bson, key, key_length,
1788 0           value->value.v_codewscope.code,
1789             value->value.v_codewscope.code_len,
1790             &local);
1791 0           bson_destroy (&local);
1792             }
1793 0           break;
1794             case BSON_TYPE_INT32:
1795 0           ret = bson_append_int32 (bson, key, key_length, value->value.v_int32);
1796 0           break;
1797             case BSON_TYPE_TIMESTAMP:
1798 0           ret = bson_append_timestamp (bson, key, key_length,
1799             value->value.v_timestamp.timestamp,
1800             value->value.v_timestamp.increment);
1801 0           break;
1802             case BSON_TYPE_INT64:
1803 0           ret = bson_append_int64 (bson, key, key_length, value->value.v_int64);
1804 0           break;
1805             case BSON_TYPE_DECIMAL128:
1806 0           ret = bson_append_decimal128 (bson, key, key_length, &(value->value.v_decimal128));
1807 0           break;
1808             case BSON_TYPE_MAXKEY:
1809 0           ret = bson_append_maxkey (bson, key, key_length);
1810 0           break;
1811             case BSON_TYPE_MINKEY:
1812 0           ret = bson_append_minkey (bson, key, key_length);
1813 0           break;
1814             case BSON_TYPE_EOD:
1815             default:
1816 0           break;
1817             }
1818              
1819 0           return ret;
1820             }
1821              
1822              
1823             void
1824 106           bson_init (bson_t *bson)
1825             {
1826 106           bson_impl_inline_t *impl = (bson_impl_inline_t *)bson;
1827              
1828 106 50         BSON_ASSERT (bson);
1829              
1830 106           impl->flags = BSON_FLAG_INLINE | BSON_FLAG_STATIC;
1831 106           impl->len = 5;
1832 106           impl->data[0] = 5;
1833 106           impl->data[1] = 0;
1834 106           impl->data[2] = 0;
1835 106           impl->data[3] = 0;
1836 106           impl->data[4] = 0;
1837 106           }
1838              
1839              
1840             void
1841 0           bson_reinit (bson_t *bson)
1842             {
1843             uint8_t *data;
1844              
1845 0 0         BSON_ASSERT (bson);
1846              
1847 0           data = _bson_data (bson);
1848              
1849 0           bson->len = 5;
1850              
1851 0           data [0] = 5;
1852 0           data [1] = 0;
1853 0           data [2] = 0;
1854 0           data [3] = 0;
1855 0           data [4] = 0;
1856 0           }
1857              
1858              
1859             bool
1860 1920           bson_init_static (bson_t *bson,
1861             const uint8_t *data,
1862             size_t length)
1863             {
1864 1920           bson_impl_alloc_t *impl = (bson_impl_alloc_t *)bson;
1865             uint32_t len_le;
1866              
1867 1920 50         BSON_ASSERT (bson);
1868 1920 50         BSON_ASSERT (data);
1869              
1870 1920 100         if ((length < 5) || (length > INT_MAX)) {
    50          
1871 1           return false;
1872             }
1873              
1874 1919           memcpy (&len_le, data, sizeof (len_le));
1875              
1876 1919 100         if ((size_t)BSON_UINT32_FROM_LE (len_le) != length) {
1877 10           return false;
1878             }
1879              
1880 1909 100         if (data[length - 1]) {
1881 5           return false;
1882             }
1883              
1884 1904           impl->flags = BSON_FLAG_STATIC | BSON_FLAG_RDONLY;
1885 1904           impl->len = (uint32_t)length;
1886 1904           impl->parent = NULL;
1887 1904           impl->depth = 0;
1888 1904           impl->buf = &impl->alloc;
1889 1904           impl->buflen = &impl->alloclen;
1890 1904           impl->offset = 0;
1891 1904           impl->alloc = (uint8_t *)data;
1892 1904           impl->alloclen = length;
1893 1904           impl->realloc = NULL;
1894 1904           impl->realloc_func_ctx = NULL;
1895              
1896 1920           return true;
1897             }
1898              
1899              
1900             bson_t *
1901 1979           bson_new (void)
1902             {
1903             bson_impl_inline_t *impl;
1904             bson_t *bson;
1905              
1906 1979           bson = bson_malloc (sizeof *bson);
1907              
1908 1979           impl = (bson_impl_inline_t *)bson;
1909 1979           impl->flags = BSON_FLAG_INLINE;
1910 1979           impl->len = 5;
1911 1979           impl->data[0] = 5;
1912 1979           impl->data[1] = 0;
1913 1979           impl->data[2] = 0;
1914 1979           impl->data[3] = 0;
1915 1979           impl->data[4] = 0;
1916              
1917 1979           return bson;
1918             }
1919              
1920              
1921             bson_t *
1922 106           bson_sized_new (size_t size)
1923             {
1924             bson_impl_alloc_t *impl_a;
1925             bson_impl_inline_t *impl_i;
1926             bson_t *b;
1927              
1928 106 50         BSON_ASSERT (size <= INT32_MAX);
1929              
1930 106           b = bson_malloc (sizeof *b);
1931 106           impl_a = (bson_impl_alloc_t *)b;
1932 106           impl_i = (bson_impl_inline_t *)b;
1933              
1934 106 50         if (size <= sizeof impl_i->data) {
1935 106           bson_init (b);
1936 106           b->flags &= ~BSON_FLAG_STATIC;
1937             } else {
1938 0           impl_a->flags = BSON_FLAG_NONE;
1939 0           impl_a->len = 5;
1940 0           impl_a->parent = NULL;
1941 0           impl_a->depth = 0;
1942 0           impl_a->buf = &impl_a->alloc;
1943 0           impl_a->buflen = &impl_a->alloclen;
1944 0           impl_a->offset = 0;
1945 0           impl_a->alloclen = BSON_MAX (5, size);
1946 0           impl_a->alloc = bson_malloc (impl_a->alloclen);
1947 0           impl_a->alloc[0] = 5;
1948 0           impl_a->alloc[1] = 0;
1949 0           impl_a->alloc[2] = 0;
1950 0           impl_a->alloc[3] = 0;
1951 0           impl_a->alloc[4] = 0;
1952 0           impl_a->realloc = bson_realloc_ctx;
1953 0           impl_a->realloc_func_ctx = NULL;
1954             }
1955              
1956 106           return b;
1957             }
1958              
1959              
1960             bson_t *
1961 106           bson_new_from_data (const uint8_t *data,
1962             size_t length)
1963             {
1964             uint32_t len_le;
1965             bson_t *bson;
1966              
1967 106 50         BSON_ASSERT (data);
1968              
1969 106 50         if ((length < 5) || (length > INT_MAX) || data [length - 1]) {
    50          
    50          
1970 0           return NULL;
1971             }
1972              
1973 106           memcpy (&len_le, data, sizeof (len_le));
1974              
1975 106 50         if (length != (size_t)BSON_UINT32_FROM_LE (len_le)) {
1976 0           return NULL;
1977             }
1978              
1979 106           bson = bson_sized_new (length);
1980 106           memcpy (_bson_data (bson), data, length);
1981 106           bson->len = (uint32_t)length;
1982              
1983 106           return bson;
1984             }
1985              
1986              
1987             bson_t *
1988 0           bson_new_from_buffer (uint8_t **buf,
1989             size_t *buf_len,
1990             bson_realloc_func realloc_func,
1991             void *realloc_func_ctx)
1992             {
1993             bson_impl_alloc_t *impl;
1994             uint32_t len_le;
1995             uint32_t length;
1996             bson_t *bson;
1997              
1998 0 0         BSON_ASSERT (buf);
1999 0 0         BSON_ASSERT (buf_len);
2000              
2001 0 0         if (!realloc_func) {
2002 0           realloc_func = bson_realloc_ctx;
2003             }
2004              
2005 0           bson = bson_malloc0 (sizeof *bson);
2006 0           impl = (bson_impl_alloc_t *)bson;
2007              
2008 0 0         if (!*buf) {
2009 0           length = 5;
2010 0           len_le = BSON_UINT32_TO_LE (length);
2011 0           *buf_len = 5;
2012 0           *buf = realloc_func (*buf, *buf_len, realloc_func_ctx);
2013 0           memcpy (*buf, &len_le, sizeof (len_le));
2014 0           (*buf) [4] = '\0';
2015             } else {
2016 0 0         if ((*buf_len < 5) || (*buf_len > INT_MAX)) {
    0          
2017 0           bson_free (bson);
2018 0           return NULL;
2019             }
2020              
2021 0           memcpy (&len_le, *buf, sizeof (len_le));
2022 0           length = BSON_UINT32_FROM_LE(len_le);
2023             }
2024              
2025 0 0         if ((*buf)[length - 1]) {
2026 0           bson_free (bson);
2027 0           return NULL;
2028             }
2029              
2030 0           impl->flags = BSON_FLAG_NO_FREE;
2031 0           impl->len = length;
2032 0           impl->buf = buf;
2033 0           impl->buflen = buf_len;
2034 0           impl->realloc = realloc_func;
2035 0           impl->realloc_func_ctx = realloc_func_ctx;
2036              
2037 0           return bson;
2038             }
2039              
2040              
2041             bson_t *
2042 0           bson_copy (const bson_t *bson)
2043             {
2044             const uint8_t *data;
2045              
2046 0 0         BSON_ASSERT (bson);
2047              
2048 0           data = _bson_data (bson);
2049 0           return bson_new_from_data (data, bson->len);
2050             }
2051              
2052              
2053             void
2054 0           bson_copy_to (const bson_t *src,
2055             bson_t *dst)
2056             {
2057             const uint8_t *data;
2058             bson_impl_alloc_t *adst;
2059             size_t len;
2060              
2061 0 0         BSON_ASSERT (src);
2062 0 0         BSON_ASSERT (dst);
2063              
2064 0 0         if ((src->flags & BSON_FLAG_INLINE)) {
2065 0           memcpy (dst, src, sizeof *dst);
2066 0           dst->flags = (BSON_FLAG_STATIC | BSON_FLAG_INLINE);
2067 0           return;
2068             }
2069              
2070 0           data = _bson_data (src);
2071 0           len = bson_next_power_of_two ((size_t)src->len);
2072              
2073 0           adst = (bson_impl_alloc_t *)dst;
2074 0           adst->flags = BSON_FLAG_STATIC;
2075 0           adst->len = src->len;
2076 0           adst->parent = NULL;
2077 0           adst->depth = 0;
2078 0           adst->buf = &adst->alloc;
2079 0           adst->buflen = &adst->alloclen;
2080 0           adst->offset = 0;
2081 0           adst->alloc = bson_malloc (len);
2082 0           adst->alloclen = len;
2083 0           adst->realloc = bson_realloc_ctx;
2084 0           adst->realloc_func_ctx = NULL;
2085 0           memcpy (adst->alloc, data, src->len);
2086             }
2087              
2088              
2089             static bool
2090 0           should_ignore (const char *first_exclude,
2091             va_list args,
2092             const char *name)
2093             {
2094 0           bool ret = false;
2095 0           const char *exclude = first_exclude;
2096             va_list args_copy;
2097              
2098 0           va_copy (args_copy, args);
2099              
2100             do {
2101 0 0         if (!strcmp (name, exclude)) {
2102 0           ret = true;
2103 0           break;
2104             }
2105 0 0         } while ((exclude = va_arg (args_copy, const char *)));
    0          
2106              
2107 0           va_end (args_copy);
2108              
2109 0           return ret;
2110             }
2111              
2112              
2113             static void
2114 0           _bson_copy_to_excluding_va (const bson_t *src,
2115             bson_t *dst,
2116             const char *first_exclude,
2117             va_list args)
2118             {
2119             bson_iter_t iter;
2120              
2121 0 0         if (bson_iter_init (&iter, src)) {
2122 0 0         while (bson_iter_next (&iter)) {
2123 0 0         if (!should_ignore (first_exclude, args, bson_iter_key (&iter))) {
2124 0 0         if (!bson_append_iter (dst, NULL, 0, &iter)) {
2125             /*
2126             * This should not be able to happen since we are copying
2127             * from within a valid bson_t.
2128             */
2129 0           BSON_ASSERT (false);
2130             return;
2131             }
2132             }
2133             }
2134             }
2135             }
2136              
2137              
2138             void
2139 0           bson_copy_to_excluding (const bson_t *src,
2140             bson_t *dst,
2141             const char *first_exclude,
2142             ...)
2143             {
2144             va_list args;
2145              
2146 0 0         BSON_ASSERT (src);
2147 0 0         BSON_ASSERT (dst);
2148 0 0         BSON_ASSERT (first_exclude);
2149              
2150 0           bson_init (dst);
2151              
2152 0           va_start (args, first_exclude);
2153 0           _bson_copy_to_excluding_va (src, dst, first_exclude, args);
2154 0           va_end (args);
2155 0           }
2156              
2157             void
2158 0           bson_copy_to_excluding_noinit (const bson_t *src,
2159             bson_t *dst,
2160             const char *first_exclude,
2161             ...)
2162             {
2163             va_list args;
2164              
2165 0 0         BSON_ASSERT (src);
2166 0 0         BSON_ASSERT (dst);
2167 0 0         BSON_ASSERT (first_exclude);
2168              
2169 0           va_start (args, first_exclude);
2170 0           _bson_copy_to_excluding_va (src, dst, first_exclude, args);
2171 0           va_end (args);
2172 0           }
2173              
2174              
2175             void
2176 2074           bson_destroy (bson_t *bson)
2177             {
2178 2074 50         BSON_ASSERT (bson);
2179              
2180 2074 100         if (!(bson->flags &
2181             (BSON_FLAG_RDONLY | BSON_FLAG_INLINE | BSON_FLAG_NO_FREE))) {
2182 60           bson_free (*((bson_impl_alloc_t *)bson)->buf);
2183             }
2184              
2185 2074 50         if (!(bson->flags & BSON_FLAG_STATIC)) {
2186 2074           bson_free (bson);
2187             }
2188 2074           }
2189              
2190              
2191             bool
2192 0           bson_steal (bson_t *dst,
2193             bson_t *src)
2194             {
2195             bson_impl_inline_t *src_inline;
2196             bson_impl_inline_t *dst_inline;
2197             bson_impl_alloc_t *alloc;
2198              
2199 0 0         BSON_ASSERT (dst);
2200 0 0         BSON_ASSERT (src);
2201              
2202 0           bson_init (dst);
2203              
2204 0 0         if (src->flags & (BSON_FLAG_CHILD | BSON_FLAG_IN_CHILD | BSON_FLAG_RDONLY)) {
2205 0           return false;
2206             }
2207              
2208 0 0         if (src->flags & BSON_FLAG_INLINE) {
2209 0           src_inline = (bson_impl_inline_t *) src;
2210 0           dst_inline = (bson_impl_inline_t *) dst;
2211 0           dst_inline->len = src_inline->len;
2212 0           memcpy (dst_inline->data, src_inline->data, sizeof src_inline->data);
2213              
2214             /* for consistency, src is always invalid after steal, even if inline */
2215 0           src->len = 0;
2216             } else {
2217 0           memcpy (dst, src, sizeof (bson_t));
2218 0           alloc = (bson_impl_alloc_t *) dst;
2219 0           alloc->flags |= BSON_FLAG_STATIC;
2220 0           alloc->buf = &alloc->alloc;
2221 0           alloc->buflen = &alloc->alloclen;
2222             }
2223              
2224 0 0         if (!(src->flags & BSON_FLAG_STATIC)) {
2225 0           bson_free (src);
2226             } else {
2227             /* src is invalid after steal */
2228 0           src->len = 0;
2229             }
2230              
2231 0           return true;
2232             }
2233              
2234              
2235             uint8_t *
2236 0           bson_destroy_with_steal (bson_t *bson,
2237             bool steal,
2238             uint32_t *length)
2239             {
2240 0           uint8_t *ret = NULL;
2241              
2242 0 0         BSON_ASSERT (bson);
2243              
2244 0 0         if (length) {
2245 0           *length = bson->len;
2246             }
2247              
2248 0 0         if (!steal) {
2249 0           bson_destroy (bson);
2250 0           return NULL;
2251             }
2252              
2253 0 0         if ((bson->flags & (BSON_FLAG_CHILD |
2254             BSON_FLAG_IN_CHILD |
2255             BSON_FLAG_RDONLY))) {
2256             /* Do nothing */
2257 0 0         } else if ((bson->flags & BSON_FLAG_INLINE)) {
2258             bson_impl_inline_t *inl;
2259              
2260 0           inl = (bson_impl_inline_t *)bson;
2261 0           ret = bson_malloc (bson->len);
2262 0           memcpy (ret, inl->data, bson->len);
2263             } else {
2264             bson_impl_alloc_t *alloc;
2265              
2266 0           alloc = (bson_impl_alloc_t *)bson;
2267 0           ret = *alloc->buf;
2268 0           *alloc->buf = NULL;
2269             }
2270              
2271 0           bson_destroy (bson);
2272              
2273 0           return ret;
2274             }
2275              
2276              
2277             const uint8_t *
2278 7054           bson_get_data (const bson_t *bson)
2279             {
2280 7054 50         BSON_ASSERT (bson);
2281              
2282 7054           return _bson_data (bson);
2283             }
2284              
2285              
2286             uint32_t
2287 0           bson_count_keys (const bson_t *bson)
2288             {
2289 0           uint32_t count = 0;
2290             bson_iter_t iter;
2291              
2292 0 0         BSON_ASSERT (bson);
2293              
2294 0 0         if (bson_iter_init (&iter, bson)) {
2295 0 0         while (bson_iter_next (&iter)) {
2296 0           count++;
2297             }
2298             }
2299              
2300 0           return count;
2301             }
2302              
2303              
2304             bool
2305 0           bson_has_field (const bson_t *bson,
2306             const char *key)
2307             {
2308             bson_iter_t iter;
2309             bson_iter_t child;
2310              
2311 0 0         BSON_ASSERT (bson);
2312 0 0         BSON_ASSERT (key);
2313              
2314 0 0         if (NULL != strchr (key, '.')) {
2315 0           return (bson_iter_init (&iter, bson) &&
2316 0           bson_iter_find_descendant (&iter, key, &child));
2317             }
2318              
2319 0           return bson_iter_init_find (&iter, bson, key);
2320             }
2321              
2322              
2323             int
2324 0           bson_compare (const bson_t *bson,
2325             const bson_t *other)
2326             {
2327             const uint8_t *data1;
2328             const uint8_t *data2;
2329             size_t len1;
2330             size_t len2;
2331             int64_t ret;
2332              
2333 0           data1 = _bson_data (bson) + 4;
2334 0           len1 = bson->len - 4;
2335              
2336 0           data2 = _bson_data (other) + 4;
2337 0           len2 = other->len - 4;
2338              
2339 0 0         if (len1 == len2) {
2340 0           return memcmp (data1, data2, len1);
2341             }
2342              
2343 0           ret = memcmp (data1, data2, BSON_MIN (len1, len2));
2344              
2345 0 0         if (ret == 0) {
2346 0           ret = (int64_t) (len1 - len2);
2347             }
2348              
2349 0 0         return (ret < 0) ? -1 : (ret > 0);
2350             }
2351              
2352              
2353             bool
2354 0           bson_equal (const bson_t *bson,
2355             const bson_t *other)
2356             {
2357 0           return !bson_compare (bson, other);
2358             }
2359              
2360              
2361             static bool
2362 0           _bson_as_json_visit_utf8 (const bson_iter_t *iter,
2363             const char *key,
2364             size_t v_utf8_len,
2365             const char *v_utf8,
2366             void *data)
2367             {
2368 0           bson_json_state_t *state = data;
2369             char *escaped;
2370              
2371 0           escaped = bson_utf8_escape_for_json (v_utf8, v_utf8_len);
2372              
2373 0 0         if (escaped) {
2374 0           bson_string_append (state->str, "\"");
2375 0           bson_string_append (state->str, escaped);
2376 0           bson_string_append (state->str, "\"");
2377 0           bson_free (escaped);
2378 0           return false;
2379             }
2380              
2381 0           return true;
2382             }
2383              
2384              
2385             static bool
2386 0           _bson_as_json_visit_int32 (const bson_iter_t *iter,
2387             const char *key,
2388             int32_t v_int32,
2389             void *data)
2390             {
2391 0           bson_json_state_t *state = data;
2392              
2393 0           bson_string_append_printf (state->str, "%" PRId32, v_int32);
2394              
2395 0           return false;
2396             }
2397              
2398              
2399             static bool
2400 0           _bson_as_json_visit_int64 (const bson_iter_t *iter,
2401             const char *key,
2402             int64_t v_int64,
2403             void *data)
2404             {
2405 0           bson_json_state_t *state = data;
2406              
2407 0           bson_string_append_printf (state->str, "%" PRId64, v_int64);
2408              
2409 0           return false;
2410             }
2411              
2412              
2413             static bool
2414 0           _bson_as_json_visit_decimal128 (const bson_iter_t *iter,
2415             const char *key,
2416             const bson_decimal128_t *value,
2417             void *data)
2418             {
2419 0           bson_json_state_t *state = data;
2420             char decimal128_string[BSON_DECIMAL128_STRING];
2421 0           bson_decimal128_to_string(value, decimal128_string);
2422              
2423 0           bson_string_append (state->str, "{ \"$numberDecimal\" : \"");
2424 0           bson_string_append (state->str, decimal128_string);
2425 0           bson_string_append (state->str, "\" }");
2426              
2427 0           return false;
2428             }
2429              
2430              
2431             static bool
2432 0           _bson_as_json_visit_double (const bson_iter_t *iter,
2433             const char *key,
2434             double v_double,
2435             void *data)
2436             {
2437 0           bson_json_state_t *state = data;
2438              
2439             #ifdef BSON_NEEDS_SET_OUTPUT_FORMAT
2440             unsigned int current_format = _set_output_format(_TWO_DIGIT_EXPONENT);
2441             #endif
2442              
2443 0           bson_string_append_printf (state->str, "%.15g", v_double);
2444              
2445             #ifdef BSON_NEEDS_SET_OUTPUT_FORMAT
2446             _set_output_format(current_format);
2447             #endif
2448              
2449 0           return false;
2450             }
2451              
2452              
2453             static bool
2454 0           _bson_as_json_visit_undefined (const bson_iter_t *iter,
2455             const char *key,
2456             void *data)
2457             {
2458 0           bson_json_state_t *state = data;
2459              
2460 0           bson_string_append (state->str, "{ \"$undefined\" : true }");
2461              
2462 0           return false;
2463             }
2464              
2465              
2466             static bool
2467 0           _bson_as_json_visit_null (const bson_iter_t *iter,
2468             const char *key,
2469             void *data)
2470             {
2471 0           bson_json_state_t *state = data;
2472              
2473 0           bson_string_append (state->str, "null");
2474              
2475 0           return false;
2476             }
2477              
2478              
2479             static bool
2480 0           _bson_as_json_visit_oid (const bson_iter_t *iter,
2481             const char *key,
2482             const bson_oid_t *oid,
2483             void *data)
2484             {
2485 0           bson_json_state_t *state = data;
2486             char str[25];
2487              
2488 0           bson_oid_to_string (oid, str);
2489 0           bson_string_append (state->str, "{ \"$oid\" : \"");
2490 0           bson_string_append (state->str, str);
2491 0           bson_string_append (state->str, "\" }");
2492              
2493 0           return false;
2494             }
2495              
2496              
2497             static bool
2498 0           _bson_as_json_visit_binary (const bson_iter_t *iter,
2499             const char *key,
2500             bson_subtype_t v_subtype,
2501             size_t v_binary_len,
2502             const uint8_t *v_binary,
2503             void *data)
2504             {
2505 0           bson_json_state_t *state = data;
2506             size_t b64_len;
2507             char *b64;
2508              
2509 0           b64_len = (v_binary_len / 3 + 1) * 4 + 1;
2510 0           b64 = bson_malloc0 (b64_len);
2511 0           b64_ntop (v_binary, v_binary_len, b64, b64_len);
2512              
2513 0           bson_string_append (state->str, "{ \"$type\" : \"");
2514 0           bson_string_append_printf (state->str, "%02x", v_subtype);
2515 0           bson_string_append (state->str, "\", \"$binary\" : \"");
2516 0           bson_string_append (state->str, b64);
2517 0           bson_string_append (state->str, "\" }");
2518 0           bson_free (b64);
2519              
2520 0           return false;
2521             }
2522              
2523              
2524             static bool
2525 0           _bson_as_json_visit_bool (const bson_iter_t *iter,
2526             const char *key,
2527             bool v_bool,
2528             void *data)
2529             {
2530 0           bson_json_state_t *state = data;
2531              
2532 0 0         bson_string_append (state->str, v_bool ? "true" : "false");
2533              
2534 0           return false;
2535             }
2536              
2537              
2538             static bool
2539 0           _bson_as_json_visit_date_time (const bson_iter_t *iter,
2540             const char *key,
2541             int64_t msec_since_epoch,
2542             void *data)
2543             {
2544 0           bson_json_state_t *state = data;
2545              
2546 0           bson_string_append (state->str, "{ \"$date\" : ");
2547 0           bson_string_append_printf (state->str, "%" PRId64, msec_since_epoch);
2548 0           bson_string_append (state->str, " }");
2549              
2550 0           return false;
2551             }
2552              
2553              
2554             static bool
2555 0           _bson_as_json_visit_regex (const bson_iter_t *iter,
2556             const char *key,
2557             const char *v_regex,
2558             const char *v_options,
2559             void *data)
2560             {
2561 0           bson_json_state_t *state = data;
2562              
2563 0           bson_string_append (state->str, "{ \"$regex\" : \"");
2564 0           bson_string_append (state->str, v_regex);
2565 0           bson_string_append (state->str, "\", \"$options\" : \"");
2566 0           bson_string_append (state->str, v_options);
2567 0           bson_string_append (state->str, "\" }");
2568              
2569 0           return false;
2570             }
2571              
2572              
2573             static bool
2574 0           _bson_as_json_visit_timestamp (const bson_iter_t *iter,
2575             const char *key,
2576             uint32_t v_timestamp,
2577             uint32_t v_increment,
2578             void *data)
2579             {
2580 0           bson_json_state_t *state = data;
2581              
2582 0           bson_string_append (state->str, "{ \"$timestamp\" : { \"t\" : ");
2583 0           bson_string_append_printf (state->str, "%u", v_timestamp);
2584 0           bson_string_append (state->str, ", \"i\" : ");
2585 0           bson_string_append_printf (state->str, "%u", v_increment);
2586 0           bson_string_append (state->str, " } }");
2587              
2588 0           return false;
2589             }
2590              
2591              
2592             static bool
2593 0           _bson_as_json_visit_dbpointer (const bson_iter_t *iter,
2594             const char *key,
2595             size_t v_collection_len,
2596             const char *v_collection,
2597             const bson_oid_t *v_oid,
2598             void *data)
2599             {
2600 0           bson_json_state_t *state = data;
2601             char str[25];
2602              
2603 0           bson_string_append (state->str, "{ \"$ref\" : \"");
2604 0           bson_string_append (state->str, v_collection);
2605 0           bson_string_append (state->str, "\"");
2606              
2607 0 0         if (v_oid) {
2608 0           bson_oid_to_string (v_oid, str);
2609 0           bson_string_append (state->str, ", \"$id\" : \"");
2610 0           bson_string_append (state->str, str);
2611 0           bson_string_append (state->str, "\"");
2612             }
2613              
2614 0           bson_string_append (state->str, " }");
2615              
2616 0           return false;
2617             }
2618              
2619              
2620             static bool
2621 0           _bson_as_json_visit_minkey (const bson_iter_t *iter,
2622             const char *key,
2623             void *data)
2624             {
2625 0           bson_json_state_t *state = data;
2626              
2627 0           bson_string_append (state->str, "{ \"$minKey\" : 1 }");
2628              
2629 0           return false;
2630             }
2631              
2632              
2633             static bool
2634 0           _bson_as_json_visit_maxkey (const bson_iter_t *iter,
2635             const char *key,
2636             void *data)
2637             {
2638 0           bson_json_state_t *state = data;
2639              
2640 0           bson_string_append (state->str, "{ \"$maxKey\" : 1 }");
2641              
2642 0           return false;
2643             }
2644              
2645              
2646              
2647              
2648             static bool
2649 0           _bson_as_json_visit_before (const bson_iter_t *iter,
2650             const char *key,
2651             void *data)
2652             {
2653 0           bson_json_state_t *state = data;
2654             char *escaped;
2655              
2656 0 0         if (state->count) {
2657 0           bson_string_append (state->str, ", ");
2658             }
2659              
2660 0 0         if (state->keys) {
2661 0           escaped = bson_utf8_escape_for_json (key, -1);
2662 0 0         if (escaped) {
2663 0           bson_string_append (state->str, "\"");
2664 0           bson_string_append (state->str, escaped);
2665 0           bson_string_append (state->str, "\" : ");
2666 0           bson_free (escaped);
2667             } else {
2668 0           return true;
2669             }
2670             }
2671              
2672 0           state->count++;
2673              
2674 0           return false;
2675             }
2676              
2677              
2678             static bool
2679 0           _bson_as_json_visit_code (const bson_iter_t *iter,
2680             const char *key,
2681             size_t v_code_len,
2682             const char *v_code,
2683             void *data)
2684             {
2685 0           bson_json_state_t *state = data;
2686             char *escaped;
2687              
2688 0           escaped = bson_utf8_escape_for_json (v_code, v_code_len);
2689              
2690 0 0         if (escaped) {
2691 0           bson_string_append (state->str, "\"");
2692 0           bson_string_append (state->str, escaped);
2693 0           bson_string_append (state->str, "\"");
2694 0           bson_free (escaped);
2695 0           return false;
2696             }
2697              
2698 0           return true;
2699             }
2700              
2701              
2702             static bool
2703 0           _bson_as_json_visit_symbol (const bson_iter_t *iter,
2704             const char *key,
2705             size_t v_symbol_len,
2706             const char *v_symbol,
2707             void *data)
2708             {
2709 0           bson_json_state_t *state = data;
2710              
2711 0           bson_string_append (state->str, "\"");
2712 0           bson_string_append (state->str, v_symbol);
2713 0           bson_string_append (state->str, "\"");
2714              
2715 0           return false;
2716             }
2717              
2718              
2719             static bool
2720 0           _bson_as_json_visit_codewscope (const bson_iter_t *iter,
2721             const char *key,
2722             size_t v_code_len,
2723             const char *v_code,
2724             const bson_t *v_scope,
2725             void *data)
2726             {
2727 0           bson_json_state_t *state = data;
2728             char *escaped;
2729              
2730 0           escaped = bson_utf8_escape_for_json (v_code, v_code_len);
2731              
2732 0 0         if (escaped) {
2733 0           bson_string_append (state->str, "\"");
2734 0           bson_string_append (state->str, escaped);
2735 0           bson_string_append (state->str, "\"");
2736 0           bson_free (escaped);
2737 0           return false;
2738             }
2739              
2740 0           return true;
2741             }
2742              
2743              
2744             static const bson_visitor_t bson_as_json_visitors = {
2745             _bson_as_json_visit_before,
2746             NULL, /* visit_after */
2747             NULL, /* visit_corrupt */
2748             _bson_as_json_visit_double,
2749             _bson_as_json_visit_utf8,
2750             _bson_as_json_visit_document,
2751             _bson_as_json_visit_array,
2752             _bson_as_json_visit_binary,
2753             _bson_as_json_visit_undefined,
2754             _bson_as_json_visit_oid,
2755             _bson_as_json_visit_bool,
2756             _bson_as_json_visit_date_time,
2757             _bson_as_json_visit_null,
2758             _bson_as_json_visit_regex,
2759             _bson_as_json_visit_dbpointer,
2760             _bson_as_json_visit_code,
2761             _bson_as_json_visit_symbol,
2762             _bson_as_json_visit_codewscope,
2763             _bson_as_json_visit_int32,
2764             _bson_as_json_visit_timestamp,
2765             _bson_as_json_visit_int64,
2766             _bson_as_json_visit_maxkey,
2767             _bson_as_json_visit_minkey,
2768             NULL, /* visit_unsupported_type */
2769             _bson_as_json_visit_decimal128,
2770             };
2771              
2772              
2773             static bool
2774 0           _bson_as_json_visit_document (const bson_iter_t *iter,
2775             const char *key,
2776             const bson_t *v_document,
2777             void *data)
2778             {
2779 0           bson_json_state_t *state = data;
2780 0           bson_json_state_t child_state = { 0, true };
2781             bson_iter_t child;
2782              
2783 0 0         if (state->depth >= BSON_MAX_RECURSION) {
2784 0           bson_string_append (state->str, "{ ... }");
2785 0           return false;
2786             }
2787              
2788 0 0         if (bson_iter_init (&child, v_document)) {
2789 0           child_state.str = bson_string_new ("{ ");
2790 0           child_state.depth = state->depth + 1;
2791 0           bson_iter_visit_all (&child, &bson_as_json_visitors, &child_state);
2792 0           bson_string_append (child_state.str, " }");
2793 0           bson_string_append (state->str, child_state.str->str);
2794 0           bson_string_free (child_state.str, true);
2795             }
2796              
2797 0           return false;
2798             }
2799              
2800              
2801             static bool
2802 0           _bson_as_json_visit_array (const bson_iter_t *iter,
2803             const char *key,
2804             const bson_t *v_array,
2805             void *data)
2806             {
2807 0           bson_json_state_t *state = data;
2808 0           bson_json_state_t child_state = { 0, false };
2809             bson_iter_t child;
2810              
2811 0 0         if (state->depth >= BSON_MAX_RECURSION) {
2812 0           bson_string_append (state->str, "{ ... }");
2813 0           return false;
2814             }
2815              
2816 0 0         if (bson_iter_init (&child, v_array)) {
2817 0           child_state.str = bson_string_new ("[ ");
2818 0           child_state.depth = state->depth + 1;
2819 0           bson_iter_visit_all (&child, &bson_as_json_visitors, &child_state);
2820 0           bson_string_append (child_state.str, " ]");
2821 0           bson_string_append (state->str, child_state.str->str);
2822 0           bson_string_free (child_state.str, true);
2823             }
2824              
2825 0           return false;
2826             }
2827              
2828              
2829             char *
2830 0           bson_as_json (const bson_t *bson,
2831             size_t *length)
2832             {
2833             bson_json_state_t state;
2834             bson_iter_t iter;
2835              
2836 0 0         BSON_ASSERT (bson);
2837              
2838 0 0         if (length) {
2839 0           *length = 0;
2840             }
2841              
2842 0 0         if (bson_empty0 (bson)) {
    0          
    0          
2843 0 0         if (length) {
2844 0           *length = 3;
2845             }
2846              
2847 0           return bson_strdup ("{ }");
2848             }
2849              
2850 0 0         if (!bson_iter_init (&iter, bson)) {
2851 0           return NULL;
2852             }
2853              
2854 0           state.count = 0;
2855 0           state.keys = true;
2856 0           state.str = bson_string_new ("{ ");
2857 0           state.depth = 0;
2858              
2859 0 0         if (bson_iter_visit_all (&iter, &bson_as_json_visitors, &state) ||
    0          
2860 0           iter.err_off) {
2861             /*
2862             * We were prematurely exited due to corruption or failed visitor.
2863             */
2864 0           bson_string_free (state.str, true);
2865 0 0         if (length) {
2866 0           *length = 0;
2867             }
2868 0           return NULL;
2869             }
2870              
2871 0           bson_string_append (state.str, " }");
2872              
2873 0 0         if (length) {
2874 0           *length = state.str->len;
2875             }
2876              
2877 0           return bson_string_free (state.str, false);
2878             }
2879              
2880              
2881             char *
2882 0           bson_array_as_json (const bson_t *bson,
2883             size_t *length)
2884             {
2885             bson_json_state_t state;
2886             bson_iter_t iter;
2887              
2888 0 0         BSON_ASSERT (bson);
2889              
2890 0 0         if (length) {
2891 0           *length = 0;
2892             }
2893              
2894 0 0         if (bson_empty0 (bson)) {
    0          
    0          
2895 0 0         if (length) {
2896 0           *length = 3;
2897             }
2898              
2899 0           return bson_strdup ("[ ]");
2900             }
2901              
2902 0 0         if (!bson_iter_init (&iter, bson)) {
2903 0           return NULL;
2904             }
2905              
2906 0           state.count = 0;
2907 0           state.keys = false;
2908 0           state.str = bson_string_new ("[ ");
2909 0           state.depth = 0;
2910 0           bson_iter_visit_all (&iter, &bson_as_json_visitors, &state);
2911              
2912 0 0         if (bson_iter_visit_all (&iter, &bson_as_json_visitors, &state) ||
    0          
2913 0           iter.err_off) {
2914             /*
2915             * We were prematurely exited due to corruption or failed visitor.
2916             */
2917 0           bson_string_free (state.str, true);
2918 0 0         if (length) {
2919 0           *length = 0;
2920             }
2921 0           return NULL;
2922             }
2923              
2924 0           bson_string_append (state.str, " ]");
2925              
2926 0 0         if (length) {
2927 0           *length = state.str->len;
2928             }
2929              
2930 0           return bson_string_free (state.str, false);
2931             }
2932              
2933              
2934             static bool
2935 99           _bson_iter_validate_utf8 (const bson_iter_t *iter,
2936             const char *key,
2937             size_t v_utf8_len,
2938             const char *v_utf8,
2939             void *data)
2940             {
2941 99           bson_validate_state_t *state = data;
2942             bool allow_null;
2943              
2944 99 50         if ((state->flags & BSON_VALIDATE_UTF8)) {
2945 0           allow_null = !!(state->flags & BSON_VALIDATE_UTF8_ALLOW_NULL);
2946              
2947 0 0         if (!bson_utf8_validate (v_utf8, v_utf8_len, allow_null)) {
2948 0           state->err_offset = iter->off;
2949 0           return true;
2950             }
2951             }
2952              
2953 99 50         if ((state->flags & BSON_VALIDATE_DOLLAR_KEYS)) {
2954 0 0         if (state->phase == BSON_VALIDATE_PHASE_LF_REF_UTF8) {
2955 0           state->phase = BSON_VALIDATE_PHASE_LF_ID_KEY;
2956 0 0         } else if (state->phase == BSON_VALIDATE_PHASE_LF_DB_UTF8) {
2957 0           state->phase = BSON_VALIDATE_PHASE_NOT_DBREF;
2958             }
2959             }
2960              
2961 99           return false;
2962             }
2963              
2964              
2965             static void
2966 49           _bson_iter_validate_corrupt (const bson_iter_t *iter,
2967             void *data)
2968             {
2969 49           bson_validate_state_t *state = data;
2970              
2971 49           state->err_offset = iter->err_off;
2972 49           }
2973              
2974              
2975             static bool
2976 1885           _bson_iter_validate_before (const bson_iter_t *iter,
2977             const char *key,
2978             void *data)
2979             {
2980 1885           bson_validate_state_t *state = data;
2981              
2982 1885 50         if ((state->flags & BSON_VALIDATE_DOLLAR_KEYS)) {
2983 0 0         if (key[0] == '$') {
2984 0 0         if (state->phase == BSON_VALIDATE_PHASE_LF_REF_KEY &&
    0          
2985 0           strcmp (key, "$ref") == 0) {
2986 0           state->phase = BSON_VALIDATE_PHASE_LF_REF_UTF8;
2987 0 0         } else if (state->phase == BSON_VALIDATE_PHASE_LF_ID_KEY &&
    0          
2988 0           strcmp (key, "$id") == 0) {
2989 0           state->phase = BSON_VALIDATE_PHASE_LF_DB_KEY;
2990 0 0         } else if (state->phase == BSON_VALIDATE_PHASE_LF_DB_KEY &&
    0          
2991 0           strcmp (key, "$db") == 0) {
2992 0           state->phase = BSON_VALIDATE_PHASE_LF_DB_UTF8;
2993             } else {
2994 0           state->err_offset = iter->off;
2995 0           return true;
2996             }
2997 0 0         } else if (state->phase == BSON_VALIDATE_PHASE_LF_ID_KEY ||
    0          
2998 0 0         state->phase == BSON_VALIDATE_PHASE_LF_REF_UTF8 ||
2999 0           state->phase == BSON_VALIDATE_PHASE_LF_DB_UTF8) {
3000 0           state->err_offset = iter->off;
3001 0           return true;
3002             } else {
3003 0           state->phase = BSON_VALIDATE_PHASE_NOT_DBREF;
3004             }
3005             }
3006              
3007 1885 50         if ((state->flags & BSON_VALIDATE_DOT_KEYS)) {
3008 0 0         if (strstr (key, ".")) {
3009 0           state->err_offset = iter->off;
3010 0           return true;
3011             }
3012             }
3013              
3014 1885           return false;
3015             }
3016              
3017              
3018             static bool
3019 15           _bson_iter_validate_codewscope (const bson_iter_t *iter,
3020             const char *key,
3021             size_t v_code_len,
3022             const char *v_code,
3023             const bson_t *v_scope,
3024             void *data)
3025             {
3026 15           bson_validate_state_t *state = data;
3027             size_t offset;
3028              
3029 15 100         if (!bson_validate (v_scope, state->flags, &offset, NULL, NULL)) {
3030 1           state->err_offset = iter->off + offset;
3031 1           return false;
3032             }
3033              
3034 15           return true;
3035             }
3036              
3037             static void
3038 5           _bson_iter_record_unsupported_type (const bson_iter_t *iter,
3039             const char *key,
3040             uint32_t type_code,
3041             void *data)
3042             {
3043 5           bson_validate_state_t *state = data;
3044 5           state->invalid_key = key;
3045 5           state->invalid_type = type_code;
3046 5           }
3047              
3048             static bool
3049             _bson_iter_validate_document (const bson_iter_t *iter,
3050             const char *key,
3051             const bson_t *v_document,
3052             void *data);
3053              
3054              
3055             static const bson_visitor_t bson_validate_funcs = {
3056             _bson_iter_validate_before,
3057             NULL, /* visit_after */
3058             _bson_iter_validate_corrupt,
3059             NULL, /* visit_double */
3060             _bson_iter_validate_utf8,
3061             _bson_iter_validate_document,
3062             _bson_iter_validate_document, /* visit_array */
3063             NULL, /* visit_binary */
3064             NULL, /* visit_undefined */
3065             NULL, /* visit_oid */
3066             NULL, /* visit_bool */
3067             NULL, /* visit_date_time */
3068             NULL, /* visit_null */
3069             NULL, /* visit_regex */
3070             NULL, /* visit_dbpoint */
3071             NULL, /* visit_code */
3072             NULL, /* visit_symbol */
3073             _bson_iter_validate_codewscope,
3074             NULL, /* visit_int32 */
3075             NULL, /* visit_timestamp */
3076             NULL, /* visit_int64 */
3077             NULL, /* visit_maxkey */
3078             NULL, /* visit_minkey */
3079             _bson_iter_record_unsupported_type,
3080             NULL, /* visit_decimal128 */
3081             };
3082              
3083              
3084             static bool
3085 1890           _bson_iter_validate_document (const bson_iter_t *iter,
3086             const char *key,
3087             const bson_t *v_document,
3088             void *data)
3089             {
3090 1890           bson_validate_state_t *state = data;
3091             bson_iter_t child;
3092 1890           bson_validate_phase_t phase = state->phase;
3093              
3094 1890 50         if (!bson_iter_init (&child, v_document)) {
3095 0           state->err_offset = iter->off;
3096 0           return true;
3097             }
3098              
3099 1890 100         if (state->phase == BSON_VALIDATE_PHASE_START) {
3100 1631           state->phase = BSON_VALIDATE_PHASE_TOP;
3101             } else {
3102 259           state->phase = BSON_VALIDATE_PHASE_LF_REF_KEY;
3103             }
3104              
3105 1890           bson_iter_visit_all (&child, &bson_validate_funcs, state);
3106              
3107 1890 50         if (state->phase == BSON_VALIDATE_PHASE_LF_ID_KEY ||
    50          
3108 1890 50         state->phase == BSON_VALIDATE_PHASE_LF_REF_UTF8 ||
3109 1890           state->phase == BSON_VALIDATE_PHASE_LF_DB_UTF8) {
3110 0           state->err_offset = iter->off;
3111 0           return true;
3112             }
3113              
3114 1890           state->phase = phase;
3115              
3116 1890           return false;
3117             }
3118              
3119              
3120             bool
3121 1631           bson_validate (const bson_t *bson,
3122             bson_validate_flags_t flags,
3123             size_t *offset,
3124             const char **invalid_key,
3125             uint32_t *invalid_type)
3126             {
3127 1631           bson_validate_state_t state = { flags, -1, BSON_VALIDATE_PHASE_START };
3128             bson_iter_t iter;
3129              
3130 1631 50         if (!bson_iter_init (&iter, bson)) {
3131 0           state.err_offset = 0;
3132 0           goto failure;
3133             }
3134              
3135 1631           _bson_iter_validate_document (&iter, NULL, bson, &state);
3136              
3137             failure:
3138              
3139 1631 50         if (offset) {
3140 1631           *offset = state.err_offset;
3141             }
3142 1631 100         if (invalid_key) {
3143 1616           *invalid_key = state.invalid_key;
3144             }
3145 1631 100         if (invalid_type) {
3146 1616           *invalid_type = state.invalid_type;
3147             }
3148              
3149 1631           return state.err_offset < 0;
3150             }
3151              
3152              
3153             bool
3154 2           bson_concat (bson_t *dst,
3155             const bson_t *src)
3156             {
3157 2 50         BSON_ASSERT (dst);
3158 2 50         BSON_ASSERT (src);
3159              
3160 2 50         if (!bson_empty (src)) {
    50          
3161 2           return _bson_append (dst, 1, src->len - 5,
3162 2           src->len - 5, _bson_data (src) + 4);
3163             }
3164              
3165 0           return true;
3166             }