Vince's CSV Parser
Loading...
Searching...
No Matches
csv_row.cpp
Go to the documentation of this file.
1
5#include <cassert>
6#include <functional>
7#include "csv_row.hpp"
8
9namespace csv {
10 namespace internals {
11 CSV_INLINE csv::string_view get_trimmed(csv::string_view sv, const WhitespaceMap& ws_flags) noexcept
12 {
13 // Lazy trim only when requested
14 size_t start = 0;
15 while (start < sv.size() && ws_flags[sv[start] + CHAR_OFFSET]) {
16 ++start;
17 }
18
19 size_t end = sv.size();
20 while (end > start && ws_flags[sv[end - 1] + CHAR_OFFSET]) {
21 --end;
22 }
23
24 return sv.substr(start, end - start);
25 }
26 }
27
38 return CSVField(this->get_field(n));
39 }
40
49 auto & col_names = this->data->col_names;
50 auto col_pos = col_names->index_of(col_name);
51 if (col_pos > -1) {
52 return this->operator[](col_pos);
53 }
54
55 throw std::runtime_error("Can't find a column named " + std::string(col_name));
56 }
57
58 CSV_INLINE CSVRow::operator std::vector<std::string>() const {
59 std::vector<std::string> ret;
60 for (size_t i = 0; i < size(); i++)
61 ret.push_back(std::string(this->get_field(i)));
62
63 return ret;
64 }
65
67 if (!data) return csv::string_view();
68 const csv::string_view full = data->data;
69 if (data_start >= full.size()) return csv::string_view();
70 const size_t end = full.find('\n', data_start);
71 const size_t len = (end == csv::string_view::npos)
72 ? (full.size() - data_start)
73 : (end - data_start);
74 return full.substr(data_start, len);
75 }
76
78 CSV_INLINE std::unordered_map<std::string, std::string> CSVRow::to_unordered_map() const {
79 std::unordered_map<std::string, std::string> row_map;
80 row_map.reserve(this->size());
81
82 for (size_t i = 0; i < this->size(); i++) {
83 auto col_name = (*this->data->col_names)[i];
84 row_map[col_name] = this->operator[](i).get<std::string>();
85 }
86
87 return row_map;
88 }
89
91 CSV_INLINE std::unordered_map<std::string, std::string> CSVRow::to_unordered_map(
92 const std::vector<std::string>& subset
93 ) const {
94 std::unordered_map<std::string, std::string> row_map;
95 row_map.reserve(subset.size());
96
97 for (const auto& col_name : subset)
98 row_map[col_name] = this->operator[](col_name).get<std::string>();
99
100 return row_map;
101 }
102
103 CSV_INLINE csv::string_view CSVRow::get_field(size_t index) const
104 {
105 return this->get_field_impl(index, this->data);
106 }
107
108 CSV_INLINE csv::string_view CSVRow::get_field_safe(size_t index, internals::RawCSVDataPtr _data) const
109 {
110 return this->get_field_impl(index, _data);
111 }
112
113 CSV_INLINE bool CSVField::try_parse_decimal(long double& dVal, const char decimalSymbol) {
114 // If field has already been parsed to empty, no need to do it aagin:
115 if (this->_type == DataType::CSV_NULL)
116 return false;
117
118 // Not yet parsed or possibly parsed with other decimalSymbol
119 if (this->_type == DataType::UNKNOWN || this->_type == DataType::CSV_STRING || this->_type == DataType::CSV_DOUBLE)
120 this->_type = internals::data_type(this->sv, &this->value, decimalSymbol); // parse again
121
122 // Integral types are not affected by decimalSymbol and need not be parsed again
123
124 // Either we already had an integral type before, or we we just got any numeric type now.
125 if (this->_type >= DataType::CSV_INT8 && this->_type <= DataType::CSV_DOUBLE) {
126 dVal = this->value;
127 return true;
128 }
129
130 // CSV_NULL or CSV_STRING, not numeric
131 return false;
132 }
133
134#ifdef _MSC_VER
135#pragma region CSVRow Iterator
136#endif
139 return CSVRow::iterator(this, 0);
140 }
141
148 return CSVRow::iterator(this, (int)this->size());
149 }
150
151 CSV_INLINE CSVRow::reverse_iterator CSVRow::rbegin() const noexcept {
152 return std::reverse_iterator<CSVRow::iterator>(this->end());
153 }
154
155 CSV_INLINE CSVRow::reverse_iterator CSVRow::rend() const {
156 return std::reverse_iterator<CSVRow::iterator>(this->begin());
157 }
158
159 CSV_INLINE CSV_NON_NULL(2)
160 CSVRow::iterator::iterator(const CSVRow* _reader, int _i)
161 : daddy(_reader), data(_reader->data), i(_i) {
162 if (_i < (int)this->daddy->size())
163 this->field = std::make_shared<CSVField>(
164 CSVField(this->daddy->get_field_safe(_i, this->data)));
165 else
166 this->field = nullptr;
167 }
168
169 CSV_INLINE CSVRow::iterator::reference CSVRow::iterator::operator*() const {
170 return *(this->field.get());
171 }
172
173 CSV_INLINE CSVRow::iterator::pointer CSVRow::iterator::operator->() const {
174 return this->field;
175 }
176
177 CSV_INLINE CSVRow::iterator& CSVRow::iterator::operator++() {
178 // Pre-increment operator
179 this->i++;
180 if (this->i < (int)this->daddy->size())
181 this->field = std::make_shared<CSVField>(
182 CSVField(this->daddy->get_field_safe(i, this->data)));
183 else // Reached the end of row
184 this->field = nullptr;
185 return *this;
186 }
187
188 CSV_INLINE CSVRow::iterator CSVRow::iterator::operator++(int) {
189 // Post-increment operator
190 auto temp = *this;
191 this->operator++();
192 return temp;
193 }
194
195 CSV_INLINE CSVRow::iterator& CSVRow::iterator::operator--() {
196 // Pre-decrement operator
197 this->i--;
198 this->field = std::make_shared<CSVField>(
199 CSVField(this->daddy->get_field_safe(this->i, this->data)));
200 return *this;
201 }
202
203 CSV_INLINE CSVRow::iterator CSVRow::iterator::operator--(int) {
204 // Post-decrement operator
205 auto temp = *this;
206 this->operator--();
207 return temp;
208 }
209
210 CSV_INLINE CSVRow::iterator CSVRow::iterator::operator+(difference_type n) const {
211 // Allows for iterator arithmetic
212 return CSVRow::iterator(this->daddy, i + (int)n);
213 }
214
215 CSV_INLINE CSVRow::iterator CSVRow::iterator::operator-(difference_type n) const {
216 // Allows for iterator arithmetic
217 return CSVRow::iterator::operator+(-n);
218 }
219#ifdef _MSC_VER
220#pragma endregion CSVRow Iterator
221#endif
222}
Data type representing individual CSV values.
Definition csv_row.hpp:67
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...
Definition csv_row.cpp:113
T get()
Returns the value casted to the requested type, performing type checking before.
Definition csv_row.hpp:108
A random access iterator over the contents of a CSV row.
Definition csv_row.hpp:336
iterator end() const noexcept
Return an iterator pointing to just after the end of the CSVRow.
Definition csv_row.cpp:147
std::reverse_iterator< iterator > reverse_iterator
A reverse iterator over the contents of a CSVRow.
Definition csv_row.hpp:376
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,...
Definition csv_row.cpp:66
std::unordered_map< std::string, std::string > to_unordered_map() const
Convert this CSVRow into an unordered map.
Definition csv_row.cpp:78
CONSTEXPR size_t size() const noexcept
Return the number of fields in this row.
Definition csv_row.hpp:281
CSVField operator[](size_t n) const
Return a CSVField object corrsponding to the nth value in the row.
Definition csv_row.cpp:37
iterator begin() const
Return an iterator pointing to the first field.
Definition csv_row.cpp:138
#define CSV_INLINE
Helper macro which should be #defined as "inline" in the single header version.
Definition common.hpp:26
Defines the data type used for storing information about a CSV row.
The all encompassing namespace.
@ CSV_DOUBLE
Floating point value.
@ CSV_NULL
Empty string.
@ CSV_INT8
8-bit integer
@ CSV_STRING
Non-numeric string.
constexpr unsigned CHAR_OFFSET
Offset to convert char into array index.
Definition common.hpp:299
nonstd::string_view string_view
The string_view class used by this library.
Definition common.hpp:135