BSON 库的文档网上资源很少,因为它毕竟是 MongoDB 内部用于数据消息序列化的而开发的子模块。
不过好在它是开源的,通过阅读它的源代码也可学习到它的调用方法。
再加上我们仅仅使用 BSON 来编写消息模块,用到 BSON 的地方并不多,学习来难度就大大减少了。
前文中提到的关于消息的操作可以分为,解析消息、构造消息。
解析消息,数据的流动方向便是从消息 struct message --> BSONObj 中
构造消息,数据的流动方向便是从用户输入 BSONObj --> struct message 中
本篇文章主要介绍 BSONObj 与 BSONObjBuilder、字符串之间的转换方法。
首先通过 2 个小程序来编写简单的 BSONObj 借助于 BSONObjBuilder 和 const char * 的构造方法。
最后的第 3 个程序实现了按步骤执行的消息的构造与解析的调用,暂时还没有将构造、解析方法进行封装到子函数中
运行环境: linux ,
编译工具: gcc, g++ , boost 静态库,
autotools {autoscan , aclocal , autoconf , autoheader ,automake }
在这里我为了编译方便,在工作目录之下每次仅仅保留 Main.cpp ,这样实验使用的 3 个文件,
可以共用同一个 configure.in 和 Makefile.am ,无需为每个Main.cpp 一次创建。
但是每次工作目录下面必须保证只有一个 .cpp 文件,不然 autoscan 会将多个含有 main 入口函数的文件添加到等待编译文件中,
同时编译多个含有 main 函数的文件很有可能会报错。
第一次编译的时候,需要按照前一篇文章中分别改写文件 configure.scan 和创建文件 Makefile.am
后续的编译中只需要编写 build.sh 脚本,每次运行 build.sh 即可
1. build.sh (首次编译,不要调用 build.sh 脚本)
-
#!/bin/sh
-
-
autoscan
-
aclocal
-
autoconf
-
autoheader
-
automake --add-missing
-
./configure CXXFLAGS= CFLAGS=
-
make
2. configure.scan 修改之后更名为 ---> configure.in
configure.in
-
# -*- Autoconf -*-
-
# Process this file with autoconf to produce a configure script.
-
-
#AC_PREREQ([2.63])
-
#modified by Aimer :
-
#this line means final executable file name , it can be considered
-
#as the project name
-
AC_INIT(Bson_Test)
-
-
#add by Aimer :
-
#this line means in this project I will add third party libs
-
#such as bson , boost and so on
-
AC_USE_SYSTEM_EXTENSIONS
-
-
#add by Aimer :AM_INIT_AUTOMAKE( executable file name , version number )
-
AM_INIT_AUTOMAKE(Bson_Test,1.0)
-
-
AC_CONFIG_SRCDIR([Main.cpp])
-
AC_CONFIG_HEADERS([config.h])
-
-
# Checks for programs.
-
AC_PROG_CXX
-
# add by Aimer
-
AC_PROG_CC
-
-
#modified by Aimer
-
AC_OUTPUT(Makefile)
3. Makefile.am
-
AUTOMAKE_OPTIONS=foreign
-
bin_PROGRAMS=Bson_Test----------------------------------> 最终生成的可执行文件的名称,运行方式 ./Bson_Test
-
BSON_SRC_PATH=/unixC/Bson/bson/src
-
BOOST_LIB_PATH=/unixC/Boost/boost_1_58_0
-
-
#what source files Bson_Test needs ?
-
Bson_Test_SOURCES=\
-
Main.cpp \
-
$(BSON_SRC_PATH)/bsonobj.cpp $(BSON_SRC_PATH)/util/json.cpp \
-
$(BSON_SRC_PATH)/oid.cpp $(BSON_SRC_PATH)/lib/base64.cpp \
-
$(BSON_SRC_PATH)/lib/md5.cpp $(BSON_SRC_PATH)/lib/nonce.cpp
-
-
-
Bson_Test_CXXFLAGS=\
-
-I$(BOOST_LIB_PATH) -I$(BSON_SRC_PATH) -D_FILE_OFFSET_BITS=64 \
-
-ggdb -Wall -O0
-
-
-
Bson_Test_LDADD=\
-
-lpthread -lm -lboost_system -lboost_thread \
-
-lboost_thread -lboost_program_options -lrt
-
-
Bson_Test_LDFLAGS=\
-
-fPIC -rdynamic -L$(BOOST_LIB_PATH)/stage/lib -pthread
4. Main.cpp (测试文件 1)
-
#include <cstdio>
-
#include <bson.h>
-
#include <iostream>
-
#include <vector>
-
-
using namespace std ;
-
using namespace bson ;
-
-
void iter ( bo o )
-
{
-
// iterator example
-
cout << "\niter()\n";
-
-
for ( bo::iterator i(o) ; i.more() ;)
-
{
-
cout << ' '<< i.next().toString() << endl ;
-
}
-
}
-
-
int main ( int argc ,char **argv )
-
{
-
BufBuilder bson(1) ;
-
bson.appendStr("hello Aimer") ;
-
-
cout<<bson.buf() << endl ;
-
cout<< bson.len() << endl;
-
printf ("hello Aimer \n") ;
-
-
cout <<"------bson tests----------"<<endl ;
-
-
cout << "build bits : " << 8*sizeof(char *) << endl ;
-
-
// a bson object defaults on construction to {}
-
-
bo empty ;
-
-
cout << "empty: " << empty << endl ;
-
-
// make a simple {name :'joe', age: 33.7} object
-
{
-
bob b ;
-
b.append("name","joe") ;
-
b.append("age", 33.7) ;
-
b.obj () ;
-
}
-
-
// make {name : 'joe' , age: 33.7 } with a more compact notation
-
bo x = bob().append("name","joe").append("age",33.7).obj() ;
-
-
// convert from bson to json
-
string json = x.toString () ;
-
cout << "json for x :"<< json << endl ;
-
-
// access some fields of bson object x
-
cout << "Some x things : " << x["name"]<< ' ' << x["age"].Number() <<' '<<endl;
-
cout << " is x empty : " << x.isEmpty () << endl ;
-
-
-
// test BSONObj
-
string line ;
-
char data[0] ;
-
-
-
cout << "-------test BSONObj ---------"<<endl ;
-
cout << "input message "<< endl ;
-
cin >> line ;
-
-
cout << "line.size = "<< line.size() << endl ;
-
memcpy (&data[0] , line.c_str() , line.size()) ;
-
bson::BSONObj bsonData = bson::BSONObj( &data[0] ) ;
-
-
cout << &(data[0]) << endl ;
-
-
return 0;
-
}
5. Main.cpp (测试文件 2)
-
#include <cstdio>
-
#include <bson.h>
-
#include <iostream>
-
#include <vector>
-
-
using namespace std ;
-
using namespace bson ;
-
-
typedef struct msg
-
{
-
int len ;
-
char data[0] ;
-
} msg_t ;
-
-
-
int main ( int argc , char ** argv )
-
{
-
string line ;
-
BSONObjBuilder builder ;
-
-
cout << "input message "<<endl ;
-
cin >> line ;
-
-
builder.append ("line size", (int)line.size()) ;
-
builder.append ("file content", line.c_str()) ;
-
-
BSONObj key = builder.obj() ;
-
cout << key.toString() << endl ;
-
return 0 ;
-
}
6. Main.cpp (测试文件 3)
-
#include <iostream>
-
#include <cstdio>
-
#include <cstring>
-
#include <bson.h>
-
-
using namespace std ;
-
using namespace bson ;
-
-
enum MSG_TYPE
-
{
-
request = 0 ,
-
response
-
} ;
-
-
typedef struct msg_header
-
{
-
int type ;
-
int len ;
-
}msg_header_t ;
-
-
-
typedef struct msg
-
{
-
msg_header_t msg_header ;
-
char data[0] ;
-
} msg_t ;
-
-
int main ( int argc , char ** argv )
-
{
-
// first we test how to parse message into the BSONObj object
-
// data message from string -> char data[0] -> BSONObjBuilder -> BSONObj
-
-
// here i tried to use &data[0] as the const char * to initialize BSONObj
-
// but overflow error happened each time (cry),so I chosoe another way
-
-
string line ;
-
char *pBuffer = NULL ;
-
msg_t *message = NULL ;
-
int len = (int)sizeof(msg_t);
-
-
BSONObjBuilder bsonBuilder ;
-
BSONObj bsonObj ;
-
cout << "extract message data(content) from char * to BSONObj " << endl ;
-
-
-
cout << "input message content "<< endl ;
-
cin >> line ;
-
len += line.size ()+1 ;
-
-
pBuffer = (char*)malloc(len * sizeof(char)) ;
-
message = (msg_t*)(pBuffer) ;
-
-
message->msg_header.type = 0;
-
message->msg_header.len = len ;
-
-
memcpy( &message->data[0] , line.c_str () , line.size( ) ) ;
-
message->data[line.size()] = '\0' ;
-
-
cout << &message->data[0] << endl ;
-
-
bsonBuilder.append("request message data", &message->data[0] ) ;
-
-
bsonObj = bsonBuilder.obj () ;
-
-
cout << bsonObj.objsize() << endl ;
-
-
// this can not be parsed by std::cout , only out put '%'
-
// cout << bsonObj.objdata() << endl ;
-
-
cout << bsonObj.toString() << endl ;
-
-
// second we test how to build message by message length and message data
-
// message data is stored in BSONObj
-
// data from BSONObj -> char data[0]
-
-
cout << "build a message , message data from BSONObj" << endl ;
-
msg_t *message2 = NULL ;
-
int msg_len = sizeof(msg_t) ;
-
-
if ( bsonObj.objsize() != 0 )
-
msg_len += bsonObj.objsize ()+1 ;
-
-
pBuffer = (char*)malloc(msg_len * sizeof(char)) ;
-
-
message2 = (msg_t*)pBuffer ;
-
-
message2->msg_header.len = msg_len ;
-
message2->msg_header.type = 0 ;
-
-
if ( bsonObj.objsize() != 0 )
-
memcpy ( &message2->data[0] , bsonObj.objdata () , bsonObj.objsize() ) ;
-
-
message2->data[bsonObj.objsize()] = '\0' ;
-
-
-
BSONObj obj2 = BSONObj (&message2->data[0]);
-
-
cout << obj2.objsize () << endl ;
-
cout << obj2.toString() << endl ;
-
-
return 0 ;
-
}
end
阅读(4915) | 评论(0) | 转发(0) |