Rewrite concat_string_ref

This commit is contained in:
Tatsuhiro Tsujikawa 2016-03-20 17:55:17 +09:00
parent d2b55ad1a2
commit dc3119303a
5 changed files with 53 additions and 61 deletions

View File

@ -1187,17 +1187,10 @@ void prepare_redirect_response(Stream *stream, Http2Handler *hd,
authority = stream->header.host; authority = stream->header.host;
} }
size_t len = scheme.size() + str_size("://") + authority.size() + path.size(); auto location = concat_string_ref(
auto iov = make_byte_ref(stream->balloc, len + 1); stream->balloc, scheme, StringRef::from_lit("://"), authority, path);
auto p = iov.base;
p = std::copy(std::begin(scheme), std::end(scheme), p);
p = util::copy_lit(p, "://");
p = std::copy(std::begin(authority), std::end(authority), p);
p = std::copy(std::begin(path), std::end(path), p);
*p = '\0';
auto headers = auto headers = HeaderRefs{{StringRef::from_lit("location"), location}};
HeaderRefs{{StringRef::from_lit("location"), StringRef{iov.base, p}}};
auto sessions = hd->get_sessions(); auto sessions = hd->get_sessions();
auto status_page = sessions->get_server()->get_status_page(status); auto status_page = sessions->get_server()->get_status_page(status);

View File

@ -120,31 +120,43 @@ StringRef make_string_ref(BlockAllocator &alloc, const StringRef &src) {
return StringRef{dst, src.size()}; return StringRef{dst, src.size()};
} }
// Returns the string which is the concatenation of |a| and |b| in // private function used in concat_string_ref. this is the base
// this order. The resulting string will be NULL-terminated. // function of concat_string_ref_count().
template <typename BlockAllocator> inline size_t concat_string_ref_count(size_t acc) { return acc; }
StringRef concat_string_ref(BlockAllocator &alloc, const StringRef &a,
const StringRef &b) { // private function used in concat_string_ref. This function counts
auto len = a.size() + b.size(); // the sum of length of given arguments. The calculated length is
auto dst = static_cast<uint8_t *>(alloc.alloc(len + 1)); // accumulated, and passed to the next function.
auto p = dst; template <typename... Args>
p = std::copy(std::begin(a), std::end(a), p); size_t concat_string_ref_count(size_t acc, const StringRef &value,
p = std::copy(std::begin(b), std::end(b), p); Args &&... args) {
*p = '\0'; return concat_string_ref_count(acc + value.size(),
return StringRef{dst, len}; std::forward<Args>(args)...);
} }
// Returns the string which is the concatenation of |a|, |b| and |c| // private function used in concat_string_ref. this is the base
// in this order. The resulting string will be NULL-terminated. // function of concat_string_ref_copy().
template <typename BlockAllocator> inline uint8_t *concat_string_ref_copy(uint8_t *p) { return p; }
StringRef concat_string_ref(BlockAllocator &alloc, const StringRef &a,
const StringRef &b, const StringRef &c) { // private function used in concat_string_ref. This function copies
auto len = a.size() + b.size() + c.size(); // given strings into |p|. |p| is incremented by the copied length,
// and returned. In the end, return value points to the location one
// beyond the last byte written.
template <typename... Args>
uint8_t *concat_string_ref_copy(uint8_t *p, const StringRef &value,
Args &&... args) {
p = std::copy(std::begin(value), std::end(value), p);
return concat_string_ref_copy(p, std::forward<Args>(args)...);
}
// Returns the string which is the concatenation of |args| in the
// given order. The resulting string will be NULL-terminated.
template <typename BlockAllocator, typename... Args>
StringRef concat_string_ref(BlockAllocator &alloc, Args &&... args) {
size_t len = concat_string_ref_count(0, std::forward<Args>(args)...);
auto dst = static_cast<uint8_t *>(alloc.alloc(len + 1)); auto dst = static_cast<uint8_t *>(alloc.alloc(len + 1));
auto p = dst; auto p = dst;
p = std::copy(std::begin(a), std::end(a), p); p = concat_string_ref_copy(p, std::forward<Args>(args)...);
p = std::copy(std::begin(b), std::end(b), p);
p = std::copy(std::begin(c), std::end(c), p);
*p = '\0'; *p = '\0';
return StringRef{dst, len}; return StringRef{dst, len};
} }

View File

@ -48,20 +48,11 @@ StringRef create_error_html(BlockAllocator &balloc, unsigned int http_status) {
auto status_string = http2::get_status_string(balloc, http_status); auto status_string = http2::get_status_string(balloc, http_status);
const auto &server_name = httpconf.server_name; const auto &server_name = httpconf.server_name;
size_t len = 256 + server_name.size() + status_string.size() * 2; return concat_string_ref(
balloc, StringRef::from_lit(R"(<!DOCTYPE html><html lang="en"><title>)"),
auto iov = make_byte_ref(balloc, len + 1); status_string, StringRef::from_lit("</title><body><h1>"), status_string,
auto p = iov.base; StringRef::from_lit("</h1><footer>"), server_name,
StringRef::from_lit("</footer></body></html>"));
p = util::copy_lit(p, R"(<!DOCTYPE html><html lang="en"><title>)");
p = std::copy(std::begin(status_string), std::end(status_string), p);
p = util::copy_lit(p, "</title><body><h1>");
p = std::copy(std::begin(status_string), std::end(status_string), p);
p = util::copy_lit(p, "</h1><footer>");
p = std::copy(std::begin(server_name), std::end(server_name), p);
p = util::copy_lit(p, "</footer></body></html>");
*p = '\0';
return StringRef{iov.base, p};
} }
StringRef create_forwarded(BlockAllocator &balloc, int params, StringRef create_forwarded(BlockAllocator &balloc, int params,

View File

@ -264,14 +264,8 @@ void rewrite_request_host_path_from_uri(BlockAllocator &balloc, Request &req,
auto q = util::get_uri_field(uri.c_str(), u, UF_QUERY); auto q = util::get_uri_field(uri.c_str(), u, UF_QUERY);
path = StringRef{std::begin(path), std::end(q)}; path = StringRef{std::begin(path), std::end(q)};
} else { } else {
auto iov = make_byte_ref(balloc, path.size() + 1 + fdata.len + 1); path = concat_string_ref(balloc, path, StringRef::from_lit("?"),
auto p = iov.base; StringRef{&uri[fdata.off], fdata.len});
p = std::copy(std::begin(path), std::end(path), p);
*p++ = '?';
p = std::copy_n(&uri[fdata.off], fdata.len, p);
*p = '\0';
path = StringRef{iov.base, p};
} }
} }

View File

@ -437,11 +437,11 @@ public:
return StringRef(s); return StringRef(s);
} }
const_iterator begin() const { return base; }; constexpr const_iterator begin() const { return base; };
const_iterator cbegin() const { return base; }; constexpr const_iterator cbegin() const { return base; };
const_iterator end() const { return base + len; }; constexpr const_iterator end() const { return base + len; };
const_iterator cend() const { return base + len; }; constexpr const_iterator cend() const { return base + len; };
const_reverse_iterator rbegin() const { const_reverse_iterator rbegin() const {
return const_reverse_iterator{base + len}; return const_reverse_iterator{base + len};
@ -453,10 +453,12 @@ public:
const_reverse_iterator rend() const { return const_reverse_iterator{base}; } const_reverse_iterator rend() const { return const_reverse_iterator{base}; }
const_reverse_iterator crend() const { return const_reverse_iterator{base}; } const_reverse_iterator crend() const { return const_reverse_iterator{base}; }
const char *c_str() const { return base; } constexpr const char *c_str() const { return base; }
size_type size() const { return len; } constexpr size_type size() const { return len; }
bool empty() const { return len == 0; } constexpr bool empty() const { return len == 0; }
const_reference operator[](size_type pos) const { return *(base + pos); } constexpr const_reference operator[](size_type pos) const {
return *(base + pos);
}
std::string str() const { return std::string(base, len); } std::string str() const { return std::string(base, len); }
const uint8_t *byte() const { const uint8_t *byte() const {