2 * This file is part of the GROMACS molecular simulation package.
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,2018,2019,2020, 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.
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.
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.
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.
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.
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.
39 #include "gmxfio_xdr.h"
47 #include "gromacs/fileio/gmxfio.h"
48 #include "gromacs/fileio/xdrf.h"
49 #include "gromacs/utility/fatalerror.h"
50 #include "gromacs/utility/gmxassert.h"
51 #include "gromacs/utility/smalloc.h"
53 #include "gmxfio_impl.h"
55 /* Enumerated for data types in files */
77 static const char* eioNames[eioNR] = { "REAL", "FLOAT", "DOUBLE", "INT", "INT32", "INT64",
78 "UCHAR", "CHAR", "NCHAR", "NUCHAR", "USHORT", "RVEC",
79 "NRVEC", "IVEC", "STRING", "OPAQUE" };
81 void gmx_fio_setprecision(t_fileio* fio, gmx_bool bDouble)
84 fio->bDouble = bDouble;
88 bool gmx_fio_is_double(t_fileio* fio)
90 bool isDouble = false;
92 isDouble = fio->bDouble;
97 XDR* gmx_fio_getxdr(t_fileio* fio)
101 GMX_RELEASE_ASSERT(fio->xdr != nullptr, "Implementation error: NULL XDR pointers");
107 /* check the number of items given against the type */
108 static void gmx_fio_check_nitem(int eio, std::size_t nitem, const char* file, int line)
111 && !((eio == eioNRVEC) || (eio == eioNUCHAR) || (eio == eioNCHAR) || (eio == eioOPAQUE)))
114 "nitem may differ from 1 only for %s, %s, %s or %s, not for %s"
116 eioNames[eioNUCHAR], eioNames[eioNRVEC], eioNames[eioNCHAR], eioNames[eioOPAQUE],
117 eioNames[eio], file, line);
121 /* output a data type error. */
122 [[noreturn]] static void gmx_fio_fe(t_fileio* fio, int eio, const char* desc, const char* srcfile, int line)
124 gmx_fatal(FARGS, "Trying to %s %s type %d (%s), src %s, line %d", fio->bRead ? "read" : "write",
125 desc, eio, ((eio >= 0) && (eio < eioNR)) ? eioNames[eio] : "unknown", srcfile, line);
128 /* This is the part that reads xdr files. */
131 do_xdr(t_fileio* fio, void* item, std::size_t nitem, int eio, const char* desc, const char* srcfile, int line)
133 unsigned char ucdum, *ucptr;
146 GMX_RELEASE_ASSERT(fio->xdr != nullptr, "Implementation error: NULL XDR pointers");
147 gmx_fio_check_nitem(eio, nitem, srcfile, line);
153 if (item && !fio->bRead)
155 d = *(static_cast<real*>(item));
157 res = xdr_double(fio->xdr, &d);
160 *(static_cast<real*>(item)) = d;
165 if (item && !fio->bRead)
167 f = *(static_cast<real*>(item));
169 res = xdr_float(fio->xdr, &f);
172 *(static_cast<real*>(item)) = f;
177 if (item && !fio->bRead)
179 f = *(static_cast<float*>(item));
181 res = xdr_float(fio->xdr, &f);
184 *(static_cast<float*>(item)) = f;
188 if (item && !fio->bRead)
190 d = *(static_cast<double*>(item));
192 res = xdr_double(fio->xdr, &d);
195 *(static_cast<double*>(item)) = d;
199 if (item && !fio->bRead)
201 idum = *static_cast<int*>(item);
203 res = xdr_int(fio->xdr, &idum);
206 *static_cast<int*>(item) = idum;
210 if (item && !fio->bRead)
212 s32dum = *static_cast<int32_t*>(item);
214 res = xdr_int32(fio->xdr, &s32dum);
217 *static_cast<int32_t*>(item) = s32dum;
221 if (item && !fio->bRead)
223 s64dum = *static_cast<int64_t*>(item);
225 res = xdr_int64(fio->xdr, &s64dum);
228 *static_cast<int64_t*>(item) = s64dum;
232 if (item && !fio->bRead)
234 ucdum = *static_cast<unsigned char*>(item);
236 res = xdr_u_char(fio->xdr, &ucdum);
239 *static_cast<unsigned char*>(item) = ucdum;
243 if (item && !fio->bRead)
245 cdum = *static_cast<char*>(item);
247 res = xdr_char(fio->xdr, &cdum);
250 *static_cast<char*>(item) = cdum;
254 cptr = static_cast<char*>(item);
255 GMX_RELEASE_ASSERT(nitem < static_cast<std::size_t>(std::numeric_limits<int>::max()),
256 "The XDR interface cannot handle array lengths > 2^31");
257 res = xdr_vector(fio->xdr, cptr, static_cast<int>(nitem),
258 static_cast<unsigned int>(sizeof(char)),
259 reinterpret_cast<xdrproc_t>(xdr_char));
262 ucptr = static_cast<unsigned char*>(item);
263 GMX_RELEASE_ASSERT(nitem < static_cast<std::size_t>(std::numeric_limits<int>::max()),
264 "The XDR interface cannot handle array lengths > 2^31");
265 res = xdr_vector(fio->xdr, reinterpret_cast<char*>(ucptr), static_cast<int>(nitem),
266 static_cast<unsigned int>(sizeof(unsigned char)),
267 reinterpret_cast<xdrproc_t>(xdr_u_char));
270 if (item && !fio->bRead)
272 us = *static_cast<unsigned short*>(item);
274 res = xdr_u_short(fio->xdr, &us);
277 *static_cast<unsigned short*>(item) = us;
283 if (item && !fio->bRead)
285 for (m = 0; (m < DIM); m++)
287 dvec[m] = (static_cast<real*>(item))[m];
290 res = xdr_vector(fio->xdr, reinterpret_cast<char*>(dvec), DIM,
291 static_cast<unsigned int>(sizeof(double)),
292 reinterpret_cast<xdrproc_t>(xdr_double));
295 for (m = 0; (m < DIM); m++)
297 (static_cast<real*>(item))[m] = dvec[m];
303 if (item && !fio->bRead)
305 for (m = 0; (m < DIM); m++)
307 fvec[m] = (static_cast<real*>(item))[m];
310 res = xdr_vector(fio->xdr, reinterpret_cast<char*>(fvec), DIM,
311 static_cast<unsigned int>(sizeof(float)),
312 reinterpret_cast<xdrproc_t>(xdr_float));
315 for (m = 0; (m < DIM); m++)
317 (static_cast<real*>(item))[m] = fvec[m];
325 for (std::size_t j = 0; j < nitem && res; j++)
329 ptr = (static_cast<rvec*>(item))[j];
331 res = static_cast<bool_t>(do_xdr(fio, ptr, 1, eioRVEC, desc, srcfile, line));
335 iptr = static_cast<int*>(item);
337 for (m = 0; (m < DIM) && res; m++)
339 if (item && !fio->bRead)
343 res = xdr_int(fio->xdr, &idum);
359 slen = strlen(static_cast<char*>(item)) + 1;
371 if (xdr_int(fio->xdr, &slen) <= 0)
374 "wrong string length %d for string %s"
375 " (source %s, line %d)",
376 slen, desc, srcfile, line);
378 if (!item && fio->bRead)
384 cptr = static_cast<char*>(item);
388 res = xdr_string(fio->xdr, &cptr, slen);
394 if (!item && fio->bRead)
402 if (item == nullptr && nitem > 0)
404 gmx_fatal(FARGS, "Null pointer provided for non-zero length XDR opaque data.");
409 // We need to support very large opaque data objects although the default
410 // XDR interface only uses integers for the size field, since gromacs-2020
411 // e.g. embeds the entire TPR body as a single such object, which would break all
412 // TPR files larger than 2GB unless we handle it as a special case.
413 // To avoid inserting extra padding, we calculate the chunk size as:
414 // - The max value of a signed integer + 1
415 // - Subtract 4 (the XDR object size) to get a size within the range of the signed int.
416 const std::size_t maxChunk =
417 static_cast<std::size_t>(std::numeric_limits<int>::max()) + 1 - 4;
419 for (res = 1; res > 0 && nitem > 0;)
421 std::size_t thisChunk = std::min(maxChunk, nitem);
422 res = xdr_opaque(fio->xdr, reinterpret_cast<char*>(item), thisChunk);
432 default: gmx_fio_fe(fio, eio, desc, srcfile, line);
438 /*******************************************************************
440 * READ/WRITE FUNCTIONS
442 *******************************************************************/
444 gmx_bool gmx_fio_writee_string(t_fileio* fio, const char* item, const char* desc, const char* srcfile, int line)
447 void* it = const_cast<char*>(item); /* ugh.. */
449 ret = do_xdr(fio, it, 1, eioSTRING, desc, srcfile, line);
454 gmx_bool gmx_fio_doe_real(t_fileio* fio, real* item, const char* desc, const char* srcfile, int line)
458 ret = do_xdr(fio, item, 1, eioREAL, desc, srcfile, line);
463 gmx_bool gmx_fio_doe_float(t_fileio* fio, float* item, const char* desc, const char* srcfile, int line)
467 ret = do_xdr(fio, item, 1, eioFLOAT, desc, srcfile, line);
472 gmx_bool gmx_fio_doe_double(t_fileio* fio, double* item, const char* desc, const char* srcfile, int line)
476 ret = do_xdr(fio, item, 1, eioDOUBLE, desc, srcfile, line);
482 gmx_bool gmx_fio_doe_gmx_bool(t_fileio* fio, gmx_bool* item, const char* desc, const char* srcfile, int line)
490 ret = do_xdr(fio, &itmp, 1, eioINT, desc, srcfile, line);
495 int itmp = static_cast<int>(*item);
496 ret = do_xdr(fio, &itmp, 1, eioINT, desc, srcfile, line);
502 gmx_bool gmx_fio_doe_int(t_fileio* fio, int* item, const char* desc, const char* srcfile, int line)
506 ret = do_xdr(fio, item, 1, eioINT, desc, srcfile, line);
511 gmx_bool gmx_fio_doe_int32(t_fileio* fio, int32_t* item, const char* desc, const char* srcfile, int line)
515 ret = do_xdr(fio, item, 1, eioINT32, desc, srcfile, line);
520 gmx_bool gmx_fio_doe_int64(t_fileio* fio, int64_t* item, const char* desc, const char* srcfile, int line)
524 ret = do_xdr(fio, item, 1, eioINT64, desc, srcfile, line);
529 gmx_bool gmx_fio_doe_uchar(t_fileio* fio, unsigned char* item, const char* desc, const char* srcfile, int line)
533 ret = do_xdr(fio, item, 1, eioUCHAR, desc, srcfile, line);
538 gmx_bool gmx_fio_doe_char(t_fileio* fio, char* item, const char* desc, const char* srcfile, int line)
542 ret = do_xdr(fio, item, 1, eioCHAR, desc, srcfile, line);
547 gmx_bool gmx_fio_doe_ushort(t_fileio* fio, unsigned short* item, const char* desc, const char* srcfile, int line)
551 ret = do_xdr(fio, item, 1, eioUSHORT, desc, srcfile, line);
556 gmx_bool gmx_fio_doe_rvec(t_fileio* fio, rvec* item, const char* desc, const char* srcfile, int line)
560 ret = do_xdr(fio, item, 1, eioRVEC, desc, srcfile, line);
565 gmx_bool gmx_fio_doe_ivec(t_fileio* fio, ivec* item, const char* desc, const char* srcfile, int line)
569 ret = do_xdr(fio, item, 1, eioIVEC, desc, srcfile, line);
574 gmx_bool gmx_fio_doe_string(t_fileio* fio, char* item, const char* desc, const char* srcfile, int line)
578 ret = do_xdr(fio, item, 1, eioSTRING, desc, srcfile, line);
583 gmx_bool gmx_fio_doe_opaque(t_fileio* fio, char* data, std::size_t size, const char* desc, const char* srcfile, int line)
587 ret = do_xdr(fio, data, size, eioOPAQUE, desc, srcfile, line);
592 /* Array reading & writing */
594 gmx_bool gmx_fio_ndoe_real(t_fileio* fio, real* item, int n, const char* desc, const char* srcfile, int line)
599 for (i = 0; i < n; i++)
601 ret = ret && do_xdr(fio, &(item[i]), 1, eioREAL, desc, srcfile, line);
608 gmx_bool gmx_fio_ndoe_float(t_fileio* fio, float* item, int n, const char* desc, const char* srcfile, int line)
613 for (i = 0; i < n; i++)
615 ret = ret && do_xdr(fio, &(item[i]), 1, eioFLOAT, desc, srcfile, line);
622 gmx_bool gmx_fio_ndoe_double(t_fileio* fio, double* item, int n, const char* desc, const char* srcfile, int line)
627 for (i = 0; i < n; i++)
629 ret = ret && do_xdr(fio, &(item[i]), 1, eioDOUBLE, desc, srcfile, line);
636 gmx_bool gmx_fio_ndoe_gmx_bool(t_fileio* fio, gmx_bool* item, int n, const char* desc, const char* srcfile, int line)
642 for (i = 0; i < n; i++)
647 ret = ret && do_xdr(fio, &itmp, 1, eioINT, desc, srcfile, line);
648 item[i] = (itmp != 0);
652 int itmp = static_cast<int>(item[i]);
653 ret = ret && do_xdr(fio, &itmp, 1, eioINT, desc, srcfile, line);
660 gmx_bool gmx_fio_ndoe_int(t_fileio* fio, int* item, int n, const char* desc, const char* srcfile, int line)
665 for (i = 0; i < n; i++)
667 ret = ret && do_xdr(fio, &(item[i]), 1, eioINT, desc, srcfile, line);
674 gmx_bool gmx_fio_ndoe_int64(t_fileio* fio, int64_t* item, int n, const char* desc, const char* srcfile, int line)
679 for (i = 0; i < n; i++)
681 ret = ret && do_xdr(fio, &(item[i]), 1, eioINT64, desc, srcfile, line);
688 gmx_bool gmx_fio_ndoe_uchar(t_fileio* fio, unsigned char* item, int n, const char* desc, const char* srcfile, int line)
692 ret = ret && do_xdr(fio, item, n, eioNUCHAR, desc, srcfile, line);
697 gmx_bool gmx_fio_ndoe_char(t_fileio* fio, char* item, int n, const char* desc, const char* srcfile, int line)
701 ret = ret && do_xdr(fio, item, n, eioNCHAR, desc, srcfile, line);
707 gmx_bool gmx_fio_ndoe_ushort(t_fileio* fio, unsigned short* item, int n, const char* desc, const char* srcfile, int line)
712 for (i = 0; i < n; i++)
714 ret = ret && do_xdr(fio, &(item[i]), 1, eioUSHORT, desc, srcfile, line);
721 gmx_bool gmx_fio_ndoe_rvec(t_fileio* fio, rvec* item, int n, const char* desc, const char* srcfile, int line)
725 ret = ret && do_xdr(fio, item, n, eioNRVEC, desc, srcfile, line);
731 gmx_bool gmx_fio_ndoe_ivec(t_fileio* fio, ivec* item, int n, const char* desc, const char* srcfile, int line)
736 for (i = 0; i < n; i++)
738 ret = ret && do_xdr(fio, &(item[i]), 1, eioIVEC, desc, srcfile, line);
745 gmx_bool gmx_fio_ndoe_string(t_fileio* fio, char* item[], int n, const char* desc, const char* srcfile, int line)
750 for (i = 0; i < n; i++)
752 ret = ret && do_xdr(fio, &(item[i]), 1, eioSTRING, desc, srcfile, line);
761 FileIOXdrSerializer::FileIOXdrSerializer(t_fileio* fio) : fio_(fio)
763 GMX_RELEASE_ASSERT(fio, "Need valid file io handle");
766 bool FileIOXdrSerializer::reading() const
771 void FileIOXdrSerializer::doBool(bool* value)
773 gmx_fio_do_gmx_bool(fio_, *value);
776 void FileIOXdrSerializer::doUChar(unsigned char* value)
778 gmx_fio_do_uchar(fio_, *value);
781 void FileIOXdrSerializer::doChar(char* value)
783 gmx_fio_do_char(fio_, *value);
786 void FileIOXdrSerializer::doUShort(unsigned short* value)
788 gmx_fio_do_ushort(fio_, *value);
791 void FileIOXdrSerializer::doInt(int* value)
793 gmx_fio_do_int(fio_, *value);
796 void FileIOXdrSerializer::doInt32(int32_t* value)
798 gmx_fio_do_int32(fio_, *value);
801 void FileIOXdrSerializer::doInt64(int64_t* value)
803 gmx_fio_do_int64(fio_, *value);
806 void FileIOXdrSerializer::doFloat(float* value)
808 gmx_fio_do_float(fio_, *value);
811 void FileIOXdrSerializer::doDouble(double* value)
813 gmx_fio_do_double(fio_, *value);
816 void FileIOXdrSerializer::doReal(real* value)
818 gmx_fio_do_real(fio_, *value);
821 void FileIOXdrSerializer::doIvec(ivec* value)
823 gmx_fio_do_ivec(fio_, *value);
826 void FileIOXdrSerializer::doRvec(rvec* value)
828 gmx_fio_do_rvec(fio_, *value);
831 void FileIOXdrSerializer::doCharArray(char* values, int elements)
833 gmx_fio_ndo_char(fio_, values, elements);
836 void FileIOXdrSerializer::doUCharArray(unsigned char* values, int elements)
838 gmx_fio_ndo_uchar(fio_, values, elements);
841 void FileIOXdrSerializer::doRvecArray(rvec* values, int elements)
843 gmx_fio_ndo_rvec(fio_, values, elements);
846 void FileIOXdrSerializer::doString(std::string* value)
848 // TODO: Use an arbitrary length buffer (but that is not supported in
853 std::strncpy(buf, value->c_str(), STRLEN);
856 gmx_fio_do_string(fio_, buf);
863 void FileIOXdrSerializer::doOpaque(char* data, std::size_t size)
865 gmx_fio_do_opaque(fio_, data, size);