Cleanup
This commit is contained in:
@@ -44,7 +44,7 @@ UNICODE_OBJ := $(patsubst libs/unicode_width/%.c,$(OBJ_DIR)/unicode_width/%.o,$(
|
|||||||
|
|
||||||
LIBS := $(PCRE_LIBS) $(LIBGRAPHEME_LIBS) $(MRUBY_LIBS)
|
LIBS := $(PCRE_LIBS) $(LIBGRAPHEME_LIBS) $(MRUBY_LIBS)
|
||||||
|
|
||||||
SRC := $(wildcard $(SRC_DIR)/**/*.cc) $(wildcard $(SRC_DIR)/*.cc)
|
SRC := $(shell find $(SRC_DIR) -type f -name '*.cc')
|
||||||
OBJ_DEBUG := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/debug/%.o,$(SRC))
|
OBJ_DEBUG := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/debug/%.o,$(SRC))
|
||||||
OBJ_RELEASE := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/release/%.o,$(SRC))
|
OBJ_RELEASE := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/release/%.o,$(SRC))
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
gnumake
|
gnumake
|
||||||
xxd
|
xxd
|
||||||
bash
|
bash
|
||||||
|
findutils
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
@@ -100,6 +101,7 @@
|
|||||||
hostPkgs.xxd
|
hostPkgs.xxd
|
||||||
hostPkgs.gdb
|
hostPkgs.gdb
|
||||||
hostPkgs.binutils
|
hostPkgs.binutils
|
||||||
|
hostPkgs.findutils
|
||||||
|
|
||||||
pkgs.libgrapheme
|
pkgs.libgrapheme
|
||||||
pkgs.pcre2
|
pkgs.pcre2
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
inline int read_file(const char *path, char **text, uint32_t *len) {
|
||||||
|
FILE *f = fopen(path, "rb");
|
||||||
|
if (!f)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
long size = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
|
if (size < 0 || size > UINT32_MAX) {
|
||||||
|
fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*len = (uint32_t)size;
|
||||||
|
|
||||||
|
*text = (char *)malloc(*len + 1);
|
||||||
|
if (!*text) {
|
||||||
|
fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t read = fread(*text, 1, *len, f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
if (read != *len) {
|
||||||
|
free(*text);
|
||||||
|
*text = NULL;
|
||||||
|
*len = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*text)[*len] = '\0'; // handy if treating it as a C string
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -30,6 +30,7 @@ extern "C" {
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
|
#include <iostream>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
struct AppendBuffer {
|
struct AppendBuffer : Buffer {
|
||||||
static constexpr uint32_t CHUNK_SIZE = 1 << 16;
|
static constexpr uint32_t CHUNK_SIZE = 1 << 16;
|
||||||
|
|
||||||
using TChunk = char[CHUNK_SIZE];
|
using TChunk = char[CHUNK_SIZE];
|
||||||
std::vector<TChunk *> buf;
|
std::vector<TChunk *> buf;
|
||||||
TChunk *t_current;
|
TChunk *t_current;
|
||||||
@@ -22,9 +25,14 @@ struct AppendBuffer {
|
|||||||
inline void key(char c);
|
inline void key(char c);
|
||||||
void append(const char *text, uint32_t length);
|
void append(const char *text, uint32_t length);
|
||||||
|
|
||||||
|
const char *read(uint32_t pos, uint32_t *out_len);
|
||||||
|
uint32_t count_lines(uint32_t pos, uint32_t length);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void new_text_chunk();
|
inline void new_text_chunk();
|
||||||
inline void new_line_chunk();
|
inline void new_line_chunk();
|
||||||
|
|
||||||
|
inline uint32_t find_newline(uint32_t target, uint32_t low, uint32_t high);
|
||||||
|
|
||||||
inline void _append(const char *text, uint32_t length);
|
inline void _append(const char *text, uint32_t length);
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
struct Buffer {
|
||||||
|
virtual const char *read(uint32_t pos, uint32_t *out_len) = 0;
|
||||||
|
virtual uint32_t count_lines(uint32_t pos, uint32_t length) = 0;
|
||||||
|
|
||||||
|
virtual ~Buffer() = default;
|
||||||
|
};
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
struct OriginalBuffer {
|
struct OriginalBuffer : Buffer {
|
||||||
char *buf;
|
char *buf;
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
std::vector<uint32_t> newlines;
|
std::vector<uint32_t> newlines;
|
||||||
@@ -23,4 +24,7 @@ struct OriginalBuffer {
|
|||||||
~OriginalBuffer() {
|
~OriginalBuffer() {
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *read(uint32_t pos, uint32_t *out_len);
|
||||||
|
uint32_t count_lines(uint32_t pos, uint32_t length);
|
||||||
};
|
};
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "buffer/buffer.h"
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
struct Shard {
|
struct Shard {
|
||||||
@@ -14,7 +15,7 @@ struct Shard {
|
|||||||
std::atomic_uint32_t refs;
|
std::atomic_uint32_t refs;
|
||||||
|
|
||||||
Shard(ShardKind kind, uint32_t length, uint32_t lines)
|
Shard(ShardKind kind, uint32_t length, uint32_t lines)
|
||||||
: kind(kind), length(length), lines(lines) {};
|
: kind(kind), length(length), lines(lines), refs(0) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ShardPtr {
|
struct ShardPtr {
|
||||||
@@ -53,17 +54,18 @@ struct Branch : Shard {
|
|||||||
|
|
||||||
Branch(Shard *l, Shard *r)
|
Branch(Shard *l, Shard *r)
|
||||||
: Shard(ShardKind::Branch, l->length + r->length, l->lines + r->lines),
|
: Shard(ShardKind::Branch, l->length + r->length, l->lines + r->lines),
|
||||||
left(ShardPtr(l)), right(ShardPtr(r)) {};
|
left(l), right(r) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Petal : Shard {
|
struct Petal : Shard {
|
||||||
enum struct Kind {
|
Buffer *source;
|
||||||
Original,
|
|
||||||
Append
|
|
||||||
} source;
|
|
||||||
|
|
||||||
uint32_t pos;
|
uint32_t pos;
|
||||||
|
|
||||||
Petal(uint32_t length, uint32_t lines, Kind source, uint32_t pos)
|
Petal(uint32_t length, uint32_t lines, Buffer *source, uint32_t pos)
|
||||||
: Shard(ShardKind::Petal, length, lines), source(source), pos(pos) {};
|
: Shard(ShardKind::Petal, length, lines), source(source), pos(pos) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::pair<ShardPtr, ShardPtr> split(Shard *n, uint32_t offset);
|
||||||
|
|
||||||
|
void print_shard(const Shard *shard, int depth = 0);
|
||||||
|
|||||||
+3
-3
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "append_buffer.h"
|
#include "buffer/append.h"
|
||||||
#include "original_buffer.h"
|
#include "buffer/original.h"
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "shard.h"
|
#include "shard.h"
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ struct Vase {
|
|||||||
root = new Petal(
|
root = new Petal(
|
||||||
length,
|
length,
|
||||||
original.newlines.size(),
|
original.newlines.size(),
|
||||||
Petal::Kind::Original,
|
&original,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+14
@@ -1,5 +1,19 @@
|
|||||||
|
#include "io/file.h"
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
#include "vase/shard.h"
|
||||||
|
#include "vase/vase.h"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
char *text;
|
||||||
|
uint32_t len;
|
||||||
|
|
||||||
|
int s = read_file("./flake.nix", &text, &len);
|
||||||
|
if (!s)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
Vase vase = Vase(text, len);
|
||||||
|
|
||||||
|
print_shard(vase.root.ptr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
#include "vase/append_buffer.h"
|
|
||||||
|
|
||||||
AppendBuffer::AppendBuffer() {
|
|
||||||
new_text_chunk();
|
|
||||||
new_line_chunk();
|
|
||||||
}
|
|
||||||
|
|
||||||
AppendBuffer::~AppendBuffer() {
|
|
||||||
for (auto p : buf)
|
|
||||||
free(p);
|
|
||||||
for (auto p : newlines)
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void AppendBuffer::key(char c) {
|
|
||||||
if (t_offset == CHUNK_SIZE)
|
|
||||||
new_text_chunk();
|
|
||||||
(*t_current)[t_offset++] = c;
|
|
||||||
if (c == '\n') {
|
|
||||||
if (l_offset == CHUNK_SIZE)
|
|
||||||
new_line_chunk();
|
|
||||||
(*l_current)[l_offset++] = current_offset;
|
|
||||||
}
|
|
||||||
++current_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppendBuffer::append(const char *text, uint32_t length) {
|
|
||||||
while (length) {
|
|
||||||
uint32_t space = CHUNK_SIZE - t_offset;
|
|
||||||
if (space == 0) {
|
|
||||||
new_text_chunk();
|
|
||||||
space = CHUNK_SIZE;
|
|
||||||
}
|
|
||||||
uint32_t copy = length < space ? length : space;
|
|
||||||
_append(text, copy);
|
|
||||||
text += copy;
|
|
||||||
length -= copy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void AppendBuffer::new_text_chunk() {
|
|
||||||
t_current = (TChunk *)malloc(sizeof(TChunk));
|
|
||||||
buf.push_back(t_current);
|
|
||||||
t_offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void AppendBuffer::new_line_chunk() {
|
|
||||||
l_current = (LChunk *)malloc(sizeof(LChunk));
|
|
||||||
newlines.push_back(l_current);
|
|
||||||
l_offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void AppendBuffer::_append(const char *text, uint32_t length) {
|
|
||||||
memcpy((*t_current) + t_offset, text, length);
|
|
||||||
|
|
||||||
const char *p = text;
|
|
||||||
const char *end = text + length;
|
|
||||||
|
|
||||||
while (p < end) {
|
|
||||||
p = (const char *)memchr(p, '\n', end - p);
|
|
||||||
if (!p)
|
|
||||||
break;
|
|
||||||
if (l_offset == CHUNK_SIZE)
|
|
||||||
new_line_chunk();
|
|
||||||
(*l_current)[l_offset++] = current_offset + uint32_t(p - text);
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
t_offset += length;
|
|
||||||
current_offset += length;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
#include "vase/buffer/append.h"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
AppendBuffer::AppendBuffer() {
|
||||||
|
new_text_chunk();
|
||||||
|
new_line_chunk();
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendBuffer::~AppendBuffer() {
|
||||||
|
for (auto p : buf)
|
||||||
|
free(p);
|
||||||
|
for (auto p : newlines)
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void AppendBuffer::key(char c) {
|
||||||
|
if (t_offset == CHUNK_SIZE)
|
||||||
|
new_text_chunk();
|
||||||
|
(*t_current)[t_offset++] = c;
|
||||||
|
if (c == '\n') {
|
||||||
|
if (l_offset == CHUNK_SIZE)
|
||||||
|
new_line_chunk();
|
||||||
|
(*l_current)[l_offset++] = current_offset;
|
||||||
|
}
|
||||||
|
++current_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppendBuffer::append(const char *text, uint32_t length) {
|
||||||
|
while (length) {
|
||||||
|
uint32_t space = CHUNK_SIZE - t_offset;
|
||||||
|
if (space == 0) {
|
||||||
|
new_text_chunk();
|
||||||
|
space = CHUNK_SIZE;
|
||||||
|
}
|
||||||
|
uint32_t copy = length < space ? length : space;
|
||||||
|
_append(text, copy);
|
||||||
|
text += copy;
|
||||||
|
length -= copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *AppendBuffer::read(uint32_t pos, uint32_t *out_len) {
|
||||||
|
if (pos >= current_offset)
|
||||||
|
return nullptr;
|
||||||
|
uint32_t local_offset = pos % CHUNK_SIZE;
|
||||||
|
if (out_len) {
|
||||||
|
uint32_t remaining = current_offset - pos;
|
||||||
|
uint32_t until_chunk_end = CHUNK_SIZE - local_offset;
|
||||||
|
*out_len = std::min(remaining, until_chunk_end);
|
||||||
|
}
|
||||||
|
return &(*buf[pos / CHUNK_SIZE])[local_offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t AppendBuffer::find_newline(uint32_t target, uint32_t low, uint32_t high) {
|
||||||
|
if (low >= high)
|
||||||
|
return low;
|
||||||
|
|
||||||
|
uint32_t first_chunk = low / CHUNK_SIZE;
|
||||||
|
uint32_t last_chunk = (high - 1) / CHUNK_SIZE;
|
||||||
|
|
||||||
|
uint32_t left = first_chunk;
|
||||||
|
uint32_t right = last_chunk;
|
||||||
|
|
||||||
|
while (left < right) {
|
||||||
|
uint32_t mid = left + (right - left) / 2;
|
||||||
|
|
||||||
|
uint32_t first_value = (*newlines[mid])[0];
|
||||||
|
|
||||||
|
if (first_value < target)
|
||||||
|
left = mid + 1;
|
||||||
|
else
|
||||||
|
right = mid;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t chunk = left;
|
||||||
|
|
||||||
|
if (chunk > first_chunk) {
|
||||||
|
LChunk &prev = *newlines[chunk - 1];
|
||||||
|
|
||||||
|
uint32_t prev_size =
|
||||||
|
(chunk - 1 == newlines.size() - 1) ? l_offset : CHUNK_SIZE;
|
||||||
|
|
||||||
|
if (prev[prev_size - 1] >= target)
|
||||||
|
chunk--;
|
||||||
|
}
|
||||||
|
|
||||||
|
LChunk &c = *newlines[chunk];
|
||||||
|
|
||||||
|
uint32_t chunk_size =
|
||||||
|
(chunk == newlines.size() - 1) ? l_offset : CHUNK_SIZE;
|
||||||
|
|
||||||
|
uint32_t l = 0;
|
||||||
|
uint32_t r = chunk_size;
|
||||||
|
|
||||||
|
while (l < r) {
|
||||||
|
uint32_t m = l + (r - l) / 2;
|
||||||
|
|
||||||
|
if (c[m] < target)
|
||||||
|
l = m + 1;
|
||||||
|
else
|
||||||
|
r = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunk * CHUNK_SIZE + l;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t AppendBuffer::count_lines(uint32_t pos, uint32_t length) {
|
||||||
|
if (newlines.empty())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uint32_t total_newlines = CHUNK_SIZE * (newlines.size() - 1) + l_offset;
|
||||||
|
uint32_t pos_index = find_newline(pos, 0, total_newlines);
|
||||||
|
uint32_t end_index = find_newline(pos + length, pos_index, total_newlines);
|
||||||
|
|
||||||
|
return end_index - pos_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void AppendBuffer::new_text_chunk() {
|
||||||
|
t_current = (TChunk *)malloc(sizeof(TChunk));
|
||||||
|
buf.push_back(t_current);
|
||||||
|
t_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void AppendBuffer::new_line_chunk() {
|
||||||
|
l_current = (LChunk *)malloc(sizeof(LChunk));
|
||||||
|
newlines.push_back(l_current);
|
||||||
|
l_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void AppendBuffer::_append(const char *text, uint32_t length) {
|
||||||
|
memcpy((*t_current) + t_offset, text, length);
|
||||||
|
|
||||||
|
const char *p = text;
|
||||||
|
const char *end = text + length;
|
||||||
|
|
||||||
|
while (p < end) {
|
||||||
|
p = (const char *)memchr(p, '\n', end - p);
|
||||||
|
if (!p)
|
||||||
|
break;
|
||||||
|
if (l_offset == CHUNK_SIZE)
|
||||||
|
new_line_chunk();
|
||||||
|
(*l_current)[l_offset++] = current_offset + uint32_t(p - text);
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_offset += length;
|
||||||
|
current_offset += length;
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#include "vase/buffer/original.h"
|
||||||
|
|
||||||
|
const char *OriginalBuffer::read(uint32_t pos, uint32_t *out_len) {
|
||||||
|
if (pos >= length)
|
||||||
|
return nullptr;
|
||||||
|
*out_len = length - pos;
|
||||||
|
return buf + pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t OriginalBuffer::count_lines(uint32_t pos, uint32_t length) {
|
||||||
|
auto start = std::lower_bound(
|
||||||
|
newlines.begin(),
|
||||||
|
newlines.end(),
|
||||||
|
pos
|
||||||
|
);
|
||||||
|
|
||||||
|
auto end = std::lower_bound(
|
||||||
|
start,
|
||||||
|
newlines.end(),
|
||||||
|
pos + length
|
||||||
|
);
|
||||||
|
|
||||||
|
return (uint32_t)(end - start);
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
#include "vase/shard.h"
|
||||||
|
|
||||||
|
std::pair<ShardPtr, ShardPtr> split(Shard *n, uint32_t offset) {
|
||||||
|
if (!n)
|
||||||
|
return {nullptr, nullptr};
|
||||||
|
|
||||||
|
if (offset == 0)
|
||||||
|
return {nullptr, ShardPtr(n)};
|
||||||
|
|
||||||
|
if (offset == n->length)
|
||||||
|
return {ShardPtr(n), nullptr};
|
||||||
|
|
||||||
|
if (n->kind == Shard::ShardKind::Branch) {
|
||||||
|
Branch *b = static_cast<Branch *>(n);
|
||||||
|
|
||||||
|
if (offset < b->left.ptr->length) {
|
||||||
|
auto [a, b2] = split(b->left.ptr, offset);
|
||||||
|
|
||||||
|
return {
|
||||||
|
a,
|
||||||
|
ShardPtr(new Branch(
|
||||||
|
b2.ptr,
|
||||||
|
b->right.ptr
|
||||||
|
))
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
auto [a, b2] = split(
|
||||||
|
b->right.ptr,
|
||||||
|
offset - b->left.ptr->length
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
ShardPtr(new Branch(
|
||||||
|
b->left.ptr,
|
||||||
|
a.ptr
|
||||||
|
)),
|
||||||
|
b2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Petal *p = static_cast<Petal *>(n);
|
||||||
|
|
||||||
|
auto left = new Petal(
|
||||||
|
offset,
|
||||||
|
p->source->count_lines(0, offset),
|
||||||
|
p->source,
|
||||||
|
p->pos
|
||||||
|
);
|
||||||
|
|
||||||
|
auto right = new Petal(
|
||||||
|
p->length - offset,
|
||||||
|
p->source->count_lines(offset, p->length),
|
||||||
|
p->source,
|
||||||
|
p->pos + offset
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
ShardPtr(left),
|
||||||
|
ShardPtr(right)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_shard(const Shard *shard, int depth) {
|
||||||
|
if (!shard) {
|
||||||
|
std::cout << std::string(depth * 2, ' ') << "<null>\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string indent(depth * 2, ' ');
|
||||||
|
|
||||||
|
std::cout << indent;
|
||||||
|
|
||||||
|
if (shard->kind == Shard::ShardKind::Branch) {
|
||||||
|
auto *branch = static_cast<const Branch *>(shard);
|
||||||
|
|
||||||
|
std::cout
|
||||||
|
<< "Branch"
|
||||||
|
<< " @" << shard
|
||||||
|
<< " len=" << shard->length
|
||||||
|
<< " lines=" << shard->lines
|
||||||
|
<< " refs=" << shard->refs.load()
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
std::cout << indent << "├─ left:\n";
|
||||||
|
print_shard(branch->left.ptr, depth + 2);
|
||||||
|
|
||||||
|
std::cout << indent << "└─ right:\n";
|
||||||
|
print_shard(branch->right.ptr, depth + 2);
|
||||||
|
} else {
|
||||||
|
auto *petal = static_cast<const Petal *>(shard);
|
||||||
|
|
||||||
|
std::cout
|
||||||
|
<< "Petal"
|
||||||
|
<< " @" << shard
|
||||||
|
<< " len=" << shard->length
|
||||||
|
<< " lines=" << shard->lines
|
||||||
|
<< " refs=" << shard->refs.load()
|
||||||
|
<< " source=@" << petal->source
|
||||||
|
<< " pos=" << petal->pos
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user