📄 apr_brigade.c
字号:
return rv; vec->iov_len = iov_len; /* set indirectly in case size differs */ ++vec; } *nvec = vec - orig; return APR_SUCCESS;}APU_DECLARE(apr_status_t) apr_brigade_vputstrs(apr_bucket_brigade *b, apr_brigade_flush flush, void *ctx, va_list va){ for (;;) { const char *str = va_arg(va, const char *); apr_status_t rv; if (str == NULL) break; rv = apr_brigade_write(b, flush, ctx, str, strlen(str)); if (rv != APR_SUCCESS) return rv; } return APR_SUCCESS;}APU_DECLARE(apr_status_t) apr_brigade_putc(apr_bucket_brigade *b, apr_brigade_flush flush, void *ctx, const char c){ return apr_brigade_write(b, flush, ctx, &c, 1);}APU_DECLARE(apr_status_t) apr_brigade_write(apr_bucket_brigade *b, apr_brigade_flush flush, void *ctx, const char *str, apr_size_t nbyte){ apr_bucket *e = APR_BRIGADE_LAST(b); apr_size_t remaining = APR_BUCKET_BUFF_SIZE; char *buf = NULL; if (!APR_BRIGADE_EMPTY(b) && APR_BUCKET_IS_HEAP(e)) { apr_bucket_heap *h = e->data; /* HEAP bucket start offsets are always in-memory, safe to cast */ remaining = h->alloc_len - (e->length + (apr_size_t)e->start); buf = h->base + e->start + e->length; } if (nbyte > remaining) { /* either a buffer bucket exists but is full, * or no buffer bucket exists and the data is too big * to buffer. In either case, we should flush. */ if (flush) { e = apr_bucket_transient_create(str, nbyte, b->bucket_alloc); APR_BRIGADE_INSERT_TAIL(b, e); return flush(b, ctx); } else { e = apr_bucket_heap_create(str, nbyte, NULL, b->bucket_alloc); APR_BRIGADE_INSERT_TAIL(b, e); return APR_SUCCESS; } } else if (!buf) { /* we don't have a buffer, but the data is small enough * that we don't mind making a new buffer */ buf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->bucket_alloc); e = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE, apr_bucket_free, b->bucket_alloc); APR_BRIGADE_INSERT_TAIL(b, e); e->length = 0; /* We are writing into the brigade, and * allocating more memory than we need. This * ensures that the bucket thinks it is empty just * after we create it. We'll fix the length * once we put data in it below. */ } /* there is a sufficiently big buffer bucket available now */ memcpy(buf, str, nbyte); e->length += nbyte; return APR_SUCCESS;}APU_DECLARE(apr_status_t) apr_brigade_writev(apr_bucket_brigade *b, apr_brigade_flush flush, void *ctx, const struct iovec *vec, apr_size_t nvec){ apr_bucket *e; apr_size_t total_len; apr_size_t i; char *buf; /* Compute the total length of the data to be written. */ total_len = 0; for (i = 0; i < nvec; i++) { total_len += vec[i].iov_len; } /* If the data to be written is very large, try to convert * the iovec to transient buckets rather than copying. */ if (total_len > APR_BUCKET_BUFF_SIZE) { if (flush) { for (i = 0; i < nvec; i++) { e = apr_bucket_transient_create(vec[i].iov_base, vec[i].iov_len, b->bucket_alloc); APR_BRIGADE_INSERT_TAIL(b, e); } return flush(b, ctx); } else { for (i = 0; i < nvec; i++) { e = apr_bucket_heap_create((const char *) vec[i].iov_base, vec[i].iov_len, NULL, b->bucket_alloc); APR_BRIGADE_INSERT_TAIL(b, e); } return APR_SUCCESS; } } i = 0; /* If there is a heap bucket at the end of the brigade * already, copy into the existing bucket. */ e = APR_BRIGADE_LAST(b); if (!APR_BRIGADE_EMPTY(b) && APR_BUCKET_IS_HEAP(e)) { apr_bucket_heap *h = e->data; apr_size_t remaining = h->alloc_len - (e->length + (apr_size_t)e->start); buf = h->base + e->start + e->length; if (remaining >= total_len) { /* Simple case: all the data will fit in the * existing heap bucket */ for (; i < nvec; i++) { apr_size_t len = vec[i].iov_len; memcpy(buf, (const void *) vec[i].iov_base, len); buf += len; } e->length += total_len; return APR_SUCCESS; } else { /* More complicated case: not all of the data * will fit in the existing heap bucket. The * total data size is <= APR_BUCKET_BUFF_SIZE, * so we'll need only one additional bucket. */ const char *start_buf = buf; for (; i < nvec; i++) { apr_size_t len = vec[i].iov_len; if (len > remaining) { break; } memcpy(buf, (const void *) vec[i].iov_base, len); buf += len; remaining -= len; } e->length += (buf - start_buf); total_len -= (buf - start_buf); if (flush) { apr_status_t rv = flush(b, ctx); if (rv != APR_SUCCESS) { return rv; } } /* Now fall through into the case below to * allocate another heap bucket and copy the * rest of the array. (Note that i is not * reset to zero here; it holds the index * of the first vector element to be * written to the new bucket.) */ } } /* Allocate a new heap bucket, and copy the data into it. * The checks above ensure that the amount of data to be * written here is no larger than APR_BUCKET_BUFF_SIZE. */ buf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->bucket_alloc); e = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE, apr_bucket_free, b->bucket_alloc); for (; i < nvec; i++) { apr_size_t len = vec[i].iov_len; memcpy(buf, (const void *) vec[i].iov_base, len); buf += len; } e->length = total_len; APR_BRIGADE_INSERT_TAIL(b, e); return APR_SUCCESS;}APU_DECLARE(apr_status_t) apr_brigade_puts(apr_bucket_brigade *bb, apr_brigade_flush flush, void *ctx, const char *str){ apr_size_t len = strlen(str); apr_bucket *bkt = APR_BRIGADE_LAST(bb); if (!APR_BRIGADE_EMPTY(bb) && APR_BUCKET_IS_HEAP(bkt)) { /* If there is enough space available in a heap bucket * at the end of the brigade, copy the string directly * into the heap bucket */ apr_bucket_heap *h = bkt->data; apr_size_t bytes_avail = h->alloc_len - bkt->length; if (bytes_avail >= len) { char *buf = h->base + bkt->start + bkt->length; memcpy(buf, str, len); bkt->length += len; return APR_SUCCESS; } } /* If the string could not be copied into an existing heap * bucket, delegate the work to apr_brigade_write(), which * knows how to grow the brigade */ return apr_brigade_write(bb, flush, ctx, str, len);}APU_DECLARE_NONSTD(apr_status_t) apr_brigade_putstrs(apr_bucket_brigade *b, apr_brigade_flush flush, void *ctx, ...){ va_list va; apr_status_t rv; va_start(va, ctx); rv = apr_brigade_vputstrs(b, flush, ctx, va); va_end(va); return rv;}APU_DECLARE_NONSTD(apr_status_t) apr_brigade_printf(apr_bucket_brigade *b, apr_brigade_flush flush, void *ctx, const char *fmt, ...){ va_list ap; apr_status_t rv; va_start(ap, fmt); rv = apr_brigade_vprintf(b, flush, ctx, fmt, ap); va_end(ap); return rv;}struct brigade_vprintf_data_t { apr_vformatter_buff_t vbuff; apr_bucket_brigade *b; /* associated brigade */ apr_brigade_flush *flusher; /* flushing function */ void *ctx; char *cbuff; /* buffer to flush from */};static apr_status_t brigade_flush(apr_vformatter_buff_t *buff){ /* callback function passed to ap_vformatter to be * called when vformatter needs to buff and * buff.curpos > buff.endpos */ /* "downcast," have really passed a brigade_vprintf_data_t* */ struct brigade_vprintf_data_t *vd = (struct brigade_vprintf_data_t*)buff; apr_status_t res = APR_SUCCESS; res = apr_brigade_write(vd->b, *vd->flusher, vd->ctx, vd->cbuff, APR_BUCKET_BUFF_SIZE); if(res != APR_SUCCESS) { return -1; } vd->vbuff.curpos = vd->cbuff; vd->vbuff.endpos = vd->cbuff + APR_BUCKET_BUFF_SIZE; return res;}APU_DECLARE(apr_status_t) apr_brigade_vprintf(apr_bucket_brigade *b, apr_brigade_flush flush, void *ctx, const char *fmt, va_list va){ /* the cast, in order of appearance */ struct brigade_vprintf_data_t vd; char buf[APR_BUCKET_BUFF_SIZE]; apr_size_t written; vd.vbuff.curpos = buf; vd.vbuff.endpos = buf + APR_BUCKET_BUFF_SIZE; vd.b = b; vd.flusher = &flush; vd.ctx = ctx; vd.cbuff = buf; written = apr_vformatter(brigade_flush, &vd.vbuff, fmt, va); if (written == -1) { return -1; } /* tack on null terminator to remaining string */ *(vd.vbuff.curpos) = '\0'; /* write out what remains in the buffer */ return apr_brigade_write(b, flush, ctx, buf, vd.vbuff.curpos - buf);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -