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