summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/contrib/strutl.cc48
-rw-r--r--apt-pkg/contrib/strutl.h2
2 files changed, 50 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;
+}
+
}
}
/*}}}*/
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<std::string> list, const std::string &sep);
+ // Returns string display length honoring multi-byte characters
+ size_t DisplayLength(StringView str);
}
}