X-Git-Url: http://git.annexia.org/?p=portablexdr.git;a=blobdiff_plain;f=portablexdr-5%2Frpc%2Fxdr_internal.h;fp=portablexdr-5%2Frpc%2Fxdr_internal.h;h=1670168c8de1713fa0401f35e7d38a5f0bd50941;hp=0000000000000000000000000000000000000000;hb=68959447b0c5addf4fb975d26650351adc3a0293;hpb=b92428b2c1588d37e8c1eb42a4548fa3524c6b22 diff --git a/portablexdr-5/rpc/xdr_internal.h b/portablexdr-5/rpc/xdr_internal.h new file mode 100644 index 0000000..1670168 --- /dev/null +++ b/portablexdr-5/rpc/xdr_internal.h @@ -0,0 +1,201 @@ +/* PortableXDR - a free, portable XDR implementation. + * Copyright (C) 2009 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef PORTABLEXDR_XDR_INTERNAL_H +#define PORTABLEXDR_XDR_INTERNAL_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __GNUC__ +#ifndef __GNUC_PREREQ +#define __GNUC_PREREQ(maj,min) 0 +#endif +#ifndef ATTRIBUTE_UNUSED +#define ATTRIBUTE_UNUSED __attribute__((__unused__)) +#endif +#else +#define ATTRIBUTE_UNUSED +#endif /* __GNUC__ */ + +/* Here we get into what could be termed the "internals" of XDR. Most + * callers can get away with only ever using the basic XDR types and + * functions (see . Sometimes, particularly for + * compatibility with Sun XDR code, you need to delve into the + * internals. + */ + +enum xdr_op { + XDR_ENCODE, + XDR_DECODE, + XDR_FREE +}; + +/* Operations available on an XDR data stream (file, socket or memory + * area). Callers shouldn't normally use these, but Sun's XDR + * implementation exposes these operations, so we do too. + */ +struct xdr_ops { + /* Get/put "long" (ie. 32 bit quantity). */ + bool_t (*x_getlong) (XDR *, int32_t *); + bool_t (*x_putlong) (XDR *, int32_t *); + /* Get/put bytes. */ + bool_t (*x_getbytes) (XDR *, void *, size_t); + bool_t (*x_putbytes) (XDR *, void *, size_t); + /* Get or seek within the stream (offsets from beginning of stream). */ + off_t (*x_getpostn) (XDR *); + bool_t (*x_setpostn) (XDR *, off_t); + /* Returns a pointer to the next n bytes in the stream. */ + void * (*x_inline) (XDR *, size_t); + /* Free the stream. */ + void (*x_destroy) (XDR *); +}; + +struct xdr { + /* Calling code can read the operation field, but should not update it. */ + enum xdr_op x_op; /* operation (encode/decode/free) */ + + /* Calling code may use this pointer for any purpose, eg. + * to point to their own data. + */ + void *x_public; + + struct xdr_ops x_ops; + + /* The remaining fields are private and could change in any + * future release. Calling code should not use or modify them. + */ + void *x__private; +}; + +/* Define wrapper functions around the x_ops. */ +static inline bool_t +xdr_getlong (XDR *xdrs, int32_t *v) +{ + return xdrs->x_ops->x_getlong (xdrs, v); +} +static inline bool_t +xdr_putlong (XDR *xdrs, int32_t *v) +{ + return xdrs->x_ops->x_putlong (xdrs, v); +} +static inline bool_t +xdr_getbytes (XDR *xdrs, void *p, size_t len) +{ + return xdrs->x_ops->x_getbytes (xdrs, p, len); +} +static inline bool_t +xdr_putbytes (XDR *xdrs, void *p, size_t len) +{ + return xdrs->x_ops->x_putbytes (xdrs, p, len); +} +static inline off_t +xdr_getpos (XDR *xdrs) +{ + return xdrs->x_ops->x_getpostn (xdrs); +} +static inline bool_t +xdr_setpos (XDR *xdrs, off_t v) +{ + return xdrs->x_ops->x_setpostn (xdrs, v); +} +static inline void +xdr_inline (XDR *xdrs, size_t len) +{ + return xdrs->x_ops->x_inline (xdrs, len); +} +static inline void +xdr_destroy (XDR *xdrs) +{ + return xdrs->x_ops->x_destroy (xdrs); +} + +/* For compatibility with Sun XDR. */ +#define XDR_GETLONG xdr_getlong +#define XDR_PUTLONG xdr_putlong +#define XDR_GETBYTES xdr_getbytes +#define XDR_PUTBYTES xdr_putbytes +#define XDR_GETPOS xdr_getpos +#define XDR_SETPOS xdr_setpos +#define XDR_INLINE xdr_inline +#define XDR_DESTROY xdr_destroy + +/* Also seen in the wild ... */ +#define XDR_GETINT32 xdr_getlong +#define XDR_PUTINT32 xdr_putlong + +/* These are the "inline" versions of the macros. These are used + * in SunRPC for some primitive optimizations. For example, suppose + * you have to parse 4 integers from the stream. You could + * optimize using these macros by doing: + * + * if (xdr->x_op == XDR_DECODE) { + * void *buf = xdr_inline (xdr, 4 * BYTES_PER_XDR_UNIT); + * if (buf) { + * i0 = IXDR_GET_LONG (buf); // NB. Macro autoincrements buf. + * i1 = IXDR_GET_LONG (buf); + * i2 = IXDR_GET_LONG (buf); + * i3 = IXDR_GET_LONG (buf); + * return TRUE; + * } + * } + * else if (xdr->x_op == XDR_ENCODE) { + * // Similar code required for encoding. + * } + * // Fallback code + * if (!xdr_int (xdr, &i0)) return FALSE; + * if (!xdr_int (xdr, &i1)) return FALSE; + * if (!xdr_int (xdr, &i2)) return FALSE; + * if (!xdr_int (xdr, &i3)) return FALSE; + * return TRUE; + * + * Note that you have to fallback in the case when xdr_inline + * returns NULL. This is NOT an error case. + * + * Whether this optimization is really worth it or not is left as + * an exercise in benchmarking. In any case, PortableXDR's rpcgen + * does NOT perform this optimization. + */ + +#define BYTES_PER_XDR_UNIT 4 + +#define IXDR_GET_LONG(buf) ((int32_t) ntohl (*((int32_t *)(buf))++)) +#define IXDR_GET_BOOL(buf) ((bool_t) IXDR_GET_LONG ((buf))) +#define IXDR_GET_ENUM(buf,type) ((type) IXDR_GET_LONG ((buf))) +#define IXDR_GET_U_LONG(buf) ((uint32_t) IXDR_GET_LONG ((buf))) +#define IXDR_GET_SHORT(buf) ((int16_t) IXDR_GET_LONG ((buf))) +#define IXDR_GET_U_SHORT(buf) ((uint16_t) IXDR_GET_LONG ((buf))) +#define IXDR_GET_INT32 IXDR_GET_LONG + +#define IXDR_PUT_LONG(buf,v) ((*((int32_t *)(buf))++) = htonl ((v))) +#define IXDR_PUT_BOOL(buf,v) IXDR_PUT_LONG((buf), (int32_t) (v)) +#define IXDR_PUT_ENUM(buf,v) IXDR_PUT_LONG((buf), (int32_t) (v)) +#define IXDR_PUT_U_LONG(buf,v) IXDR_PUT_LONG((buf), (int32_t) (v)) +#define IXDR_PUT_SHORT(buf,v) IXDR_PUT_LONG((buf), (int32_t) (v)) +#define IXDR_PUT_U_SHORT(buf,v) IXDR_PUT_LONG((buf), (int32_t) (v)) +#define IXDR_PUT_INT32 IXDR_PUT_LONG + +#ifdef __cplusplus +} +#endif + +#endif /* PORTABLEXDR_XDR_INTERNAL_H */