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
2fd8f9ec
Commit
2fd8f9ec
authored
Sep 02, 2019
by
Victor Zverovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Initial implementation of optimal compile-time formatter generation
parent
fe642d76
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
136 additions
and
0 deletions
+136
-0
include/fmt/compile.h
include/fmt/compile.h
+134
-0
include/fmt/core.h
include/fmt/core.h
+2
-0
No files found.
include/fmt/compile.h
View file @
2fd8f9ec
...
...
@@ -321,6 +321,140 @@ class compiled_format : private compiled_format_base<S> {
explicit
constexpr
compiled_format
(
basic_string_view
<
char_type
>
format_str
)
:
compiled_format_base
<
S
>
(
format_str
),
format_str_
(
format_str
)
{}
};
#ifdef __cpp_if_constexpr
template
<
typename
...
Args
>
struct
type_list
{};
// Returns a reference to the argument at index N from [first, rest...].
template
<
int
N
,
typename
T
,
typename
...
Args
>
const
auto
&
get
(
const
T
&
first
,
const
Args
&
...
rest
)
{
if
constexpr
(
sizeof
...(
Args
)
==
0
)
return
first
;
else
return
get
(
rest
...);
}
template
<
int
N
,
typename
>
struct
get_type_impl
;
template
<
int
N
,
typename
...
Args
>
struct
get_type_impl
<
N
,
type_list
<
Args
...
>>
{
using
type
=
remove_cvref_t
<
decltype
(
get
<
N
>
(
std
::
declval
<
Args
>
()...))
>
;
};
template
<
int
N
,
typename
T
>
using
get_type
=
typename
get_type_impl
<
N
,
T
>::
type
;
template
<
typename
Char
>
struct
text
{
basic_string_view
<
Char
>
data
;
template
<
typename
OutputIt
,
typename
...
Args
>
OutputIt
format
(
OutputIt
out
,
const
Args
&
...)
{
// TODO: reserve
return
copy_str
<
Char
>
(
data
.
begin
(),
data
.
end
(),
out
);
}
};
template
<
typename
Char
>
constexpr
text
<
Char
>
make_text
(
basic_string_view
<
Char
>
s
,
size_t
pos
,
size_t
size
)
{
return
{{
&
s
[
pos
],
size
}};
}
template
<
typename
Char
,
typename
OutputIt
,
typename
T
,
std
::
enable_if_t
<
std
::
is_integral_v
<
T
>,
int
>
=
0
>
OutputIt
format_default
(
OutputIt
out
,
T
value
)
{
// TODO: reserve
format_int
fi
(
value
);
return
std
::
copy
(
fi
.
data
(),
fi
.
data
()
+
fi
.
size
(),
out
);
}
template
<
typename
Char
,
typename
OutputIt
>
OutputIt
format_default
(
OutputIt
out
,
Char
value
)
{
*
out
++
=
value
;
return
out
;
}
template
<
typename
Char
,
typename
OutputIt
>
OutputIt
format_default
(
OutputIt
out
,
const
Char
*
value
)
{
auto
length
=
std
::
char_traits
<
Char
>::
length
(
value
);
return
copy_str
<
Char
>
(
value
,
value
+
length
,
out
);
}
// A replacement field that refers to argument N.
template
<
typename
Char
,
typename
T
,
int
N
>
struct
field
{
template
<
typename
OutputIt
,
typename
...
Args
>
OutputIt
format
(
OutputIt
out
,
const
Args
&
...
args
)
{
// This ensures that the argument type is convertile to `const T&`.
const
T
&
arg
=
get
<
N
>
(
args
...);
return
format_default
<
Char
>
(
out
,
arg
);
}
};
template
<
typename
L
,
typename
R
>
struct
concat
{
L
lhs
;
R
rhs
;
template
<
typename
OutputIt
,
typename
...
Args
>
OutputIt
format
(
OutputIt
out
,
const
Args
&
...
args
)
{
out
=
lhs
.
format
(
out
,
args
...);
return
rhs
.
format
(
out
,
args
...);
}
};
template
<
typename
L
,
typename
R
>
constexpr
concat
<
L
,
R
>
make_concat
(
L
lhs
,
R
rhs
)
{
return
{
lhs
,
rhs
};
}
template
<
typename
Char
>
constexpr
size_t
parse_text
(
basic_string_view
<
Char
>
str
,
size_t
pos
)
{
for
(
size_t
size
=
str
.
size
();
pos
!=
size
;
++
pos
)
{
if
(
str
[
pos
]
==
'{'
||
str
[
pos
]
==
'}'
)
break
;
}
return
pos
;
}
template
<
typename
Args
,
size_t
POS
,
int
ID
,
typename
S
>
constexpr
auto
compile_format_string
(
S
format_str
);
template
<
typename
Args
,
size_t
POS
,
int
ID
,
typename
T
,
typename
S
>
auto
parse_tail
(
T
head
,
S
format_str
)
{
if
constexpr
(
POS
!=
to_string_view
(
format_str
).
size
())
return
make_concat
(
head
,
compile_format_string
<
Args
,
POS
,
ID
>
(
format_str
));
else
return
head
;
}
template
<
typename
Args
,
size_t
POS
,
int
ID
,
typename
S
>
constexpr
auto
compile_format_string
(
S
format_str
)
{
using
char_type
=
char_t
<
S
>
;
constexpr
basic_string_view
<
char_type
>
str
=
format_str
;
if
constexpr
(
str
.
size
()
==
0
)
{
return
make_text
(
str
,
0
,
0
);
}
else
if
constexpr
(
str
[
POS
]
==
'{'
)
{
if
(
POS
+
1
==
str
.
size
())
throw
format_error
(
"unmatched '{' in format string"
);
if
constexpr
(
str
[
POS
+
1
]
==
'{'
)
{
return
parse_tail
<
Args
,
POS
+
2
,
ID
>
(
make_text
(
str
,
POS
,
1
),
format_str
);
}
else
if
constexpr
(
str
[
POS
+
1
]
==
'}'
)
{
return
parse_tail
<
Args
,
POS
+
2
,
ID
+
1
>
(
field
<
char_type
,
get_type
<
ID
,
Args
>
,
ID
>
(),
format_str
);
}
else
{
throw
format_error
(
"invalid format string"
);
}
}
else
if
constexpr
(
str
[
POS
]
==
'}'
)
{
if
(
POS
+
1
==
str
.
size
())
throw
format_error
(
"unmatched '}' in format string"
);
return
parse_tail
<
Args
,
POS
+
2
,
ID
>
(
make_text
(
str
,
POS
,
1
),
format_str
);
}
else
{
constexpr
auto
end
=
parse_text
(
str
,
POS
+
1
);
return
parse_tail
<
Args
,
end
,
ID
>
(
make_text
(
str
,
POS
,
end
-
POS
),
format_str
);
}
}
template
<
typename
...
Args
,
typename
S
>
constexpr
auto
compile
(
S
format_str
)
{
return
compile_format_string
<
type_list
<
Args
...
>
,
0
,
0
>
(
format_str
);
}
#endif // __cpp_if_constexpr
}
// namespace internal
#if FMT_USE_CONSTEXPR
...
...
include/fmt/core.h
View file @
2fd8f9ec
...
...
@@ -295,6 +295,8 @@ template <typename Char> class basic_string_view {
FMT_CONSTEXPR
iterator
begin
()
const
{
return
data_
;
}
FMT_CONSTEXPR
iterator
end
()
const
{
return
data_
+
size_
;
}
FMT_CONSTEXPR
const
Char
&
operator
[](
size_t
pos
)
const
{
return
data_
[
pos
];
}
FMT_CONSTEXPR
void
remove_prefix
(
size_t
n
)
{
data_
+=
n
;
size_
-=
n
;
...
...
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