reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
LinkedHashMap.hxx
Go to the documentation of this file.
1#if !defined(RESIP_LINKEDHASHMAP_HXX)
2#define RESIP_LINKEDHASHMAP_HXX
3
4#include <functional>
5#include <iterator>
6#include <list>
7#include <unordered_map>
8#include <utility>
9
10namespace resip
11{
12
24template <class Key, class T, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key> >
26{
27 public:
28 typedef Key key_type;
29 typedef T mapped_type;
30 typedef std::pair<const Key, T> value_type;
31
32 private:
33 typedef std::list<value_type> List;
34
35 public:
36 typedef typename List::size_type size_type;
37 typedef typename List::iterator iterator;
38 typedef typename List::const_iterator const_iterator;
39
41 LinkedHashMap(const LinkedHashMap& rhs) : mList(rhs.mList) { reindex(); }
42 LinkedHashMap(LinkedHashMap&& rhs) noexcept { swap(rhs); }
43 LinkedHashMap& operator=(LinkedHashMap rhs) noexcept { swap(rhs); return *this; }
44
45 iterator begin() { return mList.begin(); }
46 iterator end() { return mList.end(); }
47 const_iterator begin() const { return mList.begin(); }
48 const_iterator end() const { return mList.end(); }
49 const_iterator cbegin() const { return mList.begin(); }
50 const_iterator cend() const { return mList.end(); }
51
52 bool empty() const { return mList.empty(); }
53 size_type size() const { return mList.size(); }
54
55 void clear()
56 {
57 mIndex.clear();
58 mList.clear();
59 }
60
61 iterator find(const Key& key)
62 {
63 typename Index::iterator i = mIndex.find(key);
64 return i == mIndex.end() ? mList.end() : i->second;
65 }
66
67 const_iterator find(const Key& key) const
68 {
69 typename Index::const_iterator i = mIndex.find(key);
70 return i == mIndex.end() ? mList.end() : const_iterator(i->second);
71 }
72
73 size_type count(const Key& key) const { return mIndex.count(key); }
74
76 T& operator[](const Key& key)
77 {
78 iterator i = find(key);
79 if (i == mList.end())
80 {
81 i = append(value_type(key, T()));
82 }
83 return i->second;
84 }
85
87 std::pair<iterator, bool> insert(const value_type& value)
88 {
89 iterator i = find(value.first);
90 if (i != mList.end())
91 {
92 return std::make_pair(i, false);
93 }
94 return std::make_pair(append(value), true);
95 }
96
99 {
100 mIndex.erase(pos->first);
101 return mList.erase(pos);
102 }
103
104 size_type erase(const Key& key)
105 {
106 typename Index::iterator i = mIndex.find(key);
107 if (i == mIndex.end())
108 {
109 return 0;
110 }
111 mList.erase(i->second);
112 mIndex.erase(i);
113 return 1;
114 }
115
116 void swap(LinkedHashMap& rhs) noexcept
117 {
118 // std::list::swap keeps iterators valid, so each index still refers to its list
119 mList.swap(rhs.mList);
120 mIndex.swap(rhs.mIndex);
121 }
122
123 private:
124 typedef std::unordered_map<Key, iterator, Hash, KeyEqual> Index;
125
126 iterator append(const value_type& value)
127 {
128 mList.push_back(value);
129 iterator i = std::prev(mList.end());
130 try
131 {
132 mIndex.emplace(i->first, i);
133 }
134 catch (...)
135 {
136 mList.pop_back();
137 throw;
138 }
139 return i;
140 }
141
142 void reindex()
143 {
144 mIndex.clear();
145 mIndex.reserve(mList.size());
146 for (iterator i = mList.begin(); i != mList.end(); ++i)
147 {
148 mIndex.emplace(i->first, i);
149 }
150 }
151
152 List mList;
153 Index mIndex;
154};
155
156}
157
158#endif
159
160/* ====================================================================
161 *
162 * Copyright (c) 2026 SIP Spectrum, Inc. https://www.sipspectrum.com
163 *
164 * Redistribution and use in source and binary forms, with or without
165 * modification, are permitted provided that the following conditions
166 * are met:
167 *
168 * 1. Redistributions of source code must retain the above copyright
169 * notice, this list of conditions and the following disclaimer.
170 *
171 * 2. Redistributions in binary form must reproduce the above copyright
172 * notice, this list of conditions and the following disclaimer in
173 * the documentation and/or other materials provided with the
174 * distribution.
175 *
176 * 3. Neither the name of the author(s) nor the names of any contributors
177 * may be used to endorse or promote products derived from this software
178 * without specific prior written permission.
179 *
180 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS "AS IS" AND
181 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
182 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
183 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
184 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
185 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
186 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
187 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
188 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
189 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
190 * SUCH DAMAGE.
191 *
192 * ====================================================================
193 */
A hash map that iterates in insertion order, so a container filled while parsing (eg.
size_type count(const Key &key) const
const_iterator end() const
std::pair< const Key, T > value_type
size_type erase(const Key &key)
iterator find(const Key &key)
List::const_iterator const_iterator
T & operator[](const Key &key)
Appends a default-constructed value if key is not present.
const_iterator begin() const
void swap(LinkedHashMap &rhs) noexcept
LinkedHashMap & operator=(LinkedHashMap rhs) noexcept
size_type size() const
LinkedHashMap(LinkedHashMap &&rhs) noexcept
List::size_type size_type
LinkedHashMap(const LinkedHashMap &rhs)
const_iterator cend() const
iterator erase(const_iterator pos)
std::pair< iterator, bool > insert(const value_type &value)
Appends value if its key is not present; otherwise leaves the existing element.
const_iterator cbegin() const
const_iterator find(const Key &key) const
List::iterator iterator
dcm! – add UnusedChecking(_enum) below;