NAMD
IndexFile.h
Go to the documentation of this file.
1 
7 /*
8  IndexFile Class
9  Given an IndexFile name, provide access to the data via std::vectors.
10 
11  Index files contain lists of uint32 atom indices and are used to
12  convey subset membership.
13 
14  Format is:
15  byte 0 : version 1
16  byte 1-4 : count of elements as binary unsigned int
17  element 0 .. N
18  elements : unsigned int (4 bytes) atom index counting from 0
19 
20  Version 0 was just the elements and can heuristically be
21  distinguished by the initial byte being 0. As the handful of
22  index files made in that format were all placing indices in order
23  with a relatively small starting value.
24 
25  The IndexFile class holds only the ifstream, filename, element
26  count and version.
27 
28  Expected usage is constructor, getAllElements, destructor.
29 
30  IndexFile is a header only class, implemented via ifstream
31  because that should allow portability per the standard, unlike
32  the older file APIs where we have to painstakingly debug corner
33  cases demarcated with ifdefs for windows and other aberrations.
34 */
35 
36 #ifndef INDEXFILE_H
37 #define INDEXFILE_H
38 #include <iostream>
39 #include <fstream>
40 #include <vector>
41 #include <algorithm>
42 
43 #ifdef MEM_OPT_VERSION
44 static_assert (sizeof(off_t) >= sizeof(uint64_t), "off_t less than 64bits not supported in MEM_OPT_VERSION");
45 #endif
46 class IndexFile {
47  private:
48  std::string filename;
49  std::ifstream fileStream;
50  unsigned int numElements;
51  unsigned short version;
52  bool networkEndian;
53  public:
54  IndexFile(std::string _filename): filename(_filename){
55  version=0;
56  open();
57  if(fileStream.fail())
58  NAMD_die("error in IndexFile::IndexFile");
59  }
60 
62  unsigned int size(){ return numElements;}
63  unsigned int getNumElements(){ return numElements;}
64  std::vector<unsigned int> getAllElements()
65  {
66  std::vector<unsigned int> index;
67  index.resize(numElements);
68  fileStream.read(reinterpret_cast<char*>(&index[0]), index.size()* sizeof(unsigned int));
69  // auto print = [] (const int &n){ std::cout << n << "\n";};
70  // std::for_each(index.begin(), index.end(), print);
71  if(networkEndian)
72  std::for_each(index.begin(), index.end(), [] (unsigned int &n) { n = ntohl(n);});
73  if(fileStream.good())
74  return index;
75  else
76  NAMD_die("error in IndexFile::getAllElements");
77  }
78 
79  void seek(off_t pos) {fileStream.seekg(pos);}
80 
81  std::vector<unsigned int> getNElements(off_t offset, size_t numElementsRange)
82  {
83  std::vector<unsigned int> index;
84  index.resize(numElementsRange);
85  seek(offset);
86  fileStream.read(reinterpret_cast<char*>(&index[0]), index.size()* sizeof(unsigned int));
87  if(networkEndian)
88  std::for_each(index.begin(), index.end(), [] (unsigned int &n) { n = ntohl(n);});
89  if(fileStream.good())
90  return index;
91  else
92  NAMD_die("error in IndexFile::getNElements");
93  }
94 
95  std::vector<unsigned int> getNElements(size_t numElements){
96  return getNElements(0, numElements);
97  }
98 
99  std::vector<unsigned int> getElements()
100  {
101  return getAllElements();
102  }
103 
104  bool open()
105  {
106  fileStream.open(filename.c_str(), std::ios::in | std::ifstream::binary);
107  // ifstream portable way to get file size
108  fileStream.read(reinterpret_cast<char*>(&version), sizeof(unsigned short int));
109  fileStream.seekg(0, fileStream.end);
110  unsigned int lengthCheck = fileStream.tellg();
111  unsigned int countedLength =0;
112  fileStream.seekg(0, fileStream.beg);
113  unsigned short beVersion=ntohs(version);
114  if(version>=256)
115  {
116  if(ntohs(version)==1)
117  {
118  networkEndian = true;
119  version = beVersion;
120 
121  }
122  }
123  switch (version) {
124  case 0:
125  numElements = lengthCheck/sizeof(unsigned int);
126  break;
127  case 1:
128  fileStream.seekg(2, fileStream.beg); // need to seek past the version
129  fileStream.read(reinterpret_cast<char*>(&numElements), sizeof(unsigned int));
130  numElements = (networkEndian) ? ntohl(numElements) : numElements;
131  countedLength = (lengthCheck-sizeof(char)-sizeof(unsigned int))/sizeof(unsigned int);
132  if(numElements!= countedLength)
133  {
134  std::string e="error in IndexFile::open mismatch in element count";
135  e+=" file reports "+std::to_string(numElements)+ " counted "+std::to_string(countedLength);
136  NAMD_die(e.c_str());
137  }
138  break;
139  default:
140  NAMD_die("error in IndexFile::open unsupported version");
141  break;
142  }
143  return(fileStream.is_open());
144  }
145 
146  void close(){fileStream.close();}
147 
148 };
149 #endif // Index
std::vector< unsigned int > getNElements(off_t offset, size_t numElementsRange)
Definition: IndexFile.h:81
std::vector< unsigned int > getElements()
Definition: IndexFile.h:99
void close()
Definition: IndexFile.h:146
unsigned int getNumElements()
Definition: IndexFile.h:63
~IndexFile()
Definition: IndexFile.h:61
void NAMD_die(const char *err_msg)
Definition: common.C:147
std::vector< unsigned int > getNElements(size_t numElements)
Definition: IndexFile.h:95
IndexFile(std::string _filename)
Definition: IndexFile.h:54
std::vector< unsigned int > getAllElements()
Definition: IndexFile.h:64
unsigned int size()
Definition: IndexFile.h:62
bool open()
Definition: IndexFile.h:104
void seek(off_t pos)
Definition: IndexFile.h:79