#include "core/io/toml_file.hpp" #include "core/common/utils.hpp" #include #include #include namespace clrsync::core::io { toml_file::toml_file(std::string path) { m_path = normalize_path(path).string(); } Result toml_file::parse() { if (!std::filesystem::exists(m_path)) return Err(error_code::file_not_found, "File does not exist", m_path); m_file = toml::parse_file(m_path); return Ok(); } const std::string toml_file::get_string_value(const std::string §ion, const std::string &key) const { return m_file[section][key].value_or(""); } uint32_t toml_file::get_uint_value(const std::string §ion, const std::string &key) const { return m_file[section][key].value_or(0); } uint32_t toml_file::get_bool_value(const std::string §ion, const std::string &key) const { return m_file[section][key].value_or(false); } std::map toml_file::get_table(const std::string §ion_path) const { auto parts = split(section_path, '.'); const toml::table *tbl = m_file.as_table(); for (const auto &part : parts) { if (auto subtbl = tbl->at(part).as_table()) tbl = subtbl; else return {}; } std::map result; for (const auto &p : *tbl) { const auto &val = p.second; if (auto b = val.value()) result[std::string(p.first.str())] = *b; else if (auto s = val.value()) result[std::string(p.first.str())] = *s; else if (auto i = val.value()) result[std::string(p.first.str())] = static_cast(*i); else if (auto d = val.value()) result[std::string(p.first.str())] = static_cast(*d); else result[std::string(p.first.str())] = {}; } return result; } void toml_file::insert_or_update_value(const std::string §ion, const std::string &key, const value_type &value) { toml::table *tbl = m_file.as_table(); std::stringstream ss(section); std::string part; while (std::getline(ss, part, '.')) { auto *sub = (*tbl)[part].as_table(); if (!sub) { (*tbl).insert_or_assign(part, toml::table{}); sub = (*tbl)[part].as_table(); } tbl = sub; } std::visit([&](auto &&v) { tbl->insert_or_assign(key, v); }, value); } void toml_file::remove_section(const std::string §ion) { toml::table *tbl = m_file.as_table(); auto parts = split(section, '.'); if (parts.empty()) return; for (size_t i = 0; i < parts.size() - 1; ++i) { auto *sub = (*tbl)[parts[i]].as_table(); if (!sub) return; tbl = sub; } tbl->erase(parts.back()); } Result toml_file::save_file() { try { std::filesystem::create_directories(std::filesystem::path(m_path).parent_path()); } catch (const std::exception &e) { return Err(error_code::dir_create_failed, e.what(), m_path); } std::ofstream stream(m_path, std::ios::binary); if (!stream) return Err(error_code::file_write_failed, "Failed to open file for writing", m_path); stream << m_file; if (!stream) return Err(error_code::file_write_failed, "Failed to write to file", m_path); return Ok(); } std::vector toml_file::split(const std::string &s, char delim) const { std::vector result; std::string current; for (char c : s) { if (c == delim) { if (!current.empty()) { result.push_back(current); current.clear(); } } else { current += c; } } if (!current.empty()) result.push_back(current); return result; } } // namespace clrsync::core::io