15 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
16 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
18 #include "absl/base/attributes.h"
19 #include "absl/strings/internal/str_format/arg.h"
20 #include "absl/strings/internal/str_format/extension.h"
24 #ifndef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
28 #if ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__) && \
29 !defined(__INTELLISENSE__)
30 #define ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 1
31 #endif // ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__) &&
33 #endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
39 constexpr
bool AllOf() {
return true; }
41 template <
typename...
T>
46 #ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
48 constexpr
bool ContainsChar(
const char* chars,
char c) {
49 return *chars == c || (*chars && ContainsChar(chars + 1, c));
64 constexpr ConvList without_front()
const {
69 template <
size_t count>
85 return ContainsChar(chars, GetChar(
format, 0))
86 ? ConsumeAnyOf(ConsumeFront(
format), chars)
90 constexpr
bool IsDigit(
char c) {
return c >=
'0' &&
c <=
'9'; }
100 constexpr Integer ConsumePositionalDollar()
const {
108 ? ParseDigits(ConsumeFront(
format),
116 return ParseDigits(
format).ConsumePositionalDollar();
126 constexpr ConvParser SetArgs(ConvList
args)
const {
127 return ConvParser(format_,
args,
error_, arg_position_, is_positional_);
130 constexpr ConvParser SetError(
bool error)
const {
135 constexpr ConvParser SetArgPosition(
int arg_position)
const {
136 return ConvParser(format_,
args_,
error_, arg_position, is_positional_);
141 constexpr ConvParser ConsumeNextArg(
char conv)
const {
148 constexpr ConvParser VerifyPositional(Integer i,
char conv)
const {
153 constexpr ConvParser ParseArgPosition(Integer
arg)
const {
154 return SetFormat(
arg.format).SetArgPosition(
arg.
value);
158 constexpr ConvParser ParseFlags()
const {
159 return SetFormat(ConsumeAnyOf(format_,
"-+ #0"));
165 constexpr ConvParser ParseWidth()
const {
166 return IsDigit(GetChar(format_, 0))
167 ? SetFormat(ParseDigits(format_).
format)
168 : GetChar(format_, 0) ==
'*'
171 ParsePositional(ConsumeFront(format_)),
'*')
172 : SetFormat(ConsumeFront(format_))
180 constexpr ConvParser ParsePrecision()
const {
181 return GetChar(format_, 0) !=
'.'
183 : GetChar(format_, 1) ==
'*'
186 ParsePositional(ConsumeFront(format_, 2)),
'*')
187 : SetFormat(ConsumeFront(format_, 2))
189 : SetFormat(ParseDigits(ConsumeFront(format_)).
format);
193 constexpr ConvParser ParseLength()
const {
194 return SetFormat(ConsumeAnyOf(format_,
"lLhjztq"));
199 constexpr ConvParser ParseConversion()
const {
200 return is_positional_
201 ? VerifyPositional({ConsumeFront(format_), arg_position_},
203 : ConsumeNextArg(GetChar(format_, 0))
204 .SetFormat(ConsumeFront(format_));
208 int arg_position,
bool is_positional)
212 arg_position_(arg_position),
213 is_positional_(is_positional) {}
221 is_positional_(is_positional) {}
226 constexpr ConvParser
Run()
const {
227 return (is_positional_ ? ParseArgPosition(ParsePositional(format_)) : *
this)
236 constexpr ConvList
args()
const {
return args_; }
238 constexpr
bool is_positional()
const {
return is_positional_; }
259 (GetChar(
format, 0) ==
'%' && GetChar(
format, 1) !=
'%');
267 return FoundPercent(
format) || !limit
269 : ConsumeNonPercentInner(
280 return FoundPercent(
format)
282 : ConsumeNonPercent(ConsumeNonPercentInner(
format));
287 : GetChar(
format, 0) ==
'$';
290 constexpr
bool RunImpl(
bool is_positional)
const {
294 return (format_.empty() && (is_positional ||
args_.count == 0)) ||
297 ConvParser(ConsumeFront(format_),
args_, is_positional).
Run()));
300 constexpr
bool ValidateArg(ConvParser
conv)
const {
301 return !
conv.error() && FormatParser(
conv.format(),
conv.args())
302 .RunImpl(
conv.is_positional());
313 constexpr
bool Run()
const {
314 return RunImpl(!format_.empty() && IsPositional(ConsumeFront(format_)));
327 return FormatParser(
format,
328 {ConvListT<
sizeof...(C)>{{
C...}}.list,
sizeof...(C)})
332 #endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
338 #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_