16 while (start < sv.size() && ws_flags[sv[start] +
CHAR_OFFSET]) {
20 size_t end = sv.size();
21 while (end > start && ws_flags[sv[end - 1] +
CHAR_OFFSET]) {
25 return sv.substr(start, end - start);
29#if CSV_EXCEPTIONS_ENABLED
31 if (n >= this->
size())
throw std::runtime_error(internals::CSV_ERROR_INDEX_OUT_OF_BOUNDS);
32 return this->make_field(n, this->data);
36#if CSV_EXCEPTIONS_ENABLED
38 auto & col_names = this->data->col_names;
39 auto col_pos = col_names->index_of(col_name);
44 internals::throw_column_not_found(col_name);
49 if (index >=
size()) {
53 return make_field(index, data);
58 const int index = data && data->col_names ? data->col_names->index_of(name) :
CSV_NOT_FOUND;
61 internals::make_prefixed_message(internals::ERROR_COLUMN_NOT_FOUND, name));
64 return try_field(
static_cast<size_t>(index), error);
67 CSVRow::operator std::vector<std::string>()
const {
68 std::vector<std::string> ret;
69 for (
size_t i = 0; i < size(); i++)
70 ret.push_back(std::string(this->get_field(i)));
80 if (data_end != (std::numeric_limits<size_t>::max)()
81 && data_end >= data_start
82 && data_end <= full.size()) {
83 return full.substr(data_start, data_end - data_start);
86 const size_t end = full.find(
'\n', data_start);
87 const size_t len = (end == csv::string_view::npos)
88 ? (full.size() - data_start)
90 return full.substr(data_start, len);
94 return to_unordered_map_impl(
nullptr, error);
98 CSVError& error,
const std::vector<std::string>& subset)
const {
99 return to_unordered_map_impl(&subset, error);
102 std::unordered_map<std::string, std::string> CSVRow::to_unordered_map_impl(
103 const std::vector<std::string>* subset, CSVError& error)
const {
105 std::unordered_map<std::string, std::string> out;
107 if (!data || !data->col_names)
return out;
109 if (names.size() <
size()) {
114 for (
size_t i = 0; i <
size(); ++i) out[names[i]] = std::string(get_field(i));
116 out.reserve(subset->size());
117 for (
const auto& name : *subset) {
119 if (error)
return out;
120 out[name] = std::string(field.get_sv());
126#if CSV_EXCEPTIONS_ENABLED
130 if (error)
throw std::out_of_range(std::string(error.context));
135 const std::vector<std::string>& subset)
const {
138 internals::throw_error(error);
145 return this->get_field_impl(index, this->data);
148 csv::string_view CSVRow::get_field_safe(
size_t index, internals::RawCSVDataPtr _data)
const
150 return this->get_field_impl(index, _data);
153 CSVField CSVRow::make_field(
size_t index,
const internals::RawCSVDataPtr& _data)
const
156 const size_t field_index = this->fields_start + index;
157 if (_data->has_field_scalars() && field_index < _data->field_scalars.size()) {
158 return CSVField(field, _data->field_scalars[field_index]);
161 return CSVField(field);
169 if (this->type_ == DataType::UNKNOWN)
176 double parsed_value = 0;
177 if (!classify_scalar::parse_float(this->sv.data(), this->sv.data() + this->sv.size(), parsed_value, decimalSymbol)) {
190 dVal = this->numeric_value_as_long_double();
199 if (this->type_ == DataType::UNKNOWN)
203 out = this->value_.timestamp;
207 if (this->stores_integral() && this->value_.integer >= 0) {
208 out =
static_cast<std::uint64_t
>(this->value_.integer);
216#pragma region CSVRow Iterator
219 return iterator(
this, 0);
222 CSVRow::iterator CSVRow::end() const noexcept {
223 return iterator(
this,
static_cast<iterator::difference_type
>(this->
size()));
226 CSVRow::reverse_iterator CSVRow::rbegin() const noexcept {
227 return reverse_iterator(this->end());
230 CSVRow::reverse_iterator CSVRow::rend() const noexcept {
231 return reverse_iterator(this->begin());
234 CSVRow::iterator::pointer::pointer(
const CSVField& field) noexcept
237 CSVField* CSVRow::iterator::pointer::operator->() noexcept {
238 return &this->field_;
241 const CSVField* CSVRow::iterator::pointer::operator->() const noexcept {
242 return &this->field_;
246 CSVRow::iterator::iterator(const CSVRow* row, difference_type index) noexcept
247 : data_(row->data), data_start_(row->data_start),
248 fields_start_(row->fields_start), row_length_(row->row_length), index_(index) {}
250 CSVRow::iterator::reference CSVRow::iterator::operator*()
const {
253 const CSVRow snapshot(this->data_, this->data_start_, this->fields_start_, this->row_length_);
254 return snapshot.make_field(
static_cast<size_t>(this->index_), this->data_);
257 CSVRow::iterator::pointer CSVRow::iterator::operator->()
const {
258 return pointer(**
this);
261 CSVRow::iterator::reference CSVRow::iterator::operator[](difference_type n)
const {
265 CSVRow::iterator& CSVRow::iterator::operator++() noexcept {
269 CSVRow::iterator CSVRow::iterator::operator++(
int)
noexcept {
270 iterator previous = *
this;
275 CSVRow::iterator& CSVRow::iterator::operator--() noexcept {
279 CSVRow::iterator CSVRow::iterator::operator--(
int)
noexcept {
280 iterator previous = *
this;
285 CSVRow::iterator CSVRow::iterator::operator+(difference_type n)
const noexcept {
286 iterator result = *
this;
291 CSVRow::iterator& CSVRow::iterator::operator+=(difference_type n)
noexcept {
296 CSVRow::iterator CSVRow::iterator::operator-(difference_type n)
const noexcept {
297 iterator result = *
this;
302 CSVRow::iterator& CSVRow::iterator::operator-=(difference_type n)
noexcept {
307 CSVRow::iterator::difference_type CSVRow::iterator::operator-(
const iterator& other)
const noexcept {
308 return this->index_ - other.index_;
311 CSVRow::iterator operator+(CSVRow::iterator::difference_type n,
const CSVRow::iterator& it)
noexcept {
315 bool CSVRow::iterator::operator==(
const iterator& other)
const noexcept {
316 return this->data_ == other.data_ && this->data_start_ == other.data_start_
317 && this->fields_start_ == other.fields_start_ && this->row_length_ == other.row_length_
318 && this->index_ == other.index_;
321 bool CSVRow::iterator::operator!=(
const iterator& other)
const noexcept {
322 return !(*
this == other);
325 bool CSVRow::iterator::operator<(
const iterator& other)
const noexcept {
326 return this->index_ < other.index_;
329 bool CSVRow::iterator::operator>(
const iterator& other)
const noexcept {
330 return other < *
this;
333 bool CSVRow::iterator::operator<=(
const iterator& other)
const noexcept {
334 return !(other < *
this);
337 bool CSVRow::iterator::operator>=(
const iterator& other)
const noexcept {
338 return !(*
this < other);
341 CSVRow::reverse_iterator::reverse_iterator(iterator base) noexcept
342 : base_(std::move(base)) {}
344 CSVRow::reverse_iterator::reference CSVRow::reverse_iterator::operator*()
const {
345 return this->base_[-1];
348 CSVRow::reverse_iterator::pointer CSVRow::reverse_iterator::operator->()
const {
349 return pointer(**
this);
352 CSVRow::reverse_iterator::reference CSVRow::reverse_iterator::operator[](difference_type n)
const {
356 CSVRow::reverse_iterator& CSVRow::reverse_iterator::operator++() noexcept {
360 CSVRow::reverse_iterator CSVRow::reverse_iterator::operator++(
int)
noexcept {
361 reverse_iterator previous = *
this;
366 CSVRow::reverse_iterator& CSVRow::reverse_iterator::operator--() noexcept {
370 CSVRow::reverse_iterator CSVRow::reverse_iterator::operator--(
int)
noexcept {
371 reverse_iterator previous = *
this;
376 CSVRow::reverse_iterator CSVRow::reverse_iterator::operator+(difference_type n)
const noexcept {
377 return reverse_iterator(this->base_ - n);
380 CSVRow::reverse_iterator& CSVRow::reverse_iterator::operator+=(difference_type n)
noexcept {
385 CSVRow::reverse_iterator CSVRow::reverse_iterator::operator-(difference_type n)
const noexcept {
386 return reverse_iterator(this->base_ + n);
389 CSVRow::reverse_iterator& CSVRow::reverse_iterator::operator-=(difference_type n)
noexcept {
394 CSVRow::reverse_iterator::difference_type
395 CSVRow::reverse_iterator::operator-(
const reverse_iterator& other)
const noexcept {
396 return other.base_ - this->base_;
399 CSVRow::reverse_iterator operator+(
400 CSVRow::reverse_iterator::difference_type n,
const CSVRow::reverse_iterator& it)
noexcept {
404 bool CSVRow::reverse_iterator::operator==(
const reverse_iterator& other)
const noexcept {
405 return this->base_ == other.base_;
408 bool CSVRow::reverse_iterator::operator!=(
const reverse_iterator& other)
const noexcept {
409 return !(*
this == other);
412 bool CSVRow::reverse_iterator::operator<(
const reverse_iterator& other)
const noexcept {
413 return other.base_ < this->base_;
416 bool CSVRow::reverse_iterator::operator>(
const reverse_iterator& other)
const noexcept {
417 return other < *
this;
420 bool CSVRow::reverse_iterator::operator<=(
const reverse_iterator& other)
const noexcept {
421 return !(other < *
this);
424 bool CSVRow::reverse_iterator::operator>=(
const reverse_iterator& other)
const noexcept {
425 return !(*
this < other);
432#pragma endregion CSVRow Iterator
Data type representing individual CSV values.
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...
bool try_parse_timestamp(std::uint64_t &out) const noexcept
Parse this field as Unix milliseconds.
Iterator producing short-lived CSVField values with independent lazy conversion caches.
iterator base() const noexcept
The forward iterator one past the field this iterator produces.
CSVField try_field(size_t index, CSVError &error) const
Checked field retrieval.
csv::string_view raw_str() const noexcept
Return a string_view of the raw bytes of this row as they appear in the underlying parse buffer,...
const std::vector< std::string > & get_col_names() const
Retrieve this row's associated column names.
std::unordered_map< std::string, std::string > try_to_unordered_map(CSVError &error) const
Materialize named values; unknown names or absent header positions report an error.
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.
CSVField operator[](size_t n) const
Return the field at n.
Shared exception message templates and throw helpers.
Defines the data type used for storing information about a CSV row.
The all encompassing namespace.
@ CSV_TIMESTAMP
Timestamp value.
@ CSV_DOUBLE
Floating point value.
@ CSV_STRING
Non-scalar string.
@ IndexOutOfBounds
A row/column position exceeds the visible schema or physical record width.
@ ColumnNotFound
A requested name is absent from the visible column schema.
constexpr int CSV_NOT_FOUND
Integer indicating a requested column wasn't found.
constexpr unsigned CHAR_OFFSET
Offset to convert char into array index.
std::string_view string_view
The string_view class used by this library.
A diagnostic whose text remains valid for the lifetime of the error.