summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-04-16 02:39:16 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-04-16 02:39:16 +0200
commit33920df299620822cd9f95f9c7475d1e39a21e63 (patch)
treeaeec0e4b4bb289c0f0a036d845033ee628e22a42
parenta082738f04e099b7200172a8742d9e1cbf6bb1c1 (diff)
downloadserenity-33920df299620822cd9f95f9c7475d1e39a21e63.zip
AK: Try to use StringViews more for substrings and splitting.
-rw-r--r--AK/AKString.h18
-rw-r--r--AK/String.cpp44
-rw-r--r--AK/StringView.cpp54
-rw-r--r--AK/StringView.h19
-rw-r--r--Applications/IRCClient/IRCClient.cpp2
-rw-r--r--Kernel/FileSystem/VirtualFileSystem.cpp3
-rw-r--r--Kernel/Makefile1
-rw-r--r--Kernel/init.cpp4
-rw-r--r--LibC/Makefile1
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 \