#include #include namespace AK { StringView::StringView(const String& string) : m_impl(string.impl()) , m_characters(string.characters()) , m_length(string.length()) { } StringView::StringView(const ByteBuffer& buffer) : m_characters((const char*)buffer.data()) , m_length(buffer.size()) { } Vector StringView::split_view(const char separator, bool keep_empty) const { if (is_empty()) return {}; Vector v; ssize_t substart = 0; for (ssize_t i = 0; i < length(); ++i) { char ch = characters_without_null_termination()[i]; if (ch == separator) { ssize_t sublen = i - substart; if (sublen != 0 || keep_empty) v.append(substring_view(substart, sublen)); substart = i + 1; } } ssize_t taillen = length() - substart; if (taillen != 0 || keep_empty) v.append(substring_view(substart, taillen)); if (characters_without_null_termination()[length() - 1] == separator && keep_empty) v.append(String::empty()); return v; } Vector StringView::lines(bool consider_cr) const { if (is_empty()) return {}; if (!consider_cr) return split_view('\n', true); Vector v; ssize_t substart = 0; bool last_ch_was_cr = false; bool split_view = false; for (ssize_t i = 0; i < length(); ++i) { char ch = characters_without_null_termination()[i]; if (ch == '\n') { split_view = true; if (last_ch_was_cr) { substart = i + 1; split_view = false; last_ch_was_cr = false; } } if (ch == '\r') { split_view = true; last_ch_was_cr = true; } if (split_view) { ssize_t sublen = i - substart; if (sublen != 0) v.append(substring_view(substart, sublen)); substart = i + 1; } split_view = false; } ssize_t taillen = length() - substart; if (taillen != 0) v.append(substring_view(substart, taillen)); return v; } bool StringView::starts_with(const StringView& str) const { if (str.is_empty()) return true; if (is_empty()) return false; if (str.length() > length()) return false; if (characters_without_null_termination() == str.characters_without_null_termination()) return true; return !memcmp(characters_without_null_termination(), str.characters_without_null_termination(), str.length()); } StringView StringView::substring_view(int start, int length) const { if (!length) return {}; ASSERT(start + length <= m_length); return { m_characters + start, length }; } StringView StringView::substring_view_starting_from_substring(const StringView& substring) const { const char* remaining_characters = substring.characters_without_null_termination(); ASSERT(remaining_characters >= m_characters); ASSERT(remaining_characters <= m_characters + m_length); int remaining_length = m_length - (remaining_characters - m_characters); return { remaining_characters, remaining_length }; } StringView StringView::substring_view_starting_after_substring(const StringView& substring) const { const char* remaining_characters = substring.characters_without_null_termination() + substring.length(); ASSERT(remaining_characters >= m_characters); ASSERT(remaining_characters <= m_characters + m_length); int remaining_length = m_length - (remaining_characters - m_characters); return { remaining_characters, remaining_length }; } int StringView::to_int(bool& ok) const { bool negative = false; int value = 0; int i = 0; if (is_empty()) { ok = false; return 0; } if (characters_without_null_termination()[0] == '-') { i++; negative = true; } for (; i < length(); i++) { if (characters_without_null_termination()[i] < '0' || characters_without_null_termination()[i] > '9') { ok = false; return 0; } value = value * 10; value += characters_without_null_termination()[i] - '0'; } ok = true; return negative ? -value : value; } unsigned StringView::to_uint(bool& ok) const { unsigned value = 0; for (ssize_t i = 0; i < length(); ++i) { if (characters_without_null_termination()[i] < '0' || characters_without_null_termination()[i] > '9') { ok = false; return 0; } value = value * 10; value += characters_without_null_termination()[i] - '0'; } ok = true; return value; } unsigned StringView::hash() const { if (is_empty()) return 0; if (m_impl) return m_impl->hash(); return string_hash(characters_without_null_termination(), length()); } }