APU_DECLARE(apr_bucket_brigade *) apr_brigade_split_ex(apr_bucket_brigade *b, apr_bucket *e, apr_bucket_brigade *a) { apr_bucket *f; if (!a) { a = apr_brigade_create(b->p, b->bucket_alloc); } else if (!APR_BRIGADE_EMPTY(a)) { apr_brigade_cleanup(a); } /* Return an empty brigade if there is nothing left in * the first brigade to split off */ if (e != APR_BRIGADE_SENTINEL(b)) { f = APR_RING_LAST(&b->list); APR_RING_UNSPLICE(e, f, link); APR_RING_SPLICE_HEAD(&a->list, e, f, apr_bucket, link); } APR_BRIGADE_CHECK_CONSISTENCY(a); APR_BRIGADE_CHECK_CONSISTENCY(b); return a; }
/** * Split the contents of a brigade after bucket 'e' to an existing brigade * * XXXX: Should this function be added to APR-Util? */ static void brigade_move(apr_bucket_brigade *b, apr_bucket_brigade *a, apr_bucket *e) { apr_bucket *f; if (e != APR_BRIGADE_SENTINEL(b)) { f = APR_RING_LAST(&b->list); APR_RING_UNSPLICE(e, f, link); APR_RING_SPLICE_HEAD(&a->list, e, f, apr_bucket, link); } APR_BRIGADE_CHECK_CONSISTENCY(a); APR_BRIGADE_CHECK_CONSISTENCY(b); }
APU_DECLARE(apr_status_t) apr_brigade_partition(apr_bucket_brigade *b, apr_off_t point, apr_bucket **after_point) { apr_bucket *e; const char *s; apr_size_t len; apr_uint64_t point64; apr_status_t rv; if (point < 0) { /* this could cause weird (not necessarily SEGV) things to happen */ return APR_EINVAL; } if (point == 0) { *after_point = APR_BRIGADE_FIRST(b); return APR_SUCCESS; } /* * Try to reduce the following casting mess: We know that point will be * larger equal 0 now and forever and thus that point (apr_off_t) and * apr_size_t will fit into apr_uint64_t in any case. */ point64 = (apr_uint64_t)point; APR_BRIGADE_CHECK_CONSISTENCY(b); for (e = APR_BRIGADE_FIRST(b); e != APR_BRIGADE_SENTINEL(b); e = APR_BUCKET_NEXT(e)) { /* For an unknown length bucket, while 'point64' is beyond the possible * size contained in apr_size_t, read and continue... */ if ((e->length == (apr_size_t)(-1)) && (point64 > (apr_uint64_t)APR_SIZE_MAX)) { /* point64 is too far out to simply split this bucket, * we must fix this bucket's size and keep going... */ rv = apr_bucket_read(e, &s, &len, APR_BLOCK_READ); if (rv != APR_SUCCESS) { *after_point = e; return rv; } } else if ((point64 < (apr_uint64_t)e->length) || (e->length == (apr_size_t)(-1))) { /* We already consumed buckets where point64 is beyond * our interest ( point64 > APR_SIZE_MAX ), above. * Here point falls between 0 and APR_SIZE_MAX * and is within this bucket, or this bucket's len * is undefined, so now we are ready to split it. * First try to split the bucket natively... */ if ((rv = apr_bucket_split(e, (apr_size_t)point64)) != APR_ENOTIMPL) { *after_point = APR_BUCKET_NEXT(e); return rv; } /* if the bucket cannot be split, we must read from it, * changing its type to one that can be split */ rv = apr_bucket_read(e, &s, &len, APR_BLOCK_READ); if (rv != APR_SUCCESS) { *after_point = e; return rv; } /* this assumes that len == e->length, which is okay because e * might have been morphed by the apr_bucket_read() above, but * if it was, the length would have been adjusted appropriately */ if (point64 < (apr_uint64_t)e->length) { rv = apr_bucket_split(e, (apr_size_t)point64); *after_point = APR_BUCKET_NEXT(e); return rv; } } if (point64 == (apr_uint64_t)e->length) { *after_point = APR_BUCKET_NEXT(e); return APR_SUCCESS; } point64 -= (apr_uint64_t)e->length; } *after_point = APR_BRIGADE_SENTINEL(b); return APR_INCOMPLETE; }
APU_DECLARE(apr_status_t) apr_brigade_partition(apr_bucket_brigade *b, apr_off_t point, apr_bucket **after_point) { apr_bucket *e; const char *s; apr_size_t len; apr_status_t rv; if (point < 0) { /* this could cause weird (not necessarily SEGV) things to happen */ return APR_EINVAL; } if (point == 0) { *after_point = APR_BRIGADE_FIRST(b); return APR_SUCCESS; } APR_BRIGADE_CHECK_CONSISTENCY(b); for (e = APR_BRIGADE_FIRST(b); e != APR_BRIGADE_SENTINEL(b); e = APR_BUCKET_NEXT(e)) { if ((e->length == (apr_size_t)(-1)) && (point > (apr_size_t)(-1))) { /* point is too far out to simply split this bucket, * we must fix this bucket's size and keep going... */ rv = apr_bucket_read(e, &s, &len, APR_BLOCK_READ); if (rv != APR_SUCCESS) { *after_point = e; return rv; } } if ((point < e->length) || (e->length == (apr_size_t)(-1))) { /* We already checked e->length -1 above, so we now * trust e->length < MAX_APR_SIZE_T. * First try to split the bucket natively... */ if ((rv = apr_bucket_split(e, (apr_size_t)point)) != APR_ENOTIMPL) { *after_point = APR_BUCKET_NEXT(e); return rv; } /* if the bucket cannot be split, we must read from it, * changing its type to one that can be split */ rv = apr_bucket_read(e, &s, &len, APR_BLOCK_READ); if (rv != APR_SUCCESS) { *after_point = e; return rv; } /* this assumes that len == e->length, which is okay because e * might have been morphed by the apr_bucket_read() above, but * if it was, the length would have been adjusted appropriately */ if (point < e->length) { rv = apr_bucket_split(e, (apr_size_t)point); *after_point = APR_BUCKET_NEXT(e); return rv; } } if (point == e->length) { *after_point = APR_BUCKET_NEXT(e); return APR_SUCCESS; } point -= e->length; } *after_point = APR_BRIGADE_SENTINEL(b); return APR_INCOMPLETE; }