Ghidra Decompiler Analysis Engine
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 
63 template<typename _recordtype>
64 class rangemap {
65 public:
66  typedef typename _recordtype::linetype linetype;
67  typedef typename _recordtype::subsorttype subsorttype;
68  typedef typename _recordtype::inittype inittype;
69 private:
74  class AddrRange {
75  friend class rangemap<_recordtype>;
76  friend class PartIterator;
77  mutable linetype first;
78  linetype last;
79  mutable linetype a;
80  mutable linetype b;
81  mutable subsorttype subsort;
82  mutable typename std::list<_recordtype>::iterator value;
83  AddrRange(linetype l) : subsort(false) { last = l; }
84  AddrRange(linetype l,const subsorttype &s) : subsort(s) { last = l; }
85  public:
86  bool operator<(const AddrRange &op2) const {
87  if (last != op2.last) return (last < op2.last);
88  return (subsort < op2.subsort);
89  }
90  typename std::list<_recordtype>::iterator getValue(void) const { return value; }
91  };
92 public:
99  class PartIterator {
100  typename std::multiset<AddrRange>::const_iterator iter;
101  public:
102  PartIterator(void) {}
103  PartIterator(typename std::multiset<AddrRange>::const_iterator i) { iter=i; }
104  _recordtype &operator*(void) { return *(*iter).value; }
105  PartIterator &operator++(void) { ++iter; return *this; }
106  PartIterator operator++(int i) {
107  PartIterator orig(iter); ++iter; return orig; }
108  PartIterator &operator--(void) { --iter; return *this; }
109  PartIterator operator--(int i) {
110  PartIterator orig(iter); --iter; return orig; }
111  PartIterator &operator=(const PartIterator &op2) {
112  iter = op2.iter; return *this;
113  }
114  bool operator==(const PartIterator &op2) const {
115  return (iter==op2.iter);
116  }
117  bool operator!=(const PartIterator &op2) const {
118  return (iter!=op2.iter);
119  }
120  typename std::list<_recordtype>::iterator getValueIter(void) const {
121  return (*iter).getValue(); }
122  };
123 
124  typedef PartIterator const_iterator;
125 
126 private:
127  std::multiset<AddrRange> tree;
128  std::list<_recordtype> record;
129 
130  void zip(linetype i,typename std::multiset<AddrRange>::iterator iter);
131  void unzip(linetype i,typename std::multiset<AddrRange>::iterator iter);
132 public:
133  bool empty(void) const { return record.empty(); }
134  void clear(void) { tree.clear(); record.clear(); }
135  typename std::list<_recordtype>::const_iterator begin_list(void) const { return record.begin(); }
136  typename std::list<_recordtype>::const_iterator end_list(void) const { return record.end(); }
137  typename std::list<_recordtype>::iterator begin_list(void) { return record.begin(); }
138  typename std::list<_recordtype>::iterator end_list(void) { return record.end(); }
139 
140  const_iterator begin(void) const { return PartIterator(tree.begin()); }
141  const_iterator end(void) const { return PartIterator(tree.end()); }
142 
144  std::pair<const_iterator,const_iterator> find(linetype a) const;
145 
147  std::pair<const_iterator,const_iterator>
148  find(linetype a,const subsorttype &subsort1,const subsorttype &subsort2) const;
149 
151  const_iterator find_begin(linetype point) const;
152 
154  const_iterator find_end(linetype point) const;
155 
157  const_iterator find_overlap(linetype point,linetype end) const;
158 
160  typename std::list<_recordtype>::iterator insert(const inittype &data,linetype a,linetype b);
161 
163  void erase(typename std::list<_recordtype>::iterator v);
164 
166  void erase(const_iterator iter) { erase( iter.getValueIter() ); }
167 };
168 
174 template<typename _recordtype>
175 void rangemap<_recordtype>::zip(linetype i,typename std::multiset<AddrRange>::iterator iter)
176 
177 {
178  linetype f = (*iter).first;
179  while((*iter).last == i)
180  tree.erase(iter++);
181  i = i+1;
182  while((iter!=tree.end())&&((*iter).first==i)) {
183  (*iter).first = f;
184  ++iter;
185  }
186 }
187 
193 template<typename _recordtype>
194 void rangemap<_recordtype>::unzip(linetype i,typename std::multiset<AddrRange>::iterator iter)
195 
196 {
197  typename std::multiset<AddrRange>::iterator hint = iter;
198  if ((*iter).last == i) return; // Can't split size 1 (i.e. split already present)
199  linetype f;
200  linetype plus1 = i+1;
201  while((iter!=tree.end())&&((*iter).first<=i)) {
202  f = (*iter).first;
203  (*iter).first = plus1;
204  typename std::multiset<AddrRange>::iterator newiter;
205  newiter = tree.insert(hint,AddrRange(i,(*iter).subsort));
206  const AddrRange &newrange( *newiter );
207  newrange.first = f;
208  newrange.a = (*iter).a;
209  newrange.b = (*iter).b;
210  newrange.value = (*iter).value;
211  ++iter;
212  }
213 }
214 
219 template<typename _recordtype>
220 typename std::list<_recordtype>::iterator
222 
223 {
224  linetype f=a;
225  typename std::list<_recordtype>::iterator liter;
226  typename std::multiset<AddrRange>::iterator low = tree.lower_bound(AddrRange(f));
227 
228  if (low != tree.end()) {
229  if ((*low).first < f) // Check if left boundary refines existing partition
230  unzip(f-1,low); // If so do the refinement
231  }
232 
233  record.emplace_front( data, a, b );
234  liter = record.begin();
235 
236  AddrRange addrrange(b,(*liter).getSubsort());
237  addrrange.a = a;
238  addrrange.b = b;
239  addrrange.value = liter;
240  typename std::multiset<AddrRange>::iterator spot = tree.lower_bound(addrrange);
241  // Where does the new record go in full list, insert it
242  record.splice( (spot==tree.end()) ? record.end():(*spot).value,
243  record,liter);
244 
245  while((low != tree.end())&&((*low).first<=b)) {
246  if (f <= (*low).last) { // Do we overlap at all
247  if (f < (*low).first) {
248  // Assume the hint makes this insert an O(1) op
249  addrrange.first = f;
250  addrrange.last = (*low).first-1;
251  tree.insert(low,addrrange);
252  f = (*low).first;
253  }
254  if ((*low).last <= b) { // Insert as much of interval as we can
255  addrrange.first = f;
256  addrrange.last = (*low).last;
257  tree.insert(low,addrrange);
258  if ((*low).last==b) break; // Did we manage to insert it all
259  f = (*low).last + 1;
260  }
261  else if (b < (*low).last) { // We can insert everything left, but must refine
262  unzip(b,low);
263  break;
264  }
265  }
266  ++low;
267  }
268  if (f <= b) {
269  addrrange.first = f;
270  addrrange.last = b;
271  tree.insert(addrrange);
272  }
273 
274  return liter;
275 }
276 
278 template<typename _recordtype>
279 void rangemap<_recordtype>::erase(typename std::list<_recordtype>::iterator v)
280 
281 {
282  linetype a = (*v).getFirst();
283  linetype b = (*v).getLast();
284  bool leftsew = true;
285  bool rightsew = true;
286  bool rightoverlap = false;
287  bool leftoverlap = false;
288  typename std::multiset<AddrRange>::iterator low = tree.lower_bound(AddrRange(a));
289  typename std::multiset<AddrRange>::iterator uplow = low;
290 
291  linetype aminus1 = a-1;
292  while (uplow != tree.begin()) {
293  --uplow;
294  if ((*uplow).last != aminus1) break;
295  if ((*uplow).b == aminus1) {
296  leftsew = false; // Still a split between a-1 and a
297  break;
298  }
299  }
300  do {
301  if ((*low).value == v)
302  tree.erase(low++);
303  else {
304  if ((*low).a < a)
305  leftoverlap = true; // a splits somebody else
306  else if ((*low).a == a)
307  leftsew = false; // Somebody else splits at a (in addition to v)
308  if (b < (*low).b)
309  rightoverlap = true; // b splits somebody else
310  else if ((*low).b == b)
311  rightsew = false; // Somebody else splits at b (in addition to v)
312  low++;
313  }
314  } while ((low != tree.end())&&((*low).first<=b));
315  if (low != tree.end()) {
316  if ((*low).a-1 == b)
317  rightsew = false;
318  }
319  if (leftsew&&leftoverlap)
320  zip(a-1,tree.lower_bound(AddrRange(a-1)));
321  if (rightsew&&rightoverlap)
322  zip(b,tree.lower_bound(AddrRange(b)));
323  record.erase(v);
324 }
325 
328 template<typename _recordtype>
329 std::pair<typename rangemap<_recordtype>::const_iterator,typename rangemap<_recordtype>::const_iterator>
331 
332 {
333  AddrRange addrrange(point);
334  typename std::multiset<AddrRange>::const_iterator iter1,iter2;
335 
336  iter1 = tree.lower_bound(addrrange);
337  // Check for no intersection
338  if ((iter1==tree.end())||(point < (*iter1).first))
339  return std::pair<PartIterator,PartIterator>(PartIterator(iter1),PartIterator(iter1));
340 
341  AddrRange addrend((*iter1).last,subsorttype(true));
342  iter2 = tree.upper_bound(addrend);
343 
344  return std::pair<PartIterator,PartIterator>(PartIterator(iter1),PartIterator(iter2));
345 }
346 
351 template<typename _recordtype>
352 std::pair<typename rangemap<_recordtype>::const_iterator,typename rangemap<_recordtype>::const_iterator>
353 rangemap<_recordtype>::find(linetype point,const subsorttype &sub1,const subsorttype &sub2) const
354 
355 {
356  AddrRange addrrange(point,sub1);
357  typename std::multiset<AddrRange>::const_iterator iter1,iter2;
358 
359  iter1 = tree.lower_bound(addrrange);
360  if ((iter1==tree.end())||(point < (*iter1).first))
361  return std::pair<PartIterator,PartIterator>(PartIterator(iter1),PartIterator(iter1));
362 
363  AddrRange addrend((*iter1).last,sub2);
364  iter2 = tree.upper_bound(addrend);
365 
366  return std::pair<PartIterator,PartIterator>(PartIterator(iter1),PartIterator(iter2));
367 }
368 
371 template<typename _recordtype>
374 
375 {
376  AddrRange addrrange(point);
377  typename std::multiset<AddrRange>::const_iterator iter;
378 
379  iter = tree.lower_bound(addrrange);
380  return iter;
381 }
382 
385 template<typename _recordtype>
388 
389 {
390  AddrRange addrend(point,subsorttype(true));
391  typename std::multiset<AddrRange>::const_iterator iter;
392 
393  iter = tree.upper_bound(addrend);
394  if ((iter==tree.end())||(point < (*iter).first))
395  return iter;
396 
397  // If we reach here, (*iter).last is bigger than point (as per upper_bound) but
398  // point >= than (*iter).first, i.e. point is contained in the sub-range.
399  // So we have to do one more search for first sub-range after the containing sub-range.
400  AddrRange addrbeyond((*iter).last,subsorttype(true));
401  return tree.upper_bound(addrbeyond);
402 }
403 
407 template<typename _recordtype>
410 
411 {
412  AddrRange addrrange(point);
413  typename std::multiset<AddrRange>::const_iterator iter;
414 
415  // First range where right boundary is equal to or past point
416  iter = tree.lower_bound(addrrange);
417  if (iter==tree.end()) return iter;
418  if ((*iter).first<=end)
419  return iter;
420  return tree.end();
421 }
422 
423 #endif
rangemap::erase
void erase(typename std::list< _recordtype >::iterator v)
Erase a given record from the container.
Definition: rangemap.hh:279
rangemap::find
std::pair< const_iterator, const_iterator > find(linetype a) const
Find sub-ranges intersecting the given boundary point.
Definition: rangemap.hh:330
rangemap::find_end
const_iterator find_end(linetype point) const
Find ending of sub-ranges that contain the given boundary point.
Definition: rangemap.hh:387
rangemap
An interval map container.
Definition: rangemap.hh:64
rangemap::PartIterator
An iterator into the interval map container.
Definition: rangemap.hh:99
rangemap::subsorttype
_recordtype::subsorttype subsorttype
The data-type used for subsorting.
Definition: rangemap.hh:67
rangemap::inittype
_recordtype::inittype inittype
The data-type containing initialization data for records.
Definition: rangemap.hh:68
rangemap::erase
void erase(const_iterator iter)
Erase a record given an iterator.
Definition: rangemap.hh:166
rangemap::const_iterator
PartIterator const_iterator
The main sub-range iterator data-type.
Definition: rangemap.hh:124
rangemap::find_overlap
const_iterator find_overlap(linetype point, linetype end) const
Find first record overlapping given interval.
Definition: rangemap.hh:409
rangemap::insert
std::list< _recordtype >::iterator insert(const inittype &data, linetype a, linetype b)
Insert a new record into the container.
Definition: rangemap.hh:221
rangemap::linetype
_recordtype::linetype linetype
Integer data-type defining the linear domain.
Definition: rangemap.hh:66
rangemap::find_begin
const_iterator find_begin(linetype point) const
Find beginning of sub-ranges that contain the given boundary point.
Definition: rangemap.hh:373