From 8e8e451046e8643fbf58d8c8534577b602f06fc9 Mon Sep 17 00:00:00 2001
From: Florian Prill <florian.prill@dwd.de>
Date: Wed, 15 May 2019 17:01:39 +0200
Subject: [PATCH] timedelta divide: no negative divisor allowed; restructured
 return code.

---
 src/mtime_timedelta.c | 99 +++++++++++++++++++++++--------------------
 1 file changed, 53 insertions(+), 46 deletions(-)

diff --git a/src/mtime_timedelta.c b/src/mtime_timedelta.c
index 98d24363..019d572c 100644
--- a/src/mtime_timedelta.c
+++ b/src/mtime_timedelta.c
@@ -1177,63 +1177,70 @@ struct _divisionquotienttimespan*
 divideTimeDelta(struct _timedelta* dividend, struct _timedelta* divisor,
 		struct _datetime* base_dt, struct _divisionquotienttimespan* quo_ret)
 {
-  if ((dividend == NULL) || (divisor == NULL) || (quo_ret == NULL))  return NULL;
+  struct _divisionquotienttimespan* ret = quo_ret;
+  struct _juliandelta *jd_dividend = NULL, *jd_divisor = NULL;
+
+  if ((dividend == NULL) || (divisor == NULL) || (quo_ret == NULL))  ret = NULL;
 
   /* convert dividend and divisor into _juliandelta data type. */
-  struct _juliandelta* jd_dividend = newJulianDelta('+', 0, 0);
-  if ( jd_dividend == NULL ) return NULL;
-  jd_dividend = timeDeltaToJulianDelta(dividend, base_dt, jd_dividend);
-  if ( jd_dividend == NULL )
-    {
-      deallocateJulianDelta(jd_dividend);
-      return NULL;
+  if (ret != NULL) {
+    jd_dividend = newJulianDelta('+', 0, 0);
+    if ( jd_dividend == NULL )
+      ret = NULL;
+    else {
+      jd_dividend = timeDeltaToJulianDelta(dividend, base_dt, jd_dividend);
+      if ( jd_dividend == NULL )  ret = NULL;
     }
+  }
 
-  struct _juliandelta* jd_divisor = newJulianDelta('+', 0, 0);
-  if ( jd_divisor == NULL ) return NULL;
-  jd_divisor = timeDeltaToJulianDelta(divisor, base_dt, jd_divisor);
-  if ( jd_divisor == NULL )
-    {
-      deallocateJulianDelta(jd_divisor);
-      return NULL;
+  if (ret != NULL) {
+    jd_divisor = newJulianDelta('+', 0, 0);
+    if ( jd_divisor == NULL )
+      ret = NULL;
+    else {
+      jd_divisor = timeDeltaToJulianDelta(divisor, base_dt, jd_divisor);
+      if (( jd_divisor == NULL )  || ( jd_divisor->sign == '-' )) ret = NULL;
     }
-
-  /* perform large integer division. */
-  t_int days1, day_fraction1, days2, day_fraction2;
-  t_int q_decimal  = 0, remainder_days  = 0, remainder_ms  = 0;
-
-  days1           = (t_int) jd_dividend->day;
-  day_fraction1   = (t_int) jd_dividend->ms;
-  days2           = (t_int) jd_divisor->day;
-  day_fraction2   = (t_int) jd_divisor->ms;
-
-  int ret = divide_timespan(days1, day_fraction1, days2, day_fraction2,
-			    &q_decimal, &remainder_days, &remainder_ms);
-
-  quo_ret->quotient        = (int64_t) 0;
-  quo_ret->remainder_days  = (int64_t) 0;
-  quo_ret->remainder_in_ms = (int64_t) 0;
-  if (ret == 0) {
-    quo_ret->quotient        = (int64_t) q_decimal;
-    quo_ret->remainder_days  = (int64_t) remainder_days;
-    quo_ret->remainder_in_ms = (int64_t) remainder_ms;
   }
 
-  /* correct sign. */
-
- /* TODO: maybe we should better remove negative time span division. Is it well-defined? */
-  if (jd_dividend->sign != jd_divisor->sign) {
-    quo_ret->quotient        *= -1;
-    quo_ret->remainder_days  *= -1;
-    quo_ret->remainder_in_ms *= -1;
+  if (ret != NULL) {
+    /* perform large integer division. */
+    t_int days1, day_fraction1, days2, day_fraction2;
+    t_int q_decimal  = 0, remainder_days  = 0, remainder_ms  = 0;
+
+    days1           = (t_int) jd_dividend->day;
+    day_fraction1   = (t_int) jd_dividend->ms;
+    days2           = (t_int) jd_divisor->day;
+    day_fraction2   = (t_int) jd_divisor->ms;
+
+    int iret = divide_timespan(days1, day_fraction1, days2, day_fraction2,
+			       &q_decimal, &remainder_days, &remainder_ms);
+
+    quo_ret->quotient        = (int64_t) 0;
+    quo_ret->remainder_days  = (int64_t) 0;
+    quo_ret->remainder_in_ms = (int64_t) 0;
+    if (iret != 0)
+      ret = NULL;
+    else {
+      quo_ret->quotient        = (int64_t) q_decimal;
+      quo_ret->remainder_days  = (int64_t) remainder_days;
+      quo_ret->remainder_in_ms = (int64_t) remainder_ms;
+    }
   }
 
-  deallocateJulianDelta(jd_dividend);
-  deallocateJulianDelta(jd_divisor);
+  if (ret != NULL) {
+    if ( jd_dividend->sign == '-' ) {
+      /* correct sign. */
+      quo_ret->quotient        *= -1;
+      quo_ret->remainder_days  *= -1;
+      quo_ret->remainder_in_ms *= -1;
+    }
+  }
 
-  if (ret != 0)  return NULL;
+  if (jd_dividend != NULL)  deallocateJulianDelta(jd_dividend);
+  if (jd_divisor  != NULL)  deallocateJulianDelta(jd_divisor);
 
-  return (quo_ret);
+  return ret;
 }
 
 
-- 
GitLab