Itasca C++ Interface
Loading...
Searching...
No Matches
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
27INTELWARNING(186) // Pointless comparison of unsigned integer with zero
28PUSHWARNING
29VSWARNING(ALL_CODE_ANALYSIS_WARNINGS)
30INTELWARNING(177)
31INTELWARNING(280) // selector expression is constant
32GNUWARNING("-Wstringop-overflow")
33#ifdef CLANGCOMP
34# pragma warning ( disable : ALL_CODE_ANALYSIS_WARNINGS ) // Nonstandard
35#endif
36#include "../fmt/format.h"
37POPWARNING
38
39// Global namespace versions of std strings
40using wstring = std::wstring; // Old string class to avoid interface compatibility breaks
41using 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.
47BASE_EXPORT std::tuple<int32,bool> isInt32(const string &in);
48BASE_EXPORT std::tuple<uint32,bool> isUInt32(const string &in);
49BASE_EXPORT std::tuple<int64,bool> isInt64(const string &in);
50BASE_EXPORT std::tuple<uint64,bool> isUInt64(const string &in);
51BASE_EXPORT std::tuple<double,bool> isDouble(const string &in);
52BASE_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
57template <typename T,typename ... Args>
58T 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}
68inline int32 toInt32(const string &in, bool throwException = false) { return toStringConv<int32>(in, throwException, isInt32); }
69inline uint32 toUInt32(const string &in,bool throwException=false) { return toStringConv<uint32>(in, throwException, isUInt32); }
70inline int64 toInt64(const string &in,bool throwException=false) { return toStringConv<int64>(in, throwException, isInt64); }
71inline uint64 toUInt64(const string &in,bool throwException=false) { return toStringConv<uint64>(in, throwException, isUInt64); }
72inline double toDouble(const string &in,bool throwException=false) { return toStringConv<double>(in, throwException, isDouble); }
73inline 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.
77class 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
100BASE_EXPORT string tostring(const std::wstring &s); // Converts wstring to string
101BASE_EXPORT string tostring(const std::u16string &s);
102BASE_EXPORT string tostring(const std::u32string &s);
103BASE_EXPORT std::wstring towstring(const string &s); // Converts string ot wstring
104BASE_EXPORT std::wstring towstring(const std::u16string &s);
105BASE_EXPORT std::u16string tou16string(const string &s); // Converts string to u16string
106BASE_EXPORT std::u16string tou16string(const std::wstring &s); // Converts wstring to u16string
107BASE_EXPORT std::u16string tou16string(const std::string_view &s); // Converts string to u32string
108BASE_EXPORT std::u32string tou32string(const std::string &s); // Converts string to u32string
109BASE_EXPORT std::u32string tou32string(const std::string_view &s); // Converts string to u32string
110BASE_EXPORT string toUpper(const string &s); // All upper case
111BASE_EXPORT string toLower(const string &s); // All lower case
112BASE_EXPORT string capitalizeFirstLetter(const string &s);
113template <typename T,typename U> T join(const std::vector<T> &s,const U &sep); // Note works on StringList
114BASE_EXPORT std::vector<string> split(const string &s, const string &sep,bool keepEmptyParts=false);
115BASE_EXPORT std::vector<string> splitRegex(const string &s,const string &regex,bool keepEmptyParts=false); // NOTE Case insensitive
116BASE_EXPORT string matchRegex(const string &s,const string &regex,string::size_type start=0); // NOTE Case insensitive
117BASE_EXPORT string replaceRegex(const string &s,const string &regex,const string &after); // NOTE Case insensitive
118BASE_EXPORT string::size_type findRegex(const string &s,const string &regex,string::size_type start=0); // NOTE Case insensitive
119BASE_EXPORT bool exactMatchRegex(const string &s,const string &regex); // NOTE Case insensitive
120BASE_EXPORT string trimmed(const string &s); // Removes whitespace on front and back.
121BASE_EXPORT string simplified(const string &s); // As trimmed, but also reduces whitespace sequences inside to one space.
122BASE_EXPORT string replaceAll(const string &s, const string &sub,const string &newsub); // Replace all instances of sub wiwth newsub in s
123BASE_EXPORT string toBase64(const std::vector<char> &in);
124BASE_EXPORT std::vector<char> fromBase64(const string &in);
125BASE_EXPORT bool startsWith(const string &in,const string &check, bool caseSensitive = false);
126BASE_EXPORT bool endsWith(const string &in, const string &check, bool caseSensitive = false);
127BASE_EXPORT string clipLen(const string &in,string::size_type length);
128BASE_EXPORT string cleanupTypename(const char *name);
129BASE_EXPORT string convertPercentToBracket(const string &s);
130BASE_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.
134class 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
152BASE_EXPORT int32 caseInsensitiveCompare(const string &s1, const string &s2);
153BASE_EXPORT int32 caseInsensitiveCompare(const string &s1, const std::string_view &s2);
154inline int32 caseInsensitiveCompare(const string &s1, const char *str) { return caseInsensitiveCompare(s1,std::string_view(str)); }
155BASE_EXPORT uint64 caseInsensitiveHash(const string &s);
156BASE_EXPORT uint64 caseInsensitiveFind(const string &s1, const string &s2, string::size_type start = 0);
157BASE_EXPORT string caseInsensitiveReplace(const string &start,const string &before,const string &after);
158BASE_EXPORT bool caseInsensitiveContains(const std::vector<string> &all, const string &s2);
159BASE_EXPORT uint64 caseInsensitiveFind(const std::vector<string> &all, const string &s2);
160BASE_EXPORT bool checkLeft(const string &s,const string &c); // Checks if c matches start of s (case insensitive)
161inline bool equal(const string &s,const string &c) { return caseInsensitiveCompare(s,c)==0; } // Handy shorthand
162inline 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//*/
174BASE_EXPORT bool match(const string &keyword,const string &token);
175BASE_EXPORT void matchSynonymsAllowed(bool b);
176BASE_EXPORT bool matchSynonymsAllowed();
177
178// Create a fmt::format specification using the parameters indicated {:fw.pn}
179// Note position indicator is not included (yet).
180BASE_EXPORT string buildFormat(int64 width, char notation='\0', int precision=-1,char fill=' ');
181
182namespace 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!
215struct StringCILess {
216 public:
217 bool operator()(const string &left, const string &right) const {
218 return caseInsensitiveCompare(left,right) < 0;
219 }
220};
221struct StringCIEqual {
222 public:
223 bool operator()(const string &left, const string &right) const {
224 return caseInsensitiveCompare(left,right) == 0;
225 }
226};
227struct 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
245template <typename T> using StringMap = std::map<string, T, StringCILess>;
246
247template <typename T> using StringMultiMap = std::multimap<string, T, StringCILess>;
248
249template <typename T> using StringHashMap = std::unordered_map<string, T, StringCIHash, StringCIEqual>;
250
251using StringSet = std::set<string, StringCILess>;
252
253using StringHashSet = std::unordered_set<string, StringCIHash, StringCIEqual>;
254
255template <class T>
256inline 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)
266template <>
267inline 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
274template <typename T,typename U>
275T 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.
bool isDouble(const QString &in, double *d)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition baseqstring.cpp:273
bool isBool(const QString &in, bool *b, const QString &out)
Definition baseqstring.cpp:231
std::tuple< int64, bool > isInt64(const string &s)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition basestring.cpp:56
bool toBool(const QString &in, bool *ok, const QString &out)
Definition baseqstring.cpp:280
#define BASE_EXPORT
Definition basedef.h:24
std::tuple< uint64, bool > isUInt64(const string &s)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition basestring.cpp:65
std::tuple< uint32, bool > isUInt32(const string &s)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition basestring.cpp:47
A overflow checked shorthand for static_cast<T>().