compat: replace timegm()
authorRémi Denis-Courmont <remi@remlab.net>
Thu, 10 Dec 2015 20:06:38 +0000 (22:06 +0200)
committerRémi Denis-Courmont <remi@remlab.net>
Thu, 10 Dec 2015 20:06:38 +0000 (22:06 +0200)
compat/timegm.c [new file with mode: 0644]
configure.ac
include/vlc_fixups.h

diff --git a/compat/timegm.c b/compat/timegm.c
new file mode 100644 (file)
index 0000000..68a3030
--- /dev/null
@@ -0,0 +1,72 @@
+/*****************************************************************************
+ * timegm.c: BSD/GNU timegm() replacement
+ *****************************************************************************
+ * Copyright © 2007 Laurent Aimar
+ * Copyright © 2015 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <time.h>
+
+static bool is_leap_year(unsigned y)
+{
+    if (y % 4)
+        return false;
+    if (y % 100)
+        return true;
+    if (y % 400)
+        return false;
+    return true;
+}
+
+time_t timegm(const struct tm *tm)
+{
+    static const unsigned ydays[12 + 1] = {
+        0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+    };
+
+    if (tm->tm_year < 70 /* FIXME: (negative) dates before Epoch */
+     || tm->tm_mon < 0 || tm->tm_mon > 11
+     || tm->tm_mday < 1 || tm->tm_mday > 31
+     || tm->tm_hour < 0 || tm->tm_hour > 23
+     || tm->tm_min < 0 || tm->tm_min > 59
+     || tm->tm_sec < 0 || tm->tm_sec > 60 /* mind the leap second */)
+        return -1;
+
+    /* Count the number of days */
+    unsigned t = 365 * (tm->tm_year - 70)
+                 + ydays[tm->tm_mon] + (tm->tm_mday - 1);
+
+    /* TODO: unroll */
+    for (int i = 70; i < tm->tm_year; i++)
+        t += is_leap_year(1900 + i);
+
+    if (tm->tm_mon > 1)
+        t += is_leap_year(1900 + tm->tm_year);
+
+    t *= 24;
+    t += tm->tm_hour;
+    t *= 60;
+    t += tm->tm_min;
+    t *= 60;
+    t += tm->tm_sec;
+    return t;
+}
index 9105e2b..968f260 100644 (file)
@@ -564,7 +564,7 @@ need_libc=false
 dnl Check for usual libc functions
 AC_CHECK_DECLS([nanosleep],,,[#include <time.h>])
 AC_CHECK_FUNCS([daemon fcntl fstatvfs fork getenv getpwuid_r isatty lstat memalign mkostemp mmap open_memstream openat pread posix_fadvise posix_madvise setlocale stricmp strnicmp strptime uselocale pthread_cond_timedwait_monotonic_np pthread_condattr_setclock])
-AC_REPLACE_FUNCS([atof atoll dirfd fdopendir ffsll flockfile fsync getdelim getpid lldiv nrand48 poll posix_memalign rewind setenv strcasecmp strcasestr strdup strlcpy strndup strnlen strnstr strsep strtof strtok_r strtoll swab tdestroy timespec_get strverscmp])
+AC_REPLACE_FUNCS([atof atoll dirfd fdopendir ffsll flockfile fsync getdelim getpid lldiv nrand48 poll posix_memalign rewind setenv strcasecmp strcasestr strdup strlcpy strndup strnlen strnstr strsep strtof strtok_r strtoll swab tdestroy timegm timespec_get strverscmp])
 AC_CHECK_FUNCS(fdatasync,,
   [AC_DEFINE(fdatasync, fsync, [Alias fdatasync() to fsync() if missing.])
 ])
index 1764e4c..a028df7 100644 (file)
@@ -40,7 +40,8 @@
 # endif
 #endif
 
-#if !defined (HAVE_GMTIME_R) || !defined (HAVE_LOCALTIME_R)
+#if !defined (HAVE_GMTIME_R) || !defined (HAVE_LOCALTIME_R) \
+ || !defined (HAVE_TIMEGM)
 # include <time.h> /* time_t */
 #endif
 
@@ -198,6 +199,10 @@ struct tm *gmtime_r (const time_t *, struct tm *);
 struct tm *localtime_r (const time_t *, struct tm *);
 #endif
 
+#ifndef HAVE_TIMEGM
+time_t timegm(const struct tm *);
+#endif
+
 #ifndef HAVE_TIMESPEC_GET
 #define TIME_UTC 1
 struct timespec;