■
struct apr_bucket_type_t { //このbucketのタイプ名 const char *name; //このbucketが理解出来る関数の数. 5未満は駄目 int num_func; //bucketがメタデータを含んでいるかどうか enum { APR_BUCKET_DATA = 0, APR_BUCKET_METADATA = 1 } is_metadata; //bucketが使っているデータの開放(free)。ただし、他のbucketと //共有してない場合。 void (*destroy)(void *data); //bucketからデータを読み取る apr_status_t (*read)(apr_bucket *b, const char **str, apr_size_t *len, apr_read_type_e block); //bucketのデータをpoolに入れて取っておく? //通常bucketデータはこのpoolに入れておかないと破棄される? apr_status_t (*setaside)(apr_bucket *e, apr_pool_t *pool); //bucketの分割 apr_status_t (*split)(apr_bucket *e, apr_size_t point); //bucketのコピー apr_status_t (*copy)(apr_bucket *e, apr_bucket **c); };
bucketの基本操作を関数ポインタで持った構造体
struct apr_bucket { APR_RING_ENTRY(apr_bucket) link; const apr_bucket_type_t *type; apr_size_t length; //bucketの長さ、知られていなければ-1 apr_off_t start; void *data; void (*free)(void *e); apr_bucket_alloc_t *list; };
bucket構造体の本体でring構造を持ち(APR_RING_ENTRY)brigateのLinkとして繋いでいく。
dataがこのbucketが示すデータへのポインタで
freeはこのbucketを開放する関数ポインタ(たとえばfree())
listはこのbucketがallocateされているfreelistへのポインタ。
※このポインタとfreeで実際に開放が行われている?
struct apr_bucket_brigade { // brigade用のpool?よくわからない。 apr_pool_t *p; // このbrigadeに繋げるbucket ringのhead APR_RING_HEAD(apr_bucket_list, par_bucket) list; // このbucketがallocateされているfreelistへのポインタ apr_bucket_alloc_t *bucket_alloc; }; || *brigadeの操作用マクロ群 >|c| #define APR_BRIGADE_SENTINEL(b) APR_RING_SENTINEL(&(b)->list, apr_bucket, link) //このbrigadeの番兵(head位置) #define APR_BRIGADE_EMPTY(b) APR_RING_EMPTY(&(b)->list, apr_bucket, link) //brigadeが空かどうか #define APR_BRIGADE_FIRST(b) APR_RING_FIRST(&(b)->list) #define APR_BRIGADE_LAST(b) APR_RING_LAST(&(b)->list)
#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) || brigade「b」の先頭にbucket「e」を挿入 >|c| #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)
brigade「b」の最後尾にbucket「e」を挿入
#define APR_BRIGADE_CONCAT(a, b) #define APR_BRIGADE_PREPEND(a, b) #define APR_BUCKET_NEXT(e) APR_RING_NEXT((e), link) #define APR_BUCKET_REMOVE(e) APR_RING_REMOVE((e), link) #define APR_BUCKET_INIT(e) APR_RING_ELEM_INIT((e), link) #define APR_BUCKET_IS_XXX // bucket内のtype調査マクロ群
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 */ };
apr_bucketの共用体。heap用、pool用、mmap用、file用などがある。
以下brigade関連の操作関数
//brigadeを新しく作る APU_DECLARE(apr_bucket_brigade *) apr_brigade_create(apr_pool_t *p, apr_bucket_alloc_t *list); //このbrigadeのbucket全て消し、自分も消す APU_DECLARE(apr_status_t) apr_brigade_destroy(apr_bucket_brigade *b); //このbrigadeのbucketを全て消し空にする。 APU_DECLARE(apr_status_t) apr_brigade_cleanup(void *data); //eでbrigadeを分割し新しく出来たbrigade(eを含む)を返す APU_DECLARE(apr_bucket_brigade *) apr_brigade_split(apr_bucket_brigade *b, apr_bucket *e); //brigade bをオフセット pointの位置で分割し、after_pointで分割後のポインタ位置を返す。(splitとの違いは新しくbrigadeを作ってそれを返すかどうか???) APU_DECLARE(apr_status_t) apr_brigade_partition(apr_bucket_brigade *b, apr_off_t point, apr_bucket **after_point); //このbrigadeの長さを返す APU_DECLARE(apr_status_t) apr_brigade_length(apr_bucket_brigade *bb, int read_all, apr_off_t *length); //byte系のデータをこのbrigadeに追加?(新しくbucketを作ってる?) APU_DECLARE(apr_status_t) apr_brigade_flatten(apr_bucket_brigade *bb, char *c, apr_size_t *len); APU_DECLARE(apr_status_t) apr_brigade_pflatten(apr_bucket_brigade *bb, char **c, apr_size_t *len, apr_pool_t *pool); //1行毎の分割用 HTTP用 APU_DECLARE(apr_status_t) apr_brigade_split_line(apr_bucket_brigade *bbOut, apr_bucket_brigade *bbIn, apr_read_type_e block, apr_off_t maxbytes); APU_DECLARE(apr_status_t) apr_brigade_to_iovec(apr_bucket_brigade *b, struct iovec *vec, int *nvec); //以下brigadeへの書き込み関数 APU_DECLARE(apr_status_t) apr_brigade_vputstrs(apr_bucket_brigade *b, apr_brigade_flush flush, void *ctx, va_list va); 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); 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); APU_DECLARE(apr_status_t) apr_brigade_puts(apr_bucket_brigade *bb, apr_brigade_flush flush, void *ctx, const char *str); APU_DECLARE(apr_status_t) apr_brigade_putc(apr_bucket_brigade *b, apr_brigade_flush flush, void *ctx, const char c); APU_DECLARE_NONSTD(apr_status_t) apr_brigade_putstrs(apr_bucket_brigade *b, apr_brigade_flush flush, void *ctx, ...); APU_DECLARE_NONSTD(apr_status_t) apr_brigade_printf(apr_bucket_brigade *b, apr_brigade_flush flush, void *ctx, const char *fmt, ...) __attribute__((format(printf,4,5))); //ファイル挿入用 APU_DECLARE(apr_bucket *) apr_brigade_insert_file(apr_bucket_brigade *bb, apr_file_t *f, apr_off_t start, apr_off_t len, apr_pool_t *p);