diff options
author | Алексей Шилин <rootlexx@mail.ru> | 2019-11-23 00:56:46 +0300 |
---|---|---|
committer | Алексей Шилин <rootlexx@mail.ru> | 2019-11-25 19:02:47 +0300 |
commit | 6ad35af2b63b32f9070c622b69da1c05535086a0 (patch) | |
tree | 334c9f557c360caa72e3ee3122ccf6431e7e817d /apt-pkg/contrib/strutl.cc | |
parent | 83f2732b10498c4a3abdfbc072da63803557ce9b (diff) |
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.
Diffstat (limited to 'apt-pkg/contrib/strutl.cc')
-rw-r--r-- | apt-pkg/contrib/strutl.cc | 48 |
1 files changed, 48 insertions, 0 deletions
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 <string.h> #include <time.h> #include <unistd.h> +#include <wchar.h> #include <apti18n.h> /*}}}*/ @@ -96,6 +97,53 @@ std::string Join(std::vector<std::string> 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<size_t>(-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<size_t>(-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; +} + } } /*}}}*/ |