7.3. "struct" --- 文字列データをパックされたバイナリデータとして解釈する
************************************************************************

このモジュールは、 Python の値と Python 上で文字列データとして表される
C の構造体データとの間の変換を実現します。このモジュールは特に、ファイ
ルに保存されたり、ネットワーク接続を経由したバイナリデータを扱うときに
使われます。このモジュールでは、C 構造体のレイアウトおよび Python の値
との間で行いたい変換をコンパクトに表現するために、 フォーマット文字列
を使います。

注釈: デフォルトでは、与えられた C の構造体をパックする際に、関連す
  る C デ ータ型を適切にアラインメント(alignment)するために数バイトの
  パディン グを行うことがあります。この挙動が選択されたのは、パックさ
  れた構造体 のバイト表現を対応する C 構造体のメモリレイアウトに正確に
  対応させる ためです。プラットフォーム独立のデータフォーマットを扱っ
  たり、隠れた パディングを排除したりするには、サイズ及びアラインメン
  トとして "native" の代わりに "standard" を使うようにします: 詳しくは
  バイトオ ーダ、サイズ、アラインメント を参照して下さい。


7.3.1. 関数と例外
=================

このモジュールは以下の例外と関数を定義しています:

exception struct.error

   様々な状況で送出された例外です; 引数は何が問題かを記述する文字列で
   す。

struct.pack(fmt, v1, v2, ...)

   フォーマット文字列 *fmt* に従い値 *v1*, *v2*, ...  をパックして、文
   字列で返します。引数は指定したフォーマットが要求する型と正確に一致
   していなければなりません。

struct.pack_into(fmt, buffer, offset, v1, v2, ...)

   フォーマット文字列 *fmt* に従い値 *v1*, *v2*, ...  をパックして文字
   列にし、書き込み可能な *buffer* のオフセット *offset* 位置より書き
   込みます。オフセットは省略出来ません。

   バージョン 2.5 で追加.

struct.unpack(fmt, string)

   (おそらく "pack(fmt, ...)" でパックされた) バッファ *buffer* から与
   えられた書式文字列 *fmt* に従ってアンパックします。値が一つしかない
   場合を含め、結果はタプルで返されます。文字列データにはフォーマット
   が要求するだけのデータが正確に含まれていなければなりません
   ("len(bytes)" が "calcsize(fmt)" と一致しなければなりません)。

struct.unpack_from(fmt, buffer[, offset=0])

   バッファ *buffer* の *offset* の位置から、書式化文字列 *fmt* に従っ
   てアンパックします。結果は要素が1つでもタプルとして返されます。
   *buffer* は少なくとも書式が要求するデータサイズを持っていなくてはな
   りません ("len(buffer[offset:])" は少なくとも "calcsize(fmt)" 以上
   でなくてはなりません)。

   バージョン 2.5 で追加.

struct.calcsize(fmt)

   与えられたフォーマットに対応する構造体のサイズ (すなわち文字列デー
   タのサイズ) を返します。


7.3.2. フォーマット文字列
=========================

フォーマット文字列はデータをパックしたりアンパックしたりするときの期待
されるレイアウトを指定するためのメカニズムです。文字列はパック/アンパ
ックされるデータの型を指定する フォーマット文字 から組み立てられます。
さらに、 バイトオーダ、サイズ、アラインメント を制御するための特殊文字
もあります。


7.3.2.1. バイトオーダ、サイズ、アラインメント
---------------------------------------------

デフォルトでは、C での型はマシンのネイティブ (native) の形式およびバイ
トオーダ (byte order) で表され、適切にアラインメント (alignment) する
ために、必要に応じて数バイトのパディングを行ってスキップします (これは
C コンパイラが用いるルールに従います)。

これに代わって、フォーマット文字列の最初の文字を使って、バイトオーダや
サイズ、アラインメントを指定することができます。指定できる文字を以下の
テーブルに示します:

+-------------+--------------------------+------------+-------------+
| 文字        | バイトオーダ             | サイズ     | アラインメ  |
|             |                          |            | ント        |
+=============+==========================+============+=============+
| "@"         | native                   | native     | native      |
+-------------+--------------------------+------------+-------------+
| "="         | native                   | standard   | none        |
+-------------+--------------------------+------------+-------------+
| "<"         | リトルエンディアン       | standard   | none        |
+-------------+--------------------------+------------+-------------+
| ">"         | ビッグエンディアン       | standard   | none        |
+-------------+--------------------------+------------+-------------+
| "!"         | ネットワーク (= ビッグエ | standard   | none        |
|             | ンディアン)              |            |             |
+-------------+--------------------------+------------+-------------+

フォーマット文字列の最初の文字が上のいずれかでない場合、"'@'" であると
みなされます。

ネイティブのバイトオーダはビッグエンディアンかリトルエンディアンで、ホ
スト計算機に依存します。例えば、Intel x86 および AMD64 (x86-64) はリト
ルエンディアンです。Motorola 68000 および PowerPC G5 はビッグエンディ
アンです。ARM および Intel Itanium はエンディアンを切り替えられる機能
を備えています (バイエンディアン)。使っているシステムでのエンディアン
は "sys.byteorder" を使って調べて下さい。

ネイティブのサイズおよびアラインメントは C コンパイラの "sizeof" 式で
決定されます。ネイティブのサイズおよびアラインメントはネイティブのバイ
トオーダと同時に使われます。

標準のサイズはフォーマット文字だけで決まります。 フォーマット文字 の表
を参照して下さい。

"'@'" と "'='" の違いに注意してください: 両方ともネイティブのバイトオ
ーダですが、後者のバイトサイズとアラインメントは標準のものに合わせてあ
ります。

"'!'" 表記法はネットワークバイトオーダがビッグエンディアンかリトルエン
ディアンか忘れちゃったという熱意に乏しい人向けに用意されています。

バイトオーダに関して、「(強制的にバイトスワップを行う)ネイティブの逆」
を指定する方法はありません。"'<'" または "'>'" のうちふさわしい方を選
んでください。

注釈:

1. パディングは構造体のメンバの並びの中にだけ自動で追加されます。最
   初 や最後にパディングが追加されることはありません。

2. ネイティブでないサイズおよびアラインメントが使われる場合にはパデ
   ィ ングは行われません (たとえば '<', '>', '=', '!' を使った場合です
   )。

3. 特定の型によるアラインメント要求に従うように構造体の末端をそろえ
   る には、繰り返し回数をゼロにした特定の型でフォーマットを終端します
   。 例 を参照して下さい。


7.3.2.2. フォーマット文字
-------------------------

フォーマット文字 (format character) は以下の意味を持っています; C と
Python の間の変換では、値は正確に以下に指定された型でなくてはなりませ
ん: 「標準のサイズ」列は standard サイズ使用時にパックされた値が何バイ
トかを示します。つまり、フォーマット文字列が "'<'", "'>'", "'!'",
"'='" のいずれかで始まっている場合のものです。native サイズ使用時には
パックされた値の大きさはプラットフォーム依存です。

+----------+----------------------------+----------------------+------------------+--------------+
| フォーマ | C の型                     | Python の型          | 標準のサイズ     | 注釈         |
| ット     |                            |                      |                  |              |
+==========+============================+======================+==================+==============+
| "x"      | パディングバイト           | 値なし               |                  |              |
+----------+----------------------------+----------------------+------------------+--------------+
| "c"      | "char"                     | 長さ 1 の文字列      | 1                |              |
+----------+----------------------------+----------------------+------------------+--------------+
| "b"      | "signed char"              | integer              | 1                | (3)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "B"      | "unsigned char"            | integer              | 1                | (3)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "?"      | "_Bool"                    | 真偽値型(bool)       | 1                | (1)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "h"      | "short"                    | integer              | 2                | (3)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "H"      | "unsigned short"           | integer              | 2                | (3)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "i"      | "int"                      | integer              | 4                | (3)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "I"      | "unsigned int"             | integer              | 4                | (3)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "l"      | "long"                     | integer              | 4                | (3)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "L"      | "unsigned long"            | integer              | 4                | (3)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "q"      | "long long"                | integer              | 8                | (2), (3)     |
+----------+----------------------------+----------------------+------------------+--------------+
| "Q"      | "unsigned long long"       | integer              | 8                | (2), (3)     |
+----------+----------------------------+----------------------+------------------+--------------+
| "f"      | "float"                    | float                | 4                | (4)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "d"      | "double"                   | float                | 8                | (4)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "s"      | "char[]"                   | string               |                  |              |
+----------+----------------------------+----------------------+------------------+--------------+
| "p"      | "char[]"                   | string               |                  |              |
+----------+----------------------------+----------------------+------------------+--------------+
| "P"      | "void *"                   | integer              |                  | (5), (3)     |
+----------+----------------------------+----------------------+------------------+--------------+

注釈:

1. "'?'" 変換コードは C99 で定義された "_Bool" 型に対応します。その
   型 が利用できない場合は、 "char" で代用されます。標準モードでは常に
   1バ イトで表現されます。

   バージョン 2.6 で追加.

2. 変換コード "'q'" および "'Q'" は、ネイティブモードではプラットフ
   ォ ームの C コンパイラが C の "long long" 型をサポートする場合、ま
   たは Windows では "__int64" をサポートする場合にのみ利用できます。
   標準モ ードでは常に利用できます。

   バージョン 2.2 で追加.

3. 整数変換コードで非整数をパックしようとするとき、その非整数が
   "__index__()" メソッドを持っていると、パッキングの前に、そのメソッ
   ドが変数を整数に変換するために呼び出されます。 "__index__()" メソッ
   ドが存在しないか、 "__index__()" メソッドの呼び出しが "TypeError"
   を送出したら、次に "__int__()" メソッドが試されます。しかし、
   "__int__()" の使用は非推奨で、 "DeprecationWarning" を送出します。

   バージョン 2.7 で変更: 非整数に対して "__index__()" メソッドが使わ
   れるようになったのは 2.7 の新機能です。

   バージョン 2.7 で変更: バージョン 2.7 以前では、すべての整数変換コ
   ードが変換に "__int__()" メソッドを使うわけではなく、浮動小数点の引
   数にのみ "DeprecationWarning" が送出されていました。

4. "'f'" および "'d'" 変換コードについて、パックされた表現は IEEE
   754 binary32 ("'f'" の場合) または binary64 ("'d'" の場合) フォーマ
   ット が、プラットフォームにおける浮動小数点数のフォーマットに関係な
   く使 われます。

5. "'P'" フォーマット文字はネイティブバイトオーダでのみ利用可能です
   ( デフォルトのネットワークバイトオーダに設定するか、"'@'" バイトオ
   ー ダ指定文字を指定しなければなりません)。"'='" を指定した場合、ホ
   スト 計算機のバイトオーダに基づいてリトルエンディアンとビッグエンデ
   ィア ンのどちらを使うかを決めます。struct モジュールはこの設定をネ
   イティ ブのオーダ設定として解釈しないので、"'P'" を使うことはできま
   せん。

フォーマット文字の前に整数をつけ、繰り返し回数 (count) を指定すること
ができます。例えば、フォーマット文字列 "'4h'" は "'hhhh'" と全く同じ意
味です。

フォーマット文字間の空白文字は無視されます; count とフォーマット文字の
間にはスペースを入れてはいけません。

フォーマット文字 "'s'" では、count は文字列のサイズとして扱われます。
他のフォーマット文字のように繰り返し回数ではありません; 例えば、
"'10c'" が 10 個のキャラクタを表すのに対して、 "'10s'" は 10 バイトの
長さを持った 1 個の文字列です。count の指定がない場合のデフォルトは 1
です。文字列をパックする際には、指定した長さにフィットするように、必要
に応じて切り詰められたりヌル文字で穴埋めされたりします。アンパック時は
、取り出される文字列は正確に指定サイズのサイズを持ちます。また特殊なケ
ースとして、("'0c'" が 0 個のキャラクタを表すのに対して) "'0s'" は 1
個の空文字列を意味します。

フォーマット文字 "'p'" は "Pascal 文字列 (pascal string)"  をコードし
ます。Pascal 文字列は count で与えられる *固定長のバイト列* に収められ
た短い可変長の文字列です。このデータの先頭の 1 バイトには文字列の長さ
か255 のうち、小さい方の数が収められます。その後に文字列のバイトデータ
が続きます。 "pack()" に渡された Pascal 文字列の長さが長すぎた
(count-1 よりも長い) 場合、先頭の "count-1" バイトが書き込まれます。文
字列が "count-1" よりも短い場合、指定した count バイトに達するまでの残
りの部分はヌルで埋められます。 "unpack()" では、フォーマット文字 "'p'"
は指定された "count" バイトだけデータを読み込みますが、返される文字列
は決して 255 文字を超えることはないので注意してください。

フォーマット文字 "'P'" では、返される値は Python 整数型または long 整
数型で、これはポインタの値を Python での整数にキャストする際に、値を保
持するために必要なサイズに依存します。 *NULL* ポインタは常に Python 整
数型の "0" になります。ポインタ型のサイズを持った値をパックする際には
、Python 整数型か long 整数型オブジェクトのどちらかが使われます。例え
ば、 Alpha および Merced プロセッサは 64 bit のポインタ値を使いますが
、これはポインタを保持するために Python long 整数型が使われることを意
味します; 32 bit ポインタを使う他のプラットフォームでは Python 整数型
が使われます。

"'?'" フォーマット文字では、返り値は "True" または "False" です。パッ
クするときには、引数オブジェクトの論理値としての値が使われます。 0 ま
たは 1 のネイティブや標準の真偽値表現でパックされ、アンパックされると
きはゼロでない値は "True" になります。


7.3.2.3. 例
-----------

注釈: 全ての例は、ビッグエンディアンのマシンで、ネイティブのバイトオ
  ーダ、 サイズおよびアラインメントを仮定します。

基本的な例として、三つの整数をパック/アンパックします:

   >>> from struct import *
   >>> pack('hhl', 1, 2, 3)
   '\x00\x01\x00\x02\x00\x00\x00\x03'
   >>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
   (1, 2, 3)
   >>> calcsize('hhl')
   8

アンパックした結果のフィールドは、変数に割り当てるか named tuple でラ
ップすることによって名前を付けることができます:

   >>> record = 'raymond   \x32\x12\x08\x01\x08'
   >>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)

   >>> from collections import namedtuple
   >>> Student = namedtuple('Student', 'name serialnum school gradelevel')
   >>> Student._make(unpack('<10sHHb', record))
   Student(name='raymond   ', serialnum=4658, school=264, gradelevel=8)

アラインメントの要求を満たすために必要なパディングが異なるという理由に
より、フォーマット文字の順番がサイズの違いを生み出すことがあります:

   >>> pack('ci', '*', 0x12131415)
   '*\x00\x00\x00\x12\x13\x14\x15'
   >>> pack('ic', 0x12131415, '*')
   '\x12\x13\x14\x15*'
   >>> calcsize('ci')
   8
   >>> calcsize('ic')
   5

以下のフォーマット "'llh0l'" は、long 型が 4 バイトを境界としてそろえ
られていると仮定して、末端に 2 バイトをパディングします:

   >>> pack('llh0l', 1, 2, 3)
   '\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'

この例はネイティブのサイズとアラインメントが使われているときだけ思った
通りに動きます。標準のサイズとアラインメントはアラインメントの設定では
いかなるアラインメントも行いません。

参考:

  "array" モジュール
     一様なデータ型からなるバイナリ記録データのパック。

  "xdrlib" モジュール
     XDR データのパックおよびアンパック。


7.3.3. クラス
=============

"struct" モジュールは次の型を定義します:

class struct.Struct(format)

   フォーマット文字列 *format* に従ってバイナリデータを読み書きする、
   新しい Struct オブジェクトを返します。 Struct オブジェクトを一度作
   ってからそのメソッドを使うと、フォーマット文字列のコンパイルが一度
   で済むので、 "struct" モジュールの関数を同じフォーマットで何度も呼
   び出すよりも効率的です。

   バージョン 2.5 で追加.

   コンパイルされた Struct オブジェクトは以下のメソッドと属性をサポー
   トします:

   pack(v1, v2, ...)

      "pack()" 関数と同じ、コンパイルされたフォーマットを利用するメソ
      ッドです。 ("len(result)" は "self.size" と等しいでしょう)

   pack_into(buffer, offset, v1, v2, ...)

      "pack_into()" 関数と同じ、コンパイルされたフォーマットを利用する
      メソッドです。

   unpack(string)

      "unpack()" 関数と同じ、コンパイルされたフォーマットを利用するメ
      ソッドです。 ("len(string)" は "self.size" と等しくなければなり
      ません)。

   unpack_from(buffer, offset=0)

      "unpack_from()" 関数と同じ、コンパイルされたフォーマットを利用す
      るメソッドです。 ("len(buffer[offset:])" は "self.size" 以上でな
      ければなりません)。

   format

      この Struct オブジェクトを作成する時に利用されたフォーマット文字
      列です。

   size

      "format" に対応する struct (とそれによる文字列) のサイズを計算し
      たものです。
