char const* template_formatter::next_specifier(output_buffer* pbuffer, char const* pformat) { #ifdef _GNU_SOURCE while(true) { char const* pspecifier = strchrnul(pformat, '%'); auto len = pspecifier - pformat; auto p = pbuffer->reserve(len); std::memcpy(p, pformat, len); pbuffer->commit(len); if(*pspecifier == '\0') return nullptr; pformat = pspecifier + 1; if(*pformat != '%') return pformat; // Found "%%". Add a single '%' and continue. ++pformat; append_percent(pbuffer); } #else static_assert(false, "need replacement for strchrnul"); #endif }
void template_formatter::format(output_buffer* pbuffer, char const* pformat) { // There are no remaining arguments to format, so we will ignore additional // format specifications that might occur in the format string. However, we // still need to treat "%%" as "%". We'll iterate over on next_specifier // and when it finds a format specifier, we append a '%' and move on. while((pformat = next_specifier(pbuffer, pformat)) != nullptr) append_percent(pbuffer); }
static void format(output_buffer* pbuffer, char const* pformat, T&& value, Args&&... args) { pformat = next_specifier(pbuffer, pformat); if(not pformat) return; char const* pnext_format = detail::invoke_custom_format(pbuffer, pformat, std::forward<T>(value)); if(pnext_format) pformat = pnext_format; else append_percent(pbuffer); return template_formatter::format(pbuffer, pformat, std::forward<Args>(args)...); }