1 #pragma once
2
3 #include <string>
4 #include <wchar.h>
5
6 #include <algorithm>
7 #include <memory>
8
9 #pragma warning(push, 0)
10 #include <utf8/utf8.h>
11 #ifdef WIN32
12 #include <wcwidth.h>
13 #endif
14 #pragma warning(pop)
15
16 #ifdef max
17 #undef max
18 #endif
19
u8to16(const std::string & u8)20 inline std::wstring u8to16(const std::string& u8) {
21 std::wstring result;
22 utf8::utf8to16(u8.begin(), u8.end(), std::back_inserter(result));
23 return result;
24 }
25
u16to8(const std::wstring & u16)26 inline std::string u16to8(const std::wstring& u16) {
27 std::string result;
28 utf8::utf16to8(u16.begin(), u16.end(), std::back_inserter(result));
29 return result;
30 }
31
u8cols(const std::string & str)32 static inline size_t u8cols(const std::string& str) {
33 std::wstring wstr = u8to16(str);
34 #ifdef WIN32
35 int result = std::max(0, mk_wcswidth(wstr.c_str(), wstr.size()));
36 #else
37 int result = std::max(0, wcswidth(wstr.c_str(), wstr.size()));
38 #endif
39 return (result > 0) ? result : str.size();
40 }
41
u8len(const std::string & str)42 inline static size_t u8len(const std::string& str) {
43 try {
44 return utf8::distance(str.begin(), str.end());
45 }
46 catch (...) {
47 return str.length();
48 }
49 }
50
51 /* get the (raw) character index of the "nth" logical/display character */
u8offset(const std::string & str,int n)52 inline static size_t u8offset(const std::string& str, int n) {
53 if (str.size() == 0) {
54 return std::string::npos;
55 }
56
57 std::string::const_iterator it = str.begin();
58
59 int count = 0;
60 while (count < n && it != str.end()) {
61 utf8::unchecked::next(it);
62 ++count;
63 }
64
65 return (size_t)(it - str.begin());
66 }
67
u8substr(const std::string & in,int offset,int len)68 inline static std::string u8substr(const std::string& in, int offset, int len) {
69 std::string::const_iterator begin = in.begin() + offset;
70 std::string::const_iterator it = begin;
71
72 int count = 0;
73 while (count < len && it != in.end()) {
74 utf8::unchecked::next(it);
75 ++count;
76 }
77
78 return std::string(begin, it);
79 }
80
81 template<typename... Args>
u8fmt(const std::string & format,Args...args)82 static std::string u8fmt(const std::string& format, Args ... args) {
83 /* https://stackoverflow.com/a/26221725 */
84 size_t size = std::snprintf(nullptr, 0, format.c_str(), args ...) + 1; /* extra space for '\0' */
85 std::unique_ptr<char[]> buf(new char[size]);
86 std::snprintf(buf.get(), size, format.c_str(), args ...);
87 return std::string(buf.get(), buf.get() + size - 1); /* omit the '\0' */
88 }
89
u8replace(std::string & input,const std::string & find,const std::string & replace)90 static inline void u8replace(
91 std::string& input, const std::string& find, const std::string& replace)
92 {
93 size_t pos = input.find(find);
94 while (pos != std::string::npos) {
95 input.replace(pos, find.size(), replace);
96 pos = input.find(find, pos + replace.size());
97 }
98 }
99