b2876d0566d8e9cc738334e57e39bbbfdb9cf387
[alexxy/gromacs.git] / src / gromacs / fileio / gmxfio-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 "gmxfio-xdr.h"
40
41 #include <assert.h>
42 #include <stdio.h>
43 #include <string.h>
44
45 #include "gromacs/fileio/gmxfio.h"
46 #include "gromacs/fileio/xdrf.h"
47 #include "gromacs/utility/fatalerror.h"
48 #include "gromacs/utility/smalloc.h"
49
50 #include "gmxfio-impl.h"
51
52 /* Enumerated for data types in files */
53 enum {
54     eioREAL, eioFLOAT, eioDOUBLE, eioINT, eioINT64,
55     eioUCHAR, eioNUCHAR, eioUSHORT,
56     eioRVEC, eioNRVEC, eioIVEC, eioSTRING, eioNR
57 };
58
59 static const char *eioNames[eioNR] =
60 {
61     "REAL", "INT", "GMX_STE_T", "UCHAR", "NUCHAR", "USHORT", "RVEC", "NRVEC",
62     "IVEC", "STRING"
63 };
64
65 void gmx_fio_setprecision(t_fileio *fio, gmx_bool bDouble)
66 {
67     gmx_fio_lock(fio);
68     fio->bDouble = bDouble;
69     gmx_fio_unlock(fio);
70 }
71
72 XDR *gmx_fio_getxdr(t_fileio *fio)
73 {
74     XDR *ret = NULL;
75     gmx_fio_lock(fio);
76     assert(fio->xdr != NULL);
77     ret = fio->xdr;
78     gmx_fio_unlock(fio);
79     return ret;
80 }
81
82 /* check the number of items given against the type */
83 static void gmx_fio_check_nitem(int eio, int nitem, const char *file, int line)
84 {
85     if ((nitem != 1) && !((eio == eioNRVEC) || (eio == eioNUCHAR)))
86     {
87         gmx_fatal(FARGS,
88                   "nitem (%d) may differ from 1 only for %s or %s, not   for %s"
89                   "(%s, %d)", nitem, eioNames[eioNUCHAR], eioNames[eioNRVEC],
90                   eioNames[eio], file, line);
91     }
92 }
93
94 /* output a data type error. */
95 static void gmx_fio_fe(t_fileio *fio, int eio, const char *desc,
96                        const char *srcfile, int line)
97 {
98
99     gmx_fatal(FARGS, "Trying to %s %s type %d (%s), src %s, line %d",
100               fio->bRead ? "read" : "write", desc, eio,
101               ((eio >= 0) && (eio < eioNR)) ? eioNames[eio] : "unknown",
102               srcfile, line);
103 }
104
105 /* This is the part that reads xdr files.  */
106
107 static gmx_bool do_xdr(t_fileio *fio, void *item, int nitem, int eio,
108                        const char *desc, const char *srcfile, int line)
109 {
110     unsigned char   ucdum, *ucptr;
111     bool_t          res = 0;
112     float           fvec[DIM];
113     double          dvec[DIM];
114     int             j, m, *iptr, idum;
115     gmx_int64_t     sdum;
116     real           *ptr;
117     unsigned short  us;
118     double          d = 0;
119     float           f = 0;
120
121     assert(fio->xdr != NULL);
122     gmx_fio_check_nitem(eio, nitem, srcfile, line);
123     switch (eio)
124     {
125         case eioREAL:
126             if (fio->bDouble)
127             {
128                 if (item && !fio->bRead)
129                 {
130                     d = *((real *) item);
131                 }
132                 res = xdr_double(fio->xdr, &d);
133                 if (item)
134                 {
135                     *((real *) item) = d;
136                 }
137             }
138             else
139             {
140                 if (item && !fio->bRead)
141                 {
142                     f = *((real *) item);
143                 }
144                 res = xdr_float(fio->xdr, &f);
145                 if (item)
146                 {
147                     *((real *) item) = f;
148                 }
149             }
150             break;
151         case eioFLOAT:
152             if (item && !fio->bRead)
153             {
154                 f = *((float *) item);
155             }
156             res = xdr_float(fio->xdr, &f);
157             if (item)
158             {
159                 *((float *) item) = f;
160             }
161             break;
162         case eioDOUBLE:
163             if (item && !fio->bRead)
164             {
165                 d = *((double *) item);
166             }
167             res = xdr_double(fio->xdr, &d);
168             if (item)
169             {
170                 *((double *) item) = d;
171             }
172             break;
173         case eioINT:
174             if (item && !fio->bRead)
175             {
176                 idum = *(int *) item;
177             }
178             res = xdr_int(fio->xdr, &idum);
179             if (item)
180             {
181                 *(int *) item = idum;
182             }
183             break;
184         case eioINT64:
185             if (item && !fio->bRead)
186             {
187                 sdum = *(gmx_int64_t *) item;
188             }
189             res = xdr_int64(fio->xdr, &sdum);
190             if (item)
191             {
192                 *(gmx_int64_t *) item = sdum;
193             }
194             break;
195         case eioUCHAR:
196             if (item && !fio->bRead)
197             {
198                 ucdum = *(unsigned char *) item;
199             }
200             res = xdr_u_char(fio->xdr, &ucdum);
201             if (item)
202             {
203                 *(unsigned char *) item = ucdum;
204             }
205             break;
206         case eioNUCHAR:
207             ucptr = (unsigned char *) item;
208             res   = 1;
209             for (j = 0; (j < nitem) && res; j++)
210             {
211                 res = xdr_u_char(fio->xdr, &(ucptr[j]));
212             }
213             break;
214         case eioUSHORT:
215             if (item && !fio->bRead)
216             {
217                 us = *(unsigned short *) item;
218             }
219             res = xdr_u_short(fio->xdr, (unsigned short *) &us);
220             if (item)
221             {
222                 *(unsigned short *) item = us;
223             }
224             break;
225         case eioRVEC:
226             if (fio->bDouble)
227             {
228                 if (item && !fio->bRead)
229                 {
230                     for (m = 0; (m < DIM); m++)
231                     {
232                         dvec[m] = ((real *) item)[m];
233                     }
234                 }
235                 res = xdr_vector(fio->xdr, (char *) dvec, DIM,
236                                  (unsigned int) sizeof(double),
237                                  (xdrproc_t) xdr_double);
238                 if (item)
239                 {
240                     for (m = 0; (m < DIM); m++)
241                     {
242                         ((real *) item)[m] = dvec[m];
243                     }
244                 }
245             }
246             else
247             {
248                 if (item && !fio->bRead)
249                 {
250                     for (m = 0; (m < DIM); m++)
251                     {
252                         fvec[m] = ((real *) item)[m];
253                     }
254                 }
255                 res = xdr_vector(fio->xdr, (char *) fvec, DIM,
256                                  (unsigned int) sizeof(float),
257                                  (xdrproc_t) xdr_float);
258                 if (item)
259                 {
260                     for (m = 0; (m < DIM); m++)
261                     {
262                         ((real *) item)[m] = fvec[m];
263                     }
264                 }
265             }
266             break;
267         case eioNRVEC:
268             ptr = NULL;
269             res = 1;
270             for (j = 0; (j < nitem) && res; j++)
271             {
272                 if (item)
273                 {
274                     ptr = ((rvec *) item)[j];
275                 }
276                 res = do_xdr(fio, ptr, 1, eioRVEC, desc, srcfile, line);
277             }
278             break;
279         case eioIVEC:
280             iptr = (int *) item;
281             res  = 1;
282             for (m = 0; (m < DIM) && res; m++)
283             {
284                 if (item && !fio->bRead)
285                 {
286                     idum = iptr[m];
287                 }
288                 res = xdr_int(fio->xdr, &idum);
289                 if (item)
290                 {
291                     iptr[m] = idum;
292                 }
293             }
294             break;
295         case eioSTRING:
296         {
297             char *cptr;
298             int   slen;
299
300             if (item)
301             {
302                 if (!fio->bRead)
303                 {
304                     slen = strlen((char *) item) + 1;
305                 }
306                 else
307                 {
308                     slen = 0;
309                 }
310             }
311             else
312             {
313                 slen = 0;
314             }
315
316             if (xdr_int(fio->xdr, &slen) <= 0)
317             {
318                 gmx_fatal(FARGS, "wrong string length %d for string %s"
319                           " (source %s, line %d)", slen, desc, srcfile, line);
320             }
321             if (!item && fio->bRead)
322             {
323                 snew(cptr, slen);
324             }
325             else
326             {
327                 cptr = (char *)item;
328             }
329             if (cptr)
330             {
331                 res = xdr_string(fio->xdr, &cptr, slen);
332             }
333             else
334             {
335                 res = 1;
336             }
337             if (!item && fio->bRead)
338             {
339                 sfree(cptr);
340             }
341             break;
342         }
343         default:
344             gmx_fio_fe(fio, eio, desc, srcfile, line);
345     }
346
347     return (res != 0);
348 }
349
350 /*******************************************************************
351  *
352  * READ/WRITE FUNCTIONS
353  *
354  *******************************************************************/
355
356 gmx_bool gmx_fio_writee_string(t_fileio *fio, const char *item,
357                                const char *desc, const char *srcfile, int line)
358 {
359     gmx_bool ret;
360     void    *it = (void*)item; /* ugh.. */
361     gmx_fio_lock(fio);
362     ret = do_xdr(fio, it, 1, eioSTRING, desc, srcfile, line);
363     gmx_fio_unlock(fio);
364     return ret;
365 }
366
367 gmx_bool gmx_fio_doe_real(t_fileio *fio, real *item,
368                           const char *desc, const char *srcfile, int line)
369 {
370     gmx_bool ret;
371     gmx_fio_lock(fio);
372     ret = do_xdr(fio, item, 1, eioREAL, desc, srcfile, line);
373     gmx_fio_unlock(fio);
374     return ret;
375
376 }
377
378 gmx_bool gmx_fio_doe_float(t_fileio *fio, float *item,
379                            const char *desc, const char *srcfile, int line)
380 {
381     gmx_bool ret;
382     gmx_fio_lock(fio);
383     ret = do_xdr(fio, item, 1, eioFLOAT, desc, srcfile, line);
384     gmx_fio_unlock(fio);
385     return ret;
386 }
387
388 gmx_bool gmx_fio_doe_double(t_fileio *fio, double *item,
389                             const char *desc, const char *srcfile, int line)
390 {
391     gmx_bool ret;
392     gmx_fio_lock(fio);
393     ret = do_xdr(fio, item, 1, eioDOUBLE, desc, srcfile, line);
394     gmx_fio_unlock(fio);
395     return ret;
396 }
397
398
399 gmx_bool gmx_fio_doe_gmx_bool(t_fileio *fio, gmx_bool *item,
400                               const char *desc, const char *srcfile, int line)
401 {
402     gmx_bool ret;
403
404     gmx_fio_lock(fio);
405     if (fio->bRead)
406     {
407         int itmp = 0;
408         ret      = do_xdr(fio, &itmp, 1, eioINT, desc, srcfile, line);
409         *item    = itmp;
410     }
411     else
412     {
413         int itmp = *item;
414         ret      = do_xdr(fio, &itmp, 1, eioINT, desc, srcfile, line);
415     }
416     gmx_fio_unlock(fio);
417     return ret;
418 }
419
420 gmx_bool gmx_fio_doe_int(t_fileio *fio, int *item,
421                          const char *desc, const char *srcfile, int line)
422 {
423     gmx_bool ret;
424     gmx_fio_lock(fio);
425     ret = do_xdr(fio, item, 1, eioINT, desc, srcfile, line);
426     gmx_fio_unlock(fio);
427     return ret;
428 }
429
430 gmx_bool gmx_fio_doe_int64(t_fileio *fio, gmx_int64_t *item,
431                            const char *desc, const char *srcfile, int line)
432 {
433     gmx_bool ret;
434     gmx_fio_lock(fio);
435     ret = do_xdr(fio, item, 1, eioINT64, desc, srcfile, line);
436     gmx_fio_unlock(fio);
437     return ret;
438 }
439
440 gmx_bool gmx_fio_doe_uchar(t_fileio *fio, unsigned char *item,
441                            const char *desc, const char *srcfile, int line)
442 {
443     gmx_bool ret;
444     gmx_fio_lock(fio);
445     ret = do_xdr(fio, item, 1, eioUCHAR, desc, srcfile, line);
446     gmx_fio_unlock(fio);
447     return ret;
448 }
449
450 gmx_bool gmx_fio_doe_ushort(t_fileio *fio, unsigned short *item,
451                             const char *desc, const char *srcfile, int line)
452 {
453     gmx_bool ret;
454     gmx_fio_lock(fio);
455     ret = do_xdr(fio, item, 1, eioUSHORT, desc, srcfile, line);
456     gmx_fio_unlock(fio);
457     return ret;
458 }
459
460 gmx_bool gmx_fio_doe_rvec(t_fileio *fio, rvec *item,
461                           const char *desc, const char *srcfile, int line)
462 {
463     gmx_bool ret;
464     gmx_fio_lock(fio);
465     ret = do_xdr(fio, item, 1, eioRVEC, desc, srcfile, line);
466     gmx_fio_unlock(fio);
467     return ret;
468 }
469
470 gmx_bool gmx_fio_doe_ivec(t_fileio *fio, ivec *item,
471                           const char *desc, const char *srcfile, int line)
472 {
473     gmx_bool ret;
474     gmx_fio_lock(fio);
475     ret = do_xdr(fio, item, 1, eioIVEC, desc, srcfile, line);
476     gmx_fio_unlock(fio);
477     return ret;
478 }
479
480 gmx_bool gmx_fio_doe_string(t_fileio *fio, char *item,
481                             const char *desc, const char *srcfile, int line)
482 {
483     gmx_bool ret;
484     gmx_fio_lock(fio);
485     ret = do_xdr(fio, item, 1, eioSTRING, desc, srcfile, line);
486     gmx_fio_unlock(fio);
487     return ret;
488 }
489
490
491 /* Array reading & writing */
492
493 gmx_bool gmx_fio_ndoe_real(t_fileio *fio, real *item, int n,
494                            const char *desc, const char *srcfile, int line)
495 {
496     gmx_bool ret = TRUE;
497     int      i;
498     gmx_fio_lock(fio);
499     for (i = 0; i < n; i++)
500     {
501         ret = ret && do_xdr(fio, &(item[i]), 1, eioREAL, desc,
502                             srcfile, line);
503     }
504     gmx_fio_unlock(fio);
505     return ret;
506 }
507
508
509
510 gmx_bool gmx_fio_ndoe_float(t_fileio *fio, float *item, int n,
511                             const char *desc, const char *srcfile, int line)
512 {
513     gmx_bool ret = TRUE;
514     int      i;
515     gmx_fio_lock(fio);
516     for (i = 0; i < n; i++)
517     {
518         ret = ret && do_xdr(fio, &(item[i]), 1, eioFLOAT, desc,
519                             srcfile, line);
520     }
521     gmx_fio_unlock(fio);
522     return ret;
523 }
524
525
526
527 gmx_bool gmx_fio_ndoe_double(t_fileio *fio, double *item, int n,
528                              const char *desc, const char *srcfile, int line)
529 {
530     gmx_bool ret = TRUE;
531     int      i;
532     gmx_fio_lock(fio);
533     for (i = 0; i < n; i++)
534     {
535         ret = ret && do_xdr(fio, &(item[i]), 1, eioDOUBLE, desc,
536                             srcfile, line);
537     }
538     gmx_fio_unlock(fio);
539     return ret;
540 }
541
542
543
544 gmx_bool gmx_fio_ndoe_gmx_bool(t_fileio *fio, gmx_bool *item, int n,
545                                const char *desc, const char *srcfile, int line)
546 {
547     gmx_bool ret = TRUE;
548     int      i;
549
550     gmx_fio_lock(fio);
551     for (i = 0; i < n; i++)
552     {
553         if (fio->bRead)
554         {
555             int itmp = 0;
556             ret      = ret && do_xdr(fio, &itmp, 1, eioINT, desc, srcfile, line);
557             item[i]  = itmp;
558         }
559         else
560         {
561             int itmp = item[i];
562             ret      = ret && do_xdr(fio, &itmp, 1, eioINT, desc, srcfile, line);
563         }
564     }
565     gmx_fio_unlock(fio);
566     return ret;
567 }
568
569 gmx_bool gmx_fio_ndoe_int(t_fileio *fio, int *item, int n,
570                           const char *desc, const char *srcfile, int line)
571 {
572     gmx_bool ret = TRUE;
573     int      i;
574     gmx_fio_lock(fio);
575     for (i = 0; i < n; i++)
576     {
577         ret = ret && do_xdr(fio, &(item[i]), 1, eioINT, desc,
578                             srcfile, line);
579     }
580     gmx_fio_unlock(fio);
581     return ret;
582 }
583
584
585
586 gmx_bool gmx_fio_ndoe_int64(t_fileio *fio, gmx_int64_t *item, int n,
587                             const char *desc, const char *srcfile, int line)
588 {
589     gmx_bool ret = TRUE;
590     int      i;
591     gmx_fio_lock(fio);
592     for (i = 0; i < n; i++)
593     {
594         ret = ret && do_xdr(fio, &(item[i]), 1, eioINT64, desc,
595                             srcfile, line);
596     }
597     gmx_fio_unlock(fio);
598     return ret;
599 }
600
601
602
603 gmx_bool gmx_fio_ndoe_uchar(t_fileio *fio, unsigned char *item, int n,
604                             const char *desc, const char *srcfile, int line)
605 {
606     gmx_bool ret = TRUE;
607     gmx_fio_lock(fio);
608     ret = ret && do_xdr(fio, item, n, eioNUCHAR, desc,
609                         srcfile, line);
610     gmx_fio_unlock(fio);
611     return ret;
612 }
613
614
615
616 gmx_bool gmx_fio_ndoe_ushort(t_fileio *fio, unsigned short *item, int n,
617                              const char *desc, const char *srcfile, int line)
618 {
619     gmx_bool ret = TRUE;
620     int      i;
621     gmx_fio_lock(fio);
622     for (i = 0; i < n; i++)
623     {
624         ret = ret && do_xdr(fio, &(item[i]), 1, eioUSHORT, desc,
625                             srcfile, line);
626     }
627     gmx_fio_unlock(fio);
628     return ret;
629 }
630
631
632
633 gmx_bool gmx_fio_ndoe_rvec(t_fileio *fio, rvec *item, int n,
634                            const char *desc, const char *srcfile, int line)
635 {
636     gmx_bool ret = TRUE;
637     gmx_fio_lock(fio);
638     ret = ret && do_xdr(fio, item, n, eioNRVEC, desc, srcfile, line);
639     gmx_fio_unlock(fio);
640     return ret;
641 }
642
643
644
645 gmx_bool gmx_fio_ndoe_ivec(t_fileio *fio, ivec *item, int n,
646                            const char *desc, const char *srcfile, int line)
647 {
648     gmx_bool ret = TRUE;
649     int      i;
650     gmx_fio_lock(fio);
651     for (i = 0; i < n; i++)
652     {
653         ret = ret && do_xdr(fio, &(item[i]), 1, eioIVEC, desc,
654                             srcfile, line);
655     }
656     gmx_fio_unlock(fio);
657     return ret;
658 }
659
660
661
662 gmx_bool gmx_fio_ndoe_string(t_fileio *fio, char *item[], int n,
663                              const char *desc, const char *srcfile, int line)
664 {
665     gmx_bool ret = TRUE;
666     int      i;
667     gmx_fio_lock(fio);
668     for (i = 0; i < n; i++)
669     {
670         ret = ret && do_xdr(fio, &(item[i]), 1, eioSTRING, desc,
671                             srcfile, line);
672     }
673     gmx_fio_unlock(fio);
674     return ret;
675 }