1 // SciTE - Scintilla based Text Editor
2 /** @file StringHelpers.h
3 ** Definition of widely useful string functions.
4 **/
5 // Copyright 2010 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
7
8 #ifndef STRINGHELPERS_H
9 #define STRINGHELPERS_H
10
11 bool StartsWith(std::wstring_view s, std::wstring_view start);
12 bool StartsWith(std::string_view s, std::string_view start);
13 bool EndsWith(std::wstring_view s, std::wstring_view end);
14 bool Contains(std::string const &s, char ch) noexcept;
15
16 // Substitute is duplicated instead of templated as it was ambiguous when implemented as a template.
17 int Substitute(std::wstring &s, const std::wstring &sFind, const std::wstring &sReplace);
18 int Substitute(std::string &s, const std::string &sFind, const std::string &sReplace);
19
20 template <typename T>
Remove(T & s,const T & sFind)21 int Remove(T &s, const T &sFind) {
22 return Substitute(s, sFind, T());
23 }
24
25 bool RemoveStringOnce(std::string &s, const char *marker);
26
27 std::string StdStringFromInteger(int i);
28 std::string StdStringFromSizeT(size_t i);
29 std::string StdStringFromDouble(double d, int precision);
30
31 int IntegerFromString(const std::string &val, int defaultValue);
32 intptr_t IntPtrFromString(const std::string &val, intptr_t defaultValue);
33 long long LongLongFromString(const std::string &val, long long defaultValue);
34
35 // Basic case lowering that converts A-Z to a-z.
36 // Does not handle non-ASCII characters.
37 void LowerCaseAZ(std::string &s);
38
MakeUpperCase(char ch)39 constexpr char MakeUpperCase(char ch) noexcept {
40 if (ch < 'a' || ch > 'z')
41 return ch;
42 else
43 return ch - 'a' + 'A';
44 }
45
MakeLowerCase(char c)46 constexpr char MakeLowerCase(char c) noexcept {
47 if (c >= 'A' && c <= 'Z') {
48 return c - 'A' + 'a';
49 } else {
50 return c;
51 }
52 }
53
IsASCII(int ch)54 constexpr bool IsASCII(int ch) noexcept {
55 return (ch >= 0) && (ch < 0x80);
56 }
57
IsASpace(int ch)58 constexpr bool IsASpace(int ch) noexcept {
59 return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
60 }
61
IsADigit(int ch)62 constexpr bool IsADigit(int ch) noexcept {
63 return (ch >= '0') && (ch <= '9');
64 }
65
IsAlphabetic(int ch)66 constexpr bool IsAlphabetic(int ch) noexcept {
67 return ((ch >= 'A') && (ch <= 'Z')) || ((ch >= 'a') && (ch <= 'z'));
68 }
69
IsAlphaNumeric(int ch)70 constexpr bool IsAlphaNumeric(int ch) noexcept {
71 return
72 ((ch >= '0') && (ch <= '9')) ||
73 ((ch >= 'a') && (ch <= 'z')) ||
74 ((ch >= 'A') && (ch <= 'Z'));
75 }
76
77 intptr_t IntegerFromText(const char *s) noexcept;
78
79 // StringSplit can be expanded over std::string or GUI::gui_string
80 template <typename T>
StringSplit(const T & text,int separator)81 std::vector<T> StringSplit(const T &text, int separator) {
82 std::vector<T> vs(text.empty() ? 0 : 1);
83 for (typename T::const_iterator it=text.begin(); it!=text.end(); ++it) {
84 if (*it == separator) {
85 vs.push_back(T());
86 } else {
87 vs.back() += *it;
88 }
89 }
90 return vs;
91 }
92
ListFromString(const GUI::gui_string & args)93 inline std::vector<GUI::gui_string> ListFromString(const GUI::gui_string &args) {
94 return StringSplit(args, '\n');
95 }
96
97
98 // Safer version of string copy functions like strcpy, wcsncpy, etc.
99 // Instantiate over fixed length strings of both char and wchar_t.
100 // May truncate if source doesn't fit into dest with room for NUL.
101
102 template <typename T, size_t count>
StringCopy(T (& dest)[count],const T * source)103 void StringCopy(T(&dest)[count], const T *source) noexcept {
104 for (size_t i=0; i<count; i++) {
105 dest[i] = source[i];
106 if (!source[i])
107 break;
108 }
109 dest[count-1] = 0;
110 }
111
112 int CompareNoCase(const char *a, const char *b) noexcept;
113 bool EqualCaseInsensitive(const char *a, const char *b) noexcept;
114 bool EqualCaseInsensitive(std::string_view a, std::string_view b) noexcept;
115 bool isprefix(const char *target, const char *prefix) noexcept;
116
117 constexpr const char *UTF8BOM = "\xef\xbb\xbf";
118
119 std::u32string UTF32FromUTF8(std::string_view s);
120 unsigned int UTF32Character(const char *utf8) noexcept;
121
122 std::string Slash(const std::string &s, bool quoteQuotes);
123 unsigned int UnSlash(char *s) noexcept;
124 std::string UnSlashString(const char *s);
125 std::string UnSlashLowOctalString(const char *s);
126
127 class ILocalize {
128 public:
129 virtual GUI::gui_string Text(const char *s, bool retainIfNotFound=true) = 0;
130 };
131
132 /**
133 * This is a fixed length list of strings suitable for display in combo boxes
134 * as a memory of user entries.
135 */
136 template < int sz >
137 class EntryMemory {
138 std::string entries[sz];
139 public:
Insert(const std::string & s)140 void Insert(const std::string &s) {
141 for (int i = 0; i < sz; i++) {
142 if (entries[i] == s) {
143 for (int j = i; j > 0; j--) {
144 entries[j] = entries[j - 1];
145 }
146 entries[0] = s;
147 return;
148 }
149 }
150 for (int k = sz - 1; k > 0; k--) {
151 entries[k] = entries[k - 1];
152 }
153 entries[0] = s;
154 }
AppendIfNotPresent(const std::string & s)155 void AppendIfNotPresent(const std::string &s) {
156 for (int i = 0; i < sz; i++) {
157 if (entries[i] == s) {
158 return;
159 }
160 if (0 == entries[i].length()) {
161 entries[i] = s;
162 return;
163 }
164 }
165 }
166 void AppendList(const std::string &s, char sep = '|') {
167 int start = 0;
168 int end = 0;
169 while (s[end] != '\0') {
170 end = start;
171 while ((s[end] != sep) && (s[end] != '\0'))
172 ++end;
173 AppendIfNotPresent(s.substr(start, end-start));
174 start = end + 1;
175 }
176 }
Length()177 int Length() const noexcept {
178 int len = 0;
179 for (int i = 0; i < sz; i++)
180 if (entries[i].length())
181 len++;
182 return len;
183 }
At(int n)184 std::string At(int n) const {
185 return entries[n];
186 }
AsVector()187 std::vector<std::string>AsVector() {
188 std::vector<std::string> ret;
189 for (int i = 0; i < sz; i++) {
190 if (entries[i].length())
191 ret.push_back(entries[i].c_str());
192 }
193 return ret;
194 }
195 };
196
197 typedef EntryMemory < 10 > ComboMemory;
198
199 #endif
200