451 lines
12 KiB
C++
451 lines
12 KiB
C++
#ifndef _XDR_CLASS_H_
|
|
#define _XDR_CLASS_H_
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#if defined (ultrix) || defined (sgi) || defined (solaris)
|
|
#include <rpc/types.h>
|
|
#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 <types.h>
|
|
#include <rpc/types.h>
|
|
#include <sys/uio.h>
|
|
#include <sys/socket.h>
|
|
#endif
|
|
#include <rpc/xdr.h>
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
#include "xdr.h"
|
|
#else
|
|
#include <rpc/rpc.h>
|
|
#include <netinet/in.h>
|
|
#endif
|
|
#include <cdevTypes.h>
|
|
|
|
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 <class T> 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<max)?slen:max;
|
|
memcpy(*data, s, *len);
|
|
}
|
|
}
|
|
if(s!=NULL) delete s;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int get_timestamp ( cdev_TS_STAMP & ts )
|
|
{ return ready()?xdr_timestamp(&xdrs, &ts):0; }
|
|
|
|
int get ( char & x ) { return get_char(x); }
|
|
int get ( unsigned char & x ) { return get_u_char(x); }
|
|
int get ( int & x ) { return get_int(x); }
|
|
int get ( unsigned int & x ) { return get_u_int(x); }
|
|
int get ( short & x ) { return get_short(x); }
|
|
int get ( unsigned short & x ) { return get_u_short(x); }
|
|
int get ( long & x ) { return get_long(x); }
|
|
int get ( unsigned long & x ) { return get_u_long(x); }
|
|
int get ( float & x ) { return get_float(x); }
|
|
int get ( double & x ) { return get_double(x); }
|
|
int get ( char ** s, unsigned max = -1U) { return get_string(s, max); }
|
|
int get ( void ** x, unsigned *len, unsigned max = -1U) { return get_opaque(x, len, max); }
|
|
int get ( cdev_TS_STAMP & ts ) { return get_timestamp(ts); }
|
|
};
|
|
|
|
|
|
#endif // _XDR_CLASS_H_
|