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 )
77 int l = strlen( sin );
85 while( isspace( sin[i] ) && sin[i] != delimT::eol && i < l )
96 array.push_back( stoT<typename arrT::value_type>(
"", &errc ) );
100 return internal::mxlib_error_report<verboseT>( errc, std::format(
"processing column {}", colno ) );
106 std::stringstream sinstr( sin );
108 std::getline( sinstr, str, delimT::delim );
111 if( str[str.size() - 1] == delimT::eol )
113 str.erase( str.size() - 1 );
117 if( str.size() == 0 )
119 array.push_back( stoT<typename arrT::value_type>( MX_READCOL_MISSINGVALSTR, &errc ) );
123 array.push_back( stoT<typename arrT::value_type>( str, &errc ) );
128 return internal::mxlib_error_report<verboseT>( errc, std::format(
"processing column {}", colno ) );
131 sin += ( str.size() + 1 ) *
sizeof(
char );
132 sz -= ( str.size() + 1 ) *
sizeof(
char );
134 catch(
const std::invalid_argument &e )
138 std::format(
"processing column {}: {}", colno, e.what() ) );
140 catch(
const std::out_of_range &e )
144 std::format(
"processing column {}: {}", colno, e.what() ) );
146 catch(
const std::bad_alloc &e )
150 #if defined( MXLIB_CATCH_ALL_EXCEPTIONS )
152 std::format(
"processing column {}: {}", colno, e.what() ) );
155 std::format(
"processing column {}: {}", colno, e.what() ) ));
159 catch(
const std::exception &e )
162 #if defined( MXLIB_CATCH_ALL_EXCEPTIONS ) || defined( MXLIB_CATCH_NONALLOC_EXCEPTIONS )
164 std::format(
"processing column {}: {}", colno, e.what() ) );
168 std::format(
"processing column {}: {}", colno, e.what() ) ));
176 #if defined( MXLIB_CATCH_ALL_EXCEPTIONS ) || defined( MXLIB_CATCH_NONALLOC_EXCEPTIONS )
178 std::format(
"processing column {}", colno) );
182 std::format(
"processing column {}", colno) ));
188 return readcol<delimT, verboseT>( sin, sz, colno, arrays... );
220template <
class delimT = readColSpaceDelim,
class verboseT =
verbose::d,
typename... arrTs>
244 return internal::mxlib_error_report<verboseT>( errc,
"Opening " + fname +
" for reading" );
256 std::getline( fin, line, delimT::eol );
258 catch(
const std::bad_alloc &e )
262 #if defined( MXLIB_CATCH_ALL_EXCEPTIONS )
264 std::format(
"Reading from {} at line {}: {}.",
265 fname, lineno, e.what() ) );
269 std::format(
"Reading from {} at line {}: {}.",
270 fname, lineno, e.what() ) ) );
274 catch(
const std::exception &e )
278 #if defined( MXLIB_CATCH_ALL_EXCEPTIONS ) || defined(MXLIB_CATCH_NONALLOC_EXCEPTIONS)
281 std::format(
"Reading from {} at line {}: {}.",
287 std::format(
"Reading from {} at line {}: {}.",
288 fname, lineno, e.what() ) ) );
296 #if defined( MXLIB_CATCH_ALL_EXCEPTIONS ) || defined(MXLIB_CATCH_NONALLOC_EXCEPTIONS)
299 std::format(
"Reading from {} at line {}",
304 std::format(
"Reading from {} at line {}",
310 if( line.size() == 0 )
317 bool nonspace =
false;
318 while( i < line.size() && line[i] != delimT::comment )
320 if( !nonspace && !isspace( line[i] ) )
328 if( i == 0 || !nonspace )
333 if( i < line.size() )
335 line.erase( line.begin() + i, line.end() );
339 error_t errc = readcol<delimT, verboseT>( line.c_str(), line.size(), colno, arrays... );
343 return internal::mxlib_error_report<verboseT>(
345 std::format(
"Reading from {} at line {} column {}", fname, lineno + 1, colno + 1 ) );
350 if( fin.bad() && !fin.fail() )
362 return internal::mxlib_error_report<verboseT>( errc,
"Reading from " + fname );
381 return internal::mxlib_error_report<verboseT>( errc,
"Closing" + fname );
402 template <
typename T>
403 void push_back(
const T &arg )
Augments an exception with the source file and line.
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.
@ std_exception
An exception was thrown.
@ filererr
An error occurred while reading from a file.
@ exception
An exception was thrown.
@ std_bad_alloc
A bad allocation 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.
MXLIB_DEFAULT_VERBOSITY d
The default verbosity.
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.