Vince's CSV Parser
Loading...
Searching...
No Matches
data_frame_cell.hpp
1#pragma once
2
3#include <stdexcept>
4#include <string>
5#include <utility>
6
7#include "../csv_exceptions.hpp"
8#include "../csv_row.hpp"
9#include "data_frame_storage.hpp"
10#include "fwd.hpp"
11#include "row_overlay.hpp"
12
13namespace csv {
14 class DataFrameCell : public CSVField {
15 public:
16#if CSV_EXCEPTIONS_ENABLED
17 using CSVField::get;
18#endif
19 using CSVField::get_sv;
21 using CSVField::is_int;
23 using CSVField::is_num;
24 using CSVField::is_str;
26 using CSVField::type;
27
28 DataFrameCell() : CSVField(csv::string_view()), row_(nullptr), edit_context_(nullptr), col_index_(0), can_mutate_(false) {}
29
30 DataFrameCell(const DataFrameCell& other)
32 row_(other.row_),
33 edit_context_(other.edit_context_),
34 col_index_(other.col_index_),
35 can_mutate_(other.can_mutate_),
36 frame_bound_(other.frame_bound_),
37 owned_value_(other.owned_value_) {
38 this->refresh_value();
39 }
40
41 DataFrameCell(DataFrameCell&& other) noexcept
43 row_(other.row_),
44 edit_context_(other.edit_context_),
45 col_index_(other.col_index_),
46 can_mutate_(other.can_mutate_),
47 frame_bound_(other.frame_bound_),
48 owned_value_(std::move(other.owned_value_)) {
49 this->refresh_value();
50 }
51
53 const CSVRow* _row,
54 RowOverlay* _row_overlay,
55 size_t _col_index
57 row_(_row),
58 edit_context_(_row_overlay),
59 col_index_(_col_index),
60 can_mutate_(true) {
61 this->refresh_value(_row_overlay);
62 }
63
65 const CSVRow* _row,
66 const RowOverlay* _row_overlay,
67 size_t _col_index
69 row_(_row),
70 edit_context_(_row_overlay),
71 col_index_(_col_index),
72 can_mutate_(false) {
73 this->refresh_value(_row_overlay);
74 }
75
76 DataFrameCell& operator=(const DataFrameCell& other) {
77 if (this != &other) {
78 row_ = other.row_;
79 edit_context_ = other.edit_context_;
80 col_index_ = other.col_index_;
81 can_mutate_ = other.can_mutate_;
82 owned_value_ = other.owned_value_;
83 frame_bound_ = other.frame_bound_;
84 this->refresh_value();
85 }
86
87 return *this;
88 }
89
90 DataFrameCell& operator=(DataFrameCell&& other) noexcept {
91 if (this != &other) {
92 row_ = other.row_;
93 edit_context_ = other.edit_context_;
94 col_index_ = other.col_index_;
95 can_mutate_ = other.can_mutate_;
96 owned_value_ = std::move(other.owned_value_);
97 frame_bound_ = other.frame_bound_;
98 this->refresh_value();
99 }
100
101 return *this;
102 }
103
104#if CSV_EXCEPTIONS_ENABLED
105 DataFrameCell& operator=(csv::string_view value) {
106 CSVError error;
107 this->try_assign(value, error);
108 internals::throw_dataframe_error(error);
109 return *this;
110 }
111#endif
112
115 error.clear();
116 if (!can_mutate_ || !edit_context_)
117 return internals::fail_static(error, CSVErrorCode::ReadOnlyProxy, internals::ERROR_CANNOT_EDIT_CONST_DF_CELL);
118 this->assign(std::string(value));
119 return true;
120 }
121
123#if CSV_EXCEPTIONS_ENABLED
124 template<typename T = std::string>
125 T get() const {
126 return CSVField::template get<T>();
127 }
128#endif
129
130 bool is_null() const noexcept {
131 return CSVField::is_null();
132 }
133
134 bool is_str() const noexcept {
135 return CSVField::is_str();
136 }
137
138 bool is_num() const noexcept {
139 return CSVField::is_num();
140 }
141
142 bool is_int() const noexcept {
143 return CSVField::is_int();
144 }
145
146 bool is_float() const noexcept {
147 return CSVField::is_float();
148 }
149
150 DataType type() const noexcept {
151 return CSVField::type();
152 }
153
154 template<typename T>
155 bool try_get(T& out) const noexcept {
156 return CSVField::template try_get<T>(out);
157 }
158
159 template<typename T>
160 bool try_get(T& out, CSVConversionError& error) const noexcept {
161 return CSVField::template try_get<T>(out, error);
162 }
163
164 private:
165 template<typename KeyType> friend class DataFrame;
166
167 // Frame-bound cells can defer overlay allocation until assignment. Cell
168 // reads retain the existing snapshot semantics; row proxies resolve afresh.
169 DataFrameCell(
170 const CSVRow* source, const RowOverlay* overlay, size_t column,
171 const internals::data_frame::DataFrameStorage* storage,
172 bool mutable_access
173 ) : CSVField(csv::string_view()), row_(source),
174 edit_context_(mutable_access ? static_cast<const void*>(storage) : static_cast<const void*>(overlay)),
175 col_index_(column), can_mutate_(mutable_access), frame_bound_(mutable_access) {
176 this->refresh_value(overlay);
177 }
178
179 const internals::data_frame::DataFrameStorage* storage() const {
180 return static_cast<const internals::data_frame::DataFrameStorage*>(edit_context_);
181 }
182
183 const RowOverlay* find_overlay() const {
184 if (frame_bound_) {
185 return this->storage()->find_edits(row_);
186 }
187 return static_cast<const RowOverlay*>(edit_context_);
188 }
189
190 void refresh_value() {
191 this->refresh_value(this->find_overlay());
192 }
193
194 void refresh_value(const RowOverlay* overlay) {
195 if (!row_) {
196 CSVField::operator=(CSVField(csv::string_view()));
197 return;
198 }
199
200 if (overlay && overlay->try_get_copy(col_index_, owned_value_)) {
201 CSVField::operator=(CSVField(csv::string_view(owned_value_)));
202 return;
203 }
204
205 owned_value_.clear();
206 CSVField::operator=(CSVField(internals::data_frame::RowViewAccessor::view(*row_, col_index_)));
207 }
208
209 DataFrameCell& assign(std::string stored) {
210 owned_value_ = stored;
211 auto* state = frame_bound_
212 ? const_cast<internals::data_frame::DataFrameStorage*>(this->storage()) : nullptr;
213 RowOverlay* overlay = state ? state->ensure_edits(row_)
214 : const_cast<RowOverlay*>(static_cast<const RowOverlay*>(edit_context_));
215 overlay->set(col_index_, std::move(stored));
216 CSVField::operator=(CSVField(csv::string_view(owned_value_)));
217 return *this;
218 }
219
220 const CSVRow* row_;
221 // Tagged context: standalone/read-only cells hold an overlay; mutable
222 // frame-bound cells hold the lazy handler. This uses existing padding
223 // for the tag instead of adding an owner pointer and row index per cell.
224 const void* edit_context_;
225 size_t col_index_;
226 bool can_mutate_;
227 bool frame_bound_ = false;
228 std::string owned_value_;
229 };
230}
Data type representing individual CSV values.
Definition csv_row.hpp:74
DataType type() const noexcept
Return the type of the underlying CSV data.
Definition csv_row.hpp:345
bool is_num() const noexcept
Returns true if field is an integer or float.
Definition csv_row.hpp:326
bool is_str() const noexcept
Returns true if field is a non-numeric, non-empty string.
Definition csv_row.hpp:323
bool try_get(T &out) const noexcept
Non-throwing equivalent of get().
Definition csv_row.hpp:188
bool is_null() const noexcept
Returns true if field is an empty string or string of whitespace characters.
Definition csv_row.hpp:320
constexpr CSVField(csv::string_view _sv) noexcept
Constructs a CSVField from a string_view.
Definition csv_row.hpp:77
T get() const
Returns the value casted to the requested type, performing type checking before.
Definition csv_row.hpp:140
bool is_float() const noexcept
Returns true if field is a floating point value.
Definition csv_row.hpp:336
bool is_int() const noexcept
Returns true if field is an integer.
Definition csv_row.hpp:331
CONSTEXPR csv::string_view get_sv() const noexcept
Return a string view over the field's contents.
Definition csv_row.hpp:317
Data structure for representing CSV rows.
Definition csv_row.hpp:533
bool try_assign(csv::string_view value, CSVError &error)
Assign through a mutable cell, preserving the current value on validation failure.
T get() const
Const-friendly read access for proxy use in column iteration and callbacks.
The all encompassing namespace.
DataType
Enumerates the different CSV field types recognized by this library.
Definition data_type.hpp:14
CSVConversionError
Non-throwing CSVField conversion result.
Definition csv_error.hpp:23
@ ReadOnlyProxy
Mutation was requested through a cell, row, or column without edit permission.
std::string_view string_view
The string_view class used by this library.
Definition common.hpp:182
A diagnostic whose text remains valid for the lifetime of the error.
Definition csv_error.hpp:94