string.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. * Copyright 2010-2017 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
  4. */
  5. #ifndef BX_STRING_H_HEADER_GUARD
  6. #define BX_STRING_H_HEADER_GUARD
  7. #include "bx.h"
  8. #include <alloca.h>
  9. #include <stdarg.h> // va_list
  10. #include <wchar.h> // wchar_t
  11. #include <bx/allocator.h>
  12. #include <bx/hash.h>
  13. #ifndef va_copy
  14. # define va_copy(_a, _b) (_a) = (_b)
  15. #endif // va_copy
  16. namespace bx
  17. {
  18. ///
  19. bool toBool(const char* _str);
  20. /// Case insensitive string compare.
  21. int32_t stricmp(const char* _a, const char* _b);
  22. ///
  23. size_t strnlen(const char* _str, size_t _max);
  24. /// Copy _num characters from string _src to _dst buffer of maximum _dstSize capacity
  25. /// including zero terminator. Copy will be terminated with '\0'.
  26. size_t strlncpy(char* _dst, size_t _dstSize, const char* _src, size_t _num = -1);
  27. /// Find substring in string. Limit search to _size.
  28. const char* strnstr(const char* _str, const char* _find, size_t _size);
  29. /// Find substring in string. Case insensitive.
  30. const char* stristr(const char* _str, const char* _find);
  31. /// Find substring in string. Case insensitive. Limit search to _max.
  32. const char* stristr(const char* _str, const char* _find, size_t _max);
  33. /// Find new line. Returns pointer after new line terminator.
  34. const char* strnl(const char* _str);
  35. /// Find end of line. Retuns pointer to new line terminator.
  36. const char* streol(const char* _str);
  37. /// Skip whitespace.
  38. const char* strws(const char* _str);
  39. /// Skip non-whitespace.
  40. const char* strnws(const char* _str);
  41. /// Skip word.
  42. const char* strword(const char* _str);
  43. /// Find matching block.
  44. const char* strmb(const char* _str, char _open, char _close);
  45. // Normalize string to sane line endings.
  46. void eolLF(char* _out, size_t _size, const char* _str);
  47. // Finds identifier.
  48. const char* findIdentifierMatch(const char* _str, const char* _word);
  49. // Finds any identifier from NULL terminated array of identifiers.
  50. const char* findIdentifierMatch(const char* _str, const char* _words[]);
  51. /// Cross platform implementation of vsnprintf that returns number of
  52. /// characters which would have been written to the final string if
  53. /// enough space had been available.
  54. int32_t vsnprintf(char* _str, size_t _count, const char* _format, va_list _argList);
  55. /// Cross platform implementation of vsnwprintf that returns number of
  56. /// characters which would have been written to the final string if
  57. /// enough space had been available.
  58. int32_t vsnwprintf(wchar_t* _str, size_t _count, const wchar_t* _format, va_list _argList);
  59. ///
  60. int32_t snprintf(char* _str, size_t _count, const char* _format, ...);
  61. ///
  62. int32_t swnprintf(wchar_t* _out, size_t _count, const wchar_t* _format, ...);
  63. ///
  64. template <typename Ty>
  65. inline void stringPrintfVargs(Ty& _out, const char* _format, va_list _argList)
  66. {
  67. char temp[2048];
  68. char* out = temp;
  69. int32_t len = bx::vsnprintf(out, sizeof(temp), _format, _argList);
  70. if ( (int32_t)sizeof(temp) < len)
  71. {
  72. out = (char*)alloca(len+1);
  73. len = bx::vsnprintf(out, len, _format, _argList);
  74. }
  75. out[len] = '\0';
  76. _out.append(out);
  77. }
  78. ///
  79. template <typename Ty>
  80. inline void stringPrintf(Ty& _out, const char* _format, ...)
  81. {
  82. va_list argList;
  83. va_start(argList, _format);
  84. stringPrintfVargs(_out, _format, argList);
  85. va_end(argList);
  86. }
  87. /// Replace all instances of substring.
  88. template <typename Ty>
  89. inline Ty replaceAll(const Ty& _str, const char* _from, const char* _to)
  90. {
  91. Ty str = _str;
  92. size_t startPos = 0;
  93. const size_t fromLen = strlen(_from);
  94. const size_t toLen = strlen(_to);
  95. while ( (startPos = str.find(_from, startPos) ) != Ty::npos)
  96. {
  97. str.replace(startPos, fromLen, _to);
  98. startPos += toLen;
  99. }
  100. return str;
  101. }
  102. /// Extract base file name from file path.
  103. const char* baseName(const char* _filePath);
  104. /// Convert size in bytes to human readable string.
  105. void prettify(char* _out, size_t _count, uint64_t _size);
  106. /// Copy src to string dst of size siz. At most siz-1 characters
  107. /// will be copied. Always NUL terminates (unless siz == 0).
  108. /// Returns strlen(src); if retval >= siz, truncation occurred.
  109. size_t strlcpy(char* _dst, const char* _src, size_t _siz);
  110. /// Appends src to string dst of size siz (unlike strncat, siz is the
  111. /// full size of dst, not space left). At most siz-1 characters
  112. /// will be copied. Always NUL terminates (unless siz <= strlen(dst)).
  113. /// Returns strlen(src) + MIN(siz, strlen(initial dst)).
  114. /// If retval >= siz, truncation occurred.
  115. size_t strlcat(char* _dst, const char* _src, size_t _siz);
  116. /// Non-zero-terminated string view.
  117. class StringView
  118. {
  119. public:
  120. StringView()
  121. {
  122. clear();
  123. }
  124. StringView(const StringView& _rhs)
  125. {
  126. set(_rhs.m_ptr, _rhs.m_len);
  127. }
  128. StringView& operator=(const StringView& _rhs)
  129. {
  130. set(_rhs.m_ptr, _rhs.m_len);
  131. return *this;
  132. }
  133. StringView(const char* _ptr, uint32_t _len = UINT16_MAX)
  134. {
  135. set(_ptr, _len);
  136. }
  137. void set(const char* _ptr, uint32_t _len = UINT16_MAX)
  138. {
  139. clear();
  140. if (NULL != _ptr)
  141. {
  142. uint32_t len = uint32_t(strnlen(_ptr, _len) );
  143. if (0 != len)
  144. {
  145. m_len = len;
  146. m_ptr = _ptr;
  147. }
  148. }
  149. }
  150. void clear()
  151. {
  152. m_ptr = "";
  153. m_len = 0;
  154. }
  155. const char* getPtr() const
  156. {
  157. return m_ptr;
  158. }
  159. const char* getTerm() const
  160. {
  161. return m_ptr + m_len;
  162. }
  163. bool isEmpty() const
  164. {
  165. return 0 == m_len;
  166. }
  167. uint32_t getLength() const
  168. {
  169. return m_len;
  170. }
  171. protected:
  172. const char* m_ptr;
  173. uint32_t m_len;
  174. };
  175. inline uint32_t hashMurmur2A(const StringView& _data)
  176. {
  177. return hashMurmur2A(_data.getPtr(), _data.getLength() );
  178. }
  179. inline uint32_t hashMurmur2A(const char* _data)
  180. {
  181. return hashMurmur2A(StringView(_data) );
  182. }
  183. /// ASCII string
  184. template<bx::AllocatorI** AllocatorT>
  185. class StringT : public StringView
  186. {
  187. public:
  188. StringT()
  189. : StringView()
  190. {
  191. }
  192. StringT(const StringT<AllocatorT>& _rhs)
  193. : StringView()
  194. {
  195. set(_rhs.m_ptr, _rhs.m_len);
  196. }
  197. StringT<AllocatorT>& operator=(const StringT<AllocatorT>& _rhs)
  198. {
  199. set(_rhs.m_ptr, _rhs.m_len);
  200. return *this;
  201. }
  202. StringT(const char* _ptr, uint32_t _len = UINT32_MAX)
  203. {
  204. set(_ptr, _len);
  205. }
  206. StringT(const StringView& _rhs)
  207. {
  208. set(_rhs.getPtr(), _rhs.getLength() );
  209. }
  210. ~StringT()
  211. {
  212. clear();
  213. }
  214. void set(const char* _ptr, uint32_t _len = UINT32_MAX)
  215. {
  216. clear();
  217. append(_ptr, _len);
  218. }
  219. void append(const char* _ptr, uint32_t _len = UINT32_MAX)
  220. {
  221. if (0 != _len)
  222. {
  223. uint32_t old = m_len;
  224. uint32_t len = m_len + uint32_t(strnlen(_ptr, _len) );
  225. char* ptr = (char*)BX_REALLOC(*AllocatorT, 0 != m_len ? const_cast<char*>(m_ptr) : NULL, len+1);
  226. m_len = len;
  227. strlncpy(ptr + old, len-old+1, _ptr, _len);
  228. *const_cast<char**>(&m_ptr) = ptr;
  229. }
  230. }
  231. void clear()
  232. {
  233. if (0 != m_len)
  234. {
  235. BX_FREE(*AllocatorT, const_cast<char*>(m_ptr) );
  236. StringView::clear();
  237. }
  238. }
  239. };
  240. } // namespace bx
  241. #endif // BX_STRING_H_HEADER_GUARD