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
418659ad
Commit
418659ad
authored
Mar 03, 2018
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix compilation errors on gcc 4.4
parent
1d2adef2
Changes
8
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
232 additions
and
183 deletions
+232
-183
include/fmt/core.h
include/fmt/core.h
+17
-3
include/fmt/format.h
include/fmt/format.h
+156
-128
include/fmt/ostream.h
include/fmt/ostream.h
+2
-2
include/fmt/printf.h
include/fmt/printf.h
+23
-23
test/custom-formatter-test.cc
test/custom-formatter-test.cc
+1
-1
test/format-impl-test.cc
test/format-impl-test.cc
+2
-2
test/format-test.cc
test/format-test.cc
+8
-5
test/util-test.cc
test/util-test.cc
+23
-19
No files found.
include/fmt/core.h
View file @
418659ad
...
...
@@ -167,6 +167,11 @@
# define FMT_USE_EXPERIMENTAL_STRING_VIEW
#endif
// std::result_of is defined in <functional> in gcc 4.4.
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 404
# include <functional>
#endif
namespace
fmt
{
// An implementation of declval for pre-C++11 compilers such as gcc 4.
...
...
@@ -302,8 +307,6 @@ class basic_buffer {
std
::
size_t
capacity_
;
protected:
typedef
const
T
&
const_reference
;
basic_buffer
(
T
*
p
=
FMT_NULL
,
std
::
size_t
size
=
0
,
std
::
size_t
capacity
=
0
)
FMT_NOEXCEPT:
ptr_
(
p
),
size_
(
size
),
capacity_
(
capacity
)
{}
...
...
@@ -322,6 +325,7 @@ class basic_buffer {
public:
typedef
T
value_type
;
typedef
const
T
&
const_reference
;
virtual
~
basic_buffer
()
{}
...
...
@@ -655,6 +659,16 @@ enum { MAX_PACKED_ARGS = 15 };
template
<
typename
Context
>
class
arg_map
;
template
<
typename
>
struct
result_of
;
template
<
typename
F
,
typename
...
Args
>
struct
result_of
<
F
(
Args
...)
>
{
// A workaround for gcc 4.4 that doesn't allow F to be a reference.
typedef
typename
std
::
result_of
<
typename
std
::
remove_reference
<
F
>::
type
(
Args
...)
>::
type
type
;
};
}
// A formatting argument. It is a trivially copyable/constructible type to
...
...
@@ -669,7 +683,7 @@ class basic_arg {
friend
FMT_CONSTEXPR
basic_arg
<
ContextType
>
internal
::
make_arg
(
const
T
&
value
);
template
<
typename
Visitor
,
typename
Ctx
>
friend
FMT_CONSTEXPR
typename
std
::
result_of
<
Visitor
(
int
)
>::
type
friend
FMT_CONSTEXPR
typename
internal
::
result_of
<
Visitor
(
int
)
>::
type
visit
(
Visitor
&&
vis
,
basic_arg
<
Ctx
>
arg
);
friend
class
basic_format_args
<
Context
>
;
...
...
include/fmt/format.h
View file @
418659ad
This diff is collapsed.
Click to expand it.
include/fmt/ostream.h
View file @
418659ad
...
...
@@ -61,8 +61,8 @@ class convert_to_int<T, Char, true> {
private:
template
<
typename
U
>
static
decltype
(
std
::
declval
<
test_stream
<
Char
>&>
()
<<
std
::
declval
<
U
>
(),
std
::
true_type
()
)
test
(
int
);
internal
::
declval
<
test_stream
<
Char
>&>
(
)
<<
internal
::
declval
<
U
>
(),
std
::
true_type
())
test
(
int
);
template
<
typename
>
static
std
::
false_type
test
(...);
...
...
include/fmt/printf.h
View file @
418659ad
...
...
@@ -19,7 +19,7 @@ namespace internal {
// Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers.
template
<
bool
IsSigned
>
struct
IntC
hecker
{
struct
int_c
hecker
{
template
<
typename
T
>
static
bool
fits_in_int
(
T
value
)
{
unsigned
max
=
std
::
numeric_limits
<
int
>::
max
();
...
...
@@ -29,7 +29,7 @@ struct IntChecker {
};
template
<
>
struct
IntC
hecker
<
true
>
{
struct
int_c
hecker
<
true
>
{
template
<
typename
T
>
static
bool
fits_in_int
(
T
value
)
{
return
value
>=
std
::
numeric_limits
<
int
>::
min
()
&&
...
...
@@ -38,12 +38,12 @@ struct IntChecker<true> {
static
bool
fits_in_int
(
int
)
{
return
true
;
}
};
class
PrintfPrecisionHandler
{
class
printf_precision_handler
:
public
function
<
int
>
{
public:
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
int
>::
type
operator
()(
T
value
)
{
if
(
!
IntC
hecker
<
std
::
numeric_limits
<
T
>::
is_signed
>::
fits_in_int
(
value
))
if
(
!
int_c
hecker
<
std
::
numeric_limits
<
T
>::
is_signed
>::
fits_in_int
(
value
))
FMT_THROW
(
format_error
(
"number is too big"
));
return
static_cast
<
int
>
(
value
);
}
...
...
@@ -57,7 +57,7 @@ class PrintfPrecisionHandler {
};
// An argument visitor that returns true iff arg is a zero integer.
class
IsZeroInt
{
class
is_zero_int
:
public
function
<
bool
>
{
public:
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
bool
>::
type
...
...
@@ -77,7 +77,7 @@ struct make_unsigned_or_bool<bool> {
};
template
<
typename
T
,
typename
Context
>
class
ArgConverter
{
class
arg_converter
:
public
function
<
void
>
{
private:
typedef
typename
Context
::
char_type
Char
;
...
...
@@ -85,7 +85,7 @@ class ArgConverter {
typename
Context
::
char_type
type_
;
public:
ArgC
onverter
(
basic_arg
<
Context
>
&
arg
,
Char
type
)
arg_c
onverter
(
basic_arg
<
Context
>
&
arg
,
Char
type
)
:
arg_
(
arg
),
type_
(
type
)
{}
void
operator
()(
bool
value
)
{
...
...
@@ -134,19 +134,19 @@ class ArgConverter {
// unsigned).
template
<
typename
T
,
typename
Context
,
typename
Char
>
void
convert_arg
(
basic_arg
<
Context
>
&
arg
,
Char
type
)
{
visit
(
ArgC
onverter
<
T
,
Context
>
(
arg
,
type
),
arg
);
visit
(
arg_c
onverter
<
T
,
Context
>
(
arg
,
type
),
arg
);
}
// Converts an integer argument to char for printf.
template
<
typename
Context
>
class
CharConverter
{
class
char_converter
:
public
function
<
void
>
{
private:
basic_arg
<
Context
>
&
arg_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
CharC
onverter
);
FMT_DISALLOW_COPY_AND_ASSIGN
(
char_c
onverter
);
public:
explicit
CharC
onverter
(
basic_arg
<
Context
>
&
arg
)
:
arg_
(
arg
)
{}
explicit
char_c
onverter
(
basic_arg
<
Context
>
&
arg
)
:
arg_
(
arg
)
{}
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
>::
type
...
...
@@ -163,16 +163,16 @@ class CharConverter {
// Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative.
template
<
typename
Char
>
class
PrintfWidthHandler
{
class
printf_width_handler
:
public
function
<
unsigned
>
{
private:
typedef
basic_format_specs
<
Char
>
format_specs
;
format_specs
&
spec_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
PrintfWidthH
andler
);
FMT_DISALLOW_COPY_AND_ASSIGN
(
printf_width_h
andler
);
public:
explicit
PrintfWidthH
andler
(
format_specs
&
spec
)
:
spec_
(
spec
)
{}
explicit
printf_width_h
andler
(
format_specs
&
spec
)
:
spec_
(
spec
)
{}
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
unsigned
>::
type
...
...
@@ -213,10 +213,11 @@ class basic_printf_context;
\endrst
*/
template
<
typename
Range
>
class
printf_arg_formatter
:
public
internal
::
arg_formatter_base
<
Range
>
{
class
printf_arg_formatter
:
public
internal
::
function
<
void
>
,
public
internal
::
arg_formatter_base
<
Range
>
{
private:
typedef
typename
Range
::
value_type
char_type
;
typedef
decltype
(
std
::
declval
<
Range
>
().
begin
())
iterator
;
typedef
decltype
(
internal
::
declval
<
Range
>
().
begin
())
iterator
;
typedef
internal
::
arg_formatter_base
<
Range
>
base
;
typedef
basic_printf_context
<
iterator
,
char_type
>
context_type
;
...
...
@@ -417,7 +418,7 @@ unsigned basic_printf_context<OutputIt, Char, AF>::parse_header(
}
else
if
(
*
it
==
'*'
)
{
++
it
;
spec
.
width_
=
visit
(
internal
::
PrintfWidthH
andler
<
char_type
>
(
spec
),
get_arg
(
it
));
visit
(
internal
::
printf_width_h
andler
<
char_type
>
(
spec
),
get_arg
(
it
));
}
return
arg_index
;
}
...
...
@@ -453,14 +454,14 @@ void basic_printf_context<OutputIt, Char, AF>::format() {
}
else
if
(
*
it
==
'*'
)
{
++
it
;
spec
.
precision_
=
visit
(
internal
::
PrintfPrecisionH
andler
(),
get_arg
(
it
));
visit
(
internal
::
printf_precision_h
andler
(),
get_arg
(
it
));
}
else
{
spec
.
precision_
=
0
;
}
}
format_arg
arg
=
get_arg
(
it
,
arg_index
);
if
(
spec
.
flag
(
HASH_FLAG
)
&&
visit
(
internal
::
IsZeroI
nt
(),
arg
))
if
(
spec
.
flag
(
HASH_FLAG
)
&&
visit
(
internal
::
is_zero_i
nt
(),
arg
))
spec
.
flags_
&=
~
internal
::
to_unsigned
<
int
>
(
HASH_FLAG
);
if
(
spec
.
fill_
==
'0'
)
{
if
(
arg
.
is_arithmetic
())
...
...
@@ -514,7 +515,7 @@ void basic_printf_context<OutputIt, Char, AF>::format() {
break
;
case
'c'
:
// TODO: handle wchar_t
visit
(
internal
::
CharC
onverter
<
basic_printf_context
>
(
arg
),
arg
);
visit
(
internal
::
char_c
onverter
<
basic_printf_context
>
(
arg
),
arg
);
break
;
}
}
...
...
@@ -539,8 +540,7 @@ struct printf_context {
std
::
back_insert_iterator
<
Buffer
>
,
typename
Buffer
::
value_type
>
type
;
};
typedef
basic_format_args
<
typename
printf_context
<
internal
::
buffer
>::
type
>
printf_args
;
typedef
basic_format_args
<
printf_context
<
internal
::
buffer
>::
type
>
printf_args
;
inline
std
::
string
vsprintf
(
string_view
format
,
printf_args
args
)
{
memory_buffer
buffer
;
...
...
@@ -565,7 +565,7 @@ inline std::string sprintf(string_view format_str, const Args & ... args) {
inline
std
::
wstring
vsprintf
(
wstring_view
format
,
basic_format_args
<
typename
printf_context
<
internal
::
wbuffer
>::
type
>
args
)
{
basic_format_args
<
printf_context
<
internal
::
wbuffer
>::
type
>
args
)
{
wmemory_buffer
buffer
;
printf
(
buffer
,
format
,
args
);
return
to_string
(
buffer
);
...
...
test/custom-formatter-test.cc
View file @
418659ad
...
...
@@ -18,7 +18,7 @@ class CustomArgFormatter :
public
fmt
::
arg_formatter
<
fmt
::
back_insert_range
<
fmt
::
internal
::
buffer
>>
{
public:
typedef
fmt
::
back_insert_range
<
fmt
::
internal
::
buffer
>
range
;
typedef
decltype
(
std
::
declval
<
range
>
().
begin
())
iterator
;
typedef
decltype
(
fmt
::
internal
::
declval
<
range
>
().
begin
())
iterator
;
typedef
fmt
::
arg_formatter
<
range
>
base
;
CustomArgFormatter
(
fmt
::
basic_context
<
iterator
,
char
>
&
ctx
,
...
...
test/format-impl-test.cc
View file @
418659ad
...
...
@@ -44,7 +44,7 @@
#undef max
template
<
typename
T
>
struct
ValueExtractor
{
struct
ValueExtractor
:
fmt
::
internal
::
function
<
T
>
{
T
operator
()(
T
value
)
{
return
value
;
}
...
...
@@ -59,7 +59,7 @@ struct ValueExtractor {
TEST
(
FormatTest
,
ArgConverter
)
{
long
long
value
=
std
::
numeric_limits
<
long
long
>::
max
();
auto
arg
=
fmt
::
internal
::
make_arg
<
fmt
::
context
>
(
value
);
visit
(
fmt
::
internal
::
ArgC
onverter
<
long
long
,
fmt
::
context
>
(
arg
,
'd'
),
arg
);
visit
(
fmt
::
internal
::
arg_c
onverter
<
long
long
,
fmt
::
context
>
(
arg
,
'd'
),
arg
);
EXPECT_EQ
(
value
,
visit
(
ValueExtractor
<
long
long
>
(),
arg
));
}
...
...
test/format-test.cc
View file @
418659ad
...
...
@@ -1205,7 +1205,9 @@ TEST(FormatterTest, FormatPointer) {
EXPECT_EQ
(
"0x"
+
std
::
string
(
sizeof
(
void
*
)
*
CHAR_BIT
/
4
,
'f'
),
format
(
"{0}"
,
reinterpret_cast
<
void
*>
(
~
uintptr_t
())));
EXPECT_EQ
(
"0x1234"
,
format
(
"{}"
,
fmt
::
ptr
(
reinterpret_cast
<
int
*>
(
0x1234
))));
EXPECT_EQ
(
"0x0"
,
format
(
"{}"
,
nullptr
));
#if FMT_USE_NULLPTR
EXPECT_EQ
(
"0x0"
,
format
(
"{}"
,
FMT_NULL
));
#endif
}
TEST
(
FormatterTest
,
FormatString
)
{
...
...
@@ -1450,7 +1452,7 @@ TEST(FormatTest, JoinArg) {
EXPECT_EQ
(
L"(1, 2, 3)"
,
format
(
L"({})"
,
join
(
v1
,
v1
+
3
,
L", "
)));
EXPECT_EQ
(
"1, 2, 3"
,
format
(
"{0:{1}}"
,
join
(
v1
,
v1
+
3
,
", "
),
1
));
#if FMT_
HAS_GXX_CXX11
#if FMT_
USE_TRAILING_RETURN && (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 405)
EXPECT_EQ
(
"(1, 2, 3)"
,
format
(
"({})"
,
join
(
v1
,
", "
)));
EXPECT_EQ
(
"(+01.20, +03.40)"
,
format
(
"({:+06.2f})"
,
join
(
v2
,
", "
)));
#endif
...
...
@@ -1551,7 +1553,8 @@ TEST(FormatTest, FixedEnum) {
typedef
fmt
::
back_insert_range
<
fmt
::
internal
::
buffer
>
buffer_range
;
class
mock_arg_formatter
:
class
mock_arg_formatter
:
public
fmt
::
internal
::
function
<
void
>
,
public
fmt
::
internal
::
arg_formatter_base
<
buffer_range
>
{
private:
MOCK_METHOD1
(
call
,
void
(
int
value
));
...
...
@@ -1602,8 +1605,8 @@ template <>
struct
formatter
<
variant
>
:
dynamic_formatter
<>
{
auto
format
(
variant
value
,
context
&
ctx
)
->
decltype
(
ctx
.
begin
())
{
if
(
value
.
type
==
variant
::
INT
)
return
dynamic_formatter
::
format
(
42
,
ctx
);
return
dynamic_formatter
::
format
(
"foo"
,
ctx
);
return
dynamic_formatter
<>
::
format
(
42
,
ctx
);
return
dynamic_formatter
<>
::
format
(
"foo"
,
ctx
);
}
};
}
...
...
test/util-test.cc
View file @
418659ad
...
...
@@ -478,12 +478,12 @@ bool operator==(custom_value<Char> lhs, custom_value<Char> rhs) {
}
}
template
<
typename
T
>
struct
MockVisitor
{
// Use a unique result type to make sure that there are no undesirable
// conversions.
struct
Result
{};
// Use a unique result type to make sure that there are no undesirable
// conversions.
struct
Result
{};
template
<
typename
T
>
struct
MockVisitor
:
fmt
::
internal
::
function
<
Result
>
{
MockVisitor
()
{
ON_CALL
(
*
this
,
visit
(
_
)).
WillByDefault
(
Return
(
Result
()));
}
...
...
@@ -529,8 +529,9 @@ VISIT_TYPE(float, double);
fmt::visit(visitor, make_arg<fmt::basic_context<iterator, Char>>(value)); \
}
#define CHECK_ARG(value) { \
typename VisitType<decltype(value)>::Type expected = value; \
#define CHECK_ARG(value, typename_) { \
typedef decltype(value) value_type; \
typename_ VisitType<value_type>::Type expected = value; \
CHECK_ARG_(char, expected, value) \
CHECK_ARG_(wchar_t, expected, value) \
}
...
...
@@ -556,9 +557,9 @@ typename std::enable_if<std::is_floating_point<T>::value, T>::type
}
TYPED_TEST
(
NumericArgTest
,
MakeAndVisit
)
{
CHECK_ARG
(
test_value
<
TypeParam
>
());
CHECK_ARG
(
std
::
numeric_limits
<
TypeParam
>::
min
());
CHECK_ARG
(
std
::
numeric_limits
<
TypeParam
>::
max
());
CHECK_ARG
(
test_value
<
TypeParam
>
()
,
typename
);
CHECK_ARG
(
std
::
numeric_limits
<
TypeParam
>::
min
()
,
typename
);
CHECK_ARG
(
std
::
numeric_limits
<
TypeParam
>::
max
()
,
typename
);
}
TEST
(
UtilTest
,
CharArg
)
{
...
...
@@ -594,22 +595,25 @@ TEST(UtilTest, PointerArg) {
const
void
*
cp
=
0
;
CHECK_ARG_
(
char
,
cp
,
p
);
CHECK_ARG_
(
wchar_t
,
cp
,
p
);
CHECK_ARG
(
cp
);
CHECK_ARG
(
cp
,
);
}
TEST
(
UtilTest
,
CustomArg
)
{
::
Test
test
;
typedef
typename
fmt
::
basic_arg
<
fmt
::
context
>::
handle
handle
;
typedef
MockVisitor
<
handle
>
visitor
;
testing
::
StrictMock
<
visitor
>
v
;
EXPECT_CALL
(
v
,
visit
(
_
)).
WillOnce
(
testing
::
Invoke
([
&
](
handle
h
)
{
struct
check_custom
{
Result
operator
()(
fmt
::
basic_arg
<
fmt
::
context
>::
handle
h
)
const
{
fmt
::
memory_buffer
buffer
;
fmt
::
internal
::
basic_buffer
<
char
>
&
base
=
buffer
;
fmt
::
context
ctx
(
std
::
back_inserter
(
base
),
""
,
fmt
::
format_args
());
h
.
format
(
ctx
);
EXPECT_EQ
(
"test"
,
std
::
string
(
buffer
.
data
(),
buffer
.
size
()));
return
visitor
::
Result
();
}));
return
Result
();
}
};
TEST
(
UtilTest
,
CustomArg
)
{
::
Test
test
;
typedef
MockVisitor
<
fmt
::
basic_arg
<
fmt
::
context
>::
handle
>
visitor
;
testing
::
StrictMock
<
visitor
>
v
;
EXPECT_CALL
(
v
,
visit
(
_
)).
WillOnce
(
testing
::
Invoke
(
check_custom
()));
fmt
::
visit
(
v
,
make_arg
<
fmt
::
context
>
(
test
));
}
...
...
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