Map.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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/Concepts.h>
  8. #include <AK/HashMap.h>
  9. #include <AK/RedBlackTree.h>
  10. #include <LibJS/Runtime/GlobalObject.h>
  11. #include <LibJS/Runtime/Object.h>
  12. #include <LibJS/Runtime/Value.h>
  13. #include <LibJS/Runtime/ValueTraits.h>
  14. namespace JS {
  15. class Map : public Object {
  16. JS_OBJECT(Map, Object);
  17. // NOTE: This awkwardness is due to Set using a Map internally.
  18. friend class Set;
  19. public:
  20. static Map* create(Realm&);
  21. virtual ~Map() override = default;
  22. void map_clear();
  23. bool map_remove(Value const&);
  24. Optional<Value> map_get(Value const&) const;
  25. bool map_has(Value const&) const;
  26. void map_set(Value const&, Value);
  27. size_t map_size() const;
  28. struct EndIterator {
  29. };
  30. template<bool IsConst>
  31. struct IteratorImpl {
  32. bool is_end() const
  33. {
  34. return m_map.m_keys.begin_from(m_index).is_end()
  35. && m_map.m_keys.find_smallest_not_below_iterator(m_index).is_end();
  36. }
  37. IteratorImpl& operator++()
  38. {
  39. ++m_index;
  40. return *this;
  41. }
  42. decltype(auto) operator*()
  43. {
  44. ensure_next_element();
  45. return *m_map.m_entries.find(*m_map.m_keys.begin_from(m_index));
  46. }
  47. decltype(auto) operator*() const
  48. {
  49. ensure_next_element();
  50. return *m_map.m_entries.find(*m_map.m_keys.begin_from(m_index));
  51. }
  52. bool operator==(IteratorImpl const& other) const { return m_index == other.m_index && &m_map == &other.m_map; }
  53. bool operator==(EndIterator const&) const { return is_end(); }
  54. private:
  55. friend class Map;
  56. IteratorImpl(Map const& map) requires(IsConst)
  57. : m_map(map)
  58. {
  59. ensure_index();
  60. }
  61. IteratorImpl(Map& map) 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, Map const&, 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. }