File indexing completed on 2025-01-18 09:27:23
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
0016 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
0017
0018 #include <algorithm>
0019
0020 #include "absl/base/attributes.h"
0021 #include "absl/strings/internal/str_format/arg.h"
0022 #include "absl/strings/internal/str_format/constexpr_parser.h"
0023 #include "absl/strings/internal/str_format/extension.h"
0024
0025
0026
0027 #ifndef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
0028
0029
0030
0031 #if ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__) && \
0032 !defined(__INTELLISENSE__)
0033 #define ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 1
0034 #endif
0035
0036 #endif
0037
0038 namespace absl {
0039 ABSL_NAMESPACE_BEGIN
0040 namespace str_format_internal {
0041
0042 #ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
0043
0044 template <FormatConversionCharSet... C>
0045 constexpr bool ValidFormatImpl(string_view format) {
0046 int next_arg = 0;
0047 const char* p = format.data();
0048 const char* const end = p + format.size();
0049 constexpr FormatConversionCharSet
0050 kAllowedConvs[(std::max)(sizeof...(C), size_t{1})] = {C...};
0051 bool used[(std::max)(sizeof...(C), size_t{1})]{};
0052 constexpr int kNumArgs = sizeof...(C);
0053 while (p != end) {
0054 while (p != end && *p != '%') ++p;
0055 if (p == end) {
0056 break;
0057 }
0058 if (p + 1 >= end) return false;
0059 if (p[1] == '%') {
0060
0061 p += 2;
0062 continue;
0063 }
0064
0065 UnboundConversion conv(absl::kConstInit);
0066 p = ConsumeUnboundConversion(p + 1, end, &conv, &next_arg);
0067 if (p == nullptr) return false;
0068 if (conv.arg_position <= 0 || conv.arg_position > kNumArgs) {
0069 return false;
0070 }
0071 if (!Contains(kAllowedConvs[conv.arg_position - 1], conv.conv)) {
0072 return false;
0073 }
0074 used[conv.arg_position - 1] = true;
0075 for (auto extra : {conv.width, conv.precision}) {
0076 if (extra.is_from_arg()) {
0077 int pos = extra.get_from_arg();
0078 if (pos <= 0 || pos > kNumArgs) return false;
0079 used[pos - 1] = true;
0080 if (!Contains(kAllowedConvs[pos - 1], '*')) {
0081 return false;
0082 }
0083 }
0084 }
0085 }
0086 if (sizeof...(C) != 0) {
0087 for (bool b : used) {
0088 if (!b) return false;
0089 }
0090 }
0091 return true;
0092 }
0093
0094 #endif
0095
0096 }
0097 ABSL_NAMESPACE_END
0098 }
0099
0100 #endif