Merge release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / fileio / gmxfio_xdr.c
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, 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 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #include <ctype.h>
42 #include <stdio.h>
43 #include <errno.h>
44 #ifdef HAVE_IO_H
45 #include <io.h>
46 #endif
47
48 #include "gmx_fatal.h"
49 #include "macros.h"
50 #include "smalloc.h"
51 #include "futil.h"
52 #include "filenm.h"
53 #include "string2.h"
54 #include "gmxfio.h"
55 #include "md5.h"
56
57 #ifdef GMX_THREAD_MPI
58 #include "thread_mpi.h"
59 #endif
60
61 #include "gmxfio_int.h"
62
63 /* This is the part that reads xdr files.  */
64
65
66 /* file type functions */
67 static gmx_bool do_xdrread(t_fileio *fio, void *item, int nitem, int eio,
68                            const char *desc, const char *srcfile, int line);
69 static gmx_bool do_xdrwrite(t_fileio *fio, const void *item, int nitem, int eio,
70                             const char *desc, const char *srcfile, int line);
71
72
73 const t_iotype xdr_iotype = {do_xdrread, do_xdrwrite};
74
75
76 #ifdef USE_XDR
77
78 static gmx_bool do_xdr(t_fileio *fio, void *item, int nitem, int eio,
79                        const char *desc, const char *srcfile, int line)
80 {
81     unsigned char   ucdum, *ucptr;
82     bool_t          res = 0;
83     float           fvec[DIM];
84     double          dvec[DIM];
85     int             j, m, *iptr, idum;
86     gmx_large_int_t sdum;
87     real           *ptr;
88     unsigned short  us;
89     double          d = 0;
90     float           f = 0;
91
92     gmx_fio_check_nitem(eio, nitem, srcfile, line);
93     switch (eio)
94     {
95         case eioREAL:
96             if (fio->bDouble)
97             {
98                 if (item && !fio->bRead)
99                 {
100                     d = *((real *) item);
101                 }
102                 res = xdr_double(fio->xdr, &d);
103                 if (item)
104                 {
105                     *((real *) item) = d;
106                 }
107             }
108             else
109             {
110                 if (item && !fio->bRead)
111                 {
112                     f = *((real *) item);
113                 }
114                 res = xdr_float(fio->xdr, &f);
115                 if (item)
116                 {
117                     *((real *) item) = f;
118                 }
119             }
120             break;
121         case eioFLOAT:
122             if (item && !fio->bRead)
123             {
124                 f = *((float *) item);
125             }
126             res = xdr_float(fio->xdr, &f);
127             if (item)
128             {
129                 *((float *) item) = f;
130             }
131             break;
132         case eioDOUBLE:
133             if (item && !fio->bRead)
134             {
135                 d = *((double *) item);
136             }
137             res = xdr_double(fio->xdr, &d);
138             if (item)
139             {
140                 *((double *) item) = d;
141             }
142             break;
143         case eioINT:
144             if (item && !fio->bRead)
145             {
146                 idum = *(int *) item;
147             }
148             res = xdr_int(fio->xdr, &idum);
149             if (item)
150             {
151                 *(int *) item = idum;
152             }
153             break;
154         case eioGMX_LARGE_INT:
155             /* do_xdr will not generate a warning when a 64bit gmx_large_int_t
156              * value that is out of 32bit range is read into a 32bit gmx_large_int_t.
157              */
158             if (item && !fio->bRead)
159             {
160                 sdum = *(gmx_large_int_t *) item;
161             }
162             res = xdr_gmx_large_int(fio->xdr, &sdum);
163             if (item)
164             {
165                 *(gmx_large_int_t *) item = sdum;
166             }
167             break;
168         case eioUCHAR:
169             if (item && !fio->bRead)
170             {
171                 ucdum = *(unsigned char *) item;
172             }
173             res = xdr_u_char(fio->xdr, &ucdum);
174             if (item)
175             {
176                 *(unsigned char *) item = ucdum;
177             }
178             break;
179         case eioNUCHAR:
180             ucptr = (unsigned char *) item;
181             res   = 1;
182             for (j = 0; (j < nitem) && res; j++)
183             {
184                 res = xdr_u_char(fio->xdr, &(ucptr[j]));
185             }
186             break;
187         case eioUSHORT:
188             if (item && !fio->bRead)
189             {
190                 us = *(unsigned short *) item;
191             }
192             res = xdr_u_short(fio->xdr, (unsigned short *) &us);
193             if (item)
194             {
195                 *(unsigned short *) item = us;
196             }
197             break;
198         case eioRVEC:
199             if (fio->bDouble)
200             {
201                 if (item && !fio->bRead)
202                 {
203                     for (m = 0; (m < DIM); m++)
204                     {
205                         dvec[m] = ((real *) item)[m];
206                     }
207                 }
208                 res = xdr_vector(fio->xdr, (char *) dvec, DIM,
209                                  (unsigned int) sizeof(double),
210                                  (xdrproc_t) xdr_double);
211                 if (item)
212                 {
213                     for (m = 0; (m < DIM); m++)
214                     {
215                         ((real *) item)[m] = dvec[m];
216                     }
217                 }
218             }
219             else
220             {
221                 if (item && !fio->bRead)
222                 {
223                     for (m = 0; (m < DIM); m++)
224                     {
225                         fvec[m] = ((real *) item)[m];
226                     }
227                 }
228                 res = xdr_vector(fio->xdr, (char *) fvec, DIM,
229                                  (unsigned int) sizeof(float),
230                                  (xdrproc_t) xdr_float);
231                 if (item)
232                 {
233                     for (m = 0; (m < DIM); m++)
234                     {
235                         ((real *) item)[m] = fvec[m];
236                     }
237                 }
238             }
239             break;
240         case eioNRVEC:
241             ptr = NULL;
242             res = 1;
243             for (j = 0; (j < nitem) && res; j++)
244             {
245                 if (item)
246                 {
247                     ptr = ((rvec *) item)[j];
248                 }
249                 res = do_xdr(fio, ptr, 1, eioRVEC, desc, srcfile, line);
250             }
251             break;
252         case eioIVEC:
253             iptr = (int *) item;
254             res  = 1;
255             for (m = 0; (m < DIM) && res; m++)
256             {
257                 if (item && !fio->bRead)
258                 {
259                     idum = iptr[m];
260                 }
261                 res = xdr_int(fio->xdr, &idum);
262                 if (item)
263                 {
264                     iptr[m] = idum;
265                 }
266             }
267             break;
268         case eioSTRING:
269         {
270             char *cptr;
271             int   slen;
272
273             if (item)
274             {
275                 if (!fio->bRead)
276                 {
277                     slen = strlen((char *) item) + 1;
278                 }
279                 else
280                 {
281                     slen = 0;
282                 }
283             }
284             else
285             {
286                 slen = 0;
287             }
288
289             if (xdr_int(fio->xdr, &slen) <= 0)
290             {
291                 gmx_fatal(FARGS, "wrong string length %d for string %s"
292                           " (source %s, line %d)", slen, desc, srcfile, line);
293             }
294             if (!item && fio->bRead)
295             {
296                 snew(cptr, slen);
297             }
298             else
299             {
300                 cptr = (char *)item;
301             }
302             if (cptr)
303             {
304                 res = xdr_string(fio->xdr, &cptr, slen);
305             }
306             else
307             {
308                 res = 1;
309             }
310             if (!item && fio->bRead)
311             {
312                 sfree(cptr);
313             }
314             break;
315         }
316         default:
317             gmx_fio_fe(fio, eio, desc, srcfile, line);
318     }
319     if ((res == 0) && (fio->bDebug))
320     {
321         fprintf(stderr, "Error in xdr I/O %s %s to file %s (source %s, line %d)\n",
322                 eioNames[eio], desc, fio->fn, srcfile, line);
323     }
324
325     return (res != 0);
326 }
327
328
329 static gmx_bool do_xdrread(t_fileio *fio, void *item, int nitem, int eio,
330                            const char *desc, const char *srcfile, int line)
331 {
332     return do_xdr(fio, item, nitem, eio, desc, srcfile, line);
333 }
334
335
336 static gmx_bool do_xdrwrite(t_fileio *fio, const void *item, int nitem, int eio,
337                             const char *desc, const char *srcfile, int line)
338 {
339     void *it = (void*)item; /* ugh.. */
340     return do_xdr(fio, it, nitem, eio, desc, srcfile, line);
341 }
342
343 #endif