binary.pack
- バイナリデータのパック ¶このモジュールは、バイナリデータをテンプレートを使って パック/アンパック(読み書き)するためのインタフェースを提供します。 この機能は、その多くをPerlのpack/unpack関数から着想し、他の言語での 同じような機能と比較しながら、しかし、データベースライクな処理に 便利なように、より一般的でより効率が良くなるように実装しました。 これを受けて、最も大きな相違点は、全てのパック可能な値はアンパック 可能で(逆も同様)、パック/アンパックのデフォルトの振る舞いはポートI/Oを 使うので、巨大なファイルを読みながらそこからアンパックすることが できます。また、テンプレートはディスパッチクロージャとして格納でき、 パック、アンパック、あるいは値のスキップさえも、テンプレートを パーズし直すことなく行えます。
{binary.pack
}
listにある値を、文字列templateで指定されたフォーマットに
したがって、現在の出力ポートに書き出します。テンプレート文字列は、
1文字のコードの連続で、オプションで(デフォルトが1である)カウント用の数字
が続きます。
フォーマット文字は一般的に、カウントを文字のバイト数と解釈する
文字列型と、カウントを繰り返し指示子と解釈するオブジェクト型に
分けられます。カウントは文字*
で指定され、文字列型では
文字列の全体の長さを、オブジェクト型では残りの全ての値を使うことを
意味します。
カウントは大括弧に囲まれたテンプレートとしても指定でき、その場合
カウントはその大括弧を囲んでいるテンプレートのバイト数を意味します。
例えば、x[L]
はlongをスキップします。
特別なフォーマット文字/
は、パックされたデータが、値に続く
動的なカウント分を含むという構造を表すために使われます。
テンプレートは、<count-item>/<value-item>
のように書かれ、
ここでは<count-item>
は数値のカウントと解釈されるいかなる
テンプレート文字、<value-item>
はこのカウントを使ういかなる
他のテンプレート文字です。
<value-item
>の後に通常のカウントが与えられても、無視されます。
フォーマット文字@
は、カウントとともに使われ、テンプレートの
最初からの絶対位置までパディングします。
サブテンプレートは、括弧の中にグループ化されます。<>が使われると、 ネストされたリストに再帰的に適用されるグループ化オペレータとしても 振舞います。
文字列型:
a
任意の不完全文字列。NULLでパディングされます。
A
テキスト文字列。空白スペースでパディングされます。
Z
NULL終端(ASCIZ)文字列。NULLでパディングされます。
b
ビット文字列(それぞれのバイトにおけるビットオーダーは昇順)。
B
ビット文字列(それぞれのバイトにおけるビットオーダーは降順)。
h
16進文字列(低いニブルが先)。
H
16進文字列(高いニブルが先)。
オブジェクト型:
c
符号付き8ビット整数。
C
符号なし8ビット整数。
s
符号付き16ビット整数。
S
符号なし16ビット整数。
i
符号付き整数(>= 32ビット)。
I
符号なし整数(>= 32ビット)。
l
符号付きlong(32ビット)。
L
符号なしlong(32ビット)。
n, n!
ネットワークオーダー(ビッグエンディアン)での符号なし/符号つきshort(16ビット)。
N, N!
ネットワークオーダー(ビッグエンディアン)での符号なし/符号つきlong(32ビット)。
v, v!
VAXオーダー(リトルエンディアン)での符号なし/符号つきshort(16ビット)。
V, V!
VAXオーダー(リトルエンディアン)での符号なし/符号つきlong(32ビット)。
q
符号付きquad(64ビット)。
Q
符号なしquad(64ビット)。
f
ネイティブ形式の単精度float。
d
ネイティブ形式の倍精度float。
w
BER圧縮された整数。ベース128における符号なし整数で、最も大きな桁が 最初で、高いビットが最後の(一番小さな)バイト以外にセットされる。 したがって、どのような大きさの整数もエンコードできるが、 エンコーディングは効率的で、小さな整数は通常のchar/short/int エンコーディングの場合よりも占有する空間が少ない。
x
NULLバイト。
o
S式。read
とwrite
で扱われる。
オプションのキーワード:outputが与えられると、 現在の出力ポートの代わりにそのポートが使われます。 :to-string?が与えられそれが真である場合は、 パックは蓄積され、その出力は文字列として返ります。
(pack "CCCC" '(65 66 67 68) :to-string? #t) ⇒ "ABCD" (pack "C/a*" '("hello") :to-string? #t) ⇒ "\x05hello"
{binary.pack
}
packの逆を行うもので、unpackは現在の入力ポートから、値が文字列の
templateでパックされているものとして読み込み、その値をリストとして
返します。unpackはpackと同じフォーマット文字列を受け付けます。
また、いかなるリストxとフォーマット文字列fmtにおいても、
次のようなトートロジーが維持されます。
(equal? x (unpack fmt :from-string (pack fmt x :to-string? #t)))
ただ一つの例外は、テンプレートが*
を含み、o
テンプレートが
使われている場合です。これは、Schemeの数値リテラルは確実に区切られる
ことができないからです(pack
の将来のバージョンでは、
新しいread構文を登録することによってこれは回避されるでしょう)。
オプションのキーワード:inputが与えられると、現在の入力ポートの 代わりにそのポートが使われます。:from-stringが与えられると、 packはその文字列を入力とします。
(unpack "CCCC" :from-string "ABCD") ⇒ '(65 66 67 68) (unpack "C/a*" :from-string "\x05hello") ⇒ '("hello")
註: 現在のバージョンには、unpack
のテンプレートの
@
が想定したように動かないというバグがあります。
将来のバージョンでfixされます。
{binary.pack
}
unpack-skipは、値を返さないことを除いてunpackと同じです。
いくつかのケースでは、特に固定サイズのテンプレートを使うときには、
単に値を読み飛ばしたいときにより効率的です。
{binary.pack
}
低レベルなインタフェースです。この関数は、pack、unpackやキャッシュ
された同じテンプレートを読み飛ばす時に使われるディスパッチクロージャを
返します。ディスパッチクロージャは、以下のようにシンボルメソッドを
受け付けます。
'pack list
listにあるアイテムを、現在の出力ポートへpackします。
'unpack
現在の入力ポートからアイテムをunpackします。
'skip
現在の入力ポートからのアイテムをスキップします。
'packer
キャッシュされた’packクロージャを返します。
'unpacker
キャッシュされた’unpackクロージャを返します。
'skipper
キャッシュされた’skipクロージャを返します。
'length
テンプレートの知られている固定された長さを返します。
'variable-length?
テンプレートが可変長の要素を持っている場合に#tを返します。