1/*
2 * Copyright (C) 2012 Apple Inc. All Rights Reserved.
3 * Copyright (C) 2012 Patrick Gansterer <paroga@paroga.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22#pragma once
23
24#include <wtf/text/LChar.h>
25
26namespace WTF {
27
28enum PositiveOrNegativeNumber { PositiveNumber, NegativeNumber };
29
30template<typename> struct IntegerToStringConversionTrait;
31
32template<typename T, typename UnsignedIntegerType, PositiveOrNegativeNumber NumberType, typename AdditionalArgumentType>
33static typename IntegerToStringConversionTrait<T>::ReturnType numberToStringImpl(UnsignedIntegerType number, AdditionalArgumentType additionalArgument)
34{
35 LChar buf[sizeof(UnsignedIntegerType) * 3 + 1];
36 LChar* end = std::end(buf);
37 LChar* p = end;
38
39 do {
40 *--p = static_cast<LChar>((number % 10) + '0');
41 number /= 10;
42 } while (number);
43
44 if (NumberType == NegativeNumber)
45 *--p = '-';
46
47 return IntegerToStringConversionTrait<T>::flush(p, static_cast<unsigned>(end - p), additionalArgument);
48}
49
50template<typename T, typename SignedIntegerType>
51inline typename IntegerToStringConversionTrait<T>::ReturnType numberToStringSigned(SignedIntegerType number, typename IntegerToStringConversionTrait<T>::AdditionalArgumentType* additionalArgument = nullptr)
52{
53 if (number < 0)
54 return numberToStringImpl<T, typename std::make_unsigned<SignedIntegerType>::type, NegativeNumber>(-number, additionalArgument);
55 return numberToStringImpl<T, typename std::make_unsigned<SignedIntegerType>::type, PositiveNumber>(number, additionalArgument);
56}
57
58template<typename T, typename UnsignedIntegerType>
59inline typename IntegerToStringConversionTrait<T>::ReturnType numberToStringUnsigned(UnsignedIntegerType number, typename IntegerToStringConversionTrait<T>::AdditionalArgumentType* additionalArgument = nullptr)
60{
61 return numberToStringImpl<T, UnsignedIntegerType, PositiveNumber>(number, additionalArgument);
62}
63
64template<typename CharacterType, typename UnsignedIntegerType, PositiveOrNegativeNumber NumberType>
65static void writeNumberToBufferImpl(UnsignedIntegerType number, CharacterType* destination)
66{
67 LChar buf[sizeof(UnsignedIntegerType) * 3 + 1];
68 LChar* end = std::end(buf);
69 LChar* p = end;
70
71 do {
72 *--p = static_cast<LChar>((number % 10) + '0');
73 number /= 10;
74 } while (number);
75
76 if (NumberType == NegativeNumber)
77 *--p = '-';
78
79 while (p < end)
80 *destination++ = static_cast<CharacterType>(*p++);
81}
82
83template<typename CharacterType, typename SignedIntegerType>
84inline void writeNumberToBufferSigned(SignedIntegerType number, CharacterType* destination)
85{
86 if (number < 0)
87 return writeNumberToBufferImpl<CharacterType, typename std::make_unsigned<SignedIntegerType>::type, NegativeNumber>(-number, destination);
88 return writeNumberToBufferImpl<CharacterType, typename std::make_unsigned<SignedIntegerType>::type, PositiveNumber>(number, destination);
89}
90
91template<typename CharacterType, typename UnsignedIntegerType>
92inline void writeNumberToBufferUnsigned(UnsignedIntegerType number, CharacterType* destination)
93{
94 return writeNumberToBufferImpl<CharacterType, UnsignedIntegerType, PositiveNumber>(number, destination);
95}
96
97template<typename UnsignedIntegerType, PositiveOrNegativeNumber NumberType>
98static unsigned lengthOfNumberAsStringImpl(UnsignedIntegerType number)
99{
100 unsigned length = 0;
101
102 do {
103 ++length;
104 number /= 10;
105 } while (number);
106
107 if (NumberType == NegativeNumber)
108 ++length;
109
110 return length;
111}
112
113template<typename SignedIntegerType>
114inline unsigned lengthOfNumberAsStringSigned(SignedIntegerType number)
115{
116 if (number < 0)
117 return lengthOfNumberAsStringImpl<typename std::make_unsigned<SignedIntegerType>::type, NegativeNumber>(-number);
118 return lengthOfNumberAsStringImpl<typename std::make_unsigned<SignedIntegerType>::type, PositiveNumber>(number);
119}
120
121template<typename UnsignedIntegerType>
122inline unsigned lengthOfNumberAsStringUnsigned(UnsignedIntegerType number)
123{
124 return lengthOfNumberAsStringImpl<UnsignedIntegerType, PositiveNumber>(number);
125}
126
127} // namespace WTF
128