You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					169 lines
				
				3.7 KiB
			
		
		
			
		
	
	
					169 lines
				
				3.7 KiB
			|   
											11 years ago
										 | function BinaryString(source) { | ||
|  | 	this._source = null; | ||
|  | 	this._bytes  = []; | ||
|  | 	this._pos    = 0; | ||
|  | 	this._length = 0; | ||
|  | 
 | ||
|  | 	this._init = function(source) { | ||
|  | 		this._source = source; | ||
|  | 		this._bytes  = this._stringToBytes(this._source); | ||
|  | 		this._length = this._bytes.length; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	this.current = function() {return this._pos;} | ||
|  | 
 | ||
|  | 	this.rewind  = function() {return this.jump(0);} | ||
|  | 	this.end     = function() {return this.jump(this.length()  - 1);} | ||
|  | 	this.next    = function() {return this.jump(this.current() + 1);} | ||
|  | 	this.prev    = function() {return this.jump(this.current() - 1);} | ||
|  | 
 | ||
|  | 	this.jump = function(pos) { | ||
|  | 		if (pos < 0 || pos >= this.length()) return false; | ||
|  | 
 | ||
|  | 		this._pos = pos; | ||
|  | 		return true; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	this.readByte = function(pos) { | ||
|  | 		pos = (typeof pos == 'number') ? pos : this.current(); | ||
|  | 		return this.readBytes(1, pos)[0]; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	this.readBytes = function(length, pos) { | ||
|  | 		length = length || 1; | ||
|  | 		pos    = (typeof pos == 'number') ? pos : this.current(); | ||
|  | 
 | ||
|  | 		if (pos          >  this.length() || | ||
|  | 		    pos          <  0             || | ||
|  | 		    length       <= 0             || | ||
|  | 		    pos + length >  this.length() || | ||
|  | 		    pos + length <  0 | ||
|  | 		) { | ||
|  | 			return false; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		var bytes = []; | ||
|  | 		 | ||
|  | 		for (var i = pos; i < pos + length; i++) { | ||
|  | 			bytes.push(this._bytes[i]); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return bytes; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	this.length = function() {return this._length;} | ||
|  | 
 | ||
|  | 	this.toString = function() { | ||
|  | 		var string = '', | ||
|  | 		    length = this.length(); | ||
|  | 
 | ||
|  | 		for (var i = 0; i < length; i++) { | ||
|  | 			string += String.fromCharCode(this.readByte(i)); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return string; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	this.toUtf8 = function() { | ||
|  | 		var inc    = 0, | ||
|  | 		    string = '', | ||
|  | 		    length = this.length(); | ||
|  | 
 | ||
|  | 		// determine if first 3 characters are the BOM
 | ||
|  | 		// then skip them in output if so
 | ||
|  | 		if (length >= 3               && | ||
|  | 		    this.readByte(0) === 0xEF && | ||
|  | 		    this.readByte(1) === 0xBB && | ||
|  | 		    this.readByte(2) === 0xBF | ||
|  | 		) { | ||
|  | 			inc = 3; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		for (; inc < length; inc++) { | ||
|  | 			var byte1 = this.readByte(inc), | ||
|  | 			    byte2 = 0, | ||
|  | 			    byte3 = 0, | ||
|  | 			    byte4 = 0, | ||
|  | 			    code1 = 0, | ||
|  | 			    code2 = 0, | ||
|  | 			    point = 0; | ||
|  | 
 | ||
|  | 			switch (true) { | ||
|  | 				// single byte character; same as ascii
 | ||
|  | 				case (byte1 < 0x80): | ||
|  | 					code1 = byte1; | ||
|  | 					break; | ||
|  | 
 | ||
|  | 				// 2 byte character
 | ||
|  | 				case (byte1 >= 0xC2 && byte1 < 0xE0): | ||
|  | 					byte2 = this.readByte(++inc); | ||
|  | 
 | ||
|  | 					code1 = ((byte1 & 0x1F) << 6) + | ||
|  | 					         (byte2 & 0x3F); | ||
|  | 					break; | ||
|  | 
 | ||
|  | 				// 3 byte character
 | ||
|  | 				case (byte1 >= 0xE0 && byte1 < 0xF0): | ||
|  | 					byte2 = this.readByte(++inc); | ||
|  | 					byte3 = this.readByte(++inc); | ||
|  | 
 | ||
|  | 					code1 = ((byte1 & 0xFF) << 12) + | ||
|  | 					        ((byte2 & 0x3F) <<  6) + | ||
|  | 					         (byte3 & 0x3F); | ||
|  | 					break; | ||
|  | 
 | ||
|  | 				// 4 byte character
 | ||
|  | 				case (byte1 >= 0xF0 && byte1 < 0xF5): | ||
|  | 					byte2 = this.readByte(++inc); | ||
|  | 					byte3 = this.readByte(++inc); | ||
|  | 					byte4 = this.readByte(++inc); | ||
|  | 
 | ||
|  | 					point = ((byte1 & 0x07) << 18) + | ||
|  | 					        ((byte2 & 0x3F) << 12) + | ||
|  | 					        ((byte3 & 0x3F) <<  6) + | ||
|  | 					         (byte4 & 0x3F) | ||
|  | 					point -= 0x10000; | ||
|  | 
 | ||
|  | 					code1 = (point >> 10)    + 0xD800; | ||
|  | 					code2 = (point &  0x3FF) + 0xDC00; | ||
|  | 					break; | ||
|  | 
 | ||
|  | 				default: | ||
|  | 					throw 'Invalid byte ' + this._byteToString(byte1) + ' whilst converting to UTF-8'; | ||
|  | 					break; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			string += (code2) ? String.fromCharCode(code1, code2) | ||
|  | 			                  : String.fromCharCode(code1); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return string; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	this.toArray  = function() {return this.readBytes(this.length() - 1, 0);}  | ||
|  | 
 | ||
|  | 
 | ||
|  | 	this._stringToBytes = function(str) { | ||
|  | 		var bytes = [], | ||
|  | 		    chr   = 0; | ||
|  | 
 | ||
|  | 		for (var i = 0; i < str.length; i++) { | ||
|  | 			chr = str.charCodeAt(i); | ||
|  | 			bytes.push(chr & 0xFF); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return bytes; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	this._byteToString = function(byte) { | ||
|  | 		var asString = byte.toString(16).toUpperCase(); | ||
|  | 		while (asString.length < 2) { | ||
|  | 			asString = '0' + asString; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return '0x' + asString; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	this._init(source); | ||
|  | } |