libUTL++
SpanCol.h
1 #pragma once
2 
4 
5 #include <libutl/RBtree.h>
6 #include <libutl/Span.h>
7 
9 
10 UTL_NS_BEGIN;
11 
13 
52 
54 template <class T, class D = T>
55 class SpanCol : public TRBtree<Span<T, D>>
56 {
58 
59 public:
60  typedef typename TRBtree<Span<T, D>>::iterator iterator;
61 
62 public:
64  D
65  totalSize() const
66  {
67  return _totalSize;
68  }
69 
70  bool
71  add(const Object& object)
72  {
73  if (this->isOwner())
74  return add(object.clone());
75  else
76  return add(&object);
77  }
78 
79  virtual bool add(const Object* object);
80 
81  T minBegin() const;
82 
83  T maxEnd() const;
84 
85  virtual bool isMergeable(const Object& lhs, const Object& rhs) const;
86 
87  void remove(const Span<T, D>& span);
88 
89  virtual bool
90  remove(const Object& key)
91  {
92  return RBtree::remove(key);
93  }
94 
96  span() const
97  {
98  return Span<T, D>(minBegin(), maxEnd());
99  }
100 
101 protected:
102  virtual void
103  onAdd(const Object& object)
104  {
105  }
106  virtual void
107  onRemove(const Object& object)
108  {
109  }
110  virtual void merge(Object& lhs, const Object& rhs);
111  virtual Span<T, D> remove(Object& object, const Span<T, D>& span);
112 
113 private:
114  void
115  init()
116  {
117  _totalSize = 0;
118  }
119  void
120  deInit()
121  {
122  }
123 
124 private:
125  D _totalSize;
126 };
127 
129 
130 template <class T, class D>
131 bool
133 {
134  auto& spanRef = utl::cast<Span<T, D>>(object->getKey());
135  Span<T, D> span = spanRef;
136  span.setRelaxed(true);
137 
138  if (span.isNil())
139  {
140  if (this->isOwner())
141  {
142  delete object;
143  }
144  return false;
145  }
146 
147  iterator it = this->findFirstIt(span);
148 
149  while (it != this->end())
150  {
151  Object& curObj = **it;
152  Span<T, D>& curSpan = (Span<T, D>&)curObj.getKey();
153 
154  if (curSpan != span)
155  {
156  break;
157  }
158 
159  if (isMergeable(*object, curObj))
160  {
161  merge((Object&)*object, curObj);
162  onRemove(curObj);
163  this->removeIt(it);
164  continue;
165  }
166  else
167  {
168  // Remove the span from curSpan
169  Span<T, D> rhsSpan = remove(curObj, span);
170  // When we remove the span from curSpan, we may bisect it.
171  // If so, rhsSpan will contain the other half of curSpan.
172  // We need to construct another object based on this
173  // information and add it.
174  if (!rhsSpan.isNil())
175  {
176  // clone curObj to get rhsObj
177  Object* rhsObj = curObj.clone();
178 
179  // set the rhsSpan's begin, end time
180  Span<T, D>& _rhsSpan = (Span<T, D>&)rhsObj->getKey();
181  _rhsSpan.Span<T, D>::copy(rhsSpan);
182 
183  // add rhsObj
184  add(rhsObj);
185  }
186  // If curSpan is NIL we should remove it entirely
187  if (curSpan.isNil())
188  {
189  onRemove(curObj);
190  this->removeIt(it);
191  continue;
192  }
193  }
194 
195  it++;
196  }
197 
198  // merge with adjacent spans
199 
200  // find a span that is adjacent on the left
201  span.set(spanRef.begin() - 1, spanRef.begin());
202  it = this->findIt(span);
203  Object* adjObj = *it;
204  if (adjObj != nullptr)
205  {
206  if (isMergeable(*object, *adjObj))
207  {
208  merge((Object&)*object, *adjObj);
209  onRemove(*adjObj);
210  this->removeIt(it);
211  }
212  }
213 
214  // find a span that is adjacent on the right
215  span.set(spanRef.end(), spanRef.end() + 1);
216  it = this->findIt(span);
217  adjObj = *it;
218  if (adjObj != nullptr)
219  {
220  if (isMergeable(*object, *adjObj))
221  {
222  merge((Object&)*object, *adjObj);
223  onRemove(*adjObj);
224  this->removeIt(it);
225  }
226  }
227 
228  // finally add span to the tree
229  _totalSize += spanRef.size();
230  onAdd(*object);
231  RBtree::add(object);
232 
233  return true;
234 }
235 
237 
238 template <class T, class D>
239 T
241 {
242  T res = T();
243 
244  if (this->_items > 0)
245  {
246  res = ((Span<T, D>*)this->first())->begin();
247  }
248 
249  return res;
250 }
251 
253 
254 template <class T, class D>
255 T
256 SpanCol<T, D>::maxEnd() const
257 {
258  T res = T();
259 
260  if (this->_items > 0)
261  {
262  res = ((Span<T, D>*)this->last())->end();
263  }
264 
265  return res;
266 }
267 
269 
270 template <class T, class D>
271 bool
272 SpanCol<T, D>::isMergeable(const Object& lhs, const Object& rhs) const
273 {
274  const Span<T, D>& lhsSpan = (const Span<T, D>&)lhs.getKey();
275  const Span<T, D>& rhsSpan = (const Span<T, D>&)rhs.getKey();
276  Span<T, D> saveLHS = lhsSpan;
277  ((Span<T, D>&)lhsSpan).Span<T, D>::copy(rhsSpan);
278  bool res = (lhs == rhs);
279  ((Span<T, D>&)lhsSpan).Span<T, D>::copy(saveLHS);
280  return res;
281 }
282 
284 
285 template <class T, class D>
286 void
287 SpanCol<T, D>::remove(const Span<T, D>& _span)
288 {
289  Span<T, D> span = _span;
290  span.setRelaxed(true);
291 
292  iterator it = this->findFirstIt(span);
293 
294  while (it != this->end())
295  {
296  Object& curObj = **it;
297  Span<T, D>& curSpan = (Span<T, D>&)(curObj.getKey());
298 
299  // if curSpan doesn't overlap with ts's span, we're done
300  if (curSpan != span)
301  {
302  break;
303  }
304 
305  // Remove the span from curSpan
306  Span<T, D> rhsSpan = remove(curObj, span);
307  // When we remove the span from curSpan, we may bisect it.
308  // If so, rhsSpan will contain the other half of curSpan.
309  // We need to construct another object based on this
310  // information and add it.
311  if (!rhsSpan.isNil())
312  {
313  // Clone curObj to get rhsObj
314  Object* rhsObj = curObj.clone();
315 
316  // Set the rhsSpan's begin, end time
317  Span<T, D>& _rhsSpan = (Span<T, D>&)rhsObj->getKey();
318  _rhsSpan.Span<T, D>::copy(rhsSpan);
319 
320  // Add rhsObj
321  onAdd(*rhsObj);
322  add(rhsObj);
323  }
324  // If curSpan is NIL we should remove it entirely
325  if (curSpan.isNil())
326  {
327  // don't call onRemove() because we called remove()
328  this->removeIt(it);
329  continue;
330  }
331 
332  it++;
333  }
334 }
335 
337 
338 template <class T, class D>
339 void
340 SpanCol<T, D>::merge(Object& lhs, const Object& rhs)
341 {
342  Span<T, D>& lhsSpan = (Span<T, D>&)lhs.getKey();
343  const Span<T, D>& rhsSpan = (const Span<T, D>&)rhs.getKey();
344  lhsSpan.merge(rhsSpan);
345  _totalSize -= rhsSpan.size();
346 }
347 
349 
350 template <class T, class D>
352 SpanCol<T, D>::remove(Object& object, const Span<T, D>& span)
353 {
354  Span<T, D>& objSpan = (Span<T, D>&)object.getKey();
355  Span<T, D> overlap = objSpan.overlap(span);
356  _totalSize -= overlap.size();
357  return objSpan.remove(span);
358 }
359 
361 
362 UTL_NS_END;
363 
365 
T * clone(const T *object)
Create a clone of the given object.
Definition: util_inl.h:404
void merge(const Span< T, D > &span)
Merge with the given span.
Definition: Span.h:184
D totalSize() const
Get the total size of all spans.
Definition: SpanCol.h:65
void deInit()
De-initialize UTL++.
void merge(const FwdIt &lhsBegin, const FwdIt &lhsEnd, const FwdIt &rhsBegin, const FwdIt &rhsEnd, FwdIt &out, const Ordering *ordering=nullptr, bool cloning=false)
Merge two sorted sequences into a single sorted sequence.
D size() const
Return the size (end - begin).
Definition: Span.h:136
void remove(FwdIt &begin, const FwdIt &end, bool cmp=false, const Predicate *pred=nullptr, bool predVal=false)
Remove objects from a sequence.
Template version of RBtree.
Definition: TRBtree.h:25
#define UTL_CLASS_DECL_TPL2_TPLxTPL2(DC, DC_T1, DC_T2, BC, BC_BT, BC_T1, BC_T2)
Declaration of standard UTL++ functionality for a template class with two parameters, where the base class has one template parameter, which itself is a class with two template parameters.
Definition: macros.h:753
Span collection.
Definition: SpanCol.h:55
virtual void set(const Object *object)
Set the current object.
In-order bi-directional BinTree iterator.
Definition: BinTreeIt.h:22
void setRelaxed(bool relaxed)
Set the relaxed flag.
Definition: Span.h:129
#define UTL_CLASS_IMPL_TPL2(className, T1, T2)
Implementation of standard UTL++ functionality for a template class with two parameters.
Definition: macros.h:917
Span< T, D > overlap(const Span< T, D > &span) const
Return the sub-span that overlaps with the given span.
Definition: Span.h:400
virtual const Object & getKey() const
Get the key for this object.
bool isNil() const
Determine whether the span is nil.
Definition: Span.h:108
Span of values.
Definition: Span.h:47
Root of UTL++ class hierarchy.
Definition: Object.h:52
Span< T, D > remove(const Span< T, D > &span)
Remove the given span from self.
Definition: Span.h:420
void init()
Initialize UTL++.