diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-04-16 02:39:16 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-04-16 02:39:16 +0200 |
commit | 33920df299620822cd9f95f9c7475d1e39a21e63 (patch) | |
tree | aeec0e4b4bb289c0f0a036d845033ee628e22a42 | |
parent | a082738f04e099b7200172a8742d9e1cbf6bb1c1 (diff) | |
download | serenity-33920df299620822cd9f95f9c7475d1e39a21e63.zip |
AK: Try to use StringViews more for substrings and splitting.
-rw-r--r-- | AK/AKString.h | 18 | ||||
-rw-r--r-- | AK/String.cpp | 44 | ||||
-rw-r--r-- | AK/StringView.cpp | 54 | ||||
-rw-r--r-- | AK/StringView.h | 19 | ||||
-rw-r--r-- | Applications/IRCClient/IRCClient.cpp | 2 | ||||
-rw-r--r-- | Kernel/FileSystem/VirtualFileSystem.cpp | 3 | ||||
-rw-r--r-- | Kernel/Makefile | 1 | ||||
-rw-r--r-- | Kernel/init.cpp | 4 | ||||
-rw-r--r-- | LibC/Makefile | 1 |
9 files changed, 133 insertions, 13 deletions
diff --git a/AK/AKString.h b/AK/AKString.h index 3c2fdd7f87..cd13f7f722 100644 --- a/AK/AKString.h +++ b/AK/AKString.h @@ -78,7 +78,10 @@ public: } Vector<String> split(char separator) const; - String substring(ssize_t start, ssize_t length) const; + String substring(int start, int length) const; + + Vector<StringView> split_view(char separator) const; + StringView substring_view(int start, int length) const; bool is_null() const { return !m_impl; } bool is_empty() const { return length() == 0; } @@ -124,6 +127,19 @@ private: RetainPtr<StringImpl> m_impl; }; +inline bool StringView::operator==(const String& string) const +{ + if (string.is_null()) + return !m_characters; + if (!m_characters) + return false; + if (m_length != string.length()) + return false; + if (m_characters == string.characters()) + return true; + return !memcmp(m_characters, string.characters(), m_length); +} + template<> struct Traits<String> { static unsigned hash(const String& s) { return s.impl() ? s.impl()->hash() : 0; } diff --git a/AK/String.cpp b/AK/String.cpp index e3fa54ff80..fbdaa350ef 100644 --- a/AK/String.cpp +++ b/AK/String.cpp @@ -47,18 +47,24 @@ String String::isolated_copy() const return String(move(*impl)); } -String String::substring(ssize_t start, ssize_t length) const +String String::substring(int start, int length) const { if (!length) - return empty(); + return { }; ASSERT(m_impl); ASSERT(start + length <= m_impl->length()); // FIXME: This needs some input bounds checking. - char* buffer; - auto new_impl = StringImpl::create_uninitialized(length, buffer); - memcpy(buffer, characters() + start, length); - buffer[length] = '\0'; - return new_impl; + return { characters() + start, length }; +} + +StringView String::substring_view(int start, int length) const +{ + if (!length) + return { }; + ASSERT(m_impl); + ASSERT(start + length <= m_impl->length()); + // FIXME: This needs some input bounds checking. + return { characters() + start, length }; } Vector<String> String::split(const char separator) const @@ -85,6 +91,30 @@ Vector<String> String::split(const char separator) const return v; } +Vector<StringView> String::split_view(const char separator) const +{ + if (is_empty()) + return { }; + + Vector<StringView> v; + ssize_t substart = 0; + for (ssize_t i = 0; i < length(); ++i) { + char ch = characters()[i]; + if (ch == separator) { + ssize_t sublen = i - substart; + if (sublen != 0) + v.append(substring_view(substart, sublen)); + substart = i + 1; + } + } + ssize_t taillen = length() - substart; + if (taillen != 0) + v.append(substring_view(substart, taillen)); + if (characters()[length() - 1] == separator) + v.append(empty().view()); + return v; +} + ByteBuffer String::to_byte_buffer() const { if (!m_impl) diff --git a/AK/StringView.cpp b/AK/StringView.cpp new file mode 100644 index 0000000000..06fe6752e5 --- /dev/null +++ b/AK/StringView.cpp @@ -0,0 +1,54 @@ +#include <AK/StringView.h> +#include <AK/AKString.h> + +namespace AK { + +Vector<StringView> StringView::split_view(const char separator) const +{ + if (is_empty()) + return { }; + + Vector<StringView> v; + ssize_t substart = 0; + for (ssize_t i = 0; i < length(); ++i) { + char ch = characters()[i]; + if (ch == separator) { + ssize_t sublen = i - substart; + if (sublen != 0) + v.append(substring_view(substart, sublen)); + substart = i + 1; + } + } + ssize_t taillen = length() - substart; + if (taillen != 0) + v.append(substring_view(substart, taillen)); + if (characters()[length() - 1] == separator) + v.append(String::empty().view()); + return v; +} + +StringView StringView::substring_view(int start, int length) const +{ + if (!length) + return { }; + ASSERT(start + length <= m_length); + return { m_characters + start, length }; +} + +unsigned StringView::to_uint(bool& ok) const +{ + unsigned value = 0; + for (ssize_t i = 0; i < length(); ++i) { + if (characters()[i] < '0' || characters()[i] > '9') { + ok = false; + return 0; + } + value = value * 10; + value += characters()[i] - '0'; + } + ok = true; + return value; +} + + +} diff --git a/AK/StringView.h b/AK/StringView.h index 6dd8cef17a..51ccd2f67c 100644 --- a/AK/StringView.h +++ b/AK/StringView.h @@ -1,5 +1,11 @@ #pragma once +#include <AK/Vector.h> + +namespace AK { + +class String; + class StringView { public: StringView() { } @@ -19,7 +25,20 @@ public: int length() const { return m_length; } char operator[](int index) const { return m_characters[index]; } + StringView substring_view(int start, int length) const; + Vector<StringView> split_view(char) const; + unsigned to_uint(bool& ok) const; + + bool operator==(const char* cstring) const { return !strcmp(m_characters, cstring); } + bool operator!=(const char* cstring) const { return strcmp(m_characters, cstring); } + + bool operator==(const String&) const; + private: const char* m_characters { nullptr }; int m_length { 0 }; }; + +} + +using AK::StringView; diff --git a/Applications/IRCClient/IRCClient.cpp b/Applications/IRCClient/IRCClient.cpp index 0a9cb11790..5c53b1e84a 100644 --- a/Applications/IRCClient/IRCClient.cpp +++ b/Applications/IRCClient/IRCClient.cpp @@ -561,7 +561,7 @@ void IRCClient::handle_user_command(const String& input) auto parts = input.split(' '); if (parts.is_empty()) return; - auto command = parts[0].to_uppercase(); + auto command = String(parts[0]).to_uppercase(); if (command == "/NICK") { if (parts.size() >= 2) change_nick(parts[1]); diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index 76d25c1eb2..e3a1737d35 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -577,8 +577,7 @@ KResultOr<InodeIdentifier> VFS::resolve_path(StringView path, InodeIdentifier ba if (path.is_empty()) return KResult(-EINVAL); - // FIXME: Use StringView::split() once it exists. - auto parts = String(path).split('/'); + auto parts = path.split_view('/'); InodeIdentifier crumb_id; if (path[0] == '/') diff --git a/Kernel/Makefile b/Kernel/Makefile index e738a35582..a771e4f068 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -68,6 +68,7 @@ AK_OBJS = \ ../AK/String.o \ ../AK/StringImpl.o \ ../AK/StringBuilder.o \ + ../AK/StringView.o \ ../AK/FileSystemPath.o \ ../AK/StdLibExtras.o diff --git a/Kernel/init.cpp b/Kernel/init.cpp index ea74bdc741..440aac263a 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -25,14 +25,14 @@ #include <Kernel/Net/E1000NetworkAdapter.h> #include <Kernel/Net/NetworkTask.h> -//#define SPAWN_TERMINAL +#define SPAWN_TERMINAL //#define SPAWN_LAUNCHER //#define SPAWN_GUITEST2 //#define SPAWN_FILE_MANAGER //#define SPAWN_PROCESS_MANAGER //#define SPAWN_TEXT_EDITOR //#define SPAWN_FONTEDITOR -#define SPAWN_VISUAL_BUILDER +//#define SPAWN_VISUAL_BUILDER //#define SPAWN_MULTIPLE_SHELLS //#define STRESS_TEST_SPAWNING diff --git a/LibC/Makefile b/LibC/Makefile index dd2d7c839d..f6c209cfee 100644 --- a/LibC/Makefile +++ b/LibC/Makefile @@ -1,6 +1,7 @@ AK_OBJS = \ ../AK/StringImpl.o \ ../AK/String.o \ + ../AK/StringView.o \ ../AK/StringBuilder.o \ ../AK/FileSystemPath.o \ ../AK/StdLibExtras.o \ |