string.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. /*
  2. * Copyright 2010-2013 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #ifndef BX_PRINTF_H_HEADER_GUARD
  6. #define BX_PRINTF_H_HEADER_GUARD
  7. #include "bx.h"
  8. #include <alloca.h>
  9. #include <ctype.h> // tolower
  10. #include <stdarg.h> // va_list
  11. #include <stdio.h> // vsnprintf, vsnwprintf
  12. #include <string.h>
  13. #include <wchar.h> // wchar_t
  14. namespace bx
  15. {
  16. inline bool toBool(const char* _str)
  17. {
  18. char ch = (char)tolower(_str[0]);
  19. return ch == 't' || ch == '1';
  20. }
  21. /// Case insensitive string compare.
  22. inline int32_t stricmp(const char* _a, const char* _b)
  23. {
  24. #if BX_COMPILER_MSVC
  25. return _stricmp(_a, _b);
  26. #else
  27. return strcasecmp(_a, _b);
  28. #endif // BX_COMPILER_
  29. }
  30. ///
  31. inline size_t strnlen(const char* _str, size_t _max)
  32. {
  33. const char* end = _str + _max;
  34. const char* ptr;
  35. for (ptr = _str; ptr < end && *ptr != '\0'; ++ptr);
  36. return ptr - _str;
  37. }
  38. /// Find substring in string. Limit search to _size.
  39. inline const char* strnstr(const char* _str, const char* _find, size_t _size)
  40. {
  41. char first = *_find;
  42. if ('\0' == first)
  43. {
  44. return _str;
  45. }
  46. const char* cmp = _find + 1;
  47. size_t len = strlen(cmp);
  48. do
  49. {
  50. for (char match = *_str++; match != first && 0 < _size; match = *_str++, --_size)
  51. {
  52. if ('\0' == match)
  53. {
  54. return NULL;
  55. }
  56. }
  57. if (0 == _size)
  58. {
  59. return NULL;
  60. }
  61. } while (0 != strncmp(_str, cmp, len) );
  62. return --_str;
  63. }
  64. /// Find new line. Returns pointer after new line terminator.
  65. inline const char* strnl(const char* _str)
  66. {
  67. for (; '\0' != *_str; _str += strnlen(_str, 1024) )
  68. {
  69. const char* eol = strnstr(_str, "\r\n", 1024);
  70. if (NULL != eol)
  71. {
  72. return eol + 2;
  73. }
  74. eol = strnstr(_str, "\n", 1024);
  75. if (NULL != eol)
  76. {
  77. return eol + 1;
  78. }
  79. }
  80. return _str;
  81. }
  82. /// Find end of line. Retuns pointer to new line terminator.
  83. inline const char* streol(const char* _str)
  84. {
  85. for (; '\0' != *_str; _str += strnlen(_str, 1024) )
  86. {
  87. const char* eol = strnstr(_str, "\r\n", 1024);
  88. if (NULL != eol)
  89. {
  90. return eol;
  91. }
  92. eol = strnstr(_str, "\n", 1024);
  93. if (NULL != eol)
  94. {
  95. return eol;
  96. }
  97. }
  98. return _str;
  99. }
  100. /// Skip whitespace.
  101. inline const char* strws(const char* _str)
  102. {
  103. for (; isspace(*_str); ++_str);
  104. return _str;
  105. }
  106. /// Skip non-whitespace.
  107. inline const char* strnws(const char* _str)
  108. {
  109. for (; !isspace(*_str); ++_str);
  110. return _str;
  111. }
  112. /// Skip word.
  113. inline const char* strword(const char* _str)
  114. {
  115. for (char ch = *_str++; isalnum(ch) || '_' == ch; ch = *_str++);
  116. return _str-1;
  117. }
  118. /// Find matching block.
  119. inline const char* strmb(const char* _str, char _open, char _close)
  120. {
  121. int count = 0;
  122. for (char ch = *_str++; ch != '\0' && count >= 0; ch = *_str++)
  123. {
  124. if (ch == _open)
  125. {
  126. count++;
  127. }
  128. else if (ch == _close)
  129. {
  130. count--;
  131. if (0 == count)
  132. {
  133. return _str-1;
  134. }
  135. }
  136. }
  137. return NULL;
  138. }
  139. // Normalize string to sane line endings.
  140. inline void eolLF(char* _out, size_t _size, const char* _str)
  141. {
  142. if (0 < _size)
  143. {
  144. char* end = _out + _size - 1;
  145. for (char ch = *_str++; ch != '\0' && _out < end; ch = *_str++)
  146. {
  147. if ('\r' != ch)
  148. {
  149. *_out++ = ch;
  150. }
  151. }
  152. *_out = '\0';
  153. }
  154. }
  155. /// Cross platform implementation of vsnprintf that returns number of
  156. /// characters which would have been written to the final string if
  157. /// enough space had been available.
  158. inline int32_t vsnprintf(char* _str, size_t _count, const char* _format, va_list _argList)
  159. {
  160. #if BX_COMPILER_MSVC
  161. int32_t len = ::vsnprintf(_str, _count, _format, _argList);
  162. return -1 == len ? ::_vscprintf(_format, _argList) : len;
  163. #else
  164. return ::vsnprintf(_str, _count, _format, _argList);
  165. #endif // BX_COMPILER_MSVC
  166. }
  167. /// Cross platform implementation of vsnwprintf that returns number of
  168. /// characters which would have been written to the final string if
  169. /// enough space had been available.
  170. inline int32_t vsnwprintf(wchar_t* _str, size_t _count, const wchar_t* _format, va_list _argList)
  171. {
  172. #if BX_COMPILER_MSVC
  173. int32_t len = ::_vsnwprintf_s(_str, _count, _count, _format, _argList);
  174. return -1 == len ? ::_vscwprintf(_format, _argList) : len;
  175. #elif defined(__MINGW32__)
  176. return ::vsnwprintf(_str, _count, _format, _argList);
  177. #else
  178. return ::vswprintf(_str, _count, _format, _argList);
  179. #endif // BX_COMPILER_MSVC
  180. }
  181. inline int32_t snprintf(char* _str, size_t _count, const char* _format, ...) // BX_PRINTF_ARGS(3, 4)
  182. {
  183. va_list argList;
  184. va_start(argList, _format);
  185. int32_t len = vsnprintf(_str, _count, _format, argList);
  186. va_end(argList);
  187. return len;
  188. }
  189. inline int32_t swnprintf(wchar_t* _out, size_t _count, const wchar_t* _format, ...)
  190. {
  191. va_list argList;
  192. va_start(argList, _format);
  193. int32_t len = vsnwprintf(_out, _count, _format, argList);
  194. va_end(argList);
  195. return len;
  196. }
  197. template <typename Ty>
  198. inline void stringPrintfVargs(Ty& _out, const char* _format, va_list _argList)
  199. {
  200. char temp[2048];
  201. char* out = temp;
  202. int32_t len = bx::vsnprintf(out, sizeof(temp), _format, _argList);
  203. if ( (int32_t)sizeof(temp) < len)
  204. {
  205. out = (char*)alloca(len+1);
  206. len = bx::vsnprintf(out, len, _format, _argList);
  207. }
  208. out[len] = '\0';
  209. _out.append(out);
  210. }
  211. template <typename Ty>
  212. inline void stringPrintf(Ty& _out, const char* _format, ...)
  213. {
  214. va_list argList;
  215. va_start(argList, _format);
  216. stringPrintfVargs(_out, _format, argList);
  217. va_end(argList);
  218. }
  219. /*
  220. * Copyright (c) 1998 Todd C. Miller <[email protected]>
  221. *
  222. * Permission to use, copy, modify, and distribute this software for any
  223. * purpose with or without fee is hereby granted, provided that the above
  224. * copyright notice and this permission notice appear in all copies.
  225. *
  226. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  227. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  228. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  229. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  230. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  231. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  232. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  233. */
  234. /// Copy src to string dst of size siz. At most siz-1 characters
  235. /// will be copied. Always NUL terminates (unless siz == 0).
  236. /// Returns strlen(src); if retval >= siz, truncation occurred.
  237. inline size_t strlcpy(char* _dst, const char* _src, size_t _siz)
  238. {
  239. char* dd = _dst;
  240. const char* ss = _src;
  241. size_t nn = _siz;
  242. /* Copy as many bytes as will fit */
  243. if (nn != 0)
  244. {
  245. while (--nn != 0)
  246. {
  247. if ( (*dd++ = *ss++) == '\0')
  248. {
  249. break;
  250. }
  251. }
  252. }
  253. /* Not enough room in dst, add NUL and traverse rest of src */
  254. if (nn == 0)
  255. {
  256. if (_siz != 0)
  257. {
  258. *dd = '\0'; /* NUL-terminate dst */
  259. }
  260. while (*ss++)
  261. {
  262. }
  263. }
  264. return(ss - _src - 1); /* count does not include NUL */
  265. }
  266. /// Appends src to string dst of size siz (unlike strncat, siz is the
  267. /// full size of dst, not space left). At most siz-1 characters
  268. /// will be copied. Always NUL terminates (unless siz <= strlen(dst)).
  269. /// Returns strlen(src) + MIN(siz, strlen(initial dst)).
  270. /// If retval >= siz, truncation occurred.
  271. inline size_t strlcat(char* _dst, const char* _src, size_t _siz)
  272. {
  273. char* dd = _dst;
  274. const char *s = _src;
  275. size_t nn = _siz;
  276. size_t dlen;
  277. /* Find the end of dst and adjust bytes left but don't go past end */
  278. while (nn-- != 0 && *dd != '\0')
  279. {
  280. dd++;
  281. }
  282. dlen = dd - _dst;
  283. nn = _siz - dlen;
  284. if (nn == 0)
  285. {
  286. return(dlen + strlen(s));
  287. }
  288. while (*s != '\0')
  289. {
  290. if (nn != 1)
  291. {
  292. *dd++ = *s;
  293. nn--;
  294. }
  295. s++;
  296. }
  297. *dd = '\0';
  298. return(dlen + (s - _src)); /* count does not include NUL */
  299. }
  300. } // namespace bx
  301. #endif // BX_PRINTF_H_HEADER_GUARD