Просмотр исходного кода

Unify gmtime and localtime code

Apparently gmtime was already implemented when I made localtime, so we had two different things written from scratch. We decided in the relibc channel of the Redox OS Mattermost chat to use my code, as it is more extensively tested and perhaps is clearer in how it works.
jD91mZM2 6 лет назад
Родитель
Сommit
eb6ddac1eb
4 измененных файлов с 21 добавлено и 91 удалено
  1. 0 41
      src/header/time/helpers.rs
  2. 17 48
      src/header/time/mod.rs
  3. 2 0
      tests/expected/time/localtime.stdout
  4. 2 2
      tests/time/localtime.c

+ 0 - 41
src/header/time/helpers.rs

@@ -1,41 +0,0 @@
-use platform::types::*;
-
-use super::constants::*;
-
-// compute year, month, day & day of year
-// for description of this algorithm see
-// http://howardhinnant.github.io/date_algorithms.html#civil_from_days
-#[inline(always)]
-pub(crate) fn civil_from_days(days: c_long) -> (c_int, c_int, c_int, c_int) {
-    let (era, year): (c_int, c_int);
-    let (erayear, mut yearday, mut month, day): (c_int, c_int, c_int, c_int);
-    let eraday: c_ulong;
-
-    era = (if days >= 0 {
-        days
-    } else {
-        days - (DAYS_PER_ERA - 1)
-    } / DAYS_PER_ERA) as c_int;
-    eraday = (days - era as c_long * DAYS_PER_ERA) as c_ulong;
-    let a = eraday / (DAYS_PER_4_YEARS - 1);
-    let b = eraday / DAYS_PER_CENTURY;
-    let c = eraday / (DAYS_PER_ERA as c_ulong - 1);
-    erayear = ((eraday - a + b - c) / 365) as c_int;
-    let d = DAYS_PER_YEAR * erayear + erayear / 4 - erayear / 100;
-    yearday = (eraday - d as c_ulong) as c_int;
-    month = (5 * yearday + 2) / 153;
-    day = yearday - (153 * month + 2) / 5 + 1;
-    month += if month < 10 { 2 } else { -10 };
-    year = ADJUSTED_EPOCH_YEAR + erayear + era * YEARS_PER_ERA + (month <= 1) as c_int;
-    yearday += if yearday >= DAYS_PER_YEAR - DAYS_IN_JANUARY - DAYS_IN_FEBRUARY {
-        -(DAYS_PER_YEAR - DAYS_IN_JANUARY - DAYS_IN_FEBRUARY)
-    } else {
-        DAYS_IN_JANUARY + DAYS_IN_FEBRUARY + is_leap(erayear)
-    };
-    return (year, month, day, yearday);
-}
-
-#[inline(always)]
-fn is_leap(y: c_int) -> c_int {
-    ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) as c_int
-}

+ 17 - 48
src/header/time/mod.rs

@@ -8,10 +8,8 @@ use platform::types::*;
 use platform::{Pal, Sys};
 
 use self::constants::*;
-use self::helpers::*;
 
 pub mod constants;
-mod helpers;
 mod strftime;
 
 #[repr(C)]
@@ -158,54 +156,10 @@ pub extern "C" fn getdate(string: *const c_char) -> tm {
 }
 
 #[no_mangle]
-pub extern "C" fn gmtime(timer: *const time_t) -> *mut tm {
+pub unsafe extern "C" fn gmtime(timer: *const time_t) -> *mut tm {
     unsafe { gmtime_r(timer, &mut TM) }
 }
 
-#[no_mangle]
-pub extern "C" fn gmtime_r(clock: *const time_t, result: *mut tm) -> *mut tm {
-    let (mut days, mut rem): (c_long, c_long);
-    let mut weekday: c_int;
-    let lcltime = unsafe { *clock };
-
-    days = lcltime / SECSPERDAY + EPOCH_ADJUSTMENT_DAYS;
-    rem = lcltime % SECSPERDAY;
-    if rem < 0 {
-        rem += SECSPERDAY;
-        days -= 1;
-    }
-    unsafe {
-        (*result).tm_hour = (rem / SECSPERHOUR) as c_int;
-        rem %= SECSPERHOUR;
-        (*result).tm_min = (rem / SECSPERMIN) as c_int;
-        (*result).tm_sec = (rem % SECSPERMIN) as c_int;
-    }
-
-    weekday = ((ADJUSTED_EPOCH_WDAY + days) % DAYSPERWEEK as c_long) as c_int;
-    if weekday < 0 {
-        weekday += DAYSPERWEEK;
-    }
-    unsafe { (*result).tm_wday = weekday };
-
-    let (year, month, day, yearday) = civil_from_days(days);
-    unsafe {
-        (*result).tm_yday = yearday;
-        (*result).tm_year = year - YEAR_BASE;
-        (*result).tm_mon = month;
-        (*result).tm_mday = day;
-
-        (*result).tm_isdst = 0;
-        (*result).tm_gmtoff = 0;
-        (*result).tm_zone = UTC;
-    }
-    result
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn localtime(clock: *const time_t) -> *mut tm {
-    localtime_r(clock, &mut TM)
-}
-
 const MONTH_DAYS: [[c_int; 12]; 2] = [
     // Non-leap years:
     [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
@@ -213,12 +167,13 @@ const MONTH_DAYS: [[c_int; 12]; 2] = [
     [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
 ];
 
+#[inline(always)]
 fn leap_year(year: c_int) -> bool {
     year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn localtime_r(clock: *const time_t, t: *mut tm) -> *mut tm {
+pub unsafe extern "C" fn gmtime_r(clock: *const time_t, t: *mut tm) -> *mut tm {
     let clock = *clock;
 
     let mut day = (clock / (60 * 60 * 24)) as c_int;
@@ -288,11 +243,25 @@ pub unsafe extern "C" fn localtime_r(clock: *const time_t, t: *mut tm) -> *mut t
         (*t).tm_mon += 1;
     }
     (*t).tm_mday = 1 + day as c_int;
+
     (*t).tm_isdst = 0;
+    (*t).tm_gmtoff = 0;
+    (*t).tm_zone = UTC;
 
     t
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn localtime(clock: *const time_t) -> *mut tm {
+    localtime_r(clock, &mut TM)
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn localtime_r(clock: *const time_t, t: *mut tm) -> *mut tm {
+    // TODO: Change tm_isdst, tm_gmtoff, tm_zone
+    gmtime_r(clock, t)
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn mktime(t: *mut tm) -> time_t {
     let mut year = (*t).tm_year + 1900;

+ 2 - 0
tests/expected/time/localtime.stdout

@@ -1,6 +1,8 @@
 Year 69, Day of year: 333, Month 10, Day of month: 29, Day of week: 6, 0:0:0
 Year 69, Day of year: 365, Month 11, Day of month: 31, Day of week: 3, 0:0:0
+Year 69, Day of year: 365, Month 11, Day of month: 31, Day of week: 3, 23:59:59
 Year 69, Day of year: 365, Month 11, Day of month: 31, Day of week: 3, 23:51:40
 Year 70, Day of year: 0, Month 0, Day of month: 1, Day of week: 4, 0:0:0
+Year 70, Day of year: 0, Month 0, Day of month: 1, Day of week: 4, 0:0:1
 Year 118, Day of year: 193, Month 6, Day of month: 13, Day of week: 5, 4:9:10
 Fri Jul 13 06:03:43 2018

+ 2 - 2
tests/time/localtime.c

@@ -3,8 +3,8 @@
 
 int main() {
     int day = 60 * 60 * 24;
-    time_t inputs[] = { -(day * 33), -day, -500, 0, 1531454950 };
-    for (int i = 0; i < 5; i += 1) {
+    time_t inputs[] = { -(day * 33), -day, -1, -500, 0, 1, 1531454950 };
+    for (int i = 0; i < (sizeof(inputs) / sizeof(time_t)); i += 1) {
         struct tm* t = localtime(&inputs[i]);
 
         printf(