mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 09:00:22 +00:00
AK: Try to use StringViews more for substrings and splitting.
This commit is contained in:
parent
a082738f04
commit
33920df299
Notes:
sideshowbarker
2024-07-19 14:41:32 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/33920df2996
9 changed files with 133 additions and 13 deletions
|
@ -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; }
|
||||
|
|
|
@ -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
AK/StringView.cpp
Normal file
54
AK/StringView.cpp
Normal file
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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] == '/')
|
||||
|
|
|
@ -68,6 +68,7 @@ AK_OBJS = \
|
|||
../AK/String.o \
|
||||
../AK/StringImpl.o \
|
||||
../AK/StringBuilder.o \
|
||||
../AK/StringView.o \
|
||||
../AK/FileSystemPath.o \
|
||||
../AK/StdLibExtras.o
|
||||
|
||||
|
|
|
@ -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,6 +1,7 @@
|
|||
AK_OBJS = \
|
||||
../AK/StringImpl.o \
|
||||
../AK/String.o \
|
||||
../AK/StringView.o \
|
||||
../AK/StringBuilder.o \
|
||||
../AK/FileSystemPath.o \
|
||||
../AK/StdLibExtras.o \
|
||||
|
|
Loading…
Reference in a new issue