Files
rainmelt/html/util.js
2012-08-05 19:21:17 +09:00

220 lines
5.5 KiB
JavaScript

var BinaryBuffer = function() {
this.bufferSize = 32;
this.buffer = new Uint8Array(this.bufferSize);
this.length = 0;
};
BinaryBuffer.prototype.append = function(v) {
if (this.length >= this.bufferSize) {
this.bufferSize *= 2;
var newBuffer = new Uint8Array(this.bufferSize);
newBuffer.set(this.buffer);
this.buffer = newBuffer;
}
this.buffer[this.length] = v;
this.length++;
};
BinaryBuffer.prototype.compact = function() {
this.bufferSize = this.length;
var newBuffer = new Uint8Array(this.bufferSize);
newBuffer.set(this.buffer, 0, newBuffer.length);
this.buffer = newBuffer;
};
var Unicode = {};
Unicode.toUTF8 = function(s) {
var index = 0;
var buffer = new BinaryBuffer();
while (index < s.length) {
var codePoint;
var code = s.charCodeAt(index);
index++;
if (code >= 0xd800 && code < 0xdc00) {
if (index >= s.length) {
throw "Bad character";
}
var code2 = s.charCodeAt(index);
index++;
if (code2 < 0xdc00 || code2 >= 0xe000) {
throw "Bad character";
}
codePoint = (code - 0xd800 << 10) + code2 - 0xdc00 + 0x10000;
} else {
codePoint = code;
}
if (codePoint < 0x80) {
buffer.append(codePoint);
} else if (codePoint < 0x800) {
buffer.append(0xc0 | codePoint >>> 6);
buffer.append(0x80 | (codePoint & 0x3f));
} else if (codePoint < 0x10000) {
buffer.append(0xe0 | codePoint >>> 12);
buffer.append(0x80 | (codePoint >>> 6 & 0x3f));
buffer.append(0x80 | (codePoint & 0x3f));
} else if (codePoint < 0x200000) {
buffer.append(0xf0 | codePoint >>> 18);
buffer.append(0x80 | (codePoint >>> 12 & 0x3f));
buffer.append(0x80 | (codePoint >>> 6 & 0x3f));
buffer.append(0x80 | (codePoint & 0x3f));
} else {
throw "Bad code point";
break;
}
}
buffer.compact;
return buffer.buffer;
};
Unicode.fromUTF8 = function(buffer) {
var s = '';
var index = 0;
while (index < buffer.length) {
var head = buffer[index];
var n;
if ((head & 0x80) == 0x00) {
n = 1;
} else if ((head & 0xe0) == 0xc0) {
n = 2;
} else if ((head & 0xf0) == 0xe0) {
n = 3;
} else if ((head & 0xf8) == 0xf0) {
n = 4;
} else if ((head & 0xfc) == 0xf8) {
n = 5;
} else if ((head & 0xfe) == 0xfc) {
n = 6;
} else {
break;
}
var b = [];
for (var i = 0; i < n; i++) {
b[i] = buffer[index];
index++;
}
var codePoint;
switch (b.length) {
case 1:
codePoint = b[0];
break;
case 2:
codePoint = (b[0] & 0x1f) << 6 | (b[1] & 0x3f);
break;
case 3:
codePoint = (b[0] & 0x0f) << 12 | (b[1] & 0x3f) << 6 | (b[2] & 0x3f);
break;
case 4:
codePoint = (b[0] & 0x07) << 18 | (b[1] & 0x3f) << 12 | (b[2] & 0x3f) << 6 | (b[3] & 0x3f);
break;
case 5:
throw "Parse error";
case 6:
throw "Parse error";
default:
throw "Unreachable";
break;
}
if (codePoint < 0x10000) {
s += String.fromCharCode(codePoint);
} else {
s += String.fromCharCode(codePoint - 0x10000 >>> 10 + 0xd800);
s += String.fromCharCode((codePoint - 0x10000 & 0x3ff) + 0xdc00);
}
}
return s;
};
var Base64 = {};
Base64.encoderMap = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
];
Base64.decoderMap = {
'A':0, 'B':1, 'C':2, 'D':3, 'E':4, 'F':5, 'G':6, 'H':7, 'I':8, 'J':9, 'K':10, 'L':11, 'M':12, 'N':13, 'O':14, 'P':15,
'Q':16, 'R':17, 'S':18, 'T':19, 'U':20, 'V':21, 'W':22, 'X':23, 'Y':24, 'Z':25, 'a':26, 'b':27, 'c':28, 'd':29, 'e':30, 'f':31,
'g':32, 'h':33, 'i':34, 'j':35, 'k':36, 'l':37, 'm':38, 'n':39, 'o':40, 'p':41, 'q':42, 'r':43, 's':44, 't':45, 'u':46, 'v':47,
'w':48, 'x':49, 'y':50, 'z':51, '0':52, '1':53, '2':54, '3':55, '4':56, '5':57, '6':58, '7':59, '8':60, '9':61, '+':62, '/':63,
};
Base64.getBase64Index = function(b, i) {
// 00000011 11112222 22333333
var j = Math.floor(i / 4) * 3;
switch (i % 4) {
case 0:
return (b[j] & 0xfc) >>> 2;
case 1:
if (j + 1 < b.length) {
return (b[j] & 0x03) << 4 | (b[j + 1] & 0xf0) >>> 4;
} else {
return (b[j] & 0x03) << 4;
}
case 2:
if (j + 2 < b.length) {
return (b[j + 1] & 0x0f) << 2 | (b[j + 2] & 0xc0) >>> 6;
} else {
return (b[j + 1] & 0x0f) << 2;
}
case 3:
return b[j + 2] & 0x3f;
default:
return 0;
}
};
Base64.encode = function(b) {
var meanSize = Math.floor((b.length * 8 + 5) / 6);
var resultSize = Math.floor((meanSize + 3) / 4) * 4;
var sb = '';
for (var i = 0; i < meanSize; i++) {
sb += this.encoderMap[this.getBase64Index(b, i)];
}
for (var i = meanSize; i < resultSize; i++) {
sb += '=';
}
return sb;
};
Base64.getRawByte = function(s, i) {
// 00000011 11112222 22333333
var j = Math.floor(i * 8 / 6 / 4) * 4;
switch (i % 3) {
case 0:
return this.decoderMap[s.charAt(j)] << 2 | this.decoderMap[s.charAt(j + 1)] >>> 4;
case 1:
return this.decoderMap[s.charAt(j + 1)] << 4 & 0xf0 | this.decoderMap[s.charAt(j + 2)] >>> 2;
case 2:
return this.decoderMap[s.charAt(j + 2)] << 6 & 0xc0 | this.decoderMap[s.charAt(j + 3)];
default:
return 0;
}
};
Base64.decode = function(s) {
var meanSize = s.length;
for (var i = s.length - 1; i >= 0; i--) {
if (s.charAt(i) == '=') {
meanSize--;
}
}
var resultSize = Math.floor(meanSize * 6 / 8);
var result = new Uint8Array(resultSize);
for (var i = 0; i < resultSize; i++) {
result[i] = this.getRawByte(s, i);
}
return result;
};