26#ifndef __readColumns_hpp__
27#define __readColumns_hpp__
34#include "../mxlib.hpp"
38#define MX_READCOL_MISSINGVALSTR "-99"
45struct readColSpaceDelim
47 static constexpr char delim =
' ';
48 static constexpr char strDelim =
'"';
49 static constexpr char eol =
'\n';
50 static constexpr char comment =
'#';
51 static constexpr const char *missingValStr = MX_READCOL_MISSINGVALSTR;
54struct readColCommaDelim
56 static constexpr char delim =
',';
57 static constexpr char strdelim =
'"';
58 static constexpr char eol =
'\n';
59 static constexpr char comment =
'#';
60 static constexpr const char *missingValStr = MX_READCOL_MISSINGVALSTR;
63template <
class delimT,
class verboseT>
64error_t readcol( [[maybe_unused]]
const char *sin, [[maybe_unused]]
int sz, [[maybe_unused]]
int & colno )
69template <
class delimT,
class verboseT,
typename arrT,
typename... arrTs>
70error_t readcol(
const char *sin,
int sz,
int & colno, arrT &array, arrTs &...arrays )
79 int l = strlen( sin );
87 while( isspace( sin[i] ) && sin[i] != delimT::eol && i < l )
97 array.push_back( convertFromString<typename arrT::value_type>(
"" ) );
101 std::stringstream sinstr( sin );
103 std::getline( sinstr, str, delimT::delim );
106 if( str[str.size() - 1] == delimT::eol )
108 str.erase( str.size() - 1 );
111 if( str.size() == 0 )
113 array.push_back( convertFromString<typename arrT::value_type>( MX_READCOL_MISSINGVALSTR ) );
117 array.push_back( convertFromString<typename arrT::value_type>( str ) );
120 sin += ( str.size() + 1 ) *
sizeof(
char );
121 sz -= ( str.size() + 1 ) *
sizeof(
char );
123 catch(
const std::invalid_argument &e )
126 std::format(
"processing column {}: {}", colno, e.what() ) );
128 catch(
const std::out_of_range &e )
131 std::format(
"processing column {}: {}", colno, e.what() ) );
133 catch(
const std::exception &e )
136 std::format(
"processing column {}: {}", colno, e.what() ) );
140 return internal::mxlib_error_report<verboseT>(
error_t::exception, std::format(
"processing column {}.", colno ) );
144 return readcol<delimT, verboseT>( sin, sz, colno, arrays... );
179template <
class delimT = readColSpaceDelim,
class verboseT = verbose::vvv,
typename... arrTs>
203 return internal::mxlib_error_report<verboseT>( errc,
"Opening " + fname +
" for reading" );
215 std::getline( fin, line, delimT::eol );
217 catch(
const std::exception &e )
219 return internal::mxlib_error_report<verboseT>(
221 std::format(
"Reading from {} at line {}. {}.", fname, lineno, e.what() ) );
225 return internal::mxlib_error_report<verboseT>(
227 std::format(
"Reading from {} at line {}.", fname, lineno ) );
230 if( line.size() == 0 )
237 bool nonspace =
false;
238 while( i < line.size() && line[i] != delimT::comment )
240 if( !nonspace && !isspace( line[i] ) )
248 if( i == 0 || !nonspace )
253 if( i < line.size() )
255 line.erase( line.begin() + i, line.end() );
259 error_t errc = readcol<delimT, verboseT>( line.c_str(), line.size(), colno, arrays... );
263 return internal::mxlib_error_report<verboseT>( errc, std::format(
"Reading from {} at line {} column {}",fname, lineno+1, colno+1) );
268 if( fin.bad() && !fin.fail() )
280 return internal::mxlib_error_report<verboseT>( errc,
"Reading from " + fname );
299 return internal::mxlib_error_report<verboseT>( errc,
"Closing" + fname );
320 template <
typename T>
321 void push_back(
const T &arg )
error_t readColumns(const std::string &fname, arrTs &...arrays)
Read in columns from a text file.
error_t
The mxlib error codes.
static constexpr error_t errno2error_t(const int &err)
Convert an errno code to error_t.
@ noerror
No error has occurred.
@ filererr
An error occurred while reading from a file.
@ exception
An exception was thrown.
@ filecerr
An error occurred while closing a file.
@ fileoerr
An error occurred while opening a file.
@ std_out_of_range
An out of range exception was thrown.
@ std_invalid_argument
An invalid argument exception was thrown.
Utilities for working with strings.
A dummy class to allow mx::readColumns to skip a column(s) in a file without requiring memory allocat...
std::string value_type
value_type is defined as std::string so that no conversions take place.