Vince's CSV Parser
Loading...
Searching...
No Matches
row_overlay.hpp
1#pragma once
2
3#include <atomic>
4#include <memory>
5#include <string>
6#include <unordered_map>
7#include <utility>
8
9#include "../common.hpp"
10
11namespace csv {
12 struct RowOverlay {
13 RowOverlay() = default;
14 RowOverlay(const RowOverlay&) = delete;
15 RowOverlay& operator=(const RowOverlay&) = delete;
16
17 RowOverlay(RowOverlay&& other) noexcept : values(std::move(other.values)) {
18 busy.clear(std::memory_order_release);
19 }
20
21 RowOverlay& operator=(RowOverlay&& other) noexcept {
22 if (this != &other) {
23 values = std::move(other.values);
24 busy.clear(std::memory_order_release);
25 }
26 return *this;
27 }
28
29 bool try_get_copy(size_t col_index, std::string& out) const {
30 row_overlay_lock_guard lock(this);
31 auto it = values.find(col_index);
32 if (it == values.end()) {
33 return false;
34 }
35
36 out = it->second;
37 return true;
38 }
39
48 bool try_get_view(size_t col_index, csv::string_view& out) const {
49 row_overlay_lock_guard lock(this);
50 auto it = values.find(col_index);
51 if (it == values.end()) {
52 return false;
53 }
54
55 out = csv::string_view(it->second);
56 return true;
57 }
58
59 void set(size_t col_index, std::string value) {
60 row_overlay_lock_guard lock(this);
61 values[col_index] = std::move(value);
62 }
63
64 bool empty() const {
65 row_overlay_lock_guard lock(this);
66 return values.empty();
67 }
68
69 RowOverlay snapshot() const {
70 row_overlay_lock_guard lock(this);
71 RowOverlay result;
72 result.values = values;
73 return result;
74 }
75
76 private:
77 struct row_overlay_lock_guard {
78 explicit row_overlay_lock_guard(const RowOverlay* overlay)
79 : busy(const_cast<std::atomic_flag&>(overlay->busy)) {
80 while (busy.test_and_set(std::memory_order_acquire)) {}
81 }
82
83 ~row_overlay_lock_guard() {
84 busy.clear(std::memory_order_release);
85 }
86
87 std::atomic_flag& busy;
88 };
89
90 mutable std::atomic_flag busy = ATOMIC_FLAG_INIT;
91 std::unordered_map<size_t, std::string> values;
92 };
93
95 RowOverlaySlot() noexcept : ptr(nullptr) {}
96 RowOverlaySlot(const RowOverlaySlot&) = delete;
97 RowOverlaySlot& operator=(const RowOverlaySlot&) = delete;
98
99 RowOverlaySlot(RowOverlaySlot&& other) noexcept
100 : ptr(nullptr),
101 owned(std::move(other.owned)) {
102 RowOverlay* overlay = owned.get();
103 ptr.store(overlay, std::memory_order_release);
104 other.ptr.store(nullptr, std::memory_order_release);
105 }
106
107 RowOverlaySlot& operator=(RowOverlaySlot&& other) noexcept {
108 if (this != &other) {
109 owned = std::move(other.owned);
110 RowOverlay* overlay = owned.get();
111 ptr.store(overlay, std::memory_order_release);
112 other.ptr.store(nullptr, std::memory_order_release);
113 }
114
115 return *this;
116 }
117
118 RowOverlay* get() noexcept {
119 return ptr.load(std::memory_order_acquire);
120 }
121
122 const RowOverlay* get() const noexcept {
123 return ptr.load(std::memory_order_acquire);
124 }
125
126 RowOverlay* ensure() {
127 RowOverlay* overlay = this->get();
128 if (!overlay) {
129 owned.reset(new RowOverlay());
130 overlay = owned.get();
131 ptr.store(overlay, std::memory_order_release);
132 }
133
134 return overlay;
135 }
136
137 private:
138 std::atomic<RowOverlay*> ptr;
139 std::unique_ptr<RowOverlay> owned;
140 };
141}
The all encompassing namespace.
std::string_view string_view
The string_view class used by this library.
Definition common.hpp:182
bool try_get_view(size_t col_index, csv::string_view &out) const
Return a view into an edited cell without copying.