【TARS】TARS协议的编解码

目录

 

0.现有编解码方式

1.编解码

2.TARS底层协议

3.TUP

3.1TUP是什么

3.2TUP能做什么

3.3TUP不能做什么

3.4依赖和约束 

4.TARS协议的序列化与反序列化调用的函数

5.源码分布

6.协议序列化分析(以响应报文为例)

6.0如何进行序列化

6.1响应包体

6.2响应包体中每个成员变量的序列化后的组成部分HEAD+BUF

6.3分析HEAD

6.3.1HEAD的组成

6.3.2TAG的取值逻辑

6.3.3 TYPE的取值范围与取值逻辑

7.响应协议反序列化

7.1理解反序列化

7.2路小饭的协议反序列化测试示例

8.我自己写的测试序列化和反序列化的测试程序及逻辑说明

 

 


 

0.现有编解码方式

序列化与反序列化编码原理--阅读链接--感谢作者!

1.编解码

引用阅读

官方引用阅读-02-关于协议,Tars文件以及翻译工具tars2node的说明

宝藏文章!

统一通信协议 TarsTup

宝藏路小饭

路小饭对于TARS的编解码的讲解

路小饭对TARS的编解码的测试用例

编码-序列化
解码-反序列化

序列化:将对象变为二进制内容,写入到IO流中;
反序列化:从IO流获取到二进制内容,将其恢复为对象.

tars序列化过程:TARS编码协议是一种数据编解码规则,它将整形、枚举值、字符串、序列、字典、自定义结构
体等数据类型按照一定的规则编码到二进制数据流中。对端接收到二进制数据流之后,按照相应的规则反序列化
可得到原始数值。简单理解,TARS编码协议提供了一种将数据序列化、反序列化的方法。其角色和我们认识的
protobuf、json、xml等同.

2.TARS底层协议

Tars服务之间通讯的底层协议格式, 具体参见RequestF.tars & BaseF.tars.

RequestPacket和ResponsePacket 是两个Tars服务通信的底层协议, 简单的说如果不通过Tars的
Communicator来通信, 你可以自己组包来完成和Tars服务的通信(当然这会有相当的难度, 需要你
对Tars底层协议非常熟悉), 因此为了方便TUP构建出来解决这种问题.


module tars
{
    //请求包体
    struct RequestPacket
    {
        1  require short        iVersion;
        2  require byte         cPacketType  = 0;
        3  require int          iMessageType = 0;
        4  require int          iRequestId;
        5  require string       sServantName = "";
        6  require string       sFuncName    = "";
        7  require vector sBuffer;
        8  require int          iTimeout     = 0;
        9  require map context;
        10 require map status;
    };

    //响应包体
    struct ResponsePacket
    {
        1 require short         iVersion;
        2 require byte          cPacketType  = 0;
        3 require int           iRequestId;
        4 require int           iMessageType = 0;
        5 require int           iRet         = 0;
        6 require vector  sBuffer;
        7 require map status;
        8 optional string        sResultDesc;
        9 optional map context;
    };
};
module tars
{
    
    // 定义协议的版本号

    const short TARSVERSION  = 0x01;
    const short TUPVERSION  = 0x03;

    
    // 定义消息的类型

    // 普通调用
    const byte TARSNORMAL  = 0x00;

    // 单向调用
    const byte TARSONEWAY  = 0x01;

    
    // TARS定义的返回码

    const int TARSSERVERSUCCESS       = 0;       //服务器端处理成功
    const int TARSSERVERDECODEERR     = -1;      //服务器端解码异常
    const int TARSSERVERENCODEERR     = -2;      //服务器端编码异常
    const int TARSSERVERNOFUNCERR     = -3;      //服务器端没有该函数
    const int TARSSERVERNOSERVANTERR  = -4;      //服务器端没有该Servant对象
    const int TARSSERVERRESETGRID     = -5;      //服务器端灰度状态不一致
    const int TARSSERVERQUEUETIMEOUT  = -6;      //服务器队列超过限制
    const int TARSASYNCCALLTIMEOUT    = -7;      //异步调用超时
    const int TARSINVOKETIMEOUT       = -7;      //调用超时
    const int TARSPROXYCONNECTERR     = -8;      //proxy链接异常
    const int TARSSERVEROVERLOAD      = -9;      //服务器端超负载,超过队列长度
    const int TARSADAPTERNULL         = -10;     //客户端选路为空,服务不存在或者所有服务down掉了
    const int TARSINVOKEBYINVALIDESET = -11;     //客户端按set规则调用非法
    const int TARSCLIENTDECODEERR     = -12;     //客户端解码异常
    const int TARSSERVERUNKNOWNERR    = -99;     //服务器端位置异常

    /
    // 定义按位的消息状态类型,可复合

    const int TARSMESSAGETYPENULL     = 0x00;    //无状态
    const int TARSMESSAGETYPEHASH     = 0x01;    //HASH消息
    const int TARSMESSAGETYPEGRID     = 0x02;    //灰度消息
    const int TARSMESSAGETYPEDYED     = 0x04;    //染色消息
    const int TARSMESSAGETYPESAMPLE   = 0x08;    //stat采样消息
    const int TARSMESSAGETYPEASYNC    = 0x10;    //异步调用程序
    //const int TARSMESSAGETYPELOADED = 0x20;    //按负载值调用程序
    //const int TARSMESSAGETYPESETED = 0x40;     //按set规则调用类型,此字段后面将不使用
    const int TARSMESSAGETYPESETNAME = 0x80;     //按setname规则调用类型
    const int TARSMESSAGETYPETRACK   = 0x100;    //track调用链消息
    /
}

3.TUP

3.1TUP是什么

TUP(Tars Uni-Protocol的简称),Tars统一协议,是基于Tars编码的命令字(Command)层协议的封装。
它的存在最早是为了方便各语言客户端调用Tars服务, 只提供了编解码, 网路通讯需要自己实现, 当然如果
Tars提供了这个语言的客户端, 那么就不需要再使用TUP协议来调用Tars服务了.


在正式使用中, 我们有这种场景, 以供大家参考:

(1)后端服务使用Tars服务实现;
(2)实现一个HTTP+TUP协议的全异步代理, 即入口是HTTP+TUP, 出口是TARS协议的代理;
(3)Android/Ios通过TUP协议, 并通过这个代理服务, 完成和后台任何Tars服务的通信.

3.2TUP能做什么

1.支持java、c++等语言;

2.支持对象的序列化和反序列化;

3.支持协议动态扩展;

4.提供put/get泛型接口,快速实现客户端/服务端的编解码;

5.支持直接调用Tars的服务端.

3.3TUP不能做什么

1.只做协议封装,不包含网络层;

2.不支持数据压缩(可在业务层处理);

3.不支持加密协议(可在业务层处理).

3.4依赖和约束 

1.依赖Tars协议,TUP用到的结构体对象必须通过Tars定义后生成;
2.依赖各个语言的代码生成工具,如:tars2cpp/tars2java等;
3.TarsUniPacket中封装的Tars相关的接口(如getTars.../setTars...),只有在调用Tars服务是需要用到
4.使用过程中,使用UniPacket完成请求与相应的数据传递,其中ServantName(服务对象名) 与FuncName
(接口名)为必须设定的参数,否则编码失败
5.不建议get/put太多数据,如果有比较多数据,建议在tars文件中组成一个struct,然后put/get到
UniPacket中,便于提高效率和减少网络包大小;
6.UniPacket编码后的结果在包头包含了4个字节网络字节序的包长信息,长度包括包头,接收方收到包后需根据
包头的内容,判断包长,确保包完整后,传入解码接口进行解码(无需去掉包头);
7.Tars c++语言的string 类型接口建议不要包含二进制数据,二进制数据用vector传输.

4.TARS协议的序列化与反序列化调用的函数

序列化数据使用的是:  ResponsePacket.writeTo()
反序列化数据使用的是:ResponsePacket.readFrom()
代码路径:D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\servant\tup\RequestF.h
struct RequestPacket
{
  ...

        template
        void writeTo(tars::TarsOutputStream& _os) const
        {
            _os.write(iVersion, 1);
            _os.write(cPacketType, 2);
            _os.write(iMessageType, 3);
            _os.write(iRequestId, 4);
            _os.write(sServantName, 5);
            _os.write(sFuncName, 6);
            _os.write(sBuffer, 7);
            _os.write(iTimeout, 8);
            _os.write(context, 9);
            _os.write(status, 10);
        }
        template
        void readFrom(tars::TarsInputStream& _is)
        {
            resetDefautlt();
            _is.read(iVersion, 1, true);
            _is.read(cPacketType, 2, true);
            _is.read(iMessageType, 3, true);
            _is.read(iRequestId, 4, true);
            _is.read(sServantName, 5, true);
            _is.read(sFuncName, 6, true);
            _is.read(sBuffer, 7, true);
            _is.read(iTimeout, 8, true);
            _is.read(context, 9, true);
            _is.read(status, 10, true);
        }
...
}


 struct ResponsePacket {
...
        template
        void writeTo(tars::TarsOutputStream& _os) const
        {
            _os.write(iVersion, 1);
            _os.write(cPacketType, 2);
            _os.write(iRequestId, 3);
            _os.write(iMessageType, 4);
            _os.write(iRet, 5);
            _os.write(sBuffer, 6);
            _os.write(status, 7);
            if (sResultDesc != "")
            {
                _os.write(sResultDesc, 8);
            }
            if (context.size() > 0)
            {
                _os.write(context, 9);
            }
        }
        template
        void readFrom(tars::TarsInputStream& _is)
        {
            resetDefautlt();
            _is.read(iVersion, 1, true);
            _is.read(cPacketType, 2, true);
            _is.read(iRequestId, 3, true);
            _is.read(iMessageType, 4, true);
            _is.read(iRet, 5, true);
            _is.read(sBuffer, 6, true);
            _is.read(status, 7, true);
            _is.read(sResultDesc, 8, false);
            _is.read(context, 9, false);
        }




...
}

5.源码分布

D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\servant\tup\tup.h
D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\servant\tup\Tars.h
D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\servant\tup\RequestF.h

6.协议序列化分析(以响应报文为例)

6.0如何进行序列化

把结构化数据序列化,就是想办法把不同类型的数据按照顺序放在一个字符串里,反序列化就是还能从这个字符
串里把类型和数据正确解析出来,一般来说,要达成正确的效果,必须考虑三点:

(1)标记数据的位置,例如是位于字符串头部还是字符串末尾,或者中间某个部分.
(2)标记数据的类型,例如int char float vector等
(3)标记数据内容.

6.1响应包体

struct ResponsePacket
{
        1 require short         iVersion;
        2 require byte          cPacketType  = 0;
        3 require int           iRequestId;
        4 require int           iMessageType = 0;
        5 require int           iRet         = 0;
        6 require vector  sBuffer;
        7 require map status;
        8 optional string        sResultDesc;
        9 optional map context;
};

6.2响应包体中每个成员变量的序列化后的组成部分HEAD+BUF

每个成员变量的数据是由两部分组成:
HEAD + BUF 

HEAD为头部信息(包含了数据位置和数据类型),BUF为实际数据.
注意BUF里可以继续嵌套| HEAD | BUF |这样的类型,以满足复杂数据结构的需要.
像char、short、int之类的简单类型时,只需要:| HEAD | BUF |
当数据类型为vector< char >时,就变为了| HEAD1 | HEAD2 | BUF |,这时候HEAD1 存储vector类型,HEAD2 存储char类型

6.3分析HEAD

6.3.1HEAD的组成

HEAD的构成为:
| TAG1(4 bits) | TYPE(4 bits) | TAG2(1 byte或者8 bits).
D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\servant\tup\RequestF.h
响应报文的序列化源码:        
struct ResponsePacket 
{
        ...
        template // line 204 ,ver 2-14-2
        void writeTo(tars::TarsOutputStream& _os) const
        {
            _os.write(iVersion, 1);
            _os.write(cPacketType, 2);
            _os.write(iRequestId, 3);
            _os.write(iMessageType, 4);
            _os.write(iRet, 5);
            _os.write(sBuffer, 6);
            _os.write(status, 7);
            if (sResultDesc != "")
            {
                _os.write(sResultDesc, 8);
            }
            if (context.size() > 0)
            {
                _os.write(context, 9);
            }
}





write的第一个参数的值是每个变量对应的value值,第二个参数对应的值是每个变量对应的tag值.
要注意每个变量还自己带了一个属性值,就是它的数据类型.

write函数给出了很多重载形式:
如:

 

6.3.2TAG的取值逻辑

#define TarsWriteToHead(os, type, tag) \
do { \
    if (tars_likely((tag) < 15)) \
    { \
        //当tag的值小于15的时候只有TAG1
        TarsWriteUInt8TTypeBuf( os, (type) + ((tag)<<4) , (os)._len); \
    } \
    else \
    { \
        //当tag的值小于15的时候有TAG1还有TAG2
        TarsWriteUInt8TTypeBuf( os, (type) + (240) , (os)._len); \
        TarsWriteUInt8TTypeBuf( os, (tag),  (os)._len);\
    } \
} while(0)


#define TarsWriteUInt8TTypeBuf(os, val, osLen) \
do { \
    TarsReserveBuf(os, (osLen)+sizeof(uint8_t)); \
    (*(uint8_t *)((os)._buf + (osLen))) = (val); \
    (osLen) += sizeof(uint8_t); \
} while(0)


【具体看个TAG小于14的例子:TAG1为1,TYPE为TarsHeadeInt32(2),用二进制表示的话,TAG1为0001,
TYPE为0010,HEAD组成方式是将TAG1二进制和TYPE二进制拼接起来,即:
00010010 换算为10进制是18。 前4位为TAG1,后4位为TYPE,从这样的拼接方式中可以看到,相当于是把
TAG1右移了4位再加上TYPE
从上面贴出的代码中我们也可以看到拼接方式的表示:"(type) + ((tag)<<4)",即:HEAD = 2 + (1<<4) 
= 2 + 16 = 18。就这样Tars协议可以用1byte同时表示数据类型和数据位置.

再看个TAG大于14的例子:TAG1为240(固定值),TAG2为200,TYPE为TarsHeadeInt32(2),HEAD的二进制表示为:
11110010 11001000 用10进制表示为242 200 前八位中,1111代表TAG1的值240(即11110000),0010代
表TYPE的值2(即0010)。后八位为TAG2的值200(即11001000)
】


6.3.3 TYPE的取值范围与取值逻辑

TYPE表示类型,用4个二进制位表示,取值范围是0~15,用来标识数据类型,也就是下面的值中的一个.
//数据头类型
#define TarsHeadeChar  0        // 0000
#define TarsHeadeShort 1        // 0001
#define TarsHeadeInt32 2        // 0010
#define TarsHeadeInt64 3        // 0011
#define TarsHeadeFloat 4        // 0100
#define TarsHeadeDouble 5       // 0101
#define TarsHeadeString1 6      // 0110
#define TarsHeadeString4 7      // 0111
#define TarsHeadeMap 8          // 1000
#define TarsHeadeList 9         // 1001
#define TarsHeadeStructBegin 10 // 1010
#define TarsHeadeStructEnd 11   // 1011
#define TarsHeadeZeroTag 12     // 1100
#define TarsHeadeSimpleList 13  // 1101


D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\servant\tup\Tars.h
此处版本是2-14-2.从64行开始声明

7.响应协议反序列化

7.1理解反序列化

理解了协议的序列化,反序列化就比较简单了,假设已经知道iVersion的反序列化数据为^P^A,其中|HEAD|为
^P(注意,HEAD只占一个Byte)

^P转为十进制整数为16,转为二进制为00010000
将数据00010000右移4位为00000001,这就是TAG的值1
将数据00010000做与运算:00010000 & 0x0F = 0, 这就是TYPE的值0,即TarsHeadeChar
知道了TYPE的值,后面|BUF|所占长度可由TYPE得到,本例中也占一个字节,及^A,转为十进制整数为1
这样就完成了iVersion的反序列化

7.2路小饭的协议反序列化测试示例

路小饭的文章链接-访问原文可以看到路小饭提供的测试代码-谢谢路小饭啦

路小饭的代码在我的虚拟机上的位置:/home/muten/TARS-MODULE/Luxiaofan/lxf

//learn-tars/tup/main.cpp
 56 //反序列化
 57 
 58     list done;
 59 
 60     ProxyProtocol   _proxyProtocol;
 61 
 62     _proxyProtocol.responseFunc = ProxyProtocol::tarsResponse;
 63 
 64     const char* data = s.c_str();
 65 
 66     size_t len = s.size();
 67 
        //反序列化方法,反序列化完的数据放入done中
 68     size_t pos = _proxyProtocol.responseFunc(data, len, done);


这里的responseExFunc来自ProxyProtocol::tarsResponse,其中最主要的逻辑是
//learn-tars/tup/AppProtocal.h
451                 ResponsePacket rsp;
452                 rsp.readFrom(is);

rsp.readFrom(is)中readFrom的实现代码如下:
//learn-tars/tup/RequestF.h
166         template
167         void readFrom(tars::TarsInputStream& _is)
168         {
169             resetDefautlt();
170             _is.read(iVersion, 1, true);
171             _is.read(cPacketType, 2, true);
172             _is.read(iRequestId, 3, true);
173             _is.read(iMessageType, 4, true);
174             _is.read(iRet, 5, true);
175             _is.read(sBuffer, 6, true);
176             _is.read(status, 7, true);
177             _is.read(sResultDesc, 8, false);
178             _is.read(context, 9, false);
179         }

同样以iVersion为例,简要说明代码处理流程:

上面170行代码会调用:
//learn-tars/tup/Tars.h
1105         void read(Short& n, uint8_t tag, bool isRequire = true)
1106         {
1107             std::cout<<"read Short "<> 4; \
 263     std::cout<<"TarsPeekFromHead tmpTag "<<(int)tmpTag<

8.我自己写的测试序列化和反序列化的测试程序及逻辑说明

代码路径:/home/muten/TARS-MODULE

【TARS】TARS协议的编解码_第1张图片

// 编译的时候加上-std=c++11

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
typedef bool    Bool;
typedef char    Char;
typedef short   Short;
typedef float   Float;
typedef double  Double;
typedef int     Int32;
typedef long long   Int64;
struct TarsStructBase;

typedef unsigned char   UInt8;
typedef unsigned short  UInt16;
typedef unsigned int    UInt32;
const Char TARSNORMAL = 0;
const Short TARSVERSION = 1;

//Int32 iVersion;
Short iVersion;
Char cPacketType;
Int32 iMessageType;
Int32 iRequestId;
string sServantName;
string sFuncName;
std::string sResultDesc;
vector sBuffer;
Int32 iTimeout;
map context;
map status;
Int32 iRet;


#ifndef tars_unlikely
#if defined(__GNUC__) && __GNUC__ >= 4
#define tars_unlikely(x)            (__builtin_expect(!!(x),0))
#else
#define tars_unlikely(x)   (x)
#endif
#endif
#define TarsHeadeChar  0
#define TarsHeadeShort 1
#define TarsHeadeInt32 2
#define TarsHeadeInt64 3
#define TarsHeadeFloat 4
#define TarsHeadeDouble 5
#define TarsHeadeString1 6
#define TarsHeadeString4 7
#define TarsHeadeMap 8
#define TarsHeadeList 9
#define TarsHeadeStructBegin 10
#define TarsHeadeStructEnd 11
#define TarsHeadeZeroTag 12
#define TarsHeadeSimpleList 13


string StrToBitStr(const char* str)
{
	// cout << "str is" << str < bstr ;
	for(int i=0;i<16;i++)
	{   
		//cout << "str["< bits =  bitset<8>(str[i]);
		for(int j = 0;j<8;j++)
		{
			bstr[i*8+j] = bits[j];
			//cout << "i*8 + j = " <
		void readFrom(InputStreamT& is)
		{
			size_t n = peekFrom(is);
			is.skip(n);
		}
	/// 读取头信息,但不前移流的偏移量
	template
		size_t peekFrom(InputStreamT& is)
		{
			helper h;
			size_t n = sizeof(h);
			is.peekBuf(&h, sizeof(h));
			_type = h.type;
			if (h.tag == 15)
			{
				is.peekBuf(&_tag, sizeof(_tag), sizeof(h));
				n += sizeof(_tag);
			}
			else
			{
				_tag = h.tag;
			}
			return n;
		}

	/// 写入数据头信息
	template
		void writeTo(OutputStreamT& os)
		{
			/*
			   helper h;
			   h.type = _type;
			   if(_tag < 15){
			   h.tag = _tag;
			   os.writeBuf(&h, sizeof(h));
			   }else{
			   h.tag = 15;
			   os.writeBuf(&h, sizeof(h));
			   os.writeBuf(&_tag, sizeof(_tag));
			   }
			   */
			writeTo(os, _type, _tag);
		}

	/// 写入数据头信息
	template
		static void writeTo(OutputStreamT& os, uint8_t type, uint8_t tag)
		{
			helper h;  h.type = type;
			if (tag < 15)
			{
				h.tag = tag;
				os.writeBuf((const char *)&h, sizeof(h));
			}
			else{
				h.tag = 15;os.writeBuf((const char *)&h, sizeof(h));os.writeBuf((const char *)&tag, sizeof(tag));						}
		}
};



// 编码相应的宏
/*
   (os)._reserve(os, len1)我的代码这里实例化之后调用的原型是std::function  _reserve = BufferWriter::reserve;
   (os)._reserve(os, len1);中的第二个参数值是要申请的字节数,如果len1小于128,则将len1赋值为128,如果len1>=128,则就取len1的值为要申请的字节数.
   在D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\servant\tup\Tars.h中
   */
#define TarsReserveBuf(os, len) \
	do{ \
		if(tars_likely((os)._buf_len < (len))) \
		{ \
			cout << "line = 196 TarsReserveBuf ,len is "<= 15)的时候有tag1也有tag2


*/


//TarsWriteToHead在代码D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\servant\tup\Tars.h中,写协议头的宏函数
#define TarsWriteToHead(os, type, tag) \
	do { \
		if (tars_likely((tag) < 15)) \
		{ \
			cout << "line = 229 ,will call TarsWriteUInt8TTypeBuf function,type is "<<(int)type <<",注意注意,您已进入写协议头的函数,此次只有tag1噢,type is "<<(int)type << ",tag is "<<(int)tag <<". (type) + ((tag)<<4) is "<< (type) + ((tag)<<4) << endl;\
			TarsWriteUInt8TTypeBuf( os, (type) + ((tag)<<4) , (os)._len); \
			cout << "line = 231 ,type is "< struct type_of_size { char elements[N]; };

	typedef type_of_size<1>     yes_type;
	typedef type_of_size<2>     no_type;

	namespace meta_detail
	{
		struct any_conversion
		{
			template  any_conversion(const volatile T&);
			template  any_conversion(T&);
		};

		template  struct conversion_checker
		{
			static no_type _m_check(any_conversion ...);
			static yes_type _m_check(T, int);
		};
	}

	template 
		class is_convertible
		{
			static From _m_from;
			public:
			enum { value = sizeof( meta_detail::conversion_checker::_m_check(_m_from, 0) ) == sizeof(yes_type) };
		};

	template 
		struct type2type { typedef T type; };

	template 
		struct is_same_type
		{
			enum { value = is_convertible< type2type, type2type >::value };
		};

	// enable_if
	template struct enable_if_c { typedef T type; };

	template struct enable_if_c {};

	template 
		struct enable_if : public enable_if_c {};

	template struct disable_if_c { typedef T type; };

	template struct disable_if_c {};

	template 
		struct disable_if : public disable_if_c {};
}



inline Int64 tars_htonll(Int64 x)
{
	detail::bswap_helper h;
	h.i64 = x;
	Int32 tmp = htonl(h.i32[1]);
	h.i32[1] = htonl(h.i32[0]);
	h.i32[0] = tmp;
	return h.i64;
}


inline Float tars_ntohf(Float x)
{
	union {
		Float f;
		Int32 i32;
	} helper;

	helper.f = x;
	helper.i32 = htonl( helper.i32 );

	return helper.f;
}
#       define tars_htonf(x)     tars_ntohf(x)


inline Double tars_ntohd(Double x)
{
	union {
		Double d;
		Int64 i64;
	} helper;

	helper.d = x;
	helper.i64 = tars_htonll( helper.i64 );

	return helper.d;
}
#       define tars_htond(x)     tars_ntohd(x)



#define tars_likely(x)   (x)

class BufferWriter
{
	public:
		char *  _buf;
		size_t  _len;
		size_t  _buf_len;
		std::function  _reserve = BufferWriter::reserve;    //扩展空间

		static char* reserve(BufferWriter &os, size_t len)
		{
			char * p = new char[(len)]; cout << "You haved entered function BufferWriter::reserve. (os)._len is "<< (os)._len < getByteBuffer() const       { return std::vector(_buf, _buf + _len);}
		const char * getBuffer() const                { return _buf;}
             size_t getLength() const                     { return _len;}  
             void swap(std::vector& v)              { v.assign(_buf, _buf + _len); }
             void swap(std::string& v)                    { v.assign(_buf, _len); }
             void swap(BufferWriter& buf)
                 {
	             std::swap(_buf, buf._buf);
	             std::swap(_buf_len, buf._buf_len);
	             std::swap(_len, buf._len);
                 }
};

template
class TarsOutputStream : public WriterT
{
	public:
		void writeUnknown(const std::string& s)
		{
			cout << "line = "<< __LINE__<< ", call func " <<__func__<< endl;
			this->writeBuf(s.data(), s.size());
		}
		void writeUnknownV2(const std::string& s)
		{
			cout << "line = "<< __LINE__<< ", call func " <<__func__<< endl;
			DataHead::writeTo(*this, DataHead::eStructBegin, 0);
			this->writeBuf(s.data(), s.size());
			DataHead::writeTo(*this, DataHead::eStructEnd, 0);
		}
		void write(Bool b, uint8_t tag)
		{
			cout << "line = "<< __LINE__<< ", call func " <<__func__<< endl;
			write((Char) b, tag);
		}

		void write(Char n, uint8_t tag)//D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\servant\tup\Tars.h
		{

			cout << "line = "<< __LINE__<< ", enter function write(Char,uint8_t). ,n is "<< (int)n << ",tag is "<<(int)tag << endl;
			if (tars_unlikely(n == 0))
                        {
				cout << "line = "<< __LINE__<< ", n == 0, it will call func TarsWriteToHead ," <<"tag is "<<(int)tag<<",TarsHeadeZeroTag is "<= (-128) && n <= 127)
			{
				cout << "line = "<< __LINE__<< ",n>=(-128) & n <= 127" <= (-32768) && n <= 32767)
			{
				cout << "line = "<< __LINE__<< ", convert call write(Int32,uint8_t) to call write(Short,uint8_t), n is Short(0011),tage is " <<(int)tag<< endl;
				write((Short) n, tag);
			}
			else
			{  
				cout << "line = "<< __LINE__<< ", call func TarsWriteToHead, htonl, TarsWriteInt32TypeBuf" << endl;
				TarsWriteToHead(*this, TarsHeadeInt32, tag);
				cout << "line = "<< __LINE__<< ", 经过写头HEAD的信息之后,序列化为:【"<< StrToBitStr((*this)._buf)<<"】, it will call func  TarsWriteInt32TypeBuf"<= (-2147483647-1) && n <= 2147483647)
			{
				write((Int32) n, tag);
			}
			else
			{
				cout << "line = "<< __LINE__<< ", n == 0, it will call func TarsWriteToHead ," <<"tag is "<<(int)tag<<",TarsHeadeInt64 is "< 255))
			{  
				cout << "line = "<< __LINE__<< ", tars_unlikely(s.size() > 255  "<< endl;
				if (tars_unlikely(s.size() > TARS_MAX_STRING_LENGTH))
				{
					char ss[128];
					snprintf(ss, sizeof(ss), "invalid string size, tag: %d, size: %u", tag, (uint32_t)s.size());
					//throw TarsDecodeInvalidValue(ss);
					cout << ss << endl;
				}
				TarsWriteToHead(*this, TarsHeadeString4, tag);
				uint32_t n = htonl((uint32_t)s.size());
				TarsWriteUInt32TTypeBuf(*this, n, (*this)._len);
				TarsWriteTypeBuf(*this, s.data(), s.size());
			}
			else
			{
				cout << "line = "<< __LINE__<< ", tars_unlikely(s.size() <= 255  "<< endl;
				TarsWriteToHead(*this, TarsHeadeString1, tag);
				cout << "line = "<< __LINE__<< ", 经过字段的HEAD的信息之后,序列化为:【"<< StrToBitStr((*this)._buf)<<"】, it will call func  TarsWriteUInt8TTypeBuf and TarsWriteTypeBuf"<
			void write(const std::map& m, uint8_t tag)
			{
				cout << "line = "<< __LINE__<< ", call func write(const std::map,uint8_t)." << endl;
				TarsWriteToHead(*this, TarsHeadeMap, tag);
				Int32 n = (Int32)m.size();
				cout << "line = "<< __LINE__<< ", func write(const std::map,uint8_t)中将要调用write(n, 0)并将要遍历容器map的对象m并且将调用write(i->first, 0)和write(i->second, 1)" << endl;
				write(n, 0);
				typedef typename std::map::const_iterator IT;
				for (IT i = m.begin(); i != m.end(); ++i)
				{
					write(i->first, 0);
					write(i->second, 1);
				}
			}

		template
			void write(const std::vector& v, uint8_t tag)
			{
				cout << "line = "<< __LINE__<< ", call func write(const std::vector& v, uint8_t tag." << endl;
                         TarsWriteToHead(*this, TarsHeadeList, tag);
				Int32 n = (Int32)v.size();
				write(n, 0);
				typedef typename std::vector::const_iterator IT;
				for (IT i = v.begin(); i != v.end(); ++i)
					write(*i, 0);
			}

		template
			void write(const T *v, const UInt32 len, uint8_t tag)
			{
				cout << "line = "<< __LINE__<< ", call func write(const T *v, const UInt32 len, uint8_t tag)." << endl;
                         TarsWriteToHead(*this, TarsHeadeList, tag);
				write(len, 0);
				for (Int32 i = 0; i < (Int32)len; ++i)
				{
					write(v[i], 0);
				}
			}





		template
			void write(const std::vector& v, uint8_t tag)
			{
				cout << "line = "<< __LINE__<< ", call func write(const std::vector& v, uint8_t tag).it will call TarsWriteToHead(*this, TarsHeadeSimpleList, tag)" << endl;
                         TarsWriteToHead(*this, TarsHeadeSimpleList, tag);//标记 TarsHeadeSimpleList
                         cout << "line = "<< __LINE__<< ", call func write(const std::vector& v, uint8_t tag).it will call TarsWriteToHead(*this, TarsHeadeChar, 0)" << endl;
				TarsWriteToHead(*this, TarsHeadeChar, 0);// 标记 TarsHeadeSimpleList
				Int32 n = (Int32)v.size(); 
				write(n, 0); // 将vector的size的大小写道序列中,用Int32的变量来接住这个大小,然后再写进序列中
				TarsWriteTypeBuf(*this, v.data(), v.size());
			}






		template
			void write(const T& v, uint8_t tag, typename detail::disable_if, void ***>::type dummy = 0)
			{
				write((Int32) v, tag);
			}

		template
			void write(const T& v, uint8_t tag, typename detail::enable_if, void ***>::type dummy = 0)
			{
				TarsWriteToHead(*this, TarsHeadeStructBegin, tag);
				v.writeTo(*this);
				TarsWriteToHead(*this, TarsHeadeStructEnd, 0);
			}
};


// 这里用的是ResponsePacket那一部分的代码,编码,代码路径D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\servant\tup\Tars.h
template
void writeTo(TarsOutputStream& _os)    
{ 
	cout << "line = "<<__LINE__<<",_os.write(iVersion, 1) ====================================================================================================================" < 0)
	   {
	  cout << "line = "<<__LINE__<<",_os.write(sResultDesc, 9)=================================================================================================================="<(is)._buf_len) )\
    { \
        char s[64]; \
        snprintf(s, sizeof(s), "buffer overflow when peekBuf, over %u.", (uint32_t)((is)._buf_len)); \
        throw TarsDecodeException(s); \
    } \
    (buf) = (*((type *)((is)._buf+(is)._cur+(offset)))); \
} while(0)

#define TarsPeekTypeBufNoTag(is, offset, type) \
do { \
    if(tars_unlikely((is)._cur+(offset)+sizeof(type)>(is)._buf_len) )\
    { \
        char s[64]; \
        snprintf(s, sizeof(s), "buffer overflow when peekBuf, over %u.", (uint32_t)((is)._buf_len)); \
        throw TarsDecodeException(s); \
    } \
} while(0)

#define TarsReadCharTypeBuf(is, buf) \
do { \
    TarsPeekTypeBuf(is, buf, 0, Char); \
    (is)._cur += sizeof(Char); \
} while(0)

#define TarsReadShortTypeBuf(is, buf) \
do { \
    TarsPeekTypeBuf(is, buf, 0, Short); \
    (is)._cur += sizeof(Short); \
} while(0)

#define TarsReadInt32TypeBuf(is, buf) \
do { \
    TarsPeekTypeBuf(is, buf, 0, Int32); \
    (is)._cur += sizeof(Int32); \
} while(0)

#define TarsReadInt64TypeBuf(is, buf) \
do { \
    TarsPeekTypeBuf(is, buf, 0, Int64); \
    (is)._cur += sizeof(Int64); \
} while(0)

#define TarsReadFloatTypeBuf(is, buf) \
do { \
    TarsPeekTypeBuf(is, buf, 0, Float); \
    (is)._cur += sizeof(Float); \
} while(0)

#define TarsReadDoubleTypeBuf(is, buf) \
do { \
    TarsPeekTypeBuf(is, buf, 0, Double); \
    (is)._cur += sizeof(Double); \
} while(0)

#define TarsReadTypeBuf(is, buf, type) \
do { \
    TarsPeekTypeBuf(is, buf, 0, type); \
    (is)._cur += sizeof(type); \
} while(0)

#define TarsReadHeadSkip(is, len) \
do {\
    (is)._cur += (len); \
} while(0)

#define TarsPeekFromHead(is, type, tag, n) \
do { \
    (n) = 1; \
    uint8_t typeTag, tmpTag; \
    TarsPeekTypeBuf(is, typeTag, 0, uint8_t); \
    tmpTag = typeTag >> 4; \
    (type) = (typeTag & 0x0F); \
    if(tars_unlikely(tmpTag == 15)) \
    { \
        TarsPeekTypeBuf(is, tag, 1, uint8_t); \
        (n) += 1; \
    } \
    else \
    { \
        (tag) = tmpTag; \
    } \
} while(0)

#define readFromHead(is, type ,tag) \
do { \
    size_t n = 0; \
    TarsPeekFromHead(is, type, tag, n); \
    TarsReadHeadSkip(is, n); \
} while(0)

#define TarsPeekFromHeadNoTag(is, type, n) \
do { \
    (n) = 1; \
    uint8_t typeTag, tmpTag; \
    TarsPeekTypeBuf(is, typeTag, 0, uint8_t); \
    tmpTag = typeTag >> 4; \
    (type) = (typeTag & 0x0F); \
    if(tars_unlikely(tmpTag == 15)) \
    { \
        TarsPeekTypeBufNoTag(is, 1, uint8_t); \
        (n) += 1; \
    } \
} while(0)

#define readFromHeadNoTag(is, type) \
do { \
    size_t n = 0; \
    TarsPeekFromHeadNoTag(is, type, n); \
    TarsReadHeadSkip(is, n); \
} while(0)

#define TarsPeekBuf(is ,buf, len, offset) \
do {\
    if (tars_unlikely((is)._cur + (offset) + (len) > (is)._buf_len)) \
    { \
        char s[64]; \
        snprintf(s, sizeof(s), "buffer overflow when peekBuf, over %u.", (uint32_t)((is)._buf_len)); \
        throw TarsDecodeException(s); \
    } \
    ::memcpy(buf, (is)._buf + (is)._cur + (offset), (len)); \
} while(0)

#define TarsReadBuf(is, buf, len) \
do { \
    cout << "line = 956 in mocro function TarsReadBuf" < (is)._buf_len)) \
    { \
        char s[64]; \
        snprintf(s, sizeof(s), "buffer overflow when peekBuf, over %u.", (uint32_t)((is)._buf_len)); \
        throw TarsDecodeException(s); \
    } \
    str.assign((is)._buf + (is)._cur, (is)._buf + (is)._cur + (len)); \
    (is)._cur += len; \
} while (0)


/*line 984 TarsPeekFromHead里进行了运算,得到TYPE和TAGE
  this指针指向TarsInputStream一个对象,在这个对象继承自ReaderT,ReaderT=BufferReader,
  BufferReader中有:
  const char *        _buf;        ///< 缓冲区
  size_t              _buf_len;    ///< 缓冲区长度
  size_t              _cur;        ///< 当前位置

*/
#define TarsSkipToTag(flag, tag, retHeadType, retHeadTag) \
do { \
    try \
    { \
       cout << "line = 985 in mocro function TarsSkipToTag" <_buf is 【"<< this->_buf <<"】,this->_buf_len is "<_buf_len<<",this->_cur is "<< this->_cur< _buf_len)
		{
			char s[64];
			snprintf(s, sizeof(s), "buffer overflow when peekBuf, over %u.", (uint32_t)_buf_len);
			throw TarsDecodeException(s);
		}
		::memcpy(buf, _buf + _cur + offset, len);
	}

	/// 读取缓存 for vector
	template 
	void readBuf(std::vector& v, size_t len)
	{
		if(len <= _buf_len && (_cur + len) <= _buf_len)
		{
			peekBuf(v, len);
			_cur += len;
		}
		else
		{
			char s[64];
			snprintf(s, sizeof(s), "buffer overflow when skip, over %u.", (uint32_t)_buf_len);
			throw TarsDecodeException(s);
		}
	}

	/// 读取缓存,但不改变偏移量 for vector
	template 
	void peekBuf(std::vector& v, size_t len, size_t offset = 0)
	{
		if (_cur + offset + len > _buf_len)
		{
			char s[64];
			snprintf(s, sizeof(s), "buffer overflow when peekBuf, over %u.", (uint32_t)_buf_len);
			throw TarsDecodeException(s);
		}

		const char* begin = _buf + _cur + offset;
		v.assign(begin, begin + len);
	}

	/// 跳过len个字节
	void skip(size_t len)
	{
		if(len <= _buf_len && (_cur + len) <= _buf_len)
		{
			_cur += len;
		}
		else
		{
			char s[64];
			snprintf(s, sizeof(s), "buffer overflow when skip, over %u.", (uint32_t)_buf_len);
			throw TarsDecodeException(s);
		}
	}

	/// 设置缓存
	void setBuffer(const char * buf, size_t len)
	{
		_buf = buf;
		_buf_len = len;
		_cur = 0;
	}

	/// 设置缓存
	template
	void setBuffer(const std::vector &buf)
	{
		_buf = buf.data();
		_buf_len = buf.size();
		_cur = 0;
	}

	/**
	 * 判断是否已经到BUF的末尾
	 */
	bool hasEnd()
	{
		if(_cur > _buf_len)
		{
			char s[64];
			snprintf(s, sizeof(s), "buffer overflow when skip, over %u.", (uint32_t)_buf_len);
			throw TarsDecodeException(s);
		}
		return _cur >= _buf_len;
	}
	size_t tellp() const
	{
		return _cur;
	}
	const char* base() const
	{
		return _buf;
	}
	size_t size() const
	{
		return _buf_len;
	}
};


// TARS输入流的类的定义,代码路径D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\servant\tup\Tars.h
template
class TarsInputStream : public ReaderT
{
public:

	/// 跳到指定标签的元素前
	bool skipToTag(uint8_t tag)
	{
		try
		{
			uint8_t headType = 0, headTag = 0;
			while (!ReaderT::hasEnd())
			{
				size_t len = 0;
				TarsPeekFromHead(*this, headType, headTag, len);
				if (tag <= headTag || headType == TarsHeadeStructEnd)
					return headType == TarsHeadeStructEnd?false:(tag == headTag);
				TarsReadHeadSkip(*this, len);
				skipField(headType);
			}
		}
		catch (TarsDecodeException& e)
		{
		}
		return false;
	}

	/// 跳到当前结构的结束
	void skipToStructEnd()
	{
		uint8_t headType = 0;
		do
		{
			readFromHeadNoTag(*this, headType);
			skipField(headType);
		}while (headType != TarsHeadeStructEnd);
	}

	/// 跳过一个字段
	void skipField()
	{
		uint8_t headType = 0;
		readFromHeadNoTag(*this, headType);
		skipField(headType);
	}

	/// 跳过一个字段,不包含头信息
	void skipField(uint8_t type)
	{
		switch (type)
		{
			case TarsHeadeChar:
				TarsReadHeadSkip(*this, sizeof(Char));
				break;
			case TarsHeadeShort:
				TarsReadHeadSkip(*this, sizeof(Short));
				break;
			case TarsHeadeInt32:
				TarsReadHeadSkip(*this, sizeof(Int32));
				break;
			case TarsHeadeInt64:
				TarsReadHeadSkip(*this, sizeof(Int64));
				break;
			case TarsHeadeFloat:
				TarsReadHeadSkip(*this, sizeof(Float));
				break;
			case TarsHeadeDouble:
				TarsReadHeadSkip(*this, sizeof(Double));
				break;
			case TarsHeadeString1:
			{
				size_t len = 0;
				TarsReadTypeBuf(*this, len, uint8_t);
				TarsReadHeadSkip(*this, len);
			}
				break;
			case TarsHeadeString4:
			{
				size_t len = 0;
				TarsReadTypeBuf(*this, len, uint32_t);
				len = ntohl((uint32_t)len);
				TarsReadHeadSkip(*this, len);
			}
				break;
			case TarsHeadeMap:
			{
				UInt32 size = 0;
				read(size, 0);
				for (UInt32 i = 0; i < size * 2; ++i)
					skipField();
			}
				break;
			case TarsHeadeList:
			{
				UInt32 size = 0;
				read(size, 0);
				for (UInt32 i = 0; i < size; ++i)
					skipField();
			}
				break;
			case TarsHeadeSimpleList:
			{
				
                         uint8_t headType = 0, headTag = 0;
				readFromHead(*this, headType, headTag);
				if (tars_unlikely(headType != TarsHeadeChar))
				{
					char s[64];
					snprintf(s, sizeof(s), "skipField with invalid type, type value: %d, %d, %d.", type, headType, headTag);
					throw TarsDecodeMismatch(s);
				}
				UInt32 size = 0;
				read(size, 0);
				TarsReadHeadSkip(*this, size);
			}
				break;
			case TarsHeadeStructBegin:
				skipToStructEnd();
				break;
			case TarsHeadeStructEnd:
			case TarsHeadeZeroTag:
				break;
			default:
			{
				char s[64];
				snprintf(s, sizeof(s), "skipField with invalid type, type value:%d.", type);
				throw TarsDecodeMismatch(s);
			}
		}
	}

	/// 读取一个指定类型的数据(基本类型)
	template
	inline T readByType()
	{
		T n;
		this->readBuf(&n, sizeof(n));
		return n;
	}
	void readUnknown(std::string & sUnkown, uint8_t tag)
	{

		size_t start = ReaderT::tellp();
		size_t last  = start;
		try
		{
			uint8_t lasttag = tag;
			DataHead h;
			while (!ReaderT::hasEnd())
			{
				size_t len = h.peekFrom(*this);
				if ( h.getTag() <=lasttag)
				{
					break;
				}
				lasttag = h.getTag();
				this->skip(len);
				skipField(h.getType());
				last = ReaderT::tellp(); //记录下最后一次正常到达的位置
			}
		}
		catch (...) //
		{
			throw;
		}
		std::string s(ReaderT::base() +start, last - start);
		sUnkown = s;
		return ;

	}
	friend class XmlProxyCallback;

	void read(Bool& b, uint8_t tag, bool isRequire = true)
	{
		Char c = b;
		read(c, tag, isRequire);
		b = c ? true : false;
	}

	void read(Char& c, uint8_t tag, bool isRequire = true)
	{
		uint8_t headType = 0, headTag = 0;
		bool skipFlag = false;
		TarsSkipToTag(skipFlag, tag, headType, headTag);
		if (tars_likely(skipFlag))
		{
			switch (headType)
			{
				case TarsHeadeZeroTag:
					c = 0;
					break;
				case TarsHeadeChar:
					TarsReadTypeBuf(*this, c, Char);
					break;
				default:
				{
					char s[64];
					snprintf(s, sizeof(s), "read 'Char' type mismatch, tag: %d, get type: %d.", tag, headType);
					throw TarsDecodeMismatch(s);
				}

			}
		}
		else if (tars_unlikely(isRequire))
		{
			char s[64];
			snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d.", tag, headTag);
                        cout << "line = "<<__LINE__<< ", require field not exist, tag:"<< tag << ",headTag is "<< headTag< TARS_MAX_STRING_LENGTH))
					{
						char s[128];
						snprintf(s, sizeof(s), "invalid string size, tag: %d, size: %d", tag, strLength);
						throw TarsDecodeInvalidValue(s);
					}
				}
					break;
				default:
				{
					char s[64];
					snprintf(s, sizeof(s), "read 'string' type mismatch, tag: %d, get type: %d, tag: %d.", tag, headType, headTag);
					throw TarsDecodeMismatch(s);
				}
			}
			TarsReadStringBuf(*this, s, strLength);
		}
		else if (tars_unlikely(isRequire))
		{
			char s[64];
			snprintf(s, sizeof(s), "require field not exist, tag: %d", tag);
			throw TarsDecodeRequireNotExist(s);
		}
	}

	void read(char *buf, const UInt32 bufLen, UInt32 & readLen, uint8_t tag, bool isRequire = true)
	{
		uint8_t headType = 0, headTag = 0;
		bool skipFlag = false;
		TarsSkipToTag(skipFlag, tag, headType, headTag);
		if (tars_likely(skipFlag))
		{
			switch(headType)
			{
				case TarsHeadeSimpleList:
				{
					uint8_t hheadType, hheadTag;
					readFromHead(*this, hheadType, hheadTag);
					if (tars_unlikely(hheadType != TarsHeadeChar))
					{
						char s[128];
						snprintf(s, sizeof(s), "type mismatch, tag: %d, type: %d, %d, %d", tag, headType, hheadType, hheadTag);
						throw TarsDecodeMismatch(s);
					}
					UInt32 size = 0;
					read(size, 0);
					if (tars_unlikely(size > bufLen))
					{
						char s[128];
						snprintf(s, sizeof(s), "invalid size, tag: %d, type: %d, %d, size: %d", tag, headType, hheadType, size);
						throw TarsDecodeInvalidValue(s);
					}
					//TarsReadTypeBuf(*this, size, UInt32);
					this->readBuf(buf, size);
					readLen = size;
				}
					break;

				default:
				{
					char s[128];
					snprintf(s, sizeof(s), "type mismatch, tag: %d, type: %d", tag, headType);
					throw TarsDecodeMismatch(s);
				}
			}
		}
		else if (tars_unlikely(isRequire))
		{
			char s[128];
			snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag);
			throw TarsDecodeRequireNotExist(s);
		}
	}


	template
	void read(std::map& m, uint8_t tag, bool isRequire = true)
	{
		uint8_t headType = 0, headTag = 0;
		bool skipFlag = false;
		TarsSkipToTag(skipFlag, tag, headType, headTag);
		if (tars_likely(skipFlag))
		{
			switch(headType)
			{
				case TarsHeadeMap:
				{
					UInt32 size = 0;
					read(size, 0);
					if (tars_unlikely(size > this->size()))
					{
						char s[128];
						snprintf(s, sizeof(s), "invalid map, tag: %d, size: %d", tag, size);
						throw TarsDecodeInvalidValue(s);
					}
					m.clear();

					for (UInt32 i = 0; i < size; ++i)
					{
						std::pair pr;
						read(pr.first, 0);
						read(pr.second, 1);
						m.insert(pr);
					}
				}
					break;
				default:
				{
					char s[64];
					snprintf(s, sizeof(s), "read 'map' type mismatch, tag: %d, get type: %d.", tag, headType);
					throw TarsDecodeMismatch(s);
				}
			}
		}
		else if (tars_unlikely(isRequire))
		{
			char s[64];
			snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag);
			throw TarsDecodeRequireNotExist(s);
		}
	}

	template
	void read(std::vector& v, uint8_t tag, bool isRequire = true)
	{
	      cout << "line = "<<__LINE__<<", 调用了read(std::vector& v, uint8_t tag, bool isRequire = true)"< this->size()))
					{
						char s[128];
						snprintf(s, sizeof(s), "invalid size, tag: %d, type: %d, %d, size: %d", tag, headType, hheadType, size);
						throw TarsDecodeInvalidValue(s);
					}

					this->readBuf(v, size);
				}
					break;
				case TarsHeadeList:
				{
					UInt32 size = 0;
					read(size, 0);
					if (tars_unlikely(size > this->size()))
					{
						char s[128];
						snprintf(s, sizeof(s), "invalid size, tag: %d, type: %d, size: %d", tag, headType, size);
						throw TarsDecodeInvalidValue(s);
					}
					v.reserve(size);
					v.resize(size);
					for (UInt32 i = 0; i < size; ++i)
						read(v[i], 0);
				}
					break;
				default:
				{
					char s[128];
					snprintf(s, sizeof(s), "type mismatch, tag: %d, type: %d", tag, headType);
					throw TarsDecodeMismatch(s);
				}
			}
                
                int i = v.size();
                for(i = 0;i& v, uint8_t tag, bool isRequire = true) 快要调用结束啦"<
	void read(std::vector& v, uint8_t tag, bool isRequire = true)
	{
            cout << "line = "<<__LINE__<<",调用了read(std::vector& v, uint8_t tag, bool isRequire = true)"< this->size()))
					{
						char s[128];
						snprintf(s, sizeof(s), "invalid size, tag: %d, type: %d, size: %d", tag, headType, size);
						throw TarsDecodeInvalidValue(s);
					}
					v.reserve(size);
					v.resize(size);
					for (UInt32 i = 0; i < size; ++i)
						read(v[i], 0);
				}
					break;
				default:
				{
					char s[64];
					snprintf(s, sizeof(s), "read 'vector' type mismatch, tag: %d, get type: %d.", tag, headType);
					throw TarsDecodeMismatch(s);
				}
			}
		}
		else if (tars_unlikely(isRequire))
		{
			char s[64];
			snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag);
			throw TarsDecodeRequireNotExist(s);
		}
	}

	/// 读取结构数组
	template
	void read(T* v, const UInt32 len, UInt32 & readLen, uint8_t tag, bool isRequire = true)
	{
		uint8_t headType = 0, headTag = 0;
		bool skipFlag = false;
		TarsSkipToTag(skipFlag, tag, headType, headTag);
		if (tars_likely(skipFlag))
		{
			switch(headType)
			{
				case TarsHeadeList:
				{
					UInt32 size = 0;
					read(size, 0);
					if (tars_unlikely(size > this->size()))
					{
						char s[128];
						snprintf(s, sizeof(s), "invalid size, tag: %d, type: %d, size: %d", tag, headType, size);
						throw TarsDecodeInvalidValue(s);
					}
					for (UInt32 i = 0; i < size; ++i)
						read(v[i], 0);
					readLen = size;
				}
					break;
				default:
				{
					char s[64];
					snprintf(s, sizeof(s), "read 'vector struct' type mismatch, tag: %d, get type: %d.", tag, headType);
					throw TarsDecodeMismatch(s);
				}
			}
		}
		else if (tars_unlikely(isRequire))
		{
			char s[64];
			snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag);
			throw TarsDecodeRequireNotExist(s);
		}
	}

	template
	void read(T& v, uint8_t tag, bool isRequire = true, typename detail::disable_if, void ***>::type dummy = 0)
	{
		Int32 n = 0;
		read(n, tag, isRequire);
		v = (T) n;
	}

	/// 读取结构
	template
	void read(T& v, uint8_t tag, bool isRequire = true, typename detail::enable_if, void ***>::type dummy = 0)
	{
		uint8_t headType = 0, headTag = 0;
		bool skipFlag = false;
		TarsSkipToTag(skipFlag, tag, headType, headTag);
		if (tars_likely(skipFlag))
		{
			if (tars_unlikely(headType != TarsHeadeStructBegin))
			{
				char s[64];
				snprintf(s, sizeof(s), "read 'struct' type mismatch, tag: %d, get type: %d.", tag, headType);
				throw TarsDecodeMismatch(s);
			}
			v.readFrom(*this);
			skipToStructEnd();
		}
		else if (tars_unlikely(isRequire))
		{
			char s[64];
			snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag);
			throw TarsDecodeRequireNotExist(s);
		}
	}
};

void resetDefautlt()
{
            iVersion = 0;
            cPacketType = 0;
            iRequestId = 0;
            iMessageType = 0;
            iRet = 0;
}





class Buffer
{

    public:
	    Buffer() { }
	    Buffer(const vector &sBuffer) : _buffer(sBuffer) {}
	    Buffer(const char *sBuffer, size_t length) : _buffer(sBuffer, sBuffer+length) {}

        void swap(vector &buff, size_t pos = 0)
        {
	    	if(_pos != 0)
		{
	    	    buff.resize(length());
	    	    memcpy(&buff[0], buffer(), length());
		}
	      else
                {
			    buff.swap(_buffer);
		}
	      _pos = pos;
        }

        void clear()
        {
            _buffer.clear();
	        _pos = 0;
        }

        bool empty() const
        {
            return _buffer.size() <= _pos;
        }

        void addBuffer(const vector &buffer)
        {
            _buffer.insert(_buffer.end(), buffer.begin(), buffer.end());
        }

        void assign(const char *buffer, size_t length, size_t pos = 0)
        {
            _buffer.assign(buffer, buffer + length);
	        _pos = pos;
        }

        void setBuffer(const vector &buff, size_t pos = 0)
        {
	        _buffer  = buff;
	        _pos     = pos;
        }

	    char *buffer() { return _buffer.data() + _pos; }

        const char *buffer() const { return _buffer.data() + _pos; }

        size_t length() const { return _buffer.size() - _pos; }

        size_t pos() const { return _pos; }

        char &at(size_t offset)
        {
	    	if(_pos + offset >= _buffer.size() )
               {
                    cout << "line ="<<__LINE__<<"[TC_NetWorkBuffer::Buffer] at offset overflow" <= _buffer.size() )
		     {
                           cout << "line ="<<__LINE__<<"[TC_NetWorkBuffer::Buffer] at offset overflow" <    _buffer;
	    size_t          _pos = 0;

    };


enum PACKET_TYPE
{
        PACKET_LESS = 0,
        PACKET_FULL = 1,
	  PACKET_FULL_CLOSE = 2,  ///< get whole package, and need close connection, for example: http
        PACKET_ERR  = -1,   
};

size_t _length = 0;

std::list> _bufferList;

size_t getBufferLength()
{
    cout<<"line is "<<__LINE__<<"_length is "<<_length<< endl;
    return _length;
}




template
T getHeader(size_t len) 
{
		if(getBufferLength() < len)
		{
			cout<<"line is "<<__LINE__<< "[TC_NetWorkBuffer::getHeader] no enough buff "<length());

		memcpy(buffer + pos, (*it)->buffer(), len);

		left -= len;
		pos += len;

		++it;
	}

	return pos;
}


vector getBuffers() 
{
    vector buffer;

    buffer.resize(_length);

	getBuffers(&buffer[0], _length);

	return buffer;
}


bool getHeader(size_t len, std::string &buffer)
{
    cout<<"line is "<<__LINE__<< endl;
    if(getBufferLength() < len)
        return false;
  
    cout<<"line is "<<__LINE__<< endl;
    buffer.clear();
 
    cout<<"line is "<<__LINE__<< endl;

    if(len == 0)
    {
        return true;
    }

    cout<<"line is "<<__LINE__<< endl;
    buffer.resize(len);

    cout<<"line is "<<__LINE__<< endl;
    getBuffers(&buffer[0], len);

    return true;
}

bool getHeader(size_t len, std::vector &buffer)
{
    if(getBufferLength() < len)
        return false;

    buffer.clear();

    if(len == 0)
    {
        return true;
    }

    buffer.resize(len);

	getBuffers(&buffer[0], len);

    return true;
}

bool moveHeader(size_t len)
{
    if(getBufferLength() < len)
     {
       cout << "line = "<<__LINE__<<",getBufferLength()  is "<< getBufferLength() << ", len is "<< len <size() >= _pos);

    size_t left = (*it)->length();

    if(left > len)
    {
	    (*it)->add(len);
        _length -= len;
    }
    else if(left == len)
    {
        _length -= len;
        _bufferList.erase(it);
    }
    else
    {
        _length -= left;

        _bufferList.erase(it);

        return moveHeader(len - left);
    }
    return true;
}



template
T getValue()
{
	  vector buffer;

        if(getHeader(sizeof(T), buffer))
        {
            if(sizeof(T) == 2)
            {
                return ntohs(*(uint16_t*)buffer.data());
            }
            else if(sizeof(T) == 4)
            {
                return ntohl(*(uint32_t*)buffer.data());
            }
            return *((T*)buffer.data());
        }
        return 0;
 }

 

template
PACKET_TYPE parseBuffer(vector &buffer, T minLength, T maxLength)
{
      cout <<"line = "<<__LINE__<<", enter function parseBuffer" << endl;
      if(getBufferLength() < sizeof(T))
        {
            cout <<"line = "<<__LINE__<<", getBufferLength() is "<< _length << ",sizeof(T) is "<< sizeof(T) << endl;
            return PACKET_LESS;
        }
      cout <<"line = "<<__LINE__ << endl;
        if(minLength < sizeof(T))
            minLength = sizeof(T);
      
      cout <<"line = "<<__LINE__ << endl;
        T length = getValue();
        
      cout <<"line = "<<__LINE__ << endl;
      if(length < minLength || length > maxLength)
        {
            return PACKET_ERR;
        }

        if(getBufferLength() < length)
        {
            return PACKET_LESS;
        }

        //往后移动
		//move backward
        moveHeader(sizeof(T));

        //读取length长度的buffer
	//Read buffer of length length
        if(!getHeader(length - sizeof(T), buffer))
        {
            return PACKET_LESS;
        }

        moveHeader(length - sizeof(T));
        return PACKET_FULL;
}

PACKET_TYPE parseBufferOf4(vector &buffer, uint32_t minLength, uint32_t maxLength)
{
     cout <<"line = "<<__LINE__<<", enter function parseBufferOf4" << endl;
     return parseBuffer(buffer, minLength, maxLength);
}

// 这里用的是ResponsePacket那一部分的代码,解码,代码路径D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\servant\tup\Tars.h
template
void readFrom(TarsInputStream& _is)
{
               
            resetDefautlt();
            cout <<"line = "<<__LINE__<<" ,start to  _is.read(iVersion, 1, true);====================================================================================================" << endl; 
            _is.read(iVersion, 1, true);


            cout <<"line = "<<__LINE__<<" ,start to  _is.read(cPacketType, 2, true);====================================================================================================" << endl; 
            _is.read(cPacketType, 2, true);


            cout <<"line = "<<__LINE__<<" ,start to  _is.read(iRequestId, 3, true);====================================================================================================" << endl; 
            _is.read(iRequestId, 3, true);


            cout <<"line = "<<__LINE__<<" ,start to  _is.read(iMessageType, 4, true);====================================================================================================" << endl; 
            _is.read(iMessageType, 4, true);


            cout <<"line = "<<__LINE__<<" ,start to  _is.read(iRet, 5, true);====================================================================================================" << endl;
            _is.read(iRet, 5, true);

               
            cout <<"line = "<<__LINE__<<" ,start to  _is.read(sBuffer, 6, true);====================================================================================================" << endl;
            _is.read(sBuffer, 6, true);
            //_is.read(status, 7, true);
            //_is.read(sResultDesc, 8, false);
            //_is.read(context, 9, false);
}



int main(){
	printf("__GNUC__ = %d\n",__GNUC__); 
	TarsOutputStream os;
	vector buffer;
	string res = "aaaa";
	buffer.assign(res.begin(),res.end());// 将res的值赋值到buffer中
	status["status"] = "status";
	map _responseContext;
	_responseContext["context"] = "context";

	iVersion       = TARSVERSION;//tag 1   value1  type Short
	cPacketType    = TARSNORMAL; //tage2   value0  type Char
	iRequestId     = 1;          //tag 3   value1  type Int32 
	iMessageType   = 0;          //tag 4   value0  type Int32
	iRet = 1;                    //tag 5   value1
	//iRet = 0;                    //tag 5   value0
	sBuffer        = buffer;     //tage 6  value(aaaa) 将buffer的值赋值给sBuffer,后续会调用_os.write(sBuffer, 6);
	status         = status;     //tage 7  value(<"status","status">)        type map
	sResultDesc    = "123";            //tag  8  value("123") type std::string
	context        = _responseContext; //tag  9  value(<"context","context">)  
      cout <<"line is "<<__LINE__<< ",开始解码啦***************************************************************************************************************************************************"< is;
        // 设置读的缓存,void setBuffer(const char * buf, size_t len), D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\servant\tup\Tars.h中的609行
       is.setBuffer(os._buf, os._buf_len);
	 

	 readFrom(is);
                           /* 
                        static TC_NetWorkBuffer::PACKET_TYPE tarsResponseLen(TC_NetWorkBuffer &in, ResponsePacket& rsp) 这个函数对应着呆小板所说的那个responseFunc
                        D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\servant\servant\AppProtocol.h
                           */
         
     




}

/*
//Int32 iVersion;
Short iVersion;
Char cPacketType;
Int32 iMessageType;
Int32 iRequestId;
string sServantName;
string sFuncName;
std::string sResultDesc;
vector sBuffer;
Int32 iTimeout;
map context;
map status;
Int32 iRet;
*/




 

 

 

 

 

 

你可能感兴趣的:(开源软件)