-/***************************************************************************
- timecvt.cpp - description
- -------------------
- begin : Fri May 11 2001
- copyright : (C) 2001 by STYLETEC
- email : info@styletec.de
- ***************************************************************************/
+/** @file
+ * @brief time related functions.
+ *
+ * @copyright Copyright © 2001-2008 by Intra2net AG
+ * @license commercial
+ * @contact info@intra2net.com
+ *
+ */
+
#include <string>
#include <sstream>
#include <iomanip>
#include <bitset>
#include <stdexcept>
+#include <iterator>
+#include <algorithm>
#include <time.h>
#include <sys/timeb.h>
return rtn;
}
+
+
+/*
+** implementaion of Interval
+*/
+
+/**
+ * @brief tests if there is some overlapping with another interval
+ * @param other the other interval
+ * @return @a true if the two intervals have a non empty intersection.
+ */
+bool Interval::intersects(const Interval& other) const
+{
+ return
+ // // other start within this:
+ (other.m_lower_bound >= m_lower_bound and other.m_lower_bound < m_upper_bound )
+ // // other end within this:
+ or (other.m_upper_bound > m_lower_bound and other.m_upper_bound <= m_upper_bound )
+ // // other contains this
+ or (other.m_lower_bound <= m_lower_bound and other.m_upper_bound >= m_upper_bound )
+ ;
+} // eo Interval::intersects(const Interval&)
+
+
+/**
+ * @brief tests if the current interval (fully) contains another one.
+ * @param other the other interval.
+ * @return @a true if the current interval fully contains the other interval.
+ */
+bool Interval::contains(const Interval& other) const
+{
+ return (other.m_lower_bound >= m_lower_bound)
+ and (other.m_upper_bound <= m_upper_bound)
+ ;
+} // eo Interval::contains(const Interval& other) const
+
+
+/*
+** implementation of Intervals:
+*/
+
+
+Intervals::Intervals()
+{
+} // eo Intervals::Intervals
+
+
+/**
+ * @brief tests if one of the intervals of the list intersects with the given interval.
+ * @param other the interval to check for intersection.
+ * @return @a true if there is an intersection.
+ */
+bool Intervals::intersects(const Interval& other) const
+{
+ for(const_iterator it= begin();
+ it != end();
+ ++it)
+ {
+ if ( it->intersects(other) )
+ {
+ return true;
+ }
+ }
+ return false;
+} // eo Intervals::intersects(const Interval&) const
+
+
+/**
+ * @brief tests if we have at least one intersection with another Intervals instance.
+ * @param other the other instance.
+ * @return @a true if there is an intersection.
+ */
+bool Intervals::intersects(const Intervals& other) const
+{
+ for(const_iterator it= begin();
+ it != end();
+ ++it)
+ {
+ if ( other.intersects( *it ) )
+ {
+ return true;
+ }
+ }
+ return false;
+} // eo Intervals::intersects(const Intervals&) const
+
+
+/**
+ * @brief adds a new interval to the list.
+ * @param new_frame the new interval.
+ *
+ * Adds the interval to the list and joins overlapping intervals.
+ */
+void Intervals::add(const Interval& new_frame)
+{
+ if (not new_frame.is_valid() or new_frame.empty())
+ {
+ // well... we will not insert invalid or empty frames!
+ return;
+ }
+ for (IntervalList::iterator it= m_intervals.begin();
+ it != m_intervals.end();
+ ++it)
+ {
+ Interval& current_frame = *it;
+ if ( new_frame.m_lower_bound > current_frame.m_upper_bound )
+ {
+ // new_frame begins later than current end; go on:
+ continue;
+ }
+ // at this point: the begin of the new frame is less then the current end.
+ // now let's determine how we can insert the new frame:
+
+ if ( new_frame.m_upper_bound < current_frame.m_lower_bound )
+ {
+ // new disjoint frame; insert it before the current frame:
+ m_intervals.insert( it, new_frame );
+ // and we are done.
+ return;
+ }
+ // at this point: the end of the new frame is >= current begin.
+ if ( new_frame.m_upper_bound <= current_frame.m_upper_bound )
+ {
+ // the end of the new frame is within our current frame; we need to combine
+ if (new_frame.m_lower_bound < current_frame.m_lower_bound)
+ {
+ // the new interval starts earlier; we need to adjust our current frame:
+ current_frame.m_lower_bound = new_frame.m_lower_bound;
+ }
+ // NOTE no "else" part needed since in that case our current frame already
+ // contains the new one!
+
+ // we are done:
+ return;
+ }
+ // at this point: end of new frame > end of current frame
+ // so we need to extend the current frame; at least the end.
+ // But we need to deal with intersects of following frames... *sigh*
+
+ // first the simple part: let's see if we need to move the start:
+ if ( new_frame.m_lower_bound < current_frame.m_lower_bound)
+ {
+ // yes, we need to move the start:
+ current_frame.m_lower_bound = new_frame.m_lower_bound;
+ }
+
+ // now let's extend the end:
+ current_frame.m_upper_bound = new_frame.m_upper_bound;
+
+ // well... let's walk through the following frames; looking for more joins...:
+ IntervalList::iterator it2 = it;
+ while( ++(it2=it) != m_intervals.end()
+ and current_frame.m_upper_bound >= it2->m_lower_bound
+ )
+ {
+ Interval next_frame= *it2;
+ if ( current_frame.m_upper_bound < next_frame.m_upper_bound )
+ {
+ // in this case our end is within the next frame.
+ // adjust our end.
+ current_frame.m_upper_bound = next_frame.m_upper_bound;
+ }
+ // and remove the next frame since the current frame contains it (now):
+ m_intervals.erase(it2);
+ }
+ // we are done!
+ return;
+ }
+ // at this point: new frame starts later than the last frame ends
+ // append the new frame:
+ m_intervals.push_back( new_frame );
+} // eo Intervals::add(const Interval&)
+
+
+/**
+ * @brief subtracts a time interval from the list.
+ * @param del_frame the time interval to subtract.
+ *
+ * removes the time interval from the list; cut off parts from or remove existing
+ * intervals if they overlap.
+ */
+void Intervals::sub(const Interval& del_frame)
+{
+ if (not del_frame.is_valid() or del_frame.empty() )
+ {
+ return;
+ }
+ for (IntervalList::iterator it= m_intervals.begin();
+ it != m_intervals.end();
+ )
+ {
+ Interval& current_frame = *it;
+ if ( del_frame.m_lower_bound >= current_frame.m_upper_bound )
+ {
+ // del_frame begins later than current end; go on:
+ ++it;
+ continue;
+ }
+ // at this point: the begin of the del frame is less then the current end.
+ if ( del_frame.m_upper_bound < current_frame.m_lower_bound )
+ {
+ // end is before our start; nothing to do.
+ return;
+ }
+ // at this point: the end of the del frame is >= current begin.
+ if ( del_frame.m_upper_bound < current_frame.m_upper_bound )
+ {
+ // del frame end point is within our interval.
+ if ( del_frame.m_lower_bound > current_frame.m_lower_bound)
+ {
+ // the del frame is within our interval... we need to split:
+ m_intervals.insert(it, Interval( current_frame.m_lower_bound, del_frame.m_lower_bound ) );
+ }
+ // adjust start of current frame:
+ current_frame.m_lower_bound= del_frame.m_upper_bound;
+ // and we are done!
+ return;
+ }
+ // at this point the end of the del frame is >= current end
+ if ( del_frame.m_lower_bound > current_frame.m_lower_bound )
+ {
+ // a part of the current interval needs to be preserved..
+ // move the end.
+ current_frame.m_upper_bound= del_frame.m_lower_bound;
+ // and continue with the next interval:
+ ++it;
+ continue;
+ }
+ // at this point; the whole frame needs to be deleted..
+ if ( it == m_intervals.begin())
+ {
+ m_intervals.erase(it);
+ it= m_intervals.begin();
+ }
+ else
+ {
+ IntervalList::iterator it2= it++;
+ m_intervals.erase(it2);
+ }
+ }
+} // eo Intervals::sub(const Interval&)
+
+
+/**
+ * @brief returns if we contain an interval.
+ * @param other the interval to check.
+ * @return @a true if we cover the given interval, too.
+ */
+bool Intervals::contains(const Interval& other) const
+{
+ for(const_iterator it= begin();
+ it != end();
+ ++it)
+ {
+ if ( it->contains( other ))
+ {
+ return true;
+ }
+ }
+ return false;
+} // eo Intervals::contains(const Interval&) const
+
+
+/**
+ * @brief returns if we contain another interval combination.
+ * @param other the intervals to check.
+ * @return @a true if we cover the given intervals, too.
+ *
+ * @internal we rely on the fact that the lists are sorted and contain
+ * disjoint intervals.
+ */
+bool Intervals::contains(const Intervals& other) const
+{
+ const_iterator my_it= begin();
+ const_iterator other_it= other.begin();
+ while( my_it != end() and other_it!= other.end() )
+ {
+ // seek the first interval which contains the lower bound of the current other interval
+ while (my_it != end()
+ and my_it->m_lower_bound > other_it->m_lower_bound
+ and other_it->m_lower_bound >= my_it->m_upper_bound
+ )
+ {
+ ++my_it;
+ }
+ if (my_it == end())
+ {
+ break;
+ }
+ if (not my_it->contains( *other_it ))
+ {
+ // if we don't contain the current other; we're done:
+ return false;
+ }
+ //else check the next other interval:
+ ++other_it;
+ }
+ return (other_it == other.end());
+} // eo Intervals::comtains(const Intervals&) const
+
+
+bool Intervals::operator==(const Intervals& other) const
+{
+ // since we keep sorted lists: just compare the lists :-)
+ return m_intervals == other.m_intervals;
+} // eo Intervals::operator==(const Intervals&)
+
+
+Intervals& Intervals::operator+=(const Interval& other)
+{
+ add(other);
+ return *this;
+} // eo operator+=(const Interval&)
+
+
+Intervals& Intervals::operator-=(const Interval& other)
+{
+ sub(other);
+ return *this;
+} // eo operator-=(const Interval&)
+
+
+Intervals& Intervals::operator+=(const Intervals& other)
+{
+ for(const_iterator it= other.begin();
+ it != other.end();
+ ++it)
+ {
+ add( *it );
+ }
+ return *this;
+} // eo operator+=(const Intervals&)
+
+
+Intervals& Intervals::operator-=(const Intervals& other)
+{
+ if (&other == this)
+ {
+ m_intervals.clear();
+ }
+ else
+ {
+ for(const_iterator it= other.begin();
+ it != other.end();
+ ++it)
+ {
+ sub( *it );
+ }
+ }
+ return *this;
+} // eo operator-=(const Intervals&)
-/***************************************************************************
- timecvt.hxx - description
- -------------------
- begin : Fri May 11 2001
- copyright : (C) 2001 by STYLETEC
- email : info@styletec.de
- ***************************************************************************/
+/** @file
+ * @brief time related functions.
+ *
+ * @copyright Copyright © 2001-2008 by Intra2net AG
+ * @license commercial
+ * @contact info@intra2net.com
+ *
+ */
#ifndef __TIMEFUNC_HXX
#define __TIMEFUNC_HXX
+#include <string>
#include <bitset>
+#include <list>
+
double prec_time(void);
static std::string get_english_display(WEEKDAY day);
};
+
+/**
+ * @brief structure representing a single (half-open) interval.
+ */
+class Interval
+{
+ public:
+ Interval()
+ : m_lower_bound(0)
+ , m_upper_bound(0)
+ {
+ } //
+
+ Interval( unsigned int start, unsigned int end )
+ : m_lower_bound(start)
+ , m_upper_bound(end)
+ {
+ } //
+
+ bool is_valid() const
+ {
+ return m_lower_bound <= m_upper_bound;
+ } // eo is_valid() const
+
+ bool empty() const
+ {
+ return m_lower_bound == m_upper_bound;
+ } // eo empty() const
+
+
+ unsigned int lower_bound() const { return m_lower_bound; }
+ unsigned int upper_bound() const { return m_upper_bound; }
+
+
+ bool operator== (const Interval& other) const
+ {
+ return m_lower_bound == other.m_lower_bound and m_upper_bound == other.m_upper_bound;
+ } // eo operator==(const Interval&)
+
+
+ /**
+ * @brief less operator. compares only the start times!
+ * @param other the other interval to compare with.
+ * @return @a true if the current start is less than the other start.
+ */
+ bool operator<(const Interval& other) const
+ {
+ return m_lower_bound < other.m_lower_bound;
+ } // eo operator<(const Interval&)
+
+
+ bool intersects(const Interval& other) const;
+ bool contains(const Interval& other) const;
+
+
+ protected:
+
+ friend class Intervals;
+
+ unsigned int m_lower_bound;
+ unsigned int m_upper_bound;
+
+}; // eo Interval
+
+
+
+/**
+ * @brief structure representing a combination of single disjoint (half open) intervals.
+ *
+ * Basic idea is that this structure provides an interface for adding and
+ * subtracting single intervals and keeps the internal list of intervals as
+ * a list of disjoint intervals.
+ *
+ * @note the list is sorted by the start; lower comes first.
+ *
+ * @note the class provides some methods similar to STL container classes;
+ * i.e. it can be used with (at least some) STL algorithms.
+ *
+ * @internal
+ * we use a std::list for the intervals; this means we don't invalidate all
+ * iterators when we insert or delete within loops...
+ * And we use that fact!!
+ */
+class Intervals
+{
+ public:
+ typedef std::list< Interval > IntervalList;
+ typedef IntervalList::value_type value_type;
+ typedef IntervalList::const_iterator const_iterator;
+ typedef IntervalList::const_iterator iterator; // we allow only const...
+ typedef IntervalList::size_type size_type;
+
+ public:
+ Intervals();
+
+ void add(const Interval& new_frame);
+ void sub(const Interval& new_frame);
+
+
+ const_iterator begin() const { return m_intervals.begin(); }
+ const_iterator end() const { return m_intervals.end(); }
+
+ bool empty() const { return m_intervals.empty(); }
+ const Interval& front() const { return m_intervals.front(); }
+ const Interval& back() const { return m_intervals.back(); }
+
+ size_type size() const { return m_intervals.size(); }
+
+ bool intersects(const Interval& other) const;
+ bool intersects(const Intervals& other) const;
+
+ bool contains(const Interval& other) const;
+ bool contains(const Intervals& other) const;
+
+ bool operator==(const Intervals& other) const;
+ bool operator!=(const Intervals& other) const {return not (*this == other) ; }
+
+ Intervals& operator+=(const Interval& other);
+ Intervals& operator-=(const Interval& other);
+
+ Intervals& operator+=(const Intervals& other);
+ Intervals& operator-=(const Intervals& other);
+
+ protected:
+
+ std::list< Interval > m_intervals;
+
+}; // eo Intervals
+
+
+
+
#endif