📄 apr_buckets.h
字号:
* destroy the bucket it points to, then APR_BRIGADE_FOREACH * will have no way to find out what bucket to use for its next * iteration. The reason for this can be seen by looking closely * at the equivalent loops given in the tip above. So, for example, * if you are writing a loop that empties out a brigade one bucket * at a time, APR_BRIGADE_FOREACH just won't work for you. Do it * by hand, like so: * <pre> * while (!APR_BRIGADE_EMPTY(b)) { * e = APR_BRIGADE_FIRST(b); * ... * apr_bucket_delete(e); * } * </pre> * @deprecated This macro causes more headaches than it's worth. Use * one of the alternatives documented here instead; the clarity gained * in what's really going on is well worth the extra line or two of code. * This macro will be removed at some point in the future. */#define APR_BRIGADE_FOREACH(e, b) \ APR_RING_FOREACH((e), &(b)->list, apr_bucket, link)/** * Insert a list of buckets at the front of a brigade * @param b The brigade to add to * @param e The first bucket in a list of buckets to insert */#define APR_BRIGADE_INSERT_HEAD(b, e) do { \ apr_bucket *ap__b = (e); \ APR_RING_INSERT_HEAD(&(b)->list, ap__b, apr_bucket, link); \ APR_BRIGADE_CHECK_CONSISTENCY((b)); \ } while (0)/** * Insert a list of buckets at the end of a brigade * @param b The brigade to add to * @param e The first bucket in a list of buckets to insert */#define APR_BRIGADE_INSERT_TAIL(b, e) do { \ apr_bucket *ap__b = (e); \ APR_RING_INSERT_TAIL(&(b)->list, ap__b, apr_bucket, link); \ APR_BRIGADE_CHECK_CONSISTENCY((b)); \ } while (0)/** * Concatenate brigade b onto the end of brigade a, leaving brigade b empty * @param a The first brigade * @param b The second brigade */#define APR_BRIGADE_CONCAT(a, b) do { \ APR_RING_CONCAT(&(a)->list, &(b)->list, apr_bucket, link); \ APR_BRIGADE_CHECK_CONSISTENCY((a)); \ } while (0)/** * Prepend brigade b onto the beginning of brigade a, leaving brigade b empty * @param a The first brigade * @param b The second brigade */#define APR_BRIGADE_PREPEND(a, b) do { \ APR_RING_PREPEND(&(a)->list, &(b)->list, apr_bucket, link); \ APR_BRIGADE_CHECK_CONSISTENCY((a)); \ } while (0)/** * Insert a list of buckets before a specified bucket * @param a The bucket to insert before * @param b The buckets to insert */#define APR_BUCKET_INSERT_BEFORE(a, b) do { \ apr_bucket *ap__a = (a), *ap__b = (b); \ APR_RING_INSERT_BEFORE(ap__a, ap__b, link); \ APR_BUCKET_CHECK_CONSISTENCY(ap__a); \ } while (0)/** * Insert a list of buckets after a specified bucket * @param a The bucket to insert after * @param b The buckets to insert */#define APR_BUCKET_INSERT_AFTER(a, b) do { \ apr_bucket *ap__a = (a), *ap__b = (b); \ APR_RING_INSERT_AFTER(ap__a, ap__b, link); \ APR_BUCKET_CHECK_CONSISTENCY(ap__a); \ } while (0)/** * Get the next bucket in the list * @param e The current bucket * @return The next bucket */#define APR_BUCKET_NEXT(e) APR_RING_NEXT((e), link)/** * Get the previous bucket in the list * @param e The current bucket * @return The previous bucket */#define APR_BUCKET_PREV(e) APR_RING_PREV((e), link)/** * Remove a bucket from its bucket brigade * @param e The bucket to remove */#define APR_BUCKET_REMOVE(e) APR_RING_REMOVE((e), link)/** * Initialize a new bucket's prev/next pointers * @param e The bucket to initialize */#define APR_BUCKET_INIT(e) APR_RING_ELEM_INIT((e), link)/** * Determine if a bucket contains metadata. An empty bucket is * safe to arbitrarily remove if and only if this is false. * @param e The bucket to inspect * @return true or false */#define APR_BUCKET_IS_METADATA(e) ((e)->type->is_metadata)/** * Determine if a bucket is a FLUSH bucket * @param e The bucket to inspect * @return true or false */#define APR_BUCKET_IS_FLUSH(e) ((e)->type == &apr_bucket_type_flush)/** * Determine if a bucket is an EOS bucket * @param e The bucket to inspect * @return true or false */#define APR_BUCKET_IS_EOS(e) ((e)->type == &apr_bucket_type_eos)/** * Determine if a bucket is a FILE bucket * @param e The bucket to inspect * @return true or false */#define APR_BUCKET_IS_FILE(e) ((e)->type == &apr_bucket_type_file)/** * Determine if a bucket is a PIPE bucket * @param e The bucket to inspect * @return true or false */#define APR_BUCKET_IS_PIPE(e) ((e)->type == &apr_bucket_type_pipe)/** * Determine if a bucket is a SOCKET bucket * @param e The bucket to inspect * @return true or false */#define APR_BUCKET_IS_SOCKET(e) ((e)->type == &apr_bucket_type_socket)/** * Determine if a bucket is a HEAP bucket * @param e The bucket to inspect * @return true or false */#define APR_BUCKET_IS_HEAP(e) ((e)->type == &apr_bucket_type_heap)/** * Determine if a bucket is a TRANSIENT bucket * @param e The bucket to inspect * @return true or false */#define APR_BUCKET_IS_TRANSIENT(e) ((e)->type == &apr_bucket_type_transient)/** * Determine if a bucket is a IMMORTAL bucket * @param e The bucket to inspect * @return true or false */#define APR_BUCKET_IS_IMMORTAL(e) ((e)->type == &apr_bucket_type_immortal)#if APR_HAS_MMAP/** * Determine if a bucket is a MMAP bucket * @param e The bucket to inspect * @return true or false */#define APR_BUCKET_IS_MMAP(e) ((e)->type == &apr_bucket_type_mmap)#endif/** * Determine if a bucket is a POOL bucket * @param e The bucket to inspect * @return true or false */#define APR_BUCKET_IS_POOL(e) ((e)->type == &apr_bucket_type_pool)/* * General-purpose reference counting for the various bucket types. * * Any bucket type that keeps track of the resources it uses (i.e. * most of them except for IMMORTAL, TRANSIENT, and EOS) needs to * attach a reference count to the resource so that it can be freed * when the last bucket that uses it goes away. Resource-sharing may * occur because of bucket splits or buckets that refer to globally * cached data. *//** @see apr_bucket_refcount */typedef struct apr_bucket_refcount apr_bucket_refcount;/** * The structure used to manage the shared resource must start with an * apr_bucket_refcount which is updated by the general-purpose refcount * code. A pointer to the bucket-type-dependent private data structure * can be cast to a pointer to an apr_bucket_refcount and vice versa. */struct apr_bucket_refcount { /** The number of references to this bucket */ int refcount;};/* ***** Reference-counted bucket types ***** *//** @see apr_bucket_heap */typedef struct apr_bucket_heap apr_bucket_heap;/** * A bucket referring to data allocated off the heap. */struct apr_bucket_heap { /** Number of buckets using this memory */ apr_bucket_refcount refcount; /** The start of the data actually allocated. This should never be * modified, it is only used to free the bucket. */ char *base; /** how much memory was allocated */ apr_size_t alloc_len; /** function to use to delete the data */ void (*free_func)(void *data);};/** @see apr_bucket_pool */typedef struct apr_bucket_pool apr_bucket_pool;/** * A bucket referring to data allocated from a pool */struct apr_bucket_pool { /** The pool bucket must be able to be easily morphed to a heap * bucket if the pool gets cleaned up before all references are * destroyed. This apr_bucket_heap structure is populated automatically * when the pool gets cleaned up, and subsequent calls to pool_read() * will result in the apr_bucket in question being morphed into a * regular heap bucket. (To avoid having to do many extra refcount * manipulations and b->data manipulations, the apr_bucket_pool * struct actually *contains* the apr_bucket_heap struct that it * will become as its first element; the two share their * apr_bucket_refcount members.) */ apr_bucket_heap heap; /** The block of data actually allocated from the pool. * Segments of this block are referenced by adjusting * the start and length of the apr_bucket accordingly. * This will be NULL after the pool gets cleaned up. */ const char *base; /** The pool the data was allocated from. When the pool * is cleaned up, this gets set to NULL as an indicator * to pool_read() that the data is now on the heap and * so it should morph the bucket into a regular heap * bucket before continuing. */ apr_pool_t *pool; /** The freelist this structure was allocated from, which is * needed in the cleanup phase in order to allocate space on the heap */ apr_bucket_alloc_t *list;};#if APR_HAS_MMAP/** @see apr_bucket_mmap */typedef struct apr_bucket_mmap apr_bucket_mmap;/** * A bucket referring to an mmap()ed file */struct apr_bucket_mmap { /** Number of buckets using this memory */ apr_bucket_refcount refcount; /** The mmap this sub_bucket refers to */ apr_mmap_t *mmap;};#endif/** @see apr_bucket_file */typedef struct apr_bucket_file apr_bucket_file;/** * A bucket referring to an file */struct apr_bucket_file { /** Number of buckets using this memory */ apr_bucket_refcount refcount; /** The file this bucket refers to */ apr_file_t *fd; /** The pool into which any needed structures should * be created while reading from this file bucket */ apr_pool_t *readpool;#if APR_HAS_MMAP /** Whether this bucket should be memory-mapped if * a caller tries to read from it */ int can_mmap;#endif /* APR_HAS_MMAP */};/** @see apr_bucket_structs */typedef union apr_bucket_structs apr_bucket_structs;/** * A union of all bucket structures so we know what * the max size is. */union apr_bucket_structs { apr_bucket b; /**< Bucket */ apr_bucket_heap heap; /**< Heap */ apr_bucket_pool pool; /**< Pool */#if APR_HAS_MMAP apr_bucket_mmap mmap; /**< MMap */#endif apr_bucket_file file; /**< File */};/** * The amount that apr_bucket_alloc() should allocate in the common case. * Note: this is twice as big as apr_bucket_structs to allow breathing * room for third-party bucket types. */#define APR_BUCKET_ALLOC_SIZE APR_ALIGN_DEFAULT(2*sizeof(apr_bucket_structs))/* ***** Bucket Brigade Functions ***** *//** * Create a new bucket brigade. The bucket brigade is originally empty. * @param p The pool to associate with the brigade. Data is not allocated out * of the pool, but a cleanup is registered. * @param list The bucket allocator to use * @return The empty bucket brigade */APU_DECLARE(apr_bucket_brigade *) apr_brigade_create(apr_pool_t *p, apr_bucket_alloc_t *list);/** * destroy an entire bucket brigade. This includes destroying all of the * buckets within the bucket brigade's bucket list. * @param b The bucket brigade to destroy */APU_DECLARE(apr_status_t) apr_brigade_destroy(apr_bucket_brigade *b);/** * empty out an entire bucket brigade. This includes destroying all of the * buckets within the bucket brigade's bucket list. This is similar to * apr_brigade_destroy(), except that it does not deregister the brigade's * pool cleanup function. * @param data The bucket brigade to clean up * @remark Generally, you should use apr_brigade_destroy(). This function * can be useful in situations where you have a single brigade that * you wish to reuse many times by destroying all of the buckets in * the brigade and putting new buckets into it later. */APU_DECLARE(apr_status_t) apr_brigade_cleanup(void *data);/** * Split a bucket brigade into two, such that the given bucket is the * first in the new bucket brigade. This function is useful when a * filter wants to pass only the initial part of a brigade to the next * filter. * @param b The brigade to split * @param e The first element of the new brigade * @return The new brigade */APU_DECLARE(apr_bucket_brigade *) apr_brigade_split(apr_bucket_brigade *b, apr_bucket *e);/** * Partition a bucket brigade at a given offset (in bytes from the start of * the brigade). This is useful whenever a filter wants to use known ranges * of bytes from the brigade; the ranges can even overlap. * @param b The brigade to partition * @param point The offset at which to partition the brigade * @param after_point Returns a pointer to the first bucket after the partition */APU_DECLARE(apr_status_t) apr_brigade_partition(apr_bucket_brigade *b, apr_off_t point, apr_bucket **after_point);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -