This commit is contained in:
2026-08-30 12:51:11 +01:00
parent b8eac7b2da
commit afa60dd12f
24 changed files with 821 additions and 803 deletions
-10
View File
@@ -80,20 +80,15 @@ Shard *substitute(
(end + 1 == line_count)
? root->length
: offset_of(root, end + 1);
std::vector<RegexMatch> matches = _regex_search(root, pattern, start_offset, end_offset, options);
if (matches.empty())
return root;
std::vector<ReplacePart> replace_parts = parse_replace(ap, replace);
std::vector<Shard *> pieces;
pieces.reserve(matches.size() * 2 + 1);
Shard *remaining = root;
Shard::retain(remaining);
uint64_t cursor = 0;
for (const RegexMatch &match : matches) {
uint64_t gap = match.start - cursor;
if (gap > 0) {
@@ -102,11 +97,9 @@ Shard *substitute(
pieces.push_back(keep);
remaining = rest;
}
auto [dropped, rest2] = Shard::split(remaining, match.end - match.start);
Shard::release(remaining);
remaining = rest2;
for (size_t i = 0; i < replace_parts.size(); ++i) {
const ReplacePart &part = replace_parts[i];
switch (part.type) {
@@ -141,11 +134,9 @@ Shard *substitute(
cursor = match.end;
}
pieces.push_back(remaining);
for (auto &part : replace_parts)
if (part.type == ReplacePart::PartType::Constant)
Shard::release(std::get<Shard *>(part.value));
std::vector<Shard *> compact;
compact.reserve(pieces.size());
for (Shard *p : pieces) {
@@ -154,7 +145,6 @@ Shard *substitute(
else if (p)
Shard::release(p);
}
Shard *new_root = compact.empty() ? nullptr : Shard::build(compact.data(), 0, compact.size());
Shard::release(root);
return new_root;
+11 -52
View File
@@ -1,3 +1,4 @@
#include "internal/io/io.h"
#include "internal/vase/vase.h"
namespace bed::internal::vase {
@@ -192,10 +193,10 @@ Shard *Shard::append(Shard *root, Shard *leaf) {
Shard *Shard::build(Shard **pieces, uint64_t lo, uint64_t hi) {
if (hi - lo == 1)
return pieces[lo];
size_t mid = lo + (hi - lo) / 2;
uint64_t mid = lo + (hi - lo) / 2;
Shard *left = build(pieces, lo, mid);
Shard *right = build(pieces, mid, hi);
Shard *node = new Branch(left, right);
Shard *node = Shard::concat(left, right);
Shard::release(left);
Shard::release(right);
return node;
@@ -208,9 +209,11 @@ Shard *Shard::from_command(const char *cmd, bool posix_ending) {
delete o;
return nullptr;
}
io::IO::cleanup();
FILE *pipe = popen(cmd, "r");
if (!pipe) {
delete o;
io::IO::enable_raw();
return nullptr;
}
std::vector<Shard *> pieces;
@@ -245,6 +248,7 @@ Shard *Shard::from_command(const char *cmd, bool posix_ending) {
if (!write_all(dest_fd, buf, buf_cursor)) {
pclose(pipe);
delete o;
io::IO::enable_raw();
return nullptr;
}
pieces.push_back(new Petal(buf_cursor, lines, o, pos));
@@ -254,20 +258,24 @@ Shard *Shard::from_command(const char *cmd, bool posix_ending) {
break;
if (ferror(pipe)) {
delete o;
io::IO::enable_raw();
return nullptr;
}
}
int status = pclose(pipe);
if (status == -1) {
delete o;
io::IO::enable_raw();
return nullptr;
}
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
delete o;
io::IO::enable_raw();
return nullptr;
}
if (pieces.empty()) {
delete o;
io::IO::enable_raw();
return nullptr;
}
if (posix_ending) {
@@ -287,6 +295,7 @@ Shard *Shard::from_command(const char *cmd, bool posix_ending) {
}
}
o->initialize();
io::IO::enable_raw();
if (pieces.size() == 1)
return pieces[0];
return build(pieces.data(), 0, pieces.size());
@@ -421,54 +430,4 @@ Shard *Shard::from_string(const char *data, uint64_t len, bool posix_ending) {
return pieces[0];
return build(pieces.data(), 0, pieces.size());
}
void Shard::dump(Shard *node, int depth) {
if (!node) {
std::cout << std::string(depth * 2, ' ') << "<null>\n";
return;
}
std::string indent(depth * 2, ' ');
std::cout << indent
<< "Shard@" << node
<< " kind=";
switch (node->kind) {
case Shard::Kind::Branch:
std::cout << "Branch";
break;
case Shard::Kind::Petal:
std::cout << "Petal";
break;
}
std::cout
<< " height=" << unsigned(node->height)
<< " length=" << node->length
<< " lines=" << node->lines
<< " refs=" << node->refs.load()
<< "\n";
if (node->kind == Shard::Kind::Branch) {
auto *branch = (Branch *)node;
std::cout << indent << " left:\n";
dump(branch->left, depth + 2);
std::cout << indent << " right:\n";
dump(branch->right, depth + 2);
} else {
auto *petal = static_cast<Petal *>(node);
constexpr auto clean = [](const std::string &text) {
std::string result = text;
size_t pos = 0;
while ((pos = result.find('\n', pos)) != std::string::npos) {
result.replace(pos, 1, "\\n");
pos += 2;
}
return result;
};
std::cout
<< indent << " source=" << petal->source
<< " pos=" << petal->pos
<< " length=" << petal->length
<< " lines=" << petal->lines
<< " text=\"" << clean(std::string(petal->source->read(petal->pos), petal->length))
<< "\"\n";
}
}
} // namespace bed::internal::vase
+32
View File
@@ -222,6 +222,38 @@ Shard *erase(Shard *root, uint64_t start, uint64_t end) {
return new_root;
}
Shard *join(Shard *root, uint64_t start, uint64_t end) {
if (!start || !end)
throw ed_error("Invalid range.");
start--;
end--;
if (!root)
throw ed_error("line range out of bounds");
uint64_t line_count = root->lines + 1;
if (start >= end || end >= line_count)
throw ed_error("line range out of bounds");
uint64_t offset = offset_of(root, start);
std::vector<Shard *> pieces;
pieces.reserve(end - start + 3);
auto [a, b] = Shard::split(root, offset);
pieces.push_back(a);
for (uint64_t line = start; line < end; line++) {
uint64_t nl_pos = offset_of(b, 1) - 1;
auto [content, rest] = Shard::split(b, nl_pos);
Shard::release(b);
auto [nl, next_b] = Shard::split(rest, 1);
Shard::release(rest);
Shard::release(nl);
pieces.push_back(content);
b = next_b;
}
pieces.push_back(b);
Shard *joined = Shard::build(pieces.data(), 0, pieces.size());
Shard::release(root);
return joined;
}
Shard *copy(Shard *root, uint64_t start, uint64_t end) {
if (!start || !end)
throw ed_error("Invalid range.");