static S2N_RESULT process_state()

in utils/s2n_asn1_time.c [73:233]


static S2N_RESULT process_state(parser_state *state, char current_char, struct parser_args *args) {
    switch (*state) {
        case ON_YEAR_DIGIT_1:
            PARSE_DIGIT(current_char, args->current_digit);
            args->time.tm_year = args->current_digit;
            *state = ON_YEAR_DIGIT_2;
            return S2N_RESULT_OK;
        case ON_YEAR_DIGIT_2:
            PARSE_DIGIT(current_char, args->current_digit);
            args->time.tm_year = args->time.tm_year * 10 + args->current_digit;
            *state = ON_YEAR_DIGIT_3;
            return S2N_RESULT_OK;
        case ON_YEAR_DIGIT_3:
            PARSE_DIGIT(current_char, args->current_digit);
            args->time.tm_year = args->time.tm_year * 10 + args->current_digit;
            *state = ON_YEAR_DIGIT_4;
            return S2N_RESULT_OK;
        case ON_YEAR_DIGIT_4:
            PARSE_DIGIT(current_char, args->current_digit);
            args->time.tm_year = args->time.tm_year * 10 + args->current_digit;
            args->time.tm_year -= 1900;
            if (args->time.tm_year < 0) {
                return S2N_RESULT_ERROR;
            }

            *state = ON_MONTH_DIGIT_1;
            return S2N_RESULT_OK;
        case ON_MONTH_DIGIT_1:
            PARSE_DIGIT(current_char, args->current_digit);
            args->time.tm_mon = args->current_digit;
            *state = ON_MONTH_DIGIT_2;
            return S2N_RESULT_OK;
        case ON_MONTH_DIGIT_2:
            PARSE_DIGIT(current_char, args->current_digit);
            args->time.tm_mon = args->time.tm_mon * 10 + args->current_digit;
            args->time.tm_mon -= 1;

            if (args->time.tm_mon < 0 || args->time.tm_mon > 11) {
                return S2N_RESULT_ERROR;
            }

            *state = ON_DAY_DIGIT_1;
            return S2N_RESULT_OK;
        case ON_DAY_DIGIT_1:
            PARSE_DIGIT(current_char, args->current_digit);
            args->time.tm_mday = args->current_digit;
            *state = ON_DAY_DIGIT_2;
            return S2N_RESULT_OK;
        case ON_DAY_DIGIT_2:
            PARSE_DIGIT(current_char, args->current_digit);
            args->time.tm_mday = args->time.tm_mday * 10 + args->current_digit;

            if (args->time.tm_mday < 0 || args->time.tm_mday > 31) {
                return S2N_RESULT_ERROR;
            }

            *state = ON_HOUR_DIGIT_1;
            return S2N_RESULT_OK;
        case ON_HOUR_DIGIT_1:
            PARSE_DIGIT(current_char, args->current_digit);
            args->time.tm_hour = args->current_digit;
            *state = ON_HOUR_DIGIT_2;
            return S2N_RESULT_OK;
        case ON_HOUR_DIGIT_2:
            PARSE_DIGIT(current_char, args->current_digit);
            args->time.tm_hour = args->time.tm_hour * 10 + args->current_digit;

            if (args->time.tm_hour < 0 || args->time.tm_hour > 23) {
                return S2N_RESULT_ERROR;
            }

            *state = ON_MINUTE_DIGIT_1;
            return S2N_RESULT_OK;
        case ON_MINUTE_DIGIT_1:
            PARSE_DIGIT(current_char, args->current_digit);
            args->time.tm_min = args->current_digit;
            *state = ON_MINUTE_DIGIT_2;
            return S2N_RESULT_OK;
        case ON_MINUTE_DIGIT_2:
            PARSE_DIGIT(current_char, args->current_digit);
            args->time.tm_min = args->time.tm_min * 10 + args->current_digit;

            if (args->time.tm_min < 0 || args->time.tm_min > 59) {
                return S2N_RESULT_ERROR;
            }

            *state = ON_SECOND_DIGIT_1;
            return S2N_RESULT_OK;
        case ON_SECOND_DIGIT_1:
            PARSE_DIGIT(current_char, args->current_digit);
            args->time.tm_sec = args->current_digit;
            *state = ON_SECOND_DIGIT_2;
            return S2N_RESULT_OK;
        case ON_SECOND_DIGIT_2:
            PARSE_DIGIT(current_char, args->current_digit);
            args->time.tm_sec = args->time.tm_sec * 10 + args->current_digit;

            if (args->time.tm_sec < 0 || args->time.tm_sec > 59) {
                return S2N_RESULT_ERROR;
            }

            *state = ON_SUBSECOND;
            return S2N_RESULT_OK;
        case ON_SUBSECOND:
            if (current_char == '.' || isdigit(current_char)) {
                *state = ON_SUBSECOND;
                return S2N_RESULT_OK;
            }
            FALL_THROUGH;
        case ON_TIMEZONE:
            if (current_char == 'Z' || current_char == 'z') {
                args->local_time_assumed = 0;
                *state = FINISHED;
                return S2N_RESULT_OK;
            } else if (current_char == '-') {
                args->local_time_assumed = 0;
                args->offset_negative = 1;
                *state = ON_OFFSET_HOURS_DIGIT_1;
                return S2N_RESULT_OK;
            } else if (current_char == '+') {
                args->local_time_assumed = 0;
                args->offset_negative = 0;
                *state = ON_OFFSET_HOURS_DIGIT_1;
                return S2N_RESULT_OK;
            }

            return S2N_RESULT_ERROR;
        case ON_OFFSET_HOURS_DIGIT_1:
            PARSE_DIGIT(current_char, args->current_digit);
            args->offset_hours = args->current_digit;
            *state = ON_OFFSET_HOURS_DIGIT_2;
            return S2N_RESULT_OK;
        case ON_OFFSET_HOURS_DIGIT_2:
            PARSE_DIGIT(current_char, args->current_digit);
            args->offset_hours = args->offset_hours * 10 + args->current_digit;

            if (args->offset_hours < 0 || args->offset_hours > 23) {
                return S2N_RESULT_ERROR;
            }

            *state = ON_OFFSET_MINUTES_DIGIT_1;
            return S2N_RESULT_OK;
        case ON_OFFSET_MINUTES_DIGIT_1:
            PARSE_DIGIT(current_char, args->current_digit);
            args->offset_minutes = args->current_digit;
            *state = ON_OFFSET_MINUTES_DIGIT_2;
            return S2N_RESULT_OK;
        case ON_OFFSET_MINUTES_DIGIT_2:
            PARSE_DIGIT(current_char, args->current_digit);
            args->offset_minutes = args->offset_minutes * 10 + args->current_digit;

            if (args->offset_minutes < 0 || args->offset_minutes > 23) {
                return S2N_RESULT_ERROR;
            }

            *state = FINISHED;
            return S2N_RESULT_OK;
        default:
            return S2N_RESULT_ERROR;
    }
}