|  | // Copyright 2014 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef BASE_BIG_ENDIAN_H_ | 
|  | #define BASE_BIG_ENDIAN_H_ | 
|  |  | 
|  | #include <stddef.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include "base/base_export.h" | 
|  | #include "base/strings/string_piece.h" | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | // Read an integer (signed or unsigned) from |buf| in Big Endian order. | 
|  | // Note: this loop is unrolled with -O1 and above. | 
|  | // 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. | 
|  | template<typename T> | 
|  | inline void ReadBigEndian(const char buf[], T* out) { | 
|  | *out = buf[0]; | 
|  | for (size_t i = 1; i < sizeof(T); ++i) { | 
|  | *out <<= 8; | 
|  | // Must cast to uint8_t to avoid clobbering by sign extension. | 
|  | *out |= static_cast<uint8_t>(buf[i]); | 
|  | } | 
|  | } | 
|  |  | 
|  | // 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) { | 
|  | for (size_t i = 0; i < sizeof(T); ++i) { | 
|  | buf[sizeof(T)-i-1] = static_cast<char>(val & 0xFF); | 
|  | val >>= 8; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Specializations to make clang happy about the (dead code) shifts above. | 
|  | template <> | 
|  | inline void ReadBigEndian<uint8_t>(const char buf[], uint8_t* out) { | 
|  | *out = buf[0]; | 
|  | } | 
|  |  | 
|  | template <> | 
|  | inline void WriteBigEndian<uint8_t>(char buf[], uint8_t val) { | 
|  | buf[0] = static_cast<char>(val); | 
|  | } | 
|  |  | 
|  | // Allows reading integers in network order (big endian) while iterating over | 
|  | // an underlying buffer. All the reading functions advance the internal pointer. | 
|  | class BASE_EXPORT BigEndianReader { | 
|  | public: | 
|  | BigEndianReader(const char* buf, size_t len); | 
|  |  | 
|  | const char* ptr() const { return ptr_; } | 
|  | int remaining() const { return end_ - ptr_; } | 
|  |  | 
|  | 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 ReadU8(uint8_t* value); | 
|  | bool ReadU16(uint16_t* value); | 
|  | bool ReadU32(uint32_t* value); | 
|  | bool ReadU64(uint64_t* value); | 
|  |  | 
|  | private: | 
|  | // Hidden to promote type safety. | 
|  | template<typename T> | 
|  | bool Read(T* v); | 
|  |  | 
|  | const char* ptr_; | 
|  | const char* end_; | 
|  | }; | 
|  |  | 
|  | // 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); | 
|  |  | 
|  | char* ptr() const { return ptr_; } | 
|  | int remaining() const { return end_ - ptr_; } | 
|  |  | 
|  | bool Skip(size_t len); | 
|  | 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); | 
|  |  | 
|  | char* ptr_; | 
|  | char* end_; | 
|  | }; | 
|  |  | 
|  | }  // namespace base | 
|  |  | 
|  | #endif  // BASE_BIG_ENDIAN_H_ |