目录
扫描二维码关注公众号,回复:
12730558 查看本文章
6.2响应包体中每个成员变量的序列化后的组成部分HEAD+BUF
0.现有编解码方式
1.编解码
官方引用阅读-02-关于协议,Tars文件以及翻译工具tars2node的说明
编码-序列化
解码-反序列化
序列化:将对象变为二进制内容,写入到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<byte> sBuffer; 8 require int iTimeout = 0; 9 require map<string, string> context; 10 require map<string, string> 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<byte> sBuffer; 7 require map<string, string> status; 8 optional string sResultDesc; 9 optional map<string, string> 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<typename WriterT>
void writeTo(tars::TarsOutputStream<WriterT>& _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<typename ReaderT>
void readFrom(tars::TarsInputStream<ReaderT>& _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<typename WriterT>
void writeTo(tars::TarsOutputStream<WriterT>& _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<typename ReaderT>
void readFrom(tars::TarsInputStream<ReaderT>& _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<byte> sBuffer;
7 require map<string, string> status;
8 optional string sResultDesc;
9 optional map<string, string> 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<typename WriterT> // line 204 ,ver 2-14-2
void writeTo(tars::TarsOutputStream<WriterT>& _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路小饭的协议反序列化测试示例
路小饭的文章链接-访问原文可以看到路小饭提供的测试代码-谢谢路小饭啦
//learn-tars/tup/main.cpp 56 //反序列化 57 58 list<ResponsePacket> 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<typename ReaderT> 167 void readFrom(tars::TarsInputStream<ReaderT>& _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 "<<std::endl; 1108 uint8_t headType = 0, headTag = 0; 1109 bool skipFlag = false; //TarsSkipToTag方法会确认TYPE和TAG的值 1110 TarsSkipToTag(skipFlag, tag, headType, headTag); 1111 if (tars_likely(skipFlag)) 1112 { //根据headType的值确定后面|BUF|内容的长度 1113 switch (headType) 1114 { 1115 case TarsHeadeZeroTag: 1116 std::cout<<"read Short TarsHeadeZeroTag"<<std::endl; 1117 n = 0; 1118 break; 1119 case TarsHeadeChar: 1120 std::cout<<"read Char TarsHeadeChar"<<std::endl; 1121 TarsReadTypeBuf(*this, n, Char); 1122 break; 1123 case TarsHeadeShort: 1124 std::cout<<"read Short TarsHeadeShort"<<std::endl; 1125 TarsReadTypeBuf(*this, n, Short); 1126 n = ntohs(n); 1127 break; 1128 default: 1129 { 1130 char s[64]; 1131 snprintf(s, sizeof(s), "read 'Short' type mism atch, tag: %d, get type: %d.", tag, headType); 1132 throw TarsDecodeMismatch(s); 1133 } 1134 } 1135 } 1136 else if (tars_unlikely(isRequire)) 1137 { 1138 char s[64]; 1139 snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); 1140 throw TarsDecodeRequireNotExist(s); 1141 } 1142 std::cout<<"read Short n is "<<n<<std::endl; 1143 1144 } 1110行函数TarsSkipToTag会确认TYPE和TAG的值 1113行会根据headType的值确定后面|BUF|内容的长度 再看下TarsSkipToTag是怎么处理的: //learn-tars/tup/Tars.h 335 #define TarsSkipToTag(flag, tag, retHeadType, retHeadTag) \ 336 do { \ 337 try \ 338 { \ 339 uint8_t nextHeadType, nextHeadTag; \ 340 while (!ReaderT::hasEnd()) \ 341 { \ 342 size_t len = 0; \ //TarsPeekFromHead里进行了运算,得到TYPE和TAGE 343 TarsPeekFromHead(*this, nextHeadType, nextHeadTag, len); \ 344 if (tars_unlikely(nextHeadType == TarsHeadeStructEnd || ta g < nextHeadTag)) \ 345 { \ 346 break; \ 347 } \ 348 if (tag == nextHeadTag) \ 349 { \ 350 std::cout<<"TarsSkipToTag tag == nextHeadTag"<<std::en dl; \ 351 (retHeadType) = nextHeadType; \ 352 (retHeadTag) = nextHeadTag; \ 353 TarsReadHeadSkip(*this, len); \ 354 (flag) = true; \ 355 break; \ 356 } \ 357 std::cout<<"TarsSkipToTag tag != nextHeadTag"<<std::endl; \ 358 TarsReadHeadSkip(*this, len); \ 359 skipField(nextHeadType); \ 360 } \ 361 } \ 362 catch (TarsDecodeException& e) \ 363 { \ 364 } \ 365 } while(0) 343 行TarsPeekFromHead函数里得到了nextHeadType和nextHeadTag,对应着9.2.7节中的运算 //learn-tars/tup/Tars.h 255 #define TarsPeekFromHead(is, type, tag, n) \ 256 do { \ 257 std::cout<<"TarsPeekFromHead begin"<<std::endl; \ 258 (n) = 1; \ 259 uint8_t typeTag, tmpTag; \ 260 TarsPeekTypeBuf(is, typeTag, 0, uint8_t); \ 261 std::cout<<"TarsPeekFromHead typeTag "<<(int)typeTag<<std::endl; \ 262 tmpTag = typeTag >> 4; \ 263 std::cout<<"TarsPeekFromHead tmpTag "<<(int)tmpTag<<std::endl; \ 264 (type) = (typeTag & 0x0F); \ 265 std::cout<<"TarsPeekFromHead type "<<(int)type<<std::endl; \ 266 if(tars_unlikely(tmpTag == 15)) \ 267 { \ 268 std::cout<<"TarsPeekFromHead unlikely tmpTag "<<(int)tmpTag<<s td::endl; \ 269 TarsPeekTypeBuf(is, tag, 1, uint8_t); \ 270 (n) += 1; \ 271 } \ 272 else \ 273 { \ 274 (tag) = tmpTag; \ 275 } \ 276 } while(0) 路小饭于2019-04-12
8.我自己写的测试序列化和反序列化的测试程序及逻辑说明
// 编译的时候加上-std=c++11
#include <iostream>
#include <cassert>
#include <vector>
#include <map>
#include <string>
#include <stdexcept>
#include <functional>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <bitset>
#include <list>
#include <memory>
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<Char> sBuffer;
Int32 iTimeout;
map<std::string, std::string> context;
map<std::string, std::string> 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 <<endl;
bitset<128> bstr ;
for(int i=0;i<16;i++)
{
//cout << "str["<<i<<"] is " << str[i] << endl;
bitset<8> bits = bitset<8>(str[i]);
for(int j = 0;j<8;j++)
{
bstr[i*8+j] = bits[j];
//cout << "i*8 + j = " <<i*8 + j<<", bstr[i*8+j]" << bstr[i*8+j] <<endl;
}
}
return bstr.to_string();
}
#ifndef TARS_MAX_STRING_LENGTH
#define TARS_MAX_STRING_LENGTH (100 * 1024 * 1024)
#endif
class DataHead
{
uint8_t _type;
uint8_t _tag;
public:
enum
{
eChar = 0,
eShort = 1,
eInt32 = 2,
eInt64 = 3,
eFloat = 4,
eDouble = 5,
eString1 = 6,
eString4 = 7,
eMap = 8,
eList = 9,
eStructBegin = 10,
eStructEnd = 11,
eZeroTag = 12,
eSimpleList = 13,
};
#pragma pack(1)
struct helper
{
uint8_t type : 4;
uint8_t tag : 4;
};
#pragma pack()
public:
DataHead() : _type(0), _tag(0) {}
DataHead(uint8_t type, uint8_t tag) : _type(type), _tag(tag) {}
uint8_t getTag() const { return _tag;}
void setTag(uint8_t t) { _tag = t;}
uint8_t getType() const { return _type;}
void setType(uint8_t t) { _type = t;}
/// 读取数据头信息
template<typename InputStreamT>
void readFrom(InputStreamT& is)
{
size_t n = peekFrom(is);
is.skip(n);
}
/// 读取头信息,但不前移流的偏移量
template<typename InputStreamT>
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<typename OutputStreamT>
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<typename OutputStreamT>
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<char*(BufferWriter &, size_t)> _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 "<<len<<endl;\
size_t len1 = (len)<<1; \
cout << "line = 198 TarsReserveBuf ,经过(len)<<1计算的len1 的值是 "<<len1<<endl;\
if(len1<128) len1=128; \
cout << "line = 200 TarsReserveBuf ,最后经过逻辑赋值的len1的值是 "<<len1<<", will enter BufferWriter::reserve function "<<endl;\
(os)._buf = (os)._reserve(os, len1); \
(os)._buf_len = (len1); \
cout << "line = 203,经过BufferWriter::reserve后(os)._buf is [ "<<(os)._buf<<"], (os)._buf_len is "<< (os)._buf_len<<",(os)_len is "<<(os)._len <<endl;\
} \
}while(0)
/*
TAG由TAG1和TAG2一起组成,标识数据的位置。当TAG值不超过14时候,只需要TAG1,当TAG值超过14时候,TAG1为240,TAG2标识TAG的值。下面的代码标明了这个逻辑:
具体看个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)
tars_likely((tag) < 15)时候只有TAG1,当tars_likely((tag) >= 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 "<<type << ",tag is ["<< (int)tag <<"]"<< endl;\
} \
else \
{ \
cout << "line = 235 "<<__LINE__<<",type is "<<type << "tag is "<< tag <<",注意注意,您已进入写协议头的函数,此次会有两个tag噢,tag is "<<(int)tag<< endl;\
TarsWriteUInt8TTypeBuf( os, (type) + (240) , (os)._len); \
TarsWriteUInt8TTypeBuf( os, (tag), (os)._len);\
} \
} while(0)//TarsWriteCharTypeBuf(*this, n, (*this)._len),在调用TarsWriteCharTypeBuf的时候第三个参数传递的是指针,osLen变化会导致(*this)._len的变化
#define TarsWriteCharTypeBuf(os, val, osLen) \
do { \
cout << "line = 245, val is ["<< (int)val << "],osLen is "<< osLen<<","<<",将要开始调用TarsReserveBuf,(os)._buf_len is "<< (os)._buf_len <<",(osLen)+sizeof(Char) is "<<(osLen)+sizeof(Char) <<endl;\
TarsReserveBuf(os, (osLen)+sizeof(Char)); \
(*(Char *)((os)._buf + (osLen))) = (val); \
cout << "line 248,(os)._buf is "<< (os)._buf<<"(os)._len is "<<(os)._len << endl;\
(osLen) += sizeof(Char); \
cout << "line 250,(os)._buf is "<< (os)._buf<<"(os)._len is "<<(os)._len << endl;\
} while(0)
#define TarsWriteInt32TypeBuf(os, val, osLen) \
do { \
cout << "line = 258 "<<__LINE__<<endl;\
TarsReserveBuf(os, (osLen)+sizeof(Int32)); \
(*(Int32 *)((os)._buf + (osLen))) = (val); \
(osLen) += sizeof(Int32); \
} while(0)
#define TarsWriteInt64TypeBuf(os, val, osLen) \
do { \
cout << "line = 266 "<<__LINE__<<endl;\
TarsReserveBuf(os, (osLen)+sizeof(Int64)); \
(*(Int64 *)((os)._buf + (osLen))) = (val); \
(osLen) += sizeof(Int64); \
} while(0)
#define TarsWriteFloatTypeBuf(os, val, osLen) \
do { \
cout << "line = 274 "<<__LINE__<<endl;\
TarsReserveBuf(os, (osLen)+sizeof(Float)); \
(*(Float *)((os)._buf + (osLen))) = (val); \
(osLen) += sizeof(Float); \
} while(0)
#define TarsWriteDoubleTypeBuf(os, val, osLen) \
do { \
cout << "line = 282 "<<__LINE__<<endl;\
TarsReserveBuf(os, (osLen)+sizeof(Double)); \
(*(Double *)((os)._buf + (osLen))) = (val); \
(osLen) += sizeof(Double); \
} while(0)
#define TarsWriteUInt32TTypeBuf(os, val, osLen) \
do { \
cout << "line = 290 "<<__LINE__<<endl;\
TarsReserveBuf(os, (osLen)+sizeof(uint32_t)); \
(*(uint32_t *)((os)._buf + (osLen))) = (val); \
(osLen) += sizeof(uint32_t); \
} while(0)
// 调用方法:TarsWriteUInt8TTypeBuf(*this, n, (*this)._len);
#define TarsWriteUInt8TTypeBuf(os, val, osLen) \
do { \
cout << "line = 302,TarsWriteUInt8TTypeBuf ,val is "<< (int)val <<", osLen is "<<osLen<<", [(osLen)+sizeof(uint8_t)] is "<<( (osLen)+sizeof(uint8_t) )<<endl;\
cout << "line 303,(os)._len is "<<(os)._len << endl;\
TarsReserveBuf(os, (osLen)+sizeof(uint8_t)); \
cout << "line 305,(os)._buf is 【"<< (os)._buf<<"】,(os)._len is "<<(os)._len <<", StrToBitStr((os)._buf) is "<< StrToBitStr((os)._buf)<< endl;\
(*(uint8_t *)((os)._buf + (osLen))) = (val); \
(osLen) += sizeof(uint8_t); \
cout << "line 308 ,(os)._buf is 【"<< (char*)(os)._buf<<"】,(os)._len is "<<(os)._len <<", StrToBitStr((os)._buf) is "<< StrToBitStr((os)._buf)<< endl;\
} while(0)
#define TarsWriteUIntTypeBuf(os, val, osLen) \
do { \
cout << "line = 312 "<<__LINE__<<endl;\
TarsReserveBuf(os, (osLen)+sizeof(unsigned int)); \
(*(unsigned int *)((os)._buf + (osLen))) = (val); \
(osLen) += sizeof(unsigned int); \
} while(0)
#define TarsWriteShortTypeBuf(os, val, osLen) \
do { \
cout << "line = 320 "<<endl;\
TarsReserveBuf(os, (osLen)+sizeof(Short)); \
(*(Short *)((os)._buf + (osLen))) = (val); \
(osLen) += sizeof(Short); \
} while(0)
//memcpy(p, (os)._buf, (os)._len);//void *memcpy(void *dest, void *src, unsigned int count);把资源内存(src所指向的内存区域) 拷贝到目标内存(dest所指向的内存区域);拷贝多少个?有一个count变量控制
#define TarsWriteTypeBuf(os, buf, len) \
do { \
cout << "line = 347 ,len is "<<len<<", buf is 【" << (char *)(buf)<< "】"<<"StrToBitStr(((char *)(buf)) is "<<StrToBitStr(buf) <<",(os)._len is "<<(os)._len<< endl;\
TarsReserveBuf(os, (os)._len + (len)); \
cout<< "line = 349 StrToBitStr((os)._buf) is "<< StrToBitStr((os)._buf)<<",(os)._buf is"<< (os)._buf << ",(os)._len "<< (os)._len << endl;\
cout << "line = 350 ,buf is "<< buf <<endl;\
memcpy((os)._buf + (os)._len, (const void *)(buf), (len)); \
(os)._len += (len); \
cout << "line = 353,(os)._len = "<<(os)._len<<", (os)._buf[9] = "<< (os)._buf[9]<<", (os)._buf[10] = "<< (os)._buf[10]<<", (os)._buf[11] = "<< (os)._buf[11]<<endl;\
cout << "line = 353,(os)._len = "<<(os)._len<<", (os)._buf[12] = "<< (int)((os)._buf[12])<<", (os)._buf[13] = "<< (os)._buf[13]<<", (os)._buf[14] = "<< (os)._buf[14]<<", (os)._buf[15] = "<< (os)._buf[15]<<endl;\
cout<< "line = 354 StrToBitStr((os)._buf) is "<< StrToBitStr((os)._buf)<< endl;\
} while(0)
namespace detail
{
union bswap_helper
{
Int64 i64;
Int32 i32[2];
};
// is_convertible
template<int N> 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 <typename T> any_conversion(const volatile T&);
template <typename T> any_conversion(T&);
};
template <typename T> struct conversion_checker
{
static no_type _m_check(any_conversion ...);
static yes_type _m_check(T, int);
};
}
template<typename From, typename To>
class is_convertible
{
static From _m_from;
public:
enum { value = sizeof( meta_detail::conversion_checker<To>::_m_check(_m_from, 0) ) == sizeof(yes_type) };
};
template<typename T>
struct type2type { typedef T type; };
template<typename T, typename U>
struct is_same_type
{
enum { value = is_convertible< type2type<T>, type2type<U> >::value };
};
// enable_if
template<bool B, class T = void> struct enable_if_c { typedef T type; };
template<class T> struct enable_if_c<false, T> {};
template<class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
template<bool B, class T = void> struct disable_if_c { typedef T type; };
template<class T> struct disable_if_c<true, T> {};
template<class Cond, class T = void>
struct disable_if : public disable_if_c<Cond::value, T> {};
}
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<char*(BufferWriter &, size_t)> _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 <<endl; if((os)._buf == NULL) cout << "(os)._buf is NULL"<<endl;
memcpy(p, (os)._buf, (os)._len);//void *memcpy(void *dest, void *src, unsigned int count);把资源内存(src所指向的内存区域) 拷贝到目标内存(dest所指向的内存区域);拷贝多少个?有一个count变量控制
delete[] (os)._buf;
return p;
}
private:
BufferWriter(const BufferWriter & bw);
BufferWriter& operator=(const BufferWriter& buf);
public:
BufferWriter()
: _buf(NULL)
, _len(0)
, _buf_len(0)
{}
~BufferWriter()
{
delete[] _buf;
}
void reset() { _len = 0;}
void writeBuf(const char * buf, size_t len)
{
TarsReserveBuf(*this, _len + len);
memcpy(_buf + _len, buf, len);
_len += len;
}
std::vector<char> getByteBuffer() const { return std::vector<char>(_buf, _buf + _len);}
const char * getBuffer() const { return _buf;}
size_t getLength() const { return _len;}
void swap(std::vector<char>& 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<typename WriterT = BufferWriter>
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 "<<TarsHeadeZeroTag<< endl;
TarsWriteToHead(*this, TarsHeadeZeroTag, tag);
cout << "line = "<< __LINE__<< ", 经过写头BUF 的信息之后,序列化为:【"<< StrToBitStr((*this)._buf)<<"】."<<endl;
}
else
{
cout << "line = "<< __LINE__<< ", it will call func TarsWriteToHead ," <<"tag is "<<(int)tag<<",TarsHeadeChar is "<<TarsHeadeChar<< endl;
TarsWriteToHead(*this, TarsHeadeChar, tag);
cout << "line = "<< __LINE__<< ", 经过写头HEAD的信息之后,序列化为:【"<< StrToBitStr((*this)._buf)<<"】, it will call func TarsWriteCharTypeBuf"<<endl;
TarsWriteCharTypeBuf(*this, n, (*this)._len);
cout << "line = "<< __LINE__<< ", 经过写头BUF 的信息之后,序列化为:【"<< StrToBitStr((*this)._buf)<<"】."<<endl;
}
}
void write(UInt8 n, uint8_t tag)
{
cout << "line = "<< __LINE__<< ", call func " <<__func__<< endl;
write((Short) n, tag);
}
void write(Short n, uint8_t tag)
{
cout << "line = "<< __LINE__<< ", n = " <<n<<",call func write(Short,uint8_t),tag is ["<<(int)tag<<"]"<< endl;
if (n >= (-128) && n <= 127)
{
cout << "line = "<< __LINE__<< ",n>=(-128) & n <= 127" <<endl;
write((Char) n, tag);
}
else
{
cout << "line = "<< __LINE__<< ", it will call func TarsWriteToHead ," <<"tag is "<<(int)tag<<",TarsHeadeShort is "<<TarsHeadeShort<< endl;
TarsWriteToHead(*this, TarsHeadeShort, tag);
cout << "line = "<< __LINE__<< ", 经过写头HEAD的信息之后,序列化为:【"<< StrToBitStr((*this)._buf)<<"】, it will call func TarsWriteShortTypeBuf"<<endl;
n = htons(n);
TarsWriteShortTypeBuf(*this, n, (*this)._len);
cout << "line = "<< __LINE__<< ", 经过写头BUF 的信息之后,序列化为:【"<< StrToBitStr((*this)._buf)<<"】."<<endl;
}
}
void write(UInt16 n, uint8_t tag)
{
cout << "line = "<< __LINE__<< ", call func " <<__func__<< endl;
write((Int32) n, tag);
}
void write(Int32 n, uint8_t tag)
{
cout << "line = "<< __LINE__<< ", call func write, n is Int32(0010),tage is " <<(int)tag<< endl;
if (n >= (-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"<<endl;
n = htonl(n);
TarsWriteInt32TypeBuf(*this, n, (*this)._len);
cout << "line = "<< __LINE__<< ", 经过写头BUF 的信息之后,序列化为:【"<< StrToBitStr((*this)._buf)<<"】."<<endl;
}
}
void write(UInt32 n, uint8_t tag)
{
cout << "line = "<< __LINE__<< ", call func " <<__func__<< endl;
write((Int64) n, tag);
}
void write(Int64 n, uint8_t tag)
{
cout << "line = "<< __LINE__<< ", call func " <<__func__<< endl;
if (n >= (-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 "<<TarsHeadeInt64<< endl;
TarsWriteToHead(*this, TarsHeadeInt64, tag);
cout << "line = "<< __LINE__<< ", 经过写头HEAD的信息之后,序列化为:【"<< StrToBitStr((*this)._buf)<<"】, it will call func TarsWriteInt64TypeBuf"<<endl;
n = tars_htonll(n);
TarsWriteInt64TypeBuf(*this, n, (*this)._len);
cout << "line = "<< __LINE__<< ", 经过写头BUF 的信息之后,序列化为:【"<< StrToBitStr((*this)._buf)<<"】."<<endl;
}
}
void write(Float n, uint8_t tag)
{
cout << "line = "<< __LINE__<< ", call func " <<__func__<< endl;
TarsWriteToHead(*this, TarsHeadeFloat, tag);
n = tars_htonf(n);
TarsWriteFloatTypeBuf(*this, n, (*this)._len);
}
void write(Double n, uint8_t tag)
{
cout << "line = "<< __LINE__<< ", call func " <<__func__<< endl;
TarsWriteToHead(*this, TarsHeadeDouble, tag);
n = tars_htond(n);
TarsWriteDoubleTypeBuf(*this, n, (*this)._len);
}
void write(const std::string& s, uint8_t tag)
{
cout << "line = "<< __LINE__<< ", call func write(const std::string&,uint8_t). s.size() is "<< s.size()<< endl;
if (tars_unlikely(s.size() > 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"<<endl;
uint8_t n = (uint8_t)s.size();
cout << "line = "<< __LINE__<< ", n = "<<(int)n<< endl;
TarsWriteUInt8TTypeBuf(*this, n, (*this)._len);
TarsWriteTypeBuf(*this, s.data(), s.size());
cout << "line = "<< __LINE__<< ", 经过写头BUF 的信息之后,序列化为:【"<< StrToBitStr((*this)._buf)<<"】."<<endl;
}
}
void write(const char *buf, const UInt32 len, uint8_t tag)
{
cout << "line = "<< __LINE__<< ", call func " <<__func__<< endl;
TarsWriteToHead(*this, TarsHeadeSimpleList, tag);
TarsWriteToHead(*this, TarsHeadeChar, 0);
write(len, 0);
TarsWriteTypeBuf(*this, buf, len);
}
template<typename K, typename V, typename Cmp, typename Alloc>
void write(const std::map<K, V, Cmp, Alloc>& m, uint8_t tag)
{
cout << "line = "<< __LINE__<< ", call func write(const std::map<K,V,Cmp,Alloc>,uint8_t)." << endl;
TarsWriteToHead(*this, TarsHeadeMap, tag);
Int32 n = (Int32)m.size();
cout << "line = "<< __LINE__<< ", func write(const std::map<K,V,Cmp,Alloc>,uint8_t)中将要调用write(n, 0)并将要遍历容器map的对象m并且将调用write(i->first, 0)和write(i->second, 1)" << endl;
write(n, 0);
typedef typename std::map<K, V, Cmp, Alloc>::const_iterator IT;
for (IT i = m.begin(); i != m.end(); ++i)
{
write(i->first, 0);
write(i->second, 1);
}
}
template<typename T, typename Alloc>
void write(const std::vector<T, Alloc>& v, uint8_t tag)
{
cout << "line = "<< __LINE__<< ", call func write(const std::vector<T, Alloc>& v, uint8_t tag." << endl;
TarsWriteToHead(*this, TarsHeadeList, tag);
Int32 n = (Int32)v.size();
write(n, 0);
typedef typename std::vector<T, Alloc>::const_iterator IT;
for (IT i = v.begin(); i != v.end(); ++i)
write(*i, 0);
}
template<typename T>
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<typename Alloc>
void write(const std::vector<Char, Alloc>& v, uint8_t tag)
{
cout << "line = "<< __LINE__<< ", call func write(const std::vector<Char, Alloc>& 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<Char, Alloc>& 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<typename T>
void write(const T& v, uint8_t tag, typename detail::disable_if<detail::is_convertible<T*, TarsStructBase*>, void ***>::type dummy = 0)
{
write((Int32) v, tag);
}
template<typename T>
void write(const T& v, uint8_t tag, typename detail::enable_if<detail::is_convertible<T*, TarsStructBase*>, 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<typename WriterT>
void writeTo(TarsOutputStream<WriterT>& _os)
{
cout << "line = "<<__LINE__<<",_os.write(iVersion, 1) ====================================================================================================================" <<endl;
_os.write(iVersion, 1);
cout << "line = "<<__LINE__<<",_os.write(cPacketType, 2)==================================================================================================================" <<endl;
_os.write(cPacketType, 2);
cout << "line = "<<__LINE__<<",_os.write(iRequestId, 3)==================================================================================================================" <<endl;
_os.write(iRequestId, 3);
cout << "line = "<<__LINE__<<",_os.write(iMessageType, 4)=================================================================================================================="<<endl;
_os.write(iMessageType, 4);
cout << "line = "<<__LINE__<<",_os.write(iRet, 5)==========================================================================================================================" <<endl;
_os.write(iRet, 5);
cout << "line = "<<__LINE__<<",_os.write(sBuffer, 6)=======================================================================================================================" <<endl;
_os.write(sBuffer, 6);
/*
cout << "line = "<<__LINE__<<",_os.write(status, 7)=========================================================================================================================" <<endl;
_os.write(status, 7);
if (sResultDesc != "")
{
cout << "line = "<<__LINE__<<",_os.write(sResultDesc, 8)==================================================================================================================" <<endl;
_os.write(sResultDesc, 8);
}
if (context.size() > 0)
{
cout << "line = "<<__LINE__<<",_os.write(sResultDesc, 9)=================================================================================================================="<<endl;
_os.write(sResultDesc, 9);
}
cout << "line = "<<__LINE__<<",_os.write(iVersion, 16) ====================================================================================================================" <<endl;
_os.write(iVersion, 16);
*/
}
// 定义一些异常类
struct TarsProtoException : public std::runtime_error
{
TarsProtoException(const std::string& s) : std::runtime_error(s) {}
};
struct TarsEncodeException : public TarsProtoException
{
TarsEncodeException(const std::string& s) : TarsProtoException(s) {}
};
struct TarsDecodeException : public TarsProtoException
{
TarsDecodeException(const std::string& s) : TarsProtoException(s) {}
};
struct TarsDecodeMismatch : public TarsDecodeException
{
TarsDecodeMismatch(const std::string & s) : TarsDecodeException(s) {}
};
struct TarsDecodeRequireNotExist : public TarsDecodeException
{
TarsDecodeRequireNotExist(const std::string & s) : TarsDecodeException(s) {}
};
struct TarsDecodeInvalidValue : public TarsDecodeException
{
TarsDecodeInvalidValue(const std::string & s) : TarsDecodeException(s) {}
};
struct TarsNotEnoughBuff : public TarsProtoException
{
TarsNotEnoughBuff(const std::string & s) : TarsProtoException(s) {}
};
//解码相应的宏
#define TarsPeekTypeBuf(is, buf, 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); \
} \
(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" <<endl;\
TarsPeekBuf(is, buf, len, 0); \
(is)._cur += (len); \
} while(0)
#define TarsReadStringBuf(is, str, len) \
do{\
if (tars_unlikely((is)._cur + (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); \
} \
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" <<endl;\
uint8_t nextHeadType, nextHeadTag; \
while (!ReaderT::hasEnd()) \
{ \
cout << "line = 989 in mocro function TarsSkipToTag, ReaderT::hasEnd() is false" <<endl;\
size_t len = 0; \
cout << "line = 991 in mocro function TarsSkipToTag, will start function TarsPeekFromHead" <<endl;\
TarsPeekFromHead(*this, nextHeadType, nextHeadTag, len); \
cout << "line = 993 in mocro function TarsSkipToTag, this->_buf is 【"<< this->_buf <<"】,this->_buf_len is "<<this->_buf_len<<",this->_cur is "<< this->_cur<<endl;\
if (tars_unlikely(nextHeadType == TarsHeadeStructEnd || tag < nextHeadTag)) \
{ \
break; \
} \
if (tag == nextHeadTag) \
{ \
(retHeadType) = nextHeadType; \
(retHeadTag) = nextHeadTag; \
TarsReadHeadSkip(*this, len); \
(flag) = true; \
break; \
} \
TarsReadHeadSkip(*this, len); \
skipField(nextHeadType); \
} \
} \
catch (TarsDecodeException& e) \
{ \
} \
} while(0)
#if __BYTE_ORDER == __BIG_ENDIAN
# define tars_ntohll(x) (x)
# define tars_htonll(x) (x)
# define tars_ntohf(x) (x)
# define tars_htonf(x) (x)
# define tars_ntohd(x) (x)
# define tars_htond(x) (x)
#else
# if __BYTE_ORDER == __LITTLE_ENDIAN
# define tars_ntohll(x) tars_htonll(x)
# define tars_htonf(x) tars_ntohf(x)
# define tars_htond(x) tars_ntohd(x)
# endif
#endif
// 缓冲区读取封装器
class BufferReader
{
private:
BufferReader(const BufferReader&);
BufferReader& operator=(const BufferReader&);
public:
const char * _buf; ///< 缓冲区
size_t _buf_len; ///< 缓冲区长度
size_t _cur; ///< 当前位置
public:
BufferReader() : _buf(NULL),_buf_len(0),_cur(0) {}
void reset() { _cur = 0;}
/// 读取缓存
void readBuf(void * buf, size_t len)
{
if(len <= _buf_len && (_cur + len) <= _buf_len)
{
peekBuf(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 peekBuf(void * buf, 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);
}
::memcpy(buf, _buf + _cur + offset, len);
}
/// 读取缓存 for vector<char>
template <typename Alloc>
void readBuf(std::vector<Char, Alloc>& 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<char>
template <typename Alloc>
void peekBuf(std::vector<Char, Alloc>& 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<typename Alloc>
void setBuffer(const std::vector<char,Alloc> &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<typename ReaderT = BufferReader>
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<typename T>
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<<endl;
throw TarsDecodeRequireNotExist(s);
}
}
void read(UInt8& n, uint8_t tag, bool isRequire = true)
{
Short i = (Short)n;
read(i,tag,isRequire);
n = (UInt8)i;
}
void read(Short& n, uint8_t tag, bool isRequire = true)
{
uint8_t headType = 0, headTag = 0;
bool skipFlag = false;
cout << "line = "<<__LINE__<<",skipFlag is "<< skipFlag<< ", isRequire is "<<isRequire <<", n is "<< n << ", tag is "<< (int)tag <<endl;
TarsSkipToTag(skipFlag, tag, headType, headTag);
cout << "line = "<<__LINE__<<",skipFlag is "<< skipFlag<< ", isRequire is "<<isRequire <<", n is "<< n << ", tag is "<< (int)tag <<endl;
if (tars_likely(skipFlag))
{
switch (headType)
{
case TarsHeadeZeroTag:
n = 0;
break;
case TarsHeadeChar:
TarsReadTypeBuf(*this, n, Char);
break;
case TarsHeadeShort:
TarsReadTypeBuf(*this, n, Short);
n = ntohs(n);
break;
default:
{
char s[64];
snprintf(s, sizeof(s), "read 'Short' type mismatch, tag: %d, get type: %d.", tag, headType);
throw TarsDecodeMismatch(s);
}
}
}
else if (tars_unlikely(isRequire))
{
char s[64];
cout<<"line = "<<__LINE__<<", require field not exist"<<endl;
snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag);
throw TarsDecodeRequireNotExist(s);
}
std::cout<<"read Short n is "<<n<<std::endl;
}
void read(UInt16& n, uint8_t tag, bool isRequire = true)
{
Int32 i = (Int32)n;
read(i,tag,isRequire);
n = (UInt16)i;
}
void read(Int32& n, uint8_t tag, bool isRequire = true)
{
uint8_t headType = 1, headTag = 1;
bool skipFlag = false;
TarsSkipToTag(skipFlag, tag, headType, headTag);
if (tars_likely(skipFlag))
{
switch (headType)
{
case TarsHeadeZeroTag:
n = 0;
break;
case TarsHeadeChar:
TarsReadTypeBuf(*this, n, Char);
break;
case TarsHeadeShort:
TarsReadTypeBuf(*this, n, Short);
n = (Short)ntohs(n);
break;
case TarsHeadeInt32:
TarsReadTypeBuf(*this, n, Int32);
n = ntohl(n);
break;
default:
{
char s[64];
snprintf(s, sizeof(s), "read 'Int32' 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 headType: %d, headTag: %d", tag, headType, headTag);
throw TarsDecodeRequireNotExist(s);
}
std::cout<<"read Int32 n is "<<n<<std::endl;
}
void read(UInt32& n, uint8_t tag, bool isRequire = true)
{
Int64 i = (Int64)n;
read(i,tag,isRequire);
n = (UInt32)i;
}
void read(Int64& n, 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:
n = 0;
break;
case TarsHeadeChar:
TarsReadTypeBuf(*this, n, Char);
break;
case TarsHeadeShort:
TarsReadTypeBuf(*this, n, Short);
n = (Short) ntohs(n);
break;
case TarsHeadeInt32:
TarsReadTypeBuf(*this, n, Int32);
n = (Int32) ntohl(n);
break;
case TarsHeadeInt64:
TarsReadTypeBuf(*this, n, Int64);
n = tars_ntohll(n);
break;
default:
{
char s[64];
snprintf(s, sizeof(s), "read 'Int64' 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);
}
std::cout<<"read Int64 n is "<<n<<std::endl;
}
void read(Float& n, 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:
n = 0;
break;
case TarsHeadeFloat:
TarsReadTypeBuf(*this, n, float);
n = tars_ntohf(n);
break;
default:
{
char s[64];
snprintf(s, sizeof(s), "read 'Float' 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);
}
}
void read(Double& n, 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:
n = 0;
break;
case TarsHeadeFloat:
TarsReadTypeBuf(*this, n, float);
n = tars_ntohf(n);
break;
case TarsHeadeDouble:
TarsReadTypeBuf(*this, n, double);
n = tars_ntohd(n);
break;
default:
{
char s[64];
snprintf(s, sizeof(s), "read 'Double' 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);
}
}
void read(std::string& s, uint8_t tag, bool isRequire = true)
{
uint8_t headType = 0, headTag = 0;
bool skipFlag = false;
TarsSkipToTag(skipFlag, tag, headType, headTag);
if (tars_likely(skipFlag))
{
uint32_t strLength = 0;
switch (headType)
{
case TarsHeadeString1:
{
TarsReadTypeBuf(*this, strLength, uint8_t);
}
break;
case TarsHeadeString4:
{
TarsReadTypeBuf(*this, strLength, uint32_t);
strLength = ntohl(strLength);
if (tars_unlikely(strLength > 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<typename K, typename V, typename Cmp, typename Alloc>
void read(std::map<K, V, Cmp, Alloc>& 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<K, V> 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<typename Alloc>
void read(std::vector<Char, Alloc>& v, uint8_t tag, bool isRequire = true)
{
cout << "line = "<<__LINE__<<", 调用了read(std::vector<Char, Alloc>& v, uint8_t tag, bool isRequire = true)"<<endl;
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 > 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.size();i++)
{
cout <<"line = "<<__LINE__<<", v["<<i<<"] is "<<v[i]<<endl;
}
cout << "line = "<<__LINE__<<", read(std::vector<Char, Alloc>& v, uint8_t tag, bool isRequire = true) 快要调用结束啦"<<endl;
}
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<typename T, typename Alloc>
void read(std::vector<T, Alloc>& v, uint8_t tag, bool isRequire = true)
{
cout << "line = "<<__LINE__<<",调用了read(std::vector<T, Alloc>& v, uint8_t tag, bool isRequire = true)"<<endl;
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);
}
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<typename T>
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<typename T>
void read(T& v, uint8_t tag, bool isRequire = true, typename detail::disable_if<detail::is_convertible<T*, TarsStructBase*>, void ***>::type dummy = 0)
{
Int32 n = 0;
read(n, tag, isRequire);
v = (T) n;
}
/// 读取结构
template<typename T>
void read(T& v, uint8_t tag, bool isRequire = true, typename detail::enable_if<detail::is_convertible<T*, TarsStructBase*>, 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<char> &sBuffer) : _buffer(sBuffer) {}
Buffer(const char *sBuffer, size_t length) : _buffer(sBuffer, sBuffer+length) {}
void swap(vector<char> &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<char> &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<char> &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" <<endl;
exit(1);
}
return _buffer[_pos + offset];
}
char at(size_t offset) const
{
if(_pos + offset >= _buffer.size() )
{
cout << "line ="<<__LINE__<<"[TC_NetWorkBuffer::Buffer] at offset overflow" <<endl;
exit(1);
}
return _buffer[_pos + offset];
}
void add(uint32_t ret)
{
_pos += ret;
assert(_pos <= _buffer.size());
}
protected:
vector<char> _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<std::shared_ptr<Buffer>> _bufferList;
size_t getBufferLength()
{
cout<<"line is "<<__LINE__<<"_length is "<<_length<< endl;
return _length;
}
template<typename T>
T getHeader(size_t len)
{
if(getBufferLength() < len)
{
cout<<"line is "<<__LINE__<< "[TC_NetWorkBuffer::getHeader] no enough buff "<<endl;
exit(0);
}
T buffer;
if(len == 0)
{
return buffer;
}
buffer.resize(len);
getBuffers(&buffer[0], len);
return buffer;
}
size_t getBuffers(char *buffer, size_t length)
{
assert(length <= getBufferLength());
auto it = _bufferList.begin();
size_t left = length;
size_t pos = 0;
while(it != _bufferList.end() && left != 0)
{
size_t len = min(left, (*it)->length());
memcpy(buffer + pos, (*it)->buffer(), len);
left -= len;
pos += len;
++it;
}
return pos;
}
vector<char> getBuffers()
{
vector<char> 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<char> &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 <<endl;
return false;
}
if(len == 0)
{
cout << "line = "<<__LINE__<<", len is 0"<<endl;
return true;
}
auto it = _bufferList.begin();
// assert(it->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<typename T>
T getValue()
{
vector<char> 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<typename T>
PACKET_TYPE parseBuffer(vector<char> &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<T>();
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<char> &buffer, uint32_t minLength, uint32_t maxLength)
{
cout <<"line = "<<__LINE__<<", enter function parseBufferOf4" << endl;
return parseBuffer<uint32_t>(buffer, minLength, maxLength);
}
// 这里用的是ResponsePacket那一部分的代码,解码,代码路径D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\servant\tup\Tars.h
template<typename ReaderT>
void readFrom(TarsInputStream<ReaderT>& _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<BufferWriter> os;
vector<char> buffer;
string res = "aaaa";
buffer.assign(res.begin(),res.end());// 将res的值赋值到buffer中
status["status"] = "status";
map<string, string> _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<std::string, std::string>
sResultDesc = "123"; //tag 8 value("123") type std::string
context = _responseContext; //tag 9 value(<"context","context">)
cout <<"line is "<<__LINE__<< ",开始解码啦***************************************************************************************************************************************************"<<endl;
cout <<endl<<endl<<endl<<endl;
writeTo(os);
cout <<"os._buf is ["<< os._buf<<"],os._len "<< os._len << ",os._buf_len is "<< os._buf_len << endl;
cout <<"os._buf is "<<StrToBitStr(os._buf)<<endl;
cout <<endl<<endl<<endl<<endl;
cout <<"line is "<<__LINE__<< ",开始解码啦****************************************************************************************************************************************************"<<endl;
cout <<endl<<endl<<endl<<endl;
TarsInputStream<BufferReader> 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<Char> sBuffer;
Int32 iTimeout;
map<std::string, std::string> context;
map<std::string, std::string> status;
Int32 iRet;
*/