From 75048390f3d5fc49f6c8f1c64c6312ed93d70773 Mon Sep 17 00:00:00 2001 From: Florian Prill <florian.prill@dwd.de> Date: Fri, 21 Jun 2019 20:47:58 +0200 Subject: [PATCH] Implemented gettriggernextevent for hl interface (untested). --- include/mtime_eventHandling.h | 15 +++++++ src/libmtime_hl.f90 | 2 +- src/mtime_c_bindings.f90 | 17 +++++++- src/mtime_eventHandling.c | 78 ++++++++++++++++++++++------------- src/mtime_t_datetime.inc | 1 - src/mtime_t_event.inc | 61 ++++++++++++++++++++++++--- src/mtime_t_timedelta.inc | 4 +- 7 files changed, 139 insertions(+), 39 deletions(-) diff --git a/include/mtime_eventHandling.h b/include/mtime_eventHandling.h index 21cfbbd0..393922df 100644 --- a/include/mtime_eventHandling.h +++ b/include/mtime_eventHandling.h @@ -153,6 +153,21 @@ iseventNextInNextYearRaw(struct _datetime* event_triggerNextEventDateTime, char* eventToString(struct _event* e, char* string); +void +getTriggerNextEventAtDateTimeRaw(struct _datetime* eventLastDateTime, + bool nextEventIsFirst, + struct _datetime* triggerNextEventDateTime, + struct _timedelta* eventInterval, + struct _datetime* current_dt, + struct _datetime* dt_return); + +struct _datetime* +getTriggerNextEventAtDateTime(struct _datetime* eventLastDateTime, + bool nextEventIsFirst, + struct _datetime* triggerNextEventDateTime, + struct _timedelta* eventInterval, + struct _datetime* current_dt); + struct _datetime* getTriggerNextEventAtDateTime(struct _event* e, struct _datetime* dt_current, struct _datetime* dt_return); diff --git a/src/libmtime_hl.f90 b/src/libmtime_hl.f90 index 6b40c518..4eb857c2 100644 --- a/src/libmtime_hl.f90 +++ b/src/libmtime_hl.f90 @@ -59,7 +59,7 @@ MODULE mtime_hl ! TODO: simply repeat the implementation of "divisionquotienttimespan" in order to disentangle the mtime_hl and the mtime Fortran modules. ! PUBLIC :: divisionquotienttimespan - + PUBLIC :: no_of_sec_in_a_day !> NOTE / TODO: diff --git a/src/mtime_c_bindings.f90 b/src/mtime_c_bindings.f90 index eb5cd831..ffb102b2 100644 --- a/src/mtime_c_bindings.f90 +++ b/src/mtime_c_bindings.f90 @@ -652,6 +652,22 @@ MODULE mtime_c_bindings logical(c_bool) :: ret end function my_iseventnextinnextyear ! + SUBROUTINE my_gettriggernexteventatdatetimeraw(eventLastDateTime, & + & nextEventIsFirst, & + & triggerNextEventDateTime, & + & eventInterval, & + & my_currentdatetime, & + & c_pointer) & + & BIND(c, name='getTriggerNextEventAtDateTimeRaw') + IMPORT :: c_ptr, c_bool + TYPE(c_ptr), VALUE :: eventLastDateTime + LOGICAL(c_bool) :: nextEventIsFirst + TYPE(c_ptr), VALUE :: triggerNextEventDateTime + TYPE(c_ptr), VALUE :: eventInterval + TYPE(c_ptr), VALUE :: my_currentdatetime + TYPE(c_ptr) :: c_pointer + END SUBROUTINE my_gettriggernexteventatdatetimeraw + ! function my_gettriggernexteventatdatetime(my_event,my_currentdatetime,my_datetime) result(c_pointer) & & bind(c, name='getTriggerNextEventAtDateTime') import :: c_ptr @@ -809,7 +825,6 @@ contains integer, intent(IN) :: lineno character(LEN=*), intent(IN) :: routine_str - character(len=max_mtime_error_str_len) :: error_str if (lcond) call handle_errno_base(errno, routine_str, lineno) end subroutine handle_errno_cond diff --git a/src/mtime_eventHandling.c b/src/mtime_eventHandling.c index c21f7f09..91651295 100644 --- a/src/mtime_eventHandling.c +++ b/src/mtime_eventHandling.c @@ -1511,53 +1511,75 @@ getEventFirstTriggerDateTime(struct _datetime* start_dt, struct _timedelta* time } -/** - * @brief Get the Datetime when 'this' event will be triggered next. - * - * WARNING: The value returned is with-respect-to current_dt and not a true copy of triggerNextEventDateTime in the event data structure. - * - * @param e - * A pointer to struct _event. This is the event being queried. - * - * @param dt_return - * A pointer to struct _datetime. The next trigger datetime is copied here. - * - * @return dt_return - * A pointer to DateTime with next-trigger datetime. - */ - -struct _datetime* -getTriggerNextEventAtDateTime(struct _event* e, struct _datetime* current_dt, struct _datetime* dt_return) +void +getTriggerNextEventAtDateTimeRaw(struct _datetime* eventLastDateTime, + bool nextEventIsFirst, + struct _datetime* triggerNextEventDateTime, + struct _timedelta* eventInterval, + struct _datetime* current_dt, + struct _datetime* dt_return) { - if ((e != NULL) && (current_dt != NULL) && (dt_return != NULL)) + dt_return = NULL; + if ((eventLastDateTime != NULL) && + (triggerNextEventDateTime != NULL) && + (eventInterval != NULL) && + (current_dt != NULL) && + (dt_return != NULL)) { /* If last date is defined, check if current_dt is ahead of event->eventLastDateTime. Return on NULL indicating no future trigger event scheduled.*/ - if (e->eventLastDateTime && (compareDatetime(current_dt,e->eventLastDateTime) == greater_than)) - return NULL; + if (eventLastDateTime && (compareDatetime(current_dt,eventLastDateTime) == greater_than)) + { + dt_return = NULL; + return; + } /* This if should evaluate to false normally. The only occasion when it does not is if the current_dt > triggerNextEventDateTime and isCurrentEventActive(.) has never been called */ if ( - (e->nextEventIsFirst) + (nextEventIsFirst) && - (compareDatetime(current_dt,e->triggerNextEventDateTime) == greater_than) + (compareDatetime(current_dt,triggerNextEventDateTime) == greater_than) ) { struct _timedelta* modulo_td = newTimeDelta("PT00.000S"); // Get the first trigger time and return (WARNING: Do not update e->triggerNextEventDateTime here!). - moduloTimeDeltaFromDateTime(e->triggerNextEventDateTime, e->eventInterval, current_dt, modulo_td); + moduloTimeDeltaFromDateTime(triggerNextEventDateTime, eventInterval, current_dt, modulo_td); addTimeDeltaToDateTime(current_dt,modulo_td,dt_return); // Cleanup. deallocateTimeDelta(modulo_td); - return dt_return; + return; } // else ... - dt_return = replaceDatetime(e->triggerNextEventDateTime, dt_return); - return dt_return; + dt_return = replaceDatetime(triggerNextEventDateTime, dt_return); } - else - return NULL; +} + + +/** + * @brief Get the Datetime when 'this' event will be triggered next. + * + * WARNING: The value returned is with-respect-to current_dt and not a true copy of triggerNextEventDateTime in the event data structure. + * + * @param e + * A pointer to struct _event. This is the event being queried. + * + * @param dt_return + * A pointer to struct _datetime. The next trigger datetime is copied here. + * + * @return dt_return + * A pointer to DateTime with next-trigger datetime. + */ +struct _datetime* +getTriggerNextEventAtDateTime(struct _event* e, struct _datetime* current_dt, struct _datetime* dt_return) +{ + if ((e == NULL) || (current_dt == NULL) || (dt_return == NULL)) return NULL; + + getTriggerNextEventAtDateTimeRaw(e->eventLastDateTime, + e->nextEventIsFirst, + e->triggerNextEventDateTime, + e->eventInterval, current_dt, + dt_return); } /** diff --git a/src/mtime_t_datetime.inc b/src/mtime_t_datetime.inc index 5f1ad0aa..49e1e8d6 100644 --- a/src/mtime_t_datetime.inc +++ b/src/mtime_t_datetime.inc @@ -9,7 +9,6 @@ CHARACTER(len=*), INTENT(in) :: dt_string TYPE(c_ptr) :: c_pointer TYPE(datetime), POINTER :: dt_tmp - INTEGER :: errno c_pointer = my_newdatetime(TRIM(ADJUSTL(dt_string))//c_null_char) CALL handle_errno(.NOT. c_ASSOCIATED(c_pointer), 4 *100 + 1, __FILE__, __LINE__) CALL c_f_pointer(c_pointer, dt_tmp) diff --git a/src/mtime_t_event.inc b/src/mtime_t_event.inc index b36a406a..521b32f9 100644 --- a/src/mtime_t_event.inc +++ b/src/mtime_t_event.inc @@ -151,17 +151,68 @@ res = this%eventLastDateTime END FUNCTION t_event_getLastDatetime - FUNCTION t_event_getNextOccurrenceDatetime(this, my_currentdatetime) RESULT(res) + FUNCTION t_event_getNextOccurrenceDatetime(this, query_start_dt) RESULT(res) TYPE(t_datetime) :: res CLASS(t_event) :: this - TYPE(t_datetime), INTENT(IN) :: my_currentdatetime - res = this%triggerNextEventDateTime + TYPE(t_datetime), INTENT(IN), OPTIONAL :: query_start_dt + ! + TYPE(datetime), POINTER :: dt_tmp + TYPE(c_ptr) :: tmp_dt, tmp_evLastDateTime, tmp_evInterval + TYPE(c_ptr) :: event_triggerNextEventDateTime, c_pointer1 + LOGICAL(c_bool) :: event_nextEventIsFirst + + IF (PRESENT(query_start_dt)) THEN + ! if a start for our query is given, invoke + ! "my_gettriggernexteventatdatetime": + + ! --- copy-in: + + c_pointer1 = res%get_c_pointer() + tmp_dt = query_start_dt%get_c_pointer() + tmp_evLastDateTime = this%eventLastDateTime%get_c_pointer() + tmp_evInterval = this%eventInterval%get_c_pointer() + event_nextEventIsFirst = this%nextEventIsFirst + event_triggerNextEventDateTime = c_null_ptr + IF (ASSOCIATED(this%triggerNextEventDateTime )) & + & event_triggerNextEventDateTime = this%triggerNextEventDateTime%get_c_pointer() + + ! --- call C routine: + + CALL my_gettriggernexteventatdatetimeraw( & + & tmp_evLastDateTime, event_nextEventIsFirst, & + & event_triggerNextEventDateTime, tmp_evInterval, & + & tmp_dt, c_pointer1) + + ! --- copy-out: + + CALL C_F_POINTER(c_pointer1, dt_tmp) + res%dt = dt_tmp + + IF (C_ASSOCIATED(event_triggerNextEventDateTime)) THEN + IF (.NOT. ASSOCIATED(this%triggerNextEventDateTime)) ALLOCATE(this%triggerNextEventDateTime) + CALL C_F_POINTER(event_triggerNextEventDateTime, dt_tmp) + this%triggerNextEventDateTime%dt = dt_tmp + END IF + + ! --- clean up: + + CALL my_deallocatedatetime(tmp_dt) + IF (C_ASSOCIATED(tmp_evLastDateTime)) CALL my_deallocatedatetime(tmp_evLastDateTime) + IF (C_ASSOCIATED(tmp_evInterval)) CALL my_deallocatetimedelta(tmp_evInterval) + + IF (C_ASSOCIATED(event_triggerNextEventDateTime )) & + & CALL my_deallocatedatetime(event_triggerNextEventDateTime ) + + CALL my_deallocatedatetime(c_pointer1) + + ELSE + res = this%triggerNextEventDateTime + END IF END FUNCTION t_event_getNextOccurrenceDatetime - FUNCTION t_event_getPrevOccurrenceDatetime(this, my_currentdatetime) RESULT(res) + FUNCTION t_event_getPrevOccurrenceDatetime(this) RESULT(res) TYPE(t_datetime) :: res CLASS(t_event) :: this - TYPE(t_datetime), INTENT(IN) :: my_currentdatetime res = this%triggeredPreviousEventDateTime END FUNCTION t_event_getPrevOccurrenceDatetime diff --git a/src/mtime_t_timedelta.inc b/src/mtime_t_timedelta.inc index b348412f..f1f1ec4c 100644 --- a/src/mtime_t_timedelta.inc +++ b/src/mtime_t_timedelta.inc @@ -151,8 +151,7 @@ TYPE(t_timedelta), TARGET :: scaled_td INTEGER(c_int32_t), INTENT(in) :: lambda CLASS(t_timedelta), TARGET, INTENT(in) :: this - TYPE(timedelta), POINTER :: td_tmp - TYPE(c_ptr) :: c_pointer, dummy_ptr, c_ptr_result + TYPE(c_ptr) :: dummy_ptr ! cast into real since in mtime int implementation scalar ! multiplication can not give a value in excess of 24 hours @@ -222,7 +221,6 @@ TYPE(t_timedelta), INTENT(in), target :: divisor TYPE(t_datetime), INTENT(IN), target :: referenceDateTime TYPE(divisionquotienttimespan), target :: quotient - TYPE(t_datetime), target :: dt_tmp type(c_ptr) :: dummy_ptr dummy_ptr = my_divideTimeDelta(c_loc(this%td), c_loc(divisor%td), & -- GitLab