docs: function( b, profile ) {
  
  	// The object table to use
  	this.profile = profile;
  
  	// Exported properties prefix
  	this.prefix = "";
  
  	// If we are given an array as buffer, it means
  	// that we loaded separate chunks rather than a 
  	// single, unifide buffer.
  	this.sparse = (b instanceof Array);
  	var hv16, hv32, primBufLen, header_size = 32;
  	if (this.sparse) {
  
  		// Setup views to the buffer
  		this.u8  = new Uint8Array(b[0]);
  		this.s8  = new Int8Array(b[0]);
  		this.u16 = new Uint16Array(b[1]);
  		this.s16 = new Int16Array(b[1]);
  		this.u32 = new Uint32Array(b[2]);
  		this.s32 = new Int32Array(b[2]);
  		this.f32 = new Float32Array(b[2]);
  		this.f64 = new Float64Array(b[3]);
  
  		// Header views
  		hv16 = new Uint16Array(b[0], 0, header_size/2);
  		hv32 = new Uint32Array(b[0], 0, header_size/4);
  
  		// Length of the primary buffer
  		primBufLen = b[0].byteLength;
  
  	} else {
  
  		// Setup views to the buffer
  		this.u8  = new Uint8Array(b);
  		this.s8  = new Int8Array(b);
  		this.u16 = new Uint16Array(b);
  		this.s16 = new Int16Array(b);
  		this.u32 = new Uint32Array(b);
  		this.s32 = new Int32Array(b);
  		this.f32 = new Float32Array(b);
  		this.f64 = new Float64Array(b);
  
  		// Header views
  		hv16 = new Uint16Array(b);
  		hv32 = new Uint32Array(b);
  
  		// Length of the primary buffer
  		primBufLen = b.byteLength;
  
  	}
  
  	// Read header
  	this.magic  	= hv16[0];
  	this.table_id  	= hv16[1];
  	this.version 	= hv16[2];
  	this.table_count= hv16[3];
  
  	// Expand version
  	this.ver_major = this.version & 0x00ff;
  	this.ver_minor = (this.version & 0xff00) >> 8;
  
  	// Calculate upper bounds
  	this.max64  	= hv32[2];
  	this.max32 		= hv32[3];
  	this.max16 		= hv32[4];
  	this.max8  		= hv32[5];
  	this.lenST 		= hv32[6];
  	this.lenOT 		= hv32[7];
  
  	// Validate magic
  	if (this.magic == 0x3142) {
  		throw {
  			'name' 		: 'EndianessError',
  			'message'	: 'Unfortunately the JBB format is currently only compatible with Little-Endian CPUs',
  			toString 	: function(){return this.name + ": " + this.message;}
  		}
  	} else if (this.magic != 0x4231) {
  		throw {
  			'name' 		: 'DecodingError',
  			'message'	: 'This does not look like a JBB archive! (Magic is 0x'+this.magic.toString(16)+')',
  			toString 	: function(){return this.name + ": " + this.message;}
  		}
  	}
  
  	// Validate bundle version number
  	if (this.version != 0x0102) {
  		throw {
  			'name' 		: 'DecodingError',
  			'message'	: 'Unsupported bundle version v'+this.ver_minor+'.'+this.ver_minor,
  			toString 	: function(){return this.name + ": " + this.message;}
  		}
  	}
  
  	// Setup indices
  	if (this.sparse) {
  
  		// Setup indices
  		this.i64 = 0;
  		this.i32 = 0;
  		this.i16 = 0;
  		this.i8  = header_size;
  		this.iEnd= this.i8 + this.max8 - this.lenST;
  
  		// Offsets of array beginning (for getting array portions)
  		this.ofs8  = this.i8;
  		this.ofs16 = this.i16;
  		this.ofs32 = this.i32;
  		this.ofs64 = this.i64;
  
  	} else {
  
  		// Setup indices
  		this.i64 = header_size;
  		this.i32 = this.i64 + this.max64;
  		this.i16 = this.i32 + this.max32;
  		this.i8  = this.i16 + this.max16;
  		this.iEnd= this.i8 + this.max8 - this.lenST;
  
  		// Offsets of array beginning (for getting array portions)
  		this.ofs8  = this.i8;
  		this.ofs16 = this.i16;
  		this.ofs32 = this.i32;
  		this.ofs64 = this.i64;
  
  		// Convert to element index
  		this.i16 /= 2;
  		this.i32 /= 4;
  		this.i64 /= 8;
  
  	}
  
  	// Current position of i16 used later
  	var ci16 = this.i16;
  
  	// Load object tables
  	var ots = [];
  	if (this.table_count <= 1) {
  
  		// The bundle can have no profile if needed
  		if (this.table_id !== 0x00)
  			ots.push( this.table_id );
  
  	} else if (this.table_id !== 0x00) {
  		throw {
  			'name' 		: 'DecodingError',
  			'message'	: 'Invalid header data',
  			toString 	: function(){return this.name + ": " + this.message;}
  		}
  	} else {
  		// Read known table IDs
  		for (var i=0; i<this.table_count; ++i) {
  			ots.push( this.u16[ this.i16++ ] );
  		}
  	}
  
  	// Activate the correct object IDs
  	this.profile.use( ots );		
  
  	// Internal reference table
  	this.iref_table = [];
  
  	// Populate string lookup table
  	var str = "", parsing = false;
  	this.string_table = [];
  	if (this.lenST > 0) {
  		for (var l=this.i8+this.max8, i=l-this.lenST; i<l; ++i) {
  			var c = this.u8[i];
  			if (c === 0) {
  				this.string_table.push(str);
  				str = "";
  				parsing = false;
  			} else {
  				str += String.fromCharCode(c);
  				parsing = true;
  			}
  		}
  		if (parsing) this.string_table.push(str);
  	}
  
  	// Populate object signature lookup table
  	var obj = [], keysPending = 0, active = false;
  	this.signature_table = [];
  	if (this.lenOT > 0) {
  		for (var l=ci16*2+this.max16, i=l-this.lenOT; i<l; i+=2) {
  			var c = this.u16[i/2];
  			if (keysPending--) {
  				obj.push( this.string_table[c] );
  			} else {
  				if (active) this.signature_table.push(obj);
  				obj = []; keysPending = c;
  				active = true;
  			}
  		}
  		if (active) this.signature_table.push(obj);
  	}
  
  
  	// NOTE: The follwing functions *MUST* have a body smaller than 600
  	//       bytes in order to be inlined by the compiler.
  
  	// Create fast numerical read functions
  	var scope = this;
  
  	// Create fast typed array read function
  	if (this.sparse) {
  		this.readTypedArray = function( t, l ) 
  		{ var o8=this.i8,o16=2*this.i16,o32=4*this.i32,o64=8*this.i64;
  		  switch (t) {
  				case 0:this.i8+=l;return new Uint8Array(b[0],o8,l);
  				case 1:this.i8+=l;return new Int8Array(b[0],o8,l);
  				case 2:this.i16+=l;return new Uint16Array(b[1],o16,l);
  				case 3:this.i16+=l;return new Int16Array(b[1],o16,l);
  				case 4:this.i32+=l;return new Uint32Array(b[2],o32,l);
  				case 5:this.i32+=l;return new Int32Array(b[2],o32,l);
  				case 6:this.i32+=l;return new Float32Array(b[2],o32,l);
  				case 7:this.i64+=l;return new Float64Array(b[3],o64,l);
  			}
  		}
  	} else {
  		this.readTypedArray = function( t, l )
  		{ var o8=this.i8,o16=2*this.i16,o32=4*this.i32,o64=8*this.i64;
  		  switch (t) {
  				case 0:this.i8+=l;return new Uint8Array(b,o8,l);
  				case 1:this.i8+=l;return new Int8Array(b,o8,l);
  				case 2:this.i16+=l;return new Uint16Array(b,o16,l);
  				case 3:this.i16+=l;return new Int16Array(b,o16,l);
  				case 4:this.i32+=l;return new Uint32Array(b,o32,l);
  				case 5:this.i32+=l;return new Int32Array(b,o32,l);
  				case 6:this.i32+=l;return new Float32Array(b,o32,l);
  				case 7:this.i64+=l;return new Float64Array(b,o64,l);
  			}
  		}
  	}
  
  	// Create simple object factories from the object table
  	this.factory_plain = [];
  	this.factory_plain_bulk = [];
  	for (var i=0; i<this.signature_table.length; ++i) {
  
  		// Build factory funtion
  		var props = this.signature_table[i], llen = props.length,
  			factoryPlain = "return {", factoryBulk = "var c=values.length/"+llen+";"+factoryPlain;
  		for (var j=0; j<llen; ++j) {
  			factoryPlain += "'"+props[j]+"': values["+j+"],";
  			factoryBulk +=  "'"+props[j]+"': values[i+c*"+j+"],";
  			// factoryBulk +=  "'"+props[j]+"': values[("+j+"*len)+i],";
  		}
  		factoryPlain += "}";
  		factoryBulk += "}";
  
  		// Compile factory function
  		this.factory_plain.push( new Function("values", factoryPlain) );
  		this.factory_plain_bulk.push( new Function("values", "i", factoryBulk) );
  		// this.factory_plain_bulk.push( new Function("values", "len", "i", factoryBulk) );
  
  	}
  
  	// Generate property de-weaving functions for some 
  	// widely used dimentions
  	this.factory_weave = [
  		function(a,b) { return [] }
  	];
  	for (var i=1; i<16; ++i) {
  		this.factory_weave.push( genWeavePropFn(i) );
  	}
  
  }