| 2260 | |
| 2261 | template <bool IS_CONSTEXPR, typename Char, typename Handler> |
| 2262 | FMT_CONSTEXPR FMT_INLINE void parse_format_string(basic_string_view<Char> format_str, Handler&& handler) { |
| 2263 | auto begin = format_str.data(); |
| 2264 | auto end = begin + format_str.size(); |
| 2265 | if (end - begin < 32) { |
| 2266 | // Use a simple loop instead of memchr for small strings. |
| 2267 | const Char* p = begin; |
| 2268 | while (p != end) { |
| 2269 | auto c = *p++; |
| 2270 | if (c == '{') { |
| 2271 | handler.on_text(begin, p - 1); |
| 2272 | begin = p = parse_replacement_field(p - 1, end, handler); |
| 2273 | } else if (c == '}') { |
| 2274 | if (p == end || *p != '}') return handler.on_error("unmatched '}' in format string"); |
| 2275 | handler.on_text(begin, p); |
| 2276 | begin = ++p; |
| 2277 | } |
| 2278 | } |
| 2279 | handler.on_text(begin, end); |
| 2280 | return; |
| 2281 | } |
| 2282 | |
| 2283 | struct writer { |
| 2284 | FMT_CONSTEXPR void operator()(const Char* from, const Char* to) { |
| 2285 | if (from == to) return; |
| 2286 | for (;;) { |
| 2287 | const Char* p = nullptr; |
| 2288 | if (!find<IS_CONSTEXPR>(from, to, Char('}'), p)) return handler_.on_text(from, to); |
| 2289 | ++p; |
| 2290 | if (p == to || *p != '}') return handler_.on_error("unmatched '}' in format string"); |
| 2291 | handler_.on_text(from, p); |
| 2292 | from = p + 1; |
| 2293 | } |
| 2294 | } |
| 2295 | |
| 2296 | Handler& handler_; |
| 2297 | } write = {handler}; |
| 2298 | |
| 2299 | while (begin != end) { |
| 2300 | // Doing two passes with memchr (one for '{' and another for '}') is up to |
| 2301 | // 2.5x faster than the naive one-pass implementation on big format strings. |
| 2302 | const Char* p = begin; |
| 2303 | if (*begin != '{' && !find<IS_CONSTEXPR>(begin + 1, end, Char('{'), p)) return write(begin, end); |
| 2304 | write(begin, p); |
| 2305 | begin = parse_replacement_field(p, end, handler); |
| 2306 | } |
| 2307 | } |
| 2308 | |
| 2309 | template <typename T, bool = is_named_arg<T>::value> struct strip_named_arg { |
| 2310 | using type = T; |