16bool is_wildcard_marker(std::string_view line)
19 return line ==
"*" || line ==
"-";
24 if (is_wildcard_marker(line)) {
25 return std::optional<Rgba32>{std::nullopt};
28 const std::vector<std::string> color_components =
split(std::string{line},
" ");
30 if (color_components.size() != 3) {
35 auto red_result = parse_int<int>(color_components[0]);
36 auto green_result = parse_int<int>(color_components[1]);
37 auto blue_result = parse_int<int>(color_components[2]);
39 if (!red_result.has_value()) {
43 if (!green_result.has_value()) {
45 "invalid rgb green component '{}': {}",
47 green_result.error())};
49 if (!blue_result.has_value()) {
51 "invalid rgb blue component '{}': {}",
FormatParam{color_components[2],
Style::bold}, blue_result.error())};
54 const auto red = red_result.value();
55 const auto green = green_result.value();
56 const auto blue = blue_result.value();
58 if (red < 0 || red > 255) {
63 if (green < 0 || green > 255) {
68 if (blue < 0 || blue > 255) {
73 return std::optional{
Rgba32{
74 static_cast<std::uint8_t
>(
red),
75 static_cast<std::uint8_t
>(
green),
76 static_cast<std::uint8_t
>(
blue),
81 const std::filesystem::path &path,
91 std::vector<std::string> lines{};
93 std::ifstream stream{path};
94 std::string line_buf{};
95 while (std::getline(stream, line_buf)) {
97 lines.push_back(line_buf);
102 std::vector<std::string> err_lines{};
103 err_lines.push_back(format.
format(
104 "{}: file is empty, expected at least 3 header lines:",
FormatParam{path.string(), Style::bold}));
105 err_lines.emplace_back();
106 err_lines.push_back(format.
format(
"{}",
FormatParam{
"JASC-PAL", Style::italic}));
108 err_lines.push_back(format.
format(
"{}",
FormatParam{
"<PAL-SIZE>", Style::italic}));
113 if (lines.size() < 3) {
114 std::vector<std::string> err_lines{};
115 err_lines.push_back(format.
format(
116 "{}: file too short, expected at least 3 header lines",
FormatParam{path.string(), Style::bold}));
117 err_lines.emplace_back();
118 err_lines.append_range(file_printer.
print(lines, std::vector<std::size_t>{0}));
125 if (lines[0] !=
"JASC-PAL") {
126 std::vector<std::string> err_lines{};
127 err_lines.push_back(format.
format(
128 "{}:{}: expected '{}' as first line of file",
132 err_lines.emplace_back();
133 err_lines.append_range(file_printer.
print(lines, std::vector<std::size_t>{0}));
138 if (lines[1] !=
"0100") {
139 std::vector<std::string> err_lines{};
140 err_lines.push_back(format.
format(
141 "{}:{}: expected '{}' as second line of file",
145 err_lines.emplace_back();
146 err_lines.append_range(file_printer.
print(lines, std::vector<std::size_t>{1}));
151 const auto declared_size_result = parse_int<std::size_t>(lines[2]);
152 if (!declared_size_result.has_value()) {
153 std::vector<std::string> err_lines{};
154 err_lines.push_back(format.
format(
155 "{}:{}: expected integral value for declared size",
158 err_lines.emplace_back();
159 err_lines.append_range(file_printer.
print(lines, std::vector<std::size_t>{2}));
162 const auto declared_size = declared_size_result.value();
164 std::vector<std::string> err_lines{};
165 err_lines.push_back(format.
format(
166 "{}:{}: expected declared size to be '{}', saw '{}'",
171 err_lines.emplace_back();
172 err_lines.append_range(file_printer.
print(lines, std::vector<std::size_t>{2}));
177 for (std::size_t color_index = 0; color_index < lines.size() - 3; ++color_index) {
178 const std::size_t line_index = color_index + 3;
179 const auto &line = lines[line_index];
180 const auto color_result = parse_jasc_line(line, format);
182 if (!color_result.has_value()) {
183 std::vector<std::string> err_lines{};
184 err_lines.push_back(format.
format(
185 "{}:{}: error parsing color",
188 err_lines.emplace_back();
189 err_lines.append_range(file_printer.
print(lines, std::vector{line_index}));
194 if (
const auto &maybe_color = color_result.value(); maybe_color.has_value()) {
195 pal.set(color_index, maybe_color.value());
199 if (!allow_wildcards) {
200 std::vector<std::string> err_lines{};
201 err_lines.push_back(format.
format(
202 "{}:{}: wildcard not allowed",
205 err_lines.emplace_back();
206 err_lines.append_range(file_printer.
print(lines, std::vector{line_index}));
209 pal.set_wildcard(color_index);
213 if (
const std::size_t actual_color_count = lines.size() - 3; actual_color_count != declared_size) {
214 std::vector<std::string> err_lines{};
215 err_lines.push_back(format.
format(
216 "{}: declared size is '{}' but only saw {} defined colors",
220 err_lines.emplace_back();
221 err_lines.append_range(file_printer.
print(lines, std::vector<std::size_t>{2}));
235 return parse_jasc_file(path,
true, *format_, *file_printer_);
240 return parse_jasc_file(path,
false, *format_, *file_printer_);
A result type that maintains a chainable sequence of errors for debugging and error reporting.
A service for printing file lines with highlighted lines and line numbers.
std::vector< std::string > print(const std::vector< std::string > &lines, const std::vector< std::size_t > &line_indices_to_highlight, std::size_t window_size=9) const
Prints lines with specified lines highlighted and line numbers shown.
ChainableResult< Palette< Rgba32, pal::max_size > > load_with_wildcards(const std::filesystem::path &path) const override
ChainableResult< Palette< Rgba32, pal::max_size > > load(const std::filesystem::path &path) const override
A generic palette container for colors that support transparency checking.
Represents a 32-bit RGBA color.
static constexpr std::uint8_t alpha_opaque
static const Style bold
Bold text formatting.
Abstract base class for applying text styling with context-aware formatting.
virtual std::string format(const std::string &format_str, const std::vector< FormatParam > ¶ms) const
Formats a string with styled parameters using fmtlib syntax.
constexpr std::size_t max_size
std::string & trim_line_ending(std::string &line)
Removes line ending characters from a string in-place.
@ split
Split the animation into separate animations for each palette variant (not yet implemented).
Utility functions for string manipulation and formatting.