2024-12-01 19:35:24 +00:00
|
|
|
//| Copyright: (C) 2020-2024 Kevin Larke <contact AT larke DOT org>
|
|
|
|
//| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
|
2023-05-12 01:09:04 +00:00
|
|
|
#ifndef cwCsv_h
|
|
|
|
#define cwCsv_h
|
|
|
|
|
|
|
|
namespace cw
|
|
|
|
{
|
|
|
|
namespace csv
|
|
|
|
{
|
|
|
|
typedef handle<struct csv_str> handle_t;
|
|
|
|
|
2023-05-12 13:00:50 +00:00
|
|
|
// The first line of the CSV is expected to hold the column titles.
|
|
|
|
// If titlesA and titleN are valid then these will be verified to exist when the CSV file is opened.
|
2023-05-12 01:09:04 +00:00
|
|
|
rc_t create( handle_t& hRef, const char* fname, const char** titleA=nullptr, unsigned titleN=0 );
|
|
|
|
|
|
|
|
rc_t destroy(handle_t& hRef );
|
|
|
|
|
2023-05-12 13:00:50 +00:00
|
|
|
// Count of lines in the CSV including the title line.
|
|
|
|
// Subtract 1 to get the count of data lines.
|
2023-05-12 01:09:04 +00:00
|
|
|
rc_t line_count( handle_t h, unsigned& lineCntRef );
|
|
|
|
|
2023-05-12 13:00:50 +00:00
|
|
|
// Count of columns in the first row (title row).
|
|
|
|
unsigned col_count( handle_t h );
|
|
|
|
|
|
|
|
const char* col_title( handle_t h, unsigned idx );
|
2023-05-12 01:09:04 +00:00
|
|
|
unsigned title_col_index( handle_t h, const char* title );
|
2024-01-28 18:20:10 +00:00
|
|
|
bool has_field( handle_t h, const char* title );
|
2023-05-12 01:09:04 +00:00
|
|
|
|
2023-05-12 13:00:50 +00:00
|
|
|
// Reset the CSV to make the title line current.
|
|
|
|
// The next call to 'next_line()' will make the first data row current.
|
2023-05-12 01:09:04 +00:00
|
|
|
rc_t rewind( handle_t h );
|
2023-05-12 13:00:50 +00:00
|
|
|
|
|
|
|
// Make the next row current. The 'getv()' and parse_???()' functions
|
|
|
|
// operate on the current row.
|
|
|
|
// This function return kEofRC when it increments past the last line in the file.
|
2023-05-12 01:09:04 +00:00
|
|
|
rc_t next_line( handle_t h );
|
|
|
|
|
2023-07-26 00:19:59 +00:00
|
|
|
// line index (first line==0) of the line currently bei[ng parsed.
|
2023-05-12 01:09:04 +00:00
|
|
|
unsigned cur_line_index( handle_t h );
|
|
|
|
|
2023-05-12 13:00:50 +00:00
|
|
|
// Return the count of characters in the field identified by 'colIdx'.
|
2023-05-12 01:09:04 +00:00
|
|
|
rc_t field_char_count( handle_t h, unsigned colIdx, unsigned& charCntRef );
|
|
|
|
|
2023-07-26 00:19:59 +00:00
|
|
|
rc_t parse_field( handle_t h, unsigned colIdx, uint8_t& valRef );
|
2023-05-12 01:09:04 +00:00
|
|
|
rc_t parse_field( handle_t h, unsigned colIdx, unsigned& valRef );
|
|
|
|
rc_t parse_field( handle_t h, unsigned colIdx, int& valRef );
|
|
|
|
rc_t parse_field( handle_t h, unsigned colIdx, double& valRef );
|
2024-02-20 02:57:54 +00:00
|
|
|
rc_t parse_field( handle_t h, unsigned colIdx, bool& valRef );
|
|
|
|
|
2023-07-26 00:19:59 +00:00
|
|
|
|
|
|
|
// The returned pointer is a pointer into an internal 'line' buffer.
|
|
|
|
// The reference is therefore only valid until the next call to next_line().
|
2023-05-12 01:09:04 +00:00
|
|
|
rc_t parse_field( handle_t h, unsigned colIdx, const char*& valRef );
|
|
|
|
|
2023-07-26 00:19:59 +00:00
|
|
|
rc_t parse_field( handle_t h, const char* colLabel, uint8_t& valRef );
|
2023-05-12 01:09:04 +00:00
|
|
|
rc_t parse_field( handle_t h, const char* colLabel, unsigned& valRef );
|
|
|
|
rc_t parse_field( handle_t h, const char* colLabel, int& valRef );
|
|
|
|
rc_t parse_field( handle_t h, const char* colLabel, double& valRef );
|
2024-02-20 02:57:54 +00:00
|
|
|
rc_t parse_field( handle_t h, const char* colLabel, bool& valRef );
|
2023-07-26 00:19:59 +00:00
|
|
|
|
|
|
|
// The returned pointer is a pointer into an internal 'line' buffer.
|
|
|
|
// The reference is therefore only valid until the next call to next_line().
|
2023-05-12 01:09:04 +00:00
|
|
|
rc_t parse_field( handle_t h, const char* colLabel, const char*& valRef );
|
|
|
|
|
|
|
|
inline rc_t _getv(handle_t) { return kOkRC; }
|
|
|
|
|
|
|
|
// getv("label0",v0,"label1",v1, ... )
|
|
|
|
template< typename T0, typename T1, typename... ARGS >
|
|
|
|
rc_t _getv( handle_t h, T0 label, T1& valRef, ARGS&&... args )
|
|
|
|
{
|
|
|
|
rc_t rc = parse_field(h,label,valRef);
|
|
|
|
|
|
|
|
// if no error occurred ....
|
|
|
|
if( rc == kOkRC )
|
|
|
|
rc = _getv(h,std::forward<ARGS>(args)...); // ... recurse to find next label/value pair
|
|
|
|
else
|
|
|
|
rc = cwLogError(rc,"CSV parse failed for column label:'%s' on line index:%i.",cwStringNullGuard(label),cur_line_index(h));
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
// getv("label0",v0,"label1",v1, ... )
|
|
|
|
template< typename T0, typename T1, typename... ARGS >
|
|
|
|
rc_t getv( handle_t h, T0 label, T1& valRef, ARGS&&... args )
|
|
|
|
{ return _getv(h,label,valRef,args...); }
|
|
|
|
|
|
|
|
rc_t test( const object_t* args );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|