Next: バイトのunpackとpackを行う関数, Up: バイト配列のpackとunpack [Contents][Index]
unpackとpackを制御するためには、データレイアウト仕様(data layout
specification)を記述します(Bindatタイプ式(Bindat type
expression)とも呼ばれる)。これにはベースタイプ(base
type)と複数フィールドからなるコンポジットタイプ(composite
type)があり、処理するフィールドそれぞれの長さ、packやunpackを行う方法をこの仕様が制御します。わたしたちはbindatタイプの値を、通常は-bindat-specで終わる名前の変数に保持しています。このような種類の名前は、自動的に危険(risky)だと認識されます(ファイルローカル変数を参照)。
Bindatタイプの式であるtypeに応じて、Bindatタイプの値オブジェクトを作成する。
フィールドのタイプ(type)はフィールドが表すオブジェクトのサイズ(バイト単位)、およびそれがマルチバイトフィールドならフィールがバイトオーダーされる方法を記述します。可能なオーダーはビッグエンディアン(big
endian。ネットワークバイトオーダーとも呼ばれる)、およびリトルエンディアン(little
endian)の2つです。たとえば数字#x23cd (10進の9165)のビッグエンディアンは#x23
#xcdの2バイト、リトルエンディアンは#xcd #x23になるでしょう。以下は可能なタイプの値です:
u8byte長さ1の符号なしタイプ。
uint bitlen &optional le長さbitlenビットのネットワークバイトオーダー(ビッグエンディアン)による符号なし整数。bitlenは8の倍数であること。leが非nilなら、リトルエンディアンによるバイトオーダーを使用する。
sint bitlen le長さbitlenビットのネットワークバイトオーダー(ビッグエンディアン)による符号付き整数。bitlenは8の倍数であること。leが非nilなら、リトルエンディアンによるバイトオーダーを使用する。
str len長さがlenバイトであるようなユニバイト文字列(テキストの表現方法を参照)。packを行う際には入力文字列の最初のlenバイトがpack済み出力にコピーされる。入力文字列がlenより短い場合には、残りのバイトはnull(0)になる。ただし事前に割り当てた文字列がbindat-packに与えられた場合には、残りのバイトは未変更のまま残される。入力文字列がASCII文字とeight-bit文字だけから構成されたマルチバイト文字列の場合には、packを行う前にユニバイトに変換される。それ以外のマルチバイト文字列の場合にはエラーをシグナルする。unpackを行う際には、pack済み入力文字列中のすべてのnullバイトはunpack済み出力にも出現することになるだろう。
strz &optional lenlenが与えられない場合にはnull終端された可変長ユニバイト文字列である(テキストの表現方法を参照)。strzへpackする際には、入力文字列全体にnull(0)バイトを付加してpack出力にコピーする(strzへのpackに事前割り当て済みの文字列が与えられた場合には、その事前割り当て済み文字列は出力文字列の終端にnullバイトを付加するための十分なスペースをもっている必要がある;
バイトのunpackとpackを行う関数を参照)。pack済み出力の長さは、入力文字列の長さに(null終端用の)1を加えた値になる。入力文字列にnullバイトが含まれていてはならない。入力文字列がASCII文字とeight-bit文字だけから構成されたマルチバイト文字列の場合には、packを行う前にユニバイトに変換される。それ以外のマルチバイト文字列の場合にはエラーをシグナルする。strzのunpack時には、入力文字列を終端するnullバイトまで(ただしnullバイト自体は除外)のすべてのバイトが出力文字列に含まれることになる。
lenが与えられた場合にはstrと同じように振る舞うが2つ異なる点がある:
警告: 入力文字列がlenより短かったり、最初のlenバイトにnullバイトが含まれている場合のみ、pack済出力がnull終端される。
vec len [type]len要素のベクター。要素のタイプはtypeにより与えられる(デフォルトはバイト)。typeは任意のBindatタイプ式を指定できる。
repeat len [type]vecと同様だがリストから双方向にunpack/packする(vecはunpackするベクター)。
bits lenlenバイト内で1にセットされたビットのリスト。バイトはビッグエンディアンオーダーで、ビットは8 * len
- 1で始まり0で終わるよう番号が付けされる。たとえばbits 2では、#x28
#x1cは(2 3 4 11 13)、#x1c #x28は(3 5 10 11
12)にunpackされる。
fill lenlenバイトは単なるフィラーとして使用される。これらのバイトはpack時には未変更のままとなり通常は0のままであることを、unpack時には単にnilをリターンすることを意味する。
align lenfillと同様だが、次のlenの倍数バイトまでスキップを要するバイト数である点が異なる。
type expこれによりタイプを間接的に参照できる。expはBindatタイプvalueをリターンするLisp式であること。
unit expこれは0ビットのスペースを使用する簡易タイプ。expはそのようなフィールドの“unpack”を試みた際にリターンされる値を記述する。
struct fields...複数フィールドから構成されるコンポジットタイプ(composite typex: 複合型)。フィールドはそれぞれ(name
type)という形式をもち、typeには任意のBindatタイプ式を指定できる。alignやfillのフィールドのように、そのフィールド値が命名に値しない場合には、nameは_でもよい。コンテキストによりBindatタイプ式であることが明確なら、シンボルstructは省略可。
上述のタイプの中で、lenとbitlenはフィールド内のバイト数(またはビット数)を指定する整数として与えられます。そのフィールドが固定長でなければ、通常は値は先行するフィールドの値に依存します。この理由により、lenの長さは定数である必要がないので任意のLisp式を指定することができ、フィールド名から先行するフィールドの値を通じて参照することができるのです。
たとえば先頭のバイトが16ビット整数の後続ベクターにサイズを与えるデータレイアウトの仕様は、以下のようになります:
(bindat-type (len u8) (payload vec (1+ len) uint 16))