#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <list>
#include "xim.h"
//
// Routines for byte manipulating
//
int
rup4(int l)
{
if ((l%4)==0) {
return l;
}
return (l&0xffffffc)+4;
}
void
writeC8(C8 val, int byte_order, unsigned char *buf)
{
buf[0] = val;
}
void writeC16(C16 val,int byte_order,unsigned char *buf)
{
if ( byte_order == LSB_FIRST ){
buf[0] = val & 255;
buf[1] = (val >> 8) & 255;
}else{
buf[1] = val & 255;
buf[0] = (val >> 8) & 255;
}
}
void writeC32(unsigned int val,int byte_order,unsigned char *buf)
{
if ( byte_order == LSB_FIRST ){
buf[0] = val & 255;
buf[1] = (val >> 8) & 255;
buf[2] = (val >> 16) & 255;
buf[3] = (val >> 24) & 255;
}else{
buf[3] = val & 255;
buf[2] = (val >> 8) & 255;
buf[1] = (val >> 16) & 255;
buf[0] = (val >> 24) & 255;
}
}
C8 readC8(unsigned char *buf)
{
return buf[0];
}
C16 readC16(unsigned char *buf,int byte_order)
{
C16 v;
if ( byte_order == LSB_FIRST ){
v = buf[0] + buf[1]*256;
}else{
v = buf[1] + buf[0]*256;
}
return v;
}
C32 readC32(unsigned char *buf,int byte_order)
{
C32 v;
if ( byte_order == LSB_FIRST ){
v = buf[0] + buf[1]*256 + (buf[2]<<16) +(buf[3]<<24);
}else{
v = buf[3] + buf[2]*256 + (buf[1]<<16) +(buf[0]<<24);
}
return v;
}
//
// TxPacket
//
class TxElement{
public:
virtual ~TxElement(){};
virtual int get_size()=0;
virtual int write_to_buf(unsigned char *buf,int byte_order)=0;
};
class TxC8 : public TxElement{
public:
TxC8(int v){
val = v;
}
int get_size()
{
return 1;
}
int write_to_buf(unsigned char *buf,int bo)
{
writeC8(val,bo,buf);
return 1;
}
private:
C8 val;
};
class TxC16 : public TxElement{
public:
TxC16(int v){
val = v;
}
int get_size()
{
return 2;
}
int write_to_buf(unsigned char *buf,int bo)
{
writeC16(val,bo,buf);
return 2;
}
private:
C16 val;
};
class TxC32 : public TxElement{
public:
TxC32(unsigned int v){
val = v;
}
int get_size()
{
return 4;
}
int write_to_buf(unsigned char *buf,int bo)
{
writeC32(val,bo,buf);
return 4;
}
private:
C32 val;
};
class TxString : public TxElement{
public:
TxString(char *s){
init(s,strlen(s));
}
TxString(char *s,int len){
init(s,len);
}
~TxString(){
free(m_str);
}
int get_size(){
return 2+m_len+pad4(2+m_len);
}
int write_to_buf(unsigned char *buf,int bo){
writeC16(m_len,bo,buf);
memcpy(&buf[2],m_str,m_len);
return get_size();
}
private:
void init(char *s,int len)
{
m_len = len;
m_str = (char *)malloc(len+1);
strncpy(m_str,s,len);
}
int m_len;
char *m_str;
};
class TxBytes : public TxElement{
public:
TxBytes(char *s,int len)
{
m_str = (char *)malloc(len);
m_len = len;
memcpy(m_str,s,len);
};
~TxBytes()
{
free(m_str);
}
int get_size()
{
return m_len;
}
int write_to_buf(unsigned char *buf,int bo){
memcpy(buf,m_str,m_len);
return get_size();
}
private:
int m_len;
char *m_str;
};
class TxPacket_impl : public TxPacket{
public:
TxPacket_impl(int major,int minor);
~TxPacket_impl();
int get_length();
int write_to_buf(unsigned char *buf,int buflen,int byte_order);
void dump(int byte_order);
int get_major();
int pushC8(unsigned int);
int pushC16(unsigned int );
int pushC32(unsigned int );
int pushSTRING(char *);
int pushBytes(char *,int );
int pop_back();
private:
void write_header(unsigned char *buf,int l,int byte_order);
int m_major,m_minor;
std::list <TxElement *> m_elms;
};
TxPacket_impl::TxPacket_impl(int major,int minor)
{
m_major = major;
m_minor = minor;
}
TxPacket_impl::~TxPacket_impl()
{
std::list<TxElement *>::iterator i;
for ( i = m_elms.begin() ; i != m_elms.end() ; i++){
delete *i;
}
}
int TxPacket_impl::get_length()
{
std::list<TxElement *>::iterator i;
int l;
l = 4;
for ( i = m_elms.begin() ; i != m_elms.end() ; i++){
l += (*i)->get_size();
}
return l;
}
int TxPacket_impl::write_to_buf(unsigned char *buf,int buflen,int byte_order)
{
std::list<TxElement *>::iterator i;
int l,m;
l = 4;
for ( i = m_elms.begin() ; i != m_elms.end() ; i++){
m = (*i)->get_size();
if ( l + m > buflen ){
return 0;
}
m = (*i)->write_to_buf(&buf[l],byte_order);
l +=m;
}
l = rup4(l);
write_header(buf,l,byte_order);
return l;
}
int TxPacket_impl::pushC8(unsigned int v)
{
TxElement *e;
e = new TxC8(v);
m_elms.push_back(e);
return e->get_size();
}
int TxPacket_impl::pushC16(unsigned int v)
{
TxElement *e;
e = new TxC16(v);
m_elms.push_back(e);
return e->get_size();
}
int TxPacket_impl::pushC32(unsigned int v)
{
TxElement *e;
e = new TxC32(v);
m_elms.push_back(e);
return e->get_size();
}
int TxPacket_impl::pushSTRING(char *s)
{
TxElement *e;
e = new TxString(s);
m_elms.push_back(e);
return e->get_size();
}
int TxPacket_impl::pushBytes(char *b,int len)
{
TxElement *e;
e = new TxBytes(b,len);
m_elms.push_back(e);
return e->get_size();
}
int TxPacket_impl::pop_back()
{
int len;
TxElement *e;
e = m_elms.back();
len = e->get_size();
delete e;
m_elms.pop_back();
return len;
}
void TxPacket_impl::write_header(unsigned char *buf,int l,int byte_order)
{
buf[0] = m_major;
buf[1] = m_minor;
writeC16(l/4-1,byte_order,&buf[2]);
}
void TxPacket_impl::dump(int byte_order)
{
unsigned char *buf;
int len;
len = get_length();
buf = (unsigned char *)malloc(len);
write_to_buf(buf,len,byte_order);
hex_dump(buf,len);
free(buf);
}
int TxPacket_impl::get_major()
{
return m_major;
}
TxPacket *createTxPacket(int major,int minor)
{
return new TxPacket_impl(major,minor);
}
//
// Routines for RxPacket
//
class RxPacket_impl : public RxPacket{
public:
RxPacket_impl(unsigned char *buf,int byte_order);
void rewind();
C8 getC8();
C16 getC16();
C32 getC32();
int getStrLen();
void getStr(char *buf);
int getStr8Len();
void getStr8(char *);
int getMajor();
void dump();
bool isOverRun(){
if ( (g_option_mask & OPT_TRACE) && mIsOverRun ){
printf("RxPacket Overrun.\n");
}
return mIsOverRun;
};
private:
bool canRead(int );
int mLen;
unsigned char *mBuf;
int mIndex;
int mByteOrder;
bool mIsOverRun;
};
RxPacket_impl::RxPacket_impl(unsigned char *b,int byte_order)
{
mLen = getPacketLength(b,byte_order);
mBuf = (unsigned char *)malloc(mLen);
memcpy(mBuf,b,mLen);
mByteOrder = byte_order;
rewind();
}
void RxPacket_impl::rewind()
{
mIndex = 4;
mIsOverRun = false;
}
C8 RxPacket_impl::getC8()
{
C8 v;
if ( !canRead(1)){
mIsOverRun = true;
return 0;
}
v = readC8(&mBuf[mIndex]);
mIndex += 1;
return v;
}
C16 RxPacket_impl::getC16()
{
C16 v;
if ( !canRead(2)){
mIsOverRun = true;
return 0;
}
v = readC16(&mBuf[mIndex], mByteOrder);
mIndex += 2;
return v;
}
C32 RxPacket_impl::getC32()
{
C32 v;
if ( !canRead(4)){
mIsOverRun = true;
return 0;
}
v = readC32(&mBuf[mIndex], mByteOrder);
mIndex += 4;
return v;
}
int RxPacket_impl::getStrLen()
{
if ( !canRead(2)){
mIsOverRun = true;
return 0;
}
return readC16(&mBuf[mIndex],mByteOrder);
}
void RxPacket_impl::getStr(char *buf)
{
int l;
l = getStrLen();
if ( !canRead(l+2)){
mIsOverRun = true;
return ;
}
memcpy(buf,&mBuf[mIndex+2],l);
mIndex += (2 + l + pad4(2+l));
}
int RxPacket_impl::getStr8Len()
{
if ( !canRead(1)){
mIsOverRun = true;
return 0;
}
return readC8(&mBuf[mIndex]);
}
void RxPacket_impl::getStr8(char *buf)
{
int l;
l = getStr8Len();
if ( !canRead(l+1)){
mIsOverRun = true;
return ;
}
memcpy(buf,&mBuf[mIndex+1],l);
mIndex += (1+l);
}
int RxPacket_impl::getMajor()
{
return mBuf[0];
}
void RxPacket_impl::dump()
{
hex_dump(mBuf,mLen);
}
bool RxPacket_impl::canRead(int s)
{
if ( mIndex +s > mLen ){
return false;
}
return true;
}
// static methods
int RxPacket::getPacketLength(unsigned char *buf, int byte_order)
{
if (byte_order == BYTEORDER_UNKNOWN) {
return 0;
}
return readC16(&buf[2], byte_order)*4+4;
}
RxPacket *createRxPacket(unsigned char *buf,int byte_order)
{
return new RxPacket_impl(buf,byte_order);
}
/*
* Local variables:
* c-indent-level: 4
* c-basic-offset: 4
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1