Serenity Operating System
at portability 222 lines 6.9 kB view raw
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 27#include <AK/ByteBuffer.h> 28#include <AK/String.h> 29#include <AK/StringView.h> 30#include <AK/Vector.h> 31 32namespace AK { 33 34StringView::StringView(const String& string) 35 : m_impl(string.impl()) 36 , m_characters(string.characters()) 37 , m_length(string.length()) 38{ 39} 40 41StringView::StringView(const ByteBuffer& buffer) 42 : m_characters((const char*)buffer.data()) 43 , m_length((size_t)buffer.size()) 44{ 45} 46 47Vector<StringView> StringView::split_view(const char separator, bool keep_empty) const 48{ 49 if (is_empty()) 50 return {}; 51 52 Vector<StringView> v; 53 size_t substart = 0; 54 for (size_t i = 0; i < length(); ++i) { 55 char ch = characters_without_null_termination()[i]; 56 if (ch == separator) { 57 size_t sublen = i - substart; 58 if (sublen != 0 || keep_empty) 59 v.append(substring_view(substart, sublen)); 60 substart = i + 1; 61 } 62 } 63 size_t taillen = length() - substart; 64 if (taillen != 0 || keep_empty) 65 v.append(substring_view(substart, taillen)); 66 return v; 67} 68 69Vector<StringView> StringView::lines(bool consider_cr) const 70{ 71 if (is_empty()) 72 return {}; 73 74 if (!consider_cr) 75 return split_view('\n', true); 76 77 Vector<StringView> v; 78 size_t substart = 0; 79 bool last_ch_was_cr = false; 80 bool split_view = false; 81 for (size_t i = 0; i < length(); ++i) { 82 char ch = characters_without_null_termination()[i]; 83 if (ch == '\n') { 84 split_view = true; 85 if (last_ch_was_cr) { 86 substart = i + 1; 87 split_view = false; 88 last_ch_was_cr = false; 89 } 90 } 91 if (ch == '\r') { 92 split_view = true; 93 last_ch_was_cr = true; 94 } 95 if (split_view) { 96 size_t sublen = i - substart; 97 v.append(substring_view(substart, sublen)); 98 substart = i + 1; 99 } 100 split_view = false; 101 } 102 size_t taillen = length() - substart; 103 if (taillen != 0) 104 v.append(substring_view(substart, taillen)); 105 return v; 106} 107 108bool StringView::starts_with(char ch) const 109{ 110 if (is_empty()) 111 return false; 112 return ch == characters_without_null_termination()[0]; 113} 114 115bool StringView::starts_with(const StringView& str) const 116{ 117 if (str.is_empty()) 118 return true; 119 if (is_empty()) 120 return false; 121 if (str.length() > length()) 122 return false; 123 if (characters_without_null_termination() == str.characters_without_null_termination()) 124 return true; 125 return !memcmp(characters_without_null_termination(), str.characters_without_null_termination(), str.length()); 126} 127 128bool StringView::ends_with(char ch) const 129{ 130 if (is_empty()) 131 return false; 132 return ch == characters_without_null_termination()[length() - 1]; 133} 134 135bool StringView::ends_with(const StringView& str) const 136{ 137 if (str.is_empty()) 138 return true; 139 if (is_empty()) 140 return false; 141 if (str.length() > length()) 142 return false; 143 return !memcmp(characters_without_null_termination() + length() - str.length(), str.characters_without_null_termination(), str.length()); 144} 145 146StringView StringView::substring_view(size_t start, size_t length) const 147{ 148 ASSERT(start + length <= m_length); 149 return { m_characters + start, length }; 150} 151 152StringView StringView::substring_view_starting_from_substring(const StringView& substring) const 153{ 154 const char* remaining_characters = substring.characters_without_null_termination(); 155 ASSERT(remaining_characters >= m_characters); 156 ASSERT(remaining_characters <= m_characters + m_length); 157 size_t remaining_length = m_length - (remaining_characters - m_characters); 158 return { remaining_characters, remaining_length }; 159} 160 161StringView StringView::substring_view_starting_after_substring(const StringView& substring) const 162{ 163 const char* remaining_characters = substring.characters_without_null_termination() + substring.length(); 164 ASSERT(remaining_characters >= m_characters); 165 ASSERT(remaining_characters <= m_characters + m_length); 166 size_t remaining_length = m_length - (remaining_characters - m_characters); 167 return { remaining_characters, remaining_length }; 168} 169 170int StringView::to_int(bool& ok) const 171{ 172 bool negative = false; 173 int value = 0; 174 size_t i = 0; 175 176 if (is_empty()) { 177 ok = false; 178 return 0; 179 } 180 181 if (characters_without_null_termination()[0] == '-') { 182 i++; 183 negative = true; 184 } 185 for (; i < length(); i++) { 186 if (characters_without_null_termination()[i] < '0' || characters_without_null_termination()[i] > '9') { 187 ok = false; 188 return 0; 189 } 190 value = value * 10; 191 value += characters_without_null_termination()[i] - '0'; 192 } 193 ok = true; 194 195 return negative ? -value : value; 196} 197 198unsigned StringView::to_uint(bool& ok) const 199{ 200 unsigned value = 0; 201 for (size_t i = 0; i < length(); ++i) { 202 if (characters_without_null_termination()[i] < '0' || characters_without_null_termination()[i] > '9') { 203 ok = false; 204 return 0; 205 } 206 value = value * 10; 207 value += characters_without_null_termination()[i] - '0'; 208 } 209 ok = true; 210 return value; 211} 212 213unsigned StringView::hash() const 214{ 215 if (is_empty()) 216 return 0; 217 if (m_impl) 218 return m_impl->hash(); 219 return string_hash(characters_without_null_termination(), length()); 220} 221 222}