/* * Copyright (c) 2020, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include #include namespace AK { struct FlyStringImplTraits : public Traits { static unsigned hash(StringImpl const* s) { return s ? s->hash() : 0; } static bool equals(StringImpl const* a, StringImpl const* b) { VERIFY(a); VERIFY(b); return *a == *b; } }; static Singleton> s_table; static HashTable& fly_impls() { return *s_table; } void FlyString::did_destroy_impl(Badge, StringImpl& impl) { fly_impls().remove(&impl); } FlyString::FlyString(DeprecatedString const& string) { if (string.is_null()) return; if (string.impl()->is_fly()) { m_impl = string.impl(); return; } auto it = fly_impls().find(const_cast(string.impl())); if (it == fly_impls().end()) { fly_impls().set(const_cast(string.impl())); string.impl()->set_fly({}, true); m_impl = string.impl(); } else { VERIFY((*it)->is_fly()); m_impl = *it; } } FlyString::FlyString(StringView string) { if (string.is_null()) return; auto it = fly_impls().find(string.hash(), [&](auto& candidate) { return string == candidate; }); if (it == fly_impls().end()) { auto new_string = string.to_deprecated_string(); fly_impls().set(new_string.impl()); new_string.impl()->set_fly({}, true); m_impl = new_string.impl(); } else { VERIFY((*it)->is_fly()); m_impl = *it; } } template Optional FlyString::to_int(TrimWhitespace trim_whitespace) const { return StringUtils::convert_to_int(view(), trim_whitespace); } template Optional FlyString::to_int(TrimWhitespace) const; template Optional FlyString::to_int(TrimWhitespace) const; template Optional FlyString::to_int(TrimWhitespace) const; template Optional FlyString::to_int(TrimWhitespace) const; template Optional FlyString::to_uint(TrimWhitespace trim_whitespace) const { return StringUtils::convert_to_uint(view(), trim_whitespace); } template Optional FlyString::to_uint(TrimWhitespace) const; template Optional FlyString::to_uint(TrimWhitespace) const; template Optional FlyString::to_uint(TrimWhitespace) const; template Optional FlyString::to_uint(TrimWhitespace) const; #ifndef KERNEL Optional FlyString::to_double(TrimWhitespace trim_whitespace) const { return StringUtils::convert_to_floating_point(view(), trim_whitespace); } Optional FlyString::to_float(TrimWhitespace trim_whitespace) const { return StringUtils::convert_to_floating_point(view(), trim_whitespace); } #endif bool FlyString::equals_ignoring_case(StringView other) const { return StringUtils::equals_ignoring_case(view(), other); } bool FlyString::starts_with(StringView str, CaseSensitivity case_sensitivity) const { return StringUtils::starts_with(view(), str, case_sensitivity); } bool FlyString::ends_with(StringView str, CaseSensitivity case_sensitivity) const { return StringUtils::ends_with(view(), str, case_sensitivity); } FlyString FlyString::to_lowercase() const { return DeprecatedString(*m_impl).to_lowercase(); } bool FlyString::operator==(DeprecatedString const& other) const { return m_impl == other.impl() || view() == other.view(); } bool FlyString::operator==(StringView string) const { return view() == string; } bool FlyString::operator==(char const* string) const { return view() == string; } }