size_t util_http_reader_read()

in External/HTTP/util_http_reader.c [132:501]


size_t util_http_reader_read(struct util_http_reader* r, char* buffer, size_t length) {
    size_t n;
    int post;
    HAPPrecondition(r != NULL);
    HAPPrecondition(buffer != NULL);
    r->result_token = NULL;
    r->result_length = 0;
    n = 0;
    HAPAssert(n <= length);
    if (n < length) {
        do {
            switch (r->state) {
                case util_HTTP_READER_STATE_EXPECTING_METHOD:
                    if (r->substate == SUBSTATE_NONE) {
                        n += skip_whitespace(&buffer[n], length - n);
                        HAPAssert(n <= length);
                        if (n < length) {
                            if (buffer[n] == CR) {
                                n++;
                                r->substate = SUBSTATE_AFTER_CR;
                            } else if (buffer[n] == LF) {
                                n++;
                            } else {
                                r->state = util_HTTP_READER_STATE_READING_METHOD;
                            }
                        }
                    } else {
                        HAPAssert(r->substate == SUBSTATE_AFTER_CR);
                        if (buffer[n] == LF) {
                            n++;
                            r->substate = SUBSTATE_NONE;
                        } else {
                            r->state = util_HTTP_READER_STATE_ERROR;
                        }
                    }
                    break;
                case util_HTTP_READER_STATE_READING_METHOD:
                    if (r->substate == SUBSTATE_NONE) {
                        if (is_token_char(buffer[n])) {
                            r->substate = SUBSTATE_READING;
                        } else {
                            r->state = util_HTTP_READER_STATE_ERROR;
                        }
                    } else {
                        HAPAssert(r->substate == SUBSTATE_READING);
                        n += read_octets(r, &buffer[n], length - n, is_token_char);
                        HAPAssert(n <= length);
                        if (n < length) {
                            r->state = util_HTTP_READER_STATE_COMPLETED_METHOD;
                            r->substate = SUBSTATE_NONE;
                        }
                    }
                    break;
                case util_HTTP_READER_STATE_COMPLETED_METHOD:
                    r->state = util_HTTP_READER_STATE_EXPECTING_URI;
                    break;
                case util_HTTP_READER_STATE_EXPECTING_URI:
                    if (r->substate == SUBSTATE_NONE) {
                        if (is_whitespace(buffer[n])) {
                            n++;
                            r->substate = SUBSTATE_AFTER_SP;
                        } else {
                            r->state = util_HTTP_READER_STATE_ERROR;
                        }
                    } else {
                        HAPAssert(r->substate == SUBSTATE_AFTER_SP);
                        n += skip_whitespace(&buffer[n], length - n);
                        HAPAssert(n <= length);
                        if (n < length) {
                            r->state = util_HTTP_READER_STATE_READING_URI;
                            r->substate = SUBSTATE_NONE;
                        }
                    }
                    break;
                case util_HTTP_READER_STATE_READING_URI:
                    if (r->substate == SUBSTATE_NONE) {
                        if (is_uri_char(buffer[n])) {
                            r->substate = SUBSTATE_READING;
                        } else {
                            r->state = util_HTTP_READER_STATE_ERROR;
                        }
                    } else {
                        HAPAssert(r->substate == SUBSTATE_READING);
                        n += read_octets(r, &buffer[n], length - n, is_uri_char);
                        HAPAssert(n <= length);
                        if (n < length) {
                            r->state = util_HTTP_READER_STATE_COMPLETED_URI;
                            r->substate = SUBSTATE_NONE;
                        }
                    }
                    break;
                case util_HTTP_READER_STATE_COMPLETED_URI:
                    r->state = util_HTTP_READER_STATE_EXPECTING_VERSION;
                    break;
                case util_HTTP_READER_STATE_EXPECTING_VERSION:
                    if (r->type == util_HTTP_READER_TYPE_REQUEST) {
                        if (r->substate == SUBSTATE_NONE) {
                            if (is_whitespace(buffer[n])) {
                                n++;
                                r->substate = SUBSTATE_AFTER_SP;
                            } else {
                                r->state = util_HTTP_READER_STATE_ERROR;
                            }
                        } else {
                            HAPAssert(r->substate == SUBSTATE_AFTER_SP);
                            n += skip_whitespace(&buffer[n], length - n);
                            HAPAssert(n <= length);
                            if (n < length) {
                                r->state = util_HTTP_READER_STATE_READING_VERSION;
                                r->substate = SUBSTATE_NONE;
                            }
                        }
                    } else {
                        HAPAssert(r->type == util_HTTP_READER_TYPE_RESPONSE);
                        if (r->substate == SUBSTATE_NONE) {
                            n += skip_whitespace(&buffer[n], length - n);
                            HAPAssert(n <= length);
                            if (n < length) {
                                if (buffer[n] == CR) {
                                    n++;
                                    r->substate = SUBSTATE_AFTER_CR;
                                } else if (buffer[n] == LF) {
                                    n++;
                                } else {
                                    r->state = util_HTTP_READER_STATE_READING_VERSION;
                                }
                            }
                        } else {
                            HAPAssert(r->substate == SUBSTATE_AFTER_CR);
                            if (buffer[n] == LF) {
                                n++;
                                r->substate = SUBSTATE_NONE;
                            } else {
                                r->state = util_HTTP_READER_STATE_ERROR;
                            }
                        }
                    }
                    break;
                case util_HTTP_READER_STATE_READING_VERSION:
                    if (r->substate == SUBSTATE_NONE) {
                        if (is_version_char(buffer[n])) {
                            r->substate = SUBSTATE_READING;
                        } else {
                            r->state = util_HTTP_READER_STATE_ERROR;
                        }
                    } else {
                        HAPAssert(r->substate == SUBSTATE_READING);
                        n += read_octets(r, &buffer[n], length - n, is_version_char);
                        HAPAssert(n <= length);
                        if (n < length) {
                            r->state = util_HTTP_READER_STATE_COMPLETED_VERSION;
                            r->substate = SUBSTATE_NONE;
                        }
                    }
                    break;
                case util_HTTP_READER_STATE_COMPLETED_VERSION:
                    if (r->type == util_HTTP_READER_TYPE_REQUEST) {
                        r->state = util_HTTP_READER_STATE_EXPECTING_HEADER_NAME;
                    } else {
                        HAPAssert(r->type == util_HTTP_READER_TYPE_RESPONSE);
                        r->state = util_HTTP_READER_STATE_EXPECTING_STATUS;
                    }
                    break;
                case util_HTTP_READER_STATE_EXPECTING_STATUS:
                    if (r->substate == SUBSTATE_NONE) {
                        if (is_whitespace(buffer[n])) {
                            n++;
                            r->substate = SUBSTATE_AFTER_SP;
                        } else {
                            r->state = util_HTTP_READER_STATE_ERROR;
                        }
                    } else {
                        HAPAssert(r->substate == SUBSTATE_AFTER_SP);
                        n += skip_whitespace(&buffer[n], length - n);
                        HAPAssert(n <= length);
                        if (n < length) {
                            r->state = util_HTTP_READER_STATE_READING_STATUS;
                            r->substate = SUBSTATE_NONE;
                        }
                    }
                    break;
                case util_HTTP_READER_STATE_READING_STATUS:
                    if (r->substate == SUBSTATE_NONE) {
                        if (is_digit(buffer[n])) {
                            r->substate = SUBSTATE_READING;
                        } else {
                            r->state = util_HTTP_READER_STATE_ERROR;
                        }
                    } else {
                        HAPAssert(r->substate == SUBSTATE_READING);
                        n += read_octets(r, &buffer[n], length - n, is_digit);
                        HAPAssert(n <= length);
                        if (n < length) {
                            r->state = util_HTTP_READER_STATE_COMPLETED_STATUS;
                            r->substate = SUBSTATE_NONE;
                        }
                    }
                    break;
                case util_HTTP_READER_STATE_COMPLETED_STATUS:
                    r->state = util_HTTP_READER_STATE_EXPECTING_REASON;
                    break;
                case util_HTTP_READER_STATE_EXPECTING_REASON:
                    if (r->substate == SUBSTATE_NONE) {
                        if (is_whitespace(buffer[n])) {
                            n++;
                            r->substate = SUBSTATE_AFTER_SP;
                        } else {
                            r->state = util_HTTP_READER_STATE_ERROR;
                        }
                    } else {
                        HAPAssert(r->substate == SUBSTATE_AFTER_SP);
                        n += skip_whitespace(&buffer[n], length - n);
                        HAPAssert(n <= length);
                        if (n < length) {
                            r->state = util_HTTP_READER_STATE_READING_REASON;
                            r->substate = SUBSTATE_NONE;
                        }
                    }
                    break;
                case util_HTTP_READER_STATE_READING_REASON:
                    n += read_octets(r, &buffer[n], length - n, is_text_char);
                    HAPAssert(n <= length);
                    if (n < length) {
                        r->state = util_HTTP_READER_STATE_COMPLETED_REASON;
                    }
                    break;
                case util_HTTP_READER_STATE_COMPLETED_REASON:
                    r->state = util_HTTP_READER_STATE_EXPECTING_HEADER_NAME;
                    break;
                case util_HTTP_READER_STATE_EXPECTING_HEADER_NAME:
                    if (r->substate == SUBSTATE_NONE) {
                        if (buffer[n] == CR) {
                            n++;
                            r->substate = SUBSTATE_AFTER_CR;
                        } else if (buffer[n] == LF) {
                            n++;
                            r->state = util_HTTP_READER_STATE_READING_HEADER_NAME;
                        } else {
                            r->state = util_HTTP_READER_STATE_ERROR;
                        }
                    } else {
                        HAPAssert(r->substate == SUBSTATE_AFTER_CR);
                        if (buffer[n] == LF) {
                            n++;
                            r->state = util_HTTP_READER_STATE_READING_HEADER_NAME;
                            r->substate = SUBSTATE_NONE;
                        } else {
                            r->state = util_HTTP_READER_STATE_ERROR;
                        }
                    }
                    break;
                case util_HTTP_READER_STATE_READING_HEADER_NAME:
                    if (r->substate == SUBSTATE_NONE) {
                        if (is_token_char(buffer[n])) {
                            r->substate = SUBSTATE_READING;
                        } else {
                            r->state = util_HTTP_READER_STATE_ENDING_HEADER_LINES;
                        }
                    } else {
                        HAPAssert(r->substate == SUBSTATE_READING);
                        n += read_octets(r, &buffer[n], length - n, is_token_char);
                        HAPAssert(n <= length);
                        if (n < length) {
                            r->state = util_HTTP_READER_STATE_COMPLETED_HEADER_NAME;
                            r->substate = SUBSTATE_NONE;
                        }
                    }
                    break;
                case util_HTTP_READER_STATE_COMPLETED_HEADER_NAME:
                    r->state = util_HTTP_READER_STATE_EXPECTING_HEADER_VALUE;
                    break;
                case util_HTTP_READER_STATE_EXPECTING_HEADER_VALUE:
                    if (buffer[n] == ':') {
                        n++;
                        r->state = util_HTTP_READER_STATE_READING_HEADER_VALUE;
                    } else {
                        r->state = util_HTTP_READER_STATE_ERROR;
                    }
                    break;
                case util_HTTP_READER_STATE_READING_HEADER_VALUE:
                    n += read_octets_and_quotes(r, &buffer[n], length - n, is_text_char);
                    HAPAssert(n <= length);
                    if (n < length) {
                        r->state = util_HTTP_READER_STATE_COMPLETED_HEADER_VALUE;
                    }
                    break;
                case util_HTTP_READER_STATE_COMPLETED_HEADER_VALUE:
                    r->state = util_HTTP_READER_STATE_ENDING_HEADER_LINE;
                    break;
                case util_HTTP_READER_STATE_ENDING_HEADER_LINE:
                    if (r->substate == SUBSTATE_NONE) {
                        if (buffer[n] == CR) {
                            n++;
                            r->substate = SUBSTATE_AFTER_CR;
                        } else if (buffer[n] == LF) {
                            n++;
                            r->substate = SUBSTATE_AFTER_LF;
                        } else {
                            r->state = util_HTTP_READER_STATE_ERROR;
                        }
                    } else if (r->substate == SUBSTATE_AFTER_CR) {
                        if (buffer[n] == LF) {
                            n++;
                            r->substate = SUBSTATE_AFTER_LF;
                        } else {
                            r->state = util_HTTP_READER_STATE_ERROR;
                        }
                    } else {
                        HAPAssert(r->substate == SUBSTATE_AFTER_LF);
                        if (is_whitespace(buffer[n])) {
                            r->state = util_HTTP_READER_STATE_READING_HEADER_VALUE;
                            r->substate = SUBSTATE_NONE;
                        } else if (r->in_quoted_string) {
                            r->state = util_HTTP_READER_STATE_ERROR;
                        } else {
                            r->state = util_HTTP_READER_STATE_READING_HEADER_NAME;
                            r->substate = SUBSTATE_NONE;
                        }
                    }
                    break;
                case util_HTTP_READER_STATE_ENDING_HEADER_LINES:
                    if (r->substate == SUBSTATE_NONE) {
                        if (buffer[n] == CR) {
                            n++;
                            r->substate = SUBSTATE_AFTER_CR;
                        } else if (buffer[n] == LF) {
                            n++;
                            r->state = util_HTTP_READER_STATE_DONE;
                        } else {
                            r->state = util_HTTP_READER_STATE_ERROR;
                        }
                    } else {
                        HAPAssert(r->substate == SUBSTATE_AFTER_CR);
                        if (buffer[n] == LF) {
                            n++;
                            r->state = util_HTTP_READER_STATE_DONE;
                            r->substate = SUBSTATE_NONE;
                        } else {
                            r->state = util_HTTP_READER_STATE_ERROR;
                        }
                    }
                    break;
                case util_HTTP_READER_STATE_DONE:
                case util_HTTP_READER_STATE_ERROR:
                    break;
                default:
                    HAPFatalError();
                    break;
            }
        } while ((n < length) && (r->state != util_HTTP_READER_STATE_COMPLETED_METHOD) &&
                 (r->state != util_HTTP_READER_STATE_COMPLETED_URI) &&
                 (r->state != util_HTTP_READER_STATE_COMPLETED_VERSION) &&
                 (r->state != util_HTTP_READER_STATE_COMPLETED_STATUS) &&
                 (r->state != util_HTTP_READER_STATE_COMPLETED_REASON) &&
                 (r->state != util_HTTP_READER_STATE_COMPLETED_HEADER_NAME) &&
                 (r->state != util_HTTP_READER_STATE_COMPLETED_HEADER_VALUE) &&
                 (r->state != util_HTTP_READER_STATE_DONE) && (r->state != util_HTTP_READER_STATE_ERROR));
    }
    post = (n == length) ||
           ((n < length) &&
            ((r->state == util_HTTP_READER_STATE_ERROR) || (r->state == util_HTTP_READER_STATE_COMPLETED_METHOD) ||
             (r->state == util_HTTP_READER_STATE_COMPLETED_URI) ||
             (r->state == util_HTTP_READER_STATE_COMPLETED_VERSION) ||
             (r->state == util_HTTP_READER_STATE_COMPLETED_STATUS) ||
             (r->state == util_HTTP_READER_STATE_COMPLETED_REASON) ||
             (r->state == util_HTTP_READER_STATE_COMPLETED_HEADER_NAME) ||
             (r->state == util_HTTP_READER_STATE_COMPLETED_HEADER_VALUE) || (r->state == util_HTTP_READER_STATE_DONE)));
    HAPAssert(post);
    return n;
}