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(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) requires(IsConst)
  55. : m_map(map)
  56. {
  57. ensure_index();
  58. }
  59. IteratorImpl(Map& map) requires(!IsConst)
  60. : m_map(map)
  61. {
  62. ensure_index();
  63. }
  64. void ensure_index() const
  65. {
  66. if (m_map.m_keys.is_empty())
  67. m_index = m_map.m_next_insertion_id;
  68. else
  69. m_index = m_map.m_keys.begin().key();
  70. }
  71. void ensure_next_element() const
  72. {
  73. if (auto it = m_map.m_keys.find_smallest_not_below_iterator(m_index); it.is_end())
  74. m_index = m_map.m_next_insertion_id;
  75. else
  76. m_index = it.key();
  77. }
  78. Conditional<IsConst, Map const&, Map&> m_map;
  79. mutable size_t m_index { 0 };
  80. };
  81. using Iterator = IteratorImpl<false>;
  82. using ConstIterator = IteratorImpl<true>;
  83. ConstIterator begin() const { return { *this }; }
  84. Iterator begin() { return { *this }; }
  85. EndIterator end() const { return {}; }
  86. private:
  87. explicit Map(Object& prototype);
  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. }