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 using namespace Hazelnp;
4 
5 bool 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 
14 std::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 
27 std::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 
56 bool 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 
82 bool 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 
125 std::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 
132 std::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 
173 std::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 }
Hazelnp
Definition: CmdArgsInterface.h:7
Hazelnp::Internal::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:5
Hazelnp::Internal::StringTools::ToLower
static std::string ToLower(const std::string &str)
Will make a string all lower-case.
Definition: StringTools.cpp:173
Hazelnp::Internal::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:14
Hazelnp::Internal::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:82
Hazelnp::Internal::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:125
Hazelnp::Internal::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:56
StringTools.h