source: XIOS/dev/dev_olga/src/extern/src_netcdf4/xxdr.c @ 1022

Last change on this file since 1022 was 1022, checked in by mhnguyen, 7 years ago
File size: 10.4 KB
Line 
1/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
2   See the COPYRIGHT file for more information. */
3
4/*
5 * Copyright (c) 2009, Sun Microsystems, Inc.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 * - Redistributions of source code must retain the above copyright notice,
11 *   this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright notice,
13 *   this list of conditions and the following disclaimer in the documentation
14 *   and/or other materials provided with the distribution.
15 * - Neither the name of Sun Microsystems, Inc. nor the names of its
16 *   contributors may be used to endorse or promote products derived
17 *   from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 *      from: @(#)xdr.h 1.19 87/04/22 SMI
32 *      from: @(#)xdr.h        2.2 88/07/29 4.0 RPCSRC
33 *      $FreeBSD: src/include/rpc/xdr.h,v 1.23 2003/03/07 13:19:40 nectar Exp $
34 *      $NetBSD: xdr.h,v 1.19 2000/07/17 05:00:45 matt Exp $
35 */
36
37/* Define our own implementation of the needed
38   elements of XDR. Assumes read-only
39*/
40
41#undef XXDRTRACE
42
43#include "config.h"
44#include <stdlib.h>
45#include <stdio.h>
46#include <assert.h>
47#include <string.h>
48#include <stdarg.h>
49#ifdef HAVE_UNISTD_H
50#include <unistd.h>
51#endif
52
53#include "xxdr.h"
54
55int xxdr_network_order; /* network order is big endian */
56static int xxdr_big_endian; /* what is this machine? */
57
58#ifdef XXDRTRACE
59static void
60xxdrtrace(XXDR* xdr, char* where, off_t arg)
61{
62fprintf(stderr,"xxdr: %s: arg=%ld ; pos=%ld len=%ld\n",
63        where,arg,(long)xdr->pos,(long)xdr->length);
64fflush(stderr);
65}
66#else
67#define xxdrtrace(x,y,z)
68#endif
69
70/* Read-only operations */
71
72int xxdr_getbytes(XXDR* xdrs, char* memory, off_t count)
73{
74    if(!memory) return 0;
75    if(!xdrs->getbytes(xdrs,memory,count))
76        return 0;
77    return 1;
78}
79
80
81/* get a unsigned int from underlying stream*/
82int
83xxdr_uint(XXDR* xdr, unsigned int* ip)
84{
85   if(!ip) return 0;
86   if(!xdr->getbytes(xdr,(char*)ip,sizeof(*ip)))
87        return 0;
88    /*convert from network order*/
89    if(!xxdr_network_order) {
90        swapinline32(ip);
91    }
92    return 1;
93}
94
95/* get a long long  from underlying stream*/
96int
97xxdr_ulonglong(XXDR* xdr, unsigned long* llp)
98{
99   /* Pull two units */
100   if(!llp) return 0;
101   if(!xdr->getbytes(xdr,(char*)llp,sizeof(*llp)))
102       return 0;
103   /* Convert to signed/unsigned  */
104   /*convert from network order*/
105   if(!xxdr_network_order) {
106       swapinline64(llp);
107   }
108   return 1;
109}
110
111/* get some bytes from underlying stream;
112   will move xdrs pointer to next XDRUNIT boundary*/
113int
114xxdr_opaque(XXDR* xdr, char* mem, off_t count)
115{
116    off_t pos,rounded;
117    if(!xdr->getbytes(xdr,mem,count))
118        return 0;
119    pos = xxdr_getpos(xdr);
120    rounded = RNDUP(pos);
121    return xxdr_skip(xdr,(rounded - pos));
122}
123
124/* get counted string from underlying stream*/
125int
126xxdr_string(XXDR* xdrs, char** sp, off_t* lenp)
127{
128    char* s;
129    unsigned int len;
130    if(!xxdr_uint(xdrs,&len)) return 0;
131    s = (char*)malloc((off_t)len+1);
132    if(s == NULL) return 0;
133    if(!xxdr_opaque(xdrs,s,len)) {
134        free((void*)s); 
135        return 0;
136    }
137    s[len] = '\0'; /* make sure it is null terminated */
138    if(sp) *sp = s;
139    if(lenp) *lenp = len;
140    /* xxdr_opaque will have skippped any trailing bytes */
141    return 1;   
142}
143
144/* returns bytes off from beginning*/
145off_t
146xxdr_getpos(XXDR* xdr)
147{
148    return xdr->getpos(xdr);
149}
150
151/* reposition the stream*/
152int
153xxdr_setpos(XXDR* xdr, off_t pos)
154{
155    return xdr->setpos(xdr,pos);
156}
157
158/* returns total available starting at current position */
159off_t
160xxdr_getavail(XXDR* xdr)
161{
162    return xdr->getavail(xdr);
163}
164
165/* free up XXDR  structure */
166void
167xxdr_free(XXDR* xdr)
168{
169    xdr->free(xdr);   
170}
171
172/***********************************/
173
174/* Skip exacly "len" bytes in the input; any rounding must be done by the caller*/
175int
176xxdr_skip(XXDR* xdrs, off_t len)
177{
178    unsigned int pos;
179    pos = xxdr_getpos(xdrs);
180    pos = (pos + len);
181    if(pos < 0) pos = 0;
182    return xxdr_setpos(xdrs,pos);
183}
184
185/* skip "n" string/bytestring instances in the input*/
186int
187xxdr_skip_strings(XXDR* xdrs, off_t n)
188{
189    while(n-- > 0) {
190        unsigned int slen;
191        if(!xxdr_uint(xdrs,&slen)) return 0;
192        slen = RNDUP(slen);
193        if(xxdr_skip(xdrs,slen)) return 0;
194    }
195    return 1;
196}
197
198unsigned int
199xdr_roundup(unsigned int n)
200{
201    unsigned int rounded;
202    rounded = RNDUP(n);
203    return rounded;
204}
205
206unsigned int
207ocbyteswap(unsigned int i)
208{
209    unsigned int swap,b0,b1,b2,b3;
210    b0 = (i>>24) & 0x000000ff;
211    b1 = (i>>16) & 0x000000ff;
212    b2 = (i>>8) & 0x000000ff;
213    b3 = (i) & 0x000000ff;
214    swap = (b0 | (b1 << 8) | (b2 << 16) | (b3 << 24));
215    return swap;
216}
217
218/**************************************************/
219/* File based xdr */
220static void
221xxdr_filefree(XXDR* xdrs)
222{
223    if(xdrs != NULL) {
224        (void)fflush((FILE *)xdrs->data);
225        free(xdrs);
226    }
227}
228
229static int
230xxdr_filegetbytes(XXDR* xdrs, char* addr, off_t len)
231{
232    int ok = 1;
233    int count;
234
235xxdrtrace(xdrs,"getbytes",len);
236    if(len < 0) len = 0;
237    if(!xdrs->valid)
238    {
239        if(fseek((FILE *)xdrs->data, xdrs->pos + xdrs->base, 0) != 0) {
240            ok=0;
241            goto done;
242        }
243        xdrs->valid = 1;
244    }
245    if(xdrs->pos + len > xdrs->length)
246        return 0;
247    if(len > 0) {
248        count = fread(addr, len, 1, (FILE*)xdrs->data);
249        if(count <= 0) {
250            ok=0;
251            goto done;
252        }
253    }
254    xdrs->pos += len;
255done:
256    return ok;
257}
258
259static off_t
260xxdr_filegetpos(XXDR* xdrs)
261{
262xxdrtrace(xdrs,"getpos",0);
263    return xdrs->pos;
264}
265
266static off_t
267xxdr_filegetavail(XXDR* xdrs)
268{
269xxdrtrace(xdrs,"getavail",0);
270    return (xdrs->length - xdrs->pos);
271}
272
273static int
274xxdr_filesetpos(XXDR* xdrs, off_t pos) 
275{ 
276    int ok = 1;
277xxdrtrace(xdrs,"setpos",pos);
278    if(pos == xdrs->pos) goto done;
279    if(pos < 0) pos = 0;
280    if(pos > xdrs->length) {ok=0;goto done;}
281    xdrs->pos = pos;
282    xdrs->valid = 0;
283done:
284    return ok;
285}
286
287
288/*
289Modified to track the current position to avoid the file io
290operation.  Not sure if this worth the effort because I
291don't actually know the cost to doing an fseek
292*/
293
294/*
295 * Initialize a stdio xdr stream.
296 * Sets the xdr stream handle xdrs for use on the stream file.
297 * Operation flag is set to op.
298 */
299XXDR*
300xxdr_filecreate(FILE* file, off_t base)
301{
302    XXDR* xdrs = (XXDR*)calloc(1,sizeof(XXDR));
303    if(xdrs != NULL) {
304        xdrs->data = (void*)file;
305        xdrs->base = base;
306        xdrs->pos = 0;
307        xdrs->valid = 0;
308        if(fseek(file,0L,SEEK_END)) return NULL;
309        xdrs->length = (off_t)ftell(file);
310        xdrs->length -= xdrs->base;
311        xdrs->getbytes = xxdr_filegetbytes;
312        xdrs->setpos = xxdr_filesetpos;
313        xdrs->getpos = xxdr_filegetpos;
314        xdrs->getavail = xxdr_filegetavail;
315        xdrs->free = xxdr_filefree;
316    }
317xxdrtrace(xdrs,"create",base);
318    return xdrs;
319}
320
321/**************************************************/
322/* memory based xdr */
323
324static void
325xxdr_memfree(XXDR* xdrs)
326{
327    if(xdrs != NULL) {
328        free(xdrs);
329    }
330}
331
332static int
333xxdr_memgetbytes(XXDR* xdrs, char* addr, off_t len)
334{
335    int ok = 1;
336
337xxdrtrace(xdrs,"getbytes",len);
338    if(len < 0) len = 0;
339    if(xdrs->pos+len > xdrs->length) {ok=0; goto done;}
340    if(len > 0) {
341        memcpy(addr,(char*)xdrs->data+xdrs->base+xdrs->pos, len);
342    }
343    xdrs->pos += len;
344done:
345    return ok;
346}
347
348static off_t
349xxdr_memgetpos(XXDR* xdrs)
350{
351xxdrtrace(xdrs,"getpos",0);
352    return xdrs->pos;
353}
354
355static off_t
356xxdr_memgetavail(XXDR* xdrs)
357{
358xxdrtrace(xdrs,"getavail",0);
359    return (xdrs->length - xdrs->pos);
360}
361
362
363static int
364xxdr_memsetpos(XXDR* xdrs, off_t pos) 
365{ 
366    int ok = 1;
367xxdrtrace(xdrs,"setpos",pos);
368    if(pos == xdrs->pos) goto done;
369    if(pos > xdrs->length) {ok=0; goto done;}
370    xdrs->pos = pos;
371done:
372    return ok;
373}
374
375/*
376Modified to track the current position to avoid the file io
377operation.  Not sure if this worth the effort because I
378don't actually know the cost to doing an fseek
379*/
380
381/*
382 * Initialize a stdio xdr stream.
383 * Sets the xdr stream handle xdrs for use on the
384 * given memory starting at base offset.
385 */
386XXDR*
387xxdr_memcreate(char* mem, off_t memsize, off_t base)
388{
389    XXDR* xdrs = (XXDR*)calloc(1,sizeof(XXDR));
390    if(xdrs != NULL) {
391        /* zero base memory */
392        xdrs->data = (void*)(mem + base);
393        xdrs->base = 0;
394        xdrs->length = memsize - base;
395        xdrs->pos = 0;
396        xdrs->getbytes = xxdr_memgetbytes;
397        xdrs->setpos = xxdr_memsetpos;
398        xdrs->getpos = xxdr_memgetpos;
399        xdrs->getavail = xxdr_memgetavail;
400        xdrs->free = xxdr_memfree;
401    }
402xxdrtrace(xdrs,"create",base);
403    return xdrs;
404}
405
406/* Float utility types */
407
408/* get a float from underlying stream*/
409int
410xxdr_float(XXDR* xdr, float* fp)
411{
412   int status = 0;
413   float f;
414   unsigned int* data = (unsigned int*)&f;
415   /* Pull one unit directly into a float */
416   status = xxdr_uint(xdr,data);
417   if(status && fp)
418        *fp = f;
419   return status;
420}
421
422/* Get a double from underlying stream */
423int
424xxdr_double(XXDR* xdr, double* dp)
425{
426   int status = 0;
427   char data[2*XDRUNIT];
428   /* Pull two units */
429   status = xxdr_opaque(xdr,data,2*XDRUNIT);
430   if(status && dp) {
431        xxdrntohdouble(data,dp);
432   }
433   return status;
434}
435
436/* Double needs special handling */
437void
438xxdrntohdouble(char* c8, double* dp)
439{
440    unsigned int ii[2];
441    memcpy(ii,c8,2*XDRUNIT);
442    if(!xxdr_big_endian) {
443        unsigned int tmp;
444        /* reverse byte order */
445        swapinline32(&ii[0]);
446        swapinline32(&ii[1]);
447        /* interchange ii[0] and ii[1] */
448        tmp = ii[0];
449        ii[0] = ii[1];
450        ii[1] = tmp;
451    }
452    if(dp) *dp = *(double*)ii;
453}
454
455void
456xxdr_init()
457{
458    /* Compute if we are same as network order v-a-v xdr */
459    int testint = 0x00000001;
460    char *byte = (char *)&testint;
461    xxdr_big_endian = (byte[0] == 0 ? 1 : 0);
462    xxdr_network_order = xxdr_big_endian;
463}
Note: See TracBrowser for help on using the repository browser.