Haio 0.2.X
Homebrew Asset IO/CDN
Loading...
Searching...
No Matches
pipeline.cpp
Go to the documentation of this file.
1#include <haio.hpp>
2#include <haio_string.hpp>
3
4#include <boost/url/encoding_opts.hpp>
5#include <boost/url/parse.hpp>
6
7#include <stdexcept>
8
9namespace Haio {
10
12 tokens_.push_back(std::move(token));
13 return *this;
14}
15
16const std::vector<Token>& Pipeline::tokens() const {
17 return tokens_;
18}
19
20namespace Tokens {
21Token Source(std::string bucket, std::string path) {
23 token.bucket = std::move(bucket);
24 token.path = std::move(path);
25 return token;
26}
27
31
34 token.format = format;
35 return token;
36}
37
40 token.rect = rect;
41 return token;
42}
43
46 token.size = size;
47 return token;
48}
49
50Token ResizeByPercent(int percent) {
51 Token token;
52 token.kind = TokenKind::Resize;
53 token.percent = percent;
54 return token;
55}
56
57Token Palette(std::string palette, Dither dither, size_t limit, Limit limitHow) {
58 Token token;
60 token.palette = std::move(palette);
61 token.dither = dither;
62 token.limit = limit;
63 token.limitHow = limitHow;
64 return token;
65}
66
67Token Radius(int radius) {
69 token.radius = radius;
70 return token;
71}
72
73Token Encode(Format format, std::optional<Color> color) {
75 token.format = format;
76 token.color = color;
77 return token;
78}
79}
80
81std::unordered_map<std::string, std::string> parseQueryMap(std::string_view query) {
82 std::unordered_map<std::string, std::string> out;
83 if (!query.empty() && query.front() == '?') query.remove_prefix(1);
84 if (query.empty()) return out;
85
86 std::string target = "/?";
87 target.append(query);
88
89 auto parsed = boost::urls::parse_origin_form(target);
90 if (!parsed) throw std::runtime_error("invalid query: " + parsed.error().message());
91
92 boost::urls::encoding_opts opts;
93 opts.space_as_plus = true;
94 for (const auto& param : parsed->params(opts)) {
95 if (!param.key.empty()) out[param.key] = param.has_value ? param.value : std::string{};
96 }
97 return out;
98}
99
100std::vector<Token> parseQueryTokens(std::string_view query) {
101 const auto values = parseQueryMap(query);
102 std::vector<Token> tokens;
103
104 if (auto it = values.find("crop"); it != values.end()) tokens.push_back(Tokens::Crop(String::getRect(it->second)));
105 /**
106 * a url cannot carry a percent sign: "%" opens an escape, so "?resize=30%" is a
107 * broken request rather than a small picture. "30pct" says the same thing and
108 * survives, and both spellings are read here so a query and a command line can
109 * be written the same way.
110 */
111 const auto resizeToken = [](const std::string& value) {
112 const auto share = String::getPercent(value);
113 return share != 0 ? Tokens::ResizeByPercent(share) : Tokens::Resize(String::getSize(value));
114 };
115
116 if (auto it = values.find("size"); it != values.end()) tokens.push_back(resizeToken(it->second));
117 if (auto it = values.find("resize"); it != values.end()) tokens.push_back(resizeToken(it->second));
118 if (auto it = values.find("radius"); it != values.end()) tokens.push_back(Tokens::Radius(String::getInt(it->second)));
119 /**
120 * the colour inside the container, spelled the way ffmpeg spells it.
121 *
122 * it can arrive without a format, and that is a request rather than a mistake:
123 * "?pix_fmt=rgb565" with nothing to wrap it is raw pixels in that colour, which
124 * is what a caller loading a texture straight into a gpu is asking for.
125 */
126 auto pixelFormat = values.find("pix_fmt");
127 if (pixelFormat == values.end()) pixelFormat = values.find("pix_format");
128
129 std::optional<Color> color;
130 if (pixelFormat != values.end()) {
131 color = colorNamed(pixelFormat->second);
132 if (!color) throw std::runtime_error("unknown pixel format: " + pixelFormat->second);
133 }
134
135 if (auto it = values.find("format"); it != values.end()) {
136 tokens.push_back(Tokens::Encode(formatFromName(it->second), color));
137 } else if (color) {
138 tokens.push_back(Tokens::Encode(Format::RAW, color));
139 }
140
141 return tokens;
142}
143
144}
const std::vector< Token > & tokens() const
Definition pipeline.cpp:16
Pipeline & operator|=(Token token)
Definition pipeline.cpp:11
Size getSize(std::string_view value)
Definition string.cpp:67
int getPercent(std::string_view value)
Definition string.cpp:52
int getInt(std::string_view value)
Definition string.cpp:34
Rect getRect(std::string_view value)
Definition string.cpp:88
Token Palette(std::string palette, Dither dither, size_t limit, Limit limitHow)
Definition pipeline.cpp:57
Token Encode(Format format, std::optional< Color > color=std::nullopt)
Definition pipeline.cpp:73
Token Decode(Format format)
Definition pipeline.cpp:32
Token Source(std::string bucket, std::string path)
Definition pipeline.cpp:21
Token Resize(Size size)
Definition pipeline.cpp:44
Token DecodeAuto()
Definition pipeline.cpp:28
Token ResizeByPercent(int percent)
Definition pipeline.cpp:50
Token Crop(Rect rect)
Definition pipeline.cpp:38
Token Radius(int radius)
Definition pipeline.cpp:67
Definition haio.hpp:11
std::string bucket
std::optional< Color > color
std::vector< Token > parseQueryTokens(std::string_view query)
Definition pipeline.cpp:100
TokenKind kind
constexpr Format formatFromName(std::string_view name)
constexpr std::optional< Color > colorNamed(std::string_view name)
std::string path
std::string palette
std::unordered_map< std::string, std::string > parseQueryMap(std::string_view query)
Definition pipeline.cpp:81