Extracts SpdyHeaderBlock::Storage as a separate library. This is a continuation of the attempt to simplify SpdyHeaderBlock.

gfe-relnote: Refactoring, no functional change.
PiperOrigin-RevId: 284571559
Change-Id: I8396e585439ec58bcdba6aeb22f44f56352625ba
diff --git a/spdy/core/spdy_header_block.cc b/spdy/core/spdy_header_block.cc
index 91c8494..9ccc627 100644
--- a/spdy/core/spdy_header_block.cc
+++ b/spdy/core/spdy_header_block.cc
@@ -25,9 +25,6 @@
 // large header blocks.
 const size_t kInitialMapBuckets = 11;
 
-// SpdyHeaderBlock::Storage allocates blocks of this size by default.
-const size_t kDefaultStorageBlockSize = 2048;
-
 const char kCookieKey[] = "cookie";
 const char kNullSeparator = 0;
 
@@ -42,62 +39,7 @@
 
 }  // namespace
 
-// This class provides a backing store for SpdyStringPieces. It previously used
-// custom allocation logic, but now uses an UnsafeArena instead. It has the
-// property that SpdyStringPieces that refer to data in Storage are never
-// invalidated until the Storage is deleted or Clear() is called.
-//
-// Write operations always append to the last block. If there is not enough
-// space to perform the write, a new block is allocated, and any unused space
-// is wasted.
-class SpdyHeaderBlock::Storage {
- public:
-  Storage() : arena_(kDefaultStorageBlockSize) {}
-  Storage(const Storage&) = delete;
-  Storage& operator=(const Storage&) = delete;
-
-  SpdyStringPiece Write(const SpdyStringPiece s) {
-    return SpdyStringPiece(arena_.Memdup(s.data(), s.size()), s.size());
-  }
-
-  // If |s| points to the most recent allocation from arena_, the arena will
-  // reclaim the memory. Otherwise, this method is a no-op.
-  void Rewind(const SpdyStringPiece s) {
-    arena_.Free(const_cast<char*>(s.data()), s.size());
-  }
-
-  void Clear() { arena_.Reset(); }
-
-  // Given a list of fragments and a separator, writes the fragments joined by
-  // the separator to a contiguous region of memory. Returns a SpdyStringPiece
-  // pointing to the region of memory.
-  SpdyStringPiece WriteFragments(const std::vector<SpdyStringPiece>& fragments,
-                                 SpdyStringPiece separator) {
-    if (fragments.empty()) {
-      return SpdyStringPiece();
-    }
-    size_t total_size = separator.size() * (fragments.size() - 1);
-    for (const auto fragment : fragments) {
-      total_size += fragment.size();
-    }
-    char* dst = arena_.Alloc(total_size);
-    size_t written = Join(dst, fragments, separator);
-    DCHECK_EQ(written, total_size);
-    return SpdyStringPiece(dst, total_size);
-  }
-
-  size_t bytes_allocated() const { return arena_.status().bytes_allocated(); }
-
-  // TODO(xunjieli): https://crbug.com/669108. Merge this with bytes_allocated()
-  size_t EstimateMemoryUsage() const {
-    return arena_.status().bytes_allocated();
-  }
-
- private:
-  SpdyUnsafeArena arena_;
-};
-
-SpdyHeaderBlock::HeaderValue::HeaderValue(Storage* storage,
+SpdyHeaderBlock::HeaderValue::HeaderValue(SpdyHeaderStorage* storage,
                                           SpdyStringPiece key,
                                           SpdyStringPiece initial_value)
     : storage_(storage),
@@ -186,8 +128,8 @@
 
 SpdyHeaderBlock::ValueProxy::~ValueProxy() {
   // If the ValueProxy is destroyed while lookup_result_ == block_->end(),
-  // the assignment operator was never used, and the block's Storage can
-  // reclaim the memory used by the key. This makes lookup-only access to
+  // the assignment operator was never used, and the block's SpdyHeaderStorage
+  // can reclaim the memory used by the key. This makes lookup-only access to
   // SpdyHeaderBlock through operator[] memory-neutral.
   if (valid_ && lookup_result_ == block_->map_.end()) {
     block_->GetStorage()->Rewind(key_);
@@ -197,7 +139,7 @@
 SpdyHeaderBlock::ValueProxy& SpdyHeaderBlock::ValueProxy::operator=(
     const SpdyStringPiece value) {
   *spdy_header_block_value_size_ += value.size();
-  Storage* storage = block_->GetStorage();
+  SpdyHeaderStorage* storage = block_->GetStorage();
   if (lookup_result_ == block_->map_.end()) {
     SPDY_DVLOG(1) << "Inserting: (" << key_ << ", " << value << ")";
     lookup_result_ =
@@ -300,7 +242,7 @@
     SPDY_DVLOG(1) << "Updating key: " << iter->first
                   << " with value: " << value.second;
     value_size_ -= iter->second.SizeEstimate();
-    auto* storage = GetStorage();
+    SpdyHeaderStorage* storage = GetStorage();
     iter->second =
         HeaderValue(storage, iter->first, storage->Write(value.second));
   }
@@ -350,14 +292,14 @@
 void SpdyHeaderBlock::AppendHeader(const SpdyStringPiece key,
                                    const SpdyStringPiece value) {
   auto backed_key = WriteKey(key);
-  auto* storage = GetStorage();
+  SpdyHeaderStorage* storage = GetStorage();
   map_.emplace(std::make_pair(
       backed_key, HeaderValue(storage, backed_key, storage->Write(value))));
 }
 
-SpdyHeaderBlock::Storage* SpdyHeaderBlock::GetStorage() {
+SpdyHeaderStorage* SpdyHeaderBlock::GetStorage() {
   if (storage_ == nullptr) {
-    storage_ = std::make_unique<Storage>();
+    storage_ = std::make_unique<SpdyHeaderStorage>();
   }
   return storage_.get();
 }
@@ -375,23 +317,4 @@
   }
 }
 
-size_t Join(char* dst,
-            const std::vector<SpdyStringPiece>& fragments,
-            SpdyStringPiece 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