home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / xdr.zip / XDR.CPP < prev    next >
C/C++ Source or Header  |  1993-08-04  |  20KB  |  843 lines

  1. /*************************************************************************
  2. *
  3. * File Name     : xdr.cpp
  4. *
  5. * Description: OS/2 XDR library
  6. *
  7. * Exports      : xdrstdio_create()       xdrmem_create()        xdr_destroy()
  8. *               xdr_free()            xdrmem_base()        xdr_getpos()
  9. *               xdr_setpos()            xdr_char()            xdr_short()
  10. *               xdr_u_short()        xdr_int()            xdr_u_int()
  11. *               xdr_long()            xdr_u_long()        xdr_void()
  12. *               xdr_enum()            xdr_string()        xdr_opaque()
  13. *               xdr_bytes()            xdr_vector()        xdr_array()
  14. *               xdr_union()
  15. *
  16. * Imports     : memcpy <mem.h>        malloc <stdlib.h>    free <stdlib.h>
  17. *               realloc <stdlib.h>    fseek <stdio.h>        fread <stdio.h>
  18. *               fwrite <stdio.h>     ftell <stdio.h>        strlen.h <string.h>
  19. *
  20. * copyright (c) Jörg Caumanns, 1993 [caumanns@cs.tu-berlin.de]
  21. *
  22. *      DISCLAIMER OF WARRANTIES.
  23. *      The code is provided "AS IS", without warranty of any kind.
  24. *
  25. *************************************************************************/
  26. #include <os2def.h>
  27. #include <stdio.h>
  28. #include <mem.h>
  29. #include <string.h>
  30. #include <stdlib.h>
  31. #include <xdr.h>
  32.  
  33. /*
  34. * constants
  35. */
  36. #define BYTES_PER_XDR_UNIT     4
  37. #define MEMSIZE_BASE        4096    // page size
  38.  
  39.  
  40. /***
  41. * XDRR structure:
  42. *
  43. * In order to provide some kind of object-oriented feeling, the XDR
  44. * structure defined in XDR.H is just a dummy for the 'real' XDR
  45. * structure XDRR defined here.
  46. * All constants and datatypes needed to implement XDRR are defined in this
  47. * module, not in XDR.H. You should only use the datatypes and functions
  48. * defined in XDR.H so that any changes in the XDRR structure are invisible
  49. * to your programs.
  50. ***/
  51. typedef enum XDR_STREAM    {
  52.             MEMORY,                 // memory stream
  53.             STDIO    };                // I/O stream
  54.  
  55. typedef struct XDR_STDIO    {
  56.     FILE *pf;                        // file pointer
  57.     };
  58.  
  59. typedef struct XDR_MEM        {
  60.     ULONG ulSize;                    // size of memory buffer
  61.     CHAR  *pb;                        // address of memory buffer
  62.     BOOL  fAlloc;                    // false -> buffer was preallocated
  63.     };
  64.  
  65. typedef struct XDRR    {
  66.     XDR_STREAM     stream;
  67.     XDR_OP        op;
  68.     UINT        offset;
  69.     union {
  70.         XDR_STDIO io;
  71.         XDR_MEM   mem;
  72.         } u;
  73.     };
  74.  
  75. /*
  76. * Makros
  77. */
  78. #define RNDUP(x)    ((((x)+3) >> 2) << 2)    // round to a multiple of 4
  79.  
  80. #define OP(xdr)        (((XDRR *)(xdr))->op)    // access certain elements of
  81. #define MEM(xdr)    ((((XDRR *)(xdr))->u).mem)    // struct XDRR
  82. #define IO(xdr)        ((((XDRR *)(xdr))->u).io)
  83.  
  84. /*
  85. * forward declarations
  86. */
  87. static BOOL xdr_read(XDR *, CHAR *, ULONG);
  88. static BOOL xdr_write(XDR *, CHAR *, ULONG);
  89. /*************************************************************************
  90. *
  91. * Names : XDR_Read, XDR_Write
  92. *
  93. * Descr.: Read/Write n Bytes from/to a given memory location/file
  94. *
  95. * Impl. : xdr_write reallocates a memory buffer allocated by
  96. *          'xdrmem_create' if it's not big enough.
  97. *          This is different from the 'normal' XDR semantics, but I think
  98. *          it's quite useful.
  99. *
  100. * Param.: XDR  *xdr        - xdr instance handle
  101. *          CHAR *pBuf    - buffer holding bytes read / to be written
  102. *          ULONG cBytes    - bytes to read/write
  103. *
  104. * Return: BOOL fSuccess
  105. *
  106. *************************************************************************/
  107. static BOOL xdr_read(XDR *xdr, CHAR *pBuf, ULONG cBytes)    {
  108.  
  109.     switch(((XDRR *)xdr)->stream)    {
  110.         case MEMORY:
  111.             if((((XDRR *)xdr)->offset + cBytes) > MEM(xdr).ulSize)
  112.                 return FALSE;
  113.  
  114.             memcpy(pBuf, MEM(xdr).pb + ((XDRR *)xdr)->offset, cBytes);
  115.             ((XDRR *)xdr)->offset += cBytes;
  116.             return TRUE;
  117.  
  118.         case STDIO:
  119.             ((XDRR *)xdr)->offset += cBytes;
  120.             return (BOOL)fread(pBuf, 1, cBytes, IO(xdr).pf);
  121.         }
  122.     return FALSE;
  123.     }
  124.  
  125. static BOOL xdr_write(XDR *xdr, CHAR *pBuf, ULONG cBytes)    {
  126.  
  127.   again:
  128.     switch(((XDRR *)xdr)->stream)    {
  129.         case MEMORY:
  130.             if((((XDRR *)xdr)->offset + cBytes) > MEM(xdr).ulSize)    {
  131.                 if(MEM(xdr).fAlloc)    {
  132.                     MEM(xdr).ulSize *= 2;
  133.                     MEM(xdr).pb = (CHAR *)realloc(MEM(xdr).pb, MEM(xdr).ulSize);
  134.                     goto again;
  135.                     }
  136.                 else
  137.                     return FALSE;
  138.                 }
  139.  
  140.             memcpy(MEM(xdr).pb + ((XDRR *)xdr)->offset, pBuf, cBytes);
  141.             ((XDRR *)xdr)->offset += cBytes;
  142.             return TRUE;
  143.  
  144.         case STDIO:
  145.             ((XDRR *)xdr)->offset += cBytes;
  146.             return (BOOL)fwrite(pBuf, 1, cBytes, IO(xdr).pf);
  147.         }
  148.     return FALSE;
  149.     }
  150.  
  151.  
  152. /*************************************************************************
  153. *
  154. * Name    : xdrstdio_create
  155. *
  156. * Descr.: associate a XDR stream with a file pointer
  157. *
  158. * Impl. : -
  159. *
  160. * Param.: XDR  *xdr        - xdr handle (return)
  161.           FILE *pf        - File pointer to associate XDR stream with
  162. *          XDR_OPT option- option (decode, encode, free)
  163. *
  164. * Return: void
  165. *
  166. *************************************************************************/
  167. void xdrstdio_create(XDR *xdr, FILE *pf, XDR_OP option)    {
  168.  
  169.     ((XDRR *)xdr)->stream    = STDIO;
  170.     ((XDRR *)xdr)->op        = option;
  171.     ((XDRR *)xdr)->offset    = ftell(pf);
  172.     IO(xdr).pf                = pf;
  173.     }
  174.  
  175.  
  176. /*************************************************************************
  177. *
  178. * Name    : xdrmem_create
  179. *
  180. * Descr.: associate a XDR stream with a memory buffer
  181. *
  182. * Impl. : If 'pAddr' or 'size' is 0, 'xdrmem_create' allocates a
  183. *          memory buffer of size MEMSIZE_BASE (4 KB).
  184. *          If this buffer is not large enough it is enlarged automatically
  185. *          by this library. If you use this feature call 'xdrmem_base' to
  186. *          get the buffer's address.
  187. *
  188. * Param.: XDR *xdr        - xdr handle (return)
  189. *          CHAR *pAddr    - pointer to begin of memory buffer
  190. *          ULONG size    - size of memory buffer
  191. *          XDR_OPT option- option (decode, encode, free)
  192. *
  193. * Return: void
  194. *
  195. *************************************************************************/
  196. void xdrmem_create(XDR *xdr, CHAR *pAddr, ULONG size, XDR_OP option)    {
  197.  
  198.     ((XDRR *)xdr)->stream    = MEMORY;
  199.     ((XDRR *)xdr)->op         = option;
  200.     ((XDRR *)xdr)->offset    = 0;
  201.     if((!pAddr) || (!size))    {
  202.         MEM(xdr).pb         = (CHAR *)malloc(MEMSIZE_BASE);
  203.         MEM(xdr).ulSize     = MEMSIZE_BASE;
  204.         MEM(xdr).fAlloc        = TRUE;
  205.         }
  206.     else    {
  207.         MEM(xdr).pb         = pAddr;
  208.         MEM(xdr).ulSize     = size;
  209.         MEM(xdr).fAlloc        = FALSE;
  210.         }
  211.     }
  212.  
  213.  
  214. /*************************************************************************
  215. *
  216. * Names    : xdrmem_base
  217. *
  218. * Descr.: Get the current base address
  219. *
  220. * Impl. : -
  221. *
  222. * Param.: XDR *xdr        - xdr handle
  223. *
  224. * Return: CHAR *base    - base address
  225. *
  226. *************************************************************************/
  227. CHAR *xdrmem_base(XDR *xdr)    {
  228.  
  229.     return MEM(xdr).pb;
  230.     }
  231.  
  232.  
  233. /*************************************************************************
  234. *
  235. * Names    : xdr_getpos, xdr_setpos
  236. *
  237. * Descr.: get/set the current read/write offset
  238. *
  239. * Impl. : If 'xdr' points to a standard I/O stream the file pointer
  240. *          is returned / moved.
  241. *
  242. * Param.: XDR *xdr        - xdr handle
  243. *          UINT pos        - new offset (xdr_setpos)
  244. *
  245. * Return: a) UINT offset
  246. *          b) BOOL fSuccess
  247. *
  248. *************************************************************************/
  249. UINT xdr_getpos(XDR *xdr)    {
  250.  
  251.     return ((XDRR *)xdr)->offset;
  252.     }
  253.  
  254. BOOL xdr_setpos(XDR *xdr, UINT pos)    {
  255.  
  256.     ((XDRR *)xdr)->offset = pos;
  257.  
  258.     if(((XDRR *)xdr)->stream == STDIO)
  259.         return (fseek(IO(xdr).pf, pos, 0) == 0)? TRUE : FALSE;
  260.  
  261.     return TRUE;
  262.     }
  263.  
  264.  
  265. /*************************************************************************
  266. *
  267. * Name    : xdr_destroy
  268. *
  269. * Descr.: free all resources allocated by this library
  270. *
  271. * Impl. : Release memory allocated bx 'xdrmem_create'.
  272. *
  273. * Param.: XDR *xdr        - xdr handle
  274. *
  275. * Return: -
  276. *
  277. *************************************************************************/
  278. VOID xdr_destroy(XDR *xdr)    {
  279.  
  280.     switch(((XDRR *)xdr)->stream)    {
  281.         case MEMORY:
  282.             if(MEM(xdr).fAlloc)
  283.                 free(MEM(xdr).pb);
  284.             break;
  285.         case STDIO:
  286.             break;
  287.         }
  288.     }
  289.  
  290.  
  291. /*************************************************************************
  292. *
  293. * Name    : (Short, UShort, Int, ....)
  294. *
  295. * Descr.: Read/Write an object of the given type from/to the XDR stream
  296. *
  297. * Impl. : -
  298. *
  299. * Param.: XDR      *xdr        - xdr handle
  300. *          type_t *pObject    - object to be read/written
  301. *
  302. * Return: BOOL fSuccess
  303. *
  304. *************************************************************************/
  305. /**
  306. *
  307. * xdr_char
  308. *
  309. **/
  310. BOOL xdr_char(XDR *xdr, CHAR *pch)    {
  311.     CHAR tmp[BYTES_PER_XDR_UNIT];
  312.  
  313.     memset(tmp, 0, BYTES_PER_XDR_UNIT);
  314.  
  315.     switch(OP(xdr))    {
  316.         case XDR_ENCODE:
  317.             tmp[BYTES_PER_XDR_UNIT-1] = *pch;
  318.             return xdr_write(xdr, tmp, BYTES_PER_XDR_UNIT);
  319.  
  320.         case XDR_DECODE:
  321.             if(!xdr_read(xdr, tmp, BYTES_PER_XDR_UNIT))
  322.                 return FALSE;
  323.             *pch = tmp[BYTES_PER_XDR_UNIT-1];
  324.             return TRUE;
  325.  
  326.         case XDR_FREE:
  327.             return TRUE;
  328.         }
  329.     return FALSE;
  330.     }
  331.  
  332.  
  333. /**
  334. *
  335. * xdr_short
  336. *
  337. **/
  338. BOOL xdr_short(XDR *xdr, SHORT *ps)    {
  339.     CHAR tmp[BYTES_PER_XDR_UNIT];
  340.  
  341.     switch(OP(xdr))    {
  342.         case XDR_ENCODE:
  343.             tmp[BYTES_PER_XDR_UNIT-1] = ((CHAR *)ps)[0];
  344.             tmp[BYTES_PER_XDR_UNIT-2] = ((CHAR *)ps)[1];
  345.             return xdr_write(xdr, tmp, BYTES_PER_XDR_UNIT);
  346.  
  347.         case XDR_DECODE:
  348.             if(!xdr_read(xdr, tmp, BYTES_PER_XDR_UNIT))
  349.                 return FALSE;
  350.             ((CHAR *)ps)[0] = tmp[BYTES_PER_XDR_UNIT-1];
  351.             ((CHAR *)ps)[1] = tmp[BYTES_PER_XDR_UNIT-2];
  352.             return TRUE;
  353.  
  354.         case XDR_FREE:
  355.             return TRUE;
  356.         }
  357.     return FALSE;
  358.     }
  359.  
  360. /**
  361. *
  362. * xdr_u_short
  363. *
  364. **/
  365. BOOL xdr_u_short(XDR *xdr, USHORT *ps)    {
  366.  
  367.     return xdr_short(xdr, (SHORT *)ps);
  368.     }
  369.  
  370.  
  371. /**
  372. *
  373. * xdr_int
  374. *
  375. **/
  376. BOOL xdr_int(XDR *xdr, INT *p)    {
  377.     CHAR tmp[BYTES_PER_XDR_UNIT];
  378.  
  379.     switch(OP(xdr))    {
  380.         case XDR_ENCODE:
  381.             tmp[BYTES_PER_XDR_UNIT-1] = ((CHAR *)p)[0];
  382.             tmp[BYTES_PER_XDR_UNIT-2] = ((CHAR *)p)[1];
  383.             tmp[BYTES_PER_XDR_UNIT-3] = ((CHAR *)p)[2];
  384.             tmp[BYTES_PER_XDR_UNIT-4] = ((CHAR *)p)[3];
  385.             return xdr_write(xdr, tmp, BYTES_PER_XDR_UNIT);
  386.  
  387.         case XDR_DECODE:
  388.             if(!xdr_read(xdr, tmp, BYTES_PER_XDR_UNIT))
  389.                 return FALSE;
  390.             ((CHAR *)p)[0] = tmp[BYTES_PER_XDR_UNIT-1];
  391.             ((CHAR *)p)[1] = tmp[BYTES_PER_XDR_UNIT-2];
  392.             ((CHAR *)p)[2] = tmp[BYTES_PER_XDR_UNIT-3];
  393.             ((CHAR *)p)[3] = tmp[BYTES_PER_XDR_UNIT-4];
  394.             return TRUE;
  395.  
  396.         case XDR_FREE:
  397.             return TRUE;
  398.         }
  399.     return FALSE;
  400.     }
  401.  
  402. /**
  403. *
  404. * xdr_u_int
  405. *
  406. **/
  407. BOOL xdr_u_int(XDR *xdr, UINT *p)    {
  408.  
  409.     return xdr_int(xdr, (INT *)p);
  410.     }
  411.  
  412. /**
  413. *
  414. * xdr_long
  415. *
  416. **/
  417. BOOL xdr_long(XDR *xdr, LONG *p)    {
  418.  
  419.     return xdr_int(xdr, (INT *)p);
  420.     }
  421.  
  422. /**
  423. *
  424. * xdr_u_long
  425. *
  426. **/
  427. BOOL xdr_u_long(XDR *xdr, ULONG *p)    {
  428.  
  429.     return xdr_int(xdr, (INT *)p);
  430.     }
  431.  
  432. /**
  433. *
  434. * xdr_void
  435. *
  436. **/
  437. BOOL xdr_void(XDR *xdr, VOID *p)    {
  438.  
  439.     return TRUE;
  440.     }
  441.  
  442. /**
  443. *
  444. * xdr_enum
  445. *
  446. **/
  447. BOOL xdr_enum(XDR *xdr, INT *p)    {
  448.  
  449.     return xdr_int(xdr, p);
  450.     }
  451.  
  452.  
  453.  
  454. /*************************************************************************
  455. *
  456. * Name    : xdr_string
  457. *
  458. * Descr.: Convert a 0-terminated string to XDR and vice versa
  459. *
  460. * Impl. : A string is represented as <UINT length><bytes[x]>, where x
  461. *          is a multiple of BYTES_PER_XDR_UNIT (4).
  462. *          If '*ppsz' is set to NULL at decoding, memory is allocated by
  463. *          this routine.
  464. ** Param.: CHAR **ppsz    - pointer to string
  465. *          UINT sizeMax    - maximum string length
  466. *
  467. * Return: BOOL fSuccess
  468. *
  469. *************************************************************************/
  470. BOOL xdr_string(XDR *xdr, CHAR **ppsz, UINT sizeMax)    {
  471.     UINT len, i, last;
  472.     CHAR tmp[BYTES_PER_XDR_UNIT];
  473.  
  474.     switch(OP(xdr))    {
  475.         case XDR_ENCODE:
  476.             if((!*ppsz) || ((len = strlen(*ppsz)) > sizeMax))
  477.                 return FALSE;
  478.  
  479.             xdr_u_int(xdr, &len);     // write length
  480.  
  481.             last = (len >> 2) << 2; // write full units
  482.             if(!xdr_write(xdr, *ppsz, last))
  483.                 return FALSE;
  484.  
  485.             if(last != len)    {        // fill last unit with zeros
  486.                 memset(tmp, 0, BYTES_PER_XDR_UNIT);
  487.                 for(i = last; i < len; i++)
  488.                     tmp[i-last] = (*ppsz)[i];
  489.  
  490.                 if(!xdr_write(xdr, tmp, BYTES_PER_XDR_UNIT))
  491.                     return FALSE;
  492.                 }
  493.  
  494.             return TRUE;
  495.  
  496.         case XDR_DECODE:
  497.  
  498.             xdr_u_int(xdr, &len);    // read string length
  499.  
  500.             if(len > sizeMax)
  501.                 return FALSE;
  502.  
  503.             if(!*ppsz)    {            // allocate memory (if requested)
  504.                 if(len == RNDUP(len))
  505.                     *ppsz = (CHAR *)malloc(len+1);
  506.                 else
  507.                     *ppsz = (CHAR *)malloc(RNDUP(len));
  508.                 }
  509.  
  510.             if(!xdr_read(xdr, *ppsz, RNDUP(len)))
  511.                 return FALSE;
  512.             (*ppsz)[len] = 0;
  513.  
  514.             return TRUE;
  515.  
  516.         case XDR_FREE:
  517.             if(*ppsz)
  518.                 free(*ppsz);
  519.             return TRUE;
  520.  
  521.         }
  522.     return FALSE;
  523.     }
  524.  
  525.  
  526. /*************************************************************************
  527. *
  528. * Name    : xdr_opaque
  529. *
  530. * Descr.: handle an uninterpreted array of bytes
  531. *
  532. * Impl. : the byte-array is represented as <bytes[x]>, where x is a
  533. *          is a multiple of BYTES_PER_XDR_UNIT (4).
  534. *
  535. * Param.: CHAR *pb        - byte array
  536. *          UINT size        - size of byte array
  537. *
  538. * Return: BOOL fSuccess
  539. *
  540. *************************************************************************/
  541. BOOL xdr_opaque(XDR *xdr, BYTE *pp, UINT size)    {
  542.     UINT i, last;
  543.     CHAR tmp[BYTES_PER_XDR_UNIT];
  544.  
  545.     switch(OP(xdr))    {
  546.         case XDR_ENCODE:
  547.             last = (size >> 2) << 2;
  548.             if(!xdr_write(xdr, (CHAR *)pp, last))    // write full units
  549.                 return FALSE;
  550.  
  551.             if(last != size)    {    // fill last unit with zeros
  552.                 memset(tmp, 0, BYTES_PER_XDR_UNIT);
  553.                 for(i = last; i < size; i++)
  554.                     tmp[i-last] = pp[i];
  555.  
  556.                 if(!xdr_write(xdr, tmp, BYTES_PER_XDR_UNIT))
  557.                     return FALSE;
  558.                 }
  559.  
  560.             return TRUE;
  561.  
  562.         case XDR_DECODE:
  563.             if(!xdr_read(xdr, (CHAR *)pp, size))
  564.                 return FALSE;
  565.             if(!xdr_read(xdr, tmp, RNDUP(size)-size))
  566.                 return FALSE;
  567.  
  568.             return TRUE;
  569.  
  570.         case XDR_FREE:
  571.             return TRUE;
  572.  
  573.         }
  574.     return FALSE;
  575.     }
  576.  
  577.  
  578. /*************************************************************************
  579. *
  580. * Name    : xdr_bytes
  581. *
  582. * Descr.: handle a vaiable length array of bytes
  583. *
  584. * Impl. : A byte array is represented as <UINT length><bytes[x]> where x
  585. *          is a multiple of BYTES_PER_XDR_UNIT (4).
  586. *          If '*ppb' is set to NULL at decoding, memory is allocated by
  587. *          this routine.
  588. ** Param.: CHAR **ppb    - pointer to string
  589. *          UINT *psize    - array size
  590. *          UINT sizeMax    - maximum string length
  591. *
  592. * Return: INT number of bytes read/written from/to the XDR stream
  593. *
  594. *************************************************************************/
  595. BOOL xdr_bytes(XDR *xdr, BYTE **ppb, UINT *psize, UINT sizeMax)    {
  596.     UINT len, i, last;
  597.     CHAR tmp[BYTES_PER_XDR_UNIT];
  598.  
  599.     switch(OP(xdr))    {
  600.         case XDR_ENCODE:
  601.             if((!*ppb) || (*psize > sizeMax))
  602.                 return FALSE;
  603.  
  604.             xdr_u_int(xdr, psize);            // write length
  605.  
  606.             last = (*psize >> 2) << 2;
  607.             if(!xdr_write(xdr, (CHAR *)*ppb, last))    // write full units
  608.                 return FALSE;
  609.  
  610.             if(last != *psize)    {    // fill last unit with zeros
  611.                 memset(tmp, 0, BYTES_PER_XDR_UNIT);
  612.                 for(i = last; i < *psize; i++)
  613.                     tmp[i-last] = (*ppb)[i];
  614.  
  615.                 if(!xdr_write(xdr, tmp, BYTES_PER_XDR_UNIT))
  616.                     return FALSE;
  617.                 }
  618.  
  619.             return TRUE;
  620.  
  621.         case XDR_DECODE:
  622.  
  623.             xdr_u_int(xdr, psize);    // read length
  624.  
  625.             if(*psize > sizeMax)
  626.                 return FALSE;
  627.  
  628.             if(!*ppb)    {            // allocate memory (if requested)
  629.                 *ppb = (BYTE *)malloc(RNDUP(*psize));
  630.                 }
  631.  
  632.             return xdr_read(xdr, (CHAR *)*ppb, RNDUP(*psize));
  633.  
  634.         case XDR_FREE:
  635.             if(*ppb)
  636.                 free(*ppb);
  637.             return TRUE;
  638.  
  639.         }
  640.     return FALSE;
  641.     }
  642.  
  643.  
  644. /*************************************************************************
  645. *
  646. * Name    : xdr_vector
  647. *
  648. * Descr.: handle a fixed-length array of objects
  649. *
  650. * Impl. : -
  651. *
  652. * Param.: XDR    *xdr    - XDR handle
  653. *          CHAR  *pa        - array pointer
  654. *          UINT    cObj    - number of objects in the array
  655. *          UINT    cbObj    - size of a single object
  656. *          xdrproc_t proc- procedure to handle an object
  657. *
  658. *************************************************************************/
  659. BOOL xdr_vector(XDR *xdr, CHAR *pa, UINT cObj, UINT cbObj, xdrproc_t proc) {
  660.  
  661.     for(INT i  = 0; i < cObj; i++, pa += cbObj)    {
  662.         if(!proc(xdr, (VOID *)pa))
  663.             return FALSE;
  664.         }
  665.  
  666.     return TRUE;
  667.     }
  668.  
  669. /*************************************************************************
  670. *
  671. * Name    : xdr_array
  672. *
  673. * Descr.: handle a variable-length array of objects
  674. *
  675. * Impl. : If '*ppa' is set to NULL at decoding, memory is allocated by
  676. *          this routine.
  677. *
  678. * Param.: XDR    *xdr    - XDR handle
  679. *          CHAR  **ppa    - array pointer
  680. *          UINT    *pcObj    - number of objects in the array
  681. *          UINT  maxObj    - maximum number of objects
  682. *          UINT    cbObj    - size of a single object
  683. *          xdrproc_t proc- procedure to handle an object
  684. *
  685. *************************************************************************/
  686. BOOL xdr_array(XDR *xdr, CHAR **ppa, UINT *pcObj, UINT maxObj,
  687.                                             UINT cbObj, xdrproc_t proc) {
  688.     INT i;
  689.  
  690.     switch(OP(xdr))    {
  691.         case XDR_ENCODE:
  692.             if(*pcObj > maxObj)
  693.                 return FALSE;
  694.  
  695.             if(!xdr_u_int(xdr, pcObj))    // write object counter
  696.                 return FALSE;
  697.             break;
  698.  
  699.         case XDR_DECODE:
  700.             if(!xdr_u_int(xdr, pcObj))    // read object counter
  701.                 return FALSE;
  702.  
  703.             if(*pcObj > maxObj)
  704.                 return FALSE;
  705.  
  706.             if(!*ppa)
  707.                 *ppa = (CHAR *)malloc(*pcObj * cbObj);
  708.             break;
  709.  
  710.         case XDR_FREE:
  711.             if(*ppa)
  712.                 free(*ppa);
  713.             return TRUE;
  714.         }
  715.                                         // encode/decode each object
  716.     for(i = 0; i < *pcObj; i++, (*ppa) += cbObj)
  717.         if(!proc(xdr, (VOID *)*ppa))
  718.             return FALSE;
  719.  
  720.     return TRUE;
  721.     }
  722.  
  723.  
  724. /*************************************************************************
  725. *
  726. * Name    : xdr_union
  727. *
  728. * Descr.: handle a discriminated union of objects
  729. *
  730. * Impl. : -
  731. *
  732. * Param.: XDR    *xdr    - XDR handle
  733. *          INT   *pDiscr - discriminator
  734. *          CHAR  *pUnion    - pointer to union
  735. *          xdr_discrim * - list of discriminators and their xdr-procs
  736. *          xdrproc_t def - procedure if no discriminator matches
  737. *
  738. *************************************************************************/
  739. BOOL xdr_union(XDR *xdr, INT *pDiscr, CHAR *pUnion, xdr_discrim *choices,
  740.                                                         xdrproc_t defaultarm) {
  741.     xdr_discrim *arm;
  742.  
  743.     xdr_int(xdr, pDiscr);            // write/read discriminator
  744.  
  745.     for(arm = choices; arm->discr && arm->discr != *pDiscr; arm++)
  746.         ;
  747.  
  748.     if(arm->discr)
  749.         return arm->proc(xdr, pUnion);
  750.  
  751.     return (defaultarm)? defaultarm(xdr, pUnion) : FALSE;
  752.     }
  753.  
  754.  
  755. /*************************************************************************
  756. *
  757. * Name    : xdr_reference
  758. *
  759. * Descr.: handle a reference to an objects
  760. *
  761. * Impl. : -
  762. *
  763. * Param.: XDR    *xdr    - XDR handle
  764. *          CHAR  **pp    - object pointer
  765. *          UINT    cbObj    - size of a single object
  766. *          xdrproc_t proc- procedure to handle an object
  767. *
  768. *************************************************************************/
  769. BOOL xdr_reference(XDR *xdr, CHAR **pp, UINT cbObj, xdrproc_t proc) {
  770.  
  771.     switch(OP(xdr))    {
  772.         case XDR_ENCODE:
  773.             if(!*pp)
  774.                 return FALSE;
  775.             break;
  776.  
  777.         case XDR_DECODE:
  778.             if(!*pp)
  779.                 *pp = (CHAR *)malloc(cbObj);
  780.             break;
  781.  
  782.         case XDR_FREE:
  783.             if(*pp)
  784.                 free(*pp);
  785.             return TRUE;
  786.         }
  787.  
  788.     return proc(xdr, (VOID *)*pp);
  789.     }
  790.  
  791.  
  792. /*************************************************************************
  793. *
  794. * Name    : xdr_pointer
  795. *
  796. * Descr.: handle linked lists of objects
  797. *
  798. * Impl. : -
  799. *
  800. * Param.: XDR    *xdr    - XDR handle
  801. *          CHAR  **pp    - pointer to next object
  802. *          UINT    cbObj    - size of a single object
  803. *          xdrproc_t proc- procedure to handle an object
  804. *
  805. *************************************************************************/
  806. BOOL xdr_pointer(XDR *xdr, CHAR **pp, UINT cbObj, xdrproc_t proc) {
  807.     INT fNext;
  808.  
  809.     fNext = (*pp)? TRUE : FALSE;    // needed only on XDR_ENCODE
  810.  
  811.     xdr_enum(xdr, &fNext);
  812.     if(fNext)
  813.         return xdr_reference(xdr, pp, cbObj, proc);
  814.  
  815.     return TRUE;
  816.     }
  817.  
  818.  
  819. /*************************************************************************
  820. *
  821. * Name    : xdr_free
  822. *
  823. * Descr.: free memory allocated by this library
  824. *
  825. * Impl. : -
  826. *
  827. * Param.: xdrproc_t     - procedure that allocated the memory buffer
  828. *          CHAR  *p        - pointer to memory object
  829. *
  830. *************************************************************************/
  831. VOID xdr_free(xdrproc_t proc, CHAR *p)    {
  832.  
  833.     if((proc == (xdrproc_t)xdr_array) ||
  834.                         (proc == (xdrproc_t)xdr_bytes)        ||
  835.                         (proc == (xdrproc_t)xdr_pointer)    ||
  836.                         (proc == (xdrproc_t)xdr_reference)    ||
  837.                         (proc == (xdrproc_t)xdr_string)        ||
  838.                         (proc == (xdrproc_t)xdr_vector))
  839.         if(p)
  840.             free(p);
  841.     }
  842.  
  843.