in source/date_time.c [435:568]
static int s_parse_rfc_822(
const struct aws_byte_cursor *date_str_cursor,
struct tm *parsed_time,
struct aws_date_time *dt) {
size_t len = date_str_cursor->len;
size_t index = 0;
size_t state_start_index = 0;
int state = ON_WEEKDAY;
bool error = false;
AWS_ZERO_STRUCT(*parsed_time);
while (!error && index < len) {
char c = date_str_cursor->ptr[index];
switch (state) {
/* week day abbr is optional. */
case ON_WEEKDAY:
if (c == ',') {
state = ON_SPACE_DELIM;
state_start_index = index + 1;
} else if (aws_isdigit(c)) {
state = ON_MONTH_DAY;
} else if (!aws_isalpha(c)) {
error = true;
}
break;
case ON_SPACE_DELIM:
if (aws_isspace(c)) {
state = ON_MONTH_DAY;
state_start_index = index + 1;
} else {
error = true;
}
break;
case ON_MONTH_DAY:
if (aws_isdigit(c)) {
parsed_time->tm_mday = parsed_time->tm_mday * 10 + (c - '0');
} else if (aws_isspace(c)) {
state = ON_MONTH;
state_start_index = index + 1;
} else {
error = true;
}
break;
case ON_MONTH:
if (aws_isspace(c)) {
int monthNumber =
get_month_number_from_str((const char *)date_str_cursor->ptr, state_start_index, index + 1);
if (monthNumber > -1) {
state = ON_YEAR;
state_start_index = index + 1;
parsed_time->tm_mon = monthNumber;
} else {
error = true;
}
} else if (!aws_isalpha(c)) {
error = true;
}
break;
/* year can be 4 or 2 digits. */
case ON_YEAR:
if (aws_isspace(c) && index - state_start_index == 4) {
state = ON_HOUR;
state_start_index = index + 1;
parsed_time->tm_year -= 1900;
} else if (aws_isspace(c) && index - state_start_index == 2) {
state = 5;
state_start_index = index + 1;
parsed_time->tm_year += 2000 - 1900;
} else if (aws_isdigit(c)) {
parsed_time->tm_year = parsed_time->tm_year * 10 + (c - '0');
} else {
error = true;
}
break;
case ON_HOUR:
if (c == ':' && index - state_start_index == 2) {
state = ON_MINUTE;
state_start_index = index + 1;
} else if (aws_isdigit(c)) {
parsed_time->tm_hour = parsed_time->tm_hour * 10 + (c - '0');
} else {
error = true;
}
break;
case ON_MINUTE:
if (c == ':' && index - state_start_index == 2) {
state = ON_SECOND;
state_start_index = index + 1;
} else if (aws_isdigit(c)) {
parsed_time->tm_min = parsed_time->tm_min * 10 + (c - '0');
} else {
error = true;
}
break;
case ON_SECOND:
if (aws_isspace(c) && index - state_start_index == 2) {
state = ON_TZ;
state_start_index = index + 1;
} else if (aws_isdigit(c)) {
parsed_time->tm_sec = parsed_time->tm_sec * 10 + (c - '0');
} else {
error = true;
}
break;
case ON_TZ:
if ((aws_isalnum(c) || c == '-' || c == '+') && (index - state_start_index) < 5) {
dt->tz[index - state_start_index] = c;
} else {
error = true;
}
break;
default:
error = true;
break;
}
index++;
}
if (dt->tz[0] != 0) {
if (is_utc_time_zone(dt->tz)) {
dt->utc_assumed = true;
} else {
error = true;
}
}
return error || state != ON_TZ ? AWS_OP_ERR : AWS_OP_SUCCESS;
}