Commit ef14cd42 authored by Mathieu STEFANI's avatar Mathieu STEFANI

Got rid of abusive macros for CacheControl header parsing

parent 791f2ea9
...@@ -93,54 +93,72 @@ CacheControl::parseRaw(const char* str, size_t len) { ...@@ -93,54 +93,72 @@ CacheControl::parseRaw(const char* str, size_t len) {
return p - str == len; return p - str == len;
}; };
#define MAX_SIZE(s) \ struct DirectiveValue {
std::min(sizeof(s) - 1, len - (begin - str)) const char* const str;
const size_t size;
#define TRY_PARSE_TRIVIAL_DIRECTIVE(dstr, directive) \ CacheDirective::Directive repr;
if (memcmp(begin, dstr, MAX_SIZE(dstr)) == 0) { \ };
directives_.push_back(CacheDirective(CacheDirective::directive)); \
begin += sizeof(dstr) - 1; \ #define VALUE(divStr, enumValue) { divStr, sizeof(divStr) - 1, CacheDirective::enumValue }
break; \
} \ static constexpr DirectiveValue TrivialDirectives[] = {
(void) 0 VALUE("no-cache" , NoCache ),
VALUE("no-store" , NoStore ),
// @Todo: check for overflow VALUE("no-transform" , NoTransform ),
#define TRY_PARSE_TIMED_DIRECTIVE(dstr, directive) \ VALUE("only-if-cached" , OnlyIfCached ),
if (memcmp(begin, dstr, MAX_SIZE(dstr)) == 0) { \ VALUE("public" , Public ),
const char *p = static_cast<const char *>(memchr(str, '=', len)); \ VALUE("private" , Private ),
if (p == NULL) { \ VALUE("must-revalidate" , MustRevalidate ),
throw std::runtime_error("Invalid caching directive, missing delta-seconds"); \ VALUE("proxy-revalidate", ProxyRevalidate)
} \ };
char *end; \
int secs = strtol(p + 1, &end, 10); \ static constexpr DirectiveValue TimedDirectives[] = {
if (!eof(end) && *end != ',') { \ VALUE("max-age" , CacheDirective::MaxAge ),
throw std::runtime_error("Invalid caching directive, malformated delta-seconds"); \ VALUE("max-stale", CacheDirective::MaxStale),
} \ VALUE("min-fresh", CacheDirective::MinFresh),
directives_.push_back(CacheDirective(CacheDirective::directive, std::chrono::seconds(secs))); \ VALUE("s-maxage" , CacheDirective::SMaxAge )
begin = end; \ };
break; \
} \ #undef VALUE
(void) 0
const char *begin = str; const char *begin = str;
auto memsize = [&](size_t s) {
return std::min(s, len - (begin - str));
};
do { do {
do { bool found = false;
TRY_PARSE_TRIVIAL_DIRECTIVE("no-cache", NoCache); // First scan trivial directives
TRY_PARSE_TRIVIAL_DIRECTIVE("no-store", NoStore); for (const auto& d: TrivialDirectives) {
TRY_PARSE_TRIVIAL_DIRECTIVE("no-transform", NoTransform); if (memcmp(begin, d.str, memsize(d.size)) == 0) {
TRY_PARSE_TRIVIAL_DIRECTIVE("only-if-cached", OnlyIfCached); directives_.push_back(CacheDirective(d.repr));
TRY_PARSE_TRIVIAL_DIRECTIVE("public", Public); begin += d.size;
TRY_PARSE_TRIVIAL_DIRECTIVE("private", Private); found = true;
TRY_PARSE_TRIVIAL_DIRECTIVE("must-revalidate", MustRevalidate); break;
TRY_PARSE_TRIVIAL_DIRECTIVE("proxy-revalidate", ProxyRevalidate); }
}
TRY_PARSE_TIMED_DIRECTIVE("max-age", MaxAge);
TRY_PARSE_TIMED_DIRECTIVE("max-stale", MaxStale); // Not found, let's try timed directives
TRY_PARSE_TIMED_DIRECTIVE("min-fresh", MinFresh); if (!found) {
TRY_PARSE_TIMED_DIRECTIVE("s-maxage", SMaxAge); for (const auto& d: TimedDirectives) {
if (memcmp(begin, d.str, memsize(d.size)) == 0) {
} while (false); const char *p = static_cast<const char *>(memchr(begin, '=', memsize(len)));
if (p == NULL) {
throw std::runtime_error("Invalid caching directive, missing delta-seconds");
}
char *end;
int secs = strtol(p + 1, &end, 10);
if (!eof(end) && *end != ',') {
throw std::runtime_error("Invalid caching directive, malformated delta-seconds");
}
directives_.push_back(CacheDirective(d.repr, std::chrono::seconds(secs)));
begin = end;
found = true;
break;
}
}
}
if (!eof(begin)) { if (!eof(begin)) {
if (*begin != ',') if (*begin != ',')
...@@ -151,9 +169,6 @@ CacheControl::parseRaw(const char* str, size_t len) { ...@@ -151,9 +169,6 @@ CacheControl::parseRaw(const char* str, size_t len) {
} while (!eof(begin)); } while (!eof(begin));
#undef TRY_PARSE_TRIVIAL_DIRECTIVE
#undef TRY_PARSE_TIMED_DIRECTIVE
} }
void void
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment