mirror of https://github.com/KLayout/klayout.git
Merge pull request #1855 from KLayout/issue-1853
Issue 1853 (slow Cell#write any Layout#write with huge polygons)
This commit is contained in:
commit
ff708186ec
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
|
||||
#include "dbPolygonGenerators.h"
|
||||
#include "tlTimer.h"
|
||||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
|
|
@ -51,18 +52,18 @@ struct PGPoint
|
|||
class PGPolyContour
|
||||
{
|
||||
public:
|
||||
typedef std::deque <db::Point> contour_type;
|
||||
typedef std::list <db::Point> contour_type;
|
||||
typedef contour_type::const_iterator const_iterator;
|
||||
typedef contour_type::iterator iterator;
|
||||
|
||||
PGPolyContour ()
|
||||
: m_is_hole (false), m_next (-1), m_last (-1)
|
||||
: m_is_hole (false), m_next (-1), m_last (-1), m_size (0)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
PGPolyContour (const PGPolyContour &d)
|
||||
: m_contour (d.m_contour), m_is_hole (d.m_is_hole), m_next (d.m_next), m_last (d.m_last)
|
||||
: m_contour (d.m_contour), m_is_hole (d.m_is_hole), m_next (d.m_next), m_last (d.m_last), m_size (d.m_size)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
|
@ -74,6 +75,7 @@ public:
|
|||
m_is_hole = d.m_is_hole;
|
||||
m_next = d.m_next;
|
||||
m_last = d.m_last;
|
||||
m_size = d.m_size;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -86,14 +88,45 @@ public:
|
|||
db::Point &front () { return m_contour.front (); }
|
||||
const db::Point &back () const { return m_contour.back (); }
|
||||
db::Point &back () { return m_contour.back (); }
|
||||
void push_back (const db::Point &p) { m_contour.push_back (p); }
|
||||
void push_front (const db::Point &p) { m_contour.push_front (p); }
|
||||
void pop_back () { m_contour.pop_back (); }
|
||||
void pop_front () { m_contour.pop_front (); }
|
||||
iterator erase (iterator i) { return m_contour.erase (i); }
|
||||
iterator insert (iterator i, const db::Point &p) { return m_contour.insert (i, p); }
|
||||
|
||||
void push_back (const db::Point &p)
|
||||
{
|
||||
m_contour.push_back (p);
|
||||
++m_size;
|
||||
}
|
||||
|
||||
void push_front (const db::Point &p)
|
||||
{
|
||||
m_contour.push_front (p);
|
||||
++m_size;
|
||||
}
|
||||
|
||||
void pop_back ()
|
||||
{
|
||||
m_contour.pop_back ();
|
||||
--m_size;
|
||||
}
|
||||
|
||||
void pop_front ()
|
||||
{
|
||||
m_contour.pop_front ();
|
||||
--m_size;
|
||||
}
|
||||
|
||||
iterator erase (iterator i)
|
||||
{
|
||||
--m_size;
|
||||
return m_contour.erase (i);
|
||||
}
|
||||
|
||||
iterator insert (iterator i, const db::Point &p)
|
||||
{
|
||||
++m_size;
|
||||
return m_contour.insert (i, p);
|
||||
}
|
||||
|
||||
bool empty () const { return m_contour.empty (); }
|
||||
size_t size () const { return m_contour.size (); }
|
||||
size_t size () const { return m_size; }
|
||||
|
||||
void last (long n)
|
||||
{
|
||||
|
|
@ -127,23 +160,37 @@ public:
|
|||
|
||||
void clear ()
|
||||
{
|
||||
m_size = 0;
|
||||
m_next = -1;
|
||||
m_last = -1;
|
||||
m_contour.clear ();
|
||||
}
|
||||
|
||||
void erase (iterator from, iterator to)
|
||||
void erase (iterator from, iterator to)
|
||||
{
|
||||
m_size -= std::distance (from, to);
|
||||
m_contour.erase (from, to);
|
||||
}
|
||||
|
||||
void splice (iterator at, PGPolyContour &contour)
|
||||
{
|
||||
m_size += contour.size ();
|
||||
contour.m_size = 0;
|
||||
m_contour.splice (at, contour.m_contour);
|
||||
}
|
||||
|
||||
template <class I>
|
||||
iterator insert (iterator at, I from, I to)
|
||||
{
|
||||
m_size += std::distance (from, to);
|
||||
#if 0
|
||||
// NOTE: in some STL m_contour.insert already returns the new iterator
|
||||
size_t index_at = at - m_contour.begin ();
|
||||
m_contour.insert (at, from, to);
|
||||
return m_contour.begin () + index_at;
|
||||
#else
|
||||
return m_contour.insert (at, from, to);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -151,10 +198,46 @@ private:
|
|||
bool m_is_hole;
|
||||
long m_next;
|
||||
long m_last;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
static inline
|
||||
PGPolyContour::const_iterator operator+ (PGPolyContour::const_iterator i, int n)
|
||||
{
|
||||
while (n-- > 0) {
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
class PGContourList
|
||||
static inline
|
||||
PGPolyContour::iterator operator+ (PGPolyContour::iterator i, int n)
|
||||
{
|
||||
while (n-- > 0) {
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static inline
|
||||
PGPolyContour::const_iterator operator- (PGPolyContour::const_iterator i, int n)
|
||||
{
|
||||
while (n-- > 0) {
|
||||
--i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static inline
|
||||
PGPolyContour::iterator operator- (PGPolyContour::iterator i, int n)
|
||||
{
|
||||
while (n-- > 0) {
|
||||
--i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
class PGContourList
|
||||
{
|
||||
public:
|
||||
PGContourList ()
|
||||
|
|
@ -487,7 +570,7 @@ void PolygonGenerator::eliminate_hole ()
|
|||
tl_assert (cprev.size () >= 2);
|
||||
|
||||
// Compute intersection point with next edge
|
||||
db::Edge eprev (cprev.end ()[-2], cprev.back ());
|
||||
db::Edge eprev (*(cprev.end () - 2), cprev.back ());
|
||||
db::Coord xprev = db::coord_traits<db::Coord>::rounded (edge_xaty (eprev, m_y));
|
||||
db::Point pprev (xprev, m_y);
|
||||
|
||||
|
|
@ -497,7 +580,7 @@ void PolygonGenerator::eliminate_hole ()
|
|||
|
||||
cc.is_hole (false);
|
||||
cc.push_back (c.front ());
|
||||
cc.push_back (c.begin ()[1]);
|
||||
cc.push_back (*(c.begin () + 1));
|
||||
if (pprev != cc.back ()) {
|
||||
cc.push_back (pprev);
|
||||
}
|
||||
|
|
@ -506,7 +589,7 @@ void PolygonGenerator::eliminate_hole ()
|
|||
}
|
||||
|
||||
cprev.back () = pprev;
|
||||
while (cprev.size () > 2 && cprev.back ().y () == m_y && cprev.end ()[-2].y () == m_y && cprev.back ().x () <= cprev.end ()[-2].x ()) {
|
||||
while (cprev.size () > 2 && cprev.back ().y () == m_y && (cprev.end () - 2)->y () == m_y && cprev.back ().x () <= (cprev.end () - 2)->x ()) {
|
||||
cprev.pop_back ();
|
||||
}
|
||||
cprev.insert (cprev.end (), c.end () - 2, c.end ());
|
||||
|
|
@ -597,7 +680,7 @@ PolygonGenerator::join_contours (db::Coord x)
|
|||
tl_assert (cprev.size () >= 2);
|
||||
|
||||
// compute intersection point with next edge
|
||||
db::Edge eprev (cprev.end ()[-2], cprev.back ());
|
||||
db::Edge eprev (*(cprev.end () - 2), cprev.back ());
|
||||
db::Coord xprev = db::coord_traits<db::Coord>::rounded (edge_xaty (eprev, m_y));
|
||||
db::Point pprev (xprev, m_y);
|
||||
|
||||
|
|
@ -605,13 +688,13 @@ PolygonGenerator::join_contours (db::Coord x)
|
|||
tl_assert (c2.size () >= 2);
|
||||
|
||||
cprev.back () = pprev;
|
||||
while (cprev.size () > 2 && cprev.back ().y () == m_y && cprev.end ()[-2].y () == m_y && cprev.back ().x () <= cprev.end ()[-2].x ()) {
|
||||
while (cprev.size () > 2 && cprev.back ().y () == m_y && (cprev.end () - 2)->y () == m_y && cprev.back ().x () <= (cprev.end () - 2)->x ()) {
|
||||
cprev.pop_back ();
|
||||
}
|
||||
|
||||
if (iprev == i1) {
|
||||
|
||||
if (cprev.begin ()->y () == m_y && cprev.begin ()[1].y () == m_y && cprev.front ().x () >= cprev.begin ()[1].x ()) {
|
||||
if (cprev.front ().y () == m_y && (cprev.begin () + 1)->y () == m_y && cprev.front ().x () >= (cprev.begin () + 1)->x ()) {
|
||||
cprev.front () = cprev.back ();
|
||||
} else {
|
||||
cprev.push_front (cprev.back ());
|
||||
|
|
@ -621,7 +704,7 @@ PolygonGenerator::join_contours (db::Coord x)
|
|||
|
||||
} else {
|
||||
|
||||
cprev.insert (cprev.end (), c1.begin (), c1.end ());
|
||||
cprev.splice (cprev.end (), c1);
|
||||
cprev.is_hole (false);
|
||||
|
||||
mp_contours->join (iprev, i1);
|
||||
|
|
@ -666,9 +749,11 @@ PolygonGenerator::join_contours (db::Coord x)
|
|||
|
||||
// remove c1 from list of contours, join with c2
|
||||
if (c2.is_hole ()) {
|
||||
c2.insert (c2.end (), c1.begin () + 1, c1.end ());
|
||||
c1.pop_front ();
|
||||
c2.splice (c2.end (), c1);
|
||||
} else {
|
||||
c2.insert (c2.begin (), c1.begin (), c1.end () - 1);
|
||||
c1.pop_back ();
|
||||
c2.splice (c2.begin (), c1);
|
||||
}
|
||||
|
||||
mp_contours->join (i2, i1);
|
||||
|
|
@ -685,9 +770,11 @@ PolygonGenerator::join_contours (db::Coord x)
|
|||
|
||||
// remove c1 from list of contours, join with c2
|
||||
if (c2.is_hole ()) { // yes! c2 is correct!
|
||||
c1.insert (c1.end (), c2.begin () + 1, c2.end ());
|
||||
c2.pop_front ();
|
||||
c1.splice (c1.end (), c2);
|
||||
} else {
|
||||
c1.insert (c1.begin (), c2.begin (), c2.end () - 1);
|
||||
c2.pop_back ();
|
||||
c1.splice (c1.begin (), c2);
|
||||
}
|
||||
|
||||
mp_contours->join (i1, i2);
|
||||
|
|
@ -740,8 +827,8 @@ PolygonGenerator::join_contours (db::Coord x)
|
|||
// shallow analysis: insert the cutline at the end of the sequence - this may
|
||||
// cut lines collinear with contour edges
|
||||
|
||||
eprev = db::Edge (ins[-2], ins[-1]);
|
||||
xprev = db::coord_traits<db::Coord>::rounded (edge_xaty (db::Edge (ins[-2], ins[-1]), m_y));
|
||||
eprev = db::Edge (*(ins - 2), *(ins - 1));
|
||||
xprev = db::coord_traits<db::Coord>::rounded (edge_xaty (db::Edge (*(ins - 2), *(ins - 1)), m_y));
|
||||
#else
|
||||
// deep analysis: determine insertion point: pick the one where the cutline is shortest
|
||||
|
||||
|
|
@ -763,17 +850,17 @@ PolygonGenerator::join_contours (db::Coord x)
|
|||
db::Point pprev (xprev, m_y);
|
||||
|
||||
// remove collinear edges along the cut line
|
||||
ins[-1] = pprev;
|
||||
while (ins - cprev.begin () > 1 && ins[-2].y () == m_y && ins[-1].y () == m_y) {
|
||||
*(ins - 1) = pprev;
|
||||
while (ins - 1 != cprev.begin () && (ins - 2)->y () == m_y && (ins - 1)->y () == m_y) {
|
||||
ins = cprev.erase (ins - 1);
|
||||
}
|
||||
|
||||
if ((c1.begin () + 1)->y () == m_y) {
|
||||
ins = cprev.insert (ins, c1.begin () + 1, c1.end ());
|
||||
ins += c1.size () - 1;
|
||||
ins = ins + (c1.size () - 1);
|
||||
} else {
|
||||
ins = cprev.insert (ins, c1.begin (), c1.end ());
|
||||
ins += c1.size ();
|
||||
ins = ins + c1.size ();
|
||||
}
|
||||
|
||||
ins = cprev.insert (ins, pprev);
|
||||
|
|
|
|||
|
|
@ -109,16 +109,130 @@ private:
|
|||
bool m_owned;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An iterator for the linked list
|
||||
*/
|
||||
template <class C>
|
||||
class list_iterator
|
||||
{
|
||||
public:
|
||||
typedef std::bidirectional_iterator_tag category;
|
||||
typedef C value_type;
|
||||
typedef C &reference;
|
||||
typedef C *pointer;
|
||||
|
||||
list_iterator (C *p = 0) : mp_p (p) { }
|
||||
list_iterator operator++ () { mp_p = static_cast<C *> (mp_p->mp_next); return *this; }
|
||||
list_iterator operator-- () { mp_p = static_cast<C *> (mp_p->mp_prev); return *this; }
|
||||
|
||||
list_iterator operator++ (int)
|
||||
{
|
||||
list_iterator r = *this;
|
||||
++*this;
|
||||
return r;
|
||||
}
|
||||
|
||||
list_iterator operator-- (int)
|
||||
{
|
||||
list_iterator r = *this;
|
||||
--*this;
|
||||
return r;
|
||||
}
|
||||
|
||||
C *operator-> () const
|
||||
{
|
||||
return mp_p;
|
||||
}
|
||||
|
||||
C &operator* () const
|
||||
{
|
||||
return *mp_p;
|
||||
}
|
||||
|
||||
bool operator== (list_iterator other) const { return mp_p == other.mp_p; }
|
||||
bool operator!= (list_iterator other) const { return mp_p != other.mp_p; }
|
||||
|
||||
private:
|
||||
C *mp_p;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A reverse iterator for the linked list
|
||||
*/
|
||||
template <class C>
|
||||
class reverse_list_iterator
|
||||
{
|
||||
public:
|
||||
typedef std::bidirectional_iterator_tag category;
|
||||
typedef C value_type;
|
||||
typedef C &reference;
|
||||
typedef C *pointer;
|
||||
|
||||
reverse_list_iterator (C *p = 0) : mp_p (p) { }
|
||||
reverse_list_iterator operator++ () { mp_p = static_cast<C *> (mp_p->mp_prev); return *this; }
|
||||
reverse_list_iterator operator-- () { mp_p = static_cast<C *> (mp_p->mp_next); return *this; }
|
||||
|
||||
reverse_list_iterator operator++ (int)
|
||||
{
|
||||
reverse_list_iterator r = *this;
|
||||
++*this;
|
||||
return r;
|
||||
}
|
||||
|
||||
reverse_list_iterator operator-- (int)
|
||||
{
|
||||
reverse_list_iterator r = *this;
|
||||
--*this;
|
||||
return r;
|
||||
}
|
||||
|
||||
C *operator-> () const
|
||||
{
|
||||
return mp_p;
|
||||
}
|
||||
|
||||
C &operator* () const
|
||||
{
|
||||
return *mp_p;
|
||||
}
|
||||
|
||||
bool operator== (reverse_list_iterator other) const { return mp_p == other.mp_p; }
|
||||
bool operator!= (reverse_list_iterator other) const { return mp_p != other.mp_p; }
|
||||
|
||||
private:
|
||||
C *mp_p;
|
||||
};
|
||||
|
||||
template <class C>
|
||||
class list_impl<C, false>
|
||||
{
|
||||
public:
|
||||
typedef list_iterator<C> iterator;
|
||||
typedef list_iterator<const C> const_iterator;
|
||||
typedef reverse_list_iterator<C> reverse_iterator;
|
||||
typedef reverse_list_iterator<const C> const_reverse_iterator;
|
||||
|
||||
typedef C value_type;
|
||||
|
||||
list_impl () : m_head (), m_back ()
|
||||
{
|
||||
m_head.mp_next = &m_back;
|
||||
m_back.mp_prev = &m_head;
|
||||
}
|
||||
|
||||
list_impl (const list_impl &&other)
|
||||
{
|
||||
swap (other);
|
||||
}
|
||||
|
||||
list_impl &operator= (const list_impl &&other)
|
||||
{
|
||||
if (&other != this) {
|
||||
swap (other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
list_impl (const list_impl &) { tl_assert (false); }
|
||||
list_impl &operator= (const list_impl &) { tl_assert (false); return *this; }
|
||||
|
||||
|
|
@ -143,6 +257,18 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void erase (iterator i)
|
||||
{
|
||||
erase (i.operator-> ());
|
||||
}
|
||||
|
||||
void erase (iterator from, iterator to)
|
||||
{
|
||||
while (from != to) {
|
||||
erase (from++);
|
||||
}
|
||||
}
|
||||
|
||||
void swap (list_impl<C, false> &other)
|
||||
{
|
||||
std::swap (m_head.mp_next, other.m_head.mp_next);
|
||||
|
|
@ -196,14 +322,24 @@ public:
|
|||
delete first ();
|
||||
}
|
||||
|
||||
void insert (C *after, C *new_obj)
|
||||
C *insert (C *after, C *new_obj)
|
||||
{
|
||||
insert_impl (after, new_obj, true);
|
||||
return insert_impl (after, new_obj, true);
|
||||
}
|
||||
|
||||
void insert_before (C *before, C *new_obj)
|
||||
iterator insert (iterator after, C *new_obj)
|
||||
{
|
||||
insert_before_impl (before, new_obj, true);
|
||||
return iterator (insert (after.operator-> (), new_obj));
|
||||
}
|
||||
|
||||
C *insert_before (C *before, C *new_obj)
|
||||
{
|
||||
return insert_before_impl (before, new_obj, true);
|
||||
}
|
||||
|
||||
iterator insert_before (iterator before, C *new_obj)
|
||||
{
|
||||
return iterator (insert_before_impl (before.operator-> (), new_obj, true));
|
||||
}
|
||||
|
||||
void push_back (C *new_obj)
|
||||
|
|
@ -216,14 +352,24 @@ public:
|
|||
push_front_impl (new_obj, true);
|
||||
}
|
||||
|
||||
void insert (C *after, C &new_obj)
|
||||
C *insert (C *after, C &new_obj)
|
||||
{
|
||||
insert_impl (after, &new_obj, false);
|
||||
return insert_impl (after, &new_obj, false);
|
||||
}
|
||||
|
||||
void insert_before (C *before, C &new_obj)
|
||||
iterator insert (iterator after, C &new_obj)
|
||||
{
|
||||
insert_before_impl (before, &new_obj, false);
|
||||
return iterator (insert_impl (after.operator-> (), &new_obj, false));
|
||||
}
|
||||
|
||||
C *insert_before (C *before, C &new_obj)
|
||||
{
|
||||
return insert_before_impl (before, &new_obj, false);
|
||||
}
|
||||
|
||||
iterator insert_before (iterator before, C &new_obj)
|
||||
{
|
||||
return iterator (insert_before_impl (before.operator-> (), &new_obj, false));
|
||||
}
|
||||
|
||||
void push_back (C &new_obj)
|
||||
|
|
@ -269,7 +415,7 @@ protected:
|
|||
private:
|
||||
list_node<C> m_head, m_back;
|
||||
|
||||
void insert_impl (C *after, C *new_obj, bool owned)
|
||||
C *insert_impl (C *after, C *new_obj, bool owned)
|
||||
{
|
||||
list_node<C> *after_node = after;
|
||||
if (! after) {
|
||||
|
|
@ -281,9 +427,11 @@ private:
|
|||
after_node->mp_next = new_obj;
|
||||
new_obj->mp_prev = after_node;
|
||||
new_obj->mp_next->mp_prev = new_obj;
|
||||
|
||||
return new_obj;
|
||||
}
|
||||
|
||||
void insert_before_impl (C *before, C *new_obj, bool owned)
|
||||
C *insert_before_impl (C *before, C *new_obj, bool owned)
|
||||
{
|
||||
list_node<C> *before_node = before;
|
||||
if (! before) {
|
||||
|
|
@ -295,6 +443,8 @@ private:
|
|||
before_node->mp_prev = new_obj;
|
||||
new_obj->mp_next = before_node;
|
||||
new_obj->mp_prev->mp_next = new_obj;
|
||||
|
||||
return new_obj;
|
||||
}
|
||||
|
||||
void push_back_impl (C *new_obj, bool owned)
|
||||
|
|
@ -313,6 +463,11 @@ class list_impl<C, true>
|
|||
: public list_impl<C, false>
|
||||
{
|
||||
public:
|
||||
typedef typename list_impl<C, false>::iterator iterator;
|
||||
typedef typename list_impl<C, false>::const_iterator const_iterator;
|
||||
typedef typename list_impl<C, false>::reverse_iterator reverse_iterator;
|
||||
typedef typename list_impl<C, false>::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
using list_impl<C, false>::insert;
|
||||
using list_impl<C, false>::push_back;
|
||||
using list_impl<C, false>::pop_back;
|
||||
|
|
@ -339,14 +494,52 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
void insert (C *after, const C &obj)
|
||||
C *insert (C *after, const C &obj)
|
||||
{
|
||||
insert (after, new C (obj));
|
||||
return insert (after, new C (obj));
|
||||
}
|
||||
|
||||
void insert_before (C *before, const C &obj)
|
||||
iterator insert (iterator after, const C &obj)
|
||||
{
|
||||
insert_before (before, new C (obj));
|
||||
return insert (after, new C (obj));
|
||||
}
|
||||
|
||||
template <class Iter>
|
||||
iterator insert (iterator after, Iter from, Iter to)
|
||||
{
|
||||
if (from == to) {
|
||||
return after;
|
||||
} else {
|
||||
iterator first = this->insert (after, *from++);
|
||||
for (iterator next = first; from != to; ++from) {
|
||||
next = this->insert (next, *from);
|
||||
}
|
||||
return first;
|
||||
}
|
||||
}
|
||||
|
||||
C *insert_before (C *before, const C &obj)
|
||||
{
|
||||
return insert_before (before, new C (obj));
|
||||
}
|
||||
|
||||
iterator insert_before (iterator before, const C &obj)
|
||||
{
|
||||
return insert_before (before, new C (obj));
|
||||
}
|
||||
|
||||
template <class Iter>
|
||||
iterator insert_before (iterator before, Iter from, Iter to)
|
||||
{
|
||||
if (from == to) {
|
||||
return before;
|
||||
} else {
|
||||
iterator first = this->insert_before (before, *from++);
|
||||
for (iterator next = first; from != to; ++from) {
|
||||
next = this->insert (next, *from);
|
||||
}
|
||||
return first;
|
||||
}
|
||||
}
|
||||
|
||||
void push_back (const C &obj)
|
||||
|
|
@ -360,72 +553,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An iterator for the linked list
|
||||
*/
|
||||
template <class C>
|
||||
class list_iterator
|
||||
{
|
||||
public:
|
||||
typedef std::bidirectional_iterator_tag category;
|
||||
typedef C value_type;
|
||||
typedef C &reference;
|
||||
typedef C *pointer;
|
||||
|
||||
list_iterator (C *p = 0) : mp_p (p) { }
|
||||
list_iterator operator++ () { mp_p = static_cast<C *> (mp_p->mp_next); return *this; }
|
||||
list_iterator operator-- () { mp_p = static_cast<C *> (mp_p->mp_prev); return *this; }
|
||||
|
||||
C *operator-> () const
|
||||
{
|
||||
return mp_p;
|
||||
}
|
||||
|
||||
C &operator* () const
|
||||
{
|
||||
return *mp_p;
|
||||
}
|
||||
|
||||
bool operator== (list_iterator other) const { return mp_p == other.mp_p; }
|
||||
bool operator!= (list_iterator other) const { return mp_p != other.mp_p; }
|
||||
|
||||
private:
|
||||
C *mp_p;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A reverse iterator for the linked list
|
||||
*/
|
||||
template <class C>
|
||||
class reverse_list_iterator
|
||||
{
|
||||
public:
|
||||
typedef std::bidirectional_iterator_tag category;
|
||||
typedef C value_type;
|
||||
typedef C &reference;
|
||||
typedef C *pointer;
|
||||
|
||||
reverse_list_iterator (C *p = 0) : mp_p (p) { }
|
||||
reverse_list_iterator operator++ () { mp_p = static_cast<C *> (mp_p->mp_prev); return *this; }
|
||||
reverse_list_iterator operator-- () { mp_p = static_cast<C *> (mp_p->mp_next); return *this; }
|
||||
|
||||
C *operator-> () const
|
||||
{
|
||||
return mp_p;
|
||||
}
|
||||
|
||||
C &operator* () const
|
||||
{
|
||||
return *mp_p;
|
||||
}
|
||||
|
||||
bool operator== (reverse_list_iterator other) const { return mp_p == other.mp_p; }
|
||||
bool operator!= (reverse_list_iterator other) const { return mp_p != other.mp_p; }
|
||||
|
||||
private:
|
||||
C *mp_p;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A linked list
|
||||
*
|
||||
|
|
@ -448,12 +575,10 @@ class list
|
|||
: public list_impl<C, CanCopy>
|
||||
{
|
||||
public:
|
||||
typedef list_iterator<C> iterator;
|
||||
typedef list_iterator<const C> const_iterator;
|
||||
typedef reverse_list_iterator<C> reverse_iterator;
|
||||
typedef reverse_list_iterator<const C> const_reverse_iterator;
|
||||
|
||||
typedef C value_type;
|
||||
typedef typename list_impl<C, CanCopy>::iterator iterator;
|
||||
typedef typename list_impl<C, CanCopy>::const_iterator const_iterator;
|
||||
typedef typename list_impl<C, CanCopy>::reverse_iterator reverse_iterator;
|
||||
typedef typename list_impl<C, CanCopy>::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
using list_impl<C, CanCopy>::first;
|
||||
using list_impl<C, CanCopy>::last;
|
||||
|
|
|
|||
|
|
@ -82,9 +82,9 @@ void current_utc_time (struct timespec *ts)
|
|||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Gets the current time in ms from epoch
|
||||
// Gets the current time in ns from epoch
|
||||
|
||||
static int64_t ms_time ()
|
||||
static int64_t ns_time ()
|
||||
{
|
||||
#if defined(__MACH__) && defined(__APPLE__)
|
||||
|
||||
|
|
@ -94,24 +94,27 @@ static int64_t ms_time ()
|
|||
clock_get_time(cclock, &mts);
|
||||
mach_port_deallocate(mach_task_self(), cclock);
|
||||
|
||||
return int64_t (mts.tv_sec) * 1000 + int64_t (0.5 + mts.tv_nsec / 1.0e6);
|
||||
return int64_t (mts.tv_sec) * 1000000000 + int64_t (mts.tv_nsec);
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
FILETIME ft;
|
||||
GetSystemTimeAsFileTime (&ft);
|
||||
static LARGE_INTEGER freq = { 0 };
|
||||
|
||||
uint64_t t = (uint64_t (ft.dwHighDateTime) << (sizeof (ft.dwHighDateTime) * 8)) | uint64_t (ft.dwLowDateTime);
|
||||
t -= ft_to_epoch_offset;
|
||||
if (freq.QuadPart == 0) {
|
||||
QueryPerformanceFrequency (&freq);
|
||||
tl_assert (freq.QuadPart > 0);
|
||||
}
|
||||
|
||||
// FILETIME uses 100ns resolution, hence divide by 10000 to get ms:
|
||||
return int64_t (t / 10000);
|
||||
LARGE_INTEGER qpc;
|
||||
QueryPerformanceCounter (&qpc);
|
||||
|
||||
return int64_t (double (qpc.QuadPart) / double (freq.QuadPart) * 1e9 + 0.5);
|
||||
|
||||
#else
|
||||
|
||||
timespec ts;
|
||||
clock_gettime (CLOCK_REALTIME, &ts);
|
||||
return int64_t (ts.tv_sec) * 1000 + int64_t (0.5 + ts.tv_nsec / 1.0e6);
|
||||
return int64_t (ts.tv_sec) * 1000000000 + int64_t (ts.tv_nsec);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
|
@ -120,8 +123,8 @@ static int64_t ms_time ()
|
|||
// Implementation of Timer
|
||||
|
||||
Timer::Timer ()
|
||||
: m_user_ms (0), m_sys_ms (0), m_wall_ms (0),
|
||||
m_user_ms_res (0), m_sys_ms_res (0), m_wall_ms_res (0)
|
||||
: m_user_ms (0), m_sys_ms (0), m_wall_ns (0),
|
||||
m_user_ms_res (0), m_sys_ms_res (0), m_wall_ns_res (0)
|
||||
{
|
||||
// ..
|
||||
}
|
||||
|
|
@ -142,7 +145,7 @@ Timer::start ()
|
|||
m_sys_ms += (timer_t) ((clks.tms_stime + clks.tms_cstime) * clk2msec + 0.5);
|
||||
#endif
|
||||
|
||||
m_wall_ms += ms_time ();
|
||||
m_wall_ns += ns_time ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -150,15 +153,15 @@ Timer::stop ()
|
|||
{
|
||||
m_user_ms = -m_user_ms;
|
||||
m_sys_ms = -m_sys_ms;
|
||||
m_wall_ms = -m_wall_ms;
|
||||
m_wall_ns = -m_wall_ns;
|
||||
start ();
|
||||
|
||||
m_user_ms_res = m_user_ms;
|
||||
m_sys_ms_res = m_sys_ms;
|
||||
m_wall_ms_res = m_wall_ms;
|
||||
m_wall_ns_res = m_wall_ns;
|
||||
m_user_ms = 0;
|
||||
m_sys_ms = 0;
|
||||
m_wall_ms = 0;
|
||||
m_wall_ns = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -166,20 +169,20 @@ Timer::take ()
|
|||
{
|
||||
timer_t user_ms = m_user_ms;
|
||||
timer_t sys_ms = m_sys_ms;
|
||||
timer_t wall_ms = m_wall_ms;
|
||||
timer_t wall_ns = m_wall_ns;
|
||||
|
||||
m_user_ms = -m_user_ms;
|
||||
m_sys_ms = -m_sys_ms;
|
||||
m_wall_ms = -m_wall_ms;
|
||||
m_wall_ns = -m_wall_ns;
|
||||
start ();
|
||||
|
||||
m_user_ms_res = m_user_ms;
|
||||
m_sys_ms_res = m_sys_ms;
|
||||
m_wall_ms_res = m_wall_ms;
|
||||
m_wall_ns_res = m_wall_ns;
|
||||
|
||||
m_user_ms = user_ms;
|
||||
m_sys_ms = sys_ms;
|
||||
m_wall_ms = wall_ms;
|
||||
m_wall_ns = wall_ns;
|
||||
}
|
||||
|
||||
size_t
|
||||
|
|
@ -288,20 +291,20 @@ SelfTimer::report () const
|
|||
|
||||
Clock::Clock (double s)
|
||||
{
|
||||
m_clock_ms = s * 1000.0;
|
||||
m_clock_ns = s * 1e9;
|
||||
}
|
||||
|
||||
double
|
||||
Clock::seconds () const
|
||||
{
|
||||
return double (m_clock_ms) * 0.001;
|
||||
return double (m_clock_ns) * 1e-9;
|
||||
}
|
||||
|
||||
Clock
|
||||
Clock::current ()
|
||||
{
|
||||
Clock c;
|
||||
c.m_clock_ms += ms_time ();
|
||||
c.m_clock_ns += ns_time ();
|
||||
return c;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ public:
|
|||
*/
|
||||
double sec_wall () const
|
||||
{
|
||||
return (double (m_wall_ms_res) * 0.001);
|
||||
return (double (m_wall_ns_res) * 1e-9);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -101,8 +101,8 @@ public:
|
|||
static size_t memory_size ();
|
||||
|
||||
private:
|
||||
timer_t m_user_ms, m_sys_ms, m_wall_ms;
|
||||
timer_t m_user_ms_res, m_sys_ms_res, m_wall_ms_res;
|
||||
timer_t m_user_ms, m_sys_ms, m_wall_ns;
|
||||
timer_t m_user_ms_res, m_sys_ms_res, m_wall_ns_res;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -182,7 +182,7 @@ public:
|
|||
/**
|
||||
* @brief Default constructor: construct a clock object pointing to an arbitrary value
|
||||
*/
|
||||
Clock () : m_clock_ms (0)
|
||||
Clock () : m_clock_ns (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -196,7 +196,7 @@ public:
|
|||
* @brief Copy constructor
|
||||
*/
|
||||
Clock (const Clock &d)
|
||||
: m_clock_ms (d.m_clock_ms)
|
||||
: m_clock_ns (d.m_clock_ns)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -206,7 +206,7 @@ public:
|
|||
*/
|
||||
Clock &operator= (Clock d)
|
||||
{
|
||||
m_clock_ms = d.m_clock_ms;
|
||||
m_clock_ns = d.m_clock_ns;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -215,7 +215,7 @@ public:
|
|||
*/
|
||||
bool operator== (Clock d) const
|
||||
{
|
||||
return m_clock_ms == d.m_clock_ms;
|
||||
return m_clock_ns == d.m_clock_ns;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -231,7 +231,7 @@ public:
|
|||
*/
|
||||
bool operator< (Clock d) const
|
||||
{
|
||||
return m_clock_ms < d.m_clock_ms;
|
||||
return m_clock_ns < d.m_clock_ns;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -239,7 +239,7 @@ public:
|
|||
*/
|
||||
Clock &operator-= (Clock d)
|
||||
{
|
||||
m_clock_ms -= d.m_clock_ms;
|
||||
m_clock_ns -= d.m_clock_ns;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -264,7 +264,7 @@ public:
|
|||
static Clock current ();
|
||||
|
||||
private:
|
||||
timer_t m_clock_ms;
|
||||
timer_t m_clock_ns;
|
||||
};
|
||||
|
||||
} // namespace tl
|
||||
|
|
|
|||
|
|
@ -403,3 +403,70 @@ TEST(2_BasicNoCopy)
|
|||
|
||||
EXPECT_EQ (obj_count, size_t (0)); // mc2 gone as well
|
||||
}
|
||||
|
||||
TEST(3_Insert)
|
||||
{
|
||||
obj_count = 0;
|
||||
|
||||
tl::list<MyClass1> l1;
|
||||
tl::list<MyClass1>::iterator i1;
|
||||
|
||||
EXPECT_EQ (l1.empty (), true);
|
||||
EXPECT_EQ (l1.size (), size_t (0));
|
||||
EXPECT_EQ (l2s (l1), "");
|
||||
|
||||
l1.push_back (MyClass1 (42));
|
||||
EXPECT_EQ (l2s (l1), "42");
|
||||
EXPECT_EQ (l1.size (), size_t (1));
|
||||
|
||||
i1 = l1.insert_before (l1.end (), MyClass1 (17));
|
||||
EXPECT_EQ (l2s (l1), "42,17");
|
||||
EXPECT_EQ (i1->n, 17);
|
||||
EXPECT_EQ (l1.size (), size_t (2));
|
||||
|
||||
i1 = l1.insert_before (i1, MyClass1 (11));
|
||||
EXPECT_EQ (l2s (l1), "42,11,17");
|
||||
EXPECT_EQ (i1->n, 11);
|
||||
EXPECT_EQ (l1.size (), size_t (3));
|
||||
|
||||
i1 = l1.insert (i1, MyClass1 (12));
|
||||
EXPECT_EQ (l2s (l1), "42,11,12,17");
|
||||
EXPECT_EQ (i1->n, 12);
|
||||
EXPECT_EQ (l1.size (), size_t (4));
|
||||
|
||||
MyClass1 arr[3] = { MyClass1 (1), MyClass1 (2), MyClass1 (3) };
|
||||
|
||||
i1 = l1.insert (i1, arr + 0, arr + 0);
|
||||
EXPECT_EQ (l2s (l1), "42,11,12,17");
|
||||
EXPECT_EQ (i1->n, 12);
|
||||
EXPECT_EQ (l1.size (), size_t (4));
|
||||
|
||||
i1 = l1.insert (i1, arr + 0, arr + 3);
|
||||
EXPECT_EQ (l2s (l1), "42,11,12,1,2,3,17");
|
||||
EXPECT_EQ (i1->n, 1);
|
||||
EXPECT_EQ (l1.size (), size_t (7));
|
||||
|
||||
l1.clear ();
|
||||
l1.push_back (MyClass1 (42));
|
||||
i1 = l1.insert_before (l1.end (), MyClass1 (17));
|
||||
EXPECT_EQ (l2s (l1), "42,17");
|
||||
EXPECT_EQ (i1->n, 17);
|
||||
EXPECT_EQ (l1.size (), size_t (2));
|
||||
|
||||
i1 = l1.insert_before (i1, arr + 0, arr + 0);
|
||||
EXPECT_EQ (l2s (l1), "42,17");
|
||||
EXPECT_EQ (i1->n, 17);
|
||||
EXPECT_EQ (l1.size (), size_t (2));
|
||||
|
||||
i1 = l1.insert_before (i1, arr + 0, arr + 3);
|
||||
EXPECT_EQ (l2s (l1), "42,1,2,3,17");
|
||||
EXPECT_EQ (i1->n, 1);
|
||||
EXPECT_EQ (l1.size (), size_t (5));
|
||||
|
||||
// test erase range
|
||||
l1.erase (i1, l1.end ());
|
||||
EXPECT_EQ (l2s (l1), "42");
|
||||
EXPECT_EQ (l1.size (), size_t (1));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue