DeprecatedFlyString.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <andreas@ladybird.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/ByteString.h>
  7. #include <AK/DeprecatedFlyString.h>
  8. #include <AK/HashTable.h>
  9. #include <AK/Optional.h>
  10. #include <AK/Singleton.h>
  11. #include <AK/StringUtils.h>
  12. #include <AK/StringView.h>
  13. namespace AK {
  14. struct DeprecatedFlyStringImplTraits : public Traits<StringImpl const*> {
  15. static unsigned hash(StringImpl const* s) { return s->hash(); }
  16. static bool equals(StringImpl const* a, StringImpl const* b)
  17. {
  18. return *a == *b;
  19. }
  20. };
  21. static Singleton<HashTable<StringImpl const*, DeprecatedFlyStringImplTraits>> s_table;
  22. static HashTable<StringImpl const*, DeprecatedFlyStringImplTraits>& fly_impls()
  23. {
  24. return *s_table;
  25. }
  26. void DeprecatedFlyString::did_destroy_impl(Badge<StringImpl>, StringImpl& impl)
  27. {
  28. fly_impls().remove(&impl);
  29. }
  30. DeprecatedFlyString::DeprecatedFlyString(ByteString const& string)
  31. : m_impl(string.impl())
  32. {
  33. if (string.impl()->is_fly())
  34. return;
  35. auto it = fly_impls().find(string.impl());
  36. if (it == fly_impls().end()) {
  37. fly_impls().set(string.impl());
  38. string.impl()->set_fly({}, true);
  39. m_impl = string.impl();
  40. } else {
  41. VERIFY((*it)->is_fly());
  42. m_impl = **it;
  43. }
  44. }
  45. DeprecatedFlyString::DeprecatedFlyString(StringView string)
  46. : m_impl(StringImpl::the_empty_stringimpl())
  47. {
  48. if (string.is_null())
  49. return;
  50. auto it = fly_impls().find(string.hash(), [&](auto& candidate) {
  51. return string == *candidate;
  52. });
  53. if (it == fly_impls().end()) {
  54. auto new_string = string.to_byte_string();
  55. fly_impls().set(new_string.impl());
  56. new_string.impl()->set_fly({}, true);
  57. m_impl = new_string.impl();
  58. } else {
  59. VERIFY((*it)->is_fly());
  60. m_impl = **it;
  61. }
  62. }
  63. bool DeprecatedFlyString::equals_ignoring_ascii_case(StringView other) const
  64. {
  65. return StringUtils::equals_ignoring_ascii_case(view(), other);
  66. }
  67. bool DeprecatedFlyString::starts_with(StringView str, CaseSensitivity case_sensitivity) const
  68. {
  69. return StringUtils::starts_with(view(), str, case_sensitivity);
  70. }
  71. bool DeprecatedFlyString::ends_with(StringView str, CaseSensitivity case_sensitivity) const
  72. {
  73. return StringUtils::ends_with(view(), str, case_sensitivity);
  74. }
  75. DeprecatedFlyString DeprecatedFlyString::to_lowercase() const
  76. {
  77. return ByteString(*m_impl).to_lowercase();
  78. }
  79. bool DeprecatedFlyString::operator==(ByteString const& other) const
  80. {
  81. return m_impl == other.impl() || view() == other.view();
  82. }
  83. bool DeprecatedFlyString::operator==(StringView string) const
  84. {
  85. return view() == string;
  86. }
  87. bool DeprecatedFlyString::operator==(char const* string) const
  88. {
  89. return view() == string;
  90. }
  91. }