]> git.lizzy.rs Git - minetest.git/blob - src/util/string.h
Fix most warnings, re-fix MSVC compile error
[minetest.git] / src / util / string.h
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #ifndef UTIL_STRING_HEADER
21 #define UTIL_STRING_HEADER
22
23 #include "../irrlichttypes.h"
24 #include "../strfnd.h" // For trim()
25 #include "pointer.h"
26 #include <string>
27 #include <cstring>
28 #include <vector>
29 #include <sstream>
30
31 struct FlagDesc {
32         const char *name;
33         u32 flag;
34 };
35
36 static inline std::string padStringRight(std::string s, size_t len)
37 {
38         if(len > s.size())
39                 s.insert(s.end(), len - s.size(), ' ');
40         return s;
41 }
42
43 // ends: NULL- or ""-terminated array of strings
44 // Returns "" if no end could be removed.
45 static inline std::string removeStringEnd(const std::string &s, const char *ends[])
46 {
47         const char **p = ends;
48         for(; (*p) && (*p)[0] != '\0'; p++){
49                 std::string end = *p;
50                 if(s.size() < end.size())
51                         continue;
52                 if(s.substr(s.size()-end.size(), end.size()) == end)
53                         return s.substr(0, s.size() - end.size());
54         }
55         return "";
56 }
57
58 // Tests if two strings are equal, optionally case insensitive
59 inline bool str_equal(const std::wstring& s1, const std::wstring& s2,
60                 bool case_insensitive = false)
61 {
62         if(case_insensitive)
63         {
64                 if(s1.size() != s2.size())
65                         return false;
66                 for(size_t i = 0; i < s1.size(); ++i)
67                         if(tolower(s1[i]) != tolower(s2[i]))
68                                 return false;
69                 return true;
70         }
71         else
72         {
73                 return s1 == s2;
74         }
75 }
76
77 // Tests if the second string is a prefix of the first, optionally case insensitive
78 inline bool str_starts_with(const std::wstring& str, const std::wstring& prefix,
79                 bool case_insensitive = false)
80 {
81         if(str.size() < prefix.size())
82                 return false;
83         if(case_insensitive)
84         {
85                 for(size_t i = 0; i < prefix.size(); ++i)
86                         if(tolower(str[i]) != tolower(prefix[i]))
87                                 return false;
88         }
89         else
90         {
91                 for(size_t i = 0; i < prefix.size(); ++i)
92                         if(str[i] != prefix[i])
93                                 return false;
94         }
95         return true;
96 }
97
98 inline std::wstring narrow_to_wide(const std::string& mbs)
99 {
100         size_t wcl = mbs.size();
101         Buffer<wchar_t> wcs(wcl+1);
102         size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
103         if(l == (size_t)(-1))
104                 return L"<invalid multibyte string>";
105         wcs[l] = 0;
106         return *wcs;
107 }
108
109 inline std::string wide_to_narrow(const std::wstring& wcs)
110 {
111         size_t mbl = wcs.size()*4;
112         SharedBuffer<char> mbs(mbl+1);
113         size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
114         if(l == (size_t)(-1))
115                 mbs[0] = 0;
116         else
117                 mbs[l] = 0;
118         return *mbs;
119 }
120
121 // Split a string using the given delimiter. Returns a vector containing
122 // the component parts.
123 inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
124 {
125         std::vector<std::wstring> parts;
126         std::wstringstream sstr(str);
127         std::wstring part;
128         while(std::getline(sstr, part, delimiter))
129                 parts.push_back(part);
130         return parts;
131 }
132
133 inline std::string lowercase(const std::string &s)
134 {
135         std::string s2;
136         for(size_t i=0; i<s.size(); i++)
137         {
138                 char c = s[i];
139                 if(c >= 'A' && c <= 'Z')
140                         c -= 'A' - 'a';
141                 s2 += c;
142         }
143         return s2;
144 }
145
146 inline bool is_yes(const std::string &s)
147 {
148         std::string s2 = lowercase(trim(s));
149         if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
150                 return true;
151         return false;
152 }
153
154 inline s32 mystoi(const std::string &s, s32 min, s32 max)
155 {
156         s32 i = atoi(s.c_str());
157         if(i < min)
158                 i = min;
159         if(i > max)
160                 i = max;
161         return i;
162 }
163
164
165 // MSVC2010 includes it's own versions of these
166 //#if !defined(_MSC_VER) || _MSC_VER < 1600
167
168 inline s32 mystoi(const std::string &s)
169 {
170         return atoi(s.c_str());
171 }
172
173 inline s32 mystoi(const std::wstring &s)
174 {
175         return atoi(wide_to_narrow(s).c_str());
176 }
177
178 inline float mystof(const std::string &s)
179 {
180         // This crap causes a segfault in certain cases on MinGW
181         /*float f;
182         std::istringstream ss(s);
183         ss>>f;
184         return f;*/
185         // This works in that case
186         return atof(s.c_str());
187 }
188
189 //#endif
190
191 #define stoi mystoi
192 #define stof mystof
193
194 inline std::string itos(s32 i)
195 {
196         std::ostringstream o;
197         o<<i;
198         return o.str();
199 }
200
201 inline std::string ftos(float f)
202 {
203         std::ostringstream o;
204         o<<f;
205         return o.str();
206 }
207
208 inline void str_replace(std::string & str, std::string const & pattern,
209                 std::string const & replacement)
210 {
211         std::string::size_type start = str.find(pattern, 0);
212         while(start != str.npos)
213         {
214                 str.replace(start, pattern.size(), replacement);
215                 start = str.find(pattern, start+replacement.size());
216         }
217 }
218
219 inline void str_replace_char(std::string & str, char from, char to)
220 {
221         for(unsigned int i=0; i<str.size(); i++)
222         {
223                 if(str[i] == from)
224                         str[i] = to;
225         }
226 }
227
228 /*
229         Checks if a string contains only supplied characters
230 */
231 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
232 {
233         for(u32 i=0; i<s.size(); i++)
234         {
235                 bool confirmed = false;
236                 for(u32 j=0; j<allowed_chars.size(); j++)
237                 {
238                         if(s[i] == allowed_chars[j])
239                         {
240                                 confirmed = true;
241                                 break;
242                         }
243                 }
244                 if(confirmed == false)
245                         return false;
246         }
247         return true;
248 }
249
250 /*
251         Checks if a string contains no blacklisted characters (opposite
252         function of string_allowed())
253 */
254 inline bool string_allowed_blacklist(const std::string & s, const std::string & blacklisted_chars)
255 {
256         for(unsigned int i = 0; i < s.length(); i++)
257         {
258                 bool invalid = false;
259                 for(unsigned int j = 0; j < blacklisted_chars.length(); j++)
260                 {
261                         if(s[i] == blacklisted_chars[j])
262                         {
263                                 invalid = true;
264                                 break;
265                         }
266                 }
267                 if(invalid)
268                         return false;
269         }
270         return true;
271 }
272
273 /*
274         Forcefully wraps string into rows using \n
275         (no word wrap, used for showing paths in gui)
276 */
277 inline std::string wrap_rows(const std::string &from, u32 rowlen)
278 {
279         std::string to;
280         for(u32 i=0; i<from.size(); i++)
281         {
282                 if(i != 0 && i%rowlen == 0)
283                         to += '\n';
284                 to += from[i];
285         }
286         return to;
287 }
288
289 std::string translatePassword(std::string playername, std::wstring password);
290 size_t curl_write_data(char *ptr, size_t size, size_t nmemb, void *userdata);
291 u32 readFlagString(std::string str, FlagDesc *flagdesc);
292 std::string writeFlagString(u32 flags, FlagDesc *flagdesc);
293 char *mystrtok_r(char *s, const char *sep, char **lasts);
294
295 #endif
296