7#include "../csv_exceptions.hpp"
8#include "../csv_row.hpp"
9#include "../json_converter.hpp"
10#include "data_frame_cell.hpp"
14 template<
typename KeyType>
18 DataFrameRow() : row(nullptr), frame(nullptr), row_index(0), row_overlay(nullptr), key_ptr(nullptr), can_mutate(false) {}
27 ) : row(_row), frame(_frame), row_index(_row_index), row_overlay(_edits), key_ptr(_key), can_mutate(true) {}
36 ) : row(_row), frame(_frame), row_index(_row_index), row_overlay(_edits), key_ptr(_key), can_mutate(false) {}
39#if CSV_EXCEPTIONS_ENABLED
41 return field_or_throw(*
this, col);
46#if CSV_EXCEPTIONS_ENABLED
48 return field_or_throw(*
this, n);
53#if CSV_EXCEPTIONS_ENABLED
55 return field_or_throw(*
this, col);
60#if CSV_EXCEPTIONS_ENABLED
62 return field_or_throw(*
this, n);
68 if (!this->validate_field(index, error))
return {};
69 return frame ? frame->try_make_cell(row_index, index, can_mutate, error) : this->make_cell(index);
72 if (!this->validate_field(index, error))
return {};
73 return frame ? frame->try_make_cell(row_index, index,
false, error) : this->make_cell(index);
75 DataFrameCell
try_field(
const std::string& name, CSVError& error) {
76 const size_t index = this->try_find_column(name, error);
77 return error ? DataFrameCell() : this->
try_field(index, error);
79 DataFrameCell
try_field(
const std::string& name, CSVError& error)
const {
80 const size_t index = this->try_find_column(name, error);
81 return error ? DataFrameCell() : this->
try_field(index, error);
84 bool try_erase(CSVError& error) {
86 if (!can_mutate || !frame)
88 return const_cast<DataFrame<KeyType>*
>(frame)->erase_at_index(row_index);
92 bool is_valid() const noexcept {
return row !=
nullptr; }
95 size_t size()
const {
return frame ? frame->
n_cols() : (row ? row->
size() : 0); }
109 const KeyType&
key()
const {
return *key_ptr; }
115#if CSV_EXCEPTIONS_ENABLED
118 const bool result = this->try_erase(error);
119 internals::throw_dataframe_error(error);
125#if CSV_EXCEPTIONS_ENABLED
126 operator std::vector<std::string>()
const {
127 std::vector<std::string> result;
128 result.reserve(this->
size());
130 for (
size_t i = 0; i < this->
size(); i++) {
131 result.push_back(std::string(this->make_cell(i).get_sv()));
139#if CSV_EXCEPTIONS_ENABLED
140 std::string
to_json(
const std::vector<std::string>& subset = {})
const {
144 internals::throw_error(error);
151 if (!this->validate_fields(subset, error))
return {};
152 const field_string_accessor field_at(
this);
153 return frame ? this->get_frame_json_converter().try_row_to_json(this->
size(), field_at, subset, error)
154 : this->make_detached_json_converter().try_row_to_json(this->
size(), field_at, subset, error);
159#if CSV_EXCEPTIONS_ENABLED
160 std::string
to_json_array(
const std::vector<std::string>& subset = {})
const {
164 internals::throw_error(error);
171 if (!this->validate_fields(subset, error))
return {};
172 const field_string_accessor field_at(
this);
173 return frame ? this->get_frame_json_converter().try_row_to_json_array(this->
size(), field_at, subset, error)
174 : this->make_detached_json_converter().try_row_to_json_array(this->
size(), field_at, subset, error);
177#if defined(CSV_HAS_CXX20) && CSV_EXCEPTIONS_ENABLED
184 return std::views::iota(
size_t{0}, this->
size())
185 | std::views::transform([
this](
size_t i) {
return std::string(this->make_cell(i).get_sv()); });
190#if CSV_EXCEPTIONS_ENABLED
192 template<
typename Self,
typename Column>
193 static DataFrameCell field_or_throw(Self& self,
const Column& column) {
195 auto result = self.try_field(column, error);
196 internals::throw_dataframe_error(error);
201 bool validate_field(
size_t index, CSVError& error)
const {
205 if (index >= this->
size())
210 struct field_string_accessor {
211 explicit field_string_accessor(
const DataFrameRow* owner) : owner(owner) {}
213 std::string operator()(
size_t i)
const {
214 return std::string(owner->make_cell(i).get_sv());
220 const internals::JsonConverter& get_frame_json_converter()
const {
221 return frame->json_converter_.get_or_create([
this]() {
222 return std::make_shared<internals::JsonConverter>(frame->
columns());
226 internals::JsonConverter make_detached_json_converter()
const {
230 DataFrameCell make_cell(
size_t col_index) {
232 return frame->make_cell(row, row_index, col_index, can_mutate);
236 ? DataFrameCell(row,
const_cast<RowOverlay*
>(row_overlay), col_index)
237 : DataFrameCell(row, row_overlay, col_index);
240 DataFrameCell make_cell(
size_t col_index)
const {
242 return frame->make_cell(row, row_index, col_index,
false);
245 return DataFrameCell(row, row_overlay, col_index);
248 size_t try_find_column(
const std::string& col, CSVError& error)
const {
254 if (frame)
return frame->try_find_column(col, error);
260 return static_cast<size_t>(position);
263 bool validate_fields(
const std::vector<std::string>& subset, CSVError& error)
const {
265 if (subset.empty()) {
266 for (
size_t i = 0; i < this->
size(); ++i) {
268 if (error)
return false;
271 for (
const auto& name : subset) {
273 if (error)
return false;
280 const DataFrame<KeyType>* frame;
282 const RowOverlay* row_overlay;
283 const KeyType* key_ptr;
Data structure for representing CSV rows.
const std::vector< std::string > & get_col_names() const
Retrieve this row's associated column names.
CONSTEXPR size_t size() const noexcept
Return the number of fields in this row.
internals::ConstColNamesPtr col_names_ptr() const noexcept
Internal accessor for preserving resolved column-name lookup policy across helper types.
DataFrameCell operator[](const std::string &col)
Access a field by column name, preserving edit support.
std::string to_json(const std::vector< std::string > &subset={}) const
Convert to JSON.
DataFrameRow(const CSVRow *_row, const DataFrame< KeyType > *_frame, size_t _row_index, const RowOverlay *_edits, const KeyType *_key)
Construct a read-only DataFrameRow wrapper.
auto to_sv_range() const
Convert this DataFrameRow into a std::ranges::input_range of strings, respecting the sparse overlay (...
DataFrameRow(const CSVRow *_row, DataFrame< KeyType > *_frame, size_t _row_index, RowOverlay *_edits, const KeyType *_key)
Construct a mutable DataFrameRow wrapper.
DataFrameCell operator[](size_t n)
Access a field by position, preserving edit support.
DataFrameRow()
Default constructor (creates an unbound proxy).
const std::vector< std::string > & get_col_names() const
Get column names.
DataFrameCell operator[](size_t n) const
Access a field by position, checking edits first.
DataFrameCell operator[](const std::string &col) const
Access a field by column name, checking edits first.
std::string to_json_array(const std::vector< std::string > &subset={}) const
Convert to JSON array.
size_t size() const
Get the number of visible fields in the row.
std::string try_to_json_array(const std::vector< std::string > &subset, CSVError &error) const
Serialize selected visible columns, reporting lookup and physical-row bounds errors.
std::string try_to_json(const std::vector< std::string > &subset, CSVError &error) const
Serialize selected visible columns, reporting lookup and physical-row bounds errors.
const KeyType & key() const
Get the key for this row (only valid for keyed DataFrames).
bool empty() const
Check if the row is empty.
const CSVRow & get_underlying_row() const
Get the underlying CSVRow without applying cell edits or column visibility.
bool is_valid() const noexcept
Whether the proxy is bound.
bool erase()
Delete this row from the parent DataFrame.
DataFrameCell try_field(size_t index, CSVError &error)
Checked cell access.
size_t n_cols() const noexcept
Get the number of visible columns in the DataFrame.
const std::vector< std::string > & columns() const noexcept
Get the column names in order.
The all encompassing namespace.
@ IndexOutOfBounds
A row/column position exceeds the visible schema or physical record width.
@ InvalidProxy
A proxy is unbound or a column proxy was invalidated by structural mutation.
@ ColumnNotFound
A requested name is absent from the visible column schema.
@ ReadOnlyProxy
Mutation was requested through a cell, row, or column without edit permission.
constexpr int CSV_NOT_FOUND
Integer indicating a requested column wasn't found.
A diagnostic whose text remains valid for the lifetime of the error.