1 /* A type-safe hash map that retains the insertion order of keys.
2 Copyright (C) 2019-2024 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
21 #ifndef GCC_ORDERED_HASH_MAP_H
22 #define GCC_ORDERED_HASH_MAP_H
25 - The keys must be PODs, since vec<> uses assignment to populate slots
26 without properly initializing them.
27 - doesn't have GTY support.
28 - supports removal, but retains order of original insertion.
29 (Removal might be better handled by using a doubly-linked list
30 of nodes, holding the values). */
32 template<typename KeyId
, typename Value
,
34 class ordered_hash_map
36 typedef typename
Traits::key_type Key
;
39 ordered_hash_map () {}
41 ordered_hash_map (const ordered_hash_map
&other
)
42 : m_map (other
.m_map
),
43 m_keys (other
.m_keys
.length ()),
44 m_key_index (other
.m_key_index
)
48 FOR_EACH_VEC_ELT (other
.m_keys
, i
, key
)
49 m_keys
.quick_push (key
);
52 /* If key K isn't already in the map add key K with value V to the map, and
53 return false. Otherwise set the value of the entry for key K to be V and
56 bool put (const Key
&k
, const Value
&v
)
58 bool existed
= m_map
.put (k
, v
);
62 int &slot
= m_key_index
.get_or_insert (k
, &key_present
);
65 slot
= m_keys
.length ();
72 /* If the passed in key is in the map return its value otherwise NULL. */
74 Value
*get (const Key
&k
)
79 /* Return a reference to the value for the passed in key, creating the entry
80 if it doesn't already exist. If existed is not NULL then it is set to
81 false if the key was not previously in the map, and true otherwise. */
83 Value
&get_or_insert (const Key
&k
, bool *existed
= NULL
)
86 Value
&ret
= m_map
.get_or_insert (k
, &_existed
);
91 int &slot
= m_key_index
.get_or_insert (k
, &key_present
);
94 slot
= m_keys
.length ();
105 /* Removing a key removes it from the map, but retains the insertion
108 void remove (const Key
&k
)
113 size_t elements () const { return m_map
.elements (); }
115 void empty () { m_map
.empty(); }
120 explicit iterator (const ordered_hash_map
&map
, unsigned idx
) :
121 m_ordered_hash_map (map
), m_idx (idx
) {}
123 iterator
&operator++ ()
125 /* Increment m_idx until we find a non-deleted element, or go beyond
130 if (valid_index_p ())
136 /* Can't use std::pair here, because GCC before 4.3 don't handle
137 std::pair where template parameters are references well.
139 struct reference_pair
{
143 reference_pair (const Key
&key
, Value
&value
)
144 : first (key
), second (value
) {}
146 template <typename K
, typename V
>
147 operator std::pair
<K
, V
> () const { return std::pair
<K
, V
> (first
, second
); }
150 reference_pair
operator* ()
152 const Key
&k
= m_ordered_hash_map
.m_keys
[m_idx
];
154 = const_cast<ordered_hash_map
&> (m_ordered_hash_map
).get (k
);
156 return reference_pair (k
, *slot
);
160 operator != (const iterator
&other
) const
162 return m_idx
!= other
.m_idx
;
165 /* Treat one-beyond-the-end as valid, for handling the "end" case. */
167 bool valid_index_p () const
169 if (m_idx
> m_ordered_hash_map
.m_keys
.length ())
171 if (m_idx
== m_ordered_hash_map
.m_keys
.length ())
173 const Key
&k
= m_ordered_hash_map
.m_keys
[m_idx
];
175 = const_cast<ordered_hash_map
&> (m_ordered_hash_map
).get (k
);
179 const ordered_hash_map
&m_ordered_hash_map
;
183 /* Standard iterator retrieval methods. */
185 iterator
begin () const
187 iterator i
= iterator (*this, 0);
188 while (!i
.valid_index_p () && i
!= end ())
192 iterator
end () const { return iterator (*this, m_keys
.length ()); }
195 /* The assignment operator is not yet implemented; prevent erroneous
196 usage of unsafe compiler-generated one. */
197 void operator= (const ordered_hash_map
&);
199 /* The underlying map. */
200 hash_map
<KeyId
, Value
, Traits
> m_map
;
202 /* The ordering of the keys. */
203 auto_vec
<Key
> m_keys
;
205 /* For each key that's ever been in the map, its index within m_keys. */
206 hash_map
<KeyId
, int> m_key_index
;
209 /* Two-argument form. */
211 template<typename Key
, typename Value
,
212 typename Traits
= simple_hashmap_traits
<default_hash_traits
<Key
>,
214 class ordered_hash_map
;
216 #endif /* GCC_ORDERED_HASH_MAP_H */