QualifiedName.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /*
  2. * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/HashTable.h>
  7. #include <LibWeb/DOM/QualifiedName.h>
  8. namespace Web::DOM {
  9. struct ImplTraits : public Traits<QualifiedName::Impl*> {
  10. static unsigned hash(QualifiedName::Impl* impl)
  11. {
  12. return pair_int_hash(impl->local_name.hash(), pair_int_hash(impl->prefix.hash(), impl->namespace_.hash()));
  13. }
  14. static bool equals(QualifiedName::Impl* a, QualifiedName::Impl* b)
  15. {
  16. return a->local_name == b->local_name
  17. && a->prefix == b->prefix
  18. && a->namespace_ == b->namespace_;
  19. }
  20. };
  21. static HashTable<QualifiedName::Impl*, ImplTraits> impls;
  22. static NonnullRefPtr<QualifiedName::Impl> ensure_impl(DeprecatedFlyString const& local_name, DeprecatedFlyString const& prefix, DeprecatedFlyString const& namespace_)
  23. {
  24. auto hash = pair_int_hash(local_name.hash(), pair_int_hash(prefix.hash(), namespace_.hash()));
  25. auto it = impls.find(hash, [&](QualifiedName::Impl* entry) {
  26. return entry->local_name == local_name
  27. && entry->prefix == prefix
  28. && entry->namespace_ == namespace_;
  29. });
  30. if (it != impls.end())
  31. return *(*it);
  32. return adopt_ref(*new QualifiedName::Impl(local_name, prefix, namespace_));
  33. }
  34. QualifiedName::QualifiedName(DeprecatedFlyString const& local_name, DeprecatedFlyString const& prefix, DeprecatedFlyString const& namespace_)
  35. : m_impl(ensure_impl(local_name, prefix, namespace_))
  36. {
  37. }
  38. QualifiedName::Impl::Impl(DeprecatedFlyString const& a_local_name, DeprecatedFlyString const& a_prefix, DeprecatedFlyString const& a_namespace)
  39. : local_name(a_local_name)
  40. , prefix(a_prefix)
  41. , namespace_(a_namespace)
  42. {
  43. impls.set(this);
  44. make_internal_string();
  45. }
  46. QualifiedName::Impl::~Impl()
  47. {
  48. impls.remove(this);
  49. }
  50. // https://dom.spec.whatwg.org/#concept-attribute-qualified-name
  51. // https://dom.spec.whatwg.org/#concept-element-qualified-name
  52. void QualifiedName::Impl::make_internal_string()
  53. {
  54. // This is possible to do according to the spec: "User agents could have this as an internal slot as an optimization."
  55. if (prefix.is_null()) {
  56. as_string = local_name;
  57. return;
  58. }
  59. as_string = DeprecatedString::formatted("{}:{}", prefix, local_name);
  60. }
  61. void QualifiedName::set_prefix(DeprecatedFlyString const& value)
  62. {
  63. m_impl->prefix = value;
  64. }
  65. }