blob: e99590568b99902c33170556322fd52557596f1f [file] [log] [blame]
#include "spdy/core/spdy_header_storage.h"
#include <cstring>
#include "common/platform/api/quiche_logging.h"
namespace spdy {
namespace {
// SpdyHeaderStorage allocates blocks of this size by default.
const size_t kDefaultStorageBlockSize = 2048;
} // namespace
SpdyHeaderStorage::SpdyHeaderStorage() : arena_(kDefaultStorageBlockSize) {}
absl::string_view SpdyHeaderStorage::Write(const absl::string_view s) {
return absl::string_view(arena_.Memdup(s.data(), s.size()), s.size());
}
void SpdyHeaderStorage::Rewind(const absl::string_view s) {
arena_.Free(const_cast<char*>(s.data()), s.size());
}
absl::string_view SpdyHeaderStorage::WriteFragments(
const std::vector<absl::string_view>& fragments,
absl::string_view separator) {
if (fragments.empty()) {
return absl::string_view();
}
size_t total_size = separator.size() * (fragments.size() - 1);
for (const absl::string_view& fragment : fragments) {
total_size += fragment.size();
}
char* dst = arena_.Alloc(total_size);
size_t written = Join(dst, fragments, separator);
QUICHE_DCHECK_EQ(written, total_size);
return absl::string_view(dst, total_size);
}
size_t Join(char* dst,
const std::vector<absl::string_view>& fragments,
absl::string_view separator) {
if (fragments.empty()) {
return 0;
}
auto* original_dst = dst;
auto it = fragments.begin();
memcpy(dst, it->data(), it->size());
dst += it->size();
for (++it; it != fragments.end(); ++it) {
memcpy(dst, separator.data(), separator.size());
dst += separator.size();
memcpy(dst, it->data(), it->size());
dst += it->size();
}
return dst - original_dst;
}
} // namespace spdy