Created
March 19, 2012 13:43
-
-
Save jamesu/2112670 to your computer and use it in GitHub Desktop.
Javascript Byte IO for haXe using ArrayBuffers
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
// Example usage | |
class Example | |
{ | |
public static function test() | |
{ | |
var bytes = new JSByteIO(new ArrayBuffer(128)); | |
// Writing and reading a line | |
bytes.writeString("HELLO WORLD\n"); | |
bytes.seek(0, Seek.SeekBegin); | |
trace(bytes.readLine()); // HELLO WORLD | |
// Numbers | |
bytes.seek(0, Seek.SeekBegin); | |
bytes.writeInt32(-100); | |
bytes.writeInt16(-100); | |
bytes.writeInt8(-100); | |
bytes.writeUInt32(100); | |
bytes.writeUInt16(100); | |
bytes.writeUInt8(100); | |
bytes.writeFloat(1234.5); | |
trace(bytes.tell()); // 18 | |
bytes.seek(0, Seek.SeekBegin); | |
trace(bytes.readInt32()); // -100 | |
trace(bytes.readInt16()); // -100 | |
trace(bytes.readInt8()); // -100 | |
trace(bytes.readUInt32()); // 100 | |
trace(bytes.readUInt16()); // 100 | |
trace(bytes.readUInt8()); // 100 | |
trace(bytes.readFloat()); // 1234.5 | |
// Generic bytes | |
bytes.writeBytes(bytes.bytes, 0, 18); | |
trace(bytes.tell()); // 36 | |
bytes.seek(18, Seek.SeekBegin); | |
trace(bytes.readInt32()); // -100 | |
trace(bytes.readInt16()); // -100 | |
trace(bytes.readInt8()); // -100 | |
trace(bytes.readUInt32()); // 100 | |
trace(bytes.readUInt16()); // 100 | |
trace(bytes.readUInt8()); // 100 | |
trace(bytes.readFloat()); // 1234.5 | |
} | |
} |
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
/* | |
JSByteIO - Javascript stream reader using ArrayBuffers | |
Copyright (C) 2012 James S Urquhart (jamesu at gmail.com) | |
Licensed under the MIT License. | |
*/ | |
import js.XMLHttpRequest; | |
enum Seek | |
{ | |
SeekEnd; | |
SeekCur; | |
SeekBegin; | |
} | |
class JSByteIO | |
{ | |
public var data : ArrayBuffer; | |
public var bytes : Uint8Array; | |
public var pos: Int; | |
// Temp buffers used for conversion | |
private var conversionBuffer: ArrayBuffer; | |
private var conversionUChar : Uint8Array; | |
private var conversionChar : Int8Array; | |
private var conversionUShort: Uint16Array; | |
private var conversionShort: Int16Array; | |
private var conversionUInt: Uint32Array; | |
private var conversionInt: Int32Array; | |
private var floatConversion: Float32Array; | |
public function new(?theData: ArrayBuffer) | |
{ | |
data = theData; | |
bytes = new Uint8Array(theData); | |
pos = 0; | |
conversionBuffer = new ArrayBuffer(16); | |
conversionUChar = new Uint8Array(conversionBuffer); | |
conversionChar = new Int8Array(conversionBuffer); | |
conversionUShort = new Uint16Array(conversionBuffer); | |
conversionShort = new Int16Array(conversionBuffer); | |
conversionUInt = new Uint32Array(conversionBuffer); | |
conversionInt = new Int32Array(conversionBuffer); | |
floatConversion = new Float32Array(conversionBuffer); | |
} | |
public function close() : Void | |
{ | |
data = null; | |
bytes = null; | |
} | |
// Input | |
public function read(nbytes : Int) : Uint8Array | |
{ | |
var buf = new Uint8Array(nbytes); | |
var i=0; | |
while( nbytes > 0 ) { | |
buf[i] = bytes[pos]; | |
i += 1; | |
pos += 1; | |
nbytes -= 1; | |
} | |
return buf; | |
} | |
public function readStringBytes(nbytes : Int) | |
{ | |
var buf = new StringBuf(); | |
for (i in 0...nbytes) | |
buf.addChar(this.readUInt8()); | |
return buf.toString(); | |
} | |
public function readUInt8() { | |
if( this.pos + 1 > this.bytes.length ) | |
throw new Eof(); | |
var c = bytes[pos]; | |
pos += 1; | |
return c; | |
} | |
public function readBytes(s : Uint8Array, p : Int, len : Int) : Int | |
{ | |
var count: Int = 0; | |
var i: Int = p; | |
var j: Int = 0; | |
var end = p+len; | |
var start = this.pos; | |
for (i in p...end) { | |
if (this.pos >= data.length) | |
break; | |
s[i] = this.bytes[this.pos++]; | |
} | |
return this.pos-start; | |
} | |
public function readFloat() : Float { | |
var n = this.readUInt32(); | |
conversionInt.set([n], 0); | |
return floatConversion[0]; | |
} | |
public function readInt8() : Int { | |
var n = readUInt8(); | |
conversionChar[0] = n; | |
return conversionChar[0]; | |
} | |
public function readInt16() : Int { | |
conversionUChar[0] = readUInt8(); | |
conversionUChar[1] = readUInt8(); | |
return conversionShort[0]; | |
} | |
public function readUInt16() : Int { | |
conversionUChar[0] = readUInt8(); | |
conversionUChar[1] = readUInt8(); | |
return conversionUShort[0]; | |
} | |
public function readInt32() { | |
conversionUChar[0] = readUInt8(); | |
conversionUChar[1] = readUInt8(); | |
conversionUChar[2] = readUInt8(); | |
conversionUChar[3] = readUInt8(); | |
return conversionInt[0]; | |
} | |
public function readUInt32() { | |
conversionUChar[0] = readUInt8(); | |
conversionUChar[1] = readUInt8(); | |
conversionUChar[2] = readUInt8(); | |
conversionUChar[3] = readUInt8(); | |
return conversionUInt[0]; | |
} | |
public function readLine() : String | |
{ | |
var buf = new StringBuf(); | |
var last : Int; | |
var c : Int = 0; | |
try { | |
while( true ) { | |
last = readUInt8(); | |
if (last == 10 || last == 0) break; | |
if (last != 13) { buf.addChar( last ); c++; } | |
} | |
} catch( e : Dynamic ) { | |
} | |
return c == 0 ? null : buf.toString(); | |
} | |
public function prepare(nbytes : Int) : Void | |
{ | |
var i = nbytes - 1; | |
while (i >= 0) | |
{ | |
bytes[i] = 0; | |
i -= 1; | |
} | |
} | |
public function writeString(s : Dynamic) : Void | |
{ | |
var i = 0; | |
for (i in 0...s.length) | |
{ | |
writeUInt8(s.charCodeAt(i)); | |
} | |
} | |
public function write(s : Uint8Array) : Void | |
{ | |
var i = 0; | |
for (i in 0...s.length) | |
{ | |
writeUInt8(s[i]); | |
} | |
} | |
public function writeBytes(s : Uint8Array, p : Int, len : Int) : Int | |
{ | |
var opos: Int = pos; | |
try | |
{ | |
write(s.subarray(p, len)); | |
} | |
catch (e: Dynamic) | |
{ | |
return 0; | |
} | |
return pos - opos; | |
} | |
public function writeUInt8(c : Int) : Void | |
{ | |
if (this.pos + 1 > this.bytes.length) | |
throw new Eof(); | |
bytes[pos] = c; | |
pos += 1; | |
} | |
public function writeFloat(x : Float) : Void | |
{ | |
floatConversion[0] = x; | |
writeUInt8(conversionUChar[0]); | |
writeUInt8(conversionUChar[1]); | |
writeUInt8(conversionUChar[2]); | |
writeUInt8(conversionUChar[3]); | |
} | |
public function writeInt16(x : Int) : Void | |
{ | |
conversionShort[0] = x; | |
writeUInt8(conversionUChar[0]); | |
writeUInt8(conversionUChar[1]); | |
} | |
public function writeInt32(x : Int) : Void | |
{ | |
conversionInt[0] = x; | |
writeUInt8(conversionUChar[0]); | |
writeUInt8(conversionUChar[1]); | |
writeUInt8(conversionUChar[2]); | |
writeUInt8(conversionUChar[3]); | |
} | |
public function writeInt8(x : Int) : Void | |
{ | |
conversionChar[0] = x; | |
writeUInt8(conversionUChar[0]); | |
} | |
public function writeUInt16(x : Int) : Void | |
{ | |
conversionUShort[0] = x; | |
writeUInt8(conversionUChar[0]); | |
writeUInt8(conversionUChar[1]); | |
} | |
public function writeUInt32(x : Int) : Void | |
{ | |
conversionUInt[0] = x; | |
writeUInt8(conversionUChar[0]); | |
writeUInt8(conversionUChar[1]); | |
writeUInt8(conversionUChar[2]); | |
writeUInt8(conversionUChar[3]); | |
} | |
public function seek(p : Int, pos : Seek) : Void | |
{ | |
switch (pos) | |
{ | |
case SeekEnd: | |
this.pos = bytes.length - p; | |
case SeekCur: | |
this.pos += p; | |
case SeekBegin: | |
this.pos = p; | |
} | |
} | |
public function tell() : Int | |
{ | |
return pos; | |
} | |
// Static utils | |
public static function fromURL(url: String) : JSByteIO | |
{ | |
// Grab data from url | |
var req: Dynamic = new XMLHttpRequest(); | |
req.open("GET", url, false); | |
req.responseType = "arraybuffer"; | |
req.send(null); | |
var res = new JSByteIO(req.response); | |
trace("XMLHttpRequest: Loaded " + res.bytes.length + " bytes (Type = '" + req.getResponseHeader("Content-Type") + "')"); | |
return res; | |
} | |
} |
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
// Types necessary for JSByteIO | |
enum Error { | |
Blocked; | |
Closed; | |
Overflow; | |
Custom( e : Dynamic ); | |
} | |
class Eof | |
{ | |
public function new() | |
{ | |
} | |
public function toString() : String | |
{ | |
return "EOF"; | |
} | |
} | |
extern class ArrayBuffer { | |
public var length: Int; | |
public function new(size: Int) : Void; | |
} | |
extern class TypedArray implements Array<Dynamic> { | |
public var length: Int; | |
public function set(array: Dynamic, offset: Int) : Void; | |
// So the code doesn't complain | |
/** | |
Returns a new Array by appending [a] to [this]. | |
**/ | |
function concat( a : Array<Dynamic> ) : Array<Dynamic>; | |
/** | |
Returns a representation of an array with [sep] for separating each element. | |
**/ | |
function join( sep : String ) : String; | |
/** | |
Removes the last element of the array and returns it. | |
**/ | |
function pop() : Null<Dynamic>; | |
/** | |
Adds the element [x] at the end of the array. | |
**/ | |
function push(x : Dynamic) : Int; | |
/** | |
Reverse the order of elements of the Array. | |
**/ | |
function reverse() : Void; | |
/** | |
Removes the first element and returns it. | |
**/ | |
function shift() : Null<Dynamic>; | |
/** | |
Copies the range of the array starting at [pos] up to, | |
but not including, [end]. Both [pos] and [end] can be | |
negative to count from the end: -1 is the last item in | |
the array. | |
**/ | |
function slice( pos : Int, ?end : Int ) : Array<Dynamic>; | |
/** | |
Sort the Array according to the comparison function [f]. | |
[f(x,y)] should return [0] if [x == y], [>0] if [x > y] | |
and [<0] if [x < y]. | |
**/ | |
function sort( f : Dynamic -> Dynamic -> Int ) : Void; | |
/** | |
Removes [len] elements starting from [pos] an returns them. | |
**/ | |
function splice( pos : Int, len : Int ) : Array<Dynamic>; | |
/** | |
Returns a displayable representation of the Array content. | |
**/ | |
function toString() : String; | |
/** | |
Adds the element [x] at the start of the array. | |
**/ | |
function unshift( x : Dynamic ) : Void; | |
/** | |
Inserts the element [x] at the position [pos]. | |
All elements after [pos] are moved one index ahead. | |
**/ | |
function insert( pos : Int, x : Dynamic ) : Void; | |
/** | |
Removes the first occurence of [x]. | |
Returns false if [x] was not present. | |
Elements are compared by using standard equality. | |
**/ | |
function remove( x : Dynamic ) : Bool; | |
/** | |
Returns a copy of the Array. Dynamic values are not | |
copied, only the Array structure. | |
**/ | |
function copy() : Array<Dynamic>; | |
/** | |
Returns an iterator of the Array values. | |
**/ | |
function iterator() : Iterator<Null<Dynamic>>; | |
} | |
extern class Float32Array extends TypedArray { | |
public function subarray(begin: Int, end: Int) : Float32Array; | |
public function new(data: Dynamic, ?offset: Int , ?length: Int) : Void; | |
} | |
extern class Int8Array extends TypedArray { | |
public function subarray(begin: Int, end: Int) : Int8Array; | |
public function new(data: Dynamic, ?offset: Int , ?length: Int) : Void; | |
} | |
extern class Int16Array extends TypedArray { | |
public function subarray(begin: Int, end: Int) : Int16Array; | |
public function new(data: Dynamic, ?offset: Int , ?length: Int) : Void; | |
} | |
extern class Int32Array extends TypedArray { | |
public function subarray(begin: Int, end: Int) : Int32Array; | |
public function new(data: Dynamic, ?offset: Int , ?length: Int) : Void; | |
} | |
extern class Uint8Array extends TypedArray { | |
public function subarray(begin: Int, end: Int) : Uint8Array; | |
public function new(data: Dynamic, ?offset: Int , ?length: Int) : Void; | |
} | |
extern class Uint16Array extends TypedArray { | |
public function subarray(begin: Int, end: Int) : Uint16Array; | |
public function new(data: Dynamic, ?offset: Int , ?length: Int) : Void; | |
} | |
extern class Uint32Array extends TypedArray { | |
public function subarray(begin: Int, end: Int) : Uint32Array; | |
public function new(data: Dynamic, ?offset: Int , ?length: Int) : Void; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment