vxorg/vxheaven_parse.cpp
2024-10-21 12:27:40 -04:00

122 lines
4.2 KiB
C++

#include "vxheaven_parse.hpp"
#include <format>
#include <fstream>
#include <optional>
#include <ranges>
#include <span>
#include <string>
#include <string_view>
#include <vector>
namespace vxorg {
/// Wrapper for std::views::split.
/// Make sure line outlives the vector.
std::vector<std::string_view> split_by(const std::string& string, char delim) {
auto res = std::vector<std::string_view> {};
for(auto word : std::views::split(string, delim)) {
res.push_back(std::string_view(word));
}
return res;
}
std::string get_sample_name(VxHeavenTree::Node* node) {
if(node == nullptr)
return "";
if(!node->data().is_sample)
return node->data().name;
std::string sample_name {};
std::vector<vxorg::VxHeavenItem*> parent_list {};
vxorg::VxHeavenTree::Node* parent = node->parent_node();
while(parent) {
if(parent->data().name.empty())
break;
parent_list.push_back(&parent->data());
parent = parent->parent_node();
}
for(auto& item : std::views::reverse(parent_list)) {
sample_name += std::format("{}.", item->name);
}
sample_name += node->data().name;
return sample_name;
}
void parse_into_tree(VxHeavenTree& tree, std::istream& is) {
std::string line {};
while(std::getline(is, line)) {
auto split = split_by(line, '.');
VxHeavenTree::Node* type_leaf { nullptr };
VxHeavenTree::Node* platform_leaf { nullptr };
VxHeavenTree::Node* family_leaf { nullptr };
VxHeavenTree::Node* sample_leaf { nullptr };
if(auto* node = tree.root_node()->find_child([&](auto* node) { return node->data().name == split[0]; }); node == nullptr) {
// std::printf("making leaf for type %.*s\n", split[0].length(), split[0].data());
type_leaf = tree.create_leaf({ .name = std::string(split[0].data(), split[0].length()), .is_sample = false });
} else {
// std::printf("using existing leaf for type %.*s\n", split[0].length(), split[0].data());
type_leaf = node;
}
if(split.size() == 1) {
type_leaf->data().is_sample = true;
continue;
}
if(auto* n = type_leaf->find_child([&](auto* node) {
// auto matches = node->data().name == split[1];
// std::printf("trying to find %.*s in node %s's child %s: %s\n", split[1].length(), split[1].data(),
// type_leaf->data().name.c_str(), node->data().name.c_str(), matches ? "matches": "doesnt fucking match god damn it");
return node->data().name == split[1];
});
n == nullptr) {
// std::printf("making leaf for platform %s %.*s\n", type_leaf->data().name.c_str(), split[1].length(), split[1].data());
platform_leaf = type_leaf->create_leaf({ .name = std::string(split[1].data(), split[1].length()), .is_sample = false });
} else {
// std::printf("using existing leaf for platform %.*s\n", split[1].length(), split[1].data());
platform_leaf = n;
}
if(auto* n = platform_leaf->find_child([&](auto* node) { return node->data().name == split[2]; }); n == nullptr) {
// std::printf("making leaf for platform %s %.*s\n", type_leaf->data().name.c_str(), split[1].length(), split[1].data());
family_leaf = platform_leaf->create_leaf({ .name = std::string(split[2].data(), split[2].length()), .is_sample = false });
} else {
// std::printf("using existing leaf for platform %.*s\n", split[1].length(), split[1].data());
family_leaf = n;
}
// Handle famlies with a variantless sample inside of them
if(split.size() == 3) {
family_leaf->data().is_sample = true;
continue;
}
if(split.size() > 4) {
auto subvariants = std::span(split.data() + 4, split.size() - 4);
auto leaf = family_leaf;
for(auto& subvariant : subvariants) {
if(auto* node = leaf->find_child([&](auto* node) { return node->data().name == subvariant; }); node == nullptr) {
leaf = leaf->create_leaf({ .name = std::string(subvariant.data(), subvariant.length()), .is_sample = false });
}
}
leaf->data().is_sample = true;
} else {
auto subvariant = split[3];
if(auto* node = family_leaf->find_child([&](auto* node) { return node->data().name == subvariant; }); node == nullptr) {
family_leaf->create_leaf({ .name = std::string(subvariant.data(), subvariant.length()), .is_sample = true });
}
}
}
}
} // namespace vxorg