#ifdef HAVE_CONFIG_H # include "config.h" #endif #include #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 m_elms; }; TxPacket_impl::TxPacket_impl(int major,int minor) { m_major = major; m_minor = minor; } TxPacket_impl::~TxPacket_impl() { std::list::iterator i; for ( i = m_elms.begin() ; i != m_elms.end() ; i++){ delete *i; } } int TxPacket_impl::get_length() { std::list::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::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: */