0

I have documents in a mongo collection which look like: { "f" : [ 283, 180, 284 ], "l":["1","29"] } I am using the mongoDB c driver to fetch these documents and perform some operations on these> I would like to restore element "f" back as an array of integers and the element "l" back as an two multidimensional char array.

while (mongoc_cursor_next (cursor, &doc))
{
    bson_iter_t it;
    bson_iter_init(&it, doc);

    while (bson_iter_next(&it))
    {  
        const char * key=bson_iter_key(&it);
        bson_type_t type=bson_iter_type(&it);
        const uint8_t *data = NULL;
        uint32_t len = 0;
        bson_iter_array (&it, &len, &data);

    }

}

I am not able to figure out how I can extract "f" to int* and "l" to char**. I tried to type cast the pointer (data) to different types but the values are not proper. How do I go about it?

Terminator
  • 117
  • 1
  • 12

1 Answers1

1

There are two ways. 1st, you can convert it to bson, and extract values by keys '1', '2', etc :

bson_t * doc = /*your bson doc*/;
bson_iter_t iter;
bson_iter_init(&iter, doc);

// requesting for f
bson_iter_find(&iter, "f");

const ui8 * data = NULL;
uint32_t len = 0;
bson_iter_array(&iter, &len, &data);

bson_t * fSubArray = bson_new_from_data(data, len);

bson_iter_t fIter;

bson_iter_init(&fIter, fSubArray);

bson_iter_find(&fIter, "0");
bson_iter_int32(&fIter) == 283;

bson_iter_find(&fIter, "1");
bson_iter_int32(&fIter) == 180;

bson_iter_find(&fIter, "2");
bson_iter_int32(&fIter) == 284;

// requesting for l
bson_iter_find(&iter, "l");

const ui8 * data = NULL;
uint32_t len = 0;
bson_iter_array(&iter, &len, &data);

bson_t * fSubArray = bson_new_from_data(data, len);

bson_iter_t fIter;

bson_iter_init(&fIter, fSubArray);

bson_iter_find(&fIter, "0");
strcmp(bson_iter_utf8(&fIter), "1") == 0;

bson_iter_find(&fIter, "1");
strcmp(bson_iter_utf8(&fIter), "29") == 0;

Also, mongoc recommend to use bson_uint32_to_string function for fast string to int converting.

2nd you can acces directly to data from bson_iter_array(&iter, &len, &data), if perfomance of first method isn't clear:

data has next format:

total bytes in data | bson type | string index           | 4 for int32, 1 for char, etc.| bson type | ... | end of data
4 bytes             |   1 byte  | null-terminated string | sizeof(element) bytes        | 1 byte    | ... | \0

so, if you know size of your data , you can access directly to it. But you should consider, that data has net byte order.

for example, if we know, that array is [int32(2), int64(4)], data would be:

4 bytes             | 1 byte          | null-terminated string | sizeof(int32) bytes      | 1 byte          | 1 byte  | sizeof(int64) bytes | \0
23 0 0 0            | 16              | 48 0                   | 2 0 0 0                  | 18              | 49 0    | 4 0 0 0 0 0 0 0     | 0
totaly 23 bytes     | BSON_TYPE_INT32 | "0\0"                  | 2                        | BSON_TYPE_INT64 | "1\0"   | 4                   | end