binary

ReferenceTOPKeywords

コマンド名

binary -バイナリ値を生成、あるいは文字列に変換します。

構文

binary format formatString ?arg arg ...?
binary scan string formatString ?varName varName ...?

記述

本コマンドはバイナリデータ処理を提供します。 binary format は普通のTcl値(文字)からバイナリ値を生成します。例えば、32ビットアーキテクチャの場合、整数値"16"と"22"から2つの4バイト整数バイナリ値(計8バイト)を生成して返します。binary scanは逆にバイナリ値を普通のTcl値(文字)に変換してTcl変数にセットします。

binary format

binary format コマンドはformatStringによって指定されたフォーマットに従って後続の引数で示された値からバイナリ値を生成して返します

formatStringは1個以上のフィールドコードを含む文字列です。各フィールドコードは1つのタイプを示す文字とオプションの整数値の組で構成されます。タイプ文字は値の型を示します。これに続くcountはタイプ文字の繰り返し数を示します。countを与える場合は正の10進整数か *のいずれかです。 通常*は残りの全てが同じタイプの連続であることを示します。フィールドコードは1つの引数をフォーマットするために使用されます。フォーマット文字列内のフィールドコード数と同じ数の値が後続のアーギュメントに見つけられないとエラーが生成されます。

フィールドコードと引数の関係を明らかにするために、下記の例を見て下さい。

binary format d3d {1.0 2.0 3.0 4.0} 0.1

フィールドコードは2つありますので値も2つ続いています。最初の値は4つの数字のリストですが、最初のフィールドコードのcountが3のため、前からの3つの数字のみが使われます。2番目の値(0.1)は第2のフィールドコードに対応します。結果のバイナリ列は1.0,2.0,3.0,0.1の4つの倍精度実数列です。

フィールドコードによってバイナリデータが作成されると、出力バッファのカレントポジションからデータ格納され、最後に格納されたバイトの後にカーソルが移動します。最初にカーソルはバッファの先頭ポジション0にあります。使えるタイプは次の文字のいずれかです。

a
A
b
B
h
H
c
s
S
i
I
w
W
f
d
x
X
@
a
長さがcountの文字列を出力します。argcountより少ないバイトを持っている場合、フィールドを補足するために0バイトが使われます。argが指定された長さより長い場合、余った文字は無視されます。count*ならば、argにおけるバイトの全てがフォーマットされます。countが省略される場合、1文字だけフォーマットされます。例えば
binary format a7a*a alpha bravo charlie

alpha\000\000bravocに相当する文字列を返します。

A
このフォームはaとほぼ同じで、ただしフィールドを補足するものは「スペース」で、0値ではありません。例えば
binary format A6A*A alpha bravo charlie

alpha bravocを返します。

b
長さcount の2進数列をバイト単位でlow-to-high順に出力します。Argは文字1及び0から成る列でなければなりません。low-to-high順にフォーマットされたビットを最初から最後まで順番に出力します。argcountより少ない数字であれば、不足するビットに0が補足されます。argが数字の指定された数以上ある場合、余った数字は無視されます。count*ならば、argにおける数字の全てが評価されます。countが省略された場合1つの数字がフォーマットされます。フォーマットされたビット数がバイトの境界に到達しない場合には不足しているビットが0で埋められます。例えば
	
binary format b5b* 11100 111000011010
\x07\x87\x05に相当する列を返します。
B
各バイトごとにビットがhigh-to-low順に格納されるということを除けば、このフォームはbと同じです。例えば
binary format B5B* 11100 111000011010

\xe0\xe1\xa0に相当する列を返します。

h
長さcount の16進数列をバイトごとにlow-to-high順に出力します。Argは「0123456789abcdefABCDEF」のいずれかから成る文字列でなければなりません。2つの16進数字からバイト値を求め、low-to-high順に出力します。argcountより少ない数字である場合、不足する文字に0が補足されます。argが指定された数より多い場合、余った数字は無視されます。count*ならば、argにおける数字の全てが評価されます。countが省略された場合、ひとつの数字がフォーマットされます。フォーマットされた値がバイトの境界で終わらない場合(16進数列数が奇数)、最後のバイトの不足する4ビットは0で埋められます。例えば
binary format h3h* AB def

\xba\x00\xed\x0fに相当する列を返します。

H
各バイトごとに数字がhigh-to-low順に格納されるということを除けば、このフォームはbと同じです。例えば
binary format H3H* ab DEF

\xab\x00\xde\xf0に相当する列を返します。

c
1個以上の8ビット整数値を出力します。 countが指定されない場合、argは1つの整数値でなければなりません。countが指定された場合、argは少なくともcount個々の整数要素を含むリストでなければなりません。各整数のlow-order8ビット値が1バイト値として出力バッファに積まれていきます。count*ならば、リストにおける整数の全てが評価されます。リストの要素数がcountより少ない場合、エラーが生成されます。リストの要素数がcountより大きい場合、余った要素は無視されます。例えば
binary format c3cc* {3 -3 128 1} 260 {2 5}

\x03\xfd\x80\x04\x02\x05に相当する列を返します。一方、

binary format c {2 5}

はエラーを生成します。

s
1個以上の16ビット整数をリトルエンディアン(little-endian)順に出力します。LOWバイト側を先に格納した16ビット整数が返されます。例えば
binary format s3 {3 -3 258 1}

\x03\x00\xfd\xff\x02\x01に相当する列を返します。

S
ビッグエンディアン(big-endian)順に出力するということを除けば、このフォームはsと同じです。 例えば
binary format S3 {3 -3 258 1}

\x00\x03\xff\xfd\x01\x02に相当する列を返します。

i
1個以上の32ビット整数をリトルエンディアン(little-endian)順に出力します。LOWバイトからHIGHバイト順に32ビット整数4バイトが出力されます。例えば
binary format i3 {3 -3 65536 1}

\x03\x00\x00\x00\xfd\xff\xff\xff\x00\x00\x01\x00を返します。

I
ビッグエンディアン(big-endian)順に出力するということを除けば、このフォームはiと同じです。例えば
binary format I3 {3 -3 65536 1}

\x00\x00\x00\x03\xff\xff\xff\xfd\x00\x01\x00\x00を返します。

w
1個以上の64ビット整数を、リトルエンディアン(little-endian)順に出力します。LOWバイトからHIGHバイト順に64ビット整数8バイトが出力されます。例えば
binary format w 7810179016327718216

は列HelloTclを返します。

W
1個以上の64ビット整数を、ビッグエンディアン(big-endian)順に出力します。例えば
binary format W 4785469626960341345

は列BigEndianを返します。

f
1個以上の単精度浮動小数点数を出力します。浮動小数点数はアーキテクチャの間の移植ができません。。浮動小数点数のサイズもアーキテクチャによって異なりますので、生成したバイト数も異なります。もし変換値がコンピュータ固有の最大値よりオーバーフローした場合、代りにシステムによって定義されたFLT_MAX値が返されます。Tclが内部で倍精度浮動小数点数を使うので、単精度への変換には精度の損失が発生する場合があります。例えば、Intel Pentiumプロセッサ上で動くWindowsシステム上で、
binary format f2 {1.6 3.4}

\xcd\xcc\xcc\x3f\x9a\x99\x59\x40に相当する列を返します。

d
1個以上の倍精度浮動小数点数を出力するということを除けば、このフォームはfと同じです。例えば、Intel Pentiumプロセッサ上で動くWindowsシステム上で、
binary format d1 {1.6}

\x9a\x99\x99\x99\x99\x99\xf9\x3fに相当する列を返します。

x
count個のヌルバイトを出力します。countが指定されない場合は、一つのヌルバイトを出力します。count*の場合、エラーを生成します。このタイプは引数を消費しません。例えば
binary format a3xa3x2a3 abc def ghi

abc\000def\000\000ghiに相当する列を返します。

X
出力バッファのカーソルを逆方向にcountバイト移動します。 count*である場合、または現在のカーソルポジションより大きい場合は、カーソルは0にポジションされます。よって次に出力されるバイトは最初のバイトになります。countが省略された場合、カーソルはただ1バイトだけ逆方向に移動します。 このタイプは引数を消費しません。例えば
binary format a3X*a3X2a3 abc def ghi

dghiを返します。

@
出力列におけるカーソルをcountによって指定されたポジションに移動します。ポジション0は出力列の最初のバイトを示します。countがそれまでに格納されたバイト数を越えたポジションである場合は、ヌルバイトが埋められたあと、指定されたポジションに移動されます。count*であれば、カーソルは現在の出力後尾に移動されます。countが省略された場合、エラーが生成されます。このタイプは引数を消費しません。例えば
binary format a5@2a1@*a3@10a1 abcde f ghi j

abfdeghi\000\000jを返します。

binary scan

binary scanコマンドはバイナリ列を変換し、変換した個数を返します。 stringはバイナリの入力値で、formatStringはどのようにこの入力値を変換するかを示すフォーマットです。各varNameは変数の名前を示します。stringをスキャンして得られた値は順に対応する変数に格納されます。

binary formatと同様に、formatStringはフィールドコードの連続です。各フィールドコードは1つのタイプを表す文字と省略可能な整数countとのペアです。大多数のフィールドコードは、スキャン結果値を変数に保存するので、フィールドコードの数だけのvarNameが必要になります。タイプ文字はバイナリデータの型を示します。countはそのタイプの連続数を示します。countは正の10進整数もしくは*です。 *は残りのバイナリデータが全てそのタイプであることを示します。もしデータのバイト数がフィールドコードの要求バイト数より少ない場合、変数には何も代入しないで終了し、セットした変数の個数を返します。一方、引数の個数が足りない場合にはエラーが生成されます。

binary formatと同様に、例を使ってbinary scanサブ‐コマンドにおけるフィールドコードと引数の間の関係を説明します。

binary scan $bytes s3s first second

このコマンドは3つの整数のリストを変数firstに割り当て、1つの値を変数secondに割り当てます。しかし、bytesが8バイト(すなわち、4つの2バイト整数)より少ない場合はsecondへの割り当ては行いません。更に、bytesが6バイト(すなわち、3つの2バイト整数)よりも少ない場合にはfirstへの割り当ても行なわれません。従って

puts [binary scan abcdefg s3s first second]
puts $first
puts $second

は以下のものを出力します(変数のいずれも事前に設定されていないと仮定します ) 。

1
25185 25699 26213
can't read "second": no such variable

注意: cs とS ( 64bitシステム上のiIも ) は内部ではsigned long値に変換されます。変換の際、MSB(文字は0x80、shortは0x8000、intは0x80000000)が符号ビットとして使われます。従ってMSBが1の場合は負数として扱われ、符号拡張が行われます。このようなケースが下記の例です。

set signShort [binary format s1 0x8000]
binary scan $signShort s1 val;# val == 0xFFFF8000

もし符号なし値(unsigned)を生成したい場合は、返り値を希望のサイズにマスクします。例えば、unsigned short値を生成するためには上位16bビットを0クリアします

set unsigendShort [expr {$val & 0xFFFF}];# val == 0x00008000

フィールドコードにより変換が行われる時はバイナリデータ内の架空のカーソルが移動されます。フィールドコードはカーソルがあるバイトにアクセスし、使用したバイト数だけカーソルを進めます。最初にカーソルはデータの先頭ポジションにあります。フィールドコードに使用できるタイプ文字は次の中のひとつです。

a
A
b
B
h
H
c
s
S
i
I
w
W
f
d
x
X
@
a
データからcount長の文字列を取り出します。count*であれば、stringsの残っている全バイトが変数に代入されます。countが省略された場合は、1文字が代入されます。データにcount数だけの文字がない場合はすぐにデータスキャンを終了します。例えば
binary scan abcde\000fghi a6a10 var1 var2

1を返し、var1abcde\000に相当する文字列を格納しますが、var2は更新されません。

A
変数に格納される前に、スキャンされた値から後部の空白とヌルを取り除くことを除いて、このフォームはaと同じです。例えば
binary scan "abc efghi  \000" A* var1

var1abc efghiを格納して、1を返します。

b
バイトデータのビットをlow-to-high順に、1と0文字列で表現される長さcountの2進数に変換します。データバイトは前から後ろの順ですが、各バイト内ではlow-to-high順にビットがスキャンされます。次の変換に移るとき、変換されずに余ったビットは無視されて次のバイトから開始されます。count*である場合は stringの残っている全ビットがスキャンされます。countが省略される場合は1ビットだけがスキャンされます。例えば
binary scan \x07\x87\x05 b5b* var1 var2

var111100を格納して、var21110000110100000を格納して、2を返します。

B
各バイト内におけるビットがhigh-to-low順にスキャンされるということを除いて、このフォームはbと同じです。例えば
binary scan \x70\x87\x05 B5B* var1 var2

var101110を格納して、var21000011100000101を格納して、2を返します。

h
バイトデータのビットを、low-to-high順に、「0123456789abcdef」のいずれかの文字で表現される長さcountの16進数列に変換します。データバイトは前から後ろの順番ですが、各バイト内ではlow-to-high順に4ビット単位でスキャンします。次の変換に移るとき、変換されずに余った4ビットは無視されて次のバイトから開始されます。count*である場合は stringに残っている全ビットがスキャンされます。countが省略される場合は1文字分の16進数(即ち4ビット)がスキャンされます。例えば
binary scan \x07\x86\x05 h3h* var1 var2

var1706を格納して、var250を格納して、2を返します。

H
各バイト内における4ビットがhigh-to-low順にスキャンされるということを除いて、このフォームはhと同じです。例えば
binary scan \x07\x86\x05 H3H* var1 var2

var1078を格納して、var205を格納して、2を返します。

c
データをcount個数分の8ビットの符号付き整数に変換し、リストとして変数に格納します。もしcount*である場合、 stringに残っている全バイトがスキャンされます。countが省略されると1つの8ビット整数がスキャンされます。 例えば
binary scan \x07\x86\x05 c2c* var1 var2

var1に{7 -122}を格納して、var25を格納して2を返します。注意するのは返された整数は符号付きであることです。それら整数は以下のような式を用いて符号なし8ビット整数(unsigned char)に変換できます。

expr ( $num + 0x100 ) % 0x100
s
データをlittle-endianと見なし、順にcount個数分の16ビット符号付き整数に変換して変数に格納します。count*である場合、 stringに残っている全バイトがスキャンされます。countが省略されると1つの16ビット整数だけがスキャンされます。 例えば、
binary scan \x05\x00\x07\x00\xf0\xff s2s* var1 var2

var1に{5 7}を、var2-16を格納して2を返します。注意するのは返された整数は符号付きであることです。それらの整数は以下のような式を用いて符号なし16ビット整数(unsigned short)に変換できます。

expr ( $num + 0x10000 ) % 0x10000
S
データをbig-endianと見なす点を除いてsと同じです。例えば、
binary scan \x00\x05\x00\x07\xff\xf0 S2S* var1 var2

var1に{5 7}を、var2-16を格納して2を返します。

i
データをlittle-endianと見なし、順にcount個数分の32ビット符号付き整数に変換して変数に格納します。count*である場合、 stringに残っている全バイトがスキャンされます。countが省略されると1つの32ビット整数だけがスキャンされます。 例えば、
binary scan \x05\x00\x00\x00\x07\x00\x00\x00\xf0\xff\xff\xff i2i* var1 var2

var1に{5 7}を、var2-16を格納して2を返します。注意する点は返される値が符号付き整数である点です。Tclでは符号なし32ビット整数を扱えません。

I
データをbig-endianと見なす点を除いてiと同じです。例えば、
 
binary scan \x00\x00\x00\x05\x00\x00\x00\x07\xff\xff\xff\xf0 I2I* var1 var2

var1に{5 7}を、var2-16を格納して2を返します。

w
データをlittle-endianと見なし、順にcount数分の64ビット符号付き整数に変換して変数に格納します。count*である場合、 stringに残っている全バイトがスキャンされます。countが省略されると1つの64ビット整数だけがスキャンされます。 例えば、
binary scan \x05\x00\x00\x00\x07\x00\x00\x00\xf0\xff\xff\xff wi* var1 var2

var130064771077を、var2-16を格納して2を返します。注意する点は返される値が符号付き整数であるということです。Tclでは符号なし64ビット整数を扱えません。

W
データをbig-endianと見なす点を除いて、wと同じです。例えば、
binary scan \x00\x00\x00\x05\x00\x00\x00\x07\xff\xff\xff\xf0 WI* var1 var2

var121474836487を、var2-16を格納して2を返します。

f
count個数分の単精度浮動小数数に変換して変数に格納します。count*である場合、 stringに残っている全バイトがスキャンされます。countが省略されると1つの単精度浮動小数点数がスキャンされます。浮動小数点数のサイズはアーキテクチャによって違うので、スキャンされたバイト数も異なります。もしデータが有効な浮動小数点数でない場合、結果値は未定義で、コンパイラに依存します。例えば、Intel Pentiumプロセッサ上で動くWindowsシステム上で、
binary scan \x3f\xcc\xcc\xcd f var1

var11.6000000238418579を格納して1を返します。

d
count個数分の倍精度浮動小数点数に変換する点を除いてfと同じです。例えば、Intel Pentiumプロセッサ上で動くWindowsシステム上で、
binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f d var1

var11.6000000000000001を格納して1を返します。

x
string におけるカーソルをcountバイト後ろに相対移動します。 count*であるか、または移動しようとするカーソルが現在のバイト数を越える場合、カーソルはstringの最後のバイトの後に置かれます。countが省略された場合、カーソルは順方向に1バイト移動します。このタイプは引数を消費しません。例えば、
binary scan \x01\x02\x03\x04 x2H* var1

var10304を格納して1を返します。

X
string におけるカーソルをcountバイト前に相対移動します。count*であるか、または先頭バイトを通過してしまう場合にはstringの最初のバイトを示すポジション0に置かれます。countが省略された場合は、カーソルは逆方向に1バイト移動します。
注意:このタイプは引数を消費しません。例えば
binary scan \x01\x02\x03\x04 c2XH* var1 var2

var1に{1 2}を、var2020304を格納して2を返します。

@
カーソルをデータのcountバイト位置に絶対移動します。ポジション0がstringにおける最初のバイトを指します。countstring の境界を越えたポジションを示す場合、カーソルは最後のバイトの後に置かれます。countが省略さた場合、エラーが生成されます。例えば
binary scan \x01\x02\x03\x04 c2@1H* var1 var2

var1に{1 2}を、var2020304を格納して2を返します。

プラットフォーム問題

コンピュータ固有のバイト順を考慮して整数値をフォーマットもしくはスキャンしなければなりませんが、tcl_platform配列のbyteOrder要素を参照することで、big-endian/little-endianのどちらを使用すべきか知ることができます。

参照

scan, tclvars

キーワード

binary, format, scan


Copyright © 1997 by Sun Microsystems, Inc. Copyright © 1995-1997 Roger E. Critchlow Jr.