Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AK: Cherry Pick the Optional changes from LB #25337

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
5 changes: 5 additions & 0 deletions AK/Assertions.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@ static constexpr bool TODO = false;
# define TODO() VERIFY(TODO) /* NOLINT(cert-dcl03-c,misc-static-assert) No, this can't be static_assert, it's a runtime check */
# define TODO_AARCH64() VERIFY(TODO) /* NOLINT(cert-dcl03-c,misc-static-assert) No, this can't be static_assert, it's a runtime check */
# define TODO_RISCV64() VERIFY(TODO) /* NOLINT(cert-dcl03-c,misc-static-assert) No, this can't be static_assert, it's a runtime check */

// For LB compatibility
// Note: Assertions in LB are removed in release builds
# define ASSERT(expr) VERIFY(expr)
# define ASSERT_NOT_REACHED() VERIFY_NOT_REACHED()
#endif
18 changes: 18 additions & 0 deletions AK/ByteBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#pragma once

#include <AK/Assertions.h>
#include <AK/Badge.h>
#include <AK/Error.h>
#include <AK/Span.h>
#include <AK/Types.h>
Expand Down Expand Up @@ -298,6 +299,23 @@ class ByteBuffer {
operator ReadonlyBytes() const { return bytes(); }

ALWAYS_INLINE size_t capacity() const { return m_inline ? inline_capacity : m_outline_capacity; }
ALWAYS_INLINE bool is_inline() const { return m_inline; }

struct OutlineBuffer {
Bytes buffer;
size_t capacity { 0 };
};
Optional<OutlineBuffer> leak_outline_buffer(Badge<StringBuilder>)
{
if (m_inline)
return {};

auto buffer = bytes();
m_inline = true;
m_size = 0;

return OutlineBuffer { buffer, capacity() };
}

private:
void move_from(ByteBuffer&& other)
Expand Down
2 changes: 2 additions & 0 deletions AK/FlyString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ FlyString FlyString::from_utf8_without_validation(ReadonlyBytes string)

FlyString::FlyString(String const& string)
{
ASSERT(!string.is_invalid());

if (string.is_short_string()) {
m_data = string;
return;
Expand Down
118 changes: 118 additions & 0 deletions AK/FlyString.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <AK/Error.h>
#include <AK/Format.h>
#include <AK/Optional.h>
#include <AK/Platform.h>
#include <AK/String.h>
#include <AK/Traits.h>
Expand Down Expand Up @@ -77,12 +78,129 @@ class FlyString {
}

private:
friend class Optional<FlyString>;

explicit FlyString(nullptr_t)
: m_data(Detail::StringBase(nullptr))
{
}

explicit FlyString(Detail::StringBase data)
: m_data(move(data))
{
}

Detail::StringBase m_data;

bool is_invalid() const { return m_data.is_invalid(); }
};

template<>
class Optional<FlyString> : public OptionalBase<FlyString> {
template<typename U>
friend class Optional;

public:
using ValueType = FlyString;

Optional() = default;

template<SameAs<OptionalNone> V>
Optional(V) { }

Optional(Optional<FlyString> const& other)
{
if (other.has_value())
m_value = other.m_value;
}

Optional(Optional&& other)
: m_value(other.m_value)
{
}

template<typename U = FlyString>
requires(!IsSame<OptionalNone, RemoveCVReference<U>>)
explicit(!IsConvertible<U&&, FlyString>) Optional(U&& value)
requires(!IsSame<RemoveCVReference<U>, Optional<FlyString>> && IsConstructible<FlyString, U &&>)
: m_value(forward<U>(value))
{
}

template<SameAs<OptionalNone> V>
Optional& operator=(V)
{
clear();
return *this;
}

Optional& operator=(Optional const& other)
{
if (this != &other) {
clear();
m_value = other.m_value;
}
return *this;
}

Optional& operator=(Optional&& other)
{
if (this != &other) {
clear();
m_value = other.m_value;
}
return *this;
}

template<typename O>
ALWAYS_INLINE bool operator==(Optional<O> const& other) const
{
return has_value() == other.has_value() && (!has_value() || value() == other.value());
}

template<typename O>
ALWAYS_INLINE bool operator==(O const& other) const
{
return has_value() && value() == other;
}

void clear()
{
m_value = FlyString(nullptr);
}

[[nodiscard]] bool has_value() const
{
return !m_value.is_invalid();
}

[[nodiscard]] FlyString& value() &
{
VERIFY(has_value());
return m_value;
}

[[nodiscard]] FlyString const& value() const&
{
VERIFY(has_value());
return m_value;
}

[[nodiscard]] FlyString value() &&
{
return release_value();
}

[[nodiscard]] FlyString release_value()
{
VERIFY(has_value());
FlyString released_value = m_value;
clear();
return released_value;
}

private:
FlyString m_value = FlyString(nullptr);
};

template<>
Expand Down
12 changes: 12 additions & 0 deletions AK/Forward.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ namespace AK {
namespace Detail {
template<size_t inline_capacity>
class ByteBuffer;

class StringData;
}

enum class TrailingCodePointTransformation : u8;
Expand Down Expand Up @@ -128,6 +130,16 @@ class NonnullOwnPtr;
template<typename T>
class Optional;

#ifndef KERNEL

template<>
class Optional<String>;

template<>
class Optional<FlyString>;

#endif

#ifdef KERNEL
template<typename T>
class NonnullLockRefPtr;
Expand Down
43 changes: 43 additions & 0 deletions AK/Noncopyable.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,46 @@ public: \
public: \
c(c const&) = default; \
c& operator=(c const&) = default

#define AK_MAKE_CONDITIONALLY_NONMOVABLE(c, ...) \
public: \
c(c&&) \
requires(!(AK::Detail::IsMoveConstructible __VA_ARGS__)) \
= delete; \
c& operator=(c&&) \
requires(!(AK::Detail::IsMoveConstructible __VA_ARGS__) \
|| !(AK::Detail::IsDestructible __VA_ARGS__)) \
= delete

#define AK_MAKE_CONDITIONALLY_MOVABLE(c, T) \
AK_MAKE_CONDITIONALLY_NONMOVABLE(c, T); \
c(c&&) = default; \
c& operator=(c&&) = default

#define AK_MAKE_CONDITIONALLY_NONCOPYABLE(c, ...) \
public: \
c(c const&) \
requires(!(AK::Detail::IsCopyConstructible __VA_ARGS__)) \
= delete; \
c& operator=(c const&) \
requires(!(AK::Detail::IsCopyConstructible __VA_ARGS__) \
|| !(AK::Detail::IsDestructible __VA_ARGS__)) \
= delete

#define AK_MAKE_CONDITIONALLY_COPYABLE(c, ...) \
AK_MAKE_CONDITIONALLY_NONCOPYABLE(c, __VA_ARGS__); \
c(c const&) = default; \
c& operator=(c const&) = default

#define AK_MAKE_CONDITIONALLY_NONDESTRUCTIBLE(c, ...) \
public: \
~c() \
requires(!(AK::Detail::IsDestructible __VA_ARGS__)) \
= delete

#define AK_MAKE_CONDITIONALLY_DESTRUCTIBLE(c, ...) \
public: \
~c() \
requires(!(AK::Detail::IsDestructible __VA_ARGS__)) \
= delete; \
~c() = default
Loading
Loading