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