string.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Copyright 2010-2012 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #ifndef __BX_PRINTF_H__
  6. #define __BX_PRINTF_H__
  7. #include "bx.h"
  8. #include <alloca.h>
  9. #include <stdarg.h> // va_list
  10. #include <stdio.h> // vsnprintf
  11. #include <string.h>
  12. #include <string>
  13. namespace bx
  14. {
  15. /// Case insensitive string compare.
  16. inline int32_t stricmp(const char* _a, const char* _b)
  17. {
  18. #if BX_COMPILER_MSVC
  19. return _stricmp(_a, _b);
  20. #else
  21. return strcasecmp(_a, _b);
  22. #endif // BX_COMPILER_
  23. }
  24. ///
  25. inline size_t strnlen(const char* _str, size_t _max)
  26. {
  27. const char* end = _str + _max;
  28. const char* ptr;
  29. for (ptr = _str; ptr < end && *ptr != '\0'; ++ptr);
  30. return ptr - _str;
  31. }
  32. /// Find substring in string. Limit search to _size.
  33. inline const char* strnstr(const char* _str, const char* _find, size_t _size)
  34. {
  35. char first = *_find;
  36. if ('\0' == first)
  37. {
  38. return _str;
  39. }
  40. const char* cmp = _find + 1;
  41. size_t len = strlen(cmp);
  42. do
  43. {
  44. for (char match = *_str++; match != first && 0 < _size; match = *_str++, --_size)
  45. {
  46. if ('\0' == match)
  47. {
  48. return NULL;
  49. }
  50. }
  51. if (0 == _size)
  52. {
  53. return NULL;
  54. }
  55. } while (0 != strncmp(_str, cmp, len) );
  56. return --_str;
  57. }
  58. /// Find new line. Returns pointer after new line terminator.
  59. inline const char* strnl(const char* _str)
  60. {
  61. for (; '\0' != *_str; _str += strnlen(_str, 1024) )
  62. {
  63. const char* eol = strnstr(_str, "\r\n", 1024);
  64. if (NULL != eol)
  65. {
  66. return eol + 2;
  67. }
  68. eol = strnstr(_str, "\n", 1024);
  69. if (NULL != eol)
  70. {
  71. return eol + 1;
  72. }
  73. }
  74. return _str;
  75. }
  76. /// Find end of line. Retuns pointer to new line terminator.
  77. inline const char* streol(const char* _str)
  78. {
  79. for (; '\0' != *_str; _str += strnlen(_str, 1024) )
  80. {
  81. const char* eol = strnstr(_str, "\r\n", 1024);
  82. if (NULL != eol)
  83. {
  84. return eol;
  85. }
  86. eol = strnstr(_str, "\n", 1024);
  87. if (NULL != eol)
  88. {
  89. return eol;
  90. }
  91. }
  92. return _str;
  93. }
  94. /// Skip whitespace.
  95. inline const char* strws(const char* _str)
  96. {
  97. for (; isspace(*_str); ++_str);
  98. return _str;
  99. }
  100. /// Skip non-whitespace.
  101. inline const char* strnws(const char* _str)
  102. {
  103. for (; !isspace(*_str); ++_str);
  104. return _str;
  105. }
  106. /// Skip word.
  107. inline const char* strword(const char* _str)
  108. {
  109. for (char ch = *_str++; isalnum(ch) || '_' == ch; ch = *_str++);
  110. return _str-1;
  111. }
  112. /// Find matching block.
  113. inline const char* strmb(const char* _str, char _open, char _close)
  114. {
  115. int count = 0;
  116. for (char ch = *_str++; ch != '\0' && count >= 0; ch = *_str++)
  117. {
  118. if (ch == _open)
  119. {
  120. count++;
  121. }
  122. else if (ch == _close)
  123. {
  124. count--;
  125. if (0 == count)
  126. {
  127. return _str-1;
  128. }
  129. }
  130. }
  131. return NULL;
  132. }
  133. // Normalize string to sane line endings.
  134. inline void eolLF(char* _out, size_t _size, const char* _str)
  135. {
  136. if (0 < _size)
  137. {
  138. char* end = _out + _size - 1;
  139. for (char ch = *_str++; ch != '\0' && _out < end; ch = *_str++)
  140. {
  141. if ('\r' != ch)
  142. {
  143. *_out++ = ch;
  144. }
  145. }
  146. *_out = '\0';
  147. }
  148. }
  149. /// Cross platform implementation of vsnprintf that returns number of
  150. /// characters which would have been written to the final string if
  151. /// enough space had been available.
  152. inline int32_t vsnprintf(char* _str, size_t _size, const char* _format, va_list _argList)
  153. {
  154. #if BX_COMPILER_MSVC
  155. int32_t len = ::vsnprintf(_str, _size, _format, _argList);
  156. return -1 == len ? ::_vscprintf(_format, _argList) : len;
  157. #else
  158. return ::vsnprintf(_str, _size, _format, _argList);
  159. #endif // BX_COMPILER_MSVC
  160. }
  161. inline int32_t snprintf(char* _str, size_t _size, const char* _format, ...) // BX_PRINTF_ARGS(3, 4)
  162. {
  163. va_list argList;
  164. va_start(argList, _format);
  165. int32_t len = vsnprintf(_str, _size, _format, argList);
  166. va_end(argList);
  167. return len;
  168. }
  169. inline void stringPrintfVargs(std::string& _out, const char* _format, va_list _argList)
  170. {
  171. char temp[2048];
  172. char* out = temp;
  173. int32_t len = bx::vsnprintf(out, sizeof(temp), _format, _argList);
  174. if ( (int32_t)sizeof(temp) < len)
  175. {
  176. out = (char*)alloca(len+1);
  177. len = bx::vsnprintf(out, len, _format, _argList);
  178. }
  179. out[len] = '\0';
  180. _out.append(out);
  181. }
  182. inline void stringPrintf(std::string& _out, const char* _format, ...)
  183. {
  184. va_list argList;
  185. va_start(argList, _format);
  186. stringPrintfVargs(_out, _format, argList);
  187. va_end(argList);
  188. }
  189. } // namespace bx
  190. #endif // __BX_PRINTF_H__