12bde8e466a4451c7319e3a072d118917957d6554Steve Block/*
22bde8e466a4451c7319e3a072d118917957d6554Steve Block * Copyright (C) 2011 Research In Motion Limited. All rights reserved.
32bde8e466a4451c7319e3a072d118917957d6554Steve Block *
42bde8e466a4451c7319e3a072d118917957d6554Steve Block * This library is free software; you can redistribute it and/or
52bde8e466a4451c7319e3a072d118917957d6554Steve Block * modify it under the terms of the GNU Library General Public
62bde8e466a4451c7319e3a072d118917957d6554Steve Block * License as published by the Free Software Foundation; either
72bde8e466a4451c7319e3a072d118917957d6554Steve Block * version 2 of the License, or (at your option) any later version.
82bde8e466a4451c7319e3a072d118917957d6554Steve Block *
92bde8e466a4451c7319e3a072d118917957d6554Steve Block * This library is distributed in the hope that it will be useful,
102bde8e466a4451c7319e3a072d118917957d6554Steve Block * but WITHOUT ANY WARRANTY; without even the implied warranty of
112bde8e466a4451c7319e3a072d118917957d6554Steve Block * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
122bde8e466a4451c7319e3a072d118917957d6554Steve Block * Library General Public License for more details.
132bde8e466a4451c7319e3a072d118917957d6554Steve Block *
142bde8e466a4451c7319e3a072d118917957d6554Steve Block * You should have received a copy of the GNU Library General Public License
152bde8e466a4451c7319e3a072d118917957d6554Steve Block * along with this library; see the file COPYING.LIB.  If not, write to
162bde8e466a4451c7319e3a072d118917957d6554Steve Block * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
172bde8e466a4451c7319e3a072d118917957d6554Steve Block * Boston, MA 02110-1301, USA.
182bde8e466a4451c7319e3a072d118917957d6554Steve Block */
192bde8e466a4451c7319e3a072d118917957d6554Steve Block
202bde8e466a4451c7319e3a072d118917957d6554Steve Block#ifndef HexNumber_h
212bde8e466a4451c7319e3a072d118917957d6554Steve Block#define HexNumber_h
222bde8e466a4451c7319e3a072d118917957d6554Steve Block
232bde8e466a4451c7319e3a072d118917957d6554Steve Block#include <wtf/text/StringConcatenate.h>
242bde8e466a4451c7319e3a072d118917957d6554Steve Block
252bde8e466a4451c7319e3a072d118917957d6554Steve Blocknamespace WTF {
262bde8e466a4451c7319e3a072d118917957d6554Steve Block
272bde8e466a4451c7319e3a072d118917957d6554Steve Blockenum HexConversionMode {
282bde8e466a4451c7319e3a072d118917957d6554Steve Block    Lowercase,
292bde8e466a4451c7319e3a072d118917957d6554Steve Block    Uppercase
302bde8e466a4451c7319e3a072d118917957d6554Steve Block};
312bde8e466a4451c7319e3a072d118917957d6554Steve Block
322bde8e466a4451c7319e3a072d118917957d6554Steve Blocknamespace Internal {
332bde8e466a4451c7319e3a072d118917957d6554Steve Block
342bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic const char* hexDigitsForMode(HexConversionMode mode)
352bde8e466a4451c7319e3a072d118917957d6554Steve Block{
362bde8e466a4451c7319e3a072d118917957d6554Steve Block    static const char lowerHexDigits[17] = "0123456789abcdef";
372bde8e466a4451c7319e3a072d118917957d6554Steve Block    static const char upperHexDigits[17] = "0123456789ABCDEF";
382bde8e466a4451c7319e3a072d118917957d6554Steve Block    return mode == Lowercase ? lowerHexDigits : upperHexDigits;
392bde8e466a4451c7319e3a072d118917957d6554Steve Block}
402bde8e466a4451c7319e3a072d118917957d6554Steve Block
412bde8e466a4451c7319e3a072d118917957d6554Steve Block}; // namespace Internal
422bde8e466a4451c7319e3a072d118917957d6554Steve Block
432bde8e466a4451c7319e3a072d118917957d6554Steve Blocktemplate<typename T>
442bde8e466a4451c7319e3a072d118917957d6554Steve Blockinline void appendByteAsHex(unsigned char byte, T& destination, HexConversionMode mode = Uppercase)
452bde8e466a4451c7319e3a072d118917957d6554Steve Block{
462bde8e466a4451c7319e3a072d118917957d6554Steve Block    const char* hexDigits = Internal::hexDigitsForMode(mode);
472bde8e466a4451c7319e3a072d118917957d6554Steve Block    destination.append(hexDigits[byte >> 4]);
482bde8e466a4451c7319e3a072d118917957d6554Steve Block    destination.append(hexDigits[byte & 0xF]);
492bde8e466a4451c7319e3a072d118917957d6554Steve Block}
502bde8e466a4451c7319e3a072d118917957d6554Steve Block
512bde8e466a4451c7319e3a072d118917957d6554Steve Blocktemplate<typename T>
522bde8e466a4451c7319e3a072d118917957d6554Steve Blockinline void placeByteAsHexCompressIfPossible(unsigned char byte, T& destination, unsigned& index, HexConversionMode mode = Uppercase)
532bde8e466a4451c7319e3a072d118917957d6554Steve Block{
542bde8e466a4451c7319e3a072d118917957d6554Steve Block    const char* hexDigits = Internal::hexDigitsForMode(mode);
552bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (byte >= 0x10)
562bde8e466a4451c7319e3a072d118917957d6554Steve Block        destination[index++] = hexDigits[byte >> 4];
572bde8e466a4451c7319e3a072d118917957d6554Steve Block    destination[index++] = hexDigits[byte & 0xF];
582bde8e466a4451c7319e3a072d118917957d6554Steve Block}
592bde8e466a4451c7319e3a072d118917957d6554Steve Block
602bde8e466a4451c7319e3a072d118917957d6554Steve Blocktemplate<typename T>
612bde8e466a4451c7319e3a072d118917957d6554Steve Blockinline void placeByteAsHex(unsigned char byte, T& destination, HexConversionMode mode = Uppercase)
622bde8e466a4451c7319e3a072d118917957d6554Steve Block{
632bde8e466a4451c7319e3a072d118917957d6554Steve Block    const char* hexDigits = Internal::hexDigitsForMode(mode);
642bde8e466a4451c7319e3a072d118917957d6554Steve Block    *destination++ = hexDigits[byte >> 4];
652bde8e466a4451c7319e3a072d118917957d6554Steve Block    *destination++ = hexDigits[byte & 0xF];
662bde8e466a4451c7319e3a072d118917957d6554Steve Block}
672bde8e466a4451c7319e3a072d118917957d6554Steve Block
682bde8e466a4451c7319e3a072d118917957d6554Steve Blocktemplate<typename T>
692bde8e466a4451c7319e3a072d118917957d6554Steve Blockinline void appendUnsignedAsHex(unsigned number, T& destination, HexConversionMode mode = Uppercase)
702bde8e466a4451c7319e3a072d118917957d6554Steve Block{
712bde8e466a4451c7319e3a072d118917957d6554Steve Block    const char* hexDigits = Internal::hexDigitsForMode(mode);
722bde8e466a4451c7319e3a072d118917957d6554Steve Block    Vector<UChar, 8> result;
732bde8e466a4451c7319e3a072d118917957d6554Steve Block    do {
742bde8e466a4451c7319e3a072d118917957d6554Steve Block        result.prepend(hexDigits[number % 16]);
752bde8e466a4451c7319e3a072d118917957d6554Steve Block        number >>= 4;
762bde8e466a4451c7319e3a072d118917957d6554Steve Block    } while (number > 0);
772bde8e466a4451c7319e3a072d118917957d6554Steve Block
782bde8e466a4451c7319e3a072d118917957d6554Steve Block    destination.append(result.data(), result.size());
792bde8e466a4451c7319e3a072d118917957d6554Steve Block}
802bde8e466a4451c7319e3a072d118917957d6554Steve Block
812bde8e466a4451c7319e3a072d118917957d6554Steve Block// Same as appendUnsignedAsHex, but using exactly 'desiredDigits' for the conversion.
822bde8e466a4451c7319e3a072d118917957d6554Steve Blocktemplate<typename T>
832bde8e466a4451c7319e3a072d118917957d6554Steve Blockinline void appendUnsignedAsHexFixedSize(unsigned number, T& destination, unsigned desiredDigits, HexConversionMode mode = Uppercase)
842bde8e466a4451c7319e3a072d118917957d6554Steve Block{
852bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(desiredDigits);
862bde8e466a4451c7319e3a072d118917957d6554Steve Block
872bde8e466a4451c7319e3a072d118917957d6554Steve Block    const char* hexDigits = Internal::hexDigitsForMode(mode);
882bde8e466a4451c7319e3a072d118917957d6554Steve Block    Vector<UChar, 8> result;
892bde8e466a4451c7319e3a072d118917957d6554Steve Block    do {
902bde8e466a4451c7319e3a072d118917957d6554Steve Block        result.prepend(hexDigits[number % 16]);
912bde8e466a4451c7319e3a072d118917957d6554Steve Block        number >>= 4;
922bde8e466a4451c7319e3a072d118917957d6554Steve Block    } while (result.size() < desiredDigits);
932bde8e466a4451c7319e3a072d118917957d6554Steve Block
942bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(result.size() == desiredDigits);
952bde8e466a4451c7319e3a072d118917957d6554Steve Block    destination.append(result.data(), result.size());
962bde8e466a4451c7319e3a072d118917957d6554Steve Block}
972bde8e466a4451c7319e3a072d118917957d6554Steve Block
982bde8e466a4451c7319e3a072d118917957d6554Steve Block} // namespace WTF
992bde8e466a4451c7319e3a072d118917957d6554Steve Block
1002bde8e466a4451c7319e3a072d118917957d6554Steve Blockusing WTF::appendByteAsHex;
1012bde8e466a4451c7319e3a072d118917957d6554Steve Blockusing WTF::appendUnsignedAsHex;
1022bde8e466a4451c7319e3a072d118917957d6554Steve Blockusing WTF::appendUnsignedAsHexFixedSize;
1032bde8e466a4451c7319e3a072d118917957d6554Steve Blockusing WTF::placeByteAsHex;
1042bde8e466a4451c7319e3a072d118917957d6554Steve Blockusing WTF::placeByteAsHexCompressIfPossible;
1052bde8e466a4451c7319e3a072d118917957d6554Steve Blockusing WTF::Lowercase;
1062bde8e466a4451c7319e3a072d118917957d6554Steve Block
1072bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif // HexNumber_h
108