28ea2377eee013d1025ba3186abaf6b00134aaed
[alexxy/gromacs.git] / src / gromacs / fileio / gmxfio_asc.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,2014, 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
38
39 #include "gmxpre.h"
40
41 #include "config.h"
42
43 #include <ctype.h>
44 #include <errno.h>
45 #include <stdio.h>
46 #include <string.h>
47 #ifdef HAVE_IO_H
48 #include <io.h>
49 #endif
50
51 #include "gromacs/utility/fatalerror.h"
52 #include "gromacs/legacyheaders/macros.h"
53 #include "gromacs/utility/smalloc.h"
54 #include "gromacs/utility/futil.h"
55 #include "filenm.h"
56 #include "gromacs/utility/cstringutil.h"
57 #include "gmxfio.h"
58 #include "md5.h"
59
60 #include "gmxfio_int.h"
61
62
63 /* This is the part that reads dummy and ascii files.  */
64
65
66
67
68 /* file type functions */
69 static gmx_bool do_ascread(t_fileio *fio, void *item, int nitem, int eio,
70                            const char *desc, const char *srcfile, int line);
71 static gmx_bool do_ascwrite(t_fileio *fio, const void *item, int nitem, int eio,
72                             const char *desc, const char *srcfile, int line);
73 static gmx_bool do_dummyread(t_fileio *fio, void *item, int nitem, int eio,
74                              const char *desc, const char *srcfile, int line);
75 static gmx_bool do_dummywrite(t_fileio *fio, const void *item, int nitem, int eio,
76                               const char *desc, const char *srcfile, int line);
77
78
79 const t_iotype asc_iotype = {do_ascread, do_ascwrite};
80 const t_iotype dummy_iotype = {do_dummyread, do_dummywrite};
81
82
83
84
85
86
87 static gmx_bool do_dummyread(t_fileio gmx_unused *fio, void gmx_unused *item, int gmx_unused nitem, int gmx_unused eio,
88                              const char gmx_unused *desc, const char gmx_unused *srcfile, int gmx_unused line)
89 {
90     gmx_fatal(FARGS, "File type not set!");
91     return FALSE;
92 }
93
94 static gmx_bool do_dummywrite(t_fileio gmx_unused *fio, const void gmx_unused *item, int gmx_unused nitem, int gmx_unused eio,
95                               const char gmx_unused *desc, const char gmx_unused *srcfile, int gmx_unused line)
96 {
97     gmx_fatal(FARGS, "File type not set!");
98     return FALSE;
99 }
100
101
102
103 static void encode_string(int maxlen, char dst[], const char src[])
104 {
105     int i;
106
107     for (i = 0; (i < maxlen - 1) && (src[i] != '\0'); i++)
108     {
109         if ((src[i] == ' ') || (src[i] == '\t'))
110         {
111             dst[i] = '_';
112         }
113         else
114         {
115             dst[i] = src[i];
116         }
117     }
118     dst[i] = '\0';
119
120     if (i == maxlen)
121     {
122         fprintf(stderr, "String '%s' truncated to '%s'\n", src, dst);
123     }
124 }
125
126 static void decode_string(int maxlen, char dst[], const char src[])
127 {
128     int i;
129
130     for (i = 0; (i < maxlen - 1) && (src[i] != '\0'); i++)
131     {
132         if (src[i] == '_')
133         {
134             dst[i] = ' ';
135         }
136         else
137         {
138             dst[i] = src[i];
139         }
140     }
141     dst[i] = '\0';
142
143     if (i == maxlen)
144     {
145         fprintf(stderr, "String '%s' truncated to '%s'\n", src, dst);
146     }
147 }
148
149 static gmx_bool do_ascwrite(t_fileio *fio, const void *item, int nitem, int eio,
150                             const char *desc, const char *srcfile, int line)
151 {
152     int            i;
153     int            res = 0, *iptr;
154     real          *ptr;
155     char           strbuf[256];
156     char           buf[GMX_FIO_BUFLEN];
157     unsigned char *ucptr;
158     FILE          *fp = fio->fp;
159
160     gmx_fio_check_nitem(eio, nitem, srcfile, line);
161     switch (eio)
162     {
163         case eioREAL:
164         case eioFLOAT:
165         case eioDOUBLE:
166             res = fprintf(fp, "%18.10e%s\n", *((real *) item),
167                           gmx_fio_dbgstr(fio, desc, buf));
168             break;
169         case eioINT:
170             res = fprintf(fp, "%18d%s\n", *((int *) item), gmx_fio_dbgstr(fio,
171                                                                           desc,
172                                                                           buf));
173             break;
174         case eioINT64:
175             sprintf(strbuf, "%s%s%s", "%", GMX_PRId64, "\n");
176             res = fprintf(fp, strbuf, *((gmx_int64_t *) item),
177                           gmx_fio_dbgstr(fio, desc, buf));
178             break;
179         case eioUCHAR:
180             res = fprintf(fp, "%4d%s\n", *((unsigned char *) item),
181                           gmx_fio_dbgstr(fio, desc, buf));
182             break;
183         case eioNUCHAR:
184             ucptr = (unsigned char *) item;
185             for (i = 0; (i < nitem); i++)
186             {
187                 res = fprintf(fp, "%4d", (int) ucptr[i]);
188             }
189             fprintf(fio->fp, "%s\n", gmx_fio_dbgstr(fio, desc, buf));
190             break;
191         case eioUSHORT:
192             res = fprintf(fp, "%18d%s\n", *((unsigned short *) item),
193                           gmx_fio_dbgstr(fio, desc, buf));
194             break;
195         case eioRVEC:
196             ptr = (real *) item;
197             res = fprintf(fp, "%18.10e%18.10e%18.10e%s\n", ptr[XX],
198                           ptr[YY], ptr[ZZ], gmx_fio_dbgstr(fio, desc, buf));
199             break;
200         case eioNRVEC:
201             for (i = 0; (i < nitem); i++)
202             {
203                 ptr = ((rvec *) item)[i];
204                 res = fprintf(fp, "%18.10e%18.10e%18.10e%s\n", ptr[XX],
205                               ptr[YY], ptr[ZZ], gmx_fio_dbgstr(fio, desc, buf));
206             }
207             break;
208         case eioIVEC:
209             iptr = (int *) item;
210             res  = fprintf(fp, "%18d%18d%18d%s\n", iptr[XX], iptr[YY],
211                            iptr[ZZ], gmx_fio_dbgstr(fio, desc, buf));
212             break;
213         case eioSTRING:
214             encode_string(256, strbuf, (char *) item);
215             res = fprintf(fp, "%-18s%s\n", strbuf, gmx_fio_dbgstr(fio, desc, buf));
216             break;
217         default:
218             gmx_fio_fe(fio, eio, desc, srcfile, line);
219     }
220     if ((res <= 0) && fio->bDebug)
221     {
222         fprintf(stderr,
223                 "Error writing %s %s to file %s (source %s, line %d)\n",
224                 eioNames[eio], desc, fio->fn, srcfile, line);
225     }
226
227     return (res > 0);
228 }
229
230
231 static char *next_item(FILE *fp, char *buf, int buflen)
232 {
233     int      rd;
234     gmx_bool in_comment = FALSE;
235     gmx_bool in_token   = FALSE;
236     int      i          = 0;
237     /* This routine reads strings from the file fp, strips comment
238      * and buffers. For thread-safety reasons, It reads through getc()  */
239
240     rd = getc(fp);
241     if (rd == EOF)
242     {
243         gmx_file("End of file");
244     }
245     do
246     {
247         if (in_comment)
248         {
249             if (rd == '\n')
250             {
251                 in_comment = FALSE;
252             }
253         }
254         else if (in_token)
255         {
256             if (isspace(rd) || rd == ';')
257             {
258                 break;
259             }
260             buf[i++] = (char) rd;
261         }
262         else
263         {
264             if (!isspace(rd))
265             {
266                 if (rd == ';')
267                 {
268                     in_comment = TRUE;
269                 }
270                 else
271                 {
272                     in_token = TRUE;
273                     buf[i++] = (char) (rd);
274                 }
275             }
276         }
277         if (i >= buflen - 2)
278         {
279             break;
280         }
281     }
282     while ((rd = getc(fp)) != EOF);
283
284     fprintf(stderr, "WARNING, ftpASC file type not tested!\n");
285
286     buf[i] = 0;
287
288     return buf;
289 }
290
291 static gmx_bool do_ascread(t_fileio *fio, void *item, int nitem, int eio,
292                            const char *desc, const char *srcfile, int line)
293 {
294     FILE           *fp = fio->fp;
295     int             i, m, res = 0, *iptr, ix;
296     gmx_int64_t     s;
297     double          d, x;
298     real           *ptr;
299     unsigned char   uc, *ucptr;
300     char           *cptr;
301 #define NEXT_ITEM_BUF_LEN 128
302     char            ni_buf[NEXT_ITEM_BUF_LEN];
303
304     gmx_fio_check_nitem(eio, nitem, srcfile, line);
305     switch (eio)
306     {
307         case eioREAL:
308         case eioFLOAT:
309         case eioDOUBLE:
310             res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf", &d);
311             if (item)
312             {
313                 *((real *) item) = d;
314             }
315             break;
316         case eioINT:
317             res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &i);
318             if (item)
319             {
320                 *((int *) item) = i;
321             }
322             break;
323         case eioINT64:
324             res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN),
325                          "%"GMX_SCNd64, &s);
326             if (item)
327             {
328                 *((gmx_int64_t *) item) = s;
329             }
330             break;
331         case eioUCHAR:
332             res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%c", &uc);
333             if (item)
334             {
335                 *((unsigned char *) item) = uc;
336             }
337             break;
338         case eioNUCHAR:
339             ucptr = (unsigned char *) item;
340             for (i = 0; (i < nitem); i++)
341             {
342                 res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &ix);
343                 if (item)
344                 {
345                     ucptr[i] = ix;
346                 }
347             }
348             break;
349         case eioUSHORT:
350             res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &i);
351             if (item)
352             {
353                 *((unsigned short *) item) = i;
354             }
355             break;
356         case eioRVEC:
357             ptr = (real *) item;
358             for (m = 0; (m < DIM); m++)
359             {
360                 res    = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf\n", &x);
361                 ptr[m] = x;
362             }
363             break;
364         case eioNRVEC:
365             for (i = 0; (i < nitem); i++)
366             {
367                 ptr = ((rvec *) item)[i];
368                 for (m = 0; (m < DIM); m++)
369                 {
370                     res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf\n",
371                                  &x);
372                     if (item)
373                     {
374                         ptr[m] = x;
375                     }
376                 }
377             }
378             break;
379         case eioIVEC:
380             iptr = (int *) item;
381             for (m = 0; (m < DIM); m++)
382             {
383                 res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d\n", &ix);
384                 if (item)
385                 {
386                     iptr[m] = ix;
387                 }
388             }
389             break;
390         case eioSTRING:
391             cptr = next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN);
392             if (item)
393             {
394                 decode_string(strlen(cptr) + 1, (char *) item, cptr);
395                 /* res = sscanf(cptr,"%s",(char *)item);*/
396                 res = 1;
397             }
398             break;
399         default:
400             gmx_fio_fe(fio, eio, desc, srcfile, line);
401     }
402
403     if ((res <= 0) && fio->bDebug)
404     {
405         fprintf(stderr,
406                 "Error reading %s %s from file %s (source %s, line %d)\n",
407                 eioNames[eio], desc, fio->fn, srcfile, line);
408     }
409     return (res > 0);
410 }