String.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <AK/FlyString.h>
  27. #include <AK/Format.h>
  28. #include <AK/Memory.h>
  29. #include <AK/StdLibExtras.h>
  30. #include <AK/String.h>
  31. #include <AK/StringBuilder.h>
  32. #include <AK/StringView.h>
  33. #include <AK/Vector.h>
  34. #ifndef KERNEL
  35. # include <inttypes.h>
  36. #endif
  37. namespace AK {
  38. String::String(const StringView& view)
  39. {
  40. if (view.m_impl)
  41. m_impl = *view.m_impl;
  42. else
  43. m_impl = StringImpl::create(view.characters_without_null_termination(), view.length());
  44. }
  45. bool String::operator==(const FlyString& fly_string) const
  46. {
  47. return *this == String(fly_string.impl());
  48. }
  49. bool String::operator==(const String& other) const
  50. {
  51. if (!m_impl)
  52. return !other.m_impl;
  53. if (!other.m_impl)
  54. return false;
  55. if (length() != other.length())
  56. return false;
  57. return !memcmp(characters(), other.characters(), length());
  58. }
  59. bool String::operator==(const StringView& other) const
  60. {
  61. if (!m_impl)
  62. return !other.m_characters;
  63. if (!other.m_characters)
  64. return false;
  65. if (length() != other.length())
  66. return false;
  67. return !memcmp(characters(), other.characters_without_null_termination(), length());
  68. }
  69. bool String::operator<(const String& other) const
  70. {
  71. if (!m_impl)
  72. return other.m_impl;
  73. if (!other.m_impl)
  74. return false;
  75. return strcmp(characters(), other.characters()) < 0;
  76. }
  77. bool String::operator>(const String& other) const
  78. {
  79. if (!m_impl)
  80. return other.m_impl;
  81. if (!other.m_impl)
  82. return false;
  83. return strcmp(characters(), other.characters()) > 0;
  84. }
  85. String String::empty()
  86. {
  87. return StringImpl::the_empty_stringimpl();
  88. }
  89. bool String::copy_characters_to_buffer(char* buffer, size_t buffer_size) const
  90. {
  91. // We must fit at least the NUL-terminator.
  92. ASSERT(buffer_size > 0);
  93. size_t characters_to_copy = min(length(), buffer_size - 1);
  94. __builtin_memcpy(buffer, characters(), characters_to_copy);
  95. buffer[characters_to_copy] = 0;
  96. return characters_to_copy == length();
  97. }
  98. String String::isolated_copy() const
  99. {
  100. if (!m_impl)
  101. return {};
  102. if (!m_impl->length())
  103. return empty();
  104. char* buffer;
  105. auto impl = StringImpl::create_uninitialized(length(), buffer);
  106. memcpy(buffer, m_impl->characters(), m_impl->length());
  107. return String(move(*impl));
  108. }
  109. String String::substring(size_t start, size_t length) const
  110. {
  111. if (!length)
  112. return "";
  113. ASSERT(m_impl);
  114. ASSERT(start + length <= m_impl->length());
  115. // FIXME: This needs some input bounds checking.
  116. return { characters() + start, length };
  117. }
  118. StringView String::substring_view(size_t start, size_t length) const
  119. {
  120. ASSERT(m_impl);
  121. ASSERT(start + length <= m_impl->length());
  122. // FIXME: This needs some input bounds checking.
  123. return { characters() + start, length };
  124. }
  125. Vector<String> String::split(char separator, bool keep_empty) const
  126. {
  127. return split_limit(separator, 0, keep_empty);
  128. }
  129. Vector<String> String::split_limit(char separator, size_t limit, bool keep_empty) const
  130. {
  131. if (is_empty())
  132. return {};
  133. Vector<String> v;
  134. size_t substart = 0;
  135. for (size_t i = 0; i < length() && (v.size() + 1) != limit; ++i) {
  136. char ch = characters()[i];
  137. if (ch == separator) {
  138. size_t sublen = i - substart;
  139. if (sublen != 0 || keep_empty)
  140. v.append(substring(substart, sublen));
  141. substart = i + 1;
  142. }
  143. }
  144. size_t taillen = length() - substart;
  145. if (taillen != 0 || keep_empty)
  146. v.append(substring(substart, taillen));
  147. return v;
  148. }
  149. Vector<StringView> String::split_view(const char separator, bool keep_empty) const
  150. {
  151. if (is_empty())
  152. return {};
  153. Vector<StringView> v;
  154. size_t substart = 0;
  155. for (size_t i = 0; i < length(); ++i) {
  156. char ch = characters()[i];
  157. if (ch == separator) {
  158. size_t sublen = i - substart;
  159. if (sublen != 0 || keep_empty)
  160. v.append(substring_view(substart, sublen));
  161. substart = i + 1;
  162. }
  163. }
  164. size_t taillen = length() - substart;
  165. if (taillen != 0 || keep_empty)
  166. v.append(substring_view(substart, taillen));
  167. return v;
  168. }
  169. ByteBuffer String::to_byte_buffer() const
  170. {
  171. if (!m_impl)
  172. return nullptr;
  173. return ByteBuffer::copy(reinterpret_cast<const u8*>(characters()), length());
  174. }
  175. Optional<int> String::to_int() const
  176. {
  177. return StringUtils::convert_to_int(view());
  178. }
  179. Optional<unsigned> String::to_uint() const
  180. {
  181. return StringUtils::convert_to_uint(view());
  182. }
  183. template<typename T>
  184. String String::number(T value) { return formatted("{}", value); }
  185. template String String::number(unsigned char);
  186. template String String::number(unsigned short);
  187. template String String::number(unsigned int);
  188. template String String::number(unsigned long);
  189. template String String::number(unsigned long long);
  190. template String String::number(char);
  191. template String String::number(short);
  192. template String String::number(int);
  193. template String String::number(long);
  194. template String String::number(long long);
  195. template String String::number(signed char);
  196. String String::format(const char* fmt, ...)
  197. {
  198. StringBuilder builder;
  199. va_list ap;
  200. va_start(ap, fmt);
  201. builder.appendvf(fmt, ap);
  202. va_end(ap);
  203. return builder.to_string();
  204. }
  205. bool String::starts_with(const StringView& str, CaseSensitivity case_sensitivity) const
  206. {
  207. return StringUtils::starts_with(*this, str, case_sensitivity);
  208. }
  209. bool String::starts_with(char ch) const
  210. {
  211. if (is_empty())
  212. return false;
  213. return characters()[0] == ch;
  214. }
  215. bool String::ends_with(const StringView& str, CaseSensitivity case_sensitivity) const
  216. {
  217. return StringUtils::ends_with(*this, str, case_sensitivity);
  218. }
  219. bool String::ends_with(char ch) const
  220. {
  221. if (is_empty())
  222. return false;
  223. return characters()[length() - 1] == ch;
  224. }
  225. String String::repeated(char ch, size_t count)
  226. {
  227. if (!count)
  228. return empty();
  229. char* buffer;
  230. auto impl = StringImpl::create_uninitialized(count, buffer);
  231. memset(buffer, ch, count);
  232. return *impl;
  233. }
  234. bool String::matches(const StringView& mask, CaseSensitivity case_sensitivity) const
  235. {
  236. return StringUtils::matches(*this, mask, case_sensitivity);
  237. }
  238. bool String::contains(const String& needle) const
  239. {
  240. if (is_null() || needle.is_null())
  241. return false;
  242. return strstr(characters(), needle.characters());
  243. }
  244. Optional<size_t> String::index_of(const String& needle, size_t start) const
  245. {
  246. if (is_null() || needle.is_null())
  247. return {};
  248. const char* self_characters = characters();
  249. const char* result = strstr(self_characters + start, needle.characters());
  250. if (!result)
  251. return {};
  252. return Optional<size_t> { result - self_characters };
  253. }
  254. bool String::equals_ignoring_case(const StringView& other) const
  255. {
  256. return StringUtils::equals_ignoring_case(view(), other);
  257. }
  258. int String::replace(const String& needle, const String& replacement, bool all_occurrences)
  259. {
  260. if (is_empty())
  261. return 0;
  262. Vector<size_t> positions;
  263. size_t start = 0, pos;
  264. for (;;) {
  265. const char* ptr = strstr(characters() + start, needle.characters());
  266. if (!ptr)
  267. break;
  268. pos = ptr - characters();
  269. positions.append(pos);
  270. if (!all_occurrences)
  271. break;
  272. start = pos + 1;
  273. }
  274. if (!positions.size())
  275. return 0;
  276. StringBuilder b;
  277. size_t lastpos = 0;
  278. for (auto& pos : positions) {
  279. b.append(substring_view(lastpos, pos - lastpos));
  280. b.append(replacement);
  281. lastpos = pos + needle.length();
  282. }
  283. b.append(substring_view(lastpos, length() - lastpos));
  284. m_impl = StringImpl::create(b.build().characters());
  285. return positions.size();
  286. }
  287. String escape_html_entities(const StringView& html)
  288. {
  289. StringBuilder builder;
  290. for (size_t i = 0; i < html.length(); ++i) {
  291. if (html[i] == '<')
  292. builder.append("&lt;");
  293. else if (html[i] == '>')
  294. builder.append("&gt;");
  295. else if (html[i] == '&')
  296. builder.append("&amp;");
  297. else
  298. builder.append(html[i]);
  299. }
  300. return builder.to_string();
  301. }
  302. String::String(const FlyString& string)
  303. : m_impl(string.impl())
  304. {
  305. }
  306. String String::to_lowercase() const
  307. {
  308. if (!m_impl)
  309. return {};
  310. return m_impl->to_lowercase();
  311. }
  312. String String::to_uppercase() const
  313. {
  314. if (!m_impl)
  315. return {};
  316. return m_impl->to_uppercase();
  317. }
  318. bool operator<(const char* characters, const String& string)
  319. {
  320. if (!characters)
  321. return !string.is_null();
  322. if (string.is_null())
  323. return false;
  324. return __builtin_strcmp(characters, string.characters()) < 0;
  325. }
  326. bool operator>=(const char* characters, const String& string)
  327. {
  328. return !(characters < string);
  329. }
  330. bool operator>(const char* characters, const String& string)
  331. {
  332. if (!characters)
  333. return !string.is_null();
  334. if (string.is_null())
  335. return false;
  336. return __builtin_strcmp(characters, string.characters()) > 0;
  337. }
  338. bool operator<=(const char* characters, const String& string)
  339. {
  340. return !(characters > string);
  341. }
  342. bool String::operator==(const char* cstring) const
  343. {
  344. if (is_null())
  345. return !cstring;
  346. if (!cstring)
  347. return false;
  348. return !__builtin_strcmp(characters(), cstring);
  349. }
  350. StringView String::view() const
  351. {
  352. return { characters(), length() };
  353. }
  354. InputStream& operator>>(InputStream& stream, String& string)
  355. {
  356. StringBuilder builder;
  357. for (;;) {
  358. char next_char;
  359. stream >> next_char;
  360. if (stream.has_any_error()) {
  361. stream.set_fatal_error();
  362. string = nullptr;
  363. return stream;
  364. }
  365. if (next_char) {
  366. builder.append(next_char);
  367. } else {
  368. string = builder.to_string();
  369. return stream;
  370. }
  371. }
  372. }
  373. String String::vformatted(StringView fmtstr, TypeErasedFormatParams params)
  374. {
  375. StringBuilder builder;
  376. vformat(builder, fmtstr, params);
  377. return builder.to_string();
  378. }
  379. }