+php_http_header_parser_state_t php_http_header_parser_parse_stream(php_http_header_parser_t *parser, php_http_buffer_t *buf, php_stream *s, unsigned flags, HashTable *headers, php_http_info_callback_t callback_func, void *callback_arg)
+{
+ php_http_header_parser_state_t state = PHP_HTTP_HEADER_PARSER_STATE_START;
+ TSRMLS_FETCH_FROM_CTX(parser->ts);
+
+ if (!buf->data) {
+ php_http_buffer_resize_ex(buf, 0x1000, 1, 0);
+ }
+ while (1) {
+ size_t justread = 0;
+#if DBG_PARSER
+ const char *states[] = {"START", "KEY", "VALUE", "VALUE_EX", "HEADER_DONE", "DONE"};
+ fprintf(stderr, "#SHP: %s (f:%u)\n", states[state], flags);
+#endif
+ /* resize if needed */
+ if (buf->free < 0x1000) {
+ php_http_buffer_resize_ex(buf, 0x1000, 1, 0);
+ }
+ switch (state) {
+ case PHP_HTTP_HEADER_PARSER_STATE_FAILURE:
+ case PHP_HTTP_HEADER_PARSER_STATE_DONE:
+ return state;
+
+ default:
+ /* read line */
+ php_stream_get_line(s, buf->data + buf->used, buf->free, &justread);
+ /* if we fail reading a whole line, try a single char */
+ if (!justread) {
+ int c = php_stream_getc(s);
+
+ if (c != EOF) {
+ char s[1] = {c};
+ justread = php_http_buffer_append(buf, s, 1);
+ }
+ }
+ php_http_buffer_account(buf, justread);
+ }
+
+ if (justread) {
+ state = php_http_header_parser_parse(parser, buf, flags, headers, callback_func, callback_arg);
+ } else if (php_stream_eof(s)) {
+ return php_http_header_parser_parse(parser, buf, flags | PHP_HTTP_HEADER_PARSER_CLEANUP, headers, callback_func, callback_arg);
+ } else {
+ return state;
+ }
+ }
+
+ return PHP_HTTP_HEADER_PARSER_STATE_DONE;
+}