1 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_ 2 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_ 9 #ifndef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 10 #if defined(__clang__) && !defined(__native_client__) 11 #if __has_attribute(enable_if) 12 #define ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 1 13 #endif // __has_attribute(enable_if) 14 #endif // defined(__clang__) && !defined(__native_client__) 15 #endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 20 constexpr
bool AllOf() {
return true; }
22 template <
typename... T>
23 constexpr
bool AllOf(
bool b, T... t) {
24 return b &&
AllOf(t...);
27 template <
typename Arg>
30 std::declval<const Arg&>(), std::declval<const ConversionSpec&>(),
31 std::declval<FormatSinkImpl*>()))::kConv;
34 #if ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 36 constexpr
bool ContainsChar(
const char* chars,
char c) {
37 return *chars == c || (*chars && ContainsChar(chars + 1, c));
48 constexpr
Conv operator[](
int i)
const {
49 return i < count ? array[
i] :
Conv{};
52 constexpr ConvList without_front()
const {
53 return count != 0 ? ConvList{array + 1, count - 1} : *
this;
57 template <
size_t count>
60 Conv list[count ? count : 1];
63 constexpr
char GetChar(
string_view str,
size_t index) {
64 return index < str.
size() ? str[index] :
char{};
73 return ContainsChar(chars, GetChar(format, 0))
74 ? ConsumeAnyOf(ConsumeFront(format), chars)
78 constexpr
bool IsDigit(
char c) {
return c >=
'0' && c <=
'9'; }
88 constexpr Integer ConsumePositionalDollar()
const {
89 return GetChar(format, 0) ==
'$' ? Integer{ConsumeFront(format), value}
95 return IsDigit(GetChar(format, 0))
96 ? ParseDigits(ConsumeFront(format),
97 10 *
value + GetChar(format, 0) -
'0')
103 constexpr Integer ParsePositional(
string_view format) {
104 return ParseDigits(format).ConsumePositionalDollar();
110 constexpr ConvParser SetFormat(
string_view format)
const {
111 return ConvParser(format,
args_, error_, arg_position_, is_positional_);
114 constexpr ConvParser SetArgs(ConvList args)
const {
115 return ConvParser(format_, args, error_, arg_position_, is_positional_);
118 constexpr ConvParser SetError(
bool error)
const {
119 return ConvParser(format_,
args_, error_ || error, arg_position_,
123 constexpr ConvParser SetArgPosition(
int arg_position)
const {
124 return ConvParser(format_,
args_, error_, arg_position, is_positional_);
129 constexpr ConvParser ConsumeNextArg(
char conv)
const {
136 constexpr ConvParser VerifyPositional(Integer
i,
char conv)
const {
137 return SetFormat(i.format).SetError(!
Contains(
args_[i.value - 1], conv));
141 constexpr ConvParser ParseArgPosition(Integer
arg)
const {
142 return SetFormat(arg.format).SetArgPosition(arg.value);
146 constexpr ConvParser ParseFlags()
const {
147 return SetFormat(ConsumeAnyOf(format_,
"-+ #0"));
153 constexpr ConvParser ParseWidth()
const {
154 return IsDigit(GetChar(format_, 0))
155 ? SetFormat(ParseDigits(format_).format)
156 : GetChar(format_, 0) ==
'*' 159 ParsePositional(ConsumeFront(format_)),
'*')
160 : SetFormat(ConsumeFront(format_))
168 constexpr ConvParser ParsePrecision()
const {
169 return GetChar(format_, 0) !=
'.' 171 : GetChar(format_, 1) ==
'*' 174 ParsePositional(ConsumeFront(format_, 2)),
'*')
175 : SetFormat(ConsumeFront(format_, 2))
177 : SetFormat(ParseDigits(ConsumeFront(format_)).format);
181 constexpr ConvParser ParseLength()
const {
182 return SetFormat(ConsumeAnyOf(format_,
"lLhjztq"));
187 constexpr ConvParser ParseConversion()
const {
188 return is_positional_
189 ? VerifyPositional({ConsumeFront(format_), arg_position_},
191 : ConsumeNextArg(GetChar(format_, 0))
192 .SetFormat(ConsumeFront(format_));
195 constexpr ConvParser(
string_view format, ConvList args,
bool error,
196 int arg_position,
bool is_positional)
200 arg_position_(arg_position),
201 is_positional_(is_positional) {}
204 constexpr ConvParser(
string_view format, ConvList args,
bool is_positional)
209 is_positional_(is_positional) {}
214 constexpr ConvParser Run()
const {
215 return (is_positional_ ? ParseArgPosition(ParsePositional(format_)) : *
this)
224 constexpr ConvList args()
const {
return args_; }
225 constexpr
bool error()
const {
return error_; }
226 constexpr
bool is_positional()
const {
return is_positional_; }
245 static constexpr
bool FoundPercent(
string_view format) {
246 return format.
empty() ||
247 (GetChar(format, 0) ==
'%' && GetChar(format, 1) !=
'%');
255 return FoundPercent(format) || !limit
257 : ConsumeNonPercentInner(
258 ConsumeFront(format, GetChar(format, 0) ==
'%' &&
259 GetChar(format, 1) ==
'%' 268 return FoundPercent(format)
270 : ConsumeNonPercent(ConsumeNonPercentInner(format));
273 static constexpr
bool IsPositional(
string_view format) {
274 return IsDigit(GetChar(format, 0)) ? IsPositional(ConsumeFront(format))
275 : GetChar(format, 0) ==
'$';
278 constexpr
bool RunImpl(
bool is_positional)
const {
282 return (format_.empty() && (is_positional ||
args_.count == 0)) ||
285 ConvParser(ConsumeFront(format_),
args_, is_positional).Run()));
288 constexpr
bool ValidateArg(ConvParser conv)
const {
289 return !conv.error() && FormatParser(conv.format(), conv.args())
290 .RunImpl(conv.is_positional());
294 constexpr FormatParser(
string_view format, ConvList args)
295 : format_(ConsumeNonPercent(format)),
args_(args) {}
301 constexpr
bool Run()
const {
302 return RunImpl(!format_.empty() && IsPositional(ConsumeFront(format_)));
314 constexpr
bool ValidFormatImpl(
string_view format) {
315 return FormatParser(format,
316 {ConvListT<
sizeof...(C)>{{
C...}}.list,
sizeof...(C)})
320 #endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 325 #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
std::vector< std::string > args_
constexpr size_type size() const noexcept
std::string format(const std::string &, const time_point< seconds > &, const femtoseconds &, const time_zone &)
static bool IsDigit(char c)
constexpr bool empty() const noexcept
constexpr const_pointer data() const noexcept