Predator  [unstable] git snapshot
intarena.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011 Kamil Dudka <kdudka@redhat.com>
3  *
4  * This file is part of predator.
5  *
6  * predator is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * any later version.
10  *
11  * predator is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with predator. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef H_GUARD_INTARENA_H
21 #define H_GUARD_INTARENA_H
22 
23 #include "config.h"
24 
25 #include <map>
26 #include <set>
27 #include <vector>
28 
29 #include <boost/foreach.hpp>
30 
31 #define IA_AGGRESSIVE_OPTIMIZATION 0
32 
33 /// ad-hoc implementation; wastes memory, performance, and human resources
34 template <typename TInt, typename TFld>
36  public:
37  typedef std::set<TFld> TSet;
38 
39  // for compatibility with STL
40  typedef std::pair<TInt, TInt> key_type;
41  typedef std::pair<key_type, TFld> value_type;
42 
43  typedef std::vector<key_type> TKeySet;
44 
45  private:
46  typedef std::set<TFld> TLeaf;
47  typedef std::map</* beg */ TInt, TLeaf> TLine;
48  typedef std::map</* end */ TInt, TLine> TCont;
50 
51  public:
52  void add(const key_type &, TFld);
53  void sub(const key_type &, TFld);
54  void intersects(TSet &dst, const key_type &key) const;
55  void exactMatch(TSet &dst, const key_type &key) const;
56 
57  /// return the set of all keys that map to this object
58  void reverseLookup(TKeySet &dst, TFld) const;
59 
60  void clear() {
61  cont_.clear();
62  }
63 
65  this->add(item.first, item.second);
66  return *this;
67  }
68 
70  this->sub(item.first, item.second);
71  return *this;
72  }
73 };
74 
75 template <typename TInt, typename TFld>
76 void IntervalArena<TInt, TFld>::add(const key_type &key, const TFld fld)
77 {
78  const TInt beg = key.first;
79  const TInt end = key.second;
80  CL_BREAK_IF(end <= beg);
81 
82  cont_[end][beg].insert(fld);
83 }
84 
85 template <typename TInt, typename TFld>
86 void IntervalArena<TInt, TFld>::sub(const key_type &key, const TFld fld)
87 {
88  const TInt winBeg = key.first;
89  const TInt winEnd = key.second;
90  CL_BREAK_IF(winEnd <= winBeg);
91 
92  std::vector<value_type> recoverList;
93 
94  const typename TCont::iterator itEnd = cont_.end();
95  typename TCont::iterator it =
96  cont_.lower_bound(winBeg + /* right-open interval given as key */ 1);
97 
98  while (itEnd != it) {
99  TLine &line = it->second;
100 #if !IA_AGGRESSIVE_OPTIMIZATION
101  if (line.empty()) {
102  // skip orphans
103  ++it;
104  continue;
105  }
106 #endif
107  typename TLine::iterator lineIt = line.begin();
108  TInt beg = lineIt->first;
109  if (winEnd <= beg) {
110  // we are beyond the window already
111  ++it;
112  continue;
113  }
114 
115  const TInt end = it->first;
116  bool anyHit = false;
117 
118  const typename TLine::iterator lineItEnd = line.end();
119  do {
120  // make sure the basic window axioms hold
121  CL_BREAK_IF(winEnd <= beg);
122  CL_BREAK_IF(end <= winBeg);
123 
124  // remove the object from the current leaf (if found)
125  TLeaf &os = lineIt->second;
126  if (os.erase(fld)) {
127  anyHit = true;
128 
129  if (beg < winBeg) {
130  // schedule "the part above" for re-insertion
131  const key_type key(beg, winBeg);
132  const value_type item(key, fld);
133  recoverList.push_back(item);
134  }
135  }
136 
137 #if IA_AGGRESSIVE_OPTIMIZATION
138  if (os.empty())
139  // FIXME: Can we remove items from std::map during traversal??
140  line.erase(lineIt++);
141  else
142 #endif
143  ++lineIt;
144 
145  if (lineItEnd == lineIt)
146  // end of line
147  break;
148 
149  beg = lineIt->first;
150  }
151  while (beg < winEnd);
152 
153  if (anyHit) {
154  if (winEnd < end) {
155  // schedule "the part beyond" for re-insertion
156  const key_type key(winEnd, end);
157  const value_type item(key, fld);
158  recoverList.push_back(item);
159  }
160 
161 #if IA_AGGRESSIVE_OPTIMIZATION
162  if (line.empty()) {
163  // FIXME: Can we remove items from std::map during traversal??
164  cont_.erase(it++);
165  continue;
166  }
167 #endif
168  }
169 
170  ++it;
171  }
172 
173  // go through the recoverList and re-insert the missing parts
174  BOOST_FOREACH(const value_type &rItem, recoverList) {
175  const key_type &key = rItem.first;
176  const TFld fld = rItem.second;
177  const TInt beg = key.first;
178  const TInt end = key.second;
179 
180  cont_[end][beg].insert(fld);
181  }
182 }
183 
184 template <typename TInt, typename TFld>
186 {
187  const TInt winBeg = key.first;
188  const TInt winEnd = key.second;
189  CL_BREAK_IF(winEnd <= winBeg);
190 
191  typename TCont::const_iterator it =
192  cont_.lower_bound(winBeg + /* right-open interval given as key */ 1);
193 
194  for (; cont_.end() != it; ++it) {
195  const TLine &line = it->second;
196 #if !IA_AGGRESSIVE_OPTIMIZATION
197  if (line.empty())
198  // skip orphans
199  continue;
200 #endif
201  typename TLine::const_iterator lineIt = line.begin();
202  TInt beg = lineIt->first;
203  if (winEnd <= beg)
204  // we are beyond the window already
205  continue;
206 
207  const typename TLine::const_iterator lineItEnd = line.end();
208  do {
209  // make sure the basic window axioms hold
210  CL_BREAK_IF(winEnd <= beg);
211  CL_BREAK_IF(/* end */ it->first <= winBeg);
212 
213  const TLeaf &os = lineIt->second;
214  std::copy(os.begin(), os.end(), std::inserter(dst, dst.begin()));
215 
216  // increment for next wheel
217  if (lineItEnd == ++lineIt)
218  // end of line
219  break;
220 
221  beg = lineIt->first;
222  }
223  while (beg < winEnd);
224  }
225 }
226 
227 // FIXME: brute-force method
228 // FIXME: no assumptions can be made about the output format
229 template <typename TInt, typename TFld>
231  const
232 {
233  key_type key;
234 
235  BOOST_FOREACH(typename TCont::const_reference item, cont_) {
236  key/* end */.second = item/* end */.first;
237  const TLine &line = item.second;
238 
239  BOOST_FOREACH(typename TLine::const_reference lineItem, line) {
240  const TLeaf &leaf = lineItem.second;
241  if (!hasKey(leaf, fld))
242  continue;
243 
244  key/* beg */.first = lineItem/* beg */.first;
245  dst.push_back(key);
246  }
247  }
248 }
249 
250 template <typename TInt, typename TFld>
252 {
253  typedef typename TCont::const_iterator TEndIt;
254  const TEndIt itEnd = cont_.find(/* end */ key.second);
255  if (cont_.end() == itEnd)
256  // upper bound not found
257  return;
258 
259  const TLine &line = itEnd->second;
260  const typename TLine::const_iterator itBeg = line.find(/* beg */ key.first);
261  if (line.end() == itBeg)
262  // lower bound not found
263  return;
264 
265  const TLeaf &leaf = itBeg->second;
266  std::copy(leaf.begin(), leaf.end(), std::inserter(dst, dst.begin()));
267 }
268 
269 #endif /* H_GUARD_INTARENA_H */