Itasca C++ Interface
basestring.h
Go to the documentation of this file.
1 #pragma once
7 #include "basedef.h"
8 #include "to.h"
9 #include <cctype>
10 #include <cwctype>
11 #include <string>
12 #include <vector>
13 #include <string_view>
14 #ifdef _WIN32
15 #include <codeanalysis\warnings.h>
16 #endif
17 
18 // Includes the header-only version of the fmt::format library, which we use for now until
19 // the C++20 std::format library is supported by Intel/VS
20 #define FMT_HEADER_ONLY
21 //#define FMT_API BASE_EXPORT
22 //#define FMT_EXTERN_TEMPLATE_API BASE_EXPORT
23 #ifdef _WIN32
24 # include <codeanalysis\warnings.h>
25 #endif
26 
27 INTELWARNING(186) // Pointless comparison of unsigned integer with zero
28 PUSHWARNING
29 VSWARNING(ALL_CODE_ANALYSIS_WARNINGS)
30 INTELWARNING(177)
31 INTELWARNING(280) // selector expression is constant
32 GNUWARNING("-Wstringop-overflow")
33 #ifdef CLANGCOMP
34 # pragma warning ( disable : ALL_CODE_ANALYSIS_WARNINGS ) // Nonstandard
35 #endif
36 #include "../fmt/format.h"
37 POPWARNING
38 
39 // Global namespace versions of std strings
40 using wstring = std::wstring; // Old string class to avoid interface compatibility breaks
41 using string = std::string; // Bring into global namespace like the other base types (uint32, etc)
42 //using String = std::wstring; // DEPRECATED - should not be used in new code.
43 
44 // String conversion routines.
45 // These return a tuple, the first is the converted value and the second is whether the conversion was successful.
46 // If not successful the first value is a default construction.
47 BASE_EXPORT std::tuple<int32,bool> isInt32(const string &in);
48 BASE_EXPORT std::tuple<uint32,bool> isUInt32(const string &in);
49 BASE_EXPORT std::tuple<int64,bool> isInt64(const string &in);
50 BASE_EXPORT std::tuple<uint64,bool> isUInt64(const string &in);
51 BASE_EXPORT std::tuple<double,bool> isDouble(const string &in);
52 BASE_EXPORT std::tuple<bool,bool> isBool(const string &in,const string &out="on,off,true,false,yes,no");
53 
54 // String conversion routines - converts string directly, throwing out the success check.
55 // No exception is thrown on failure - just returns a default constructed value.
56 // This is a common template used just to avoid code repetition in the type-specific version
57 template <typename T,typename ... Args>
58 T toStringConv(const string &in,Args...args,bool te, std::tuple<T,bool> (*f)(const string &,Args...)) {
59  auto [val, ok] = f(in,args...);
60  if (te==true && ok==false)
61 #ifdef __LINUX
62  throw std::runtime_error("String conversion error.");
63 #else
64  throw std::exception("String conversion error.");
65 #endif
66  return val;
67 }
68 inline int32 toInt32(const string &in, bool throwException = false) { return toStringConv<int32>(in, throwException, isInt32); }
69 inline uint32 toUInt32(const string &in,bool throwException=false) { return toStringConv<uint32>(in, throwException, isUInt32); }
70 inline int64 toInt64(const string &in,bool throwException=false) { return toStringConv<int64>(in, throwException, isInt64); }
71 inline uint64 toUInt64(const string &in,bool throwException=false) { return toStringConv<uint64>(in, throwException, isUInt64); }
72 inline double toDouble(const string &in,bool throwException=false) { return toStringConv<double>(in, throwException, isDouble); }
73 inline bool toBool(const string &in, const string &out = "on,off,true,false,yes,no", bool throwException = false) { return toStringConv<bool,const string &>(in, out, throwException, isBool); }
74 
75 
76 // vector of strings - for convenience and to add some handy utility functions.
77 class StringList : public std::vector<string> {
78  public:
79  using std::vector<string>::vector;
80  enum class Empty { Keep, Skip };
81 
82  StringList() {}
83  StringList(std::initializer_list<string> list) : std::vector<string>(list) {}
84  StringList(const StringList &s) : std::vector<string>(s) {}
85  StringList(const std::vector<string> &v) : std::vector<string>(v) {}
86  StringList(StringList &&v) noexcept : std::vector<string>(std::move(v)) {}
87  StringList(std::vector<string> &&v) noexcept : std::vector<string>(std::move(v)) {}
88 
89  const StringList &operator=(const StringList &in) { std::vector<string>::operator=(in); return *this; }
90 
91  const StringList &operator+=(const string &s) { push_back(s); return *this; }
92  const StringList &operator+=(const std::vector<string> &v) { for (auto &s : v) push_back(s); return *this; }
93  const StringList &operator<<(const string &s) { return operator+=(s); }
94  const StringList &operator<<(const StringList &s) { return operator+=(s); }
95  StringList operator+(const StringList &s) const { StringList ret(*this); ret += s; return ret; }
96 
97 };
98 
99 // String utility functions
100 BASE_EXPORT string tostring(const std::wstring &s); // Converts wstring to string
101 BASE_EXPORT string tostring(const std::u16string &s);
102 BASE_EXPORT string tostring(const std::u32string &s);
103 BASE_EXPORT std::wstring towstring(const string &s); // Converts string ot wstring
104 BASE_EXPORT std::wstring towstring(const std::u16string &s);
105 BASE_EXPORT std::u16string tou16string(const string &s); // Converts string to u16string
106 BASE_EXPORT std::u16string tou16string(const std::wstring &s); // Converts wstring to u16string
107 BASE_EXPORT std::u16string tou16string(const std::string_view &s); // Converts string to u32string
108 BASE_EXPORT std::u32string tou32string(const std::string &s); // Converts string to u32string
109 BASE_EXPORT std::u32string tou32string(const std::string_view &s); // Converts string to u32string
110 BASE_EXPORT string toUpper(const string &s); // All upper case
111 BASE_EXPORT string toLower(const string &s); // All lower case
112 BASE_EXPORT string capitalizeFirstLetter(const string &s);
113 template <typename T,typename U> T join(const std::vector<T> &s,const U &sep); // Note works on StringList
114 BASE_EXPORT std::vector<string> split(const string &s, const string &sep,bool keepEmptyParts=false);
115 BASE_EXPORT std::vector<string> splitRegex(const string &s,const string &regex,bool keepEmptyParts=false); // NOTE Case insensitive
116 BASE_EXPORT string matchRegex(const string &s,const string &regex,string::size_type start=0); // NOTE Case insensitive
117 BASE_EXPORT string replaceRegex(const string &s,const string &regex,const string &after); // NOTE Case insensitive
118 BASE_EXPORT string::size_type findRegex(const string &s,const string &regex,string::size_type start=0); // NOTE Case insensitive
119 BASE_EXPORT bool exactMatchRegex(const string &s,const string &regex); // NOTE Case insensitive
120 BASE_EXPORT string trimmed(const string &s); // Removes whitespace on front and back.
121 BASE_EXPORT string simplified(const string &s); // As trimmed, but also reduces whitespace sequences inside to one space.
122 BASE_EXPORT string replaceAll(const string &s, const string &sub,const string &newsub); // Replace all instances of sub wiwth newsub in s
123 BASE_EXPORT string toBase64(const std::vector<char> &in);
124 BASE_EXPORT std::vector<char> fromBase64(const string &in);
125 BASE_EXPORT bool startsWith(const string &in,const string &check, bool caseSensitive = false);
126 BASE_EXPORT bool endsWith(const string &in, const string &check, bool caseSensitive = false);
127 BASE_EXPORT string clipLen(const string &in,string::size_type length);
128 BASE_EXPORT string cleanupTypename(const char *name);
129 BASE_EXPORT string convertPercentToBracket(const string &s);
130 BASE_EXPORT string remove(const string &s,char c);
131 
132 // A buffer class - thin wrapper around std::vector<char>
133 // Useful in places where we would other use QByteArray.
134 class Buffer : public std::vector<char> {
135  public:
136  using std::vector<char>::vector;
137  Buffer(const std::vector<char> &v) : std::vector<char>(v) {}
138  Buffer(std::vector<char> &&v) : std::vector<char>(std::move(v)) {}
139  Buffer(const char *c, size_t len) : std::vector<char>(c, c+len) {}
140  explicit Buffer(const string &s) : std::vector<char>(s.begin(),s.end()) {}
141 
142  const Buffer &operator=(const std::vector<char> &v) { std::vector<char>::operator=(v); return *this; }
143  const Buffer &operator=(std::vector<char> &&v) { std::vector<char>::operator=(std::move(v)); return *this; }
144 
145  void append(const char *data, uint64 len) { insert(end(),data, data+len); }
146  void operator+=(const string &s) { insert(end(),s.begin(),s.end()); }
147  string toString() const { return string(begin(), end()); }
148  const char *constData() const { return data(); }
149 };
150 
151 // As string::compare but the comparison is case insensitive
152 BASE_EXPORT int32 caseInsensitiveCompare(const string &s1, const string &s2);
153 BASE_EXPORT int32 caseInsensitiveCompare(const string &s1, const std::string_view &s2);
154 inline int32 caseInsensitiveCompare(const string &s1, const char *str) { return caseInsensitiveCompare(s1,std::string_view(str)); }
155 BASE_EXPORT uint64 caseInsensitiveHash(const string &s);
156 BASE_EXPORT uint64 caseInsensitiveFind(const string &s1, const string &s2, string::size_type start = 0);
157 BASE_EXPORT string caseInsensitiveReplace(const string &start,const string &before,const string &after);
158 BASE_EXPORT bool caseInsensitiveContains(const std::vector<string> &all, const string &s2);
159 BASE_EXPORT uint64 caseInsensitiveFind(const std::vector<string> &all, const string &s2);
160 BASE_EXPORT bool checkLeft(const string &s,const string &c); // Checks if c matches start of s (case insensitive)
161 inline bool equal(const string &s,const string &c) { return caseInsensitiveCompare(s,c)==0; } // Handy shorthand
162 inline bool contains(const string &s,const string &s2) { return caseInsensitiveFind(s,s2)!=string::npos; }
163 
165 //*
166 //* Specifically, compares to length of token or keyword, whichever is shorter.\n
167 //* If token is longer than keyword no match.\n
168 //* If keyword contains the character '^', that character is disregarded for comparison purposes
169 //* and token must have at least as many characters as precede the '^' character.\n
170 //* If a token has a starting hyphen '-', then it is ignored for matching.
171 //* If a token has an internal hyphen 'one-two', then the hyphen must be present in keyword and
172 //* BOTH sides are checked using matching rules and any possible '^' character.
173 //*/
174 BASE_EXPORT bool match(const string &keyword,const string &token);
175 BASE_EXPORT void matchSynonymsAllowed(bool b);
176 BASE_EXPORT bool matchSynonymsAllowed();
177 
178 // Create a fmt::format specification using the parameters indicated {:fw.pn}
179 // Note position indicator is not included (yet).
180 BASE_EXPORT string buildFormat(int64 width, char notation='\0', int precision=-1,char fill=' ');
181 
182 namespace base {
183  // Thesee are type->string conversion functions, for convenience. less verbose than fmt::format
184  // and intended for use in formatted << output, but can be used in any string stuff.
185  // ts stands for To String, fs stands for From String.
186  // If you use these in text output I reccomend you put "using base::ts" at the start of the FUNCTION.
187  template <class T>
188  inline string ts(const T &t, int width=0, char notation = '\0', int precision = -1, char fill = ' ');
189 
190 
191  // Concise conversion from string to type. fsTest returns a tuple with the second
192  // value being a success boolean. fs just returns the type with an optional
193  // second argument indicating if an exception should be thrown on failure.
194  template <typename T>
195  std::tuple<T, bool> fsTest(const string &) { static_assert(sizeof(T{})==0); return {T{},false}; }
196  template<> inline std::tuple<int32, bool> fsTest(const string &in) { return isInt32(in); }
197  template<> inline std::tuple<uint32, bool> fsTest(const string &in) { return isUInt32(in); }
198  template<> inline std::tuple<int64, bool> fsTest(const string &in) { return isInt64(in); }
199  template<> inline std::tuple<uint64, bool> fsTest(const string &in) { return isUInt64(in); }
200  template<> inline std::tuple<double, bool> fsTest(const string &in) { return isDouble(in); }
201  template<> inline std::tuple<bool, bool> fsTest(const string &in) { return isBool(in); }
202  template<> inline std::tuple<string, bool> fsTest(const string &in) { return {in,true}; }
203 
204  template <typename T> T fs(const string &, [[maybe_unused]] bool throwException = false) { static_assert(sizeof(T{})==0); return T{}; }
205  template<> inline int32 fs(const string &in,bool throwException) { return toInt32(in,throwException); }
206  template<> inline uint32 fs(const string &in,bool throwException) { return toUInt32(in,throwException); }
207  template<> inline int64 fs(const string &in,bool throwException) { return toInt64(in,throwException); }
208  template<> inline uint64 fs(const string &in,bool throwException) { return toUInt64(in,throwException); }
209  template<> inline double fs(const string &in,bool throwException) { return toDouble(in,throwException); }
210  template<> inline bool fs(const string &in,bool throwException) { return toBool(in,"on,off,true,false,yes,no",throwException); }
211  template<> inline string fs(const string &in,bool) { return {in,true}; }
212 }
213 
214 // < and == functors for strings - to use in std containers when CI comparisons are wanted!
215 struct StringCILess {
216  public:
217  bool operator()(const string &left, const string &right) const {
218  return caseInsensitiveCompare(left,right) < 0;
219  }
220 };
222  public:
223  bool operator()(const string &left, const string &right) const {
224  return caseInsensitiveCompare(left,right) == 0;
225  }
226 };
227 struct StringCIHash {
228  public:
229  uint64 operator()(const string &in) const {
230  return caseInsensitiveHash(in);
231  }
232 };
233 
234 //----------------------------------------------------
235 // Implementations
236 //----------------------------------------------------
237 
238 // Might want to move this to a dedicated header so not everybody has to include these containers
239 
240 #include <map>
241 #include <unordered_map>
242 #include <set>
243 #include <unordered_set>
244 
245 template <typename T> using StringMap = std::map<string, T, StringCILess>;
246 
247 template <typename T> using StringMultiMap = std::multimap<string, T, StringCILess>;
248 
249 template <typename T> using StringHashMap = std::unordered_map<string, T, StringCIHash, StringCIEqual>;
250 
251 using StringSet = std::set<string, StringCILess>;
252 
253 using StringHashSet = std::unordered_set<string, StringCIHash, StringCIEqual>;
254 
255 template <class T>
256 inline string base::ts(const T &t, int width, char notation, int precision, char fill) {
257  string s = fmt::format(buildFormat(width, notation, precision, fill), t);
258  if (width!=0)
259  return clipLen(s,std::abs(width));
260  return s;
261 }
262 
263 // OK the fmt;:format library will output -0.0000 instead of 0.0000 if the value was
264 // <0 but belwo limits. This is confusing and breaks former output checks.
265 // So we need a template override to check for that and get rid of it (sigh)
266 template <>
267 inline string base::ts(const double &dIn, int width, char notation, int precision, char fill) {
268  double d(dIn);
269  if (d==0.0) // Revove -0
270  d = 0.0;
271  return fmt::format(buildFormat(width, notation, precision, fill), d);
272 }
273 
274 template <typename T,typename U>
275 T join(const std::vector<T> &s,const U &sep) {
276  string ret;
277  for (StringList::size_type i=0;i<s.size();++i) {
278  if (i) ret += sep;
279  ret += s[i];
280  }
281  return ret;
282 }
283 
284 //----------------------------------------------------
285 // Implementations
286 //----------------------------------------------------
287 
288 // EoF
Base type definitions for the engine.
Definition: basestring.h:134
Definition: basestring.h:77
BASE_EXPORT std::tuple< uint32, bool > isUInt32(const string &in)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: basestring.cpp:47
bool isBool(const QString &in, bool *b, const QString &out)
Definition: baseqstring.cpp:231
bool toBool(const QString &in, bool *ok, const QString &out)
Definition: baseqstring.cpp:280
BASE_EXPORT std::tuple< int64, bool > isInt64(const string &in)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: basestring.cpp:56
#define BASE_EXPORT
Definition: basedef.h:24
BASE_EXPORT bool match(const string &keyword, const string &token)
‍**
Definition: basestring.cpp:460
BASE_EXPORT std::tuple< uint64, bool > isUInt64(const string &in)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: basestring.cpp:65
BASE_EXPORT std::tuple< double, bool > isDouble(const string &in)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: basestring.cpp:74
Definition: basestring.h:221
Definition: basestring.h:227
Definition: basestring.h:215
A overflow checked shorthand for static_cast<T>().