Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
F
fmt
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
fmt
Commits
e9b21916
Commit
e9b21916
authored
Feb 19, 2014
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add a 32-bit version of CountDigits.
parent
3017fc6f
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
83 additions
and
39 deletions
+83
-39
format-test.cc
format-test.cc
+31
-10
format.cc
format.cc
+16
-20
format.h
format.h
+36
-9
No files found.
format-test.cc
View file @
e9b21916
...
@@ -170,6 +170,24 @@ TEST(UtilTest, Increment) {
...
@@ -170,6 +170,24 @@ TEST(UtilTest, Increment) {
EXPECT_STREQ
(
"200"
,
s
);
EXPECT_STREQ
(
"200"
,
s
);
}
}
// Tests fmt::internal::CountDigits for integer type Int.
template
<
typename
Int
>
void
TestCountDigits
(
Int
)
{
for
(
Int
i
=
0
;
i
<
10
;
++
i
)
EXPECT_EQ
(
1
,
fmt
::
internal
::
CountDigits
(
i
));
for
(
Int
i
=
1
,
n
=
1
,
end
=
std
::
numeric_limits
<
Int
>::
max
()
/
10
;
n
<=
end
;
++
i
)
{
n
*=
10
;
EXPECT_EQ
(
i
,
fmt
::
internal
::
CountDigits
(
n
-
1
));
EXPECT_EQ
(
i
+
1
,
fmt
::
internal
::
CountDigits
(
n
));
}
}
TEST
(
UtilTest
,
CountDigits
)
{
TestCountDigits
(
uint32_t
());
TestCountDigits
(
uint64_t
());
}
class
TestString
{
class
TestString
{
private:
private:
std
::
string
value_
;
std
::
string
value_
;
...
@@ -1427,18 +1445,21 @@ TEST(FormatIntTest, FormatInt) {
...
@@ -1427,18 +1445,21 @@ TEST(FormatIntTest, FormatInt) {
EXPECT_EQ
(
os
.
str
(),
fmt
::
FormatInt
(
std
::
numeric_limits
<
int64_t
>::
max
()).
str
());
EXPECT_EQ
(
os
.
str
(),
fmt
::
FormatInt
(
std
::
numeric_limits
<
int64_t
>::
max
()).
str
());
}
}
TEST
(
FormatIntTest
,
FormatDec
)
{
template
<
typename
T
>
std
::
string
FormatDec
(
T
value
)
{
char
buffer
[
10
];
char
buffer
[
10
];
char
*
ptr
=
buffer
;
char
*
ptr
=
buffer
;
fmt
::
FormatDec
(
ptr
,
42
);
fmt
::
FormatDec
(
ptr
,
value
);
EXPECT_EQ
(
buffer
+
2
,
ptr
);
return
std
::
string
(
buffer
,
ptr
);
*
ptr
=
'\0'
;
}
EXPECT_STREQ
(
"42"
,
buffer
);
ptr
=
buffer
;
TEST
(
FormatIntTest
,
FormatDec
)
{
fmt
::
FormatDec
(
ptr
,
-
42
);
EXPECT_EQ
(
"42"
,
FormatDec
(
42
));
*
ptr
=
'\0'
;
EXPECT_EQ
(
"-42"
,
FormatDec
(
-
42
));
EXPECT_EQ
(
buffer
+
3
,
ptr
);
EXPECT_EQ
(
"42"
,
FormatDec
(
42l
));
EXPECT_STREQ
(
"-42"
,
buffer
);
EXPECT_EQ
(
"42"
,
FormatDec
(
42ul
));
EXPECT_EQ
(
"42"
,
FormatDec
(
42ll
));
EXPECT_EQ
(
"42"
,
FormatDec
(
42ull
));
}
}
template
<
typename
T
>
template
<
typename
T
>
...
...
format.cc
View file @
e9b21916
...
@@ -119,26 +119,22 @@ const char fmt::internal::DIGITS[] =
...
@@ -119,26 +119,22 @@ const char fmt::internal::DIGITS[] =
"6061626364656667686970717273747576777879"
"6061626364656667686970717273747576777879"
"8081828384858687888990919293949596979899"
;
"8081828384858687888990919293949596979899"
;
const
uint64_t
fmt
::
internal
::
POWERS_OF_10
[]
=
{
#define FMT_POWERS_OF_10(prefix) \
prefix 10, \
prefix 100, \
prefix 1000, \
prefix 10000, \
prefix 100000, \
prefix 1000000, \
prefix 10000000, \
prefix 100000000, \
prefix 1000000000
const
uint32_t
fmt
::
internal
::
POWERS_OF_10_32
[]
=
{
0
,
FMT_POWERS_OF_10
()};
const
uint64_t
fmt
::
internal
::
POWERS_OF_10_64
[]
=
{
0
,
0
,
10
,
FMT_POWERS_OF_10
(),
100
,
FMT_POWERS_OF_10
(
ULongLong
(
1000000000
)
*
),
1000
,
10000
,
100000
,
1000000
,
10000000
,
100000000
,
1000000000
,
ULongLong
(
1000000000
)
*
10
,
ULongLong
(
1000000000
)
*
100
,
ULongLong
(
1000000000
)
*
1000
,
ULongLong
(
1000000000
)
*
10000
,
ULongLong
(
1000000000
)
*
100000
,
ULongLong
(
1000000000
)
*
1000000
,
ULongLong
(
1000000000
)
*
10000000
,
ULongLong
(
1000000000
)
*
100000000
,
ULongLong
(
1000000000
)
*
1000000000
,
ULongLong
(
1000000000
)
*
ULongLong
(
1000000000
)
*
10
ULongLong
(
1000000000
)
*
ULongLong
(
1000000000
)
*
10
};
};
...
...
format.h
View file @
e9b21916
...
@@ -213,17 +213,32 @@ class CharTraits<wchar_t> : public BasicCharTraits<wchar_t> {
...
@@ -213,17 +213,32 @@ class CharTraits<wchar_t> : public BasicCharTraits<wchar_t> {
const
wchar_t
*
format
,
unsigned
width
,
int
precision
,
T
value
);
const
wchar_t
*
format
,
unsigned
width
,
int
precision
,
T
value
);
};
};
// Selects uint32_t if FitsIn32Bits is true, uint64_t otherwise.
template
<
bool
FitsIn32Bits
>
struct
TypeSelector
{
typedef
uint32_t
Type
;
};
template
<
>
struct
TypeSelector
<
false
>
{
typedef
uint64_t
Type
;
};
template
<
typename
T
>
struct
IntTraitsBase
{
// Smallest of uint32_t and uint64_t that is large enough to represent
// all values of T.
typedef
typename
TypeSelector
<
std
::
numeric_limits
<
T
>::
digits
<=
32
>::
Type
MainType
;
};
// Information about an integer type.
// Information about an integer type.
// IntTraits is not specialized for integer types smaller than int,
// IntTraits is not specialized for integer types smaller than int,
// since these are promoted to int.
// since these are promoted to int.
template
<
typename
T
>
template
<
typename
T
>
struct
IntTraits
{
struct
IntTraits
:
IntTraitsBase
<
T
>
{
typedef
T
UnsignedType
;
typedef
T
UnsignedType
;
static
bool
IsNegative
(
T
)
{
return
false
;
}
static
bool
IsNegative
(
T
)
{
return
false
;
}
};
};
template
<
typename
T
,
typename
UnsignedT
>
template
<
typename
T
,
typename
UnsignedT
>
struct
SignedIntTraits
{
struct
SignedIntTraits
:
IntTraitsBase
<
T
>
{
typedef
UnsignedT
UnsignedType
;
typedef
UnsignedT
UnsignedType
;
static
bool
IsNegative
(
T
value
)
{
return
value
<
0
;
}
static
bool
IsNegative
(
T
value
)
{
return
value
<
0
;
}
};
};
...
@@ -245,17 +260,28 @@ struct IsLongDouble<long double> { enum {VALUE = 1}; };
...
@@ -245,17 +260,28 @@ struct IsLongDouble<long double> { enum {VALUE = 1}; };
void
ReportUnknownType
(
char
code
,
const
char
*
type
);
void
ReportUnknownType
(
char
code
,
const
char
*
type
);
extern
const
uint64_t
POWERS_OF_10
[];
extern
const
uint32_t
POWERS_OF_10_32
[];
extern
const
uint64_t
POWERS_OF_10_64
[];
#if FMT_GCC_VERSION >= 400 || __has_builtin(__builtin_clzll)
// Returns the number of decimal digits in n. Leading zeros are not counted
// Returns the number of decimal digits in n. Leading zeros are not counted
// except for n == 0 in which case CountDigits returns 1.
// except for n == 0 in which case CountDigits returns 1.
inline
unsigned
CountDigits
(
uint64_t
n
)
{
inline
unsigned
CountDigits
(
uint64_t
n
)
{
#if FMT_GCC_VERSION >= 400 || __has_builtin(__builtin_clzll)
// Based on http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
// Based on http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
// and the benchmark https://github.com/localvoid/cxx-benchmark-count-digits.
// and the benchmark https://github.com/localvoid/cxx-benchmark-count-digits.
uint64_t
t
=
(
64
-
__builtin_clzll
(
n
|
1
))
*
1233
>>
12
;
uint64_t
t
=
(
64
-
__builtin_clzll
(
n
|
1
))
*
1233
>>
12
;
return
t
-
(
n
<
POWERS_OF_10
[
t
])
+
1
;
return
t
-
(
n
<
POWERS_OF_10_64
[
t
])
+
1
;
}
# if FMT_GCC_VERSION >= 400 || __has_builtin(__builtin_clz)
// Optional version of CountDigits for better performance on 32-bit platforms.
inline
unsigned
CountDigits
(
uint32_t
n
)
{
uint32_t
t
=
(
32
-
__builtin_clz
(
n
|
1
))
*
1233
>>
12
;
return
t
-
(
n
<
POWERS_OF_10_32
[
t
])
+
1
;
}
# endif
#else
#else
// Slower version of CountDigits used when __builtin_clz is not available.
inline
unsigned
CountDigits
(
uint64_t
n
)
{
unsigned
count
=
1
;
unsigned
count
=
1
;
for
(;;)
{
for
(;;)
{
// Integer division is slow so do it for a group of four digits instead
// Integer division is slow so do it for a group of four digits instead
...
@@ -268,8 +294,8 @@ inline unsigned CountDigits(uint64_t n) {
...
@@ -268,8 +294,8 @@ inline unsigned CountDigits(uint64_t n) {
n
/=
10000u
;
n
/=
10000u
;
count
+=
4
;
count
+=
4
;
}
}
#endif
}
}
#endif
extern
const
char
DIGITS
[];
extern
const
char
DIGITS
[];
...
@@ -838,7 +864,7 @@ template <typename T, typename Spec>
...
@@ -838,7 +864,7 @@ template <typename T, typename Spec>
void
BasicWriter
<
Char
>::
FormatInt
(
T
value
,
const
Spec
&
spec
)
{
void
BasicWriter
<
Char
>::
FormatInt
(
T
value
,
const
Spec
&
spec
)
{
unsigned
size
=
0
;
unsigned
size
=
0
;
char
sign
=
0
;
char
sign
=
0
;
typedef
typename
internal
::
IntTraits
<
T
>::
Unsigned
Type
UnsignedType
;
typedef
typename
internal
::
IntTraits
<
T
>::
Main
Type
UnsignedType
;
UnsignedType
abs_value
=
value
;
UnsignedType
abs_value
=
value
;
if
(
internal
::
IntTraits
<
T
>::
IsNegative
(
value
))
{
if
(
internal
::
IntTraits
<
T
>::
IsNegative
(
value
))
{
sign
=
'-'
;
sign
=
'-'
;
...
@@ -850,7 +876,8 @@ void BasicWriter<Char>::FormatInt(T value, const Spec &spec) {
...
@@ -850,7 +876,8 @@ void BasicWriter<Char>::FormatInt(T value, const Spec &spec) {
}
}
switch
(
spec
.
type
())
{
switch
(
spec
.
type
())
{
case
0
:
case
'd'
:
{
case
0
:
case
'd'
:
{
unsigned
num_digits
=
internal
::
CountDigits
(
abs_value
);
typename
internal
::
IntTraits
<
T
>::
MainType
normalized_value
=
abs_value
;
unsigned
num_digits
=
internal
::
CountDigits
(
normalized_value
);
CharPtr
p
=
CharPtr
p
=
PrepareFilledBuffer
(
size
+
num_digits
,
spec
,
sign
)
+
1
-
num_digits
;
PrepareFilledBuffer
(
size
+
num_digits
,
spec
,
sign
)
+
1
-
num_digits
;
internal
::
FormatDecimal
(
GetBase
(
p
),
abs_value
,
num_digits
);
internal
::
FormatDecimal
(
GetBase
(
p
),
abs_value
,
num_digits
);
...
@@ -1380,7 +1407,7 @@ class FormatInt {
...
@@ -1380,7 +1407,7 @@ class FormatInt {
// write a terminating null character.
// write a terminating null character.
template
<
typename
T
>
template
<
typename
T
>
inline
void
FormatDec
(
char
*&
buffer
,
T
value
)
{
inline
void
FormatDec
(
char
*&
buffer
,
T
value
)
{
typedef
typename
internal
::
IntTraits
<
T
>::
Unsigned
Type
UnsignedType
;
typedef
typename
internal
::
IntTraits
<
T
>::
Main
Type
UnsignedType
;
UnsignedType
abs_value
=
value
;
UnsignedType
abs_value
=
value
;
if
(
internal
::
IntTraits
<
T
>::
IsNegative
(
value
))
{
if
(
internal
::
IntTraits
<
T
>::
IsNegative
(
value
))
{
*
buffer
++
=
'-'
;
*
buffer
++
=
'-'
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment