13.5. "xdrlib" --- XDR データのエンコードおよびデコード
*******************************************************

**ソースコード:** Lib/xdrlib.py

======================================================================

"xdrlib" モジュールは外部データ表現標準 (External Data  Representation
Standard) のサポートを実現します。この標準は 1987 年に Sun
Microsystems, Inc. によって書かれ、 **RFC 1014** で定義されています。
このモジュールでは RFC で記述されているほとんどのデータ型をサポートし
ています。

"xdrlib" モジュールでは 2 つのクラスが定義されています。一つは変数を
XDR 表現にパックするためのクラスで、もう一方は XDR 表現からアンパック
するためのものです。2 つの例外クラスが同様にして定義されています。

class xdrlib.Packer

   "Packer" はデータを XDR 表現にパックするためのクラスです。 "Packer"
   クラスのインスタンス生成は引数なしで行われます。

class xdrlib.Unpacker(data)

   "Unpacker" は Packer と対をなしていて、文字列バッファから XDR をア
   ンパックするためのクラスです。入力バッファ *data* を引数に与えてイ
   ンスタンスを生成します。

参考:

  **RFC 1014** - XDR: External Data Representation Standard
     この RFC が、かつてこのモジュールが最初に書かれた当時に XDR 標準
     であったデータのエンコード方法を定義していました。現在は **RFC
     1832** に更新されているようです。

  **RFC 1832** - XDR: External Data Representation Standard
     こちらが新しい方のRFCで、XDR の改訂版が定義されています。


13.5.1. Packer オブジェクト
===========================

"Packer" インスタンスには以下のメソッドがあります:

Packer.get_buffer()

   現在のパック処理用バッファを文字列で返します。

Packer.reset()

   パック処理用バッファをリセットして、空文字にします。

一般的には、適切な "pack_type()" メソッドを使えば、一般に用いられてい
るほとんどの XDR データをパックすることができます。各々のメソッドは一
つの引数をとり、パックしたい値を与えます。単純なデータ型をパックするメ
ソッドとして、以下のメソッド: "pack_uint()" 、 "pack_int()" 、
"pack_enum()" 、 "pack_bool()" 、 "pack_uhyper()" そして
"pack_hyper()" がサポートされています。

Packer.pack_float(value)

   単精度 (single-precision) の浮動小数点数 *value* をパックします。

Packer.pack_double(value)

   倍精度 (double-precision) の浮動小数点数 *value* をパックします。

以下のメソッドは文字列、バイト列、不透明データ (opaque data) のパック
処理をサポートします:

Packer.pack_fstring(n, s)

   固定長の文字列、*s* をパックします。*n* は文字列の長さですが、この
   値自体はデータバッファにはパック *されません*。4 バイトのアラインメ
   ントを保証するために、文字列は必要に応じて null  バイト列でパディン
   グされます。

Packer.pack_fopaque(n, data)

   "pack_fstring()" と同じく、固定長の不透明データストリームをパックし
   ます。

Packer.pack_string(s)

   可変長の文字列 *s* をパックします。文字列の長さが最初に符号なし整数
   でパックされ、続いて "pack_fstring()" を使って文字列データがパック
   されます。

Packer.pack_opaque(data)

   "pack_string()" と同じく、可変長の不透明データ文字列をパックします
   。

Packer.pack_bytes(bytes)

   "pack_string()" と同じく、可変長のバイトストリームをパックします。

以下のメソッドはアレイやリストのパック処理をサポートします:

Packer.pack_list(list, pack_item)

   一様な項目からなる *list* をパックします。このメソッドはサイズ不定
   、すなわち、全てのリスト内容を網羅するまでサイズが分からないリスト
   に対して有用です。リストのすべての項目に対し、最初に符号無し整数
   "1" がパックされ、続いてリスト中のデータがパックされます。
   *pack_item* は個々の項目をパックするために呼び出される関数です。リ
   ストの末端に到達すると、符号無し整数 "0" がパックされます。

   例えば、整数のリストをパックするには、コードは以下のようになるはず
   です:

      import xdrlib
      p = xdrlib.Packer()
      p.pack_list([1, 2, 3], p.pack_int)

Packer.pack_farray(n, array, pack_item)

   一様な項目からなる固定長のリスト (*array*) をパックします。 *n* は
   リストの長さです。この値はデータバッファにパック *されません* が、
   "len(array)" が *n* と等しくない場合、例外 "ValueError" が送出され
   ます。上と同様に、 *pack_item* は個々の要素をパック処理するための関
   数です。

Packer.pack_array(list, pack_item)

   一様の項目からなる可変長の *list* をパックします。まず、リストの長
   さが符号無し整数でパックされ、つづいて各要素が上の "pack_farray()"
   と同じやり方でパックされます。


13.5.2. Unpacker オブジェクト
=============================

"Unpacker" クラスは以下のメソッドを提供します:

Unpacker.reset(data)

   文字列バッファを *data* でリセットします。

Unpacker.get_position()

   データバッファ中の現在のアンパック処理位置を返します。

Unpacker.set_position(position)

   データバッファ中のアンパック処理位置を *position* に設定します。
   "get_position()" および "set_position()" は注意して使わなければなり
   ません。

Unpacker.get_buffer()

   現在のアンパック処理用データバッファを文字列で返します。

Unpacker.done()

   アンパック処理を終了させます。全てのデータがまだアンパックされてい
   なければ、例外 "Error" が送出されます。

上のメソッドに加えて、 "Packer" でパック処理できるデータ型はいずれも
"Unpacker" でアンパック処理できます。アンパック処理メソッドは
"unpack_type()" の形式をとり、引数をとりません。これらのメソッドはアン
パックされたデータオブジェクトを返します。

Unpacker.unpack_float()

   単精度の浮動小数点数をアンパックします。

Unpacker.unpack_double()

   "unpack_float()" と同様に、倍精度の浮動小数点数をアンパックします。

上のメソッドに加えて、文字列、バイト列、不透明データをアンパックする以
下のメソッドが提供されています:

Unpacker.unpack_fstring(n)

   固定長の文字列をアンパックして返します。*n* は予想される文字列の長
   さです。4 バイトのアラインメントを保証するために null バイトによる
   パディングが行われているものと仮定して処理を行います。

Unpacker.unpack_fopaque(n)

   "unpack_fstring()" と同様に、固定長の不透明データストリームをアンパ
   ックして返します。

Unpacker.unpack_string()

   可変長の文字列をアンパックして返します。最初に文字列の長さが符号無
   し整数としてアンパックされ、次に "unpack_fstring()" を使って文字列
   データがアンパックされます。

Unpacker.unpack_opaque()

   "unpack_string()" と同様に、可変長の不透明データ文字列をアンパック
   して返します。

Unpacker.unpack_bytes()

   "unpack_string()" と同様に、可変長のバイトストリームをアンパックし
   て返します。

以下メソッドはアレイおよびリストのアンパック処理をサポートします:

Unpacker.unpack_list(unpack_item)

   一様な項目からなるリストをアンパック処理してかえします。リストは一
   度に 1 要素づつアンパック処理されます、まず符号無し整数によるフラグ
   がアンパックされます。もしフラグが "1" なら、要素はアンパックされ、
   返り値のリストに追加されます。フラグが "0" であれば、リストの終端を
   示します。*unpack_item* は個々の項目をアンパック処理するために呼び
   出される関数です。

Unpacker.unpack_farray(n, unpack_item)

   一様な項目からなる固定長のアレイをアンパックして（リストとして）返
   します。*n* はバッファ内に存在すると期待されるリストの要素数です。
   上と同様に、*unpack_item* は各要素をアンパックするために使われる関
   数です。

Unpacker.unpack_array(unpack_item)

   一様な項目からなる可変長の *list* をアンパックして返します。まず、
   リストの長さが符号無し整数としてアンパックされ、続いて各要素が上の
   "unpack_farray()" のようにしてアンパック処理されます。


13.5.3. 例外
============

このモジュールでの例外はクラスインスタンスとしてコードされています:

exception xdrlib.Error

   ベースとなる例外クラスです。 "Error" public な属性として "msg" を持
   ち、エラーの詳細が収められています。

exception xdrlib.ConversionError

   "Error" から派生したクラスです。インスタンス変数は塚されていません
   。

これらの例外を補足する方法を以下の例に示します:

   import xdrlib
   p = xdrlib.Packer()
   try:
       p.pack_double(8.01)
   except xdrlib.ConversionError as instance:
       print 'packing the double failed:', instance.msg
