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
f8027414
Commit
f8027414
authored
Sep 30, 2018
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Impelement char8_t support
parent
76a47d41
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
107 additions
and
77 deletions
+107
-77
include/fmt/format-inl.h
include/fmt/format-inl.h
+16
-11
include/fmt/format.h
include/fmt/format.h
+91
-66
No files found.
include/fmt/format-inl.h
View file @
f8027414
...
...
@@ -192,6 +192,16 @@ void report_error(FormatFunc func, int error_code,
}
}
// namespace
FMT_FUNC
size_t
internal
::
count_code_points
(
u8string_view
s
)
{
const
char8_t
*
data
=
s
.
data
();
size_t
num_code_points
=
0
;
for
(
size_t
i
=
0
,
size
=
s
.
size
();
i
!=
size
;
++
i
)
{
if
((
data
[
i
]
&
0xc0
)
!=
0x80
)
++
num_code_points
;
}
return
num_code_points
;
}
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
class
locale
{
private:
...
...
@@ -202,21 +212,16 @@ class locale {
std
::
locale
get
()
{
return
locale_
;
}
};
FMT_FUNC
size_t
internal
::
count_code_points
(
u8string_view
s
)
{
const
char8_t
*
data
=
s
.
data
();
int
num_code_points
=
0
;
for
(
size_t
i
=
0
,
size
=
s
.
size
();
i
!=
size
;
++
i
)
{
if
((
data
[
i
]
&
0xc0
)
!=
0x80
)
++
num_code_points
;
}
return
num_code_points
;
}
namespace
internal
{
template
<
typename
Char
>
FMT_FUNC
Char
internal
::
thousands_sep
(
locale_provider
*
lp
)
{
FMT_FUNC
Char
thousands_sep
(
locale_provider
*
lp
)
{
std
::
locale
loc
=
lp
?
lp
->
locale
().
get
()
:
std
::
locale
();
return
std
::
use_facet
<
std
::
numpunct
<
Char
>>
(
loc
).
thousands_sep
();
}
template
<
>
FMT_FUNC
char8_t
thousands_sep
<
char8_t
>
(
locale_provider
*
)
{
return
static_cast
<
char8_t
>
(
','
);
}
}
#else
template
<
typename
Char
>
FMT_FUNC
Char
internal
::
thousands_sep
(
locale_provider
*
lp
)
{
...
...
include/fmt/format.h
View file @
f8027414
...
...
@@ -713,7 +713,7 @@ class null_terminating_iterator {
}
FMT_CONSTEXPR
Char
operator
*
()
const
{
return
ptr_
!=
end_
?
*
ptr_
:
0
;
return
ptr_
!=
end_
?
*
ptr_
:
Char
()
;
}
FMT_CONSTEXPR
null_terminating_iterator
operator
++
()
{
...
...
@@ -1058,19 +1058,19 @@ inline Char *format_decimal(Char *buffer, UInt value, unsigned num_digits,
// "Three Optimization Tips for C++". See speed-test for a comparison.
unsigned
index
=
static_cast
<
unsigned
>
((
value
%
100
)
*
2
);
value
/=
100
;
*--
buffer
=
data
::
DIGITS
[
index
+
1
]
;
*--
buffer
=
static_cast
<
Char
>
(
data
::
DIGITS
[
index
+
1
])
;
thousands_sep
(
buffer
);
*--
buffer
=
data
::
DIGITS
[
index
]
;
*--
buffer
=
static_cast
<
Char
>
(
data
::
DIGITS
[
index
])
;
thousands_sep
(
buffer
);
}
if
(
value
<
10
)
{
*--
buffer
=
static_cast
<
c
har
>
(
'0'
+
value
);
*--
buffer
=
static_cast
<
C
har
>
(
'0'
+
value
);
return
end
;
}
unsigned
index
=
static_cast
<
unsigned
>
(
value
*
2
);
*--
buffer
=
data
::
DIGITS
[
index
+
1
]
;
*--
buffer
=
static_cast
<
Char
>
(
data
::
DIGITS
[
index
+
1
])
;
thousands_sep
(
buffer
);
*--
buffer
=
data
::
DIGITS
[
index
]
;
*--
buffer
=
static_cast
<
Char
>
(
data
::
DIGITS
[
index
])
;
return
end
;
}
...
...
@@ -1097,7 +1097,7 @@ inline Char *format_uint(Char *buffer, UInt value, unsigned num_digits,
do
{
const
char
*
digits
=
upper
?
"0123456789ABCDEF"
:
"0123456789abcdef"
;
unsigned
digit
=
(
value
&
((
1
<<
BASE_BITS
)
-
1
));
*--
buffer
=
BASE_BITS
<
4
?
static_cast
<
char
>
(
'0'
+
digit
)
:
digits
[
digit
]
;
*--
buffer
=
static_cast
<
Char
>
(
BASE_BITS
<
4
?
'0'
+
digit
:
digits
[
digit
])
;
}
while
((
value
>>=
BASE_BITS
)
!=
0
);
return
end
;
}
...
...
@@ -1225,7 +1225,7 @@ class basic_format_specs : public align_spec {
public:
unsigned
flags_
;
int
precision_
;
C
har
type_
;
c
har
type_
;
FMT_CONSTEXPR
basic_format_specs
(
unsigned
width
=
0
,
char
type
=
0
,
wchar_t
fill
=
' '
)
...
...
@@ -1233,7 +1233,7 @@ class basic_format_specs : public align_spec {
FMT_CONSTEXPR
bool
flag
(
unsigned
f
)
const
{
return
(
flags_
&
f
)
!=
0
;
}
FMT_CONSTEXPR
int
precision
()
const
{
return
precision_
;
}
FMT_CONSTEXPR
C
har
type
()
const
{
return
type_
;
}
FMT_CONSTEXPR
c
har
type
()
const
{
return
type_
;
}
};
typedef
basic_format_specs
<
char
>
format_specs
;
...
...
@@ -1253,8 +1253,8 @@ struct format_string_traits<
S
,
typename
std
::
enable_if
<
std
::
is_base_of
<
compile_string
,
S
>::
value
>::
type
>:
format_string_traits_base
<
char
>
{};
template
<
typename
Char
,
typename
Handler
>
FMT_CONSTEXPR
void
handle_int_type_spec
(
C
har
spec
,
Handler
&&
handler
)
{
template
<
typename
Handler
>
FMT_CONSTEXPR
void
handle_int_type_spec
(
c
har
spec
,
Handler
&&
handler
)
{
switch
(
spec
)
{
case
0
:
case
'd'
:
handler
.
on_dec
();
...
...
@@ -1276,8 +1276,8 @@ FMT_CONSTEXPR void handle_int_type_spec(Char spec, Handler &&handler) {
}
}
template
<
typename
Char
,
typename
Handler
>
FMT_CONSTEXPR
void
handle_float_type_spec
(
C
har
spec
,
Handler
&&
handler
)
{
template
<
typename
Handler
>
FMT_CONSTEXPR
void
handle_float_type_spec
(
c
har
spec
,
Handler
&&
handler
)
{
switch
(
spec
)
{
case
0
:
case
'g'
:
case
'G'
:
handler
.
on_general
();
...
...
@@ -1361,13 +1361,13 @@ class float_type_checker : private ErrorHandler {
}
};
template
<
typename
ErrorHandler
,
typename
CharType
>
template
<
typename
ErrorHandler
>
class
char_specs_checker
:
public
ErrorHandler
{
private:
CharType
type_
;
char
type_
;
public:
FMT_CONSTEXPR
char_specs_checker
(
CharType
type
,
ErrorHandler
eh
)
FMT_CONSTEXPR
char_specs_checker
(
char
type
,
ErrorHandler
eh
)
:
ErrorHandler
(
eh
),
type_
(
type
)
{}
FMT_CONSTEXPR
void
on_int
()
{
...
...
@@ -1478,8 +1478,9 @@ class arg_formatter_base {
}
template
<
typename
T
>
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
iterator
>::
type
operator
()(
T
value
)
{
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
||
std
::
is_same
<
T
,
char_type
>::
value
,
iterator
>::
type
operator
()(
T
value
)
{
// MSVC2013 fails to compile separate overloads for bool and char_type so
// use std::is_same instead.
if
(
std
::
is_same
<
T
,
bool
>::
value
)
{
...
...
@@ -1692,7 +1693,7 @@ class specs_setter {
explicit
FMT_CONSTEXPR
specs_setter
(
basic_format_specs
<
Char
>
&
specs
)
:
specs_
(
specs
)
{}
FMT_CONSTEXPR
specs_setter
(
const
specs_setter
&
other
)
:
specs_
(
other
.
specs_
)
{}
FMT_CONSTEXPR
specs_setter
(
const
specs_setter
&
other
)
:
specs_
(
other
.
specs_
)
{}
FMT_CONSTEXPR
void
on_align
(
alignment
align
)
{
specs_
.
align_
=
align
;
}
FMT_CONSTEXPR
void
on_fill
(
Char
fill
)
{
specs_
.
fill_
=
fill
;
}
...
...
@@ -1712,7 +1713,9 @@ class specs_setter {
}
FMT_CONSTEXPR
void
end_precision
()
{}
FMT_CONSTEXPR
void
on_type
(
Char
type
)
{
specs_
.
type_
=
type
;
}
FMT_CONSTEXPR
void
on_type
(
Char
type
)
{
specs_
.
type_
=
static_cast
<
char
>
(
type
);
}
protected:
basic_format_specs
<
Char
>
&
specs_
;
...
...
@@ -2019,7 +2022,7 @@ FMT_CONSTEXPR Iterator parse_format_specs(Iterator it, SpecHandler &&handler) {
int
i
=
1
;
do
{
auto
p
=
it
+
i
;
switch
(
*
p
)
{
switch
(
static_cast
<
char
>
(
*
p
)
)
{
case
'<'
:
align
=
ALIGN_LEFT
;
break
;
...
...
@@ -2048,7 +2051,7 @@ FMT_CONSTEXPR Iterator parse_format_specs(Iterator it, SpecHandler &&handler) {
}
while
(
--
i
>=
0
);
// Parse sign.
switch
(
*
it
)
{
switch
(
static_cast
<
char
>
(
*
it
)
)
{
case
'+'
:
handler
.
on_plus
();
++
it
;
...
...
@@ -2178,7 +2181,7 @@ FMT_CONSTEXPR void parse_format_string(
handler
.
on_text
(
p
,
p
+
1
);
}
else
{
p
=
parse_arg_id
(
p
,
end
,
id_adapter
<
Handler
,
Char
>
{
handler
});
Char
c
=
p
!=
end
?
*
p
:
0
;
Char
c
=
p
!=
end
?
*
p
:
Char
()
;
if
(
c
==
'}'
)
{
handler
.
on_replacement_field
(
p
);
}
else
if
(
c
==
':'
)
{
...
...
@@ -2297,6 +2300,28 @@ void handle_dynamic_spec(
break
;
}
}
inline
char8_t
to_char8_t
(
char
c
)
{
return
static_cast
<
char8_t
>
(
c
);
}
template
<
typename
InputIt
,
typename
OutChar
>
struct
needs_conversion
:
std
::
integral_constant
<
bool
,
std
::
is_same
<
typename
std
::
iterator_traits
<
InputIt
>::
value_type
,
char
>::
value
&&
std
::
is_same
<
OutChar
,
char8_t
>::
value
>
{};
template
<
typename
OutChar
,
typename
InputIt
,
typename
OutputIt
>
typename
std
::
enable_if
<
!
needs_conversion
<
InputIt
,
OutChar
>::
value
,
OutputIt
>::
type
copy_str
(
InputIt
begin
,
InputIt
end
,
OutputIt
it
)
{
return
std
::
copy
(
begin
,
end
,
it
);
}
template
<
typename
OutChar
,
typename
InputIt
,
typename
OutputIt
>
typename
std
::
enable_if
<
needs_conversion
<
InputIt
,
OutChar
>::
value
,
OutputIt
>::
type
copy_str
(
InputIt
begin
,
InputIt
end
,
OutputIt
it
)
{
return
std
::
transform
(
begin
,
end
,
it
,
to_char8_t
);
}
}
// namespace internal
/** The default argument formatter. */
...
...
@@ -2439,7 +2464,7 @@ class basic_writer {
template
<
typename
It
>
void
operator
()(
It
&&
it
)
const
{
if
(
prefix
.
size
()
!=
0
)
it
=
std
::
copy_n
(
prefix
.
data
(),
prefix
.
size
(),
it
);
it
=
internal
::
copy_str
<
char_type
>
(
prefix
.
begin
(),
prefix
.
end
(),
it
);
it
=
std
::
fill_n
(
it
,
padding
,
fill
);
f
(
it
);
}
...
...
@@ -2462,7 +2487,7 @@ class basic_writer {
}
else
if
(
spec
.
precision
()
>
static_cast
<
int
>
(
num_digits
))
{
size
=
prefix
.
size
()
+
static_cast
<
std
::
size_t
>
(
spec
.
precision
());
padding
=
static_cast
<
std
::
size_t
>
(
spec
.
precision
())
-
num_digits
;
fill
=
'0'
;
fill
=
static_cast
<
char_type
>
(
'0'
)
;
}
align_spec
as
=
spec
;
if
(
spec
.
align
()
==
ALIGN_DEFAULT
)
...
...
@@ -2481,7 +2506,7 @@ class basic_writer {
unsigned
num_digits
=
internal
::
count_digits
(
abs_value
);
auto
&&
it
=
reserve
((
is_negative
?
1
:
0
)
+
num_digits
);
if
(
is_negative
)
*
it
++
=
'-'
;
*
it
++
=
static_cast
<
char_type
>
(
'-'
)
;
it
=
internal
::
format_decimal
(
it
,
abs_value
,
num_digits
);
}
...
...
@@ -2636,8 +2661,9 @@ class basic_writer {
template
<
typename
It
>
void
operator
()(
It
&&
it
)
const
{
if
(
sign
)
*
it
++
=
sign
;
it
=
std
::
copy_n
(
str
,
static_cast
<
std
::
size_t
>
(
INF_SIZE
),
it
);
*
it
++
=
static_cast
<
char_type
>
(
sign
);
it
=
internal
::
copy_str
<
char_type
>
(
str
,
str
+
static_cast
<
std
::
size_t
>
(
INF_SIZE
),
it
);
}
};
...
...
@@ -2649,7 +2675,7 @@ class basic_writer {
template
<
typename
It
>
void
operator
()(
It
&&
it
)
{
if
(
sign
)
{
*
it
++
=
s
ign
;
*
it
++
=
s
tatic_cast
<
char_type
>
(
sign
)
;
--
n
;
}
it
=
std
::
copy_n
(
buffer
.
begin
(),
n
,
it
);
...
...
@@ -2670,7 +2696,7 @@ class basic_writer {
template
<
typename
It
>
void
operator
()(
It
&&
it
)
const
{
it
=
std
::
copy_n
(
s
,
size
,
it
);
it
=
internal
::
copy_str
<
char_type
>
(
s
,
s
+
size
,
it
);
}
};
...
...
@@ -2750,7 +2776,7 @@ class basic_writer {
*/
void
write
(
string_view
value
)
{
auto
&&
it
=
reserve
(
value
.
size
());
it
=
std
::
copy
(
value
.
begin
(),
value
.
end
(),
it
);
it
=
internal
::
copy_str
<
char_type
>
(
value
.
begin
(),
value
.
end
(),
it
);
}
void
write
(
wstring_view
value
)
{
static_assert
(
std
::
is_same
<
char_type
,
wchar_t
>::
value
,
""
);
...
...
@@ -2809,12 +2835,11 @@ void basic_writer<Range>::write_str(
write_str
(
data
,
size
,
spec
);
}
template
<
typename
Char
>
struct
float_spec_handler
{
C
har
type
;
c
har
type
;
bool
upper
;
explicit
float_spec_handler
(
C
har
t
)
:
type
(
t
),
upper
(
false
)
{}
explicit
float_spec_handler
(
c
har
t
)
:
type
(
t
),
upper
(
false
)
{}
void
on_general
()
{
if
(
type
==
'G'
)
...
...
@@ -2852,8 +2877,8 @@ template <typename Range>
template
<
typename
T
>
void
basic_writer
<
Range
>::
write_double
(
T
value
,
const
format_specs
&
spec
)
{
// Check type.
float_spec_handler
<
char_type
>
handler
(
spec
.
type
(
));
internal
::
handle_float_type_spec
(
spec
.
type
()
,
handler
);
float_spec_handler
handler
(
static_cast
<
char
>
(
spec
.
type
()
));
internal
::
handle_float_type_spec
(
handler
.
type
,
handler
);
char
sign
=
0
;
// Use isnegative instead of value < 0 because the latter is always
...
...
@@ -2903,7 +2928,7 @@ void basic_writer<Range>::write_double(T value, const format_specs &spec) {
if
(
spec
.
align
()
==
ALIGN_NUMERIC
)
{
if
(
sign
)
{
auto
&&
it
=
reserve
(
1
);
*
it
++
=
s
ign
;
*
it
++
=
s
tatic_cast
<
char_type
>
(
sign
)
;
sign
=
0
;
if
(
as
.
width_
)
--
as
.
width_
;
...
...
@@ -3157,8 +3182,7 @@ struct formatter<
case
internal
:
:
char_type
:
handle_char_specs
(
&
specs_
,
internal
::
char_specs_checker
<
decltype
(
eh
),
decltype
(
type_spec
)
>
(
type_spec
,
eh
));
internal
::
char_specs_checker
<
decltype
(
eh
)
>
(
type_spec
,
eh
));
break
;
case
internal
:
:
double_type
:
case
internal
:
:
long_double_type
:
...
...
@@ -3464,9 +3488,10 @@ inline typename buffer_context<Char>::type::iterator format_to(
basic_memory_buffer
<
Char
,
SIZE
>
&
buf
,
const
String
&
format_str
,
const
Args
&
...
args
)
{
internal
::
check_format_string
<
Args
...
>
(
format_str
);
return
vformat_to
(
buf
,
basic_string_view
<
Char
>
(
format_str
),
make_format_args
<
typename
buffer_context
<
Char
>::
type
>
(
args
...));
typedef
typename
buffer_context
<
Char
>::
type
context
;
format_arg_store
<
context
,
Args
...
>
as
{
args
...};
return
vformat_to
(
buf
,
basic_string_view
<
Char
>
(
format_str
),
basic_format_args
<
context
>
(
as
));
}
template
<
typename
OutputIt
,
typename
Char
=
char
>
...
...
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