Преглед изворни кода

AK: Try to use StringViews more for substrings and splitting.

Andreas Kling пре 6 година
родитељ
комит
33920df299

+ 17 - 1
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; }

+ 37 - 7
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)

+ 54 - 0
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;
+}
+
+
+}

+ 19 - 0
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;

+ 1 - 1
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]);

+ 1 - 2
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] == '/')

+ 1 - 0
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
 

+ 2 - 2
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
 

+ 1 - 0
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 \