Fix emulator build error
[platform/framework/web/chromium-efl.git] / base / big_endian.h
1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_BIG_ENDIAN_H_
6 #define BASE_BIG_ENDIAN_H_
7
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <string.h>
11 #include <type_traits>
12
13 #include "base/base_export.h"
14 #include "base/containers/span.h"
15 #include "base/memory/raw_ptr.h"
16 #include "base/strings/string_piece.h"
17 #include "base/sys_byteorder.h"
18 #include "build/build_config.h"
19
20 namespace base {
21
22 namespace internal {
23
24 // ByteSwapIfLittleEndian performs ByteSwap if this platform is little-endian,
25 // otherwise it is a no-op.
26
27 #if defined(ARCH_CPU_LITTLE_ENDIAN)
28
29 template <typename T>
30 inline auto ByteSwapIfLittleEndian(T val) -> decltype(ByteSwap(val)) {
31   return ByteSwap(val);
32 }
33
34 #else
35
36 // The use of decltype ensures this is only enabled for types for which
37 // ByteSwap() is defined, so the same set of overloads will work on both
38 // little-endian and big-endian platforms.
39
40 template <typename T>
41 inline auto ByteSwapIfLittleEndian(T val) -> decltype(ByteSwap(val)) {
42   return val;
43 }
44
45 #endif
46
47 // We never need to byte-swap a single-byte value, but it's convenient to have
48 // this overload to avoid a special case.
49 inline uint8_t ByteSwapIfLittleEndian(uint8_t val) {
50   return val;
51 }
52
53 }  // namespace internal
54
55 // Read an integer (signed or unsigned) from |buf| in Big Endian order.
56 // Note: this loop is unrolled with -O1 and above.
57 // NOTE(szym): glibc dns-canon.c use ntohs(*(uint16_t*)ptr) which is
58 // potentially unaligned.
59 // This would cause SIGBUS on ARMv5 or earlier and ARMv6-M.
60 template <typename T>
61 inline void ReadBigEndian(const uint8_t buf[], T* out) {
62   static_assert(std::is_integral_v<T>, "T has to be an integral type.");
63   // Make an unsigned version of the output type to make shift possible
64   // without UB.
65   typename std::make_unsigned<T>::type raw;
66   memcpy(&raw, buf, sizeof(T));
67   *out = static_cast<T>(internal::ByteSwapIfLittleEndian(raw));
68 }
69
70 // Write an integer (signed or unsigned) |val| to |buf| in Big Endian order.
71 // Note: this loop is unrolled with -O1 and above.
72 template<typename T>
73 inline void WriteBigEndian(char buf[], T val) {
74   static_assert(std::is_integral_v<T>, "T has to be an integral type.");
75   const auto unsigned_val =
76       static_cast<typename std::make_unsigned<T>::type>(val);
77   const auto raw = internal::ByteSwapIfLittleEndian(unsigned_val);
78   memcpy(buf, &raw, sizeof(T));
79 }
80
81 // Allows reading integers in network order (big endian) while iterating over
82 // an underlying buffer. All the reading functions advance the internal pointer.
83 class BASE_EXPORT BigEndianReader {
84  public:
85   static BigEndianReader FromStringPiece(base::StringPiece string_piece);
86
87   BigEndianReader(const uint8_t* buf, size_t len);
88   explicit BigEndianReader(base::span<const uint8_t> buf);
89
90   const uint8_t* ptr() const { return ptr_; }
91   size_t remaining() const { return static_cast<size_t>(end_ - ptr_); }
92
93   bool Skip(size_t len);
94   bool ReadBytes(void* out, size_t len);
95   // Creates a StringPiece in |out| that points to the underlying buffer.
96   bool ReadPiece(base::StringPiece* out, size_t len);
97   bool ReadSpan(base::span<const uint8_t>* out, size_t len);
98
99   bool ReadU8(uint8_t* value);
100   bool ReadU16(uint16_t* value);
101   bool ReadU32(uint32_t* value);
102   bool ReadU64(uint64_t* value);
103
104   // Reads a length-prefixed region:
105   // 1. reads a big-endian length L from the buffer;
106   // 2. sets |*out| to a StringPiece over the next L many bytes
107   // of the buffer (beyond the end of the bytes encoding the length); and
108   // 3. skips the main reader past this L-byte substring.
109   //
110   // Fails if reading a U8 or U16 fails, or if the parsed length is greater
111   // than the number of bytes remaining in the stream.
112   //
113   // On failure, leaves the stream at the same position
114   // as before the call.
115   bool ReadU8LengthPrefixed(base::StringPiece* out);
116   bool ReadU16LengthPrefixed(base::StringPiece* out);
117
118  private:
119   // Hidden to promote type safety.
120   template<typename T>
121   bool Read(T* v);
122   template <typename T>
123   bool ReadLengthPrefixed(base::StringPiece* out);
124
125   const uint8_t* ptr_;
126   const uint8_t* end_;
127 };
128
129 // Allows writing integers in network order (big endian) while iterating over
130 // an underlying buffer. All the writing functions advance the internal pointer.
131 class BASE_EXPORT BigEndianWriter {
132  public:
133   BigEndianWriter(char* buf, size_t len);
134
135   char* ptr() const { return ptr_; }
136   size_t remaining() const { return static_cast<size_t>(end_ - ptr_); }
137
138   bool Skip(size_t len);
139   bool WriteBytes(const void* buf, size_t len);
140   bool WriteU8(uint8_t value);
141   bool WriteU16(uint16_t value);
142   bool WriteU32(uint32_t value);
143   bool WriteU64(uint64_t value);
144
145  private:
146   // Hidden to promote type safety.
147   template<typename T>
148   bool Write(T v);
149
150   raw_ptr<char, DanglingUntriaged | AllowPtrArithmetic> ptr_;
151   raw_ptr<char, DanglingUntriaged | AllowPtrArithmetic> end_;
152 };
153
154 }  // namespace base
155
156 #endif  // BASE_BIG_ENDIAN_H_