mirror of
https://gitee.com/TarsCloud/TarsCpp.git
synced 2024-12-22 22:16:38 +08:00
1969 lines
62 KiB
C++
Executable File
1969 lines
62 KiB
C++
Executable File
/**
|
||
* Tencent is pleased to support the open source community by making Tars available.
|
||
*
|
||
* Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
|
||
*
|
||
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
|
||
* in compliance with the License. You may obtain a copy of the License at
|
||
*
|
||
* https://opensource.org/licenses/BSD-3-Clause
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software distributed
|
||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||
* specific language governing permissions and limitations under the License.
|
||
*/
|
||
|
||
#ifndef __TARS_H__
|
||
#define __TARS_H__
|
||
|
||
#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>
|
||
|
||
#if defined _WIN32 || defined _WIN64
|
||
#pragma comment(lib,"ws2_32.lib")
|
||
#else
|
||
#include <arpa/inet.h>
|
||
#endif
|
||
|
||
//支持iphone
|
||
#ifdef __APPLE__
|
||
#include "TarsType.h"
|
||
#elif defined ANDROID // android
|
||
#include "TarsType.h"
|
||
#else
|
||
#include "tup/TarsType.h"
|
||
#endif
|
||
|
||
|
||
#ifndef tars_likely
|
||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||
#define tars_likely(x) (__builtin_expect(!!(x),1))
|
||
#else
|
||
#define tars_likely(x) (x)
|
||
#endif
|
||
#endif
|
||
|
||
#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
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////
|
||
//// 保留接口版本Tars宏定义
|
||
//编码相应的宏
|
||
|
||
#define TarsReserveBuf(os, len) \
|
||
do{ \
|
||
if(tars_likely((os)._buf_len < (len))) \
|
||
{ \
|
||
size_t len1 = (len)<<1; \
|
||
if(len1<128) len1=128; \
|
||
(os)._buf = (os)._reserve(os, len1); \
|
||
(os)._buf_len = (len1); \
|
||
} \
|
||
}while(0)
|
||
|
||
|
||
#define TarsWriteToHead(os, type, tag) \
|
||
do { \
|
||
if (tars_likely((tag) < 15)) \
|
||
{ \
|
||
TarsWriteUInt8TTypeBuf( os, (type) + ((tag)<<4) , (os)._len); \
|
||
} \
|
||
else \
|
||
{ \
|
||
TarsWriteUInt8TTypeBuf( os, (type) + (240) , (os)._len); \
|
||
TarsWriteUInt8TTypeBuf( os, (tag), (os)._len);\
|
||
} \
|
||
} while(0)
|
||
|
||
#define TarsWriteCharTypeBuf(os, val, osLen) \
|
||
do { \
|
||
TarsReserveBuf(os, (osLen)+sizeof(Char)); \
|
||
(*(Char *)((os)._buf + (osLen))) = (val); \
|
||
(osLen) += sizeof(Char); \
|
||
} while(0)
|
||
|
||
#define TarsWriteInt32TypeBuf(os, val, osLen) \
|
||
do { \
|
||
TarsReserveBuf(os, (osLen)+sizeof(Int32)); \
|
||
(*(Int32 *)((os)._buf + (osLen))) = (val); \
|
||
(osLen) += sizeof(Int32); \
|
||
} while(0)
|
||
|
||
#define TarsWriteInt64TypeBuf(os, val, osLen) \
|
||
do { \
|
||
TarsReserveBuf(os, (osLen)+sizeof(Int64)); \
|
||
(*(Int64 *)((os)._buf + (osLen))) = (val); \
|
||
(osLen) += sizeof(Int64); \
|
||
} while(0)
|
||
|
||
#define TarsWriteFloatTypeBuf(os, val, osLen) \
|
||
do { \
|
||
TarsReserveBuf(os, (osLen)+sizeof(Float)); \
|
||
(*(Float *)((os)._buf + (osLen))) = (val); \
|
||
(osLen) += sizeof(Float); \
|
||
} while(0)
|
||
|
||
#define TarsWriteDoubleTypeBuf(os, val, osLen) \
|
||
do { \
|
||
TarsReserveBuf(os, (osLen)+sizeof(Double)); \
|
||
(*(Double *)((os)._buf + (osLen))) = (val); \
|
||
(osLen) += sizeof(Double); \
|
||
} while(0)
|
||
|
||
#define TarsWriteUInt32TTypeBuf(os, val, osLen) \
|
||
do { \
|
||
TarsReserveBuf(os, (osLen)+sizeof(uint32_t)); \
|
||
(*(uint32_t *)((os)._buf + (osLen))) = (val); \
|
||
(osLen) += sizeof(uint32_t); \
|
||
} 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)
|
||
|
||
#define TarsWriteUIntTypeBuf(os, val, osLen) \
|
||
do { \
|
||
TarsReserveBuf(os, (osLen)+sizeof(unsigned int)); \
|
||
(*(unsigned int *)((os)._buf + (osLen))) = (val); \
|
||
(osLen) += sizeof(unsigned int); \
|
||
} while(0)
|
||
|
||
#define TarsWriteShortTypeBuf(os, val, osLen) \
|
||
do { \
|
||
TarsReserveBuf(os, (osLen)+sizeof(Short)); \
|
||
(*(Short *)((os)._buf + (osLen))) = (val); \
|
||
(osLen) += sizeof(Short); \
|
||
} while(0)
|
||
|
||
#define TarsWriteTypeBuf(os, buf, len) \
|
||
do { \
|
||
TarsReserveBuf(os, (os)._len + (len)); \
|
||
memcpy((os)._buf + (os)._len, (const void *)(buf), (len)); \
|
||
(os)._len += (len); \
|
||
} while(0)
|
||
|
||
|
||
//解码相应的宏
|
||
#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 { \
|
||
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)
|
||
|
||
#define TarsSkipToTag(flag, tag, retHeadType, retHeadTag) \
|
||
do { \
|
||
try \
|
||
{ \
|
||
uint8_t nextHeadType, nextHeadTag; \
|
||
while (!ReaderT::hasEnd()) \
|
||
{ \
|
||
size_t len = 0; \
|
||
TarsPeekFromHead(*this, nextHeadType, nextHeadTag, len); \
|
||
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)
|
||
|
||
namespace tars
|
||
{
|
||
//////////////////////////////////////////////////////////////////
|
||
struct TarsStructBase
|
||
{
|
||
protected:
|
||
TarsStructBase() {}
|
||
|
||
~TarsStructBase() {}
|
||
};
|
||
|
||
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) {}
|
||
};
|
||
|
||
//////////////////////////////////////////////////////////////////
|
||
namespace
|
||
{
|
||
/// 数据头信息的封装,包括类型和tag
|
||
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));
|
||
}
|
||
}
|
||
};
|
||
}
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////
|
||
/// 缓冲区读取器封装
|
||
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()
|
||
{
|
||
return _cur >= _buf_len;
|
||
}
|
||
size_t tellp() const
|
||
{
|
||
return _cur;
|
||
}
|
||
const char* base() const
|
||
{
|
||
return _buf;
|
||
}
|
||
size_t size() const
|
||
{
|
||
return _buf_len;
|
||
}
|
||
};
|
||
|
||
//当tars文件中含有指针型类型的数据用MapBufferReader读取
|
||
//在读数据时利用MapBufferReader提前分配的内存 减少运行过程中频繁内存分配
|
||
//结构中定义byte指针类型,指针用*来定义,如下:
|
||
//byte *m;
|
||
//指针类型使用时需要MapBufferReader提前设定预分配内存块setMapBuffer(),
|
||
//指针需要内存时通过偏移指向预分配内存块,减少解码过程中的内存申请
|
||
class MapBufferReader : public BufferReader
|
||
{
|
||
|
||
public:
|
||
MapBufferReader() : _buf_m(NULL),_buf_len_m(0),_cur_m(0) {}
|
||
|
||
void reset() { _cur_m = 0; BufferReader::reset();}
|
||
|
||
char* cur()
|
||
{
|
||
if (tars_unlikely(_buf_m == NULL))
|
||
{
|
||
char s[64];
|
||
snprintf(s, sizeof(s), "MapBufferReader's buff not set,_buf = null");
|
||
throw TarsDecodeException(s);
|
||
}
|
||
return _buf_m+_cur_m;
|
||
}
|
||
|
||
size_t left(){return _buf_len_m-_cur_m;}
|
||
|
||
/// 跳过len个字节
|
||
void mapBufferSkip(size_t len)
|
||
{
|
||
if (tars_unlikely(_cur_m + len > _buf_len_m))
|
||
{
|
||
char s[64];
|
||
snprintf(s, sizeof(s), "MapBufferReader's buffer overflow when peekBuf, over %u.", (uint32_t)_buf_len_m);
|
||
throw TarsDecodeException(s);
|
||
}
|
||
_cur_m += len;
|
||
}
|
||
|
||
/// 设置缓存
|
||
void setMapBuffer(char * buf, size_t len)
|
||
{
|
||
_buf_m = buf;
|
||
_buf_len_m = len;
|
||
_cur_m = 0;
|
||
}
|
||
|
||
/// 设置缓存
|
||
template<typename Alloc>
|
||
void setMapBuffer(std::vector<char,Alloc> &buf)
|
||
{
|
||
_buf_m = buf.data();
|
||
_buf_len_m = buf.size();
|
||
_cur_m = 0;
|
||
}
|
||
public:
|
||
char * _buf_m; ///< 缓冲区
|
||
size_t _buf_len_m; ///< 缓冲区长度
|
||
size_t _cur_m; ///< 当前位置
|
||
};
|
||
|
||
//////////////////////////////////////////////////////////////////
|
||
/// 缓冲区写入器封装
|
||
class BufferWriter
|
||
{
|
||
protected:
|
||
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)];
|
||
memcpy(p, (os)._buf, (os)._len);
|
||
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;}//{ return &_buf[0]; }
|
||
size_t getLength() const { return _len;} //{ return _buf.size(); }
|
||
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);
|
||
}
|
||
};
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||
/// 实际buffer是std::string
|
||
/// 可以swap, 把buffer交换出来, 避免一次内存copy
|
||
class BufferWriterString
|
||
{
|
||
protected:
|
||
mutable std::string _buffer;
|
||
char * _buf;
|
||
size_t _len;
|
||
size_t _buf_len;
|
||
std::function<char*(BufferWriterString &, size_t)> _reserve;
|
||
|
||
private:
|
||
//不让copy 复制
|
||
BufferWriterString(const BufferWriterString&);
|
||
BufferWriterString& operator=(const BufferWriterString& buf);
|
||
|
||
public:
|
||
BufferWriterString()
|
||
: _buf(NULL)
|
||
, _len(0)
|
||
, _buf_len(0)
|
||
{
|
||
#ifndef GEN_PYTHON_MASK
|
||
//内存分配器
|
||
_reserve = [](BufferWriterString &os, size_t len) {
|
||
os._buffer.resize(len);
|
||
return (char*)os._buffer.data();
|
||
} ;
|
||
#endif
|
||
}
|
||
|
||
~BufferWriterString()
|
||
{
|
||
}
|
||
|
||
void reset() { _len = 0;}
|
||
|
||
void writeBuf(const char * buf, size_t len)
|
||
{
|
||
TarsReserveBuf(*this, _len + len);
|
||
memcpy(_buf + _len, buf, len);
|
||
_len += len;
|
||
}
|
||
|
||
const std::string &getByteBuffer() const { _buffer.resize(_len); return _buffer;}
|
||
std::string &getByteBuffer() { _buffer.resize(_len); return _buffer;}
|
||
const char * getBuffer() const { return _buf;}
|
||
size_t getLength() const { return _len;}
|
||
void swap(std::string& v)
|
||
{
|
||
_buffer.resize(_len);
|
||
v.swap(_buffer);
|
||
_buf = NULL;
|
||
_buf_len = 0;
|
||
_len = 0;
|
||
}
|
||
void swap(std::vector<char>& v)
|
||
{
|
||
_buffer.resize(_len);
|
||
v.assign(_buffer.c_str(), _buffer.c_str() + _buffer.size());
|
||
_buf = NULL;
|
||
_buf_len = 0;
|
||
_len = 0;
|
||
}
|
||
void swap(BufferWriterString& buf)
|
||
{
|
||
buf._buffer.swap(_buffer);
|
||
std::swap(_buf, buf._buf);
|
||
std::swap(_buf_len, buf._buf_len);
|
||
std::swap(_len, buf._len);
|
||
}
|
||
};
|
||
|
||
/// 实际buffer是std::vector<char>
|
||
/// 可以swap, 把buffer交换出来, 避免一次内存copy
|
||
class BufferWriterVector
|
||
{
|
||
protected:
|
||
mutable std::vector<char> _buffer;
|
||
char * _buf;
|
||
size_t _len;
|
||
size_t _buf_len;
|
||
std::function<char*(BufferWriterVector &, size_t)> _reserve;
|
||
|
||
private:
|
||
//不让copy 复制
|
||
BufferWriterVector(const BufferWriterVector&);
|
||
BufferWriterVector& operator=(const BufferWriterVector& buf);
|
||
|
||
public:
|
||
BufferWriterVector()
|
||
: _buf(NULL)
|
||
, _len(0)
|
||
, _buf_len(0)
|
||
{
|
||
#ifndef GEN_PYTHON_MASK
|
||
//内存分配器
|
||
_reserve = [](BufferWriterVector &os, size_t len) {
|
||
os._buffer.resize(len);
|
||
return os._buffer.data();
|
||
} ;
|
||
#endif
|
||
}
|
||
|
||
~BufferWriterVector()
|
||
{
|
||
}
|
||
|
||
void reset() { _len = 0;}
|
||
|
||
void writeBuf(const char * buf, size_t len)
|
||
{
|
||
TarsReserveBuf(*this, _len + len);
|
||
memcpy(_buf + _len, buf, len);
|
||
_len += len;
|
||
}
|
||
|
||
const std::vector<char> &getByteBuffer() const { _buffer.resize(_len); return _buffer;}
|
||
std::vector<char> &getByteBuffer() { _buffer.resize(_len); return _buffer;}
|
||
const char * getBuffer() const { return _buf;}
|
||
size_t getLength() const { return _len;}
|
||
void swap(std::string& v)
|
||
{
|
||
_buffer.resize(_len);
|
||
v.assign(_buffer.data(), _buffer.size());
|
||
_buf = NULL;
|
||
_buf_len = 0;
|
||
_len = 0;
|
||
}
|
||
void swap(std::vector<char>& v)
|
||
{
|
||
_buffer.resize(_len);
|
||
v.swap(_buffer);
|
||
_buf = NULL;
|
||
_buf_len = 0;
|
||
_len = 0;
|
||
}
|
||
void swap(BufferWriterVector& buf)
|
||
{
|
||
buf._buffer.swap(_buffer);
|
||
std::swap(_buf, buf._buf);
|
||
std::swap(_buf_len, buf._buf_len);
|
||
std::swap(_len, buf._len);
|
||
}
|
||
};
|
||
|
||
//////////////////////////////////////////////////////////////////
|
||
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:
|
||
{
|
||
Int32 size = 0;
|
||
read(size, 0);
|
||
for (Int32 i = 0; i < size * 2; ++i)
|
||
skipField();
|
||
}
|
||
break;
|
||
case TarsHeadeList:
|
||
{
|
||
Int32 size = 0;
|
||
read(size, 0);
|
||
for (Int32 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);
|
||
}
|
||
Int32 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);
|
||
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;
|
||
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 = 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];
|
||
snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag);
|
||
throw TarsDecodeRequireNotExist(s);
|
||
}
|
||
}
|
||
|
||
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);
|
||
}
|
||
}
|
||
|
||
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);
|
||
}
|
||
}
|
||
|
||
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))
|
||
{
|
||
switch(headType)
|
||
{
|
||
case TarsHeadeString1:
|
||
{
|
||
size_t len = 0;
|
||
TarsReadTypeBuf(*this, len, uint8_t);
|
||
char ss[256];
|
||
//s.resize(len);
|
||
//this->readBuf((void *)s.c_str(), len);
|
||
TarsReadStringBuf(*this, s, len);
|
||
//TarsReadBuf(*this, s, len);
|
||
//s.assign(ss, ss + len);
|
||
}
|
||
break;
|
||
case TarsHeadeString4:
|
||
{
|
||
uint32_t len = 0;
|
||
TarsReadTypeBuf(*this, len, uint32_t);
|
||
len = ntohl(len);
|
||
if (tars_unlikely(len > TARS_MAX_STRING_LENGTH))
|
||
{
|
||
char s[128];
|
||
snprintf(s, sizeof(s), "invalid string size, tag: %d, size: %d", tag, len);
|
||
throw TarsDecodeInvalidValue(s);
|
||
}
|
||
//char *ss = new char[len];
|
||
//s.resize(len);
|
||
//this->readBuf((void *)s.c_str(), len);
|
||
|
||
char *ss = new char[len];
|
||
try
|
||
{
|
||
TarsReadBuf(*this, ss, len);
|
||
s.assign(ss, ss + len);
|
||
}
|
||
catch (...)
|
||
{
|
||
delete[] ss;
|
||
throw;
|
||
}
|
||
delete[] ss;
|
||
TarsReadStringBuf(*this, s, len);
|
||
}
|
||
break;
|
||
default:
|
||
{
|
||
char s[64];
|
||
snprintf(s, sizeof(s), "read 'string' 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", tag);
|
||
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)
|
||
{
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
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)
|
||
{
|
||
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);
|
||
}
|
||
}
|
||
};
|
||
|
||
//////////////////////////////////////////////////////////////////
|
||
template<typename WriterT = BufferWriter>
|
||
class TarsOutputStream : public WriterT
|
||
{
|
||
public:
|
||
void writeUnknown(const std::string& s)
|
||
{
|
||
this->writeBuf(s.data(), s.size());
|
||
}
|
||
void writeUnknownV2(const std::string& s)
|
||
{
|
||
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)
|
||
{
|
||
write((Char) b, tag);
|
||
}
|
||
|
||
void write(Char n, uint8_t tag)
|
||
{
|
||
/*
|
||
DataHead h(DataHead::eChar, tag);
|
||
if(n == 0){
|
||
h.setType(DataHead::eZeroTag);
|
||
h.writeTo(*this);
|
||
}else{
|
||
h.writeTo(*this);
|
||
this->writeBuf(&n, sizeof(n));
|
||
}
|
||
*/
|
||
if (tars_unlikely(n == 0))
|
||
{
|
||
TarsWriteToHead(*this, TarsHeadeZeroTag, tag);
|
||
}
|
||
else
|
||
{
|
||
TarsWriteToHead(*this, TarsHeadeChar, tag);
|
||
TarsWriteCharTypeBuf(*this, n, (*this)._len);
|
||
}
|
||
}
|
||
|
||
void write(UInt8 n, uint8_t tag)
|
||
{
|
||
write((Short) n, tag);
|
||
}
|
||
|
||
void write(Short n, uint8_t tag)
|
||
{
|
||
//if(n >= CHAR_MIN && n <= CHAR_MAX){
|
||
if (n >= (-128) && n <= 127)
|
||
{
|
||
write((Char) n, tag);
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
DataHead h(DataHead::eShort, tag);
|
||
h.writeTo(*this);
|
||
n = htons(n);
|
||
this->writeBuf(&n, sizeof(n));
|
||
*/
|
||
TarsWriteToHead(*this, TarsHeadeShort, tag);
|
||
n = htons(n);
|
||
TarsWriteShortTypeBuf(*this, n, (*this)._len);
|
||
}
|
||
}
|
||
|
||
void write(UInt16 n, uint8_t tag)
|
||
{
|
||
write((Int32) n, tag);
|
||
}
|
||
|
||
void write(Int32 n, uint8_t tag)
|
||
{
|
||
//if(n >= SHRT_MIN && n <= SHRT_MAX){
|
||
if (n >= (-32768) && n <= 32767)
|
||
{
|
||
write((Short) n, tag);
|
||
}
|
||
else
|
||
{
|
||
//DataHead h(DataHead::eInt32, tag);
|
||
//h.writeTo(*this);
|
||
TarsWriteToHead(*this, TarsHeadeInt32, tag);
|
||
n = htonl(n);
|
||
TarsWriteInt32TypeBuf(*this, n, (*this)._len);
|
||
}
|
||
}
|
||
|
||
void write(UInt32 n, uint8_t tag)
|
||
{
|
||
write((Int64) n, tag);
|
||
}
|
||
|
||
void write(Int64 n, uint8_t tag)
|
||
{
|
||
//if(n >= INT_MIN && n <= INT_MAX){
|
||
if (n >= (-2147483647-1) && n <= 2147483647)
|
||
{
|
||
write((Int32) n, tag);
|
||
}
|
||
else
|
||
{
|
||
//DataHead h(DataHead::eInt64, tag);
|
||
//h.writeTo(*this);
|
||
TarsWriteToHead(*this, TarsHeadeInt64, tag);
|
||
n = tars_htonll(n);
|
||
TarsWriteInt64TypeBuf(*this, n, (*this)._len);
|
||
}
|
||
}
|
||
|
||
void write(Float n, uint8_t tag)
|
||
{
|
||
//DataHead h(DataHead::eFloat, tag);
|
||
//h.writeTo(*this);
|
||
TarsWriteToHead(*this, TarsHeadeFloat, tag);
|
||
n = tars_htonf(n);
|
||
TarsWriteFloatTypeBuf(*this, n, (*this)._len);
|
||
}
|
||
|
||
void write(Double n, uint8_t tag)
|
||
{
|
||
//DataHead h(DataHead::eDouble, tag);
|
||
//h.writeTo(*this);
|
||
TarsWriteToHead(*this, TarsHeadeDouble, tag);
|
||
n = tars_htond(n);
|
||
TarsWriteDoubleTypeBuf(*this, n, (*this)._len);
|
||
}
|
||
|
||
void write(const std::string& s, uint8_t tag)
|
||
{
|
||
if (tars_unlikely(s.size() > 255))
|
||
{
|
||
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);
|
||
}
|
||
TarsWriteToHead(*this, TarsHeadeString4, tag);
|
||
uint32_t n = htonl((uint32_t)s.size());
|
||
TarsWriteUInt32TTypeBuf(*this, n, (*this)._len);
|
||
//this->writeBuf(s.data(), s.size());
|
||
TarsWriteTypeBuf(*this, s.data(), s.size());
|
||
}
|
||
else
|
||
{
|
||
TarsWriteToHead(*this, TarsHeadeString1, tag);
|
||
uint8_t n = (uint8_t)s.size();
|
||
TarsWriteUInt8TTypeBuf(*this, n, (*this)._len);
|
||
//this->writeBuf(s.data(), s.size());
|
||
TarsWriteTypeBuf(*this, s.data(), s.size());
|
||
}
|
||
}
|
||
|
||
void write(const char *buf, const UInt32 len, uint8_t tag)
|
||
{
|
||
TarsWriteToHead(*this, TarsHeadeSimpleList, tag);
|
||
TarsWriteToHead(*this, TarsHeadeChar, 0);
|
||
write(len, 0);
|
||
//this->writeBuf(buf, len);
|
||
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)
|
||
{
|
||
//DataHead h(DataHead::eMap, tag);
|
||
//h.writeTo(*this);
|
||
TarsWriteToHead(*this, TarsHeadeMap, tag);
|
||
Int32 n = (Int32)m.size();
|
||
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)
|
||
{
|
||
//DataHead h(DataHead::eList, tag);
|
||
//h.writeTo(*this);
|
||
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)
|
||
{
|
||
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)
|
||
{
|
||
//DataHead h(DataHead::eSimpleList, tag);
|
||
//h.writeTo(*this);
|
||
//DataHead hh(DataHead::eChar, 0);
|
||
//hh.writeTo(*this);
|
||
TarsWriteToHead(*this, TarsHeadeSimpleList, tag);
|
||
TarsWriteToHead(*this, TarsHeadeChar, 0);
|
||
Int32 n = (Int32)v.size();
|
||
write(n, 0);
|
||
//writeBuf(&v[0], v.size());
|
||
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)
|
||
{
|
||
//DataHead h(DataHead::eStructBegin, tag);
|
||
//h.writeTo(*this);
|
||
TarsWriteToHead(*this, TarsHeadeStructBegin, tag);
|
||
v.writeTo(*this);
|
||
TarsWriteToHead(*this, TarsHeadeStructEnd, 0);
|
||
/*
|
||
h.setType(DataHead::eStructEnd);
|
||
h.setTag(0);
|
||
h.writeTo(*this);
|
||
*/
|
||
}
|
||
};
|
||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
}
|
||
|
||
//支持iphone
|
||
#ifdef __APPLE__
|
||
#include "TarsDisplayer.h"
|
||
#else
|
||
#include "tup/TarsDisplayer.h"
|
||
#endif
|
||
|
||
#endif
|