Map.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. public:
  17. static NonnullGCPtr<Map> create(Realm&);
  18. virtual ~Map() override = default;
  19. void map_clear();
  20. bool map_remove(Value const&);
  21. Optional<Value> map_get(Value const&) const;
  22. bool map_has(Value const&) const;
  23. void map_set(Value const&, Value);
  24. size_t map_size() const;
  25. struct EndIterator {
  26. };
  27. template<bool IsConst>
  28. struct IteratorImpl {
  29. bool is_end() const
  30. {
  31. return m_map->m_keys.begin_from(m_index).is_end()
  32. && m_map->m_keys.find_smallest_not_below_iterator(m_index).is_end();
  33. }
  34. IteratorImpl& operator++()
  35. {
  36. ++m_index;
  37. return *this;
  38. }
  39. decltype(auto) operator*()
  40. {
  41. ensure_next_element();
  42. return *m_map->m_entries.find(*m_map->m_keys.begin_from(m_index));
  43. }
  44. decltype(auto) operator*() const
  45. {
  46. ensure_next_element();
  47. return *m_map->m_entries.find(*m_map->m_keys.begin_from(m_index));
  48. }
  49. bool operator==(IteratorImpl const& other) const { return m_index == other.m_index && &m_map == &other.m_map; }
  50. bool operator==(EndIterator const&) const { return is_end(); }
  51. private:
  52. friend class Map;
  53. IteratorImpl(Map const& map)
  54. requires(IsConst)
  55. : m_map(map)
  56. {
  57. ensure_index();
  58. }
  59. IteratorImpl(Map& map)
  60. requires(!IsConst)
  61. : m_map(map)
  62. {
  63. ensure_index();
  64. }
  65. void ensure_index() const
  66. {
  67. if (m_map->m_keys.is_empty())
  68. m_index = m_map->m_next_insertion_id;
  69. else
  70. m_index = m_map->m_keys.begin().key();
  71. }
  72. void ensure_next_element() const
  73. {
  74. if (auto it = m_map->m_keys.find_smallest_not_below_iterator(m_index); it.is_end())
  75. m_index = m_map->m_next_insertion_id;
  76. else
  77. m_index = it.key();
  78. }
  79. Conditional<IsConst, NonnullGCPtr<Map const>, NonnullGCPtr<Map>> m_map;
  80. mutable size_t m_index { 0 };
  81. };
  82. using Iterator = IteratorImpl<false>;
  83. using ConstIterator = IteratorImpl<true>;
  84. ConstIterator begin() const { return { *this }; }
  85. Iterator begin() { return { *this }; }
  86. EndIterator end() const { return {}; }
  87. private:
  88. explicit Map(Object& prototype);
  89. virtual void visit_edges(Visitor& visitor) override;
  90. size_t m_next_insertion_id { 0 };
  91. RedBlackTree<size_t, Value> m_keys;
  92. HashMap<Value, Value, ValueTraits> m_entries;
  93. };
  94. }