#include <vector>
#include <variant>
#include <string>
#include <iostream>
#include "cpp-httplib/httplib.h"
const std::string cSite { "http://kit.local" };
const std::string cUrlComment { "/comment/?id=" };
using StatusT = httplib::StatusCode;
using ResultT = std::variant<std::string, StatusT>;
using ErrorsList = std::vector<StatusT>;
/* define << for ResultT and Node<T> (below) to print results */
static std::ostream& operator <<(std::ostream& os, const ResultT& val) {
if (const std::string* pval = std::get_if<std::string>(&val))
std::cout << "'" << *pval << "'";
else if (const StatusT* code = std::get_if<StatusT>(&val))
std::cout << "Error " << *code << ": " << httplib::status_message(*code);
return os;
}
/* tree */
template<typename T>
struct Node {
T value;
std::vector<Node<T>> children;
Node() = delete;
Node(const T& val) : value(val) {}
void insert(Node<T>& node)
{
if (node.value == value)
return;
children.push_back(node);
}
friend std::ostream& operator <<(std::ostream& os, const Node<T>& val)
{
os << "[" << val.value << "]";
if (!val.children.empty())
os << "\nChildren:\t";
std::for_each(val.children.cbegin(), val.children.cend(),
[&os] (const Node<T> node) { os << node; });
return os;
}
};
using CommentTree = Node<ResultT>;
template<typename T1, typename T2, typename T3>
Node<T2> traverse(const Node<T1>& src, T3 f) {
Node<T2> result(f(src.value));
std::for_each(src.children.cbegin(), src.children.cend(),
[&] (const Node<T1>& node) {
result.children.push_back(traverse<T1, T2, T3>(node, f));
});
return result;
}
template<typename T1, typename T2, typename T3>
void forAll(const Node<T1> &src, std::vector<T2> &result, T3 f) {
f(src.value, result);
std::for_each(src.children.cbegin(), src.children.cend(),
[&] (const Node<T1>& node) {
forAll<T1, T2, T3>(node, result, f);
});
}
static ResultT tryGetContent(httplib::Client &c, const int x) {
auto res = c.Get(cUrlComment + std::to_string(x));
if (res->status == StatusT::OK_200)
return res->body;
return static_cast<StatusT>(res->status);
}
static std::variant<CommentTree, ErrorsList>
tryGetContent(const Node<int> &src, ErrorsList &errors) {
httplib::Client cli(cSite);
auto actionGet = [&] (const int x) {
return tryGetContent(cli, x);
};
CommentTree result = traverse<int, ResultT, decltype(actionGet)>(src, actionGet);
auto collectErrors = [&] (const CommentTree& node, ErrorsList& list) {
if (const StatusT* code = std::get_if<StatusT>(&node.value))
list.push_back(*code);
};
forAll<ResultT, StatusT, decltype(collectErrors)>(result, errors, collectErrors);
if (errors.size() > 0)
return errors;
return result;
}
int main() {
using IntNode = Node<int>;
IntNode tree { 10 };
IntNode a { 100 }, b { 101 }, c { 102 };
IntNode bb { 1001 };
b.insert(bb);
tree.insert(a);
tree.insert(b);
tree.insert(c);
IntNode root { 1 };
root.insert(tree);
std::cout << "\n Source:\n";
std::cout << root;
ErrorsList errors;
auto result = tryGetContent(root, errors);
/* print result */
if (const auto *list = std::get_if<ErrorsList>(&result)) {
std::for_each(list->cbegin(), list->cend(), [&](const StatusT code) {
std::cout << "\nError " << code << ": " << httplib::status_message(code);
});
} else if (const auto* node = std::get_if<CommentTree>(&result)) {
std::cout << "\n Result:\n";
std::cout << *node;
}
return 0;
}