Kea 3.3.1
buffer.h
Go to the documentation of this file.
1// Copyright (C) 2009-2026 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#ifndef BUFFER_H
8#define BUFFER_H
9
11
12#include <cstdint>
13#include <cstdlib>
14#include <cstring>
15#include <vector>
16
17#include <boost/shared_ptr.hpp>
18
19namespace isc {
20namespace util {
21
82public:
90 InputBuffer(const void* data, size_t len)
91 : base_(static_cast<const uint8_t*>(data)), current_(base_),
92 end_(base_ + len) {
93 }
94
96 size_t getLength() const {
97 return (static_cast<size_t>(end_ - base_));
98 }
99
101 size_t getPosition() const {
102 return (static_cast<size_t>(current_ - base_));
103 }
104
106 size_t getRemaining() const {
107 return (static_cast<size_t>(end_ - current_));
108 }
109
117 void setPosition(size_t position) {
118 // Compare sizes, not pointers: base_ + position can wrap and
119 // incorrectly pass the former pointer-based check.
120 if (position > getLength()) {
122 "InputBuffer::setPosition position is too large");
123 }
124
125 current_ = base_ + position;
126 }
127
132 uint8_t peekUint8() {
133 if (sizeof(uint8_t) > getRemaining()) {
135 "InputBuffer::peekUint8 read beyond end of buffer");
136 }
137
138 return (*current_);
139 }
140
145 uint8_t readUint8() {
146 uint8_t ret = peekUint8();
147 current_ += sizeof(uint8_t);
148
149 return (ret);
150 }
151
156 uint16_t peekUint16() {
157 if (sizeof(uint16_t) > getRemaining()) {
159 "InputBuffer::peekUint16 read beyond end of buffer");
160 }
161
162 uint16_t ret;
163 ret = (static_cast<uint16_t>(current_[0])) << 8;
164 ret |= (static_cast<uint16_t>(current_[1]));
165
166 return (ret);
167 }
168
173 uint16_t readUint16() {
174 uint16_t ret = peekUint16();
175 current_ += sizeof(uint16_t);
176
177 return (ret);
178 }
179
184 uint32_t peekUint32() {
185 if (sizeof(uint32_t) > getRemaining()) {
187 "InputBuffer::peekUint32 read beyond end of buffer");
188 }
189
190 uint32_t ret;
191 ret = (static_cast<uint32_t>(current_[0])) << 24;
192 ret |= (static_cast<uint32_t>(current_[1])) << 16;
193 ret |= (static_cast<uint32_t>(current_[2])) << 8;
194 ret |= (static_cast<uint32_t>(current_[3]));
195
196 return (ret);
197 }
198
203 uint32_t readUint32() {
204 uint32_t ret = peekUint32();
205 current_ += sizeof(uint32_t);
206
207 return (ret);
208 }
209
217 void peekData(void* data, size_t len) {
218 // Compare remaining size to len; pointer addition can wrap for
219 // very large len values and bypass the check.
220 if (len > getRemaining()) {
222 "InputBuffer::peekData read beyond end of buffer");
223 }
224
225 static_cast<void>(std::memmove(data, current_, len));
226 }
227
235 void readData(void* data, size_t len) {
236 peekData(data, len);
237 current_ += len;
238 }
239
250 void peekVector(std::vector<uint8_t>& data, size_t len) {
251 if (len > getRemaining()) {
253 "InputBuffer::peekVector read beyond end of buffer");
254 }
255
256 data.resize(len);
257 if (len) {
258 peekData(&data[0], len);
259 }
260 }
261
271 void readVector(std::vector<uint8_t>& data, size_t len) {
272 peekVector(data, len);
273 current_ += len;
274 }
275
276private:
278 const uint8_t* base_;
279
281 const uint8_t* current_;
282
284 const uint8_t* end_;
285};
286
288typedef boost::shared_ptr<InputBuffer> InputBufferPtr;
289
356public:
360 explicit OutputBuffer(size_t len) : buffer_() {
361 if (len != 0) {
362 buffer_.reserve(len);
363 }
364 }
365
369 OutputBuffer(const OutputBuffer& other) : buffer_(other.buffer_) {
370 size_t len = other.buffer_.capacity();
371 if (len != 0) {
372 buffer_.reserve(len);
373 }
374 }
375
377 ~OutputBuffer() = default;
378
383 if (this != &other) {
384 // Not self-assignment.
385 buffer_ = other.buffer_;
386 size_t len = other.buffer_.capacity();
387 if (len != 0) {
388 buffer_.reserve(len);
389 }
390 }
391
392 return (*this);
393 }
394
396 size_t getCapacity() const {
397 return (buffer_.capacity());
398 }
399
407 const uint8_t* getData() const {
408 if (!buffer_.empty()) {
409 return (&buffer_[0]);
410 } else {
411 return (0);
412 }
413 }
414
416 const void* getDataAsVoidPtr() const {
417 return (static_cast<const void*>(getData()));
418 }
419
421 size_t getLength() const {
422 return (buffer_.size());
423 }
424
432 uint8_t operator[](size_t position) const {
433 if (position >= buffer_.size()) {
435 "OutputBuffer::[]: pos (" << position
436 << ") >= size (" << buffer_.size() << ")");
437 }
438
439 return (buffer_[position]);
440 }
441
445 const std::vector<uint8_t>& getVector() const {
446 return (buffer_);
447 }
448
457 void skip(size_t len) {
458 buffer_.resize(buffer_.size() + len);
459 }
460
468 void trim(size_t len) {
469 if (len > buffer_.size()) {
471 "OutputBuffer::trim length too large from output buffer");
472 }
473
474 buffer_.resize(buffer_.size() - len);
475 }
476
478 void clear() {
479 buffer_.clear();
480 }
481
485 void writeUint8(uint8_t data) {
486 buffer_.push_back(data);
487 }
488
497 void writeUint8At(uint8_t data, size_t position) {
498 if (position + sizeof(data) > buffer_.size()) {
500 "OutputBuffer::writeUint8At write at invalid position");
501 }
502
503 buffer_[position] = data;
504 }
505
510 void writeUint16(uint16_t data) {
511 buffer_.push_back(static_cast<uint8_t>((data & 0xff00U) >> 8));
512 buffer_.push_back(static_cast<uint8_t>(data & 0x00ffU));
513 }
514
526 void writeUint16At(uint16_t data, size_t position) {
527 if (position + sizeof(data) > buffer_.size()) {
529 "OutputBuffer::writeUint16At write at invalid position");
530 }
531
532 buffer_[position] = static_cast<uint8_t>((data & 0xff00U) >> 8);
533 buffer_[position + 1] = static_cast<uint8_t>(data & 0x00ffU);
534 }
535
540 void writeUint32(uint32_t data) {
541 buffer_.push_back(static_cast<uint8_t>((data & 0xff000000) >> 24));
542 buffer_.push_back(static_cast<uint8_t>((data & 0x00ff0000) >> 16));
543 buffer_.push_back(static_cast<uint8_t>((data & 0x0000ff00) >> 8));
544 buffer_.push_back(static_cast<uint8_t>(data & 0x000000ff));
545 }
546
551 void writeUint64(uint64_t data) {
552 buffer_.push_back(static_cast<uint8_t>((data & 0xff00000000000000) >> 56));
553 buffer_.push_back(static_cast<uint8_t>((data & 0x00ff000000000000) >> 48));
554 buffer_.push_back(static_cast<uint8_t>((data & 0x0000ff0000000000) >> 40));
555 buffer_.push_back(static_cast<uint8_t>((data & 0x000000ff00000000) >> 32));
556 buffer_.push_back(static_cast<uint8_t>((data & 0x00000000ff000000) >> 24));
557 buffer_.push_back(static_cast<uint8_t>((data & 0x0000000000ff0000) >> 16));
558 buffer_.push_back(static_cast<uint8_t>((data & 0x000000000000ff00) >> 8));
559 buffer_.push_back(static_cast<uint8_t>(data & 0x00000000000000ff));
560 }
561
568 void writeData(const void* data, size_t len) {
569 if (len == 0 || data == 0) {
570 return;
571 }
572
573 const uint8_t* ptr = static_cast<const uint8_t*>(data);
574 buffer_.insert(buffer_.end(), ptr, ptr + len);
575 }
576
577private:
579 std::vector<uint8_t> buffer_;
580};
581
583typedef boost::shared_ptr<OutputBuffer> OutputBufferPtr;
584
585} // namespace util
586} // namespace isc
587
588#endif // BUFFER_H
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
void readVector(std::vector< uint8_t > &data, size_t len)
Read specified number of bytes as a vector.
Definition buffer.h:271
uint8_t peekUint8()
Peek an unsigned 8-bit integer from the buffer and return it.
Definition buffer.h:132
uint16_t peekUint16()
Peek an unsigned 16-bit integer in network byte order from the buffer, and return it.
Definition buffer.h:156
InputBuffer(const void *data, size_t len)
Constructor.
Definition buffer.h:90
uint32_t readUint32()
Read an unsigned 32-bit integer in network byte order from the buffer, and return it.
Definition buffer.h:203
void setPosition(size_t position)
Set the read position of the buffer to the given value.
Definition buffer.h:117
size_t getPosition() const
Return the current read position.
Definition buffer.h:101
uint8_t readUint8()
Read an unsigned 8-bit integer from the buffer and return it.
Definition buffer.h:145
void peekData(void *data, size_t len)
Peek data of the specified length from the buffer and copy it to the caller supplied buffer.
Definition buffer.h:217
uint32_t peekUint32()
Read an unsigned 32-bit integer in network byte order from the buffer, and return it.
Definition buffer.h:184
size_t getLength() const
Return the length of the data stored in the buffer.
Definition buffer.h:96
void readData(void *data, size_t len)
Read data of the specified length from the buffer and copy it to the caller supplied buffer.
Definition buffer.h:235
void peekVector(std::vector< uint8_t > &data, size_t len)
Peek specified number of bytes as a vector.
Definition buffer.h:250
uint16_t readUint16()
Read an unsigned 16-bit integer in network byte order from the buffer, and return it.
Definition buffer.h:173
size_t getRemaining() const
Return the size remaining to be read.
Definition buffer.h:106
OutputBuffer & operator=(const OutputBuffer &other)
Assignment operator.
Definition buffer.h:382
~OutputBuffer()=default
Destructor.
void writeUint64(uint64_t data)
Write an unsigned 64-bit integer in host byte order into the buffer in network byte order.
Definition buffer.h:551
OutputBuffer(const OutputBuffer &other)
Copy constructor.
Definition buffer.h:369
void writeUint8(uint8_t data)
Write an unsigned 8-bit integer into the buffer.
Definition buffer.h:485
void writeUint16(uint16_t data)
Write an unsigned 16-bit integer in host byte order into the buffer in network byte order.
Definition buffer.h:510
const void * getDataAsVoidPtr() const
Return data as a pointer to void.
Definition buffer.h:416
void writeUint16At(uint16_t data, size_t position)
Write an unsigned 16-bit integer in host byte order at the specified position of the buffer in networ...
Definition buffer.h:526
uint8_t operator[](size_t position) const
Return the value of the buffer at the specified position.
Definition buffer.h:432
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition buffer.h:568
void writeUint32(uint32_t data)
Write an unsigned 32-bit integer in host byte order into the buffer in network byte order.
Definition buffer.h:540
void trim(size_t len)
Trim the specified length of data from the end of the buffer.
Definition buffer.h:468
OutputBuffer(size_t len)
Constructor.
Definition buffer.h:360
void skip(size_t len)
Insert a specified length of gap at the end of the buffer.
Definition buffer.h:457
const uint8_t * getData() const
Return a pointer to the head of the data stored in the buffer.
Definition buffer.h:407
size_t getLength() const
Return the length of data written in the buffer.
Definition buffer.h:421
void clear()
Clear buffer content.
Definition buffer.h:478
size_t getCapacity() const
Return the current capacity of the buffer.
Definition buffer.h:396
void writeUint8At(uint8_t data, size_t position)
Write an unsigned 8-bit integer into the buffer.
Definition buffer.h:497
const std::vector< uint8_t > & getVector() const
Return the buffer.
Definition buffer.h:445
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< InputBuffer > InputBufferPtr
Type of pointers to input buffer.
Definition buffer.h:288
boost::shared_ptr< OutputBuffer > OutputBufferPtr
Type of pointers to output buffers.
Definition buffer.h:583
Defines the logger used by the top-level component of kea-lfc.