IndexedProperties.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. * Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/NonnullOwnPtr.h>
  8. #include <LibJS/Runtime/Shape.h>
  9. #include <LibJS/Runtime/Value.h>
  10. namespace JS {
  11. struct ValueAndAttributes {
  12. Value value;
  13. PropertyAttributes attributes { default_attributes };
  14. Optional<u32> property_offset {};
  15. };
  16. class IndexedProperties;
  17. class IndexedPropertyIterator;
  18. class GenericIndexedPropertyStorage;
  19. class IndexedPropertyStorage {
  20. public:
  21. virtual ~IndexedPropertyStorage() = default;
  22. enum class IsSimpleStorage {
  23. No,
  24. Yes,
  25. };
  26. virtual bool has_index(u32 index) const = 0;
  27. virtual Optional<ValueAndAttributes> get(u32 index) const = 0;
  28. virtual void put(u32 index, Value value, PropertyAttributes attributes = default_attributes) = 0;
  29. virtual void remove(u32 index) = 0;
  30. virtual ValueAndAttributes take_first() = 0;
  31. virtual ValueAndAttributes take_last() = 0;
  32. virtual size_t size() const = 0;
  33. virtual size_t array_like_size() const = 0;
  34. virtual bool set_array_like_size(size_t new_size) = 0;
  35. bool is_simple_storage() const { return m_is_simple_storage; }
  36. protected:
  37. explicit IndexedPropertyStorage(IsSimpleStorage is_simple_storage)
  38. : m_is_simple_storage(is_simple_storage == IsSimpleStorage::Yes) {};
  39. private:
  40. bool m_is_simple_storage { false };
  41. };
  42. class SimpleIndexedPropertyStorage final : public IndexedPropertyStorage {
  43. public:
  44. SimpleIndexedPropertyStorage()
  45. : IndexedPropertyStorage(IsSimpleStorage::Yes) {};
  46. explicit SimpleIndexedPropertyStorage(Vector<Value>&& initial_values);
  47. virtual bool has_index(u32 index) const override;
  48. virtual Optional<ValueAndAttributes> get(u32 index) const override;
  49. virtual void put(u32 index, Value value, PropertyAttributes attributes = default_attributes) override;
  50. virtual void remove(u32 index) override;
  51. virtual ValueAndAttributes take_first() override;
  52. virtual ValueAndAttributes take_last() override;
  53. virtual size_t size() const override { return m_packed_elements.size(); }
  54. virtual size_t array_like_size() const override { return m_array_size; }
  55. virtual bool set_array_like_size(size_t new_size) override;
  56. Vector<Value> const& elements() const { return m_packed_elements; }
  57. [[nodiscard]] bool inline_has_index(u32 index) const
  58. {
  59. return index < m_array_size && !m_packed_elements.data()[index].is_empty();
  60. }
  61. [[nodiscard]] Optional<ValueAndAttributes> inline_get(u32 index) const
  62. {
  63. if (!inline_has_index(index))
  64. return {};
  65. return ValueAndAttributes { m_packed_elements.data()[index], default_attributes };
  66. }
  67. private:
  68. friend GenericIndexedPropertyStorage;
  69. void grow_storage_if_needed();
  70. size_t m_array_size { 0 };
  71. Vector<Value> m_packed_elements;
  72. };
  73. class GenericIndexedPropertyStorage final : public IndexedPropertyStorage {
  74. public:
  75. explicit GenericIndexedPropertyStorage(SimpleIndexedPropertyStorage&&);
  76. explicit GenericIndexedPropertyStorage()
  77. : IndexedPropertyStorage(IsSimpleStorage::No) {};
  78. virtual bool has_index(u32 index) const override;
  79. virtual Optional<ValueAndAttributes> get(u32 index) const override;
  80. virtual void put(u32 index, Value value, PropertyAttributes attributes = default_attributes) override;
  81. virtual void remove(u32 index) override;
  82. virtual ValueAndAttributes take_first() override;
  83. virtual ValueAndAttributes take_last() override;
  84. virtual size_t size() const override { return m_sparse_elements.size(); }
  85. virtual size_t array_like_size() const override { return m_array_size; }
  86. virtual bool set_array_like_size(size_t new_size) override;
  87. HashMap<u32, ValueAndAttributes> const& sparse_elements() const { return m_sparse_elements; }
  88. private:
  89. size_t m_array_size { 0 };
  90. HashMap<u32, ValueAndAttributes> m_sparse_elements;
  91. };
  92. class IndexedPropertyIterator {
  93. public:
  94. IndexedPropertyIterator(IndexedProperties const&, u32 starting_index, bool skip_empty);
  95. IndexedPropertyIterator& operator++();
  96. IndexedPropertyIterator& operator*();
  97. bool operator!=(IndexedPropertyIterator const&) const;
  98. u32 index() const { return m_index; }
  99. private:
  100. void skip_empty_indices();
  101. IndexedProperties const& m_indexed_properties;
  102. Vector<u32> m_cached_indices;
  103. size_t m_next_cached_index { 0 };
  104. u32 m_index { 0 };
  105. bool m_skip_empty { false };
  106. };
  107. class IndexedProperties {
  108. public:
  109. IndexedProperties() = default;
  110. explicit IndexedProperties(Vector<Value> values)
  111. {
  112. if (!values.is_empty())
  113. m_storage = make<SimpleIndexedPropertyStorage>(move(values));
  114. }
  115. bool has_index(u32 index) const { return m_storage ? m_storage->has_index(index) : false; }
  116. Optional<ValueAndAttributes> get(u32 index) const;
  117. void put(u32 index, Value value, PropertyAttributes attributes = default_attributes);
  118. void remove(u32 index);
  119. void append(Value value, PropertyAttributes attributes = default_attributes) { put(array_like_size(), value, attributes); }
  120. IndexedPropertyIterator begin(bool skip_empty = true) const { return IndexedPropertyIterator(*this, 0, skip_empty); }
  121. IndexedPropertyIterator end() const { return IndexedPropertyIterator(*this, array_like_size(), false); }
  122. bool is_empty() const { return array_like_size() == 0; }
  123. size_t array_like_size() const { return m_storage ? m_storage->array_like_size() : 0; }
  124. bool set_array_like_size(size_t);
  125. IndexedPropertyStorage* storage() { return m_storage; }
  126. IndexedPropertyStorage const* storage() const { return m_storage; }
  127. size_t real_size() const;
  128. Vector<u32> indices() const;
  129. template<typename Callback>
  130. void for_each_value(Callback callback)
  131. {
  132. if (!m_storage)
  133. return;
  134. if (m_storage->is_simple_storage()) {
  135. for (auto& value : static_cast<SimpleIndexedPropertyStorage&>(*m_storage).elements())
  136. callback(value);
  137. } else {
  138. for (auto& element : static_cast<GenericIndexedPropertyStorage const&>(*m_storage).sparse_elements())
  139. callback(element.value.value);
  140. }
  141. }
  142. private:
  143. void switch_to_generic_storage();
  144. void ensure_storage();
  145. OwnPtr<IndexedPropertyStorage> m_storage;
  146. };
  147. }