545 /***********************************************************************/ |
545 /***********************************************************************/ |
546 |
546 |
547 #define MILLISECOND 1 |
547 #define MILLISECOND 1 |
548 #define SECOND 1000 * MILLISECOND |
548 #define SECOND 1000 * MILLISECOND |
549 |
549 |
|
550 #define ULL_MAX std::numeric_limits<unsigned long long>::max() |
|
551 |
|
552 /* unsigned long long -> multiply and add : time_var += interval * multiplier */ |
|
553 /* note: multiplier must be <> 0 due to overflow test */ |
|
554 #define ULL_MUL_ADD(time_var, interval, multiplier, overflow_flag) { \ |
|
555 /* Test overflow on MUL by pre-condition: If (ULL_MAX / a) < b => overflow! */ \ |
|
556 overflow_flag |= ((ULL_MAX / (multiplier)) < GET_CVALUE(uint64, interval)); \ |
|
557 /* Test overflow on ADD by pre-condition: If (ULL_MAX - a) < b => overflow! */ \ |
|
558 overflow_flag |= ((ULL_MAX - (GET_CVALUE(uint64, interval) * multiplier)) < time_var); \ |
|
559 time_var += GET_CVALUE(uint64, interval) * (multiplier); \ |
|
560 } |
|
561 |
|
562 /* long double -> multiply and add : time_var += interval * multiplier */ |
|
563 #define LDB_MUL_ADD(time_var, interval, multiplier) { \ |
|
564 time_var += GET_CVALUE(real64, interval) * (multiplier); \ |
|
565 } |
|
566 |
|
567 |
550 unsigned long long calculate_time(symbol_c *symbol) { |
568 unsigned long long calculate_time(symbol_c *symbol) { |
551 if (NULL == symbol) return 0; |
569 if (NULL == symbol) return 0; |
552 |
570 |
553 interval_c *interval = dynamic_cast<interval_c *>(symbol); |
571 interval_c *interval = dynamic_cast<interval_c *>(symbol); |
554 duration_c *duration = dynamic_cast<duration_c *>(symbol); |
572 duration_c *duration = dynamic_cast<duration_c *>(symbol); |
565 |
583 |
566 if (NULL != interval) { |
584 if (NULL != interval) { |
567 /* SYM_REF5(interval_c, days, hours, minutes, seconds, milliseconds) */ |
585 /* SYM_REF5(interval_c, days, hours, minutes, seconds, milliseconds) */ |
568 unsigned long long int time_ull = 0; |
586 unsigned long long int time_ull = 0; |
569 long double time_ld = 0; |
587 long double time_ld = 0; |
|
588 bool ovflow = false; |
570 |
589 |
571 if (NULL != interval->milliseconds) { |
590 if (NULL != interval->milliseconds) { |
572 if (VALID_CVALUE( int64, interval->milliseconds) && GET_CVALUE( int64, interval->milliseconds) < 0) ERROR; // interval elements should always be positive! |
591 if (VALID_CVALUE( int64, interval->milliseconds) && GET_CVALUE( int64, interval->milliseconds) < 0) ERROR; // interval elements should always be positive! |
573 if (VALID_CVALUE( int64, interval->milliseconds)) time_ull += GET_CVALUE( int64, interval->milliseconds) * MILLISECOND; |
592 if (VALID_CVALUE(uint64, interval->milliseconds)) ULL_MUL_ADD(time_ull, interval->milliseconds, MILLISECOND, ovflow) |
574 else if (VALID_CVALUE(uint64, interval->milliseconds)) time_ull += GET_CVALUE(uint64, interval->milliseconds) * MILLISECOND; |
593 else if (VALID_CVALUE(real64, interval->milliseconds)) LDB_MUL_ADD(time_ld , interval->milliseconds, MILLISECOND) |
575 else if (VALID_CVALUE(real64, interval->milliseconds)) time_ld += GET_CVALUE(real64, interval->milliseconds) * MILLISECOND; |
|
576 else ERROR; // if (NULL != interval->milliseconds) is true, then it must have a valid constant value! |
594 else ERROR; // if (NULL != interval->milliseconds) is true, then it must have a valid constant value! |
577 } |
595 } |
578 |
596 |
579 if (NULL != interval->seconds ) { |
597 if (NULL != interval->seconds ) { |
580 if (VALID_CVALUE( int64, interval->seconds ) && GET_CVALUE( int64, interval->seconds ) < 0) ERROR; // interval elements should always be positive! |
598 if (VALID_CVALUE( int64, interval->seconds ) && GET_CVALUE( int64, interval->seconds ) < 0) ERROR; // interval elements should always be positive! |
581 if (VALID_CVALUE( int64, interval->seconds )) time_ull += GET_CVALUE( int64, interval->seconds ) * SECOND; |
599 if (VALID_CVALUE(uint64, interval->seconds )) ULL_MUL_ADD(time_ull, interval->seconds, SECOND, ovflow) |
582 else if (VALID_CVALUE(uint64, interval->seconds )) time_ull += GET_CVALUE(uint64, interval->seconds ) * SECOND; |
600 else if (VALID_CVALUE(real64, interval->seconds )) LDB_MUL_ADD(time_ld , interval->seconds, SECOND) |
583 else if (VALID_CVALUE(real64, interval->seconds )) time_ld += GET_CVALUE(real64, interval->seconds ) * SECOND; |
|
584 else ERROR; // if (NULL != interval->seconds) is true, then it must have a valid constant value! |
601 else ERROR; // if (NULL != interval->seconds) is true, then it must have a valid constant value! |
585 } |
602 } |
586 |
603 |
587 if (NULL != interval->minutes ) { |
604 if (NULL != interval->minutes ) { |
588 if (VALID_CVALUE( int64, interval->minutes ) && GET_CVALUE( int64, interval->minutes ) < 0) ERROR; // interval elements should always be positive! |
605 if (VALID_CVALUE( int64, interval->minutes ) && GET_CVALUE( int64, interval->minutes ) < 0) ERROR; // interval elements should always be positive! |
589 if (VALID_CVALUE( int64, interval->minutes )) time_ull += GET_CVALUE( int64, interval->minutes ) * SECOND * 60; |
606 if (VALID_CVALUE(uint64, interval->minutes )) ULL_MUL_ADD(time_ull, interval->minutes, SECOND * 60, ovflow) |
590 else if (VALID_CVALUE(uint64, interval->minutes )) time_ull += GET_CVALUE(uint64, interval->minutes ) * SECOND * 60; |
607 else if (VALID_CVALUE(real64, interval->minutes )) LDB_MUL_ADD(time_ld , interval->minutes, SECOND * 60) |
591 else if (VALID_CVALUE(real64, interval->minutes )) time_ld += GET_CVALUE(real64, interval->minutes ) * SECOND * 60; |
|
592 else ERROR; // if (NULL != interval->minutes) is true, then it must have a valid constant value! |
608 else ERROR; // if (NULL != interval->minutes) is true, then it must have a valid constant value! |
593 } |
609 } |
594 |
610 |
595 if (NULL != interval->hours ) { |
611 if (NULL != interval->hours ) { |
596 if (VALID_CVALUE( int64, interval->hours ) && GET_CVALUE( int64, interval->hours ) < 0) ERROR; // interval elements should always be positive! |
612 if (VALID_CVALUE( int64, interval->hours ) && GET_CVALUE( int64, interval->hours ) < 0) ERROR; // interval elements should always be positive! |
597 if (VALID_CVALUE( int64, interval->hours )) time_ull += GET_CVALUE( int64, interval->hours ) * SECOND * 60 * 60; |
613 if (VALID_CVALUE(uint64, interval->hours )) ULL_MUL_ADD(time_ull, interval->hours, SECOND * 60 * 60, ovflow) |
598 else if (VALID_CVALUE(uint64, interval->hours )) time_ull += GET_CVALUE(uint64, interval->hours ) * SECOND * 60 * 60; |
614 else if (VALID_CVALUE(real64, interval->hours )) LDB_MUL_ADD(time_ld , interval->hours, SECOND * 60 * 60) |
599 else if (VALID_CVALUE(real64, interval->hours )) time_ld += GET_CVALUE(real64, interval->hours ) * SECOND * 60 * 60; |
|
600 else ERROR; // if (NULL != interval->hours) is true, then it must have a valid constant value! |
615 else ERROR; // if (NULL != interval->hours) is true, then it must have a valid constant value! |
601 } |
616 } |
602 |
617 |
603 if (NULL != interval->days ) { |
618 if (NULL != interval->days ) { |
604 if (VALID_CVALUE( int64, interval->days ) && GET_CVALUE( int64, interval->days ) < 0) ERROR; // interval elements should always be positive! |
619 if (VALID_CVALUE( int64, interval->days ) && GET_CVALUE( int64, interval->days ) < 0) ERROR; // interval elements should always be positive! |
605 if (VALID_CVALUE( int64, interval->days )) time_ull += GET_CVALUE( int64, interval->days ) * SECOND * 60 * 60 * 24; |
620 if (VALID_CVALUE(uint64, interval->days )) ULL_MUL_ADD(time_ull, interval->days, SECOND * 60 * 60 * 24, ovflow) |
606 else if (VALID_CVALUE(uint64, interval->days )) time_ull += GET_CVALUE(uint64, interval->days ) * SECOND * 60 * 60 * 24; |
621 else if (VALID_CVALUE(real64, interval->days )) LDB_MUL_ADD(time_ld , interval->days, SECOND * 60 * 60 * 24) |
607 else if (VALID_CVALUE(real64, interval->days )) time_ld += GET_CVALUE(real64, interval->days ) * SECOND * 60 * 60 * 24; |
|
608 else ERROR; // if (NULL != interval->days) is true, then it must have a valid constant value! |
622 else ERROR; // if (NULL != interval->days) is true, then it must have a valid constant value! |
609 } |
623 } |
610 |
624 |
|
625 /* Test overflow on ADD by pre-condition: If (ULL_MAX - a) < b => overflow! */ |
|
626 ovflow |= ((ULL_MAX - time_ull) < (unsigned long long)time_ld); |
611 time_ull += time_ld; |
627 time_ull += time_ld; |
|
628 |
|
629 if (ovflow) |
|
630 STAGE4_ERROR(symbol, symbol, "Internal overflow calculating task interval (must be <= 49 days)."); |
|
631 |
612 return time_ull; |
632 return time_ull; |
613 }; |
633 }; |
614 ERROR; // should never reach this point! |
634 ERROR; // should never reach this point! |
615 return 0; // humour the compiler! |
635 return 0; // humour the compiler! |
616 } |
636 } |