--- nono/lib/mystring.cpp 2026/04/29 17:05:08 1.1.1.6 +++ nono/lib/mystring.cpp 2026/04/29 17:05:47 1.1.1.8 @@ -86,6 +86,16 @@ string_tolower(const std::string& src) return dst; } +// 文字列 src 中の ASCII 小文字を大文字にした新しい文字列を返す。 +std::string +string_toupper(const std::string& src) +{ + std::string dst(src); + std::transform(dst.begin(), dst.end(), dst.begin(), + [](unsigned char c){ return std::toupper(c); }); + return dst; +} + // 文字列 lhs の先頭が rhs と大文字小文字の区別なしで一致すれば true を返す。 // ASCII 専用。 // C++20 の starts_with に似せておく。 @@ -182,6 +192,115 @@ format_number(uint64 val) return std::string(buf); } +// value を width 桁の16進数文字列にして返す。"%0{width}x" みたいな感じ。 +// strhex(0x12345678, 4) -> "5678" +// strhex(0x00000001, 3) -> "001" +std::string +strhex(uint32 value, int width) +{ + std::string s; + + for (width -= 1; width >= 0; width--) { + uint32 d = (value >> (width * 4)) & 0x0f; + if (__predict_true(d < 10)) { + s += '0' + d; + } else { + s += 'a' + d - 10; + } + } + return s; +} + +#define FORMAT_FULL 0 +#define FORMAT_SEC 1 + +// 経過時間 t を文字列にして返す。 +// 文字列長は、t の大きさ(とフォーマット指定)によって以下の通り。 +// +// 0 1 2 +// 01234567890123456789012345 +// "0.mmm'uuu'nnn" 10秒未満、または FORMAT_SEC なら13桁 +// "59.mmm'uuu'nnn" 1分未満なら14桁 +// " 9:59.mmm'uuu'nnn" 1時間未満なら17桁 +// " 9:59:59.mmm'uuu'nnn" 24時間未満なら20桁 +// "999d 23:59:59.mmm'uuu'nnn" 1日以上なら25桁。これが最大幅。 +// +// FORMAT_SEC は1桁秒以下の場合 (実際には1秒未満の場合) に用いる。 +// FORMAT_FULL は 1000日経過すると桁がずれるけど、それはもういいだろう。 +// +// 10秒未満の場合だけ %2u ではなく %u で1桁切り詰めているが、これは +// FORMAT_SEC との互換性のため。その必要のない10分未満と10時間未満は +// どちらも %2u で表記し桁数を維持することに努める。 +static const std::string +TimeToStrF(uint64 t, int format) +{ + char buf[32]; + char *p; + size_t len; + int n; + + uint ns = t % 1000; + t /= 1000; + uint us = t % 1000; + t /= 1000; + uint ms = t % 1000; + t /= 1000; + + uint s, m, h, d; + if (format == FORMAT_FULL) { + s = t % 60; + t /= 60; + m = t % 60; + t /= 60; + h = t % 24; + t /= 24; + d = t; + } else { + s = t; + m = 0; + h = 0; + d = 0; + } + + p = buf; + len = sizeof(buf); + if (d) { + n = snprintf(p, len, "%3ud %02u:%02u:%02u", d, h, m, s); + p += n; + len -= n; + } else if (h) { + n = snprintf(p, len, "%2u:%02u:%02u", h, m, s); + p += n; + len -= n; + } else if (m) { + n = snprintf(p, len, "%2u:%02u", m, s); + p += n; + len -= n; + } else { + n = snprintf(p, len, "%u", s); + p += n; + len -= n; + } + n = snprintf(p, len, ".%03u'%03u'%03u", ms, us, ns); + p += n; + len -= n; + + return std::string(buf, p - buf); +} + +const std::string +TimeToStr(uint64 t) +{ + return TimeToStrF(t, FORMAT_FULL); +} + +const std::string +SecToStr(uint64 t) +{ + return TimeToStrF(t, FORMAT_SEC); +} + + #if defined(SELFTEST) #include #include "stopwatch.h"