1*4c3eb207Smrg /* A type-safe hash map that retains the insertion order of keys. 2*4c3eb207Smrg Copyright (C) 2019-2020 Free Software Foundation, Inc. 3*4c3eb207Smrg 4*4c3eb207Smrg This file is part of GCC. 5*4c3eb207Smrg 6*4c3eb207Smrg GCC is free software; you can redistribute it and/or modify it under 7*4c3eb207Smrg the terms of the GNU General Public License as published by the Free 8*4c3eb207Smrg Software Foundation; either version 3, or (at your option) any later 9*4c3eb207Smrg version. 10*4c3eb207Smrg 11*4c3eb207Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12*4c3eb207Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or 13*4c3eb207Smrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14*4c3eb207Smrg for more details. 15*4c3eb207Smrg 16*4c3eb207Smrg You should have received a copy of the GNU General Public License 17*4c3eb207Smrg along with GCC; see the file COPYING3. If not see 18*4c3eb207Smrg <http://www.gnu.org/licenses/>. */ 19*4c3eb207Smrg 20*4c3eb207Smrg 21*4c3eb207Smrg #ifndef GCC_ORDERED_HASH_MAP_H 22*4c3eb207Smrg #define GCC_ORDERED_HASH_MAP_H 23*4c3eb207Smrg 24*4c3eb207Smrg /* Notes: 25*4c3eb207Smrg - The keys must be PODs, since vec<> uses assignment to populate slots 26*4c3eb207Smrg without properly initializing them. 27*4c3eb207Smrg - doesn't have GTY support. 28*4c3eb207Smrg - supports removal, but retains order of original insertion. 29*4c3eb207Smrg (Removal might be better handled by using a doubly-linked list 30*4c3eb207Smrg of nodes, holding the values). */ 31*4c3eb207Smrg 32*4c3eb207Smrg template<typename KeyId, typename Value, 33*4c3eb207Smrg typename Traits> 34*4c3eb207Smrg class ordered_hash_map 35*4c3eb207Smrg { 36*4c3eb207Smrg typedef typename Traits::key_type Key; 37*4c3eb207Smrg 38*4c3eb207Smrg public: ordered_hash_map()39*4c3eb207Smrg ordered_hash_map () {} 40*4c3eb207Smrg ordered_hash_map(const ordered_hash_map & other)41*4c3eb207Smrg ordered_hash_map (const ordered_hash_map &other) 42*4c3eb207Smrg : m_map (other.m_map), 43*4c3eb207Smrg m_keys (other.m_keys.length ()), 44*4c3eb207Smrg m_key_index (other.m_key_index) 45*4c3eb207Smrg { 46*4c3eb207Smrg unsigned i; 47*4c3eb207Smrg Key key; 48*4c3eb207Smrg FOR_EACH_VEC_ELT (other.m_keys, i, key) 49*4c3eb207Smrg m_keys.quick_push (key); 50*4c3eb207Smrg } 51*4c3eb207Smrg 52*4c3eb207Smrg /* If key K isn't already in the map add key K with value V to the map, and 53*4c3eb207Smrg return false. Otherwise set the value of the entry for key K to be V and 54*4c3eb207Smrg return true. */ 55*4c3eb207Smrg put(const Key & k,const Value & v)56*4c3eb207Smrg bool put (const Key &k, const Value &v) 57*4c3eb207Smrg { 58*4c3eb207Smrg bool existed = m_map.put (k, v); 59*4c3eb207Smrg if (!existed) 60*4c3eb207Smrg { 61*4c3eb207Smrg bool key_present; 62*4c3eb207Smrg int &slot = m_key_index.get_or_insert (k, &key_present); 63*4c3eb207Smrg if (!key_present) 64*4c3eb207Smrg { 65*4c3eb207Smrg slot = m_keys.length (); 66*4c3eb207Smrg m_keys.safe_push (k); 67*4c3eb207Smrg } 68*4c3eb207Smrg } 69*4c3eb207Smrg return existed; 70*4c3eb207Smrg } 71*4c3eb207Smrg 72*4c3eb207Smrg /* If the passed in key is in the map return its value otherwise NULL. */ 73*4c3eb207Smrg get(const Key & k)74*4c3eb207Smrg Value *get (const Key &k) 75*4c3eb207Smrg { 76*4c3eb207Smrg return m_map.get (k); 77*4c3eb207Smrg } 78*4c3eb207Smrg 79*4c3eb207Smrg /* Removing a key removes it from the map, but retains the insertion 80*4c3eb207Smrg order. */ 81*4c3eb207Smrg remove(const Key & k)82*4c3eb207Smrg void remove (const Key &k) 83*4c3eb207Smrg { 84*4c3eb207Smrg m_map.remove (k); 85*4c3eb207Smrg } 86*4c3eb207Smrg elements()87*4c3eb207Smrg size_t elements () const { return m_map.elements (); } 88*4c3eb207Smrg 89*4c3eb207Smrg class iterator 90*4c3eb207Smrg { 91*4c3eb207Smrg public: iterator(const ordered_hash_map & map,unsigned idx)92*4c3eb207Smrg explicit iterator (const ordered_hash_map &map, unsigned idx) : 93*4c3eb207Smrg m_ordered_hash_map (map), m_idx (idx) {} 94*4c3eb207Smrg 95*4c3eb207Smrg iterator &operator++ () 96*4c3eb207Smrg { 97*4c3eb207Smrg /* Increment m_idx until we find a non-deleted element, or go beyond 98*4c3eb207Smrg the end. */ 99*4c3eb207Smrg while (1) 100*4c3eb207Smrg { 101*4c3eb207Smrg ++m_idx; 102*4c3eb207Smrg if (valid_index_p ()) 103*4c3eb207Smrg break; 104*4c3eb207Smrg } 105*4c3eb207Smrg return *this; 106*4c3eb207Smrg } 107*4c3eb207Smrg 108*4c3eb207Smrg /* Can't use std::pair here, because GCC before 4.3 don't handle 109*4c3eb207Smrg std::pair where template parameters are references well. 110*4c3eb207Smrg See PR86739. */ 111*4c3eb207Smrg struct reference_pair { 112*4c3eb207Smrg const Key &first; 113*4c3eb207Smrg Value &second; 114*4c3eb207Smrg reference_pairreference_pair115*4c3eb207Smrg reference_pair (const Key &key, Value &value) 116*4c3eb207Smrg : first (key), second (value) {} 117*4c3eb207Smrg 118*4c3eb207Smrg template <typename K, typename V> 119*4c3eb207Smrg operator std::pair<K, V> () const { return std::pair<K, V> (first, second); } 120*4c3eb207Smrg }; 121*4c3eb207Smrg 122*4c3eb207Smrg reference_pair operator* () 123*4c3eb207Smrg { 124*4c3eb207Smrg const Key &k = m_ordered_hash_map.m_keys[m_idx]; 125*4c3eb207Smrg Value *slot 126*4c3eb207Smrg = const_cast<ordered_hash_map &> (m_ordered_hash_map).get (k); 127*4c3eb207Smrg gcc_assert (slot); 128*4c3eb207Smrg return reference_pair (k, *slot); 129*4c3eb207Smrg } 130*4c3eb207Smrg 131*4c3eb207Smrg bool 132*4c3eb207Smrg operator != (const iterator &other) const 133*4c3eb207Smrg { 134*4c3eb207Smrg return m_idx != other.m_idx; 135*4c3eb207Smrg } 136*4c3eb207Smrg 137*4c3eb207Smrg /* Treat one-beyond-the-end as valid, for handling the "end" case. */ 138*4c3eb207Smrg valid_index_p()139*4c3eb207Smrg bool valid_index_p () const 140*4c3eb207Smrg { 141*4c3eb207Smrg if (m_idx > m_ordered_hash_map.m_keys.length ()) 142*4c3eb207Smrg return false; 143*4c3eb207Smrg if (m_idx == m_ordered_hash_map.m_keys.length ()) 144*4c3eb207Smrg return true; 145*4c3eb207Smrg const Key &k = m_ordered_hash_map.m_keys[m_idx]; 146*4c3eb207Smrg Value *slot 147*4c3eb207Smrg = const_cast<ordered_hash_map &> (m_ordered_hash_map).get (k); 148*4c3eb207Smrg return slot != NULL; 149*4c3eb207Smrg } 150*4c3eb207Smrg 151*4c3eb207Smrg const ordered_hash_map &m_ordered_hash_map; 152*4c3eb207Smrg unsigned m_idx; 153*4c3eb207Smrg }; 154*4c3eb207Smrg 155*4c3eb207Smrg /* Standard iterator retrieval methods. */ 156*4c3eb207Smrg begin()157*4c3eb207Smrg iterator begin () const 158*4c3eb207Smrg { 159*4c3eb207Smrg iterator i = iterator (*this, 0); 160*4c3eb207Smrg while (!i.valid_index_p () && i != end ()) 161*4c3eb207Smrg ++i; 162*4c3eb207Smrg return i; 163*4c3eb207Smrg } end()164*4c3eb207Smrg iterator end () const { return iterator (*this, m_keys.length ()); } 165*4c3eb207Smrg 166*4c3eb207Smrg private: 167*4c3eb207Smrg /* The assignment operator is not yet implemented; prevent erroneous 168*4c3eb207Smrg usage of unsafe compiler-generated one. */ 169*4c3eb207Smrg void operator= (const ordered_hash_map &); 170*4c3eb207Smrg 171*4c3eb207Smrg /* The underlying map. */ 172*4c3eb207Smrg hash_map<KeyId, Value, Traits> m_map; 173*4c3eb207Smrg 174*4c3eb207Smrg /* The ordering of the keys. */ 175*4c3eb207Smrg auto_vec<Key> m_keys; 176*4c3eb207Smrg 177*4c3eb207Smrg /* For each key that's ever been in the map, its index within m_keys. */ 178*4c3eb207Smrg hash_map<KeyId, int> m_key_index; 179*4c3eb207Smrg }; 180*4c3eb207Smrg 181*4c3eb207Smrg /* Two-argument form. */ 182*4c3eb207Smrg 183*4c3eb207Smrg template<typename Key, typename Value, 184*4c3eb207Smrg typename Traits = simple_hashmap_traits<default_hash_traits<Key>, 185*4c3eb207Smrg Value> > 186*4c3eb207Smrg class ordered_hash_map; 187*4c3eb207Smrg 188*4c3eb207Smrg #endif /* GCC_ORDERED_HASH_MAP_H */ 189