Meteor2D  dev internal
Meteor is a lightweight 2D game engine.
Loading...
Searching...
No Matches
str_extensions.h
1#pragma once
2/*
3 * Developed by Guillaume Gomez <guillaume.gomez@gmail.com>.
4 * This header file has been created to make operations on string easier.
5 *
6 * List of functions:
7 * - getValueFromString
8 * - toString
9 * - split
10 * - join
11 * - getBetween
12 * - getListOfItem
13 * - replace
14 * - numberOfOccurence
15 * - truncate
16 */
17
18
19#ifndef __STRING_UTILS__
20#define __STRING_UTILS__
21
22#include <string>
23#include <sstream>
24#include <vector>
25#include <iostream>
26#include <cstring>
27#include <regex>
28
29namespace string_utils
30{
31
32 inline bool isInt(const std::string& val) {
33 std::regex r_int =
34 std::regex("[\\+-]?((\\d+(\\.(0*))?)(e[\\+]?\\d+)?)", std::regex::icase);
35
36 return std::regex_match(val, r_int);
37 }
38
39 /*
40 * Checks if `val` is any kind of float.
41 */
42 inline bool isFloat(const std::string& val) {
43 std::regex r_float = std::regex(
44 "[\\+-]?(((\\d*\\.\\d+)|(\\d+(\\.(0*))?))(e[\\+-]?((\\d*\\.\\d+)|(\\d+(\\.(0*))?)))?)",
45 std::regex::icase);
46
47 return std::regex_match(val, r_float);
48 }
49
50
51 // get a value from a string, for example :
52 // getValueFromString<int>("42") -> 42
53 template<typename T>
54 inline T getValueFromString(std::string const& s)
55 {
56 T var(0);
57 std::istringstream iss;
58
59 if (s != "")
60 {
61 iss.str(s);
62 iss >> var;
63 }
64 return var;
65 }
66
67 template<>
68 inline std::string getValueFromString<std::string>(std::string const& s)
69 {
70 std::string tmp;
71
72 tmp = s;
73 return tmp;
74 }
75
76 template<typename T>
77 inline T getValueFromString(const char* s)
78 {
79 std::string str;
80
81 if (s)
82 str = s;
83 return getValueFromString<T>(str);
84 }
85
86 // convert a value into a string, for example :
87 // toString<int>(42) -> "42"
88 // toString<float>(42.4f) -> "42.4f"
89 template<typename T>
90 std::string toString(T const& var)
91 {
92 std::ostringstream oss;
93 std::string s;
94
95 oss << var;
96 s = oss.str();
97 return s;
98 }
99
100 // splits the string into substrings wherever key occurs, example :
101 // split<std::string>("salut les amis", " ") -> std::vector<std::string>{"salut", "les", "amis"}
102 // if you want to keep empty parts, just set the last argument to true, example :
103 // split<std::string>("salut les amis", " ", true) -> std::vector<std::string>{"salut", "les", "", "", "amis"}
104 template<typename T, typename U>
105 std::vector<U> split(T const& value, const char* key, bool keepEmptyPart = false)
106 {
107 std::vector<U> result;
108 size_t pos;
109 std::string sub;
110 int size;
111 std::string copy(toString<T>(value));
112
113 if (!key)
114 return result;
115 size = strlen(key);
116 while ((pos = copy.find(key)) != std::string::npos)
117 {
118 sub = copy.substr(0, pos);
119 copy.erase(0, pos + size);
120 if (!sub.empty() || keepEmptyPart)
121 result.push_back(getValueFromString<U>(sub));
122 }
123 if (copy != "")
124 result.push_back(getValueFromString<U>(copy));
125 return result;
126 }
127
128 template<typename T, typename U>
129 std::vector<U> split(T const& value, std::string const& key, bool keepEmptyPart = false)
130 {
131 return split<T, U>(value, key.c_str(), keepEmptyPart);
132 }
133
134 // join every elements of the vector in a single string,
135 // separated by the given separator. For example :
136 // join<std::string>(std::vector<std::string>{"salut", "les", "amis"}, "/") ->
137 // "salut/les/amis"
138 template<typename T>
139 std::string join(std::vector<T> const& c, const char* separator)
140 {
141 std::ostringstream os;
142 unsigned int i(0);
143 std::string str;
144
145 while (i < c.size())
146 {
147 os.str("");
148 os.clear();
149 os << c[i++];
150 str += os.str();
151 if (i < c.size() && separator)
152 str += separator;
153 }
154 return str;
155 }
156
157 template<typename T>
158 std::string join(std::vector<T> const& c, std::string const& separator)
159 {
160 return join<T>(c, separator.c_str());
161 }
162
163 // return the value between the two given keys, example :
164 // getBetween<int>("et42tralala", "et", "tralala") -> 42
165 template<typename T>
166 T getBetween(std::string const& c, const char* key1, const char* key2)
167 {
168 size_t pos1, pos2;
169
170 if (!key1 || !key2 ||
171 (pos1 = c.find(key1)) == std::string::npos ||
172 (pos2 = c.find(key2)) == std::string::npos)
173 return getValueFromString<T>("");
174 pos1 += strlen(key1);
175 if (pos1 >= pos2)
176 return getValueFromString<T>("");
177 return getValueFromString<T>(c.substr(pos1, pos2 - pos1).c_str());
178 }
179
180 template<typename T>
181 T getBetween(const char* st, const char* key1, const char* key2)
182 {
183 std::string str;
184
185 if (st)
186 str = st;
187 return getBetween<T>(str, key1, key2);
188 }
189
190 // return a vector with every values between the two keys, example :
191 // getListOfItem<int>("<a>42</a><b><s>tralala</s><s>bis</s><a>39</a></b>") ->
192 // std::vector<int>{42, 39}
193 template<typename T>
194 std::vector<T> getListOfItem(std::string st, const char* key1, const char* key2)
195 {
196 std::vector<T> vec;
197 std::string str;
198 size_t find;
199 int length(key2 ? strlen(key2) : 0);
200
201 str = getBetween<T>(st, key1, key2);
202 for (; !str.empty(); str = getBetween<T>(st, key1, key2))
203 {
204 vec.push_back(str);
205 if ((find = st.find(key1)) == std::string::npos)
206 return vec;
207 st.erase(find, str.size() + length);
208 }
209 return vec;
210 }
211
212 template<typename T>
213 std::vector<T> getListOfItem(const char* st, const char* key1, const char* key2)
214 {
215 std::string s;
216
217 if (st)
218 s = st;
219 return getListOfItem<T>(s, key1, key2);
220 }
221
222 // replace every occurences of the specified substring (toReplace) by another one (replacement)
223 // in the given argument (s), example :
224 // replace<std::string>("salut les d'jeuns !", " ", "/") -> "salut/les/d'jeuns/!"
225 template<typename T>
226 std::string replace(T const& s, const char* toReplace, const char* replacement)
227 {
228 std::vector<T> vec;
229
230 if (!toReplace || !replacement)
231 return toString<T>(s);
232 vec = split<T, T>(s, toReplace);
233 return join<T>(vec, replacement);
234 }
235
236 template<typename T>
237 std::string replace(T const& s, std::string const& toReplace,
238 std::string const& replacement)
239 {
240 return replace<T>(s, toReplace.c_str(), replacement.c_str());
241 }
242
243 template<typename T>
244 std::string replace(T const& s, const char* toReplace,
245 std::string const& replacement)
246 {
247 return replace<T>(s, toReplace, replacement.c_str());
248 }
249
250 template<typename T>
251 std::string replace(T const& s, std::string const& toReplace,
252 const char* replacement)
253 {
254 return replace<T>(s, toReplace.c_str(), replacement);
255 }
256
257 // return the number of occurences of the given argument (toFind) in the given string (s)
258 // example : numberOfOccurence("bonjour les gens", " ") -> 2
259 template<typename T>
260 unsigned int numberOfOccurence(std::string const& s, T toFind)
261 {
262 std::string tmp(toString<T>(toFind)), tmp2(s);
263 unsigned int found(0);
264 size_t pos(0);
265
266 if (s == "" || toFind == "")
267 return 0;
268 while ((pos = tmp2.find(tmp, 0)) != std::string::npos) {
269 ++found;
270 tmp2.erase(0, pos + 1);
271 }
272 return found;
273 }
274
275 template<typename T>
276 unsigned int numberOfOccurence(char const* s, T toFind)
277 {
278 std::string tmp(s ? s : "");
279
280 if (tmp == "")
281 return 0;
282 return numberOfOccurence<T>(tmp, toFind);
283 }
284
285 // truncate the given parameter at the given position
286 template<typename T>
287 T truncate(T& s, unsigned int position)
288 {
289 std::string tmp = toString<T>(s);
290
291 if (position < tmp.length())
292 tmp.resize(position);
293 return getValueFromString<T>(tmp);
294 }
295}
296
297#endif