string: add snprintf
Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
parent
db413bb5ce
commit
a7543cf9ab
@ -28,6 +28,7 @@ int main(int, const char *[])
|
||||
UnitTests::stream::replicator();
|
||||
UnitTests::string::strncpy();
|
||||
UnitTests::string::sprintf();
|
||||
UnitTests::string::snprintf();
|
||||
UnitTests::unicode::charset_encoder();
|
||||
UnitTests::unicode::normalize();
|
||||
UnitTests::unicode::str2wstr();
|
||||
|
@ -109,6 +109,7 @@ namespace UnitTests
|
||||
public:
|
||||
TEST_METHOD(strncpy);
|
||||
TEST_METHOD(sprintf);
|
||||
TEST_METHOD(snprintf);
|
||||
};
|
||||
|
||||
TEST_CLASS(unicode)
|
||||
|
@ -42,4 +42,31 @@ namespace UnitTests
|
||||
Assert::AreEqual(str.c_str(), stdex::sprintf("%s", locale, str.data()).c_str());
|
||||
Assert::AreEqual(str.size(), stdex::sprintf("%s", locale, str.data()).size());
|
||||
}
|
||||
|
||||
void string::snprintf()
|
||||
{
|
||||
stdex::locale locale(stdex::create_locale(LC_ALL, "en_US.UTF-8"));
|
||||
|
||||
{
|
||||
wchar_t buf[0x100];
|
||||
Assert::IsTrue(stdex::snprintf(buf, _countof(buf), L"This is %ls.", locale, L"a test") == 15);
|
||||
Assert::AreEqual(L"This is a test.", buf);
|
||||
}
|
||||
{
|
||||
char buf[0x100];
|
||||
Assert::IsTrue(stdex::snprintf(buf, _countof(buf), "This is %s.", locale, "a test") == 15);
|
||||
Assert::AreEqual("This is a test.", buf);
|
||||
}
|
||||
|
||||
{
|
||||
wchar_t buf[8];
|
||||
Assert::IsTrue(stdex::snprintf(buf, _countof(buf), L"This is %ls.", locale, L"a test") == 8);
|
||||
Assert::IsTrue(stdex::strncmp(L"This is a test.", buf, _countof(buf)) == 0);
|
||||
}
|
||||
{
|
||||
char buf[8];
|
||||
Assert::IsTrue(stdex::snprintf(buf, _countof(buf), "This is %s.", locale, "a test") == 8);
|
||||
Assert::IsTrue(stdex::strncmp("This is a test.", buf, _countof(buf)) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -620,7 +620,7 @@ namespace stdex
|
||||
dst.append(1, static_cast<char>(src[i++]));
|
||||
else {
|
||||
char tmp[3 + 8 + 1 + 1];
|
||||
snprintf(tmp, _countof(tmp), "&#x%x;", static_cast<unsigned int>(src[i++]));
|
||||
::snprintf(tmp, _countof(tmp), "&#x%x;", static_cast<unsigned int>(src[i++]));
|
||||
dst.append(tmp);
|
||||
}
|
||||
}
|
||||
@ -638,7 +638,7 @@ namespace stdex
|
||||
dst.append(1, static_cast<char>(src[i++]));
|
||||
else {
|
||||
char tmp[3 + 8 + 1 + 1];
|
||||
snprintf(tmp, _countof(tmp), "&#x%x;", static_cast<unsigned int>(wstr_to_utf32(src, i, end)));
|
||||
::snprintf(tmp, _countof(tmp), "&#x%x;", static_cast<unsigned int>(wstr_to_utf32(src, i, end)));
|
||||
dst.append(tmp);
|
||||
}
|
||||
}
|
||||
@ -742,7 +742,7 @@ namespace stdex
|
||||
}
|
||||
else {
|
||||
char tmp[3 + 8 + 1 + 1];
|
||||
int m = snprintf(tmp, _countof(tmp), "&#x%x;", static_cast<unsigned int>(src[i++]));
|
||||
int m = ::snprintf(tmp, _countof(tmp), "&#x%x;", static_cast<unsigned int>(src[i++]));
|
||||
stdex_assert(m >= 0);
|
||||
if (static_cast<size_t>(m) >= count_dst)
|
||||
throw buffer_overrun;
|
||||
@ -770,7 +770,7 @@ namespace stdex
|
||||
}
|
||||
else {
|
||||
char tmp[3 + 8 + 1 + 1];
|
||||
int m = snprintf(tmp, _countof(tmp), "&#x%x;", static_cast<unsigned int>(wstr_to_utf32(src, i, end)));
|
||||
int m = ::snprintf(tmp, _countof(tmp), "&#x%x;", static_cast<unsigned int>(wstr_to_utf32(src, i, end)));
|
||||
stdex_assert(m >= 0);
|
||||
if (static_cast<size_t>(m) >= count_dst)
|
||||
throw buffer_overrun;
|
||||
|
@ -2655,6 +2655,45 @@ namespace stdex
|
||||
}
|
||||
/// \endcond
|
||||
|
||||
///
|
||||
/// Formats string using `printf()`.
|
||||
///
|
||||
/// \param[out] str Output string
|
||||
/// \param[in ] capacity Number of available code units in str
|
||||
/// \param[in ] format String template using `printf()` style
|
||||
/// \param[in ] locale Stdlib locale used to perform formatting. Use `NULL` to use locale globally set by `setlocale()`.
|
||||
///
|
||||
/// \return Number of output code units
|
||||
///
|
||||
template<class T>
|
||||
inline size_t snprintf(_Out_z_cap_(capacity) T* str, _In_ size_t capacity, _In_z_ _Printf_format_string_params_(2) const T* format, _In_opt_ locale_t locale, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, locale);
|
||||
int count = vsnprintf(str, capacity, format, locale, arg);
|
||||
va_end(arg);
|
||||
if (0 <= count && static_cast<size_t>(count) <= capacity)
|
||||
return static_cast<size_t>(count);
|
||||
#ifdef _WIN32
|
||||
if (count < 0) {
|
||||
switch (errno) {
|
||||
case 0: return capacity;
|
||||
case EINVAL: throw std::invalid_argument("invalid snprintf arguments");
|
||||
case EILSEQ: throw std::runtime_error("encoding error");
|
||||
default: throw std::runtime_error("failed to format string");
|
||||
}
|
||||
} else
|
||||
return capacity;
|
||||
#else
|
||||
switch (errno) {
|
||||
case EOVERFLOW: return capacity;
|
||||
case EINVAL: throw std::invalid_argument("invalid snprintf arguments");
|
||||
case EILSEQ: throw std::runtime_error("encoding error");
|
||||
default: throw std::runtime_error("failed to format string");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Formats string using `printf()`.
|
||||
///
|
||||
|
@ -43,7 +43,7 @@ namespace stdex
|
||||
static_cast<unsigned int>(id.Data4[0]), static_cast<unsigned int>(id.Data4[1]),
|
||||
static_cast<unsigned int>(id.Data4[2]), static_cast<unsigned int>(id.Data4[3]), static_cast<unsigned int>(id.Data4[4]), static_cast<unsigned int>(id.Data4[5]), static_cast<unsigned int>(id.Data4[6]), static_cast<unsigned int>(id.Data4[7]));
|
||||
#else
|
||||
snprintf(str, uuid_str_max, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
|
||||
::snprintf(str, uuid_str_max, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
|
||||
*reinterpret_cast<const uint32_t*>(&id[0]),
|
||||
static_cast<unsigned int>(*reinterpret_cast<const uint16_t*>(&id[4])),
|
||||
static_cast<unsigned int>(*reinterpret_cast<const uint16_t*>(&id[6])),
|
||||
|
Loading…
x
Reference in New Issue
Block a user