この節では、新たな XDR ストリームインスタンスの作成に必要な抽象データ型を示します。
例 A-13 の構造体は、XDRストリームとのインタフェースを定義します。
enum xdr_op {XDR_ENCODE=0, XDR_DECODE=1, XDR_FREE=2}; typedef struct { enum xdr_op x_op; struct xdr_ops { bool_t (*x_getlong)(); /* ストリームから long 型データを入力 */ bool_t (*x_putlong)(); /* ストリームに long 型データを出力 */ bool_t (*x_getbytes)(); /* ストリームから複数バイトを入力 */ bool_t (*x_putbytes)(); /* ストリームに複数バイトを出力 */ u_int (*x_getpostn)(); /* ストリームのオフセットを返す */ bool_t (*x_setpostn)(); /* オフセットの再設定 */ caddr_t (*x_inline)(); /* バッファリングされたデータへのポインタ */ VOID (*x_destroy)(); /* プライベートエリアの解放 */ } *x_ops; caddr_t x_public; /* ユーザデータ */ caddr_t x_private; /* プライベートデータへのポインタa */ caddr_t x_base; /* 位置情報のためのプライベートデータ */ int x_handy; /* その他のプライベートワード */ } XDR;
x_op フィールドは、現在ストリームに対して実行している処理内容を示します。このフィールドはXDR プリミティブにとっては重要なフィールドですが、ストリームの実現に対しては影響ありません。すなわち、ストリームは、この値に依存した方法で作成してはいけません。x_private、x_base、x_handy の各フィールドは、特定のストリームを実現するためのプライベートデータです。x_public は XDR クライアントのためのフィールドですので、XDR ストリームを実現するために使用したり、XDR プリミティブで使用したりしてはいけません。x_getpostn()、x_setpostn()、x_destroy() はストリームへのアクセス操作に使用するマクロです。x_inline() ルーチンには、XDR * と符号なし整数 (バイトカウント) の 2 つの引数を渡します。このルーチンからは、ストリームの内部バッファセグメントへのポインタが返されます。呼び出し側ではそのバッファセグメントを自由に使用できます。ストリーム側からみると、そのバッファセグメントに入っているデータは失われます。このルーチンは、要求されたサイズのバッファセグメントを返せない場合は NULL を返します。(x_inline() ルーチンは、バッファをサイクリックに使用するためのもので、このバッファの使用は移植可能ではありません。この機能の使用はお勧めできません。)
ストリームに対するバイトシーケンスの単純な入出力には、x_getbytes()) と x_putbytes() を使用します。入出力に成功すれば TRUE、失敗すれば FALSE が返されます。この 2 つのルーチンの引数は同じです。(xxxを関数名に合わせて置き換えます。)
bool_t xxxbytes(xdrs, buf, bytecount) XDR *xdrs; char *buf; u_int bytecount;
データストリームに対する long 型数値の入出力には、x_getlong() と x_putlong() を使用します。この 2 つのルーチンは、数値のマシン固有表現から標準外部表現への変換を担当します。変換には、UNIX のプリミティブ htonl() と ntohl() を利用できます。上位レベルのXDR 対応ソフトウェアでは、符号付きと符号なしの long 型整数のビット数は同じで、非負の整数のビットパターンは符号なし整数のビットパターンと同じであるとみなします。入出力に成功すれば TRUE 、失敗すれば FALSE が返されます。
この 2 つのルーチンの引数は同じです。
bool_t xxxlong(xdrs, lp) XDR *xdrs; long *lp;
XDR ストリームを新規開発するときは、作成ルーチンを使用して、新たな操作ルーチンを持つ XDR 構造体を作成し、クライアントに提供しなければなりません。