码迷,mamicode.com
首页 > 其他好文 > 详细

二进制编码与解码容器

时间:2015-10-19 10:43:29      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:

0 背景

   在rpc或分布式节点间的通讯框架里面,我们经常会有“编码或解码业务数据成网络二进制流”的场景要求,在jdk的nio框架里面有既有的ByteBuffer类满足此需求,那么在c++里面,同样我们简单看看具有类似功能的类DataBuffer。  

1 实现基本逻辑

   指针偏移指向同一块内存,分别表示内存的起始与结束偏移位置,分别表示读与写的偏移位置。如下图:  

技术分享

2 操作步骤

   1.1 读取数据时,仅需偏移_pdata即可

       源码如下:

技术分享
    bool readBytes(void *dst, int len) {

        if (_pdata + len > _pfree) {

            return false;

        }

        memcpy(dst, _pdata, len);

        _pdata += len;

        assert(_pfree>=_pdata);

        return true;

    }
View Code

   1.2 写数据时,仅需偏移_pfree指针即可

       源码如下:                  

技术分享
  void writeString(const char *str) {

        int len = (str ? static_cast<int32_t>(strlen(str)) : 0);

        if (len>0) len ++;

        expand(static_cast<int32_t>(len+sizeof(uint32_t)));

        writeInt32(len);

        if (len>0) {

            memcpy(_pfree, str, len);

            _pfree += (len);

        }

    }
View Code

    1.3 当所需内存不足时(_ppend - _pfree < need ),干两件事情:

        a 申请新的当前于内存空间2倍的内存(<<= 1)

        b 把已有数据拷贝至新的内存块上

       源码如下:

技术分享
inline void expand(int need) {

        if (_pstart == NULL) {

            int len = 256;

            while (len < need) len <<= 1;

            _pfree = _pdata = _pstart = (unsigned char*)malloc(len);

            _pend = _pstart + len;

        } else if (_pend - _pfree < need) { // 空间不够

            int flen = static_cast<int32_t>((_pend - _pfree) + (_pdata - _pstart));

            int dlen = static_cast<int32_t>(_pfree - _pdata);

 

            if (flen < need || flen * 4 < dlen) {

                int bufsize = static_cast<int32_t>((_pend - _pstart) * 2);

                while (bufsize - dlen < need)

                    bufsize <<= 1;

 

                unsigned char *newbuf = (unsigned char *)malloc(bufsize);

                if (newbuf == NULL)

                {

                  TBSYS_LOG(ERROR, "expand data buffer failed, length: %d", bufsize);

                }

                assert(newbuf != NULL);

                if (dlen > 0) {

                    memcpy(newbuf, _pdata, dlen);

                }

                free(_pstart);

 

                _pdata = _pstart = newbuf;

                _pfree = _pstart + dlen;

                _pend = _pstart + bufsize;

            } else {

                memmove(_pstart, _pdata, dlen);

                _pfree = _pstart + dlen;

                _pdata = _pstart;

            }

        }

    }
View Code

3 实例

3.1 输入

技术分享

3.2 输出

out1: 11 out2: 1100 out3: hello world

 

    源码请见 http://files.cnblogs.com/files/gisorange/databuffer.zip

 

  

 

二进制编码与解码容器

标签:

原文地址:http://www.cnblogs.com/gisorange/p/4891059.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!