Hatena::Groupjavascript

JavaScriptで遊ぶよ

 | 

2011-09-23

ArrayBuffer と alignment

09:28

↓このエラーでハマった。

var ab = new ArrayBuffer(10);
new Uint32Array(ab, 0, 1); // success
new Uint32Array(ab, 1, 1); // error
new Uint32Array(ab, 2, 1); // error
new Uint32Array(ab, 3, 1); // error
new Uint32Array(ab, 4, 1); // success

エラーの内容は、Chrome だと "INDEX_SIZE_ERR: DOM Exception 1" で、Opera だと "Byte offset not aligned with element size" で、Safari だと "RangeError: ArrayBuffer length minus the byteOffset is not a multiple of the element size." とか。

Uint32Array.BYTES_PER_ELEMENT は4なので、Uint32Array を読み出すのは4の倍数個目からしかできないことになってる。

仕様だとこんなふうになってる。

TypedArray(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length)

Create a new TypedArray object using the passed ArrayBuffer for its storage. Optional byteOffset and length can be used to limit the section of the buffer referenced. The byteOffset indicates the offset in bytes from the start of the ArrayBuffer, and the length is the count of elements from the offset that this TypedArray will reference. If both byteOffset and length are omitted, the TypedArray spans the entire ArrayBuffer range. If the length is omitted, the TypedArray extends from the given byteOffset until the end of the ArrayBuffer.

The given byteOffset must be a multiple of the element size of the specific type, otherwise an exception is raised.

If a given byteOffset and length references an area beyond the end of the ArrayBuffer an exception is raised.

If length is not explicitly specified, the length of the ArrayBuffer minus the byteOffset must be a multiple of the element size of the specific type, or an exception is raised.

↑強調したところ。

じゃあ中途半端なところから読み出したい場合はどうするか。

DataView というのを使うらしい。

var ab = new ArrayBuffer(10);
var view = new DataView(ab);
view.getUint32(0); // success
view.getUint32(1); // success
view.getUint32(2); // success
view.getUint32(3); // success
view.getUint32(4); // success

仕様はこんな感じ。

The DataView View Type

An ArrayBuffer is a useful object for representing an arbitrary chunk of data. In many cases, such data will be read from disk or from the network, and will not follow the alignment restrictions that are imposed on the typed array views described earlier. In addition, the data will often be heterogeneous in nature and have a defined byte order. The DataView view provides a low-level interface for reading such data from and writing it to an ArrayBuffer.

わかりにくいなあ… earlier のところには alignment なんて単語は出て来てないんですけど。どうやって調べたらいいんですか。


getUint32 とかだと一つ一つしか読み出せないし、一気にガーっと TypedArray にしたいだけなのに、このメソッドを何万回も呼ばないといけないと思うと…

正直言って blob, ArrayBuffer まわりの仕様はホント好きになれない。なんとかならないのかな。

トラックバック - http://javascript.g.hatena.ne.jp/edvakf/20110923
 |