Vince's CSV Parser
Loading...
Searching...
No Matches
row_storage.hpp
1#pragma once
2
3#include <algorithm>
4#include <cstdint>
5#include <vector>
6#include "../csv_exceptions.hpp"
7#include "../csv_row.hpp"
8#include "../raw_csv_data.hpp"
9#include "row_overlay.hpp"
10
11namespace csv {
12 namespace internals {
13 namespace data_frame {
14 // Concrete backend identity only: deliberately no virtual functions.
15 struct RowBackend {};
16
17 struct CellBinding {
18 const RowOverlay* overlay;
19 size_t physical_column;
20 };
21
22 template<typename Container>
23 inline void reserve_next(Container& values) {
24 const size_t required = values.size() + 1;
25 if (required > values.capacity()) {
26 values.reserve(std::max(required, values.capacity() * 2));
27 }
28 }
29
30 inline void validate_column(size_t index, size_t count) {
31 CSV_DEBUG_ASSERT(index < count);
32 (void)index; (void)count;
33 }
34
35 inline bool validate_row(const std::vector<std::string>& row, size_t columns, CSVError& error) {
36 error.clear();
37 if (columns == 0 && !row.empty()) {
38 return fail_static(error, CSVErrorCode::InvalidArgument, "cannot insert a non-empty row into a DataFrame without columns");
39 }
40 if (row.size() != columns) {
41 return fail_static(error, CSVErrorCode::InvalidArgument, "inserted row field count must match DataFrame column count");
42 }
43 return true;
44 }
45
46 inline std::vector<CSVRow> select_parsed_rows(
47 const std::vector<CSVRow>& rows, const std::vector<std::uint8_t>& mask, CSVError& error
48 ) {
49 error.clear();
50 if (mask.size() != rows.size()) {
51 fail_static(error, CSVErrorCode::InvalidArgument, "selected row mask size must match DataFrame row count");
52 return {};
53 }
54 std::vector<CSVRow> selected;
55 selected.reserve(static_cast<size_t>(std::count_if(mask.begin(), mask.end(),
56 [](std::uint8_t value) { return value != 0; })));
57 for (size_t i = 0; i < rows.size(); ++i) {
58 if (mask[i]) { selected.push_back(rows[i]); }
59 }
60 return selected;
61 }
62
65 public:
66 explicit inline RowStorageBuilder(ConstColNamesPtr names) : names_(std::move(names)) {}
67
68 inline void begin_row() {
69 // Offsets are chunk-local. Rotate between rows instead of accumulating
70 // arbitrarily large offsets when rebuilding a large table.
71 if (!data_ || bytes_ >= CSV_CHUNK_SIZE_DEFAULT || data_->fields.size() >= CSV_CHUNK_SIZE_DEFAULT) {
72 data_ = std::make_shared<RawCSVData>();
73 data_->col_names = std::const_pointer_cast<ColNames>(names_);
74 bytes_ = 0;
75 }
76 field_start_ = data_->fields.size();
77 data_->fields.reserve_for_source_size(field_start_ + names_->size());
78 }
79
80 inline void append_field(csv::string_view value) {
81 const size_t offset = data_->quote_arena.append(value);
82 data_->fields.emplace_back(offset, value.size(), true);
83 bytes_ += value.size();
84 }
85
86 inline CSVRow finish_row() const {
87 return CSVRow(data_, 0, field_start_, data_->fields.size() - field_start_);
88 }
89
90 static inline CSVRow make_row(const std::vector<std::string>& values, ConstColNamesPtr names) {
91 RowStorageBuilder storage(std::move(names));
92 storage.begin_row();
93 for (const auto& value : values) { storage.append_field(csv::string_view(value)); }
94 return storage.finish_row();
95 }
96
97 template<typename FieldAt>
98 static inline std::vector<CSVRow> insert_column(
99 size_t count, ConstColNamesPtr names, size_t index,
100 const std::string& default_value, const FieldAt& field_at
101 ) {
102 std::vector<CSVRow> rebuilt;
103 rebuilt.reserve(count);
104 RowStorageBuilder storage(names);
105 for (size_t row = 0; row < count; ++row) {
106 storage.begin_row();
107 for (size_t column = 0; column < names->size(); ++column) {
108 if (column == index) { storage.append_field(csv::string_view(default_value)); }
109 else {
110 const auto value = field_at(row, column < index ? column : column - 1);
111 storage.append_field(csv::string_view(value));
112 }
113 }
114 rebuilt.push_back(storage.finish_row());
115 }
116 return rebuilt;
117 }
118
119 private:
120 ConstColNamesPtr names_;
121 RawCSVDataPtr data_;
122 size_t bytes_ = 0;
123 size_t field_start_ = 0;
124 };
125 }
126 }
127}
Data structure for representing CSV rows.
Definition csv_row.hpp:533
Borrow a row and error state for synchronous, single-pass field access.
Shared lossless owned-row construction for insertion and materialization.
constexpr size_t CSV_CHUNK_SIZE_DEFAULT
Default chunk size for lazy-loading large CSV files.
Definition common.hpp:416
The all encompassing namespace.
@ InvalidArgument
Invalid operation input, such as a null stream or zero batch size.
std::string_view string_view
The string_view class used by this library.
Definition common.hpp:182