From 6ad35af2b63b32f9070c622b69da1c05535086a0 Mon Sep 17 00:00:00 2001 From: Алексей Шилин Date: Sat, 23 Nov 2019 00:56:46 +0300 Subject: strutl: Add APT::String::DisplayLength() function Returns string length, but unlike std::string::size() it honors multibyte characters. This allows to properly calculate visible sizes of console messages. --- apt-pkg/contrib/strutl.cc | 48 +++++++++++++++++++++++++++++++++++++++++++++++ apt-pkg/contrib/strutl.h | 2 ++ 2 files changed, 50 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 860e3fe47..70befdc48 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -40,6 +40,7 @@ #include #include #include +#include #include /*}}}*/ @@ -96,6 +97,53 @@ std::string Join(std::vector list, const std::string &sep) return oss.str(); } +// Returns string display length honoring multi-byte characters +size_t DisplayLength(StringView str) +{ + size_t len = 0; + + const char *p = str.data(); + const char *const end = str.end(); + + mbstate_t state{}; + while (p < end) + { + wchar_t wch; + size_t res = mbrtowc(&wch, p, end - p, &state); + switch (res) + { + case 0: + // Null wide character (i.e. L'\0') - stop + p = end; + break; + + case static_cast(-1): + // Byte sequence is invalid. Assume that it's + // a single-byte single-width character. + len += 1; + p += 1; + + // state is undefined in this case - reset it + state = {}; + + break; + + case static_cast(-2): + // Byte sequence is too short. Assume that it's + // an incomplete single-width character and stop. + len += 1; + p = end; + break; + + default: + len += wcwidth(wch); + p += res; + } + } + + return len; +} + } } /*}}}*/ diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index fc02357a8..738480402 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -33,6 +33,8 @@ namespace APT { bool Endswith(const std::string &s, const std::string &ending); bool Startswith(const std::string &s, const std::string &starting); std::string Join(std::vector list, const std::string &sep); + // Returns string display length honoring multi-byte characters + size_t DisplayLength(StringView str); } } -- cgit v1.2.3-70-g09d2