#ifndef _XDR_CLASS_H_ #define _XDR_CLASS_H_ #include #include #include #if defined (ultrix) || defined (sgi) || defined (solaris) #include #endif // Under TGV Multinet and VMS, before you can #include rpc/xdr.h (below), // rpc/types.h must be included, so that bool_t is defined and sys/types.h is // #included. // // Under TGV Multinet and VMS, if you want sys/types.h, you need to have // types.h already pulled in because sys/types.h makes it look like types.h // is loaded. Then when types.h does get loaded, it is ignored because it // looks like it is already loaded. // // rpc/types.h defines bool_t, required by rpc/xdr.h // rpc/types.h #includes sys/types.h // sys/types.h defines caddr_t, required by rpc/xdr.h and // defines u_int,u_short required by netinet/in.h // --Mr. Daniel Van Olst at SLAC vanolst@slc.slac.stanford.edu #ifdef __VMS #ifdef _TGV_MULTINET #include #include #include #include #endif #include #endif #ifdef _WIN32 #include "xdr.h" #else #include #include #endif #include static bool_t xdr_timestamp( XDR * xdrs, cdev_TS_STAMP * ts) { if ( xdr_u_long (xdrs, &ts->secPastEpoch) == 0) return 0; return (xdr_u_long (xdrs, &ts->nsec)); } // ***************************************************************************** // * XDR_Size_of : // * Functions used to determine the size of a data element once translated // * and placed into an XDR stream. // ***************************************************************************** #if !defined( NO_TEMPLATES ) template inline unsigned XDR_Sizeof( T t ) { return (RNDUP(sizeof(t))); } #else inline unsigned XDR_Sizeof(char x) { return (RNDUP(sizeof(x))); } inline unsigned XDR_Sizeof(unsigned char x) { return (RNDUP(sizeof(x))); } inline unsigned XDR_Sizeof(short x) { return (RNDUP(sizeof(x))); } inline unsigned XDR_Sizeof(unsigned short x) { return (RNDUP(sizeof(x))); } inline unsigned XDR_Sizeof(int x) { return (RNDUP(sizeof(x))); } inline unsigned XDR_Sizeof(unsigned int x) { return (RNDUP(sizeof(x))); } inline unsigned XDR_Sizeof(long x) { return (RNDUP(sizeof(x))); } inline unsigned XDR_Sizeof(unsigned long x) { return (RNDUP(sizeof(x))); } inline unsigned XDR_Sizeof(float x) { return (RNDUP(sizeof(x))); } inline unsigned XDR_Sizeof(double x) { return (RNDUP(sizeof(x))); } #endif inline unsigned XDR_Sizeof( char * s ) { return (RNDUP(strlen(s)) + BYTES_PER_XDR_UNIT); } inline unsigned XDR_Sizeof( char *, unsigned len ) { return (RNDUP(len) + BYTES_PER_XDR_UNIT); } inline unsigned XDR_Sizeof( void *, unsigned len ) { return (RNDUP(len) + BYTES_PER_XDR_UNIT); } inline unsigned XDR_Sizeof( cdev_TS_STAMP ts ) { return (RNDUP(sizeof(ts))); } typedef struct { unsigned bufLen; char * buf; } XDR_DataBlock; // ***************************************************************************** // * This is the XDR_Data class. It allows the user to pass the data associated // * with the XDR_Writer and XDR_Reader classes in a format that is not // * restricted to XDR read or XDR write. // ***************************************************************************** class XDR_Data : public XDR_DataBlock { public: XDR_Data ( void ) { buf = NULL; bufLen = 0; } XDR_Data ( char * Buf, unsigned Len ) { buf = NULL; bufLen = 0; assign(Buf, Len); } XDR_Data ( XDR_Data & x ) { buf = NULL; bufLen = 0; assign(x.buf, x.bufLen); } ~XDR_Data ( void ) { deallocate(); } unsigned & size ( void ) { return bufLen; } char * & buffer ( void ) { return buf; } int ready ( void ) { return (buf!=NULL && bufLen>0)?1:0; } void allocate ( unsigned Len ) { if(Len==0) XDR_Data::deallocate(); else if(Len!=bufLen || buf==NULL) { XDR_Data::deallocate(); bufLen = Len; buf = new char[bufLen]; XDR_Data::clear(); } else XDR_Data::clear(); } void deallocate ( void ) { if(buf!=NULL) { delete buf; buf = NULL; } bufLen = 0; } void assign ( char * Buf, unsigned Len) { XDR_Data::allocate(Len); memcpy(buf, Buf, bufLen); } void clear ( void ) { memset(buf, 0, bufLen); } void attachData ( XDR_Data & data ) { attachData(data.buf, data.bufLen); } void attachData ( char * Buf, unsigned BufLen ) { XDR_Data::deallocate(); buf = Buf; bufLen = BufLen; } void detachData ( void ) { buf = 0; bufLen = 0; } }; // ***************************************************************************** // * This is the XDR_Base class. It provides the basic mechanism for generating // * character streams that contain XDR data storage. // ***************************************************************************** class XDR_Base : public XDR_Data { protected: XDR xdrs; const enum xdr_op op; XDR_Base (enum xdr_op xop ) : XDR_Data(), op(xop) {} XDR_Base (XDR_Data & xdrData, enum xdr_op xop) : op(xop) { allocate(xdrData.size()); memcpy(buf, xdrData.buffer(), xdrData.size()); xdr_setpos(xdr(), 0); } ~XDR_Base ( void ) { deallocate(); } public: XDR * xdr ( void ) { return &xdrs; } unsigned position ( void ) { return ready()?xdr_getpos(&xdrs):0L; } void allocate ( unsigned Len) { if(Len==0) XDR_Base::deallocate(); else if(Len!=bufLen || buf==NULL) { XDR_Base::deallocate(); XDR_Data::allocate(Len); xdrmem_create(&xdrs, buf, bufLen, op); } else XDR_Data::clear(); } void deallocate ( void ) { if(ready()) { xdr_destroy(&xdrs); XDR_Data::deallocate(); } } void clear ( void ) { if(ready()) { XDR_Data::clear(); xdr_setpos(&xdrs, 0); } } void attachData ( XDR_Data & data ) { XDR_Base::attachData(data.buf, data.bufLen); } void attachData ( char * Buf, unsigned BufLen ) { XDR_Base::deallocate(); XDR_Data::attachData(Buf, BufLen); xdrmem_create(&xdrs, buf, bufLen, op); } void detachData ( void ) { XDR_Data::detachData(); XDR_Base::deallocate(); } }; // ***************************************************************************** // * This is the XDR_Writer class. It provides the mechanisms for creating and // * managing an outgoing stream of XDR data. // ***************************************************************************** class XDR_Writer : public XDR_Base { public: XDR_Writer (unsigned len = 0) : XDR_Base(XDR_ENCODE) { XDR_Base::allocate(len); } XDR_Writer (XDR_Data & xdrData ) : XDR_Base(xdrData, XDR_ENCODE) {} int put_char ( char x ) { return ready()?xdr_char(&xdrs, &x):0; } int put_u_char ( unsigned char x ) #ifndef sunos4 { return ready()?xdr_u_char(&xdrs, &x):0; } #else { return ready()?xdr_u_char(&xdrs, (char *)&x):0; } #endif int put_int ( int x ) { return ready()?xdr_int(&xdrs, &x):0; } int put_u_int ( unsigned int x ) { return ready()?xdr_u_int(&xdrs, &x):0; } int put_short ( short x ) { return ready()?xdr_short(&xdrs, &x):0; } int put_u_short( unsigned short x ) { return ready()?xdr_u_short(&xdrs, &x):0; } int put_long ( long x ) { return ready()?xdr_long(&xdrs, &x):0; } int put_u_long ( unsigned long x ) { return ready()?xdr_u_long(&xdrs, &x):0; } int put_float ( float x ) { return ready()?xdr_float(&xdrs, &x):0; } int put_double ( double x ) { return ready()?xdr_double(&xdrs, &x):0; } int put_bytes ( char ** bytes, unsigned int num ) { return ready()? xdr_bytes(&xdrs, bytes, &num, size()-position()): 0; } int put_string ( char * str ) { return ready()? xdr_string(&xdrs, &str, size()-position()): 0; } int put_opaque ( void * data, unsigned len ) { int status = 0; if(ready()) { status=xdr_u_int (&xdrs, &len); if(status) status=xdr_opaque(&xdrs, (char *)data, len); } return status; } int put_timestamp ( cdev_TS_STAMP ts ) { return ready()?xdr_timestamp(&xdrs, &ts):0; } int put ( char x ) { return put_char(x); } int put ( unsigned char x ) { return put_u_char(x); } int put ( int x ) { return put_int(x); } int put ( unsigned int x ) { return put_u_int(x); } int put ( short x ) { return put_short(x); } int put ( unsigned short x ) { return put_u_short(x); } int put ( long x ) { return put_long(x); } int put ( unsigned long x ) { return put_u_long(x); } int put ( float x ) { return put_float(x); } int put ( double x ) { return put_double(x); } int put ( char * str ) { return put_string(str); } int put ( void * x, unsigned len ) { return put_opaque(x, len); } int put ( cdev_TS_STAMP ts ) { return put_timestamp(ts); } }; // ***************************************************************************** // * This is the XDR_Reader class. It provides the mechanisms for creating and // * managing an incoming stream of XDR data. // ***************************************************************************** class XDR_Reader : public XDR_Base { public: XDR_Reader (unsigned len = 0) : XDR_Base(XDR_DECODE) { XDR_Base::allocate(len); } XDR_Reader (XDR_Data & xdrData ) : XDR_Base(xdrData, XDR_DECODE) {} int get_char ( char & x ) { return ready()?xdr_char(&xdrs, &x):0; } int get_u_char ( unsigned char & x ) #ifndef sunos4 { return ready()?xdr_u_char(&xdrs, &x):0; } #else { return ready()?xdr_u_char(&xdrs, (char *)&x):0; } #endif int get_int ( int & x ) { return ready()?xdr_int(&xdrs, &x):0; } int get_u_int ( unsigned int & x ) { return ready()?xdr_u_int(&xdrs, &x):0; } int get_short ( short & x ) { return ready()?xdr_short(&xdrs, &x):0; } int get_u_short ( unsigned short & x ) { return ready()?xdr_u_short(&xdrs, &x):0; } int get_long ( long & x ) { return ready()?xdr_long(&xdrs, &x):0; } int get_u_long ( unsigned long & x ) { return ready()?xdr_u_long(&xdrs, &x):0; } int get_float ( float & x ) { return ready()?xdr_float(&xdrs, &x):0; } int get_double ( double & x ) { return ready()?xdr_double(&xdrs, &x):0; } int get_bytes ( char ** bytes, unsigned int & num, unsigned int max ) { return ready()?xdr_bytes(&xdrs, bytes, &num, max):0; } int get_string_len ( void ) { return ready()?ntohl(*(long *)((char *)buf+xdr_getpos(&xdrs))):0; } int get_string ( char ** str, unsigned int max = -1U ) { int result = 0; int slen = get_string_len()+1; char * s = new char[slen]; if(ready()) { result = xdr_string(&xdrs, &s, slen); if(str!=NULL) { if(max==-1U || *str==NULL) { *str = s; s = NULL; } else { strncpy(*str, s, max); str[max-1] = 0; } } } if(s!=NULL) delete s; return result; } int get_opaque ( void ** data, unsigned int * len, unsigned int max = -1U) { int result = 0; if(ready()) { unsigned int slen; char * s; if((result=xdr_u_int(&xdrs, &slen))!=0) { s = new char[slen]; result=xdr_opaque(&xdrs, s, slen); } if(result!=0) { if(*data==NULL || max==-1U) { *len = slen; *data = s; s = NULL; } else { *len = (slen