string.inl 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. * Copyright 2010-2022 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
  4. */
  5. #ifndef BX_STRING_H_HEADER_GUARD
  6. # error "Must be included from bx/string.h!"
  7. #endif // BX_STRING_H_HEADER_GUARD
  8. #if BX_CRT_MSVC && !defined(va_copy)
  9. # define va_copy(_a, _b) (_a) = (_b)
  10. #endif // BX_CRT_MSVC && !defined(va_copy)
  11. namespace bx
  12. {
  13. template <typename Ty>
  14. inline void stringPrintfVargs(Ty& _out, const char* _format, va_list _argList)
  15. {
  16. char temp[2048];
  17. char* out = temp;
  18. int32_t len = vsnprintf(out, sizeof(temp), _format, _argList);
  19. if (int32_t(sizeof(temp) ) < len)
  20. {
  21. out = (char*)alloca(len);
  22. len = vsnprintf(out, len, _format, _argList);
  23. }
  24. _out.append(out, out+len);
  25. }
  26. template <typename Ty>
  27. inline void stringPrintf(Ty& _out, const char* _format, ...)
  28. {
  29. va_list argList;
  30. va_start(argList, _format);
  31. stringPrintfVargs(_out, _format, argList);
  32. va_end(argList);
  33. }
  34. inline StringView::StringView()
  35. {
  36. clear();
  37. }
  38. inline StringView::StringView(const StringView& _rhs, int32_t _start, int32_t _len)
  39. {
  40. set(_rhs, _start, _len);
  41. }
  42. inline StringView& StringView::operator=(const char* _rhs)
  43. {
  44. set(_rhs);
  45. return *this;
  46. }
  47. inline StringView& StringView::operator=(const StringView& _rhs)
  48. {
  49. set(_rhs);
  50. return *this;
  51. }
  52. inline StringView::StringView(const char* _ptr)
  53. {
  54. set(_ptr, INT32_MAX);
  55. }
  56. inline StringView::StringView(const char* _ptr, int32_t _len)
  57. {
  58. set(_ptr, _len);
  59. }
  60. inline StringView::StringView(const char* _ptr, const char* _term)
  61. {
  62. set(_ptr, _term);
  63. }
  64. inline void StringView::set(const char* _ptr)
  65. {
  66. set(_ptr, INT32_MAX);
  67. }
  68. inline void StringView::set(const char* _ptr, int32_t _len)
  69. {
  70. clear();
  71. if (NULL != _ptr)
  72. {
  73. m_len = INT32_MAX == _len ? strLen(_ptr) : _len;
  74. m_ptr = _ptr;
  75. m_0terminated = INT32_MAX == _len;
  76. }
  77. }
  78. inline void StringView::set(const char* _ptr, const char* _term)
  79. {
  80. set(_ptr, int32_t(_term-_ptr) );
  81. }
  82. inline void StringView::set(const StringView& _str, int32_t _start, int32_t _len)
  83. {
  84. const int32_t start = min(_start, _str.m_len);
  85. const int32_t len = clamp(_str.m_len - start, 0, min(_len, _str.m_len) );
  86. set(_str.m_ptr + start, len);
  87. }
  88. inline void StringView::clear()
  89. {
  90. m_ptr = "";
  91. m_len = 0;
  92. m_0terminated = true;
  93. }
  94. inline const char* StringView::getPtr() const
  95. {
  96. return m_ptr;
  97. }
  98. inline const char* StringView::getTerm() const
  99. {
  100. return m_ptr + m_len;
  101. }
  102. inline bool StringView::isEmpty() const
  103. {
  104. return 0 == m_len;
  105. }
  106. inline int32_t StringView::getLength() const
  107. {
  108. return m_len;
  109. }
  110. inline bool StringView::is0Terminated() const
  111. {
  112. return m_0terminated;
  113. }
  114. template<bx::AllocatorI** AllocatorT>
  115. inline StringT<AllocatorT>::StringT()
  116. : StringView()
  117. , m_capacity(0)
  118. {
  119. clear();
  120. }
  121. template<bx::AllocatorI** AllocatorT>
  122. inline StringT<AllocatorT>::StringT(const StringT<AllocatorT>& _rhs)
  123. : StringView()
  124. , m_capacity(0)
  125. {
  126. set(_rhs);
  127. }
  128. template<bx::AllocatorI** AllocatorT>
  129. inline StringT<AllocatorT>::StringT(const StringView& _rhs)
  130. : StringView()
  131. , m_capacity(0)
  132. {
  133. set(_rhs);
  134. }
  135. template<bx::AllocatorI** AllocatorT>
  136. inline StringT<AllocatorT>::~StringT()
  137. {
  138. clear();
  139. }
  140. template<bx::AllocatorI** AllocatorT>
  141. inline StringT<AllocatorT>& StringT<AllocatorT>::operator=(const StringT<AllocatorT>& _rhs)
  142. {
  143. set(_rhs);
  144. return *this;
  145. }
  146. template<bx::AllocatorI** AllocatorT>
  147. inline void StringT<AllocatorT>::set(const StringView& _str)
  148. {
  149. clear();
  150. append(_str);
  151. }
  152. template<bx::AllocatorI** AllocatorT>
  153. inline void StringT<AllocatorT>::append(const StringView& _str)
  154. {
  155. if (0 != _str.getLength() )
  156. {
  157. const int32_t old = m_len;
  158. const int32_t len = m_len + _str.getLength();
  159. char* ptr = const_cast<char*>(m_ptr);
  160. if (len+1 > m_capacity)
  161. {
  162. const int32_t capacity = alignUp(len+1, 256);
  163. ptr = (char*)BX_REALLOC(*AllocatorT, 0 != m_capacity ? ptr : NULL, capacity);
  164. *const_cast<char**>(&m_ptr) = ptr;
  165. m_capacity = capacity;
  166. }
  167. m_len = len;
  168. strCopy(ptr + old, len-old+1, _str);
  169. }
  170. }
  171. template<bx::AllocatorI** AllocatorT>
  172. inline void StringT<AllocatorT>::append(const char* _ptr, const char* _term)
  173. {
  174. append(StringView(_ptr, _term) );
  175. }
  176. template<bx::AllocatorI** AllocatorT>
  177. inline void StringT<AllocatorT>::clear()
  178. {
  179. m_0terminated = true;
  180. if (0 != m_capacity)
  181. {
  182. BX_FREE(*AllocatorT, const_cast<char*>(m_ptr) );
  183. StringView::clear();
  184. m_capacity = 0;
  185. }
  186. }
  187. template<bx::AllocatorI** AllocatorT>
  188. inline const char* StringT<AllocatorT>::getCPtr() const
  189. {
  190. return getPtr();
  191. }
  192. inline StringView strSubstr(const StringView& _str, int32_t _start, int32_t _len)
  193. {
  194. return StringView(_str, _start, _len);
  195. }
  196. inline LineReader::LineReader(const bx::StringView& _str)
  197. : m_str(_str)
  198. {
  199. reset();
  200. }
  201. inline void LineReader::reset()
  202. {
  203. m_curr = m_str;
  204. m_line = 0;
  205. }
  206. inline StringView LineReader::next()
  207. {
  208. if (m_curr.getPtr() != m_str.getTerm() )
  209. {
  210. ++m_line;
  211. StringView curr(m_curr);
  212. m_curr = bx::strFindNl(m_curr);
  213. StringView line(curr.getPtr(), m_curr.getPtr() );
  214. return strRTrim(strRTrim(line, "\n"), "\r");
  215. }
  216. return m_curr;
  217. }
  218. inline bool LineReader::isDone() const
  219. {
  220. return m_curr.getPtr() == m_str.getTerm();
  221. }
  222. inline uint32_t LineReader::getLine() const
  223. {
  224. return m_line;
  225. }
  226. inline bool hasPrefix(const StringView& _str, const StringView& _prefix)
  227. {
  228. const int32_t len = _prefix.getLength();
  229. return _str.getLength() >= len
  230. && 0 == strCmp(_str, _prefix, len)
  231. ;
  232. }
  233. inline bool hasSuffix(const StringView& _str, const StringView& _suffix)
  234. {
  235. const int32_t len = _suffix.getLength();
  236. return _str.getLength() >= len
  237. && 0 == strCmp(StringView(_str.getTerm() - len, _str.getTerm() ), _suffix, len)
  238. ;
  239. }
  240. inline StringView strTrimPrefix(const StringView& _str, const StringView& _prefix)
  241. {
  242. if (hasPrefix(_str, _prefix) )
  243. {
  244. return StringView(_str.getPtr() + _prefix.getLength(), _str.getTerm() );
  245. }
  246. return _str;
  247. }
  248. inline StringView strTrimSuffix(const StringView& _str, const StringView& _suffix)
  249. {
  250. if (hasSuffix(_str, _suffix) )
  251. {
  252. return StringView(_str.getPtr(), _str.getTerm() - _suffix.getLength() );
  253. }
  254. return _str;
  255. }
  256. } // namespace bx