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

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

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

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

.. note::

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

関数と例外
----------

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


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

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

.. _struct-format-strings:

フォーマット文字列
------------------

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

.. _struct-alignment:

バイトオーダ, サイズ, アラインメント
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

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

+-------+-------------------------------------+----------+----------------+
| 文字  | バイトオーダ                        | サイズ   | アラインメント |
+=======+=====================================+==========+================+
| ``@`` | ネイティブ                          | 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`` 式で決定されます。
ネイティブのサイズおよびアラインメントはネイティブのバイトオーダと同時に使われます。

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

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

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

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

注意:

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

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

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


.. _format-characters:

フォーマット文字
^^^^^^^^^^^^^^^^^

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

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


注意事項:

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

   .. versionadded:: 2.6

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

   .. versionadded:: 2.2

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

   .. versionchanged:: 2.7
      非整数への :meth:`__index__` メソッド の使用は 2.7 で追加されました。

   .. versionchanged:: 2.7
      バージョン 2.7 以前では、すべての整数変換コードが変換に :meth:`__int__`
      メソッドを使うわけではなく、浮動小数点の引数にのみ
      :exc:`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 個
の文字列です。文字列をパックする際には、指定した長さにフィットするように、必要に応じて切り詰められたりヌル文字
で穴埋めされたりします。また特殊なケースとして、(``'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 文字を超えることはないので注意してください。

フォーマット文字 ``'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 になります。

.. _struct-examples:

例
^^^^

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

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

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

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


.. seealso::

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

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


.. _struct-objects:

クラス
------

: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 (とそれによる文字列) のサイズを計算したものです。

