Last active
November 14, 2016 17:20
-
-
Save frabbit/7aa259971419b30655f8b920ff31c672 to your computer and use it in GitHub Desktop.
ByteArray haxe
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// fast byte access without class overhead and bounds checks like in haxe.io.Bytes | |
package haxe.io; | |
@:coreType abstract ByteArray { | |
public static var getIsChecked:Bool; // flags can be used in bytes to remove unnecessary or multiple bounds checks on different targets | |
public static var setIsChecked:Bool; | |
public static var blitCanThrow:Bool; // throws are neko specific flags, can be used in bytes to remove a bounds check | |
public static var subCanThrow:Bool; | |
public static var getStringCanThrow:Bool; | |
public var length(get,never) : Int; | |
public function new ():Void; | |
public function getData ():BytesData; | |
public static function ofData (data:BytesData):ByteArray; | |
function get_length() : Int; | |
public function get( pos : Int ) : Int; | |
public function set( pos : Int, v : Int ) : Void; | |
public function blit( pos : Int, src : ByteArray, srcpos : Int, len : Int ) : Void; | |
public function fill( pos : Int, len : Int, value : Int ):Void; | |
public function sub( pos : Int, len : Int ) : ByteArray; | |
public function compare( other : ByteArray ) : Int; | |
public function getDouble( pos : Int ) : Float; | |
public function getFloat( pos : Int ) : Float; | |
public function setDouble( pos : Int, v : Float ) : Void; | |
public function setFloat( pos : Int, v : Float ) : Void; | |
public function getUInt16( pos : Int ) : Int; | |
public function setUInt16( pos : Int, v : Int ) : Void; | |
public function getInt32( pos : Int ) : Int; | |
public function getInt64( pos : Int ) : haxe.Int64; | |
public function setInt32( pos : Int, v : Int ) : Void; | |
public function setInt64( pos : Int, v : haxe.Int64 ) : Void; | |
public function getString( pos : Int, len : Int ) : String; | |
public function toString() : String; | |
public static function alloc( length : Int ) : ByteArray; | |
public static function ofString( s : String ) : ByteArray; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this is the implementation for cpp (java, c#, neko etc. are quite similar) | |
package haxe.io; | |
using cpp.NativeArray; | |
private typedef ByteArrayImpl = BytesData; | |
abstract ByteArray(ByteArrayImpl) { | |
public static inline var getIsChecked = false; | |
public static inline var setIsChecked = false; | |
public static inline var blitCanThrow = false; | |
public static inline var subCanThrow = false; | |
public static inline var getStringCanThrow = false; | |
public var length(get,never) : Int; | |
inline function new (impl:ByteArrayImpl) { | |
this = impl; | |
} | |
public inline function getData ():BytesData { | |
return this; | |
} | |
inline function raw () return this; | |
public static inline function ofData (data:BytesData) { | |
return mk(data); | |
} | |
inline function get_length ():Int { | |
return untyped this.length; | |
} | |
static inline function mk (data:ByteArrayImpl):ByteArray { | |
return new ByteArray(data); | |
} | |
public inline function get( pos : Int ) : Int { | |
return untyped this.unsafeGet(pos); | |
} | |
public inline function set( pos : Int, v : Int ) : Void { | |
untyped this[pos] = v; | |
} | |
public inline function blit( pos : Int, src : ByteArray, srcpos : Int, len : Int ) : Void { | |
this.blit(pos, src.raw(), srcpos, len); | |
} | |
public inline function fill( pos : Int, len : Int, value : Int ):Void { | |
untyped __global__.__hxcpp_memory_memset(this,pos,len,value); | |
} | |
public inline function sub( pos : Int, len : Int ) : ByteArray { | |
return mk(this.slice(pos,pos+len)); | |
} | |
public inline function compare( other : ByteArray ) : Int { | |
return this.memcmp(other.raw()); | |
} | |
public inline function getDouble( pos : Int ) : Float { | |
return untyped __global__.__hxcpp_memory_get_double(this,pos); | |
} | |
public inline function getFloat( pos : Int ) : Float { | |
return untyped __global__.__hxcpp_memory_get_float(this,pos); | |
} | |
public inline function setDouble( pos : Int, v : Float ) : Void { | |
untyped __global__.__hxcpp_memory_set_double(this,pos,v); | |
} | |
public inline function setFloat( pos : Int, v : Float ) : Void { | |
untyped __global__.__hxcpp_memory_set_float(this,pos,v); | |
} | |
public inline function getUInt16( pos : Int ) : Int { | |
return get(pos) | (get(pos + 1) << 8); | |
} | |
public inline function setUInt16( pos : Int, v : Int ) : Void { | |
set(pos, v); | |
set(pos + 1, v >> 8); | |
} | |
public inline function getInt32( pos : Int ) : Int { | |
return get(pos) | (get(pos + 1) << 8) | (get(pos + 2) << 16) | (get(pos+3) << 24); | |
} | |
public inline function getInt64( pos : Int ) : haxe.Int64 { | |
return haxe.Int64.make(getInt32(pos+4),getInt32(pos)); | |
} | |
public inline function setInt32( pos : Int, v : Int ) : Void { | |
set(pos, v); | |
set(pos + 1, v >> 8); | |
set(pos + 2, v >> 16); | |
set(pos + 3, v >>> 24); | |
} | |
public inline function setInt64( pos : Int, v : haxe.Int64 ) : Void { | |
setInt32(pos, v.low); | |
setInt32(pos + 4, v.high); | |
} | |
public function getString( pos : Int, len : Int ) : String { | |
var result:String=""; | |
untyped __global__.__hxcpp_string_of_bytes(this,result,pos,len); | |
return result; | |
} | |
public inline function toString() : String { | |
return getString(0,length); | |
} | |
public static function alloc( length : Int ) : ByteArray { | |
var a = new ByteArrayImpl(); | |
if (length>0) cpp.NativeArray.setSize(a, length); | |
return mk(a); | |
} | |
public static function ofString( s : String ) : ByteArray { | |
var a = new ByteArrayImpl(); | |
untyped __global__.__hxcpp_bytes_of_string(a,s); | |
return mk(a); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The new default implementation for Bytes (hl and js have their own to avoid indirection). Very | |
// clean compared to the current one. | |
package haxe.io; | |
class Bytes { | |
public var length(default,null) : Int; | |
var b : ByteArray; | |
function new(b) { | |
this.b = b; | |
this.length = b.length; | |
} | |
inline function out(pos:Int) : Bool { | |
return (pos:UInt) >= (length:UInt); | |
} | |
public inline function get( pos : Int ) : Int { | |
return if (ByteArray.getIsChecked && out(pos)) 0 else b.get(pos); | |
} | |
public inline function set( pos : Int, v : Int ) : Void { | |
if( ByteArray.setIsChecked && out(pos) ) throw Error.OutsideBounds; | |
b.set(pos, v); | |
} | |
public inline function blit( pos : Int, src : Bytes, srcpos : Int, len : Int ) : Void { | |
return if (ByteArray.blitCanThrow) { | |
try b.blit(pos, src.b, srcpos, len) catch (e:Dynamic) throw Error.OutsideBounds; | |
} else { | |
if( (pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length) ) throw Error.OutsideBounds; | |
b.blit(pos, src.b, srcpos, len); | |
} | |
} | |
public inline function fill( pos : Int, len : Int, value : Int ) { | |
if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds; | |
b.fill(pos, len, value); | |
} | |
public inline function sub( pos : Int, len : Int ) : Bytes { | |
return if (ByteArray.subCanThrow) { | |
try new Bytes(b.sub(pos, len)) catch (e:Dynamic) throw Error.OutsideBounds; | |
} else { | |
if( (pos < 0 || len < 0 || pos + len > length) ) throw Error.OutsideBounds; | |
new Bytes(b.sub(pos, len)); | |
} | |
} | |
public inline function compare( other : Bytes ) : Int { | |
return b.compare(other.b); | |
} | |
public inline function getDouble( pos : Int ) : Float { | |
if( pos < 0 || pos + 8 > length ) throw Error.OutsideBounds; | |
return b.getDouble(pos); | |
} | |
public inline function getFloat( pos : Int ) : Float { | |
if( pos < 0 || pos + 4 > length ) throw Error.OutsideBounds; | |
return b.getFloat(pos); | |
} | |
public inline function setDouble( pos : Int, v : Float ) : Void { | |
if( pos < 0 || pos + 8 > length ) throw Error.OutsideBounds; | |
b.setDouble(pos, v); | |
} | |
public inline function setFloat( pos : Int, v : Float ) : Void { | |
if( pos < 0 || pos + 4 > length ) throw Error.OutsideBounds; | |
b.setFloat(pos, v); | |
} | |
public inline function getUInt16( pos : Int ) : Int { | |
if( pos < 0 || pos + 2 > length ) throw Error.OutsideBounds; | |
return b.getUInt16(pos); | |
} | |
public inline function setUInt16( pos : Int, v : Int ) : Void { | |
if( pos < 0 || pos + 2 > length ) throw Error.OutsideBounds; | |
b.setUInt16(pos, v); | |
} | |
public inline function getInt32( pos : Int ) : Int { | |
if( pos < 0 || pos + 4 > length ) throw Error.OutsideBounds; | |
return b.getInt32(pos); | |
} | |
public inline function getInt64( pos : Int ) : haxe.Int64 { | |
if( pos < 0 || pos + 8 > length ) throw Error.OutsideBounds; | |
return b.getInt64(pos); | |
} | |
public inline function setInt32( pos : Int, v : Int ) : Void { | |
if( pos < 0 || pos + 2 > length ) throw Error.OutsideBounds; | |
b.setInt32(pos, v); | |
} | |
public inline function setInt64( pos : Int, v : haxe.Int64 ) : Void { | |
if( pos < 0 || pos + 8 > length ) throw Error.OutsideBounds; | |
b.setInt64(pos, v); | |
} | |
public function getString( pos : Int, len : Int ) : String { | |
return if (ByteArray.getStringCanThrow) { | |
try b.getString(pos, len) catch( e : Dynamic ) throw Error.OutsideBounds; | |
} else { | |
if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds; | |
b.getString(pos, len); | |
} | |
} | |
@:deprecated("readString is deprecated, use getString instead") | |
@:noCompletion | |
public inline function readString(pos:Int, len:Int):String { | |
return getString(pos, len); | |
} | |
@:keep public inline function toString() : String { | |
return b.toString(); | |
} | |
public function toHex() : String { | |
var s = new StringBuf(); | |
var chars = []; | |
var str = "0123456789abcdef"; | |
for( i in 0...str.length ) | |
chars.push(str.charCodeAt(i)); | |
for( i in 0...length ) { | |
var c = get(i); | |
s.addChar(chars[c >> 4]); | |
s.addChar(chars[c & 15]); | |
} | |
return s.toString(); | |
} | |
public function getData() : BytesData { | |
return b.getData(); | |
} | |
public static function alloc( length : Int ) : Bytes { | |
return new Bytes(ByteArray.alloc(length)); | |
} | |
@:pure | |
public static function ofString( s : String ) : Bytes { | |
return new Bytes(ByteArray.ofString(s)); | |
} | |
public static function ofData( b : BytesData ) { | |
return new Bytes(ByteArray.ofData(b)); | |
} | |
public inline static function fastGet( b : BytesData, pos : Int ) : Int { | |
// ByteArray.ofData is a noop, targets where is is not the case have their own Bytes implementation | |
return ByteArray.ofData(b).get(pos); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// hl ByteArray uses an underlying BytesData object. | |
package haxe.io; | |
typedef ByteArrayImpl = haxe.io.BytesData; | |
abstract ByteArray(ByteArrayImpl) { | |
public var length(get,never) : Int; | |
inline function new (impl:ByteArrayImpl) { | |
this = impl; | |
} | |
inline function get_length ():Int { | |
return this.length; | |
} | |
public inline function getData ():BytesData { | |
return this; | |
} | |
inline function raw () return this; | |
public static inline function ofData (data:BytesData) { | |
return mk(data); | |
} | |
static inline function mk (data:ByteArrayImpl):ByteArray { | |
return new ByteArray(data); | |
} | |
public inline function get( pos : Int ) : Int { | |
return this.bytes[pos]; | |
} | |
public inline function set( pos : Int, v : Int ) : Void { | |
this.bytes[pos] = v; | |
} | |
public inline function blit( pos : Int, src : ByteArray, srcpos : Int, len : Int ) : Void { | |
this.bytes.blit(pos, src.raw().bytes, srcpos, len); | |
} | |
public inline function fill( pos : Int, len : Int, value : Int ):Void { | |
this.bytes.fill(pos, len, value); | |
} | |
public inline function sub( pos : Int, len : Int ) : ByteArray { | |
var impl = new ByteArrayImpl(this.bytes.sub(pos, len), len); | |
return mk(impl); | |
} | |
public function compare( other : ByteArray ) : Int { | |
var len = length < other.length ? length : other.length; | |
var r = this.bytes.compare(0, other.raw().bytes, 0, len); | |
if( r == 0 ) | |
r = length - other.length; | |
return r; | |
} | |
public inline function getDouble( pos : Int ) : Float { | |
return this.bytes.getF64(pos); | |
} | |
public inline function getFloat( pos : Int ) : Float { | |
return this.bytes.getF32(pos); | |
} | |
public inline function setDouble( pos : Int, v : Float ) : Void { | |
this.bytes.setF64(pos, v); | |
} | |
public inline function setFloat( pos : Int, v : Float ) : Void { | |
this.bytes.setF32(pos, v); | |
} | |
public inline function getUInt16( pos : Int ) : Int { | |
return this.bytes.getUI16(pos); | |
} | |
public inline function setUInt16( pos : Int, v : Int ) : Void { | |
this.bytes.setUI16(pos, v); | |
} | |
public inline function getInt32( pos : Int ) : Int { | |
return this.bytes.getI32(pos); | |
} | |
public inline function getInt64( pos : Int ) : haxe.Int64 { | |
return haxe.Int64.make(this.bytes.getI32(pos+4), this.bytes.getI32(pos)); | |
} | |
public inline function setInt32( pos : Int, v : Int ) : Void { | |
return this.bytes.setI32(pos, v); | |
} | |
public inline function setInt64( pos : Int, v : haxe.Int64 ) : Void { | |
setInt32(pos + 4, v.high); | |
setInt32(pos, v.low); | |
} | |
public function getString( pos : Int, len : Int ) : String { | |
var b = new hl.types.Bytes(len + 1); | |
b.blit(0, this.bytes, pos, len); | |
b[len] = 0; | |
return @:privateAccess String.fromUTF8(b); | |
} | |
public inline function toString() : String { | |
return getString(0,length); | |
} | |
public static function alloc( length : Int ) : ByteArray { | |
var b = new hl.types.Bytes(length); | |
b.fill(0, length, 0); | |
var impl = new ByteArrayImpl(b, length); | |
return mk(impl); | |
} | |
public static function ofString( s : String ) : ByteArray @:privateAccess { | |
var size = 0; | |
var b = s.bytes.utf16ToUtf8(0, size); | |
var impl = new ByteArrayImpl(b, size); | |
return mk(impl); | |
} | |
public inline function fastGet( pos : Int ) : Int { | |
return this.bytes[pos]; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// hl version doesn't use the ByteArray to implement Bytes | |
package haxe.io; | |
@:coreApi | |
class Bytes { | |
public var length(default,null) : Int; | |
var b : hl.types.Bytes; | |
function new(b:hl.types.Bytes,length:Int) : Void { | |
this.b = b; | |
this.length = length; | |
} | |
inline function out(pos:Int) : Bool { | |
return (pos:UInt) >= (length : UInt); | |
} | |
public function get( pos : Int ) : Int { | |
return if( out(pos) ) 0 else b[pos]; | |
} | |
public function set( pos : Int, v : Int ) : Void { | |
if( out(pos) ) throw Error.OutsideBounds; | |
b[pos] = v; | |
} | |
public function blit( pos : Int, src : Bytes, srcpos : Int, len : Int ) : Void { | |
if( pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length ) throw Error.OutsideBounds; | |
b.blit(pos, src.b, srcpos, len); | |
} | |
public function fill( pos : Int, len : Int, value : Int ) : Void { | |
if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds; | |
b.fill(pos, len, value); | |
} | |
public function sub( pos : Int, len : Int ) : Bytes { | |
if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds; | |
return new Bytes(b.sub(pos, len), len); | |
} | |
public function compare( other : Bytes ) : Int { | |
var len = length < other.length ? length : other.length; | |
var r = b.compare(0, other.b, 0, len); | |
if( r == 0 ) | |
r = length - other.length; | |
return r; | |
} | |
public function getDouble( pos : Int ) : Float { | |
return if( out(pos + 7) ) 0. else b.getF64(pos); | |
} | |
public function getFloat( pos : Int ) : Float { | |
return if( out(pos + 3) ) 0. else b.getF32(pos); | |
} | |
public function setDouble( pos : Int, v : Float ) : Void { | |
if( out(pos + 7) ) throw Error.OutsideBounds; | |
b.setF64(pos, v); | |
} | |
public function setFloat( pos : Int, v : Float ) : Void { | |
if( out(pos + 3) ) throw Error.OutsideBounds; | |
b.setF32(pos, v); | |
} | |
public inline function getUInt16( pos : Int ) : Int { | |
return if( out(pos + 1) ) 0 else b.getUI16(pos); | |
} | |
public inline function setUInt16( pos : Int, v : Int ) : Void { | |
if( out(pos + 1) ) throw Error.OutsideBounds; | |
b.setUI16(pos, v); | |
} | |
public function getInt32( pos : Int ) : Int { | |
return if( out(pos + 3) ) 0 else b.getI32(pos); | |
} | |
public function getInt64( pos : Int ) : haxe.Int64 { | |
if( out(pos + 7) ) | |
return haxe.Int64.ofInt(0); | |
return haxe.Int64.make(b.getI32(pos+4), b.getI32(pos)); | |
} | |
public function setInt32( pos : Int, v : Int ) : Void { | |
if( out(pos + 3) ) throw Error.OutsideBounds; | |
b.setI32(pos, v); | |
} | |
public inline function setInt64( pos : Int, v : haxe.Int64 ) : Void { | |
setInt32(pos + 4, v.high); | |
setInt32(pos, v.low); | |
} | |
public function getString( pos : Int, len : Int ) : String { | |
if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds; | |
var b = new hl.types.Bytes(len + 1); | |
b.blit(0, this.b, pos, len); | |
b[len] = 0; | |
return @:privateAccess String.fromUTF8(b); | |
} | |
@:deprecated("readString is deprecated, use getString instead") | |
@:noCompletion | |
public inline function readString(pos:Int, len:Int):String { | |
return getString(pos, len); | |
} | |
public function toString() : String { | |
return getString(0,length); | |
} | |
public function toHex() : String { | |
var s = new StringBuf(); | |
var chars = []; | |
var str = "0123456789abcdef"; | |
for( i in 0...str.length ) | |
chars.push(str.charCodeAt(i)); | |
for( i in 0...length ) { | |
var c = get(i); | |
s.addChar(chars[c >> 4]); | |
s.addChar(chars[c & 15]); | |
} | |
return s.toString(); | |
} | |
public inline function getData() : BytesData { | |
return new haxe.io.BytesData(b,length); | |
} | |
public static function alloc( length : Int ) : Bytes { | |
var b = new hl.types.Bytes(length); | |
b.fill(0, length, 0); | |
return new Bytes(b,length); | |
} | |
public static function ofString( s : String ) : Bytes @:privateAccess { | |
var size = 0; | |
var b = s.bytes.utf16ToUtf8(0, size); | |
return new Bytes(b,size); | |
} | |
public static function ofData( b : BytesData ) : Bytes { | |
return new Bytes(b.bytes,b.length); | |
} | |
public inline static function fastGet( b : BytesData, pos : Int ) : Int { | |
return b[pos]; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// same for js, but a lot of functionality can be shared with ByteArray (see ByteHelper next file), | |
// this is achieved through a typedef ByteArrayImpl (see next file) that matches the structure of Bytes and also the underlying type of ByteArray. | |
package haxe.io; | |
#if !nodejs | |
import js.html.compat.Uint8Array; | |
import js.html.compat.DataView; | |
#end | |
import haxe.io.ByteArray.ByteHelper; | |
@:coreApi | |
class Bytes { | |
public var length(default,null) : Int; | |
var b : js.html.Uint8Array; | |
var data : js.html.DataView; | |
function new(data:BytesData) { | |
this.length = data.byteLength; | |
this.b = new js.html.Uint8Array(data); | |
untyped { | |
b.bufferValue = data; // some impl does not return the same instance in .buffer | |
data.hxBytes = this; // store the Bytes instance, this way no new allocation is required when converting BytesData to Bytes | |
data.bytes = this.b; // for fastGet of BytesData | |
} | |
} | |
public inline function get( pos : Int ) : Int { | |
return ByteHelper.get(this, pos); | |
} | |
public inline function set( pos : Int, v : Int ) : Void { | |
ByteHelper.set(this, pos, v); | |
} | |
public inline function blit( pos : Int, src : Bytes, srcpos : Int, len : Int ) : Void { | |
if( pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length ) throw Error.OutsideBounds; | |
ByteHelper.blit(this, pos, src, srcpos, len); | |
} | |
public inline function fill( pos : Int, len : Int, value : Int ) : Void { | |
ByteHelper.fill(this, pos, len, value); | |
} | |
public inline function sub( pos : Int, len : Int ) : Bytes { | |
if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds; | |
return Bytes.ofData(ByteHelper.sub(this, pos, len)); | |
} | |
public inline function compare( other : Bytes ) : Int { | |
return ByteHelper.compare(this, other); | |
} | |
public inline function getDouble( pos : Int ) : Float { | |
return ByteHelper.getDouble(this, pos); | |
} | |
public inline function getFloat( pos : Int ) : Float { | |
return ByteHelper.getFloat(this, pos); | |
} | |
public inline function setDouble( pos : Int, v : Float ) : Void { | |
ByteHelper.setDouble(this, pos, v); | |
} | |
public inline function setFloat( pos : Int, v : Float ) : Void { | |
ByteHelper.setFloat(this, pos, v); | |
} | |
public inline function getUInt16( pos : Int ) : Int { | |
return ByteHelper.getUInt16(this, pos); | |
} | |
public inline function setUInt16( pos : Int, v : Int ) : Void { | |
ByteHelper.setUInt16(this, pos, v); | |
} | |
public inline function getInt32( pos : Int ) : Int { | |
return ByteHelper.getInt32(this, pos); | |
} | |
public inline function setInt32( pos : Int, v : Int ) : Void { | |
ByteHelper.setInt32(this, pos, v); | |
} | |
public inline function getInt64( pos : Int ) : haxe.Int64 { | |
return ByteHelper.getInt64(this, pos); | |
} | |
public inline function setInt64( pos : Int, v : haxe.Int64 ) : Void { | |
ByteHelper.setInt64(this, pos, v); | |
} | |
public function getString( pos : Int, len : Int ) : String { | |
if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds; | |
return ByteHelper.getString(this, pos, len); | |
} | |
@:deprecated("readString is deprecated, use getString instead") | |
@:noCompletion | |
public inline function readString(pos:Int, len:Int):String { | |
return getString(pos, len); | |
} | |
public inline function toString() : String { | |
return ByteHelper.getString(this, 0, length); | |
} | |
public function toHex() : String { | |
var s = new StringBuf(); | |
var chars = []; | |
var str = "0123456789abcdef"; | |
for( i in 0...str.length ) | |
chars.push(str.charCodeAt(i)); | |
for( i in 0...length ) { | |
var c = get(i); | |
s.addChar(chars[c >> 4]); | |
s.addChar(chars[c & 15]); | |
} | |
return s.toString(); | |
} | |
public inline function getData() : BytesData { | |
return ByteHelper.getData(this); | |
} | |
public static inline function alloc( length : Int ) : Bytes { | |
return new Bytes(ByteHelper.allocBuffer(length)); | |
} | |
public static inline function ofString( s : String ) : Bytes { | |
var buffer = ByteHelper.ofString(s); | |
return new Bytes(buffer); | |
} | |
public static function ofData( b : BytesData ) : Bytes { | |
var hb = untyped b.hxBytes; | |
if( hb != null ) return hb; | |
return new Bytes(b); | |
} | |
public inline static function fastGet( b : BytesData, pos : Int ) : Int { | |
return ByteHelper.fastGet(b, pos); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package haxe.io; | |
#if !nodejs | |
import js.html.compat.Uint8Array; | |
import js.html.compat.DataView; | |
#end | |
@:allow(haxe.io) | |
class ByteHelper { | |
static function sub( impl:ByteArrayImpl, pos : Int, len : Int ) : js.html.ArrayBuffer { | |
return impl.b.buffer.slice(pos+impl.b.byteOffset,pos+impl.b.byteOffset+len); | |
} | |
static function subByteArray( impl:ByteArrayImpl, pos : Int, len : Int ) : ByteArray { | |
return mkByteArray(sub(impl, pos, len)); | |
} | |
static inline function mkByteArray (buffer:js.html.ArrayBuffer):ByteArray { | |
return ByteArray.fromBuffer(buffer); | |
} | |
static inline function getLength (impl:ByteArrayImpl):Int { | |
return impl.b.byteLength; | |
} | |
static inline function get( impl:ByteArrayImpl, pos : Int ) : Int { | |
return impl.b[pos]; | |
} | |
static inline function set( impl:ByteArrayImpl, pos : Int, v : Int ) : Void { | |
impl.b[pos] = v & 0xFF; // the &0xFF is necessary for js.html.compat support | |
} | |
static inline function blit( impl:ByteArrayImpl, pos : Int, src : ByteArrayImpl, srcpos : Int, len : Int ) : Void { | |
if( srcpos == 0 && len == src.b.byteLength ) | |
impl.b.set(src.b,pos); | |
else | |
impl.b.set(src.b.subarray(srcpos,srcpos+len),pos); | |
} | |
static inline function fill( impl: ByteArrayImpl, pos : Int, len : Int, value : Int ):Void { | |
for( i in 0...len ) | |
set(impl, pos++, value); | |
} | |
inline static function initData(impl:ByteArrayImpl) : Void { | |
if( impl.data == null ) impl.data = new js.html.DataView(impl.b.buffer, impl.b.byteOffset, impl.b.byteLength); | |
} | |
static function compare( b:ByteArrayImpl, other : ByteArrayImpl ) : Int { | |
var b1 = b.b; | |
var b2 = other.b; | |
var len = (getLength(b) < getLength(other)) ? getLength(b) : getLength(other); | |
for( i in 0...len ) | |
if( b1[i] != b2[i] ) | |
return b1[i] - b2[i]; | |
return getLength(b) - getLength(other); | |
} | |
static inline function getDouble( impl:ByteArrayImpl, pos : Int ) : Float { | |
initData(impl); | |
return impl.data.getFloat64(pos, true); | |
} | |
static inline function getFloat( impl:ByteArrayImpl, pos : Int ) : Float { | |
initData(impl); | |
return impl.data.getFloat32(pos, true); | |
} | |
static inline function setDouble( impl:ByteArrayImpl, pos : Int, v : Float ) : Void { | |
initData(impl); | |
impl.data.setFloat64(pos, v, true); | |
} | |
static inline function setFloat( impl:ByteArrayImpl, pos : Int, v : Float ) : Void { | |
initData(impl); | |
impl.data.setFloat32( pos, v, true); | |
} | |
static inline function getUInt16( impl:ByteArrayImpl, pos : Int ) : Int { | |
initData(impl); | |
return impl.data.getUint16(pos, true); | |
} | |
static inline function setUInt16( impl:ByteArrayImpl, pos : Int, v : Int ) : Void { | |
initData(impl); | |
impl.data.setUint16(pos, v, true); | |
} | |
static inline function getInt32( impl:ByteArrayImpl, pos : Int ) : Int { | |
initData(impl); | |
return impl.data.getInt32(pos, true); | |
} | |
static inline function getInt64( impl:ByteArrayImpl, pos : Int ) : haxe.Int64 { | |
return Int64.make(getInt32(impl, pos + 4),getInt32(impl, pos)); | |
} | |
static inline function setInt32( impl:ByteArrayImpl, pos : Int, v : Int ) : Void { | |
initData(impl); | |
impl.data.setInt32(pos, v, true); | |
} | |
static inline function setInt64( impl:ByteArrayImpl, pos : Int, v : haxe.Int64 ) : Void { | |
setInt32(impl, pos, v.low); | |
setInt32(impl, pos + 4, v.high); | |
} | |
static function getString( impl:ByteArrayImpl, pos : Int, len : Int ) : String { | |
var s = ""; | |
var b = impl.b; | |
var fcc = String.fromCharCode; | |
var i = pos; | |
var max = pos+len; | |
// utf8-decode and utf16-encode | |
while( i < max ) { | |
var c = b[i++]; | |
if( c < 0x80 ) { | |
if( c == 0 ) break; | |
s += fcc(c); | |
} else if( c < 0xE0 ) | |
s += fcc( ((c & 0x3F) << 6) | (b[i++] & 0x7F) ); | |
else if( c < 0xF0 ) { | |
var c2 = b[i++]; | |
s += fcc( ((c & 0x1F) << 12) | ((c2 & 0x7F) << 6) | (b[i++] & 0x7F) ); | |
} else { | |
var c2 = b[i++]; | |
var c3 = b[i++]; | |
var u = ((c & 0x0F) << 18) | ((c2 & 0x7F) << 12) | ((c3 & 0x7F) << 6) | (b[i++] & 0x7F); | |
// surrogate pair | |
s += fcc( (u >> 10) + 0xD7C0 ); | |
s += fcc( (u & 0x3FF) | 0xDC00 ); | |
} | |
} | |
return s; | |
} | |
static inline function toString(impl:ByteArrayImpl) : String { | |
return getString(impl, 0, getLength(impl)); | |
} | |
static function ofString( s : String ) : js.html.ArrayBuffer { | |
var a = new Array(); | |
// utf16-decode and utf8-encode | |
var i = 0; | |
while( i < s.length ) { | |
var c : Int = StringTools.fastCodeAt(s,i++); | |
// surrogate pair | |
if( 0xD800 <= c && c <= 0xDBFF ) | |
c = (c - 0xD7C0 << 10) | (StringTools.fastCodeAt(s,i++) & 0x3FF); | |
if( c <= 0x7F ) | |
a.push(c); | |
else if( c <= 0x7FF ) { | |
private typedef ByteArrayImpl = { | |
private var b : js.html.Uint8Array; | |
private var data : js.html.DataView; | |
} | |
abstract ByteArray(ByteArrayImpl) { | |
public var length(get,never) : Int; | |
inline function new (impl:ByteArrayImpl) { | |
this = impl; | |
} | |
public static inline function fromBuffer (buffer:js.html.ArrayBuffer) { | |
var arr = new js.html.Uint8Array(buffer); | |
var impl = { | |
b : arr, | |
data : null | |
} | |
untyped { | |
arr.bufferValue = buffer; // some impl does not return the same instance in .buffer | |
buffer.bytes = arr; // for fastGet of BytesData | |
buffer.hxByteArray = impl; // store the ByteArray instance, this way no new allocation is required when converting BytesData to ByteArray | |
} | |
return new ByteArray(impl); | |
} | |
public static inline function ofData (b:BytesData) { | |
var hb:ByteArray = untyped b.hxByteArray; | |
if (hb != null) return hb; | |
return fromBuffer(b); | |
} | |
public inline function getData () { | |
return ByteHelper.getData(this); | |
} | |
inline function raw ():ByteArrayImpl return this; | |
inline function get_length ():Int { | |
return ByteHelper.getLength(this); | |
} | |
public inline function get( pos : Int ) : Int { | |
return ByteHelper.get(this, pos); | |
} | |
public inline function set( pos : Int, v : Int ) : Void { | |
ByteHelper.set(this, pos, v); | |
} | |
public inline function blit( pos : Int, src : ByteArray, srcpos : Int, len : Int ) : Void { | |
return ByteHelper.blit(this, pos, src.raw(), srcpos, len); | |
} | |
public inline function fill( pos : Int, len : Int, value : Int ):Void { | |
ByteHelper.fill(this, pos, len, value); | |
} | |
public inline function sub( pos : Int, len : Int ) : ByteArray { | |
return ByteHelper.subByteArray(this, pos, len); | |
} | |
public inline function compare( other : ByteArray ) : Int { | |
return ByteHelper.compare(this, other.raw()); | |
} | |
public inline function getDouble( pos : Int ) : Float { | |
return ByteHelper.getDouble(this, pos); | |
} | |
public inline function getFloat( pos : Int ) : Float { | |
return ByteHelper.getFloat(this, pos); | |
} | |
public inline function setDouble( pos : Int, v : Float ) : Void { | |
ByteHelper.setDouble(this, pos, v); | |
} | |
public inline function setFloat( pos : Int, v : Float ) : Void { | |
ByteHelper.setFloat(this, pos, v); | |
} | |
public inline function getUInt16( pos : Int ) : Int { | |
return ByteHelper.getUInt16(this, pos); | |
} | |
public inline function setUInt16( pos : Int, v : Int ) : Void { | |
ByteHelper.setUInt16(this, pos, v); | |
} | |
public inline function getInt32( pos : Int ) : Int { | |
return ByteHelper.getInt32(this, pos); | |
} | |
public inline function getInt64( pos : Int ) : haxe.Int64 { | |
return ByteHelper.getInt64(this, pos); | |
} | |
public inline function setInt32( pos : Int, v : Int ) : Void { | |
ByteHelper.setInt32(this, pos, v); | |
} | |
public inline function setInt64( pos : Int, v : haxe.Int64 ) : Void { | |
ByteHelper.setInt64(this, pos, v); | |
} | |
public inline function getString( pos : Int, len : Int ) : String { | |
return ByteHelper.getString(this, pos, len); | |
} | |
public inline function toString() : String { | |
return ByteHelper.toString(this); | |
} | |
public static inline function alloc( length : Int ) : ByteArray { | |
var buffer = ByteHelper.allocBuffer(length); | |
return fromBuffer(buffer); | |
} | |
public static inline function ofString( s : String ) : ByteArray { | |
return fromBuffer(ByteHelper.ofString(s)); | |
} | |
} | |
// the helper class for js | |
a.push( 0xC0 | (c >> 6) ); | |
a.push( 0x80 | (c & 63) ); | |
} else if( c <= 0xFFFF ) { | |
a.push( 0xE0 | (c >> 12) ); | |
a.push( 0x80 | ((c >> 6) & 63) ); | |
a.push( 0x80 | (c & 63) ); | |
} else { | |
a.push( 0xF0 | (c >> 18) ); | |
a.push( 0x80 | ((c >> 12) & 63) ); | |
a.push( 0x80 | ((c >> 6) & 63) ); | |
a.push( 0x80 | (c & 63) ); | |
} | |
} | |
return new js.html.Uint8Array(a).buffer; | |
} | |
static inline function fastGet( data:BytesData, pos : Int ) : Int { | |
// this requires that we have wrapped it with haxe.io.Bytes beforehand | |
return untyped data.bytes[pos]; | |
} | |
static inline function allocBuffer (length:Int) { | |
return new js.html.ArrayBuffer(length); | |
} | |
static inline function getData(impl:ByteArrayImpl) : BytesData { | |
return untyped impl.b.bufferValue; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment