// MemoryFile class V0.2 // by Maik Stöckmann function MemoryFile(arg,byteOrderBig){ this.boLittle=byteOrderBig===undefined?MemoryFile.getSystemByteOrderLittle():!byteOrderBig; this.boSwap=false; this.pos=0; if(arg instanceof ArrayBuffer){ this.buffer=new Uint8Array(arg); this.dv=new DataView(arg); this.size=this.buffer.length; }else if(typeof arg==='string' || arg instanceof String){ // base64 encoded string presumed var raw=window.atob(arg); this.size=raw.length; this.buffer=new Uint8Array(this.size); this.dv=new DataView(this.buffer.buffer); for(var a=0;athis.buffer.length) this.enlargeBuffer(this.pos-this.buffer.length+byteCount); if(this.pos+byteCount>this.size) this.size=this.pos+byteCount; }; MemoryFile.prototype.enlargeBuffer=function(needed){ var b=new Uint8Array((this.buffer.length+needed)*2); b.set(this.buffer); this.buffer=b; this.dv=new DataView(b.buffer); }; MemoryFile.prototype.toArrayBuffer=function(offset,size){ if(offset===undefined) offset=0; return this.buffer.buffer.slice(offset,size===undefined?this.size:offset+size); }; MemoryFile.prototype.toString=function(){ // to base64 encoded string var b=''; for(var a=0;a=this.size; }; MemoryFile.prototype.setSize=function(size){ if(size>this.buffer.length) this.enlargeBuffer(size-this.buffer.length); this.size=size; }; MemoryFile.SEEK_SET=0; MemoryFile.SEEK_CUR=1; MemoryFile.SEEK_END=2; MemoryFile.prototype.seek=function(offset,origin){ if(origin===MemoryFile.SEEK_CUR) this.pos+=offset; else if(origin===MemoryFile.SEEK_END) this.pos=this.size+offset; else this.pos=offset; return this.pos>=0 && this.pos<=this.size; }; MemoryFile.prototype.tell=function(){ return this.pos; }; MemoryFile.prototype.skip=function(size){ if(this.pos+size<=this.size) this.pos+=size; else throw "EOF error"; }; MemoryFile.prototype.read=function(size){ return new Uint8Array(this.readRaw(size)); }; MemoryFile.prototype.readRaw=function(size){ if(this.pos+size<=this.size){ this.pos+=size; return this.buffer.buffer.slice(this.pos-size,this.pos); } throw "EOF error"; }; MemoryFile.prototype.write=function(v){ if(v instanceof ArrayBuffer) v=new Uint8Array(v); this.ensureCapacity(v.length); this.buffer.set(v,this.pos); this.pos+=v.length; }; MemoryFile.prototype.readBool=function(){ return this.readByte()!=0; }; MemoryFile.prototype.readByte=function(){ return this.dv.getUint8(this.pos++); }; MemoryFile.prototype.readSByte=function(){ //var b=this.readByte(); //return (b & 127)-(b & 128); return this.dv.getInt8(this.pos++); }; MemoryFile.prototype.readInt16=function(){ var v=this.dv.getInt16(this.pos,this.boLittle); this.pos+=2; return v; }; MemoryFile.prototype.readUInt16=function(){ var v=this.dv.getUint16(this.pos,this.boLittle); this.pos+=2; return v; }; MemoryFile.prototype.readInt32=function(){ var v=this.dv.getInt32(this.pos,this.boLittle); this.pos+=4; return v; }; MemoryFile.prototype.readUInt32=function(){ var v=this.dv.getUint32(this.pos,this.boLittle); this.pos+=4; return v; }; MemoryFile.prototype.readUInt64=function(){ return this.readUInt(8); }; MemoryFile.prototype.readIntVarlen=function(signBitFirst){ var shift=6,b=this.readByte(); var v=signBitFirst?((b & 63)>>1):(b & 63); var negative=b & (signBitFirst?1:64); // sign bit in first byte while(b & 128){ // if the next-byte flag is set b=this.readByte(); v+=(b & 127)*Math.pow(2,shift); shift+=7; }; return negative?-v:v; }; MemoryFile.prototype.readUIntVarlen=function(){ var v=0,shift=0,b; do{ b=this.readByte(); v+=(b & 127)*Math.pow(2,shift); shift+=7; }while(b & 128); // if the next-byte flag is set return v; }; MemoryFile.prototype.readUInt=function(numBytes){ // Warning: Javascript can't handle big integers, because it uses a Double for internal number representation! var b=this.read(numBytes),v=0; if(this.boLittle) for(var a=numBytes-1;a>=0;a--) v=(v*256)+b[a]; else for(var a=0;a63){ v=Math.floor(v/64); while(v>127){size++;v=Math.floor(v/128);} size++; } return size; }; MemoryFile.prototype.writeIntVarlen=function(v,signBitFirst){ v=Math.round(v); var signBit=0; if(v<0){signBit=signBitFirst?1:64;v=-v;} this.writeByte((signBitFirst?(v & 63)<<1:(v & 63))|signBit|(v<64?0:128)); if(v>63){ v=Math.floor(v/64); // remove the six bits we wrote in the first byte while(v>127){ // while more than 7 bits of data are left, occupy the last output byte and set the next byte flag this.writeByte((v & 127)|128); // |128 to set the next byte flag v=Math.floor(v/128); // remove the seven bits we just wrote } this.writeByte(v); } }; MemoryFile.predictUIntVarlenSize=function(v){ v=Math.round(v); var size=1; while(v>127){size++;v=Math.floor(v/128);} return size; }; MemoryFile.prototype.writeUIntVarlen=function(v){ v=Math.round(v); while(v>127){ // while more than 7 bits of data are left, occupy the last output byte and set the next byte flag //var b=v & 127; //this.writeByte(b | 128); // |128 to set the next byte flag //v=(v-b)/128; // remove the seven bits we just wrote this.writeByte((v & 127)|128); // |128 to set the next byte flag v=Math.floor(v/128); // remove the seven bits we just wrote } this.writeByte(v); }; MemoryFile.prototype.writeUInt=function(v,numBytes){ // Warning: Javascript can't handle big integers, because it uses a Double for internal number representation! v=Math.round(v); var b=new Uint8Array(numBytes); if(this.boLittle) for(var a=0;a=0;a--){ b[a]=v & 255; v=Math.floor(v/256); // remove the eights bits we just wrote } this.write(b); }; MemoryFile.prototype.writeFloat16=function(v){ this.writeInt32(MemoryFile.packHalfPrecision(v)); }; MemoryFile.packHalfPrecision=function(v){ // Cast float to integer: var b=new ArrayBuffer(4); new Float32Array(b)[0]=v; var inu=new Uint32Array(b)[0]; // Convert: var m=inu & 0x7fffffff; // Non-sign bits var sign=inu & 0x80000000; // Sign bit var exponent=inu & 0x7f800000; // Exponent m>>=13; // Align mantissa on MSB sign>>=16; // Shift sign bit into position m-=0x1c000; // Adjust bias m=exponent>0x38800000?0:m; // Flush-to-zero m=exponent<0x8e000000?0x7c00:m; // Overflow to infinity. Note that you can change the constant 0x7c00 to 0x7bff to Clamp-to-max. m=exponent==0?0:m; // Denormals-as-zero m|=sign; // Re-insert sign bit return m; }; MemoryFile.prototype.writeFloat32=function(v){ this.ensureCapacity(4); this.dv.setFloat32(this.pos,v,this.boLittle); this.pos+=4; }; MemoryFile.prototype.writeFloat64=function(v){ this.ensureCapacity(8); this.dv.setFloat64(this.pos,v,this.boLittle); this.pos+=8; }; MemoryFile.predictDecimalFloatSize=function(d){ var mantissa=0; if(!isFinite(d)) return 2; var exponent=1; // use exponent 0 as symbol for special value, so we must shift the exponent by 1 if(d<0) d=-d; var fac=1,d2=d; while(Math.floor(d2)2147483647) return 2147483647; // Special hack for JavaScript: Prevent use of DecimalFloat for mantiassas langer than the limit of Int32 // write exponent: var size=2; if(exponent>63){ size++; exponent>>=6; // remove the six bits we wrote in the first byte while(exponent>127){ // while more than 7 bits of data are left, occupy the last output byte and set the next byte flag size++;exponent>>=7; // remove the seven bits we just wrote } } // write mantissa: while(mantissa>127){ // while more than 7 bits of data are left, occupy the last output byte and set the next byte flag size++;mantissa>>=7; // remove the seven bits we just wrote } return size; }; MemoryFile.prototype.writeDecimalFloat=function(d){ var signBit=0,exponent=0,mantissa=0; if(d===Number.POSITIVE_INFINITY || d===Number.NEGATIVE_INFINITY){ // Infinity // mantissa=0 }else if(isNaN(d)){ mantissa=1; }else{ exponent=1; // use exponent 0 as symbol for special value, so we must shift the exponent by 1 if(d<0){signBit=64;d=-d;} var fac=1,d2=d; while(Math.floor(d2)63){ exponent>>=6; // remove the six bits we wrote in the first byte while(exponent>127){ // while more than 7 bits of data are left, occupy the last output byte and set the next byte flag this.writeByte((exponent & 127)|128); // |128 to set the next byte flag exponent>>=7; // remove the seven bits we just wrote } this.writeByte(exponent); } // write mantissa: while(mantissa>127) { // while more than 7 bits of data are left, occupy the last output byte and set the next byte flag this.writeByte((mantissa & 127)|128); // |128 to set the next byte flag mantissa>>=7; // remove the seven bits we just wrote } this.writeByte(mantissa); }; MemoryFile.prototype.writeChars=function(s){ this.write(MemoryFile.strToUtf8(s)); }; MemoryFile.prototype.writeTinyString=function(s){ var u=MemoryFile.strToUtf8(s); if(u.length>255){ do{ s=s.substr(0,s.length-1); u=MemoryFile.strToUtf8(s); }while(u.length>255); } this.writeByte(u.length); this.write(u); }; MemoryFile.prototype.writeSmallString=function(s){ var u=MemoryFile.strToUtf8(s); if(u.length>65535){ do{ s=s.substr(0,s.length-1); u=MemoryFile.strToUtf8(s); }while(u.length>65535); } this.writeUInt16(u.length); this.write(u); }; MemoryFile.prototype.writeString=function(s){ var u=MemoryFile.strToUtf8(s); this.writeUInt32(u.length); this.write(u); }; MemoryFile.prototype.writeStringVarlen=function(s){ var u=MemoryFile.strToUtf8(s); this.writeUIntVarlen(u.length); this.write(u); }; MemoryFile.prototype.writeBytesVarlen=function(b){ this.writeUIntVarlen(b.byteLength); this.write(b); }; MemoryFile.prototype.writeZeros=function(count){ if(count>0) this.write(new Uint8Array(count)); }; MemoryFile.utf8ToStr=function(array){ var s="",i=0,len=array.length; while(i>4){ case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7: // 0xxxxxxx s+=String.fromCharCode(c); break; case 12:case 13: // 110x xxxx 10xx xxxx s+=String.fromCharCode(((c & 0x1F)<<6)|(array[i++] & 0x3F)); break; case 14: // 1110 xxxx 10xx xxxx 10xx xxxx var char2=array[i++];var char3=array[i++]; s+=String.fromCharCode(((c & 0x0F) << 12)|((char2 & 0x3F) << 6)|((char3 & 0x3F)<<0)); break; } } return s; }; MemoryFile.strToUtf8=function(s){ var u=""; for(var n=0;n127) && (c<2048)){ u+=String.fromCharCode((c>>6) | 192); u+=String.fromCharCode((c & 63) | 128); }else{ u+=String.fromCharCode((c>>12) | 224); u+=String.fromCharCode(((c>>6) & 63) | 128); u+=String.fromCharCode((c & 63) | 128); } } var array=new Uint8Array(u.length); for(var n=0;n