libuav original

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers time.hpp Source File

time.hpp

00001 /*
00002  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #ifndef UAVCAN_TIME_HPP_INCLUDED
00006 #define UAVCAN_TIME_HPP_INCLUDED
00007 
00008 #include <cstdio>
00009 #include <uavcan/std.hpp>
00010 #include <uavcan/build_config.hpp>
00011 #include <uavcan/util/templates.hpp>
00012 #include <uavcan/Timestamp.hpp>
00013 
00014 
00015 namespace uavcan
00016 {
00017 
00018 template <typename D>
00019 class DurationBase
00020 {
00021     int64_t usec_;
00022 
00023 protected:
00024     ~DurationBase() { }
00025 
00026     DurationBase()
00027         : usec_(0)
00028     {
00029         StaticAssert<(sizeof(D) == 8)>::check();
00030     }
00031 
00032 public:
00033     static D getInfinite() { return fromUSec(NumericTraits<int64_t>::max()); }
00034 
00035     static D fromUSec(int64_t us)
00036     {
00037         D d;
00038         d.usec_ = us;
00039         return d;
00040     }
00041     static D fromMSec(int64_t ms) { return fromUSec(ms * 1000); }
00042 
00043     int64_t toUSec() const { return usec_; }
00044     int64_t toMSec() const { return usec_ / 1000; }
00045 
00046     D getAbs() const { return D::fromUSec((usec_ < 0) ? (-usec_) : usec_); }
00047 
00048     bool isPositive() const { return usec_ > 0; }
00049     bool isNegative() const { return usec_ < 0; }
00050     bool isZero() const { return usec_ == 0; }
00051 
00052     bool operator==(const D& r) const { return usec_ == r.usec_; }
00053     bool operator!=(const D& r) const { return !operator==(r); }
00054 
00055     bool operator<(const D& r) const { return usec_ < r.usec_; }
00056     bool operator>(const D& r) const { return usec_ > r.usec_; }
00057     bool operator<=(const D& r) const { return usec_ <= r.usec_; }
00058     bool operator>=(const D& r) const { return usec_ >= r.usec_; }
00059 
00060     D operator+(const D& r) const { return fromUSec(usec_ + r.usec_); } // TODO: overflow check
00061     D operator-(const D& r) const { return fromUSec(usec_ - r.usec_); } // ditto
00062 
00063     D operator-() const { return fromUSec(-usec_); }
00064 
00065     D& operator+=(const D& r)
00066     {
00067         *this = *this + r;
00068         return *static_cast<D*>(this);
00069     }
00070     D& operator-=(const D& r)
00071     {
00072         *this = *this - r;
00073         return *static_cast<D*>(this);
00074     }
00075 
00076     template <typename Scale>
00077     D operator*(Scale scale)   const { return fromUSec(usec_ * scale); }
00078 
00079     template <typename Scale>
00080     D& operator*=(Scale scale)
00081     {
00082         *this = *this * scale;
00083         return *static_cast<D*>(this);
00084     }
00085 
00086     static const unsigned StringBufSize = 32;
00087     void toString(char buf[StringBufSize]) const; ///< Prints time in seconds with microsecond resolution
00088 #if UAVCAN_TOSTRING
00089     std::string toString() const;                 ///< Prints time in seconds with microsecond resolution
00090 #endif
00091 };
00092 
00093 
00094 template <typename T, typename D>
00095 class TimeBase
00096 {
00097     uint64_t usec_;
00098 
00099 protected:
00100     ~TimeBase() { }
00101 
00102     TimeBase()
00103         : usec_(0)
00104     {
00105         StaticAssert<(sizeof(T) == 8)>::check();
00106         StaticAssert<(sizeof(D) == 8)>::check();
00107     }
00108 
00109 public:
00110     static T getMax() { return fromUSec(NumericTraits<uint64_t>::max()); }
00111 
00112     static T fromUSec(uint64_t us)
00113     {
00114         T d;
00115         d.usec_ = us;
00116         return d;
00117     }
00118     static T fromMSec(uint64_t ms) { return fromUSec(ms * 1000); }
00119 
00120     uint64_t toUSec() const { return usec_; }
00121     uint64_t toMSec() const { return usec_ / 1000; }
00122 
00123     bool isZero() const { return usec_ == 0; }
00124 
00125     bool operator==(const T& r) const { return usec_ == r.usec_; }
00126     bool operator!=(const T& r) const { return !operator==(r); }
00127 
00128     bool operator<(const T& r) const { return usec_ < r.usec_; }
00129     bool operator>(const T& r) const { return usec_ > r.usec_; }
00130     bool operator<=(const T& r) const { return usec_ <= r.usec_; }
00131     bool operator>=(const T& r) const { return usec_ >= r.usec_; }
00132 
00133     T operator+(const D& r) const
00134     {
00135         if (r.isNegative())
00136         {
00137             if (uint64_t(r.getAbs().toUSec()) > usec_)
00138             {
00139                 return fromUSec(0);
00140             }
00141         }
00142         else
00143         {
00144             if (uint64_t(int64_t(usec_) + r.toUSec()) < usec_)
00145             {
00146                 return fromUSec(NumericTraits<uint64_t>::max());
00147             }
00148         }
00149         return fromUSec(uint64_t(int64_t(usec_) + r.toUSec()));
00150     }
00151 
00152     T operator-(const D& r) const
00153     {
00154         return *static_cast<const T*>(this) + (-r);
00155     }
00156     D operator-(const T& r) const
00157     {
00158         return D::fromUSec((usec_ > r.usec_) ? int64_t(usec_ - r.usec_) : -int64_t(r.usec_ - usec_));
00159     }
00160 
00161     T& operator+=(const D& r)
00162     {
00163         *this = *this + r;
00164         return *static_cast<T*>(this);
00165     }
00166     T& operator-=(const D& r)
00167     {
00168         *this = *this - r;
00169         return *static_cast<T*>(this);
00170     }
00171 
00172     static const unsigned StringBufSize = 32;
00173     void toString(char buf[StringBufSize]) const; ///< Prints time in seconds with microsecond resolution
00174 #if UAVCAN_TOSTRING
00175     std::string toString() const;                 ///< Prints time in seconds with microsecond resolution
00176 #endif
00177 };
00178 
00179 /*
00180  * Monotonic
00181  */
00182 class UAVCAN_EXPORT MonotonicDuration : public DurationBase<MonotonicDuration> { };
00183 
00184 class UAVCAN_EXPORT MonotonicTime : public TimeBase<MonotonicTime, MonotonicDuration> { };
00185 
00186 /*
00187  * UTC
00188  */
00189 class UAVCAN_EXPORT UtcDuration : public DurationBase<UtcDuration> { };
00190 
00191 class UAVCAN_EXPORT UtcTime : public TimeBase<UtcTime, UtcDuration> /// Implicitly convertible to/from uavcan.Timestamp
00192 {
00193 public:
00194     UtcTime() { }
00195 
00196     UtcTime(const Timestamp& ts)  // Implicit
00197     {
00198         operator=(ts);
00199     }
00200 
00201     UtcTime& operator=(const Timestamp& ts)
00202     {
00203         *this = fromUSec(ts.usec);
00204         return *this;
00205     }
00206 
00207     operator Timestamp() const
00208     {
00209         Timestamp ts;
00210         ts.usec = toUSec();
00211         return ts;
00212     }
00213 };
00214 
00215 // ----------------------------------------------------------------------------
00216 
00217 template <typename D>
00218 const unsigned DurationBase<D>::StringBufSize;
00219 
00220 template <typename T, typename D>
00221 const unsigned TimeBase<T, D>::StringBufSize;
00222 
00223 template <typename D>
00224 void DurationBase<D>::toString(char buf[StringBufSize]) const
00225 {
00226     char* ptr = buf;
00227     if (isNegative())
00228     {
00229         *ptr++ = '-';
00230     }
00231     (void)snprintf(ptr, StringBufSize - 1, "%llu.%06lu",
00232                    static_cast<unsigned long long>(getAbs().toUSec() / 1000000L),
00233                    static_cast<unsigned long>(getAbs().toUSec() % 1000000L));
00234 }
00235 
00236 
00237 template <typename T, typename D>
00238 void TimeBase<T, D>::toString(char buf[StringBufSize]) const
00239 {
00240     (void)snprintf(buf, StringBufSize, "%llu.%06lu",
00241                    static_cast<unsigned long long>(toUSec() / 1000000UL),
00242                    static_cast<unsigned long>(toUSec() % 1000000UL));
00243 }
00244 
00245 
00246 #if UAVCAN_TOSTRING
00247 
00248 template <typename D>
00249 std::string DurationBase<D>::toString() const
00250 {
00251     char buf[StringBufSize];
00252     toString(buf);
00253     return std::string(buf);
00254 }
00255 
00256 template <typename T, typename D>
00257 std::string TimeBase<T, D>::toString() const
00258 {
00259     char buf[StringBufSize];
00260     toString(buf);
00261     return std::string(buf);
00262 }
00263 
00264 #endif
00265 
00266 
00267 template <typename Stream, typename D>
00268 UAVCAN_EXPORT
00269 Stream& operator<<(Stream& s, const DurationBase<D>& d)
00270 {
00271     char buf[DurationBase<D>::StringBufSize];
00272     d.toString(buf);
00273     s << buf;
00274     return s;
00275 }
00276 
00277 template <typename Stream, typename T, typename D>
00278 UAVCAN_EXPORT
00279 Stream& operator<<(Stream& s, const TimeBase<T, D>& t)
00280 {
00281     char buf[TimeBase<T, D>::StringBufSize];
00282     t.toString(buf);
00283     s << buf;
00284     return s;
00285 }
00286 
00287 }
00288 
00289 #endif // UAVCAN_TIME_HPP_INCLUDED