Diligent Engine  v.2.4.g
StringTools.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019-2021 Diligent Graphics LLC
3  * Copyright 2015-2019 Egor Yusov
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * In no event and under no legal theory, whether in tort (including negligence),
18  * contract, or otherwise, unless required by applicable law (such as deliberate
19  * and grossly negligent acts) or agreed to in writing, shall any Contributor be
20  * liable for any damages, including any direct, indirect, special, incidental,
21  * or consequential damages of any character arising as a result of this License or
22  * out of the use or inability to use the software (including but not limited to damages
23  * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
24  * all other commercial damages or losses), even if such Contributor has been advised
25  * of the possibility of such damages.
26  */
27 
28 #pragma once
29 
30 #include <string>
31 #include <sstream>
32 #include <locale>
33 #include <algorithm>
34 #include <cctype>
35 #include <string.h>
36 
37 #include "../../Platforms/Basic/interface/DebugUtilities.hpp"
38 
39 namespace Diligent
40 {
41 
42 inline std::string NarrowString(const std::wstring& WideStr)
43 {
44  std::string NarrowStr;
45 
46  const std::ctype<wchar_t>& ctfacet = std::use_facet<std::ctype<wchar_t>>(std::wstringstream().getloc());
47  for (std::wstring::const_iterator CurrWChar = WideStr.begin();
48  CurrWChar != WideStr.end();
49  CurrWChar++)
50  NarrowStr.push_back(ctfacet.narrow(*CurrWChar, 0));
51 
52  return NarrowStr;
53 }
54 
55 inline std::string NarrowString(const wchar_t* WideStr)
56 {
57  std::string NarrowStr;
58 
59  const std::ctype<wchar_t>& ctfacet = std::use_facet<std::ctype<wchar_t>>(std::wstringstream().getloc());
60  for (auto CurrWChar = WideStr; *CurrWChar != 0; ++CurrWChar)
61  NarrowStr.push_back(ctfacet.narrow(*CurrWChar, 0));
62 
63  return NarrowStr;
64 }
65 
66 inline std::wstring WidenString(const char* Str)
67 {
68  std::wstring WideStr;
69 
70  const std::ctype<wchar_t>& ctfacet = std::use_facet<std::ctype<wchar_t>>(std::wstringstream().getloc());
71  for (auto CurrChar = Str; *CurrChar != 0; ++CurrChar)
72  WideStr.push_back(ctfacet.widen(*CurrChar));
73 
74  return WideStr;
75 }
76 
77 inline std::wstring WidenString(const std::string& Str)
78 {
79  std::wstring WideStr;
80 
81  const std::ctype<wchar_t>& ctfacet = std::use_facet<std::ctype<wchar_t>>(std::wstringstream().getloc());
82  for (std::string::const_iterator CurrChar = Str.begin();
83  CurrChar != Str.end();
84  CurrChar++)
85  WideStr.push_back(ctfacet.widen(*CurrChar));
86 
87  return WideStr;
88 }
89 
90 inline int StrCmpNoCase(const char* Str1, const char* Str2, size_t NumChars)
91 {
92 #if PLATFORM_ANDROID || PLATFORM_LINUX || PLATFORM_MACOS || PLATFORM_IOS
93 # define _strnicmp strncasecmp
94 #endif
95 
96  return _strnicmp(Str1, Str2, NumChars);
97 }
98 
99 inline int StrCmpNoCase(const char* Str1, const char* Str2)
100 {
101 #if PLATFORM_ANDROID || PLATFORM_LINUX || PLATFORM_MACOS || PLATFORM_IOS
102 # define _stricmp strcasecmp
103 #endif
104 
105  return _stricmp(Str1, Str2);
106 }
107 
108 // Returns true if RefStr == Str + Suff
109 // If Suff == nullptr or NoSuffixAllowed == true, also returns true if RefStr == Str
110 inline bool StreqSuff(const char* RefStr, const char* Str, const char* Suff, bool NoSuffixAllowed = false)
111 {
112  VERIFY_EXPR(RefStr != nullptr && Str != nullptr);
113  if (RefStr == nullptr)
114  return false;
115 
116  const auto* r = RefStr;
117  const auto* s = Str;
118  // abc_def abc
119  // ^ ^
120  // r s
121  for (; *r != 0 && *s != 0; ++r, ++s)
122  {
123  if (*r != *s)
124  {
125  // abc_def abx
126  // ^ ^
127  // r s
128  return false;
129  }
130  }
131 
132  if (*s != 0)
133  {
134  // ab abc
135  // ^ ^
136  // r s
137  VERIFY_EXPR(*r == 0);
138  return false;
139  }
140  else
141  {
142  // abc_def abc
143  // ^ ^
144  // r s
145 
146  if (NoSuffixAllowed && *r == 0)
147  {
148  // abc abc _def
149  // ^ ^
150  // r s
151  return true;
152  }
153 
154  if (Suff != nullptr)
155  {
156  // abc_def abc _def
157  // ^ ^ ^
158  // r s Suff
159  return strcmp(r, Suff) == 0;
160  }
161  else
162  {
163  // abc abc abc_def abc
164  // ^ ^ or ^ ^
165  // r s r s
166  return *r == 0;
167  }
168  }
169 }
170 
171 inline void StrToLowerInPlace(std::string& str)
172 {
173  std::transform(str.begin(), str.end(), str.begin(),
174  // http://en.cppreference.com/w/cpp/string/byte/tolower
175  [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
176 }
177 
178 inline std::string StrToLower(std::string str)
179 {
180  StrToLowerInPlace(str);
181  return str;
182 }
183 
184 inline bool IsNum(char c)
185 {
186  return c >= '0' && c <= '9';
187 }
188 
191 inline size_t CountFloatNumberChars(const char* str)
192 {
193  if (str == nullptr)
194  return 0;
195 
196  const auto* num_end = str;
197  const auto* c = str;
198  if (*c == 0)
199  return 0;
200 
201  if (*c == '+' || *c == '-')
202  ++c;
203 
204  if (*c == 0)
205  return 0;
206 
207  if (*c == '0' && IsNum(*(c + 1)))
208  {
209  // 01 is invalid
210  return c - str + 1;
211  }
212 
213  while (IsNum(*c))
214  num_end = ++c;
215 
216  if (*c == '.')
217  {
218  if (c != str && IsNum(c[-1]))
219  {
220  // . as well as +. or -. are not valid numbers, however 0., +0., and -0. are.
221  num_end = c + 1;
222  }
223 
224  ++c;
225  while (IsNum(*c))
226  num_end = ++c;
227 
228  if (*c == 'e' || *c == 'E')
229  {
230  if (c - str < 2 || !IsNum(c[-2]))
231  {
232  // .e as well as +.e are invalid
233  return num_end - str;
234  }
235  }
236  }
237  else if (*c == 'e' || *c == 'E')
238  {
239  if (c - str < 1 || !IsNum(c[-1]))
240  {
241  // e as well as e+1 are invalid
242  return num_end - str;
243  }
244  }
245 
246  if (*c == 'e' || *c == 'E')
247  {
248  ++c;
249  if (*c != '+' && *c != '-')
250  return num_end - str;
251 
252  ++c;
253  while (IsNum(*c))
254  num_end = ++c;
255  }
256 
257  return num_end - str;
258 }
259 
260 } // namespace Diligent
Diligent::StreqSuff
bool StreqSuff(const char *RefStr, const char *Str, const char *Suff, bool NoSuffixAllowed=false)
Definition: StringTools.hpp:110
Diligent::CountFloatNumberChars
size_t CountFloatNumberChars(const char *str)
Returns the number of chararcters at the beginning of the string that form a floating point number.
Definition: StringTools.hpp:191
Diligent::WidenString
std::wstring WidenString(const char *Str)
Definition: StringTools.hpp:66
Diligent::StrToLowerInPlace
void StrToLowerInPlace(std::string &str)
Definition: StringTools.hpp:171
Diligent::IsNum
bool IsNum(char c)
Definition: StringTools.hpp:184
Diligent::NarrowString
std::string NarrowString(const std::wstring &WideStr)
Definition: StringTools.hpp:42
VERIFY_EXPR
#define VERIFY_EXPR(...)
Definition: DebugUtilities.hpp:79
Diligent::StrCmpNoCase
int StrCmpNoCase(const char *Str1, const char *Str2, size_t NumChars)
Definition: StringTools.hpp:90
Diligent::StrToLower
std::string StrToLower(std::string str)
Definition: StringTools.hpp:178
Diligent
The library uses Direct3D-style math:
Definition: AdvancedMath.hpp:37