| 1127 | |
| 1128 | template <CFormatter TFormatter, class... TArgs> |
| 1129 | void RunFormatter( |
| 1130 | TStringBuilderBase* builder, |
| 1131 | TBasicFormatString<TArgs...> formatString, |
| 1132 | const TFormatter& formatter) |
| 1133 | { |
| 1134 | auto isValidLocations = [] (const auto& t) { |
| 1135 | return std::get<0>(t) != std::get<1>(t); |
| 1136 | }; |
| 1137 | // Generally marker is simply "%v" e.g. 2 symbols. |
| 1138 | // We assume it is used to insert something for roughly 5 symbols |
| 1139 | // of size. |
| 1140 | builder->Preallocate(std::size(formatString.Get()) + sizeof...(TArgs) * (5 - 2)); |
| 1141 | |
| 1142 | // Empty marker positions -- fallback to the normal impl. |
| 1143 | if constexpr (sizeof...(TArgs) != 0) { |
| 1144 | if (!isValidLocations(formatString.Markers[0])) { |
| 1145 | RunFormatterFullScan(builder, formatString.Get(), formatter); |
| 1146 | return; |
| 1147 | } |
| 1148 | } else { |
| 1149 | if (formatString.Escapes[0] == -2) { |
| 1150 | RunFormatterFullScan(builder, formatString.Get(), formatter); |
| 1151 | return; |
| 1152 | } |
| 1153 | } |
| 1154 | |
| 1155 | int escapesFound = 0; |
| 1156 | int currentPos = 0; |
| 1157 | |
| 1158 | auto beginIt = formatString.Get().begin(); |
| 1159 | auto size = formatString.Get().size(); |
| 1160 | |
| 1161 | const auto& [markers, escapes] = std::tie(formatString.Markers, formatString.Escapes); |
| 1162 | |
| 1163 | auto appendVerbatim = [&] (int offsetToEnd) { |
| 1164 | builder->AppendString(TStringBuf{beginIt + currentPos, beginIt + offsetToEnd}); |
| 1165 | }; |
| 1166 | |
| 1167 | auto processEscape = [&] () mutable { |
| 1168 | // OpenMP doesn't support structured bindings :(. |
| 1169 | auto escapePos = formatString.Escapes[escapesFound]; |
| 1170 | |
| 1171 | // Append everything that's present until %%. |
| 1172 | appendVerbatim(escapePos); |
| 1173 | |
| 1174 | // Append '%'. |
| 1175 | builder->AppendChar('%'); |
| 1176 | |
| 1177 | // Advance position to first '%' pos + 2. |
| 1178 | currentPos = escapePos + 2; |
| 1179 | }; |
| 1180 | |
| 1181 | int argIndex = 0; |
| 1182 | |
| 1183 | while(argIndex < std::ssize(markers)) { |
| 1184 | auto [markerStart, markerEnd] = markers[argIndex]; |
| 1185 | |
| 1186 | if ( |
no test coverage detected