123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463 |
- /* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
- See the COPYRIGHT file for more information. */
- /*
- * Copyright (c) 2009, Sun Microsystems, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * - Neither the name of Sun Microsystems, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * from: @(#)xdr.h 1.19 87/04/22 SMI
- * from: @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC
- * $FreeBSD: src/include/rpc/xdr.h,v 1.23 2003/03/07 13:19:40 nectar Exp $
- * $NetBSD: xdr.h,v 1.19 2000/07/17 05:00:45 matt Exp $
- */
- /* Define our own implementation of the needed
- elements of XDR. Assumes read-only
- */
- #undef XXDRTRACE
- #include "config.h"
- #include <stdlib.h>
- #include <stdio.h>
- #include <assert.h>
- #include <string.h>
- #include <stdarg.h>
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #include "xxdr.h"
- int xxdr_network_order; /* network order is big endian */
- static int xxdr_big_endian; /* what is this machine? */
- #ifdef XXDRTRACE
- static void
- xxdrtrace(XXDR* xdr, char* where, off_t arg)
- {
- fprintf(stderr,"xxdr: %s: arg=%ld ; pos=%ld len=%ld\n",
- where,arg,(long)xdr->pos,(long)xdr->length);
- fflush(stderr);
- }
- #else
- #define xxdrtrace(x,y,z)
- #endif
- /* Read-only operations */
- int xxdr_getbytes(XXDR* xdrs, char* memory, off_t count)
- {
- if(!memory) return 0;
- if(!xdrs->getbytes(xdrs,memory,count))
- return 0;
- return 1;
- }
- /* get a unsigned int from underlying stream*/
- int
- xxdr_uint(XXDR* xdr, unsigned int* ip)
- {
- if(!ip) return 0;
- if(!xdr->getbytes(xdr,(char*)ip,sizeof(*ip)))
- return 0;
- /*convert from network order*/
- if(!xxdr_network_order) {
- swapinline32(ip);
- }
- return 1;
- }
- /* get a long long from underlying stream*/
- int
- xxdr_ulonglong(XXDR* xdr, unsigned long* llp)
- {
- /* Pull two units */
- if(!llp) return 0;
- if(!xdr->getbytes(xdr,(char*)llp,sizeof(*llp)))
- return 0;
- /* Convert to signed/unsigned */
- /*convert from network order*/
- if(!xxdr_network_order) {
- swapinline64(llp);
- }
- return 1;
- }
- /* get some bytes from underlying stream;
- will move xdrs pointer to next XDRUNIT boundary*/
- int
- xxdr_opaque(XXDR* xdr, char* mem, off_t count)
- {
- off_t pos,rounded;
- if(!xdr->getbytes(xdr,mem,count))
- return 0;
- pos = xxdr_getpos(xdr);
- rounded = RNDUP(pos);
- return xxdr_skip(xdr,(rounded - pos));
- }
- /* get counted string from underlying stream*/
- int
- xxdr_string(XXDR* xdrs, char** sp, off_t* lenp)
- {
- char* s;
- unsigned int len;
- if(!xxdr_uint(xdrs,&len)) return 0;
- s = (char*)malloc((off_t)len+1);
- if(s == NULL) return 0;
- if(!xxdr_opaque(xdrs,s,len)) {
- free((void*)s);
- return 0;
- }
- s[len] = '\0'; /* make sure it is null terminated */
- if(sp) *sp = s;
- if(lenp) *lenp = len;
- /* xxdr_opaque will have skippped any trailing bytes */
- return 1;
- }
- /* returns bytes off from beginning*/
- off_t
- xxdr_getpos(XXDR* xdr)
- {
- return xdr->getpos(xdr);
- }
- /* reposition the stream*/
- int
- xxdr_setpos(XXDR* xdr, off_t pos)
- {
- return xdr->setpos(xdr,pos);
- }
- /* returns total available starting at current position */
- off_t
- xxdr_getavail(XXDR* xdr)
- {
- return xdr->getavail(xdr);
- }
- /* free up XXDR structure */
- void
- xxdr_free(XXDR* xdr)
- {
- xdr->free(xdr);
- }
- /***********************************/
- /* Skip exacly "len" bytes in the input; any rounding must be done by the caller*/
- int
- xxdr_skip(XXDR* xdrs, off_t len)
- {
- unsigned int pos;
- pos = xxdr_getpos(xdrs);
- pos = (pos + len);
- if(pos < 0) pos = 0;
- return xxdr_setpos(xdrs,pos);
- }
- /* skip "n" string/bytestring instances in the input*/
- int
- xxdr_skip_strings(XXDR* xdrs, off_t n)
- {
- while(n-- > 0) {
- unsigned int slen;
- if(!xxdr_uint(xdrs,&slen)) return 0;
- slen = RNDUP(slen);
- if(xxdr_skip(xdrs,slen)) return 0;
- }
- return 1;
- }
- unsigned int
- xdr_roundup(unsigned int n)
- {
- unsigned int rounded;
- rounded = RNDUP(n);
- return rounded;
- }
- unsigned int
- ocbyteswap(unsigned int i)
- {
- unsigned int swap,b0,b1,b2,b3;
- b0 = (i>>24) & 0x000000ff;
- b1 = (i>>16) & 0x000000ff;
- b2 = (i>>8) & 0x000000ff;
- b3 = (i) & 0x000000ff;
- swap = (b0 | (b1 << 8) | (b2 << 16) | (b3 << 24));
- return swap;
- }
- /**************************************************/
- /* File based xdr */
- static void
- xxdr_filefree(XXDR* xdrs)
- {
- if(xdrs != NULL) {
- (void)fflush((FILE *)xdrs->data);
- free(xdrs);
- }
- }
- static int
- xxdr_filegetbytes(XXDR* xdrs, char* addr, off_t len)
- {
- int ok = 1;
- int count;
- xxdrtrace(xdrs,"getbytes",len);
- if(len < 0) len = 0;
- if(!xdrs->valid)
- {
- if(fseek((FILE *)xdrs->data, xdrs->pos + xdrs->base, 0) != 0) {
- ok=0;
- goto done;
- }
- xdrs->valid = 1;
- }
- if(xdrs->pos + len > xdrs->length)
- return 0;
- if(len > 0) {
- count = fread(addr, len, 1, (FILE*)xdrs->data);
- if(count <= 0) {
- ok=0;
- goto done;
- }
- }
- xdrs->pos += len;
- done:
- return ok;
- }
- static off_t
- xxdr_filegetpos(XXDR* xdrs)
- {
- xxdrtrace(xdrs,"getpos",0);
- return xdrs->pos;
- }
- static off_t
- xxdr_filegetavail(XXDR* xdrs)
- {
- xxdrtrace(xdrs,"getavail",0);
- return (xdrs->length - xdrs->pos);
- }
- static int
- xxdr_filesetpos(XXDR* xdrs, off_t pos)
- {
- int ok = 1;
- xxdrtrace(xdrs,"setpos",pos);
- if(pos == xdrs->pos) goto done;
- if(pos < 0) pos = 0;
- if(pos > xdrs->length) {ok=0;goto done;}
- xdrs->pos = pos;
- xdrs->valid = 0;
- done:
- return ok;
- }
- /*
- Modified to track the current position to avoid the file io
- operation. Not sure if this worth the effort because I
- don't actually know the cost to doing an fseek
- */
- /*
- * Initialize a stdio xdr stream.
- * Sets the xdr stream handle xdrs for use on the stream file.
- * Operation flag is set to op.
- */
- XXDR*
- xxdr_filecreate(FILE* file, off_t base)
- {
- XXDR* xdrs = (XXDR*)calloc(1,sizeof(XXDR));
- if(xdrs != NULL) {
- xdrs->data = (void*)file;
- xdrs->base = base;
- xdrs->pos = 0;
- xdrs->valid = 0;
- if(fseek(file,0L,SEEK_END)) return NULL;
- xdrs->length = (off_t)ftell(file);
- xdrs->length -= xdrs->base;
- xdrs->getbytes = xxdr_filegetbytes;
- xdrs->setpos = xxdr_filesetpos;
- xdrs->getpos = xxdr_filegetpos;
- xdrs->getavail = xxdr_filegetavail;
- xdrs->free = xxdr_filefree;
- }
- xxdrtrace(xdrs,"create",base);
- return xdrs;
- }
- /**************************************************/
- /* memory based xdr */
- static void
- xxdr_memfree(XXDR* xdrs)
- {
- if(xdrs != NULL) {
- free(xdrs);
- }
- }
- static int
- xxdr_memgetbytes(XXDR* xdrs, char* addr, off_t len)
- {
- int ok = 1;
- xxdrtrace(xdrs,"getbytes",len);
- if(len < 0) len = 0;
- if(xdrs->pos+len > xdrs->length) {ok=0; goto done;}
- if(len > 0) {
- memcpy(addr,(char*)xdrs->data+xdrs->base+xdrs->pos, len);
- }
- xdrs->pos += len;
- done:
- return ok;
- }
- static off_t
- xxdr_memgetpos(XXDR* xdrs)
- {
- xxdrtrace(xdrs,"getpos",0);
- return xdrs->pos;
- }
- static off_t
- xxdr_memgetavail(XXDR* xdrs)
- {
- xxdrtrace(xdrs,"getavail",0);
- return (xdrs->length - xdrs->pos);
- }
- static int
- xxdr_memsetpos(XXDR* xdrs, off_t pos)
- {
- int ok = 1;
- xxdrtrace(xdrs,"setpos",pos);
- if(pos == xdrs->pos) goto done;
- if(pos > xdrs->length) {ok=0; goto done;}
- xdrs->pos = pos;
- done:
- return ok;
- }
- /*
- Modified to track the current position to avoid the file io
- operation. Not sure if this worth the effort because I
- don't actually know the cost to doing an fseek
- */
- /*
- * Initialize a stdio xdr stream.
- * Sets the xdr stream handle xdrs for use on the
- * given memory starting at base offset.
- */
- XXDR*
- xxdr_memcreate(char* mem, off_t memsize, off_t base)
- {
- XXDR* xdrs = (XXDR*)calloc(1,sizeof(XXDR));
- if(xdrs != NULL) {
- /* zero base memory */
- xdrs->data = (void*)(mem + base);
- xdrs->base = 0;
- xdrs->length = memsize - base;
- xdrs->pos = 0;
- xdrs->getbytes = xxdr_memgetbytes;
- xdrs->setpos = xxdr_memsetpos;
- xdrs->getpos = xxdr_memgetpos;
- xdrs->getavail = xxdr_memgetavail;
- xdrs->free = xxdr_memfree;
- }
- xxdrtrace(xdrs,"create",base);
- return xdrs;
- }
- /* Float utility types */
- /* get a float from underlying stream*/
- int
- xxdr_float(XXDR* xdr, float* fp)
- {
- int status = 0;
- float f;
- unsigned int* data = (unsigned int*)&f;
- /* Pull one unit directly into a float */
- status = xxdr_uint(xdr,data);
- if(status && fp)
- *fp = f;
- return status;
- }
- /* Get a double from underlying stream */
- int
- xxdr_double(XXDR* xdr, double* dp)
- {
- int status = 0;
- char data[2*XDRUNIT];
- /* Pull two units */
- status = xxdr_opaque(xdr,data,2*XDRUNIT);
- if(status && dp) {
- xxdrntohdouble(data,dp);
- }
- return status;
- }
- /* Double needs special handling */
- void
- xxdrntohdouble(char* c8, double* dp)
- {
- unsigned int ii[2];
- memcpy(ii,c8,2*XDRUNIT);
- if(!xxdr_big_endian) {
- unsigned int tmp;
- /* reverse byte order */
- swapinline32(&ii[0]);
- swapinline32(&ii[1]);
- /* interchange ii[0] and ii[1] */
- tmp = ii[0];
- ii[0] = ii[1];
- ii[1] = tmp;
- }
- if(dp) *dp = *(double*)ii;
- }
- void
- xxdr_init()
- {
- /* Compute if we are same as network order v-a-v xdr */
- int testint = 0x00000001;
- char *byte = (char *)&testint;
- xxdr_big_endian = (byte[0] == 0 ? 1 : 0);
- xxdr_network_order = xxdr_big_endian;
- }
|