addr_range_map.hh revision 8918
1/*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Ali Saidi
29 */
30
31#ifndef __BASE_RANGE_MAP_HH__
32#define __BASE_RANGE_MAP_HH__
33
34#include <map>
35#include <utility>
36
37#include "base/range.hh"
38
39/**
40 * The range_map uses an STL map to implement an interval tree. The
41 * type of both the key (range) and the value are template
42 * parameters. It can, for example, be used for address decoding,
43 * using a range of addresses to map to ports.
44 */
45template <class T,class V>
46class range_map
47{
48  private:
49    typedef std::map<Range<T>,V> RangeMap;
50    RangeMap tree;
51
52  public:
53    typedef typename RangeMap::iterator iterator;
54    typedef typename RangeMap::const_iterator const_iterator;
55
56    template <class U>
57    const_iterator
58    find(const Range<U> &r) const
59    {
60        const_iterator i;
61
62        i = tree.upper_bound(r);
63
64        if (i == tree.begin()) {
65            if (i->first.start <= r.end && i->first.end >= r.start)
66                return i;
67            else
68                // Nothing could match, so return end()
69                return tree.end();
70        }
71
72        --i;
73
74        if (i->first.start <= r.end && i->first.end >= r.start)
75            return i;
76
77        return tree.end();
78    }
79
80    template <class U>
81    iterator
82    find(const Range<U> &r)
83    {
84        iterator i;
85
86        i = tree.upper_bound(r);
87
88        if (i == tree.begin()) {
89            if (i->first.start <= r.end && i->first.end >= r.start)
90                return i;
91            else
92                // Nothing could match, so return end()
93                return tree.end();
94        }
95
96        --i;
97
98        if (i->first.start <= r.end && i->first.end >= r.start)
99            return i;
100
101        return tree.end();
102    }
103
104    template <class U>
105    const_iterator
106    find(const U &r) const
107    {
108        return find(RangeSize(r, 1));
109    }
110
111    template <class U>
112    iterator
113    find(const U &r)
114    {
115        return find(RangeSize(r, 1));
116    }
117
118    template <class U>
119    bool
120    intersect(const Range<U> &r)
121    {
122        iterator i;
123        i = find(r);
124        if (i != tree.end())
125            return true;
126        return false;
127    }
128
129    template <class U,class W>
130    iterator
131    insert(const Range<U> &r, const W d)
132    {
133        if (intersect(r))
134            return tree.end();
135
136        return tree.insert(std::make_pair(r, d)).first;
137    }
138
139    size_t
140    erase(T k)
141    {
142        return tree.erase(k);
143    }
144
145    void
146    erase(iterator p)
147    {
148        tree.erase(p);
149    }
150
151    void
152    erase(iterator p, iterator q)
153    {
154        tree.erase(p,q);
155    }
156
157    void
158    clear()
159    {
160        tree.erase(tree.begin(), tree.end());
161    }
162
163    const_iterator
164    begin() const
165    {
166        return tree.begin();
167    }
168
169    iterator
170    begin()
171    {
172        return tree.begin();
173    }
174
175    const_iterator
176    end() const
177    {
178        return tree.end();
179    }
180
181    iterator
182    end()
183    {
184        return tree.end();
185    }
186
187    size_t
188    size() const
189    {
190        return tree.size();
191    }
192
193    bool
194    empty() const
195    {
196        return tree.empty();
197    }
198};
199
200
201template <class T,class V>
202class range_multimap
203{
204  private:
205    typedef std::multimap<Range<T>,V> RangeMap;
206    RangeMap tree;
207
208  public:
209    typedef typename RangeMap::iterator iterator;
210
211    template <class U>
212    std::pair<iterator,iterator> find(const Range<U> &r)
213    {
214        iterator i;
215        iterator j;
216
217        i = tree.lower_bound(r);
218
219        if (i == tree.begin()) {
220          if (i->first.start <= r.end && i->first.end >= r.start)
221                return std::make_pair<iterator, iterator>(i,i);
222          else
223            // Nothing could match, so return end()
224            return std::make_pair<iterator, iterator>(tree.end(), tree.end());
225        }
226        i--;
227
228        if (i->first.start <= r.end && i->first.end >= r.start) {
229            // we have at least one match
230            j = i;
231
232            i--;
233            while (i->first.start <= r.end && i->first.end >=
234                    r.start) {
235                if (i == tree.begin())
236                    break;
237                i--;
238            }
239            if (i == tree.begin() && i->first.start <= r.end && i->first.end >=
240                                        r.start)
241                return std::make_pair<iterator, iterator>(i,j);
242            i++;
243            return std::make_pair<iterator, iterator>(i,j);
244
245        }
246
247        return std::make_pair<iterator, iterator>(tree.end(), tree.end());
248    }
249
250    template <class U>
251    bool
252    intersect(const Range<U> &r)
253    {
254        std::pair<iterator,iterator> p;
255        p = find(r);
256        if (p.first != tree.end())
257            return true;
258        return false;
259    }
260
261
262    template <class U,class W>
263    iterator
264    insert(const Range<U> &r, const W d)
265    {
266        std::pair<iterator,iterator> p;
267        p = find(r);
268        if ((p.first->first.start == r.start && p.first->first.end == r.end) ||
269                p.first == tree.end())
270            return tree.insert(std::make_pair<Range<T>,V>(r, d));
271        else
272            return tree.end();
273    }
274
275    size_t
276    erase(T k)
277    {
278        return tree.erase(k);
279    }
280
281    void
282    erase(iterator p)
283    {
284        tree.erase(p);
285    }
286
287    void
288    erase(iterator p, iterator q)
289    {
290        tree.erase(p,q);
291    }
292
293    void
294    clear()
295    {
296        tree.erase(tree.begin(), tree.end());
297    }
298
299    iterator
300    begin()
301    {
302        return tree.begin();
303    }
304
305    iterator
306    end()
307    {
308        return tree.end();
309    }
310
311    size_t
312    size()
313    {
314        return tree.size();
315    }
316
317    bool
318    empty()
319    {
320        return tree.empty();
321    }
322};
323
324#endif //__BASE_RANGE_MAP_HH__
325