Enigma  3.2.0
A Simple, Reliable and Efficient Encryption Tool
StringUtils.hpp
Go to the documentation of this file.
1 #pragma once
2 #ifndef ENIGMA_STRING_UTILS_H
3 #define ENIGMA_STRING_UTILS_H
4 
5 #include <Core/Types.hpp> // Enigma Types
6 
7 #include <algorithm> // std::all_of
8 #include <codecvt> // helps converting between UTF-X strings
9 #include <locale> // required for Linux & Darwin causes error: �wstring_convert� is not a member of �std�
10 #include <sstream> // std::stringstream
11 #include <string> // std::string, std::string_view
12 #include <utility> // std::transform
13 #include <vector>
14 
16 /*
17 * UTF-8 & UTF-16 std::string Utility
18 */
19 class StringUtils final {
20  ENIGMA_STATIC_CLASS(StringUtils);
21 
22  public:
23  /*
24  * Removes leading and trailing spaces from a string
25  */
26  template<typename StringType>
27  static void Trim(StringType& str) {
28  TrimLeft(str);
29  TrimRight(str);
30  }
31 
32 
33  /*
34  * Trim string from left
35  */
36  template<typename StringType>
37  static void TrimLeft(StringType& str) {
38  str.erase(str.begin(), std::find_if(str.begin(), str.end(), [](const auto& c) {
39  return !std::isspace(c);
40  }));
41  }
42 
43 
44  /*
45  * Trim string from right
46  */
47  template<typename StringType>
48  static void TrimRight(StringType& str) {
49  str.erase(std::find_if(str.rbegin(), str.rend(), [](const auto& c) {
50  return !std::isspace(c);
51  }).base(),
52  str.end());
53  }
54 
55 
56  /*
57  * Lowercase a string
58  */
59  template<typename StringType>
60  static void Lower(StringType& str) {
61  std::transform(str.begin(), str.end(), str.begin(), [](const auto& c) {
62  return static_cast<typename StringType::value_type>(std::tolower(c));
63  });
64  }
65 
66 
67  /*
68  * Lowercase a string and return a copy of it
69  */
70  template<typename StringType>
71  static auto LowerCopy(const StringType& str) {
72  StringType cstr = str;
73  std::transform(cstr.begin(), cstr.end(), cstr.begin(), [](const auto& c) {
74  return static_cast<typename StringType::value_type>(std::tolower(c));
75  });
76  return cstr;
77  }
78 
79 
80  /*
81  * Uppercase a string
82  */
83  template<typename StringType>
84  static void Upper(StringType& str) {
85  std::transform(str.begin(), str.end(), str.begin(), [](const auto& c) {
86  return static_cast<typename StringType::value_type>(std::toupper(c));
87  });
88  }
89 
90 
91  /*
92  * Uppercase a string and return a copy of it
93  */
94  template<typename StringType>
95  static auto UpperCopy(const StringType& str) {
96  StringType cstr = str;
97  std::transform(cstr.begin(), cstr.end(), cstr.begin(), [](const auto& c) {
98  return static_cast<typename StringType::value_type>(std::toupper(c));
99  });
100  return cstr;
101  }
102 
103 
104  /*
105  * Check if a string starts with a prefix
106  */
107  template<typename StringType>
108  static bool StartsWith(const StringType& str, const StringType& prefix) {
109  return str.size() >= prefix.size() && str.compare(0, prefix.size(), prefix) == 0;
110  }
111 
112 
113  /*
114  * Check if a string ends with a suffix
115  */
116  template<typename StringType>
117  static bool EndsWith(const StringType& str, const StringType& suffix) {
118  return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
119  }
120 
121  /*
122  * Splits string at a delimiter into parts
123  */
124  template<typename StringType>
125  static std::vector<StringType> Split(const StringType& str, const typename std::string::value_type delimiter) {
126  std::vector<StringType> parts{};
127  std::stringstream ss(str);
128  std::string line{};
129  while (std::getline(ss, line, delimiter)) {
130  parts.push_back(line);
131  }
132  return parts;
133  }
134 
135  /*
136  * Check if a string contains another
137  */
138  template<typename StringType>
139  static bool Contains(const StringType& str, const StringType& other) {
140  return str.find(other) != StringType::npos;
141  }
142 
143 
144  /*
145  * Converts UTF-8 std::string to UTF-16 std::wstring
146  */
147  static std::wstring StringToWString(const std::string& str) {
148  using convert_type = std::codecvt_utf8<wchar_t>;
149  static std::wstring_convert<convert_type, wchar_t> converter;
150  return converter.from_bytes(str);
151  }
152 
153 
154  /*
155  * Converts UTF-16 std::wstring to UTF-8 std::string
156  */
157  static std::string WStringToString(const std::wstring& wstr) {
158  using convert_type = std::codecvt_utf8<wchar_t>;
159  static std::wstring_convert<convert_type, wchar_t> converter;
160  return converter.to_bytes(wstr);
161  }
162 
163 
164  /*
165  * Convert string to any other simple type
166  */
167  template<typename T, typename StringType>
168  static T To(const StringType& str) {
169  T t{};
170  std::basic_stringstream<typename StringType::value_type> ss(str);
171  ss >> t;
172  return t;
173  }
174 
175 #if 0
176 
177  /*
178  * Cleanup a string (remove string from string)
179  */
180  static std::string Cleanup(const std::string& expr, const std::string& remove)
181  {
182  const std::size_t N = expr.size();
183  const std::size_t K = remove.size();
184  std::string result(N, '\000');
185  std::size_t srcIndex = 0;
186  std::size_t dstIndex = 0;
187  while (srcIndex < N)
188  {
189  std::size_t matchIndex = 0;
190  while (matchIndex < K - 1 && srcIndex + matchIndex < N - 1 && expr[srcIndex + matchIndex] == remove[matchIndex])
191  {
192  matchIndex++;
193  if (matchIndex == K - 1)
194  srcIndex += matchIndex;
195  }
196  result[dstIndex++] = expr[srcIndex] == '"' ? '\'' : expr[srcIndex];
197  srcIndex++;
198  }
199  result.resize(dstIndex, '\000'); // resize to fit string after removing other str
200  return result;
201  }
202  static std::wstring Cleanup(const std::wstring& expr, const std::wstring& remove)
203  {
204  const std::size_t N = expr.size();
205  const std::size_t K = remove.size();
206  std::wstring result(N, L'\000');
207  std::size_t srcIndex = 0;
208  std::size_t dstIndex = 0;
209  while (srcIndex < N)
210  {
211  std::size_t matchIndex = 0;
212  while (matchIndex < K - 1 && srcIndex + matchIndex < N - 1 && expr[srcIndex + matchIndex] == remove[matchIndex])
213  matchIndex++;
214  if (matchIndex == K - 1)
215  srcIndex += matchIndex;
216  result[dstIndex++] = expr[srcIndex] == '"' ? '\'' : expr[srcIndex];
217  srcIndex++;
218  }
219  result.resize(dstIndex, L'\000'); // resize to fit string after removing other str
220  return result;
221  }
222 
223  template <std::size_t N>
224  struct CleanupResult // wrapper to keep data variable alive in the stack after going out of scope of Cleanup function
225  {
226  char data[N];
227  };
228  template <std::size_t N, std::size_t K>
229  static auto Cleanup(const char(&expr)[N], const char(&remove)[K])
230  {
231  CleanupResult<N> result{};
232  std::size_t srcIndex = 0;
233  std::size_t dstIndex = 0;
234  //while constexpr (srcIndex < N)
235  while (srcIndex < N)
236  {
237  std::size_t matchIndex = 0;
238  while (matchIndex < K - 1 && srcIndex + matchIndex < N - 1 && expr[srcIndex + matchIndex] == remove[matchIndex])
239  matchIndex++;
240  if (matchIndex == K - 1)
241  srcIndex += matchIndex;
242  result.data[dstIndex++] = expr[srcIndex] == '"' ? '\'' : expr[srcIndex];
243  srcIndex++;
244  }
245  return result;
246  }
247 #endif
248 };
250 
251 #endif // !ENIGMA_STRING_UTILS_H
#define NS_ENIGMA_BEGIN
Enable/Disable Assertions.
Definition: Macros.hpp:13
#define NS_ENIGMA_END
Definition: Macros.hpp:14
static std::vector< StringType > Split(const StringType &str, const typename std::string::value_type delimiter)
static T To(const StringType &str)
static void Upper(StringType &str)
Definition: StringUtils.hpp:84
static std::wstring StringToWString(const std::string &str)
static auto LowerCopy(const StringType &str)
Definition: StringUtils.hpp:71
static void Lower(StringType &str)
Definition: StringUtils.hpp:60
static auto UpperCopy(const StringType &str)
Definition: StringUtils.hpp:95
static std::string WStringToString(const std::wstring &wstr)
static void Trim(StringType &str)
Definition: StringUtils.hpp:27
static bool Contains(const StringType &str, const StringType &other)
static void TrimRight(StringType &str)
Definition: StringUtils.hpp:48
static bool EndsWith(const StringType &str, const StringType &suffix)
static void TrimLeft(StringType &str)
Definition: StringUtils.hpp:37
static bool StartsWith(const StringType &str, const StringType &prefix)