diff options
author | David Crocker <dcrocker@eschertech.com> | 2021-09-13 17:54:55 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2021-09-13 17:54:55 +0300 |
commit | accf188c783b67aedf703536b25db8187a6ce55b (patch) | |
tree | c89b325f813e513c530c87e19aa84d6551b902bc /src/libc | |
parent | ae987375ceada66cb9bcccf3a8ee8347ae1e0c5b (diff) |
Tidied up strptime
Diffstat (limited to 'src/libc')
-rw-r--r-- | src/libc/strptime.cpp | 323 |
1 files changed, 185 insertions, 138 deletions
diff --git a/src/libc/strptime.cpp b/src/libc/strptime.cpp index 70835714..9f82940b 100644 --- a/src/libc/strptime.cpp +++ b/src/libc/strptime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Kungliga Tekniska Högskolan + * Copyright (c) 1999 Kungliga Tekniska H�gskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,7 +31,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * DC 2020/01/10: removged code for those format specifiers that need a locale and others that we don't need, + * DC 2020/01/10: removed code for those format specifiers that need a locale and others that we don't need, * such as GNU-specific format specifiers, AM/PM specifiers, 12-hour clock specifiers, 2-digit year specifiers, and month and day number specifiers. * The only format specifiers currently used by RepRapFirmware are: YmdHMS */ @@ -80,7 +80,9 @@ static int first_day (int year) noexcept int ret = 4; while (--year >= 1970) - ret = (ret + 365 + is_leap_year (year)) % 7; + { + ret = (ret + 365 + is_leap_year (year)) % 7; + } return ret; } @@ -94,148 +96,193 @@ const char *SafeStrptime(const char *buf, const char *format, struct tm *timeptr char c; int ymd = 0; - for (; (c = *format) != '\0'; ++format) { - const char *s; - int ret; - - if (isspace_l ((unsigned char) c, locale)) { - while (isspace_l ((unsigned char) *buf, locale)) - ++buf; - } else if (c == '%' && format[1] != '\0') { - c = *++format; - if (c == 'E' || c == 'O') - c = *++format; - switch (c) { - case 'd' : - case 'e' : - ret = strtol_l (buf, &s, 10, locale); - if (s == buf) - return NULL; - timeptr->tm_mday = ret; - buf = s; - ymd |= SET_MDAY; - break; - case 'H' : - case 'k' : /* hour with leading space - GNU extension */ - ret = strtol_l (buf, &s, 10, locale); - if (s == buf) - return NULL; - timeptr->tm_hour = ret; - buf = s; - break; - case 'm' : - ret = strtol_l (buf, &s, 10, locale); - if (s == buf) - return NULL; - timeptr->tm_mon = ret - 1; - buf = s; - ymd |= SET_MON; - break; - case 'M' : - ret = strtol_l (buf, &s, 10, locale); - if (s == buf) - return NULL; - timeptr->tm_min = ret; - buf = s; - break; - case 'n' : - if (*buf == '\n') - ++buf; - else - return NULL; - break; - case 'S' : - ret = strtol_l (buf, &s, 10, locale); - if (s == buf) - return NULL; - timeptr->tm_sec = ret; - buf = s; - break; - case 'Y' : - ret = strtol_l (buf, &s, 10, locale); - if (s == buf) - return NULL; - timeptr->tm_year = ret - tm_year_base; - buf = s; - ymd |= SET_YEAR; - break; - case 'Z' : - /* Unsupported. Just ignore. */ - break; - case '\0' : - --format; - /* FALLTHROUGH */ - /* no break - DC added for Eclipse */ - case '%' : - if (*buf == '%') - ++buf; - else - return NULL; - break; - default : - if (*buf == '%' || *++buf == c) - ++buf; + for (; (c = *format) != '\0'; ++format) + { + if (isspace_l ((unsigned char) c, locale)) + { + while (isspace_l ((unsigned char) *buf, locale)) + ++buf; + } + else if (c == '%' && format[1] != '\0') + { + c = *++format; + if (c == 'E' || c == 'O') + { + c = *++format; + } + + switch (c) + { + case 'd' : + case 'e' : + { + const char *s; + const int ret = strtol_l (buf, &s, 10, locale); + if (s == buf) { return nullptr; } + timeptr->tm_mday = ret; + buf = s; + ymd |= SET_MDAY; + } + break; + + case 'H' : + { + const char *s; + const int ret = strtol_l (buf, &s, 10, locale); + if (s == buf) { return nullptr; } + timeptr->tm_hour = ret; + buf = s; + } + break; + + case 'm' : + { + const char *s; + const int ret = strtol_l (buf, &s, 10, locale); + if (s == buf) { return nullptr; } + timeptr->tm_mon = ret - 1; + buf = s; + ymd |= SET_MON; + } + break; + + case 'M' : + { + const char *s; + const int ret = strtol_l (buf, &s, 10, locale); + if (s == buf) { return nullptr; } + timeptr->tm_min = ret; + buf = s; + } + break; + + case 'n' : + if (*buf == '\n') + { + ++buf; + } + else + { + return nullptr; + } + break; + + case 'S' : + { + const char *s; + const int ret = strtol_l (buf, &s, 10, locale); + if (s == buf) { return nullptr; } + timeptr->tm_sec = ret; + buf = s; + } + break; + + case 'Y' : + { + const char *s; + const int ret = strtol_l (buf, &s, 10, locale); + if (s == buf) { return nullptr; } + timeptr->tm_year = ret - tm_year_base; + buf = s; + ymd |= SET_YEAR; + } + break; + + case '\0' : + --format; + /* FALLTHROUGH */ + /* no break - DC added for Eclipse */ + case '%' : + if (*buf == '%') + { + ++buf; + } + else + { + return nullptr; + } + break; + + default : + if (*buf == '%' || *++buf == c) + { + ++buf; + } + else + { + return nullptr; + } + break; + } + } else - return NULL; - break; - } - } else { - if (*buf == c) - ++buf; - else - return NULL; - } + { + if (*buf == c) + { + ++buf; + } + else + { + return nullptr; + } + } } - if ((ymd & SET_YMD) == SET_YMD) { - /* all of tm_year, tm_mon and tm_mday, but... */ - - if (!(ymd & SET_YDAY)) { - /* ...not tm_yday, so fill it in */ - timeptr->tm_yday = _DAYS_BEFORE_MONTH[timeptr->tm_mon] - + timeptr->tm_mday; - if (!is_leap_year (timeptr->tm_year + tm_year_base) - || timeptr->tm_mon < 2) - { - timeptr->tm_yday--; - } - ymd |= SET_YDAY; - } + if ((ymd & SET_YMD) == SET_YMD) + { + /* all of tm_year, tm_mon and tm_mday, but... */ + if (!(ymd & SET_YDAY)) + { + /* ...not tm_yday, so fill it in */ + timeptr->tm_yday = _DAYS_BEFORE_MONTH[timeptr->tm_mon] + timeptr->tm_mday; + if (!is_leap_year(timeptr->tm_year + tm_year_base) || timeptr->tm_mon < 2) + { + timeptr->tm_yday--; + } + ymd |= SET_YDAY; + } } - else if ((ymd & (SET_YEAR | SET_YDAY)) == (SET_YEAR | SET_YDAY)) { - /* both of tm_year and tm_yday, but... */ - - if (!(ymd & SET_MON)) { - /* ...not tm_mon, so fill it in, and/or... */ - if (timeptr->tm_yday < _DAYS_BEFORE_MONTH[1]) - timeptr->tm_mon = 0; - else { - int leap = is_leap_year (timeptr->tm_year + tm_year_base); - int i; - for (i = 2; i < 12; ++i) { - if (timeptr->tm_yday < _DAYS_BEFORE_MONTH[i] + leap) - break; + else if ((ymd & (SET_YEAR | SET_YDAY)) == (SET_YEAR | SET_YDAY)) + { + /* both of tm_year and tm_yday, but... */ + if (!(ymd & SET_MON)) + { + /* ...not tm_mon, so fill it in, and/or... */ + if (timeptr->tm_yday < _DAYS_BEFORE_MONTH[1]) + { + timeptr->tm_mon = 0; + } + else + { + int leap = is_leap_year (timeptr->tm_year + tm_year_base); + int i; + for (i = 2; i < 12; ++i) + { + if (timeptr->tm_yday < _DAYS_BEFORE_MONTH[i] + leap) + { + break; + } + } + timeptr->tm_mon = i - 1; + } + } + + if (!(ymd & SET_MDAY)) + { + /* ...not tm_mday, so fill it in */ + timeptr->tm_mday = timeptr->tm_yday - _DAYS_BEFORE_MONTH[timeptr->tm_mon]; + if (!is_leap_year (timeptr->tm_year + tm_year_base) || timeptr->tm_mon < 2) + { + timeptr->tm_mday++; + } } - timeptr->tm_mon = i - 1; - } - } - - if (!(ymd & SET_MDAY)) { - /* ...not tm_mday, so fill it in */ - timeptr->tm_mday = timeptr->tm_yday - - _DAYS_BEFORE_MONTH[timeptr->tm_mon]; - if (!is_leap_year (timeptr->tm_year + tm_year_base) - || timeptr->tm_mon < 2) - { - timeptr->tm_mday++; - } - } } - if ((ymd & (SET_YEAR | SET_YDAY | SET_WDAY)) == (SET_YEAR | SET_YDAY)) { - /* fill in tm_wday */ - int fday = first_day (timeptr->tm_year + tm_year_base); - timeptr->tm_wday = (fday + timeptr->tm_yday) % 7; + if ((ymd & (SET_YEAR | SET_YDAY | SET_WDAY)) == (SET_YEAR | SET_YDAY)) + { + /* fill in tm_wday */ + int fday = first_day (timeptr->tm_year + tm_year_base); + timeptr->tm_wday = (fday + timeptr->tm_yday) % 7; } return buf; |