ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
packet_buffer.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstddef>
4#include <cstdint>
5#include <cstring>
6#include <span>
7#include <vector>
8
10
25 public:
26 PacketBuffer() = default;
27
28 // Disable copy semantics - PacketBuffer contains pointers and copying would create dangling references
29 PacketBuffer(const PacketBuffer &) = delete;
31
32 // Enable move semantics
35
39 PacketBuffer(const uint8_t *data, size_t length) : pre_buffer_(data), pre_length_(length) {}
40
44 explicit PacketBuffer(const std::vector<uint8_t> &vec) : pre_buffer_(vec.data()), pre_length_(vec.size()) {}
45 // A temporary vector would leave the buffer dangling
46 explicit PacketBuffer(std::vector<uint8_t> &&) = delete;
47
51 PacketBuffer(const uint8_t *pre_data, size_t pre_length, const uint8_t *post_data, size_t post_length)
52 : pre_buffer_(pre_data), pre_length_(pre_length), post_buffer_(post_data), post_length_(post_length) {}
53
57 PacketBuffer(const uint8_t *pre_data, size_t pre_length, const PacketBuffer *mid_buffer, const uint8_t *post_data,
58 size_t post_length)
59 : pre_buffer_(pre_data),
60 pre_length_(pre_length),
61 mid_buffer_(mid_buffer),
62 post_buffer_(post_data),
63 post_length_(post_length) {}
64
68 size_t size() const {
69 size_t total = this->pre_length_ + this->post_length_;
70 if (this->mid_buffer_ != nullptr) {
71 total += this->mid_buffer_->size();
72 }
73 return total;
74 }
75
79 bool empty() const { return this->size() == 0; }
80
84 bool is_contiguous() const { return this->mid_buffer_ == nullptr && this->post_length_ == 0; }
85
89 std::span<const uint8_t> as_span() const { return {this->pre_buffer_, this->pre_length_}; }
90
96 uint8_t operator[](size_t index) const {
97 if (index < this->pre_length_) {
98 return this->pre_buffer_[index];
99 }
100 index -= this->pre_length_;
101
102 if (this->mid_buffer_ != nullptr) {
103 size_t mid_size = this->mid_buffer_->size();
104 if (index < mid_size) {
105 return (*this->mid_buffer_)[index];
106 }
107 index -= mid_size;
108 }
109
110 return index < this->post_length_ ? this->post_buffer_[index] : 0;
111 }
112
120 size_t copy_to(uint8_t *dest, size_t count, size_t offset = 0) const {
121 size_t total_size = this->size();
122 if (offset >= total_size) {
123 return 0;
124 }
125
126 size_t available = total_size - offset;
127 size_t to_copy = count < available ? count : available;
128 size_t copied = 0;
129
130 // Copy from pre_buffer
131 if (offset < this->pre_length_) {
132 size_t pre_offset = offset;
133 size_t pre_available = this->pre_length_ - pre_offset;
134 size_t pre_copy = to_copy < pre_available ? to_copy : pre_available;
135 std::memcpy(dest, this->pre_buffer_ + pre_offset, pre_copy);
136 copied += pre_copy;
137 dest += pre_copy;
138 offset += pre_copy;
139 }
140
141 // Copy from mid_buffer
142 size_t mid_size = this->mid_buffer_ != nullptr ? this->mid_buffer_->size() : 0;
143 if (copied < to_copy && offset < this->pre_length_ + mid_size) {
144 size_t mid_offset = offset - this->pre_length_;
145 size_t mid_available = mid_size - mid_offset;
146 size_t mid_copy = (to_copy - copied) < mid_available ? (to_copy - copied) : mid_available;
147 this->mid_buffer_->copy_to(dest, mid_copy, mid_offset);
148 copied += mid_copy;
149 dest += mid_copy;
150 offset += mid_copy;
151 }
152
153 // Copy from post_buffer
154 if ((copied < to_copy) && (this->post_length_ > 0)) {
155 size_t post_offset = offset - this->pre_length_ - mid_size;
156 size_t post_available = this->post_length_ - post_offset;
157 size_t post_copy = (to_copy - copied) < post_available ? (to_copy - copied) : post_available;
158 std::memcpy(dest, this->post_buffer_ + post_offset, post_copy);
159 copied += post_copy;
160 }
161
162 return copied;
163 }
164
165 private:
166 const uint8_t *pre_buffer_{nullptr};
167 size_t pre_length_{0};
168 const PacketBuffer *mid_buffer_{nullptr};
169 const uint8_t *post_buffer_{nullptr};
170 size_t post_length_{0};
171};
172
173} // namespace esphome::packet_interface
A buffer class that efficiently represents a composite buffer with three sections:
PacketBuffer & operator=(const PacketBuffer &)=delete
size_t copy_to(uint8_t *dest, size_t count, size_t offset=0) const
Copy data from the buffer to a destination pointer.
std::span< const uint8_t > as_span() const
Get the data as one span.
PacketBuffer(std::vector< uint8_t > &&)=delete
PacketBuffer(const PacketBuffer &)=delete
PacketBuffer & operator=(PacketBuffer &&)=default
PacketBuffer(const uint8_t *pre_data, size_t pre_length, const uint8_t *post_data, size_t post_length)
Construct with pre and post buffers.
size_t size() const
Get the total size of the buffer.
PacketBuffer(const uint8_t *data, size_t length)
Construct from a single buffer.
PacketBuffer(const std::vector< uint8_t > &vec)
Construct from a vector.
uint8_t operator[](size_t index) const
Access a byte at a specific position.
bool empty() const
Check if the buffer is empty.
PacketBuffer(const uint8_t *pre_data, size_t pre_length, const PacketBuffer *mid_buffer, const uint8_t *post_data, size_t post_length)
Construct with pre, mid, and post buffers.
bool is_contiguous() const
Check if all the data is held in the pre-buffer, so it can be read as one span.
PacketBuffer(PacketBuffer &&)=default
unsigned count
Definition gif.cpp:51
uint16_t length
Definition tt21100.cpp:0