CDT  v4.2.0
инструменты разработчика
rope.hpp
См. документацию.
1#pragma once
2
3#include <variant>
4#include <set>
5#include <stack>
6#include <string_view>
7#include "check.hpp"
8#include "print.hpp"
9
10namespace eosio {
11 template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
12 template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
13
14 namespace impl {
15 struct str_t;
16 struct concat_t;
17 typedef std::variant<concat_t, str_t> rope_node;
18
19 struct str_t {
20 const char* c_str;
21 size_t size;
22 mutable const rope_node* temp = nullptr;
23 };
24
25 struct concat_t {
26 rope_node* left = nullptr;
27 rope_node* right = nullptr;
28 mutable const rope_node* temp = nullptr;
29 mutable bool temp_left = false;
30 };
31 }
32
33 using namespace impl;
34 class rope {
35 private:
36 rope_node* root = nullptr;
37 rope_node* last = nullptr;
38 size_t size = 0;
39
40 static constexpr size_t strlen(const char* str) {
41 int i=0;
42 while (str[i++]);
43 return i;
44 }
45
46 static void c_str(char* buffer, const rope_node* r, size_t& off) {
47 bool going_down = true;
48 if (r) {
49 std::visit([](const auto& n) {
50 n.temp = nullptr;
51 }, *r);
52 }
53 while (r) {
54 if (going_down) {
55 std::visit(overloaded {
56 [&](const concat_t& c) {
57 if (c.left) {
58 c.temp_left = true;
59 std::visit([&](const auto& n){
60 n.temp = r;
61 }, *c.left);
62 going_down = true;
63 r = c.left;
64 } else if (c.right) {
65 c.temp_left = false;
66 std::visit([&](const auto& n){
67 n.temp = r;
68 }, *c.right);
69 going_down = true;
70 r = c.right;
71 } else {
72 going_down = false;
73 r = c.temp;
74 }
75 },
76 [&](const str_t& s) {
77 off -= s.size;
78 memcpy(buffer+off, s.c_str, s.size);
79 going_down = false;
80 r = s.temp;
81 }
82 }, *r);
83 } else {
84 const auto& c = std::get<concat_t>(*r);
85 if (c.temp_left && c.right) {
86 c.temp_left = false;
87 std::visit([&](const auto& n){
88 n.temp = r;
89 }, *c.right);
90 going_down = true;
91 r = c.right;
92 } else {
93 going_down = false;
94 r = c.temp;
95 }
96 }
97 }
98 }
99
100 void append(rope_node* rn, bool use_left=false) {
101 auto cc = std::get_if<concat_t>(rn);
102 eosio::check(cc, "append should only allow concat nodes");
103 if (use_left)
104 root = new rope_node(concat_t{rn, root});
105 else {
106 cc->right = root;
107 root = rn;
108 }
109 }
110
111 void at(char& ret, size_t index, rope_node* rn, size_t& index_so_far, bool& stop) {
112 if (rn) {
113 std::visit(overloaded {
114 [&](const concat_t& c) {
115 if (!stop) {
116 if (c.left)
117 at(ret, index, c.left, index_so_far, stop);
118 if (c.right)
119 at(ret, index, c.right, index_so_far, stop);
120 }
121 },
122 [&](const str_t& s) {
123 index_so_far -= s.size;
124 if (index >= index_so_far) {
125 ret = s.c_str[index-index_so_far];
126 stop = true;
127 }
128 }
129 }, *rn);
130 }
131 }
132
133 public:
134 rope(const char* s) {
135 root = new rope_node(concat_t{new rope_node(str_t{s,strlen(s)-1}), nullptr});
136 last = root;
137 size += strlen(s)-1;
138 }
139
140 rope(std::string_view s = "") {
141 root = new rope_node(concat_t{new rope_node(str_t{s.begin(),s.size()}), nullptr});
142 size += s.size();
143 }
144
145 template <size_t N>
146 inline constexpr void append(const char (&s)[N]) {
147 append(s, N);
148 }
149
150 void append(const char* s, size_t len) {
151 str_t _s{s, len};
152 rope_node* rn = new rope_node(concat_t{new rope_node(_s), nullptr});
153 append(rn);
154 size += len;
155 }
156
157 constexpr char at(size_t index) {
158 char ret = '\0';
159 size_t sz = size;
160 bool stop = false;
161 at(ret, index, root, sz, stop);
162 return ret;
163 }
164
165 constexpr void append(const rope& r) {
166 append(r.root, true);
167 size += r.size;
168 }
169
170 constexpr void append(rope&& r) {
171 append(r.root, true);
172 size += r.size;
173 }
174
175 constexpr char operator[](size_t index) {
176 return at(index);
177 }
178
179 constexpr rope& operator+= (const char* s) {
180 append(s, strlen(s)-1);
181 return *this;
182 }
183
184 constexpr rope& operator+= (const rope& r) {
185 append(r);
186 return *this;
187 }
188 constexpr rope& operator+= (rope&& r) {
189 append(std::move(r));
190 return *this;
191 }
192
193 friend rope operator+ (rope lhs, const char* s) {
194 lhs += s;
195 return lhs;
196 }
197
198 friend rope operator+ (rope lhs, const rope& rhs) {
199 lhs += rhs;
200 return lhs;
201 }
202
203 friend rope operator+ (rope lhs, rope&& rhs) {
204 lhs += std::move(rhs);
205 return lhs;
206 }
207
208
209 constexpr size_t length() {
210 return size;
211 }
212
213 void print()const {
215 }
216
217 char* c_str()const {
218 char* ret = new char[size+1];
219 if (root) {
220 size_t off = size;
221 c_str(ret, root, off);
222 }
223 ret[size] = '\0';
224 return ret;
225 }
226
227 std::string_view sv()const {
228 return {c_str(), size};
229 }
230 };
231} // ns eosio