1//
2// Copyright (C) 2011 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "shill/net/byte_string.h"
18
19#include <netinet/in.h>
20#include <string.h>
21
22#include <algorithm>
23
24#include <base/strings/string_number_conversions.h>
25
26using std::min;
27using std::string;
28using std::vector;
29
30namespace shill {
31
32ByteString::ByteString(const ByteString& b) {
33  data_ = b.data_;
34}
35
36ByteString& ByteString::operator=(const ByteString& b) {
37  data_ = b.data_;
38  return *this;
39}
40
41unsigned char* ByteString::GetData() {
42  return (GetLength() == 0) ? nullptr : &data_.front();
43}
44
45const unsigned char* ByteString::GetConstData() const {
46  return (GetLength() == 0) ? nullptr : &data_.front();
47}
48
49size_t ByteString::GetLength() const {
50  return data_.size();
51}
52
53ByteString ByteString::GetSubstring(size_t offset, size_t length) const {
54  if (offset > GetLength()) {
55    offset = GetLength();
56  }
57  if (length > GetLength() - offset) {
58    length = GetLength() - offset;
59  }
60  return ByteString(GetConstData() + offset, length);
61}
62
63// static
64ByteString ByteString::CreateFromCPUUInt32(uint32_t val) {
65  return ByteString(reinterpret_cast<unsigned char*>(&val), sizeof(val));
66}
67
68// static
69ByteString ByteString::CreateFromNetUInt32(uint32_t val) {
70  return CreateFromCPUUInt32(ntohl(val));
71}
72
73// static
74ByteString ByteString::CreateFromHexString(const string& hex_string) {
75  vector<uint8_t> bytes;
76  if (!base::HexStringToBytes(hex_string, &bytes)) {
77    return ByteString();
78  }
79  return ByteString(&bytes.front(), bytes.size());
80}
81
82bool ByteString::ConvertToCPUUInt32(uint32_t* val) const {
83  if (val == nullptr || GetLength() != sizeof(*val)) {
84    return false;
85  }
86  memcpy(val, GetConstData(), sizeof(*val));
87
88  return true;
89}
90
91bool ByteString::ConvertToNetUInt32(uint32_t* val) const {
92  if (!ConvertToCPUUInt32(val)) {
93    return false;
94  }
95  *val = ntohl(*val);
96  return true;
97}
98
99template <typename T>
100bool ByteString::ConvertByteOrderAsUIntArray(T (*converter)(T)) {
101  size_t length = GetLength();
102  if ((length % sizeof(T)) != 0) {
103    return false;
104  }
105  for (auto i = data_.begin(); i != data_.end(); i += sizeof(T)) {
106    // Take care of word alignment.
107    T val;
108    memcpy(&val, &(*i), sizeof(T));
109    val = converter(val);
110    memcpy(&(*i), &val, sizeof(T));
111  }
112  return true;
113}
114
115bool ByteString::ConvertFromNetToCPUUInt32Array() {
116  return ConvertByteOrderAsUIntArray(ntohl);
117}
118
119bool ByteString::ConvertFromCPUToNetUInt32Array() {
120  return ConvertByteOrderAsUIntArray(htonl);
121}
122
123bool ByteString::IsZero() const {
124  for (const auto& i : data_) {
125    if (i != 0) {
126      return false;
127    }
128  }
129  return true;
130}
131
132bool ByteString::BitwiseAnd(const ByteString& b) {
133  if (GetLength() != b.GetLength()) {
134    return false;
135  }
136  auto lhs = data_.begin();
137  for (const auto& rhs : b.data_) {
138    *lhs++ &= rhs;
139  }
140  return true;
141}
142
143bool ByteString::BitwiseOr(const ByteString& b) {
144  if (GetLength() != b.GetLength()) {
145    return false;
146  }
147  auto lhs = data_.begin();
148  for (const auto& rhs : b.data_) {
149    *lhs++ |= rhs;
150  }
151  return true;
152}
153
154void ByteString::BitwiseInvert() {
155  for (auto& i : data_) {
156    i = ~i;
157  }
158}
159
160bool ByteString::Equals(const ByteString& b) const {
161  if (GetLength() != b.GetLength()) {
162    return false;
163  }
164  auto lhs = data_.begin();
165  for (const auto& rhs : b.data_) {
166    if (*lhs++ != rhs) {
167      return false;
168    }
169  }
170  return true;
171}
172
173void ByteString::Append(const ByteString& b) {
174  data_.insert(data_.end(), b.data_.begin(), b.data_.end());
175}
176
177void ByteString::Clear() {
178  data_.clear();
179}
180
181void ByteString::Resize(int size) {
182  data_.resize(size, 0);
183}
184
185string ByteString::HexEncode() const {
186  return base::HexEncode(GetConstData(), GetLength());
187}
188
189bool ByteString::CopyData(size_t size, void* output) const {
190  if (output == nullptr || GetLength() < size) {
191    return false;
192  }
193  memcpy(output, GetConstData(), size);
194  return true;
195}
196
197// static
198bool ByteString::IsLessThan(const ByteString& lhs, const ByteString& rhs) {
199  size_t byte_count = min(lhs.GetLength(), rhs.GetLength());
200  int result = memcmp(lhs.GetConstData(), rhs.GetConstData(), byte_count);
201  if (result == 0) {
202    return lhs.GetLength() < rhs.GetLength();
203  }
204  return result < 0;
205}
206
207}  // namespace shill
208