Chinaunix首页 | 论坛 | 博客
  • 博客访问: 563477
  • 博文数量: 104
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1559
  • 用 户 组: 普通用户
  • 注册时间: 2014-08-21 00:58
个人简介

锻炼精神,首先要锻炼肉体

文章分类

全部博文(104)

文章存档

2018年(1)

2016年(1)

2015年(101)

2014年(1)

我的朋友

分类: C/C++

2015-04-26 09:48:55

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 脚本)
  

点击(此处)折叠或打开

  1. #!/bin/sh

  2. autoscan
  3. aclocal
  4. autoconf
  5. autoheader
  6. automake --add-missing
  7. ./configure CXXFLAGS= CFLAGS=
  8. make
2. configure.scan 修改之后更名为 ---> configure.in
   configure.in    

点击(此处)折叠或打开

  1. # -*- Autoconf -*-
  2. # Process this file with autoconf to produce a configure script.
  3. #AC_PREREQ([2.63])
  4. #modified by Aimer :
  5. #this line means final executable file name , it can be considered
  6. #as the project name
  7. AC_INIT(Bson_Test)
  8. #add by Aimer :
  9. #this line means in this project I will add third party libs
  10. #such as bson , boost and so on
  11. AC_USE_SYSTEM_EXTENSIONS
  12. #add by Aimer :AM_INIT_AUTOMAKE( executable file name , version number )
  13. AM_INIT_AUTOMAKE(Bson_Test,1.0)
  14. AC_CONFIG_SRCDIR([Main.cpp])
  15. AC_CONFIG_HEADERS([config.h])
  16. # Checks for programs.
  17. AC_PROG_CXX
  18. # add by Aimer
  19. AC_PROG_CC

  20. #modified by Aimer
  21. AC_OUTPUT(Makefile)
3. Makefile.am 

点击(此处)折叠或打开

  1. AUTOMAKE_OPTIONS=foreign
  2. bin_PROGRAMS=Bson_Test----------------------------------> 最终生成的可执行文件的名称,运行方式 ./Bson_Test
  3. BSON_SRC_PATH=/unixC/Bson/bson/src
  4. BOOST_LIB_PATH=/unixC/Boost/boost_1_58_0
  5. #what source files Bson_Test needs ?
  6. Bson_Test_SOURCES=\
  7. Main.cpp \
  8. $(BSON_SRC_PATH)/bsonobj.cpp $(BSON_SRC_PATH)/util/json.cpp \
  9. $(BSON_SRC_PATH)/oid.cpp $(BSON_SRC_PATH)/lib/base64.cpp \
  10. $(BSON_SRC_PATH)/lib/md5.cpp $(BSON_SRC_PATH)/lib/nonce.cpp
  11. Bson_Test_CXXFLAGS=\
  12. -I$(BOOST_LIB_PATH) -I$(BSON_SRC_PATH) -D_FILE_OFFSET_BITS=64 \
  13. -ggdb -Wall -O0
  14. Bson_Test_LDADD=\
  15. -lpthread -lm -lboost_system -lboost_thread \
  16. -lboost_thread -lboost_program_options -lrt
  17. Bson_Test_LDFLAGS=\
  18. -fPIC -rdynamic -L$(BOOST_LIB_PATH)/stage/lib -pthread
4. Main.cpp (测试文件 1)

点击(此处)折叠或打开

  1. #include <cstdio>
  2. #include <bson.h>
  3. #include <iostream>
  4. #include <vector>

  5. using namespace std ;
  6. using namespace bson ;

  7. void iter ( bo o )
  8. {
  9.   // iterator example
  10.   cout << "\niter()\n";

  11.   for ( bo::iterator i(o) ; i.more() ;)
  12.   {
  13.     cout << ' '<< i.next().toString() << endl ;
  14.   }
  15. }

  16. int main ( int argc ,char **argv )
  17. {
  18.   BufBuilder bson(1) ;
  19.   bson.appendStr("hello Aimer") ;

  20.   cout<<bson.buf() << endl ;
  21.   cout<< bson.len() << endl;
  22.   printf ("hello Aimer \n") ;

  23.   cout <<"------bson tests----------"<<endl ;
  24.  
  25.   cout << "build bits : " << 8*sizeof(char *) << endl ;
  26.   
  27.   // a bson object defaults on construction to {}
  28.   
  29.   bo empty ;
  30.   
  31.   cout << "empty: " << empty << endl ;
  32.   
  33.    // make a simple {name :'joe', age: 33.7} object
  34.    {
  35.     bob b ;
  36.     b.append("name","joe") ;
  37.     b.append("age", 33.7) ;
  38.         b.obj () ;
  39.    }
  40.      
  41.   // make {name : 'joe' , age: 33.7 } with a more compact notation
  42.   bo x = bob().append("name","joe").append("age",33.7).obj() ;
  43.   
  44.   // convert from bson to json
  45.   string json = x.toString () ;
  46.   cout << "json for x :"<< json << endl ;
  47.   
  48.  // access some fields of bson object x
  49.   cout << "Some x things : " << x["name"]<< ' ' << x["age"].Number() <<' '<<endl;
  50.   cout << " is x empty : " << x.isEmpty () << endl ;
  51.  

  52. // test BSONObj
  53.   string line ;
  54.   char data[0] ;
  55.   

  56.   cout << "-------test BSONObj ---------"<<endl ;
  57.   cout << "input message "<< endl ;
  58.   cin >> line ;
  59.   
  60.   cout << "line.size = "<< line.size() << endl ;
  61.   memcpy (&data[0] , line.c_str() , line.size()) ;
  62.   bson::BSONObj bsonData = bson::BSONObj( &data[0] ) ;
  63.   
  64.     cout << &(data[0]) << endl ;

  65.   return 0;
  66. }
5. Main.cpp (测试文件 2)

点击(此处)折叠或打开

  1. #include <cstdio>
  2. #include <bson.h>
  3. #include <iostream>
  4. #include <vector>

  5. using namespace std ;
  6. using namespace bson ;

  7. typedef struct msg
  8. {
  9.   int len ;
  10.   char data[0] ;
  11. } msg_t ;


  12. int main ( int argc , char ** argv )
  13. {
  14.   string line ;
  15.   BSONObjBuilder builder ;

  16.   cout << "input message "<<endl ;
  17.   cin >> line ;

  18.   builder.append ("line size", (int)line.size()) ;
  19.   builder.append ("file content", line.c_str()) ;

  20.   BSONObj key = builder.obj() ;
  21.   cout << key.toString() << endl ;
  22.   return 0 ;
  23. }
6. Main.cpp (测试文件 3) 

点击(此处)折叠或打开

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <bson.h>

  5. using namespace std ;
  6. using namespace bson ;

  7. enum MSG_TYPE
  8. {
  9.   request = 0 ,
  10.   response
  11. } ;

  12. typedef struct msg_header
  13. {
  14.   int type ;
  15.   int len ;
  16. }msg_header_t ;


  17. typedef struct msg
  18. {
  19.   msg_header_t msg_header ;
  20.   char data[0] ;
  21. } msg_t ;

  22. int main ( int argc , char ** argv )
  23. {
  24. // first we test how to parse message into the BSONObj object
  25. // data message from string -> char data[0] -> BSONObjBuilder -> BSONObj

  26. // here i tried to use &data[0] as the const char * to initialize BSONObj
  27. // but overflow error happened each time (cry),so I chosoe another way  

  28.     string line ;
  29.     char *pBuffer = NULL ;
  30.     msg_t *message = NULL ;
  31.     int len = (int)sizeof(msg_t);    
  32.     
  33.     BSONObjBuilder bsonBuilder ;
  34.     BSONObj bsonObj ;
  35. cout << "extract message data(content) from char * to BSONObj " << endl ;


  36.     cout << "input message content "<< endl ;
  37.     cin >> line ;
  38.     len += line.size ()+1 ;

  39.         pBuffer = (char*)malloc(len * sizeof(char)) ;
  40.     message = (msg_t*)(pBuffer) ;

  41.     message->msg_header.type = 0;
  42.     message->msg_header.len = len ;
  43.     
  44.     memcpy( &message->data[0] , line.c_str () , line.size( ) ) ;
  45.     message->data[line.size()] = '\0' ;
  46.     
  47.     cout << &message->data[0] << endl ;

  48.     bsonBuilder.append("request message data", &message->data[0] ) ;
  49.     
  50.     bsonObj = bsonBuilder.obj () ;

  51.     cout << bsonObj.objsize() << endl ;

  52. // this can not be parsed by std::cout , only out put '%'
  53. //    cout << bsonObj.objdata() << endl ;

  54.     cout << bsonObj.toString() << endl ;    
  55.         
  56. // second we test how to build message by message length and message data
  57. // message data is stored in BSONObj
  58. // data from BSONObj -> char data[0]

  59. cout << "build a message , message data from BSONObj" << endl ;
  60.     msg_t *message2 = NULL ;
  61.     int msg_len = sizeof(msg_t) ;
  62.         
  63.     if ( bsonObj.objsize() != 0 )
  64.         msg_len += bsonObj.objsize ()+1 ;
  65.     
  66.     pBuffer = (char*)malloc(msg_len * sizeof(char)) ;
  67.     
  68.     message2 = (msg_t*)pBuffer ;
  69.     
  70.     message2->msg_header.len = msg_len ;
  71.     message2->msg_header.type = 0 ;
  72.     
  73.     if ( bsonObj.objsize() != 0 )
  74.      memcpy ( &message2->data[0] , bsonObj.objdata () , bsonObj.objsize() ) ;
  75.     
  76.     message2->data[bsonObj.objsize()] = '\0' ;    

  77.     
  78.     BSONObj obj2 = BSONObj (&message2->data[0]);
  79.     
  80.     cout << obj2.objsize () << endl ;
  81.     cout << obj2.toString() << endl ;
  82.     
  83.     return 0 ;
  84. }
end
阅读(4814) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~