The Apache Modules Book has the following piece of code in it:
apr_status_t status;
int end = 0;
apr_size_t bytes, count = 0;
const char *buf;
apr_bucket *b;
apr_bucket_brigade *bb;
/* OK, we have some input data. Now read and count it. */
/* Create a brigade to put the data into. */
bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
do {
/* Read a chunk of input into bb */
status = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
APR_BLOCK_READ, BUFLEN);
if ( status == APR_SUCCESS ) {
/* Loop over the contents of bb */
for (b = APR_BRIGADE_FIRST(bb);
b != APR_BRIGADE_SENTINEL(bb);
b = APR_BUCKET_NEXT(b) ) {
/* Check for EOS */
if (APR_BUCKET_IS_EOS(b)) {
end = 1;
break;
} else if (APR_BUCKET_IS_METADATA(b)) {
continue;
}
/* To get the actual length, we need to read the data */
bytes = BUFLEN;
status = apr_bucket_read(b, &buf, &bytes,
APR_BLOCK_READ);
count += bytes;
}
}
/* Discard data we're finished with */
apr_brigade_cleanup(bb);
} while (!end && (status == APR_SUCCESS));
mod_cgi.c, amongst others (in the Apache source code), contains something similar:
do {
apr_bucket *bucket;
rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
APR_BLOCK_READ, HUGE_STRING_LEN);
if (rv != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01225)
"Error reading request entity data");
return ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
}
for (bucket = APR_BRIGADE_FIRST(bb);
bucket != APR_BRIGADE_SENTINEL(bb);
bucket = APR_BUCKET_NEXT(bucket))
{
const char *data;
apr_size_t len;
if (APR_BUCKET_IS_EOS(bucket)) {
seen_eos = 1;
break;
}
/* We can't do much with this. */
if (APR_BUCKET_IS_FLUSH(bucket)) {
continue;
}
/* If the child stopped, we still must read to EOS. */
if (child_stopped_reading) {
continue;
}
/* read */
apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
if (conf->logname && dbpos < conf->bufbytes) {
int cursize;
if ((dbpos + len) > conf->bufbytes) {
cursize = conf->bufbytes - dbpos;
}
else {
cursize = len;
}
memcpy(dbuf + dbpos, data, cursize);
dbpos += cursize;
}
/* Keep writing data to the child until done or too much time
* elapses with no progress or an error occurs.
*/
rv = apr_file_write_full(script_out, data, len, NULL);
if (rv != APR_SUCCESS) {
/* silly script stopped reading, soak up remaining message */
child_stopped_reading = 1;
}
}
apr_brigade_cleanup(bb);
}
while (!seen_eos);
The question is - what is the point of the do/while loop here?
If we don't find eos/seen_eos inside the for loop we're apparently going to get back to ap_get_brigade. Wouldn't the arguments passed (and consequently the outcome) remain the same? And if so, can't we safely do away with the do/while loop?
Thanks.