Files
poc-links/src/main.cpp
T
Сергей Маринкевич d00bb90a38 blah
2025-08-05 19:30:21 +07:00

163 lines
5.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <iostream>
#include "Logger.h"
#include "nodes/SimpleNode.h"
#include "nodes/ComplexNode.h"
#include "iterators/Traversal.h"
void printNode(INode& node, size_t level) {
for (size_t i = level; i > 0; i--)
std::cout << " ";
std::cout << node.name() << "\n";
}
void printTreeBFS(INode& node) {
for (auto& child : traversal::BFS(&node))
printNode(*child, 0);
}
void printTreeList(INode& node) {
for (auto& child : traversal::DFS(&node))
printNode(*child, 0);
}
void printTreeLadder(INode& node) {
for (auto& [child, level] : traversal::DFS(&node))
printNode(*child, level);
}
int main() {
Logger::setMinSeverity("MAIN", Logger::Severity::Debug);
Logger::suppressCategory("Node");
Logger::suppressCategory("Link");
Logger::suppressCategory("Mixin");
Logger::suppressCategory("ConDes");
Logger::setMinSeverity("ConDes", Logger::Severity::Info);
auto& logger = Logger::get("MAIN");
logger.info("Entering main scope...");
{
auto root = ComplexNode::create("ComplexRoot");
auto child1 = ComplexNode::create("ComplexChild1");
root->linkChild(child1);
std::cout << "\nInit tree:\n";
printTreeLadder(*root);
std::cout << "\n";
{
auto child2 = ComplexNode::create("ComplexChild2");
root->linkChild(child2);
auto subchild2 = SimpleNode::create("SimpleSubChild2");
child2->linkChild(subchild2);
auto child3 = ComplexNode::create("ComplexChild3");
root->linkChild(child3);
child3->linkChild(SimpleNode::create("SimpleSubChild3"));
{
// Негативный сценарий 1: попытка добавить второй SimpleNode к ComplexNode
try {
child2->linkChild(SimpleNode::create("ShouldFail"));
logger.err("[ERROR] Не должно было получиться добавить второй SimpleNode к ComplexNode!");
} catch (const std::logic_error& e) {
logger.warn(std::string("[Ожидаемое исключение] ") + e.what());
}
// Негативный сценарий 2: попытка добавить ComplexNode к SimpleNode
// Это допустимо: SimpleNode может иметь ComplexNode в качестве единственного ребёнка
subchild2->linkChild(ComplexNode::create("GoodComplex"));
logger.info("[OK] ComplexNode успешно добавлен к SimpleNode как единственный ребёнок.");
// Негативный сценарий: попытка добавить второго ребёнка к SimpleNode
try {
subchild2->linkChild(SimpleNode::create("ShouldFail2"));
logger.err("[ERROR] Не должно было получиться добавить второго ребёнка к SimpleNode!");
} catch (const std::logic_error& e) {
logger.warn(std::string("[Ожидаемое исключение] ") + e.what());
}
// Негативный сценарий: попытка добавить SimpleNode в ComplexNode, который уже содержит несколько ComplexNode-дочерних
try {
root->linkChild(SimpleNode::create("BadSimple"));
logger.err("[ERROR] Не должно было получиться добавить SimpleNode в ComplexNode с несколькими ComplexNode-дочерними!");
} catch (const std::logic_error& e) {
logger.warn(std::string("[Ожидаемое исключение] ") + e.what());
}
}
std::cout << "\nAnother tree:\n";
printTreeLadder(*root);
std::cout << "\n";
std::cout << "\nList:\n";
printTreeList(*root);
std::cout << "\n";
std::cout << "\nBFS:\n";
printTreeBFS(*root);
std::cout << "\n";
logger.info("Unlinking ComplexChild2...\n");
child2->unlinkParent();
std::cout << "\nTree after unlink:\n";
printTreeLadder(*root);
std::cout << "\n";
logger.info("Put refs of ComplexChild2, ComplexChild3 and its children");
}
std::cout << "\nTree after scope out:\n";
printTreeLadder(*root);
std::cout << "\n";
logger.info("Unlinking ComplexChild1 and ComplexChild3...\n");
child1->unlinkParent();
for (auto child : traversal::BFS(root)) {
if (child->name() == "ComplexChild3") {
/* Avoid of disconnecting a node of the tree
* we're traversing. Method holds reference
* to it's object itself. But iterator ignores
* smart pointers, feeling free to dereference
* the destroyed object.
*/
#if 1
/* Keep in mind to keep your reference until
* the cycle ends, if you want more than just
* remove subtree.
*/
NodePtr node = *child;
node->unlinkParent();
std::cout << "Unlinked: "
<< node->name() << std::endl;
break;
#else
/* Otherwise, just break immediately you
* unlinked a node. The current pointer is not
* a valid pointer anymore.
*/
child->unlinkParent();
break;
#endif
}
}
root->linkChild(SimpleNode::create("SimpleChild4"));
std::cout << "\nTree flush and link SimpleChild4:\n";
printTreeLadder(*root);
std::cout << "\n";
}
logger.info("Exited main scope. All smart pointers destroyed.");
logger.info("(It don't? Check ConDes logger)");
return 0;
}