static int s_parse_rfc_822()

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;
}