-
-
Notifications
You must be signed in to change notification settings - Fork 45
/
colors.cpp
143 lines (114 loc) · 3.83 KB
/
colors.cpp
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "colors.h"
std::map<string, int> erroneous;
namespace Colors {
// Embedded colors, as a byte array. This array is created by compiling
// `colors.json` into `colors.bson`, using `json2bson`, then included here. The
// json library can then interpret it into a usable `Palette` object
const std::vector<uint8_t> default_colors =
#include "colors.bson"
;
} // namespace Colors
bool Colors::load(Palette *colors, const json &data) {
Palette defined;
try {
defined = data.get<Colors::Palette>();
} catch (const nlohmann::detail::parse_error &err) {
logger::error("Parsing JSON data failed: {}", err.what());
return false;
} catch (const std::invalid_argument &err) {
logger::error("Parsing JSON data failed: {}", err.what());
return false;
}
for (const auto &overriden : defined)
colors->insert_or_assign(overriden.first, overriden.second);
return true;
}
// Load colors from file into the palette passed as an argument
bool Colors::load(Palette *colors, const fs::path &color_file) {
json colors_j;
if (color_file.empty() || !fs::exists(color_file)) {
logger::error("Could not open color file `{}`", color_file.string());
return false;
}
FILE *f = fopen(color_file.string().c_str(), "r");
try {
colors_j = json::parse(f);
} catch (const nlohmann::detail::parse_error &err) {
logger::error("Parsing color file `{}` failed: {}", color_file.string(),
err.what());
fclose(f);
return false;
}
fclose(f);
bool status = load(colors, colors_j);
if (!status)
logger::error("From file `{}`", color_file.string());
return true;
}
void Colors::to_json(json &data, const Color &c) {
data = fmt::format("{:c}", c);
}
void Colors::from_json(const json &data, Color &c) {
if (data.is_string()) {
c = Colors::Color(data.get<std::string>());
} else if (data.is_array()) {
c = Colors::Color(data.get<list<int>>());
}
}
void Colors::to_json(json &j, const Block &b) {
if (b.type == Colors::BlockTypes::FULL) {
j = json(fmt::format("{:c}", b.primary));
return;
}
string type = typeToString.at(b.type);
j = json{{"type", type}, {"color", b.primary}};
if (!b.secondary.empty())
j["accent"] = b.secondary;
}
void Colors::from_json(const json &data, Block &b) {
string stype;
// If the definition is an array, the block is a full block with a single
// color
if (data.is_string() || data.is_array()) {
b = Block(BlockTypes::FULL, data);
return;
}
// If the definition is an object and there is no color, replace it with air
if (data.find("color") == data.end()) {
b = Block();
throw(std::invalid_argument(fmt::format(
"Wrong color format: no color attribute found in `{}`", data.dump())));
}
// If the type is illegal, default it with a full block
if (data.find("type") == data.end()) {
if (data.is_string() || data.is_array()) {
b = Block(BlockTypes::FULL, data["color"]);
return;
}
}
stype = data["type"].get<string>();
if (Colors::stringToType.find(stype) == stringToType.end()) {
auto pair = erroneous.find(stype);
if (pair == erroneous.end()) {
logger::warn("Block with type {} is either disabled or not implemented",
stype);
erroneous.insert(std::pair<string, int>(stype, 1));
} else
pair->second ;
b = Block(BlockTypes::FULL, data["color"]);
return;
}
BlockTypes type = stringToType.at(data["type"].get<string>());
if (data.find("accent") != data.end())
b = Block(type, data["color"], data["accent"]);
else
b = Block(type, data["color"]);
}
void Colors::to_json(json &j, const Palette &p) {
for (auto it : p)
j.emplace(it.first, json(it.second));
}
void Colors::from_json(const json &j, Palette &p) {
for (auto it : j.get<map<string, json>>())
p.emplace(it.first, it.second.get<Colors::Block>());
}