using CString = const char*; using String = std::string; //----------------------------------------------------------------------------- // Template based sprintf replacement //----------------------------------------------------------------------------- class TSException : public std::runtime_error { public: TSException() : std::runtime_error("Typed String format exception") { } TSException(CString what) : std::runtime_error(what) { } TSException(String what) : std::runtime_error(what) { } TSException(std::stringstream& what) : std::runtime_error(what.str()) { } }; //----------------------------------------------------------------------------- inline void TSSprintf(std::stringstream &ss, const char* format) { while (*format != '\0') { char fc = *format; if (fc == '%' && *(format+1) == '%') format++; ss << fc; format++; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #define _TSSPRINTF_QUALIFIERS \ format++; fc = *format; \ bool has_width = false; \ bool has_precision = false; \ bool is_left = false; \ bool is_hex = false; \ int width = 0; \ int precision = 0; \ if (fc == '-') { \ ss << std::setiosflags(std::ios::left); \ format++; fc = *format; is_left = true; \ } \ if (fc == '0') { \ ss << std::setfill('0'); \ format++; fc = *format; \ } \ while (fc >= '0' && fc <= '9') { \ width = width*10 + (fc-'0'); \ format++; fc = *format; \ has_width = true; \ } \ if (fc == '.') { \ has_precision = true; \ format++; fc = *format; \ while (fc >= '0' && fc <= '9') { \ precision = precision*10 + (fc-'0'); \ format++; fc = *format; \ } \ } \ #define _TSSPRINTF_FORMATS \ if (fc == 'l') { format++; fc = *format; } \ if (fc == 'l') { format++; fc = *format; } \ if (fc == 'h') { format++; fc = *format; } \ if (fc == 'h') { format++; fc = *format; } \ if (fc == 's') {} \ else if (fc == 'i' || fc == 'd' || fc == 'u') {} \ else if (fc == 'p' || fc == 'c') {} \ else if (fc == 'f') { \ ss << std::fixed << std::setprecision(2); \ } \ else if (fc == 'x') { \ ss << std::hex << std::nouppercase; is_hex = true; \ } \ else if (fc == 'X') { \ ss << std::hex << std::uppercase; is_hex = true; \ } \ else { \ std::stringstream es; es << "Unexpected format: '%" << fc \ << "' in '" << format << "'"; \ throw TSException(es); \ } \ #define _TSSPRINTF_APPLY_QUALIFIERS \ if (has_width) {ss< void TSSprintf(std::stringstream &ss, const char* format, T value, Targs... Fargs) { while (*format != '\0') { char fc = *format; if (fc == '%') { if (*(format+1) == '%' || *(format+1) == ' ') { fc = '%'; format++; } else { _TSSPRINTF_QUALIFIERS; _TSSPRINTF_FORMATS; _TSSPRINTF_APPLY_QUALIFIERS; TSSprintf(ss, format + 1, Fargs...); return; } } ss << fc; format++; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template String TSprintf(const char* format, T value, Targs... Fargs) { std::stringstream ss; while (*format != '\0') { char fc = *format; if (fc == '%') { if (*(format+1) == '%') { fc = '%'; format++; } else { _TSSPRINTF_QUALIFIERS; _TSSPRINTF_FORMATS; _TSSPRINTF_APPLY_QUALIFIERS; TSSprintf(ss, format + 1, Fargs...); return ss.str(); } } ss << fc; format++; } return ss.str(); }