ArrayBufferについて
WebSocketやchrome.socket、AudioやVideo APIなどが進んできたせいで、JavaScriptで生データを触ることが増えてきています。 その時に使えるのがArrayBufferというオブジェクトなんですがいまいち整理がついてないので、MDNを訳しながら、まとめてみました。
ちなみにMDNでは
Webアプリケーションがパワフルになってくるに連れて、audioやvideoの操作などの機能や、WebSocketsを用いた生データのアクセスなどが追加され、その結果、早く・容易に生のバイナリデータをJavaScirptコードで扱うことのできる機能が必要なことが明確になって来ました過去には文字列として生データを扱い、charCodeAt()を用いてデータバッファからバイトを読み取るようなこともされていました。
とあります。この機能がArrayBufferですね。
ArrayBufferとView
できる限りの柔軟さと効率を考えて、JavaScriptでは実装をbufferとviewに分割しました。
Buffer (ArrayBuffer classによって実装)
まさにデータの塊です。フォーマットもされておらず、アクセスするメカニズムも提供されていません。ただ、バッファのサイズ(bit)を指定して、メモリ上に領域を確保するだけです。ここにアクセスするために利用するのが Viewです。
View (ArrayBufferView classとそのサブクラスによって実装)
ArrayBufferにアクセスするために利用するのがviewでコンテキスト(ここでは、int8やuint8といったdata typeや、開始オフセット、要素数などを指します)を提供します。
感覚的にはCで考えてvoid*で受けてmemcpyで適当に切り取って、castして読み込むことと近いかと思っています。
viewについて
viewはLow LevelのAPIを提供するDataViewとtypeコンテキストを持つArrayBufferView(Xには型とサイズが入ります)の2つに大別されます。
DataView MDN
DataViewは型とオフセット、16bit以上の場合は、endianの指定を持つアクセサを提供します。
- Read
unsigned byte getUint8(unsigned long byteOffset);
- Write
void setUint8(unsigned long byteOffset, unsigned byte value);
その他の型とサイズはリンクを参照してください。
ArrayBufferView
DataViewは一つ一つbufferを触るAPIを提供していましたが、bufferをより扱いやすくするために、ArrayBufferViewというclassが用意されています。 このclassにより、オフセット(デフォルト0)、長さ(デフォルトはbufferの最大値まで)にもとづいてbufferを型とサイズの配列として扱うことができるようになります。
Type | SIze | Description | Equivalent C type |
---|---|---|---|
Int8Array | 1 | 8-bit twos complement signed integer | signed char |
Uint8Array | 1 | 8-bit unsigned integer | unsigned char いわゆるbyte |
Int16Array | 2 | 16-bit twos complement signed integer | short |
Uint16Array | 2 | 16-bit unsigned integer | unsigned short |
Int32Array | 4 | 32-bit twos complement signed integer | int |
Uint32Array | 4 | 32-bit unsigned integer | unsigned intN |
Float32Array | 4 | 32-bit IEEE floating point number | float |
Float64Array | 8 | 64-bit IEEE floating point number | double |
コンテキスト付きArrayBufferViewは下記のように使います
var buffer = new ArrayBuffer(32); // 32 bit のbufferを確保 console.log(buffer.byteLength); // => 32 var int8array = new Int8Array(buffer); // 8 bitで4つの要素を持つArray console.log(int8array.length); // => 4
例えばInt8ArrayのコンストラクタはこうなっていますMDN
Int8Array Int8Array(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length);
ArrayBufferの最初にヘッダ情報などが含まれている場合、offsetで開始位置を適当にすることで、扱いやすいです。
ArrayBufferTypeは、確保してあるbufferに対しての操作を提供するだけなので、例えば、Int8Arrayで操作した後に、Int16Arrayで読み込む、といったことも可能になります。
イメージ
こんな感じでheader付きのArrayBufferがあった場合、最初のheaderをDataViewで直接読み込んで、オフセットかけて残りのデータを読み込む、とかがリアルな用途かと思います。
参考
更新履歴
- 2012/09/30 1:58 ArrayBufferType => ArrayBufferView