XDR ライブラリは識別型の共用体もサポートしています。識別型の共用体は、C の共用体に、共用体の「アーム」を選択する enum_t型の値が付加されたものです。
struct xdr_discrim { enum_t value; bool_t (*proc)(); }; bool_t xdr_union(xdrs, dscmp, unp, arms, defaultarm) XDR *xdrs; enum_t *dscmp; char *unp; struct xdr_discrim *arms; bool_t (*defaultarm)(); /* NULL と同じ */
このルーチンでは、最初に *dscmp にある要素識別子を変換します。要素識別子は常に enum_t 型です。次に、*unp にある共用体が変換されます。引数 arms は xdr_discrim 構造体配列へのポインタです。各構造体には、[value,proc] のペアが入っています。共用体の要素識別子が対応する value と一致すれば、それに対する proc() が呼び出されて共用体が変換されます。xdr_discrim 構造体配列の終わりは、ルーチンの値が NULL(0) なので判別できます。arms 配列の中に要素識別子に一致するものがない場合は、defaultarm() 手続きが NULL でなければそれが呼び出されます。NULL の場合は FALSE を返します。
共用体のデータ型は、整数、文字へのポインタ (文字列)、gnumbers 構造体のどれかで、共用体と現在の型は構造体で宣言されています。 宣言は次のようになります。
enum utype {INTEGER=1, STRING=2, GNUMBERS=3}; struct u_tag { enum utype utype; /* 共用体の要素識別子 */ union { int ival; char *pval; struct gnumbers gn; } uval; };
次のサンプルプログラムでは、XDR プロシージャを構築し、識別型の共用体をデシリアライズします。
struct xdr_discrim u_tag_arms[4] = { {INTEGER, xdr_int}, {GNUMBERS, xdr_gnumbers} {STRING, xdr_wrapstring}, {__dontcare__, NULL} /* arm の最後は常に NULL の xdr_proc */ } bool_t xdr_u_tag(xdrs, utp) XDR *xdrs; struct u_tag *utp; { return(xdr_union(xdrs, &utp->utype, &utp->uval, u_tag_arms, NULL)); } |
ルーチン xdr_gnumbers() は XDR ライブラリ 内で説明しました。 この例では、xdr_union() のデフォルトの arm 引数 (最後の引数) には、 NULL を渡しています。 したがって、共用体の要素識別子の値は、u_tag_arms 配列に表示された値のどれかになります。例 A–12 もまたアームの配列内要素をソートする必要がないことを示しています。
要素識別子は、この例では連続した値をとっていますが、連続しない値でも構いません。要素識別子の型の各要素に、明示的に整数値を割り当てておくと、要素識別子の外部表現として明記でき、異なる C コンパイラでも要素識別子が同じ値で出力されることが保証されます。