23 : clean_(std::move(
other.clean_)), dirty_(std::move(
other.dirty_)), active_(&clean_) {
25 other.active_.store(&
other.clean_, std::memory_order_release);
29 clean_ = std::move(
other.clean_);
30 dirty_ = std::move(
other.dirty_);
32 other.active_.store(&
other.clean_, std::memory_order_release);
38 inline std::vector<CSVRow>& rows()
noexcept {
return clean_.rows(); }
39 inline const std::vector<CSVRow>& rows()
const noexcept {
return clean_.rows(); }
40 inline void set_names(ConstColNamesPtr names) { clean_.set_names(std::move(names)); }
41 inline const ConstColNamesPtr& names()
const noexcept {
return dispatch(Names()); }
42 inline size_t n_cols()
const noexcept {
return dispatch(Count()); }
43 inline CellBinding bind(
size_t row,
size_t column)
const {
return dispatch(Bind{row, column}); }
44 inline csv::string_view view(
size_t row,
size_t column)
const {
return dispatch(View{row, column}); }
47 if (row >= rows().size() || column >= n_cols()) {
52 if (
binding.physical_column >= rows()[row].size()) {
60 return dispatch(Edits{row_index(row)});
63 return promote().ensure_edits(row_index(row));
65 inline CSVRow make_inserted_row(
const std::vector<std::string>& row,
CSVError& error)
const {
66 return dispatch(MakeRow{row, error});
68 inline void reserve_insert() { dispatch_mutable(Reserve()); }
69 inline void insert_row(
size_t index,
CSVRow&& row) { dispatch_mutable(Insert{index, row}); }
70 inline void erase_row(
size_t index) { dispatch_mutable(Erase{index}); }
72 inline bool erase_column(
size_t index,
int key_column,
CSVError& error) {
74 if (index >= n_cols()) {
return false; }
75 return promote().erase_column(index, key_column, error);
78 template<
typename BeforeReplace>
79 inline bool insert_column(
80 size_t index,
const std::string& name,
const std::string& value,
92 active_.store(&clean_, std::memory_order_release);
110 inline bool pristine()
const noexcept {
111 return active_.load(std::memory_order_acquire) == &clean_ && rows().empty();
115 template<
typename Operation>
117 ->
decltype(
operation(std::declval<const CleanDataFrame&>())) {
122 template<
typename Operation>
124 ->
decltype(
operation(std::declval<CleanDataFrame&>())) {
133 std::lock_guard<std::mutex>
lock(transition_lock_);
134 choice = active_.load(std::memory_order_acquire);
139 active_.store(
choice, std::memory_order_release);
143 inline size_t row_index(
const CSVRow* row)
const noexcept {
144 return static_cast<size_t>(row - rows().data());
146 inline void restore_choice()
noexcept {
148 dirty_->rebind(clean_);
149 active_.store(dirty_.get(), std::memory_order_release);
151 else { active_.store(&clean_, std::memory_order_release); }
154 struct Names {
template<
typename B>
const ConstColNamesPtr& operator()(
const B&
b)
const {
return b.names(); } };
155 struct Count {
template<
typename B>
size_t operator()(
const B&
b)
const {
return b.n_cols(); } };
158 template<
typename B>
CellBinding operator()(
const B&
b)
const {
return b.bind(row, column); }
162 template<
typename B>
csv::string_view operator()(
const B&
b)
const {
return b.view(row, column); }
166 template<
typename B>
const RowOverlay* operator()(
const B&
b)
const {
return b.find_edits(row); }
169 const std::vector<std::string>& row;
171 template<
typename B>
CSVRow operator()(
const B&
b)
const {
return b.make_inserted_row(row, error); }
173 struct Reserve {
template<
typename B>
void operator()(
B&
b)
const {
b.reserve_insert(); } };
175 size_t index;
CSVRow& row;
176 template<
typename B>
void operator()(
B&
b)
const {
b.insert_row(index, std::move(row)); }
180 template<
typename B>
void operator()(
B&
b)
const {
b.erase_row(index); }
184 std::unique_ptr<DirtyDataFrame> dirty_;
185 std::mutex transition_lock_;
186 std::atomic<RowBackend*> active_;