3 /* Copyright 2009, 2010 10gen Inc.
4 * Copyright (C) 2012-2015 Softmotions Ltd <info@softmotions.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
32 #define bson_little_endian64(out, in) ( bson_swap_endian64(out, in) )
33 #define bson_little_endian32(out, in) ( bson_swap_endian32(out, in) )
34 #define bson_big_endian64(out, in) ( memcpy(out, in, 8) )
35 #define bson_big_endian32(out, in) ( memcpy(out, in, 4) )
37 #define bson_little_endian64(out, in) ( memcpy(out, in, 8) )
38 #define bson_little_endian32(out, in) ( memcpy(out, in, 4) )
39 #define bson_big_endian64(out, in) ( bson_swap_endian64(out, in) )
40 #define bson_big_endian32(out, in) ( bson_swap_endian32(out, in) )
43 const int initialBufferSize = 128;
46 #define MIN(a,b) (((a)<(b))?(a):(b))
49 #define MAX(a,b) (((a)>(b))?(a):(b))
52 /* only need one of these */
53 static const int zero = 0;
55 /* Custom standard function pointers. */
56 void *(*bson_malloc_func)(size_t) = MYMALLOC;
57 void *(*bson_realloc_func)(void *, size_t) = MYREALLOC;
58 void ( *bson_free_func)(void *) = MYFREE;
60 static int _bson_errprintf(const char *, ...);
61 bson_printf_func bson_errprintf = _bson_errprintf;
63 /* ObjectId fuzz functions. */
64 static int ( *oid_fuzz_func)(void) = NULL;
65 static int ( *oid_inc_func)(void) = NULL;
67 const char* bson_first_errormsg(bson *bson) {
71 if (bson->err & BSON_FIELD_HAS_DOT) {
72 return "BSON key contains '.' character";
73 } else if (bson->err & BSON_FIELD_INIT_DOLLAR) {
74 return "BSON key starts with '$' character";
75 } else if (bson->err & BSON_ALREADY_FINISHED) {
76 return "Trying to modify a finished BSON object";
77 } else if (bson->err & BSON_NOT_UTF8) {
78 return "A key or a string is not valid UTF-8";
80 return "Unspecified BSON error";
83 void bson_reset(bson *b) {
91 static bson_bool_t bson_isnumstr(const char *str, int len);
92 static void bson_append_fpath_from_iterator(const char *fpath, const bson_iterator *from, bson *into);
93 static const char *bson_iterator_value2(const bson_iterator *i, int *klen);
95 /* ----------------------------
97 ------------------------------ */
99 bson* bson_create(void) {
100 return (bson*) bson_malloc(sizeof (bson));
103 void bson_dispose(bson* b) {
107 bson *bson_empty(bson *obj) {
108 static char *data = "\005\0\0\0\0";
109 bson_init_data(obj, data);
118 int bson_copy(bson *out, const bson *in) {
119 if (!out || !in) return BSON_ERROR;
120 if (!in->finished) return BSON_ERROR;
121 bson_init_size(out, bson_size(in));
122 memcpy(out->data, in->data, bson_size(in));
127 int bson_init_data(bson *b, char *data) {
132 int bson_init_finished_data(bson *b, const char *data) {
133 bson_init_data(b, (char*) data);
139 int bson_size(const bson *b) {
143 bson_little_endian32(&i, b->data);
147 int bson_size2(const void *bsdata) {
151 bson_little_endian32(&i, bsdata);
155 int bson_buffer_size(const bson *b) {
156 return (b->cur - b->data + 1);
159 const char *bson_data(const bson *b) {
160 return (const char *) b->data;
163 const char* bson_data2(const bson *b, int *bsize) {
164 *bsize = bson_size(b);
168 EJDB_INLINE char hexbyte(char hex) {
169 if (hex >= '0' && hex <= '9')
171 else if (hex >= 'A' && hex <= 'F')
172 return (hex - 'A' + 10);
173 else if (hex >= 'a' && hex <= 'f')
174 return (hex - 'a' + 10);
179 void bson_oid_from_string(bson_oid_t *oid, const char *str) {
181 for (i = 0; i < 12; i++) {
182 oid->bytes[i] = (hexbyte(str[2 * i]) << 4) | hexbyte(str[2 * i + 1]);
186 void bson_oid_to_string(const bson_oid_t *oid, char *str) {
187 static const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
189 for (i = 0; i < 12; i++) {
190 str[2 * i] = hex[(oid->bytes[i] & 0xf0) >> 4];
191 str[2 * i + 1] = hex[ oid->bytes[i] & 0x0f ];
196 void bson_set_oid_fuzz(int ( *func)(void)) {
197 oid_fuzz_func = func;
200 void bson_set_oid_inc(int ( *func)(void)) {
204 void bson_oid_gen(bson_oid_t *oid) {
217 fuzz = oid_fuzz_func();
224 bson_big_endian32(&oid->ints[0], &t);
226 bson_big_endian32(&oid->ints[2], &i);
229 time_t bson_oid_generated_time(bson_oid_t *oid) {
231 bson_big_endian32(&out, &oid->ints[0]);
235 void bson_print_raw(const char *data, int depth) {
243 BSON_ITERATOR_FROM_BUFFER(&i, data);
245 while (bson_iterator_next(&i)) {
246 bson_type t = BSON_ITERATOR_TYPE(&i);
249 key = BSON_ITERATOR_KEY(&i);
251 for (temp = 0; temp <= depth; temp++)
253 fprintf(f, "%s : %d \t ", key, t);
256 fprintf(f, "%f", bson_iterator_double(&i));
259 fprintf(f, "%s", bson_iterator_string(&i));
262 fprintf(f, "SYMBOL: %s", bson_iterator_string(&i));
265 bson_oid_to_string(bson_iterator_oid(&i), oidhex);
266 fprintf(f, "%s", oidhex);
269 fprintf(f, "%s", bson_iterator_bool(&i) ? "true" : "false");
272 fprintf(f, "%" PRId64, bson_iterator_date(&i));
275 fprintf(f, "BSON_BINDATA");
278 fprintf(f, "BSON_UNDEFINED");
281 fprintf(f, "BSON_NULL");
284 fprintf(f, "BSON_REGEX: %s", bson_iterator_regex(&i));
287 fprintf(f, "BSON_CODE: %s", bson_iterator_code(&i));
289 case BSON_CODEWSCOPE:
290 fprintf(f, "BSON_CODE_W_SCOPE: %s", bson_iterator_code(&i));
291 /* bson_init( &scope ); */ /* review - stepped on by bson_iterator_code_scope? */
292 bson_iterator_code_scope(&i, &scope);
293 fprintf(f, "\n\t SCOPE: ");
294 bson_print_raw((const char*) &scope, 0);
295 /* bson_destroy( &scope ); */ /* review - causes free error */
298 fprintf(f, "%d", bson_iterator_int(&i));
301 fprintf(f, "%" PRId64 "", (uint64_t) bson_iterator_long(&i));
304 ts = bson_iterator_timestamp(&i);
305 fprintf(f, "i: %d, t: %d", ts.i, ts.t);
310 bson_print_raw(bson_iterator_value(&i), depth + 1);
313 bson_errprintf("can't print type : %d\n", t);
319 /* ----------------------------
321 ------------------------------ */
323 bson_iterator* bson_iterator_create(void) {
324 return (bson_iterator*) malloc(sizeof ( bson_iterator));
327 void bson_iterator_dispose(bson_iterator* i) {
331 void bson_iterator_init(bson_iterator *i, const bson *b) {
332 i->cur = b->data + 4;
336 void bson_iterator_from_buffer(bson_iterator *i, const char *buffer) {
341 bson_type bson_find(bson_iterator *it, const bson *obj, const char *name) {
342 BSON_ITERATOR_INIT(it, (bson *) obj);
343 while (bson_iterator_next(it)) {
344 if (strcmp(name, BSON_ITERATOR_KEY(it)) == 0)
347 return BSON_ITERATOR_TYPE(it);
350 bson_type bson_find_from_buffer(bson_iterator *it, const char *buffer, const char *name) {
351 BSON_ITERATOR_FROM_BUFFER(it, buffer);
352 while (bson_iterator_next(it)) {
353 if (strcmp(name, BSON_ITERATOR_KEY(it)) == 0)
356 return BSON_ITERATOR_TYPE(it);
359 static void bson_visit_fields_impl(bson_traverse_flags_t flags, char* pstack, int curr, bson_iterator *it, BSONVISITOR visitor, void *op) {
362 bson_visitor_cmd_t vcmd = 0;
363 while (!(vcmd & BSON_VCMD_TERMINATE) && (t = bson_iterator_next(it)) != BSON_EOO) {
364 const char* key = BSON_ITERATOR_KEY(it);
366 if (curr + klen > BSON_MAX_FPATH_LEN) {
370 if (curr > 0) { //add leading dot
371 *(pstack + curr) = '.';
374 memcpy(pstack + curr, key, klen);
377 vcmd = visitor(pstack, curr, key, klen, it, false, op);
378 if (vcmd & BSON_VCMD_TERMINATE) {
381 if (!(vcmd & BSON_VCMD_SKIP_NESTED) &&
382 ((t == BSON_OBJECT && (flags & BSON_TRAVERSE_OBJECTS_EXCLUDED) == 0) ||
383 (t == BSON_ARRAY && (flags & BSON_TRAVERSE_ARRAYS_EXCLUDED) == 0))
386 BSON_ITERATOR_SUBITERATOR(it, &sit);
387 bson_visit_fields_impl(flags, pstack, curr, &sit, visitor, op);
389 if (!(vcmd & BSON_VCMD_SKIP_AFTER)) {
390 vcmd = visitor(pstack, curr, key, klen, it, true, op);
395 curr--; //remove leading dot
400 void bson_visit_fields(bson_iterator *it, bson_traverse_flags_t flags, BSONVISITOR visitor, void *op) {
401 char pstack[BSON_MAX_FPATH_LEN + 1];
402 bson_visit_fields_impl(flags, pstack, 0, it, visitor, op);
405 static bson_type bson_find_fieldpath_value_impl(char* pstack, int curr, FFPCTX *ffpctx, bson_iterator *it) {
409 int fplen = ffpctx->fplen;
410 const char *fpath = ffpctx->fpath;
411 while ((t = bson_iterator_next(it)) != BSON_EOO) {
412 const char* key = BSON_ITERATOR_KEY(it);
414 if (curr + klen > fplen) {
418 if (curr > 0) { //add leading dot
419 *(pstack + curr) = '.';
422 memcpy(pstack + curr, key, klen);
424 for (i = 0; i < curr && i < fplen && pstack[i] == fpath[i]; ++i);
425 if (i == curr && i == fplen) { //Position matched with field path
429 if (i == curr && i < fplen && (t == BSON_OBJECT || t == BSON_ARRAY)) { //Only prefix and we can go into nested objects
430 if (ffpctx->stopnestedarr && t == BSON_ARRAY) {
432 while (fpath[p1] == '.' && p1 < fplen) p1++;
434 while (fpath[p2] != '.' && fpath[p2] > '\0' && p2 < fplen) p2++;
435 if (!bson_isnumstr(fpath + p1, p2 - p1)) { //next fpath sections is not an array index
441 BSON_ITERATOR_SUBITERATOR(it, &sit);
442 bson_type st = bson_find_fieldpath_value_impl(pstack, curr, ffpctx, &sit);
443 if (st != BSON_EOO) { //Found in nested
451 curr--; //remove leading dot
457 bson_type bson_find_fieldpath_value(const char *fpath, bson_iterator *it) {
458 return bson_find_fieldpath_value2(fpath, strlen(fpath), it);
461 bson_type bson_find_fieldpath_value2(const char *fpath, int fplen, bson_iterator *it) {
466 .stopnestedarr = false,
471 return bson_find_fieldpath_value3(&ffctx);
474 bson_type bson_find_fieldpath_value3(FFPCTX* ffctx) {
475 char pstackstack[BSON_MAX_FPATH_LEN + 1];
477 if (ffctx->fplen <= BSON_MAX_FPATH_LEN) {
478 pstack = pstackstack;
480 pstack = MYMALLOC((ffctx->fplen + 1) * sizeof (char));
485 bson_type bt = bson_find_fieldpath_value_impl(pstack, 0, ffctx, ffctx->input);
486 if (pstack != pstackstack) {
492 bson_bool_t bson_iterator_more(const bson_iterator *i) {
496 bson_type bson_iterator_next(bson_iterator *i) {
497 int ds, out, klen = 0;
500 return (bson_type) (*i->cur);
502 switch (BSON_ITERATOR_TYPE(i)) {
504 return BSON_EOO; /* don't advance */
527 bson_little_endian32(&out, bson_iterator_value2(i, &klen));
531 bson_little_endian32(&out, bson_iterator_value2(i, &klen));
536 case BSON_CODEWSCOPE:
537 bson_little_endian32(&out, bson_iterator_value2(i, &klen));
541 bson_little_endian32(&out, bson_iterator_value2(i, &klen));
546 const char *s = bson_iterator_value2(i, &klen);
556 char msg[] = "unknown type: 000000000000";
557 bson_numstr(msg + 14, (unsigned) (i->cur[0]));
558 bson_fatal_msg(0, msg);
563 for (; *(i->cur + 1 + klen) != '\0'; ++klen);
565 i->cur += (1 + klen + 1 + ds);
566 return (bson_type) (*i->cur);
569 bson_type bson_iterator_type(const bson_iterator *i) {
570 return (bson_type) i->cur[0];
573 const char *bson_iterator_key(const bson_iterator *i) {
577 const char *bson_iterator_value(const bson_iterator *i) {
579 const char *t = i->cur + 1;
580 for (; *(t + len) != '\0'; ++len);
587 int bson_iterator_int_raw(const bson_iterator *i) {
589 bson_little_endian32(&out, bson_iterator_value(i));
593 double bson_iterator_double_raw(const bson_iterator *i) {
595 bson_little_endian64(&out, bson_iterator_value(i));
599 int64_t bson_iterator_long_raw(const bson_iterator *i) {
601 bson_little_endian64(&out, bson_iterator_value(i));
605 bson_bool_t bson_iterator_bool_raw(const bson_iterator *i) {
606 return bson_iterator_value(i)[0];
609 bson_oid_t *bson_iterator_oid(const bson_iterator *i) {
610 return (bson_oid_t *) bson_iterator_value(i);
613 int bson_iterator_int(const bson_iterator *i) {
614 switch (BSON_ITERATOR_TYPE(i)) {
616 return bson_iterator_int_raw(i);
618 return bson_iterator_long_raw(i);
620 return bson_iterator_double_raw(i);
622 return bson_iterator_bool_raw(i) ? 1 : 0;
628 double bson_iterator_double(const bson_iterator *i) {
629 switch (BSON_ITERATOR_TYPE(i)) {
631 return bson_iterator_int_raw(i);
634 return bson_iterator_long_raw(i);
636 return bson_iterator_double_raw(i);
638 return bson_iterator_bool_raw(i) ? 1.0 : 0.0;
644 int64_t bson_iterator_long(const bson_iterator *i) {
645 switch (BSON_ITERATOR_TYPE(i)) {
647 return bson_iterator_int_raw(i);
650 return bson_iterator_long_raw(i);
652 return bson_iterator_double_raw(i);
654 return bson_iterator_bool_raw(i) ? 1 : 0;
660 static int64_t bson_iterator_long_ext(const bson_iterator *i) {
661 switch (BSON_ITERATOR_TYPE(i)) {
663 return bson_iterator_int_raw(i);
667 return bson_iterator_long_raw(i);
669 return bson_iterator_double_raw(i);
671 return bson_iterator_bool_raw(i) ? 1 : 0;
677 bson_timestamp_t bson_iterator_timestamp(const bson_iterator *i) {
679 bson_little_endian32(&(ts.i), bson_iterator_value(i));
680 bson_little_endian32(&(ts.t), bson_iterator_value(i) + 4);
684 int bson_iterator_timestamp_time(const bson_iterator *i) {
686 bson_little_endian32(&time, bson_iterator_value(i) + 4);
690 int bson_iterator_timestamp_increment(const bson_iterator *i) {
692 bson_little_endian32(&increment, bson_iterator_value(i));
696 bson_bool_t bson_iterator_bool(const bson_iterator *i) {
697 switch (BSON_ITERATOR_TYPE(i)) {
699 return bson_iterator_bool_raw(i);
701 return bson_iterator_int_raw(i) != 0;
704 return bson_iterator_long_raw(i) != 0;
706 return bson_iterator_double_raw(i) != 0;
716 const char *bson_iterator_string(const bson_iterator *i) {
717 switch (BSON_ITERATOR_TYPE(i)) {
720 return bson_iterator_value(i) + 4;
726 int bson_iterator_string_len(const bson_iterator *i) {
727 return bson_iterator_int_raw(i);
730 const char *bson_iterator_code(const bson_iterator *i) {
731 switch (BSON_ITERATOR_TYPE(i)) {
734 return bson_iterator_value(i) + 4;
735 case BSON_CODEWSCOPE:
736 return bson_iterator_value(i) + 8;
742 void bson_iterator_code_scope(const bson_iterator *i, bson *scope) {
743 if (BSON_ITERATOR_TYPE(i) == BSON_CODEWSCOPE) {
745 bson_little_endian32(&code_len, bson_iterator_value(i) + 4);
746 bson_init_data(scope, (void *) (bson_iterator_value(i) + 8 + code_len));
754 bson_date_t bson_iterator_date(const bson_iterator *i) {
755 return bson_iterator_long_raw(i);
758 time_t bson_iterator_time_t(const bson_iterator *i) {
759 return bson_iterator_date(i) / 1000;
762 int bson_iterator_bin_len(const bson_iterator *i) {
763 return ( bson_iterator_bin_type(i) == BSON_BIN_BINARY_OLD)
764 ? bson_iterator_int_raw(i) - 4
765 : bson_iterator_int_raw(i);
768 char bson_iterator_bin_type(const bson_iterator *i) {
769 return bson_iterator_value(i)[4];
772 const char *bson_iterator_bin_data(const bson_iterator *i) {
773 return ( bson_iterator_bin_type(i) == BSON_BIN_BINARY_OLD)
774 ? bson_iterator_value(i) + 9
775 : bson_iterator_value(i) + 5;
778 const char *bson_iterator_regex(const bson_iterator *i) {
779 return bson_iterator_value(i);
782 const char *bson_iterator_regex_opts(const bson_iterator *i) {
783 const char *p = bson_iterator_value(i);
784 return p + strlen(p) + 1;
788 void bson_iterator_subobject(const bson_iterator *i, bson *sub) {
789 bson_init_data(sub, (char *) bson_iterator_value(i));
794 void bson_iterator_subiterator(const bson_iterator *i, bson_iterator *sub) {
795 BSON_ITERATOR_FROM_BUFFER(sub, bson_iterator_value(i));
798 /* ----------------------------
800 ------------------------------ */
802 static void _bson_init_size(bson *b, int size) {
806 b->data = (char *) bson_malloc(size);
809 b->cur = b->data + 4;
813 void bson_init(bson *b) {
814 _bson_init_size(b, initialBufferSize);
817 void bson_init_as_query(bson *b) {
819 b->flags |= BSON_FLAG_QUERY_MODE;
822 void bson_init_size(bson *b, int size) {
823 _bson_init_size(b, size);
826 void bson_init_on_stack(bson *b, char *bstack, int mincapacity, int maxonstack) {
828 b->data = (mincapacity < maxonstack) ? bstack : bson_malloc_func(mincapacity);
829 b->cur = b->data + 4;
830 b->dataSize = (mincapacity < maxonstack) ? maxonstack : mincapacity;
831 if (b->data == bstack) {
832 b->flags |= BSON_FLAG_STACK_ALLOCATED;
836 void bson_append_byte(bson *b, char c) {
841 void bson_append(bson *b, const void *data, int len) {
842 memcpy(b->cur, data, len);
846 void bson_append32(bson *b, const void *data) {
847 bson_little_endian32(b->cur, data);
851 void bson_append64(bson *b, const void *data) {
852 bson_little_endian64(b->cur, data);
856 int bson_ensure_space(bson *b, const int bytesNeeded) {
857 int pos = b->cur - b->data;
858 char *orig = b->data;
861 if (pos + bytesNeeded <= b->dataSize)
864 new_size = 1.5 * (b->dataSize + bytesNeeded);
866 if (new_size < b->dataSize) {
867 if ((b->dataSize + bytesNeeded) < INT_MAX)
870 b->err = BSON_SIZE_OVERFLOW;
875 if (b->flags & BSON_FLAG_STACK_ALLOCATED) { //translate stack memory into heap
876 char *odata = b->data;
877 b->data = bson_malloc_func(new_size);
879 bson_fatal_msg(!!b->data, "malloc() failed");
883 memcpy(b->data, odata, MIN(new_size, b->dataSize));
885 b->flags &= ~BSON_FLAG_STACK_ALLOCATED; //reset this flag
887 b->data = bson_realloc(b->data, new_size);
890 bson_fatal_msg(!!b->data, "realloc() failed");
894 b->dataSize = new_size;
895 b->cur += b->data - orig;
900 int bson_finish(bson *b) {
903 if (b->err & BSON_NOT_UTF8)
907 if (bson_ensure_space(b, 1) == BSON_ERROR) return BSON_ERROR;
908 bson_append_byte(b, 0);
909 i = b->cur - b->data;
910 bson_little_endian32(b->data, &i);
917 void bson_destroy(bson *b) {
919 if (b->data && !(b->flags & BSON_FLAG_STACK_ALLOCATED)) {
927 bson_free_func(b->errstr);
933 void bson_del(bson *b) {
940 static int bson_append_estart2(bson *b, int type, const char *name, int namelen, const int dataSize);
942 static int bson_append_estart(bson *b, int type, const char *name, const int dataSize) {
943 return bson_append_estart2(b, type, name, strlen(name), dataSize);
946 static int bson_append_estart2(bson *b, int type, const char *name, int namelen, const int dataSize) {
947 const int len = namelen + 1;
950 b->err |= BSON_ALREADY_FINISHED;
954 if (bson_ensure_space(b, 1 + len + dataSize) == BSON_ERROR) {
958 if (bson_check_field_name(b, (const char *) name, namelen,
959 !(b->flags & BSON_FLAG_QUERY_MODE), !(b->flags & BSON_FLAG_QUERY_MODE)) == BSON_ERROR) {
960 bson_builder_error(b);
963 bson_append_byte(b, (char) type);
964 memcpy(b->cur, name, namelen);
971 /* ----------------------------
973 ------------------------------ */
975 int bson_append_int(bson *b, const char *name, const int i) {
976 if (bson_append_estart(b, BSON_INT, name, 4) == BSON_ERROR)
978 bson_append32(b, &i);
982 int bson_append_long(bson *b, const char *name, const int64_t i) {
983 if (bson_append_estart(b, BSON_LONG, name, 8) == BSON_ERROR)
985 bson_append64(b, &i);
989 int bson_append_double(bson *b, const char *name, const double d) {
990 if (bson_append_estart(b, BSON_DOUBLE, name, 8) == BSON_ERROR)
992 bson_append64(b, &d);
996 int bson_append_bool(bson *b, const char *name, const bson_bool_t i) {
997 if (bson_append_estart(b, BSON_BOOL, name, 1) == BSON_ERROR)
999 bson_append_byte(b, i != 0);
1003 int bson_append_null(bson *b, const char *name) {
1004 if (bson_append_estart(b, BSON_NULL, name, 0) == BSON_ERROR)
1009 int bson_append_undefined(bson *b, const char *name) {
1010 if (bson_append_estart(b, BSON_UNDEFINED, name, 0) == BSON_ERROR)
1015 int bson_append_string_base(bson *b, const char *name,
1016 const char *value, int len, bson_type type) {
1019 if (bson_check_string(b, (const char *) value, sl - 1) == BSON_ERROR)
1021 if (bson_append_estart(b, type, name, 4 + sl) == BSON_ERROR) {
1024 bson_append32(b, &sl);
1025 bson_append(b, value, sl - 1);
1026 bson_append(b, "\0", 1);
1030 int bson_append_string(bson *b, const char *name, const char *value) {
1031 return bson_append_string_base(b, name, value, strlen(value), BSON_STRING);
1034 int bson_append_symbol(bson *b, const char *name, const char *value) {
1035 return bson_append_string_base(b, name, value, strlen(value), BSON_SYMBOL);
1038 int bson_append_code(bson *b, const char *name, const char *value) {
1039 return bson_append_string_base(b, name, value, strlen(value), BSON_CODE);
1042 int bson_append_string_n(bson *b, const char *name, const char *value, int len) {
1043 return bson_append_string_base(b, name, value, len, BSON_STRING);
1046 int bson_append_symbol_n(bson *b, const char *name, const char *value, int len) {
1047 return bson_append_string_base(b, name, value, len, BSON_SYMBOL);
1050 int bson_append_code_n(bson *b, const char *name, const char *value, int len) {
1051 return bson_append_string_base(b, name, value, len, BSON_CODE);
1054 int bson_append_code_w_scope_n(bson *b, const char *name,
1055 const char *code, int len, const bson *scope) {
1058 if (!scope) return BSON_ERROR;
1060 size = 4 + 4 + sl + bson_size(scope);
1061 if (bson_append_estart(b, BSON_CODEWSCOPE, name, size) == BSON_ERROR)
1063 bson_append32(b, &size);
1064 bson_append32(b, &sl);
1065 bson_append(b, code, sl);
1066 bson_append(b, scope->data, bson_size(scope));
1070 int bson_append_code_w_scope(bson *b, const char *name, const char *code, const bson *scope) {
1071 return bson_append_code_w_scope_n(b, name, code, strlen(code), scope);
1074 int bson_append_binary(bson *b, const char *name, char type, const char *str, int len) {
1075 if (type == BSON_BIN_BINARY_OLD) {
1076 int subtwolen = len + 4;
1077 if (bson_append_estart(b, BSON_BINDATA, name, 4 + 1 + 4 + len) == BSON_ERROR)
1079 bson_append32(b, &subtwolen);
1080 bson_append_byte(b, type);
1081 bson_append32(b, &len);
1082 bson_append(b, str, len);
1084 if (bson_append_estart(b, BSON_BINDATA, name, 4 + 1 + len) == BSON_ERROR)
1086 bson_append32(b, &len);
1087 bson_append_byte(b, type);
1088 bson_append(b, str, len);
1093 int bson_append_oid(bson *b, const char *name, const bson_oid_t *oid) {
1094 if (bson_append_estart(b, BSON_OID, name, 12) == BSON_ERROR)
1096 bson_append(b, oid, 12);
1100 int bson_append_new_oid(bson *b, const char *name) {
1103 return bson_append_oid(b, name, &oid);
1106 int bson_append_regex(bson *b, const char *name, const char *pattern, const char *opts) {
1107 const int plen = strlen(pattern) + 1;
1108 const int olen = strlen(opts) + 1;
1109 if (bson_append_estart(b, BSON_REGEX, name, plen + olen) == BSON_ERROR)
1111 if (bson_check_string(b, pattern, plen - 1) == BSON_ERROR)
1113 bson_append(b, pattern, plen);
1114 bson_append(b, opts, olen);
1118 int bson_append_bson(bson *b, const char *name, const bson *bson) {
1119 if (!bson) return BSON_ERROR;
1120 if (bson_append_estart(b, BSON_OBJECT, name, bson_size(bson)) == BSON_ERROR)
1122 bson_append(b, bson->data, bson_size(bson));
1126 int bson_append_element(bson *b, const char *name_or_null, const bson_iterator *elem) {
1127 bson_iterator next = *elem;
1130 bson_iterator_next(&next);
1131 size = next.cur - elem->cur;
1133 if (name_or_null == NULL) {
1134 if (bson_ensure_space(b, size) == BSON_ERROR)
1136 bson_append(b, elem->cur, size);
1138 int data_size = size - 2 - strlen(BSON_ITERATOR_KEY(elem));
1139 bson_append_estart(b, elem->cur[0], name_or_null, data_size);
1140 bson_append(b, bson_iterator_value(elem), data_size);
1146 int bson_append_timestamp(bson *b, const char *name, bson_timestamp_t *ts) {
1147 if (bson_append_estart(b, BSON_TIMESTAMP, name, 8) == BSON_ERROR) return BSON_ERROR;
1149 bson_append32(b, &(ts->i));
1150 bson_append32(b, &(ts->t));
1155 int bson_append_timestamp2(bson *b, const char *name, int time, int increment) {
1156 if (bson_append_estart(b, BSON_TIMESTAMP, name, 8) == BSON_ERROR) return BSON_ERROR;
1158 bson_append32(b, &increment);
1159 bson_append32(b, &time);
1163 int bson_append_date(bson *b, const char *name, bson_date_t millis) {
1164 if (bson_append_estart(b, BSON_DATE, name, 8) == BSON_ERROR) return BSON_ERROR;
1165 bson_append64(b, &millis);
1169 int bson_append_time_t(bson *b, const char *name, time_t secs) {
1170 return bson_append_date(b, name, (bson_date_t) secs * 1000);
1173 int bson_append_start_object(bson *b, const char *name) {
1174 if (bson_append_estart(b, BSON_OBJECT, name, 5) == BSON_ERROR) return BSON_ERROR;
1175 b->stack[ b->stackPos++ ] = b->cur - b->data;
1176 bson_append32(b, &zero);
1180 int bson_append_start_object2(bson *b, const char *name, int namelen) {
1181 if (bson_append_estart2(b, BSON_OBJECT, name, namelen, 5) == BSON_ERROR) return BSON_ERROR;
1182 b->stack[ b->stackPos++ ] = b->cur - b->data;
1183 bson_append32(b, &zero);
1187 int bson_append_start_array(bson *b, const char *name) {
1188 return bson_append_start_array2(b, name, strlen(name));
1191 int bson_append_start_array2(bson *b, const char *name, int namelen) {
1192 if (bson_append_estart2(b, BSON_ARRAY, name, namelen, 5) == BSON_ERROR) return BSON_ERROR;
1193 b->stack[ b->stackPos++ ] = b->cur - b->data;
1194 bson_append32(b, &zero);
1198 int bson_append_finish_object(bson *b) {
1201 if (bson_ensure_space(b, 1) == BSON_ERROR) return BSON_ERROR;
1202 bson_append_byte(b, 0);
1204 start = b->data + b->stack[ --b->stackPos ];
1206 bson_little_endian32(start, &i);
1211 double bson_int64_to_double(int64_t i64) {
1212 return (double) i64;
1215 int bson_append_finish_array(bson *b) {
1216 return bson_append_finish_object(b);
1219 /* Error handling and allocators. */
1221 static bson_err_handler err_handler = NULL;
1223 bson_err_handler set_bson_err_handler(bson_err_handler func) {
1224 bson_err_handler old = err_handler;
1229 void bson_free(void *ptr) {
1230 bson_free_func(ptr);
1233 void *bson_malloc(int size) {
1235 p = bson_malloc_func(size);
1236 bson_fatal_msg(!!p, "malloc() failed");
1240 void *bson_realloc(void *ptr, int size) {
1242 p = bson_realloc_func(ptr, size);
1243 bson_fatal_msg(!!p, "realloc() failed");
1247 int _bson_errprintf(const char *format, ...) {
1250 va_start(ap, format);
1251 ret = vfprintf(stderr, format, ap);
1257 * This method is invoked when a non-fatal bson error is encountered.
1258 * Calls the error handler if available.
1262 void bson_builder_error(bson *b) {
1264 err_handler("BSON error.");
1267 void bson_fatal(int ok) {
1268 bson_fatal_msg(ok, "");
1271 void bson_fatal_msg(int ok, const char *msg) {
1278 bson_errprintf("error: %s\n", msg);
1282 /* Efficiently copy an integer to a string. */
1283 extern const char bson_numstrs[1000][4];
1285 void bson_numstr(char *str, int64_t i) {
1286 if (i >= 0 && i < 1000)
1287 memcpy(str, bson_numstrs[i], 4);
1289 sprintf(str, "%" PRId64 "", (int64_t) i);
1292 #pragma GCC diagnostic push
1293 #pragma GCC diagnostic ignored "-Wformat"
1295 int bson_numstrn(char *str, int maxbuf, int64_t i) {
1296 if (i >= 0 && i < 1000 && maxbuf > 4) {
1297 memcpy(str, bson_numstrs[i], 4);
1298 return strlen(bson_numstrs[i]);
1300 return snprintf(str, maxbuf, "%" PRId64 "", (int64_t) i);
1303 #pragma GCC diagnostic pop
1305 static bson_bool_t bson_isnumstr(const char *str, int len) {
1308 while (len > 0 && *str > '\0' && *str <= ' ') {
1312 while (len > 0 && *str >= '0' && *str <= '9') {
1317 while (len > 0 && *str > '\0' && *str <= ' ') {
1321 return (isnum && (*str == '\0' || len == 0));
1324 void bson_swap_endian64(void *outp, const void *inp) {
1325 const char *in = (const char *) inp;
1326 char *out = (char *) outp;
1338 void bson_swap_endian32(void *outp, const void *inp) {
1339 const char *in = (const char *) inp;
1340 char *out = (char *) outp;
1347 static const char *bson_iterator_value2(const bson_iterator *i, int *klen) {
1348 const char *t = i->cur + 1;
1354 int bson_append_array_from_iterator(const char *key, bson_iterator *from, bson *into) {
1355 assert(key && from && into);
1357 bson_append_start_array(into, key);
1358 while ((bt = bson_iterator_next(from)) != BSON_EOO) {
1359 bson_append_field_from_iterator(from, into);
1361 bson_append_finish_array(into);
1365 int bson_append_object_from_iterator(const char *key, bson_iterator *from, bson *into) {
1366 assert(key && from && into);
1368 bson_append_start_object(into, key);
1369 while ((bt = bson_iterator_next(from)) != BSON_EOO) {
1370 bson_append_field_from_iterator(from, into);
1372 bson_append_finish_object(into);
1376 static void bson_append_fpath_from_iterator(const char *fpath, const bson_iterator *from, bson *into) {
1377 char key[BSON_MAX_FPATH_LEN + 1];
1378 int fplen = strlen(fpath);
1379 if (fplen >= BSON_MAX_FPATH_LEN) { //protect me silently
1380 return; //todo error?
1382 const char *fp = fpath;
1384 int nl = 0; //nesting level
1385 while (fplen > 0) { //split fpath with '.' delim
1386 const char *rp = fp;
1387 const char *ep = fp + fplen;
1389 if (*rp == '.') break;
1393 memcpy(key, fp, keylen);
1397 if (fplen <= 0) { //last part of fp
1398 bson_append_field_from_iterator2(key, from, into);
1400 bson_append_finish_object(into); //arrays are covered also
1402 } else { //intermediate part
1403 if (bson_isnumstr(key, keylen)) {
1405 bson_append_start_array2(into, key, keylen);
1408 bson_append_start_object2(into, key, keylen);
1415 int bson_append_field_from_iterator2(const char *key, const bson_iterator *from, bson *into) {
1416 assert(key && from && into);
1417 bson_type t = BSON_ITERATOR_TYPE(from);
1418 if (t == BSON_EOO || into->finished) {
1424 bson_append_string(into, key, bson_iterator_string(from));
1427 bson_append_code(into, key, bson_iterator_code(from));
1430 bson_append_int(into, key, bson_iterator_int_raw(from));
1433 bson_append_double(into, key, bson_iterator_double_raw(from));
1436 bson_append_long(into, key, bson_iterator_long_raw(from));
1438 case BSON_UNDEFINED:
1439 bson_append_undefined(into, key);
1442 bson_append_null(into, key);
1445 bson_append_bool(into, key, bson_iterator_bool_raw(from));
1447 case BSON_TIMESTAMP:
1449 bson_timestamp_t ts = bson_iterator_timestamp(from);
1450 bson_append_timestamp(into, key, &ts);
1454 bson_append_date(into, key, bson_iterator_date(from));
1457 bson_append_regex(into, key, bson_iterator_regex(from), bson_iterator_regex_opts(from));
1460 bson_append_oid(into, key, bson_iterator_oid(from));
1465 BSON_ITERATOR_SUBITERATOR(from, &sit);
1466 bson_append_start_object(into, key);
1467 while (bson_iterator_next(&sit) != BSON_EOO) {
1468 bson_append_field_from_iterator(&sit, into);
1470 bson_append_finish_object(into);
1476 BSON_ITERATOR_SUBITERATOR(from, &sit);
1477 bson_append_start_array(into, key);
1478 while (bson_iterator_next(&sit) != BSON_EOO) {
1479 bson_append_field_from_iterator(&sit, into);
1481 bson_append_finish_array(into);
1485 case BSON_CODEWSCOPE:
1493 int bson_append_field_from_iterator(const bson_iterator *from, bson *into) {
1494 assert(from && into);
1495 return bson_append_field_from_iterator2(BSON_ITERATOR_KEY(from), from, into);
1501 const void *bsdata2; //bsdata to merge with
1502 int nstack; //nested object stack pos
1503 int matched; //number of matched merge fields
1506 static bson_visitor_cmd_t _bson_merge3_visitor(const char *ipath, int ipathlen, const char *key, int keylen,
1507 const bson_iterator *it, bool after, void *op) {
1508 _BSON_MERGE3_CTX *ctx = op;
1509 assert(ctx && ctx->bsout && ctx->mfields && ipath && key && it && op);
1513 bson_type bt = BSON_ITERATOR_TYPE(it);
1514 buf = (TCMAPRNUM(ctx->mfields) == 0 || after) ? NULL : tcmapget(ctx->mfields, ipath, ipathlen, &bufsz);
1517 BSON_ITERATOR_FROM_BUFFER(&it2, ctx->bsdata2);
1519 assert(bufsz == sizeof (it2off));
1520 memcpy(&it2off, buf, sizeof (it2off));
1521 assert(it2off >= 0);
1522 it2.cur = it2.cur + it2off;
1523 it2.first = (it2off == 0);
1524 tcmapout(ctx->mfields, ipath, ipathlen);
1525 bson_append_field_from_iterator2(key, &it2, ctx->bsout);
1526 return (BSON_VCMD_SKIP_AFTER | BSON_VCMD_SKIP_NESTED);
1528 if (bt == BSON_OBJECT || bt == BSON_ARRAY) {
1531 if (bt == BSON_OBJECT) {
1532 bson_append_start_object2(ctx->bsout, key, keylen);
1533 } else if (bt == BSON_ARRAY) {
1534 bson_append_start_array2(ctx->bsout, key, keylen);
1536 return BSON_VCMD_OK;
1538 if (ctx->nstack > 0) {
1539 //do we have something to add into end of nested object?
1540 tcmapiterinit(ctx->mfields);
1542 while ((mpath = tcmapiternext(ctx->mfields, &mpathlen)) != NULL) {
1544 for (; i < ipathlen && *(mpath + i) == *(ipath + i); ++i);
1545 if (i == ipathlen && *(mpath + i) == '.' && *(mpath + i + 1) != '\0') { //ipath prefixed
1547 BSON_ITERATOR_FROM_BUFFER(&it2, ctx->bsdata2);
1548 buf = tcmapget(ctx->mfields, mpath, mpathlen, &bufsz);
1550 assert(bufsz == sizeof (it2off));
1551 memcpy(&it2off, buf, sizeof (it2off));
1552 assert(it2off >= 0);
1553 it2.cur = it2.cur + it2off;
1554 it2.first = (it2off == 0);
1555 bson_append_fpath_from_iterator(mpath + i + 1, &it2, ctx->bsout);
1556 tcmapout(ctx->mfields, mpath, mpathlen);
1560 if (bt == BSON_OBJECT) {
1561 bson_append_finish_object(ctx->bsout);
1562 } else if (bt == BSON_ARRAY) {
1563 bson_append_finish_array(ctx->bsout);
1566 return BSON_VCMD_OK;
1569 bson_append_field_from_iterator(it, ctx->bsout);
1570 return BSON_VCMD_SKIP_AFTER;
1575 //merge with fpath support
1577 int bson_merge3(const void *bsdata1, const void *bsdata2, bson *out) {
1578 assert(bsdata1 && bsdata2 && out);
1579 bson_iterator it1, it2;
1581 BSON_ITERATOR_FROM_BUFFER(&it1, bsdata1);
1582 BSON_ITERATOR_FROM_BUFFER(&it2, bsdata2);
1583 const char *it2start = it2.cur;
1584 TCMAP *mfields = tcmapnew2(TCMAPTINYBNUM);
1585 _BSON_MERGE3_CTX ctx = {
1592 //collect active fpaths
1593 while ((bt = bson_iterator_next(&it2)) != BSON_EOO) {
1594 const char* key = BSON_ITERATOR_KEY(&it2);
1595 off_t it2off = (it2.cur - it2start);
1596 tcmapput(mfields, key, strlen(key), &it2off, sizeof (it2off));
1598 bson_visit_fields(&it1, 0, _bson_merge3_visitor, &ctx);
1599 assert(ctx.nstack == 0);
1600 if (TCMAPRNUM(mfields) == 0) { //all merge fields applied
1605 //apply the remaining merge fields
1606 tcmapiterinit(mfields);
1609 while ((fpath = tcmapiternext(mfields, &fplen)) != NULL) {
1610 BSON_ITERATOR_FROM_BUFFER(&it2, bsdata2);
1611 if (bson_find_fieldpath_value2(fpath, fplen, &it2) != BSON_EOO) {
1612 bson_append_fpath_from_iterator(fpath, &it2, out);
1619 int bson_merge2(const void *b1data, const void *b2data, bson_bool_t overwrite, bson *out) {
1620 bson_iterator it1, it2;
1623 BSON_ITERATOR_FROM_BUFFER(&it1, b1data);
1624 BSON_ITERATOR_FROM_BUFFER(&it2, b2data);
1625 //Append all fields in B1 overwriten by B2
1626 while ((bt1 = bson_iterator_next(&it1)) != BSON_EOO) {
1627 const char* k1 = BSON_ITERATOR_KEY(&it1);
1628 if (overwrite && strcmp(JDBIDKEYNAME, k1) && (bt2 = bson_find_from_buffer(&it2, b2data, k1)) != BSON_EOO) {
1629 bson_append_field_from_iterator(&it2, out);
1631 bson_append_field_from_iterator(&it1, out);
1634 BSON_ITERATOR_FROM_BUFFER(&it1, b1data);
1635 BSON_ITERATOR_FROM_BUFFER(&it2, b2data);
1636 //Append all fields from B2 missing in B1
1637 while ((bt2 = bson_iterator_next(&it2)) != BSON_EOO) {
1638 const char* k2 = BSON_ITERATOR_KEY(&it2);
1639 if ((bt1 = bson_find_from_buffer(&it1, b1data, k2)) == BSON_EOO) {
1640 bson_append_field_from_iterator(&it2, out);
1646 int bson_merge(const bson *b1, const bson *b2, bson_bool_t overwrite, bson *out) {
1647 assert(b1 && b2 && out);
1648 if (!b1->finished || !b2->finished || out->finished) {
1651 return bson_merge2(bson_data(b1), bson_data(b2), overwrite, out);
1654 int bson_merge_recursive2(const void *b1data, const void *b2data, bson_bool_t overwrite, bson *out) {
1655 bson_iterator it1, it2;
1658 BSON_ITERATOR_FROM_BUFFER(&it1, b1data);
1659 BSON_ITERATOR_FROM_BUFFER(&it2, b2data);
1660 //Append all fields in B1 merging with fields in B2 (for nested objects & arrays)
1661 while ((bt1 = bson_iterator_next(&it1)) != BSON_EOO) {
1662 const char* k1 = BSON_ITERATOR_KEY(&it1);
1663 bt2 = bson_find_from_buffer(&it2, b2data, k1);
1664 if (bt1 == BSON_OBJECT && bt2 == BSON_OBJECT) {
1666 bson_append_start_object(out, k1);
1667 if ((res = bson_merge_recursive2(bson_iterator_value(&it1), bson_iterator_value(&it2), overwrite, out)) != BSON_OK) {
1670 bson_append_finish_object(out);
1671 } else if (bt1 == BSON_ARRAY && bt2 == BSON_ARRAY) {
1676 bson_append_start_array(out, k1);
1677 BSON_ITERATOR_SUBITERATOR(&it1, &sit);
1678 while ((sbt = bson_iterator_next(&sit)) != BSON_EOO) {
1679 bson_append_field_from_iterator(&sit, out);
1683 char kbuf[TCNUMBUFSIZ];
1684 BSON_ITERATOR_SUBITERATOR(&it2, &sit);
1685 while ((sbt = bson_iterator_next(&sit)) != BSON_EOO) {
1686 bson_numstrn(kbuf, TCNUMBUFSIZ, c++);
1687 bson_append_field_from_iterator2(kbuf, &sit, out);
1690 bson_append_finish_array(out);
1691 } else if (overwrite && strcmp(JDBIDKEYNAME, k1) && bt2 != BSON_EOO) {
1692 bson_append_field_from_iterator(&it2, out);
1694 bson_append_field_from_iterator(&it1, out);
1698 BSON_ITERATOR_FROM_BUFFER(&it1, b1data);
1699 BSON_ITERATOR_FROM_BUFFER(&it2, b2data);
1700 //Append all fields from B2 missing in B1
1701 while ((bt2 = bson_iterator_next(&it2)) != BSON_EOO) {
1702 const char* k2 = BSON_ITERATOR_KEY(&it2);
1703 if ((bt1 = bson_find_from_buffer(&it1, b1data, k2)) == BSON_EOO) {
1704 bson_append_field_from_iterator(&it2, out);
1710 int bson_merge_recursive(const bson *b1, const bson *b2, bson_bool_t overwrite, bson *out) {
1711 assert(b1 && b2 && out);
1712 if (!b1->finished || !b2->finished || out->finished) {
1715 return bson_merge_recursive2(bson_data(b1), bson_data(b2), overwrite, out);
1719 int nstack; //nested object stack pos
1720 int matched; //number of matched include fields
1721 int astack; //nested array stack pos
1723 } _BSONSTRIPVISITORCTX;
1725 /* Discard excluded fields from BSON */
1726 static bson_visitor_cmd_t _bsonstripvisitor_exclude(const char *ipath, int ipathlen, const char *key, int keylen,
1727 const bson_iterator *it, bool after, void *op) {
1728 _BSONSTRIPVISITORCTX *ictx = op;
1730 BSONSTRIPCTX *sctx = ictx->sctx;
1731 assert(sctx && sctx->bsout && sctx->ifields && ipath && key && it && op);
1732 TCMAP *ifields = sctx->ifields;
1736 bson_type bt = BSON_ITERATOR_TYPE(it);
1738 buf = after ? NULL : tcmapget(ifields, ipath, ipathlen, &bufsz);
1740 if (bt == BSON_OBJECT || bt == BSON_ARRAY) {
1742 tcmapiterinit(ifields); //check prefix
1743 while ((ifpath = tcmapiternext2(ifields)) != NULL) {
1745 for (; i < ipathlen && *(ifpath + i) == *(ipath + i); ++i);
1746 if (i == ipathlen) { //ipath prefixes some exclude object field
1748 if (bt == BSON_OBJECT) {
1749 bson_append_start_object2(sctx->bsout, key, keylen);
1750 } else if (bt == BSON_ARRAY) {
1752 bson_append_start_array2(sctx->bsout, key, keylen);
1754 return (BSON_VCMD_OK);
1757 bson_append_field_from_iterator(it, sctx->bsout);
1758 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
1760 if (ictx->nstack > 0) {
1762 if (bt == BSON_OBJECT) {
1763 bson_append_finish_object(sctx->bsout);
1764 } else if (bt == BSON_ARRAY) {
1766 bson_append_finish_array(sctx->bsout);
1769 return (BSON_VCMD_OK);
1772 bson_append_field_from_iterator(it, sctx->bsout);
1773 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
1775 } else if (!after && ictx->astack > 0 && bson_isnumstr(key, keylen)) {
1776 bson_append_undefined(sctx->bsout, key);
1778 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
1781 /* Accept only included fields into BSON */
1782 static bson_visitor_cmd_t _bsonstripvisitor_include(const char *ipath, int ipathlen, const char *key, int keylen,
1783 const bson_iterator *it, bool after, void *op) {
1784 _BSONSTRIPVISITORCTX *ictx = op;
1786 BSONSTRIPCTX *sctx = ictx->sctx;
1787 assert(sctx && sctx->bsout && sctx->ifields && ipath && key && it && op);
1788 bson_visitor_cmd_t rv = BSON_VCMD_OK;
1789 TCMAP *ifields = sctx->ifields;
1794 const char *k = key;
1795 if (sctx->fkfields) { //find keys to override
1796 k = tcmapget(sctx->fkfields, ipath, ipathlen, &bufsz);
1801 bson_type bt = BSON_ITERATOR_TYPE(it);
1802 if (bt != BSON_OBJECT && bt != BSON_ARRAY) {
1803 if (after) { //simple primitive case
1804 return BSON_VCMD_OK;
1806 buf = tcmapget(ifields, ipath, ipathlen, &bufsz);
1809 bson_append_field_from_iterator2(k, it, sctx->bsout);
1811 return (BSON_VCMD_SKIP_AFTER);
1812 } else { //more complicated case
1814 buf = tcmapget(ifields, ipath, ipathlen, &bufsz);
1815 if (buf) { //field hitted
1816 bson_iterator cit = *it; //copy iterator
1817 bson_append_field_from_iterator(&cit, sctx->bsout);
1819 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
1820 } else { //check prefix
1821 int onstack = ictx->nstack;
1822 tcmapiterinit(ifields);
1823 while ((ifpath = tcmapiternext2(ifields)) != NULL) {
1825 for (; i < ipathlen && *(ifpath + i) == *(ipath + i); ++i);
1826 if (i == ipathlen) { //ipath prefixes some included field
1828 if (bt == BSON_OBJECT) {
1829 bson_append_start_object2(sctx->bsout, k, keylen);
1830 } else if (bt == BSON_ARRAY) {
1831 bson_append_start_array2(sctx->bsout, k, keylen);
1838 if (onstack == ictx->nstack) {
1839 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
1843 if (ictx->nstack > 0) {
1845 if (bt == BSON_OBJECT) {
1846 bson_append_finish_object(sctx->bsout);
1847 } else if (bt == BSON_ARRAY) {
1848 bson_append_finish_array(sctx->bsout);
1856 if (ictx->nstack == 0 && ictx->matched == TCMAPRNUM(ifields)) {
1857 return BSON_VCMD_TERMINATE;
1862 int bson_strip(TCMAP *ifields, bool imode, const void *bsbuf, bson *bsout) {
1863 BSONSTRIPCTX sctx = {
1870 return bson_strip2(&sctx);
1873 /* Include or exclude fpaths in the specified BSON and put resulting data into `bsout`. */
1874 int bson_strip2(BSONSTRIPCTX *sctx) {
1875 assert(sctx && sctx->bsbuf && sctx->bsout);
1876 if (!sctx->ifields || sctx->bsout->finished) {
1879 _BSONSTRIPVISITORCTX ictx = {
1886 BSON_ITERATOR_FROM_BUFFER(&it, sctx->bsbuf);
1887 bson_visit_fields(&it, 0, (sctx->imode) ? _bsonstripvisitor_include : _bsonstripvisitor_exclude, &ictx);
1888 assert(ictx.nstack == 0);
1889 return bson_finish(sctx->bsout);
1892 int bson_inplace_set_bool(bson_iterator *pos, bson_bool_t val) {
1894 bson_type bt = BSON_ITERATOR_TYPE(pos);
1895 if (bt != BSON_BOOL) {
1898 char *t = (char*) pos->cur + 1;
1904 int bson_inplace_set_long(bson_iterator *pos, int64_t val) {
1906 bson_type bt = BSON_ITERATOR_TYPE(pos);
1907 if (!BSON_IS_NUM_TYPE(bt)) {
1910 char *t = (char*) pos->cur + 1;
1912 if (bt == BSON_INT) {
1913 bson_little_endian32(t, &val);
1914 } else if (bt == BSON_LONG || bt == BSON_DATE) {
1915 bson_little_endian64(t, &val);
1916 } else if (bt == BSON_DOUBLE) {
1917 double dval = (double) val;
1918 bson_little_endian64(t, &dval);
1925 int bson_inplace_set_double(bson_iterator *pos, double val) {
1927 bson_type bt = BSON_ITERATOR_TYPE(pos);
1928 if (!BSON_IS_NUM_TYPE(bt)) {
1931 int64_t ival = (int64_t) val;
1932 char *t = (char*) pos->cur + 1;
1934 if (bt == BSON_INT) {
1935 bson_little_endian32(t, &ival);
1936 } else if (bt == BSON_LONG || bt == BSON_DATE) {
1937 bson_little_endian64(t, &ival);
1938 } else if (bt == BSON_DOUBLE) {
1939 bson_little_endian64(t, &val);
1946 int bson_compare_fpaths(const void *bsdata1, const void *bsdata2, const char *fpath1, int fplen1, const char *fpath2, int fplen2) {
1947 assert(bsdata1 && bsdata2 && fpath1 && fpath2);
1948 bson_iterator it1, it2;
1949 BSON_ITERATOR_FROM_BUFFER(&it1, bsdata1);
1950 BSON_ITERATOR_FROM_BUFFER(&it2, bsdata2);
1951 bson_find_fieldpath_value2(fpath1, fplen1, &it1);
1952 bson_find_fieldpath_value2(fpath2, fplen2, &it2);
1953 return bson_compare_it_current(&it1, &it2);
1958 * Return <0 if value pointing by it1 lesser than from it2.
1959 * Return 0 if values equal
1960 * Return >0 if value pointing by it1 greater than from it2.
1965 int bson_compare_it_current(const bson_iterator *it1, const bson_iterator *it2) {
1966 bson_type t1 = BSON_ITERATOR_TYPE(it1);
1967 bson_type t2 = BSON_ITERATOR_TYPE(it2);
1969 if ((BSON_IS_STRING_TYPE(t1) && !BSON_IS_STRING_TYPE(t2)) ||
1970 (BSON_IS_STRING_TYPE(t2) && !BSON_IS_STRING_TYPE(t1))) {
1974 if (t1 == BSON_BOOL || t1 == BSON_EOO || t1 == BSON_NULL || t1 == BSON_UNDEFINED) {
1975 int v1 = bson_iterator_bool(it1);
1976 int v2 = bson_iterator_bool(it2);
1977 return (v1 > v2) ? 1 : ((v1 < v2) ? -1 : 0);
1978 } else if (t1 == BSON_INT || t1 == BSON_LONG || t1 == BSON_DATE || t1 == BSON_TIMESTAMP) {
1979 int64_t v1 = bson_iterator_long_ext(it1);
1980 int64_t v2 = bson_iterator_long_ext(it2);
1981 return (v1 > v2) ? 1 : ((v1 < v2) ? -1 : 0);
1982 } else if (t1 == BSON_DOUBLE) {
1983 double v1 = bson_iterator_double_raw(it1);
1984 double v2 = bson_iterator_double(it2);
1985 return (v1 > v2) ? 1 : ((v1 < v2) ? -1 : 0);
1986 } else if (BSON_IS_STRING_TYPE(t1)) {
1987 const char* v1 = bson_iterator_string(it1);
1988 int l1 = bson_iterator_string_len(it1);
1989 const char* v2 = bson_iterator_string(it2);
1990 int l2 = bson_iterator_string_len(it2);
1992 TCCMPLEXICAL(rv, v1, l1, v2, l2);
1994 } else if (t1 == BSON_BINDATA && t2 == BSON_BINDATA) {
1995 int l1 = bson_iterator_bin_len(it1);
1996 int l2 = bson_iterator_bin_len(it2);
1997 return memcmp(bson_iterator_bin_data(it1), bson_iterator_bin_data(it2), MIN(l1, l2));
1998 } else if (t1 == BSON_OID && t2 == BSON_OID) {
1999 return memcmp(bson_iterator_oid(it1), bson_iterator_oid(it2), sizeof (bson_oid_t));
2000 } else if (t1 == t2 && (t1 == BSON_OBJECT || t1 == BSON_ARRAY)) {
2003 bson_iterator sit1, sit2;
2004 BSON_ITERATOR_SUBITERATOR(it1, &sit1);
2005 BSON_ITERATOR_SUBITERATOR(it2, &sit2);
2006 while ((bt1 = bson_iterator_next(&sit1)) != BSON_EOO) {
2007 bt2 = bson_iterator_next(&sit2);
2008 if (bt2 == BSON_EOO) {
2012 cv = bson_compare_it_current(&sit1, &sit2);
2017 if (cv == 0 && bson_iterator_next(&sit2) != BSON_EOO) {
2025 int bson_compare(const void *bsdata1, const void *bsdata2, const char* fpath, int fplen) {
2026 return bson_compare_fpaths(bsdata1, bsdata2, fpath, fplen, fpath, fplen);
2029 int bson_compare_string(const char *cv, const void *bsdata, const char *fpath) {
2030 assert(cv && bsdata && fpath);
2031 bson *bs1 = bson_create();
2033 bson_append_string(bs1, "$", cv);
2035 int res = bson_compare_fpaths(bson_data(bs1), bsdata, "$", 1, fpath, strlen(fpath));
2040 int bson_compare_long(const int64_t cv, const void *bsdata, const char *fpath) {
2041 bson *bs1 = bson_create();
2043 bson_append_long(bs1, "$", cv);
2045 int res = bson_compare_fpaths(bson_data(bs1), bsdata, "$", 1, fpath, strlen(fpath));
2050 int bson_compare_double(double cv, const void *bsdata, const char *fpath) {
2051 bson *bs1 = bson_create();
2053 bson_append_double(bs1, "$", cv);
2055 int res = bson_compare_fpaths(bson_data(bs1), bsdata, "$", 1, fpath, strlen(fpath));
2060 int bson_compare_bool(bson_bool_t cv, const void *bsdata, const char *fpath) {
2061 bson *bs1 = bson_create();
2063 bson_append_bool(bs1, "$", cv);
2065 int res = bson_compare_fpaths(bson_data(bs1), bsdata, "$", 1, fpath, strlen(fpath));
2070 bson* bson_dup(const bson *src) {
2072 bson *rv = bson_create();
2073 int s = bson_size(src);
2074 _bson_init_size(rv, s);
2075 memmove(rv->data, src->data, s);
2080 bson* bson_create_from_iterator(bson_iterator *from) {
2083 bson *bs = bson_create();
2084 bson_init_as_query(bs);
2085 while ((bt = bson_iterator_next(from)) != BSON_EOO) {
2086 bson_append_field_from_iterator(from, bs);
2092 bson* bson_create_from_buffer(const void* buf, int bufsz) {
2093 return bson_create_from_buffer2(bson_create(), buf, bufsz);
2096 bson* bson_create_from_buffer2(bson *rv, const void* buf, int bufsz) {
2098 assert(bufsz - 4 > 0);
2099 bson_init_size(rv, bufsz);
2100 bson_ensure_space(rv, bufsz - 4);
2101 bson_append(rv, (char*) buf + 4, bufsz - (4 + 1/*BSON_EOO*/));
2106 void bson_init_with_data(bson *bs, const void *bsdata) {
2107 memset(bs, 0, sizeof (*bs));
2108 bs->data = (char*) bsdata;
2109 bson_little_endian32(&bs->dataSize, bsdata);
2110 bs->finished = true;
2113 bool bson_find_merged_array_sets(const void *mbuf, const void *inbuf, bool expandall) {
2114 assert(mbuf && inbuf);
2116 bson_iterator it, it2;
2118 BSON_ITERATOR_FROM_BUFFER(&it, mbuf);
2120 while (!found && (bt = bson_iterator_next(&it)) != BSON_EOO) {
2121 if (expandall && bt != BSON_ARRAY) {
2124 BSON_ITERATOR_FROM_BUFFER(&it2, inbuf);
2125 bt2 = bson_find_fieldpath_value(BSON_ITERATOR_KEY(&it), &it2);
2126 if (bt2 != BSON_ARRAY) {
2130 BSON_ITERATOR_SUBITERATOR(&it2, &sit);
2131 while (!found && (bt2 = bson_iterator_next(&sit)) != BSON_EOO) {
2134 BSON_ITERATOR_SUBITERATOR(&it, &sit2);
2135 while ((bt2 = bson_iterator_next(&sit2)) != BSON_EOO) {
2136 if (!bson_compare_it_current(&sit, &sit2)) {
2142 if (!bson_compare_it_current(&sit, &it)) {
2152 bool bson_find_unmerged_array_sets(const void *mbuf, const void *inbuf) {
2153 assert(mbuf && inbuf);
2154 bool allfound = false;
2155 bson_iterator it, it2;
2157 BSON_ITERATOR_FROM_BUFFER(&it, mbuf);
2158 while ((bt = bson_iterator_next(&it)) != BSON_EOO) {
2159 BSON_ITERATOR_FROM_BUFFER(&it2, inbuf);
2160 bt2 = bson_find_fieldpath_value(BSON_ITERATOR_KEY(&it), &it2);
2161 if (bt2 == BSON_EOO) { //array missing it will be created
2165 if (bt2 != BSON_ARRAY) { //not an array field
2170 BSON_ITERATOR_SUBITERATOR(&it2, &sit);
2171 while ((bt2 = bson_iterator_next(&sit)) != BSON_EOO) {
2172 if (!bson_compare_it_current(&sit, &it)) {
2193 static bson_visitor_cmd_t bson_merge_array_sets_pull_tf(const char *fpath, int fpathlen, const char *key, int keylen, const bson_iterator *it, bool after, void *op) {
2194 BSON_MASETS_CTX *ctx = op;
2195 assert(ctx && ctx->mfields >= 0);
2197 bson_type bt = BSON_ITERATOR_TYPE(it);
2198 if (bt != BSON_OBJECT && bt != BSON_ARRAY) { //trivial case
2200 return (BSON_VCMD_OK);
2202 bson_append_field_from_iterator(it, ctx->bsout);
2203 return (BSON_VCMD_SKIP_AFTER);
2205 if (bt == BSON_ARRAY) {
2206 BSON_ITERATOR_FROM_BUFFER(&mit, ctx->mbuf);
2207 bt = bson_find_fieldpath_value2(fpath, fpathlen, &mit);
2208 if (bt == BSON_EOO || (ctx->expandall && bt != BSON_ARRAY)) {
2209 bson_append_field_from_iterator(it, ctx->bsout);
2210 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
2212 if (ctx->mfields > 0) {
2217 BSON_ITERATOR_SUBITERATOR(it, &ait);
2218 bson_append_start_array(ctx->bsout, key);
2221 while ((bt = bson_iterator_next(&ait)) != BSON_EOO) {
2223 if (ctx->expandall) {
2224 bson_iterator mitsub;
2225 BSON_ITERATOR_SUBITERATOR(&mit, &mitsub);
2226 while ((bt = bson_iterator_next(&mitsub)) != BSON_EOO) {
2227 if (!bson_compare_it_current(&ait, &mitsub)) {
2233 found = !bson_compare_it_current(&ait, &mit);
2236 char kbuf[TCNUMBUFSIZ];
2237 bson_numstrn(kbuf, TCNUMBUFSIZ, c++);
2238 bson_append_field_from_iterator2(kbuf, &ait, ctx->bsout);
2241 bson_append_finish_array(ctx->bsout);
2242 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
2246 bson_append_start_object(ctx->bsout, key);
2248 bson_append_finish_object(ctx->bsout);
2250 return (BSON_VCMD_OK);
2253 static bson_visitor_cmd_t bson_merge_array_sets_tf(const char *fpath, int fpathlen, const char *key, int keylen, const bson_iterator *it, bool after, void *op) {
2254 BSON_MASETS_CTX *ctx = op;
2255 assert(ctx && ctx->mfields >= 0);
2257 bson_type bt = BSON_ITERATOR_TYPE(it);
2259 if (bt != BSON_OBJECT && bt != BSON_ARRAY) { //trivial case
2261 return (BSON_VCMD_OK);
2263 bson_append_field_from_iterator(it, ctx->bsout);
2264 return (BSON_VCMD_SKIP_AFTER);
2266 if (bt == BSON_ARRAY) {
2268 bson_append_finish_array(ctx->bsout);
2269 return (BSON_VCMD_OK);
2271 BSON_ITERATOR_FROM_BUFFER(&mit, ctx->mbuf);
2272 bt = bson_find_fieldpath_value2(fpath, fpathlen, &mit);
2273 if (bt == BSON_EOO) {
2274 bson_append_start_array(ctx->bsout, key);
2275 return (BSON_VCMD_OK);
2277 if (ctx->expandall && bt != BSON_ARRAY) {
2278 bson_append_field_from_iterator(it, ctx->bsout);
2279 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
2281 if (ctx->mfields > 0) {
2286 BSON_ITERATOR_SUBITERATOR(it, &ait);
2287 bson_append_start_array(ctx->bsout, key);
2290 if (ctx->expandall) { //Set of array elements to add
2291 while ((bt = bson_iterator_next(&ait)) != BSON_EOO) { //Flush current array
2292 bson_append_field_from_iterator(&ait, ctx->bsout);
2295 //Iterate over set to add
2296 bson_iterator mitsub;
2297 BSON_ITERATOR_SUBITERATOR(&mit, &mitsub); //mit has BSON_ARRAY type
2298 while ((bt = bson_iterator_next(&mitsub)) != BSON_EOO) {
2300 BSON_ITERATOR_SUBITERATOR(it, &ait); //Rewind main array iterator
2301 while ((bt = bson_iterator_next(&ait)) != BSON_EOO) {
2302 if (!bson_compare_it_current(&ait, &mitsub)) {
2307 if (!found) { //Append missing element
2308 char kbuf[TCNUMBUFSIZ];
2309 bson_numstrn(kbuf, TCNUMBUFSIZ, c++);
2310 bson_append_field_from_iterator2(kbuf, &mitsub, ctx->bsout);
2314 } else { //Single element to add
2315 while ((bt = bson_iterator_next(&ait)) != BSON_EOO) {
2316 if (!found && !bson_compare_it_current(&ait, &mit)) {
2319 bson_append_field_from_iterator(&ait, ctx->bsout);
2322 if (!found) { //uppend missing element into array
2323 char kbuf[TCNUMBUFSIZ];
2324 bson_numstrn(kbuf, TCNUMBUFSIZ, c);
2325 bson_append_field_from_iterator2(kbuf, &mit, ctx->bsout);
2329 bson_append_finish_array(ctx->bsout);
2330 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
2334 bson_append_start_object(ctx->bsout, key);
2336 bson_append_finish_object(ctx->bsout);
2338 return (BSON_VCMD_OK);
2342 int bson_merge_array_sets(const void *mbuf, const void *inbuf, bool pull, bool expandall, bson *bsout) {
2343 assert(mbuf && inbuf && bsout);
2344 if (bsout->finished) {
2347 BSON_MASETS_CTX ctx = {
2352 .expandall = expandall,
2356 bson_iterator it, it2;
2357 BSON_ITERATOR_FROM_BUFFER(&it, mbuf);
2358 while ((bt = bson_iterator_next(&it)) != BSON_EOO) {
2359 if (expandall && bt != BSON_ARRAY) {
2364 BSON_ITERATOR_FROM_BUFFER(&it, inbuf);
2366 bson_visit_fields(&it, 0, bson_merge_array_sets_pull_tf, &ctx);
2368 bson_visit_fields(&it, 0, bson_merge_array_sets_tf, &ctx);
2370 if (ctx.mfields == 0 || pull) {
2374 //Append missing arrays fields
2375 BSON_ITERATOR_FROM_BUFFER(&it, mbuf);
2376 while ((bt = bson_iterator_next(&it)) != BSON_EOO) {
2377 const char *fpath = BSON_ITERATOR_KEY(&it);
2378 // all data from inbuf already in bsout
2380 BSON_ITERATOR_INIT(&it2, bsout);
2381 bt2 = bson_find_fieldpath_value(fpath, &it2);
2382 if (bt2 != BSON_EOO) continue;
2385 const char *pdp = fpath;
2388 while (*(fpath + i) != '\0') {
2389 for (; *(fpath + i) != '\0' && *(fpath + i) != '.'; ++i);
2390 if (*(fpath + i) == '\0') { //EOF
2391 assert((fpath + i) - pdp > 0);
2392 bson_append_start_array2(&bst, pdp, (fpath + i) - pdp);
2393 bson_append_field_from_iterator2("0", &it, &bst);
2394 bson_append_finish_array(&bst);
2398 assert((fpath + i) - pdp > 0);
2399 bson_append_start_object2(&bst, pdp, (fpath + i) - pdp);
2402 while (*pdp == '.') {
2407 for (; lvl > 0; --lvl) {
2408 bson_append_finish_object(&bst);
2413 bson_init_finished_data(&bsc, bson_data(bsout));
2414 bson_init_size(bsout, bson_size(bsout));
2415 int res = bson_merge_recursive(&bsc, &bst, false, bsout);
2419 if (res != BSON_OK) {
2428 int nlvl; //nesting level
2429 TCXSTR *out; //output buffer
2432 static void _jsonxstrescaped(TCXSTR *xstr, const char *str) {
2433 size_t sz = strlen(str);
2443 const char * ebuf = NULL;
2445 case '\r': ebuf = "\\r";
2447 case '\n': ebuf = "\\n";
2449 case '\\': ebuf = "\\\\";
2453 case '"': ebuf = "\\\"";
2455 case '\f': ebuf = "\\f";
2457 case '\b': ebuf = "\\b";
2459 case '\t': ebuf = "\\t";
2462 if ((unsigned char) str[e] < 0x20) {
2463 static const char *hexchar = "0123456789ABCDEF";
2464 hb[4] = hexchar[str[e] >> 4];
2465 hb[5] = hexchar[str[e] & 0x0F];
2472 tcxstrcat(xstr, str + s, e - s);
2474 tcxstrcat2(xstr, ebuf);
2480 tcxstrcat(xstr, (str + s), e - s);
2483 static int _bson2json(_BSON2JSONCTX *ctx, bson_iterator *it, bool array) {
2486 for (int i = 0; i < ctx->nlvl + (_n); ++i) tcxstrcat2(ctx->out, " ")
2489 TCXSTR *out = ctx->out;
2490 tcxstrcat2(ctx->out, array ? "[\n" : "{\n");
2493 while ((bt = bson_iterator_next(it)) != BSON_EOO) {
2496 tcxstrcat2(out, "\n");
2499 tcxstrcat2(out, ",\n");
2501 const char *key = BSON_ITERATOR_KEY(it);
2504 tcxstrcat2(out, "\"");
2505 _jsonxstrescaped(out, key);
2506 tcxstrcat2(out, "\" : ");
2512 tcxstrprintf(out, "%" PRId64, (int64_t) bson_iterator_long_ext(it));
2516 tcxstrprintf(out, "%lf", bson_iterator_double(it));
2522 tcxstrcat2(out, "\"");
2523 _jsonxstrescaped(out, bson_iterator_string(it));
2524 tcxstrcat2(out, "\"");
2531 BSON_ITERATOR_SUBITERATOR(it, &sit);
2532 _bson2json(ctx, &sit, bt == BSON_ARRAY);
2536 tcxstrcat2(out, "null");
2537 case BSON_UNDEFINED:
2541 bson_date_t t = bson_iterator_date(it);
2543 tcdatestrwww(t, INT_MAX, dbuf);
2544 tcxstrprintf(out, "\"%s\"", dbuf);
2548 tcxstrcat2(out, bson_iterator_bool(it) ? "true" : "false");
2553 bson_oid_t *oid = bson_iterator_oid(it);
2554 bson_oid_to_string(oid, xoid);
2555 tcxstrprintf(out, "\"%s\"", xoid);
2560 tcxstrcat2(out, "\"");
2561 _jsonxstrescaped(out, bson_iterator_regex(it));
2562 tcxstrcat2(out, "\"");
2567 const char *buf = bson_iterator_bin_data(it);
2568 int bsz = bson_iterator_bin_len(it);
2569 char *b64data = tcbaseencode(buf, bsz);
2570 tcxstrcat2(out, "\"");
2571 tcxstrcat2(out, b64data);
2572 tcxstrcat2(out, "\"");
2580 tcxstrcat2(out, "\n");
2582 tcxstrcat2(out, array ? "]" : "}");
2588 int bson2json(const char *bsdata, char **buf, int *sp) {
2589 assert(bsdata && buf && sp);
2591 BSON_ITERATOR_FROM_BUFFER(&it, bsdata);
2592 TCXSTR *out = tcxstrnew();
2593 _BSON2JSONCTX ctx = {
2597 int ret = _bson2json(&ctx, &it, false);
2598 if (ret == BSON_OK) {
2599 *sp = TCXSTRSIZE(out);
2600 *buf = tcxstrtomalloc(out);
2612 static void _json2bson(bson *out, const nx_json *json, const char *forcekey) {
2613 const char *key = forcekey ? forcekey : json->key;
2614 switch (json->type) {
2617 bson_append_null(out, key);
2619 case NX_JSON_OBJECT:
2622 bson_append_start_object(out, key);
2624 for (nx_json* js = json->child; js; js = js->next) {
2625 _json2bson(out, js, NULL);
2628 bson_append_finish_object(out);
2635 bson_append_start_array(out, key);
2638 char kbuf[TCNUMBUFSIZ];
2639 for (nx_json* js = json->child; js; js = js->next) {
2640 bson_numstrn(kbuf, TCNUMBUFSIZ, c++);
2641 _json2bson(out, js, kbuf);
2644 bson_append_finish_array(out);
2648 case NX_JSON_STRING:
2650 bson_append_string(out, key, json->text_value);
2652 case NX_JSON_INTEGER:
2654 if (json->int_value <= INT_MAX && json->int_value >= INT_MIN) {
2655 bson_append_int(out, key, (int) json->int_value);
2657 bson_append_long(out, key, json->int_value);
2660 case NX_JSON_DOUBLE:
2662 bson_append_double(out, key, json->dbl_value);
2666 bson_append_bool(out, key, json->int_value ? true : false);
2673 bson* json2bson(const char *jsonstr) {
2676 char *json = strdup(jsonstr); //nxjson uses inplace data modification
2680 out = bson_create();
2681 bson_init_as_query(out);
2682 const nx_json *nxjson = nx_json_parse_utf8(json);
2687 _json2bson(out, nxjson, NULL);
2693 nx_json_free(nxjson);