nx_server_plugin_sdk  1.0
Server Plugin SDK
utils.h
Go to the documentation of this file.
1 // Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: www.mozilla.org/MPL/2.0/
2 
3 #pragma once
4 
12 #include <cstddef>
13 #include <cstring>
14 #include <cstdio>
15 #include <cstdlib>
16 #include <stdint.h>
17 #include <string>
18 #include <sstream>
19 #include <vector>
20 #include <map>
21 
22 #if defined(QT_CORE_LIB)
23  // To be supported in toString().
24  #include <QtCore/QByteArray>
25  #include <QtCore/QString>
26  #include <QtCore/QUrl>
27 #endif
28 
29 #if !defined(NX_KIT_API)
30  #define NX_KIT_API /*empty*/
31 #endif
32 
33 namespace nx {
34 namespace kit {
35 namespace utils {
36 
37 //-------------------------------------------------------------------------------------------------
38 // Strings.
39 
40 inline bool isAsciiPrintable(int c)
41 {
42  return c >= 32 && c <= 126;
43 }
44 
45 inline bool isSpaceOrControlChar(char c)
46 {
47  // NOTE: Chars 128..255 should be treated as non-whitespace, thus, isprint() will not do.
48  return (((unsigned char) c) <= 32) || (c == 127);
49 }
50 
60 NX_KIT_API std::string decodeEscapedString(
61  const std::string& s, std::string* outErrorMessage = nullptr);
62 
69 template<typename T>
70 std::string toString(T value);
71 
75 template<typename... Args>
76 std::string format(const std::string& formatStr, Args... args)
77 {
78  const int size = snprintf(nullptr, 0, formatStr.c_str(), args...) + /*space for \0*/ 1;
79  if (size <= 0)
80  return formatStr; //< No better way to handle out-of-memory-like errors.
81  std::string result(size, '\0');
82  snprintf(&result[0], size, formatStr.c_str(), args...);
83  result.resize(size - /*terminating \0*/ 1);
84  return result;
85 }
86 
87 NX_KIT_API bool fromString(const std::string& s, int* value);
88 NX_KIT_API bool fromString(const std::string& s, double* value);
89 NX_KIT_API bool fromString(const std::string& s, float* value);
90 NX_KIT_API bool fromString(const std::string& s, bool* value);
91 
92 NX_KIT_API void stringReplaceAllChars(std::string* s, char sample, char replacement);
93 NX_KIT_API void stringInsertAfterEach(std::string* s, char sample, const char* insertion);
94 NX_KIT_API void stringReplaceAll(
95  std::string* s, const std::string& sample, const std::string& replacement);
96 
97 // TODO: Remove when migrating to C++20 - it has std::string::starts_with()/ends_with().
98 NX_KIT_API bool stringStartsWith(const std::string& s, const std::string& prefix);
99 NX_KIT_API bool stringEndsWith(const std::string& s, const std::string& suffix);
100 
101 // TODO: Remove when migrating to C++23 - it has std::string::contains().
102 NX_KIT_API bool stringContains(const std::string& s, const std::string& substring);
103 
104 NX_KIT_API std::string trimString(const std::string& s);
105 
106 //-------------------------------------------------------------------------------------------------
107 // OS support.
108 
109 constexpr char kPathSeparator =
110  #if defined(_WIN32)
111  '\\';
112  #else
113  '/';
114  #endif
115 
120 NX_KIT_API std::string baseName(std::string path);
121 
127 NX_KIT_API std::string absolutePath(
128  const std::string& originDir, const std::string& path);
129 
133 NX_KIT_API std::string getProcessName();
134 
139 NX_KIT_API const std::vector<std::string>& getProcessCmdLineArgs();
140 
145 NX_KIT_API std::string getPathToExecutable();
146 
147 NX_KIT_API bool fileExists(const char* filename);
148 
149 //-------------------------------------------------------------------------------------------------
150 // Aligned allocation.
151 
156 inline size_t alignUp(size_t value, size_t alignment)
157 {
158  if (alignment == 0)
159  return value;
160  const size_t remainder = value % alignment;
161  if (remainder == 0)
162  return value;
163  return value + alignment - remainder;
164 }
165 
167 constexpr size_t kMinAlignment = 16;
168 
180 template<class MallocFunc>
181 void* mallocAligned(size_t size, size_t alignment, MallocFunc mallocFunc)
182 {
183  if (alignment < kMinAlignment)
184  alignment = kMinAlignment;
185 
186  // Reject sizes that overflow the arithmetic below. Without this check an overflowing request
187  // would succeed with a buffer far smaller than asked for, turning a bogus size into a heap
188  // overflow at the first write.
189  if (alignment > SIZE_MAX - sizeof(alignment))
190  return nullptr;
191  const size_t overhead = alignment + sizeof(alignment);
192  if (size > SIZE_MAX - overhead)
193  return nullptr;
194 
195  const auto ptr = (char*) mallocFunc(size + overhead);
196  if (!ptr) //< allocation error
197  return ptr;
198 
199  char* const alignedPtr = ptr + sizeof(alignment); //< Leaving place to save misalignment.
200  const size_t misalignment = alignment - (uintptr_t) alignedPtr % alignment;
201  memcpy(ptr + misalignment, &misalignment, sizeof(misalignment)); //< Save misalignment.
202  return alignedPtr + misalignment;
203 }
204 
206 inline void* mallocAligned(size_t size, size_t alignment)
207 {
208  // NOTE: Lambda is used to suppress a warning that some ::malloc() implementations are using
209  // deprecated exception specification.
210  return mallocAligned<>(size, alignment, [](size_t size) { return ::malloc(size); });
211 }
212 
220 template<class FreeFunc>
221 void freeAligned(void* ptr, FreeFunc freeFunc)
222 {
223  if (!ptr)
224  return freeFunc(ptr);
225 
226  ptr = (char*) ptr - sizeof(size_t);
227  size_t misalignment = 0;
228  memcpy(&misalignment, ptr, sizeof(misalignment)); //< Retrieve saved misalignment.
229  ptr = (char*) ptr - misalignment;
230 
231  freeFunc(ptr);
232 }
233 
235 inline void freeAligned(void* ptr)
236 {
237  // NOTE: Lambda is used to suppress a warning that some ::free() implementations are using
238  // deprecated exception specification.
239  return freeAligned<>(ptr, [](void* ptr) { return ::free(ptr); });
240 }
241 
242 //-------------------------------------------------------------------------------------------------
243 // Implementation.
244 
245 // The order of overloads below is important - it defines which will be chosen by inline functions.
246 NX_KIT_API std::string toString(bool b);
247 NX_KIT_API std::string toString(const void* ptr);
248 inline std::string toString(void* ptr) { return toString(const_cast<const void*>(ptr)); }
249 inline std::string toString(std::nullptr_t ptr) { return toString((const void*) ptr); }
250 inline std::string toString(uint8_t i) { return toString((int) i); } //< Avoid matching as char.
251 inline std::string toString(int8_t i) { return toString((int) i); } //< Avoid matching as char.
252 NX_KIT_API std::string toString(char c);
253 NX_KIT_API std::string toString(const char* s);
254 inline std::string toString(char* s) { return toString(const_cast<const char*>(s)); }
255 NX_KIT_API std::string toString(wchar_t c);
256 NX_KIT_API std::string toString(const wchar_t* w);
257 inline std::string toString(wchar_t* w) { return toString(const_cast<const wchar_t*>(w)); }
258 
259 // std::string can contain '\0' inside, hence a dedicated implementation.
260 NX_KIT_API std::string toString(const std::string& s);
261 NX_KIT_API std::string toString(const std::wstring& w);
262 
263 
265 template<typename T>
266 std::string toString(T value)
267 {
268  std::ostringstream outputString;
269  outputString << value;
270  return outputString.str();
271 }
272 
273 #if defined(QT_CORE_LIB)
274 
275 static inline std::string toString(QByteArray b) //< By value to avoid calling the template impl.
276 {
277  return toString(b.toStdString());
278 }
279 
280 static inline std::string toString(QString s) //< By value to avoid calling the template impl.
281 {
282  return toString(s.toUtf8().constData());
283 }
284 
285 static inline std::string toString(QUrl u) //< By value to avoid calling the template impl.
286 {
287  return toString(u.toEncoded().toStdString());
288 }
289 
290 #endif // defined(QT_CORE_LIB)
291 
292 template<typename P>
293 std::string toString(P* ptr)
294 {
295  return toString((const void*) ptr);
296 }
297 
298 //-------------------------------------------------------------------------------------------------
299 // Configuration file parsing.
300 
301 NX_KIT_API bool parseNameValueFile(
302  const std::string& nameValueFilePath,
303  std::map<std::string, std::string>* nameValueMap,
304  const std::string& errorPrefix,
305  std::ostream* out,
306  bool* isFileEmpty);
307 
308 //-------------------------------------------------------------------------------------------------
309 // String conversions.
310 
312 NX_KIT_API std::string toUpper(const std::string& str);
313 
314 #if defined(_WIN32)
315 
317 NX_KIT_API std::string wideCharToStdString(const wchar_t* str);
318 
319 #endif // defined(_WIN32)
320 
321 } // namespace utils
322 } // namespace kit
323 } // namespace nx
std::string format(const std::string &formatStr, Args... args)
Definition: utils.h:76
size_t alignUp(size_t value, size_t alignment)
Definition: utils.h:156
constexpr size_t kMinAlignment
Definition: utils.h:167
void * mallocAligned(size_t size, size_t alignment, MallocFunc mallocFunc)
Definition: utils.h:181
Definition: apple_utils.h:6
void freeAligned(void *ptr, FreeFunc freeFunc)
Definition: utils.h:221
Definition: url.cpp:6