big_endian.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_BIG_ENDIAN_H_
  5. #define BASE_BIG_ENDIAN_H_
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include <type_traits>
  9. #include "base/base_export.h"
  10. #include "base/strings/string_piece.h"
  11. namespace base {
  12. // Read an integer (signed or unsigned) from |buf| in Big Endian order.
  13. // Note: this loop is unrolled with -O1 and above.
  14. // NOTE(szym): glibc dns-canon.c use ntohs(*(uint16_t*)ptr) which is
  15. // potentially unaligned.
  16. // This would cause SIGBUS on ARMv5 or earlier and ARMv6-M.
  17. template<typename T>
  18. inline void ReadBigEndian(const char buf[], T* out) {
  19. static_assert(std::is_integral<T>::value, "T has to be an integral type.");
  20. *out = buf[0];
  21. for (size_t i = 1; i < sizeof(T); ++i) {
  22. *out <<= 8;
  23. // Must cast to uint8_t to avoid clobbering by sign extension.
  24. *out |= static_cast<uint8_t>(buf[i]);
  25. }
  26. }
  27. // Write an integer (signed or unsigned) |val| to |buf| in Big Endian order.
  28. // Note: this loop is unrolled with -O1 and above.
  29. template<typename T>
  30. inline void WriteBigEndian(char buf[], T val) {
  31. static_assert(std::is_integral<T>::value, "T has to be an integral type.");
  32. for (size_t i = 0; i < sizeof(T); ++i) {
  33. buf[sizeof(T)-i-1] = static_cast<char>(val & 0xFF);
  34. val >>= 8;
  35. }
  36. }
  37. // Specializations to make clang happy about the (dead code) shifts above.
  38. template <>
  39. inline void ReadBigEndian<uint8_t>(const char buf[], uint8_t* out) {
  40. *out = buf[0];
  41. }
  42. template <>
  43. inline void WriteBigEndian<uint8_t>(char buf[], uint8_t val) {
  44. buf[0] = static_cast<char>(val);
  45. }
  46. // Allows reading integers in network order (big endian) while iterating over
  47. // an underlying buffer. All the reading functions advance the internal pointer.
  48. class BASE_EXPORT BigEndianReader {
  49. public:
  50. BigEndianReader(const char* buf, size_t len);
  51. const char* ptr() const { return ptr_; }
  52. size_t remaining() const { return end_ - ptr_; }
  53. bool Skip(size_t len);
  54. bool ReadBytes(void* out, size_t len);
  55. // Creates a StringPiece in |out| that points to the underlying buffer.
  56. bool ReadPiece(base::StringPiece* out, size_t len);
  57. bool ReadU8(uint8_t* value);
  58. bool ReadU16(uint16_t* value);
  59. bool ReadU32(uint32_t* value);
  60. bool ReadU64(uint64_t* value);
  61. // Reads a length-prefixed region:
  62. // 1. reads a big-endian length L from the buffer;
  63. // 2. sets |*out| to a StringPiece over the next L many bytes
  64. // of the buffer (beyond the end of the bytes encoding the length); and
  65. // 3. skips the main reader past this L-byte substring.
  66. //
  67. // Fails if reading a U8 or U16 fails, or if the parsed length is greater
  68. // than the number of bytes remaining in the stream.
  69. //
  70. // On failure, leaves the stream at the same position
  71. // as before the call.
  72. bool ReadU8LengthPrefixed(base::StringPiece* out);
  73. bool ReadU16LengthPrefixed(base::StringPiece* out);
  74. private:
  75. // Hidden to promote type safety.
  76. template<typename T>
  77. bool Read(T* v);
  78. template <typename T>
  79. bool ReadLengthPrefixed(base::StringPiece* out);
  80. const char* ptr_;
  81. const char* end_;
  82. };
  83. // Allows writing integers in network order (big endian) while iterating over
  84. // an underlying buffer. All the writing functions advance the internal pointer.
  85. class BASE_EXPORT BigEndianWriter {
  86. public:
  87. BigEndianWriter(char* buf, size_t len);
  88. char* ptr() const { return ptr_; }
  89. size_t remaining() const { return end_ - ptr_; }
  90. bool Skip(size_t len);
  91. bool WriteBytes(const void* buf, size_t len);
  92. bool WriteU8(uint8_t value);
  93. bool WriteU16(uint16_t value);
  94. bool WriteU32(uint32_t value);
  95. bool WriteU64(uint64_t value);
  96. private:
  97. // Hidden to promote type safety.
  98. template<typename T>
  99. bool Write(T v);
  100. char* ptr_;
  101. char* end_;
  102. };
  103. } // namespace base
  104. #endif // BASE_BIG_ENDIAN_H_