dynamic_string.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*
  2. * Copyright (c) 2012-2014 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/taylor001/crown/blob/master/LICENSE
  4. */
  5. #pragma once
  6. #include <algorithm>
  7. #include <cstring>
  8. #include "assert.h"
  9. #include "memory.h"
  10. #include "string_utils.h"
  11. #include "array.h"
  12. #include "string_utils.h"
  13. namespace crown
  14. {
  15. ///
  16. class DynamicString
  17. {
  18. public:
  19. DynamicString(Allocator& allocator = default_allocator());
  20. DynamicString(const char* s, Allocator& allocator = default_allocator());
  21. ~DynamicString();
  22. DynamicString& operator+=(const DynamicString& s);
  23. DynamicString& operator+=(const char* s);
  24. DynamicString& operator+=(const char c);
  25. ///
  26. DynamicString& operator=(const DynamicString& s);
  27. DynamicString& operator=(const char* s);
  28. DynamicString& operator=(const char c);
  29. bool operator<(const DynamicString& s) const;
  30. bool operator==(const DynamicString& s) const;
  31. bool operator==(const char* s) const;
  32. // Returns the length of the string.
  33. uint32_t length() const;
  34. /// Removes the leading string @a s.
  35. /// @note
  36. /// The string must start with @a s.
  37. void strip_leading(const char* s);
  38. /// Removes the trailing string @a s.
  39. /// @note
  40. /// The string must end with @a s.
  41. void strip_trailing(const char* s);
  42. /// Returns whether the string starts with the given @a s string.
  43. bool starts_with(const char* s) const;
  44. /// Returns wheterh the string ends with the given @a s string.
  45. bool ends_with(const char* s) const;
  46. /// Returns the string hashed to murmur2_32.
  47. StringId32 to_string_id() const;
  48. ///
  49. const char* c_str() const;
  50. private:
  51. Array<char> _data;
  52. };
  53. inline DynamicString::DynamicString(Allocator& allocator)
  54. : _data(allocator)
  55. {
  56. array::push_back(_data, '\0');
  57. }
  58. inline DynamicString::DynamicString(const char* s, Allocator& allocator)
  59. : _data(allocator)
  60. {
  61. if (s != NULL)
  62. {
  63. array::push(_data, s, strlen(s));
  64. }
  65. array::push_back(_data, '\0');
  66. }
  67. inline DynamicString::~DynamicString()
  68. {
  69. }
  70. inline DynamicString& DynamicString::operator+=(const DynamicString& s)
  71. {
  72. return *this += s.c_str();
  73. }
  74. inline DynamicString& DynamicString::operator+=(const char* s)
  75. {
  76. CE_ASSERT_NOT_NULL(s);
  77. array::pop_back(_data);
  78. array::push(_data, s, strlen(s));
  79. array::push_back(_data, '\0');
  80. return *this;
  81. }
  82. inline DynamicString& DynamicString::operator+=(const char c)
  83. {
  84. array::pop_back(_data);
  85. array::push_back(_data, c);
  86. array::push_back(_data, '\0');
  87. return *this;
  88. }
  89. inline DynamicString& DynamicString::operator=(const DynamicString& s)
  90. {
  91. _data = s._data;
  92. return *this;
  93. }
  94. inline DynamicString& DynamicString::operator=(const char* s)
  95. {
  96. CE_ASSERT_NOT_NULL(s);
  97. array::clear(_data);
  98. array::push(_data, s, strlen(s));
  99. array::push_back(_data, '\0');
  100. return *this;
  101. }
  102. inline DynamicString& DynamicString::operator=(const char c)
  103. {
  104. array::clear(_data);
  105. array::push_back(_data, c);
  106. return *this;
  107. }
  108. inline bool DynamicString::operator<(const DynamicString& s) const
  109. {
  110. return strcmp(c_str(), s.c_str()) < 0;
  111. }
  112. inline bool DynamicString::operator==(const DynamicString& s) const
  113. {
  114. return strcmp(c_str(), s.c_str()) == 0;
  115. }
  116. inline bool DynamicString::operator==(const char* s) const
  117. {
  118. CE_ASSERT_NOT_NULL(s);
  119. return strcmp(c_str(), s) == 0;
  120. }
  121. inline uint32_t DynamicString::length() const
  122. {
  123. return strlen(this->c_str());
  124. }
  125. inline void DynamicString::strip_leading(const char* s)
  126. {
  127. CE_ASSERT_NOT_NULL(s);
  128. CE_ASSERT(starts_with(s), "String does not start with %s", s);
  129. const size_t my_len = strlen(c_str());
  130. const size_t s_len = strlen(s);
  131. memmove(array::begin(_data), array::begin(_data) + s_len, (my_len - s_len));
  132. array::resize(_data, my_len - s_len);
  133. array::push_back(_data, '\0');
  134. }
  135. inline void DynamicString::strip_trailing(const char* s)
  136. {
  137. CE_ASSERT_NOT_NULL(s);
  138. CE_ASSERT(ends_with(s), "String does not end with %s", s);
  139. const size_t my_len = strlen(c_str());
  140. const size_t s_len = strlen(s);
  141. array::resize(_data, my_len - s_len);
  142. array::push_back(_data, '\0');
  143. }
  144. inline bool DynamicString::starts_with(const char* s) const
  145. {
  146. CE_ASSERT_NOT_NULL(s);
  147. return strncmp(c_str(), s, strlen(s)) == 0;
  148. }
  149. inline bool DynamicString::ends_with(const char* s) const
  150. {
  151. CE_ASSERT_NOT_NULL(s);
  152. const size_t my_len = strlen(c_str());
  153. const size_t s_len = strlen(s);
  154. if (my_len >= s_len)
  155. {
  156. return strncmp(array::begin(_data) + (my_len - s_len), s, s_len) == 0;
  157. }
  158. return false;
  159. }
  160. inline StringId32 DynamicString::to_string_id() const
  161. {
  162. return murmur2_32(c_str(), length());
  163. }
  164. inline const char* DynamicString::c_str() const
  165. {
  166. return array::begin(_data);
  167. }
  168. } // namespace crown