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