LCOV - code coverage report
Current view: top level - include/ioutils - binVector.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 14.6 % 103 15
Test Date: 2026-08-30 22:23:37 Functions: 9.1 % 22 2

            Line data    Source code
       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              : #include <vector>
      30              : #include <complex>
      31              : #include <cstdint>
      32              : 
      33              : #include "../mxlib.hpp"
      34              : 
      35              : namespace mx
      36              : {
      37              : namespace ioutils
      38              : {
      39              : 
      40              : /** \defgroup binvector binVector Binary File Format
      41              :  * \ingroup ioutils
      42              :  * \brief A simple binary file format for storing vectors of data on disk.
      43              :  *
      44              :  * The binVector file format is very simple: the first 8 bytes contain a unit64_t integer which specifies
      45              :  * the type of the data. The second 8 bytes contain a uint64_t integer which specifies the length L of the data vector.
      46              :  * The remaining L*sizeof(dataT) bytes contain the data.
      47              :  *
      48              :  * The suggested extension for BinVector files is ".binv".
      49              :  *
      50              :  *
      51              :  */
      52              : 
      53              : /// The type used for binVector sizes.
      54              : /** \ingroup binvector
      55              :  */
      56              : typedef uint64_t binVSizeT;
      57              : 
      58              : /// The type of binVector type codes.
      59              : /** \ingroup binvector
      60              :  */
      61              : typedef uint64_t binVTypeT;
      62              : 
      63              : /// Namespace fo the bin-vector type-codes.
      64              : /** \ingroup binvector
      65              :  */
      66              : namespace binVTypes
      67              : {
      68              : 
      69              : /// The pre-defined type codes for binVector.
      70              : /** \ingroup binvector
      71              :  */
      72              : enum : binVTypeT
      73              : {
      74              :     Bool = 0,
      75              :     SChar = 1,
      76              :     UChar = 2,
      77              :     Char = 3,
      78              :     WChar = 4,
      79              :     Char16 = 5,
      80              :     Char32 = 6,
      81              :     Int = 7,
      82              :     UInt = 8,
      83              :     SInt = 9,
      84              :     SUInt = 10,
      85              :     LInt = 11,
      86              :     LUInt = 12,
      87              :     LLInt = 13,
      88              :     LLUInt = 14,
      89              :     Float = 15,
      90              :     Double = 16,
      91              :     LDouble = 17,
      92              :     Quad = 18,
      93              :     CFloat = 19,
      94              :     CDouble = 20,
      95              : };
      96              : 
      97              : } // namespace binVTypes
      98              : 
      99              : /// Get the integer type code corresponding to the type.
     100              : /**
     101              :  * \returns an integer which uniquely identifies the type.
     102              :  *
     103              :  * \tparam dataT is the type
     104              :  *
     105              :  * \ingroup binvector
     106              :  */
     107              : template <typename dataT>
     108              : binVTypeT binVectorTypeCode();
     109              : 
     110              : template <>
     111            0 : binVTypeT binVectorTypeCode<bool>()
     112              : {
     113            0 :     return binVTypes::Bool;
     114              : }
     115              : 
     116              : template <>
     117            0 : binVTypeT binVectorTypeCode<signed char>()
     118              : {
     119            0 :     return binVTypes::SChar;
     120              : }
     121              : 
     122              : template <>
     123            0 : binVTypeT binVectorTypeCode<unsigned char>()
     124              : {
     125            0 :     return binVTypes::UChar;
     126              : }
     127              : 
     128              : template <>
     129            0 : binVTypeT binVectorTypeCode<char>()
     130              : {
     131            0 :     return binVTypes::Char;
     132              : }
     133              : 
     134              : template <>
     135            0 : binVTypeT binVectorTypeCode<wchar_t>()
     136              : {
     137            0 :     return binVTypes::WChar;
     138              : }
     139              : 
     140              : template <>
     141            0 : binVTypeT binVectorTypeCode<char16_t>()
     142              : {
     143            0 :     return binVTypes::Char16;
     144              : }
     145              : 
     146              : template <>
     147            0 : binVTypeT binVectorTypeCode<char32_t>()
     148              : {
     149            0 :     return binVTypes::Char32;
     150              : }
     151              : 
     152              : template <>
     153            0 : binVTypeT binVectorTypeCode<int>()
     154              : {
     155            0 :     return binVTypes::Int;
     156              : }
     157              : 
     158              : template <>
     159            0 : binVTypeT binVectorTypeCode<unsigned int>()
     160              : {
     161            0 :     return binVTypes::UInt;
     162              : }
     163              : 
     164              : template <>
     165            0 : binVTypeT binVectorTypeCode<short int>()
     166              : {
     167            0 :     return binVTypes::SInt;
     168              : }
     169              : 
     170              : template <>
     171            0 : binVTypeT binVectorTypeCode<short unsigned int>()
     172              : {
     173            0 :     return binVTypes::SUInt;
     174              : }
     175              : 
     176              : template <>
     177            0 : binVTypeT binVectorTypeCode<long int>()
     178              : {
     179            0 :     return binVTypes::LInt;
     180              : }
     181              : 
     182              : template <>
     183            0 : binVTypeT binVectorTypeCode<long unsigned int>()
     184              : {
     185            0 :     return binVTypes::LUInt;
     186              : }
     187              : 
     188              : template <>
     189            0 : binVTypeT binVectorTypeCode<long long int>()
     190              : {
     191            0 :     return binVTypes::LLInt;
     192              : }
     193              : 
     194              : template <>
     195            0 : binVTypeT binVectorTypeCode<long long unsigned int>()
     196              : {
     197            0 :     return binVTypes::LLUInt;
     198              : }
     199              : 
     200              : template <>
     201            0 : binVTypeT binVectorTypeCode<float>()
     202              : {
     203            0 :     return binVTypes::Float;
     204              : }
     205              : 
     206              : template <>
     207            1 : binVTypeT binVectorTypeCode<double>()
     208              : {
     209            1 :     return binVTypes::Double;
     210              : }
     211              : 
     212              : template <>
     213            0 : binVTypeT binVectorTypeCode<long double>()
     214              : {
     215            0 :     return binVTypes::LDouble;
     216              : }
     217              : 
     218              : template <>
     219            0 : binVTypeT binVectorTypeCode<std::complex<float>>()
     220              : {
     221            0 :     return binVTypes::CFloat;
     222              : }
     223              : 
     224              : template <>
     225            0 : binVTypeT binVectorTypeCode<std::complex<double>>()
     226              : {
     227            0 :     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            0 : 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            0 :     fin = fopen( fname.c_str(), "r" );
     250            0 :     if( fin == 0 )
     251              :     {
     252            0 :         internal::mxlib_error_report( errno2error_t( errno ), "Error from fopen [" + fname + "]" );
     253            0 :         return -1;
     254              :     }
     255              : 
     256            0 :     errno = 0;
     257            0 :     nrd = fread( &typecode, sizeof( binVTypeT ), 1, fin );
     258              : 
     259            0 :     if( nrd != 1 )
     260              :     {
     261              :         // Have to handle case where EOF reached but no error.
     262            0 :         if( errno != 0 )
     263              :         {
     264            0 :             internal::mxlib_error_report( errno2error_t( errno ), "Error reading data size [" + fname + "]" );
     265              :         }
     266              :         else
     267              :         {
     268            0 :             internal::mxlib_error_report( error_t::filererr,
     269            0 :                                           "Error reading data size, did not read enough bytes. [" + fname + "]" );
     270              :         }
     271            0 :         fclose( fin );
     272            0 :         return -1;
     273              :     }
     274              : 
     275            0 :     if( typecode != binVectorTypeCode<dataT>() )
     276              :     {
     277            0 :         internal::mxlib_error_report( error_t::sizeerr,
     278            0 :                                       "Mismatch between type dataT and type in file [" + fname + "]" );
     279            0 :         fclose( fin );
     280            0 :         return -1;
     281              :     }
     282              : 
     283            0 :     errno = 0;
     284            0 :     nrd = fread( &sz, sizeof( binVSizeT ), 1, fin );
     285              : 
     286            0 :     if( nrd != 1 )
     287              :     {
     288              :         // Have to handle case where EOF reached but no error.
     289            0 :         if( errno != 0 )
     290              :         {
     291            0 :             internal::mxlib_error_report( errno2error_t( errno ), "Error reading vector size [" + fname + "]" );
     292              :         }
     293              :         else
     294              :         {
     295            0 :             internal::mxlib_error_report( error_t::filererr,
     296            0 :                                           "Error reading vector size, did not read enough bytes [" + fname + "]" );
     297              :         }
     298            0 :         fclose( fin );
     299            0 :         return -1;
     300              :     }
     301              : 
     302            0 :     vec.resize( sz );
     303              : 
     304            0 :     errno = 0;
     305            0 :     nrd = fread( vec.data(), sizeof( dataT ), sz, fin );
     306              : 
     307            0 :     if( nrd != sz )
     308              :     {
     309              :         // Have to handle case where EOF reached but no error.
     310            0 :         if( errno != 0 )
     311              :         {
     312            0 :             internal::mxlib_error_report( errno2error_t( errno ), "Error reading data [" + fname + "]" );
     313              :         }
     314              :         else
     315              :         {
     316            0 :             internal::mxlib_error_report( error_t::filererr, "Did not read enough data [" + fname + "]" );
     317              :         }
     318            0 :         fclose( fin );
     319            0 :         return -1;
     320              :     }
     321              : 
     322            0 :     fclose( fin );
     323              : 
     324            0 :     return 0;
     325              : }
     326              : 
     327              : /// Write a BinVector file to disk.
     328              : /**
     329              :  *
     330              :  * \returns 0 on success.
     331              :  * \returns -1 if an error occurs.
     332              :  *
     333              :  * \ingroup binvector
     334              :  */
     335              : template <typename dataT>
     336            1 : int writeBinVector( const std::string &fname, ///< [in] fname is the name (full-path) of the file.
     337              :                     std::vector<dataT> &vec   ///< [in] vec is the vector which will be written to disk.
     338              : )
     339              : {
     340              : 
     341              :     FILE *fout;
     342              :     size_t nwr;
     343            1 :     binVTypeT typecode = binVectorTypeCode<dataT>();
     344            1 :     binVSizeT sz = vec.size();
     345              : 
     346            1 :     fout = fopen( fname.c_str(), "wb" );
     347            1 :     if( fout == 0 )
     348              :     {
     349            0 :         internal::mxlib_error_report( errno2error_t( errno ), "Error from fopen [" + fname + "]" );
     350            0 :         return -1;
     351              :     }
     352              : 
     353            1 :     nwr = fwrite( &typecode, sizeof( binVTypeT ), 1, fout );
     354            1 :     if( nwr != 1 )
     355              :     {
     356            0 :         internal::mxlib_error_report( errno2error_t( errno ), "Error writing typecode [" + fname + "]" );
     357            0 :         fclose( fout );
     358            0 :         return -1;
     359              :     }
     360              : 
     361            1 :     nwr = fwrite( &sz, sizeof( binVSizeT ), 1, fout );
     362            1 :     if( nwr != 1 )
     363              :     {
     364            0 :         internal::mxlib_error_report( errno2error_t( errno ), "Error writing vector size [" + fname + "]" );
     365            0 :         fclose( fout );
     366            0 :         return -1;
     367              :     }
     368              : 
     369            1 :     nwr = fwrite( vec.data(), sizeof( dataT ), vec.size(), fout );
     370            1 :     if( nwr != sz )
     371              :     {
     372            0 :         internal::mxlib_error_report( errno2error_t( errno ), "Error writing data [" + fname + "]" );
     373            0 :         fclose( fout );
     374            0 :         return -1;
     375              :     }
     376              : 
     377            1 :     fclose( fout );
     378              : 
     379            1 :     return 0;
     380              : }
     381              : 
     382              : } // namespace ioutils
     383              : } // namespace mx
     384              : 
     385              : #endif // binVector_hpp
        

Generated by: LCOV version 2.0-1