
:mod:`struct` --- 文字列データをパックされたバイナリデータとして解釈する
========================================================================

.. module:: struct
   :synopsis: 文字列データをパックされたバイナリデータとして解釈する.

.. index::
   pair: C; structures
   triple: packing; binary; data

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

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


.. exception:: error

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


.. function:: pack(fmt, v1, v2, ...)

   値 ``v1, v2, ...`` が与えられたフォーマットで含まれる文字列データを返します。
   引数は指定したフォーマットが要求する型と正確に一致していなければなりません。


.. function:: pack_into(fmt, buffer, offset, v1, v2, ...)

   ``v1, v2, ...`` を与えられたフォーマットに従ってパックし、そのバイト列を書き込み可能な *buffer*
   の *offset* を先頭に書き込みます。 offset が省略できないことに注意してください。

   .. versionadded:: 2.5


.. function:: unpack(fmt, string)

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


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

   *buffer* を与えられたフォーマットでアンパックします。
   値が一つしかない場合を含め、結果はタプルで返されます。
   *buffer* には最低でも format に要求されるサイズのデータが必要です。
   (``len(buffer[offset:])`` は ``calcsize(fmt)`` 以上で無ければなりません)。

   .. versionadded:: 2.5


.. function:: calcsize(fmt)

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

フォーマット文字 (format character) は以下の意味を持っています;
C と Python の間の変換では、値は正確に以下に指定された型でなくてはなりません:

+--------------+-------------------------+------------------+------+
| フォーマット | C での型                | Python           | 備考 |
+==============+=========================+==================+======+
| ``x``        | pad byte                | no value         |      |
+--------------+-------------------------+------------------+------+
| ``c``        | :ctype:`char`           | 長さ 1 の文字列  |      |
+--------------+-------------------------+------------------+------+
| ``b``        | :ctype:`signed char`    | 整数型 (integer) |      |
+--------------+-------------------------+------------------+------+
| ``B``        | :ctype:`unsigned char`  | 整数型           |      |
+--------------+-------------------------+------------------+------+
| ``?``        | :ctype:`_Bool`          | 真偽値型(bool)   | \(1) |
+--------------+-------------------------+------------------+------+
| ``h``        | :ctype:`short`          | 整数型           |      |
+--------------+-------------------------+------------------+------+
| ``H``        | :ctype:`unsigned short` | 整数型           |      |
+--------------+-------------------------+------------------+------+
| ``i``        | :ctype:`int`            | 整数型           |      |
+--------------+-------------------------+------------------+------+
| ``I``        | :ctype:`unsigned int`   | integer か long  |      |
+--------------+-------------------------+------------------+------+
| ``l``        | :ctype:`long`           | 整数型           |      |
+--------------+-------------------------+------------------+------+
| ``L``        | :ctype:`unsigned long`  | long 整数型      |      |
+--------------+-------------------------+------------------+------+
| ``q``        | :ctype:`long long`      | long 整数型      | \(2) |
+--------------+-------------------------+------------------+------+
| ``Q``        | :ctype:`unsigned long   | long 整数型      | \(2) |
|              | long`                   |                  |      |
+--------------+-------------------------+------------------+------+
| ``f``        | :ctype:`float`          | 浮動小数点型     |      |
+--------------+-------------------------+------------------+------+
| ``d``        | :ctype:`double`         | 浮動小数点型     |      |
+--------------+-------------------------+------------------+------+
| ``s``        | :ctype:`char[]`         | 文字列           |      |
+--------------+-------------------------+------------------+------+
| ``p``        | :ctype:`char[]`         | 文字列           |      |
+--------------+-------------------------+------------------+------+
| ``P``        | :ctype:`void \*`        | long             |      |
+--------------+-------------------------+------------------+------+

注意事項:

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

   .. versionadded:: 2.6

(2)
   フォーマット文字 ``'q'`` および ``'Q'`` は、プラットフォームの C コンパイラが C の :ctype:`long long` 型、
   Windows では :ctype:`__int64` をサポートする場合にのみ、
   プラットフォームネイティブの値との変換を行うモードだけで利用することができます。

   .. versionadded:: 2.2

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

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

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

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

フォーマット文字 ``'I'`` 、 ``'L'`` 、 ``'q'``  および ``'Q'`` では、返される値は Python long 整数です。

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

フォーマット文字 ``'?'`` では、返される値は :const:`True` か :const:`False` のどちらかです。
パック時にはオブジェクトの真偽値が利用されます。
0 か 1 のネイティブもしくは標準のbool表現がパックされます。
そしてアンパック時には非ゼロの値は True になります。

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

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

+-------+-------------------------------------------------+----------------------------+
| 文字  | バイトオーダ                                    | サイズおよびアラインメント |
+=======+=================================================+============================+
| ``@`` | ネイティブ                                      | ネイティブ                 |
+-------+-------------------------------------------------+----------------------------+
| ``=`` | ネイティブ                                      | 標準                       |
+-------+-------------------------------------------------+----------------------------+
| ``<`` | リトルエンディアン                              | 標準                       |
+-------+-------------------------------------------------+----------------------------+
| ``>`` | ビッグエンディアン                              | 標準                       |
+-------+-------------------------------------------------+----------------------------+
| ``!`` | ネットワークバイトオーダ (= ビッグエンディアン) | 標準                       |
+-------+-------------------------------------------------+----------------------------+

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

ネイティブのバイトオーダはビッグエンディアンかリトルエンディアンで、ホスト計算機に依存します。例えば、Motorola および Sun のプロセッサは
ビッグエンディアンです; Intel および DEC のプロセッサはリトルエンディアンです。

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

標準のサイズおよびアラインメントは以下のようになります: どの型に対しても、アラインメントは必要ありません (ので、パディングを使う必要があります);
:ctype:`short` は 2 バイトです; :ctype:`int` と :ctype:`long` は 4 バイトです; :ctype:`long
long` (Windows では :ctype:`__int64`) は 8 バイトです; :ctype:`float` と :ctype:`double`
は順に 32-bit あるいは 64-bit の IEEE 浮動小数点数です。 :ctype:`_Bool` は 1 byte です。

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

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

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

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

以下に例を示します (この例は全てビッグエンディアンのマシンで、ネイティブのバイトオーダ、サイズおよびアラインメントの場合です)::

   >>> 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

ヒント: 特定の型によるアラインメント要求に従うように構造体の末端をそろえるには、count をゼロにした特定の型でフォーマットを終端します。
例えば、フォーマット ``'llh0l'`` は、 long 型が 4 バイトを境界としてそろえられていると仮定して、末端に 2 バイトをパディングします。
この機能は変換対象がネイティブのサイズおよびアラインメントの場合にのみ働きます; 標準に型サイズおよびアラインメントの設定ではいかなる
アラインメントも行いません。

アンパックした結果のフィールドは、変数に割り当てるか 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', s))
    Student(name='raymond   ', serialnum=4658, school=264, gradelevel=8)


.. seealso::

   Module :mod:`array`
      一様なデータ型からなるバイナリ記録データのパック

   Module :mod:`xdrlib`
      XDR データのパックおよびアンパック。


.. _struct-objects:

Struct オブジェクト
--------------------

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

.. class:: Struct(format)

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

   .. versionadded:: 2.5

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

   .. method:: pack(v1, v2, ...)

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

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

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

   .. method:: unpack(string)

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

   .. method:: unpack_from(buffer[, offset=0])

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

   .. attribute:: format

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

   .. attribute:: size

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

