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