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