Leonetienne/Hazelnupp
Simple, easy to use, command line parameter interface
StringTools.cpp
Go to the documentation of this file.
2
3using namespace Hazelnp;
4
5bool Internal::StringTools::Contains(const std::string& str, const char c)
6{
7 for (const char& i : str)
8 if (i == c)
9 return true;
10
11 return false;
12}
13
14std::string Internal::StringTools::Replace(const std::string& str, const char find, const std::string& subst)
15{
16 std::stringstream ss;
17
18 for (std::size_t i = 0; i < str.length(); i++)
19 {
20 if (str[i] != find) ss << str[i];
21 else ss << subst;
22 }
23
24 return ss.str();
25}
26
27std::string Internal::StringTools::Replace(const std::string& str, const std::string& find, const std::string& subst)
28{
29 if (find.length() == 0) return str;
30
31 std::stringstream ss;
32
33 std::size_t posFound = 0;
34 std::size_t lastFound = 0;
35
36 while (posFound != std::string::npos)
37 {
38 lastFound = posFound;
39 posFound = str.find(find, posFound);
40
41 if (posFound != std::string::npos)
42 {
43 ss << str.substr(lastFound, posFound - lastFound) << subst;
44 posFound += find.length();
45 }
46 else
47 {
48 ss << str.substr(lastFound, (str.length()) - lastFound);
49 }
50 }
51
52 return ss.str();
53}
54
55
56bool Internal::StringTools::IsNumeric(const std::string& str, const bool allowDecimalPoint)
57{
58 if (str.length() == 0) return false;
59
60 bool alreadyParsedDecimalPoint = false;
61 std::size_t digitCount = 0;
62
63 for (std::size_t i = 0; i < str.length(); i++)
64 {
65 if (!(
66 ((str[i] >= '0') && (str[i] <= '9')) ||
67 ((str[i] == '-') && (i == 0)) ||
68 ((str[i] == '.') && (allowDecimalPoint) && (!alreadyParsedDecimalPoint) && (digitCount > 0))
69 )) return false;
70
71
72 // Here we just have to check for the character. Not for any other conditions.
73 // Why? Because if these conditions failed, the function would have already returned false.
74 if (((str[i] >= '0') && (str[i] <= '9'))) digitCount++;
75 if (str[i] == '.') alreadyParsedDecimalPoint = true;
76 }
77
78 // Even if we did not find any invalid chars, we should still return false, if we found no digits at all.
79 return digitCount > 0;
80}
81
82bool Internal::StringTools::ParseNumber(const std::string& str, bool& out_isInt, long double& out_number)
83{
84 bool isDecimal = false;
85
86 if (str.length() == 0) return false;
87 if (Contains(str, '.')) isDecimal = true;
88
89 if (isDecimal)
90 {
91 try
92 {
93 out_number = std::stold(str);
94 out_isInt = false;
95 }
96 catch (std::invalid_argument&)
97 {
98 return false;
99 }
100 catch (std::out_of_range&)
101 {
102 return false;
103 }
104 }
105 else
106 {
107 try
108 {
109 out_number = (long double)std::stoll(str);
110 out_isInt = true;
111 }
112 catch (std::invalid_argument&)
113 {
114 return false;
115 }
116 catch (std::out_of_range&)
117 {
118 return false;
119 }
120 }
121
122 return true;
123}
124
125std::vector<std::string> Internal::StringTools::SplitString(const std::string& str, const char delimiter)
126{
127 if (str.length() == 0) return std::vector<std::string>();
128
129 return SplitString(str, delimiter);
130}
131
132std::vector<std::string> Internal::StringTools::SplitString(const std::string& str, const std::string& delimiter)
133{
134 if (str.length() == 0) return std::vector<std::string>();
135
136 std::vector<std::string> parts;
137
138 if (delimiter.length() == 0) // If the delimiter is "" (empty), just split between every single char. Not useful, but logical
139 {
140 for (std::size_t i = 0; i < str.length(); i++)
141 {
142 parts.push_back(std::string({ str[i] }));
143 }
144 return parts;
145 }
146
147 std::size_t posFound = 0;
148 std::size_t lastFound = 0;
149
150 while (posFound != std::string::npos)
151 {
152 lastFound = posFound;
153 posFound = str.find(delimiter, posFound);
154
155 std::string found;
156
157 if (posFound != std::string::npos)
158 {
159 found = str.substr(lastFound, posFound - lastFound);
160 posFound += delimiter.length();
161 }
162 else
163 {
164 found = str.substr(lastFound, str.length() - lastFound);
165 }
166
167 parts.push_back(found);
168 }
169
170 return parts;
171}
172
173std::string Internal::StringTools::ToLower(const std::string& str)
174{
175 std::stringstream ss;
176 for (std::size_t i = 0; i < str.length(); i++)
177 {
178 if ((str[i] >= 'A') && (str[i] <= 'Z')) ss << (char)(((int)str[i]) + 32);
179 else if (str[i] == -60) ss << (char)-28; // AE => ae
180 else if (str[i] == -42) ss << (char)-10; // OE => oe
181 else if (str[i] == -36) ss << (char)-4; // UE => ue
182 else ss << str[i];
183 }
184
185 return ss.str();
186}
static std::string ToLower(const std::string &str)
Will make a string all lower-case.
static bool IsNumeric(const std::string &str, const bool allowDecimalPoint=false)
Will return true if the given string consists only of digits (including signage)
Definition: StringTools.cpp:56
static bool ParseNumber(const std::string &str, bool &out_isInt, long double &out_number)
Will convert the number in str to a number.
Definition: StringTools.cpp:82
static std::vector< std::string > SplitString(const std::string &str, const char delimiter)
Will split a string by a delimiter char. The delimiter will be excluded!
static std::string Replace(const std::string &str, const char find, const std::string &subst)
Will replace a part of a string with another string.
Definition: StringTools.cpp:14