Beispiel #1
0
/* Use CONVERT to convert *T to a broken down time in *TP.
   If *T is out of range for conversion, adjust it so that
   it is the nearest in-range value and then convert that.  */
static struct tm *
ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
		time_t *t, struct tm *tp)
{
  struct tm *r = convert (t, tp);

  if (!r && *t)
    {
      time_t bad = *t;
      time_t ok = 0;

      /* BAD is a known unconvertible time_t, and OK is a known good one.
	 Use binary search to narrow the range between BAD and OK until
	 they differ by 1.  */
      while (bad != (ok + ((bad < 0) ? -1 : 1)))
	{
	  time_t mid = *t = time_t_avg(ok, bad);
	  r = convert(t, tp);
	  if (r)
	    ok = mid;
	  else
	    bad = mid;
	}

      if (!r && ok)
	{
	  /* The last conversion attempt failed;
	     revert to the most recent successful attempt.  */
	  *t = ok;
	  r = convert(t, tp);
	}
    }

  return r;
}
Beispiel #2
0
/* Return 1 if A + B does not overflow.  If time_t is unsigned and if
   B's top bit is set, assume that the sum represents A - -B, and
   return 1 if the subtraction does not wrap around.  */
static int
time_t_add_ok(time_t a, time_t b)
{
  if (! TYPE_SIGNED(time_t))
    {
      time_t sum = (a + b);
      return ((sum < a) == (TIME_T_MIDPOINT <= b));
    }
  else if (WRAPV)
    {
      time_t sum = (a + b);
      return ((sum < a) == (b < 0));
    }
  else
    {
      time_t avg = time_t_avg(a, b);
      return (((TIME_T_MIN / 2) <= avg) && (avg <= (TIME_T_MAX / 2)));
    }
}
Beispiel #3
0
/* Return 1 if A + B does not overflow.  If time_t is unsigned and if
   B's top bit is set, assume that the sum represents A - -B, and
   return 1 if the subtraction does not wrap around.  */
static int
time_t_add_ok (time_t a, time_t b)
{
  if (! TYPE_SIGNED (time_t))
    {
      time_t sum = a + b;
      return (sum < a) == (TIME_T_MIDPOINT <= b);
    }
  else if (WRAPV)
    {
      time_t sum = a + b;
      return (sum < a) == (b < 0);
    }
  else
    {
      time_t avg = time_t_avg (a, b);
      return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
    }
}