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
1d3e3d8c
Commit
1d3e3d8c
authored
Jul 04, 2019
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make the 'n' format specifier work with grisu disabled
parent
bc628f8d
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
37 additions
and
17 deletions
+37
-17
include/fmt/format-inl.h
include/fmt/format-inl.h
+6
-4
include/fmt/format.h
include/fmt/format.h
+19
-8
src/format.cc
src/format.cc
+5
-5
test/locale-test.cc
test/locale-test.cc
+7
-0
No files found.
include/fmt/format-inl.h
View file @
1d3e3d8c
...
@@ -753,8 +753,8 @@ FMT_API bool grisu_format(Double value, buffer<char>& buf, int precision,
...
@@ -753,8 +753,8 @@ FMT_API bool grisu_format(Double value, buffer<char>& buf, int precision,
}
}
template
<
typename
Double
>
template
<
typename
Double
>
void
sprintf_format
(
Double
value
,
internal
::
buffer
<
char
>&
buf
,
char
*
sprintf_format
(
Double
value
,
internal
::
buffer
<
char
>&
buf
,
core_format_specs
spec
)
{
core_format_specs
spec
)
{
// Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail.
// Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail.
FMT_ASSERT
(
buf
.
capacity
()
!=
0
,
"empty buffer"
);
FMT_ASSERT
(
buf
.
capacity
()
!=
0
,
"empty buffer"
);
...
@@ -774,7 +774,7 @@ void sprintf_format(Double value, internal::buffer<char>& buf,
...
@@ -774,7 +774,7 @@ void sprintf_format(Double value, internal::buffer<char>& buf,
if
(
type
==
'%'
)
if
(
type
==
'%'
)
type
=
'f'
;
type
=
'f'
;
else
if
(
type
==
0
)
else
if
(
type
==
0
||
type
==
'n'
)
type
=
'g'
;
type
=
'g'
;
#if FMT_MSC_VER
#if FMT_MSC_VER
if
(
type
==
'F'
)
{
if
(
type
==
'F'
)
{
...
@@ -787,6 +787,7 @@ void sprintf_format(Double value, internal::buffer<char>& buf,
...
@@ -787,6 +787,7 @@ void sprintf_format(Double value, internal::buffer<char>& buf,
// Format using snprintf.
// Format using snprintf.
char
*
start
=
nullptr
;
char
*
start
=
nullptr
;
char
*
decimal_point_pos
=
nullptr
;
for
(;;)
{
for
(;;)
{
std
::
size_t
buffer_size
=
buf
.
capacity
();
std
::
size_t
buffer_size
=
buf
.
capacity
();
start
=
&
buf
[
0
];
start
=
&
buf
[
0
];
...
@@ -801,7 +802,7 @@ void sprintf_format(Double value, internal::buffer<char>& buf,
...
@@ -801,7 +802,7 @@ void sprintf_format(Double value, internal::buffer<char>& buf,
if
(
spec
.
type
!=
'a'
&&
spec
.
type
!=
'A'
)
{
if
(
spec
.
type
!=
'a'
&&
spec
.
type
!=
'A'
)
{
while
(
p
<
end
&&
*
p
>=
'0'
&&
*
p
<=
'9'
)
++
p
;
while
(
p
<
end
&&
*
p
>=
'0'
&&
*
p
<=
'9'
)
++
p
;
if
(
p
<
end
&&
*
p
!=
'e'
&&
*
p
!=
'E'
)
{
if
(
p
<
end
&&
*
p
!=
'e'
&&
*
p
!=
'E'
)
{
if
(
*
p
!=
'.'
)
*
p
=
'.'
;
decimal_point_pos
=
p
;
if
(
!
spec
.
type
)
{
if
(
!
spec
.
type
)
{
// Keep only one trailing zero after the decimal point.
// Keep only one trailing zero after the decimal point.
++
p
;
++
p
;
...
@@ -826,6 +827,7 @@ void sprintf_format(Double value, internal::buffer<char>& buf,
...
@@ -826,6 +827,7 @@ void sprintf_format(Double value, internal::buffer<char>& buf,
buf
.
reserve
(
buf
.
capacity
()
+
1
);
buf
.
reserve
(
buf
.
capacity
()
+
1
);
}
}
}
}
return
decimal_point_pos
;
}
}
}
// namespace internal
}
// namespace internal
...
...
include/fmt/format.h
View file @
1d3e3d8c
...
@@ -1052,7 +1052,7 @@ It grisu_prettify(const char* digits, int size, int exp, It it,
...
@@ -1052,7 +1052,7 @@ It grisu_prettify(const char* digits, int size, int exp, It it,
}
}
template
<
typename
Double
>
template
<
typename
Double
>
void
sprintf_format
(
Double
,
internal
::
buffer
<
char
>&
,
core_format_specs
);
char
*
sprintf_format
(
Double
,
internal
::
buffer
<
char
>&
,
core_format_specs
);
template
<
typename
Handler
>
template
<
typename
Handler
>
FMT_CONSTEXPR
void
handle_int_type_spec
(
char
spec
,
Handler
&&
handler
)
{
FMT_CONSTEXPR
void
handle_int_type_spec
(
char
spec
,
Handler
&&
handler
)
{
...
@@ -1442,13 +1442,21 @@ template <typename Range> class basic_writer {
...
@@ -1442,13 +1442,21 @@ template <typename Range> class basic_writer {
struct
double_writer
{
struct
double_writer
{
char
sign
;
char
sign
;
internal
::
buffer
<
char
>&
buffer
;
internal
::
buffer
<
char
>&
buffer
;
char
*
decimal_point_pos
;
char_type
decimal_point
;
size_t
size
()
const
{
return
buffer
.
size
()
+
(
sign
?
1
:
0
);
}
size_t
size
()
const
{
return
buffer
.
size
()
+
(
sign
?
1
:
0
);
}
size_t
width
()
const
{
return
size
();
}
size_t
width
()
const
{
return
size
();
}
template
<
typename
It
>
void
operator
()(
It
&&
it
)
{
template
<
typename
It
>
void
operator
()(
It
&&
it
)
{
if
(
sign
)
*
it
++
=
static_cast
<
char_type
>
(
sign
);
if
(
sign
)
*
it
++
=
static_cast
<
char_type
>
(
sign
);
it
=
internal
::
copy_str
<
char_type
>
(
buffer
.
begin
(),
buffer
.
end
(),
it
);
auto
begin
=
buffer
.
begin
();
if
(
decimal_point_pos
)
{
it
=
internal
::
copy_str
<
char_type
>
(
begin
,
decimal_point_pos
,
it
);
*
it
++
=
decimal_point
;
begin
=
decimal_point_pos
+
1
;
}
it
=
internal
::
copy_str
<
char_type
>
(
begin
,
buffer
.
end
(),
it
);
}
}
};
};
...
@@ -1595,7 +1603,8 @@ template <typename Range> class basic_writer {
...
@@ -1595,7 +1603,8 @@ template <typename Range> class basic_writer {
}
}
// Formats a floating-point number (double or long double).
// Formats a floating-point number (double or long double).
template
<
typename
T
>
void
write_double
(
T
value
,
const
format_specs
&
spec
);
template
<
typename
T
,
bool
USE_GRISU
=
fmt
::
internal
::
use_grisu
<
T
>()
>
void
write_double
(
T
value
,
const
format_specs
&
spec
);
/** Writes a character to the buffer. */
/** Writes a character to the buffer. */
void
write
(
char
value
)
{
void
write
(
char
value
)
{
...
@@ -2697,7 +2706,7 @@ struct float_spec_handler {
...
@@ -2697,7 +2706,7 @@ struct float_spec_handler {
};
};
template
<
typename
Range
>
template
<
typename
Range
>
template
<
typename
T
>
template
<
typename
T
,
bool
USE_GRISU
>
void
internal
::
basic_writer
<
Range
>::
write_double
(
T
value
,
void
internal
::
basic_writer
<
Range
>::
write_double
(
T
value
,
const
format_specs
&
spec
)
{
const
format_specs
&
spec
)
{
// Check type.
// Check type.
...
@@ -2728,12 +2737,14 @@ void internal::basic_writer<Range>::write_double(T value,
...
@@ -2728,12 +2737,14 @@ void internal::basic_writer<Range>::write_double(T value,
int
exp
=
0
;
int
exp
=
0
;
int
precision
=
spec
.
has_precision
()
||
!
spec
.
type
?
spec
.
precision
:
6
;
int
precision
=
spec
.
has_precision
()
||
!
spec
.
type
?
spec
.
precision
:
6
;
unsigned
options
=
handler
.
fixed
?
internal
::
grisu_options
::
fixed
:
0
;
unsigned
options
=
handler
.
fixed
?
internal
::
grisu_options
::
fixed
:
0
;
bool
use_grisu
=
fmt
::
internal
::
use_grisu
<
T
>
()
&&
bool
use_grisu
=
USE_GRISU
&&
(
spec
.
type
!=
'a'
&&
spec
.
type
!=
'A'
&&
spec
.
type
!=
'e'
&&
(
spec
.
type
!=
'a'
&&
spec
.
type
!=
'A'
&&
spec
.
type
!=
'e'
&&
spec
.
type
!=
'E'
)
&&
spec
.
type
!=
'E'
)
&&
internal
::
grisu_format
(
static_cast
<
double
>
(
value
),
buffer
,
internal
::
grisu_format
(
static_cast
<
double
>
(
value
),
buffer
,
precision
,
options
,
exp
);
precision
,
options
,
exp
);
if
(
!
use_grisu
)
internal
::
sprintf_format
(
value
,
buffer
,
spec
);
char
*
decimal_point_pos
=
nullptr
;
if
(
!
use_grisu
)
decimal_point_pos
=
internal
::
sprintf_format
(
value
,
buffer
,
spec
);
if
(
handler
.
as_percentage
)
{
if
(
handler
.
as_percentage
)
{
buffer
.
push_back
(
'%'
);
buffer
.
push_back
(
'%'
);
...
@@ -2762,8 +2773,8 @@ void internal::basic_writer<Range>::write_double(T value,
...
@@ -2762,8 +2773,8 @@ void internal::basic_writer<Range>::write_double(T value,
spec
.
has
(
HASH_FLAG
);
spec
.
has
(
HASH_FLAG
);
write_padded
(
as
,
grisu_writer
(
sign
,
buffer
,
exp
,
params
,
decimal_point
));
write_padded
(
as
,
grisu_writer
(
sign
,
buffer
,
exp
,
params
,
decimal_point
));
}
else
{
}
else
{
// TODO: set decimal point
write_padded
(
as
,
write_padded
(
as
,
double_writer
{
sign
,
buffer
});
double_writer
{
sign
,
buffer
,
decimal_point_pos
,
decimal_point
});
}
}
}
}
...
...
src/format.cc
View file @
1d3e3d8c
...
@@ -35,11 +35,11 @@ template FMT_API std::string internal::vformat<char>(
...
@@ -35,11 +35,11 @@ template FMT_API std::string internal::vformat<char>(
template
FMT_API
format_context
::
iterator
internal
::
vformat_to
(
template
FMT_API
format_context
::
iterator
internal
::
vformat_to
(
internal
::
buffer
<
char
>
&
,
string_view
,
basic_format_args
<
format_context
>);
internal
::
buffer
<
char
>
&
,
string_view
,
basic_format_args
<
format_context
>);
template
FMT_API
void
internal
::
sprintf_format
(
double
,
internal
::
buffer
<
char
>
&
,
template
FMT_API
char
*
internal
::
sprintf_format
(
double
,
internal
::
buffer
<
char
>
&
,
core_format_specs
);
core_format_specs
);
template
FMT_API
void
internal
::
sprintf_format
(
long
double
,
template
FMT_API
char
*
internal
::
sprintf_format
(
long
double
,
internal
::
buffer
<
char
>
&
,
internal
::
buffer
<
char
>
&
,
core_format_specs
);
core_format_specs
);
// Explicit instantiations for wchar_t.
// Explicit instantiations for wchar_t.
...
...
test/locale-test.cc
View file @
1d3e3d8c
...
@@ -18,6 +18,13 @@ template <typename Char> struct numpunct : std::numpunct<Char> {
...
@@ -18,6 +18,13 @@ template <typename Char> struct numpunct : std::numpunct<Char> {
TEST
(
LocaleTest
,
DoubleDecimalPoint
)
{
TEST
(
LocaleTest
,
DoubleDecimalPoint
)
{
std
::
locale
loc
(
std
::
locale
(),
new
numpunct
<
char
>
());
std
::
locale
loc
(
std
::
locale
(),
new
numpunct
<
char
>
());
EXPECT_EQ
(
"1?23"
,
fmt
::
format
(
loc
,
"{:n}"
,
1.23
));
EXPECT_EQ
(
"1?23"
,
fmt
::
format
(
loc
,
"{:n}"
,
1.23
));
// Test with Grisu disabled.
fmt
::
memory_buffer
buf
;
fmt
::
internal
::
writer
w
(
buf
,
fmt
::
internal
::
locale_ref
(
loc
));
auto
specs
=
fmt
::
format_specs
();
specs
.
type
=
'n'
;
w
.
write_double
<
double
,
false
>
(
1.23
,
specs
);
EXPECT_EQ
(
fmt
::
to_string
(
buf
),
"1?23"
);
}
}
TEST
(
LocaleTest
,
Format
)
{
TEST
(
LocaleTest
,
Format
)
{
...
...
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