String.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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/Memory.h>
  28. #include <AK/StdLibExtras.h>
  29. #include <AK/String.h>
  30. #include <AK/StringBuilder.h>
  31. #include <AK/Vector.h>
  32. #ifndef KERNEL
  33. # include <inttypes.h>
  34. #endif
  35. #ifdef KERNEL
  36. extern "C" char* strstr(const char* haystack, const char* needle);
  37. #endif
  38. namespace AK {
  39. bool String::operator==(const String& other) const
  40. {
  41. if (!m_impl)
  42. return !other.m_impl;
  43. if (!other.m_impl)
  44. return false;
  45. if (length() != other.length())
  46. return false;
  47. return !memcmp(characters(), other.characters(), length());
  48. }
  49. bool String::operator==(const StringView& other) const
  50. {
  51. if (!m_impl)
  52. return !other.m_characters;
  53. if (!other.m_characters)
  54. return false;
  55. if (length() != other.length())
  56. return false;
  57. return !memcmp(characters(), other.characters_without_null_termination(), length());
  58. }
  59. bool String::operator<(const String& other) const
  60. {
  61. if (!m_impl)
  62. return other.m_impl;
  63. if (!other.m_impl)
  64. return false;
  65. return strcmp(characters(), other.characters()) < 0;
  66. }
  67. bool String::operator>(const String& other) const
  68. {
  69. if (!m_impl)
  70. return other.m_impl;
  71. if (!other.m_impl)
  72. return false;
  73. return strcmp(characters(), other.characters()) > 0;
  74. }
  75. String String::empty()
  76. {
  77. return StringImpl::the_empty_stringimpl();
  78. }
  79. String String::isolated_copy() const
  80. {
  81. if (!m_impl)
  82. return {};
  83. if (!m_impl->length())
  84. return empty();
  85. char* buffer;
  86. auto impl = StringImpl::create_uninitialized(length(), buffer);
  87. memcpy(buffer, m_impl->characters(), m_impl->length());
  88. return String(move(*impl));
  89. }
  90. String String::substring(size_t start, size_t length) const
  91. {
  92. if (!length)
  93. return {};
  94. ASSERT(m_impl);
  95. ASSERT(start + length <= m_impl->length());
  96. // FIXME: This needs some input bounds checking.
  97. return { characters() + start, length };
  98. }
  99. StringView String::substring_view(size_t start, size_t length) const
  100. {
  101. ASSERT(m_impl);
  102. ASSERT(start + length <= m_impl->length());
  103. // FIXME: This needs some input bounds checking.
  104. return { characters() + start, length };
  105. }
  106. Vector<String> String::split(char separator, bool keep_empty) const
  107. {
  108. return split_limit(separator, 0, keep_empty);
  109. }
  110. Vector<String> String::split_limit(char separator, size_t limit, bool keep_empty) const
  111. {
  112. if (is_empty())
  113. return {};
  114. Vector<String> v;
  115. size_t substart = 0;
  116. for (size_t i = 0; i < length() && (v.size() + 1) != limit; ++i) {
  117. char ch = characters()[i];
  118. if (ch == separator) {
  119. size_t sublen = i - substart;
  120. if (sublen != 0 || keep_empty)
  121. v.append(substring(substart, sublen));
  122. substart = i + 1;
  123. }
  124. }
  125. size_t taillen = length() - substart;
  126. if (taillen != 0 || keep_empty)
  127. v.append(substring(substart, taillen));
  128. return v;
  129. }
  130. Vector<StringView> String::split_view(const char separator, bool keep_empty) const
  131. {
  132. if (is_empty())
  133. return {};
  134. Vector<StringView> v;
  135. size_t substart = 0;
  136. for (size_t i = 0; i < length(); ++i) {
  137. char ch = characters()[i];
  138. if (ch == separator) {
  139. size_t sublen = i - substart;
  140. if (sublen != 0 || keep_empty)
  141. v.append(substring_view(substart, sublen));
  142. substart = i + 1;
  143. }
  144. }
  145. size_t taillen = length() - substart;
  146. if (taillen != 0 || keep_empty)
  147. v.append(substring_view(substart, taillen));
  148. return v;
  149. }
  150. ByteBuffer String::to_byte_buffer() const
  151. {
  152. if (!m_impl)
  153. return nullptr;
  154. return ByteBuffer::copy(reinterpret_cast<const u8*>(characters()), length());
  155. }
  156. int String::to_int(bool& ok) const
  157. {
  158. return StringUtils::convert_to_int(this->view(), ok);
  159. }
  160. unsigned String::to_uint(bool& ok) const
  161. {
  162. return StringUtils::convert_to_uint(this->view(), ok);
  163. }
  164. String String::number(unsigned long long value)
  165. {
  166. int size;
  167. char buffer[32];
  168. size = sprintf(buffer, "%llu", value);
  169. return String(buffer, size);
  170. }
  171. String String::number(unsigned long value)
  172. {
  173. int size;
  174. char buffer[32];
  175. size = sprintf(buffer, "%lu", value);
  176. return String(buffer, size);
  177. }
  178. String String::number(unsigned value)
  179. {
  180. char buffer[32];
  181. int size = sprintf(buffer, "%u", value);
  182. return String(buffer, size);
  183. }
  184. String String::number(long long value)
  185. {
  186. char buffer[32];
  187. int size = sprintf(buffer, "%lld", value);
  188. return String(buffer, size);
  189. }
  190. String String::number(long value)
  191. {
  192. char buffer[32];
  193. int size = sprintf(buffer, "%ld", value);
  194. return String(buffer, size);
  195. }
  196. String String::number(int value)
  197. {
  198. char buffer[32];
  199. int size = sprintf(buffer, "%d", value);
  200. return String(buffer, size);
  201. }
  202. String String::format(const char* fmt, ...)
  203. {
  204. StringBuilder builder;
  205. va_list ap;
  206. va_start(ap, fmt);
  207. builder.appendvf(fmt, ap);
  208. va_end(ap);
  209. return builder.to_string();
  210. }
  211. bool String::starts_with(const StringView& str) const
  212. {
  213. if (str.is_empty())
  214. return true;
  215. if (is_empty())
  216. return false;
  217. if (str.length() > length())
  218. return false;
  219. return !memcmp(characters(), str.characters_without_null_termination(), str.length());
  220. }
  221. bool String::starts_with(char ch) const
  222. {
  223. if (is_empty())
  224. return false;
  225. return characters()[0] == ch;
  226. }
  227. bool String::ends_with(const StringView& str) const
  228. {
  229. if (str.is_empty())
  230. return true;
  231. if (is_empty())
  232. return false;
  233. if (str.length() > length())
  234. return false;
  235. return !memcmp(characters() + (length() - str.length()), str.characters_without_null_termination(), str.length());
  236. }
  237. bool String::ends_with(char ch) const
  238. {
  239. if (is_empty())
  240. return false;
  241. return characters()[length() - 1] == ch;
  242. }
  243. String String::repeated(char ch, size_t count)
  244. {
  245. if (!count)
  246. return empty();
  247. char* buffer;
  248. auto impl = StringImpl::create_uninitialized(count, buffer);
  249. memset(buffer, ch, count);
  250. return *impl;
  251. }
  252. bool String::matches(const StringView& mask, CaseSensitivity case_sensitivity) const
  253. {
  254. return StringUtils::matches(*this, mask, case_sensitivity);
  255. }
  256. bool String::contains(const String& needle) const
  257. {
  258. return strstr(characters(), needle.characters());
  259. }
  260. bool String::equals_ignoring_case(const StringView& other) const
  261. {
  262. return StringUtils::equals_ignoring_case(view(), other);
  263. }
  264. String escape_html_entities(const StringView& html)
  265. {
  266. StringBuilder builder;
  267. for (size_t i = 0; i < html.length(); ++i) {
  268. if (html[i] == '<')
  269. builder.append("&lt;");
  270. else if (html[i] == '>')
  271. builder.append("&gt;");
  272. else if (html[i] == '&')
  273. builder.append("&amp;");
  274. else
  275. builder.append(html[i]);
  276. }
  277. return builder.to_string();
  278. }
  279. String::String(const FlyString& string)
  280. : m_impl(string.impl())
  281. {
  282. }
  283. String String::to_lowercase() const
  284. {
  285. if (!m_impl)
  286. return {};
  287. return m_impl->to_lowercase();
  288. }
  289. String String::to_uppercase() const
  290. {
  291. if (!m_impl)
  292. return {};
  293. return m_impl->to_uppercase();
  294. }
  295. }