Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(107)

Side by Side Diff: third_party/brotli/enc/ringbuffer.h

Issue 1956893002: Added brotli enc/ and tools/ directories. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Updated to most recent build tools Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/brotli/enc/prefix.h ('k') | third_party/brotli/enc/static_dict.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* Copyright 2013 Google Inc. All Rights Reserved.
2
3 Distributed under MIT license.
4 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5 */
6
7 // Sliding window over the input data.
8
9 #ifndef BROTLI_ENC_RINGBUFFER_H_
10 #define BROTLI_ENC_RINGBUFFER_H_
11
12 #include <cstdlib> /* free, realloc */
13
14 #include "./port.h"
15 #include "./types.h"
16
17 namespace brotli {
18
19 // A RingBuffer(window_bits, tail_bits) contains `1 << window_bits' bytes of
20 // data in a circular manner: writing a byte writes it to:
21 // `position() % (1 << window_bits)'.
22 // For convenience, the RingBuffer array contains another copy of the
23 // first `1 << tail_bits' bytes:
24 // buffer_[i] == buffer_[i + (1 << window_bits)], if i < (1 << tail_bits),
25 // and another copy of the last two bytes:
26 // buffer_[-1] == buffer_[(1 << window_bits) - 1] and
27 // buffer_[-2] == buffer_[(1 << window_bits) - 2].
28 class RingBuffer {
29 public:
30 RingBuffer(int window_bits, int tail_bits)
31 : size_(1u << window_bits),
32 mask_((1u << window_bits) - 1),
33 tail_size_(1u << tail_bits),
34 total_size_(size_ + tail_size_),
35 cur_size_(0),
36 pos_(0),
37 data_(0),
38 buffer_(0) {}
39
40 ~RingBuffer(void) {
41 free(data_);
42 }
43
44 // Allocates or re-allocates data_ to the given length + plus some slack
45 // region before and after. Fills the slack regions with zeros.
46 inline void InitBuffer(const uint32_t buflen) {
47 static const size_t kSlackForEightByteHashingEverywhere = 7;
48 cur_size_ = buflen;
49 data_ = static_cast<uint8_t*>(realloc(
50 data_, 2 + buflen + kSlackForEightByteHashingEverywhere));
51 buffer_ = data_ + 2;
52 buffer_[-2] = buffer_[-1] = 0;
53 for (size_t i = 0; i < kSlackForEightByteHashingEverywhere; ++i) {
54 buffer_[cur_size_ + i] = 0;
55 }
56 }
57
58 // Push bytes into the ring buffer.
59 void Write(const uint8_t *bytes, size_t n) {
60 if (pos_ == 0 && n < tail_size_) {
61 // Special case for the first write: to process the first block, we don't
62 // need to allocate the whole ringbuffer and we don't need the tail
63 // either. However, we do this memory usage optimization only if the
64 // first write is less than the tail size, which is also the input block
65 // size, otherwise it is likely that other blocks will follow and we
66 // will need to reallocate to the full size anyway.
67 pos_ = static_cast<uint32_t>(n);
68 InitBuffer(pos_);
69 memcpy(buffer_, bytes, n);
70 return;
71 }
72 if (cur_size_ < total_size_) {
73 // Lazily allocate the full buffer.
74 InitBuffer(total_size_);
75 // Initialize the last two bytes to zero, so that we don't have to worry
76 // later when we copy the last two bytes to the first two positions.
77 buffer_[size_ - 2] = 0;
78 buffer_[size_ - 1] = 0;
79 }
80 const size_t masked_pos = pos_ & mask_;
81 // The length of the writes is limited so that we do not need to worry
82 // about a write
83 WriteTail(bytes, n);
84 if (PREDICT_TRUE(masked_pos + n <= size_)) {
85 // A single write fits.
86 memcpy(&buffer_[masked_pos], bytes, n);
87 } else {
88 // Split into two writes.
89 // Copy into the end of the buffer, including the tail buffer.
90 memcpy(&buffer_[masked_pos], bytes,
91 std::min(n, total_size_ - masked_pos));
92 // Copy into the beginning of the buffer
93 memcpy(&buffer_[0], bytes + (size_ - masked_pos),
94 n - (size_ - masked_pos));
95 }
96 buffer_[-2] = buffer_[size_ - 2];
97 buffer_[-1] = buffer_[size_ - 1];
98 pos_ += static_cast<uint32_t>(n);
99 if (pos_ > (1u << 30)) { /* Wrap, but preserve not-a-first-lap feature. */
100 pos_ = (pos_ & ((1u << 30) - 1)) | (1u << 30);
101 }
102 }
103
104 void Reset(void) {
105 pos_ = 0;
106 }
107
108 // Logical cursor position in the ring buffer.
109 uint32_t position(void) const { return pos_; }
110
111 // Bit mask for getting the physical position for a logical position.
112 uint32_t mask(void) const { return mask_; }
113
114 uint8_t *start(void) { return &buffer_[0]; }
115 const uint8_t *start(void) const { return &buffer_[0]; }
116
117 private:
118 void WriteTail(const uint8_t *bytes, size_t n) {
119 const size_t masked_pos = pos_ & mask_;
120 if (PREDICT_FALSE(masked_pos < tail_size_)) {
121 // Just fill the tail buffer with the beginning data.
122 const size_t p = size_ + masked_pos;
123 memcpy(&buffer_[p], bytes, std::min(n, tail_size_ - masked_pos));
124 }
125 }
126
127 // Size of the ringbuffer is (1 << window_bits) + tail_size_.
128 const uint32_t size_;
129 const uint32_t mask_;
130 const uint32_t tail_size_;
131 const uint32_t total_size_;
132
133 uint32_t cur_size_;
134 // Position to write in the ring buffer.
135 uint32_t pos_;
136 // The actual ring buffer containing the copy of the last two bytes, the data,
137 // and the copy of the beginning as a tail.
138 uint8_t *data_;
139 // The start of the ringbuffer.
140 uint8_t *buffer_;
141 };
142
143 } // namespace brotli
144
145 #endif // BROTLI_ENC_RINGBUFFER_H_
OLDNEW
« no previous file with comments | « third_party/brotli/enc/prefix.h ('k') | third_party/brotli/enc/static_dict.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698