StringView.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/AnyOf.h>
  7. #include <AK/ByteBuffer.h>
  8. #include <AK/Find.h>
  9. #include <AK/Function.h>
  10. #include <AK/StringBuilder.h>
  11. #include <AK/StringView.h>
  12. #include <AK/Vector.h>
  13. #ifndef KERNEL
  14. # include <AK/DeprecatedFlyString.h>
  15. # include <AK/DeprecatedString.h>
  16. # include <AK/FlyString.h>
  17. # include <AK/String.h>
  18. #endif
  19. namespace AK {
  20. #ifndef KERNEL
  21. StringView::StringView(String const& string)
  22. : m_characters(reinterpret_cast<char const*>(string.bytes().data()))
  23. , m_length(string.bytes().size())
  24. {
  25. }
  26. StringView::StringView(FlyString const& string)
  27. : m_characters(reinterpret_cast<char const*>(string.bytes().data()))
  28. , m_length(string.bytes().size())
  29. {
  30. }
  31. StringView::StringView(DeprecatedString const& string)
  32. : m_characters(string.characters())
  33. , m_length(string.length())
  34. {
  35. }
  36. StringView::StringView(DeprecatedFlyString const& string)
  37. : m_characters(string.characters())
  38. , m_length(string.length())
  39. {
  40. }
  41. #endif
  42. StringView::StringView(ByteBuffer const& buffer)
  43. : m_characters((char const*)buffer.data())
  44. , m_length(buffer.size())
  45. {
  46. }
  47. Vector<StringView> StringView::split_view(char const separator, SplitBehavior split_behavior) const
  48. {
  49. StringView seperator_view { &separator, 1 };
  50. return split_view(seperator_view, split_behavior);
  51. }
  52. Vector<StringView> StringView::split_view(StringView separator, SplitBehavior split_behavior) const
  53. {
  54. Vector<StringView> parts;
  55. for_each_split_view(separator, split_behavior, [&](StringView view) {
  56. parts.append(view);
  57. });
  58. return parts;
  59. }
  60. Vector<StringView> StringView::lines(bool consider_cr) const
  61. {
  62. if (is_empty())
  63. return {};
  64. if (!consider_cr)
  65. return split_view('\n', SplitBehavior::KeepEmpty);
  66. Vector<StringView> v;
  67. size_t substart = 0;
  68. bool last_ch_was_cr = false;
  69. bool split_view = false;
  70. for (size_t i = 0; i < length(); ++i) {
  71. char ch = characters_without_null_termination()[i];
  72. if (ch == '\n') {
  73. split_view = true;
  74. if (last_ch_was_cr) {
  75. substart = i + 1;
  76. split_view = false;
  77. }
  78. }
  79. if (ch == '\r') {
  80. split_view = true;
  81. last_ch_was_cr = true;
  82. } else {
  83. last_ch_was_cr = false;
  84. }
  85. if (split_view) {
  86. size_t sublen = i - substart;
  87. v.append(substring_view(substart, sublen));
  88. substart = i + 1;
  89. }
  90. split_view = false;
  91. }
  92. size_t taillen = length() - substart;
  93. if (taillen != 0)
  94. v.append(substring_view(substart, taillen));
  95. return v;
  96. }
  97. bool StringView::starts_with(char ch) const
  98. {
  99. if (is_empty())
  100. return false;
  101. return ch == characters_without_null_termination()[0];
  102. }
  103. bool StringView::starts_with(StringView str, CaseSensitivity case_sensitivity) const
  104. {
  105. return StringUtils::starts_with(*this, str, case_sensitivity);
  106. }
  107. bool StringView::ends_with(char ch) const
  108. {
  109. if (is_empty())
  110. return false;
  111. return ch == characters_without_null_termination()[length() - 1];
  112. }
  113. bool StringView::ends_with(StringView str, CaseSensitivity case_sensitivity) const
  114. {
  115. return StringUtils::ends_with(*this, str, case_sensitivity);
  116. }
  117. bool StringView::matches(StringView mask, Vector<MaskSpan>& mask_spans, CaseSensitivity case_sensitivity) const
  118. {
  119. return StringUtils::matches(*this, mask, case_sensitivity, &mask_spans);
  120. }
  121. bool StringView::matches(StringView mask, CaseSensitivity case_sensitivity) const
  122. {
  123. return StringUtils::matches(*this, mask, case_sensitivity);
  124. }
  125. bool StringView::contains(char needle) const
  126. {
  127. for (char current : *this) {
  128. if (current == needle)
  129. return true;
  130. }
  131. return false;
  132. }
  133. bool StringView::contains(u32 needle) const
  134. {
  135. // A code point should be at most four UTF-8 bytes, which easily fits into StringBuilder's inline-buffer.
  136. // Therefore, this will not allocate.
  137. StringBuilder needle_builder;
  138. auto result = needle_builder.try_append_code_point(needle);
  139. if (result.is_error()) {
  140. // The needle is invalid, therefore the string does not contain it.
  141. return false;
  142. }
  143. return contains(needle_builder.string_view());
  144. }
  145. bool StringView::contains(StringView needle, CaseSensitivity case_sensitivity) const
  146. {
  147. return StringUtils::contains(*this, needle, case_sensitivity);
  148. }
  149. bool StringView::equals_ignoring_ascii_case(StringView other) const
  150. {
  151. return StringUtils::equals_ignoring_ascii_case(*this, other);
  152. }
  153. #ifndef KERNEL
  154. DeprecatedString StringView::to_lowercase_string() const
  155. {
  156. return StringImpl::create_lowercased(characters_without_null_termination(), length()).release_nonnull();
  157. }
  158. DeprecatedString StringView::to_uppercase_string() const
  159. {
  160. return StringImpl::create_uppercased(characters_without_null_termination(), length()).release_nonnull();
  161. }
  162. DeprecatedString StringView::to_titlecase_string() const
  163. {
  164. return StringUtils::to_titlecase(*this);
  165. }
  166. #endif
  167. StringView StringView::substring_view_starting_from_substring(StringView substring) const
  168. {
  169. char const* remaining_characters = substring.characters_without_null_termination();
  170. VERIFY(remaining_characters >= m_characters);
  171. VERIFY(remaining_characters <= m_characters + m_length);
  172. size_t remaining_length = m_length - (remaining_characters - m_characters);
  173. return { remaining_characters, remaining_length };
  174. }
  175. StringView StringView::substring_view_starting_after_substring(StringView substring) const
  176. {
  177. char const* remaining_characters = substring.characters_without_null_termination() + substring.length();
  178. VERIFY(remaining_characters >= m_characters);
  179. VERIFY(remaining_characters <= m_characters + m_length);
  180. size_t remaining_length = m_length - (remaining_characters - m_characters);
  181. return { remaining_characters, remaining_length };
  182. }
  183. bool StringView::copy_characters_to_buffer(char* buffer, size_t buffer_size) const
  184. {
  185. // We must fit at least the NUL-terminator.
  186. VERIFY(buffer_size > 0);
  187. size_t characters_to_copy = min(m_length, buffer_size - 1);
  188. __builtin_memcpy(buffer, m_characters, characters_to_copy);
  189. buffer[characters_to_copy] = 0;
  190. return characters_to_copy == m_length;
  191. }
  192. template<typename T>
  193. Optional<T> StringView::to_int() const
  194. {
  195. return StringUtils::convert_to_int<T>(*this);
  196. }
  197. template Optional<i8> StringView::to_int() const;
  198. template Optional<i16> StringView::to_int() const;
  199. template Optional<i32> StringView::to_int() const;
  200. template Optional<long> StringView::to_int() const;
  201. template Optional<long long> StringView::to_int() const;
  202. template<typename T>
  203. Optional<T> StringView::to_uint() const
  204. {
  205. return StringUtils::convert_to_uint<T>(*this);
  206. }
  207. template Optional<u8> StringView::to_uint() const;
  208. template Optional<u16> StringView::to_uint() const;
  209. template Optional<u32> StringView::to_uint() const;
  210. template Optional<unsigned long> StringView::to_uint() const;
  211. template Optional<unsigned long long> StringView::to_uint() const;
  212. #ifndef KERNEL
  213. Optional<double> StringView::to_double(TrimWhitespace trim_whitespace) const
  214. {
  215. return StringUtils::convert_to_floating_point<double>(*this, trim_whitespace);
  216. }
  217. Optional<float> StringView::to_float(TrimWhitespace trim_whitespace) const
  218. {
  219. return StringUtils::convert_to_floating_point<float>(*this, trim_whitespace);
  220. }
  221. bool StringView::operator==(DeprecatedString const& string) const
  222. {
  223. return *this == string.view();
  224. }
  225. DeprecatedString StringView::to_deprecated_string() const { return DeprecatedString { *this }; }
  226. DeprecatedString StringView::replace(StringView needle, StringView replacement, ReplaceMode replace_mode) const
  227. {
  228. return StringUtils::replace(*this, needle, replacement, replace_mode);
  229. }
  230. #endif
  231. Vector<size_t> StringView::find_all(StringView needle) const
  232. {
  233. return StringUtils::find_all(*this, needle);
  234. }
  235. Vector<StringView> StringView::split_view_if(Function<bool(char)> const& predicate, SplitBehavior split_behavior) const
  236. {
  237. if (is_empty())
  238. return {};
  239. Vector<StringView> v;
  240. size_t substart = 0;
  241. bool keep_empty = has_flag(split_behavior, SplitBehavior::KeepEmpty);
  242. bool keep_separator = has_flag(split_behavior, SplitBehavior::KeepTrailingSeparator);
  243. for (size_t i = 0; i < length(); ++i) {
  244. char ch = characters_without_null_termination()[i];
  245. if (predicate(ch)) {
  246. size_t sublen = i - substart;
  247. if (sublen != 0 || keep_empty)
  248. v.append(substring_view(substart, keep_separator ? sublen + 1 : sublen));
  249. substart = i + 1;
  250. }
  251. }
  252. size_t taillen = length() - substart;
  253. if (taillen != 0 || keep_empty)
  254. v.append(substring_view(substart, taillen));
  255. return v;
  256. }
  257. }