Binary
はじめに
「見た目は JavaScript、頭脳(中身)は Ruby、(安定感は AC/DC)」 でお届けしているスクリプト言語 Kinx。言語はライブラリが命。ということでライブラリの使い方編。
今回は Binary です。
- 参考
- 最初の動機 ... スクリプト言語 KINX(ご紹介)
- 個別記事へのリンクは全てここに集約してあります。
- リポジトリ ... https://github.com/Kray-G/kinx
- Pull Request 等お待ちしております。
- 最初の動機 ... スクリプト言語 KINX(ご紹介)
バイナリ(Binary)は配列(Array)に似ているが、保持できる値が 0x00 ~ 0xFF までのバイト列である点が異なる。内部実装的にも単純にバイトの Vector として実装されており、バイナリデータを格納するのに適している。
Binary 特殊オブジェクト
Binary にも特殊オブジェクト Binary
があり、Binary
オブジェクトに対して関数定義することができる。尚、後述するがバイナリデータはスプレッド演算子を使って配列と相互変換できる。以下の例はバイナリを配列に変換して配列に対して map
している例となる。
Binary.toStringArray = function(bin) {
return [...bin].map(&(e) => *e);
};
System.println([...<97, 98, 99>]); // => [97, 98, 99]
System.println(<97, 98, 99>.toStringArray()); // => ["a", "b", "c"]
Binary
ファイル・ロード
バイナリデータは以下のように File.BINARY
を指定することでファイルから読み込むこともできる。指定しなかった場合は File.TEXT
と同様、文字列としてファイルを読み込む。
var file = File.load("filename", File.BINARY);
組み込み特殊メソッド
Binary には Array と同じようなメソッドが登録されている。が、基本的にバイナリ列に適用することになるため、あまり複雑なことはできない。push
、pop
、unshift
、shift
は破壊的な操作を行う。
メソッド | 意味 |
---|---|
Binary.length(bin) | バイナリ bin の要素数を返す。 |
Binary.push(bin, e) | バイナリ bin の最後の要素として e を追加する。 |
Binary.pop(bin) | バイナリ bin の最後の要素を返し、要素から削除する。 |
Binary.unshift(bin, e) | バイナリ bin の最初の要素として e を追加する。 |
Binary.shift(bin) | バイナリ bin の最初の要素を返し、要素から削除する。後ろの要素は順次先頭方向に移動する。 |
Binary.join(bin, sep, fmt) | バイナリ bin の要素を全てつなげた文字列として返す。要素と要素の間は sep でつなぐ。fmt が省略された場合 "0x02x" でフォーマットされる。 |
Binary.reverse(bin) | バイナリ bin の要素を逆順にした新たなバイナリを返す。 |
Binary.toString(bin, sep, fmt) | バイナリ bin を文字列化して返す。デフォルトのセパレータは ", " 。fmt が省略された場合 "0x02x" でフォーマットされる。 |
Binary.apply(bin, func) | func(bin) を実行する。 |
Binary.each(bin, callback) | bin の各要素 e に対して callback(e, index) を実行する。 |
Binary.map(bin, callback) | bin の各要素 e に対して callback(e, index) の結果の集合となる新たなバイナリを返す。 |
Binary.filter(bin, callback) | bin の各要素 e に対して callback(e, index) の結果が真となるもののみの集合として新たなバイナリを返す。 |
Binary.reject(bin, callback) | bin の各要素 e に対して callback(e, index) の結果が偽となるもののみの集合として新たなバイナリを返す。 |
Binary.reduce(bin, callback, initr) | 前の要素までの結果を r (初期値は initr、指定されていなければ null)として、ary の各要素 e に対し callback(r, e) を行った最終結果を返す。 |
Binary.sort(bin, comp) | 任意の bin の要素 e1, e2 に対する comp(e1, e2) の結果を利用して bin 全体をソートした新たなバイナリを返す。 |
Binary.clone(bin) | bin のコピーを作成する。 |
Binary.println(bin) | bin の各要素 e に対して System.println(e) を適用する。 |
特殊オペレーター
後置 []
オペレーター
バイナリの要素にアクセスする。
var e = ary[5]; // index は 0 はじまりなので 6 番目の要素
左辺値にもなり、バイト列を直接書き換えることができる。
var bin = <1,2,3,4,5>;
bin[2] = 255;
System.println(bin); // => <0x01, 0x02, 0xff, 0x04, 0x05>
二項 +
オペレーター
バイナリ同士をつなげる。右辺値がバイナリではない場合、SystemException("Unsupported Operator")
例外が発生する。
var bin = <1, 2, 3>;
var r = bin + <2, 4>; // => <0x01, 0x02, 0x03, 0x02, 0x04>
単項 *
オペレーター
単項 *
オペレーターをバイナリに適用した場合、バイナリを文字列に変換する。
var a = *<97, 98, 99>; // => "abc"
尚、文字列に単項 *
オペレーターを適用すると配列になるため、バイナリには戻らない。代わりに、バイナリは下記のスプレッド演算子で配列と相互変換ができる。
スプレッド演算子
配列とバイナリで相互変換可能。配列からバイナリに変換する際は、数値であれば 0x00~0xFF の値に丸められる。文字の場合は先頭の文字のみ使われる。
var a = <97, 98, 99>; // == <0x61, 0x62, 0x63>
var b = [...a]; // => [97, 98, 99]
var c = <...b>; // => <0x61, 0x62, 0x63>
var d = <...[1024,1025,1026,"abc"]>; // => <0x00, 0x01, 0x02, 0x61>
// 0x61 == 97 == 'a'
おわりに
バイナリデータも割と扱いたくなるので、一通り機能を揃えてみました。バイト単位でゴニョゴニョできると良いことあるかもしれない。なんとなく例えば x64 向け JIT ライブラリとか作れそうですね。
では、また次回。