blob: f521e90b11ab57b44aa5392de548eb2d6f98b739 [file] [log] [blame]
Paul Stewart3ecfa2b2011-07-15 10:47:42 -07001// Copyright (c) 2011 The Chromium OS 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
5#include "shill/byte_string.h"
6
7#include <netinet/in.h>
Wade Guthrieb9c3feb2013-04-25 16:31:19 -07008#include <string.h>
9
10#include <algorithm>
Paul Stewart3ecfa2b2011-07-15 10:47:42 -070011
Darin Petkove3e1cfa2011-08-11 13:41:17 -070012#include <base/string_number_conversions.h>
13
Wade Guthriec8f58922013-01-29 16:18:27 -080014using std::distance;
Wade Guthrieb9c3feb2013-04-25 16:31:19 -070015using std::min;
Darin Petkove3e1cfa2011-08-11 13:41:17 -070016using std::string;
Ben Chandc80b322013-04-08 13:46:13 -070017using std::vector;
Darin Petkove3e1cfa2011-08-11 13:41:17 -070018
Paul Stewart3ecfa2b2011-07-15 10:47:42 -070019namespace shill {
20
Wade Guthriec8f58922013-01-29 16:18:27 -080021ByteString::ByteString(const ByteString &b) {
22 data_.assign(Vector::const_iterator(b.begin_), b.data_.end());
23 begin_ = data_.begin();
24}
25
26ByteString &ByteString::operator=(const ByteString &b) {
27 data_.assign(Vector::const_iterator(b.begin_), b.data_.end());
28 begin_ = data_.begin();
29 return *this;
30}
31
32unsigned char *ByteString::GetData() {
33 return (GetLength() == 0) ? NULL : &*begin_;
34}
35
36const unsigned char *ByteString::GetConstData() const {
37 return (GetLength() == 0) ? NULL : &*begin_;
38}
39
40size_t ByteString::GetLength() const {
41 return distance(Vector::const_iterator(begin_), data_.end());
42}
43
Paul Stewart91a5aac2012-07-20 11:55:40 -070044ByteString ByteString::GetSubstring(size_t offset, size_t length) const {
45 if (offset > GetLength()) {
46 offset = GetLength();
47 }
48 if (length > GetLength() - offset) {
49 length = GetLength() - offset;
50 }
51 return ByteString(GetConstData() + offset, length);
52}
53
Paul Stewart3ecfa2b2011-07-15 10:47:42 -070054// static
55ByteString ByteString::CreateFromCPUUInt32(uint32 val) {
56 return ByteString(reinterpret_cast<unsigned char *>(&val), sizeof(val));
57}
58
59// static
60ByteString ByteString::CreateFromNetUInt32(uint32 val) {
Ben Chandc80b322013-04-08 13:46:13 -070061 return CreateFromCPUUInt32(ntohl(val));
62}
63
64// static
65ByteString ByteString::CreateFromHexString(const string &hex_string) {
66 vector<uint8> bytes;
67 if (!base::HexStringToBytes(hex_string, &bytes)) {
68 return ByteString();
69 }
70 return ByteString(&bytes.front(), bytes.size());
Paul Stewart3ecfa2b2011-07-15 10:47:42 -070071}
72
73bool ByteString::ConvertToCPUUInt32(uint32 *val) const {
Wade Guthriec8f58922013-01-29 16:18:27 -080074 if (val == NULL || GetLength() != sizeof(*val)) {
Paul Stewart3ecfa2b2011-07-15 10:47:42 -070075 return false;
76 }
77 memcpy(val, GetConstData(), sizeof(*val));
78
79 return true;
80}
81
82bool ByteString::ConvertToNetUInt32(uint32 *val) const {
83 if (!ConvertToCPUUInt32(val)) {
84 return false;
85 }
86 *val = ntohl(*val);
87 return true;
88}
89
Ben Chandc80b322013-04-08 13:46:13 -070090template <typename T>
91bool ByteString::ConvertByteOrderAsUIntArray(T (*converter)(T)) {
92 size_t length = GetLength();
93 if ((length % sizeof(T)) != 0) {
94 return false;
95 }
96 for (Vector::iterator i = begin_; i != data_.end(); i += sizeof(T)) {
97 // Take care of word alignment.
98 T val;
99 memcpy(&val, &(*i), sizeof(T));
100 val = converter(val);
101 memcpy(&(*i), &val, sizeof(T));
102 }
103 return true;
104}
105
106bool ByteString::ConvertFromNetToCPUUInt32Array() {
107 return ConvertByteOrderAsUIntArray(ntohl);
108}
109
110bool ByteString::ConvertFromCPUToNetUInt32Array() {
111 return ConvertByteOrderAsUIntArray(htonl);
112}
113
Paul Stewart3ecfa2b2011-07-15 10:47:42 -0700114bool ByteString::IsZero() const {
Wade Guthriec8f58922013-01-29 16:18:27 -0800115 for (Vector::const_iterator i = begin_; i != data_.end(); ++i) {
Paul Stewart3ecfa2b2011-07-15 10:47:42 -0700116 if (*i != 0) {
117 return false;
118 }
119 }
120 return true;
121}
122
Paul Stewartfe1c0e12012-04-30 19:57:04 -0700123bool ByteString::BitwiseAnd(const ByteString &b) {
Paul Stewartf7bf9bf2012-04-17 17:30:14 -0700124 if (GetLength() != b.GetLength()) {
125 return false;
126 }
Wade Guthriec8f58922013-01-29 16:18:27 -0800127 Vector::iterator lhs(begin_);
128 Vector::const_iterator rhs(b.begin_);
129 while (lhs != data_.end()) {
130 *lhs++ &= *rhs++;
Paul Stewartf7bf9bf2012-04-17 17:30:14 -0700131 }
132 return true;
133}
134
Paul Stewartfe1c0e12012-04-30 19:57:04 -0700135bool ByteString::BitwiseOr(const ByteString &b) {
136 if (GetLength() != b.GetLength()) {
137 return false;
138 }
Wade Guthriec8f58922013-01-29 16:18:27 -0800139 Vector::iterator lhs(begin_);
140 Vector::const_iterator rhs(b.begin_);
141 while (lhs != data_.end()) {
142 *lhs++ |= *rhs++;
Paul Stewartfe1c0e12012-04-30 19:57:04 -0700143 }
144 return true;
145}
146
147void ByteString::BitwiseInvert() {
Wade Guthriec8f58922013-01-29 16:18:27 -0800148 for (Vector::iterator i = begin_; i != data_.end(); ++i) {
149 *i = ~*i;
Paul Stewartfe1c0e12012-04-30 19:57:04 -0700150 }
151}
152
Paul Stewart3ecfa2b2011-07-15 10:47:42 -0700153bool ByteString::Equals(const ByteString &b) const {
Wade Guthriec8f58922013-01-29 16:18:27 -0800154 if (GetLength() != b.GetLength()) {
155 return false;
156 }
157 Vector::const_iterator lhs(begin_);
158 Vector::const_iterator rhs(b.begin_);
159 while(lhs != data_.end()) {
160 if (*lhs++ != *rhs++) {
161 return false;
162 }
163 }
164 return true;
Paul Stewart3ecfa2b2011-07-15 10:47:42 -0700165}
166
Paul Stewartdd7df792011-07-15 11:09:50 -0700167void ByteString::Append(const ByteString &b) {
Wade Guthriec8f58922013-01-29 16:18:27 -0800168 // Save and reapply offset since |insert| may reallocate the memory and
169 // invalidate the iterator.
170 size_t offset = distance(data_.begin(), begin_);
171 data_.insert(data_.end(), Vector::const_iterator(b.begin_), b.data_.end());
172 begin_ = data_.begin() + offset;
173}
174
175void ByteString::Clear() {
176 data_.clear();
177 begin_ = data_.begin();
178}
179
180void ByteString::Resize(int size) {
181 // Save and reapply offset since |resize| may reallocate the memory and
182 // invalidate the iterator.
183 size_t offset = distance(data_.begin(), begin_);
184 data_.resize(size + offset, 0);
185 begin_ = data_.begin() + offset;
Paul Stewartdd7df792011-07-15 11:09:50 -0700186}
187
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700188string ByteString::HexEncode() const {
189 return base::HexEncode(GetConstData(), GetLength());
190}
191
Wade Guthriec8f58922013-01-29 16:18:27 -0800192void ByteString::RemovePrefix(size_t offset) {
193 if (offset >= GetLength()) {
194 begin_ = data_.end();
195 } else {
196 begin_ += offset;
197 }
198}
199
Wade Guthrieb9c3feb2013-04-25 16:31:19 -0700200// static
201bool ByteString::IsLessThan(const ByteString &lhs, const ByteString &rhs) {
202 size_t byte_count = min(lhs.GetLength(), rhs.GetLength());
203 int result = memcmp(lhs.GetConstData(), rhs.GetConstData(), byte_count);
204 if (result == 0) {
205 return byte_count == lhs.GetLength();
206 }
207 return result < 0;
208}
209
Paul Stewart3ecfa2b2011-07-15 10:47:42 -0700210} // namespace shill