前公司有个这样的类(感觉很像stringstream),主要是网络中传数据用的(大概是因为要考虑字节序的问题,所以有了这么一个类),不过公司的实现有一个可移植性的问题:比如将网络中的一端流入一个int/long类型的数据,只要两端int/long占用字节大小不一致,那么在网络的另一端流出就会出问题。
今天自己依据其原理写了个,当然我的实现在空间上是不及前公司的,因为前公司的有一些优化,比如bool只占1bit,一个int数据可能占1/2/3/4byte;我的没有这些,bool占1bit的思想,我感觉写在上层更好,如果有必要的话;对于比较小的数压缩下空间倒是不错的想法。另外,公司是一个类,我的是三个。
写这篇文章不会被告侵权吧?!
#ifndef __BYTE_STREAM_H__
#define __BYTE_STREAM_H__
#include <string>
using std::string;
class ByteStream
{
public:
ByteStream(unsigned short len);
~ByteStream();
private:
ByteStream(const ByteStream &);
ByteStream & operator = (const ByteStream &);
public:
static void big2little(void * obj, unsigned int size);
bool seek(unsigned short offset);
unsigned short tell();
unsigned short left();
protected:
unsigned short m_length;
unsigned short m_offset;
};
class OBStream : public ByteStream
{
public:
OBStream(char * byte, unsigned short len);
~OBStream();
public:
void init(char * byte, unsigned short len);
bool writebytes(unsigned short offset,
const void * obj, unsigned short size);
public:
OBStream & write(const char * ptr, unsigned short size);
OBStream & operator << (bool);
OBStream & operator << (signed char);
OBStream & operator << (unsigned char);
OBStream & operator << (signed short);
OBStream & operator << (unsigned short);
OBStream & operator << (signed int);
OBStream & operator << (unsigned int);
OBStream & operator << (signed long);
OBStream & operator << (unsigned long);
OBStream & operator << (float);
OBStream & operator << (double);
OBStream & operator << (const string &);
private:
char * m_byte;
};
class IBStream : public ByteStream
{
public:
IBStream(const char * byte, unsigned short len);
~IBStream();
public:
void init(const char * byte, unsigned short len);
bool readbytes(unsigned short offset,
void * obj, unsigned short size);
public:
IBStream & read(char * ptr, unsigned short size);
IBStream & operator >> (bool &);
IBStream & operator >> (signed char &);
IBStream & operator >> (unsigned char &);
IBStream & operator >> (signed short &);
IBStream & operator >> (unsigned short &);
IBStream & operator >> (signed int &);
IBStream & operator >> (unsigned int &);
IBStream & operator >> (signed long &);
IBStream & operator >> (unsigned long &);
IBStream & operator >> (float &);
IBStream & operator >> (double &);
IBStream & operator >> (string &);
private:
const char * m_byte;
};
#endif
#include <cassert>
#include <cstring>
#include "ByteStream.h"
ByteStream::ByteStream(unsigned short len)
: m_length(len), m_offset(0)
{
}
ByteStream::~ByteStream()
{
}
void ByteStream::big2little(void * obj, unsigned int size)
{
static union {
unsigned short us;
unsigned char uc[sizeof(unsigned short)];
} un;
un.us = 0x0001;
if (0x00 == un.uc[0]) {
char * ptr = static_cast<char *>(obj);
for (int i = 0; i < size / 2; ++i) {
char temp = ptr[i];
ptr[i] = ptr[size - 1 - i];
ptr[size - 1 - i] = temp;
}
}
}
bool ByteStream::seek(unsigned short offset)
{
if (offset <= m_length) {
m_offset = offset;
return(true);
}
else {
return(false);
}
}
unsigned short ByteStream::tell()
{
return(m_offset);
}
unsigned short ByteStream::left()
{
return(m_length - m_offset);
}
OBStream::OBStream(char * byte, unsigned short len)
: ByteStream(len), m_byte(byte)
{
}
OBStream::~OBStream()
{
}
void OBStream::init(char * byte, unsigned short len)
{
m_length = len;
m_offset = 0;
m_byte = byte;
}
bool OBStream::writebytes(unsigned short offset,
const void * obj, unsigned short size)
{
if (offset + size <= m_length) {
memcpy(m_byte + offset, obj, size);
return(true);
}
else {
return(false);
}
}
OBStream & OBStream::write(const char * ptr, unsigned short size)
{
assert(m_offset + size <= m_length);
writebytes(m_offset, ptr, size);
m_offset += size;
return(*this);
}
OBStream & OBStream::operator << (bool value)
{
assert(m_offset + sizeof(bool) <= m_length);
big2little(&value, sizeof(bool));
writebytes(m_offset, &value, sizeof(bool));
m_offset += sizeof(bool);
return(*this);
}
OBStream & OBStream::operator << (signed char value)
{
assert(m_offset + sizeof(signed char) <= m_length);
big2little(&value, sizeof(signed char));
writebytes(m_offset, &value, sizeof(signed char));
m_offset += sizeof(signed char);
return(*this);
}
OBStream & OBStream::operator << (unsigned char value)
{
assert(m_offset + sizeof(unsigned char) <= m_length);
big2little(&value, sizeof(unsigned char));
writebytes(m_offset, &value, sizeof(unsigned char));
m_offset += sizeof(unsigned char);
return(*this);
}
OBStream & OBStream::operator << (signed short value)
{
assert(m_offset + sizeof(signed short) <= m_length);
big2little(&value, sizeof(signed short));
writebytes(m_offset, &value, sizeof(signed short));
m_offset += sizeof(signed short);
return(*this);
}
OBStream & OBStream::operator << (unsigned short value)
{
assert(m_offset + sizeof(unsigned short) <= m_length);
big2little(&value, sizeof(unsigned short));
writebytes(m_offset, &value, sizeof(unsigned short));
m_offset += sizeof(unsigned short);
return(*this);
}
OBStream & OBStream::operator << (signed int value)
{
assert(m_offset + sizeof(unsigned char) + sizeof(signed int) <= m_length);
unsigned char size = static_cast<unsigned char>(sizeof(signed int));
operator << (size);
big2little(&value, sizeof(signed int));
writebytes(m_offset, &value, sizeof(signed int));
m_offset += sizeof(signed int);
return(*this);
}
OBStream & OBStream::operator << (unsigned int value)
{
assert(m_offset + sizeof(unsigned char) + sizeof(unsigned int) <= m_length);
unsigned char size = static_cast<unsigned char>(sizeof(unsigned int));
operator << (size);
big2little(&value, sizeof(unsigned int));
writebytes(m_offset, &value, sizeof(unsigned int));
m_offset += sizeof(unsigned int);
return(*this);
}
OBStream & OBStream::operator << (signed long value)
{
assert(m_offset + sizeof(unsigned char) + sizeof(signed long) <= m_length);
unsigned char size = static_cast<unsigned char>(sizeof(signed long));
operator << (size);
big2little(&value, sizeof(signed long));
writebytes(m_offset, &value, sizeof(signed long));
m_offset += sizeof(signed long);
return(*this);
}
OBStream & OBStream::operator << (unsigned long value)
{
assert(m_offset + sizeof(unsigned char) + sizeof(unsigned long) <= m_length);
unsigned char size = static_cast<unsigned char>(sizeof(unsigned long));
operator << (size);
big2little(&value, sizeof(unsigned long));
writebytes(m_offset, &value, sizeof(unsigned long));
m_offset += sizeof(unsigned long);
return(*this);
}
OBStream & OBStream::operator << (float value)
{
assert(m_offset + sizeof(float) <= m_length);
big2little(&value, sizeof(float));
writebytes(m_offset, &value, sizeof(float));
m_offset += sizeof(float);
return(*this);
}
OBStream & OBStream::operator << (double value)
{
assert(m_offset + sizeof(double) <= m_length);
big2little(&value, sizeof(double));
writebytes(m_offset, &value, sizeof(double));
m_offset += sizeof(double);
return(*this);
}
OBStream & OBStream::operator << (const string & value)
{
assert(m_offset + sizeof(unsigned short) + value.size() <= m_length);
unsigned short size = static_cast<unsigned short>(value.size());
operator << (size);
write(value.c_str(), size);
return(*this);
}
IBStream::IBStream(const char * byte, unsigned short len)
: ByteStream(len), m_byte(byte)
{
}
IBStream::~IBStream()
{
}
void IBStream::init(const char * byte, unsigned short len)
{
m_length = len;
m_offset = 0;
m_byte = byte;
}
bool IBStream::readbytes(unsigned short offset,
void * obj, unsigned short size)
{
if (offset + size <= m_length) {
memcpy(obj, m_byte + offset, size);
return(true);
}
else {
return(false);
}
}
IBStream & IBStream::read(char * ptr, unsigned short size)
{
assert(m_offset + size <= m_length);
readbytes(m_offset, ptr, size);
m_offset += size;
return(*this);
}
IBStream & IBStream::operator >> (bool & value)
{
assert(m_offset + sizeof(bool) <= m_length);
readbytes(m_offset, &value, sizeof(bool));
big2little(&value, sizeof(bool));
m_offset += sizeof(bool);
return(*this);
}
IBStream & IBStream::operator >> (signed char & value)
{
assert(m_offset + sizeof(signed char) <= m_length);
readbytes(m_offset, &value, sizeof(signed char));
big2little(&value, sizeof(signed char));
m_offset += sizeof(signed char);
return(*this);
}
IBStream & IBStream::operator >> (unsigned char & value)
{
assert(m_offset + sizeof(unsigned char) <= m_length);
readbytes(m_offset, &value, sizeof(unsigned char));
big2little(&value, sizeof(unsigned char));
m_offset += sizeof(unsigned char);
return(*this);
}
IBStream & IBStream::operator >> (signed short & value)
{
assert(m_offset + sizeof(signed short) <= m_length);
readbytes(m_offset, &value, sizeof(signed short));
big2little(&value, sizeof(signed short));
m_offset += sizeof(signed short);
return(*this);
}
IBStream & IBStream::operator >> (unsigned short & value)
{
assert(m_offset + sizeof(unsigned short) <= m_length);
readbytes(m_offset, &value, sizeof(unsigned short));
big2little(&value, sizeof(unsigned short));
m_offset += sizeof(unsigned short);
return(*this);
}
IBStream & IBStream::operator >> (signed int & value)
{
assert(m_offset + sizeof(unsigned char) <= m_length);
unsigned char size = 0;
operator >> (size);
assert(m_offset + size <= m_length);
if (sizeof(signed int) == size) {
readbytes(m_offset, &value, sizeof(signed int));
big2little(&value, sizeof(signed int));
m_offset += sizeof(signed int);
}
else if (sizeof(signed int) > size) {
value = 0;
unsigned char * ptr = reinterpret_cast<unsigned char *>(&value);
for (int i = 0; i < size; ++i) {
operator >> (ptr[i]);
}
big2little(&value, sizeof(signed int));
}
else {
assert(sizeof(signed int) <= 8);
unsigned char ptr[8] = { 0 };
for (int i = 0; i < size; ++i) {
operator >> (ptr[i]);
}
big2little(ptr, size);
value = *(reinterpret_cast<signed int *>(ptr));
}
return(*this);
}
IBStream & IBStream::operator >> (unsigned int & value)
{
assert(m_offset + sizeof(unsigned char) <= m_length);
unsigned char size = 0;
operator >> (size);
assert(m_offset + size <= m_length);
if (sizeof(unsigned int) == size) {
readbytes(m_offset, &value, sizeof(unsigned int));
big2little(&value, sizeof(unsigned int));
m_offset += sizeof(unsigned int);
}
else if (sizeof(unsigned int) > size) {
value = 0;
unsigned char * ptr = reinterpret_cast<unsigned char *>(&value);
for (int i = 0; i < size; ++i) {
operator >> (ptr[i]);
}
big2little(&value, sizeof(unsigned int));
}
else {
assert(sizeof(unsigned int) <= 8);
unsigned char ptr[8] = { 0 };
for (int i = 0; i < size; ++i) {
operator >> (ptr[i]);
}
big2little(ptr, size);
value = *(reinterpret_cast<unsigned int *>(ptr));
}
return(*this);
}
IBStream & IBStream::operator >> (signed long & value)
{
assert(m_offset + sizeof(unsigned char) <= m_length);
unsigned char size = 0;
operator >> (size);
assert(m_offset + size <= m_length);
if (sizeof(signed long) == size) {
readbytes(m_offset, &value, sizeof(signed long));
big2little(&value, sizeof(signed long));
m_offset += sizeof(signed long);
}
else if (sizeof(signed long) > size) {
value = 0;
unsigned char * ptr = reinterpret_cast<unsigned char *>(&value);
for (int i = 0; i < size; ++i) {
operator >> (ptr[i]);
}
big2little(&value, sizeof(signed long));
}
else {
assert(sizeof(signed long) <= 8);
unsigned char ptr[8] = { 0 };
for (int i = 0; i < size; ++i) {
operator >> (ptr[i]);
}
big2little(ptr, size);
value = *(reinterpret_cast<signed long *>(ptr));
}
return(*this);
}
IBStream & IBStream::operator >> (unsigned long & value)
{
assert(m_offset + sizeof(unsigned char) <= m_length);
unsigned char size = 0;
operator >> (size);
assert(m_offset + size <= m_length);
if (sizeof(unsigned long) == size) {
readbytes(m_offset, &value, sizeof(unsigned long));
big2little(&value, sizeof(unsigned long));
m_offset += sizeof(unsigned long);
}
else if (sizeof(unsigned long) > size) {
value = 0;
unsigned char * ptr = reinterpret_cast<unsigned char *>(&value);
for (int i = 0; i < size; ++i) {
operator >> (ptr[i]);
}
big2little(&value, sizeof(unsigned long));
}
else {
assert(sizeof(unsigned long) <= 8);
unsigned char ptr[8] = { 0 };
for (int i = 0; i < size; ++i) {
operator >> (ptr[i]);
}
big2little(ptr, size);
value = *(reinterpret_cast<unsigned long *>(ptr));
}
return(*this);
}
IBStream & IBStream::operator >> (float & value)
{
assert(m_offset + sizeof(float) <= m_length);
readbytes(m_offset, &value, sizeof(float));
big2little(&value, sizeof(float));
m_offset += sizeof(float);
return(*this);
}
IBStream & IBStream::operator >> (double & value)
{
assert(m_offset + sizeof(double) <= m_length);
readbytes(m_offset, &value, sizeof(double));
big2little(&value, sizeof(double));
m_offset += sizeof(double);
return(*this);
}
IBStream & IBStream::operator >> (string & value)
{
assert(m_offset + sizeof(unsigned short) <= m_length);
unsigned short size = 0;
operator >> (size);
assert(m_offset + size <= m_length);
value.resize(size);
read(&value[0], size);
return(*this);
}
#include <complex>
#include <string>
#include <iostream>
using namespace std;
#include "ByteStream.h"
template <typename T>
OBStream & operator << (OBStream & obs, const complex<T> & comp)
{
return(obs << comp.real() << comp.imag());
}
template <typename T>
IBStream & operator >> (IBStream & ibs, complex<T> & comp)
{
T real;
T imag;
ibs >> real >> imag;
comp = complex<T>(real, imag);
return(ibs);
}
int main(int argc, char * argv[])
{
char buffer[100] = { 0 };
bool in_b = true;
signed char in_sc = 'a';
unsigned char in_uc = 'A';
signed short in_ss = 12345;
unsigned short in_us = 65535;
signed int in_si = 123456789;
unsigned int in_ui = 987654321;
signed long in_sl = 11223344;
unsigned long in_ul = 66554433;
float in_f = 123456.789f;
double in_d = 987654321.123456789;
const char * in_ptr = "ByteStream";
string in_str("Hello World");
complex<int> in_comp(123, 456);
cout << in_b << endl;
cout << in_sc << endl;
cout << in_uc << endl;
cout << in_ss << endl;
cout << in_us << endl;
cout << in_si << endl;
cout << in_ui << endl;
cout << in_sl << endl;
cout << in_ul << endl;
cout << in_f << endl;
cout << in_d << endl;
cout << in_ptr << endl;
cout << in_str << endl;
cout << in_comp << endl;
unsigned short in_size = 0;
OBStream obs(buffer, 100);
(obs << in_size << in_b << in_sc << in_uc << in_ss
<< in_us << in_si << in_ui << in_sl << in_ul
<< in_f << in_d).write(in_ptr, 10) << in_str << in_comp;
in_size = obs.tell();
obs.seek(0);
obs << in_size;
obs.seek(in_size);
cout << "write " << in_size << " Bytes" << endl;
unsigned short out_size;
bool out_b;
signed char out_sc;
unsigned char out_uc;
signed short out_ss;
unsigned short out_us;
signed int out_si;
unsigned int out_ui;
signed long out_sl;
unsigned long out_ul;
float out_f;
double out_d;
char out_ptr[11] = { 0 };
string out_str;
complex<int> out_comp;
IBStream ibs(buffer, obs.tell());
(ibs >> out_size >> out_b >> out_sc >> out_uc >> out_ss
>> out_us >> out_si >> out_ui >> out_sl >> out_ul
>> out_f >> out_d).read(out_ptr, 10) >> out_str >> out_comp;
cout << "read " << out_size << " Bytes" << endl;
cout << out_b << endl;
cout << out_sc << endl;
cout << out_uc << endl;
cout << out_ss << endl;
cout << out_us << endl;
cout << out_si << endl;
cout << out_ui << endl;
cout << out_sl << endl;
cout << out_ul << endl;
cout << out_f << endl;
cout << out_d << endl;
cout << out_ptr << endl;
cout << out_str << endl;
cout << out_comp << endl;
return(0);
}
#include <iostream>
using namespace std;
#include "ByteStream.h"
int main(int argc, char * argv[])
{
char buffer[32] = { 0 };
unsigned short in_int = 65535;
unsigned char in_int_len = sizeof(unsigned short);
long in_long = 123456;
double * in_p_long = reinterpret_cast<double *>(&in_long);
unsigned char in_long_len = sizeof(double);
unsigned short in_size = 0;
OBStream obs(buffer, 100);
obs << in_size;
obs << in_int_len << in_int; /* less-int: (len + short) like a 16bit-int*/
obs << in_long_len << (*in_p_long); /* large-long: (len + double) like a 64bit-long */
in_size = obs.tell();
obs.seek(0);
obs << in_size;
obs.seek(in_size);
cout << in_int << endl;
cout << in_long << endl;
cout << "write " << in_size << " Bytes" << endl;
unsigned short out_size = 0;
signed int out_int = 0;
signed long out_long = 0;
IBStream ibs(buffer, obs.tell());
ibs >> out_size;
ibs >> out_int; /* large-int */
ibs >> out_long; /* less-long */
cout << "read " << out_size << " Bytes" << endl;
cout << out_int << endl;
cout << out_long << endl;
return(0);
}
今天被complex<T>整了,1是对它不熟,2是模板报错乱七八糟