summaryrefslogtreecommitdiff
path: root/streaming.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2011-05-21 21:05:51 (GMT)
committerJunio C Hamano <gitster@pobox.com>2011-05-26 23:47:15 (GMT)
commit4ae6670444388f5ba68850e42a93af4019922c26 (patch)
treea065ece4a58a8f4030e77a8c26ae1391a48ae40c /streaming.c
parentb6691092d707860019bbab80eaaf9173ada10586 (diff)
downloadgit-4ae6670444388f5ba68850e42a93af4019922c26.zip
git-4ae6670444388f5ba68850e42a93af4019922c26.tar.gz
git-4ae6670444388f5ba68850e42a93af4019922c26.tar.bz2
stream filter: add "no more input" to the filters
Some filters may need to buffer the input and look-ahead inside it to decide what to output, and they may consume more than zero bytes of input and still not produce any output. After feeding all the input, pass NULL as input as keep calling stream_filter() to let such filters know there is no more input coming, and it is time for them to produce the remaining output based on the buffered input. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'streaming.c')
-rw-r--r--streaming.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/streaming.c b/streaming.c
index 565f000..91414f4 100644
--- a/streaming.c
+++ b/streaming.c
@@ -60,6 +60,7 @@ struct filtered_istream {
char obuf[FILTER_BUFFER];
int i_end, i_ptr;
int o_end, o_ptr;
+ int input_finished;
};
struct git_istream {
@@ -215,12 +216,30 @@ static read_method_decl(filtered)
fs->o_end = FILTER_BUFFER - to_receive;
continue;
}
+
+ /* tell the filter to drain upon no more input */
+ if (fs->input_finished) {
+ size_t to_receive = FILTER_BUFFER;
+ if (stream_filter(fs->filter,
+ NULL, NULL,
+ fs->obuf, &to_receive))
+ return -1;
+ fs->o_end = FILTER_BUFFER - to_receive;
+ if (!fs->o_end)
+ break;
+ continue;
+ }
fs->i_end = fs->i_ptr = 0;
/* refill the input from the upstream */
- fs->i_end = read_istream(fs->upstream, fs->ibuf, FILTER_BUFFER);
- if (fs->i_end <= 0)
- break;
+ if (!fs->input_finished) {
+ fs->i_end = read_istream(fs->upstream, fs->ibuf, FILTER_BUFFER);
+ if (fs->i_end < 0)
+ break;
+ if (fs->i_end)
+ continue;
+ }
+ fs->input_finished = 1;
}
return filled;
}
@@ -241,6 +260,7 @@ static struct git_istream *attach_stream_filter(struct git_istream *st,
fs->filter = filter;
fs->i_end = fs->i_ptr = 0;
fs->o_end = fs->o_ptr = 0;
+ fs->input_finished = 0;
ifs->size = -1; /* unknown */
return ifs;
}