1670168c8de1713fa0401f35e7d38a5f0bd50941
[portablexdr.git] / portablexdr-5 / rpc / xdr_internal.h
1 /* PortableXDR - a free, portable XDR implementation.
2  * Copyright (C) 2009 Red Hat Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
17  */
18
19 #ifndef PORTABLEXDR_XDR_INTERNAL_H
20 #define PORTABLEXDR_XDR_INTERNAL_H
21
22 #include <rpc/types.h>
23 #include <stdarg.h>
24
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28
29 #ifdef __GNUC__
30 #ifndef __GNUC_PREREQ
31 #define __GNUC_PREREQ(maj,min) 0
32 #endif
33 #ifndef ATTRIBUTE_UNUSED
34 #define ATTRIBUTE_UNUSED __attribute__((__unused__))
35 #endif
36 #else
37 #define ATTRIBUTE_UNUSED
38 #endif                          /* __GNUC__ */
39
40 /* Here we get into what could be termed the "internals" of XDR.  Most
41  * callers can get away with only ever using the basic XDR types and
42  * functions (see <rpc/xdr.h>.  Sometimes, particularly for
43  * compatibility with Sun XDR code, you need to delve into the
44  * internals.
45  */
46
47 enum xdr_op {
48   XDR_ENCODE,
49   XDR_DECODE,
50   XDR_FREE
51 };
52
53 /* Operations available on an XDR data stream (file, socket or memory
54  * area).  Callers shouldn't normally use these, but Sun's XDR
55  * implementation exposes these operations, so we do too.
56  */
57 struct xdr_ops {
58   /* Get/put "long" (ie. 32 bit quantity). */
59   bool_t    (*x_getlong)  (XDR *, int32_t *);
60   bool_t    (*x_putlong)  (XDR *, int32_t *);
61   /* Get/put bytes. */
62   bool_t    (*x_getbytes) (XDR *, void *, size_t);
63   bool_t    (*x_putbytes) (XDR *, void *, size_t);
64   /* Get or seek within the stream (offsets from beginning of stream). */
65   off_t     (*x_getpostn) (XDR *);
66   bool_t    (*x_setpostn) (XDR *, off_t);
67   /* Returns a pointer to the next n bytes in the stream. */
68   void *    (*x_inline)   (XDR *, size_t);
69   /* Free the stream. */
70   void      (*x_destroy)  (XDR *);
71 };
72
73 struct xdr {
74   /* Calling code can read the operation field, but should not update it. */
75   enum xdr_op x_op;             /* operation (encode/decode/free) */
76
77   /* Calling code may use this pointer for any purpose, eg.
78    * to point to their own data.
79    */
80   void *x_public;
81
82   struct xdr_ops x_ops;
83
84   /* The remaining fields are private and could change in any
85    * future release.  Calling code should not use or modify them.
86    */
87   void *x__private;
88 };
89
90 /* Define wrapper functions around the x_ops. */
91 static inline bool_t
92 xdr_getlong (XDR *xdrs, int32_t *v)
93 {
94   return xdrs->x_ops->x_getlong (xdrs, v);
95 }
96 static inline bool_t
97 xdr_putlong (XDR *xdrs, int32_t *v)
98 {
99   return xdrs->x_ops->x_putlong (xdrs, v);
100 }
101 static inline bool_t
102 xdr_getbytes (XDR *xdrs, void *p, size_t len)
103 {
104   return xdrs->x_ops->x_getbytes (xdrs, p, len);
105 }
106 static inline bool_t
107 xdr_putbytes (XDR *xdrs, void *p, size_t len)
108 {
109   return xdrs->x_ops->x_putbytes (xdrs, p, len);
110 }
111 static inline off_t
112 xdr_getpos (XDR *xdrs)
113 {
114   return xdrs->x_ops->x_getpostn (xdrs);
115 }
116 static inline bool_t
117 xdr_setpos (XDR *xdrs, off_t v)
118 {
119   return xdrs->x_ops->x_setpostn (xdrs, v);
120 }
121 static inline void 
122 xdr_inline (XDR *xdrs, size_t len)
123 {
124   return xdrs->x_ops->x_inline (xdrs, len);
125 }
126 static inline void
127 xdr_destroy (XDR *xdrs)
128 {
129   return xdrs->x_ops->x_destroy (xdrs);
130 }
131
132 /* For compatibility with Sun XDR. */
133 #define XDR_GETLONG  xdr_getlong
134 #define XDR_PUTLONG  xdr_putlong
135 #define XDR_GETBYTES xdr_getbytes
136 #define XDR_PUTBYTES xdr_putbytes
137 #define XDR_GETPOS   xdr_getpos
138 #define XDR_SETPOS   xdr_setpos
139 #define XDR_INLINE   xdr_inline
140 #define XDR_DESTROY  xdr_destroy
141
142 /* Also seen in the wild ... */
143 #define XDR_GETINT32 xdr_getlong
144 #define XDR_PUTINT32 xdr_putlong
145
146 /* These are the "inline" versions of the macros.  These are used
147  * in SunRPC for some primitive optimizations.  For example, suppose
148  * you have to parse 4 integers from the stream.  You could
149  * optimize using these macros by doing:
150  *
151  *   if (xdr->x_op == XDR_DECODE) {
152  *     void *buf = xdr_inline (xdr, 4 * BYTES_PER_XDR_UNIT);
153  *     if (buf) {
154  *       i0 = IXDR_GET_LONG (buf); // NB. Macro autoincrements buf.
155  *       i1 = IXDR_GET_LONG (buf);
156  *       i2 = IXDR_GET_LONG (buf);
157  *       i3 = IXDR_GET_LONG (buf);
158  *       return TRUE;
159  *     }
160  *   }
161  *   else if (xdr->x_op == XDR_ENCODE) {
162  *     // Similar code required for encoding.
163  *   }
164  *   // Fallback code
165  *   if (!xdr_int (xdr, &i0)) return FALSE;
166  *   if (!xdr_int (xdr, &i1)) return FALSE;
167  *   if (!xdr_int (xdr, &i2)) return FALSE;
168  *   if (!xdr_int (xdr, &i3)) return FALSE;
169  *   return TRUE;
170  *
171  * Note that you have to fallback in the case when xdr_inline
172  * returns NULL.  This is NOT an error case.
173  *
174  * Whether this optimization is really worth it or not is left as
175  * an exercise in benchmarking.  In any case, PortableXDR's rpcgen
176  * does NOT perform this optimization.
177  */
178
179 #define BYTES_PER_XDR_UNIT 4
180
181 #define IXDR_GET_LONG(buf) ((int32_t) ntohl (*((int32_t *)(buf))++))
182 #define IXDR_GET_BOOL(buf) ((bool_t) IXDR_GET_LONG ((buf)))
183 #define IXDR_GET_ENUM(buf,type) ((type) IXDR_GET_LONG ((buf)))
184 #define IXDR_GET_U_LONG(buf) ((uint32_t) IXDR_GET_LONG ((buf)))
185 #define IXDR_GET_SHORT(buf) ((int16_t) IXDR_GET_LONG ((buf)))
186 #define IXDR_GET_U_SHORT(buf) ((uint16_t) IXDR_GET_LONG ((buf)))
187 #define IXDR_GET_INT32 IXDR_GET_LONG
188
189 #define IXDR_PUT_LONG(buf,v) ((*((int32_t *)(buf))++) = htonl ((v)))
190 #define IXDR_PUT_BOOL(buf,v) IXDR_PUT_LONG((buf), (int32_t) (v))
191 #define IXDR_PUT_ENUM(buf,v) IXDR_PUT_LONG((buf), (int32_t) (v))
192 #define IXDR_PUT_U_LONG(buf,v) IXDR_PUT_LONG((buf), (int32_t) (v))
193 #define IXDR_PUT_SHORT(buf,v) IXDR_PUT_LONG((buf), (int32_t) (v))
194 #define IXDR_PUT_U_SHORT(buf,v) IXDR_PUT_LONG((buf), (int32_t) (v))
195 #define IXDR_PUT_INT32 IXDR_PUT_LONG
196
197 #ifdef __cplusplus
198 }
199 #endif
200
201 #endif /* PORTABLEXDR_XDR_INTERNAL_H */