~ubuntu-branches/ubuntu/trusty/syslog-ng/trusty-proposed

« back to all changes in this revision

Viewing changes to modules/afmongodb/libmongo-client/src/bson.c

  • Committer: Package Import Robot
  • Author(s): Laszlo Boszormenyi (GCS), Gergely Nagy
  • Date: 2011-10-11 14:30:48 UTC
  • mfrom: (1.3.7)
  • Revision ID: package-import@ubuntu.com-20111011143048-r1iljux9xbvj3lwh
Tags: 3.3.1.dfsg-1
* New upstream release with important fixes from upstream git tree with
  non-free manpages removed.
* Drop syslog-ng.conf(5) (closes: #496521).
* syslog-ng(8) is generated, and does not mention -Q anymore
  (closes: #616069).
* Supports CAP_SYSLOG on recent kernels (closes: #630172).
* Does not use g_timeout_add_seconds anymore (closes: #609154).

[ Gergely Nagy <algernon@madhouse-project.org> ]
* Update debian/copyright to DEP-5 format.
* Simplified the logrotate file by merging identical entries.
* Include local configuration files from /etc/syslog-ng/conf.d/ (Closes:
  #609050).
* Update syslog-ng.conf to be fully 3.3 compliant.
* Compress both source and binaries (except the syslog-ng meta
  package) with xz, instead of gzip.
* Use dpkg triggers to restart syslog-ng when appropriate.
* Include DFSG-free manual pages for all binaries.
* Build with Hardening enabled.
* Mention syslog(3) in /etc/default/syslog-ng, instead of
  <linux/kernel.h> (Closes: #608605)
* Support 'status' in the init script.
  Patch from Peter Eisentraut <petere@debian.org> (Closes: #644458)
* Build-Depend on libevtlog-dev (>= 0.2.12-5~) for correct shlibs.
* Use [linux-any] in Build-Depends instead of hardcoded links.
  (Closes: #634715)
* Use $SYSLOGNG_OPTS in the init script when reloading syslog-ng.
  (Closes: #589081)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* bson.c - libmongo-client's BSON implementation
 
2
 * Copyright 2011 Gergely Nagy <algernon@balabit.hu>
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
/** @file src/bson.c
 
18
 * Implementation of the BSON API.
 
19
 */
 
20
 
 
21
#include <glib.h>
 
22
#include <errno.h>
 
23
#include <string.h>
 
24
#include <stdarg.h>
 
25
 
 
26
#include "bson.h"
 
27
#include "libmongo-macros.h"
 
28
#include "libmongo-private.h"
 
29
 
 
30
/** @internal BSON cursor structure.
 
31
 */
 
32
struct _bson_cursor
 
33
{
 
34
  const bson *obj; /**< The BSON object this is a cursor for. */
 
35
  const gchar *key; /**< Pointer within the BSON object to the
 
36
                       current key. */
 
37
  size_t pos; /**< Position within the BSON object, pointing at the
 
38
                 element type. */
 
39
  size_t value_pos; /**< The start of the value within the BSON
 
40
                       object, pointing right after the end of the
 
41
                       key. */
 
42
};
 
43
 
 
44
/** @internal Append a byte to a BSON stream.
 
45
 *
 
46
 * @param b is the BSON stream to append to.
 
47
 * @param byte is the byte to append.
 
48
 */
 
49
static inline void
 
50
_bson_append_byte (bson *b, const guint8 byte)
 
51
{
 
52
  b->data = g_byte_array_append (b->data, &byte, sizeof (byte));
 
53
}
 
54
 
 
55
/** @internal Append a 32-bit integer to a BSON stream.
 
56
 *
 
57
 * @param b is the BSON stream to append to.
 
58
 * @param i is the integer to append.
 
59
 */
 
60
static inline void
 
61
_bson_append_int32 (bson *b, const gint32 i)
 
62
{
 
63
  b->data = g_byte_array_append (b->data, (const guint8 *)&i, sizeof (gint32));
 
64
}
 
65
 
 
66
/** @internal Append a 64-bit integer to a BSON stream.
 
67
 *
 
68
 * @param b is the BSON stream to append to.
 
69
 * @param i is the integer to append.
 
70
 */
 
71
static inline void
 
72
_bson_append_int64 (bson *b, const gint64 i)
 
73
{
 
74
  b->data = g_byte_array_append (b->data, (const guint8 *)&i, sizeof (gint64));
 
75
}
 
76
 
 
77
/** @internal Append an element header to a BSON stream.
 
78
 *
 
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)
 
81
 * name.
 
82
 *
 
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.
 
86
 *
 
87
 * @returns TRUE on success, FALSE otherwise.
 
88
 */
 
89
static inline gboolean
 
90
_bson_append_element_header (bson *b, bson_type type, const gchar *name)
 
91
{
 
92
  if (!name || !b)
 
93
    return FALSE;
 
94
 
 
95
  if (b->finished)
 
96
    return FALSE;
 
97
 
 
98
  _bson_append_byte (b, (guint8) type);
 
99
  b->data = g_byte_array_append (b->data, (const guint8 *)name,
 
100
                                 strlen (name) + 1);
 
101
 
 
102
  return TRUE;
 
103
}
 
104
 
 
105
/** @internal Append a string-like element to a BSON object.
 
106
 *
 
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.
 
110
 *
 
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.
 
116
 *
 
117
 * @note Passing @a -1 as length will use the full length of @a
 
118
 * val.
 
119
 *
 
120
 * @returns TRUE on success, FALSE otherwise.
 
121
 */
 
122
static gboolean
 
123
_bson_append_string_element (bson *b, bson_type type, const gchar *name,
 
124
                             const gchar *val, gint32 length)
 
125
{
 
126
  size_t len;
 
127
 
 
128
  if (!val || !length || length < -1)
 
129
    return FALSE;
 
130
 
 
131
  len = (length != -1) ? (size_t)length + 1: strlen (val) + 1;
 
132
 
 
133
  if (!_bson_append_element_header (b, type, name))
 
134
    return FALSE;
 
135
 
 
136
  _bson_append_int32 (b, GINT32_TO_LE (len));
 
137
 
 
138
  b->data = g_byte_array_append (b->data, (const guint8 *)val, len - 1);
 
139
  _bson_append_byte (b, 0);
 
140
 
 
141
  return TRUE;
 
142
}
 
143
 
 
144
/** @internal Append a document-like element to a BSON object.
 
145
 *
 
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).
 
149
 *
 
150
 * This convenience function can append both types.
 
151
 *
 
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.
 
156
 *
 
157
 * @note The @a doc must be a finished BSON object.
 
158
 *
 
159
 * @returns TRUE on success, FALSE otherwise.
 
160
 */
 
161
static gboolean
 
162
_bson_append_document_element (bson *b, bson_type type, const gchar *name,
 
163
                               const bson *doc)
 
164
{
 
165
  if (bson_size (doc) < 0)
 
166
    return FALSE;
 
167
 
 
168
  if (!_bson_append_element_header (b, type, name))
 
169
    return FALSE;
 
170
 
 
171
  b->data = g_byte_array_append (b->data, bson_data (doc), bson_size (doc));
 
172
  return TRUE;
 
173
}
 
174
 
 
175
/** @internal Append a 64-bit integer to a BSON object.
 
176
 *
 
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.
 
181
 *
 
182
 * @returns TRUE on success, FALSE otherwise.
 
183
 */
 
184
static inline gboolean
 
185
_bson_append_int64_element (bson *b, bson_type type, const gchar *name,
 
186
                            gint64 i)
 
187
{
 
188
  if (!_bson_append_element_header (b, type, name))
 
189
    return FALSE;
 
190
 
 
191
  _bson_append_int64 (b, GINT64_TO_LE (i));
 
192
  return TRUE;
 
193
}
 
194
 
 
195
/********************
 
196
 * Public interface *
 
197
 ********************/
 
198
 
 
199
const gchar *
 
200
bson_type_as_string (bson_type type)
 
201
{
 
202
  switch (type)
 
203
    {
 
204
    case BSON_TYPE_NONE:
 
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";
 
218
    case BSON_TYPE_OID:
 
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";
 
224
    case BSON_TYPE_NULL:
 
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";
 
242
    case BSON_TYPE_MIN:
 
243
      return "BSON_TYPE_MIN";
 
244
    case BSON_TYPE_MAX:
 
245
      return "BSON_TYPE_MAX";
 
246
    default:
 
247
      return NULL;
 
248
  }
 
249
}
 
250
 
 
251
bson *
 
252
bson_new (void)
 
253
{
 
254
  return bson_new_sized (0);
 
255
}
 
256
 
 
257
bson *
 
258
bson_new_sized (gint32 size)
 
259
{
 
260
  bson *b = g_new0 (bson, 1);
 
261
 
 
262
  b->data = g_byte_array_sized_new (size + sizeof (gint32) + sizeof (guint8));
 
263
  _bson_append_int32 (b, 0);
 
264
 
 
265
  return b;
 
266
}
 
267
 
 
268
bson *
 
269
bson_new_from_data (const guint8 *data, gint32 size)
 
270
{
 
271
  bson *b;
 
272
 
 
273
  if (!data || size <= 0)
 
274
    return NULL;
 
275
 
 
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);
 
279
 
 
280
  return b;
 
281
}
 
282
 
 
283
/** @internal Add a single element of any type to a BSON object.
 
284
 *
 
285
 * Used internally by bson_build() and bson_build_full(), this
 
286
 * function adds a single element of any supported type to the target
 
287
 * BSON object.
 
288
 *
 
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
 
293
 * them.
 
294
 * @param ap is the list of remaining parameters.
 
295
 *
 
296
 * @returns TRUE in @a single_result on success, FALSE otherwise.
 
297
 */
 
298
#define _bson_build_add_single(b,type,name,free_after,ap)               \
 
299
  {                                                                     \
 
300
    single_result = TRUE;                                               \
 
301
    switch (type)                                                       \
 
302
      {                                                                 \
 
303
      case BSON_TYPE_NONE:                                              \
 
304
      case BSON_TYPE_UNDEFINED:                                         \
 
305
      case BSON_TYPE_DBPOINTER:                                         \
 
306
        single_result = FALSE;                                          \
 
307
        break;                                                          \
 
308
      case BSON_TYPE_MIN:                                               \
 
309
      case BSON_TYPE_MAX:                                               \
 
310
      default:                                                          \
 
311
        single_result = FALSE;                                          \
 
312
        break;                                                          \
 
313
      case BSON_TYPE_DOUBLE:                                            \
 
314
        {                                                               \
 
315
          gdouble d = (gdouble)va_arg (ap, gdouble);                    \
 
316
          bson_append_double (b, name, d);                              \
 
317
          break;                                                        \
 
318
        }                                                               \
 
319
      case BSON_TYPE_STRING:                                            \
 
320
        {                                                               \
 
321
          gchar *s = (gchar *)va_arg (ap, gpointer);                    \
 
322
          gint32 l = (gint32)va_arg (ap, gint32);                       \
 
323
          bson_append_string (b, name, s, l);                           \
 
324
          if (free_after)                                               \
 
325
            g_free (s);                                                 \
 
326
          break;                                                        \
 
327
        }                                                               \
 
328
      case BSON_TYPE_DOCUMENT:                                          \
 
329
        {                                                               \
 
330
          bson *d = (bson *)va_arg (ap, gpointer);                      \
 
331
          if (free_after && bson_size (d) < 0)                          \
 
332
            bson_finish (d);                                            \
 
333
          bson_append_document (b, name, d);                            \
 
334
          if (free_after)                                               \
 
335
            bson_free (d);                                              \
 
336
          break;                                                        \
 
337
        }                                                               \
 
338
      case BSON_TYPE_ARRAY:                                             \
 
339
        {                                                               \
 
340
          bson *d = (bson *)va_arg (ap, gpointer);                      \
 
341
          if (free_after && bson_size (d) < 0)                          \
 
342
            bson_finish (d);                                            \
 
343
          bson_append_array (b, name, d);                               \
 
344
          if (free_after)                                               \
 
345
            bson_free (d);                                              \
 
346
          break;                                                        \
 
347
        }                                                               \
 
348
      case BSON_TYPE_BINARY:                                            \
 
349
        {                                                               \
 
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);                        \
 
355
          if (free_after)                                               \
 
356
            g_free (d);                                                 \
 
357
          break;                                                        \
 
358
        }                                                               \
 
359
      case BSON_TYPE_OID:                                               \
 
360
        {                                                               \
 
361
          guint8 *oid = (guint8 *)va_arg (ap, gpointer);                \
 
362
          bson_append_oid (b, name, oid);                               \
 
363
          if (free_after)                                               \
 
364
            g_free (oid);                                               \
 
365
          break;                                                        \
 
366
        }                                                               \
 
367
      case BSON_TYPE_BOOLEAN:                                           \
 
368
        {                                                               \
 
369
          gboolean v = (gboolean)va_arg (ap, guint);                    \
 
370
          bson_append_boolean (b, name, v);                             \
 
371
          break;                                                        \
 
372
        }                                                               \
 
373
      case BSON_TYPE_UTC_DATETIME:                                      \
 
374
        {                                                               \
 
375
          gint64 ts = (gint64)va_arg (ap, gint64);                      \
 
376
          bson_append_utc_datetime (b, name, ts);                       \
 
377
          break;                                                        \
 
378
        }                                                               \
 
379
      case BSON_TYPE_NULL:                                              \
 
380
        {                                                               \
 
381
          bson_append_null (b, name);                                   \
 
382
          break;                                                        \
 
383
        }                                                               \
 
384
      case BSON_TYPE_REGEXP:                                            \
 
385
        {                                                               \
 
386
          gchar *r = (gchar *)va_arg (ap, gpointer);                    \
 
387
          gchar *o = (gchar *)va_arg (ap, gpointer);                    \
 
388
          bson_append_regex (b, name, r, o);                            \
 
389
          if (free_after)                                               \
 
390
            {                                                           \
 
391
              g_free (r);                                               \
 
392
              g_free (o);                                               \
 
393
            }                                                           \
 
394
          break;                                                        \
 
395
      }                                                                 \
 
396
      case BSON_TYPE_JS_CODE:                                           \
 
397
        {                                                               \
 
398
          gchar *s = (gchar *)va_arg (ap, gpointer);                    \
 
399
          gint32 l = (gint32)va_arg (ap, gint32);                       \
 
400
          bson_append_javascript (b, name, s, l);                       \
 
401
          if (free_after)                                               \
 
402
            g_free (s);                                                 \
 
403
          break;                                                        \
 
404
        }                                                               \
 
405
      case BSON_TYPE_SYMBOL:                                            \
 
406
        {                                                               \
 
407
          gchar *s = (gchar *)va_arg (ap, gpointer);                    \
 
408
          gint32 l = (gint32)va_arg (ap, gint32);                       \
 
409
          bson_append_symbol (b, name, s, l);                           \
 
410
          if (free_after)                                               \
 
411
            g_free (s);                                                 \
 
412
          break;                                                        \
 
413
        }                                                               \
 
414
      case BSON_TYPE_JS_CODE_W_SCOPE:                                   \
 
415
        {                                                               \
 
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);        \
 
422
          if (free_after)                                               \
 
423
            bson_free (scope);                                          \
 
424
          break;                                                        \
 
425
        }                                                               \
 
426
      case BSON_TYPE_INT32:                                             \
 
427
        {                                                               \
 
428
          gint32 l = (gint32)va_arg (ap, gint32);                       \
 
429
          bson_append_int32 (b, name, l);                               \
 
430
          break;                                                        \
 
431
        }                                                               \
 
432
      case BSON_TYPE_TIMESTAMP:                                         \
 
433
        {                                                               \
 
434
          gint64 ts = (gint64)va_arg (ap, gint64);                      \
 
435
          bson_append_timestamp (b, name, ts);                          \
 
436
          break;                                                        \
 
437
        }                                                               \
 
438
      case BSON_TYPE_INT64:                                             \
 
439
        {                                                               \
 
440
          gint64 l = (gint64)va_arg (ap, gint64);                       \
 
441
          bson_append_int64 (b, name, l);                               \
 
442
          break;                                                        \
 
443
        }                                                               \
 
444
      }                                                                 \
 
445
  }
 
446
 
 
447
bson *
 
448
bson_build (bson_type type, const gchar *name, ...)
 
449
{
 
450
  va_list ap;
 
451
  bson_type t;
 
452
  const gchar *n;
 
453
  bson *b;
 
454
  gboolean single_result;
 
455
 
 
456
  b = bson_new ();
 
457
  va_start (ap, name);
 
458
  _bson_build_add_single (b, type, name, FALSE, ap);
 
459
 
 
460
  if (!single_result)
 
461
    {
 
462
      bson_free (b);
 
463
      va_end (ap);
 
464
      return NULL;
 
465
    }
 
466
 
 
467
  while ((t = (bson_type)va_arg (ap, gint)))
 
468
    {
 
469
      n = (const gchar *)va_arg (ap, gpointer);
 
470
      _bson_build_add_single (b, t, n, FALSE, ap);
 
471
      if (!single_result)
 
472
        {
 
473
          bson_free (b);
 
474
          va_end (ap);
 
475
          return NULL;
 
476
        }
 
477
    }
 
478
  va_end (ap);
 
479
 
 
480
  return b;
 
481
}
 
482
 
 
483
bson *
 
484
bson_build_full (bson_type type, const gchar *name, gboolean free_after, ...)
 
485
{
 
486
  va_list ap;
 
487
  bson_type t;
 
488
  const gchar *n;
 
489
  gboolean f;
 
490
  bson *b;
 
491
  gboolean single_result;
 
492
 
 
493
  b = bson_new ();
 
494
  va_start (ap, free_after);
 
495
  _bson_build_add_single (b, type, name, free_after, ap);
 
496
  if (!single_result)
 
497
    {
 
498
      bson_free (b);
 
499
      va_end (ap);
 
500
      return NULL;
 
501
    }
 
502
 
 
503
  while ((t = (bson_type)va_arg (ap, gint)))
 
504
    {
 
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);
 
508
      if (!single_result)
 
509
        {
 
510
          bson_free (b);
 
511
          va_end (ap);
 
512
          return NULL;
 
513
        }
 
514
    }
 
515
  va_end (ap);
 
516
 
 
517
  return b;
 
518
}
 
519
 
 
520
gboolean
 
521
bson_finish (bson *b)
 
522
{
 
523
  gint32 *i;
 
524
 
 
525
  if (!b)
 
526
    return FALSE;
 
527
 
 
528
  if (b->finished)
 
529
    return TRUE;
 
530
 
 
531
  _bson_append_byte (b, 0);
 
532
 
 
533
  i = (gint32 *) (&b->data->data[0]);
 
534
  *i = GINT32_TO_LE ((gint32) (b->data->len));
 
535
 
 
536
  b->finished = TRUE;
 
537
 
 
538
  return TRUE;
 
539
}
 
540
 
 
541
gint32
 
542
bson_size (const bson *b)
 
543
{
 
544
  if (!b)
 
545
    return -1;
 
546
 
 
547
  if (b->finished)
 
548
    return b->data->len;
 
549
  else
 
550
    return -1;
 
551
}
 
552
 
 
553
const guint8 *
 
554
bson_data (const bson *b)
 
555
{
 
556
  if (!b)
 
557
    return NULL;
 
558
 
 
559
  if (b->finished)
 
560
    return b->data->data;
 
561
  else
 
562
    return NULL;
 
563
}
 
564
 
 
565
gboolean
 
566
bson_reset (bson *b)
 
567
{
 
568
  if (!b)
 
569
    return FALSE;
 
570
 
 
571
  b->finished = FALSE;
 
572
  g_byte_array_set_size (b->data, 0);
 
573
  _bson_append_int32 (b, 0);
 
574
 
 
575
  return TRUE;
 
576
}
 
577
 
 
578
void
 
579
bson_free (bson *b)
 
580
{
 
581
  if (!b)
 
582
    return;
 
583
 
 
584
  if (b->data)
 
585
    g_byte_array_free (b->data, TRUE);
 
586
  g_free (b);
 
587
}
 
588
 
 
589
gboolean
 
590
bson_validate_key (const gchar *key, gboolean forbid_dots,
 
591
                   gboolean no_dollar)
 
592
{
 
593
  if (!key)
 
594
    {
 
595
      errno = EINVAL;
 
596
      return FALSE;
 
597
    }
 
598
  errno = 0;
 
599
 
 
600
  if (no_dollar && key[0] == '$')
 
601
    return FALSE;
 
602
 
 
603
  if (forbid_dots && strchr (key, '.') != NULL)
 
604
    return FALSE;
 
605
 
 
606
  return TRUE;
 
607
}
 
608
 
 
609
/*
 
610
 * Append elements
 
611
 */
 
612
 
 
613
gboolean
 
614
bson_append_double (bson *b, const gchar *name, gdouble val)
 
615
{
 
616
  gdouble d = GDOUBLE_TO_LE (val);
 
617
 
 
618
  if (!_bson_append_element_header (b, BSON_TYPE_DOUBLE, name))
 
619
    return FALSE;
 
620
 
 
621
  b->data = g_byte_array_append (b->data, (const guint8 *)&d, sizeof (val));
 
622
  return TRUE;
 
623
}
 
624
 
 
625
gboolean
 
626
bson_append_string (bson *b, const gchar *name, const gchar *val,
 
627
                    gint32 length)
 
628
{
 
629
  return _bson_append_string_element (b, BSON_TYPE_STRING, name, val, length);
 
630
}
 
631
 
 
632
gboolean
 
633
bson_append_document (bson *b, const gchar *name, const bson *doc)
 
634
{
 
635
  return _bson_append_document_element (b, BSON_TYPE_DOCUMENT, name, doc);
 
636
}
 
637
 
 
638
gboolean
 
639
bson_append_array (bson *b, const gchar *name, const bson *array)
 
640
{
 
641
  return _bson_append_document_element (b, BSON_TYPE_ARRAY, name, array);
 
642
}
 
643
 
 
644
gboolean
 
645
bson_append_binary (bson *b, const gchar *name, bson_binary_subtype subtype,
 
646
                    const guint8 *data, gint32 size)
 
647
{
 
648
  if (!data || !size || size <= 0)
 
649
    return FALSE;
 
650
 
 
651
  if (!_bson_append_element_header (b, BSON_TYPE_BINARY, name))
 
652
    return FALSE;
 
653
 
 
654
  _bson_append_int32 (b, GINT32_TO_LE (size));
 
655
  _bson_append_byte (b, (guint8)subtype);
 
656
 
 
657
  b->data = g_byte_array_append (b->data, data, size);
 
658
  return TRUE;
 
659
}
 
660
 
 
661
gboolean
 
662
bson_append_oid (bson *b, const gchar *name, const guint8 *oid)
 
663
{
 
664
  if (!oid)
 
665
    return FALSE;
 
666
 
 
667
  if (!_bson_append_element_header (b, BSON_TYPE_OID, name))
 
668
    return FALSE;
 
669
 
 
670
  b->data = g_byte_array_append (b->data, oid, 12);
 
671
  return TRUE;
 
672
}
 
673
 
 
674
gboolean
 
675
bson_append_boolean (bson *b, const gchar *name, gboolean value)
 
676
{
 
677
  if (!_bson_append_element_header (b, BSON_TYPE_BOOLEAN, name))
 
678
    return FALSE;
 
679
 
 
680
  _bson_append_byte (b, (guint8)value);
 
681
  return TRUE;
 
682
}
 
683
 
 
684
gboolean
 
685
bson_append_utc_datetime (bson *b, const gchar *name, gint64 ts)
 
686
{
 
687
  return _bson_append_int64_element (b, BSON_TYPE_UTC_DATETIME, name, ts);
 
688
}
 
689
 
 
690
gboolean
 
691
bson_append_null (bson *b, const gchar *name)
 
692
{
 
693
  return _bson_append_element_header (b, BSON_TYPE_NULL, name);
 
694
}
 
695
 
 
696
gboolean
 
697
bson_append_regex (bson *b, const gchar *name, const gchar *regexp,
 
698
                   const gchar *options)
 
699
{
 
700
  if (!regexp || !options)
 
701
    return FALSE;
 
702
 
 
703
  if (!_bson_append_element_header (b, BSON_TYPE_REGEXP, name))
 
704
    return FALSE;
 
705
 
 
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);
 
710
 
 
711
  return TRUE;
 
712
}
 
713
 
 
714
gboolean
 
715
bson_append_javascript (bson *b, const gchar *name, const gchar *js,
 
716
                        gint32 len)
 
717
{
 
718
  return _bson_append_string_element (b, BSON_TYPE_JS_CODE, name, js, len);
 
719
}
 
720
 
 
721
gboolean
 
722
bson_append_symbol (bson *b, const gchar *name, const gchar *symbol,
 
723
                    gint32 len)
 
724
{
 
725
  return _bson_append_string_element (b, BSON_TYPE_SYMBOL, name, symbol, len);
 
726
}
 
727
 
 
728
gboolean
 
729
bson_append_javascript_w_scope (bson *b, const gchar *name,
 
730
                                const gchar *js, gint32 len,
 
731
                                const bson *scope)
 
732
{
 
733
  gint size;
 
734
  size_t length;
 
735
 
 
736
  if (!js || !scope || bson_size (scope) < 0 || len < -1)
 
737
    return FALSE;
 
738
 
 
739
  if (!_bson_append_element_header (b, BSON_TYPE_JS_CODE_W_SCOPE, name))
 
740
    return FALSE;
 
741
 
 
742
  length = (len != -1) ? (size_t)len + 1: strlen (js) + 1;
 
743
 
 
744
  size = length + sizeof (gint32) + sizeof (gint32) + bson_size (scope);
 
745
 
 
746
  _bson_append_int32 (b, GINT32_TO_LE (size));
 
747
 
 
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);
 
752
 
 
753
  /* Append the scope */
 
754
  b->data = g_byte_array_append (b->data, bson_data (scope),
 
755
                                 bson_size (scope));
 
756
 
 
757
  return TRUE;
 
758
}
 
759
 
 
760
gboolean
 
761
bson_append_int32 (bson *b, const gchar *name, gint32 i)
 
762
{
 
763
  if (!_bson_append_element_header (b, BSON_TYPE_INT32, name))
 
764
    return FALSE;
 
765
 
 
766
  _bson_append_int32 (b, GINT32_TO_LE (i));
 
767
  return TRUE;
 
768
 }
 
769
 
 
770
gboolean
 
771
bson_append_timestamp (bson *b, const gchar *name, gint64 ts)
 
772
{
 
773
  return _bson_append_int64_element (b, BSON_TYPE_TIMESTAMP, name, ts);
 
774
}
 
775
 
 
776
gboolean
 
777
bson_append_int64 (bson *b, const gchar *name, gint64 i)
 
778
{
 
779
  return _bson_append_int64_element (b, BSON_TYPE_INT64, name, i);
 
780
}
 
781
 
 
782
/*
 
783
 * Find & retrieve data
 
784
 */
 
785
bson_cursor *
 
786
bson_cursor_new (const bson *b)
 
787
{
 
788
  bson_cursor *c;
 
789
 
 
790
  if (bson_size (b) == -1)
 
791
    return NULL;
 
792
 
 
793
  c = (bson_cursor *)g_new0 (bson_cursor, 1);
 
794
  c->obj = b;
 
795
 
 
796
  return c;
 
797
}
 
798
 
 
799
void
 
800
bson_cursor_free (bson_cursor *c)
 
801
{
 
802
  g_free (c);
 
803
}
 
804
 
 
805
/** @internal Figure out the block size of a given type.
 
806
 *
 
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.
 
809
 *
 
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
 
812
 * name).
 
813
 *
 
814
 * @returns The size of the block, or -1 on error.
 
815
 */
 
816
static gint32
 
817
_bson_get_block_size (bson_type type, const guint8 *data)
 
818
{
 
819
  glong l;
 
820
 
 
821
  switch (type)
 
822
    {
 
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);
 
836
    case BSON_TYPE_OID:
 
837
      return 12;
 
838
    case BSON_TYPE_BOOLEAN:
 
839
      return 1;
 
840
    case BSON_TYPE_UTC_DATETIME:
 
841
    case BSON_TYPE_TIMESTAMP:
 
842
    case BSON_TYPE_INT64:
 
843
      return sizeof (gint64);
 
844
    case BSON_TYPE_NULL:
 
845
    case BSON_TYPE_UNDEFINED:
 
846
    case BSON_TYPE_MIN:
 
847
    case BSON_TYPE_MAX:
 
848
      return 0;
 
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;
 
856
    case BSON_TYPE_NONE:
 
857
    default:
 
858
      return -1;
 
859
    }
 
860
}
 
861
 
 
862
gboolean
 
863
bson_cursor_next (bson_cursor *c)
 
864
{
 
865
  const guint8 *d;
 
866
  gint32 pos, bs;
 
867
 
 
868
  if (!c)
 
869
    return FALSE;
 
870
 
 
871
  d = bson_data (c->obj);
 
872
 
 
873
  if (c->pos == 0)
 
874
    pos = sizeof (guint32);
 
875
  else
 
876
    {
 
877
      bs = _bson_get_block_size (bson_cursor_type (c), d + c->value_pos);
 
878
      if (bs == -1)
 
879
        return FALSE;
 
880
      pos = c->value_pos + bs;
 
881
    }
 
882
 
 
883
  if (pos >= bson_size (c->obj) - 1)
 
884
    return FALSE;
 
885
 
 
886
  c->pos = pos;
 
887
  c->key = (gchar *) &d[c->pos + 1];
 
888
  c->value_pos = c->pos + strlen (c->key) + 2;
 
889
 
 
890
  return TRUE;
 
891
}
 
892
 
 
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)
 
896
{
 
897
  gint32 pos = start_pos, bs;
 
898
  const guint8 *d;
 
899
  gint32 name_len;
 
900
 
 
901
  name_len = strlen (name);
 
902
 
 
903
  d = bson_data (b);
 
904
 
 
905
  while (pos < end_pos)
 
906
    {
 
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;
 
911
 
 
912
      if (!memcmp (key, name, (name_len <= key_len) ? name_len : key_len))
 
913
        {
 
914
          dest_c->obj = b;
 
915
          dest_c->key = key;
 
916
          dest_c->pos = pos;
 
917
          dest_c->value_pos = value_pos;
 
918
 
 
919
          return TRUE;
 
920
        }
 
921
      bs = _bson_get_block_size (t, &d[value_pos]);
 
922
      if (bs == -1)
 
923
        return FALSE;
 
924
      pos = value_pos + bs;
 
925
    }
 
926
 
 
927
  if (wrap_over)
 
928
    return _bson_cursor_find (b, name, sizeof (gint32), start_pos,
 
929
                              FALSE, dest_c);
 
930
 
 
931
  return FALSE;
 
932
}
 
933
 
 
934
gboolean
 
935
bson_cursor_find (bson_cursor *c, const gchar *name)
 
936
{
 
937
  if (!c || !name)
 
938
    return FALSE;
 
939
 
 
940
  return _bson_cursor_find (c->obj, name, c->pos, bson_size (c->obj) - 1,
 
941
                            TRUE, c);
 
942
}
 
943
 
 
944
gboolean
 
945
bson_cursor_find_next (bson_cursor *c, const gchar *name)
 
946
{
 
947
  if (!c || !name)
 
948
    return FALSE;
 
949
 
 
950
  return _bson_cursor_find (c->obj, name, c->pos, bson_size (c->obj) - 1,
 
951
                            FALSE, c);
 
952
}
 
953
 
 
954
bson_cursor *
 
955
bson_find (const bson *b, const gchar *name)
 
956
{
 
957
  bson_cursor *c;
 
958
 
 
959
  if (bson_size (b) == -1 || !name)
 
960
    return NULL;
 
961
 
 
962
  c = bson_cursor_new (b);
 
963
  if (_bson_cursor_find (b, name, sizeof (gint32), bson_size (c->obj) - 1,
 
964
                         FALSE, c))
 
965
    return c;
 
966
  bson_cursor_free (c);
 
967
  return NULL;
 
968
}
 
969
 
 
970
bson_type
 
971
bson_cursor_type (const bson_cursor *c)
 
972
{
 
973
  if (!c || c->pos < sizeof (gint32))
 
974
    return BSON_TYPE_NONE;
 
975
 
 
976
  return (bson_type)(bson_data (c->obj)[c->pos]);
 
977
}
 
978
 
 
979
const gchar *
 
980
bson_cursor_type_as_string (const bson_cursor *c)
 
981
{
 
982
  if (!c || c->pos < sizeof (gint32))
 
983
    return NULL;
 
984
 
 
985
  return bson_type_as_string (bson_cursor_type (c));
 
986
}
 
987
 
 
988
const gchar *
 
989
bson_cursor_key (const bson_cursor *c)
 
990
{
 
991
  if (!c)
 
992
    return NULL;
 
993
 
 
994
  return c->key;
 
995
}
 
996
 
 
997
/** @internal Convenience macro to verify a cursor's type.
 
998
 *
 
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.
 
1001
 */
 
1002
#define BSON_CURSOR_CHECK_TYPE(c,type)          \
 
1003
  if (bson_cursor_type(c) != type)              \
 
1004
    return FALSE;
 
1005
 
 
1006
gboolean
 
1007
bson_cursor_get_string (const bson_cursor *c, const gchar **dest)
 
1008
{
 
1009
  if (!dest)
 
1010
    return FALSE;
 
1011
 
 
1012
  BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_STRING);
 
1013
 
 
1014
  *dest = (gchar *)(bson_data (c->obj) + c->value_pos + sizeof (gint32));
 
1015
 
 
1016
  return TRUE;
 
1017
}
 
1018
 
 
1019
gboolean
 
1020
bson_cursor_get_double (const bson_cursor *c, gdouble *dest)
 
1021
{
 
1022
  if (!dest)
 
1023
    return FALSE;
 
1024
 
 
1025
  BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_DOUBLE);
 
1026
 
 
1027
  memcpy (dest, bson_data (c->obj) + c->value_pos, sizeof (gdouble));
 
1028
  *dest = GDOUBLE_FROM_LE (*dest);
 
1029
 
 
1030
  return TRUE;
 
1031
}
 
1032
 
 
1033
gboolean
 
1034
bson_cursor_get_document (const bson_cursor *c, bson **dest)
 
1035
{
 
1036
  bson *b;
 
1037
  gint32 size;
 
1038
 
 
1039
  if (!dest)
 
1040
    return FALSE;
 
1041
 
 
1042
  BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_DOCUMENT);
 
1043
 
 
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);
 
1050
  bson_finish (b);
 
1051
 
 
1052
  *dest = b;
 
1053
 
 
1054
  return TRUE;
 
1055
}
 
1056
 
 
1057
gboolean
 
1058
bson_cursor_get_array (const bson_cursor *c, bson **dest)
 
1059
{
 
1060
  bson *b;
 
1061
  gint32 size;
 
1062
 
 
1063
  if (!dest)
 
1064
    return FALSE;
 
1065
 
 
1066
  BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_ARRAY);
 
1067
 
 
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);
 
1074
  bson_finish (b);
 
1075
 
 
1076
  *dest = b;
 
1077
 
 
1078
  return TRUE;
 
1079
}
 
1080
 
 
1081
gboolean
 
1082
bson_cursor_get_binary (const bson_cursor *c,
 
1083
                        bson_binary_subtype *subtype,
 
1084
                        const guint8 **data, gint32 *size)
 
1085
{
 
1086
  if (!subtype || !size || !data)
 
1087
    return FALSE;
 
1088
 
 
1089
  BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_BINARY);
 
1090
 
 
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 +
 
1093
                                                      sizeof (gint32)]);
 
1094
  *data = (guint8 *)(bson_data (c->obj) + c->value_pos + sizeof (gint32) + 1);
 
1095
 
 
1096
  return TRUE;
 
1097
}
 
1098
 
 
1099
gboolean
 
1100
bson_cursor_get_oid (const bson_cursor *c, const guint8 **dest)
 
1101
{
 
1102
  if (!dest)
 
1103
    return FALSE;
 
1104
 
 
1105
  BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_OID);
 
1106
 
 
1107
  *dest = (guint8 *)(bson_data (c->obj) + c->value_pos);
 
1108
 
 
1109
  return TRUE;
 
1110
}
 
1111
 
 
1112
gboolean
 
1113
bson_cursor_get_boolean (const bson_cursor *c, gboolean *dest)
 
1114
{
 
1115
  if (!dest)
 
1116
    return FALSE;
 
1117
 
 
1118
  BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_BOOLEAN);
 
1119
 
 
1120
  *dest = (gboolean)(bson_data (c->obj) + c->value_pos)[0];
 
1121
 
 
1122
  return TRUE;
 
1123
}
 
1124
 
 
1125
gboolean
 
1126
bson_cursor_get_utc_datetime (const bson_cursor *c,
 
1127
                              gint64 *dest)
 
1128
{
 
1129
  if (!dest)
 
1130
    return FALSE;
 
1131
 
 
1132
  BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_UTC_DATETIME);
 
1133
 
 
1134
  memcpy (dest, bson_data (c->obj) + c->value_pos, sizeof (gint64));
 
1135
  *dest = GINT64_FROM_LE (*dest);
 
1136
 
 
1137
  return TRUE;
 
1138
}
 
1139
 
 
1140
gboolean
 
1141
bson_cursor_get_regex (const bson_cursor *c, const gchar **regex,
 
1142
                       const gchar **options)
 
1143
{
 
1144
  if (!regex || !options)
 
1145
    return FALSE;
 
1146
 
 
1147
  BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_REGEXP);
 
1148
 
 
1149
  *regex = (gchar *)(bson_data (c->obj) + c->value_pos);
 
1150
  *options = (gchar *)(*regex + strlen(*regex) + 1);
 
1151
 
 
1152
  return TRUE;
 
1153
}
 
1154
 
 
1155
gboolean
 
1156
bson_cursor_get_javascript (const bson_cursor *c, const gchar **dest)
 
1157
{
 
1158
  if (!dest)
 
1159
    return FALSE;
 
1160
 
 
1161
  BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_JS_CODE);
 
1162
 
 
1163
  *dest = (gchar *)(bson_data (c->obj) + c->value_pos + sizeof (gint32));
 
1164
 
 
1165
  return TRUE;
 
1166
}
 
1167
 
 
1168
gboolean
 
1169
bson_cursor_get_symbol (const bson_cursor *c, const gchar **dest)
 
1170
{
 
1171
  if (!dest)
 
1172
    return FALSE;
 
1173
 
 
1174
  BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_SYMBOL);
 
1175
 
 
1176
  *dest = (gchar *)(bson_data (c->obj) + c->value_pos + sizeof (gint32));
 
1177
 
 
1178
  return TRUE;
 
1179
}
 
1180
 
 
1181
gboolean
 
1182
bson_cursor_get_javascript_w_scope (const bson_cursor *c,
 
1183
                                    const gchar **js,
 
1184
                                    bson **scope)
 
1185
{
 
1186
  bson *b;
 
1187
  gint32 size, docpos;
 
1188
 
 
1189
  if (!js || !scope)
 
1190
    return FALSE;
 
1191
 
 
1192
  BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_JS_CODE_W_SCOPE);
 
1193
 
 
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);
 
1203
  bson_finish (b);
 
1204
 
 
1205
  *scope = b;
 
1206
  *js = (gchar *)(bson_data (c->obj) + c->value_pos + sizeof (gint32) * 2);
 
1207
 
 
1208
  return TRUE;
 
1209
}
 
1210
 
 
1211
gboolean
 
1212
bson_cursor_get_int32 (const bson_cursor *c, gint32 *dest)
 
1213
{
 
1214
  if (!dest)
 
1215
    return FALSE;
 
1216
 
 
1217
  BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_INT32);
 
1218
 
 
1219
  memcpy (dest, bson_data (c->obj) + c->value_pos, sizeof (gint32));
 
1220
  *dest = GINT32_FROM_LE (*dest);
 
1221
 
 
1222
  return TRUE;
 
1223
}
 
1224
 
 
1225
gboolean
 
1226
bson_cursor_get_timestamp (const bson_cursor *c, gint64 *dest)
 
1227
{
 
1228
  if (!dest)
 
1229
    return FALSE;
 
1230
 
 
1231
  BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_TIMESTAMP);
 
1232
 
 
1233
  memcpy (dest, bson_data (c->obj) + c->value_pos, sizeof (gint64));
 
1234
  *dest = GINT64_FROM_LE (*dest);
 
1235
 
 
1236
  return TRUE;
 
1237
}
 
1238
 
 
1239
gboolean
 
1240
bson_cursor_get_int64 (const bson_cursor *c, gint64 *dest)
 
1241
{
 
1242
  if (!dest)
 
1243
    return FALSE;
 
1244
 
 
1245
  BSON_CURSOR_CHECK_TYPE (c, BSON_TYPE_INT64);
 
1246
 
 
1247
  memcpy (dest, bson_data (c->obj) + c->value_pos, sizeof (gint64));
 
1248
  *dest = GINT64_FROM_LE (*dest);
 
1249
 
 
1250
  return TRUE;
 
1251
}