OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Native Client 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 #include "debug_blob.h" | |
5 #include <ctype.h> | |
6 #include <string.h> | |
7 #include <algorithm> | |
8 #include <string> | |
9 | |
10 namespace { | |
11 char GetHexDigit(unsigned int value, int digit_position) { | |
12 // const char* kDigitStrings = "0123456789ABCDEF"; | |
13 const char* kDigitStrings = "0123456789abcdef"; | |
14 unsigned int digit = (value >> (4 * digit_position)) & 0xF; | |
15 return kDigitStrings[digit]; | |
16 } | |
17 } // namespace | |
18 | |
19 namespace debug { | |
20 Blob::Blob() { | |
21 } | |
22 | |
23 Blob::Blob(const Blob& other) { | |
24 value_ = other.value_; | |
25 } | |
26 | |
27 Blob::Blob(const void* buff, size_t buff_sz) { | |
28 const byte* char_buff = static_cast<const byte*>(buff); | |
29 for (size_t i = 0; i < buff_sz; i++ ) | |
30 PushBack(*char_buff++); | |
31 } | |
32 | |
33 Blob::Blob(const char* buff) { | |
34 if (NULL != buff) { | |
35 for (size_t i = 0; i < strlen(buff); i++ ) | |
36 PushBack(buff[i]); | |
37 } | |
38 } | |
39 | |
40 Blob::~Blob() { | |
41 } | |
42 | |
43 Blob& Blob::operator = (const Blob& other) { | |
44 value_ = other.value_; | |
45 return *this; | |
46 } | |
47 | |
48 bool Blob::operator == (const Blob& other) const { | |
49 return value_ == other.value_; | |
50 } | |
51 | |
52 size_t Blob::Size() const { | |
53 return value_.size(); | |
54 } | |
55 | |
56 byte Blob::operator[] (size_t position) const { | |
57 return value_[position]; | |
58 } | |
59 | |
60 byte Blob::Front() const { | |
61 return value_.front(); | |
62 } | |
63 | |
64 byte Blob::Back() const { | |
65 return value_.back(); | |
66 } | |
67 | |
68 byte Blob::PopFront() { | |
69 byte c = value_.front(); | |
70 value_.pop_front(); | |
71 return c; | |
72 } | |
73 | |
74 byte Blob::PopBack() { | |
75 byte c = value_.back(); | |
76 value_.pop_back(); | |
77 return c; | |
78 } | |
79 | |
80 void Blob::PushFront(byte c) { | |
81 value_.push_front(c); | |
82 } | |
83 | |
84 void Blob::PushBack(byte c) { | |
85 value_.push_back(c); | |
86 } | |
87 | |
88 void Blob::Clear() { | |
89 value_.clear(); | |
90 } | |
91 | |
92 int Blob::ToInt() const { | |
93 int result = 0; | |
94 char* ptr = reinterpret_cast<char*>(&result); | |
95 size_t bytes_to_copy = std::min(sizeof(result), Size()); | |
96 for (size_t i = 0; i < bytes_to_copy; i++) | |
97 ptr[i] = value_[i]; | |
98 return result; | |
99 } | |
100 | |
101 std::string Blob::ToString() const { | |
102 std::string result; | |
103 for (size_t i = 0; i < Size(); i++) | |
104 result.append(1, value_[i]); | |
105 return result; | |
106 } | |
107 | |
108 std::string Blob::ToHexString(bool remove_leading_zeroes) const { | |
109 std::string result; | |
110 size_t num = Size(); | |
111 for (size_t i = 0; i < num; i++) { | |
112 char c = GetHexDigit(value_[i], 1); | |
113 result.append(1, c); | |
114 c = GetHexDigit(value_[i], 0); | |
115 result.append(1, c); | |
116 } | |
117 | |
118 if (remove_leading_zeroes) { | |
119 while (result[0] == '0') | |
120 result.erase(0, 1); | |
121 } | |
122 return result; | |
123 } | |
124 | |
125 void* Blob::ToCBuffer() const { | |
126 size_t num = Size(); | |
127 char* buff = static_cast<char*>(malloc(num)); | |
128 if (NULL != buff) { | |
129 for (size_t i = 0; i < num; i++) | |
130 buff[i] = (*this)[i]; | |
131 } | |
132 return buff; | |
133 } | |
134 | |
135 bool Blob::LoadFromHexString(const std::string& hex_str) { | |
136 Blob tmp(hex_str.c_str()); | |
137 return LoadFromHexString(tmp); | |
138 } | |
139 | |
140 bool Blob::LoadFromHexString(const Blob& hex_str) { | |
141 Clear(); | |
142 size_t num = hex_str.Size(); | |
143 for (size_t i = num; i > 0; i -= 2) { | |
144 if (isspace(hex_str[i - 1])) { | |
145 i++; | |
146 } else if (i >= 2) { | |
147 unsigned int c1 = 0; | |
148 unsigned int c2 = 0; | |
149 if (!HexCharToInt(hex_str[i - 1], &c1)) return false; | |
150 if (!HexCharToInt(hex_str[i - 2], &c2)) return false; | |
151 unsigned int c = c1 + (c2 << 4); | |
152 PushFront(c); | |
153 } else { | |
154 unsigned int c = 0; | |
155 if (!HexCharToInt(hex_str[i - 1], &c)) return false; | |
156 PushFront(c); | |
157 break; | |
158 } | |
159 } | |
160 return true; | |
161 } | |
162 | |
163 void Blob::Append(const Blob& blob) { | |
164 for (size_t i = 0; i < blob.Size(); i++) | |
165 PushBack(blob[i]); | |
166 } | |
167 | |
168 bool Blob::Compare(const Blob& blob, size_t to_length) const { | |
169 if (-1 == to_length) { | |
170 if (Size() != blob.Size()) | |
171 return false; | |
172 to_length = Size(); | |
173 } | |
174 for (size_t i = 0; i < to_length; i++) | |
175 if (value_[i] != blob[i]) | |
176 return false; | |
177 return true; | |
178 } | |
179 | |
180 bool Blob::HasPrefix(const std::string& prefix) const { | |
181 size_t num = prefix.size(); | |
182 if (Size() < num) | |
183 return false; | |
184 for (size_t i = 0; i < num; i++) | |
185 if (value_[i] != prefix[i]) | |
186 return false; | |
187 return true; | |
188 } | |
189 | |
190 void Blob::Reverse() { | |
191 std::reverse(value_.begin(), value_.end()); | |
192 } | |
193 | |
194 void Blob::Split(const char* delimiters, std::deque<Blob>* tokens) const { | |
195 Blob token; | |
196 std::deque<byte>::const_iterator it = value_.begin(); | |
197 while (value_.end() != it) { | |
198 byte c = *it++; | |
199 if (strchr(delimiters, c) != 0) { | |
200 tokens->push_back(token); | |
201 token.Clear(); | |
202 } else { | |
203 token.PushBack(c); | |
204 } | |
205 } | |
206 if (0 != token.Size()) | |
207 tokens->push_back(token); | |
208 } | |
209 | |
210 bool Blob::HexCharToInt(unsigned char c, unsigned int* result) { | |
211 if (('0' <= c) && ('9' >= c)) { | |
212 *result = c - '0'; | |
213 } else if (('A' <= c) && ('F' >= c)) { | |
214 *result = c - 'A' + 10; | |
215 } else if (('a' <= c) && ('f' >= c)) { | |
216 *result = c - 'a' + 10; | |
217 } else { | |
218 return false; | |
219 } | |
220 return true; | |
221 } | |
222 | |
223 #define my_assert(x) do {\ | |
224 if(!(x)) {*error="Failed: "#x;\ | |
225 return __LINE__;}}\ | |
226 while(false) | |
227 | |
228 BlobUniTest::BlobUniTest() { | |
229 } | |
230 | |
231 int BlobUniTest::Run(std::string* error) { | |
232 if (true) { | |
233 unsigned char buff[] = {0x3, 0xAF, 0xF0}; | |
234 Blob blob(buff, sizeof(buff)); | |
235 std::string str = blob.ToHexString(true); | |
236 my_assert(str == "3aff0"); | |
237 | |
238 str = blob.ToHexString(false); | |
239 my_assert(str == "03aff0"); | |
240 | |
241 my_assert(blob[0] == 0x3); | |
242 my_assert(blob[1] == 0xAF); | |
243 my_assert(blob[2] == 0xF0); | |
244 my_assert(blob.Size() == 3); | |
245 | |
246 Blob blob2(blob); | |
247 my_assert(blob2 == blob); | |
248 my_assert(blob2[0] == 0x3); | |
249 my_assert(blob2[1] == 0xAF); | |
250 my_assert(blob2[2] == 0xF0); | |
251 my_assert(blob2.Size() == 3); | |
252 | |
253 Blob blob3; | |
254 blob3 = blob; | |
255 my_assert(blob3 == blob); | |
256 my_assert(blob3[0] == 0x3); | |
257 my_assert(blob3[1] == 0xAF); | |
258 my_assert(blob3[2] == 0xF0); | |
259 my_assert(blob3.Size() == 3); | |
260 | |
261 Blob blob4; | |
262 blob4.LoadFromHexString(std::string("3aff0")); | |
263 my_assert(blob4 == blob); | |
264 | |
265 Blob blob5; | |
266 blob5.LoadFromHexString(std::string("03aff0")); | |
267 my_assert(blob5 == blob); | |
268 | |
269 Blob blob6(std::string("03aff0").c_str()); | |
270 Blob blob7; | |
271 blob7.LoadFromHexString(blob6); | |
272 my_assert(blob7 == blob); | |
273 } | |
274 | |
275 if (true) { | |
276 unsigned char buff[] = {0, 0x3, 0xAF, 0xF0}; | |
277 Blob blob(buff, sizeof(buff)); | |
278 std::string str = blob.ToHexString(true); | |
279 my_assert(str == "3aff0"); | |
280 | |
281 str = blob.ToHexString(false); | |
282 my_assert(str == "0003aff0"); | |
283 | |
284 my_assert(blob[0] == 0); | |
285 my_assert(blob[1] == 0x3); | |
286 my_assert(blob[2] == 0xAF); | |
287 my_assert(blob[3] == 0xF0); | |
288 my_assert(blob.Size() == 4); | |
289 } | |
290 | |
291 // returns 0 if success, error code if failed. | |
292 return 0; | |
293 } | |
294 } // namespace debug | |
295 | |
OLD | NEW |