string.h - Engine C API Reference

string.h
  1. #pragma once
  2. #include "allocator.h"
  3. #include "assert.h"
  4. #include "array.h"
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <limits.h>
  8. namespace stingray_plugin_foundation {
  9. template <class T> class Vector;
  10. // ----------------------------------------------------------------------
  11. // Functions that extend the normal ANSI C string interface.
  12. // ----------------------------------------------------------------------
  13. // Returns the length of the string a 32-bit number (unsigned rather
  14. // than size_t).
  15. inline unsigned strlen32(const char *s);
  16. // Returns the length of the string a 32-bit number (unsigned rather
  17. // than size_t).
  18. inline unsigned strlenw32(const wchar_t *s);
  19. // Returns true if strings s1 and s2 are identical.
  20. inline bool strequal(const char *s1, const char *s2);
  21. // Returns true if strings s1 and s2 are identical when ignoring case.
  22. // Only ascii characters (A-Z) are considered when comparing case.
  23. bool strequali(const char *s1, const char *s2);
  24. // Returns true if string s is empty.
  25. inline bool strempty(const char *s);
  26. // Converts s to an integer and returns the result.
  27. inline int to_int(const char *s);
  28. // Converts s to an unsigned and returns the result.
  29. inline unsigned to_unsigned(const char *s);
  30. // Converts s to a float and returns the result.
  31. inline float to_float(const char *s);
  32. // Converts s to an integer and returns the result.
  33. inline int to_int(const char *s, bool &error);
  34. // Converts s to an unsigned and returns the result.
  35. inline unsigned to_unsigned(const char *s, bool &error);
  36. // Converts s to a float and returns the result.
  37. inline float to_float(const char *s, bool &error);
  38. // ----------------------------------------------------------------------
  39. // A thin wrapper around a const char * that just adds a == operator for string
  40. // comparison. Note especially that it doesn't make a copy of the string. The
  41. // original string pointer must be valid as long as this class is used.
  42. //
  43. // Typically, this class is used to make string comparisons easier to read
  44. // and prevent mistakes. An example:
  45. //
  46. // ConstString s(p)
  47. // if (s == "open")
  48. // ...
  49. class ConstString
  50. {
  51. public:
  52. // ConstString that wraps the empty string.
  53. ConstString() : s("") {}
  54. // ConstString that wraps the specified string.
  55. ConstString(const char *s_) : s(s_) {}
  56. // Returns the raw string pointer.
  57. const char *c_str() const {return s;}
  58. // Returns true if the string is empty.
  59. bool empty() const {return *s == 0;}
  60. // Returns the length of the string
  61. unsigned size() const {return strlen32(s);}
  62. const char *s;
  63. };
  64. // Comparison operators for ConstString.
  65. inline bool operator==(const ConstString &s1, const char *s2) {return strcmp(s1.s, s2) == 0;}
  66. inline bool operator==(const char *s1, const ConstString &s2) {return strcmp(s1, s2.s) == 0;}
  67. inline bool operator==(const ConstString &s1, const ConstString &s2) {return strcmp(s1.s, s2.s) == 0;}
  68. inline bool operator!=(const ConstString &s1, const char *s2) {return strcmp(s1.s, s2) != 0;}
  69. inline bool operator!=(const char *s1, const ConstString &s2) {return strcmp(s1, s2.s) != 0;}
  70. inline bool operator!=(const ConstString &s1, const ConstString &s2) {return strcmp(s1.s, s2.s) != 0;}
  71. inline bool operator<(const ConstString &s1, const char *s2) {return strcmp(s1.s, s2) < 0;}
  72. inline bool operator<(const char *s1, const ConstString &s2) {return strcmp(s1, s2.s) < 0;}
  73. inline bool operator<(const ConstString &s1, const ConstString &s2) {return strcmp(s1.s, s2.s) < 0;}
  74. // ----------------------------------------------------------------------
  75. // Class that represents a dynamic string -- a string whose content can be modified.
  76. // This class is basically just a thin wrapper around an Array<char> buffer that stores
  77. // the content of the string.
  78. class DynamicString
  79. {
  80. public:
  81. ALLOCATOR_AWARE;
  82. // Creates a new dynamic string using the specified allocator.
  83. DynamicString(Allocator &a) : _buffer(a) {}
  84. // Creates a new dynamic string initialized from s.
  85. DynamicString(Allocator &a, const char *s) : _buffer(a) { unsigned length = s ? strlen32(s) : 0; if (length > 0) { _buffer.resize(length + 1); memmove(_buffer.begin(), s, _buffer.size()); } }
  86. // Creates a new dynamic string initialized from the first n characters of s.
  87. DynamicString(Allocator &a, const char *s, unsigned n) : _buffer(a) { if (n > 0) { _buffer.resize(n + 1); memmove(_buffer.begin(), s, n); _buffer[n] = 0; } }
  88. // Copy constructor
  89. DynamicString(const DynamicString &o) : _buffer(o._buffer) {}
  90. // Assignment.
  91. void operator=(const char *s) { unsigned length = strlen32(s); if (length > 0) { _buffer.resize(length + 1); memmove(_buffer.begin(), s, _buffer.size()); } else _buffer.clear(); }
  92. // Assigns the characters from ds to this string. Does not change the allocator.
  93. void operator=(const DynamicString &ds) { _buffer = ds._buffer; }
  94. // Returns the size/length of the string. The size does not include the terminating zero.
  95. unsigned size() const {return _buffer.empty() ? 0 : _buffer.size() - 1;}
  96. // Returns true if the string is empty.
  97. bool empty() const {return size() == 0;}
  98. // Returns the C-string held by this dynamic string.
  99. char *c_str() { return _buffer.empty() ? empty_string() : _buffer.begin(); }
  100. const char *c_str() const {return _buffer.empty() ? empty_string() : _buffer.begin();}
  101. // Returns a pointer to the terminating zero at the end of C-string.
  102. char *end() { return _buffer.empty() ? c_str() : _buffer.end() - 1; }
  103. const char *end() const { return _buffer.empty() ? c_str() : _buffer.end() - 1; }
  104. // Accesses characters in the string.
  105. char &operator[](unsigned i) { return c_str()[i];}
  106. const char &operator[](unsigned i) const { return c_str()[i]; }
  107. // Resizes the string to the specified size (size does not include terminating zero).
  108. void resize(unsigned size) { bool empty = _buffer.empty(); _buffer.resize(size + 1); if (empty) _buffer[0] = '\0'; _buffer[size] = '\0'; }
  109. // Extends the string with the specified number of bytes.
  110. void extend(unsigned bytes) {resize(size() + bytes);}
  111. // Clears the memory and sets this string to the empty string.
  112. void clear() { _buffer.clear(); }
  113. // Returns the allocator of the string.
  114. Allocator &allocator() const {return _buffer.allocator();}
  115. // Swaps the contents efficiently.
  116. void swap(DynamicString &other);
  117. // Serializes the string to the stream
  118. template <class STREAM> void serialize(STREAM &s) {
  119. unsigned sz = size();
  120. s & sz;
  121. if (sz != size())
  122. resize(sz);
  123. if (sz != 0) {
  124. if (s.is_output())
  125. s.write(_buffer.begin(), sz);
  126. else
  127. s.read(_buffer.begin(), sz);
  128. }
  129. }
  130. Array<char> &buffer() { if (_buffer.empty()) _buffer.push_back(0); return _buffer; }
  131. private:
  132. // Raw access to the string buffer.
  133. Array<char> _buffer;
  134. static char *empty_string() { static char c = '\0'; return &c; }
  135. };
  136. // Comparison operators
  137. inline bool operator==(const DynamicString &s1, const char *s2) {return strcmp(s1.c_str(), s2) == 0;}
  138. inline bool operator==(const char *s1, const DynamicString &s2) {return strcmp(s1, s2.c_str()) == 0;}
  139. inline bool operator==(const DynamicString &s1, const DynamicString &s2) {return strcmp(s1.c_str(), s2.c_str()) == 0;}
  140. inline bool operator!=(const DynamicString &s1, const char *s2) {return strcmp(s1.c_str(), s2) != 0;}
  141. inline bool operator!=(const char *s1, const DynamicString &s2) {return strcmp(s1, s2.c_str()) != 0;}
  142. inline bool operator!=(const DynamicString &s1, const DynamicString &s2) {return strcmp(s1.c_str(), s2.c_str()) != 0;}
  143. inline bool operator<(const DynamicString &s1, const char *s2) {return strcmp(s1.c_str(), s2) < 0;}
  144. inline bool operator<(const char *s1, const DynamicString &s2) {return strcmp(s1, s2.c_str()) < 0;}
  145. inline bool operator<(const DynamicString &s1, const DynamicString &s2) {return strcmp(s1.c_str(), s2.c_str()) < 0;}
  146. // Appends `s` to the end of `str`.
  147. inline void append(DynamicString &str, const char *s);
  148. // Appends `c` to the end of `str`.
  149. inline void append(DynamicString &str, char c);
  150. // Appends `len` characters beginning from `s` to the end of `str`.
  151. inline void append(DynamicString &str, const char *s, unsigned len);
  152. // Inserts `s` in front of any characters in `str`.
  153. inline void prefix(DynamicString &str, const char *s);
  154. // ----------------------------------------------------------------------
  155. // Namespace for string operations.
  156. namespace string {
  157. const unsigned npos = UINT_MAX;
  158. // Returns true if c is a whitespace character.
  159. bool is_whitespace(char c);
  160. // Returns the index of the first occurrence of `c` in
  161. // `s` or `npos` if not found.
  162. unsigned find(const char *s, char c);
  163. // Returns the index of the last occurrence of `c` in
  164. // `s` or `npos` if not found.
  165. unsigned find_last(const char *s, char c);
  166. // Returns the index of the first occurrence of `substring` in
  167. // `s` or `npos` if not found.
  168. unsigned find(const char *s, const char *substring);
  169. // Returns the index of the last occurrence of `substring` in
  170. // `s` or `npos` if not found.
  171. unsigned find_last(const char *s, const char *substring);
  172. // Returns true if `s` contains `substring`.
  173. bool contains(const char *s, const char *substring);
  174. // Splits the string `s` on the first instance of `split_on` and stores the
  175. // results in `first` and `second`. If `split_on` is not found, `first`
  176. // will get the entire string.
  177. void split(const char *s, const char *split_on, DynamicString &first, DynamicString &second);
  178. // Splits the string `s` on all instances of `split_on` and stores the
  179. // results in `result`
  180. void split(const char *s, const char *split_by, Vector<DynamicString> &result);
  181. enum SkipEmpty { SKIP_EMPTY, DONT_SKIP_EMPTY };
  182. // Joins each string in `strings` into a single string separated by `separator` and stores the result in `result`.
  183. void join(const DynamicString* strings, unsigned num_strings, const char* separator, DynamicString& result, SkipEmpty skip_empty = DONT_SKIP_EMPTY);
  184. // Returns a pointer to a string with n spaces for indentation purposes. If n > 200 a string with 200 spaces
  185. // will be returned.
  186. const char *spaces(int n);
  187. // Returns true if s is a lowercase string.
  188. bool is_lowercase(const char *s);
  189. // Replaces the character range (start, start+size) in the string s with the
  190. // replacement rep.
  191. void replace(DynamicString &s, unsigned start, unsigned size, const char *rep);
  192. // Replaces the occurances of the string `find` with the replacement `rep` and returns the number of successful replacements made.
  193. unsigned replace_all(DynamicString &s, const char *find, const char *rep);
  194. // In-place converts the string to lower case
  195. void to_lower_case(char *s);
  196. // In-place converts the string to upper case
  197. void to_upper_case(char *s);
  198. // Converts from camel case to underscore representation.
  199. DynamicString from_camel_case(const char *s, Allocator &a);
  200. // Returns the string with the character stripped out.
  201. DynamicString strip(const char *s, char c, Allocator &a);
  202. // Trims whitespace from the start and end of the string and returns the result.
  203. DynamicString trim(const char *s, Allocator &a);
  204. // Returns a substring of s starting at start and of length.
  205. DynamicString substring(const char *s, unsigned start, unsigned length, Allocator &a);
  206. // Returns true if `str` contains `c`.
  207. bool in_string(const char *str, char c);
  208. // Returns true if `str` only contains characters in `allowed`.
  209. bool consists_of(const char *str, const char *allowed);
  210. // Returns true if `str` begins with `begins`.
  211. bool begins_with(const char *str, const char *begins);
  212. // Returns true if `str` ends with `ends`.
  213. bool ends_with(const char *str, const char *ends);
  214. bool ends_with(const wchar_t *str, const wchar_t *ends);
  215. // Returns a copy of the string `str` allocated with the allocator `a`.
  216. char* copy(const char *str, Allocator& a);
  217. // Copies src to dest. Truncates the copy if necessary so that more than
  218. // `dest_size` bytes are never written to `dest`. Always terminates
  219. // dest with a \0 character. Utf-8 characters are guaranteed to not get
  220. // truncated in the middle of a multibyte character.
  221. void copy(char *dest, const char *src, unsigned dest_size);
  222. void copy(wchar_t *dest, const wchar_t *src, unsigned dest_size);
  223. // Appends `src` to the end of `dest`. Truncates `dest` if necessary so that
  224. // more than `dest_size` bytes are never written to `dest`. Always terminates
  225. // dest with a \0 character. Utf-8 characters are guaranteed to not get
  226. // truncated in the middle of a multibyte character.
  227. void append(char *dest, const char *src, unsigned dest_size);
  228. void append(wchar_t *dest, const wchar_t *src, unsigned dest_size);
  229. #ifdef DEVELOPMENT
  230. // Returns a string allocated by `a` representing a typcial hex_view of the `data`.
  231. // (Such as shown by a memory debugger, for instance.)
  232. // `columns` is the number of columns of hex values in the view.
  233. // If `ascii_column` is true a column that shows ascii representation is included.
  234. DynamicString hex_view(Allocator &a, const char *data, unsigned size, unsigned columns = 16, bool ascii_column = true);
  235. #endif
  236. } // namespace string
  237. }
  238. #include "string.inl"