Next: , Up: Byte Packing   [Contents][Index]


39.20.1 データレイアウトの記述

unpackとpackを制御するためには、データレイアウト仕様(data layout specification)を記述します(Bindatタイプ式(Bindat type expression)とも呼ばれる)。これにはベースタイプ(base type)と複数フィールドからなるコンポジットタイプ(composite type)があり、処理するフィールドそれぞれの長さ、packやunpackを行う方法をこの仕様が制御します。わたしたちはbindatタイプの値を、通常は-bindat-specで終わる名前の変数に保持しています。このような種類の名前は、自動的に危険(risky)だと認識されます(File Local Variablesを参照)。

Macro: bindat-type &rest type

Bindatタイプのであるtypeに応じて、Bindatタイプのオブジェクトを作成する。

フィールドのタイプ(type)はフィールドが表すオブジェクトのサイズ(バイト単位)、およびそれがマルチバイトフィールドならフィールがバイトオーダーされる方法を記述します。可能なオーダーはビッグエンディアン(big endian。ネットワークバイトオーダーとも呼ばれる)、およびリトルエンディアン(little endian)の2つです。たとえば数字#x23cd (10進の9165)のビッグエンディアンは#x23 #xcdの2バイト、リトルエンディアンは#xcd #x23になるでしょう。以下は可能なタイプの値です:

u8
byte

長さ1の符号なしタイプ。

uint bitlen

長さbitlenビットのネットワークバイトオーダーによる符号なし整数。bitlenは8の倍数であること。

uintr bitlen

長さbitlenビットのネットワークバイトオーダーによる符号なし整数。リトルエンディアンオーダーによる符号なし整数。bitlenは8の倍数であること。

str len

長さlenのバイト文字列。

strz &optional len

長さlenの固定長フィールド、または任意長さのNUL終端されたバイト文字列。

vec len [type]

len要素のベクター。要素のタイプはtypeにより与えられる(デフォルトはバイト)。typeは任意のBindatタイプ式を指定できる。

repeat len [type]

vecと同様だがリストから双方向にunpack/packする(vecはunpackするベクター)。

bits len

lenバイト内で1にセットされたビットのリスト。バイトはビッグエンディアンオーダーで、ビットは8 * len - 1で始まり0で終わるよう番号が付けされる。たとえばbits 2では、#x28 #x1c(2 3 4 11 13)#x1c #x28(3 5 10 11 12)にunpackされる。

fill len

lenバイトは単なるフィラーとして使用される。これらのバイトはpack時には未変更のままとなり通常は0のままであることを、unpack時には単にnilをリターンすることを意味する。

align len

fillと同様だが、次のlenの倍数バイトまでスキップを要するバイト数である点が異なる。

type exp

これによりタイプを間接的に参照できる。expはBindatタイプvalueをリターンするLisp式であること。

unit exp

これは0ビットのスペースを使用する簡易タイプ。expはそのようなフィールドの“unpack”を試みた際にリターンされる値を記述する。

struct fields...

複数フィールドから構成されるコンポジットタイプ(composite typex: 複合型)。フィールドはそれぞれ(name type)という形式をもち、typeには任意のBindatタイプ式を指定できる。alignfillのフィールドのように、そのフィールド値が命名に値しない場合には、name_でもよい。コンテキストによりBindatタイプ式であることが明確なら、シンボルstructは省略可。

上述のタイプの中で、lenbitlenはフィールド内のバイト数(またはビット数)を指定する整数として与えられます。そのフィールドが固定長でなければ、通常は値は先行するフィールドの値に依存します。この理由により、lenの長さは定数である必要がないので任意のLisp式を指定することができ、フィールド名から先行するフィールドの値を通じて参照することができるのです。

たとえば先頭のバイトが16ビット整数の後続ベクターにサイズを与えるデータレイアウトの仕様は、以下のようになります:

(bindat-type
  (len      u8)
  (payload  vec (1+ len) uint 16))