ONC+ 開発ガイド

識別型の共用体

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)(); /* may equal NULL */
  

このルーチンでは、最初に *dscmp にある要素識別子を変換します。要素識別子は常に enum_t 型です。次に、*unp にある共用体が変換されます。引数 armsxdr_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;
};
  

例 A-12 では、合成データと XDR 手続きで、識別型共用体のシリアライズ (またはデシリアライズ) を行います。


例 A-12 XDR 識別型の共用体サンプルプログラム

struct xdr_discrim u_tag_arms[4] = {
 	{INTEGER, xdr_int},
 	{GNUMBERS, xdr_gnumbers}
 	{STRING, xdr_wrapstring},
 	{__dontcare__, NULL}
 	/* アームの最後は常に 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_wrapstring() はサンプルプログラム C に示しました。この例では、xdr_union()のデフォルトの arm 引数 (最後の引数) には NULL を渡しています。したがって、共用体の要素識別子の値は、u_tag_arms 配列に表示された値のどれかになります。また、この例から、arm 配列の要素はソートされていなくてもよいことがわかります。

要素識別子は、この例では連続した値を取っていますが、連続していなくてもかまいません。要素識別子の型の各要素に、明示的に整数値を割り当てておくと、要素識別子の外部表現として明記でき、異なる C コンパイラでも要素識別子が同じ値で出力されることが保証されます。

練習

この節の他のプリミティブを使用して xdr_union() を作成してください。