1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode:nil; coding:utf-8 -*- */
2 /* vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 */
3 /*
4 
5    MDAnalysis --- https://www.mdanalysis.org
6    Copyright (c) 2006-2016 The MDAnalysis Development Team and contributors
7    (see the file AUTHORS for the full list of names)
8 
9    Released under the GNU Public Licence, v2 or any higher version
10 
11    Please cite your use of MDAnalysis in published work:
12 
13    R. J. Gowers, M. Linke, J. Barnoud, T. J. E. Reddy, M. N. Melo, S. L. Seyler,
14    D. L. Dotson, J. Domanski, S. Buchoux, I. M. Kenney, and O. Beckstein.
15    MDAnalysis: A Python package for the rapid analysis of molecular dynamics
16    simulations. In S. Benthall and S. Rostrup editors, Proceedings of the 15th
17    Python in Science Conference, pages 102-109, Austin, TX, 2016. SciPy.
18 
19    N. Michaud-Agrawal, E. J. Denning, T. B. Woolf, and O. Beckstein.
20    MDAnalysis: A Toolkit for the Analysis of Molecular Dynamics Simulations.
21    J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787
22 
23 */
24 
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include "xdrfile.h"
31 #include "xdrfile_trr.h"
32 #include "trr_seek.h"
33 
read_trr_n_frames(char * fn,int * n_frames,int * est_nframes,int64_t ** offsets)34 int read_trr_n_frames(char *fn, int *n_frames, int *est_nframes,
35                       int64_t **offsets) {
36   XDRFILE *xd;
37   t_trnheader sh;
38   float time, lambda;
39   int result, framebytes, totalframebytes;
40   int64_t filesize, frame_offset;
41 
42   if ((xd = xdrfile_open(fn, "r")) == NULL)
43     return exdrFILENOTFOUND;
44   if (xdr_seek(xd, 0L, SEEK_END) != exdrOK) {
45     xdrfile_close(xd);
46     return exdrNR;
47   }
48   filesize = xdr_tell(xd);
49   if (xdr_seek(xd, 0L, SEEK_SET) != exdrOK) {
50     xdrfile_close(xd);
51     return exdrNR;
52   }
53 
54   if ((result = do_trnheader(xd, 1, &sh)) != exdrOK) {
55     xdrfile_close(xd);
56     return result;
57   }
58 
59   framebytes = sh.ir_size + sh.e_size + sh.box_size + sh.vir_size +
60                sh.pres_size + sh.top_size + sh.sym_size + sh.x_size +
61                sh.v_size + sh.f_size;
62 
63   *est_nframes =
64       (int)(filesize / ((int64_t)(framebytes + TRR_MIN_HEADER_SIZE)) +
65             1); // add one because it'd be easy to underestimate low
66                 // frame numbers.
67   *est_nframes += *est_nframes / 5;
68 
69   /* Allocate memory for the frame index array */
70   if ((*offsets = malloc(sizeof(int64_t) * *est_nframes)) == NULL) {
71     xdrfile_close(xd);
72     return exdrNOMEM;
73   }
74 
75   (*offsets)[0] = 0L;
76   *n_frames = 1;
77   while (1) {
78     if (xdr_seek(xd, (int64_t)(framebytes), SEEK_CUR) != exdrOK) {
79       free(*offsets);
80       xdrfile_close(xd);
81       return exdrNR;
82     }
83     frame_offset = xdr_tell(xd); /* Store it now, before we read the header */
84     if ((result = do_trnheader(xd, 1, &sh)) != exdrOK) /* Interpreting as EOF */
85       break;
86     /* Read was successful; this is another frame */
87     /* Check if we need to enlarge array */
88     if (*n_frames == *est_nframes) {
89       *est_nframes += *est_nframes / 5 + 1; // Increase in 20% stretches
90       if ((*offsets = realloc(*offsets, sizeof(int64_t) * *est_nframes)) ==
91           NULL) {
92         xdrfile_close(xd);
93         return exdrNOMEM;
94       }
95     }
96     (*offsets)[*n_frames] = frame_offset;
97     (*n_frames)++;
98     /* Calculate how much to skip this time */
99     framebytes = sh.ir_size + sh.e_size + sh.box_size + sh.vir_size +
100                  sh.pres_size + sh.top_size + sh.sym_size + sh.x_size +
101                  sh.v_size + sh.f_size;
102   }
103   xdrfile_close(xd);
104   return exdrOK;
105 }
106