当前位置: 首页 > 工具软件 > Libbson > 使用案例 >

libbson's append functions

郎诚
2023-12-01

前言

mongoc中, 要操作的数据都是bson_t.
bson_t的数据填充要使用mongoc的append系列函数.
bson_t中可以插入很复杂的数据结构, 可以用插入单个元素和插入数组来完成.
插入单个元素时, 用BSON_APPEND_X或bson_append_x
插入数组时, 用bson_append_array_begin和bson_append_array_end, 在begin和end之间, 插入单个元素.
结合mongoc的在线帮助和mongoc源码做了试验.

记录

#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <cstddef>

#include "MongoDbEx.h"
#include "BusinessLogic.h"

int testcase_mongoc_example_command_simple(int argc, char* argv[]);
int testcase_mongoc_example_document(int argc, char* argv[]);

int main(int argc, char* argv[])
{
    printf("============================================================\n");
    printf(">> testcase v1.0.0.5\n");
    printf("============================================================\n");
    testcase_mongoc_example_document(argc, argv);
    // testcase_mongoc_example_command_simple(argc, argv);
    printf("============================================================\n");
    printf("END\n");
    printf("============================================================\n");
    return 0;
}

int testcase_mongoc_example_document(int argc, char* argv[])
{
    TAG_PERSON_INFO person;
    bson_t* document = NULL;
    memset(&person, sizeof(person), 0);
    person.birthday.tm_year = 1973 - 1900; // base 1900
    person.birthday.tm_mon = 4;
    person.birthday.tm_mday = 1;
    person.name.first = "lostspeed";
    person.name.last = "cn";
    person.skillAry[0] = "C";
    person.skillAry[1] = "C++";
    person.skillAry[2] = "MASM";
    person.skillAry[3] = "RE";
    person.skillAry[4] = NULL; // !

    person.degreeAry[0].degree = "graduates";
    person.degreeAry[0].school = "zhongnian";
    person.degreeAry[1].degree = "graduates";
    person.degreeAry[1].school = "cr";
    person.degreeAry[2].degree = NULL; // !
    person.degreeAry[2].school = NULL; // !

    document = bson_new();
    fill_TAG_PERSON_INFO(document, &person);
    // use document ...
    ShowDocument("person", document);
    /**
    [person] { 
        "name" : { "first" : "lostspeed", "last" : "cn" }, 
        "birthday" : { "$date" : 105087610000 }, 
        "skill" : [ "C", "C++", "MASM", "RE" ], 
        "degrees" : [ 
            { "school" : "zhongnian", "degree" : "graduates" }, 
            { "school" : "cr", "degree" : "graduates" } ] 
            }
    */
    bson_destroy(document);
    return 0;
}

int testcase_mongoc_example_command_simple(int argc, char* argv[])
{
    mongoc_client_t* client = NULL;
    mongoc_database_t* database = NULL;
    mongoc_collection_t* collection = NULL;
    bson_t* insert = NULL;
    bson_error_t error;
    bool retval = false;
    mongoc_init();
    client = mongoc_client_new("mongodb://localhost:27017");
    /*
     * Register the application name so we can track it in the profile logs
     * on the server. This can also be done from the URI (see other examples).
     */
    mongoc_client_set_appname(client, "connect-example");
    database = mongoc_client_get_database(client, "db_name");
    collection = mongoc_client_get_collection(client, "db_name", "coll_name");
    // cmd :  ping
    retval = DbOptExec_command_simple(client, "admin", "ping", &error);

    if (!retval) {
        ShowErrMsg("ping", &error);
        return EXIT_FAILURE;
    }

    /**
    [ping] { "ok" : 1.0 }
    */
    insert = BCON_NEW("hello", BCON_UTF8("world"));

    if (!mongoc_collection_insert(
                collection, MONGOC_INSERT_NONE, insert, NULL, &error)) {
        ShowErrMsg("mongoc_collection_insert", &error);
    }

    // cmd : buildinfo
    bson_destroy(insert);
    retval = DbOptExec_command_simple(client, "admin", "buildinfo", &error);

    if (!retval) {
        ShowErrMsg("buildinfo", &error);
    }

    /**
    [buildinfo] {
        "version" : "2.6.10",
        "gitVersion" : "5901dbfb49d16eaef6f2c2c50fba534d23ac7f6c",
        "OpenSSLVersion" : "",
        "sysInfo" : "Linux build18.nj1.10gen.cc 2.6.32-431.3.1.el6.x86_64 #1 SMP Fri Jan 3 21:39:27 UTC 2014 x86_64 BOOST_LIB_VERSION=1_49",
        "loaderFlags" : "-fPIC -pthread -Wl,-z,now -rdynamic",
        "compilerFlags" : "-Wnon-virtual-dtor -Woverloaded-virtual -fPIC -fno-strict-aliasing -ggdb -pthread -Wall -Wsign-compare -Wno-unknown-pragmas -Winvalid-pch -pipe -Werror -O3 -Wno-unused-function -Wno-deprecated-declarations -fno-builtin-memcmp",
        "allocator" : "tcmalloc",
        "versionArray" : [ 2, 6, 10, 0 ],
        "javascriptEngine" : "V8",
        "bits" : 64,
        "debug" : false,
        "maxBsonObjectSize" : 16777216,
        "ok" : 1.0 }
    */
    // cmd : serverStatus
    retval = DbOptExec_command_simple(client, "admin", "serverStatus", &error);

    if (!retval) {
        ShowErrMsg("serverStatus", &error);
    }

    /**
    [serverStatus]
    {
    "host" : "debian",
    "version" : "2.6.10",
    "process" : "mongod",
    "pid" : 3243,
    "uptime" : 21899.0,
    "uptimeMillis" : 21897854,
    "uptimeEstimate" : 19920.0,
    "localTime" : { "$date" : 1491227764737 },
    "asserts" : { "regular" : 0, "warning" : 0, "msg" : 0, "user" : 0, "rollovers" : 0 },
    "backgroundFlushing" : { "flushes" : 364, "total_ms" : 54, "average_ms" : 0.14835164835164835195, "last_ms" : 0, "last_finished" : { "$date" : 1491227708337 } },
    "connections" : { "current" : 1, "available" : 818, "totalCreated" : 9 },
    "cursors" : { "note" : "deprecated, use server status metrics", "clientCursors_size" : 0, "totalOpen" : 0, "pinned" : 0, "totalNoTimeout" : 0, "timedOut" : 0 },
    "dur" : { "commits" : 29, "journaledMB" : 0.0, "writeToDataFilesMB" : 0.0, "compression" : 0.0, "commitsInWriteLock" : 0, "earlyCommits" : 0,
    "timeMs" : { "dt" : 3044, "prepLogBuffer" : 0, "writeToJournal" : 0, "writeToDataFiles" : 0, "remapPrivateView" : 0 } },
    "extra_info" : { "note" : "fields vary by platform", "heap_usage_bytes" : 62725408, "page_faults" : 98 },
    "globalLock" : { "totalTime" : 21897856000, "lockTime" : 5334268,
    "currentQueue" : { "total" : 0, "readers" : 0, "writers" : 0 },
    "activeClients" : { "total" : 0, "readers" : 0, "writers" : 0 } },
    "indexCounters" : { "accesses" : 19, "hits" : 19, "misses" : 0, "resets" : 0, "missRatio" : 0.0 },
    "locks" : { "." : {
    "timeLockedMicros" : { "R" : 435761, "W" : 5334268 },
    "timeAcquiringMicros" : { "R" : 4899977, "W" : 2994540 } },
    "admin" : { "timeLockedMicros" : { "r" : 151982, "w" : 0 },
    "timeAcquiringMicros" : { "r" : 369253, "w" : 0 } },
    "local" : { "timeLockedMicros" : { "r" : 128739, "w" : 83 }, "timeAcquiringMicros" : { "r" : 54838, "w" : 1 } },
    "testdb" : { "timeLockedMicros" : { "r" : 2081468, "w" : 130 }, "timeAcquiringMicros" : { "r" : 19698, "w" : 3 } },
    "mongodb" : { "timeLockedMicros" : { "r" : 191151, "w" : 128 }, "timeAcquiringMicros" : { "r" : 30413, "w" : 4 } },
    "db_name" : { "timeLockedMicros" : { "r" : 375654, "w" : 908 }, "timeAcquiringMicros" : { "r" : 14419, "w" : 40 } },
    "Barca" : { "timeLockedMicros" : { "r" : 158307, "w" : 134 }, "timeAcquiringMicros" : { "r" : 19699, "w" : 3 } },
    "dbs" : { "timeLockedMicros" : { "r" : 610389, "w" : 224 }, "timeAcquiringMicros" : { "r" : 17663, "w" : 6 } },
    "test1" : { "timeLockedMicros" : { "r" : 829203, "w" : 28 }, "timeAcquiringMicros" : { "r" : 15951, "w" : 2 } },
    "yekai" : { "timeLockedMicros" : { "r" : 2065973, "w" : 269 }, "timeAcquiringMicros" : { "r" : 61179, "w" : 4 } },
    "tutorial" : { "timeLockedMicros" : { "r" : 1491259, "w" : 157 }, "timeAcquiringMicros" : { "r" : 28555, "w" : 3 } } },
    "network" : { "bytesIn" : 5730, "bytesOut" : 13310, "numRequests" : 44 },
    "opcounters" : { "insert" : 9, "query" : 3641, "update" : 0, "delete" : 0, "getmore" : 0, "command" : 38 },
    "opcountersRepl" : { "insert" : 0, "query" : 0, "update" : 0, "delete" : 0, "getmore" : 0, "command" : 0 },
    "recordStats" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0,
    "Barca" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
    "admin" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
    "db_name" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
    "dbs" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
    "local" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
    "mongodb" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
    "test1" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
    "testdb" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
    "tutorial" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
    "yekai" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 } },
    "writeBacksQueued" : false,
    "mem" : { "bits" : 64, "resident" : 158, "virtual" : 62683, "supported" : true, "mapped" : 31251, "mappedWithJournal" : 62502 },
    "metrics" : { "cursor" : { "timedOut" : 0, "open" : { "noTimeout" : 0, "pinned" : 0, "total" : 0 } },
    "document" : { "deleted" : 0, "inserted" : 9, "returned" : 0, "updated" : 0 },
    "getLastError" : { "wtime" : { "num" : 0, "totalMillis" : 0 }, "wtimeouts" : 0 },
    "operation" : { "fastmod" : 0, "idhack" : 0, "scanAndOrder" : 0 },
    "queryExecutor" : { "scanned" : 0, "scannedObjects" : 0 },
    "record" : { "moves" : 0 },
    "repl" : {
    "apply" : { "batches" : { "num" : 0, "totalMillis" : 0 }, "ops" : 0 },
    "buffer" : { "count" : 0, "maxSizeBytes" : 268435456, "sizeBytes" : 0 },
    "network" : { "bytes" : 0, "getmores" : { "num" : 0, "totalMillis" : 0 }, "ops" : 0, "readersCreated" : 0 },
    "preload" : { "docs" : { "num" : 0, "totalMillis" : 0 }, "indexes" : { "num" : 0, "totalMillis" : 0 } } },
    "storage" : { "freelist" : { "search" : { "bucketExhausted" : 0, "requests" : 8, "scanned" : 16 } } },
    "ttl" : { "deletedDocuments" : 0, "passes" : 364 } },
    "ok" : 1.0 }
    */
    // cmd : ismaster
    retval = DbOptExec_command_simple(client, "admin", "ismaster", &error);

    if (!retval) {
        ShowErrMsg("ismaster", &error);
    }

    /**
    [ismaster] {
        "ismaster" : true,
        "maxBsonObjectSize" : 16777216,
        "maxMessageSizeBytes" : 48000000,
        "maxWriteBatchSize" : 1000,
        "localTime" : { "$date" : 1491230240360 },
        "maxWireVersion" : 2,
        "minWireVersion" : 0,
        "ok" : 1.0
        }
    */
    // cmd : getlasterror
    retval = DbOptExec_command_simple(client, "admin", "getlasterror", &error);

    if (!retval) {
        ShowErrMsg("getlasterror", &error);
    }

    /**
    [getlasterror] {
        "connectionId" : 11,
        "n" : 0,
        "syncMillis" : 0,
        "writtenTo" : null,
        "err" : null,
        "ok" : 1.0
        }
    */
    // cmd : foo
    retval = DbOptExec_command_simple(client, "admin", "foo", &error);

    if (!retval) {
        ShowErrMsg("foo", &error);
    }

    /**
    [foo] error : no such cmd: foo
    */
    // cmd : empty
    // 空命令会报错的
    //     retval = DbOptExec_command_simple(client, "admin", "{}", &error);
    //
    //     if (!retval) {
    //         ShowErrMsg("{}", &error);
    //     }
    // cmd : empty
    retval = DbOptExec_command_simple(client, "admin", "", &error);

    if (!retval) {
        ShowErrMsg("", &error);
    }

    /**
    [] error : no such cmd:
    */
    // cmd : db
    retval = DbOptExec_command_simple(client, "admin", "db", &error);

    if (!retval) {
        ShowErrMsg("db", &error);
    }

    /**
    [db] error : no such cmd: db
    */
    /**
    MongoDB shell version: 2.6.10
    connecting to: test
    > show dbs
    Barca      0.078GB
    admin      0.078GB
    db_name    0.078GB
    local      0.078GB
    mongodb    0.078GB
    test1      0.078GB
    testdb     0.078GB
    tutorial   0.078GB
    yekai      7.950GB
    >

      > use test1
      switched to db test1
      > show collections
      system.indexes
      test1
      >
    */
    // cmd : "{'drop': '%s'}"
    retval = DbOptExec_command_simple(client, "admin", "use", "test1", &error);

    if (!retval) {
        ShowErrMsg("use test1", &error);
    }

    /**
    [use test1] error : no such cmd: use
    */
    retval = DbOptExec_command_simple(client, "test1", "drop", "test1", &error);

    if (!retval) {
        ShowErrMsg("drop test1", &error);
    }

    /**
    [drop] { "ns" : "test1.test1", "nIndexesWas" : 1, "ok" : 1.0 }
    */
    /** mongo console
    > use test1
    switched to db test1
    > show collections
    system.indexes
    >
    */
    // cmd : getCmdLineOpts
    retval = DbOptExec_command_simple(client, "admin", "getCmdLineOpts", &error);

    if (!retval) {
        ShowErrMsg("getCmdLineOpts", &error);
    }

    /**
    [getCmdLineOpts] {
        "argv" : [ "\/usr\/local\/mongodb\/bin\/mongod", "--config", "\/usr\/local\/mongodb\/bin\/mongodb.conf" ],
        "parsed" : {
            "config" : "\/usr\/local\/mongodb\/bin\/mongodb.conf",
            "net" : { "http" : { "enabled" : false }, "port" : 27017 },
            "processManagement" : { "fork" : true },
            "storage" : { "dbPath" : "\/usr\/local\/mongodb\/db" },
            "systemLog" : { "destination" : "file", "path" : "\/usr\/local\/mongodb\/logs\/mongodb.log" }
            },
        "ok" : 1.0
        }
    */
    mongoc_collection_destroy(collection);
    mongoc_database_destroy(database);
    mongoc_client_destroy(client);
    mongoc_cleanup();
    return 0;
}
// BusinessLogic.h: interface for the BusinessLogic class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_BUSINESSLOGIC_H__91436BA7_97DD_495E_A750_A141145804E1__INCLUDED_)
#define AFX_BUSINESSLOGIC_H__91436BA7_97DD_495E_A750_A141145804E1__INCLUDED_

#include <bson.h>
#include <bcon.h>
#include <mongoc.h>

#ifndef BOOL
typedef bool BOOL;
#define TRUE 1
#define FALSE 0
#endif // #ifndef BOOL

typedef struct _tag_name {
    const char* first;
    const char* last;
} TAG_NAME;

typedef struct _tag_degress {
    const char* school;
    const char* degree;
} TAG_DEGRESS;

typedef struct _tag_person_info {
    TAG_NAME name;
    struct tm birthday;
    const char* skillAry[10];
    TAG_DEGRESS degreeAry[10];
} TAG_PERSON_INFO;

void fill_TAG_PERSON_INFO(bson_t* document, TAG_PERSON_INFO* person);
#endif // !defined(AFX_BUSINESSLOGIC_H__91436BA7_97DD_495E_A750_A141145804E1__INCLUDED_)
// BusinessLogic.cpp: implementation of the BusinessLogic class.
//
//////////////////////////////////////////////////////////////////////

#include "BusinessLogic.h"

void fill_TAG_PERSON_INFO(bson_t* document, TAG_PERSON_INFO* person)
{
    int i = 0;
    int iArySize = 0;
    bson_t child;
    bson_t child2;
    const char* key = NULL;
    size_t keylen = 0;
    char buf[32] = {'\0'};

    if ((NULL == document) || (NULL == person)) {
        return;
    }

    bson_append_document_begin(document, "name", -1, &child);
    BSON_APPEND_UTF8(&child, "first", person->name.first);
    BSON_APPEND_UTF8(&child, "last", person->name.last);
    bson_append_document_end(document, &child);
    BSON_APPEND_DATE_TIME(document, "birthday", mktime(&person->birthday) * 1000);
    bson_append_array_begin(document, "skill", -1, &child);
    iArySize = sizeof(person->skillAry) / sizeof(char*);

    for (i = 0; i < iArySize; i++) {
        if (NULL == person->skillAry[i]) {
            break;
        }

        keylen = bson_uint32_to_string(i + 1, &key, buf, sizeof buf);
        bson_append_utf8(&child, key, (int) keylen, person->skillAry[i], -1);
    }

    bson_append_array_end(document, &child);
    bson_append_array_begin(document, "degrees", -1, &child);
    iArySize = sizeof(person->degreeAry) / sizeof(TAG_DEGRESS);

    for (i = 0; i < iArySize; i++) {
        if ((NULL == person->degreeAry[i].degree) || (NULL == person->degreeAry[i].school)) {
            break;
        }

        bson_append_document_begin(&child, "", -1, &child2);
        bson_append_utf8(&child2, "school", -1, person->degreeAry[i].school, -1);
        bson_append_utf8(&child2, "degree", -1, person->degreeAry[i].degree, -1);
        bson_append_document_end(&child, &child2);
    }

    bson_append_array_end(document, &child);
}
// @file MongoDbEx.h
// @brief MongoDB operation

#ifndef __MONGODB_EX__
#define __MONGODB_EX__

#include <bson.h>
#include <bcon.h>
#include <mongoc.h>

#ifndef BOOL
typedef bool BOOL;
#define TRUE 1
#define FALSE 0
#endif // #ifndef BOOL

BOOL DbOptInit();
BOOL DbOptUnInit();

mongoc_client_t* DbOptOpenConect(const char* pConnectUrl);
void DbOptCloseConect(mongoc_client_t*& pDbConnect);

mongoc_database_t* DbOptOpenDb(mongoc_client_t* pDbConnect, const char* pDbName);
void DbOptCloseDb(mongoc_database_t*& pDb);

mongoc_collection_t* DbOptOpenTbl(mongoc_database_t* pDb, const char* pTblName);
void DbOptCloseTbl(mongoc_collection_t*& pTbl);

bool DbOptExec_command_simple(
    mongoc_client_t* pClient,
    const char* pcDbName,
    const char* pcCommand,
    bson_error_t* pError);
bool DbOptExec_command_simple(
    mongoc_client_t* pClient,
    const char* pcDbName,
    const char* pcCommand,
    const char* pcValue,
    bson_error_t* pError);
void ShowErrMsg(const char* pTip, bson_error_t* error);
void ShowReply(const char* pTip, bson_t* reply);
void ShowDocument(const char* pTip, bson_t* document);
bson_t* new_formatv_bson(const char* json, ...);
char* single_quotes_to_double(const char* str);

#endif // #ifndef __MONGODB_EX__
// @file MongoDbEx.cpp
// @brief ...

#include "MongoDbEx.h"

BOOL DbOptInit()
{
    mongoc_init();
}

BOOL DbOptUnInit()
{
    mongoc_cleanup();
}

mongoc_client_t* DbOptOpenConect(const char* pConnectUrl)
{
    mongoc_client_t* pDbClient = NULL;

    if (NULL != pConnectUrl) {
        pDbClient = mongoc_client_new(pConnectUrl);
    }

    return pDbClient;
}

void DbOptCloseConect(mongoc_client_t*& pDbConnect)
{
    if (NULL != pDbConnect) {
        mongoc_client_destroy(pDbConnect);
        pDbConnect = NULL;
    }
}

mongoc_database_t* DbOptOpenDb(mongoc_client_t* pDbConnect, const char* pDbName)
{
    mongoc_database_t* pDb = NULL;

    if (NULL != pDbConnect) {
        pDb = mongoc_client_get_database(pDbConnect, pDbName);
    }

    return pDb;
}

void DbOptCloseDb(mongoc_database_t*& pDb)
{
    if (NULL != pDb) {
        mongoc_database_destroy(pDb);
        pDb = NULL;
    }
}

mongoc_collection_t* DbOptOpenTbl(mongoc_database_t* pDb, const char* pTblName)
{
    mongoc_collection_t* pTbl = NULL;
    pTbl = mongoc_database_get_collection(pDb, pTblName);
    return pTbl;
}

void DbOptCloseTbl(mongoc_collection_t*& pTbl)
{
    if (NULL != pTbl) {
        mongoc_collection_destroy(pTbl);
        pTbl = NULL;
    }
}

bool DbOptExec_command_simple(
    mongoc_client_t* pClient,
    const char* pcDbName,
    const char* pcCommand,
    bson_error_t* pError)
{
    bool retval = false;
    bson_t* command = NULL;
    bson_t reply;

    do {
        command = BCON_NEW(pcCommand, BCON_INT32(1));
        // mongoc_client_command_simple 作用: 让mongodb执行一些命令, 返回一些结果
        retval = mongoc_client_command_simple(pClient, pcDbName, command, NULL, &reply, pError);

        if (!retval) {
            break;
        } else {
            ShowReply(pcCommand, &reply);
        }
    } while (0);

    bson_destroy(&reply);
    bson_destroy(command);
    return retval;
}

bool DbOptExec_command_simple(
    mongoc_client_t* pClient,
    const char* pcDbName,
    const char* pcCommand,
    const char* pcValue,
    bson_error_t* pError)
{
    bool retval = false;
    bson_t reply;
    bson_t* doc = NULL;
    char* sz_cmd = NULL;

    do {
        // mongoc_client_command_simple 作用: 让mongodb执行一些命令, 返回一些结果
        sz_cmd = bson_strdup_printf("{'%s': '%s'}", pcCommand, pcValue);
        doc = new_formatv_bson("%s", sz_cmd);
        retval = mongoc_client_command_simple(pClient, pcDbName, doc, NULL, &reply, pError);
        bson_free(sz_cmd);

        if (!retval) {
            break;
        } else {
            ShowReply(pcCommand, &reply);
        }
    } while (0);

    bson_destroy(&reply);
    bson_destroy(doc);
    return retval;
}

void ShowErrMsg(const char* pTip, bson_error_t* error)
{
    if (NULL != error) {
        fprintf(stderr, "[%s] error : %s\n\n", (NULL != pTip) ? pTip : "", error->message);
    }
}

void ShowReply(const char* pTip, bson_t* reply)
{
    char* str = NULL;

    if (NULL != reply) {
        str = bson_as_json(reply, NULL);

        if (NULL != str) {
            printf("[%s] %s\n\n", (NULL != pTip) ? pTip : "", str);
            bson_free(str);
        }
    }
}

void ShowDocument(const char* pTip, bson_t* document)
{
    char* str = NULL;

    if (NULL != document) {
        str = bson_as_json(document, NULL);
        if (NULL != str) {
            printf("[%s] %s\n\n", (NULL != pTip) ? pTip : "", str);
            bson_free(str);
        }
    }
}

bson_t* new_formatv_bson(const char* json, ...)
{
    va_list args;
    bson_error_t error;
    char* formatted;
    char* double_quoted;
    bson_t* doc;

    if (json) {
        va_start(args, json);
        formatted = bson_strdupv_printf(json, args);
        va_end(args);
        double_quoted = single_quotes_to_double(formatted);
        doc = bson_new_from_json((const uint8_t*) double_quoted, -1, &error);

        if (!doc) {
            fprintf(stderr, "%s\n", error.message);
            abort();
        }

        bson_free(formatted);
        bson_free(double_quoted);
    } else {
        doc = bson_new();
    }

    return doc;
}

char* single_quotes_to_double(const char* str)
{
    char* result = bson_strdup(str);
    char* p;

    for (p = result; *p; p++) {
        if (*p == '\'') {
            *p = '"';
        }
    }

    return result;
}




 类似资料:

相关阅读

相关文章

相关问答