📄 stream.h
字号:
////////////////////////////////////////////////////////////////////////////////
// 基本的流处理
////////////////////////////////////////////////////////////////////////////////
// Author : 黎达文
// Description : 基本的流编码解码
//
// Version : 1.3
//
// Standard include files :
//
// Start Date : 2003年4月3日
//
// Change Log : reference the end of this file
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_STREAM_H
#define INCLUDED_STREAM_H
#if defined(HAS_PRAGMA_ONCE)
#pragma PRAGMA_ONCE_DECLARE
#endif
#include "type_def.h"
#include "patterns/util/util.h" // access s_strEmpty
//CTBaseBuffer support a continuouse and auto resize buffer.
//it can convert to a base "char *" type by calling tellp method
//we use the std::vector<u8> as this CTBaseBuffer.
//CTBaseBuffer is the main container
namespace protocol
{
class BaseStream
{
typedef std::vector<char > StreamContainer;
public:
explicit BaseStream()
{
reset();
}
//integer encode routine
inline void enc32(u32 value)
{
enc8(u8(value >> 24));
enc8(u8(value >> 16));
enc8(u8(value >> 8));
enc8(u8(value));
}
inline void enc16(u16 value)
{
enc8(u8(value >> 8));
enc8(u8(value));
}
inline void enc8 (u8 value)
{
m_container.push_back(value);
}
//string encode routine
void encFixedString(const std::string& str,
size_t fixedLen,
u8 fillFlag = '\0');
void encVmaxString( const std::string& str,
size_t maxLen,
u8 endFlag = '\0');
void encString(const std::string& str);
void encStream(const BaseStream& stream);
/// integer decode routine
/**
* the follow dec method must use u8 type conversion,
* coz the base type of stream container is "char"
* if no type conversion, the shift action will not correct
*/
inline bool dec32(u32& value)
{
if(left() < sizeof(u32))
return false;
u32 accumulator = (u8)m_container[m_offset++]; // get the first byte
accumulator = (accumulator << 8) | (u8)m_container[m_offset++]; // second
accumulator = (accumulator << 8) | (u8)m_container[m_offset++]; // ...
accumulator = (accumulator << 8) | (u8)m_container[m_offset++]; // ...
value = accumulator;
return true;
}
inline bool dec16(u16& value)
{
if(left() < sizeof(u16))
return false;
u16 accumulator = (u8)m_container[m_offset++]; //get the first byte;
accumulator = (accumulator << 8) | (u8)m_container[m_offset++]; //second
value = accumulator;
return true;
}
inline bool dec8 (u8 & value)
{
if(left() < sizeof(u8))
return false;
value = (u8)m_container[m_offset++];
return true;
}
bool decFixedString(std::string& str, size_t fixedLen);
bool decVmaxString (std::string& str, size_t maxLen, u8 endFlag = '\0');
bool decString (std::string& str);
bool decStream (BaseStream& stream, size_t length);
template<class InputIterator>
void assign(InputIterator first, InputIterator last)
{
m_container.assign(first, last);
}
BaseStream& operator+=(const BaseStream& other)
{
m_container.insert(end(), other.begin(), other.end());
return *this;
}
bool operator == (const BaseStream& other) const
{
return m_container == other.m_container;
}
bool operator != (const BaseStream& other) const
{
return !(*this == other);
}
/// how many buffer left when decoding
size_t left() const
{
return size() - m_offset;
}
/// decoder offset position
size_t offset() const
{
return m_offset;
}
/**
* reset the decode offset
* default parameter means reset to begin position
* positive number means advance the position if it can advance
* if advance overflow then offset set to the last position (not the just over last position)
* negative number means back off the position if it can back off
* if back off underflow then offset set to zero
*/
void reset(int offset = 0)
{
if(offset == 0)
{
m_offset = 0;
}
else
{
m_offset += offset;
}
//check overflow or underflow
if(m_offset<0)
{
m_offset = 0;
}
else if(m_offset > size())
{
m_offset = size();
}
}
/// clear the stream buffer, not free the memory!
void clear()
{
m_container.clear();
}
/// free the stream buffer's memory
void free()
{
reset();
StreamContainer().swap(m_container);
// m_container.swap(StreamContainer());
}
/// return the current buffer position, read only!
const char *getBuffer(size_t offset = 0) const
{
if(offset>=0 && offset < m_container.size())
return &m_container[offset];
else
return stk::s_strEmpty.c_str();
}
/**
* return the buffer which can be write directly,
* must call resize method to alloc enough buffer!
*/
char *getWriteBuffer(size_t offset = 0)
{
assert(offset>=0 && offset <= m_container.size());
return &m_container[offset];
}
//make some STL algorithm interface
size_t size() const
{
return m_container.size();
}
void resize(StreamContainer::size_type newSize)
{
m_container.resize(newSize);
}
void reserve(StreamContainer::size_type count)
{
m_container.reserve(count);
}
bool empty() const
{
return m_container.empty();
}
StreamContainer::const_iterator begin() const
{
return m_container.begin();
}
/// current decode position
StreamContainer::const_iterator current() const
{
return m_container.begin()+m_offset;
}
StreamContainer::const_iterator end() const
{
return m_container.end();
}
StreamContainer::iterator begin()
{
return m_container.begin();
}
StreamContainer::iterator current()
{
return m_container.begin()+m_offset;
}
StreamContainer::iterator end()
{
return m_container.end();
}
void swap(BaseStream& right)
{
std::swap(m_offset, right.m_offset);
m_container.swap(right.m_container);
}
protected:
StreamContainer m_container;
size_t m_offset; //indicate the decode position
};
/// change the byte order(16bit)
inline u16 changeOrder(u16 org)
{
u16 result = (org>>8) & 0xFF;
result |= (org&0xFF) << 8;
return result;
}
/// change the byte order(32bit)
inline u32 changeOrder(u32 org)
{
u16 high16 = (u16)( (org>>16) && 0xFFFF );
u16 low16 = (u16)( org&0xFFFF );
high16 = changeOrder(high16);
low16 = changeOrder(low16);
return (low16<<16 | high16);
}
};
/// for the old name
namespace ptl = protocol;
/// define suntek name format
typedef protocol::BaseStream CTBaseStream;
//////////////////////////////////////////////////////////////////////////
// Change Log:
// 20021231 by darkay
// add dec_buf_v and dec_str_v method for variable length string with ending flag
// and enc_buf and enc_str with no size parameter, it encode the string while not end of \0';
// 20030105 by darkay
// modify dec_str method, move m_offset++ from the "while condition" into "while scope"
// 20030223 by darkay li
// add compatible for VC6, coz it's insert function of vector not support general parameter
// so, I must do some cast.
// Darkay Li [5/22/2003]
// add namespace protocol, and macro for suntek name format
// 2003年6月27日 by Darkay Li
// remove derive from StreamContianer, let StreamContianer as data members
// add the STL's iterator interface like begin(), end() and current()
// add encStream/decStream method
// implement decString method.
// add default ctor parameter to init stream minimal size for speed up
// 2003年12月4日 by Darkay Li
// 1. modify the stream container from vector<u8> to vector<char>,
// this modification make it convert to char * easyly
// 2. add another getBuffer interface, it return non-const char * pointer,
// it support such usage "resize stream to enough size, and use the stream buffer directly" now
// it's useful when receiving data from socket.
// 3. remove "CTBaseStream" definition
// 4. add global function changeOrder to change byte order
// 5. make much method "inline"
// 2004年3月24日 by Darkay Li
// 1. change char *getBuffer(size_t offset = 0) to
// char *getWriteBuffer(size_t offset = 0)
// for more clear mean interface name!
// 2004年12月13日 by Darkay Li
// 1. bug fix for method changeOrder(), it's a stupid coding mistake.
// u16 high16 = (u16)( (org>16) && 0xFFFF );
// ==>
// u16 high16 = (u16)( (org>>16) && 0xFFFF );
// 2. bug fix for method swap(), missed swap m_offset
//////////////////////////////////////////////////////////////////////////
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -