libuav original
Dependents: UAVCAN UAVCAN_Subscriber
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
Generated on Tue Jul 12 2022 17:17:35 by 1.7.2