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;
|
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_null() const { return !m_impl; }
|
||||||
bool is_empty() const { return length() == 0; }
|
bool is_empty() const { return length() == 0; }
|
||||||
|
@ -124,6 +127,19 @@ private:
|
||||||
RetainPtr<StringImpl> m_impl;
|
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<>
|
template<>
|
||||||
struct Traits<String> {
|
struct Traits<String> {
|
||||||
static unsigned hash(const String& s) { return s.impl() ? s.impl()->hash() : 0; }
|
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));
|
return String(move(*impl));
|
||||||
}
|
}
|
||||||
|
|
||||||
String String::substring(ssize_t start, ssize_t length) const
|
String String::substring(int start, int length) const
|
||||||
{
|
{
|
||||||
if (!length)
|
if (!length)
|
||||||
return empty();
|
return { };
|
||||||
ASSERT(m_impl);
|
ASSERT(m_impl);
|
||||||
ASSERT(start + length <= m_impl->length());
|
ASSERT(start + length <= m_impl->length());
|
||||||
// FIXME: This needs some input bounds checking.
|
// FIXME: This needs some input bounds checking.
|
||||||
char* buffer;
|
return { characters() + start, length };
|
||||||
auto new_impl = StringImpl::create_uninitialized(length, buffer);
|
}
|
||||||
memcpy(buffer, characters() + start, length);
|
|
||||||
buffer[length] = '\0';
|
StringView String::substring_view(int start, int length) const
|
||||||
return new_impl;
|
{
|
||||||
|
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
|
Vector<String> String::split(const char separator) const
|
||||||
|
@ -85,6 +91,30 @@ Vector<String> String::split(const char separator) const
|
||||||
return v;
|
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
|
ByteBuffer String::to_byte_buffer() const
|
||||||
{
|
{
|
||||||
if (!m_impl)
|
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
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Vector.h>
|
||||||
|
|
||||||
|
namespace AK {
|
||||||
|
|
||||||
|
class String;
|
||||||
|
|
||||||
class StringView {
|
class StringView {
|
||||||
public:
|
public:
|
||||||
StringView() { }
|
StringView() { }
|
||||||
|
@ -19,7 +25,20 @@ public:
|
||||||
int length() const { return m_length; }
|
int length() const { return m_length; }
|
||||||
char operator[](int index) const { return m_characters[index]; }
|
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:
|
private:
|
||||||
const char* m_characters { nullptr };
|
const char* m_characters { nullptr };
|
||||||
int m_length { 0 };
|
int m_length { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
using AK::StringView;
|
||||||
|
|
|
@ -561,7 +561,7 @@ void IRCClient::handle_user_command(const String& input)
|
||||||
auto parts = input.split(' ');
|
auto parts = input.split(' ');
|
||||||
if (parts.is_empty())
|
if (parts.is_empty())
|
||||||
return;
|
return;
|
||||||
auto command = parts[0].to_uppercase();
|
auto command = String(parts[0]).to_uppercase();
|
||||||
if (command == "/NICK") {
|
if (command == "/NICK") {
|
||||||
if (parts.size() >= 2)
|
if (parts.size() >= 2)
|
||||||
change_nick(parts[1]);
|
change_nick(parts[1]);
|
||||||
|
|
|
@ -577,8 +577,7 @@ KResultOr<InodeIdentifier> VFS::resolve_path(StringView path, InodeIdentifier ba
|
||||||
if (path.is_empty())
|
if (path.is_empty())
|
||||||
return KResult(-EINVAL);
|
return KResult(-EINVAL);
|
||||||
|
|
||||||
// FIXME: Use StringView::split() once it exists.
|
auto parts = path.split_view('/');
|
||||||
auto parts = String(path).split('/');
|
|
||||||
InodeIdentifier crumb_id;
|
InodeIdentifier crumb_id;
|
||||||
|
|
||||||
if (path[0] == '/')
|
if (path[0] == '/')
|
||||||
|
|
|
@ -68,6 +68,7 @@ AK_OBJS = \
|
||||||
../AK/String.o \
|
../AK/String.o \
|
||||||
../AK/StringImpl.o \
|
../AK/StringImpl.o \
|
||||||
../AK/StringBuilder.o \
|
../AK/StringBuilder.o \
|
||||||
|
../AK/StringView.o \
|
||||||
../AK/FileSystemPath.o \
|
../AK/FileSystemPath.o \
|
||||||
../AK/StdLibExtras.o
|
../AK/StdLibExtras.o
|
||||||
|
|
||||||
|
|
|
@ -25,14 +25,14 @@
|
||||||
#include <Kernel/Net/E1000NetworkAdapter.h>
|
#include <Kernel/Net/E1000NetworkAdapter.h>
|
||||||
#include <Kernel/Net/NetworkTask.h>
|
#include <Kernel/Net/NetworkTask.h>
|
||||||
|
|
||||||
//#define SPAWN_TERMINAL
|
#define SPAWN_TERMINAL
|
||||||
//#define SPAWN_LAUNCHER
|
//#define SPAWN_LAUNCHER
|
||||||
//#define SPAWN_GUITEST2
|
//#define SPAWN_GUITEST2
|
||||||
//#define SPAWN_FILE_MANAGER
|
//#define SPAWN_FILE_MANAGER
|
||||||
//#define SPAWN_PROCESS_MANAGER
|
//#define SPAWN_PROCESS_MANAGER
|
||||||
//#define SPAWN_TEXT_EDITOR
|
//#define SPAWN_TEXT_EDITOR
|
||||||
//#define SPAWN_FONTEDITOR
|
//#define SPAWN_FONTEDITOR
|
||||||
#define SPAWN_VISUAL_BUILDER
|
//#define SPAWN_VISUAL_BUILDER
|
||||||
//#define SPAWN_MULTIPLE_SHELLS
|
//#define SPAWN_MULTIPLE_SHELLS
|
||||||
//#define STRESS_TEST_SPAWNING
|
//#define STRESS_TEST_SPAWNING
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
AK_OBJS = \
|
AK_OBJS = \
|
||||||
../AK/StringImpl.o \
|
../AK/StringImpl.o \
|
||||||
../AK/String.o \
|
../AK/String.o \
|
||||||
|
../AK/StringView.o \
|
||||||
../AK/StringBuilder.o \
|
../AK/StringBuilder.o \
|
||||||
../AK/FileSystemPath.o \
|
../AK/FileSystemPath.o \
|
||||||
../AK/StdLibExtras.o \
|
../AK/StdLibExtras.o \
|
||||||
|
|
Loading…
Reference in a new issue