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) {
902 if (b->err & BSON_NOT_UTF8)
905 if (bson_ensure_space(b, 1) == BSON_ERROR) return BSON_ERROR;
906 bson_append_byte(b, 0);
907 i = b->cur - b->data;
908 bson_little_endian32(b->data, &i);
914 void bson_destroy(bson *b) {
916 if (b->data && !(b->flags & BSON_FLAG_STACK_ALLOCATED)) {
924 bson_free_func(b->errstr);
930 void bson_del(bson *b) {
937 static int bson_append_estart2(bson *b, int type, const char *name, int namelen, const int dataSize);
939 static int bson_append_estart(bson *b, int type, const char *name, const int dataSize) {
940 return bson_append_estart2(b, type, name, strlen(name), dataSize);
943 static int bson_append_estart2(bson *b, int type, const char *name, int namelen, const int dataSize) {
944 const int len = namelen + 1;
947 b->err |= BSON_ALREADY_FINISHED;
951 if (bson_ensure_space(b, 1 + len + dataSize) == BSON_ERROR) {
955 if (bson_check_field_name(b, (const char *) name, namelen,
956 !(b->flags & BSON_FLAG_QUERY_MODE), !(b->flags & BSON_FLAG_QUERY_MODE)) == BSON_ERROR) {
957 bson_builder_error(b);
960 bson_append_byte(b, (char) type);
961 memcpy(b->cur, name, namelen);
968 /* ----------------------------
970 ------------------------------ */
972 int bson_append_int(bson *b, const char *name, const int i) {
973 if (bson_append_estart(b, BSON_INT, name, 4) == BSON_ERROR)
975 bson_append32(b, &i);
979 int bson_append_long(bson *b, const char *name, const int64_t i) {
980 if (bson_append_estart(b, BSON_LONG, name, 8) == BSON_ERROR)
982 bson_append64(b, &i);
986 int bson_append_double(bson *b, const char *name, const double d) {
987 if (bson_append_estart(b, BSON_DOUBLE, name, 8) == BSON_ERROR)
989 bson_append64(b, &d);
993 int bson_append_bool(bson *b, const char *name, const bson_bool_t i) {
994 if (bson_append_estart(b, BSON_BOOL, name, 1) == BSON_ERROR)
996 bson_append_byte(b, i != 0);
1000 int bson_append_null(bson *b, const char *name) {
1001 if (bson_append_estart(b, BSON_NULL, name, 0) == BSON_ERROR)
1006 int bson_append_undefined(bson *b, const char *name) {
1007 if (bson_append_estart(b, BSON_UNDEFINED, name, 0) == BSON_ERROR)
1012 int bson_append_string_base(bson *b, const char *name,
1013 const char *value, int len, bson_type type) {
1016 if (bson_check_string(b, (const char *) value, sl - 1) == BSON_ERROR)
1018 if (bson_append_estart(b, type, name, 4 + sl) == BSON_ERROR) {
1021 bson_append32(b, &sl);
1022 bson_append(b, value, sl - 1);
1023 bson_append(b, "\0", 1);
1027 int bson_append_string(bson *b, const char *name, const char *value) {
1028 return bson_append_string_base(b, name, value, strlen(value), BSON_STRING);
1031 int bson_append_symbol(bson *b, const char *name, const char *value) {
1032 return bson_append_string_base(b, name, value, strlen(value), BSON_SYMBOL);
1035 int bson_append_code(bson *b, const char *name, const char *value) {
1036 return bson_append_string_base(b, name, value, strlen(value), BSON_CODE);
1039 int bson_append_string_n(bson *b, const char *name, const char *value, int len) {
1040 return bson_append_string_base(b, name, value, len, BSON_STRING);
1043 int bson_append_symbol_n(bson *b, const char *name, const char *value, int len) {
1044 return bson_append_string_base(b, name, value, len, BSON_SYMBOL);
1047 int bson_append_code_n(bson *b, const char *name, const char *value, int len) {
1048 return bson_append_string_base(b, name, value, len, BSON_CODE);
1051 int bson_append_code_w_scope_n(bson *b, const char *name,
1052 const char *code, int len, const bson *scope) {
1055 if (!scope) return BSON_ERROR;
1057 size = 4 + 4 + sl + bson_size(scope);
1058 if (bson_append_estart(b, BSON_CODEWSCOPE, name, size) == BSON_ERROR)
1060 bson_append32(b, &size);
1061 bson_append32(b, &sl);
1062 bson_append(b, code, sl);
1063 bson_append(b, scope->data, bson_size(scope));
1067 int bson_append_code_w_scope(bson *b, const char *name, const char *code, const bson *scope) {
1068 return bson_append_code_w_scope_n(b, name, code, strlen(code), scope);
1071 int bson_append_binary(bson *b, const char *name, char type, const char *str, int len) {
1072 if (type == BSON_BIN_BINARY_OLD) {
1073 int subtwolen = len + 4;
1074 if (bson_append_estart(b, BSON_BINDATA, name, 4 + 1 + 4 + len) == BSON_ERROR)
1076 bson_append32(b, &subtwolen);
1077 bson_append_byte(b, type);
1078 bson_append32(b, &len);
1079 bson_append(b, str, len);
1081 if (bson_append_estart(b, BSON_BINDATA, name, 4 + 1 + len) == BSON_ERROR)
1083 bson_append32(b, &len);
1084 bson_append_byte(b, type);
1085 bson_append(b, str, len);
1090 int bson_append_oid(bson *b, const char *name, const bson_oid_t *oid) {
1091 if (bson_append_estart(b, BSON_OID, name, 12) == BSON_ERROR)
1093 bson_append(b, oid, 12);
1097 int bson_append_new_oid(bson *b, const char *name) {
1100 return bson_append_oid(b, name, &oid);
1103 int bson_append_regex(bson *b, const char *name, const char *pattern, const char *opts) {
1104 const int plen = strlen(pattern) + 1;
1105 const int olen = strlen(opts) + 1;
1106 if (bson_append_estart(b, BSON_REGEX, name, plen + olen) == BSON_ERROR)
1108 if (bson_check_string(b, pattern, plen - 1) == BSON_ERROR)
1110 bson_append(b, pattern, plen);
1111 bson_append(b, opts, olen);
1115 int bson_append_bson(bson *b, const char *name, const bson *bson) {
1116 if (!bson) return BSON_ERROR;
1117 if (bson_append_estart(b, BSON_OBJECT, name, bson_size(bson)) == BSON_ERROR)
1119 bson_append(b, bson->data, bson_size(bson));
1123 int bson_append_element(bson *b, const char *name_or_null, const bson_iterator *elem) {
1124 bson_iterator next = *elem;
1127 bson_iterator_next(&next);
1128 size = next.cur - elem->cur;
1130 if (name_or_null == NULL) {
1131 if (bson_ensure_space(b, size) == BSON_ERROR)
1133 bson_append(b, elem->cur, size);
1135 int data_size = size - 2 - strlen(BSON_ITERATOR_KEY(elem));
1136 bson_append_estart(b, elem->cur[0], name_or_null, data_size);
1137 bson_append(b, bson_iterator_value(elem), data_size);
1143 int bson_append_timestamp(bson *b, const char *name, bson_timestamp_t *ts) {
1144 if (bson_append_estart(b, BSON_TIMESTAMP, name, 8) == BSON_ERROR) return BSON_ERROR;
1146 bson_append32(b, &(ts->i));
1147 bson_append32(b, &(ts->t));
1152 int bson_append_timestamp2(bson *b, const char *name, int time, int increment) {
1153 if (bson_append_estart(b, BSON_TIMESTAMP, name, 8) == BSON_ERROR) return BSON_ERROR;
1155 bson_append32(b, &increment);
1156 bson_append32(b, &time);
1160 int bson_append_date(bson *b, const char *name, bson_date_t millis) {
1161 if (bson_append_estart(b, BSON_DATE, name, 8) == BSON_ERROR) return BSON_ERROR;
1162 bson_append64(b, &millis);
1166 int bson_append_time_t(bson *b, const char *name, time_t secs) {
1167 return bson_append_date(b, name, (bson_date_t) secs * 1000);
1170 int bson_append_start_object(bson *b, const char *name) {
1171 if (bson_append_estart(b, BSON_OBJECT, name, 5) == BSON_ERROR) return BSON_ERROR;
1172 b->stack[ b->stackPos++ ] = b->cur - b->data;
1173 bson_append32(b, &zero);
1177 int bson_append_start_object2(bson *b, const char *name, int namelen) {
1178 if (bson_append_estart2(b, BSON_OBJECT, name, namelen, 5) == BSON_ERROR) return BSON_ERROR;
1179 b->stack[ b->stackPos++ ] = b->cur - b->data;
1180 bson_append32(b, &zero);
1184 int bson_append_start_array(bson *b, const char *name) {
1185 return bson_append_start_array2(b, name, strlen(name));
1188 int bson_append_start_array2(bson *b, const char *name, int namelen) {
1189 if (bson_append_estart2(b, BSON_ARRAY, name, namelen, 5) == BSON_ERROR) return BSON_ERROR;
1190 b->stack[ b->stackPos++ ] = b->cur - b->data;
1191 bson_append32(b, &zero);
1195 int bson_append_finish_object(bson *b) {
1198 if (bson_ensure_space(b, 1) == BSON_ERROR) return BSON_ERROR;
1199 bson_append_byte(b, 0);
1201 start = b->data + b->stack[ --b->stackPos ];
1203 bson_little_endian32(start, &i);
1208 double bson_int64_to_double(int64_t i64) {
1209 return (double) i64;
1212 int bson_append_finish_array(bson *b) {
1213 return bson_append_finish_object(b);
1216 /* Error handling and allocators. */
1218 static bson_err_handler err_handler = NULL;
1220 bson_err_handler set_bson_err_handler(bson_err_handler func) {
1221 bson_err_handler old = err_handler;
1226 void bson_free(void *ptr) {
1227 bson_free_func(ptr);
1230 void *bson_malloc(int size) {
1232 p = bson_malloc_func(size);
1233 bson_fatal_msg(!!p, "malloc() failed");
1237 void *bson_realloc(void *ptr, int size) {
1239 p = bson_realloc_func(ptr, size);
1240 bson_fatal_msg(!!p, "realloc() failed");
1244 int _bson_errprintf(const char *format, ...) {
1247 va_start(ap, format);
1248 ret = vfprintf(stderr, format, ap);
1254 * This method is invoked when a non-fatal bson error is encountered.
1255 * Calls the error handler if available.
1259 void bson_builder_error(bson *b) {
1261 err_handler("BSON error.");
1264 void bson_fatal(int ok) {
1265 bson_fatal_msg(ok, "");
1268 void bson_fatal_msg(int ok, const char *msg) {
1275 bson_errprintf("error: %s\n", msg);
1279 /* Efficiently copy an integer to a string. */
1280 extern const char bson_numstrs[1000][4];
1282 void bson_numstr(char *str, int64_t i) {
1283 if (i >= 0 && i < 1000)
1284 memcpy(str, bson_numstrs[i], 4);
1286 sprintf(str, "%" PRId64 "", (int64_t) i);
1289 #pragma GCC diagnostic push
1290 #pragma GCC diagnostic ignored "-Wformat"
1292 int bson_numstrn(char *str, int maxbuf, int64_t i) {
1293 if (i >= 0 && i < 1000 && maxbuf > 4) {
1294 memcpy(str, bson_numstrs[i], 4);
1295 return strlen(bson_numstrs[i]);
1297 return snprintf(str, maxbuf, "%" PRId64 "", (int64_t) i);
1300 #pragma GCC diagnostic pop
1302 static bson_bool_t bson_isnumstr(const char *str, int len) {
1305 while (len > 0 && *str > '\0' && *str <= ' ') {
1309 while (len > 0 && *str >= '0' && *str <= '9') {
1314 while (len > 0 && *str > '\0' && *str <= ' ') {
1318 return (isnum && (*str == '\0' || len == 0));
1321 void bson_swap_endian64(void *outp, const void *inp) {
1322 const char *in = (const char *) inp;
1323 char *out = (char *) outp;
1335 void bson_swap_endian32(void *outp, const void *inp) {
1336 const char *in = (const char *) inp;
1337 char *out = (char *) outp;
1344 static const char *bson_iterator_value2(const bson_iterator *i, int *klen) {
1345 const char *t = i->cur + 1;
1351 int bson_append_array_from_iterator(const char *key, bson_iterator *from, bson *into) {
1352 assert(key && from && into);
1354 bson_append_start_array(into, key);
1355 while ((bt = bson_iterator_next(from)) != BSON_EOO) {
1356 bson_append_field_from_iterator(from, into);
1358 bson_append_finish_array(into);
1362 int bson_append_object_from_iterator(const char *key, bson_iterator *from, bson *into) {
1363 assert(key && from && into);
1365 bson_append_start_object(into, key);
1366 while ((bt = bson_iterator_next(from)) != BSON_EOO) {
1367 bson_append_field_from_iterator(from, into);
1369 bson_append_finish_object(into);
1373 static void bson_append_fpath_from_iterator(const char *fpath, const bson_iterator *from, bson *into) {
1374 char key[BSON_MAX_FPATH_LEN + 1];
1375 int fplen = strlen(fpath);
1376 if (fplen >= BSON_MAX_FPATH_LEN) { //protect me silently
1377 return; //todo error?
1379 const char *fp = fpath;
1381 int nl = 0; //nesting level
1382 while (fplen > 0) { //split fpath with '.' delim
1383 const char *rp = fp;
1384 const char *ep = fp + fplen;
1386 if (*rp == '.') break;
1390 memcpy(key, fp, keylen);
1394 if (fplen <= 0) { //last part of fp
1395 bson_append_field_from_iterator2(key, from, into);
1397 bson_append_finish_object(into); //arrays are covered also
1399 } else { //intermediate part
1400 if (bson_isnumstr(key, keylen)) {
1402 bson_append_start_array2(into, key, keylen);
1405 bson_append_start_object2(into, key, keylen);
1412 int bson_append_field_from_iterator2(const char *key, const bson_iterator *from, bson *into) {
1413 assert(key && from && into);
1414 bson_type t = BSON_ITERATOR_TYPE(from);
1415 if (t == BSON_EOO || into->finished) {
1421 bson_append_string(into, key, bson_iterator_string(from));
1424 bson_append_code(into, key, bson_iterator_code(from));
1427 bson_append_int(into, key, bson_iterator_int_raw(from));
1430 bson_append_double(into, key, bson_iterator_double_raw(from));
1433 bson_append_long(into, key, bson_iterator_long_raw(from));
1435 case BSON_UNDEFINED:
1436 bson_append_undefined(into, key);
1439 bson_append_null(into, key);
1442 bson_append_bool(into, key, bson_iterator_bool_raw(from));
1444 case BSON_TIMESTAMP:
1446 bson_timestamp_t ts = bson_iterator_timestamp(from);
1447 bson_append_timestamp(into, key, &ts);
1451 bson_append_date(into, key, bson_iterator_date(from));
1454 bson_append_regex(into, key, bson_iterator_regex(from), bson_iterator_regex_opts(from));
1457 bson_append_oid(into, key, bson_iterator_oid(from));
1462 BSON_ITERATOR_SUBITERATOR(from, &sit);
1463 bson_append_start_object(into, key);
1464 while (bson_iterator_next(&sit) != BSON_EOO) {
1465 bson_append_field_from_iterator(&sit, into);
1467 bson_append_finish_object(into);
1473 BSON_ITERATOR_SUBITERATOR(from, &sit);
1474 bson_append_start_array(into, key);
1475 while (bson_iterator_next(&sit) != BSON_EOO) {
1476 bson_append_field_from_iterator(&sit, into);
1478 bson_append_finish_array(into);
1482 case BSON_CODEWSCOPE:
1490 int bson_append_field_from_iterator(const bson_iterator *from, bson *into) {
1491 assert(from && into);
1492 return bson_append_field_from_iterator2(BSON_ITERATOR_KEY(from), from, into);
1498 const void *bsdata2; //bsdata to merge with
1499 int nstack; //nested object stack pos
1500 int matched; //number of matched merge fields
1503 static bson_visitor_cmd_t _bson_merge3_visitor(const char *ipath, int ipathlen, const char *key, int keylen,
1504 const bson_iterator *it, bool after, void *op) {
1505 _BSONMERGE3CTX *ctx = op;
1506 assert(ctx && ctx->bsout && ctx->mfields && ipath && key && it && op);
1510 bson_type bt = BSON_ITERATOR_TYPE(it);
1511 buf = (TCMAPRNUM(ctx->mfields) == 0 || after) ? NULL : tcmapget(ctx->mfields, ipath, ipathlen, &bufsz);
1514 BSON_ITERATOR_FROM_BUFFER(&it2, ctx->bsdata2);
1516 assert(bufsz == sizeof (it2off));
1517 memcpy(&it2off, buf, sizeof (it2off));
1518 assert(it2off >= 0);
1519 it2.cur = it2.cur + it2off;
1520 it2.first = (it2off == 0);
1521 tcmapout(ctx->mfields, ipath, ipathlen);
1522 bson_append_field_from_iterator2(key, &it2, ctx->bsout);
1523 return (BSON_VCMD_SKIP_AFTER | BSON_VCMD_SKIP_NESTED);
1525 if (bt == BSON_OBJECT || bt == BSON_ARRAY) {
1528 if (bt == BSON_OBJECT) {
1529 bson_append_start_object2(ctx->bsout, key, keylen);
1530 } else if (bt == BSON_ARRAY) {
1531 bson_append_start_array2(ctx->bsout, key, keylen);
1533 return BSON_VCMD_OK;
1535 if (ctx->nstack > 0) {
1536 //do we have something to add into end of nested object?
1537 tcmapiterinit(ctx->mfields);
1539 while ((mpath = tcmapiternext(ctx->mfields, &mpathlen)) != NULL) {
1541 for (; i < ipathlen && *(mpath + i) == *(ipath + i); ++i);
1542 if (i == ipathlen && *(mpath + i) == '.' && *(mpath + i + 1) != '\0') { //ipath prefixed
1544 BSON_ITERATOR_FROM_BUFFER(&it2, ctx->bsdata2);
1545 buf = tcmapget(ctx->mfields, mpath, mpathlen, &bufsz);
1547 assert(bufsz == sizeof (it2off));
1548 memcpy(&it2off, buf, sizeof (it2off));
1549 assert(it2off >= 0);
1550 it2.cur = it2.cur + it2off;
1551 it2.first = (it2off == 0);
1552 bson_append_fpath_from_iterator(mpath + i + 1, &it2, ctx->bsout);
1553 tcmapout(ctx->mfields, mpath, mpathlen);
1557 if (bt == BSON_OBJECT) {
1558 bson_append_finish_object(ctx->bsout);
1559 } else if (bt == BSON_ARRAY) {
1560 bson_append_finish_array(ctx->bsout);
1563 return BSON_VCMD_OK;
1566 bson_append_field_from_iterator(it, ctx->bsout);
1567 return BSON_VCMD_SKIP_AFTER;
1572 //merge with fpath support
1574 int bson_merge3(const void *bsdata1, const void *bsdata2, bson *out) {
1575 assert(bsdata1 && bsdata2 && out);
1576 bson_iterator it1, it2;
1578 BSON_ITERATOR_FROM_BUFFER(&it1, bsdata1);
1579 BSON_ITERATOR_FROM_BUFFER(&it2, bsdata2);
1580 const char *it2start = it2.cur;
1581 TCMAP *mfields = tcmapnew2(TCMAPTINYBNUM);
1582 _BSONMERGE3CTX ctx = {
1589 //collect active fpaths
1590 while ((bt = bson_iterator_next(&it2)) != BSON_EOO) {
1591 const char* key = BSON_ITERATOR_KEY(&it2);
1592 off_t it2off = (it2.cur - it2start);
1593 tcmapput(mfields, key, strlen(key), &it2off, sizeof (it2off));
1595 bson_visit_fields(&it1, 0, _bson_merge3_visitor, &ctx);
1596 assert(ctx.nstack == 0);
1597 if (TCMAPRNUM(mfields) == 0) { //all merge fields applied
1602 //apply the remaining merge fields
1603 tcmapiterinit(mfields);
1606 while ((fpath = tcmapiternext(mfields, &fplen)) != NULL) {
1607 BSON_ITERATOR_FROM_BUFFER(&it2, bsdata2);
1608 if (bson_find_fieldpath_value2(fpath, fplen, &it2) != BSON_EOO) {
1609 bson_append_fpath_from_iterator(fpath, &it2, out);
1616 int bson_merge2(const void *b1data, const void *b2data, bson_bool_t overwrite, bson *out) {
1617 bson_iterator it1, it2;
1620 BSON_ITERATOR_FROM_BUFFER(&it1, b1data);
1621 BSON_ITERATOR_FROM_BUFFER(&it2, b2data);
1622 //Append all fields in B1 overwriten by B2
1623 while ((bt1 = bson_iterator_next(&it1)) != BSON_EOO) {
1624 const char* k1 = BSON_ITERATOR_KEY(&it1);
1625 if (overwrite && strcmp(JDBIDKEYNAME, k1) && (bt2 = bson_find_from_buffer(&it2, b2data, k1)) != BSON_EOO) {
1626 bson_append_field_from_iterator(&it2, out);
1628 bson_append_field_from_iterator(&it1, out);
1631 BSON_ITERATOR_FROM_BUFFER(&it1, b1data);
1632 BSON_ITERATOR_FROM_BUFFER(&it2, b2data);
1633 //Append all fields from B2 missing in B1
1634 while ((bt2 = bson_iterator_next(&it2)) != BSON_EOO) {
1635 const char* k2 = BSON_ITERATOR_KEY(&it2);
1636 if ((bt1 = bson_find_from_buffer(&it1, b1data, k2)) == BSON_EOO) {
1637 bson_append_field_from_iterator(&it2, out);
1643 int bson_merge(const bson *b1, const bson *b2, bson_bool_t overwrite, bson *out) {
1644 assert(b1 && b2 && out);
1645 if (!b1->finished || !b2->finished || out->finished) {
1648 return bson_merge2(bson_data(b1), bson_data(b2), overwrite, out);
1651 int bson_merge_recursive2(const void *b1data, const void *b2data, bson_bool_t overwrite, bson *out) {
1652 bson_iterator it1, it2;
1655 BSON_ITERATOR_FROM_BUFFER(&it1, b1data);
1656 BSON_ITERATOR_FROM_BUFFER(&it2, b2data);
1657 //Append all fields in B1 merging with fields in B2 (for nested objects & arrays)
1658 while ((bt1 = bson_iterator_next(&it1)) != BSON_EOO) {
1659 const char* k1 = BSON_ITERATOR_KEY(&it1);
1660 bt2 = bson_find_from_buffer(&it2, b2data, k1);
1661 if (bt1 == BSON_OBJECT && bt2 == BSON_OBJECT) {
1663 bson_append_start_object(out, k1);
1664 if ((res = bson_merge_recursive2(bson_iterator_value(&it1), bson_iterator_value(&it2), overwrite, out)) != BSON_OK) {
1667 bson_append_finish_object(out);
1668 } else if (bt1 == BSON_ARRAY && bt2 == BSON_ARRAY) {
1673 bson_append_start_array(out, k1);
1674 BSON_ITERATOR_SUBITERATOR(&it1, &sit);
1675 while ((sbt = bson_iterator_next(&sit)) != BSON_EOO) {
1676 bson_append_field_from_iterator(&sit, out);
1679 char kbuf[TCNUMBUFSIZ];
1680 BSON_ITERATOR_SUBITERATOR(&it2, &sit);
1681 while ((sbt = bson_iterator_next(&sit)) != BSON_EOO) {
1682 bson_numstrn(kbuf, TCNUMBUFSIZ, c++);
1683 bson_append_field_from_iterator2(kbuf, &sit, out);
1686 bson_append_finish_array(out);
1687 } else if (overwrite && strcmp(JDBIDKEYNAME, k1) && bt2 != BSON_EOO) {
1688 bson_append_field_from_iterator(&it2, out);
1690 bson_append_field_from_iterator(&it1, out);
1694 BSON_ITERATOR_FROM_BUFFER(&it1, b1data);
1695 BSON_ITERATOR_FROM_BUFFER(&it2, b2data);
1696 //Append all fields from B2 missing in B1
1697 while ((bt2 = bson_iterator_next(&it2)) != BSON_EOO) {
1698 const char* k2 = BSON_ITERATOR_KEY(&it2);
1699 if ((bt1 = bson_find_from_buffer(&it1, b1data, k2)) == BSON_EOO) {
1700 bson_append_field_from_iterator(&it2, out);
1706 int bson_merge_recursive(const bson *b1, const bson *b2, bson_bool_t overwrite, bson *out) {
1707 assert(b1 && b2 && out);
1708 if (!b1->finished || !b2->finished || out->finished) {
1711 return bson_merge_recursive2(bson_data(b1), bson_data(b2), overwrite, out);
1715 int nstack; //nested object stack pos
1716 int matched; //number of matched include fields
1717 int astack; //nested array stack pos
1719 } _BSONSTRIPVISITORCTX;
1721 /* Discard excluded fields from BSON */
1722 static bson_visitor_cmd_t _bsonstripvisitor_exclude(const char *ipath, int ipathlen, const char *key, int keylen,
1723 const bson_iterator *it, bool after, void *op) {
1724 _BSONSTRIPVISITORCTX *ictx = op;
1726 BSONSTRIPCTX *sctx = ictx->sctx;
1727 assert(sctx && sctx->bsout && sctx->ifields && ipath && key && it && op);
1728 TCMAP *ifields = sctx->ifields;
1732 bson_type bt = BSON_ITERATOR_TYPE(it);
1734 buf = after ? NULL : tcmapget(ifields, ipath, ipathlen, &bufsz);
1736 if (bt == BSON_OBJECT || bt == BSON_ARRAY) {
1738 tcmapiterinit(ifields); //check prefix
1739 while ((ifpath = tcmapiternext2(ifields)) != NULL) {
1741 for (; i < ipathlen && *(ifpath + i) == *(ipath + i); ++i);
1742 if (i == ipathlen) { //ipath prefixes some exclude object field
1744 if (bt == BSON_OBJECT) {
1745 bson_append_start_object2(sctx->bsout, key, keylen);
1746 } else if (bt == BSON_ARRAY) {
1748 bson_append_start_array2(sctx->bsout, key, keylen);
1750 return (BSON_VCMD_OK);
1753 bson_append_field_from_iterator(it, sctx->bsout);
1754 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
1756 if (ictx->nstack > 0) {
1758 if (bt == BSON_OBJECT) {
1759 bson_append_finish_object(sctx->bsout);
1760 } else if (bt == BSON_ARRAY) {
1762 bson_append_finish_array(sctx->bsout);
1765 return (BSON_VCMD_OK);
1768 bson_append_field_from_iterator(it, sctx->bsout);
1769 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
1772 if (!after && ictx->astack > 0 && bson_isnumstr(key, keylen)) {
1773 bson_append_undefined(sctx->bsout, key);
1777 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
1780 /* Accept only included fields into BSON */
1781 static bson_visitor_cmd_t _bsonstripvisitor_include(const char *ipath, int ipathlen, const char *key, int keylen,
1782 const bson_iterator *it, bool after, void *op) {
1783 _BSONSTRIPVISITORCTX *ictx = op;
1785 BSONSTRIPCTX *sctx = ictx->sctx;
1786 assert(sctx && sctx->bsout && sctx->ifields && ipath && key && it && op);
1787 bson_visitor_cmd_t rv = BSON_VCMD_OK;
1788 TCMAP *ifields = sctx->ifields;
1793 const char *k = key;
1794 if (sctx->fkfields) { //find keys to override
1795 k = tcmapget(sctx->fkfields, ipath, ipathlen, &bufsz);
1800 bson_type bt = BSON_ITERATOR_TYPE(it);
1801 if (bt != BSON_OBJECT && bt != BSON_ARRAY) {
1802 if (after) { //simple primitive case
1803 return BSON_VCMD_OK;
1805 buf = tcmapget(ifields, ipath, ipathlen, &bufsz);
1808 bson_append_field_from_iterator2(k, it, sctx->bsout);
1810 return (BSON_VCMD_SKIP_AFTER);
1811 } else { //more complicated case
1813 buf = tcmapget(ifields, ipath, ipathlen, &bufsz);
1814 if (buf) { //field hitted
1815 bson_iterator cit = *it; //copy iterator
1816 bson_append_field_from_iterator(&cit, sctx->bsout);
1818 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
1819 } else { //check prefix
1820 int onstack = ictx->nstack;
1821 tcmapiterinit(ifields);
1822 while ((ifpath = tcmapiternext2(ifields)) != NULL) {
1824 for (; i < ipathlen && *(ifpath + i) == *(ipath + i); ++i);
1825 if (i == ipathlen) { //ipath prefixes some included field
1827 if (bt == BSON_OBJECT) {
1828 bson_append_start_object2(sctx->bsout, k, keylen);
1829 } else if (bt == BSON_ARRAY) {
1830 bson_append_start_array2(sctx->bsout, k, keylen);
1837 if (onstack == ictx->nstack) {
1838 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
1842 if (ictx->nstack > 0) {
1844 if (bt == BSON_OBJECT) {
1845 bson_append_finish_object(sctx->bsout);
1846 } else if (bt == BSON_ARRAY) {
1847 bson_append_finish_array(sctx->bsout);
1855 if (ictx->nstack == 0 && ictx->matched == TCMAPRNUM(ifields)) {
1856 return BSON_VCMD_TERMINATE;
1861 int bson_strip(TCMAP *ifields, bool imode, const void *bsbuf, bson *bsout, int *matched) {
1862 BSONSTRIPCTX sctx = {
1870 int rc = bson_strip2(&sctx);
1871 *matched = sctx.matched;
1875 /* Include or exclude fpaths in the specified BSON and put resulting data into `bsout`. */
1876 int bson_strip2(BSONSTRIPCTX *sctx) {
1877 assert(sctx && sctx->bsbuf && sctx->bsout);
1878 if (!sctx->ifields || sctx->bsout->finished) {
1881 _BSONSTRIPVISITORCTX ictx = {
1888 BSON_ITERATOR_FROM_BUFFER(&it, sctx->bsbuf);
1889 bson_visit_fields(&it, 0, (sctx->imode) ? _bsonstripvisitor_include : _bsonstripvisitor_exclude, &ictx);
1890 assert(ictx.nstack == 0);
1891 sctx->matched = ictx.matched;
1892 return bson_finish(sctx->bsout);
1895 int bson_inplace_set_bool(bson_iterator *pos, bson_bool_t val) {
1897 bson_type bt = BSON_ITERATOR_TYPE(pos);
1898 if (bt != BSON_BOOL) {
1901 char *t = (char*) pos->cur + 1;
1907 int bson_inplace_set_long(bson_iterator *pos, int64_t val) {
1909 bson_type bt = BSON_ITERATOR_TYPE(pos);
1910 if (!BSON_IS_NUM_TYPE(bt)) {
1913 char *t = (char*) pos->cur + 1;
1915 if (bt == BSON_INT) {
1916 bson_little_endian32(t, &val);
1917 } else if (bt == BSON_LONG || bt == BSON_DATE) {
1918 bson_little_endian64(t, &val);
1919 } else if (bt == BSON_DOUBLE) {
1920 double dval = (double) val;
1921 bson_little_endian64(t, &dval);
1928 int bson_inplace_set_double(bson_iterator *pos, double val) {
1930 bson_type bt = BSON_ITERATOR_TYPE(pos);
1931 if (!BSON_IS_NUM_TYPE(bt)) {
1934 int64_t ival = (int64_t) val;
1935 char *t = (char*) pos->cur + 1;
1937 if (bt == BSON_INT) {
1938 bson_little_endian32(t, &ival);
1939 } else if (bt == BSON_LONG || bt == BSON_DATE) {
1940 bson_little_endian64(t, &ival);
1941 } else if (bt == BSON_DOUBLE) {
1942 bson_little_endian64(t, &val);
1949 int bson_compare_fpaths(const void *bsdata1, const void *bsdata2, const char *fpath1, int fplen1, const char *fpath2, int fplen2) {
1950 assert(bsdata1 && bsdata2 && fpath1 && fpath2);
1951 bson_iterator it1, it2;
1952 BSON_ITERATOR_FROM_BUFFER(&it1, bsdata1);
1953 BSON_ITERATOR_FROM_BUFFER(&it2, bsdata2);
1954 bson_find_fieldpath_value2(fpath1, fplen1, &it1);
1955 bson_find_fieldpath_value2(fpath2, fplen2, &it2);
1956 return bson_compare_it_current(&it1, &it2);
1961 * Return <0 if value pointing by it1 lesser than from it2.
1962 * Return 0 if values equal
1963 * Return >0 if value pointing by it1 greater than from it2.
1968 int bson_compare_it_current(const bson_iterator *it1, const bson_iterator *it2) {
1969 bson_type t1 = BSON_ITERATOR_TYPE(it1);
1970 bson_type t2 = BSON_ITERATOR_TYPE(it2);
1972 if ((BSON_IS_STRING_TYPE(t1) && !BSON_IS_STRING_TYPE(t2)) ||
1973 (BSON_IS_STRING_TYPE(t2) && !BSON_IS_STRING_TYPE(t1))) {
1977 if (t1 == BSON_BOOL || t1 == BSON_EOO || t1 == BSON_NULL || t1 == BSON_UNDEFINED) {
1978 int v1 = bson_iterator_bool(it1);
1979 int v2 = bson_iterator_bool(it2);
1980 return (v1 > v2) ? 1 : ((v1 < v2) ? -1 : 0);
1981 } else if (t1 == BSON_INT || t1 == BSON_LONG || t1 == BSON_DATE || t1 == BSON_TIMESTAMP) {
1982 int64_t v1 = bson_iterator_long_ext(it1);
1983 int64_t v2 = bson_iterator_long_ext(it2);
1984 return (v1 > v2) ? 1 : ((v1 < v2) ? -1 : 0);
1985 } else if (t1 == BSON_DOUBLE) {
1986 double v1 = bson_iterator_double_raw(it1);
1987 double v2 = bson_iterator_double(it2);
1988 return (v1 > v2) ? 1 : ((v1 < v2) ? -1 : 0);
1989 } else if (BSON_IS_STRING_TYPE(t1)) {
1990 const char* v1 = bson_iterator_string(it1);
1991 int l1 = bson_iterator_string_len(it1);
1992 const char* v2 = bson_iterator_string(it2);
1993 int l2 = bson_iterator_string_len(it2);
1995 TCCMPLEXICAL(rv, v1, l1, v2, l2);
1997 } else if (t1 == BSON_BINDATA && t2 == BSON_BINDATA) {
1998 int l1 = bson_iterator_bin_len(it1);
1999 int l2 = bson_iterator_bin_len(it2);
2000 return memcmp(bson_iterator_bin_data(it1), bson_iterator_bin_data(it2), MIN(l1, l2));
2001 } else if (t1 == BSON_OID && t2 == BSON_OID) {
2002 return memcmp(bson_iterator_oid(it1), bson_iterator_oid(it2), sizeof (bson_oid_t));
2003 } else if (t1 == t2 && (t1 == BSON_OBJECT || t1 == BSON_ARRAY)) {
2006 bson_iterator sit1, sit2;
2007 BSON_ITERATOR_SUBITERATOR(it1, &sit1);
2008 BSON_ITERATOR_SUBITERATOR(it2, &sit2);
2009 while ((bt1 = bson_iterator_next(&sit1)) != BSON_EOO) {
2010 bt2 = bson_iterator_next(&sit2);
2011 if (bt2 == BSON_EOO) {
2015 cv = bson_compare_it_current(&sit1, &sit2);
2020 if (cv == 0 && bson_iterator_next(&sit2) != BSON_EOO) {
2028 int bson_compare(const void *bsdata1, const void *bsdata2, const char* fpath, int fplen) {
2029 return bson_compare_fpaths(bsdata1, bsdata2, fpath, fplen, fpath, fplen);
2032 int bson_compare_string(const char *cv, const void *bsdata, const char *fpath) {
2033 assert(cv && bsdata && fpath);
2034 bson *bs1 = bson_create();
2036 bson_append_string(bs1, "$", cv);
2038 int res = bson_compare_fpaths(bson_data(bs1), bsdata, "$", 1, fpath, strlen(fpath));
2043 int bson_compare_long(const int64_t cv, const void *bsdata, const char *fpath) {
2044 bson *bs1 = bson_create();
2046 bson_append_long(bs1, "$", cv);
2048 int res = bson_compare_fpaths(bson_data(bs1), bsdata, "$", 1, fpath, strlen(fpath));
2053 int bson_compare_double(double cv, const void *bsdata, const char *fpath) {
2054 bson *bs1 = bson_create();
2056 bson_append_double(bs1, "$", cv);
2058 int res = bson_compare_fpaths(bson_data(bs1), bsdata, "$", 1, fpath, strlen(fpath));
2063 int bson_compare_bool(bson_bool_t cv, const void *bsdata, const char *fpath) {
2064 bson *bs1 = bson_create();
2066 bson_append_bool(bs1, "$", cv);
2068 int res = bson_compare_fpaths(bson_data(bs1), bsdata, "$", 1, fpath, strlen(fpath));
2073 bson* bson_dup(const bson *src) {
2075 bson *rv = bson_create();
2076 int s = bson_size(src);
2077 _bson_init_size(rv, s);
2078 memmove(rv->data, src->data, s);
2083 bson* bson_create_from_iterator(bson_iterator *from) {
2086 bson *bs = bson_create();
2087 bson_init_as_query(bs);
2088 while ((bt = bson_iterator_next(from)) != BSON_EOO) {
2089 bson_append_field_from_iterator(from, bs);
2095 bson* bson_create_from_buffer(const void* buf, int bufsz) {
2096 return bson_create_from_buffer2(bson_create(), buf, bufsz);
2099 bson* bson_create_from_buffer2(bson *rv, const void* buf, int bufsz) {
2101 assert(bufsz - 4 > 0);
2102 bson_init_size(rv, bufsz);
2103 bson_ensure_space(rv, bufsz - 4);
2104 bson_append(rv, (char*) buf + 4, bufsz - (4 + 1/*BSON_EOO*/));
2109 void bson_init_with_data(bson *bs, const void *bsdata) {
2110 memset(bs, 0, sizeof (*bs));
2111 bs->data = (char*) bsdata;
2112 bson_little_endian32(&bs->dataSize, bsdata);
2113 bs->finished = true;
2116 bool bson_find_merged_arrays(const void *mbuf, const void *inbuf, bool expandall) {
2117 assert(mbuf && inbuf);
2119 bson_iterator it, it2;
2121 BSON_ITERATOR_FROM_BUFFER(&it, mbuf);
2123 while (!found && (bt = bson_iterator_next(&it)) != BSON_EOO) {
2124 if (expandall && bt != BSON_ARRAY) {
2127 BSON_ITERATOR_FROM_BUFFER(&it2, inbuf);
2128 bt2 = bson_find_fieldpath_value(BSON_ITERATOR_KEY(&it), &it2);
2129 if (bt2 != BSON_ARRAY) {
2133 BSON_ITERATOR_SUBITERATOR(&it2, &sit);
2134 while (!found && (bt2 = bson_iterator_next(&sit)) != BSON_EOO) {
2137 BSON_ITERATOR_SUBITERATOR(&it, &sit2);
2138 while ((bt2 = bson_iterator_next(&sit2)) != BSON_EOO) {
2139 if (!bson_compare_it_current(&sit, &sit2)) {
2145 if (!bson_compare_it_current(&sit, &it)) {
2155 bool bson_find_unmerged_arrays(const void *mbuf, const void *inbuf) {
2156 assert(mbuf && inbuf);
2157 bool allfound = false;
2158 bson_iterator it, it2;
2160 BSON_ITERATOR_FROM_BUFFER(&it, mbuf);
2161 while ((bt = bson_iterator_next(&it)) != BSON_EOO) {
2162 BSON_ITERATOR_FROM_BUFFER(&it2, inbuf);
2163 bt2 = bson_find_fieldpath_value(BSON_ITERATOR_KEY(&it), &it2);
2164 if (bt2 == BSON_EOO) { //array missing it will be created
2168 if (bt2 != BSON_ARRAY) { //not an array field
2173 BSON_ITERATOR_SUBITERATOR(&it2, &sit);
2174 while ((bt2 = bson_iterator_next(&sit)) != BSON_EOO) {
2175 if (!bson_compare_it_current(&sit, &it)) {
2194 bson_merge_array_mode mode;
2198 static bson_visitor_cmd_t _bson_merge_arrays_pull_visitor(
2199 const char *fpath, int fpathlen,
2200 const char *key, int keylen,
2201 const bson_iterator *it, bool after, void *op) {
2203 _BSONMARRCTX *ctx = op;
2204 assert(ctx && ctx->mfields >= 0);
2206 bson_type bt = BSON_ITERATOR_TYPE(it);
2207 if (bt != BSON_OBJECT && bt != BSON_ARRAY) { //trivial case
2209 return (BSON_VCMD_OK);
2211 bson_append_field_from_iterator(it, ctx->bsout);
2212 return (BSON_VCMD_SKIP_AFTER);
2214 if (bt == BSON_ARRAY) {
2215 BSON_ITERATOR_FROM_BUFFER(&mit, ctx->mbuf);
2216 bt = bson_find_fieldpath_value2(fpath, fpathlen, &mit);
2217 if (bt == BSON_EOO || (ctx->expandall && bt != BSON_ARRAY)) {
2218 bson_append_field_from_iterator(it, ctx->bsout);
2219 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
2221 if (ctx->mfields > 0) {
2226 BSON_ITERATOR_SUBITERATOR(it, &ait);
2227 bson_append_start_array(ctx->bsout, key);
2230 while ((bt = bson_iterator_next(&ait)) != BSON_EOO) {
2232 if (ctx->expandall) {
2233 bson_iterator mitsub;
2234 BSON_ITERATOR_SUBITERATOR(&mit, &mitsub);
2235 while ((bt = bson_iterator_next(&mitsub)) != BSON_EOO) {
2236 if (!bson_compare_it_current(&ait, &mitsub)) {
2242 found = !bson_compare_it_current(&ait, &mit);
2245 char kbuf[TCNUMBUFSIZ];
2246 bson_numstrn(kbuf, TCNUMBUFSIZ, c++);
2247 bson_append_field_from_iterator2(kbuf, &ait, ctx->bsout);
2250 bson_append_finish_array(ctx->bsout);
2251 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
2255 bson_append_start_object(ctx->bsout, key);
2257 bson_append_finish_object(ctx->bsout);
2259 return (BSON_VCMD_OK);
2262 static bson_visitor_cmd_t _bson_merge_arrays_visitor(
2263 const char *fpath, int fpathlen,
2264 const char *key, int keylen,
2265 const bson_iterator *it,
2266 bool after, void *op) {
2268 _BSONMARRCTX *ctx = op;
2269 assert(ctx && ctx->mfields >= 0);
2271 bson_type bt = BSON_ITERATOR_TYPE(it);
2273 if (bt != BSON_OBJECT && bt != BSON_ARRAY) { //trivial case
2275 return (BSON_VCMD_OK);
2277 bson_append_field_from_iterator(it, ctx->bsout);
2278 return (BSON_VCMD_SKIP_AFTER);
2280 if (bt == BSON_ARRAY) {
2282 bson_append_finish_array(ctx->bsout);
2283 return (BSON_VCMD_OK);
2285 BSON_ITERATOR_FROM_BUFFER(&mit, ctx->mbuf);
2286 bt = bson_find_fieldpath_value2(fpath, fpathlen, &mit);
2287 if (bt == BSON_EOO) {
2288 bson_append_start_array(ctx->bsout, key);
2289 return (BSON_VCMD_OK);
2291 if (ctx->expandall && bt != BSON_ARRAY) {
2292 bson_append_field_from_iterator(it, ctx->bsout);
2293 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
2295 if (ctx->mfields > 0) {
2300 BSON_ITERATOR_SUBITERATOR(it, &ait);
2301 bson_append_start_array(ctx->bsout, key);
2304 if (ctx->expandall) { //Set of array elements to add
2305 while ((bt = bson_iterator_next(&ait)) != BSON_EOO) { //Flush current array
2306 bson_append_field_from_iterator(&ait, ctx->bsout);
2309 //Iterate over set to add
2310 bson_iterator mitsub;
2311 BSON_ITERATOR_SUBITERATOR(&mit, &mitsub); //mit has BSON_ARRAY type
2312 while ((bt = bson_iterator_next(&mitsub)) != BSON_EOO) {
2314 if (ctx->mode == BSON_MERGE_ARRAY_ADDSET) {
2315 BSON_ITERATOR_SUBITERATOR(it, &ait); //Rewind main array iterator
2316 while ((bt = bson_iterator_next(&ait)) != BSON_EOO) {
2317 if (!bson_compare_it_current(&ait, &mitsub)) {
2323 if (!found) { //Append missing element
2324 char kbuf[TCNUMBUFSIZ];
2325 bson_numstrn(kbuf, TCNUMBUFSIZ, c++);
2326 bson_append_field_from_iterator2(kbuf, &mitsub, ctx->bsout);
2330 } else { //Single element to add
2331 while ((bt = bson_iterator_next(&ait)) != BSON_EOO) {
2332 if ((ctx->mode == BSON_MERGE_ARRAY_ADDSET) &&
2334 !bson_compare_it_current(&ait, &mit)) {
2337 bson_append_field_from_iterator(&ait, ctx->bsout);
2340 if (!found) { //uppend missing element into array
2341 char kbuf[TCNUMBUFSIZ];
2342 bson_numstrn(kbuf, TCNUMBUFSIZ, c);
2343 bson_append_field_from_iterator2(kbuf, &mit, ctx->bsout);
2347 bson_append_finish_array(ctx->bsout);
2348 return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
2352 bson_append_start_object(ctx->bsout, key);
2354 bson_append_finish_object(ctx->bsout);
2356 return (BSON_VCMD_OK);
2359 int bson_merge_arrays(const void *mbuf,
2361 bson_merge_array_mode mode,
2365 assert(mbuf && inbuf && bsout);
2366 assert(mode == BSON_MERGE_ARRAY_ADDSET ||
2367 mode == BSON_MERGE_ARRAY_PULL ||
2368 mode == BSON_MERGE_ARRAY_PUSH);
2370 if (bsout->finished) {
2373 _BSONMARRCTX ctx = {
2378 .expandall = expandall,
2383 bson_iterator it, it2;
2384 BSON_ITERATOR_FROM_BUFFER(&it, mbuf);
2385 while ((bt = bson_iterator_next(&it)) != BSON_EOO) {
2386 if (expandall && bt != BSON_ARRAY) {
2391 BSON_ITERATOR_FROM_BUFFER(&it, inbuf);
2392 if (mode == BSON_MERGE_ARRAY_PULL) {
2393 bson_visit_fields(&it, 0, _bson_merge_arrays_pull_visitor, &ctx);
2395 bson_visit_fields(&it, 0, _bson_merge_arrays_visitor, &ctx);
2397 if (ctx.mfields == 0 || //all fields are merged
2398 mode == BSON_MERGE_ARRAY_PULL) {
2402 //Append missing arrays fields
2403 BSON_ITERATOR_FROM_BUFFER(&it, mbuf);
2404 while ((bt = bson_iterator_next(&it)) != BSON_EOO) {
2405 const char *fpath = BSON_ITERATOR_KEY(&it);
2406 // all data from inbuf already in bsout
2408 BSON_ITERATOR_INIT(&it2, bsout);
2409 bt2 = bson_find_fieldpath_value(fpath, &it2);
2410 if (bt2 != BSON_EOO) continue;
2413 const char *pdp = fpath;
2416 while (*(fpath + i) != '\0') {
2417 for (; *(fpath + i) != '\0' && *(fpath + i) != '.'; ++i);
2418 if (*(fpath + i) == '\0') { //EOF
2419 assert((fpath + i) - pdp > 0);
2420 bson_append_start_array2(&bst, pdp, (fpath + i) - pdp);
2421 bson_append_field_from_iterator2("0", &it, &bst);
2422 bson_append_finish_array(&bst);
2426 assert((fpath + i) - pdp > 0);
2427 bson_append_start_object2(&bst, pdp, (fpath + i) - pdp);
2430 while (*pdp == '.') {
2435 for (; lvl > 0; --lvl) {
2436 bson_append_finish_object(&bst);
2441 bson_init_finished_data(&bsc, bson_data(bsout));
2442 bson_init_size(bsout, bson_size(bsout));
2443 int res = bson_merge_recursive(&bsc, &bst, false, bsout);
2446 if (res != BSON_OK) {
2454 int nlvl; //nesting level
2455 TCXSTR *out; //output buffer
2458 static void _jsonxstrescaped(TCXSTR *xstr, const char *str) {
2459 size_t sz = strlen(str);
2469 const char * ebuf = NULL;
2471 case '\r': ebuf = "\\r";
2473 case '\n': ebuf = "\\n";
2475 case '\\': ebuf = "\\\\";
2479 case '"': ebuf = "\\\"";
2481 case '\f': ebuf = "\\f";
2483 case '\b': ebuf = "\\b";
2485 case '\t': ebuf = "\\t";
2488 if ((unsigned char) str[e] < 0x20) {
2489 static const char *hexchar = "0123456789ABCDEF";
2490 hb[4] = hexchar[str[e] >> 4];
2491 hb[5] = hexchar[str[e] & 0x0F];
2498 tcxstrcat(xstr, str + s, e - s);
2500 tcxstrcat2(xstr, ebuf);
2506 tcxstrcat(xstr, (str + s), e - s);
2509 static int _bson2json(_BSON2JSONCTX *ctx, bson_iterator *it, bool array) {
2512 for (int i = 0; i < ctx->nlvl + (_n); ++i) tcxstrcat2(ctx->out, " ")
2515 TCXSTR *out = ctx->out;
2516 tcxstrcat2(ctx->out, array ? "[\n" : "{\n");
2519 while ((bt = bson_iterator_next(it)) != BSON_EOO) {
2522 tcxstrcat2(out, "\n");
2525 tcxstrcat2(out, ",\n");
2527 const char *key = BSON_ITERATOR_KEY(it);
2530 tcxstrcat2(out, "\"");
2531 _jsonxstrescaped(out, key);
2532 tcxstrcat2(out, "\" : ");
2538 tcxstrprintf(out, "%" PRId64, (int64_t) bson_iterator_long_ext(it));
2542 tcxstrprintf(out, "%lf", bson_iterator_double(it));
2548 tcxstrcat2(out, "\"");
2549 _jsonxstrescaped(out, bson_iterator_string(it));
2550 tcxstrcat2(out, "\"");
2557 BSON_ITERATOR_SUBITERATOR(it, &sit);
2558 _bson2json(ctx, &sit, bt == BSON_ARRAY);
2562 tcxstrcat2(out, "null");
2563 case BSON_UNDEFINED:
2567 bson_date_t t = bson_iterator_date(it);
2569 tcdatestrwww(t, INT_MAX, dbuf);
2570 tcxstrprintf(out, "\"%s\"", dbuf);
2574 tcxstrcat2(out, bson_iterator_bool(it) ? "true" : "false");
2579 bson_oid_t *oid = bson_iterator_oid(it);
2580 bson_oid_to_string(oid, xoid);
2581 tcxstrprintf(out, "\"%s\"", xoid);
2586 tcxstrcat2(out, "\"");
2587 _jsonxstrescaped(out, bson_iterator_regex(it));
2588 tcxstrcat2(out, "\"");
2593 const char *buf = bson_iterator_bin_data(it);
2594 int bsz = bson_iterator_bin_len(it);
2595 char *b64data = tcbaseencode(buf, bsz);
2596 tcxstrcat2(out, "\"");
2597 tcxstrcat2(out, b64data);
2598 tcxstrcat2(out, "\"");
2606 tcxstrcat2(out, "\n");
2608 tcxstrcat2(out, array ? "]" : "}");
2614 int bson2json(const char *bsdata, char **buf, int *sp) {
2615 assert(bsdata && buf && sp);
2617 BSON_ITERATOR_FROM_BUFFER(&it, bsdata);
2618 TCXSTR *out = tcxstrnew();
2619 _BSON2JSONCTX ctx = {
2623 int ret = _bson2json(&ctx, &it, false);
2624 if (ret == BSON_OK) {
2625 *sp = TCXSTRSIZE(out);
2626 *buf = tcxstrtomalloc(out);
2638 static void _json2bson(bson *out, const nx_json *json, const char *forcekey) {
2639 const char *key = forcekey ? forcekey : json->key;
2640 switch (json->type) {
2643 bson_append_null(out, key);
2645 case NX_JSON_OBJECT:
2648 bson_append_start_object(out, key);
2650 for (nx_json* js = json->child; js; js = js->next) {
2651 _json2bson(out, js, NULL);
2654 bson_append_finish_object(out);
2661 bson_append_start_array(out, key);
2664 char kbuf[TCNUMBUFSIZ];
2665 for (nx_json* js = json->child; js; js = js->next) {
2666 bson_numstrn(kbuf, TCNUMBUFSIZ, c++);
2667 _json2bson(out, js, kbuf);
2670 bson_append_finish_array(out);
2674 case NX_JSON_STRING:
2676 bson_append_string(out, key, json->text_value);
2678 case NX_JSON_INTEGER:
2680 if (json->int_value <= INT_MAX && json->int_value >= INT_MIN) {
2681 bson_append_int(out, key, (int) json->int_value);
2683 bson_append_long(out, key, json->int_value);
2686 case NX_JSON_DOUBLE:
2688 bson_append_double(out, key, json->dbl_value);
2692 bson_append_bool(out, key, json->int_value ? true : false);
2699 bson* json2bson(const char *jsonstr) {
2702 char *json = strdup(jsonstr); //nxjson uses inplace data modification
2706 out = bson_create();
2707 bson_init_as_query(out);
2708 const nx_json *nxjson = nx_json_parse_utf8(json);
2713 _json2bson(out, nxjson, NULL);
2719 nx_json_free(nxjson);