diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index 43433f6a..a661fc03 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -542,7 +542,8 @@ std::vector parse_log_format(const char *optarg) { } if (literal_start < var_start) { - res.emplace_back(SHRPX_LOGF_LITERAL, strcopy(literal_start, var_start)); + res.emplace_back(SHRPX_LOGF_LITERAL, + ImmutableString(literal_start, var_start)); } literal_start = p; @@ -552,17 +553,18 @@ std::vector parse_log_format(const char *optarg) { continue; } - res.emplace_back(type, strcopy(value, var_name + var_namelen)); - auto &v = res.back().value; - for (size_t i = 0; v[i]; ++i) { - if (v[i] == '_') { - v[i] = '-'; + auto name = std::string(value, var_name + var_namelen); + for (auto &c : name) { + if (c == '_') { + c = '-'; } } + + res.emplace_back(type, ImmutableString(name)); } if (literal_start != eop) { - res.emplace_back(SHRPX_LOGF_LITERAL, strcopy(literal_start, eop)); + res.emplace_back(SHRPX_LOGF_LITERAL, ImmutableString(literal_start, eop)); } return res; diff --git a/src/shrpx_downstream.cc b/src/shrpx_downstream.cc index c9f148b9..6fe16f9e 100644 --- a/src/shrpx_downstream.cc +++ b/src/shrpx_downstream.cc @@ -224,8 +224,8 @@ void Downstream::force_resume_read() { } namespace { -const Headers::value_type *get_header_linear(const Headers &headers, - const std::string &name) { +const Headers::value_type *search_header_linear(const Headers &headers, + const StringRef &name) { const Headers::value_type *res = nullptr; for (auto &kv : headers) { if (kv.name == name) { @@ -395,8 +395,8 @@ Headers::value_type *FieldStore::header(int16_t token) { return http2::get_header(hdidx_, token, headers_); } -const Headers::value_type *FieldStore::header(const std::string &name) const { - return get_header_linear(headers_, name); +const Headers::value_type *FieldStore::header(const StringRef &name) const { + return search_header_linear(headers_, name); } void FieldStore::add_header(std::string name, std::string value) { diff --git a/src/shrpx_downstream.h b/src/shrpx_downstream.h index 7bc7f0ce..7e8c1f45 100644 --- a/src/shrpx_downstream.h +++ b/src/shrpx_downstream.h @@ -76,7 +76,7 @@ public: Headers::value_type *header(int16_t token); // Returns pointer to the header field with the name |name|. If no // such header is found, returns nullptr. - const Headers::value_type *header(const std::string &name) const; + const Headers::value_type *header(const StringRef &name) const; void add_header(std::string name, std::string value); void add_header(std::string name, std::string value, int16_t token); diff --git a/src/shrpx_log.cc b/src/shrpx_log.cc index 84498b72..aacde3f7 100644 --- a/src/shrpx_log.cc +++ b/src/shrpx_log.cc @@ -243,7 +243,7 @@ void upstream_accesslog(const std::vector &lfv, for (auto &lf : lfv) { switch (lf.type) { case SHRPX_LOGF_LITERAL: - std::tie(p, avail) = copy(lf.value.get(), avail, p); + std::tie(p, avail) = copy(lf.value, avail, p); break; case SHRPX_LOGF_REMOTE_ADDR: std::tie(p, avail) = copy(lgsp.remote_addr, avail, p); @@ -273,7 +273,7 @@ void upstream_accesslog(const std::vector &lfv, break; case SHRPX_LOGF_HTTP: if (req) { - auto hd = req->fs.header(lf.value.get()); + auto hd = req->fs.header(lf.value); if (hd) { std::tie(p, avail) = copy((*hd).value, avail, p); break; diff --git a/src/shrpx_log.h b/src/shrpx_log.h index 84d509cf..7cb00fde 100644 --- a/src/shrpx_log.h +++ b/src/shrpx_log.h @@ -134,10 +134,10 @@ enum LogFragmentType { }; struct LogFragment { - LogFragment(LogFragmentType type, std::unique_ptr value = nullptr) + LogFragment(LogFragmentType type, ImmutableString value = ImmutableString()) : type(type), value(std::move(value)) {} LogFragmentType type; - std::unique_ptr value; + ImmutableString value; }; struct LogSpec { diff --git a/src/template.h b/src/template.h index 3b617e54..259a19e1 100644 --- a/src/template.h +++ b/src/template.h @@ -218,6 +218,16 @@ inline std::unique_ptr strcopy(const std::unique_ptr &val, // appear before the final terminal NULL. class ImmutableString { public: + using traits_type = std::char_traits; + using value_type = traits_type::char_type; + using allocator_type = std::allocator; + using size_type = std::allocator_traits::size_type; + using difference_type = + std::allocator_traits::difference_type; + using const_reference = const value_type &; + using const_pointer = const value_type *; + using const_iterator = const_pointer; + ImmutableString() : len(0) {} ImmutableString(const char *s, size_t slen) : len(slen), base(strcopy(s, len)) {} @@ -244,10 +254,10 @@ public: } const char *c_str() const { return base.get(); } - size_t size() const { return len; } + size_type size() const { return len; } private: - size_t len; + size_type len; std::unique_ptr base; }; @@ -258,10 +268,19 @@ private: // function can be used to export the content as std::string. class StringRef { public: + using traits_type = std::char_traits; + using value_type = traits_type::char_type; + using allocator_type = std::allocator; + using size_type = std::allocator_traits::size_type; + using difference_type = + std::allocator_traits::difference_type; + using const_reference = const value_type &; + using const_pointer = const value_type *; + using const_iterator = const_pointer; + StringRef() : base(""), len(0) {} - template - StringRef(const T &s) - : base(s.c_str()), len(s.size()) {} + StringRef(const std::string &s) : base(s.c_str()), len(s.size()) {} + StringRef(const ImmutableString &s) : base(s.c_str()), len(s.size()) {} StringRef(const char *s) : base(s), len(strlen(s)) {} StringRef(const char *s, size_t n) : base(s), len(n) {} @@ -269,16 +288,31 @@ public: return StringRef(s, N - 1); } + const_iterator begin() const { return base; }; + const_iterator cbegin() const { return base; }; + + const_iterator end() const { return base + len; }; + const_iterator cend() const { return base + len; }; + const char *c_str() const { return base; } - size_t size() const { return len; } + size_type size() const { return len; } std::string str() const { return std::string(base, len); } private: const char *base; - size_t len; + size_type len; }; +inline bool operator==(const StringRef &lhs, const std::string &rhs) { + return lhs.size() == rhs.size() && + std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); +} + +inline bool operator==(const std::string &lhs, const StringRef &rhs) { + return rhs == lhs; +} + inline int run_app(std::function app, int argc, char **argv) { try {