My Project
rangemap.hh
Go to the documentation of this file.
1 /* ###
2  * IP: GHIDRA
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
18 
19 #ifndef __RANGEMAP__
20 #define __RANGEMAP__
21 
22 #include <set>
23 #include <list>
24 
64 template<typename _recordtype>
65 class rangemap {
66 public:
67  typedef typename _recordtype::linetype linetype;
68  typedef typename _recordtype::subsorttype subsorttype;
69  typedef typename _recordtype::inittype inittype;
70 private:
75  class AddrRange {
76  friend class rangemap<_recordtype>;
77  friend class PartIterator;
78  mutable linetype first;
79  linetype last;
80  mutable linetype a;
81  mutable linetype b;
82  mutable subsorttype subsort;
83  mutable typename std::list<_recordtype>::iterator value;
84  AddrRange(linetype l) : subsort(false) { last = l; }
85  AddrRange(linetype l,const subsorttype &s) : subsort(s) { last = l; }
86  public:
87  bool operator<(const AddrRange &op2) const {
88  if (last != op2.last) return (last < op2.last);
89  return (subsort < op2.subsort);
90  }
91  typename std::list<_recordtype>::iterator getValue(void) const { return value; }
92  };
93 public:
100  class PartIterator {
101  typename std::multiset<AddrRange>::const_iterator iter;
102  public:
103  PartIterator(void) {}
104  PartIterator(typename std::multiset<AddrRange>::const_iterator i) { iter=i; }
105  _recordtype &operator*(void) { return *(*iter).value; }
106  PartIterator &operator++(void) { ++iter; return *this; }
108  PartIterator orig(iter); ++iter; return orig; }
109  PartIterator &operator--(void) { --iter; return *this; }
111  PartIterator orig(iter); --iter; return orig; }
113  iter = op2.iter; return *this;
114  }
115  bool operator==(const PartIterator &op2) const {
116  return (iter==op2.iter);
117  }
118  bool operator!=(const PartIterator &op2) const {
119  return (iter!=op2.iter);
120  }
121  typename std::list<_recordtype>::iterator getValueIter(void) const {
122  return (*iter).getValue(); }
123  };
124 
125  typedef PartIterator const_iterator;
126 
127 private:
128  std::multiset<AddrRange> tree;
129  std::list<_recordtype> record;
130 
131  void zip(linetype i,typename std::multiset<AddrRange>::iterator iter);
132  void unzip(linetype i,typename std::multiset<AddrRange>::iterator iter);
133 public:
134  bool empty(void) const { return record.empty(); }
135  void clear(void) { tree.clear(); record.clear(); }
136  typename std::list<_recordtype>::const_iterator begin_list(void) const { return record.begin(); }
137  typename std::list<_recordtype>::const_iterator end_list(void) const { return record.end(); }
138  typename std::list<_recordtype>::iterator begin_list(void) { return record.begin(); }
139  typename std::list<_recordtype>::iterator end_list(void) { return record.end(); }
140 
141  const_iterator begin(void) const { return PartIterator(tree.begin()); }
142  const_iterator end(void) const { return PartIterator(tree.end()); }
143 
145  std::pair<const_iterator,const_iterator> find(linetype a) const;
146 
148  std::pair<const_iterator,const_iterator>
149  find(linetype a,const subsorttype &subsort1,const subsorttype &subsort2) const;
150 
152  const_iterator find_begin(linetype point) const;
153 
155  const_iterator find_end(linetype point) const;
156 
158  const_iterator find_overlap(linetype point,linetype end) const;
159 
161  typename std::list<_recordtype>::iterator insert(const inittype &data,linetype a,linetype b);
162 
164  void erase(typename std::list<_recordtype>::iterator v);
165 
167  void erase(const_iterator iter) { erase( iter.getValueIter() ); }
168 };
169 
175 template<typename _recordtype>
176 void rangemap<_recordtype>::zip(linetype i,typename std::multiset<AddrRange>::iterator iter)
177 
178 {
179  linetype f = (*iter).first;
180  while((*iter).last == i)
181  tree.erase(iter++);
182  i = i+1;
183  while((iter!=tree.end())&&((*iter).first==i)) {
184  (*iter).first = f;
185  ++iter;
186  }
187 }
188 
194 template<typename _recordtype>
195 void rangemap<_recordtype>::unzip(linetype i,typename std::multiset<AddrRange>::iterator iter)
196 
197 {
198  typename std::multiset<AddrRange>::iterator hint = iter;
199  if ((*iter).last == i) return; // Can't split size 1 (i.e. split already present)
200  linetype f;
201  linetype plus1 = i+1;
202  while((iter!=tree.end())&&((*iter).first<=i)) {
203  f = (*iter).first;
204  (*iter).first = plus1;
205  typename std::multiset<AddrRange>::iterator newiter;
206  newiter = tree.insert(hint,AddrRange(i,(*iter).subsort));
207  const AddrRange &newrange( *newiter );
208  newrange.first = f;
209  newrange.a = (*iter).a;
210  newrange.b = (*iter).b;
211  newrange.value = (*iter).value;
212  ++iter;
213  }
214 }
215 
220 template<typename _recordtype>
221 typename std::list<_recordtype>::iterator
223 
224 {
225  linetype f=a;
226  typename std::list<_recordtype>::iterator liter;
227  typename std::multiset<AddrRange>::iterator low = tree.lower_bound(AddrRange(f));
228 
229  if (low != tree.end()) {
230  if ((*low).first < f) // Check if left boundary refines existing partition
231  unzip(f-1,low); // If so do the refinement
232  }
233 
234  record.push_front( _recordtype() );
235  record.front().initialize( data, a, b );
236  liter = record.begin();
237 
238  AddrRange addrrange(b,(*liter).getSubsort());
239  addrrange.a = a;
240  addrrange.b = b;
241  addrrange.value = liter;
242  typename std::multiset<AddrRange>::iterator spot = tree.lower_bound(addrrange);
243  // Where does the new record go in full list, insert it
244  record.splice( (spot==tree.end()) ? record.end():(*spot).value,
245  record,liter);
246 
247  while((low != tree.end())&&((*low).first<=b)) {
248  if (f <= (*low).last) { // Do we overlap at all
249  if (f < (*low).first) {
250  // Assume the hint makes this insert an O(1) op
251  addrrange.first = f;
252  addrrange.last = (*low).first-1;
253  tree.insert(low,addrrange);
254  f = (*low).first;
255  }
256  if ((*low).last <= b) { // Insert as much of interval as we can
257  addrrange.first = f;
258  addrrange.last = (*low).last;
259  tree.insert(low,addrrange);
260  if ((*low).last==b) break; // Did we manage to insert it all
261  f = (*low).last + 1;
262  }
263  else if (b < (*low).last) { // We can insert everything left, but must refine
264  unzip(b,low);
265  break;
266  }
267  }
268  ++low;
269  }
270  if (f <= b) {
271  addrrange.first = f;
272  addrrange.last = b;
273  tree.insert(addrrange);
274  }
275 
276  return liter;
277 }
278 
280 template<typename _recordtype>
281 void rangemap<_recordtype>::erase(typename std::list<_recordtype>::iterator v)
282 
283 {
284  linetype a = (*v).getFirst();
285  linetype b = (*v).getLast();
286  bool leftsew = true;
287  bool rightsew = true;
288  bool rightoverlap = false;
289  bool leftoverlap = false;
290  typename std::multiset<AddrRange>::iterator low = tree.lower_bound(AddrRange(a));
291  typename std::multiset<AddrRange>::iterator uplow = low;
292 
293  linetype aminus1 = a-1;
294  while (uplow != tree.begin()) {
295  --uplow;
296  if ((*uplow).last != aminus1) break;
297  if ((*uplow).b == aminus1) {
298  leftsew = false; // Still a split between a-1 and a
299  break;
300  }
301  }
302  do {
303  if ((*low).value == v)
304  tree.erase(low++);
305  else {
306  if ((*low).a < a)
307  leftoverlap = true; // a splits somebody else
308  else if ((*low).a == a)
309  leftsew = false; // Somebody else splits at a (in addition to v)
310  if (b < (*low).b)
311  rightoverlap = true; // b splits somebody else
312  else if ((*low).b == b)
313  rightsew = false; // Somebody else splits at b (in addition to v)
314  low++;
315  }
316  } while ((low != tree.end())&&((*low).first<=b));
317  if (low != tree.end()) {
318  if ((*low).a-1 == b)
319  rightsew = false;
320  }
321  if (leftsew&&leftoverlap)
322  zip(a-1,tree.lower_bound(AddrRange(a-1)));
323  if (rightsew&&rightoverlap)
324  zip(b,tree.lower_bound(AddrRange(b)));
325  record.erase(v);
326 }
327 
330 template<typename _recordtype>
331 std::pair<typename rangemap<_recordtype>::const_iterator,typename rangemap<_recordtype>::const_iterator>
333 
334 {
335  AddrRange addrrange(point);
336  typename std::multiset<AddrRange>::const_iterator iter1,iter2;
337 
338  iter1 = tree.lower_bound(addrrange);
339  // Check for no intersection
340  if ((iter1==tree.end())||(point < (*iter1).first))
341  return std::pair<PartIterator,PartIterator>(PartIterator(iter1),PartIterator(iter1));
342 
343  AddrRange addrend((*iter1).last,subsorttype(true));
344  iter2 = tree.upper_bound(addrend);
345 
346  return std::pair<PartIterator,PartIterator>(PartIterator(iter1),PartIterator(iter2));
347 }
348 
353 template<typename _recordtype>
354 std::pair<typename rangemap<_recordtype>::const_iterator,typename rangemap<_recordtype>::const_iterator>
355 rangemap<_recordtype>::find(linetype point,const subsorttype &sub1,const subsorttype &sub2) const
356 
357 {
358  AddrRange addrrange(point,sub1);
359  typename std::multiset<AddrRange>::const_iterator iter1,iter2;
360 
361  iter1 = tree.lower_bound(addrrange);
362  if ((iter1==tree.end())||(point < (*iter1).first))
363  return std::pair<PartIterator,PartIterator>(PartIterator(iter1),PartIterator(iter1));
364 
365  AddrRange addrend((*iter1).last,sub2);
366  iter2 = tree.upper_bound(addrend);
367 
368  return std::pair<PartIterator,PartIterator>(PartIterator(iter1),PartIterator(iter2));
369 }
370 
373 template<typename _recordtype>
376 
377 {
378  AddrRange addrrange(point);
379  typename std::multiset<AddrRange>::const_iterator iter;
380 
381  iter = tree.lower_bound(addrrange);
382  return iter;
383 }
384 
387 template<typename _recordtype>
390 
391 {
392  AddrRange addrend(point,subsorttype(true));
393  typename std::multiset<AddrRange>::const_iterator iter;
394 
395  iter = tree.upper_bound(addrend);
396  if ((iter==tree.end())||(point < (*iter).first))
397  return iter;
398 
399  // If we reach here, (*iter).last is bigger than point (as per upper_bound) but
400  // point >= than (*iter).first, i.e. point is contained in the sub-range.
401  // So we have to do one more search for first sub-range after the containing sub-range.
402  AddrRange addrbeyond((*iter).last,subsorttype(true));
403  return tree.upper_bound(addrbeyond);
404 }
405 
409 template<typename _recordtype>
412 
413 {
414  AddrRange addrrange(point);
415  typename std::multiset<AddrRange>::const_iterator iter;
416 
417  // First range where right boundary is equal to or past point
418  iter = tree.lower_bound(addrrange);
419  if (iter==tree.end()) return iter;
420  if ((*iter).first<=end)
421  return iter;
422  return tree.end();
423 }
424 
425 #endif
PartIterator operator++(int i)
Post-increment the iterator.
Definition: rangemap.hh:107
const_iterator begin(void) const
Beginning of sub-ranges.
Definition: rangemap.hh:141
bool operator!=(const PartIterator &op2) const
Test inequality of iterators.
Definition: rangemap.hh:118
const_iterator find_overlap(linetype point, linetype end) const
Find first record overlapping given interval.
Definition: rangemap.hh:411
std::list< _recordtype >::iterator getValueIter(void) const
Get the recordtype iterator.
Definition: rangemap.hh:121
An iterator into the interval map container.
Definition: rangemap.hh:100
_recordtype::subsorttype subsorttype
The data-type used for subsorting.
Definition: rangemap.hh:68
PartIterator(typename std::multiset< AddrRange >::const_iterator i)
Construct given iterator.
Definition: rangemap.hh:104
const_iterator find_begin(linetype point) const
Find beginning of sub-ranges that contain the given boundary point.
Definition: rangemap.hh:375
PartIterator & operator--(void)
Pre-decrement the iterator.
Definition: rangemap.hh:109
const_iterator end(void) const
Ending of sub-ranges.
Definition: rangemap.hh:142
std::list< _recordtype >::const_iterator begin_list(void) const
Beginning of records.
Definition: rangemap.hh:136
PartIterator operator--(int i)
Post-decrement the iterator.
Definition: rangemap.hh:110
std::pair< const_iterator, const_iterator > find(linetype a) const
Find sub-ranges intersecting the given boundary point.
Definition: rangemap.hh:332
bool empty(void) const
Return true if the container is empty.
Definition: rangemap.hh:134
std::list< _recordtype >::iterator begin_list(void)
Beginning of records.
Definition: rangemap.hh:138
_recordtype::inittype inittype
The data-type containing initialization data for records.
Definition: rangemap.hh:69
bool operator==(const PartIterator &op2) const
Test equality of iterators.
Definition: rangemap.hh:115
An interval map container.
Definition: rangemap.hh:65
_recordtype & operator*(void)
Dereference to the recordtype object.
Definition: rangemap.hh:105
_recordtype::linetype linetype
Integer data-type defining the linear domain.
Definition: rangemap.hh:67
std::list< _recordtype >::const_iterator end_list(void) const
End of records.
Definition: rangemap.hh:137
void erase(const_iterator iter)
Erase a record given an iterator.
Definition: rangemap.hh:167
PartIterator(void)
Constructor.
Definition: rangemap.hh:103
void clear(void)
Clear all records from the container.
Definition: rangemap.hh:135
PartIterator const_iterator
The main sub-range iterator data-type.
Definition: rangemap.hh:125
const_iterator find_end(linetype point) const
Find ending of sub-ranges that contain the given boundary point.
Definition: rangemap.hh:389
PartIterator & operator++(void)
Pre-increment the iterator.
Definition: rangemap.hh:106
std::list< _recordtype >::iterator insert(const inittype &data, linetype a, linetype b)
Insert a new record into the container.
Definition: rangemap.hh:222
void erase(typename std::list< _recordtype >::iterator v)
Erase a given record from the container.
Definition: rangemap.hh:281
std::list< _recordtype >::iterator end_list(void)
End of records.
Definition: rangemap.hh:139
PartIterator & operator=(const PartIterator &op2)
Assign to the iterator.
Definition: rangemap.hh:112