Map.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/HashMap.h>
  8. #include <AK/RedBlackTree.h>
  9. #include <LibJS/Runtime/GlobalObject.h>
  10. #include <LibJS/Runtime/Object.h>
  11. #include <LibJS/Runtime/Value.h>
  12. #include <LibJS/Runtime/ValueTraits.h>
  13. namespace JS {
  14. class Map : public Object {
  15. JS_OBJECT(Map, Object);
  16. JS_DECLARE_ALLOCATOR(Map);
  17. public:
  18. static NonnullGCPtr<Map> create(Realm&);
  19. virtual ~Map() override = default;
  20. void map_clear();
  21. bool map_remove(Value const&);
  22. Optional<Value> map_get(Value const&) const;
  23. bool map_has(Value const&) const;
  24. void map_set(Value const&, Value);
  25. size_t map_size() const;
  26. struct EndIterator {
  27. };
  28. template<bool IsConst>
  29. struct IteratorImpl {
  30. bool is_end() const
  31. {
  32. return m_map->m_keys.begin_from(m_index).is_end()
  33. && m_map->m_keys.find_smallest_not_below_iterator(m_index).is_end();
  34. }
  35. IteratorImpl& operator++()
  36. {
  37. ++m_index;
  38. return *this;
  39. }
  40. decltype(auto) operator*()
  41. {
  42. ensure_next_element();
  43. return *m_map->m_entries.find(*m_map->m_keys.begin_from(m_index));
  44. }
  45. decltype(auto) operator*() const
  46. {
  47. ensure_next_element();
  48. return *m_map->m_entries.find(*m_map->m_keys.begin_from(m_index));
  49. }
  50. bool operator==(IteratorImpl const& other) const { return m_index == other.m_index && &m_map == &other.m_map; }
  51. bool operator==(EndIterator const&) const { return is_end(); }
  52. private:
  53. friend class Map;
  54. IteratorImpl(Map const& map)
  55. requires(IsConst)
  56. : m_map(map)
  57. {
  58. ensure_index();
  59. }
  60. IteratorImpl(Map& map)
  61. requires(!IsConst)
  62. : m_map(map)
  63. {
  64. ensure_index();
  65. }
  66. void ensure_index() const
  67. {
  68. if (m_map->m_keys.is_empty())
  69. m_index = m_map->m_next_insertion_id;
  70. else
  71. m_index = m_map->m_keys.begin().key();
  72. }
  73. void ensure_next_element() const
  74. {
  75. if (auto it = m_map->m_keys.find_smallest_not_below_iterator(m_index); it.is_end())
  76. m_index = m_map->m_next_insertion_id;
  77. else
  78. m_index = it.key();
  79. }
  80. Conditional<IsConst, NonnullGCPtr<Map const>, NonnullGCPtr<Map>> m_map;
  81. mutable size_t m_index { 0 };
  82. };
  83. using Iterator = IteratorImpl<false>;
  84. using ConstIterator = IteratorImpl<true>;
  85. ConstIterator begin() const { return { *this }; }
  86. Iterator begin() { return { *this }; }
  87. EndIterator end() const { return {}; }
  88. private:
  89. explicit Map(Object& prototype);
  90. virtual void visit_edges(Visitor& visitor) override;
  91. size_t m_next_insertion_id { 0 };
  92. RedBlackTree<size_t, Value> m_keys;
  93. HashMap<Value, Value, ValueTraits> m_entries;
  94. };
  95. }