/*
 *   DIS/x : An implementation of the IEEE 1278.1 protocol
 *
 *   Copyright (C) 1996, Riley Rainey (rainey@netcom.com)
 *
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of either:
 *
 *   a) the GNU Library General Public License as published by the Free
 *   Software Foundation; either version 2 of the License, or (at your
 *   option) any later version.  A description of the terms and conditions
 *   of the GLPL may be found in the "COPYING.LIB" file.
 *
 *   b) the "Artistic License" which comes with this Kit.  Information
 *   about this license may be found in the "Artistic" file.
 *
 *   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
 *   Library General Public License or the Artistic License for more details.
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this library; if not, write to the Free
 *   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *   Information describing how to contact the author can be found in the
 *   README file.
 */
/*
 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
 * unrestricted use provided that this legend is included on all tape
 * media and as a part of the software program in whole or part.  Users
 * may copy or modify Sun RPC without charge, but are not authorized
 * to license or distribute it to anyone else except as part of a product or
 * program developed by the user.
 * 
 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 * 
 * Sun RPC is provided with no support and without any obligation on the
 * part of Sun Microsystems, Inc. to assist in its use, correction,
 * modification or enhancement.
 * 
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
 * OR ANY PART THEREOF.
 * 
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
 * or profits or other special, indirect and consequential damages, even if
 * Sun has been advised of the possibility of such damages.
 * 
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California  94043
 */

/**
 * XDR implementation using memory buffers.
 *
 * If you have some data to be interpreted as external data representation
 * or to be converted to external data representation in a memory buffer,
 * then this is the package for you.
 * 
 * This implementation is tailored for the needs of the DIS protocol and the ACM
 * program, so deviates from the requirements of the standard by adding some
 * low-level byte-oriented routines.
 * 
 * In this implementation, the normal usage cycle is as follows:
 * 
 * 1. Create an encoding/decoding object by calling xdr_new().
 * 
 * 2. Encode/decode any number of fields by calling the appropriate functions.
 *    Each encoding/decoding function returns true if the operation succeeded,
 *    false if it fails. If a decoding operation fails, any dynamically
 *    allocated data created by xdr_var_array() and xdr_getBytesAllocate() is
 *    released before returning the failure status flag; any user's data decoded
 *    so far is then destroyed.
 * 
 * 3. Release the decoding object by calling xdr_free() or memory_dispose().
 *    Encoding/decoding objects cannot be re-used (but are recycled by
 *    xdr_free()).
 * 
 * Dynamically allocated data are allocated with the "memory" module and can
 * then be released with memory_dispose().
 * 
 * Specifications of the XDR encoding: RFC 1014.
 * 
 * @copyright Copyright (C) 1984, Sun Microsystems, Inc.
 * @version $Date: 2018/04/02 05:41:30 $
 */

#ifndef XDR_H
#define	XDR_H

#include <stdint.h>

#ifdef xdr_IMPORT
	#define EXTERN
#else
	#define EXTERN extern
#endif

/**
 * Xdr operations.  xdr_ENCODE causes the type to be encoded into the
 * stream.  xdr_DECODE causes the type to be extracted from the stream.
 * xdr_FREE can be used to release the space allocated by an xdr_DECODE
 * request.
 * 
 * FIXME: xdr_FREE not supported -- not used by ACM.
 */
typedef enum {
	xdr_ENCODE=0,
	xdr_DECODE=1,
	xdr_FREE=2
} xdr_Operation;


/**
 * The XDR handle.
 */
typedef struct xdr_Type xdr_Type;

/**
 * Client's call-back prototype to encode/decode elements of arrays.
 */
typedef int (*xdr_Callback)(xdr_Type *xdr, ...);

/**
 * Creates and initializes an encoding/decoding stream descriptor for a memory
 * buffer. Returns a recycled descriptor previously released with xdr_free() if
 * available, otherwise allocates a new one with memory_allocate().
 * @param buffer Destination (for encoding) or source (for decoding) buffer.
 * @param size Size of the buffer.
 * @param op   Requested operation: encoding, decoding, free.
 * @return New stream descriptor, possibly recycled from a previously released
 * stream descriptor. Can be released either with memory_dispose() or with
 * xdr_free() for recycling.
 */
EXTERN xdr_Type * xdr_new(char * buffer, unsigned int size, xdr_Operation op);

/**
 * Releases a stream descriptor making it available for recycling. This function
 * is usually more efficient than memory_dispose().
 * @param xdr
 */
EXTERN void xdr_free(xdr_Type *xdr);

/**
 * Set error state and removes any dynamically data allocated so far.
 * @param xdr
 * @param description
 * @return Always returns 0.
 */
EXTERN int xdr_setError(xdr_Type *xdr, char *description);

/**
 * Returns the description of the latest failed encoding/decoding operation.
 * @param xdr
 * @return Description of the latest failed encoding/decoding operation.
 */
EXTERN char * xdr_getErrorDescription(xdr_Type *xdr);

/**
 * Returns the currently performed operation as set in the creator function.
 * @param xdr
 * @return Currently performed operation.
 */
EXTERN xdr_Operation xdr_getOperation(xdr_Type * xdr);

/**
 * Returns current byte offset in the working buffer.
 * @param xdr
 * @return Current byte offset in the working buffer.
 */
EXTERN unsigned int xdr_getpos(xdr_Type *xdr);

/**
 * Set byte offset in the working buffer.
 * @param xdr
 * @param pos Offset to set.
 * @return True on success. False if the offset is beyond the end of the working
 * buffer.
 */
EXTERN int xdr_setpos(xdr_Type *xdr, unsigned int pos);

/**
 * Encodes/decodes a 32 bits signed integer.
 * @param xdr
 * @param i
 * @return
 */
EXTERN int xdr_int32(xdr_Type *xdr, int32_t *i);

/**
 * Encodes/decodes a 32 bits unsigned integer.
 * @param xdr
 * @param ui
 * @return 
 */
EXTERN int xdr_uint32(xdr_Type *xdr, uint32_t *ui);

/**
 * Low-level, byte-oriented decoding function. It is responsibility of the client
 * to comply with the XDR encoding constraints to 4 bytes boundary, possibly by
 * reading some more padding bytes.
 * @param xdr
 * @param addr Destination buffer.
 * @param len Number of bytes to read.
 * @return True on success. False on premature end of the buffer space.
 */
EXTERN int xdr_getBytes(xdr_Type * xdr, void *addr, unsigned int len);

/**
 * Low-level, byte-oriented decoding function that also allocates the required
 * memory space. It is responsibility of the client to comply with the XDR
 * encoding constraints to 4 bytes boundary, possibly by reading some more
 * padding bytes.
 * @param xdr
 * @param addr On success, here returns the pointer to the dynamically allocated
 * buffer of decoded bytes; it can be released with memory_dispose().
 * @param len Number of bytes to read.
 * @param add_nul If true, a trailing NUL byte is added, which may be safer and
 * handy with strings of characters.
 * @return True on success. False on premature end of the buffer space.
 */
EXTERN int xdr_getBytesAllocated(xdr_Type * xdr, void **addr, unsigned int len, int add_nul);

/**
 * Low-level, byte-oriented encoding function. It is responsibility of the client
 * to comply with the XDR decoding constraints to 4 bytes boundary, possibly by
 * writing some more padding bytes.
 * @param xdr
 * @param addr Source buffer.
 * @param len Number of bytes to write.
 * @return True on success. False on premature end of the buffer space.
 */
EXTERN int xdr_putBytes(xdr_Type * xdr, void *addr, unsigned int len);

/**
 * Encodes/decodes a single byte. Note that it takes 4 bytes of the working
 * buffer.
 */
EXTERN int xdr_char(xdr_Type *xdr, char *c);

/**
 * Encodes/decodes a single precision floating point number.
 * @param xdr
 * @param f
 * @return 
 */
EXTERN int xdr_float(xdr_Type *xdr, float *f);

/**
 * Encodes/decodes a double precision floating point number.
 * @param xdr
 * @param d
 * @return 
 */
EXTERN int xdr_double(xdr_Type *xdr, double *d);

/**
 * Encodes/decodes array of elements. Note that on decoding, the array must be
 * already allocated.
 * @param xdr
 * @param arrp Pointer to the array.
 * @param size Number of elements in the array.
 * @param elsize Size in bytes of each element.
 * @param elproc Element encoding/decoding procedure.
 * @return 
 */
EXTERN int xdr_vector(xdr_Type *xdr, char *arrp, unsigned int size,
	unsigned int elsize, xdr_Callback elproc);

/**
 * Encodes/decodes an array of elements allocating the array while decoding.
 * @param xdr
 * @param addrp Pointer to array pointer. While decoding, (size * elsize)
 * bytes are allocated overwriting *addrp with the new allocated array;
 * if the size is zero, nothing is allocated and *addrp is set to NULL.
 * @param size Number of elements in the array.
 * @param elsize Size in bytes of each element.
 * @param elproc Element encoding/decoding procedure.
 * @return True if the array has been successfully encoded/decoded. False if
 * the total size of the array overflows the unsigned int capacity. False if
 * any element fails to be encoded/decoded. False if the number of elements
 * exceeds the number of bytes left in the buffer.
 */
EXTERN int
xdr_var_array(xdr_Type * xdr, void * * addrp, unsigned int size,
		unsigned int elsize, xdr_Callback elproc);

#undef EXTERN
#endif	/* XDR_H */
