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 <algorithm> | |
6 #include <ctype.h> | |
7 #include <stdarg.h> | |
8 #include <string> | |
9 | |
10 namespace debug { | |
11 char Blob::GetHexDigit(unsigned int value, int digit_position) { | |
12 const char* kDigitStrings = "0123456789abcdef"; | |
13 unsigned int digit = (value >> (4 * digit_position)) & 0xF; | |
14 return kDigitStrings[digit]; | |
15 } | |
16 | |
17 Blob::Blob() { | |
18 } | |
19 | |
20 Blob::Blob(const Blob& other) { | |
21 value_ = other.value_; | |
22 } | |
23 | |
24 Blob::Blob(const void* buff, size_t buff_sz) { | |
25 const byte* char_buff = static_cast<const byte*>(buff); | |
26 for (size_t i = 0; i < buff_sz; i++ ) | |
27 PushBack(*char_buff++); | |
28 } | |
29 | |
30 Blob::Blob(const char* buff) { | |
31 if (NULL != buff) { | |
32 for (size_t i = 0; i < strlen(buff); i++ ) | |
33 PushBack(buff[i]); | |
34 } | |
35 } | |
36 | |
37 Blob::Blob(const std::string& str) { | |
38 Append(str.c_str()); | |
39 } | |
40 | |
41 Blob::~Blob() { | |
42 } | |
43 | |
44 Blob& Blob::operator = (const Blob& other) { | |
45 value_ = other.value_; | |
46 return *this; | |
47 } | |
48 | |
49 bool Blob::operator == (const Blob& other) const { | |
50 return value_ == other.value_; | |
51 } | |
52 | |
53 byte Blob::operator[] (size_t position) const { | |
54 return value_[position]; | |
55 } | |
56 | |
57 byte Blob::GetAt(size_t position) const { | |
58 return value_[position]; | |
59 } | |
60 | |
61 byte Blob::Front() const { | |
62 return value_.front(); | |
63 } | |
64 | |
65 byte Blob::Back() const { | |
66 return value_.back(); | |
67 } | |
68 | |
69 byte Blob::PopFront() { | |
70 byte c = value_.front(); | |
71 value_.pop_front(); | |
72 return c; | |
73 } | |
74 | |
75 byte Blob::PopBack() { | |
76 byte c = value_.back(); | |
77 value_.pop_back(); | |
78 return c; | |
79 } | |
80 | |
81 void Blob::PushFront(byte c) { | |
82 value_.push_front(c); | |
83 } | |
84 | |
85 void Blob::PushBack(byte c) { | |
86 value_.push_back(c); | |
87 } | |
88 | |
89 void Blob::Clear() { | |
90 value_.clear(); | |
91 } | |
92 | |
93 void Blob::Format(const char* fmt, ...) { | |
94 va_list marker; | |
95 va_start(marker, fmt); | |
96 char buff[32 * 1024]; // It's big enough for RSP messages. | |
97 signed int res = _vsnprintf_s(buff, sizeof(buff) - 1, fmt, marker); | |
98 if (-1 != res) { | |
99 buff[sizeof(buff) - 1] = 0; | |
100 buff[res] = 0; | |
101 *this = buff; | |
102 } | |
103 } | |
104 | |
105 unsigned int Blob::ToInt() const { | |
106 unsigned int result = 0; | |
107 // size_t sz = sizeof(result); | |
108 char* ptr = reinterpret_cast<char*>(&result); | |
109 size_t bytes_to_copy = std::min(sizeof(result), size()); | |
110 for (size_t i = 0; i < bytes_to_copy; i++) | |
111 ptr[i] = value_[i]; | |
112 return result; | |
113 } | |
114 | |
115 std::string Blob::ToString() const { | |
116 std::string result; | |
117 for (size_t i = 0; i < size(); i++) | |
118 result.append(1, value_[i]); | |
119 return result; | |
120 } | |
121 | |
122 std::string Blob::ToHexString(bool remove_leading_zeroes) const { | |
123 std::string result; | |
124 size_t num = size(); | |
125 for (size_t i = 0; i < num; i++) { | |
126 char c = GetHexDigit(value_[i], 1); | |
127 result.append(1, c); | |
128 c = GetHexDigit(value_[i], 0); | |
129 result.append(1, c); | |
130 } | |
131 | |
132 if (remove_leading_zeroes) { | |
133 while (result[0] == '0') | |
134 result.erase(0, 1); | |
135 } | |
136 return result; | |
137 } | |
138 | |
139 void* Blob::ToCBuffer() const { | |
140 if (0 == size()) | |
141 return NULL; | |
142 byte* buff = reinterpret_cast<byte*>(malloc(size())); | |
143 if (NULL != buff) { | |
144 for (size_t i = 0; i < size(); i++) | |
145 buff[i] = GetAt(i); | |
146 } | |
147 return buff; | |
148 } | |
149 | |
150 size_t Blob::Peek(size_t offset, void* buff, size_t buff_sz) const { | |
151 byte* out = static_cast<byte*>(buff); | |
152 size_t copied_bytes = 0; | |
153 for (size_t i = 0; i < buff_sz; i++) { | |
154 size_t pos = offset + i; | |
155 if (pos >= size()) | |
156 break; | |
157 out[i] = GetAt(pos); | |
158 copied_bytes++; | |
159 } | |
160 return copied_bytes; | |
161 } | |
162 | |
163 bool Blob::LoadFromHexString(const std::string& hex_str) { | |
164 Clear(); | |
165 size_t num = hex_str.size(); | |
166 for (size_t i = num; i > 0; i -= 2) { | |
167 if (isspace(hex_str[i - 1])) { | |
168 i++; | |
169 } else if (i >= 2) { | |
170 unsigned int c1 = 0; | |
171 unsigned int c2 = 0; | |
172 if (!HexCharToInt(hex_str[i - 1], &c1)) return false; | |
173 if (!HexCharToInt(hex_str[i - 2], &c2)) return false; | |
174 unsigned int c = c1 + (c2 << 4); | |
175 PushFront(c); | |
176 } else { | |
177 unsigned int c = 0; | |
178 if (!HexCharToInt(hex_str[i - 1], &c)) return false; | |
179 PushFront(c); | |
180 break; | |
181 } | |
182 } | |
183 return true; | |
184 } | |
185 | |
186 void Blob::Append(const Blob& blob) { | |
187 for (size_t i = 0; i < blob.size(); i++) | |
188 PushBack(blob[i]); | |
189 } | |
190 | |
191 bool Blob::Compare(const Blob& blob, size_t to_length) const { | |
192 if (-1 == to_length) { | |
193 if (size() != blob.size()) | |
194 return false; | |
195 to_length = size(); | |
196 } | |
197 for (size_t i = 0; i < to_length; i++) | |
198 if (value_[i] != blob[i]) | |
199 return false; | |
200 return true; | |
201 } | |
202 | |
203 bool Blob::IsPrefix(const Blob& prefix) const { | |
204 size_t num = prefix.size(); | |
205 if (size() < num) | |
206 return false; | |
207 for (size_t i = 0; i < num; i++) | |
208 if (value_[i] != prefix[i]) | |
209 return false; | |
210 return true; | |
211 } | |
212 | |
213 void Blob::PopMatchingCharsFromFront(const char* chars) { | |
214 while (size()) { | |
215 char c = Front(); | |
216 if (NULL == strchr(chars, c)) | |
217 break; | |
218 else | |
219 PopFront(); | |
220 } | |
221 } | |
222 | |
223 Blob Blob::PopBlobFromFrontUnilChars(const char* chars) { | |
224 Blob result; | |
225 while (size()) { | |
226 char c = PopFront(); | |
227 if (NULL != strchr(chars, c)) | |
228 break; | |
229 else | |
230 result.PushBack(c); | |
231 } | |
232 return result; | |
233 } | |
234 | |
235 unsigned int Blob::PopInt8FromFront() { | |
236 if (size() < 2) | |
237 return 0; | |
238 unsigned int dig1 = 0; | |
239 unsigned int dig2 = 0; | |
240 HexCharToInt(PopFront(), &dig1); | |
241 HexCharToInt(PopFront(), &dig2); | |
242 return (dig1 * 16) + dig2; | |
243 } | |
244 | |
245 u_int32_t Blob::PopInt32FromFront() { | |
246 u_int32_t res = 0; | |
247 size_t nibbles_to_copy = sizeof(res) * 2; | |
248 for (size_t i = 0; i < nibbles_to_copy; i++) { | |
249 if (0 == size()) | |
250 break; | |
251 unsigned int dig = 0; | |
252 HexCharToInt(PopFront(), &dig); | |
253 res = (res << 4) + dig; | |
254 } | |
255 return res; | |
256 } | |
257 | |
258 u_int64_t Blob::PopInt64FromFront() { | |
259 u_int64_t res = 0; | |
260 size_t nibbles_to_copy = sizeof(res) * 2; | |
261 for (size_t i = 0; i < nibbles_to_copy; i++) { | |
262 if (0 == size()) | |
263 break; | |
264 unsigned int dig = 0; | |
265 HexCharToInt(PopFront(), &dig); | |
266 res = (res << 4) + dig; | |
267 } | |
268 return res; | |
269 } | |
270 | |
271 void Blob::Reverse() { | |
272 std::reverse(value_.begin(), value_.end()); | |
273 } | |
274 | |
275 void Blob::Split(const char* delimiters, std::deque<Blob>* tokens) const { | |
276 tokens->clear(); | |
277 Blob token; | |
278 std::deque<byte>::const_iterator it = value_.begin(); | |
279 while (value_.end() != it) { | |
280 byte c = *it++; | |
281 if (strchr(delimiters, c) != 0) { | |
282 tokens->push_back(token); | |
283 token.Clear(); | |
284 } else { | |
285 token.PushBack(c); | |
286 } | |
287 } | |
288 if (0 != token.size()) | |
289 tokens->push_back(token); | |
290 } | |
291 | |
292 void Blob::PopSpacesFromBothEnds() { | |
293 while (size() != 0) { | |
294 char c = Front(); | |
295 if (0 != isspace(c)) | |
296 PopFront(); | |
297 else | |
298 break; | |
299 } | |
300 while (size() != 0) { | |
301 char c = Back(); | |
302 if (0 != isspace(c)) | |
303 PopBack(); | |
304 else | |
305 break; | |
306 } | |
307 } | |
308 | |
309 bool Blob::HexCharToInt(unsigned char c, unsigned int* result) { | |
310 if (('0' <= c) && ('9' >= c)) { | |
311 *result = c - '0'; | |
312 } | |
313 else if (('A' <= c) && ('F' >= c)) { | |
314 *result = c - 'A' + 10; | |
315 } | |
316 else if (('a' <= c) && ('f' >= c)) { | |
317 *result = c - 'a' + 10; | |
318 } | |
319 else { | |
320 return false; | |
321 } | |
322 return true; | |
323 } | |
324 | |
325 //------------------------------------------------------------------------------
--------------// | |
326 #define my_assert(x) do{ if(!(x)) {*error="Failed: "#x; return __LINE__;}} while
(false) | |
327 | |
328 BlobUniTest::BlobUniTest() { | |
329 } | |
330 | |
331 int BlobUniTest::Run(std::string* error) { | |
332 if (true) { | |
333 unsigned char buff[] = {0x3, 0xAF, 0xF0}; | |
334 Blob blob(buff, sizeof(buff)); | |
335 std::string str = blob.ToHexString(true); | |
336 my_assert(str == "3aff0"); | |
337 | |
338 str = blob.ToHexString(false); | |
339 my_assert(str == "03aff0"); | |
340 | |
341 my_assert(blob[0] == 0x3); | |
342 my_assert(blob[1] == 0xAF); | |
343 my_assert(blob[2] == 0xF0); | |
344 my_assert(blob.size() == 3); | |
345 | |
346 Blob blob2(blob); | |
347 my_assert(blob2 == blob); | |
348 my_assert(blob2[0] == 0x3); | |
349 my_assert(blob2[1] == 0xAF); | |
350 my_assert(blob2[2] == 0xF0); | |
351 my_assert(blob2.size() == 3); | |
352 | |
353 Blob blob3; | |
354 blob3 = blob; | |
355 my_assert(blob3 == blob); | |
356 my_assert(blob3[0] == 0x3); | |
357 my_assert(blob3[1] == 0xAF); | |
358 my_assert(blob3[2] == 0xF0); | |
359 my_assert(blob3.size() == 3); | |
360 | |
361 Blob blob4; | |
362 blob4.LoadFromHexString(std::string("3aff0")); | |
363 my_assert(blob4 == blob); | |
364 | |
365 Blob blob5; | |
366 blob5.LoadFromHexString(std::string("03aff0")); | |
367 my_assert(blob5 == blob); | |
368 | |
369 Blob blob6(std::string("03aff0").c_str()); | |
370 Blob blob7; | |
371 blob7.LoadFromHexString(blob6.ToString()); | |
372 my_assert(blob7 == blob); | |
373 | |
374 } | |
375 | |
376 if (true) { | |
377 unsigned char buff[] = {0, 0x3, 0xAF, 0xF0}; | |
378 Blob blob(buff, sizeof(buff)); | |
379 std::string str = blob.ToHexString(true); | |
380 my_assert(str == "3aff0"); | |
381 | |
382 str = blob.ToHexString(false); | |
383 my_assert(str == "0003aff0"); | |
384 | |
385 my_assert(blob[0] == 0); | |
386 my_assert(blob[1] == 0x3); | |
387 my_assert(blob[2] == 0xAF); | |
388 my_assert(blob[3] == 0xF0); | |
389 my_assert(blob.size() == 4); | |
390 } | |
391 | |
392 return 0; | |
393 } // returns 0 if success, error code if failed. | |
394 | |
395 } // namespace debug | |
OLD | NEW |