const char *input, size_t *isize_p,
char *output, size_t *osize_p)
{
- size_t count = *isize_p;
+ size_t count;
+
+ if (!input)
+ return 0; /* we do not keep any states */
+ count = *isize_p;
if (*osize_p < count)
count = *osize_p;
if (count) {
* Use as much input up to *isize_p and fill output up to *osize_p;
* update isize_p and osize_p to indicate how much buffer space was
* consumed and filled. Return 0 on success, non-zero on error.
+ *
+ * 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 and keep calling this function, 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.
*/
extern int stream_filter(struct stream_filter *,
const char *input, size_t *isize_p,
char obuf[FILTER_BUFFER];
int i_end, i_ptr;
int o_end, o_ptr;
+ int input_finished;
};
struct git_istream {
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;
}
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;
}