blob: d6745bf09fca498cc4c1e2364130f24865f55daf [file] [log] [blame]
danzh2ac23462019-04-11 13:42:16 -07001// Copyright 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/spdy/core/spdy_simple_arena.h"
6
danzh51b7cad2019-04-29 10:59:42 -07007#include <algorithm>
vasilvv0a09b8f2020-04-27 08:08:55 -07008#include <cstring>
danzh51b7cad2019-04-29 10:59:42 -07009
danzh2ac23462019-04-11 13:42:16 -070010#include "net/third_party/quiche/src/spdy/platform/api/spdy_logging.h"
11
12namespace spdy {
13
14SpdySimpleArena::SpdySimpleArena(size_t block_size) : block_size_(block_size) {}
15
16SpdySimpleArena::~SpdySimpleArena() = default;
17
18SpdySimpleArena::SpdySimpleArena(SpdySimpleArena&& other) = default;
19SpdySimpleArena& SpdySimpleArena::operator=(SpdySimpleArena&& other) = default;
20
21char* SpdySimpleArena::Alloc(size_t size) {
22 Reserve(size);
23 Block& b = blocks_.back();
24 DCHECK_GE(b.size, b.used + size);
25 char* out = b.data.get() + b.used;
26 b.used += size;
27 return out;
28}
29
30char* SpdySimpleArena::Realloc(char* original, size_t oldsize, size_t newsize) {
31 DCHECK(!blocks_.empty());
32 Block& last = blocks_.back();
33 if (last.data.get() <= original && original < last.data.get() + last.size) {
34 // (original, oldsize) is in the last Block.
35 DCHECK_GE(last.data.get() + last.used, original + oldsize);
36 if (original + oldsize == last.data.get() + last.used) {
37 // (original, oldsize) was the most recent allocation,
38 if (original + newsize < last.data.get() + last.size) {
39 // (original, newsize) fits in the same Block.
40 last.used += newsize - oldsize;
41 return original;
42 }
43 }
44 }
45 char* out = Alloc(newsize);
46 memcpy(out, original, oldsize);
47 return out;
48}
49
50char* SpdySimpleArena::Memdup(const char* data, size_t size) {
51 char* out = Alloc(size);
52 memcpy(out, data, size);
53 return out;
54}
55
56void SpdySimpleArena::Free(char* data, size_t size) {
57 if (blocks_.empty()) {
58 return;
59 }
60 Block& b = blocks_.back();
61 if (size <= b.used && data + size == b.data.get() + b.used) {
62 // The memory region passed by the caller was the most recent allocation
63 // from the final block in this arena.
64 b.used -= size;
65 }
66}
67
68void SpdySimpleArena::Reset() {
69 blocks_.clear();
70 status_.bytes_allocated_ = 0;
71}
72
73void SpdySimpleArena::Reserve(size_t additional_space) {
74 if (blocks_.empty()) {
75 AllocBlock(std::max(additional_space, block_size_));
76 } else {
77 const Block& last = blocks_.back();
78 if (last.size < last.used + additional_space) {
79 AllocBlock(std::max(additional_space, block_size_));
80 }
81 }
82}
83
84void SpdySimpleArena::AllocBlock(size_t size) {
85 blocks_.push_back(Block(size));
86 status_.bytes_allocated_ += size;
87}
88
89SpdySimpleArena::Block::Block(size_t s) : data(new char[s]), size(s), used(0) {}
90
91SpdySimpleArena::Block::~Block() = default;
92
93SpdySimpleArena::Block::Block(SpdySimpleArena::Block&& other)
94 : size(other.size), used(other.used) {
95 data = std::move(other.data);
96}
97
98SpdySimpleArena::Block& SpdySimpleArena::Block::operator=(
99 SpdySimpleArena::Block&& other) {
100 size = other.size;
101 used = other.used;
102 data = std::move(other.data);
103 return *this;
104}
105
106} // namespace spdy