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


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

unpackとpackを制御するためにはデータレイアウト仕様(data layout specification)を記述します。これは名前付きかつタイプ付けされたフィールド(field)を記述する特別なネスト化リストです。これは処理する各フィールドの長さ、およびそれをpackおよびunpackする方法を制御します。わたしたちは名前が‘-bindat-spec’で終わる変数ではbindatの仕様を遵守します。この類の変数名は自動的にrisky(危険)だと認識されます。

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

u8
byte

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

u16
word
short

長さ2のネットワークバイトオーダーによる符号なし整数。

u24

長さ3のネットワークバイトオーダーによる符号なし整数。

u32
dword
long

長さ4のネットワークバイトオーダーによる符号なし整数。注意: これらの値はEmacsの整数の実装に制限されるだろう。

u16r
u24r
u32r

それぞれ長さ2、3、4のリトルエンディアンオーダーによる符号なし整数。

str len

長さlenの文字列。

strz len

長さlenの固定長フィールド内のNUL終端された文字列。

vec len [type]

タイプtype (デフォルトはbyte)のlen要素のベクター。typeは上述した単純なタイプのいずれか、あるいは(vec len [type])という形式のリストによる別ベクターの指定。

ip

インターネットアドレスを表す4つのbyteのベクター。たとえばlocalhostは[127 0 0 1]

bits len

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

(eval form)

formはフィールドがpackやunpackされた瞬間に評価されるLisp式。評価した結果は上記にリストしたタイプ使用のいずれかであること。

固定長フィールドでは長さlenがフィールド内のバイト数を指定する整数として与えられます。

フィールド長が固定でなければ通常は先行するフィールドの値に依存します。この場合には長さlenは後述のbindat-get-fieldのフォーマット指定によりフィールド名(field name)を指定するリスト(name ...)、または式(eval form) (formはフィールド長を指定する整数に評価されること)のいずれかで与えることもできます。

フィールド仕様は一般的に([name] handler)という形式をもち、nameはオプションです。紛らわしくなるのでタイプ仕様(上述)やハンドラー仕様(後述)で意味をもつシンボルの名前は使用しないでください。nameはシンボルまたは式(eval form)でもよく、この場合にはformはシンボルに評価される必要があります。

handlerはそのフィールドがpackやunpackされる方法を記述して、以下のいずれかを指定できます:

type

タイプ仕様typeに応じてこのフィールドのunpack/packを行う。

eval form

副作用のためだけにLisp式formを評価する。フィールド名が指定されたら値はそのフィールド名にバインドされる。

fill len

lenバイトをスキップする。pack化ではそれらを未変更のままとして、通常それらは0のままとなることを意味する。unpack化ではそれらが無視されることを意味する。

align len

lenバイトの次の倍数にスキップする。

struct spec-name

副仕様(sub-specification)としてspec-nameを処理する。これは別の構造体内にネストされる構造体を記述する。

union form (tag spec)…

Lisp式formを評価、それにマッチする最初のtagを探して、それに関連付けられたレイアウト仕様specを処理する。マッチングは以下の3つのいずれかで発生し得る:

repeat count field-specs

field-specsを再帰的に順次処理した後に、最初のものから繰り返して、すべての仕様全体をcount回処理する。countはフィールド長と同じフォーマットを使用して与えられる。evalフォームが使用された場合には1回だけ評価される。正しく処理されるためには、field-specs内の各仕様が名前を含まなければならない。

bindat仕様内で仕様される(eval form)フォームでは、評価の間にformはこれらの動的にバインドされた変数へのアクセスと更新が可能である。

last

最後に処理されたフィールドの値。

bindat-raw

バイト配列のデータ。

bindat-idx

unpack化/pack化にたいする、(bindat-rawでの)カレントインデックス。

struct

これまでにunpackされた構造化データ、またはpackされた構造体全体を含むalist。この構造体の特定のフィールドにアクセスするためにbindat-get-fieldを使用できる。

count
index

repeatブロック内部では、これらは(countパラメーターで指定された)繰り返しの最大回数、および(0から数えた)カレント繰り返し回数を含む。countを0にセットすることにより、カレントの繰り返し終了後に最内繰り返しブロックを終了する。