pw_bytes: Added an ordered put method for values
Added functionality to insert values to the buffer in the endianness
order as specified by the user.
Change-Id: Ie33ac7a38a35cdd1cfdb2952233d13f09242cc8c
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/12472
Reviewed-by: Wyatt Hepler <hepler@google.com>
Commit-Queue: Shane Gomindes <shaneajg@google.com>
diff --git a/pw_bytes/byte_builder.cc b/pw_bytes/byte_builder.cc
index 80e74d2..bcfc9de 100644
--- a/pw_bytes/byte_builder.cc
+++ b/pw_bytes/byte_builder.cc
@@ -16,15 +16,8 @@
namespace pw {
-void ByteBuilder::clear() {
- size_ = 0;
- status_ = Status::OK;
- last_status_ = Status::OK;
-}
-
ByteBuilder& ByteBuilder::append(size_t count, std::byte b) {
std::byte* const append_destination = &buffer_[size_];
-
std::memset(append_destination, static_cast<int>(b), ResizeForAppend(count));
return *this;
}
@@ -36,36 +29,27 @@
}
size_t ByteBuilder::ResizeForAppend(size_t bytes_to_append) {
- const size_t copied = std::min(bytes_to_append, max_size() - size());
- size_ += copied;
-
- if (buffer_.empty() || bytes_to_append != copied) {
- SetErrorStatus(Status::RESOURCE_EXHAUSTED);
- } else {
- last_status_ = Status::OK;
+ if (!status_.ok()) {
+ return 0;
}
- return copied;
+ if (bytes_to_append > max_size() - size()) {
+ status_ = Status::RESOURCE_EXHAUSTED;
+ return 0;
+ }
+
+ size_ += bytes_to_append;
+ status_ = Status::OK;
+ return bytes_to_append;
}
void ByteBuilder::resize(size_t new_size) {
if (new_size <= size_) {
size_ = new_size;
- last_status_ = Status::OK;
+ status_ = Status::OK;
} else {
- SetErrorStatus(Status::OUT_OF_RANGE);
+ status_ = Status::OUT_OF_RANGE;
}
}
-void ByteBuilder::CopySizeAndStatus(const ByteBuilder& other) {
- size_ = other.size_;
- status_ = other.status_;
- last_status_ = other.last_status_;
-}
-
-void ByteBuilder::SetErrorStatus(Status status) {
- last_status_ = status;
- status_ = status;
-}
-
} // namespace pw
diff --git a/pw_bytes/byte_builder_test.cc b/pw_bytes/byte_builder_test.cc
index f39c422..c649b20 100644
--- a/pw_bytes/byte_builder_test.cc
+++ b/pw_bytes/byte_builder_test.cc
@@ -99,14 +99,8 @@
auto bytesTestLiteral = MakeBytes(0x04, 0x05, 0x06, 0x07);
EXPECT_FALSE(bb.append(bytesTestLiteral.data(), 4).ok());
- EXPECT_EQ(Status::RESOURCE_EXHAUSTED, bb.last_status());
-
- EXPECT_EQ(byte{0x04}, bb.data()[0]);
- EXPECT_EQ(byte{0x05}, bb.data()[1]);
- EXPECT_EQ(byte{0x06}, bb.data()[2]);
-
- EXPECT_EQ(bb.size(), bb.max_size());
- EXPECT_EQ(3u, bb.size());
+ EXPECT_EQ(Status::RESOURCE_EXHAUSTED, bb.status());
+ EXPECT_EQ(0u, bb.size());
}
TEST(ByteBuilder, Append_RepeatedBytes) {
@@ -136,10 +130,7 @@
ByteBuffer<8> bb;
EXPECT_EQ(Status::RESOURCE_EXHAUSTED, bb.append(9, byte{0x04}).status());
-
- for (size_t i = 0; i < 8; i++) {
- EXPECT_EQ(byte{0x04}, bb.data()[i]);
- }
+ EXPECT_EQ(0u, bb.size());
}
TEST(ByteBuilder, Append_Partial) {
@@ -165,8 +156,7 @@
ByteBuilder bb(buffer);
bb.resize(1);
-
- EXPECT_EQ(Status::RESOURCE_EXHAUSTED, bb.append(9, byte{0x04}).status());
+ EXPECT_EQ(Status::OUT_OF_RANGE, bb.append(9, byte{0x04}).status());
}
TEST(ByteBuilder, Resize_Smaller) {
@@ -208,43 +198,37 @@
TEST(ByteBuilder, Status_StartsOk) {
ByteBuffer<16> bb;
EXPECT_EQ(Status::OK, bb.status());
- EXPECT_EQ(Status::OK, bb.last_status());
}
-TEST(ByteBuilder, Status_StatusAndLastStatusUpdate) {
+TEST(ByteBuilder, Status_StatusUpdate) {
std::array<byte, 3> buffer = MakeBytes(0x01, 0x02, 0x03);
ByteBuffer<2> bb;
EXPECT_FALSE(bb.append(buffer.data(), 3).ok());
EXPECT_EQ(Status::RESOURCE_EXHAUSTED, bb.status());
- EXPECT_EQ(Status::RESOURCE_EXHAUSTED, bb.last_status());
bb.resize(4);
EXPECT_EQ(Status::OUT_OF_RANGE, bb.status());
- EXPECT_EQ(Status::OUT_OF_RANGE, bb.last_status());
EXPECT_FALSE(bb.append(buffer.data(), 0).ok());
EXPECT_EQ(Status::OUT_OF_RANGE, bb.status());
- EXPECT_EQ(Status::OK, bb.last_status());
}
-TEST(ByteBuilder, Status_ClearStatus_SetsStatuesToOk) {
+TEST(ByteBuilder, Status_ClearStatus_SetsStatusToOk) {
std::array<byte, 3> buffer = MakeBytes(0x01, 0x02, 0x03);
ByteBuffer<2> bb;
EXPECT_FALSE(bb.append(buffer.data(), 3).ok());
EXPECT_EQ(Status::RESOURCE_EXHAUSTED, bb.status());
- EXPECT_EQ(Status::RESOURCE_EXHAUSTED, bb.last_status());
bb.clear_status();
EXPECT_EQ(Status::OK, bb.status());
- EXPECT_EQ(Status::OK, bb.last_status());
}
TEST(ByteBuilder, PushBack) {
ByteBuffer<12> bb;
bb.push_back(byte{0x01});
- EXPECT_EQ(Status::OK, bb.last_status());
+ EXPECT_EQ(Status::OK, bb.status());
EXPECT_EQ(1u, bb.size());
EXPECT_EQ(byte{0x01}, bb.data()[0]);
}
@@ -252,7 +236,7 @@
TEST(ByteBuilder, PushBack_Full) {
ByteBuffer<1> bb;
bb.push_back(byte{0x01});
- EXPECT_EQ(Status::OK, bb.last_status());
+ EXPECT_EQ(Status::OK, bb.status());
EXPECT_EQ(1u, bb.size());
}
@@ -261,7 +245,7 @@
bb.push_back(byte{0x01});
bb.push_back(byte{0x01});
- EXPECT_EQ(Status::RESOURCE_EXHAUSTED, bb.last_status());
+ EXPECT_EQ(Status::RESOURCE_EXHAUSTED, bb.status());
EXPECT_EQ(1u, bb.size());
}
@@ -272,7 +256,7 @@
bb.append(buffer.data(), 3);
bb.pop_back();
- EXPECT_EQ(Status::OK, bb.last_status());
+ EXPECT_EQ(Status::OK, bb.status());
EXPECT_EQ(2u, bb.size());
EXPECT_EQ(byte{0x01}, bb.data()[0]);
EXPECT_EQ(byte{0x02}, bb.data()[1]);
@@ -286,7 +270,7 @@
bb.pop_back();
bb.pop_back();
bb.pop_back();
- EXPECT_EQ(Status::OK, bb.last_status());
+ EXPECT_EQ(Status::OK, bb.status());
EXPECT_EQ(0u, bb.size());
EXPECT_TRUE(bb.empty());
}
@@ -323,14 +307,12 @@
two.push_back(byte{0x01});
two.push_back(byte{0x01});
ASSERT_EQ(Status::RESOURCE_EXHAUSTED, two.status());
- ASSERT_EQ(Status::RESOURCE_EXHAUSTED, two.last_status());
one = two;
EXPECT_EQ(byte{0x01}, two.data()[7]);
EXPECT_EQ(byte{0x01}, two.data()[8]);
EXPECT_EQ(byte{0x01}, two.data()[9]);
EXPECT_EQ(Status::RESOURCE_EXHAUSTED, one.status());
- EXPECT_EQ(Status::RESOURCE_EXHAUSTED, one.last_status());
}
TEST(ByteBuffer, CopyConstructFromSameSize) {
@@ -356,9 +338,197 @@
EXPECT_EQ(byte{0x01}, two.data()[0]);
EXPECT_EQ(byte{0x02}, two.data()[1]);
-
EXPECT_EQ(Status::OK, two.status());
}
+TEST(ByteBuilder, ResizeError_NoDataAddedAfter) {
+ std::array<byte, 3> buffer = MakeBytes(0x01, 0x02, 0x03);
+ ByteBuffer<8> bb;
+
+ EXPECT_TRUE(bb.append(buffer.data(), 3).ok());
+
+ EXPECT_EQ(3u, bb.size());
+ bb.resize(5);
+ EXPECT_EQ(3u, bb.size());
+ EXPECT_EQ(bb.status(), Status::OUT_OF_RANGE);
+
+ bb.PutInt8(0xFE);
+ EXPECT_EQ(3u, bb.size());
+ EXPECT_EQ(bb.status(), Status::OUT_OF_RANGE);
+}
+
+TEST(ByteBuilder, AddingNoBytesToZeroSizedByteBuffer) {
+ std::array<byte, 3> buffer = MakeBytes(0x01, 0x02, 0x03);
+ ByteBuffer<0> bb;
+
+ EXPECT_TRUE(bb.append(buffer.data(), 0).ok());
+ EXPECT_EQ(0u, bb.size());
+}
+
+TEST(ByteBuffer, Putting8ByteInts_Full) {
+ ByteBuffer<2> bb;
+ bb.PutInt8(0xFE);
+ bb.PutUint8(0x02);
+
+ EXPECT_EQ(byte{0xFE}, bb.data()[0]);
+ EXPECT_EQ(byte{0x02}, bb.data()[1]);
+ EXPECT_EQ(Status::OK, bb.status());
+}
+
+TEST(ByteBuffer, Putting8ByteInts_Exhausted) {
+ ByteBuffer<2> bb;
+ bb.PutInt8(0xFE);
+ bb.PutUint8(0x02);
+ bb.PutUint8(0x05);
+
+ EXPECT_EQ(byte{0xFE}, bb.data()[0]);
+ EXPECT_EQ(byte{0x02}, bb.data()[1]);
+ EXPECT_EQ(Status::RESOURCE_EXHAUSTED, bb.status());
+}
+
+TEST(ByteBuffer, Putting16ByteInts_Full_kLittleEndian) {
+ ByteBuffer<4> bb;
+ bb.PutInt16(0xFFF7);
+ bb.PutUint16(0x0008);
+
+ EXPECT_EQ(byte{0xF7}, bb.data()[0]);
+ EXPECT_EQ(byte{0xFF}, bb.data()[1]);
+ EXPECT_EQ(byte{0x08}, bb.data()[2]);
+ EXPECT_EQ(byte{0x00}, bb.data()[3]);
+
+ EXPECT_EQ(Status::OK, bb.status());
+}
+
+TEST(ByteBuffer, Putting16ByteInts_Exhausted_kBigEndian) {
+ ByteBuffer<5> bb;
+ bb.PutInt16(0xFFF7, ByteOrder::kBigEndian);
+ bb.PutUint16(0x0008, ByteOrder::kBigEndian);
+
+ EXPECT_EQ(byte{0xFF}, bb.data()[0]);
+ EXPECT_EQ(byte{0xF7}, bb.data()[1]);
+ EXPECT_EQ(byte{0x00}, bb.data()[2]);
+ EXPECT_EQ(byte{0x08}, bb.data()[3]);
+
+ bb.PutInt16(0xFAFA, ByteOrder::kBigEndian);
+ EXPECT_EQ(4u, bb.size());
+ EXPECT_EQ(Status::RESOURCE_EXHAUSTED, bb.status());
+}
+
+TEST(ByteBuffer, Putting32ByteInts_Full_kLittleEndian) {
+ ByteBuffer<8> bb;
+ bb.PutInt32(0xFFFFFFF1);
+ bb.PutUint32(0x00000014);
+
+ EXPECT_EQ(byte{0xF1}, bb.data()[0]);
+ EXPECT_EQ(byte{0xFF}, bb.data()[1]);
+ EXPECT_EQ(byte{0xFF}, bb.data()[2]);
+ EXPECT_EQ(byte{0xFF}, bb.data()[3]);
+ EXPECT_EQ(byte{0x14}, bb.data()[4]);
+ EXPECT_EQ(byte{0x00}, bb.data()[5]);
+ EXPECT_EQ(byte{0x00}, bb.data()[6]);
+ EXPECT_EQ(byte{0x00}, bb.data()[7]);
+
+ EXPECT_EQ(Status::OK, bb.status());
+}
+
+TEST(ByteBuffer, Putting32ByteInts_Exhausted_kBigEndian) {
+ ByteBuffer<10> bb;
+ bb.PutInt32(0xF92927B2, ByteOrder::kBigEndian);
+ bb.PutUint32(0x0C90739E, ByteOrder::kBigEndian);
+
+ EXPECT_EQ(byte{0xF9}, bb.data()[0]);
+ EXPECT_EQ(byte{0x29}, bb.data()[1]);
+ EXPECT_EQ(byte{0x27}, bb.data()[2]);
+ EXPECT_EQ(byte{0xB2}, bb.data()[3]);
+ EXPECT_EQ(byte{0x0C}, bb.data()[4]);
+ EXPECT_EQ(byte{0x90}, bb.data()[5]);
+ EXPECT_EQ(byte{0x73}, bb.data()[6]);
+ EXPECT_EQ(byte{0x9E}, bb.data()[7]);
+
+ bb.PutInt32(-114743374, ByteOrder::kBigEndian);
+ EXPECT_EQ(8u, bb.size());
+ EXPECT_EQ(Status::RESOURCE_EXHAUSTED, bb.status());
+}
+
+TEST(ByteBuffer, Putting64ByteInts_Full_kLittleEndian) {
+ ByteBuffer<16> bb;
+ bb.PutInt64(0x000001E8A7A0D569);
+ bb.PutUint64(0xFFFFFE17585F2A97);
+
+ EXPECT_EQ(byte{0x69}, bb.data()[0]);
+ EXPECT_EQ(byte{0xD5}, bb.data()[1]);
+ EXPECT_EQ(byte{0xA0}, bb.data()[2]);
+ EXPECT_EQ(byte{0xA7}, bb.data()[3]);
+ EXPECT_EQ(byte{0xE8}, bb.data()[4]);
+ EXPECT_EQ(byte{0x01}, bb.data()[5]);
+ EXPECT_EQ(byte{0x00}, bb.data()[6]);
+ EXPECT_EQ(byte{0x00}, bb.data()[7]);
+ EXPECT_EQ(byte{0x97}, bb.data()[8]);
+ EXPECT_EQ(byte{0x2A}, bb.data()[9]);
+ EXPECT_EQ(byte{0x5F}, bb.data()[10]);
+ EXPECT_EQ(byte{0x58}, bb.data()[11]);
+ EXPECT_EQ(byte{0x17}, bb.data()[12]);
+ EXPECT_EQ(byte{0xFE}, bb.data()[13]);
+ EXPECT_EQ(byte{0xFF}, bb.data()[14]);
+ EXPECT_EQ(byte{0xFF}, bb.data()[15]);
+
+ EXPECT_EQ(Status::OK, bb.status());
+}
+
+TEST(ByteBuffer, Putting64ByteInts_Exhausted_kBigEndian) {
+ ByteBuffer<20> bb;
+ bb.PutUint64(0x000001E8A7A0D569, ByteOrder::kBigEndian);
+ bb.PutInt64(0xFFFFFE17585F2A97, ByteOrder::kBigEndian);
+
+ EXPECT_EQ(byte{0x00}, bb.data()[0]);
+ EXPECT_EQ(byte{0x00}, bb.data()[1]);
+ EXPECT_EQ(byte{0x01}, bb.data()[2]);
+ EXPECT_EQ(byte{0xE8}, bb.data()[3]);
+ EXPECT_EQ(byte{0xA7}, bb.data()[4]);
+ EXPECT_EQ(byte{0xA0}, bb.data()[5]);
+ EXPECT_EQ(byte{0xD5}, bb.data()[6]);
+ EXPECT_EQ(byte{0x69}, bb.data()[7]);
+ EXPECT_EQ(byte{0xFF}, bb.data()[8]);
+ EXPECT_EQ(byte{0xFF}, bb.data()[9]);
+ EXPECT_EQ(byte{0xFE}, bb.data()[10]);
+ EXPECT_EQ(byte{0x17}, bb.data()[11]);
+ EXPECT_EQ(byte{0x58}, bb.data()[12]);
+ EXPECT_EQ(byte{0x5F}, bb.data()[13]);
+ EXPECT_EQ(byte{0x2A}, bb.data()[14]);
+ EXPECT_EQ(byte{0x97}, bb.data()[15]);
+
+ bb.PutInt64(-6099875637501324530, ByteOrder::kBigEndian);
+ EXPECT_EQ(16u, bb.size());
+ EXPECT_EQ(Status::RESOURCE_EXHAUSTED, bb.status());
+}
+
+TEST(ByteBuffer, PuttingInts_MixedTypes_MixedEndian) {
+ ByteBuffer<16> bb;
+ bb.PutUint8(0x03);
+ bb.PutInt16(0xFD6D, ByteOrder::kBigEndian);
+ bb.PutUint32(0x482B3D9E);
+ bb.PutInt64(0x9A1C3641843DF317, ByteOrder::kBigEndian);
+ bb.PutInt8(0xFB);
+
+ EXPECT_EQ(byte{0x03}, bb.data()[0]);
+ EXPECT_EQ(byte{0xFD}, bb.data()[1]);
+ EXPECT_EQ(byte{0x6D}, bb.data()[2]);
+ EXPECT_EQ(byte{0x9E}, bb.data()[3]);
+ EXPECT_EQ(byte{0x3D}, bb.data()[4]);
+ EXPECT_EQ(byte{0x2B}, bb.data()[5]);
+ EXPECT_EQ(byte{0x48}, bb.data()[6]);
+ EXPECT_EQ(byte{0x9A}, bb.data()[7]);
+ EXPECT_EQ(byte{0x1C}, bb.data()[8]);
+ EXPECT_EQ(byte{0x36}, bb.data()[9]);
+ EXPECT_EQ(byte{0x41}, bb.data()[10]);
+ EXPECT_EQ(byte{0x84}, bb.data()[11]);
+ EXPECT_EQ(byte{0x3D}, bb.data()[12]);
+ EXPECT_EQ(byte{0xF3}, bb.data()[13]);
+ EXPECT_EQ(byte{0x17}, bb.data()[14]);
+ EXPECT_EQ(byte{0xFB}, bb.data()[15]);
+
+ EXPECT_EQ(Status::OK, bb.status());
+}
+
} // namespace
} // namespace pw
diff --git a/pw_bytes/docs.rst b/pw_bytes/docs.rst
index 83e9f1b..d67a8df 100644
--- a/pw_bytes/docs.rst
+++ b/pw_bytes/docs.rst
@@ -27,6 +27,13 @@
ByteBuilder is a utility class which facilitates the creation and
building of formatted bytes in a fixed-size buffer.
+Utilities for building byte arrays at run time
+------------------------------------------------
+-``PutInt8``, ``PutUInt8``: Inserts 8-bit integers.
+-``PutInt16``, ``PutInt16``: Inserts 16-bit integers in little/big endian.
+-``PutInt32``, ``PutUInt32``: Inserts 32-bit integers in little/big endian.
+-``PutInt64``, ``PutInt64``: Inserts 64-bit integers in little/big endian.
+
Future work
^^^^^^^^^^^
-* Adding Endianness
+- Utilities for building byte arrays at compile time.
diff --git a/pw_bytes/public/pw_bytes/byte_builder.h b/pw_bytes/public/pw_bytes/byte_builder.h
index 923f3db..eade658 100644
--- a/pw_bytes/public/pw_bytes/byte_builder.h
+++ b/pw_bytes/public/pw_bytes/byte_builder.h
@@ -25,6 +25,14 @@
namespace pw {
+// ByteOrder enum class enables users of ByteBuffer to specify the
+// desired Endianness for ordering the values to be inserted.
+enum class ByteOrder { kLittleEndian, kBigEndian };
+
+inline constexpr ByteOrder kSystemEndianness =
+ (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ? ByteOrder::kLittleEndian
+ : ByteOrder::kBigEndian);
+
// ByteBuilder facilitates building bytes in a fixed-size buffer.
// BytesBuilders never overflow. Status is tracked for each operation and
// an overall status is maintained, which reflects the most recent error.
@@ -32,7 +40,6 @@
// A ByteBuilder does not own the buffer it writes to. It can be used to write
// bytes to any buffer. The ByteBuffer template class, defined below,
// allocates a buffer alongside a ByteBuilder.
-
class ByteBuilder {
public:
// Creates an empty ByteBuilder.
@@ -63,31 +70,28 @@
return StatusWithSize(status_, size_);
}
- // The status from the last operation. May be OK while status() is not OK.
- Status last_status() const { return last_status_; }
-
// True if status() is Status::OK.
bool ok() const { return status_.ok(); }
// True if the bytes builder is empty.
bool empty() const { return size() == 0u; }
- // Returns the current length of the bytes, excluding the null terminator.
+ // Returns the current length of the bytes.
size_t size() const { return size_; }
- // Returns the maximum length of the bytes, excluding the null terminator.
+ // Returns the maximum length of the bytes.
size_t max_size() const { return buffer_.size(); }
// Clears the bytes and resets its error state.
- void clear();
+ void clear() {
+ size_ = 0;
+ status_ = Status::OK;
+ };
// Sets the statuses to Status::OK;
- void clear_status() {
- status_ = Status::OK;
- last_status_ = Status::OK;
- }
+ void clear_status() { status_ = Status::OK; }
- // Appends a single byte. Stets the status to RESOURCE_EXHAUSTED if the
+ // Appends a single byte. Sets the status to RESOURCE_EXHAUSTED if the
// byte cannot be added because the buffer is full.
void push_back(std::byte b) { append(1, b); }
@@ -101,8 +105,8 @@
ByteBuilder& append(size_t count, std::byte b);
// Appends count bytes from 'bytes' to the end of the ByteBuilder. If count
- // exceeds the remaining space in the ByteBuffer, max_size() - size()
- // bytes are appended and the status is set to RESOURCE_EXHAUSTED.
+ // exceeds the remaining space in the ByteBuffer, no bytes will be appended
+ // and the status is set to RESOURCE_EXHAUSTED.
ByteBuilder& append(const void* bytes, size_t count);
// Appends bytes from a byte span that calls the pointer/length version.
@@ -114,26 +118,84 @@
// new_size > size(), it sets status to OUT_OF_RANGE and does nothing.
void resize(size_t new_size);
+ // Put methods for inserting different 8-bit ints
+ ByteBuilder& PutUint8(uint8_t val) { return WriteInOrder(val); }
+
+ ByteBuilder& PutInt8(int8_t val) { return WriteInOrder(val); }
+
+ // Put methods for inserting different 16-bit ints
+ ByteBuilder& PutUint16(uint16_t value,
+ ByteOrder order = ByteOrder::kLittleEndian) {
+ if (kSystemEndianness != order) {
+ value = ((value & 0x00FF) << 8) | ((value & 0xFF00) >> 8);
+ }
+ return WriteInOrder(value);
+ }
+
+ ByteBuilder& PutInt16(int16_t value,
+ ByteOrder order = ByteOrder::kLittleEndian) {
+ return PutUint16(static_cast<uint16_t>(value), order);
+ }
+
+ // Put methods for inserting different 32-bit ints
+ ByteBuilder& PutUint32(uint32_t value,
+ ByteOrder order = ByteOrder::kLittleEndian) {
+ if (kSystemEndianness != order) {
+ value = ((value & 0x000000FF) << 3 * 8) | //
+ ((value & 0x0000FF00) << 1 * 8) | //
+ ((value & 0x00FF0000) >> 1 * 8) | //
+ ((value & 0xFF000000) >> 3 * 8);
+ }
+ return WriteInOrder(value);
+ }
+
+ ByteBuilder& PutInt32(int32_t value,
+ ByteOrder order = ByteOrder::kLittleEndian) {
+ return PutUint32(static_cast<uint32_t>(value), order);
+ }
+
+ // Put methods for inserting different 64-bit ints
+ ByteBuilder& PutUint64(uint64_t value,
+ ByteOrder order = ByteOrder::kLittleEndian) {
+ if (kSystemEndianness != order) {
+ value = ((value & 0x00000000000000FF) << 7 * 8) | //
+ ((value & 0x000000000000FF00) << 5 * 8) | //
+ ((value & 0x0000000000FF0000) << 3 * 8) | //
+ ((value & 0x00000000FF000000) << 1 * 8) | //
+ ((value & 0x000000FF00000000) >> 1 * 8) | //
+ ((value & 0x0000FF0000000000) >> 3 * 8) | //
+ ((value & 0x00FF000000000000) >> 5 * 8) | //
+ ((value & 0xFF00000000000000) >> 7 * 8);
+ }
+ return WriteInOrder(value);
+ }
+
+ ByteBuilder& PutInt64(int64_t value,
+ ByteOrder order = ByteOrder::kLittleEndian) {
+ return PutUint64(static_cast<uint64_t>(value), order);
+ }
+
protected:
// Functions to support ByteBuffer copies.
constexpr ByteBuilder(const span<std::byte>& buffer, const ByteBuilder& other)
- : buffer_(buffer),
- size_(other.size_),
- status_(other.status_),
- last_status_(other.last_status_) {}
+ : buffer_(buffer), size_(other.size_), status_(other.status_) {}
- void CopySizeAndStatus(const ByteBuilder& other);
+ void CopySizeAndStatus(const ByteBuilder& other) {
+ size_ = other.size_;
+ status_ = other.status_;
+ };
private:
+ template <typename T>
+ ByteBuilder& WriteInOrder(T value) {
+ return append(&value, sizeof(value));
+ }
size_t ResizeForAppend(size_t bytes_to_append);
- void SetErrorStatus(Status status);
-
const span<std::byte> buffer_;
size_t size_;
Status status_;
- Status last_status_;
};
// ByteBuffers declare a buffer along with a ByteBuilder.