cb10ba0abbfbdac6e428507390cf6f8161119cec
[alexxy/gromacs.git] / src / gromacs / fileio / gmx_system_xdr.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2013,2014, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 #include "gmxpre.h"
38
39 #include "config.h"
40
41 #ifdef GMX_INTERNAL_XDR
42
43
44 #include <stdlib.h>
45 #include <limits.h>
46 #include <string.h>
47
48 #include "gmx_system_xdr.h"
49
50
51 /* NB - THIS FILE IS ONLY USED ON MICROSOFT WINDOWS, since that
52  * system doesn't provide any standard XDR system libraries. It will
53  * most probably work on other platforms too, but make sure you
54  * test that the xtc files produced are ok before using it.
55  *
56  * This header file contains Gromacs versions of the definitions for
57  * Sun External Data Representation (XDR) headers and routines.
58  *
59  * On most UNIX systems this is already present as part of your
60  * system libraries, but since we want to make Gromacs portable to
61  * platforms like Microsoft Windows we have created a private version
62  * of the necessary routines and distribute them with the Gromacs source.
63  *
64  * Although the rest of Gromacs is LGPL, you can copy and use the XDR
65  * routines in any way you want as long as you obey Sun's license:
66  *
67  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
68  * unrestricted use provided that this legend is included on all tape
69  * media and as a part of the software program in whole or part.  Users
70  * may copy or modify Sun RPC without charge, but are not authorized
71  * to license or distribute it to anyone else except as part of a product or
72  * program developed by the user.
73  *
74  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
75  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
76  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
77  *
78  * Sun RPC is provided with no support and without any obligation on the
79  * part of Sun Microsystems, Inc. to assist in its use, correction,
80  * modification or enhancement.
81  *
82  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
83  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
84  * OR ANY PART THEREOF.
85  *
86  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
87  * or profits or other special, indirect and consequential damages, even if
88  * Sun has been advised of the possibility of such damages.
89  *
90  * Sun Microsystems, Inc.
91  * 2550 Garcia Avenue
92  * Mountain View, California  94043
93  */
94
95
96
97 /*
98  * for unit alignment
99  */
100 static char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
101
102 static xdr_uint32_t xdr_swapbytes(xdr_uint32_t x)
103 {
104     xdr_uint32_t y;
105     int          i;
106     char        *px = (char *)&x;
107     char        *py = (char *)&y;
108
109     for (i = 0; i < 4; i++)
110     {
111         py[i] = px[3-i];
112     }
113
114     return y;
115 }
116
117 static xdr_uint32_t xdr_htonl(xdr_uint32_t x)
118 {
119     short s = 0x0F00;
120     if (*((char *)&s) == (char)0x0F)
121     {
122         /* bigendian, do nothing */
123         return x;
124     }
125     else
126     {
127         /* smallendian,swap bytes */
128         return xdr_swapbytes(x);
129     }
130 }
131
132 static xdr_uint32_t xdr_ntohl(xdr_uint32_t x)
133 {
134     short s = 0x0F00;
135     if (*((char *)&s) == (char)0x0F)
136     {
137         /* bigendian, do nothing */
138         return x;
139     }
140     else
141     {
142         /* smallendian, swap bytes */
143         return xdr_swapbytes(x);
144     }
145 }
146
147
148 /*
149  * Free a data structure using XDR
150  * Not a filter, but a convenient utility nonetheless
151  */
152 void
153 xdr_free (xdrproc_t proc, char *objp)
154 {
155     XDR x;
156
157     x.x_op = XDR_FREE;
158     (*proc) ( &x, objp);
159 }
160
161 /*
162  * XDR nothing
163  */
164 bool_t
165 xdr_void (void)
166 {
167     return TRUE;
168 }
169
170 /*
171  * XDR integers
172  */
173 bool_t
174 xdr_int (XDR *xdrs, int *ip)
175 {
176     xdr_int32_t l;
177
178     switch (xdrs->x_op)
179     {
180         case XDR_ENCODE:
181             l = (xdr_int32_t) (*ip);
182             return xdr_putint32 (xdrs, &l);
183
184         case XDR_DECODE:
185             if (!xdr_getint32 (xdrs, &l))
186             {
187                 return FALSE;
188             }
189             *ip = (int) l;
190
191         case XDR_FREE:
192             return TRUE;
193     }
194     return FALSE;
195 }
196
197
198 /*
199  * XDR unsigned integers
200  */
201 bool_t
202 xdr_u_int (XDR *xdrs, unsigned int *up)
203 {
204     xdr_uint32_t l;
205
206     switch (xdrs->x_op)
207     {
208         case XDR_ENCODE:
209             l = (xdr_uint32_t) (*up);
210             return xdr_putuint32 (xdrs, &l);
211
212         case XDR_DECODE:
213             if (!xdr_getuint32 (xdrs, &l))
214             {
215                 return FALSE;
216             }
217             *up = (unsigned int) l;
218
219         case XDR_FREE:
220             return TRUE;
221     }
222     return FALSE;
223 }
224
225
226
227
228 /*
229  * XDR short integers
230  */
231 bool_t
232 xdr_short (XDR *xdrs, short *sp)
233 {
234     xdr_int32_t l;
235
236     switch (xdrs->x_op)
237     {
238         case XDR_ENCODE:
239             l = (xdr_int32_t) *sp;
240             return xdr_putint32 (xdrs, &l);
241
242         case XDR_DECODE:
243             if (!xdr_getint32 (xdrs, &l))
244             {
245                 return FALSE;
246             }
247             *sp = (short) l;
248             return TRUE;
249
250         case XDR_FREE:
251             return TRUE;
252     }
253     return FALSE;
254 }
255
256
257 /*
258  * XDR unsigned short integers
259  */
260 bool_t
261 xdr_u_short (XDR *xdrs, unsigned short *usp)
262 {
263     xdr_uint32_t l;
264
265     switch (xdrs->x_op)
266     {
267         case XDR_ENCODE:
268             l = (xdr_uint32_t) *usp;
269             return xdr_putuint32 (xdrs, &l);
270
271         case XDR_DECODE:
272             if (!xdr_getuint32 (xdrs, &l))
273             {
274                 return FALSE;
275             }
276             *usp = (unsigned short) l;
277             return TRUE;
278
279         case XDR_FREE:
280             return TRUE;
281     }
282     return FALSE;
283 }
284
285
286 /*
287  * XDR a char
288  */
289 bool_t
290 xdr_char (XDR *xdrs, char *cp)
291 {
292     int i;
293
294     i = (*cp);
295     if (!xdr_int (xdrs, &i))
296     {
297         return FALSE;
298     }
299     *cp = i;
300     return TRUE;
301 }
302
303 /*
304  * XDR an unsigned char
305  */
306 bool_t
307 xdr_u_char (XDR *xdrs, unsigned char *cp)
308 {
309     unsigned int u;
310
311     u = (*cp);
312     if (!xdr_u_int (xdrs, &u))
313     {
314         return FALSE;
315     }
316     *cp = u;
317     return TRUE;
318 }
319
320 /*
321  * XDR booleans
322  */
323 bool_t
324 xdr_bool (XDR *xdrs, int *bp)
325 {
326 #define XDR_FALSE   ((xdr_int32_t) 0)
327 #define XDR_TRUE    ((xdr_int32_t) 1)
328
329     xdr_int32_t lb;
330
331     switch (xdrs->x_op)
332     {
333         case XDR_ENCODE:
334             lb = *bp ? XDR_TRUE : XDR_FALSE;
335             return xdr_putint32 (xdrs, &lb);
336
337         case XDR_DECODE:
338             if (!xdr_getint32 (xdrs, &lb))
339             {
340                 return FALSE;
341             }
342             *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
343             return TRUE;
344
345         case XDR_FREE:
346             return TRUE;
347     }
348     return FALSE;
349 #undef XDR_FALSE
350 #undef XDR_TRUE
351 }
352
353
354
355 /*
356  * XDR opaque data
357  * Allows the specification of a fixed size sequence of opaque bytes.
358  * cp points to the opaque object and cnt gives the byte length.
359  */
360 bool_t
361 xdr_opaque (XDR *xdrs, char *cp, unsigned int cnt)
362 {
363     unsigned int rndup;
364     char         crud[BYTES_PER_XDR_UNIT];
365
366     /*
367      * if no data we are done
368      */
369     if (cnt == 0)
370     {
371         return TRUE;
372     }
373
374     /*
375      * round byte count to full xdr units
376      */
377     rndup = cnt % BYTES_PER_XDR_UNIT;
378     if (rndup > 0)
379     {
380         rndup = BYTES_PER_XDR_UNIT - rndup;
381     }
382
383     switch (xdrs->x_op)
384     {
385         case XDR_DECODE:
386             if (!xdr_getbytes (xdrs, cp, cnt))
387             {
388                 return FALSE;
389             }
390             if (rndup == 0)
391             {
392                 return TRUE;
393             }
394             return xdr_getbytes (xdrs, (char *)crud, rndup);
395
396         case XDR_ENCODE:
397             if (!xdr_putbytes (xdrs, cp, cnt))
398             {
399                 return FALSE;
400             }
401             if (rndup == 0)
402             {
403                 return TRUE;
404             }
405             return xdr_putbytes (xdrs, xdr_zero, rndup);
406
407         case XDR_FREE:
408             return TRUE;
409     }
410     return FALSE;
411 }
412
413
414 /*
415  * XDR null terminated ASCII strings
416  * xdr_string deals with "C strings" - arrays of bytes that are
417  * terminated by a NULL character.  The parameter cpp references a
418  * pointer to storage; If the pointer is null, then the necessary
419  * storage is allocated.  The last parameter is the max allowed length
420  * of the string as specified by a protocol.
421  */
422 bool_t
423 xdr_string (xdrs, cpp, maxsize)
424 XDR *xdrs;
425 char       **cpp;
426 unsigned int maxsize;
427 {
428     char        *sp       = *cpp; /* sp is the actual string pointer */
429     unsigned int size     = 0;
430     unsigned int nodesize = 0;
431
432     /*
433      * first deal with the length since xdr strings are counted-strings
434      */
435     switch (xdrs->x_op)
436     {
437         case XDR_FREE:
438             if (sp == NULL)
439             {
440                 return TRUE; /* already free */
441             }
442         /* fall through... */
443         case XDR_ENCODE:
444             if (sp == NULL)
445             {
446                 return FALSE;
447             }
448             size = strlen (sp);
449             break;
450         case XDR_DECODE:
451             break;
452     }
453
454     if (!xdr_u_int (xdrs, &size))
455     {
456         return FALSE;
457     }
458     if (size > maxsize)
459     {
460         return FALSE;
461     }
462     nodesize = size + 1;
463
464     /*
465      * now deal with the actual bytes
466      */
467     switch (xdrs->x_op)
468     {
469         case XDR_DECODE:
470             if (nodesize == 0)
471             {
472                 return TRUE;
473             }
474             if (sp == NULL)
475             {
476                 *cpp = sp = (char *) malloc (nodesize);
477             }
478             if (sp == NULL)
479             {
480                 (void) fputs ("xdr_string: out of memory\n", stderr);
481                 return FALSE;
482             }
483             sp[size] = 0;
484         /* fall into ... */
485
486         case XDR_ENCODE:
487             return xdr_opaque (xdrs, sp, size);
488
489         case XDR_FREE:
490             free (sp);
491             *cpp = NULL;
492             return TRUE;
493     }
494     return FALSE;
495 }
496
497
498
499 /* Floating-point stuff */
500
501 bool_t
502 xdr_float(xdrs, fp)
503 XDR *xdrs;
504 float *fp;
505 {
506     xdr_int32_t tmp;
507
508     switch (xdrs->x_op)
509     {
510
511         case XDR_ENCODE:
512             tmp = *(xdr_int32_t *)fp;
513             return (xdr_putint32(xdrs, &tmp));
514
515             break;
516
517         case XDR_DECODE:
518             if (xdr_getint32(xdrs, &tmp))
519             {
520                 *(xdr_int32_t *)fp = tmp;
521                 return (TRUE);
522             }
523
524             break;
525
526         case XDR_FREE:
527             return (TRUE);
528     }
529     return (FALSE);
530 }
531
532
533 bool_t
534 xdr_double(xdrs, dp)
535 XDR *xdrs;
536 double *dp;
537 {
538
539     /* Windows and some other systems dont define double-precision
540      * word order in the header files, so unfortunately we have
541      * to calculate it!
542      *
543      * For thread safety, we calculate it every time: locking this would
544      * be more expensive.
545      */
546     /*static int LSW=-1;*/ /* Least significant fp word */
547     int LSW = -1; /* Least significant fp word */
548
549
550     int        *ip;
551     xdr_int32_t tmp[2];
552
553     if (LSW < 0)
554     {
555         double x = 0.987654321; /* Just a number */
556
557         /* Possible representations in IEEE double precision:
558          * (S=small endian, B=big endian)
559          *
560          * Byte order, Word order, Hex
561          *     S           S       b8 56 0e 3c dd 9a ef 3f
562          *     B           S       3c 0e 56 b8 3f ef 9a dd
563          *     S           B       dd 9a ef 3f b8 56 0e 3c
564          *     B           B       3f ef 9a dd 3c 0e 56 b8
565          */
566
567         unsigned char ix = *((char *)&x);
568
569         if (ix == 0xdd || ix == 0x3f)
570         {
571             LSW = 1; /* Big endian word order */
572         }
573         else if (ix == 0xb8 || ix == 0x3c)
574         {
575             LSW = 0; /* Small endian word order */
576         }
577         else         /* Catch strange errors */
578         {
579             printf("Error when detecting floating-point word order.\n"
580                    "Do you have a non-IEEE system?\n"
581                    "If possible, use the XDR libraries provided with your system,\n"
582                    "instead of the Gromacs fallback XDR source.\n");
583             exit(0);
584         }
585     }
586
587     switch (xdrs->x_op)
588     {
589
590         case XDR_ENCODE:
591             ip     = (int *)dp;
592             tmp[0] = ip[!LSW];
593             tmp[1] = ip[LSW];
594             return (xdr_putint32(xdrs, tmp) &&
595                     xdr_putint32(xdrs, tmp+1));
596
597             break;
598
599         case XDR_DECODE:
600             ip = (int *)dp;
601             if (xdr_getint32(xdrs, tmp+!LSW) &&
602                 xdr_getint32(xdrs, tmp+LSW))
603             {
604                 ip[0] = tmp[0];
605                 ip[1] = tmp[1];
606                 return (TRUE);
607             }
608
609             break;
610
611         case XDR_FREE:
612             return (TRUE);
613     }
614     return (FALSE);
615 }
616
617
618 /* Array routines */
619
620 /*
621  * xdr_vector():
622  *
623  * XDR a fixed length array. Unlike variable-length arrays,
624  * the storage of fixed length arrays is static and unfreeable.
625  * > basep: base of the array
626  * > size: size of the array
627  * > elemsize: size of each element
628  * > xdr_elem: routine to XDR each element
629  */
630 bool_t
631 xdr_vector (xdrs, basep, nelem, elemsize, xdr_elem)
632 XDR *xdrs;
633 char        *basep;
634 unsigned int nelem;
635 unsigned int elemsize;
636 xdrproc_t    xdr_elem;
637 {
638 #define LASTUNSIGNED    ((unsigned int)0-1)
639     unsigned int i;
640     char        *elptr;
641
642     elptr = basep;
643     for (i = 0; i < nelem; i++)
644     {
645         if (!(*xdr_elem) (xdrs, elptr, LASTUNSIGNED))
646         {
647             return FALSE;
648         }
649         elptr += elemsize;
650     }
651     return TRUE;
652 #undef LASTUNSIGNED
653 }
654
655
656
657 static bool_t xdrstdio_getbytes (XDR *, char *, unsigned int);
658 static bool_t xdrstdio_putbytes (XDR *, char *, unsigned int);
659 static unsigned int xdrstdio_getpos (XDR *);
660 static bool_t xdrstdio_setpos (XDR *, unsigned int);
661 static xdr_int32_t *xdrstdio_inline (XDR *, int);
662 static void xdrstdio_destroy (XDR *);
663 static bool_t xdrstdio_getint32 (XDR *, xdr_int32_t *);
664 static bool_t xdrstdio_putint32 (XDR *, xdr_int32_t *);
665 static bool_t xdrstdio_getuint32 (XDR *, xdr_uint32_t *);
666 static bool_t xdrstdio_putuint32 (XDR *, xdr_uint32_t *);
667
668 /*
669  * Ops vector for stdio type XDR
670  */
671 static const struct xdr_ops xdrstdio_ops =
672 {
673     xdrstdio_getbytes,  /* deserialize counted bytes */
674     xdrstdio_putbytes,  /* serialize counted bytes */
675     xdrstdio_getpos,    /* get offset in the stream */
676     xdrstdio_setpos,    /* set offset in the stream */
677     xdrstdio_inline,    /* prime stream for inline macros */
678     xdrstdio_destroy,   /* destroy stream */
679     xdrstdio_getint32,  /* deserialize a int */
680     xdrstdio_putint32,  /* serialize a int */
681     xdrstdio_getuint32, /* deserialize a int */
682     xdrstdio_putuint32  /* serialize a int */
683 };
684
685 /*
686  * Initialize a stdio xdr stream.
687  * Sets the xdr stream handle xdrs for use on the stream file.
688  * Operation flag is set to op.
689  */
690 void
691 xdrstdio_create (XDR *xdrs, FILE *file, enum xdr_op op)
692 {
693     xdrs->x_op = op;
694     /* We have to add the const since the `struct xdr_ops' in `struct XDR'
695        is not `const'.  */
696     xdrs->x_ops     = (struct xdr_ops *) &xdrstdio_ops;
697     xdrs->x_private = (char *) file;
698     xdrs->x_handy   = 0;
699     xdrs->x_base    = 0;
700 }
701
702 /*
703  * Destroy a stdio xdr stream.
704  * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create.
705  */
706 static void
707 xdrstdio_destroy (XDR *xdrs)
708 {
709     (void) fflush ((FILE *) xdrs->x_private);
710     /* xx should we close the file ?? */
711 }
712
713
714 static bool_t
715 xdrstdio_getbytes (XDR *xdrs, char *addr, unsigned int len)
716 {
717     if ((len != 0) && (fread (addr, (int) len, 1,
718                               (FILE *) xdrs->x_private) != 1))
719     {
720         return FALSE;
721     }
722     return TRUE;
723 }
724
725 static bool_t
726 xdrstdio_putbytes (XDR *xdrs, char *addr, unsigned int len)
727 {
728     if ((len != 0) && (fwrite (addr, (int) len, 1,
729                                (FILE *) xdrs->x_private) != 1))
730     {
731         return FALSE;
732     }
733     return TRUE;
734 }
735
736 static unsigned int
737 xdrstdio_getpos (XDR *xdrs)
738 {
739     return (unsigned int) ftell ((FILE *) xdrs->x_private);
740 }
741
742 static bool_t
743 xdrstdio_setpos (XDR *xdrs, unsigned int pos)
744 {
745     return fseek ((FILE *) xdrs->x_private, (xdr_int32_t) pos, 0) < 0 ? FALSE : TRUE;
746 }
747
748 static xdr_int32_t *
749 xdrstdio_inline (XDR *xdrs, int len)
750 {
751     (void)xdrs;
752     (void)len;
753     /*
754      * Must do some work to implement this: must insure
755      * enough data in the underlying stdio buffer,
756      * that the buffer is aligned so that we can indirect through a
757      * long *, and stuff this pointer in xdrs->x_buf.  Doing
758      * a fread or fwrite to a scratch buffer would defeat
759      * most of the gains to be had here and require storage
760      * management on this buffer, so we don't do this.
761      */
762     return NULL;
763 }
764
765 static bool_t
766 xdrstdio_getint32 (XDR *xdrs, xdr_int32_t *ip)
767 {
768     xdr_int32_t mycopy;
769
770     if (fread ((char *) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1)
771     {
772         return FALSE;
773     }
774     *ip = xdr_ntohl (mycopy);
775     return TRUE;
776 }
777
778 static bool_t
779 xdrstdio_putint32 (XDR *xdrs, xdr_int32_t *ip)
780 {
781     xdr_int32_t mycopy = xdr_htonl (*ip);
782
783     ip = &mycopy;
784     if (fwrite ((char *) ip, 4, 1, (FILE *) xdrs->x_private) != 1)
785     {
786         return FALSE;
787     }
788     return TRUE;
789 }
790
791 static bool_t
792 xdrstdio_getuint32 (XDR *xdrs, xdr_uint32_t *ip)
793 {
794     xdr_uint32_t mycopy;
795
796     if (fread ((char *) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1)
797     {
798         return FALSE;
799     }
800     *ip = xdr_ntohl (mycopy);
801     return TRUE;
802 }
803
804 static bool_t
805 xdrstdio_putuint32 (XDR *xdrs, xdr_uint32_t *ip)
806 {
807     xdr_uint32_t mycopy = xdr_htonl (*ip);
808
809     ip = &mycopy;
810     if (fwrite ((char *) ip, 4, 1, (FILE *) xdrs->x_private) != 1)
811     {
812         return FALSE;
813     }
814     return TRUE;
815 }
816
817 #else
818 int
819     gmx_system_xdr_empty;
820 #endif /* GMX_SYSTEM_XDR */