diff options
Diffstat (limited to 'lib/mlibc/options/posix/generic/time.cpp')
-rw-r--r-- | lib/mlibc/options/posix/generic/time.cpp | 505 |
1 files changed, 0 insertions, 505 deletions
diff --git a/lib/mlibc/options/posix/generic/time.cpp b/lib/mlibc/options/posix/generic/time.cpp deleted file mode 100644 index 14193af..0000000 --- a/lib/mlibc/options/posix/generic/time.cpp +++ /dev/null @@ -1,505 +0,0 @@ -#include <ctype.h> -#include <langinfo.h> -#include <stdio.h> -#include <string.h> -#include <time.h> - -#include <bits/ensure.h> -#include <mlibc/strings.hpp> - -namespace { - -int month_to_day(int month) { - switch(month){ - case 0: return 0; - case 1: return 31; - case 2: return 59; - case 3: return 90; - case 4: return 120; - case 5: return 151; - case 6: return 181; - case 7: return 212; - case 8: return 243; - case 9: return 273; - case 10: return 304; - case 11: return 334; - } - return -1; -} - -int is_leapyear(int year) { - return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); -} - -int month_and_year_to_day_in_year(int month, int year){ - int day = month_to_day(month); - if(is_leapyear(year) && month < 2) - return day + 1; - - return day; -} - -int target_determination(int month) { - switch(month){ - case 0: return 3; - case 1: return 14; - case 2: return 14; - case 3: return 4; - case 4: return 9; - case 5: return 6; - case 6: return 11; - case 7: return 8; - case 8: return 5; - case 9: return 10; - case 10: return 7; - case 11: return 12; - } - - return -1; -} - -int doom_determination(int full_year) { - int century = full_year / 100; - int anchor = 2 + 5 * (century % 4) % 7; - - int year = full_year % 100; - - if(year % 2) - year += 11; - - year /= 2; - - if(year % 2) - year += 11; - - return 7 - (year % 7) + anchor; -} - -//Determine day of week through the doomsday algorithm. -int day_determination(int day, int month, int year) { - int doom = doom_determination(year); - bool leap = is_leapyear(year); - - int target = target_determination(month); - if(leap && month < 2) - target++; - - int doom_dif = (day - target) % 7; - return (doom + doom_dif) % 7; -} - -struct strptime_internal_state { - bool has_century; - bool has_year; - bool has_month; - bool has_day_of_month; - bool has_day_of_year; - bool has_day_of_week; - - bool full_year_given; - - int century; - - size_t format_index; - size_t input_index; -}; - -char *strptime_internal(const char *__restrict input, const char *__restrict format, - struct tm *__restrict tm, struct strptime_internal_state *__restrict state) { - auto matchLanginfoItem = [&] (int start, size_t num, int &dest, bool &flag) -> bool { - for(size_t i = start; i < (start + num); i++) { - const char *mon = nl_langinfo(i); - size_t len = strlen(mon); - if(mlibc::strncasecmp(&input[state->input_index], mon, len)) - continue; - state->input_index += len; - dest = i - start; - flag = true; - return true; - } - return false; - }; - - auto matchNumericRange = [&] (int start, int end, int &dest, bool *flag) -> bool { - int product = 0, n = 0; - sscanf(&input[state->input_index], "%d%n", &product, &n); - if(n == 0 || 2 < n) - return false; - if(product < start || product > end) - return false; - state->input_index += n; - dest = product; - if(flag) *flag = true; - return true; - }; - - while(isspace(input[state->input_index])) - state->input_index++; - - if(input[state->input_index] == '\0') - return NULL; - - while(format[state->format_index] != '\0'){ - if(format[state->format_index] != '%'){ - if(isspace(format[state->format_index])){ - while(isspace(input[state->input_index++])); - state->input_index--; - } - else { - if(format[state->format_index] != input[state->input_index++]) - return NULL; - } - state->format_index++; - continue; - } - state->format_index++; - switch(format[state->format_index]){ - case '%': - if(input[state->input_index++] != '%') - return NULL; - break; - case 'a': - case 'A': { - if (!matchLanginfoItem(DAY_1, 7, tm->tm_wday, state->has_day_of_week) && \ - !matchLanginfoItem(ABDAY_1, 7, tm->tm_wday, state->has_day_of_week)) - return NULL; - break; - } - case 'b': - case 'B': - case 'h': { - if (!matchLanginfoItem(MON_1, 12, tm->tm_mon, state->has_month) && \ - !matchLanginfoItem(ABMON_1, 12, tm->tm_mon, state->has_month)) - return NULL; - break; - } - case 'c': - __ensure(!"strptime() %c directive unimplemented."); - __builtin_unreachable(); - break; - case 'C': { - int product = 0, n = 0; - sscanf(&input[state->input_index], "%d%n", &product, &n); - if(n == 0 || 2 < n) - return NULL; - state->input_index += n; - state->century = product; - state->has_century = true; - break; - } - case 'd': //`%d` and `%e` are equivalent - case 'e': { - if(!matchNumericRange(1, 31, tm->tm_mday, &state->has_day_of_month)) - return NULL; - break; - } - case 'D': { //equivalent to `%m/%d/%y` - size_t pre_fi = state->format_index; - state->format_index = 0; - - char *result = strptime_internal(input, "%m/%d/%y", tm, state); - if(result == NULL) - return NULL; - - state->format_index = pre_fi; - break; - } - case 'H': { - if(!matchNumericRange(0, 23, tm->tm_hour, nullptr)) - return NULL; - break; - } - case 'I': { - if(!matchNumericRange(1, 12, tm->tm_hour, nullptr)) - return NULL; - break; - } - case 'j': { - if(!matchNumericRange(1, 366, tm->tm_yday, &state->has_day_of_year)) - return NULL; - tm->tm_yday--; - break; - } - case 'm': { - if(!matchNumericRange(1, 12, tm->tm_mon, &state->has_month)) - return NULL; - tm->tm_mon--; - break; - } - case 'M': { - if(!matchNumericRange(0, 59, tm->tm_min, nullptr)) - return NULL; - break; - } - case 'n': - case 't': { - size_t n = 0; - while(isspace(input[state->input_index++])) - n++; - if(n == 0) - return NULL; - state->input_index--; - break; - } - case 'p': { - const char *meridian_str = nl_langinfo(AM_STR); - size_t len = strlen(meridian_str); - if (!mlibc::strncasecmp(&input[state->input_index], meridian_str, len)) { - tm->tm_hour %= 12; - state->input_index += len; - break; - } - meridian_str = nl_langinfo(PM_STR); - len = strlen(meridian_str); - if (!mlibc::strncasecmp(&input[state->input_index], meridian_str, len)) { - tm->tm_hour %= 12; - tm->tm_hour += 12; - state->input_index += len; - break; - } - break; - } - case 'r': { //equivalent to `%I:%M:%S %p` - size_t pre_fi = state->format_index; - state->format_index = 0; - - char *result = strptime_internal(input, "%I:%M:%S %p", tm, state); - if(result == NULL) - return NULL; - - state->format_index = pre_fi; - break; - } - case 'R': { //equivalent to `%H:%M` - size_t pre_fi = state->format_index; - state->format_index = 0; - - char *result = strptime_internal(input, "%H:%M", tm, state); - if(result == NULL) - return NULL; - - state->format_index = pre_fi; - break; - } - case 'S': { - if(!matchNumericRange(0, 60, tm->tm_sec, nullptr)) - return NULL; - break; - } - case 'T': { //equivalent to `%H:%M:%S` - size_t pre_fi = state->format_index; - state->format_index = 0; - - char *result = strptime_internal(input, "%H:%M:%S", tm, state); - if(result == NULL) - return NULL; - - state->format_index = pre_fi; - break; - } - case 'U': - __ensure(!"strptime() %U directive unimplemented."); - __builtin_unreachable(); - break; - case 'w': { - int product = 0, n = 0; - sscanf(&input[state->input_index], "%d%n", &product, &n); - if(n == 0 || 1 < n) - return NULL; - state->input_index += n; - tm->tm_wday = product; - state->has_day_of_week = true; - break; - } - case 'W': - __ensure(!"strptime() %W directive unimplemented."); - __builtin_unreachable(); - break; - case 'x': - __ensure(!"strptime() %x directive unimplemented."); - __builtin_unreachable(); - break; - case 'X': - __ensure(!"strptime() %X directive unimplemented."); - __builtin_unreachable(); - break; - case 'y': { - int product = 0, n = 0; - sscanf(&input[state->input_index], "%d%n", &product, &n); - if(n == 0 || 2 < n) - return NULL; - if(product < 69) - product += 100; - state->input_index += n; - tm->tm_year = product; - state->has_year = true; - break; - } - case 'Y': { - int product = 0, n = 0; - sscanf(&input[state->input_index], "%d%n", &product, &n); - if(n == 0 || 4 < n) - return NULL; - state->input_index += n; - tm->tm_year = product - 1900; - state->has_year = true; - state->has_century = true; - state->full_year_given = true; - state->century = product / 100; - break; - } - case 'F': { //GNU extensions - //equivalent to `%Y-%m-%d` - size_t pre_fi = state->format_index; - state->format_index = 0; - - char *result = strptime_internal(input, "%Y-%m-%d", tm, state); - if(result == NULL) - return NULL; - - state->format_index = pre_fi; - break; - } - case 'g': - __ensure(!"strptime() %g directive unimplemented."); - __builtin_unreachable(); - break; - case 'G': - __ensure(!"strptime() %G directive unimplemented."); - __builtin_unreachable(); - break; - case 'u': { - if(!matchNumericRange(1, 7, tm->tm_wday, nullptr)) - return NULL; - tm->tm_wday--; - break; - } - case 'V': - __ensure(!"strptime() %V directive unimplemented."); - __builtin_unreachable(); - break; - case 'z': - __ensure(!"strptime() %z directive unimplemented."); - __builtin_unreachable(); - break; - case 'Z': - __ensure(!"strptime() %Z directive unimplemented."); - __builtin_unreachable(); - break; - case 's': //end of GNU extensions - __ensure(!"strptime() %s directive unimplemented."); - __builtin_unreachable(); - break; - case 'E': { //locale-dependent date & time representation - __ensure(!"strptime() %E* directives unimplemented."); - __builtin_unreachable(); - /* - state->format_index++; - switch(format[state->format_index]){ - case 'c': - break; - case 'C': - break; - case 'x': - break; - case 'X': - break; - case 'y': - break; - case 'Y': - break; - default: - return NULL; - } - */ - } - case 'O': { //locale-dependent numeric symbols - __ensure(!"strptime() %O* directives unimplemented."); - __builtin_unreachable(); - /* - state->format_index++; - switch(format[state->format_index]){ - case 'd': - case 'e': - break; - case 'H': - break; - case 'I': - break; - case 'm': - break; - case 'M': - break; - case 'S': - break; - case 'U': - break; - case 'w': - break; - case 'W': - break; - case 'y': - break; - default: - return NULL; - } - */ - } - default: - return NULL; - } - state->format_index++; - } - - return (char*)input + state->input_index; -} - -} //anonymous namespace - -char *strptime(const char *__restrict s, const char *__restrict format, struct tm *__restrict tm){ - struct strptime_internal_state state = {}; - - char *result = strptime_internal(s, format, tm, &state); - - if(result == NULL) - return NULL; - - if(state.has_century && !state.full_year_given){ - int full_year = state.century * 100; - - if(state.has_year){ - //Compensate for default century-adjustment of `%j` operand - if(tm->tm_year >= 100) - full_year += tm->tm_year - 100; - else - full_year += tm->tm_year; - } - - tm->tm_year = full_year - 1900; - - state.has_year = true; - } - - if(state.has_month && !state.has_day_of_year){ - int day = 0; - if(state.has_year) - day = month_and_year_to_day_in_year(tm->tm_mon, tm->tm_year); - else - day = month_to_day(tm->tm_mon); - - tm->tm_yday = day + tm->tm_mday - 1; - state.has_day_of_year = true; - } - - if(state.has_year && !state.has_day_of_week){ - if(!state.has_month && !state.has_day_of_month){ - tm->tm_wday = day_determination(0, 0, tm->tm_year + 1900); - } - else if(state.has_month && state.has_day_of_month){ - tm->tm_wday = day_determination(tm->tm_mday, tm->tm_mon, tm->tm_year + 1900); - } - state.has_day_of_week = true; - } - - return result; -} |