/** try to parse a time specification in seconds or fractional seconds. * The value is interpreted relative to the origin of a the given time grid * This parser recognises full seconds, fractional seconds and both together. * In any case, the actual number is required to end with a trailing \c 'sec' * @par Example specifications \verbatim 12sec --> 12 * TimeValue::SCALE -4sec --> -4 * TimeValue::SCALE 5/4sec --> 1.25 * TimeValue::SCALE -5/25sec --> -0.2 * TimeValue::SCALE 1+1/2sec --> 1.5 * TimeValue::SCALE 1-1/25sec --> 0.96 * TimeValue::SCALE -12-1/4sec --> -11.75 * TimeValue::SCALE \endverbatim * @param seconds string containing a time spec in seconds * @param grid coordinate system the parsed value is based on * @return the corresponding (opaque internal) lumiera time value * @throw error::Invalid in case of parsing failure * @note the string may contain any additional content, as long as a * regular-expression search is able to pick out a suitable value */ TimeValue Seconds::parse (string const& seconds, QuantR grid) { static regex fracSecs_parser ("(?<![\\./\\-\\d])(-?\\d+)(?:([\\-\\+]\\d+)?/(\\d+))?sec"); //__no leading[./-\d] number [+-] number '/' number 'sec' #define SUB_EXPR(N) lexical_cast<long> (match[N]) smatch match; if (regex_search (seconds, match, fracSecs_parser)) if (match[2].matched) { // complete spec with all parts FSecs fractionalPart (SUB_EXPR(2), SUB_EXPR(3)); long fullSeconds (SUB_EXPR(1)); return grid.timeOf (fullSeconds + fractionalPart); } else if (match[3].matched) { // only a fractional part was given return grid.timeOf (FSecs (SUB_EXPR(1), SUB_EXPR(3))); } else { // just simple non-fractional seconds return grid.timeOf (FSecs (SUB_EXPR(1))); } else throw error::Invalid ("unable to parse \""+seconds+"\" as (fractional)seconds" , LERR_(INVALID_TIMECODE)); }
void coverQuantisationCornerCases() { // origin at lower end of the time range FixedFrameQuantiser case1 (1, Time::MIN); CHECK (secs(0) == case1.gridAlign(Time::MIN )); CHECK (secs(0) == case1.gridAlign(Time::MIN +TimeValue(1) )); CHECK (secs(1) == case1.gridAlign(Time::MIN +secs(1) )); CHECK (Time::MAX -secs(1) > case1.gridAlign( secs(-1) )); CHECK (Time::MAX -secs(1) <= case1.gridAlign( secs (0) )); CHECK (Time::MAX > case1.gridAlign( secs (0) )); CHECK (Time::MAX == case1.gridAlign( secs(+1) )); CHECK (Time::MAX == case1.gridAlign( secs(+2) )); // origin at upper end of the time range FixedFrameQuantiser case2 (1, Time::MAX); CHECK (secs( 0) == case2.gridAlign(Time::MAX )); CHECK (secs(-1) == case2.gridAlign(Time::MAX -TimeValue(1) )); // note: next lower frame CHECK (secs(-1) == case2.gridAlign(Time::MAX -secs(1) )); // i.e. the same as a whole frame down CHECK (Time::MIN +secs(1) < case2.gridAlign( secs(+2) )); CHECK (Time::MIN +secs(1) >= case2.gridAlign( secs(+1) )); CHECK (Time::MIN < case2.gridAlign( secs(+1) )); CHECK (Time::MIN == case2.gridAlign( secs( 0) )); // note: because of downward truncating, CHECK (Time::MIN == case2.gridAlign( secs(-1) )); // resulting values will already exceed CHECK (Time::MIN == case2.gridAlign( secs(-2) )); // allowed range and thus will be clipped // maximum frame size is half the time range Duration hugeFrame(Time::MAX); FixedFrameQuantiser case3 (hugeFrame); CHECK (Time::MIN == case3.gridAlign(Time::MIN )); CHECK (Time::MIN == case3.gridAlign(Time::MIN +TimeValue(1) )); CHECK (Time::MIN == case3.gridAlign( secs(-1) )); CHECK (TimeValue(0) == case3.gridAlign( secs( 0) )); CHECK (TimeValue(0) == case3.gridAlign( secs(+1) )); CHECK (TimeValue(0) == case3.gridAlign(Time::MAX -TimeValue(1) )); CHECK (Time::MAX == case3.gridAlign(Time::MAX )); // now displacing this grid by +1sec.... FixedFrameQuantiser case4 (hugeFrame, secs(1)); CHECK (Time::MIN == case4.gridAlign(Time::MIN )); CHECK (Time::MIN == case4.gridAlign(Time::MIN +TimeValue(1) )); // clipped... CHECK (Time::MIN == case4.gridAlign(Time::MIN +secs(1) )); // but now exact (unclipped) CHECK (Time::MIN == case4.gridAlign( secs(-1) )); CHECK (Time::MIN == case4.gridAlign( secs( 0) )); CHECK (TimeValue(0) == case4.gridAlign( secs(+1) )); //.....now exactly the frame number zero CHECK (TimeValue(0) == case4.gridAlign(Time::MAX -TimeValue(1) )); CHECK (TimeValue(0) == case4.gridAlign(Time::MAX )); //.......still truncated down to frame #0 // larger frames aren't possible Duration not_really_larger(secs(10000) + hugeFrame); CHECK (hugeFrame == not_really_larger); // frame sizes below the time micro grid get trapped long subAtomic = 2*GAVL_TIME_SCALE; // too small for this universe... VERIFY_ERROR (BOTTOM_VALUE, FixedFrameQuantiser quark(subAtomic) ); VERIFY_ERROR (BOTTOM_VALUE, FixedFrameQuantiser quark(Duration (FSecs (1,subAtomic))) ); }
Clip::Clip() : timeCoord_(Time(FSecs(1)), FSecs(3)) { }