diff options
author | Cronet Mainline Eng <cronet-mainline-eng+copybara@google.com> | 2024-06-01 00:34:53 +0900 |
---|---|---|
committer | Motomu Utsumi <motomuman@google.com> | 2024-06-01 01:09:19 +0900 |
commit | b66ce594f84a102bf71c3e2754d9c0bfdd620b85 (patch) | |
tree | f9fe122e9fb8b203a1cfc6955deb5e84ad4f341a /base/big_endian.h | |
parent | 168f7e285114554eb2ac9bc22343cca461355b50 (diff) | |
download | cronet-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.h | 137 |
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 |