inline stlsoft::basic_shim_string<ff_char_t, 64> real_helper_4( double const& value , int minimumWidth , int precision , ff_char_t const* specifier ) { ff_char_t type = 'f'; ff_char_t fmt_[] = FASTFORMAT_LITERAL_STRING("%-01234567890123456789.01234567890123456789f"); ff_char_t* fmt = fmt_; if(NULL != specifier) { type = *specifier; } if( default_width_sentinel_() == minimumWidth && precision < 0) { fmt[1] = type; fmt[2] = '\0'; } else { if(default_width_sentinel_() == minimumWidth) { minimumWidth = 0; } if(precision < 0) { precision = 0; } // Performance tests show a substantial advantage in using // integer_to_string() over fastformat_util_snprintf() #if 0 int n = fastformat_util_snprintf(&fmt[0], STLSOFT_NUM_ELEMENTS(fmt_) - 1, FASTFORMAT_LITERAL_STRING("%%%d.%d%c"), minimumWidth, precision, type); FASTFORMAT_CONTRACT_ENFORCE_ASSUMPTION((n > 0) && (n < int(STLSOFT_NUM_ELEMENTS(fmt_)) - 1)); fmt[n] = '\0'; #else /* ? 0 */ const size_t fmtDim = STLSOFT_NUM_ELEMENTS(fmt_) - 1; ff_char_t* end = &fmt[fmtDim]; size_t n1; size_t n2; stlsoft::integer_to_string(end - 21, 21, precision, &n1); *--end = type; end -= n1; stlsoft::integer_to_string(end - 21, 21, minimumWidth, &n2); *--end = '.'; end -= n2; *--end = '%'; fmt = end; #endif /* 0 */ } return real_helper_2(value, fmt); }
inline S change_windows_replacement_parameters_to_fastformat(S const& str) { typedef ss_typename_type_k S::const_iterator iter_t; enum state_t { normal, percent, number } state = normal; S str2; int index = 0; str2.reserve(str.size() + 10); { for(iter_t begin = str.begin(); begin != str.end(); ++begin) { bool isNumber = false; switch(*begin) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': isNumber = true; } if( number == state && !isNumber) { ff_char_t parameter[32]; int cch = fastformat_util_snprintf(¶meter[0], STLSOFT_NUM_ELEMENTS(parameter), FASTFORMAT_LITERAL_STRING("{%d}"), index - 1); str2.append(parameter, size_t(cch)); str2.append(1u, *begin); state = normal; } else { switch(*begin) { case '%': switch(state) { default: case number: FASTFORMAT_CONTRACT_ENFORCE_UNEXPECTED_CONDITION_INTERNAL("unexpected state"); case normal: state = percent; break; case percent: state = normal; str2.append(1, '%'); break; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': switch(state) { default: FASTFORMAT_CONTRACT_ENFORCE_UNEXPECTED_CONDITION_INTERNAL("unexpected state"); case normal: str2.append(1, *begin); break; case percent: state = number; index = (*begin - '0'); break; case number: index = (10 * index) + (*begin - '0'); break; } break; default: state = normal; str2.append(1, *begin); break; } } }} if(number == state) { ff_char_t parameter[32]; int cch = fastformat_util_snprintf(¶meter[0], STLSOFT_NUM_ELEMENTS(parameter), FASTFORMAT_LITERAL_STRING("{%d}"), index - 1); str2.append(parameter, size_t(cch)); } return str2; }
inline stlsoft::basic_shim_string<ff_char_t, 64> real_helper_2( double const& value , ff_char_t const* fmt ) { typedef stlsoft::basic_shim_string<ff_char_t, 64> result_t; enum { maxRepeats = 4 }; #if _STLSOFT_VER < 0x010a0000 && \ defined(_STLSOFT_1_10_VER) && \ _STLSOFT_1_10_VER < 0x010a0109 /* Using STLSoft 1.10.1 alpha 1 - alpha 8 */ # error This class cannot work with STLSoft 1.10 versions between 1.10.1 alpha 1 and 1.10.1 alpha 9. Please download the latest version of STLSoft 1.10 alpha #elif _STLSOFT_VER >= 0x010a0000 || \ defined(_STLSOFT_1_10_VER) /* Using STLSoft 1.10+ version of basic_shim_string */ // We use the public interface of the shim string. result_t result(64); # ifndef STLSOFT_CF_THROW_BAD_ALLOC if(!result.empty()) # endif /* !STLSOFT_CF_THROW_BAD_ALLOC */ { // Unlike integral types, the string representation of floating // point values do not have a known maximum length, so we must be // flexible. // // However, some implementations of snprintf() return -1 instead of // the length that would be required, so we cannot assume -1 // indicates error. To handle this, we double the size of the buffer // up to four times, at which point we admit defeat. { for(int i = 0;; ) { int n = fastformat_util_snprintf(result.data(), result.size() - 1, fmt, value); if(n > int(result.size())) { // An implementation that does it correctly, so just resize // to the desired size and go again // This'll only return false when exception-handling is // suppressed, but the code is correct without preprocessor // logic in either case, so leave as is if(!result.resize(n)) { result.truncate(0); break; } } else if(n < 0) { if(maxRepeats == ++i) { result.truncate(0); break; } else { // This'll only return false when exception-handling is // suppressed, but the code is correct without preprocessor // logic in either case, so leave as is if(!result.resize(1u + result.size() * 2)) { result.truncate(0); break; } } } else { // It's worked! // // We must nul-terminate, and resize, so that the shim string's // length is evaluated correctly result.truncate(size_t(n)); break; } }} } return result; #else /* ? STLSoft 1.x */ /* Using STLSoft 1.9+ version of basic_shim_string */ // We have to use the internal buffer, which means that we are // relying on the internal workings of shim string, which is ugly. // With 1.10, we don't need to do this. result_t result(64); result_t::buffer_type& buffer = result.get_buffer(); # ifndef STLSOFT_CF_THROW_BAD_ALLOC if(!buffer.empty()) # endif /* !STLSOFT_CF_THROW_BAD_ALLOC */ { // Unlike integral types, the string representation of floating // point values do not have a known maximum length, so we must be // flexible. // // However, some implementations of snprintf() return -1 instead of // the length that would be required, so we cannot assume -1 // indicates error. To handle this, we double the size of the buffer // up to four times, at which point we admit defeat. { for(int i = 0;; ) { int n = fastformat_util_snprintf(&buffer[0], buffer.size() - 1, fmt, value); if(n > int(buffer.size() - 1)) { // An implementation that does it correctly, so just resize // to the desired size and go again // This'll only return false when exception-handling is // suppressed, but the code is correct without preprocessor // logic in either case, so leave as is if(!buffer.resize(size_t(n) + 1u)) { buffer.resize(1u); break; } } else if(n < 0) { if(maxRepeats == ++i) { break; } else { // This'll only return false when exception-handling is // suppressed, but the code is correct without preprocessor // logic in either case, so leave as is if(!buffer.resize(1u + buffer.size() * 2)) { buffer.resize(1u); break; } } } else { // It's worked! // // We must nul-terminate, and resize, so that the shim string's // length is evaluated correctly buffer[size_t(n)] = '\0'; buffer.resize(size_t(n) + 1u); break; } }} } return result; #endif /* STLSoft 1.x */ }