一.BinaryReader.h的定義如下:
#ifndef LINYANWENBINARYREADER_H_
#define LINYANWENBINARYREADER_H_
#include "Poco/TextConverter.h"
#include "Poco/Foundation.h"
#include <vector>
#include <istream>
namespace Linyanwen {
class TextEncoding;
class BinaryReader
/// This class reads basic types (and std::vectors thereof)
/// in binary form into an input stream.
/// It provides an extractor-based interface similar to istream.
/// The reader also supports automatic conversion from big-endian
/// (network byte order) to little-endian and vice-versa.
/// Use a BinaryWriter to create a stream suitable for a BinaryReader.
{
public:
enum StreamByteOrder
{
NATIVE_BYTE_ORDER = 1, /// the host's native byte-order
BIG_ENDIAN_BYTE_ORDER = 2, /// big-endian (network) byte-order
NETWORK_BYTE_ORDER = 2, /// big-endian (network) byte-order
LITTLE_ENDIAN_BYTE_ORDER = 3, /// little-endian byte-order
UNSPECIFIED_BYTE_ORDER = 4 /// unknown, byte-order will be determined by reading the byte-order mark
};
BinaryReader(Poco::UInt8* _buffer,Poco::UInt32 _size);
~BinaryReader();
BinaryReader& operator >>(bool& value);
BinaryReader& operator >>(char& value);
BinaryReader& operator >>(unsigned char& value);
BinaryReader& operator >>(signed char& value);
BinaryReader& operator >>(short& value);
BinaryReader& operator >>(unsigned short& value);
BinaryReader& operator >>(int& value);
BinaryReader& operator >>(unsigned int& value);
BinaryReader& operator >>(long& value);
BinaryReader& operator >>(unsigned long& value);
BinaryReader& operator >>(float& value);
BinaryReader& operator >>(double& value);
BinaryReader& operator >> (std::string& value);
/****************************************/
void read7BitEncoded(Poco::UInt32& value);
void readRaw(std::streamsize length, std::string& value);
// Reads length bytes of raw data into value.
void readRaw(char* buf, std::streamsize length);
// Reads length bytes of raw data into buf.
/****************************************/
bool good();
private:
bool _flipBytes;
Poco::TextConverter* _pTextConverter;
Poco::UInt8* buffer;
Poco::UInt32 size;
Poco::Int32 beg,end,cur;
};
inline bool BinaryReader::good(){
return cur < size;//注意cur是從0開始,size是從1開始計數的,所以是'<'而不是'<='
}
} // namespace Linyanwen
#endif /* LINYANWENBINARYREADER_H_ */
二.BinaryReader.cpp的實現,如下:
#include "LinyanwenBinaryReader.h"
#include "Poco/BinaryReader.h"
#include "Poco/ByteOrder.h"
#include "Poco/TextEncoding.h"
#include <algorithm>
namespace Linyanwen {
BinaryReader::BinaryReader(Poco::UInt8* _buffer,Poco::UInt32 _size):buffer(_buffer),size(_size)
,beg(0),cur(0),end(_size),_pTextConverter(0)
{
#if defined(POCO_ARCH_BIG_ENDIAN)
_flipBytes = (BinaryReader::NETWORK_BYTE_ORDER == LITTLE_ENDIAN_BYTE_ORDER);
#else
_flipBytes = (BinaryReader::NETWORK_BYTE_ORDER == BIG_ENDIAN_BYTE_ORDER);
#endif
}
BinaryReader::~BinaryReader()
{
delete _pTextConverter;
}
BinaryReader& BinaryReader::operator >> (bool& value)
{
// _istr.read((char*) &value, sizeof(value));
*((char*)&value) = *(buffer+cur);
++cur;
return *this;
}
BinaryReader& BinaryReader::operator >> (char& value)
{
// _istr.read((char*) &value, sizeof(value));
*((char*)&value) = *(buffer+cur);
++cur;
return *this;
}
BinaryReader& BinaryReader::operator >> (unsigned char& value)
{
// _istr.read((char*) &value, sizeof(value));
*((char*)&value) = *(buffer+cur);
++cur;
return *this;
}
BinaryReader& BinaryReader::operator >> (signed char& value)
{
// _istr.read((char*) &value, sizeof(value));
*((char*)&value) = *(buffer+cur);
++cur;
return *this;
}
BinaryReader& BinaryReader::operator >> (short& value)
{
// _istr.read((char*) &value, sizeof(value));
for(int i=0;i<sizeof(value);++i)
*((char*)&value+i) = *(buffer+cur+i);
cur = cur + sizeof(value);
if (_flipBytes) value = Poco::ByteOrder::flipBytes(value);
return *this;
}
BinaryReader& BinaryReader::operator >> (unsigned short& value)
{
// _istr.read((char*) &value, sizeof(value));
for(int i=0;i<sizeof(value);++i)
*((char*)&value+i) = *(buffer+cur+i);
cur = cur + sizeof(value);
if (_flipBytes) value = Poco::ByteOrder::flipBytes(value);
return *this;
}
BinaryReader& BinaryReader::operator >> (int& value)
{
// _istr.read((char*) &value, sizeof(value));
for(int i=0;i<sizeof(value);++i)
*((char*)&value+i) = *(buffer+cur+i);
cur = cur + sizeof(value);
if (_flipBytes) value = Poco::ByteOrder::flipBytes(value);
return *this;
}
BinaryReader& BinaryReader::operator >> (unsigned int& value)
{
// _istr.read((char*) &value, sizeof(value));
for(int i=0;i<sizeof(value);++i)
*((char*)&value+i) = *(buffer+cur+i);
cur = cur + sizeof(value);
if (_flipBytes) value = Poco::ByteOrder::flipBytes(value);
return *this;
}
BinaryReader& BinaryReader::operator >> (long& value)
{
// _istr.read((char*) &value, sizeof(value));
for(int i=0;i<sizeof(value);++i)
*((char*)&value+i) = *(buffer+cur+i);
cur = cur + sizeof(value);
#if defined(POCO_LONG_IS_64_BIT)
if (_flipBytes) value = Poco::ByteOrder::flipBytes((Poco::Int64) value);
#else
if (_flipBytes) value = Poco::ByteOrder::flipBytes((Poco::Int32) value);
#endif
return *this;
}
BinaryReader& BinaryReader::operator >> (unsigned long& value)
{
// _istr.read((char*) &value, sizeof(value));
for(int i=0;i<sizeof(value);++i)
*((char*)&value+i) = *(buffer+cur+i);
cur = cur + sizeof(value);
#if defined(POCO_LONG_IS_64_BIT)
if (_flipBytes) value = Poco::ByteOrder::flipBytes((Poco::UInt64) value);
#else
if (_flipBytes) value = Poco::ByteOrder::flipBytes((Poco::UInt32) value);
#endif
return *this;
}
BinaryReader& BinaryReader::operator >> (float& value)
{
if (_flipBytes)
{
char* ptr = (char*) &value;
ptr += sizeof(value);
for (unsigned i = 0; i < sizeof(value); ++i)
// _istr.read(--ptr, 1);
*(--ptr) = *(buffer+cur+i);
cur = cur + sizeof(value);
}
else
{
// _istr.read((char*) &value, sizeof(value));
for(int i=0;i<sizeof(value);++i)
*((char*)&value+i) = *(buffer+cur+i);
cur = cur + sizeof(value);
}
return *this;
}
BinaryReader& BinaryReader::operator >> (double& value)
{
if (_flipBytes)
{
char* ptr = (char*) &value;
ptr += sizeof(value);
for (unsigned i = 0; i < sizeof(value); ++i)
// _istr.read(--ptr, 1);
*(--ptr) = *(buffer+cur+i);
cur = cur + sizeof(value);
}
else
{
// _istr.read((char*) &value, sizeof(value));
for(int i=0;i<sizeof(value);++i)
*((char*)&value+i) = *(buffer+cur+i);
cur = cur + sizeof(value);
}
return *this;
}
BinaryReader& BinaryReader::operator >> (std::string& value)
{
Poco::UInt32 size = 0;
read7BitEncoded(size);
value.clear();
if (!good()) return *this;
value.reserve(size);
while (size--)
{
char c;
// if (!_istr.read(&c, 1).good()) break;
if(!good()) break;
*((char*)&c) = *(buffer+cur);
++cur;
value += c;
}
if (_pTextConverter)
{
std::string converted;
_pTextConverter->convert(value, converted);
std::swap(value, converted);
}
return *this;
}
void BinaryReader::read7BitEncoded(Poco::UInt32& value)
{
char c;
value = 0;
int s = 0;
do
{
c = 0;
// _istr.read(&c, 1);
*((char*)&c) = *(buffer+cur);
++cur;
Poco::UInt32 x = (c & 0x7F);
x <<= s;
value += x;
s += 7;
}
while (c & 0x80);
}
void BinaryReader::readRaw(std::streamsize length, std::string& value)
{
value.clear();
value.reserve(static_cast<std::string::size_type>(length));
while (length--)
{
char c;
// if (!_istr.read(&c, 1).good()) break;
if(!good()) break;
*((char*)&c) = *(buffer+cur);
++cur;
value += c;
}
}
void BinaryReader::readRaw(char* buf, std::streamsize length)
{
// _istr.read(buffer, length);
for(int i=0;i<length;++i)
*(buf+i) = *(buffer+cur+i);
cur = cur + length;
}
} // namespace Linyanwen
轉載請註明出處:山水間部落格,http://blog.csdn.net/linyanwen99/article/details/8599680