For Development HEAD DRAFTSearch (procedure/syntax/module):

12.2 binary.pack - バイナリデータのパック

Module: binary.pack

このモジュールは、バイナリデータをテンプレートを使って パック/アンパック(読み書き)するためのインタフェースを提供します。 この機能は、その多くをPerlのpack/unpack関数から着想し、他の言語での 同じような機能と比較しながら、しかし、データベースライクな処理に 便利なように、より一般的でより効率が良くなるように実装しました。 これを受けて、最も大きな相違点は、全てのパック可能な値はアンパック 可能で(逆も同様)、パック/アンパックのデフォルトの振る舞いはポートI/Oを 使うので、巨大なファイルを読みながらそこからアンパックすることが できます。また、テンプレートはディスパッチクロージャとして格納でき、 パック、アンパック、あるいは値のスキップさえも、テンプレートを パーズし直すことなく行えます。

Function: pack template list :key output to-string?

{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式。readwriteで扱われる。

オプションのキーワード:outputが与えられると、 現在の出力ポートの代わりにそのポートが使われます。 :to-string?が与えられそれが真である場合は、 パックは蓄積され、その出力は文字列として返ります。

(pack "CCCC" '(65 66 67 68) :to-string? #t)
 ⇒ "ABCD"

(pack "C/a*" '("hello") :to-string? #t)
 ⇒ "\x05hello"
Function: unpack template :key :input :from-string

{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されます。

Function: unpack-skip template :key :input

{binary.pack} unpack-skipは、値を返さないことを除いてunpackと同じです。 いくつかのケースでは、特に固定サイズのテンプレートを使うときには、 単に値を読み飛ばしたいときにより効率的です。

Function: make-packer template

{binary.pack} 低レベルなインタフェースです。この関数は、pack、unpackやキャッシュ された同じテンプレートを読み飛ばす時に使われるディスパッチクロージャを 返します。ディスパッチクロージャは、以下のようにシンボルメソッドを 受け付けます。

'pack list

listにあるアイテムを、現在の出力ポートへpackします。

'unpack

現在の入力ポートからアイテムをunpackします。

'skip

現在の入力ポートからのアイテムをスキップします。

'packer

キャッシュされた’packクロージャを返します。

'unpacker

キャッシュされた’unpackクロージャを返します。

'skipper

キャッシュされた’skipクロージャを返します。

'length

テンプレートの知られている固定された長さを返します。

'variable-length?

テンプレートが可変長の要素を持っている場合に#tを返します。



For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT