Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_ring_buffer / public / pw_ring_buffer / prefixed_entry_ring_buffer.h
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15
16 #include <cstddef>
17 #include <span>
18
19 #include "pw_status/status.h"
20
21 namespace pw {
22 namespace ring_buffer {
23
24 // A circular ring buffer for arbitrary length data entries. Each PushBack()
25 // produces a buffer entry. Each entry consists of a preamble followed by an
26 // arbitrary length data chunk. The preamble is comprised of an optional user
27 // preamble byte and an always present varint. The varint encodes the number of
28 // bytes in the data chunk.
29 //
30 // The ring buffer holds the most recent entries stored in the buffer. Once
31 // filled to capacity, incoming entries bump out the oldest entries to make
32 // room. Entries are internally wrapped around as needed.
33 class PrefixedEntryRingBuffer {
34  public:
35   typedef Status (*ReadOutput)(std::span<const std::byte>);
36
37   PrefixedEntryRingBuffer(bool user_preamble = false)
38       : buffer_(nullptr),
39         buffer_bytes_(0),
40         write_idx_(0),
41         read_idx_(0),
42         entry_count_(0),
43         user_preamble_(user_preamble) {}
44
45   // Set the raw buffer to be used by the ring buffer.
46   //
47   // Return values:
48   // OK - successfully set the raw buffer.
49   // INVALID_ARGUMENT - Argument was nullptr, size zero, or too large.
50   Status SetBuffer(std::span<std::byte> buffer);
51
52   // Removes all data from the ring buffer.
53   void Clear();
54
55   // Write a chunk of data to the ring buffer. If available space is less than
56   // size of data chunk to be written then silently pop and discard oldest
57   // stored data chunks until space is available.
58   //
59   // Preamble argument is a caller-provided value prepended to the front of the
60   // entry. It is only used if user_preamble was set at class construction
61   // time.
62   //
63   // Return values:
64   // OK - Data successfully written to the ring buffer.
65   // INVALID_ARGUMENT - Size of data to write is zero bytes
66   // FAILED_PRECONDITION - Buffer not initialized.
67   // OUT_OF_RANGE - Size of data is greater than buffer size.
68   Status PushBack(std::span<const std::byte> data,
69                   std::byte user_preamble_data = std::byte(0)) {
70     return InternalPushBack(data, user_preamble_data, true);
71   }
72
73   // Write a chunk of data to the ring buffer if there is space available.
74   //
75   // Preamble argument is a caller-provided value prepended to the front of the
76   // entry. It is only used if user_preamble was set at class construction
77   // time.
78   //
79   // Return values:
80   // OK - Data successfully written to the ring buffer.
81   // INVALID_ARGUMENT - Size of data to write is zero bytes
82   // FAILED_PRECONDITION - Buffer not initialized.
83   // OUT_OF_RANGE - Size of data is greater than buffer size.
84   // RESOURCE_EXHAUSTED - The ring buffer doesn't have space for the data
85   // without popping off existing elements.
86   Status TryPushBack(std::span<const std::byte> data,
87                      std::byte user_preamble_data = std::byte(0)) {
88     return InternalPushBack(data, user_preamble_data, false);
89   }
90
91   // Read the oldest stored data chunk of data from the ring buffer to
92   // the provided destination std::span. The number of bytes read is written to
93   // bytes_read
94   //
95   // Return values:
96   // OK - Data successfully read from the ring buffer.
97   // FAILED_PRECONDITION - Buffer not initialized.
98   // OUT_OF_RANGE - No entries in ring buffer to read.
99   // RESOURCE_EXHAUSTED - Destination data std::span was smaller number of bytes
100   // than the data size of the data chunk being read.  Available destination
101   // bytes were filled, remaining bytes of the data chunk were ignored.
102   Status PeekFront(std::span<std::byte> data, size_t* bytes_read);
103
104   Status PeekFront(ReadOutput output);
105
106   // Same as Read but includes the entry's preamble of optional user value and
107   // the varint of the data size
108   Status PeekFrontWithPreamble(std::span<std::byte> data, size_t* bytes_read);
109
110   Status PeekFrontWithPreamble(ReadOutput output);
111
112   // Pop and discard the oldest stored data chunk of data from the ring buffer.
113   //
114   // Return values:
115   // OK - Data successfully read from the ring buffer.
116   // FAILED_PRECONDITION - Buffer not initialized.
117   // OUT_OF_RANGE - No entries in ring buffer to pop.
118   Status PopFront();
119
120   // Dering the buffer by reordering entries internally in the buffer by
121   // rotating to have the oldest entry is at the lowest address/index with
122   // newest entry at the highest address.
123   //
124   // Return values:
125   // OK - Buffer data successfully deringed.
126   // FAILED_PRECONDITION - Buffer not initialized.
127   Status Dering();
128
129   // Get the number of variable-length entries currently in the ring buffer.
130   //
131   // Return value:
132   // Entry count.
133   size_t EntryCount() { return entry_count_; }
134
135   // Get the size in bytes of all the current entries in the ring buffer,
136   // including preamble and data chunk.
137   size_t TotalUsedBytes() { return buffer_bytes_ - RawAvailableBytes(); }
138
139   // Get the size in bytes of the next chunk, not including preamble, to be
140   // read.
141   size_t FrontEntryDataSizeBytes();
142
143   // Get the size in bytes of the next chunk, including preamble and data
144   // chunk, to be read.
145   size_t FrontEntryTotalSizeBytes();
146
147  private:
148   struct EntryInfo {
149     size_t preamble_bytes;
150     size_t data_bytes;
151   };
152
153   // Internal version of Read used by all the public interface versions. T
154   // should be of type ReadOutput.
155   template <typename T>
156   Status InternalRead(T read_output, bool get_preamble);
157
158   // Push back implementation, which optionally discards front elements to fit
159   // the incoming element.
160   Status InternalPushBack(std::span<const std::byte> data,
161                           std::byte user_preamble_data,
162                           bool pop_front_if_needed);
163
164   // Get info struct with the size of the preamble and data chunk for the next
165   // entry to be read.
166   EntryInfo FrontEntryInfo();
167
168   // Get the raw number of available bytes free in the ring buffer. This is
169   // not available bytes for data, since there is a variable size preamble for
170   // each entry.
171   size_t RawAvailableBytes();
172
173   // Do the basic write of the specified number of bytes starting at the last
174   // write index of the ring buffer to the destination, handing any wrap-around
175   // of the ring buffer. This is basic, raw operation with no safety checks.
176   void RawWrite(std::span<const std::byte> source);
177
178   // Do the basic read of the specified number of bytes starting at the given
179   // index of the ring buffer to the destination, handing any wrap-around of
180   // the ring buffer. This is basic, raw operation with no safety checks.
181   void RawRead(std::byte* destination, size_t source_idx, size_t length_bytes);
182
183   size_t IncrementIndex(size_t index, size_t count);
184
185   std::byte* buffer_;
186   size_t buffer_bytes_;
187
188   size_t write_idx_;
189   size_t read_idx_;
190   size_t entry_count_;
191   const bool user_preamble_;
192
193   // Worst case size for the variable-sized preable that is prepended to
194   // each entry.
195   static constexpr size_t kMaxEntryPreambleBytes = sizeof(size_t) + 1;
196
197   // Maximum bufer size allowed. Restricted to this to allow index aliasing to
198   // not overflow.
199   static constexpr size_t kMaxBufferBytes =
200       std::numeric_limits<size_t>::max() / 2;
201 };
202
203 }  // namespace ring_buffer
204 }  // namespace pw