]> code.delx.au - pulseaudio/blobdiff - src/pulse/timeval.c
i18n: Update Russian translation
[pulseaudio] / src / pulse / timeval.c
index 180e0159eb600e40c685b2f590deafff72c38737..a394dbea0a629ae54b86687642b5a6c4648bfe88 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id$ */
-
 /***
   This file is part of PulseAudio.
 
 #include <windows.h>
 #endif
 
-#include <pulsecore/winsock.h>
 #include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
 
 #include "timeval.h"
 
 struct timeval *pa_gettimeofday(struct timeval *tv) {
-#ifdef HAVE_GETTIMEOFDAY
     pa_assert(tv);
 
-    pa_assert_se(gettimeofday(tv, NULL) == 0);
-    return tv;
-#elif defined(OS_IS_WIN32)
+#if defined(OS_IS_WIN32)
     /*
      * Copied from implementation by Steven Edwards (LGPL).
      * Found on wine mailing list.
      */
-
 #if defined(_MSC_VER) || defined(__BORLANDC__)
 #define EPOCHFILETIME (116444736000000000i64)
 #else
 #define EPOCHFILETIME (116444736000000000LL)
 #endif
-
-    FILETIME        ft;
-    LARGE_INTEGER   li;
-    __int64         t;
-
-    pa_assert(tv);
+{
+    FILETIME ft;
+    LARGE_INTEGER li;
+    int64_t t;
 
     GetSystemTimeAsFileTime(&ft);
     li.LowPart  = ft.dwLowDateTime;
@@ -70,11 +62,14 @@ struct timeval *pa_gettimeofday(struct timeval *tv) {
     t /= 10;                /* In microseconds */
     tv->tv_sec  = (time_t) (t / PA_USEC_PER_SEC);
     tv->tv_usec = (suseconds_t) (t % PA_USEC_PER_SEC);
-
-    return tv;
+}
+#elif defined(HAVE_GETTIMEOFDAY)
+    pa_assert_se(gettimeofday(tv, NULL) == 0);
 #else
 #error "Platform lacks gettimeofday() or equivalent function."
 #endif
+
+    return tv;
 }
 
 pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
@@ -83,8 +78,8 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
     pa_assert(a);
     pa_assert(b);
 
-    /* Check which whan is the earlier time and swap the two arguments if required. */
-    if (pa_timeval_cmp(a, b) < 0) {
+    /* Check which is the earlier time and swap the two arguments if required. */
+    if (PA_UNLIKELY(pa_timeval_cmp(a, b) < 0)) {
         const struct timeval *c;
         c = a;
         a = b;
@@ -92,13 +87,13 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
     }
 
     /* Calculate the second difference*/
-    r = ((pa_usec_t) a->tv_sec - b->tv_sec) * PA_USEC_PER_SEC;
+    r = ((pa_usec_t) a->tv_sec - (pa_usec_t) b->tv_sec) * PA_USEC_PER_SEC;
 
     /* Calculate the microsecond difference */
     if (a->tv_usec > b->tv_usec)
-        r += ((pa_usec_t) a->tv_usec - b->tv_usec);
+        r += (pa_usec_t) a->tv_usec - (pa_usec_t) b->tv_usec;
     else if (a->tv_usec < b->tv_usec)
-        r -= ((pa_usec_t) b->tv_usec - a->tv_usec);
+        r -= (pa_usec_t) b->tv_usec - (pa_usec_t) a->tv_usec;
 
     return r;
 }
@@ -130,53 +125,87 @@ pa_usec_t pa_timeval_age(const struct timeval *tv) {
 }
 
 struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) {
-    unsigned long secs;
+    time_t secs;
     pa_assert(tv);
 
-    secs = (unsigned long) (v/PA_USEC_PER_SEC);
-    tv->tv_sec += secs;
-    v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
+    secs = (time_t) (v/PA_USEC_PER_SEC);
 
+    if (PA_UNLIKELY(tv->tv_sec > PA_INT_TYPE_MAX(time_t) - secs))
+        goto overflow;
+
+    tv->tv_sec += secs;
+    v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
     tv->tv_usec += (suseconds_t) v;
 
     /* Normalize */
-    while (tv->tv_usec >= PA_USEC_PER_SEC) {
+    while ((pa_usec_t) tv->tv_usec >= PA_USEC_PER_SEC) {
+
+        if (PA_UNLIKELY(tv->tv_sec >= PA_INT_TYPE_MAX(time_t)))
+            goto overflow;
+
         tv->tv_sec++;
-        tv->tv_usec -= PA_USEC_PER_SEC;
+        tv->tv_usec -= (suseconds_t) PA_USEC_PER_SEC;
     }
 
     return tv;
+
+overflow:
+    tv->tv_sec = PA_INT_TYPE_MAX(time_t);
+    tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1);
+    return tv;
 }
 
 struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v) {
-    unsigned long secs;
+    time_t secs;
     pa_assert(tv);
 
-    secs = (unsigned long) (v/PA_USEC_PER_SEC);
+    secs = (time_t) (v/PA_USEC_PER_SEC);
+
+    if (PA_UNLIKELY(tv->tv_sec < secs))
+        goto underflow;
+
     tv->tv_sec -= secs;
-    v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
+    v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
 
     if (tv->tv_usec >= (suseconds_t) v)
         tv->tv_usec -= (suseconds_t) v;
     else {
+
+        if (PA_UNLIKELY(tv->tv_sec <= 0))
+            goto underflow;
+
         tv->tv_sec --;
-        tv->tv_usec = tv->tv_usec + PA_USEC_PER_SEC - v;
+        tv->tv_usec += (suseconds_t) (PA_USEC_PER_SEC - v);
     }
 
     return tv;
+
+underflow:
+    tv->tv_sec = 0;
+    tv->tv_usec = 0;
+    return tv;
 }
 
 struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) {
     pa_assert(tv);
 
-    tv->tv_sec = v / PA_USEC_PER_SEC;
-    tv->tv_usec = v % PA_USEC_PER_SEC;
+    if (PA_UNLIKELY(v == PA_USEC_INVALID)) {
+        tv->tv_sec = PA_INT_TYPE_MAX(time_t);
+        tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1);
+
+        return tv;
+    }
+
+    tv->tv_sec = (time_t) (v / PA_USEC_PER_SEC);
+    tv->tv_usec = (suseconds_t) (v % PA_USEC_PER_SEC);
 
     return tv;
 }
 
 pa_usec_t pa_timeval_load(const struct timeval *tv) {
-    pa_assert(tv);
+
+    if (PA_UNLIKELY(!tv))
+        return PA_USEC_INVALID;
 
     return
         (pa_usec_t) tv->tv_sec * PA_USEC_PER_SEC +