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.prepend(hexDigits[number % 16]);
75        number >>= 4;
76    } while (number > 0);
77
78    destination.append(result.data(), result.size());
79}
80
81// Same as appendUnsignedAsHex, but using exactly 'desiredDigits' for the conversion.
82template<typename T>
83inline void appendUnsignedAsHexFixedSize(unsigned number, T& destination, unsigned desiredDigits, HexConversionMode mode = Uppercase)
84{
85    ASSERT(desiredDigits);
86
87    const LChar* hexDigits = Internal::hexDigitsForMode(mode);
88    Vector<LChar, 8> result;
89    do {
90        result.prepend(hexDigits[number % 16]);
91        number >>= 4;
92    } while (result.size() < desiredDigits);
93
94    ASSERT(result.size() == desiredDigits);
95    destination.append(result.data(), result.size());
96}
97
98} // namespace WTF
99
100using WTF::appendByteAsHex;
101using WTF::appendUnsignedAsHex;
102using WTF::appendUnsignedAsHexFixedSize;
103using WTF::placeByteAsHex;
104using WTF::placeByteAsHexCompressIfPossible;
105using WTF::Lowercase;
106
107#endif // HexNumber_h
108