mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
binVector.hpp
Go to the documentation of this file.
1 /** \file binVector.hpp
2  * \author Jared R. Males
3  * \brief A utility to read/write vectors of data from/to a binary file.
4  * \ingroup utils_files
5  */
6 
7 //***********************************************************************//
8 // Copyright 2015, 2016, 2017 Jared R. Males (jaredmales@gmail.com)
9 //
10 // This file is part of mxlib.
11 //
12 // mxlib is free software: you can redistribute it and/or modify
13 // it under the terms of the GNU General Public License as published by
14 // the Free Software Foundation, either version 3 of the License, or
15 // (at your option) any later version.
16 //
17 // mxlib is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU General Public License
23 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
24 //***********************************************************************//
25 
26 #ifndef binVector_hpp
27 #define binVector_hpp
28 
29 
30 #include <vector>
31 #include <complex>
32 
33 #include "../mxlib.hpp"
34 #include "../mxError.hpp"
35 
36 namespace mx
37 {
38 namespace ioutils
39 {
40 
41 /** \defgroup binvector binVector Binary File Format
42  * \ingroup ioutils
43  * \brief A simple binary file format for storing vectors of data on disk.
44  *
45  * The binVector file format is very simple: the first 8 bytes contain a unit64_t integer which specifies
46  * the type of the data. The second 8 bytes contain a uint64_t integer which specifies the length L of the data vector.
47  * The remaining L*sizeof(dataT) bytes contain the data.
48  *
49  * The suggested extension for BinVector files is ".binv".
50  *
51  *
52  */
53 
54 /// The type used for binVector sizes.
55 /** \ingroup binVector
56  */
57 typedef uint64_t binVSizeT;
58 
59 /// The type of binVector type codes.
60 /** \ingroup binvector
61  */
62 typedef uint64_t binVTypeT;
63 
64 ///Namespace fo the bin-vector type-codes.
65 /** \ingroup binvector
66  */
67 namespace binVTypes
68 {
69 
70 /// The pre-defined type codes for binVector.
71 /** \ingroup binvector
72  */
73 enum : binVTypeT { Bool = 0,
74  SChar = 1,
75  UChar = 2,
76  Char = 3,
77  WChar = 4,
78  Char16 = 5,
79  Char32 = 6,
80  Int = 7,
81  UInt = 8,
82  SInt = 9,
83  SUInt = 10,
84  LInt = 11,
85  LUInt = 12,
86  LLInt = 13,
87  LLUInt = 14,
88  Float = 15,
89  Double = 16,
90  LDouble = 17,
91  Quad = 18,
92  CFloat = 19,
93  CDouble = 20,
94  };
95 
96 } //namespace binVTyes
97 
98 ///Get the integer type code corresponding to the type.
99 /**
100  * \returns an integer which uniquely identifies the type.
101  *
102  * \tparam dataT is the type
103  *
104  * \ingroup binvector
105  */
106 template<typename dataT>
108 
109 template<>
110 binVTypeT binVectorTypeCode<bool>()
111 {
112  return binVTypes::Bool;
113 }
114 
115 template<>
116 binVTypeT binVectorTypeCode<signed char>()
117 {
118  return binVTypes::SChar;
119 }
120 
121 template<>
122 binVTypeT binVectorTypeCode<unsigned char>()
123 {
124  return binVTypes::UChar;
125 }
126 
127 template<>
128 binVTypeT binVectorTypeCode<char>()
129 {
130  return binVTypes::Char;
131 }
132 
133 template<>
134 binVTypeT binVectorTypeCode<wchar_t>()
135 {
136  return binVTypes::WChar;
137 }
138 
139 template<>
140 binVTypeT binVectorTypeCode<char16_t>()
141 {
142  return binVTypes::Char16;
143 }
144 
145 template<>
146 binVTypeT binVectorTypeCode<char32_t>()
147 {
148  return binVTypes::Char32;
149 }
150 
151 template<>
152 binVTypeT binVectorTypeCode<int>()
153 {
154  return binVTypes::Int;
155 }
156 
157 template<>
158 binVTypeT binVectorTypeCode<unsigned int>()
159 {
160  return binVTypes::UInt;
161 }
162 
163 template<>
164 binVTypeT binVectorTypeCode<short int>()
165 {
166  return binVTypes::SInt;
167 }
168 
169 template<>
170 binVTypeT binVectorTypeCode<short unsigned int>()
171 {
172  return binVTypes::SUInt;
173 }
174 
175 template<>
176 binVTypeT binVectorTypeCode<long int>()
177 {
178  return binVTypes::LInt;
179 }
180 
181 template<>
182 binVTypeT binVectorTypeCode<long unsigned int>()
183 {
184  return binVTypes::LUInt;
185 }
186 
187 template<>
188 binVTypeT binVectorTypeCode<long long int>()
189 {
190  return binVTypes::LLInt;
191 }
192 
193 template<>
194 binVTypeT binVectorTypeCode<long long unsigned int>()
195 {
196  return binVTypes::LLUInt;
197 }
198 
199 
200 template<>
201 binVTypeT binVectorTypeCode<float>()
202 {
203  return binVTypes::Float;
204 }
205 
206 template<>
207 binVTypeT binVectorTypeCode<double>()
208 {
209  return binVTypes::Double;
210 }
211 
212 template<>
213 binVTypeT binVectorTypeCode<long double>()
214 {
215  return binVTypes::LDouble;
216 }
217 
218 template<>
219 binVTypeT binVectorTypeCode<std::complex<float>>()
220 {
221  return binVTypes::CFloat;
222 }
223 
224 template<>
225 binVTypeT binVectorTypeCode<std::complex<double>>()
226 {
227  return binVTypes::CDouble;
228 }
229 
230 /// Read a BinVector file from disk.
231 /**
232  * \note dataT must match what was stored in the file.
233  *
234  * \returns 0 on success.
235  * \returns -1 if an error occurs.
236  *
237  * \ingroup binvector
238  */
239 template<typename dataT>
240 int readBinVector( std::vector<dataT> & vec, ///< [out] vec is a vector which will be resized and populated.
241  const std::string & fname ///< [in] fname is the name (full-path) of the file.
242  )
243 {
244  FILE *fin;
245  binVTypeT typecode;
246  binVSizeT sz;
247  size_t nrd;
248 
249  fin = fopen(fname.c_str(), "r");
250  if(fin == 0)
251  {
252  mxPError("readBinVector", errno, "Error from fopen [" + fname + "]");
253  return -1;
254  }
255 
256  errno = 0;
257  nrd = fread(&typecode, sizeof(binVTypeT), 1, fin);
258 
259  if(nrd != 1)
260  {
261  //Have to handle case where EOF reached but no error.
262  if(errno != 0)
263  {
264  mxPError("readBinVector", errno, "Error reading data size [" + fname + "]");
265  }
266  else
267  {
268  mxError("readBinVector", MXE_FILERERR, "Error reading data size, did not read enough bytes. [" + fname + "]");
269  }
270  fclose(fin);
271  return -1;
272  }
273 
274  if( typecode != binVectorTypeCode<dataT>() )
275  {
276  mxError("readBinVector", MXE_SIZEERR, "Mismatch between type dataT and type in file [" + fname + "]");
277  fclose(fin);
278  return -1;
279  }
280 
281 
282  errno = 0;
283  nrd = fread(&sz, sizeof(binVSizeT), 1, fin);
284 
285  if(nrd != 1)
286  {
287  //Have to handle case where EOF reached but no error.
288  if(errno != 0)
289  {
290  mxPError("readBinVector", errno, "Error reading vector size [" + fname + "]");
291  }
292  else
293  {
294  mxError("readBinVector", MXE_FILERERR, "Error reading vector size, did not read enough bytes [" + fname + "]");
295  }
296  fclose(fin);
297  return -1;
298  }
299 
300  vec.resize(sz);
301 
302  errno = 0;
303  nrd = fread(vec.data(), sizeof(dataT), sz, fin);
304 
305  if(nrd != sz)
306  {
307  //Have to handle case where EOF reached but no error.
308  if(errno != 0)
309  {
310  mxPError("readBinVector", errno, "Error reading data [" + fname + "]");
311  }
312  else
313  {
314  mxError("readBinVector", MXE_FILERERR, "Did not read enough data [" + fname + "]");
315  }
316  fclose(fin);
317  return -1;
318  }
319 
320  fclose(fin);
321 
322  return 0;
323 }
324 
325 /// Write a BinVector file to disk.
326 /**
327  *
328  * \returns 0 on success.
329  * \returns -1 if an error occurs.
330  *
331  * \ingroup binvector
332  */
333 template<typename dataT>
334 int writeBinVector( const std::string & fname, ///< [in] fname is the name (full-path) of the file.
335  std::vector<dataT> & vec ///< [in] vec is the vector which will be written to disk.
336  )
337 {
338 
339  FILE *fout;
340  size_t nwr;
341  binVTypeT typecode = binVectorTypeCode<dataT>();
342  binVSizeT sz = vec.size();
343 
344  fout = fopen(fname.c_str(), "wb");
345  if(fout == 0)
346  {
347  mxPError("writeBinVector", errno, "Error from fopen [" + fname + "]");
348  return -1;
349  }
350 
351  nwr = fwrite( &typecode, sizeof(binVTypeT), 1, fout);
352  if(nwr != 1)
353  {
354  mxPError("writeBinVector", errno, "Error writing typecode [" + fname + "]");
355  fclose(fout);
356  return -1;
357  }
358 
359  nwr = fwrite( &sz, sizeof(binVSizeT), 1, fout);
360  if(nwr != 1)
361  {
362  mxPError("writeBinVector", errno, "Error writing vector size [" + fname + "]");
363  fclose(fout);
364  return -1;
365  }
366 
367  nwr = fwrite( vec.data(), sizeof(dataT), vec.size(), fout);
368  if(nwr != sz)
369  {
370  mxPError("writeBinVector", errno, "Error writing data [" + fname + "]");
371  fclose(fout);
372  return -1;
373  }
374 
375  fclose(fout);
376 
377  return 0;
378 }
379 
380 
381 } //namespace ioutils
382 } //namespace mx
383 
384 #endif //binVector_hpp
uint64_t binVSizeT
The type used for binVector sizes.
Definition: binVector.hpp:57
int writeBinVector(const std::string &fname, std::vector< dataT > &vec)
Write a BinVector file to disk.
Definition: binVector.hpp:334
binVTypeT binVectorTypeCode()
Get the integer type code corresponding to the type.
uint64_t binVTypeT
The type of binVector type codes.
Definition: binVector.hpp:62
int readBinVector(std::vector< dataT > &vec, const std::string &fname)
Read a BinVector file from disk.
Definition: binVector.hpp:240
The mxlib c++ namespace.
Definition: mxError.hpp:107