11#include <unordered_set>
23 class IBasicCSVParser;
25 static const std::string ERROR_NAN =
"Not a number.";
26 static const std::string ERROR_OVERFLOW =
"Overflow error.";
27 static const std::string ERROR_FLOAT_TO_INT =
28 "Attempted to convert a floating point value to an integral type.";
29 static const std::string ERROR_NEG_TO_UNSIGNED =
"Negative numbers cannot be converted to unsigned types.";
44 operator std::string()
const {
45 return std::string(
"<CSVField> ") + std::string(this->sv);
76 template<
typename T = std::
string> T
get() {
80 throw std::runtime_error(internals::ERROR_NAN);
87 throw std::runtime_error(internals::ERROR_FLOAT_TO_INT);
91 if (this->value < 0) {
92 throw std::runtime_error(internals::ERROR_NEG_TO_UNSIGNED);
102 throw std::runtime_error(internals::ERROR_OVERFLOW);
106 throw std::runtime_error(internals::ERROR_OVERFLOW);
110 return static_cast<T
>(this->value);
148 template<
typename T = std::
string>
164 if (this->value < 0) {
182 out =
static_cast<T
>(this->value);
189 template<
typename T =
long long>
191 static_assert(std::is_integral<T>::value,
192 "try_parse_hex only works with integral types (int, long, long long, etc.)");
193 return internals::try_parse_hex(this->sv, parsedValue);
220 static_assert(std::is_arithmetic<T>::value,
221 "T should be a numeric value.");
223 if (this->_type != DataType::UNKNOWN) {
266 long double value = 0;
269 CONSTEXPR_14
void get_value() noexcept {
273 if ((
int)_type < 0) {
287 CSVRow(internals::RawCSVDataPtr _data) : data(_data) {}
288 CSVRow(internals::RawCSVDataPtr _data,
size_t _data_start,
size_t _field_bounds)
289 : data(_data), data_start(_data_start), fields_start(_field_bounds) {}
290 CSVRow(internals::RawCSVDataPtr _data,
size_t _data_start,
size_t _field_bounds,
size_t _row_length)
291 : data(_data), data_start(_data_start), fields_start(_field_bounds), row_length(_row_length) {}
303 std::string
to_json(
const std::vector<std::string>& subset = {})
const;
304 std::string
to_json_array(
const std::vector<std::string>& subset = {})
const;
308 return this->data->col_names->get_col_names();
322 const std::vector<std::string>& subset
333 operator std::vector<std::string>()
const;
341#ifndef DOXYGEN_SHOULD_SKIP_THIS
343 using difference_type = int;
344 using pointer = std::shared_ptr<CSVField>;
346 using iterator_category = std::random_access_iterator_tag;
350 reference operator*()
const;
351 pointer operator->()
const;
357 iterator operator+(difference_type n)
const;
358 iterator operator-(difference_type n)
const;
362 return this->i == other.i;
372 const CSVRow * daddy =
nullptr;
373 internals::RawCSVDataPtr data =
nullptr;
374 std::shared_ptr<CSVField> field =
nullptr;
393 inline
csv::
string_view get_field_impl(
size_t index, const internals::RawCSVDataPtr& _data)
const {
396 if (index >= this->
size())
397 throw std::runtime_error(
"Index out of bounds.");
399 const size_t field_index = this->fields_start + index;
400 auto field = _data->fields[field_index];
401 auto field_str =
csv::string_view(_data->data).substr(this->data_start + field.start);
403 if (field.has_double_quote) {
404 auto& value = _data->double_quote_fields[field_index];
407 std::lock_guard<std::mutex> lock(_data->double_quote_init_lock);
411 bool prev_ch_quote =
false;
412 for (
size_t i = 0; i < field.length; i++) {
413 if (_data->parse_flags[field_str[i] +
CHAR_OFFSET] == ParseFlags::QUOTE) {
415 prev_ch_quote =
false;
419 prev_ch_quote =
true;
423 value += field_str[i];
431 return field_str.substr(0, field.length);
440 csv::string_view get_field_safe(
size_t index, internals::RawCSVDataPtr _data)
const;
442 internals::RawCSVDataPtr data;
445 size_t data_start = 0;
448 size_t fields_start = 0;
451 size_t row_length = 0;
455#pragma region CSVField::get Specializations
459 inline std::string CSVField::get<std::string>() {
460 return std::string(this->sv);
475 CONSTEXPR_14
long double CSVField::get<long double>() {
477 throw std::runtime_error(internals::ERROR_NAN);
484 inline bool CSVField::try_get<std::string>(std::string& out)
noexcept {
485 out = std::string(this->sv);
498 CONSTEXPR_14
bool CSVField::try_get<long double>(
long double& out)
noexcept {
506#pragma endregion CSVField::get Specializations
513 return this->sv == other;
520 return this->sv == other;
530 os << std::string(value);
Data type representing individual CSV values.
CONSTEXPR_14 bool is_num() noexcept
Returns true if field is an integer or float.
bool try_parse_decimal(long double &dVal, const char decimalSymbol='.')
Attempts to parse a decimal (or integer) value using the given symbol, returning true if the value is...
CONSTEXPR_14 bool is_str() noexcept
Returns true if field is a non-numeric, non-empty string.
CONSTEXPR_14 bool is_int() noexcept
Returns true if field is an integer.
CONSTEXPR_14 bool is_null() noexcept
Returns true if field is an empty string or string of whitespace characters.
constexpr CSVField(csv::string_view _sv) noexcept
Constructs a CSVField from a string_view.
CONSTEXPR_14 DataType type() noexcept
Return the type of the underlying CSV data.
T get()
Returns the value casted to the requested type, performing type checking before.
CONSTEXPR_14 bool operator==(T other) const noexcept
Compares the contents of this field to a numeric value.
bool try_get(T &out) noexcept
Attempts to retrieve the value as the requested type without throwing exceptions.
CONSTEXPR_14 bool is_float() noexcept
Returns true if field is a floating point value.
CONSTEXPR csv::string_view get_sv() const noexcept
Return a string view over the field's contents.
bool try_parse_hex(T &parsedValue)
Parse a hexadecimal value, returning false if the value is not hex.
A random access iterator over the contents of a CSV row.
CONSTEXPR bool operator==(const iterator &other) const noexcept
Two iterators are equal if they point to the same field.
Data structure for representing CSV rows.
iterator end() const noexcept
Return an iterator pointing to just after the end of the CSVRow.
std::reverse_iterator< iterator > reverse_iterator
A reverse iterator over the contents of a CSVRow.
std::string to_json(const std::vector< std::string > &subset={}) const
Convert a CSV row to a JSON object, i.e.
CONSTEXPR bool empty() const noexcept
Indicates whether row is empty or not.
std::string to_json_array(const std::vector< std::string > &subset={}) const
Convert a CSV row to a JSON array, i.e.
std::unordered_map< std::string, std::string > to_unordered_map() const
Convert this CSVRow into an unordered map.
CONSTEXPR size_t size() const noexcept
Return the number of fields in this row.
std::vector< std::string > get_col_names() const
Retrieve this row's associated column names.
CSVField operator[](size_t n) const
Return a CSVField object corrsponding to the nth value in the row.
iterator begin() const
Return an iterator pointing to the first field.
CSVRow(internals::RawCSVDataPtr _data)
Construct a CSVRow from a RawCSVDataPtr.
Abstract base class which provides CSV parsing logic.
A standalone header file containing shared code.
#define IF_CONSTEXPR
Expands to if constexpr in C++17 and if otherwise.
#define CONSTEXPR
Expands to constexpr in decent compilers and inline otherwise.
std::ostream & operator<<(std::ostream &os, csv::CSVField const &value)
Stream insertion helper for CSVField.
Implements data type parsing functionality.
CONSTEXPR_14 DataType data_type(csv::string_view in, long double *const out, const char decimalSymbol)
Distinguishes numeric from other text values.
bool is_equal(T a, T b, T epsilon=0.001)
ParseFlags
An enum used for describing the significance of each character with respect to CSV parsing.
CSV_CONST CONSTEXPR_17 OutArray arrayToDefault(T &&value)
Helper constexpr function to initialize an array with all the elements set to value.
CONSTEXPR_14 long double get_uint_max()
Given a byte size, return the largest number than can be stored in an unsigned integer of that size.
The all encompassing namespace.
DataType
Enumerates the different CSV field types that are recognized by this library.
@ CSV_INT64
64-bit integer (long long on MSVC/GCC)
@ CSV_DOUBLE
Floating point value.
@ CSV_STRING
Non-numeric string.
constexpr unsigned CHAR_OFFSET
Offset to convert char into array index.
nonstd::string_view string_view
The string_view class used by this library.
Implements Functions related to hexadecimal parsing.
Internal data structures for CSV parsing.