Skip to content

Commit

Permalink
Merge pull request HaxeFoundation#3827 from HaxeFoundation/typed_arrays
Browse files Browse the repository at this point in the history
cross platform typed array proposal
  • Loading branch information
ncannasse committed Feb 15, 2015
2 parents 25bf7d9 + 0c76e79 commit e31e94f
Show file tree
Hide file tree
Showing 14 changed files with 549 additions and 24 deletions.
68 changes: 68 additions & 0 deletions std/haxe/io/ArrayBufferView.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package haxe.io;

typedef ArrayBufferViewData = #if js js.html.ArrayBufferView #else ArrayBufferViewImpl #end

#if !js
class ArrayBufferViewImpl {
public var bytes : haxe.io.Bytes;
public var byteOffset : Int;
public var byteLength : Int;
public function new(bytes, pos, length) {
this.bytes = bytes;
this.byteOffset = pos;
this.byteLength = length;
}
public function sub( begin : Int, ?length : Int ) {
if( length == null ) length = byteLength - begin;
if( begin < 0 || length < 0 || begin + length > byteLength ) throw Error.OutsideBounds;
return new ArrayBufferViewImpl(bytes, byteOffset + begin, length);
}
}
#end

abstract ArrayBufferView(ArrayBufferViewData) {

public static var EMULATED(get,never) : Bool;
static #if !js inline #end function get_EMULATED() {
return #if js (cast js.html.ArrayBuffer) == js.html.compat.ArrayBuffer #else false #end;
}

public var buffer(get,never) : haxe.io.Bytes;
public var byteOffset(get, never) : Int;
public var byteLength(get, never) : Int;

public inline function new( size : Int ) {
#if js
this = new js.html.Uint8Array(size);
#else
this = new ArrayBufferViewData(haxe.io.Bytes.alloc(size), 0, size);
#end
}

inline function get_byteOffset() return this.byteOffset;
inline function get_byteLength() return this.byteLength;
function get_buffer() : haxe.io.Bytes {
#if js
return haxe.io.Bytes.ofData(this.buffer);
#else
return this.bytes;
#end
}

public inline function sub( begin : Int, ?length : Int ) {
#if js
return fromData(new js.html.Uint8Array(this.buffer.slice(begin, length == null ? null : begin+length)));
#else
return fromData(this.sub(begin,length));
#end
}

public inline function getData() : ArrayBufferViewData {
return this;
}

public static inline function fromData( a : ArrayBufferViewData ) : ArrayBufferView {
return cast a;
}

}
12 changes: 11 additions & 1 deletion std/haxe/io/BytesBuffer.hx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ class BytesBuffer {
b.Write(src.getData(), 0, src.length);
#elseif java
b.write(src.getData(), 0, src.length);
#elseif js
var b1 = b;
var b2 = @:privateAccess src.b;
for( i in 0...src.length )
b.push(b2[i]);
#else
var b1 = b;
var b2 = src.getData();
Expand Down Expand Up @@ -158,6 +163,11 @@ class BytesBuffer {
b.Write(src.getData(), pos, len);
#elseif java
b.write(src.getData(), pos, len);
#elseif js
var b1 = b;
var b2 = @:privateAccess src.b;
for( i in pos...pos+len )
b.push(b2[i]);
#else
var b1 = b;
var b2 = src.getData();
Expand Down Expand Up @@ -189,7 +199,7 @@ class BytesBuffer {
var buf = python.lib.Builtin.bytearray(b);
var bytes = new Bytes(buf.length, buf);
#elseif js
var bytes = new Bytes(b.length,new BytesData(b));
var bytes = new Bytes(new js.html.Uint8Array(b).buffer);
#else
var bytes = new Bytes(b.length,b);
#end
Expand Down
2 changes: 1 addition & 1 deletion std/haxe/io/BytesData.hx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ package haxe.io;
#elseif python
typedef BytesData = python.lib.ByteArray;
#elseif js
typedef BytesData = js.html.Uint8Array;
typedef BytesData = js.html.ArrayBuffer;
#else
typedef BytesData = Array<Int>;
#end
6 changes: 3 additions & 3 deletions std/haxe/io/BytesInput.hx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
package haxe.io;

class BytesInput extends Input {
var b : BytesData;
var b : #if js js.html.Uint8Array #else BytesData #end;
#if !flash9
var pos : Int;
var len : Int;
Expand Down Expand Up @@ -50,7 +50,7 @@ class BytesInput extends Input {
this.b = ba;
this.b.endian = flash.utils.Endian.LITTLE_ENDIAN;
#else
this.b = b.getData();
this.b = #if js @:privateAccess b.b #else b.getData() #end;
this.pos = pos;
this.len = len;
this.totlen = len;
Expand Down Expand Up @@ -144,7 +144,7 @@ class BytesInput extends Input {
untyped __php__("$buf->b = substr($buf->b, 0, $pos) . substr($this->b, $this->pos, $len) . substr($buf->b, $pos+$len)");
#else
var b1 = b;
var b2 = buf.getData();
var b2 = #if js @:privateAccess buf.b #else buf.getData() #end;
for( i in 0...len )
b2[pos+i] = b1[this.pos+i];
#end
Expand Down
106 changes: 106 additions & 0 deletions std/haxe/io/Float32Array.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright (C)2005-2015 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package haxe.io;

#if js
import js.html.compat.Float32Array;
#end

typedef Float32ArrayData = #if js js.html.Float32Array #else ArrayBufferView.ArrayBufferViewData #end

abstract Float32Array(Float32ArrayData) {

public static inline var BYTES_PER_ELEMENT = 4;
public var length(get,never) : Int;
public var view(get,never) : ArrayBufferView;

public inline function new( elements : Int ) {
#if js
this = new Float32ArrayData(elements);
#else
this = new ArrayBufferView(elements * BYTES_PER_ELEMENT).getData();
#end
}

inline function get_length() {
#if js
return this.length;
#else
return this.byteLength >> 2;
#end
}

public inline function get_view() : ArrayBufferView {
return ArrayBufferView.fromData(this);
}

@:arrayAccess public inline function get( index : Int ) : Float {
#if js
return this[index];
#else
return this.bytes.getFloat((index<<2) + this.byteOffset);
#end
}

@:arrayAccess public inline function set( index : Int, value : Float ) : Float {
#if js
return this[index] = value;
#else
if( index >= 0 && index < length ) {
this.bytes.setFloat((index<<2) + this.byteOffset, value);
return value;
}
return 0;
#end
}

public inline function sub( begin : Int, ?length : Int ) {
#if js
return fromData(this.subarray(begin, length == null ? null : begin+length));
#else
return fromData(this.sub(begin<<2,length<<2));
#end
}

public inline function getData() : Float32ArrayData {
return this;
}

public static function fromData( d : Float32ArrayData ) : Float32Array {
return cast d;
}

public static function fromArray( a : Array<Float>, pos = 0, ?length ) : Float32Array {
if( length == null ) length = a.length - pos;
if( pos < 0 || length < 0 || pos + length > a.length ) throw Error.OutsideBounds;
#if js
if( pos == 0 && length == a.length )
return fromData(new Float32ArrayData(a));
#end
var i = new Float32Array(a.length);
for( idx in 0...length )
i[idx] = a[idx + pos];
return i;
}

}

2 changes: 1 addition & 1 deletion std/haxe/io/Input.hx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class Input {
**/
public function readBytes( s : Bytes, pos : Int, len : Int ) : Int {
var k = len;
var b = s.getData();
var b = #if js @:privateAccess s.b #else s.getData() #end;
if( pos < 0 || len < 0 || pos + len > s.length )
throw Error.OutsideBounds;
while( k > 0 ) {
Expand Down
102 changes: 102 additions & 0 deletions std/haxe/io/Uint8Array.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright (C)2005-2015 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package haxe.io;

typedef Uint8ArrayData = #if js js.html.Uint8Array #else ArrayBufferView.ArrayBufferViewData #end

abstract Uint8Array(Uint8ArrayData) {

public static inline var BYTES_PER_ELEMENT = 1;
public var length(get,never) : Int;
public var view(get,never) : ArrayBufferView;

public inline function new( elements : Int ) {
#if js
this = new Uint8ArrayData(elements * BYTES_PER_ELEMENT);
#else
this = new ArrayBufferView(elements * BYTES_PER_ELEMENT).getData();
#end
}

inline function get_length() {
#if js
return this.length;
#else
return this.byteLength;
#end
}

public inline function get_view() : ArrayBufferView {
return ArrayBufferView.fromData(this);
}

@:arrayAccess public inline function get( index : Int ) {
#if js
return this[index];
#else
return this.bytes.get(index + this.byteOffset);
#end
}

@:arrayAccess public inline function set( index : Int, value : Int ) : Int {
#if js
return this[index] = value & 0xFF; // &0xFF necessary for html compat
#else
if( index >= 0 && index < length ) {
this.bytes.set(index + this.byteOffset, value);
return value;
}
return 0;
#end
}

public inline function sub( begin : Int, ?length : Int ) {
#if js
return fromData(this.subarray(begin, length == null ? null : begin+length));
#else
return fromData(this.sub(begin,length));
#end
}

public inline function getData() : Uint8ArrayData {
return this;
}

public static function fromData( d : Uint8ArrayData ) : Uint8Array {
return cast d;
}

public static function fromArray( a : Array<Int>, pos = 0, ?length ) : Uint8Array {
if( length == null ) length = a.length - pos;
if( pos < 0 || length < 0 || pos + length > a.length ) throw Error.OutsideBounds;
#if js
if( pos == 0 && length == a.length )
return fromData(new Uint8ArrayData(a));
#end
var i = new Uint8Array(a.length);
for( idx in 0...length )
i[idx] = a[idx + pos];
return i;
}

}

Loading

0 comments on commit e31e94f

Please sign in to comment.