フィルタの勉強: ブリッジの回し方とAPI

バケットを詰め替える場合

while (!APR_BRIGADE_EMPTY(bb)) {
  apr_bucket *e = APR_BRIGADE_FIRST(bb);

  if (APR_BUCKET_IS_EOS(e)) { // APR_BUCKET_IS_EOCはなくなったよう
    // ストリームの終端
    APR_BUCKET_REMOVE(e);
    APR_BRIGADE_INSERT_TAIL(bbout, e);
    break;
  }

  if (APR_BUCKET_IS_FLUSH(e)) {
    // バッファの出力を指示するメタバケット
    APR_BUCKET_REMOVE(e);
    APR_BRIGADE_INSERT_TAIL(bbout, e);
    continue;
  }

  if (APR_BUCKET_IS_METADATA(e)) {
    // メタバケットの判定
  // flushもメタバケットのひとつ
    APR_BUCKET_REMOVE(e);
    APR_BRIGADE_INSERT_TAIL(bbout, e);
    continue;
  }

  // フィルタリング処理など
  APR_BRIGADE_INSERT_TAIL(bbout, b);
  apr_bucket_delete(e);
}

入力されたブリッジのバケットを新しいブリッジに詰め替える場合は、入力ブリッジのバケットを削除しながら回すのでwhile (!APR_BRIGADE_EMPTY(bb))を使う。
メタバケットは基本的にブリッジを移し替えるだけ。flushの指示に従うかは任意でよいのかな?
APR_BUCKET_REMOVE(e)でブリッジが指す先頭バケットのポインタが変わるように思える。*1
apr_bucket_delete(e)は小文字だけど(なんで?)マクロ。

#define apr_bucket_delete(e) do {					\
        APR_BUCKET_REMOVE(e);						\
        apr_bucket_destroy(e);						\
    } while (0)

バケットの種類はこちらを参照。

バケットをなめるだけ

for (e = APR_BRIGADE_FIRST(bb); e != APR_BRIGADE_SENTINEL(bb); e = APR_BUCKET_NEXT(e)) {
  if (APR_BUCKET_IS_EOS(e)) {
    // ストリームの終端
    break;
  }
}

// 入力ブリッジを、そのまま次の出力フィルタに渡す
ap_pass_brigade(f->next, bb);

入力ブリッジに手を加えない場合はfor (e = APR_BRIGADE_FIRST(bb);〜で回す。
はじめAPR_BRIGADE_EMPTY(bb)APR_BRIGADE_SENTINEL(bb)の違いがよく分からなかった。APR_BUCKET_NEXT(e)は、たぶんブリッジの指す先頭バケットのポインタを変更しないで、次のバケットのポインタを返すんだと思う。

*1:リンクリストのコンテナってなんだかへんな感じ。リンクリスト自体がコンテナのように見える