1// Copyright (c) 2012 The Chromium 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// String manipulation functions used in the RLZ library.
6
7#include "rlz/lib/string_utils.h"
8
9#include "rlz/lib/assert.h"
10
11namespace rlz_lib {
12
13bool IsAscii(unsigned char letter) {
14  return letter < 0x80;
15}
16
17bool GetHexValue(char letter, int* value) {
18  if (!value) {
19    ASSERT_STRING("GetHexValue: Invalid output paramter");
20    return false;
21  }
22  *value = 0;
23
24  if (letter >= '0' && letter <= '9')
25    *value = letter - '0';
26  else if (letter >= 'a' && letter <= 'f')
27    *value = (letter - 'a') + 0xA;
28  else if (letter >= 'A' && letter <= 'F')
29    *value = (letter - 'A') + 0xA;
30  else
31    return false;
32
33  return true;
34}
35
36int HexStringToInteger(const char* text) {
37  if (!text) {
38    ASSERT_STRING("HexStringToInteger: text is NULL.");
39    return 0;
40  }
41
42  int idx = 0;
43  // Ignore leading whitespace.
44  while (text[idx] == '\t' || text[idx] == ' ')
45    idx++;
46
47  if ((text[idx] == '0') &&
48      (text[idx + 1] == 'X' || text[idx + 1] == 'x'))
49    idx +=2;  // String is of the form 0x...
50
51  int number = 0;
52  int digit = 0;
53  for (; text[idx] != '\0'; idx++) {
54    if (!GetHexValue(text[idx], &digit)) {
55      // Ignore trailing whitespaces, but assert on other trailing characters.
56      bool only_whitespaces = true;
57      while (only_whitespaces && text[idx])
58        only_whitespaces = (text[idx++] == ' ');
59      if (!only_whitespaces)
60        ASSERT_STRING("HexStringToInteger: text contains non-hex characters.");
61      return number;
62    }
63    number = (number << 4) | digit;
64  }
65
66  return number;
67}
68
69bool BytesToString(const unsigned char* data,
70                   int data_len,
71                   std::string* string) {
72  if (!string)
73    return false;
74
75  string->clear();
76  if (data_len < 1 || !data)
77    return false;
78
79  static const char kHex[] = "0123456789ABCDEF";
80
81  // Fix the buffer size to begin with to avoid repeated re-allocation.
82  string->resize(data_len * 2);
83  int index = data_len;
84  while (index--) {
85    string->at(2 * index) = kHex[data[index] >> 4];  // high digit
86    string->at(2 * index + 1) = kHex[data[index] & 0x0F];  // low digit
87  }
88
89  return true;
90}
91
92}  // namespace rlz_lib
93