a utility for compressing messages to be shared among processes


 

Data shared among processes could be limited to integers and strings. Other types could be present with these two types.

1.     A floating value could be presented in the form of mantissa and exponent, both could be int type.

2.     Composed types are  built upon integers and strings

Keys:

1.     A string is a sequence of bytes leading its length

2.     An integer is in the form of a sequence of bytes. For each byte, the highest byte is an indicator showing whether more bytes followed; the lower 7bits of all bytes compose that integer. The 1th byte is for 0-6th bit of the integer, the 2nd byte is for 7-13th bit of that integer, etc. Why we do this way? It's independent of the byte order of the system. And it could also save memory. e.g., an int of 56 normally occupies 4 bytes for a 32-bit system. Encode it with our tool, only 1 byte is needed. As long as we have a well-designed protocol, we could save a lot of network bandwidth.

The code is attached bellow. Comments are welcomed via emails. Enjoy :-).  

 

 

//feel free to use it in your project with nothing guaranteed
//mail to: bruceadi(at)hotmail.com 
#include <iostream> 
#include <fstream>

class encoder
{
public:
  encoder(std::ostream& os): os_(os)
  {
  }

  encoder& operator <<(int val)
  {   
    return *this << (unsigned int)(val);
  }

  encoder& operator <<(unsigned int val)
  {
    do
    {
      unsigned char b = val & 0x7f;
      val >>= 7;
      if(val) b |= 0x80;
      os_.write((char*)&b, 1);
    }while(val);
    return *this;
  } 

  encoder& operator <<(char val)
  {
    os_.write(&val, 1);
    return *this;
  }

  encoder& operator <<(unsigned char val)
  {
    os_.write((char*)&val, 1);
    return *this;
  }

  encoder& operator <<(signed char val)
  {
    os_.write((char*)&val, 1);
    return *this;
  }

  encoder& operator <<(char const* val)
  {
    size_t len = strlen(val); 
    *this << len;
    os_.write(val, len);
    return *this;
  }

private:
  encoder& operator=(encoder const&);
  encoder(encoder const&);
  std::ostream& os_;
};

class decoder
{
public:
  decoder(std::istream& is): is_(is)
  {
  }

  decoder& operator >> (int& val)
  {
    unsigned int v;
    *this >> v;
    val = (int)v;
    return *this;
  }

  decoder& operator >> (unsigned int& val)
  {
    val = 0;
    unsigned char ch, cnt = 0;
    do
    {
      is_.read((char*)&ch, 1);
      val += (ch & 0x7f) << cnt;
      cnt += 7;
    }while(ch & 0x80);
    return *this;
  }

  decoder& operator >> (char& val)
  {
    is_.read(&val, 1); 
    return *this;
  }

  decoder& operator >> (unsigned char& val)
  {
    is_.read((char*)&val, 1); 
    return *this;
  }

  decoder& operator >> (signed char& val)
  {
    is_.read((char*)&val, 1); 
    return *this;
  }

  decoder& operator >> (char* val)
  {
    size_t len; 
    *this >> len;
    is_.read(val, len);  
    val[len] = 0;
    return *this;
  }

private:
  decoder& operator=(decoder const&);
  decoder(decoder const&);
  std::istream& is_;
};

//the following code is only for demostration, not part of the library 

struct Float
{
  int exp;
  int man;
};

encoder& operator<<(encoder & en,Float const& f)
{
  return en << f.man << f.exp;
}

decoder& operator >> (decoder & de, Float& f)
{
  return de >> f.man >> f.exp;
}



struct Message
{
  char c;
  short s;
  int i;
  unsigned char str[2];
  char name[4];
};



encoder& operator<<(encoder & en,Message const& msg)
{

  en << msg.c << (int)msg.s << msg.i;
  for(size_t i = 0; i < sizeof(msg.str); ++i)
  {
    en << msg.str[i];
  }
  en << msg.name;
  return en;
}

decoder& operator >> (decoder & de,Message & msg)
{
  de >>  msg.c;
  int s;
  de >> s >> msg.i;
  msg.s = (short)s;
  for(size_t i = 0; i < sizeof(msg.str); ++i)
  {
    de >> msg.str[i];
  }
  de >> msg.name;
  return de;
}


std::ostream& operator<<(std::ostream& os, Message const& msg)
{
  return os << msg.c << " " << msg.s << " " <<  msg.i << " " << (int)msg.str[0] << " "<< (int)msg.str[1] << " " 
  << (unsigned int)msg.name[0] << " "<< (unsigned int)msg.name[1] << " "
  << (unsigned int)msg.name[2] << " "<< (unsigned int)msg.name[3] << std::endl;
}

std::ostream& operator<<(std::ostream& os, Float const& f)
{
  return os << f.exp << " " << f.man;
}


template <typename T>
void test(T const& a )
{
  {
    std::cout << "before: " << std::endl  << a << std::endl;
    std::ofstream ofs("bin");
    encoder en(ofs);
    en << a;
  }

  {
    T msg;
    std::ifstream ifs("bin");
    decoder de(ifs);
    de >>  msg;
    std::cout <<  "after: " << std::endl << msg << std::endl;
  }
}
int main ()
{
  test(7867);

  test(90U);

  Message msg;
  strncpy(msg.name, "yello ass", sizeof(msg.name) -1 );
  test(msg);

  Float f;
  test(f);


  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值