SYCL: Avoid using no_init read accessor in rocFFT
[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,2016,2017 by the GROMACS development team.
7  * Copyright (c) 2018,2019,2020,2021, by the GROMACS development team, led by
8  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
9  * and including many others, as listed in the AUTHORS file in the
10  * top-level source directory and at http://www.gromacs.org.
11  *
12  * GROMACS is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * as published by the Free Software Foundation; either version 2.1
15  * of the License, or (at your option) any later version.
16  *
17  * GROMACS is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with GROMACS; if not, see
24  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
26  *
27  * If you want to redistribute modifications to GROMACS, please
28  * consider that scientific software is very special. Version
29  * control is crucial - bugs must be traceable. We will be happy to
30  * consider code for inclusion in the official distribution, but
31  * derived work must not be called official GROMACS. Details are found
32  * in the README & COPYING files - if they are missing, get the
33  * official version at http://www.gromacs.org.
34  *
35  * To help us fund GROMACS development, we humbly ask that you cite
36  * the research papers on the package. Check out http://www.gromacs.org.
37  */
38 #include "gmxpre.h"
39
40 #include "gmxfio_xdr.h"
41
42 #include <cstddef>
43 #include <cstdio>
44 #include <cstring>
45
46 #include <limits>
47
48 #include "gromacs/fileio/gmxfio.h"
49 #include "gromacs/fileio/xdrf.h"
50 #include "gromacs/utility/enumerationhelpers.h"
51 #include "gromacs/utility/fatalerror.h"
52 #include "gromacs/utility/gmxassert.h"
53 #include "gromacs/utility/smalloc.h"
54
55 #include "gmxfio_impl.h"
56
57 /* Enumerated for data types in files */
58 enum class InputOutputType : int
59 {
60     Real,
61     Float,
62     Double,
63     Int,
64     Int32,
65     Int64,
66     UnsignedChar,
67     Char,
68     CharArray,
69     UnsignedCharArray,
70     UnsignedShort,
71     RVec,
72     RVecArray,
73     IVec,
74     String,
75     Opaque,
76     Count
77 };
78
79 static const char* enumValueToString(InputOutputType enumValue)
80 {
81     constexpr gmx::EnumerationArray<InputOutputType, const char*> ioTypeNames = {
82         "REAL",  "FLOAT",  "DOUBLE", "INT",  "INT32", "INT64", "UCHAR",  "CHAR",
83         "NCHAR", "NUCHAR", "USHORT", "RVEC", "NRVEC", "IVEC",  "STRING", "OPAQUE"
84     };
85     return ioTypeNames[enumValue];
86 }
87
88 void gmx_fio_setprecision(t_fileio* fio, gmx_bool bDouble)
89 {
90     gmx_fio_lock(fio);
91     fio->bDouble = bDouble;
92     gmx_fio_unlock(fio);
93 }
94
95 bool gmx_fio_is_double(t_fileio* fio)
96 {
97     bool isDouble = false;
98     gmx_fio_lock(fio);
99     isDouble = fio->bDouble;
100     gmx_fio_unlock(fio);
101     return isDouble;
102 }
103
104 XDR* gmx_fio_getxdr(t_fileio* fio)
105 {
106     XDR* ret = nullptr;
107     gmx_fio_lock(fio);
108     GMX_RELEASE_ASSERT(fio->xdr != nullptr, "Implementation error: NULL XDR pointers");
109     ret = fio->xdr;
110     gmx_fio_unlock(fio);
111     return ret;
112 }
113
114 /* check the number of items given against the type */
115 static void gmx_fio_check_nitem(InputOutputType eio, std::size_t nitem, const char* file, int line)
116 {
117     if ((nitem != 1)
118         && !((eio == InputOutputType::RVecArray) || (eio == InputOutputType::UnsignedCharArray)
119              || (eio == InputOutputType::CharArray) || (eio == InputOutputType::Opaque)))
120     {
121         gmx_fatal(FARGS,
122                   "nitem may differ from 1 only for %s, %s, %s or %s, not for %s"
123                   "(%s, %d)",
124                   enumValueToString(InputOutputType::UnsignedCharArray),
125                   enumValueToString(InputOutputType::RVecArray),
126                   enumValueToString(InputOutputType::CharArray),
127                   enumValueToString(InputOutputType::Opaque),
128                   enumValueToString(eio),
129                   file,
130                   line);
131     }
132 }
133
134 /* output a data type error. */
135 [[noreturn]] static void
136 gmx_fio_fe(t_fileio* fio, InputOutputType eio, const char* desc, const char* srcfile, int line)
137 {
138     gmx_fatal(FARGS,
139               "Trying to %s %s type %d (%s), src %s, line %d",
140               fio->bRead ? "read" : "write",
141               desc,
142               static_cast<int>(eio),
143               ((eio >= InputOutputType::Real) && (eio < InputOutputType::Count)) ? enumValueToString(eio)
144                                                                                  : "unknown",
145               srcfile,
146               line);
147 }
148
149 /* This is the part that reads xdr files.  */
150 static gmx_bool do_xdr(t_fileio*       fio,
151                        void*           item,
152                        std::size_t     nitem,
153                        InputOutputType eio,
154                        const char*     desc,
155                        const char*     srcfile,
156                        int             line)
157 {
158     unsigned char  ucdum, *ucptr;
159     char           cdum, *cptr;
160     bool_t         res = 0;
161     float          fvec[DIM];
162     double         dvec[DIM];
163     int            m, *iptr, idum;
164     int32_t        s32dum;
165     int64_t        s64dum;
166     real*          ptr;
167     unsigned short us;
168     double         d = 0;
169     float          f = 0;
170
171     GMX_RELEASE_ASSERT(fio->xdr != nullptr, "Implementation error: NULL XDR pointers");
172     gmx_fio_check_nitem(eio, nitem, srcfile, line);
173     switch (eio)
174     {
175         case InputOutputType::Real:
176             if (fio->bDouble)
177             {
178                 if (item && !fio->bRead)
179                 {
180                     d = *(static_cast<real*>(item));
181                 }
182                 res = xdr_double(fio->xdr, &d);
183                 if (item)
184                 {
185                     *(static_cast<real*>(item)) = d;
186                 }
187             }
188             else
189             {
190                 if (item && !fio->bRead)
191                 {
192                     f = *(static_cast<real*>(item));
193                 }
194                 res = xdr_float(fio->xdr, &f);
195                 if (item)
196                 {
197                     *(static_cast<real*>(item)) = f;
198                 }
199             }
200             break;
201         case InputOutputType::Float:
202             if (item && !fio->bRead)
203             {
204                 f = *(static_cast<float*>(item));
205             }
206             res = xdr_float(fio->xdr, &f);
207             if (item)
208             {
209                 *(static_cast<float*>(item)) = f;
210             }
211             break;
212         case InputOutputType::Double:
213             if (item && !fio->bRead)
214             {
215                 d = *(static_cast<double*>(item));
216             }
217             res = xdr_double(fio->xdr, &d);
218             if (item)
219             {
220                 *(static_cast<double*>(item)) = d;
221             }
222             break;
223         case InputOutputType::Int:
224             if (item && !fio->bRead)
225             {
226                 idum = *static_cast<int*>(item);
227             }
228             res = xdr_int(fio->xdr, &idum);
229             if (item)
230             {
231                 *static_cast<int*>(item) = idum;
232             }
233             break;
234         case InputOutputType::Int32:
235             if (item && !fio->bRead)
236             {
237                 s32dum = *static_cast<int32_t*>(item);
238             }
239             res = xdr_int32(fio->xdr, &s32dum);
240             if (item)
241             {
242                 *static_cast<int32_t*>(item) = s32dum;
243             }
244             break;
245         case InputOutputType::Int64:
246             if (item && !fio->bRead)
247             {
248                 s64dum = *static_cast<int64_t*>(item);
249             }
250             res = xdr_int64(fio->xdr, &s64dum);
251             if (item)
252             {
253                 *static_cast<int64_t*>(item) = s64dum;
254             }
255             break;
256         case InputOutputType::UnsignedChar:
257             if (item && !fio->bRead)
258             {
259                 ucdum = *static_cast<unsigned char*>(item);
260             }
261             res = xdr_u_char(fio->xdr, &ucdum);
262             if (item)
263             {
264                 *static_cast<unsigned char*>(item) = ucdum;
265             }
266             break;
267         case InputOutputType::Char:
268             if (item && !fio->bRead)
269             {
270                 cdum = *static_cast<char*>(item);
271             }
272             res = xdr_char(fio->xdr, &cdum);
273             if (item)
274             {
275                 *static_cast<char*>(item) = cdum;
276             }
277             break;
278         case InputOutputType::CharArray:
279             cptr = static_cast<char*>(item);
280             GMX_RELEASE_ASSERT(nitem < static_cast<std::size_t>(std::numeric_limits<int>::max()),
281                                "The XDR interface cannot handle array lengths > 2^31");
282             res = xdr_vector(fio->xdr,
283                              cptr,
284                              static_cast<int>(nitem),
285                              static_cast<unsigned int>(sizeof(char)),
286                              reinterpret_cast<xdrproc_t>(xdr_char));
287             break;
288         case InputOutputType::UnsignedCharArray:
289             ucptr = static_cast<unsigned char*>(item);
290             GMX_RELEASE_ASSERT(nitem < static_cast<std::size_t>(std::numeric_limits<int>::max()),
291                                "The XDR interface cannot handle array lengths > 2^31");
292             res = xdr_vector(fio->xdr,
293                              reinterpret_cast<char*>(ucptr),
294                              static_cast<int>(nitem),
295                              static_cast<unsigned int>(sizeof(unsigned char)),
296                              reinterpret_cast<xdrproc_t>(xdr_u_char));
297             break;
298         case InputOutputType::UnsignedShort:
299             if (item && !fio->bRead)
300             {
301                 us = *static_cast<unsigned short*>(item);
302             }
303             res = xdr_u_short(fio->xdr, &us);
304             if (item)
305             {
306                 *static_cast<unsigned short*>(item) = us;
307             }
308             break;
309         case InputOutputType::RVec:
310             if (fio->bDouble)
311             {
312                 if (item && !fio->bRead)
313                 {
314                     for (m = 0; (m < DIM); m++)
315                     {
316                         dvec[m] = (static_cast<real*>(item))[m];
317                     }
318                 }
319                 res = xdr_vector(fio->xdr,
320                                  reinterpret_cast<char*>(dvec),
321                                  DIM,
322                                  static_cast<unsigned int>(sizeof(double)),
323                                  reinterpret_cast<xdrproc_t>(xdr_double));
324                 if (item)
325                 {
326                     for (m = 0; (m < DIM); m++)
327                     {
328                         (static_cast<real*>(item))[m] = dvec[m];
329                     }
330                 }
331             }
332             else
333             {
334                 if (item && !fio->bRead)
335                 {
336                     for (m = 0; (m < DIM); m++)
337                     {
338                         fvec[m] = (static_cast<real*>(item))[m];
339                     }
340                 }
341                 res = xdr_vector(fio->xdr,
342                                  reinterpret_cast<char*>(fvec),
343                                  DIM,
344                                  static_cast<unsigned int>(sizeof(float)),
345                                  reinterpret_cast<xdrproc_t>(xdr_float));
346                 if (item)
347                 {
348                     for (m = 0; (m < DIM); m++)
349                     {
350                         (static_cast<real*>(item))[m] = fvec[m];
351                     }
352                 }
353             }
354             break;
355         case InputOutputType::RVecArray:
356             ptr = nullptr;
357             res = 1;
358             for (std::size_t j = 0; j < nitem && res; j++)
359             {
360                 if (item)
361                 {
362                     ptr = (static_cast<rvec*>(item))[j];
363                 }
364                 res = static_cast<bool_t>(do_xdr(fio, ptr, 1, InputOutputType::RVec, desc, srcfile, line));
365             }
366             break;
367         case InputOutputType::IVec:
368             iptr = static_cast<int*>(item);
369             res  = 1;
370             for (m = 0; (m < DIM) && res; m++)
371             {
372                 if (item && !fio->bRead)
373                 {
374                     idum = iptr[m];
375                 }
376                 res = xdr_int(fio->xdr, &idum);
377                 if (item)
378                 {
379                     iptr[m] = idum;
380                 }
381             }
382             break;
383         case InputOutputType::String:
384         {
385             char* cptr;
386             int   slen;
387
388             if (item)
389             {
390                 if (!fio->bRead)
391                 {
392                     slen = strlen(static_cast<char*>(item)) + 1;
393                 }
394                 else
395                 {
396                     slen = 0;
397                 }
398             }
399             else
400             {
401                 slen = 0;
402             }
403
404             if (xdr_int(fio->xdr, &slen) <= 0)
405             {
406                 gmx_fatal(FARGS,
407                           "wrong string length %d for string %s"
408                           " (source %s, line %d)",
409                           slen,
410                           desc,
411                           srcfile,
412                           line);
413             }
414             if (!item && fio->bRead)
415             {
416                 snew(cptr, slen);
417             }
418             else
419             {
420                 cptr = static_cast<char*>(item);
421             }
422             if (cptr)
423             {
424                 res = xdr_string(fio->xdr, &cptr, slen);
425             }
426             else
427             {
428                 res = 1;
429             }
430             if (!item && fio->bRead)
431             {
432                 sfree(cptr);
433             }
434             break;
435         }
436         case InputOutputType::Opaque:
437         {
438             if (item == nullptr && nitem > 0)
439             {
440                 gmx_fatal(FARGS, "Null pointer provided for non-zero length XDR opaque data.");
441             }
442
443             if (nitem > 0)
444             {
445                 // We need to support very large opaque data objects although the default
446                 // XDR interface only uses integers for the size field, since gromacs-2020
447                 // e.g. embeds the entire TPR body as a single such object, which would break all
448                 // TPR files larger than 2GB unless we handle it as a special case.
449                 // To avoid inserting extra padding, we calculate the chunk size as:
450                 // - The max value of a signed integer + 1
451                 // - Subtract 4 (the XDR object size) to get a size within the range of the signed int.
452                 const std::size_t maxChunk =
453                         static_cast<std::size_t>(std::numeric_limits<int>::max()) + 1 - 4;
454
455                 for (res = 1; res > 0 && nitem > 0;)
456                 {
457                     std::size_t thisChunk = std::min(maxChunk, nitem);
458                     res = xdr_opaque(fio->xdr, reinterpret_cast<char*>(item), thisChunk);
459                     nitem -= thisChunk;
460                 }
461             }
462             else
463             {
464                 res = 1;
465             }
466             break;
467         }
468         default: gmx_fio_fe(fio, eio, desc, srcfile, line);
469     }
470
471     return (res != 0);
472 }
473
474 /*******************************************************************
475  *
476  * READ/WRITE FUNCTIONS
477  *
478  *******************************************************************/
479
480 gmx_bool gmx_fio_writee_string(t_fileio* fio, const char* item, const char* desc, const char* srcfile, int line)
481 {
482     gmx_bool ret;
483     void*    it = const_cast<char*>(item); /* ugh.. */
484     gmx_fio_lock(fio);
485     ret = do_xdr(fio, it, 1, InputOutputType::String, desc, srcfile, line);
486     gmx_fio_unlock(fio);
487     return ret;
488 }
489
490 gmx_bool gmx_fio_doe_real(t_fileio* fio, real* item, const char* desc, const char* srcfile, int line)
491 {
492     gmx_bool ret;
493     gmx_fio_lock(fio);
494     ret = do_xdr(fio, item, 1, InputOutputType::Real, desc, srcfile, line);
495     gmx_fio_unlock(fio);
496     return ret;
497 }
498
499 gmx_bool gmx_fio_doe_float(t_fileio* fio, float* item, const char* desc, const char* srcfile, int line)
500 {
501     gmx_bool ret;
502     gmx_fio_lock(fio);
503     ret = do_xdr(fio, item, 1, InputOutputType::Float, desc, srcfile, line);
504     gmx_fio_unlock(fio);
505     return ret;
506 }
507
508 gmx_bool gmx_fio_doe_double(t_fileio* fio, double* item, const char* desc, const char* srcfile, int line)
509 {
510     gmx_bool ret;
511     gmx_fio_lock(fio);
512     ret = do_xdr(fio, item, 1, InputOutputType::Double, desc, srcfile, line);
513     gmx_fio_unlock(fio);
514     return ret;
515 }
516
517
518 gmx_bool gmx_fio_doe_gmx_bool(t_fileio* fio, gmx_bool* item, const char* desc, const char* srcfile, int line)
519 {
520     gmx_bool ret;
521
522     gmx_fio_lock(fio);
523     if (fio->bRead)
524     {
525         int itmp = 0;
526         ret      = do_xdr(fio, &itmp, 1, InputOutputType::Int, desc, srcfile, line);
527         *item    = (itmp != 0);
528     }
529     else
530     {
531         int itmp = static_cast<int>(*item);
532         ret      = do_xdr(fio, &itmp, 1, InputOutputType::Int, desc, srcfile, line);
533     }
534     gmx_fio_unlock(fio);
535     return ret;
536 }
537
538 gmx_bool gmx_fio_doe_int(t_fileio* fio, int* item, const char* desc, const char* srcfile, int line)
539 {
540     gmx_bool ret;
541     gmx_fio_lock(fio);
542     ret = do_xdr(fio, item, 1, InputOutputType::Int, desc, srcfile, line);
543     gmx_fio_unlock(fio);
544     return ret;
545 }
546
547 gmx_bool gmx_fio_doe_int32(t_fileio* fio, int32_t* item, const char* desc, const char* srcfile, int line)
548 {
549     gmx_bool ret;
550     gmx_fio_lock(fio);
551     ret = do_xdr(fio, item, 1, InputOutputType::Int32, desc, srcfile, line);
552     gmx_fio_unlock(fio);
553     return ret;
554 }
555
556 gmx_bool gmx_fio_doe_int64(t_fileio* fio, int64_t* item, const char* desc, const char* srcfile, int line)
557 {
558     gmx_bool ret;
559     gmx_fio_lock(fio);
560     ret = do_xdr(fio, item, 1, InputOutputType::Int64, desc, srcfile, line);
561     gmx_fio_unlock(fio);
562     return ret;
563 }
564
565 gmx_bool gmx_fio_doe_uchar(t_fileio* fio, unsigned char* item, const char* desc, const char* srcfile, int line)
566 {
567     gmx_bool ret;
568     gmx_fio_lock(fio);
569     ret = do_xdr(fio, item, 1, InputOutputType::UnsignedChar, desc, srcfile, line);
570     gmx_fio_unlock(fio);
571     return ret;
572 }
573
574 gmx_bool gmx_fio_doe_char(t_fileio* fio, char* item, const char* desc, const char* srcfile, int line)
575 {
576     gmx_bool ret;
577     gmx_fio_lock(fio);
578     ret = do_xdr(fio, item, 1, InputOutputType::Char, desc, srcfile, line);
579     gmx_fio_unlock(fio);
580     return ret;
581 }
582
583 gmx_bool gmx_fio_doe_ushort(t_fileio* fio, unsigned short* item, const char* desc, const char* srcfile, int line)
584 {
585     gmx_bool ret;
586     gmx_fio_lock(fio);
587     ret = do_xdr(fio, item, 1, InputOutputType::UnsignedShort, desc, srcfile, line);
588     gmx_fio_unlock(fio);
589     return ret;
590 }
591
592 gmx_bool gmx_fio_doe_rvec(t_fileio* fio, rvec* item, const char* desc, const char* srcfile, int line)
593 {
594     gmx_bool ret;
595     gmx_fio_lock(fio);
596     ret = do_xdr(fio, item, 1, InputOutputType::RVec, desc, srcfile, line);
597     gmx_fio_unlock(fio);
598     return ret;
599 }
600
601 gmx_bool gmx_fio_doe_ivec(t_fileio* fio, ivec* item, const char* desc, const char* srcfile, int line)
602 {
603     gmx_bool ret;
604     gmx_fio_lock(fio);
605     ret = do_xdr(fio, item, 1, InputOutputType::IVec, desc, srcfile, line);
606     gmx_fio_unlock(fio);
607     return ret;
608 }
609
610 gmx_bool gmx_fio_doe_string(t_fileio* fio, char* item, const char* desc, const char* srcfile, int line)
611 {
612     gmx_bool ret;
613     gmx_fio_lock(fio);
614     ret = do_xdr(fio, item, 1, InputOutputType::String, desc, srcfile, line);
615     gmx_fio_unlock(fio);
616     return ret;
617 }
618
619 gmx_bool gmx_fio_doe_opaque(t_fileio* fio, char* data, std::size_t size, const char* desc, const char* srcfile, int line)
620 {
621     gmx_bool ret;
622     gmx_fio_lock(fio);
623     ret = do_xdr(fio, data, size, InputOutputType::Opaque, desc, srcfile, line);
624     gmx_fio_unlock(fio);
625     return ret;
626 }
627
628 /* Array reading & writing */
629
630 gmx_bool gmx_fio_ndoe_real(t_fileio* fio, real* item, int n, const char* desc, const char* srcfile, int line)
631 {
632     gmx_bool ret = TRUE;
633     int      i;
634     gmx_fio_lock(fio);
635     for (i = 0; i < n; i++)
636     {
637         ret = ret && do_xdr(fio, &(item[i]), 1, InputOutputType::Real, desc, srcfile, line);
638     }
639     gmx_fio_unlock(fio);
640     return ret;
641 }
642
643
644 gmx_bool gmx_fio_ndoe_float(t_fileio* fio, float* item, int n, const char* desc, const char* srcfile, int line)
645 {
646     gmx_bool ret = TRUE;
647     int      i;
648     gmx_fio_lock(fio);
649     for (i = 0; i < n; i++)
650     {
651         ret = ret && do_xdr(fio, &(item[i]), 1, InputOutputType::Float, desc, srcfile, line);
652     }
653     gmx_fio_unlock(fio);
654     return ret;
655 }
656
657
658 gmx_bool gmx_fio_ndoe_double(t_fileio* fio, double* item, int n, const char* desc, const char* srcfile, int line)
659 {
660     gmx_bool ret = TRUE;
661     int      i;
662     gmx_fio_lock(fio);
663     for (i = 0; i < n; i++)
664     {
665         ret = ret && do_xdr(fio, &(item[i]), 1, InputOutputType::Double, desc, srcfile, line);
666     }
667     gmx_fio_unlock(fio);
668     return ret;
669 }
670
671
672 gmx_bool gmx_fio_ndoe_gmx_bool(t_fileio* fio, gmx_bool* item, int n, const char* desc, const char* srcfile, int line)
673 {
674     gmx_bool ret = TRUE;
675     int      i;
676
677     gmx_fio_lock(fio);
678     for (i = 0; i < n; i++)
679     {
680         if (fio->bRead)
681         {
682             int itmp = 0;
683             ret      = ret && do_xdr(fio, &itmp, 1, InputOutputType::Int, desc, srcfile, line);
684             item[i]  = (itmp != 0);
685         }
686         else
687         {
688             int itmp = static_cast<int>(item[i]);
689             ret      = ret && do_xdr(fio, &itmp, 1, InputOutputType::Int, desc, srcfile, line);
690         }
691     }
692     gmx_fio_unlock(fio);
693     return ret;
694 }
695
696 gmx_bool gmx_fio_ndoe_int(t_fileio* fio, int* item, int n, const char* desc, const char* srcfile, int line)
697 {
698     gmx_bool ret = TRUE;
699     int      i;
700     gmx_fio_lock(fio);
701     for (i = 0; i < n; i++)
702     {
703         ret = ret && do_xdr(fio, &(item[i]), 1, InputOutputType::Int, desc, srcfile, line);
704     }
705     gmx_fio_unlock(fio);
706     return ret;
707 }
708
709
710 gmx_bool gmx_fio_ndoe_int64(t_fileio* fio, int64_t* item, int n, const char* desc, const char* srcfile, int line)
711 {
712     gmx_bool ret = TRUE;
713     int      i;
714     gmx_fio_lock(fio);
715     for (i = 0; i < n; i++)
716     {
717         ret = ret && do_xdr(fio, &(item[i]), 1, InputOutputType::Int64, desc, srcfile, line);
718     }
719     gmx_fio_unlock(fio);
720     return ret;
721 }
722
723
724 gmx_bool gmx_fio_ndoe_uchar(t_fileio* fio, unsigned char* item, int n, const char* desc, const char* srcfile, int line)
725 {
726     gmx_bool ret = TRUE;
727     gmx_fio_lock(fio);
728     ret = ret && do_xdr(fio, item, n, InputOutputType::UnsignedCharArray, desc, srcfile, line);
729     gmx_fio_unlock(fio);
730     return ret;
731 }
732
733 gmx_bool gmx_fio_ndoe_char(t_fileio* fio, char* item, int n, const char* desc, const char* srcfile, int line)
734 {
735     gmx_bool ret = TRUE;
736     gmx_fio_lock(fio);
737     ret = ret && do_xdr(fio, item, n, InputOutputType::CharArray, desc, srcfile, line);
738     gmx_fio_unlock(fio);
739     return ret;
740 }
741
742
743 gmx_bool gmx_fio_ndoe_ushort(t_fileio* fio, unsigned short* item, int n, const char* desc, const char* srcfile, int line)
744 {
745     gmx_bool ret = TRUE;
746     int      i;
747     gmx_fio_lock(fio);
748     for (i = 0; i < n; i++)
749     {
750         ret = ret && do_xdr(fio, &(item[i]), 1, InputOutputType::UnsignedShort, desc, srcfile, line);
751     }
752     gmx_fio_unlock(fio);
753     return ret;
754 }
755
756
757 gmx_bool gmx_fio_ndoe_rvec(t_fileio* fio, rvec* item, int n, const char* desc, const char* srcfile, int line)
758 {
759     gmx_bool ret = TRUE;
760     gmx_fio_lock(fio);
761     ret = ret && do_xdr(fio, item, n, InputOutputType::RVecArray, desc, srcfile, line);
762     gmx_fio_unlock(fio);
763     return ret;
764 }
765
766
767 gmx_bool gmx_fio_ndoe_ivec(t_fileio* fio, ivec* item, int n, const char* desc, const char* srcfile, int line)
768 {
769     gmx_bool ret = TRUE;
770     int      i;
771     gmx_fio_lock(fio);
772     for (i = 0; i < n; i++)
773     {
774         ret = ret && do_xdr(fio, &(item[i]), 1, InputOutputType::IVec, desc, srcfile, line);
775     }
776     gmx_fio_unlock(fio);
777     return ret;
778 }
779
780
781 gmx_bool gmx_fio_ndoe_string(t_fileio* fio, char* item[], int n, const char* desc, const char* srcfile, int line)
782 {
783     gmx_bool ret = TRUE;
784     int      i;
785     gmx_fio_lock(fio);
786     for (i = 0; i < n; i++)
787     {
788         ret = ret && do_xdr(fio, &(item[i]), 1, InputOutputType::String, desc, srcfile, line);
789     }
790     gmx_fio_unlock(fio);
791     return ret;
792 }
793
794 namespace gmx
795 {
796
797 FileIOXdrSerializer::FileIOXdrSerializer(t_fileio* fio) : fio_(fio)
798 {
799     GMX_RELEASE_ASSERT(fio, "Need valid file io handle");
800 }
801
802 bool FileIOXdrSerializer::reading() const
803 {
804     return fio_->bRead;
805 }
806
807 void FileIOXdrSerializer::doBool(bool* value)
808 {
809     gmx_fio_do_gmx_bool(fio_, *value);
810 }
811
812 void FileIOXdrSerializer::doUChar(unsigned char* value)
813 {
814     gmx_fio_do_uchar(fio_, *value);
815 }
816
817 void FileIOXdrSerializer::doChar(char* value)
818 {
819     gmx_fio_do_char(fio_, *value);
820 }
821
822 void FileIOXdrSerializer::doUShort(unsigned short* value)
823 {
824     gmx_fio_do_ushort(fio_, *value);
825 }
826
827 void FileIOXdrSerializer::doInt(int* value)
828 {
829     gmx_fio_do_int(fio_, *value);
830 }
831
832 void FileIOXdrSerializer::doInt32(int32_t* value)
833 {
834     gmx_fio_do_int32(fio_, *value);
835 }
836
837 void FileIOXdrSerializer::doInt64(int64_t* value)
838 {
839     gmx_fio_do_int64(fio_, *value);
840 }
841
842 void FileIOXdrSerializer::doFloat(float* value)
843 {
844     gmx_fio_do_float(fio_, *value);
845 }
846
847 void FileIOXdrSerializer::doDouble(double* value)
848 {
849     gmx_fio_do_double(fio_, *value);
850 }
851
852 void FileIOXdrSerializer::doReal(real* value)
853 {
854     gmx_fio_do_real(fio_, *value);
855 }
856
857 void FileIOXdrSerializer::doIvec(ivec* value)
858 {
859     gmx_fio_do_ivec(fio_, *value);
860 }
861
862 void FileIOXdrSerializer::doRvec(rvec* value)
863 {
864     gmx_fio_do_rvec(fio_, *value);
865 }
866
867 void FileIOXdrSerializer::doCharArray(char* values, int elements)
868 {
869     gmx_fio_ndo_char(fio_, values, elements);
870 }
871
872 void FileIOXdrSerializer::doUCharArray(unsigned char* values, int elements)
873 {
874     gmx_fio_ndo_uchar(fio_, values, elements);
875 }
876
877 void FileIOXdrSerializer::doRvecArray(rvec* values, int elements)
878 {
879     gmx_fio_ndo_rvec(fio_, values, elements);
880 }
881
882 void FileIOXdrSerializer::doString(std::string* value)
883 {
884     // TODO: Use an arbitrary length buffer (but that is not supported in
885     // gmx_fio, either).
886     char buf[STRLEN];
887     if (!fio_->bRead)
888     {
889         std::strncpy(buf, value->c_str(), STRLEN);
890         buf[STRLEN - 1] = 0;
891     }
892     gmx_fio_do_string(fio_, buf);
893     if (fio_->bRead)
894     {
895         *value = buf;
896     }
897 }
898
899 void FileIOXdrSerializer::doOpaque(char* data, std::size_t size)
900 {
901     gmx_fio_do_opaque(fio_, data, size);
902 }
903
904 } // namespace gmx