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 #include "base/big_endian.h"
6
7 #include <string.h>
8
9 #include "base/numerics/checked_math.h"
10 #include "base/strings/string_piece.h"
11
12 namespace base {
13
FromStringPiece(base::StringPiece string_piece)14 BigEndianReader BigEndianReader::FromStringPiece(
15 base::StringPiece string_piece) {
16 return BigEndianReader(base::as_bytes(base::make_span(string_piece)));
17 }
18
BigEndianReader(const uint8_t * buf,size_t len)19 BigEndianReader::BigEndianReader(const uint8_t* buf, size_t len)
20 : ptr_(buf), end_(ptr_ + len) {
21 // Ensure `len` does not cause `end_` to wrap around.
22 CHECK_GE(end_, ptr_);
23 }
24
BigEndianReader(base::span<const uint8_t> buf)25 BigEndianReader::BigEndianReader(base::span<const uint8_t> buf)
26 : ptr_(buf.data()), end_(buf.data() + buf.size()) {}
27
Skip(size_t len)28 bool BigEndianReader::Skip(size_t len) {
29 if (len > remaining())
30 return false;
31 ptr_ += len;
32 return true;
33 }
34
ReadBytes(void * out,size_t len)35 bool BigEndianReader::ReadBytes(void* out, size_t len) {
36 if (len > remaining())
37 return false;
38 memcpy(out, ptr_, len);
39 ptr_ += len;
40 return true;
41 }
42
ReadPiece(base::StringPiece * out,size_t len)43 bool BigEndianReader::ReadPiece(base::StringPiece* out, size_t len) {
44 if (len > remaining())
45 return false;
46 *out = base::StringPiece(reinterpret_cast<const char*>(ptr_), len);
47 ptr_ += len;
48 return true;
49 }
50
ReadSpan(base::span<const uint8_t> * out,size_t len)51 bool BigEndianReader::ReadSpan(base::span<const uint8_t>* out, size_t len) {
52 if (len > remaining())
53 return false;
54 *out = base::make_span(ptr_, len);
55 ptr_ += len;
56 return true;
57 }
58
59 template<typename T>
Read(T * value)60 bool BigEndianReader::Read(T* value) {
61 if (sizeof(T) > remaining())
62 return false;
63 ReadBigEndian<T>(ptr_, value);
64 ptr_ += sizeof(T);
65 return true;
66 }
67
ReadU8(uint8_t * value)68 bool BigEndianReader::ReadU8(uint8_t* value) {
69 return Read(value);
70 }
71
ReadU16(uint16_t * value)72 bool BigEndianReader::ReadU16(uint16_t* value) {
73 return Read(value);
74 }
75
ReadU32(uint32_t * value)76 bool BigEndianReader::ReadU32(uint32_t* value) {
77 return Read(value);
78 }
79
ReadU64(uint64_t * value)80 bool BigEndianReader::ReadU64(uint64_t* value) {
81 return Read(value);
82 }
83
84 template <typename T>
ReadLengthPrefixed(base::StringPiece * out)85 bool BigEndianReader::ReadLengthPrefixed(base::StringPiece* out) {
86 T t_len;
87 if (!Read(&t_len))
88 return false;
89 size_t len = strict_cast<size_t>(t_len);
90 const uint8_t* original_ptr = ptr_;
91 if (!Skip(len)) {
92 ptr_ -= sizeof(T);
93 return false;
94 }
95 *out = base::StringPiece(reinterpret_cast<const char*>(original_ptr), len);
96 return true;
97 }
98
ReadU8LengthPrefixed(base::StringPiece * out)99 bool BigEndianReader::ReadU8LengthPrefixed(base::StringPiece* out) {
100 return ReadLengthPrefixed<uint8_t>(out);
101 }
102
ReadU16LengthPrefixed(base::StringPiece * out)103 bool BigEndianReader::ReadU16LengthPrefixed(base::StringPiece* out) {
104 return ReadLengthPrefixed<uint16_t>(out);
105 }
106
BigEndianWriter(char * buf,size_t len)107 BigEndianWriter::BigEndianWriter(char* buf, size_t len)
108 : ptr_(buf), end_(ptr_ + len) {
109 // Ensure `len` does not cause `end_` to wrap around.
110 CHECK_GE(end_, ptr_);
111 }
112
Skip(size_t len)113 bool BigEndianWriter::Skip(size_t len) {
114 if (len > remaining())
115 return false;
116 ptr_ += len;
117 return true;
118 }
119
WriteBytes(const void * buf,size_t len)120 bool BigEndianWriter::WriteBytes(const void* buf, size_t len) {
121 if (len > remaining())
122 return false;
123 memcpy(ptr_, buf, len);
124 ptr_ += len;
125 return true;
126 }
127
128 template<typename T>
Write(T value)129 bool BigEndianWriter::Write(T value) {
130 if (sizeof(T) > remaining())
131 return false;
132 WriteBigEndian<T>(ptr_, value);
133 ptr_ += sizeof(T);
134 return true;
135 }
136
WriteU8(uint8_t value)137 bool BigEndianWriter::WriteU8(uint8_t value) {
138 return Write(value);
139 }
140
WriteU16(uint16_t value)141 bool BigEndianWriter::WriteU16(uint16_t value) {
142 return Write(value);
143 }
144
WriteU32(uint32_t value)145 bool BigEndianWriter::WriteU32(uint32_t value) {
146 return Write(value);
147 }
148
WriteU64(uint64_t value)149 bool BigEndianWriter::WriteU64(uint64_t value) {
150 return Write(value);
151 }
152
153 } // namespace base
154