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