1/*
2 * Copyright (C) 2011 Research In Motion Limited. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB.  If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20#ifndef HexNumber_h
21#define HexNumber_h
22
23#include <wtf/text/StringConcatenate.h>
24
25namespace WTF {
26
27enum HexConversionMode {
28    Lowercase,
29    Uppercase
30};
31
32namespace Internal {
33
34const LChar lowerHexDigits[17] = "0123456789abcdef";
35const LChar upperHexDigits[17] = "0123456789ABCDEF";
36inline const LChar* hexDigitsForMode(HexConversionMode mode)
37{
38    return mode == Lowercase ? lowerHexDigits : upperHexDigits;
39}
40
41}; // namespace Internal
42
43template<typename T>
44inline void appendByteAsHex(unsigned char byte, T& destination, HexConversionMode mode = Uppercase)
45{
46    const LChar* hexDigits = Internal::hexDigitsForMode(mode);
47    destination.append(hexDigits[byte >> 4]);
48    destination.append(hexDigits[byte & 0xF]);
49}
50
51template<typename T>
52inline void placeByteAsHexCompressIfPossible(unsigned char byte, T& destination, unsigned& index, HexConversionMode mode = Uppercase)
53{
54    const LChar* hexDigits = Internal::hexDigitsForMode(mode);
55    if (byte >= 0x10)
56        destination[index++] = hexDigits[byte >> 4];
57    destination[index++] = hexDigits[byte & 0xF];
58}
59
60template<typename T>
61inline void placeByteAsHex(unsigned char byte, T& destination, HexConversionMode mode = Uppercase)
62{
63    const LChar* hexDigits = Internal::hexDigitsForMode(mode);
64    *destination++ = hexDigits[byte >> 4];
65    *destination++ = hexDigits[byte & 0xF];
66}
67
68template<typename T>
69inline void appendUnsignedAsHex(unsigned number, T& destination, HexConversionMode mode = Uppercase)
70{
71    const LChar* hexDigits = Internal::hexDigitsForMode(mode);
72    Vector<LChar, 8> result;
73    do {
74        result.append(hexDigits[number % 16]);
75        number >>= 4;
76    } while (number > 0);
77
78    result.reverse();
79    destination.append(result.data(), result.size());
80}
81
82template<typename T>
83inline void appendUnsigned64AsHex(uint64_t number, T& destination, HexConversionMode mode = Uppercase)
84{
85    const LChar* hexDigits = Internal::hexDigitsForMode(mode);
86    Vector<LChar, 8> result;
87    do {
88        result.append(hexDigits[number % 16]);
89        number >>= 4;
90    } while (number > 0);
91
92    result.reverse();
93    destination.append(result.data(), result.size());
94}
95
96// Same as appendUnsignedAsHex, but using exactly 'desiredDigits' for the conversion.
97template<typename T>
98inline void appendUnsignedAsHexFixedSize(unsigned number, T& destination, unsigned desiredDigits, HexConversionMode mode = Uppercase)
99{
100    ASSERT(desiredDigits);
101
102    const LChar* hexDigits = Internal::hexDigitsForMode(mode);
103    Vector<LChar, 8> result;
104    do {
105        result.append(hexDigits[number % 16]);
106        number >>= 4;
107    } while (result.size() < desiredDigits);
108
109    ASSERT(result.size() == desiredDigits);
110    result.reverse();
111    destination.append(result.data(), result.size());
112}
113
114} // namespace WTF
115
116using WTF::appendByteAsHex;
117using WTF::appendUnsignedAsHex;
118using WTF::appendUnsignedAsHexFixedSize;
119using WTF::placeByteAsHex;
120using WTF::placeByteAsHexCompressIfPossible;
121using WTF::Lowercase;
122
123#endif // HexNumber_h
124