MongoBson * mongo_bson_dup (const MongoBson *bson) { MongoBson *ret = NULL; if (bson) { if (bson->static_data) { ret = mongo_bson_new_from_data(bson->static_data, bson->static_len); } else { ret = mongo_bson_new_from_data(bson->buf->data, bson->buf->len); } } return ret; }
/** * mongo_bson_ref: * @bson: (in): A #MongoBson. * * Atomically increments the reference count of @bson by one. If @bson * contains a static buffer, then a new structure will be returned. * * Returns: (transfer full): @bson. */ MongoBson * mongo_bson_ref (MongoBson *bson) { g_return_val_if_fail(bson != NULL, NULL); g_return_val_if_fail(bson->ref_count > 0, NULL); if (G_UNLIKELY(bson->static_data)) { return mongo_bson_new_from_data(bson->static_data, bson->static_len); } g_atomic_int_inc(&bson->ref_count); return bson; }
/** * mongo_bson_stream_next: * @stream: (in): A #MongoBsonStream. * * Gets the next #MongoBson document found in the stream. * * Returns: (transfer full): A #MongoBson if successful; otherwise %NULL. */ MongoBson * mongo_bson_stream_next (MongoBsonStream *stream) { MongoBson *bson; guint32 doc_len_le; guint32 doc_len; guint8 *buffer; g_return_val_if_fail(MONGO_IS_BSON_STREAM(stream), NULL); g_return_val_if_fail(stream->priv->stream || stream->priv->channel, NULL); if (!mongo_bson_stream_read(stream, (guint8 *)&doc_len_le, sizeof doc_len_le, sizeof doc_len_le)) { return NULL; } doc_len = GUINT32_FROM_LE(doc_len_le); /* * Sanity check to make sure it is less than 8mB and * greater than 5 bytes (minimum required). */ if (doc_len > (1024 * 1024 * 8) || doc_len <= 5) { return NULL; } buffer = g_malloc(doc_len); memcpy(buffer, &doc_len_le, sizeof doc_len_le); /* * Read the rest of the BSON document into our buffer. */ if (!mongo_bson_stream_read(stream, buffer + sizeof doc_len_le, doc_len, doc_len - sizeof doc_len_le)) { return NULL; } if (!(bson = mongo_bson_new_from_data(buffer, doc_len))) { g_free(buffer); return NULL; } return bson; }
static MongoBson * mongo_bson_iter_get_value_document (MongoBsonIter *iter, MongoBsonType type) { const guint8 *buffer; gpointer endbuf; guint32 array_len; g_return_val_if_fail(iter != NULL, NULL); g_return_val_if_fail(iter->user_data1 != NULL, NULL); g_return_val_if_fail(iter->user_data2 != NULL, NULL); g_return_val_if_fail(iter->user_data6 != NULL, NULL); g_return_val_if_fail((type == MONGO_BSON_ARRAY) || (type == MONGO_BSON_DOCUMENT), NULL); if (G_LIKELY(ITER_IS_TYPE(iter, type))) { endbuf = GSIZE_TO_POINTER(GPOINTER_TO_SIZE(iter->user_data1) + GPOINTER_TO_SIZE(iter->user_data2)); if ((iter->user_data6 + 5) > endbuf) { return NULL; } memcpy(&array_len, iter->user_data6, sizeof array_len); array_len = GINT_FROM_LE(array_len); if ((iter->user_data6 + array_len) > endbuf) { return NULL; } buffer = iter->user_data6; return mongo_bson_new_from_data(buffer, array_len); } if (type == MONGO_BSON_ARRAY) { g_warning("Current key is not an array."); } else if (type == MONGO_BSON_DOCUMENT) { g_warning("Current key is not a document."); } else { g_assert_not_reached(); } return NULL; }
static gboolean mongo_message_query_load_from_data (MongoMessage *message, const guint8 *data, gsize data_len) { MongoMessageQueryPrivate *priv; MongoMessageQuery *query = (MongoMessageQuery *)message; const gchar *name; MongoBson *bson; guint32 vu32; ENTRY; g_assert(MONGO_IS_MESSAGE_QUERY(query)); g_assert(data); g_assert(data_len); priv = query->priv; if (data_len > 4) { /* Query flags */ memcpy(&vu32, data, sizeof vu32); priv->flags = GUINT32_FROM_LE(vu32); data_len -= 4; data += 4; /* Walk through collection name */ for (name = (gchar *)data; data_len && *data; data_len--, data++) { } if (data_len) { mongo_message_query_set_collection(query, name); data_len--; data++; /* Skipped documents */ if (data_len > 4) { memcpy(&vu32, data, sizeof vu32); mongo_message_query_set_skip(query, GUINT32_FROM_LE(vu32)); data_len -= 4; data += 4; /* Maximum return documents */ if (data_len > 4) { memcpy(&vu32, data, sizeof vu32); mongo_message_query_set_limit(query, GUINT32_FROM_LE(vu32)); data_len -= 4; data += 4; /* Query BSON document */ if (data_len > 4) { memcpy(&vu32, data, sizeof vu32); vu32 = GUINT32_FROM_LE(vu32); if (data_len >= vu32) { bson = mongo_bson_new_from_data(data, vu32); mongo_message_query_take_query(query, bson); data_len -= vu32; data += vu32; /* Fields bson document */ if (data_len > 4) { memcpy(&vu32, data, sizeof vu32); vu32 = GUINT32_FROM_LE(vu32); if (data_len >= vu32) { bson = mongo_bson_new_from_data(data, vu32); mongo_message_query_take_fields(query, bson); data_len -= vu32; data += vu32; } } RETURN(data_len == 0); } } } } } } RETURN(FALSE); }
static gboolean mongo_message_update_load_from_data (MongoMessage *message, const guint8 *data, gsize length) { MongoMessageUpdate *update = (MongoMessageUpdate *)message; const gchar *name; MongoBson *bson; guint32 v32; ENTRY; g_assert(MONGO_IS_MESSAGE_UPDATE(update)); g_assert(data); g_assert(length); if (length >= 4) { /* First 4 bytes are ZERO, reserved for future. */ length -= 4; data += 4; if (length >= 1) { /* Walk through collection name */ for (name = (gchar *)data; length && *data; length--, data++) { } if (length) { mongo_message_update_set_collection(update, name); length--; data++; /* Update flags */ if (length >= 4) { memcpy(&v32, data, sizeof v32); mongo_message_update_set_flags(update, GUINT32_FROM_LE(v32)); length -= 4; data += 4; /* Query BSON */ if (length >= 4) { memcpy(&v32, data, sizeof v32); v32 = GUINT32_FROM_LE(v32); if (v32 <= length) { if ((bson = mongo_bson_new_from_data(data, v32))) { mongo_message_update_set_query(update, bson); mongo_bson_unref(bson); length -= v32; data += v32; /* Update BSON */ if (length >= 4) { memcpy(&v32, data, sizeof v32); v32 = GUINT32_FROM_LE(v32); if (v32 <= length) { if ((bson = mongo_bson_new_from_data(data, v32))) { mongo_message_update_set_update(update, bson); mongo_bson_unref(bson); length -= v32; data += v32; RETURN(length == 0); } } } } } } } } } } RETURN(FALSE); }