add debugPrintDot
This commit is contained in:
@@ -13,6 +13,7 @@ add_executable(conflict_set_test ConflictSet.cpp ConflictSet.h)
|
|||||||
target_compile_definitions(conflict_set_test PRIVATE ENABLE_TESTS)
|
target_compile_definitions(conflict_set_test PRIVATE ENABLE_TESTS)
|
||||||
# keep asserts for test
|
# keep asserts for test
|
||||||
target_compile_options(conflict_set_test PRIVATE -UNDEBUG)
|
target_compile_options(conflict_set_test PRIVATE -UNDEBUG)
|
||||||
|
target_compile_options(conflict_set_test PRIVATE -Wall -Wextra -Wpedantic -Wunreachable-code)
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
add_test(NAME conflict_set_test COMMAND conflict_set_test)
|
add_test(NAME conflict_set_test COMMAND conflict_set_test)
|
@@ -86,6 +86,77 @@ void destroyNode(Node *node) {
|
|||||||
assert(node->child[1] == nullptr);
|
assert(node->child[1] == nullptr);
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return a pointer to the node whose key immediately follows `n`'s key (if
|
||||||
|
// `dir` is false, precedes). Return nullptr if none exists.
|
||||||
|
[[maybe_unused]] Node *next(Node *n, bool dir) {
|
||||||
|
// Traverse left spine of right child (when moving right, i.e. dir = true)
|
||||||
|
if (n->child[dir]) {
|
||||||
|
n = n->child[dir];
|
||||||
|
while (n->child[!dir]) {
|
||||||
|
n = n->child[!dir];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Search upward for a node such that we're the left child (when moving
|
||||||
|
// right, i.e. dir = true)
|
||||||
|
while (n->parent && n == n->parent->child[dir]) {
|
||||||
|
n = n->parent;
|
||||||
|
}
|
||||||
|
n = n->parent;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a pointer to the node whose key is greatest among keys in the tree
|
||||||
|
// rooted at `n` (if dir = false, least). Return nullptr if none exists (i.e.
|
||||||
|
// `n` is null).
|
||||||
|
[[maybe_unused]] Node *extrema(Node *n, bool dir) {
|
||||||
|
if (n == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
while (n->child[dir] != nullptr) {
|
||||||
|
n = n->child[dir];
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] void debugPrintDot(FILE *file, Node *node) {
|
||||||
|
|
||||||
|
struct DebugDotPrinter {
|
||||||
|
|
||||||
|
explicit DebugDotPrinter(FILE *file) : file(file) {}
|
||||||
|
|
||||||
|
void print(Node *node) {
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
if (node->child[0] != nullptr) {
|
||||||
|
fprintf(file, " _%.*s -> _%.*s;\n", node->len,
|
||||||
|
(const char *)(node + 1), node->child[0]->len,
|
||||||
|
(const char *)(node->child[0] + 1));
|
||||||
|
print(node->child[0]);
|
||||||
|
} else {
|
||||||
|
fprintf(file, " _%.*s -> null%d;\n", node->len,
|
||||||
|
(const char *)(node + 1), id);
|
||||||
|
fprintf(file, " null%d [shape=point];\n", id);
|
||||||
|
++id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int id = 0;
|
||||||
|
FILE *file;
|
||||||
|
};
|
||||||
|
|
||||||
|
fprintf(file, "digraph TreeSet {\n");
|
||||||
|
fprintf(file, " node [fontname=\"Scientifica\"];\n");
|
||||||
|
for (auto iter = extrema(node, false); iter != nullptr;
|
||||||
|
iter = next(iter, true)) {
|
||||||
|
fprintf(file, " _%.*s;\n", node->len, (const char *)(node + 1));
|
||||||
|
}
|
||||||
|
if (node != nullptr) {
|
||||||
|
DebugDotPrinter{file}.print(node);
|
||||||
|
}
|
||||||
|
fprintf(file, "}\n");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
struct ConflictSet::Impl {
|
struct ConflictSet::Impl {
|
||||||
@@ -151,5 +222,8 @@ ConflictSet &ConflictSet::operator=(ConflictSet &&other) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_TESTS
|
#ifdef ENABLE_TESTS
|
||||||
int main(void) { ConflictSet cs{0}; }
|
int main(void) {
|
||||||
|
ConflictSet::Impl cs{0};
|
||||||
|
debugPrintDot(stdout, cs.root);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
@@ -55,7 +55,9 @@ struct ConflictSet {
|
|||||||
ConflictSet(const ConflictSet &) = delete;
|
ConflictSet(const ConflictSet &) = delete;
|
||||||
ConflictSet &operator=(const ConflictSet &) = delete;
|
ConflictSet &operator=(const ConflictSet &) = delete;
|
||||||
|
|
||||||
private:
|
/// @private
|
||||||
struct Impl;
|
struct Impl;
|
||||||
|
|
||||||
|
private:
|
||||||
Impl *impl;
|
Impl *impl;
|
||||||
};
|
};
|
Reference in New Issue
Block a user