-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfig.cpp
More file actions
98 lines (83 loc) · 3.08 KB
/
config.cpp
File metadata and controls
98 lines (83 loc) · 3.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "global.h"
import config;
Config::Config(const std::filesystem::path& dataDirectory)
try
: filepath(dataDirectory / filename)
{}
LOG_RETHROW
void Config::save() const
try
{
std::ofstream out(filepath);
out.exceptions(std::ios::badbit | std::ios::failbit);
out << "Version: "s << maxVersion << '\n';
for (const std::filesystem::path& file : recentFiles)
out << "File: "s << file << '\n';
}
LOG_RETHROW
void Config::load()
try
{
const std::regex
regex_comment(R"(\s*(?:#.*)?)"s, std::regex::optimize),
regex_version(R"(\s*version:\s*(\d+)\s*)"s, std::regex::optimize | std::regex::icase),
regex_file(R"(\s*file:\s*(.+)\s*)"s, std::regex::optimize | std::regex::icase);
std::ifstream in(filepath);
std::optional<unsigned> opt_version;
for (std::string line; std::getline(in, line);)
{
std::smatch match;
// Comment
if (std::regex_match(line, match, regex_comment))
continue;
// Version (this should be the first value)
if (std::regex_match(line, match, regex_version))
{
unsigned long version;
try
{
version = std::stoul(match[1]);
}
catch (const std::out_of_range& e)
{
throw std::runtime_error(LOG_INFO "Version in config file ("s + std::string(match[1]) + ") is greater than supported ("s + std::to_string(maxVersion) + "): "s + e.what());
}
catch (const std::invalid_argument& e)
{
throw std::runtime_error(LOG_INFO "Invalid version in config file ("s + std::string(match[1]) + "): "s + e.what());
}
if (opt_version)
{
DebugFile(DebugFile::warning) << LOG_INFO "Version specified more than once, ignoring additional versions\n"s;
continue;
}
if (version > maxVersion)
throw std::runtime_error(LOG_INFO "Version in config "s + std::to_string(version) + "file is greater than supported ("s + std::to_string(maxVersion) + ")"s);
opt_version = version;
continue;
}
// If we got this far without a version, that's an error
if (!opt_version)
throw std::runtime_error(LOG_INFO "Version not specified first in config file"s);
// Recent files
if (std::regex_match(line, match, regex_file))
{
std::filesystem::path path;
std::istringstream in_filepath{std::string(match[1])};
in_filepath >> path;
recentFiles.push_back(std::move(path));
continue;
}
// Unrecognised values; ignore them
DebugFile(DebugFile::warning) << LOG_INFO "Unknown config key\n"s;
}
}
LOG_RETHROW
void Config::addRecentFile(std::filesystem::path recentFilepath)
try
{
if (auto&& it(std::find(std::begin(recentFiles), std::end(recentFiles), recentFilepath)); it != std::end(recentFiles))
recentFiles.erase(it);
recentFiles.push_back(recentFilepath);
}
LOG_RETHROW