1
/* bson.c - libmongo-client's BSON implementation
2
* Copyright 2011 Gergely Nagy <algernon@balabit.hu>
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
18
* Implementation of the BSON API.
27
#include "libmongo-macros.h"
28
#include "libmongo-private.h"
30
/** @internal BSON cursor structure.
34
const bson *obj; /**< The BSON object this is a cursor for. */
35
const gchar *key; /**< Pointer within the BSON object to the
37
size_t pos; /**< Position within the BSON object, pointing at the
39
size_t value_pos; /**< The start of the value within the BSON
40
object, pointing right after the end of the
44
/** @internal Append a byte to a BSON stream.
46
* @param b is the BSON stream to append to.
47
* @param byte is the byte to append.
50
_bson_append_byte (bson *b, const guint8 byte)
52
b->data = g_byte_array_append (b->data, &byte, sizeof (byte));
55
/** @internal Append a 32-bit integer to a BSON stream.
57
* @param b is the BSON stream to append to.
58
* @param i is the integer to append.
61
_bson_append_int32 (bson *b, const gint32 i)
63
b->data = g_byte_array_append (b->data, (const guint8 *)&i, sizeof (gint32));
66
/** @internal Append a 64-bit integer to a BSON stream.
68
* @param b is the BSON stream to append to.
69
* @param i is the integer to append.
72
_bson_append_int64 (bson *b, const gint64 i)
74
b->data = g_byte_array_append (b->data, (const guint8 *)&i, sizeof (gint64));
77
/** @internal Append an element header to a BSON stream.
79
* The element header is a single byte, signaling the type of the
80
* element, followed by a NULL-terminated C string: the key (element)
83
* @param b is the BSON object to append to.
84
* @param type is the element type to append.
85
* @param name is the key name.
87
* @returns TRUE on success, FALSE otherwise.
89
static inline gboolean
90
_bson_append_element_header (bson *b, bson_type type, const gchar *name)
98
_bson_append_byte (b, (guint8) type);
99
b->data = g_byte_array_append (b->data, (const guint8 *)name,
105
/** @internal Append a string-like element to a BSON object.
107
* There are a few string-like elements in the BSON spec that differ
108
* only in type, not in structure. This convenience function is used
109
* to append them with the appropriate type.
111
* @param b is the BSON object to append to.
112
* @param type is the string-like type to append.
113
* @param name is the key name.
114
* @param val is the value to append.
115
* @param length is the length of the value.
117
* @note Passing @a -1 as length will use the full length of @a
120
* @returns TRUE on success, FALSE otherwise.
123
_bson_append_string_element (bson *b, bson_type type, const gchar *name,
124
const gchar *val, gint32 length)
128
if (!val || !length || length < -1)
131
len = (length != -1) ? (size_t)length + 1: strlen (val) + 1;
133
if (!_bson_append_element_header (b, type, name))
136
_bson_append_int32 (b, GINT32_TO_LE (len));
138
b->data = g_byte_array_append (b->data, (const guint8 *)val, len - 1);
139
_bson_append_byte (b, 0);
144
/** @internal Append a document-like element to a BSON object.
146
* Arrays and documents are both similar, and differ very little:
147
* different type, and arrays have restrictions on key names (which
148
* are not enforced by this library).
150
* This convenience function can append both types.
152
* @param b is the BSON object to append to.
153
* @param type is the document-like type to append.
154
* @param name is the key name.
155
* @param doc is the document-like object to append.
157
* @note The @a doc must be a finished BSON object.
159
* @returns TRUE on success, FALSE otherwise.
162
_bson_append_document_element (bson *b, bson_type type, const gchar *name,
165
if (bson_size (doc) < 0)
168
if (!_bson_append_element_header (b, type, name))
171
b->data = g_byte_array_append (b->data, bson_data (doc), bson_size (doc));
175
/** @internal Append a 64-bit integer to a BSON object.
177
* @param b is the BSON object to append to.
178
* @param type is the int64-like type to append.
179
* @param name is the key name.
180
* @param i is the 64-bit value to append.
182
* @returns TRUE on success, FALSE otherwise.
184
static inline gboolean
185
_bson_append_int64_element (bson *b, bson_type type, const gchar *name,
188
if (!_bson_append_element_header (b, type, name))
191
_bson_append_int64 (b, GINT64_TO_LE (i));
195
/********************
197
********************/
200
bson_type_as_string (bson_type type)
205
return "BSON_TYPE_NONE";
206
case BSON_TYPE_DOUBLE:
207
return "BSON_TYPE_DOUBLE";
208
case BSON_TYPE_STRING:
209
return "BSON_TYPE_STRING";
210
case BSON_TYPE_DOCUMENT:
211
return "BSON_TYPE_DOCUMENT";
212
case BSON_TYPE_ARRAY:
213
return "BSON_TYPE_ARRAY";
214
case BSON_TYPE_BINARY:
215
return "BSON_TYPE_BINARY";
216
case BSON_TYPE_UNDEFINED:
217
return "BSON_TYPE_UNDEFINED";
219
return "BSON_TYPE_OID";
220
case BSON_TYPE_BOOLEAN:
221
return "BSON_TYPE_BOOLEAN";
222
case BSON_TYPE_UTC_DATETIME:
223
return "BSON_TYPE_UTC_DATETIME";
225
return "BSON_TYPE_NULL";
226
case BSON_TYPE_REGEXP:
227
return "BSON_TYPE_REGEXP";
228
case BSON_TYPE_DBPOINTER:
229
return "BSON_TYPE_DBPOINTER";
230
case BSON_TYPE_JS_CODE:
231
return "BSON_TYPE_JS_CODE";
232
case BSON_TYPE_SYMBOL:
233
return "BSON_TYPE_SYMBOL";
234
case BSON_TYPE_JS_CODE_W_SCOPE:
235
return "BSON_TYPE_JS_CODE_W_SCOPE";
236
case BSON_TYPE_INT32:
237
return "BSON_TYPE_INT32";
238
case BSON_TYPE_TIMESTAMP:
239
return "BSON_TYPE_TIMESTAMP";
240
case BSON_TYPE_INT64:
241
return "BSON_TYPE_INT64";
243
return "BSON_TYPE_MIN";
245
return "BSON_TYPE_MAX";
254
return bson_new_sized (0);
258
bson_new_sized (gint32 size)
260
bson *b = g_new0 (bson, 1);
262
b->data = g_byte_array_sized_new (size + sizeof (gint32) + sizeof (guint8));
263
_bson_append_int32 (b, 0);
269
bson_new_from_data (const guint8 *data, gint32 size)
273
if (!data || size <= 0)
276
b = g_new0 (bson, 1);
277
b->data = g_byte_array_sized_new (size + sizeof (guint8));
278
b->data = g_byte_array_append (b->data, data, size);
283
/** @internal Add a single element of any type to a BSON object.
285
* Used internally by bson_build() and bson_build_full(), this
286
* function adds a single element of any supported type to the target
289
* @param b is the target BSON object.
290
* @param type is the element type to add.
291
* @param name is the key name.
292
* @param free_after signals whether to free the values after adding
294
* @param ap is the list of remaining parameters.
296
* @returns TRUE in @a single_result on success, FALSE otherwise.
298
#define _bson_build_add_single(b,type,name,free_after,ap) \
300
single_result = TRUE; \
303
case BSON_TYPE_NONE: \
304
case BSON_TYPE_UNDEFINED: \
305
case BSON_TYPE_DBPOINTER: \
306
single_result = FALSE; \
308
case BSON_TYPE_MIN: \
309
case BSON_TYPE_MAX: \
311
single_result = FALSE; \
313
case BSON_TYPE_DOUBLE: \
315
gdouble d = (gdouble)va_arg (ap, gdouble); \
316
bson_append_double (b, name, d); \
319
case BSON_TYPE_STRING: \
321
gchar *s = (gchar *)va_arg (ap, gpointer); \
322
gint32 l = (gint32)va_arg (ap, gint32); \
323
bson_append_string (b, name, s, l); \
328
case BSON_TYPE_DOCUMENT: \
330
bson *d = (bson *)va_arg (ap, gpointer); \
331
if (free_after && bson_size (d) < 0) \
333
bson_append_document (b, name, d); \
338
case BSON_TYPE_ARRAY: \
340
bson *d = (bson *)va_arg (ap, gpointer); \
341
if (free_after && bson_size (d) < 0) \
343
bson_append_array (b, name, d); \
348
case BSON_TYPE_BINARY: \
350
bson_binary_subtype s = \
351
(bson_binary_subtype)va_arg (ap, guint); \
352
guint8 *d = (guint8 *)va_arg (ap, gpointer); \
353
gint32 l = (gint32)va_arg (ap, gint32); \
354
bson_append_binary (b, name, s, d, l); \
359
case BSON_TYPE_OID: \
361
guint8 *oid = (guint8 *)va_arg (ap, gpointer); \
362
bson_append_oid (b, name, oid); \
367
case BSON_TYPE_BOOLEAN: \
369
gboolean v = (gboolean)va_arg (ap, guint); \
370
bson_append_boolean (b, name, v); \
373
case BSON_TYPE_UTC_DATETIME: \
375
gint64 ts = (gint64)va_arg (ap, gint64); \
376
bson_append_utc_datetime (b, name, ts); \
379
case BSON_TYPE_NULL: \
381
bson_append_null (b, name); \
384
case BSON_TYPE_REGEXP: \
386
gchar *r = (gchar *)va_arg (ap, gpointer); \
387
gchar *o = (gchar *)va_arg (ap, gpointer); \
388
bson_append_regex (b, name, r, o); \
396
case BSON_TYPE_JS_CODE: \
398
gchar *s = (gchar *)va_arg (ap, gpointer); \
399
gint32 l = (gint32)va_arg (ap, gint32); \
400
bson_append_javascript (b, name, s, l); \
405
case BSON_TYPE_SYMBOL: \
407
gchar *s = (gchar *)va_arg (ap, gpointer); \
408
gint32 l = (gint32)va_arg (ap, gint32); \
409
bson_append_symbol (b, name, s, l); \
414
case BSON_TYPE_JS_CODE_W_SCOPE: \
416
gchar *s = (gchar *)va_arg (ap, gpointer); \
417
gint32 l = (gint32)va_arg (ap, gint32); \
418
bson *scope = (bson *)va_arg (ap, gpointer); \
419
if (free_after && bson_size (scope) < 0) \
420
bson_finish (scope); \
421
bson_append_javascript_w_scope (b, name, s, l, scope); \
426
case BSON_TYPE_INT32: \
428
gint32 l = (gint32)va_arg (ap, gint32); \
429
bson_append_int32 (b, name, l); \
432
case BSON_TYPE_TIMESTAMP: \
434
gint64 ts = (gint64)va_arg (ap, gint64); \
435
bson_append_timestamp (b, name, ts); \
438
case BSON_TYPE_INT64: \
440
gint64 l = (gint64)va_arg (ap, gint64); \
441
bson_append_int64 (b, name, l); \
448
bson_build (bson_type type, const gchar *name, ...)
454
gboolean single_result;
458
_bson_build_add_single (b, type, name, FALSE, ap);
467
while ((t = (bson_type)va_arg (ap, gint)))
469
n = (const gchar *)va_arg (ap, gpointer);
470
_bson_build_add_single (b, t, n, FALSE, ap);
484
bson_build_full (bson_type type, const gchar *name, gboolean free_after, ...)
491
gboolean single_result;
494
va_start (ap, free_after);
495
_bson_build_add_single (b, type, name, free_after, ap);
503
while ((t = (bson_type)va_arg (ap, gint)))
505
n = (const gchar *)va_arg (ap, gpointer);
506
f = (gboolean)va_arg (ap, gint);
507
_bson_build_add_single (b, t, n, f, ap);
521
bson_finish (bson *b)
531
_bson_append_byte (b, 0);
533
i = (gint32 *) (&b->data->data[0]);
534
*i = GINT32_TO_LE ((gint32) (b->data->len));
542
bson_size (const bson *b)
554
bson_data (const bson *b)
560
return b->data->data;
572
g_byte_array_set_size (b->data, 0);
573
_bson_append_int32 (b, 0);
585
g_byte_array_free (b->data, TRUE);
590
bson_validate_key (const gchar *key, gboolean forbid_dots,
600
if (no_dollar && key[0] == '$')
603
if (forbid_dots && strchr (key, '.') != NULL)
614
bson_append_double (bson *b, const gchar *name, gdouble val)
616
gdouble d = GDOUBLE_TO_LE (val);
618
if (!_bson_append_element_header (b, BSON_TYPE_DOUBLE, name))
621
b->data = g_byte_array_append (b->data, (const guint8 *)&d, sizeof (val));
626
bson_append_string (bson *b, const gchar *name, const gchar *val,
629
return _bson_append_string_element (b, BSON_TYPE_STRING, name, val, length);
633
bson_append_document (bson *b, const gchar *name, const bson *doc)
635
return _bson_append_document_element (b, BSON_TYPE_DOCUMENT, name, doc);
639
bson_append_array (bson *b, const gchar *name, const bson *array)
641
return _bson_append_document_element (b, BSON_TYPE_ARRAY, name, array);
645
bson_append_binary (bson *b, const gchar *name, bson_binary_subtype subtype,
646
const guint8 *data, gint32 size)
648
if (!data || !size || size <= 0)
651
if (!_bson_append_element_header (b, BSON_TYPE_BINARY, name))
654
_bson_append_int32 (b, GINT32_TO_LE (size));
655
_bson_append_byte (b, (guint8)subtype);
657
b->data = g_byte_array_append (b->data, data, size);
662
bson_append_oid (bson *b, const gchar *name, const guint8 *oid)
667
if (!_bson_append_element_header (b, BSON_TYPE_OID, name))
670
b->data = g_byte_array_append (b->data, oid, 12);
675
bson_append_boolean (bson *b, const gchar *name, gboolean value)
677
if (!_bson_append_element_header (b, BSON_TYPE_BOOLEAN, name))
680
_bson_append_byte (b, (guint8)value);
685
bson_append_utc_datetime (bson *b, const gchar *name, gint64 ts)
687
return _bson_append_int64_element (b, BSON_TYPE_UTC_DATETIME, name, ts);
691
bson_append_null (bson *b, const gchar *name)
693
return _bson_append_element_header (b, BSON_TYPE_NULL, name);
697
bson_append_regex (bson *b, const gchar *name, const gchar *regexp,
698
const gchar *options)
700
if (!regexp || !options)
703
if (!_bson_append_element_header (b, BSON_TYPE_REGEXP, name))
706
b->data = g_byte_array_append (b->data, (const guint8 *)regexp,
707
strlen (regexp) + 1);
708
b->data = g_byte_array_append (b->data, (const guint8 *)options,
709
strlen (options) + 1);
715
bson_append_javascript (bson *b, const gchar *name, const gchar *js,
718
return _bson_append_string_element (b, BSON_TYPE_JS_CODE, name, js, len);
722
bson_append_symbol (bson *b, const gchar *name, const gchar *symbol,
725
return _bson_append_string_element (b, BSON_TYPE_SYMBOL, name, symbol, len);
729
bson_append_javascript_w_scope (bson *b, const gchar *name,
730
const gchar *js, gint32 len,
736
if (!js || !scope || bson_size (scope) < 0 || len < -1)
739
if (!_bson_append_element_header (b, BSON_TYPE_JS_CODE_W_SCOPE, name))
742
length = (len != -1) ? (size_t)len + 1: strlen (js) + 1;
744
size = length + sizeof (gint32) + sizeof (gint32) + bson_size (scope);
746
_bson_append_int32 (b, GINT32_TO_LE (size));
748
/* Append the JS code */
749
_bson_append_int32 (b, GINT32_TO_LE (length));
750
b->data = g_byte_array_append (b->data, (const guint8 *)js, length - 1);
751
_bson_append_byte (b, 0);
753
/* Append the scope */
754
b->data = g_byte_array_append (b->data, bson_data (scope),
761
bson_append_int32 (bson *b, const gchar *name, gint32 i)
763
if (!_bson_append_element_header (b, BSON_TYPE_INT32, name))
766
_bson_append_int32 (b, GINT32_TO_LE (i));
771
bson_append_timestamp (bson *b, const gchar *name, gint64 ts)
773
return _bson_append_int64_element (b, BSON_TYPE_TIMESTAMP, name, ts);
777
bson_append_int64 (bson *b, const gchar *name, gint64 i)
779
return _bson_append_int64_element (b, BSON_TYPE_INT64, name, i);
783
* Find & retrieve data
786
bson_cursor_new (const bson *b)
790
if (bson_size (b) == -1)
793
c = (bson_cursor *)g_new0 (bson_cursor, 1);
800
bson_cursor_free (bson_cursor *c)
805
/** @internal Figure out the block size of a given type.
807
* Provided a #bson_type and some raw data, figures out the length of
808
* the block, counted from rigth after the element name's position.
810
* @param type is the type of object we need the size for.
811
* @param data is the raw data (starting right after the element's
814
* @returns The size of the block, or -1 on error.
817
_bson_get_block_size (bson_type type, const guint8 *data)
823
case BSON_TYPE_STRING:
824
case BSON_TYPE_JS_CODE:
825
case BSON_TYPE_SYMBOL:
826
return bson_stream_doc_size (data, 0) + sizeof (gint32);
827
case BSON_TYPE_DOCUMENT:
828
case BSON_TYPE_ARRAY:
829
case BSON_TYPE_JS_CODE_W_SCOPE:
830
return bson_stream_doc_size (data, 0);
831
case BSON_TYPE_DOUBLE:
832
return sizeof (gdouble);
833
case BSON_TYPE_BINARY:
834
return bson_stream_doc_size (data, 0) +
835
sizeof (gint32) + sizeof (guint8);
838
case BSON_TYPE_BOOLEAN:
840
case BSON_TYPE_UTC_DATETIME:
841
case BSON_TYPE_TIMESTAMP:
842
case BSON_TYPE_INT64:
843
return sizeof (gint64);
845
case BSON_TYPE_UNDEFINED:
849
case BSON_TYPE_REGEXP:
850
l = strlen((gchar *)data);
851
return l + strlen((gchar *)(data + l + 1)) + 2;
852
case BSON_TYPE_INT32:
853
return sizeof (gint32);
854
case BSON_TYPE_DBPOINTER:
855
return bson_stream_doc_size (data, 0) + sizeof (gint32) + 12;
863
bson_cursor_next (bson_cursor *c)
871
d = bson_data (c->obj);
874
pos = sizeof (guint32);
877
bs = _bson_get_block_size (bson_cursor_type (c), d + c->value_pos);
880
pos = c->value_pos + bs;
883
if (pos >= bson_size (c->obj) - 1)
887
c->key = (gchar *) &d[c->pos + 1];
888
c->value_pos = c->pos + strlen (c->key) + 2;
893
static inline gboolean
894
_bson_cursor_find (const bson *b, const gchar *name, size_t start_pos,
895
gint32 end_pos, gboolean wrap_over, bson_cursor *dest_c)
897
gint32 pos = start_pos, bs;
901
name_len = strlen (name);
905
while (pos < end_pos)
907
bson_type t = (bson_type) d[pos];
908
const gchar *key = (gchar *) &d[pos + 1];
909
gint32 key_len = strlen (key);
910
gint32 value_pos = pos + key_len + 2;
912
if (!memcmp (key, name, (name_len <= key_len) ? name_len : key_len))
917
dest_c->value_pos = value_pos;
921
bs = _bson_get_block_size (t, &d[value_pos]);
924
pos = value_pos + bs;
928
return _bson_cursor_find (b, name, sizeof (gint32), start_pos,
935
bson_cursor_find (bson_cursor *c, const gchar *name)
940
return _bson_cursor_find (c->obj, name, c->pos, bson_size (c->obj) - 1,
945
bson_cursor_find_next (bson_cursor *c, const gchar *name)
950
return _bson_cursor_find (c->obj, name, c->pos, bson_size (c->obj) - 1,
955
bson_find (const bson *b, const gchar *name)
959
if (bson_size (b) == -1 || !name)
962
c = bson_cursor_new (b);
963
if (_bson_cursor_find (b, name, sizeof (gint32), bson_size (c->obj) - 1,
966
bson_cursor_free (c);
971
bson_cursor_type (const bson_cursor *c)
973
if (!c || c->pos < sizeof (gint32))
974
return BSON_TYPE_NONE;
976
return (bson_type)(bson_data (c->obj)[c->pos]);
980
bson_cursor_type_as_string (const bson_cursor *c)
982
if (!c || c->pos < sizeof (gint32))
985
return bson_type_as_string (bson_cursor_type (c));
989
bson_cursor_key (const bson_cursor *c)
997
/** @internal Convenience macro to verify a cursor's type.
999
* Verifies that the cursor's type is the same as the type requested
1000
* by the caller, and returns FALSE if there is a mismatch.
1002
#define BSON_CURSOR_CHECK_TYPE(c,type) \
1003
if (bson_cursor_type(c) != type) \
1007
bson_cursor_get_string (const bson_cursor *c, const gchar **dest)
1012
BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_STRING);
1014
*dest = (gchar *)(bson_data (c->obj) + c->value_pos + sizeof (gint32));
1020
bson_cursor_get_double (const bson_cursor *c, gdouble *dest)
1025
BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_DOUBLE);
1027
memcpy (dest, bson_data (c->obj) + c->value_pos, sizeof (gdouble));
1028
*dest = GDOUBLE_FROM_LE (*dest);
1034
bson_cursor_get_document (const bson_cursor *c, bson **dest)
1042
BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_DOCUMENT);
1044
size = bson_stream_doc_size (bson_data(c->obj), c->value_pos) -
1045
sizeof (gint32) - 1;
1046
b = bson_new_sized (size);
1047
b->data = g_byte_array_append (b->data,
1048
bson_data (c->obj) + c->value_pos +
1049
sizeof (gint32), size);
1058
bson_cursor_get_array (const bson_cursor *c, bson **dest)
1066
BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_ARRAY);
1068
size = bson_stream_doc_size (bson_data(c->obj), c->value_pos) -
1069
sizeof (gint32) - 1;
1070
b = bson_new_sized (size);
1071
b->data = g_byte_array_append (b->data,
1072
bson_data (c->obj) + c->value_pos +
1073
sizeof (gint32), size);
1082
bson_cursor_get_binary (const bson_cursor *c,
1083
bson_binary_subtype *subtype,
1084
const guint8 **data, gint32 *size)
1086
if (!subtype || !size || !data)
1089
BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_BINARY);
1091
*size = bson_stream_doc_size (bson_data(c->obj), c->value_pos);
1092
*subtype = (bson_binary_subtype)(bson_data (c->obj)[c->value_pos +
1094
*data = (guint8 *)(bson_data (c->obj) + c->value_pos + sizeof (gint32) + 1);
1100
bson_cursor_get_oid (const bson_cursor *c, const guint8 **dest)
1105
BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_OID);
1107
*dest = (guint8 *)(bson_data (c->obj) + c->value_pos);
1113
bson_cursor_get_boolean (const bson_cursor *c, gboolean *dest)
1118
BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_BOOLEAN);
1120
*dest = (gboolean)(bson_data (c->obj) + c->value_pos)[0];
1126
bson_cursor_get_utc_datetime (const bson_cursor *c,
1132
BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_UTC_DATETIME);
1134
memcpy (dest, bson_data (c->obj) + c->value_pos, sizeof (gint64));
1135
*dest = GINT64_FROM_LE (*dest);
1141
bson_cursor_get_regex (const bson_cursor *c, const gchar **regex,
1142
const gchar **options)
1144
if (!regex || !options)
1147
BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_REGEXP);
1149
*regex = (gchar *)(bson_data (c->obj) + c->value_pos);
1150
*options = (gchar *)(*regex + strlen(*regex) + 1);
1156
bson_cursor_get_javascript (const bson_cursor *c, const gchar **dest)
1161
BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_JS_CODE);
1163
*dest = (gchar *)(bson_data (c->obj) + c->value_pos + sizeof (gint32));
1169
bson_cursor_get_symbol (const bson_cursor *c, const gchar **dest)
1174
BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_SYMBOL);
1176
*dest = (gchar *)(bson_data (c->obj) + c->value_pos + sizeof (gint32));
1182
bson_cursor_get_javascript_w_scope (const bson_cursor *c,
1187
gint32 size, docpos;
1192
BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_JS_CODE_W_SCOPE);
1194
docpos = bson_stream_doc_size (bson_data (c->obj),
1195
c->value_pos + sizeof (gint32)) +
1196
sizeof (gint32) * 2;
1197
size = bson_stream_doc_size (bson_data (c->obj), c->value_pos + docpos) -
1198
sizeof (gint32) - 1;
1199
b = bson_new_sized (size);
1200
b->data = g_byte_array_append (b->data,
1201
bson_data (c->obj) + c->value_pos + docpos +
1202
sizeof (gint32), size);
1206
*js = (gchar *)(bson_data (c->obj) + c->value_pos + sizeof (gint32) * 2);
1212
bson_cursor_get_int32 (const bson_cursor *c, gint32 *dest)
1217
BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_INT32);
1219
memcpy (dest, bson_data (c->obj) + c->value_pos, sizeof (gint32));
1220
*dest = GINT32_FROM_LE (*dest);
1226
bson_cursor_get_timestamp (const bson_cursor *c, gint64 *dest)
1231
BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_TIMESTAMP);
1233
memcpy (dest, bson_data (c->obj) + c->value_pos, sizeof (gint64));
1234
*dest = GINT64_FROM_LE (*dest);
1240
bson_cursor_get_int64 (const bson_cursor *c, gint64 *dest)
1245
BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_INT64);
1247
memcpy (dest, bson_data (c->obj) + c->value_pos, sizeof (gint64));
1248
*dest = GINT64_FROM_LE (*dest);