diff --git a/src/lib/time/lumitime.cpp b/src/lib/time/lumitime.cpp index d2daba3c2..15444a60c 100644 --- a/src/lib/time/lumitime.cpp +++ b/src/lib/time/lumitime.cpp @@ -50,8 +50,9 @@ namespace time { } - const Time Time::MAX ( TimeValue (+std::numeric_limits::max()) ); - const Time Time::MIN ( TimeValue (-std::numeric_limits::max()) ); + /** @note the allowed time range is explicitly limited to help overflow protection */ + const Time Time::MAX ( TimeValue::buildRaw_(+std::numeric_limits::max() / 30) ); + const Time Time::MIN ( TimeValue::buildRaw_(-_raw(Time::MAX) ) ); /** convenience constructor to build an @@ -100,6 +101,15 @@ namespace time { } + /** @internal backdoor to sneak in a raw time value + * bypassing any normalisation and limiting */ + TimeValue + TimeValue::buildRaw_ (gavl_time_t raw) + { + return reinterpret_cast (raw); + } + + }} // namespace lib::Time diff --git a/src/lib/time/timevalue.hpp b/src/lib/time/timevalue.hpp index a19c806be..94b51d209 100644 --- a/src/lib/time/timevalue.hpp +++ b/src/lib/time/timevalue.hpp @@ -71,9 +71,13 @@ namespace time { } public: + /** explicit limit of allowed time range */ + static gavl_time_t limited (gavl_time_t raw); + + explicit TimeValue (gavl_time_t val=0) - : t_(val) + : t_(limited (val)) { } /** copy initialisation allowed */ @@ -83,6 +87,7 @@ namespace time { /** @internal to pass Time values to C functions */ friend gavl_time_t _raw (TimeValue const& time) { return time.t_; } + static TimeValue buildRaw_(gavl_time_t); // Supporting totally_ordered friend bool operator< (TimeValue const& t1, TimeValue const& t2) { return t1.t_ < t2.t_; } @@ -306,5 +311,25 @@ namespace time { }; + + + /* == implementations == */ + + /** @internal applies a limiter on the provided + * raw time value to keep it within the arbitrary + * boundaries defined by (Time::MAX, Time::MIN). + * While Time entities are \c not a "safeInt" + * implementation, we limit new values and + * establish this safety margin to prevent + * wrap-around during time quantisation */ + inline gavl_time_t + TimeValue::limited (gavl_time_t raw) + { + return raw > Time::MAX? Time::MAX.t_ + : raw < Time::MIN? Time::MIN.t_ + : raw; + } + + }} // lib::time #endif diff --git a/src/tool/try.cpp b/src/tool/try.cpp index 16716ccae..ef05aaa97 100644 --- a/src/tool/try.cpp +++ b/src/tool/try.cpp @@ -60,7 +60,7 @@ main (int, char**) int64_t muks = std::numeric_limits::max(); - muks -= 5; + muks /= 30; double murks(muks); cout << format("%f // %f || %g \n") % muks % murks % std::numeric_limits::epsilon(); diff --git a/wiki/renderengine.html b/wiki/renderengine.html index ed5b6a57c..550b53eaa 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -4192,7 +4192,7 @@ Viewed as a micro program, the processing patterns are ''weak typed'' &mdash
a given Render Engine configuration is a list of Processors. Each Processor in turn contains a Graph of ProcNode.s to do the acutal data processing. In order to cary out any calculations, the Processor needs to be called with a StateProxy containing the state information for this RenderProcess
 
-
+
The Quantiser implementation works by determining the grid interval containing a given raw time.
 These grid intervals are denoted by ordinal numbers (frame numbers), with interval #0 starting at the grid's origin and negative ordinals allowed.
 
@@ -4241,6 +4241,10 @@ There is an existing [[SafeInt class by David LeBlanc|http://safeint.codeplex.co
 ;ignore the problem
 :again, because of the huge time range, the problem could generally be deemed irrelevant
 :we could apply a limiter to enforce a reduced time range just in the quantisation and evaluation of timecodes
+
+A combination of the last approaches seems to be most appropriate here:
+Limit the officially allowed time range and perform simple checks when quantising a time value and when applying a scale factor.
+We limit {{{Time::MAX}}} by factor 1/30 and define the minimum //symmetrically to this.// This still leaves us with ''±9700 years allowed timerange''.