二进制编码与解码容器

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;

    }

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);

        }

    }

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;

            }

        }

    }

3 实例

3.1 输入

3.2 输出

out1: 11 out2: 1100 out3: hello world

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

时间: 2024-10-17 07:13:39

二进制编码与解码容器的相关文章

各种音视频编解码学习详解

各种音视频编解码学习详解 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放license收费等等.最近因为项目的关系,需要理清媒体的codec,比较搞的是,在豆丁网上看运营商的规范 标准,同一运营商同样的业务在不同文档中不同的要求,而且有些要求就我看来应当是历史的延续,也就是现在已经很少采用了.所以豆丁上看不出所以然,从 wiki上查.中文的wiki信息量有限,很短,而wiki的英文内容内多,删减版

(8)容器(下)

Matroska(MKV) MKV ,不是任何的编解码或者系统的标准,但实际上可封装任何的东西.是一个开放以及开源的容器格式. 扩展名 .mkv .mka .mks  互联网媒体类型 video/x-matroska audio/x-matroska 开 发者 Matroska.org  格式 视频文件格式  专门属 多媒体  自由文件格式? Yes: GNU LGPL Matroska,很多人把它当作为MKV,其实MKV只 是Matroska媒体系列的其中一种文件.Matroska是一种新的多

音视频编码基础知识

本文转载自 http://blog.csdn.net/ljzcom/article/details/7336258 ,如有需要,请移步查看. Technorati 标签: 音视频 编码 基础知识 --------------------------------分割线开始----------------------------------------------- 编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中

H5游戏开发的那些坑(一) 客户端

[客户端] 1.关于游戏引擎 在15年3月开始准备做h5游戏的时候,首先遇到的问题就是引擎选型的问题. 当时市面上的2d引擎主要有3个:白鹭egret,layabox和cocos2d-js. 一方面,是因为我以前用cocos2d-x(c++)做了一年多的手游客户端,所以,很自然就选择了cocos2d-js.另一方面,是因为当时市面上其他两个引擎的成功项目还不多. cocos引擎的每一次版本更新,我们都会第一时间在我们的游戏里面进行测试. 如果发现游戏在android手机上的性能有明显提升,我们就

音视频技术总结

1. 常用的基本知识 基本概念 编解码 编解码器(codec)指的是一个能够对一个信号或者一个数据流进行变换的设备或者 程序.这里指的变换既包括将信号或者数据流进行编码(通常是为了传输.存储或者加密)或者提取得到一个编码流的操作,也包括为了观察或者处理从这个编码流 中恢复适合观察或操作的形式的操作.编解码器经常用在视频会议和流媒体等应用中. 容器 很多多媒体数据流需要同时包含音频数据和视频数据,这时通常会加入一些用于音频和视 频数据同步的元数据,例如字幕.这三种数据流可能会被不同的程序,进程或者

h5牛牛平台架设游戏开发的架构总结(一) 客户端

有问题Q1446595067官网:h5.haozibbs.com或http:\www.qabaa.com [客户端]1.关于游戏引擎在15年3月开始准备做h5游戏的时候,首先遇到的问题就是引擎选型的问题.当时市面上的2d引擎主要有3个:白鹭egret,layabox和cocos2d-js.一方面,是因为我以前用cocos2d-x(c++)做了一年多的手游客户端,所以,很自然就选择了cocos2d-js.另一方面,是因为当时市面上其他两个引擎的成功项目还不多.cocos引擎的每一次版本更新,我们都

2018/11/9(python)

---恢复内容开始--- 1.前项引用 在函数定义之前,函数无法调用. 2.递归 import time def T(x): if x==1: return x else: time.sleep(2) #暂停 print(x) return x*T(x-1) x=T(5) print(x) 3.函数调用 def T(): print(1) def Y(): return T #返回T函数地址 Y()() **********************************************

计算机 编码 解码

目录 1 字符 & 编码 2 记事本下的乱码 3 UTF-8解码过程 4 UTF-16解码过程 5 ISO-8859-1 6 byte范围 在阅读本文章之前,我建议你首先看阮一峰的博客:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html 1 字符 & 编码 字符: 是文字和符号的总称.一个汉字.标点符号.英文字母.数字,这都是字符 字符集: 是多个字符的集合.我们可以理解为一本大字典.字符集种类很多,每个字

FFmpeg学习2:解码数据结构及函数总结

在上一篇文章中,对FFmpeg的视频解码过程做了一个总结.由于才接触FFmpeg,还是挺陌生的,这里就解码过程再做一个总结.本文的总结分为以下两个部分: 数据读取,主要关注在解码过程中所用到的FFmpeg中的结构体. 解码过程中所调用的函数 在学习的过程主要参考的是dranger tutorial,所以跟着教程在本文的最后使用SDL2.0将解码后的数据输出到屏幕上. 数据的读取 一个多媒体文件包含有多个流(视频流 video stream,音频流 audio stream,字幕等):流是一种抽象