Fixes.
This commit is contained in:
@@ -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
@@ -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
|
||||
|
||||
@@ -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.");
|
||||
|
||||
Reference in New Issue
Block a user