Map.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. public:
  18. static Map* create(GlobalObject&);
  19. explicit Map(Object& prototype);
  20. virtual ~Map() override = default;
  21. void map_clear();
  22. bool map_remove(Value const&);
  23. Optional<Value> map_get(Value const&) const;
  24. bool map_has(Value const&) const;
  25. void map_set(Value const&, Value);
  26. size_t map_size() const;
  27. struct EndIterator {
  28. };
  29. template<bool IsConst>
  30. struct IteratorImpl {
  31. bool is_end() const
  32. {
  33. return m_map.m_keys.begin_from(m_index).is_end()
  34. && m_map.m_keys.find_smallest_not_below_iterator(m_index).is_end();
  35. }
  36. IteratorImpl& operator++()
  37. {
  38. ++m_index;
  39. return *this;
  40. }
  41. decltype(auto) operator*()
  42. {
  43. ensure_next_element();
  44. return *m_map.m_entries.find(*m_map.m_keys.begin_from(m_index));
  45. }
  46. decltype(auto) operator*() const
  47. {
  48. ensure_next_element();
  49. return *m_map.m_entries.find(*m_map.m_keys.begin_from(m_index));
  50. }
  51. bool operator==(IteratorImpl const& other) const { return m_index == other.m_index && &m_map == &other.m_map; }
  52. bool operator==(EndIterator const&) const { return is_end(); }
  53. private:
  54. friend class Map;
  55. IteratorImpl(Map const& map) requires(IsConst)
  56. : m_map(map)
  57. {
  58. ensure_index();
  59. }
  60. IteratorImpl(Map& map) 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, Map const&, 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. virtual void visit_edges(Visitor& visitor) override;
  89. size_t m_next_insertion_id { 0 };
  90. RedBlackTree<size_t, Value> m_keys;
  91. HashMap<Value, Value, ValueTraits> m_entries;
  92. };
  93. }