summaryrefslogtreecommitdiff
path: root/base/big_endian.h
diff options
context:
space:
mode:
authorCronet Mainline Eng <cronet-mainline-eng+copybara@google.com>2024-06-01 00:34:53 +0900
committerMotomu Utsumi <motomuman@google.com>2024-06-01 01:09:19 +0900
commitb66ce594f84a102bf71c3e2754d9c0bfdd620b85 (patch)
treef9fe122e9fb8b203a1cfc6955deb5e84ad4f341a /base/big_endian.h
parent168f7e285114554eb2ac9bc22343cca461355b50 (diff)
downloadcronet-b66ce594f84a102bf71c3e2754d9c0bfdd620b85.tar.gz
Import Cronet version 123.0.6312.40
FolderOrigin-RevId: /tmp/copybara-origin/src Change-Id: Ie1ecf4a8ee6c6263302f0e88e86baa49a8052442
Diffstat (limited to 'base/big_endian.h')
-rw-r--r--base/big_endian.h137
1 files changed, 95 insertions, 42 deletions
diff --git a/base/big_endian.h b/base/big_endian.h
index 37e794738..4a89ca44d 100644
--- a/base/big_endian.h
+++ b/base/big_endian.h
@@ -8,11 +8,13 @@
#include <stddef.h>
#include <stdint.h>
#include <string.h>
+#include <optional>
#include <type_traits>
#include "base/base_export.h"
+#include "base/compiler_specific.h"
#include "base/containers/span.h"
-#include "base/memory/raw_ptr.h"
+#include "base/memory/raw_span.h"
#include "base/strings/string_piece.h"
#include "base/sys_byteorder.h"
#include "build/build_config.h"
@@ -57,25 +59,44 @@ inline uint8_t ByteSwapIfLittleEndian(uint8_t val) {
// NOTE(szym): glibc dns-canon.c use ntohs(*(uint16_t*)ptr) which is
// potentially unaligned.
// This would cause SIGBUS on ARMv5 or earlier and ARMv6-M.
+//
+// DEPRECATED: Use base::numerics::*FromBigEndian to convert big-endian byte
+// encoding to primitives.
template <typename T>
-inline void ReadBigEndian(const uint8_t buf[], T* out) {
+inline void ReadBigEndian(span<const uint8_t, sizeof(T)> buffer, T* out) {
static_assert(std::is_integral_v<T>, "T has to be an integral type.");
// Make an unsigned version of the output type to make shift possible
// without UB.
- typename std::make_unsigned<T>::type raw;
- memcpy(&raw, buf, sizeof(T));
+ std::make_unsigned_t<T> raw;
+ byte_span_from_ref(raw).copy_from(buffer);
*out = static_cast<T>(internal::ByteSwapIfLittleEndian(raw));
}
-// Write an integer (signed or unsigned) |val| to |buf| in Big Endian order.
-// Note: this loop is unrolled with -O1 and above.
-template<typename T>
-inline void WriteBigEndian(char buf[], T val) {
- static_assert(std::is_integral_v<T>, "T has to be an integral type.");
- const auto unsigned_val =
- static_cast<typename std::make_unsigned<T>::type>(val);
+// TODO(crbug.com/40284755): Remove this function when there are no callers.
+template <typename T>
+inline void ReadBigEndian(const uint8_t buf[], T* out) {
+ ReadBigEndian(span<const uint8_t, sizeof(T)>(buf, sizeof(T)), out);
+}
+
+// Write an integer (signed or unsigned) `val` to `buffer` in Big Endian order.
+// The `buffer` must be the same size (in bytes) as the integer `val`.
+//
+// DEPRECATED: Use base::numerics::*ToBigEndian to convert primitives to big-
+// endian byte encoding.
+template <typename T>
+ requires(std::is_integral_v<T>)
+inline void WriteBigEndian(span<uint8_t, sizeof(T)> buffer, T val) {
+ const auto unsigned_val = static_cast<std::make_unsigned_t<T>>(val);
const auto raw = internal::ByteSwapIfLittleEndian(unsigned_val);
- memcpy(buf, &raw, sizeof(T));
+ buffer.copy_from(byte_span_from_ref(raw));
+}
+
+// TODO(crbug.com/40284755): Remove this function when there are no callers.
+template <typename T>
+ requires(std::is_integral_v<T>)
+inline void WriteBigEndian(char buf[], T val) {
+ return WriteBigEndian(
+ as_writable_bytes(span<char, sizeof(T)>(buf, sizeof(T))), val);
}
// Allows reading integers in network order (big endian) while iterating over
@@ -84,28 +105,43 @@ class BASE_EXPORT BigEndianReader {
public:
static BigEndianReader FromStringPiece(base::StringPiece string_piece);
- explicit BigEndianReader(base::span<const uint8_t> buf);
+ explicit BigEndianReader(base::span<const uint8_t> buffer);
+
+ // TODO(crbug.com/40284755): Remove this overload.
+ UNSAFE_BUFFER_USAGE BigEndianReader(const uint8_t* buf, size_t len);
- // TODO(crbug.com/1490484): Remove this overload.
- BigEndianReader(const uint8_t* buf, size_t len);
+ ~BigEndianReader();
// Returns a span over all unread bytes.
- span<const uint8_t> remaining_bytes() const {
- // SAFETY: The cast value is non-negative because `ptr_` is never moved past
- // `end_`.
- return make_span(ptr_, static_cast<size_t>(end_ - ptr_));
- }
+ span<const uint8_t> remaining_bytes() const { return buffer_; }
- // TODO(crbug.com/1490484): Remove this method.
- const uint8_t* ptr() const { return ptr_; }
- // TODO(crbug.com/1490484): Remove this method.
- size_t remaining() const { return static_cast<size_t>(end_ - ptr_); }
+ // TODO(crbug.com/40284755): Remove this method.
+ const uint8_t* ptr() const { return buffer_.data(); }
+ // TODO(crbug.com/40284755): Remove this method.
+ size_t remaining() const { return buffer_.size(); }
bool Skip(size_t len);
bool ReadBytes(void* out, size_t len);
// Creates a StringPiece in |out| that points to the underlying buffer.
bool ReadPiece(base::StringPiece* out, size_t len);
- bool ReadSpan(base::span<const uint8_t>* out, size_t len);
+
+ // Returns a span over `n` bytes from the buffer and moves the internal state
+ // past those bytes, or returns nullopt and if there are not `n` bytes
+ // remaining in the buffer.
+ std::optional<span<const uint8_t>> ReadSpan(base::StrictNumeric<size_t> n);
+
+ // Returns a span over `N` bytes from the buffer and moves the internal state
+ // past those bytes, or returns nullopt and if there are not `N` bytes
+ // remaining in the buffer.
+ template <size_t N>
+ std::optional<span<const uint8_t, N>> ReadFixedSpan() {
+ if (remaining() < N) {
+ return std::nullopt;
+ }
+ auto [consume, remain] = buffer_.split_at<N>();
+ buffer_ = remain;
+ return {consume};
+ }
bool ReadU8(uint8_t* value);
bool ReadU16(uint16_t* value);
@@ -127,39 +163,56 @@ class BASE_EXPORT BigEndianReader {
bool ReadU16LengthPrefixed(base::StringPiece* out);
private:
- // Hidden to promote type safety.
- template<typename T>
- bool Read(T* v);
- template <typename T>
- bool ReadLengthPrefixed(base::StringPiece* out);
-
- const uint8_t* ptr_;
- const uint8_t* end_;
+ // TODO(danakj): Switch to raw_span in its own CL.
+ span<const uint8_t> buffer_;
};
// Allows writing integers in network order (big endian) while iterating over
// an underlying buffer. All the writing functions advance the internal pointer.
class BASE_EXPORT BigEndianWriter {
public:
- BigEndianWriter(char* buf, size_t len);
+ // Constructs a BigEndianWriter that will write into the given buffer.
+ BigEndianWriter(span<uint8_t> buffer);
+
+ // TODO(crbug.com/40284755): Remove this overload.
+ UNSAFE_BUFFER_USAGE BigEndianWriter(char* buf, size_t len);
- char* ptr() const { return ptr_; }
- size_t remaining() const { return static_cast<size_t>(end_ - ptr_); }
+ ~BigEndianWriter();
+
+ char* ptr() const { return reinterpret_cast<char*>(buffer_.data()); }
+ size_t remaining() const { return buffer_.size(); }
+
+ // Returns a span over all unwritten bytes.
+ span<uint8_t> remaining_bytes() const { return buffer_; }
bool Skip(size_t len);
+ // TODO(crbug.com/40284755): WriteBytes() calls should be replaced with
+ // WriteSpan().
bool WriteBytes(const void* buf, size_t len);
bool WriteU8(uint8_t value);
bool WriteU16(uint16_t value);
bool WriteU32(uint32_t value);
bool WriteU64(uint64_t value);
- private:
- // Hidden to promote type safety.
- template<typename T>
- bool Write(T v);
+ // Writes the span of bytes to the backing buffer. If there is not enough
+ // room, it writes nothing and returns false.
+ bool WriteSpan(base::span<const uint8_t> bytes);
+
+ // Writes `N` bytes to the backing buffer. If there is not enough room, it
+ // writes nothing and returns false.
+ template <size_t N>
+ bool WriteFixedSpan(base::span<const uint8_t, N> bytes) {
+ if (remaining() < N) {
+ return false;
+ }
+ auto [write, remain] = buffer_.split_at<N>();
+ write.copy_from(bytes);
+ buffer_ = remain;
+ return true;
+ }
- raw_ptr<char, DanglingUntriaged | AllowPtrArithmetic> ptr_;
- raw_ptr<char, DanglingUntriaged | AllowPtrArithmetic> end_;
+ private:
+ raw_span<uint8_t, DanglingUntriaged> buffer_;
};
} // namespace base