Compare commits
47 Commits
Author | SHA1 | Date | |
---|---|---|---|
712ae72156 | |||
|
c5a3340a13 | ||
|
49f9469bfd | ||
|
c54fef010f | ||
|
8b84926984 | ||
|
ed4674f721 | ||
|
545cae0f21 | ||
|
c439d0a170 | ||
68b8abc469 | |||
|
df97310b71 | ||
|
76cb135585 | ||
|
a109259e10 | ||
|
c4626055ff | ||
|
20bed84814 | ||
|
e7c9b79676 | ||
|
66ab9f25b4 | ||
|
bde896c451 | ||
|
c67e0582f3 | ||
|
aafbc0e083 | ||
|
ba0b45c7e8 | ||
|
ca845c0080 | ||
|
73eb31e1ed | ||
|
f9c33cc112 | ||
|
8cd0bc48ec | ||
|
ea400ab670 | ||
|
54046325da | ||
|
952531809b | ||
|
3ee2edc04b | ||
|
f527c6b28c | ||
|
e684b80b11 | ||
|
454734989a | ||
|
94a64a218a | ||
|
670ac1314b | ||
|
8e5c528f55 | ||
|
767ab55060 | ||
|
f041dcd8bb | ||
|
a643e57ef1 | ||
|
ed56a62799 | ||
|
8f2a49efd0 | ||
|
552de8b45a | ||
|
9099f2eb2e | ||
|
787dc230c2 | ||
|
10967b0a55 | ||
|
bff3fb392d | ||
|
a35f1b86c1 | ||
|
008bdeb906 | ||
|
60e61beb06 |
32
LICENSE
32
LICENSE
@ -1,3 +1,32 @@
|
||||
At your option you may choose either of the following licenses:
|
||||
|
||||
* The MIT License (MIT)
|
||||
* The Apache License 2.0 (Apache-2.0)
|
||||
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 AJ ONeal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
@ -186,7 +215,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
Copyright 2015 AJ ONeal
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -199,4 +228,3 @@
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
149
README.md
149
README.md
@ -1,10 +1,98 @@
|
||||
utf8-typed
|
||||
==========
|
||||
Unibabel
|
||||
========
|
||||
|
||||
Base64, TypedArrays, and UTF-8 / Unicode conversions in Browser (and Node) JavaScript
|
||||
Minimalistic **Base64**, **TypedArrays**, and **UTF-8** / **Unicode** conversions in Browser (and Node) JavaScript. Optional add-on support for **hex** and **base32**.
|
||||
|
||||
This is based wholly on the work by good folks at the MDN.
|
||||
See <https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding>
|
||||
See <https://coolaj86.com/articles/base64-unicode-utf-8-javascript-and-you/>
|
||||
|
||||
See also
|
||||
|
||||
* [TextEncoder](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder/encode) / [TextDecoder](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/decode)
|
||||
* [DateView](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView)
|
||||
* [text-encoding](https://github.com/inexorabletash/text-encoding)
|
||||
* [TextEncoderLite (based on Buffer)](https://github.com/coolaj86/TextEncoderLite/tree/litest)
|
||||
* [TextEncoderLite (based on text-encoding)](https://github.com/coolaj86/TextEncoderLite/tree/lite)
|
||||
* [Beatgammit's base64-js](https://github.com/beatgammit/base64-js)
|
||||
|
||||
Are you in the right place?
|
||||
------------------------
|
||||
|
||||
Dear Node.js Users:
|
||||
|
||||
You SHOULD NOT use this module. You already have [`Buffer`](https://nodejs.org/api/buffer.html) and [`thirty-two`](https://github.com/chrisumbel/thirty-two):
|
||||
|
||||
```javascript
|
||||
var buf = new Buffer('I ½ ♥ 💩', 'utf8');
|
||||
buf.toString('hex');
|
||||
buf.toString('base64');
|
||||
buf.toString('ascii');
|
||||
buf.toString('utf8');
|
||||
buf.toString('binary'); // deprecated, do not use
|
||||
```
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
You just include the `index.js` in a lovely script tag.
|
||||
|
||||
```bash
|
||||
bower install --save unibabel
|
||||
```
|
||||
|
||||
```html
|
||||
<script src="/bower_components/unibabel/index.js"></script>
|
||||
```
|
||||
|
||||
Dear WebPack / Broccoli, Gulp / Grunt Users:
|
||||
|
||||
I don't know how your build systems work these days,
|
||||
but Unibabel is exported as `Unibabel`
|
||||
and you can access it as `window.Unibabel`.
|
||||
|
||||
API
|
||||
===
|
||||
|
||||
```javascript
|
||||
// TypedArray <--> UTF8
|
||||
var uint8Array = Unibabel.strToUtf8Arr(str);
|
||||
var str = Unibabel.utf8ArrToStr(uint8Array);
|
||||
|
||||
// TypedArray <--> Base64
|
||||
var base64 = Unibabel.arrToBase64(uint8Array)
|
||||
var uint8Array = Unibabel.base64ToArr(base64)
|
||||
```
|
||||
|
||||
**Normal APIs**
|
||||
|
||||
`index.js`
|
||||
|
||||
* utf8ToBuffer(utf8str) => array
|
||||
* bufferToUtf8(array) => string
|
||||
* utf8ToBase64(utf8str) => base64
|
||||
* base64ToUtf8(base64) => string
|
||||
* bufferToBase64(array) => base64
|
||||
* base64ToBuffer(base64) => array
|
||||
|
||||
**Hex APIs**
|
||||
|
||||
`unibabel.hex.js`
|
||||
|
||||
* hexToBuffer(hexstr) => array
|
||||
* bufferToHex(array) => hexstr
|
||||
|
||||
**Base32 APIs**
|
||||
|
||||
`unibabel.base32.js`
|
||||
|
||||
* base32ToBuffer(b32str) => array
|
||||
* bufferToBase32(array) => b32str
|
||||
|
||||
**Helper APIs**
|
||||
|
||||
* utf8ToBinaryString(utf8str) => binstr
|
||||
* binaryStringToUtf8(binstr) => utf8str
|
||||
* bufferToBinaryString(buffer) => binstr
|
||||
* binaryStringToBuffer(binstr) => array
|
||||
|
||||
Examples
|
||||
========
|
||||
@ -12,25 +100,21 @@ Examples
|
||||
```javascript
|
||||
// Base64
|
||||
|
||||
var myArray = base64DecToArr("QmFzZSA2NCDigJQgTW96aWxsYSBEZXZlbG9wZXIgTmV0d29yaw=="); // "Base 64 \u2014 Mozilla Developer Network"
|
||||
|
||||
var myBuffer = base64DecToArr("QmFzZSA2NCDigJQgTW96aWxsYSBEZXZlbG9wZXIgTmV0d29yaw==").buffer; // "Base 64 \u2014 Mozilla Developer Network"
|
||||
var myArray = Unibabel.base64ToArr("QmFzZSA2NCDigJQgTW96aWxsYSBEZXZlbG9wZXIgTmV0d29yaw=="); // "Base 64 \u2014 Mozilla Developer Network"
|
||||
var myBuffer = Unibabel.base64ToArr("QmFzZSA2NCDigJQgTW96aWxsYSBEZXZlbG9wZXIgTmV0d29yaw==").buffer; // "Base 64 \u2014 Mozilla Developer Network"
|
||||
|
||||
console.log(myBuffer.byteLength);
|
||||
|
||||
// Crazy Unicode
|
||||
|
||||
var sMyInput = "I'm a ☢ ☃ that plays 𝄢 guitar and spea̧͈͖ks Ar̽̾̈́͒͑ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜!";
|
||||
|
||||
var aMyUTF8Input = strToUTF8Arr(sMyInput);
|
||||
|
||||
var sMyBase64 = base64EncArr(aMyUTF8Input);
|
||||
var aMyUTF8Input = Unibabel.strToUtf8Arr(sMyInput);
|
||||
var sMyBase64 = Unibabel.arrToBase64(aMyUTF8Input);
|
||||
|
||||
alert(sMyBase64);
|
||||
|
||||
var aMyUTF8Output = base64DecToArr(sMyBase64);
|
||||
|
||||
var sMyOutput = UTF8ArrToStr(aMyUTF8Output);
|
||||
var aMyUTF8Output = Unibabel.base64ToArr(sMyBase64);
|
||||
var sMyOutput = Unibabel.utf8ArrToStr(aMyUTF8Output);
|
||||
|
||||
alert(sMyOutput);
|
||||
```
|
||||
@ -38,7 +122,38 @@ alert(sMyOutput);
|
||||
License
|
||||
=======
|
||||
|
||||
Mozilla has licensed this code in the Public Domain, which means that I am at liberty to re-license my copy
|
||||
under the Apache 2, which is something that, general speaking, your legal department will feel more comfortable with.
|
||||
* `index.js` and `unibabel.hex.js` are dual-licensed as Apache 2.0 and MIT.
|
||||
* `unibabel.base32.js` is a modified version of [thirty-two](https://github.com/chrisumbel/thirty-two) and is therefore licensed MIT.
|
||||
|
||||
Some parts of the code were taken from MDN, which Mozilla has licensed in the Public Domain,
|
||||
which means that I am at liberty to re-license my copy under the Apache 2 and MIT licenses.
|
||||
|
||||
See <https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses>
|
||||
|
||||
ChangeLog
|
||||
====
|
||||
|
||||
v2.1.0
|
||||
------
|
||||
|
||||
Added `unibabel.base32.js`
|
||||
|
||||
v2.0.0
|
||||
------
|
||||
|
||||
The new implementation is binary compatible with node.js, TextEncoder,
|
||||
and other more-common UTF-8 encodings.
|
||||
|
||||
It is also based on DOM APIs which result in much less code and are still
|
||||
backwards compatible all the way back to IE6 (not on purpose, just that
|
||||
it happens to work).
|
||||
|
||||
See <https://coolaj86.com/articles/base64-unicode-utf-8-javascript-and-you/>
|
||||
|
||||
v1.0.0
|
||||
------
|
||||
|
||||
This version was based on the work by good folks at the MDN, however,
|
||||
the UTF-8 conversion was not byte-compatible with other UTF-8 conversions
|
||||
(such as node.js and TextEncoder), so don't use it.
|
||||
See <https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding>
|
||||
|
15
bower.json
15
bower.json
@ -1,10 +1,9 @@
|
||||
{
|
||||
"name": "unibabel",
|
||||
"main": "index.js",
|
||||
"version": "1.0.0-rc1",
|
||||
"homepage": "https://github.com/coolaj86/unibabel-js",
|
||||
"homepage": "https://git.coolaj86.com/coolaj86/unibabel.js",
|
||||
"authors": [
|
||||
"AJ ONeal <awesome@coolaj86.com>"
|
||||
"AJ ONeal <coolaj86@gmail.com>"
|
||||
],
|
||||
"description": "Convert between UTF8, TypedArrays, and Base64",
|
||||
"moduleType": [
|
||||
@ -12,15 +11,21 @@
|
||||
"node"
|
||||
],
|
||||
"keywords": [
|
||||
"ascii",
|
||||
"binary",
|
||||
"utf8",
|
||||
"utf-8",
|
||||
"ArrayBuffer",
|
||||
"TypedArrays",
|
||||
"TypedArray",
|
||||
"Uint",
|
||||
"Uint8Array",
|
||||
"Base64",
|
||||
"b64"
|
||||
"b64",
|
||||
"Base32",
|
||||
"b32"
|
||||
],
|
||||
"license": "Apache2",
|
||||
"license": "Apache-2.0",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
|
12
examples/index.html
Normal file
12
examples/index.html
Normal file
@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
This is for testing. Look in the console.
|
||||
<script src="../index.js"></script>
|
||||
<script src="../unibabel.hex.js"></script>
|
||||
<script src="../unibabel.base32.js"></script>
|
||||
<script src="./test.js"></script>
|
||||
</body>
|
||||
</html>
|
30
examples/node-buffer.js
Normal file
30
examples/node-buffer.js
Normal file
@ -0,0 +1,30 @@
|
||||
var str = "I ½ ♥ 𩶘";
|
||||
var buf = new Buffer(str);
|
||||
var base64 = buf.toString('base64');
|
||||
var hex = buf.toString('hex');
|
||||
var bytes = Array.prototype.map.call(buf, function (byte) {
|
||||
return byte;
|
||||
});
|
||||
|
||||
console.log('');
|
||||
console.log('UTF-8');
|
||||
console.log(str);
|
||||
console.log(base64);
|
||||
console.log(hex);
|
||||
console.log('[ ' + bytes.join(', ') + ' ]');
|
||||
console.log('');
|
||||
|
||||
// Array.prototype.map.call(crypto.randomBytes(8), function (b) { return b; });
|
||||
var bytes = [ 255, 226, 26, 243, 134, 206, 147, 107 ];
|
||||
buf = new Buffer(bytes);
|
||||
str = buf.toString('binary');
|
||||
base64 = buf.toString('base64');
|
||||
hex = buf.toString('hex');
|
||||
|
||||
console.log('');
|
||||
console.log('binary');
|
||||
console.log(str);
|
||||
console.log(base64);
|
||||
console.log(hex);
|
||||
console.log(bytes);
|
||||
console.log('');
|
8
examples/node-thirty-two.js
Normal file
8
examples/node-thirty-two.js
Normal file
@ -0,0 +1,8 @@
|
||||
var base32 = require('thirty-two');
|
||||
var str = "I ½ ♥ 𩶘";
|
||||
var buf = new Buffer(str, 'utf8');
|
||||
console.log('charLen', 7);
|
||||
console.log('byteLen', buf.byteLength, JSON.stringify(buf.toString('utf8')));
|
||||
var b32 = base32.encode(buf); // to base32
|
||||
console.log('encoded', b32.toString('utf8'));
|
||||
console.log('decoded', base32.decode(b32).toString('utf8'));
|
95
examples/test.js
Normal file
95
examples/test.js
Normal file
@ -0,0 +1,95 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var Unibabel = window.Unibabel;
|
||||
|
||||
//UTF-8
|
||||
var pass = true;
|
||||
var references = {
|
||||
string: "I ½ ♥ 𩶘"
|
||||
, array: [ 73, 32, 194, 189, 32, 226, 153, 165, 32, 240, 169, 182, 152 ]
|
||||
, hex: "4920c2bd20e299a520f0a9b698"
|
||||
, base64: "SSDCvSDimaUg8Km2mA=="
|
||||
, base32: 'JEQMFPJA4KM2KIHQVG3JQ==='
|
||||
};
|
||||
references.buffer = new Uint8Array(references.array);
|
||||
var binrefs = {
|
||||
// Note that the binary string "ÿâó<86>Î<93>k" can't be serialized to text
|
||||
array: [ 255, 226, 26, 243, 134, 206, 147, 107 ]
|
||||
, hex: "ffe21af386ce936b"
|
||||
, base64: "/+Ia84bOk2s="
|
||||
};
|
||||
binrefs.buffer = new Uint8Array(binrefs.array);
|
||||
|
||||
var str = references.string;
|
||||
var buf = Unibabel.utf8ToBuffer(references.string);
|
||||
var base64 = Unibabel.bufferToBase64(references.buffer);
|
||||
var hex = Unibabel.bufferToHex(references.buffer);
|
||||
var b32 = Unibabel.bufferToBase32(references.buffer);
|
||||
|
||||
function buffersAreEqual(buf1, buf2) {
|
||||
if (buf1.length !== buf2.length) {
|
||||
return false;
|
||||
}
|
||||
return Array.prototype.every.call(buf1, function (byte, i) {
|
||||
if (byte === buf2[i]) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO compare buffer
|
||||
if (!buffersAreEqual(buf, references.array)) {
|
||||
pass = false;
|
||||
console.warn('[FAIL] utf8 -> buffer', buf);
|
||||
}
|
||||
if (base64 !== references.base64) {
|
||||
pass = false;
|
||||
console.warn('[FAIL] utf8 -> base64', base64);
|
||||
}
|
||||
if (hex !== references.hex) {
|
||||
pass = false;
|
||||
console.warn('[FAIL] utf8 -> hex', hex);
|
||||
}
|
||||
|
||||
|
||||
// binary
|
||||
var bytes = binrefs.array;
|
||||
buf = new Uint8Array(bytes);
|
||||
str = Unibabel.bufferToBinaryString(buf);
|
||||
base64 = Unibabel.bufferToBase64(buf);
|
||||
hex = Unibabel.bufferToHex(buf);
|
||||
|
||||
// This can't be properly tested because binary strings can't be parsed
|
||||
// if (str !== "ÿâóÎk") {
|
||||
// pass = false;
|
||||
// console.log('[FAIL] binary -> str', str);
|
||||
// }
|
||||
if (binrefs.base64 !== base64) {
|
||||
pass = false;
|
||||
console.warn('[FAIL] binary -> base64', base64);
|
||||
}
|
||||
if (binrefs.hex !== hex) {
|
||||
pass = false;
|
||||
console.warn('[FAIL] binary -> hex', hex);
|
||||
}
|
||||
|
||||
//
|
||||
// Base32
|
||||
//
|
||||
b32 = Unibabel.bufferToBase32(references.buffer);
|
||||
if (references.base32 !== b32) {
|
||||
pass = false;
|
||||
console.warn('[FAIL] binary -> base32', references.base32, '!==', b32);
|
||||
}
|
||||
buf = Unibabel.base32ToBuffer(references.base32);
|
||||
if (!buffersAreEqual(buf, references.buffer)) {
|
||||
pass = false;
|
||||
console.warn('[FAIL] base32 -> binary', references.buffer, '!==', buf);
|
||||
}
|
||||
|
||||
if (pass) {
|
||||
console.info('[PASS] :-D');
|
||||
}
|
||||
|
||||
}());
|
198
examples/utf8-mdn.js
Normal file
198
examples/utf8-mdn.js
Normal file
@ -0,0 +1,198 @@
|
||||
(function (exports) {
|
||||
"use strict";
|
||||
var Unibabel = {};
|
||||
|
||||
/*\
|
||||
|*|
|
||||
|*| Base64 / binary data / UTF-8 strings utilities
|
||||
|*|
|
||||
|*| https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
|
||||
|*|
|
||||
\*/
|
||||
|
||||
/* Array of bytes to base64 string decoding */
|
||||
|
||||
function b64ToUint6 (nChr) {
|
||||
|
||||
return nChr > 64 && nChr < 91 ?
|
||||
nChr - 65
|
||||
: nChr > 96 && nChr < 123 ?
|
||||
nChr - 71
|
||||
: nChr > 47 && nChr < 58 ?
|
||||
nChr + 4
|
||||
: nChr === 43 ?
|
||||
62
|
||||
: nChr === 47 ?
|
||||
63
|
||||
:
|
||||
0;
|
||||
|
||||
}
|
||||
|
||||
function base64DecToArr (sBase64, nBlocksSize) {
|
||||
|
||||
var
|
||||
sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length,
|
||||
nOutLen = nBlocksSize ? Math.ceil((nInLen * 3 + 1 >> 2) / nBlocksSize) * nBlocksSize : nInLen * 3 + 1 >> 2, taBytes = new Uint8Array(nOutLen);
|
||||
|
||||
for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
|
||||
nMod4 = nInIdx & 3;
|
||||
nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 6 * (3 - nMod4);
|
||||
if (nMod4 === 3 || nInLen - nInIdx === 1) {
|
||||
for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
|
||||
taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
|
||||
}
|
||||
nUint24 = 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return taBytes;
|
||||
}
|
||||
|
||||
/* Base64 string to array encoding */
|
||||
|
||||
function uint6ToB64 (nUint6) {
|
||||
|
||||
return nUint6 < 26 ?
|
||||
nUint6 + 65
|
||||
: nUint6 < 52 ?
|
||||
nUint6 + 71
|
||||
: nUint6 < 62 ?
|
||||
nUint6 - 4
|
||||
: nUint6 === 62 ?
|
||||
43
|
||||
: nUint6 === 63 ?
|
||||
47
|
||||
:
|
||||
65;
|
||||
|
||||
}
|
||||
|
||||
function base64EncArr (aBytes, delim) {
|
||||
|
||||
var nMod3 = 2, sB64Enc = "";
|
||||
|
||||
for (var nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) {
|
||||
nMod3 = nIdx % 3;
|
||||
if (delim) {
|
||||
if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) {
|
||||
sB64Enc += "\r\n";
|
||||
}
|
||||
}
|
||||
nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24);
|
||||
if (nMod3 === 2 || aBytes.length - nIdx === 1) {
|
||||
sB64Enc += String.fromCharCode(uint6ToB64(nUint24 >>> 18 & 63), uint6ToB64(nUint24 >>> 12 & 63), uint6ToB64(nUint24 >>> 6 & 63), uint6ToB64(nUint24 & 63));
|
||||
nUint24 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return sB64Enc.substr(0, sB64Enc.length - 2 + nMod3) + (nMod3 === 2 ? '' : nMod3 === 1 ? '=' : '==');
|
||||
|
||||
}
|
||||
|
||||
/* UTF-8 array to DOMString and vice versa */
|
||||
|
||||
function UTF8ArrToStr (aBytes) {
|
||||
|
||||
var sView = "";
|
||||
|
||||
for (var nPart, nLen = aBytes.length, nIdx = 0; nIdx < nLen; nIdx++) {
|
||||
nPart = aBytes[nIdx];
|
||||
sView += String.fromCharCode(
|
||||
nPart > 251 && nPart < 254 && nIdx + 5 < nLen ? /* six bytes */
|
||||
/* (nPart - 252 << 30) may be not so safe in ECMAScript! So...: */
|
||||
(nPart - 252) * 1073741824 + (aBytes[++nIdx] - 128 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
|
||||
: nPart > 247 && nPart < 252 && nIdx + 4 < nLen ? /* five bytes */
|
||||
(nPart - 248 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
|
||||
: nPart > 239 && nPart < 248 && nIdx + 3 < nLen ? /* four bytes */
|
||||
(nPart - 240 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
|
||||
: nPart > 223 && nPart < 240 && nIdx + 2 < nLen ? /* three bytes */
|
||||
(nPart - 224 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
|
||||
: nPart > 191 && nPart < 224 && nIdx + 1 < nLen ? /* two bytes */
|
||||
(nPart - 192 << 6) + aBytes[++nIdx] - 128
|
||||
: /* nPart < 127 ? */ /* one byte */
|
||||
nPart
|
||||
);
|
||||
}
|
||||
|
||||
return sView;
|
||||
|
||||
}
|
||||
|
||||
function strToUTF8Arr (sDOMStr) {
|
||||
|
||||
var aBytes, nChr, nStrLen = sDOMStr.length, nArrLen = 0;
|
||||
|
||||
/* mapping... */
|
||||
|
||||
for (var nMapIdx = 0; nMapIdx < nStrLen; nMapIdx++) {
|
||||
nChr = sDOMStr.charCodeAt(nMapIdx);
|
||||
nArrLen += nChr < 0x80 ? 1 : nChr < 0x800 ? 2 : nChr < 0x10000 ? 3 : nChr < 0x200000 ? 4 : nChr < 0x4000000 ? 5 : 6;
|
||||
}
|
||||
|
||||
aBytes = new Uint8Array(nArrLen);
|
||||
|
||||
/* transcription... */
|
||||
|
||||
for (var nIdx = 0, nChrIdx = 0; nIdx < nArrLen; nChrIdx++) {
|
||||
nChr = sDOMStr.charCodeAt(nChrIdx);
|
||||
if (nChr < 128) {
|
||||
/* one byte */
|
||||
aBytes[nIdx++] = nChr;
|
||||
} else if (nChr < 0x800) {
|
||||
/* two bytes */
|
||||
aBytes[nIdx++] = 192 + (nChr >>> 6);
|
||||
aBytes[nIdx++] = 128 + (nChr & 63);
|
||||
} else if (nChr < 0x10000) {
|
||||
/* three bytes */
|
||||
aBytes[nIdx++] = 224 + (nChr >>> 12);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr & 63);
|
||||
} else if (nChr < 0x200000) {
|
||||
/* four bytes */
|
||||
aBytes[nIdx++] = 240 + (nChr >>> 18);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 12 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr & 63);
|
||||
} else if (nChr < 0x4000000) {
|
||||
/* five bytes */
|
||||
aBytes[nIdx++] = 248 + (nChr >>> 24);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 18 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 12 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr & 63);
|
||||
} else /* if (nChr <= 0x7fffffff) */ {
|
||||
/* six bytes */
|
||||
aBytes[nIdx++] = 252 + (nChr >>> 30);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 24 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 18 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 12 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr & 63);
|
||||
}
|
||||
}
|
||||
|
||||
return aBytes;
|
||||
|
||||
}
|
||||
|
||||
// helpers, not generally useful
|
||||
Unibabel.uint6ToB64 = uint6ToB64;
|
||||
Unibabel.b64ToUint6 = b64ToUint6;
|
||||
|
||||
/* Base64 <--> TypedArray <--> UTF-8 */
|
||||
|
||||
// TypedArray <--> UTF-8
|
||||
Unibabel.strToUtf8Arr = strToUTF8Arr;
|
||||
Unibabel.utf8ArrToStr = UTF8ArrToStr;
|
||||
// TypedArray <--> Base64
|
||||
Unibabel.arrToBase64 = base64EncArr;
|
||||
Unibabel.base64ToArr = base64DecToArr;
|
||||
|
||||
if ('undefined' !== typeof module) {
|
||||
module.exports = exports = Unibabel;
|
||||
}
|
||||
|
||||
exports.Unibabel = Unibabel;
|
||||
}('undefined' !== typeof window ? window : exports));
|
266
index.js
266
index.js
@ -1,194 +1,104 @@
|
||||
(function (exports) {
|
||||
"use strict";
|
||||
var Unibabel = {};
|
||||
'use strict';
|
||||
|
||||
/*\
|
||||
|*|
|
||||
|*| Base64 / binary data / UTF-8 strings utilities
|
||||
|*|
|
||||
|*| https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
|
||||
|*|
|
||||
\*/
|
||||
|
||||
/* Array of bytes to base64 string decoding */
|
||||
|
||||
function b64ToUint6 (nChr) {
|
||||
|
||||
return nChr > 64 && nChr < 91 ?
|
||||
nChr - 65
|
||||
: nChr > 96 && nChr < 123 ?
|
||||
nChr - 71
|
||||
: nChr > 47 && nChr < 58 ?
|
||||
nChr + 4
|
||||
: nChr === 43 ?
|
||||
62
|
||||
: nChr === 47 ?
|
||||
63
|
||||
:
|
||||
0;
|
||||
function utf8ToBinaryString(str) {
|
||||
var escstr = encodeURIComponent(str);
|
||||
// replaces any uri escape sequence, such as %0A,
|
||||
// with binary escape, such as 0x0A
|
||||
var binstr = escstr.replace(/%([0-9A-F]{2})/g, function(match, p1) {
|
||||
return String.fromCharCode(parseInt(p1, 16));
|
||||
});
|
||||
|
||||
return binstr;
|
||||
}
|
||||
|
||||
function base64DecToArr (sBase64, nBlocksSize) {
|
||||
function utf8ToBuffer(str) {
|
||||
var binstr = utf8ToBinaryString(str);
|
||||
var buf = binaryStringToBuffer(binstr);
|
||||
return buf;
|
||||
}
|
||||
|
||||
var
|
||||
sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length,
|
||||
nOutLen = nBlocksSize ? Math.ceil((nInLen * 3 + 1 >> 2) / nBlocksSize) * nBlocksSize : nInLen * 3 + 1 >> 2, taBytes = new Uint8Array(nOutLen);
|
||||
|
||||
for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
|
||||
nMod4 = nInIdx & 3;
|
||||
nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 6 * (3 - nMod4);
|
||||
if (nMod4 === 3 || nInLen - nInIdx === 1) {
|
||||
for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
|
||||
taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
|
||||
}
|
||||
nUint24 = 0;
|
||||
function utf8ToBase64(str) {
|
||||
var binstr = utf8ToBinaryString(str);
|
||||
return btoa(binstr);
|
||||
}
|
||||
|
||||
function binaryStringToUtf8(binstr) {
|
||||
var escstr = binstr.replace(/(.)/g, function (m, p) {
|
||||
var code = p.charCodeAt(0).toString(16).toUpperCase();
|
||||
if (code.length < 2) {
|
||||
code = '0' + code;
|
||||
}
|
||||
return '%' + code;
|
||||
});
|
||||
|
||||
return decodeURIComponent(escstr);
|
||||
}
|
||||
|
||||
function bufferToUtf8(buf) {
|
||||
var binstr = bufferToBinaryString(buf);
|
||||
|
||||
return binaryStringToUtf8(binstr);
|
||||
}
|
||||
|
||||
function base64ToUtf8(b64) {
|
||||
var binstr = atob(b64);
|
||||
|
||||
return binaryStringToUtf8(binstr);
|
||||
}
|
||||
|
||||
function bufferToBinaryString(buf) {
|
||||
var binstr = Array.prototype.map.call(buf, function (ch) {
|
||||
return String.fromCharCode(ch);
|
||||
}).join('');
|
||||
|
||||
return binstr;
|
||||
}
|
||||
|
||||
function bufferToBase64(arr) {
|
||||
var binstr = bufferToBinaryString(arr);
|
||||
return btoa(binstr);
|
||||
}
|
||||
|
||||
function binaryStringToBuffer(binstr) {
|
||||
var buf;
|
||||
|
||||
if ('undefined' !== typeof Uint8Array) {
|
||||
buf = new Uint8Array(binstr.length);
|
||||
} else {
|
||||
buf = [];
|
||||
}
|
||||
|
||||
return taBytes;
|
||||
Array.prototype.forEach.call(binstr, function (ch, i) {
|
||||
buf[i] = ch.charCodeAt(0);
|
||||
});
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Base64 string to array encoding */
|
||||
|
||||
function uint6ToB64 (nUint6) {
|
||||
|
||||
return nUint6 < 26 ?
|
||||
nUint6 + 65
|
||||
: nUint6 < 52 ?
|
||||
nUint6 + 71
|
||||
: nUint6 < 62 ?
|
||||
nUint6 - 4
|
||||
: nUint6 === 62 ?
|
||||
43
|
||||
: nUint6 === 63 ?
|
||||
47
|
||||
:
|
||||
65;
|
||||
|
||||
function base64ToBuffer(base64) {
|
||||
var binstr = atob(base64);
|
||||
var buf = binaryStringToBuffer(binstr);
|
||||
return buf;
|
||||
}
|
||||
|
||||
function base64EncArr (aBytes) {
|
||||
exports.Unibabel = {
|
||||
utf8ToBinaryString: utf8ToBinaryString
|
||||
, utf8ToBuffer: utf8ToBuffer
|
||||
, utf8ToBase64: utf8ToBase64
|
||||
, binaryStringToUtf8: binaryStringToUtf8
|
||||
, bufferToUtf8: bufferToUtf8
|
||||
, base64ToUtf8: base64ToUtf8
|
||||
, bufferToBinaryString: bufferToBinaryString
|
||||
, bufferToBase64: bufferToBase64
|
||||
, binaryStringToBuffer: binaryStringToBuffer
|
||||
, base64ToBuffer: base64ToBuffer
|
||||
|
||||
var nMod3 = 2, sB64Enc = "";
|
||||
// compat
|
||||
, strToUtf8Arr: utf8ToBuffer
|
||||
, utf8ArrToStr: bufferToUtf8
|
||||
, arrToBase64: bufferToBase64
|
||||
, base64ToArr: base64ToBuffer
|
||||
};
|
||||
|
||||
for (var nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) {
|
||||
nMod3 = nIdx % 3;
|
||||
if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) { sB64Enc += "\r\n"; }
|
||||
nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24);
|
||||
if (nMod3 === 2 || aBytes.length - nIdx === 1) {
|
||||
sB64Enc += String.fromCharCode(uint6ToB64(nUint24 >>> 18 & 63), uint6ToB64(nUint24 >>> 12 & 63), uint6ToB64(nUint24 >>> 6 & 63), uint6ToB64(nUint24 & 63));
|
||||
nUint24 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return sB64Enc.substr(0, sB64Enc.length - 2 + nMod3) + (nMod3 === 2 ? '' : nMod3 === 1 ? '=' : '==');
|
||||
|
||||
}
|
||||
|
||||
/* UTF-8 array to DOMString and vice versa */
|
||||
|
||||
function UTF8ArrToStr (aBytes) {
|
||||
|
||||
var sView = "";
|
||||
|
||||
for (var nPart, nLen = aBytes.length, nIdx = 0; nIdx < nLen; nIdx++) {
|
||||
nPart = aBytes[nIdx];
|
||||
sView += String.fromCharCode(
|
||||
nPart > 251 && nPart < 254 && nIdx + 5 < nLen ? /* six bytes */
|
||||
/* (nPart - 252 << 30) may be not so safe in ECMAScript! So...: */
|
||||
(nPart - 252) * 1073741824 + (aBytes[++nIdx] - 128 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
|
||||
: nPart > 247 && nPart < 252 && nIdx + 4 < nLen ? /* five bytes */
|
||||
(nPart - 248 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
|
||||
: nPart > 239 && nPart < 248 && nIdx + 3 < nLen ? /* four bytes */
|
||||
(nPart - 240 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
|
||||
: nPart > 223 && nPart < 240 && nIdx + 2 < nLen ? /* three bytes */
|
||||
(nPart - 224 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
|
||||
: nPart > 191 && nPart < 224 && nIdx + 1 < nLen ? /* two bytes */
|
||||
(nPart - 192 << 6) + aBytes[++nIdx] - 128
|
||||
: /* nPart < 127 ? */ /* one byte */
|
||||
nPart
|
||||
);
|
||||
}
|
||||
|
||||
return sView;
|
||||
|
||||
}
|
||||
|
||||
function strToUTF8Arr (sDOMStr) {
|
||||
|
||||
var aBytes, nChr, nStrLen = sDOMStr.length, nArrLen = 0;
|
||||
|
||||
/* mapping... */
|
||||
|
||||
for (var nMapIdx = 0; nMapIdx < nStrLen; nMapIdx++) {
|
||||
nChr = sDOMStr.charCodeAt(nMapIdx);
|
||||
nArrLen += nChr < 0x80 ? 1 : nChr < 0x800 ? 2 : nChr < 0x10000 ? 3 : nChr < 0x200000 ? 4 : nChr < 0x4000000 ? 5 : 6;
|
||||
}
|
||||
|
||||
aBytes = new Uint8Array(nArrLen);
|
||||
|
||||
/* transcription... */
|
||||
|
||||
for (var nIdx = 0, nChrIdx = 0; nIdx < nArrLen; nChrIdx++) {
|
||||
nChr = sDOMStr.charCodeAt(nChrIdx);
|
||||
if (nChr < 128) {
|
||||
/* one byte */
|
||||
aBytes[nIdx++] = nChr;
|
||||
} else if (nChr < 0x800) {
|
||||
/* two bytes */
|
||||
aBytes[nIdx++] = 192 + (nChr >>> 6);
|
||||
aBytes[nIdx++] = 128 + (nChr & 63);
|
||||
} else if (nChr < 0x10000) {
|
||||
/* three bytes */
|
||||
aBytes[nIdx++] = 224 + (nChr >>> 12);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr & 63);
|
||||
} else if (nChr < 0x200000) {
|
||||
/* four bytes */
|
||||
aBytes[nIdx++] = 240 + (nChr >>> 18);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 12 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr & 63);
|
||||
} else if (nChr < 0x4000000) {
|
||||
/* five bytes */
|
||||
aBytes[nIdx++] = 248 + (nChr >>> 24);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 18 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 12 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr & 63);
|
||||
} else /* if (nChr <= 0x7fffffff) */ {
|
||||
/* six bytes */
|
||||
aBytes[nIdx++] = 252 + (nChr >>> 30);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 24 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 18 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 12 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
|
||||
aBytes[nIdx++] = 128 + (nChr & 63);
|
||||
}
|
||||
}
|
||||
|
||||
return aBytes;
|
||||
|
||||
}
|
||||
|
||||
// helpers, not generally useful
|
||||
Unibabel.uint6ToB64 = uint6ToB64;
|
||||
Unibabel.b64ToUint6 = b64ToUint6;
|
||||
|
||||
/* Base64 <--> TypedArray <--> UTF-8 */
|
||||
|
||||
// TypedArray <--> UTF-8
|
||||
Unibabel.strToUtf8Arr = strToUTF8Arr;
|
||||
Unibabel.Utf8ArrToStr = UTF8ArrToStr;
|
||||
// TypedArray <--> Base64
|
||||
Unibabel.base64ToArr = base64EncArr;
|
||||
Unibabel.arrToBase64 = base64DecToArr;
|
||||
|
||||
if ('undefined' !== typeof module) {
|
||||
module.exports = exports = Unibabel;
|
||||
}
|
||||
|
||||
exports.Unibabel = Unibabel;
|
||||
}('undefined' !== typeof window ? window : exports));
|
||||
}('undefined' !== typeof exports && exports || 'undefined' !== typeof window && window || global));
|
||||
|
19
node.js
Normal file
19
node.js
Normal file
@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
console.warn("Please don't use Unibabel in node.js. If you think you really think you have a valid use case please report it at https://git.coolaj86.com/coolaj86/unibabel.js/issues/new");
|
||||
throw new Error("[unibabel] you're doing it wrong");
|
||||
|
||||
/*
|
||||
var data = 'I ½ ♥ 💩';
|
||||
var encoding = 'utf8';
|
||||
var buf = new Buffer(data, encoding);
|
||||
buf.toString('hex');
|
||||
buf.toString('base64');
|
||||
buf.toString('ascii');
|
||||
buf.toString('utf8');
|
||||
buf.toString('binary'); // deprecated, do not use
|
||||
|
||||
var Base32 = require('thirty-two');
|
||||
var b32 = Base32.encode(buf);
|
||||
Base32.decode(buf);
|
||||
*/
|
37
package.json
Normal file
37
package.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "unibabel",
|
||||
"version": "2.1.8",
|
||||
"description": "Base64, TypedArrays, and UTF-8 / Unicode conversions in Browser (and Node) JavaScript",
|
||||
"main": "node.js",
|
||||
"browser": {
|
||||
"./node.js": "./index.js"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.coolaj86.com/coolaj86/unibabel.js.git"
|
||||
},
|
||||
"keywords": [
|
||||
"ascii",
|
||||
"binary",
|
||||
"utf8",
|
||||
"utf-8",
|
||||
"ArrayBuffer",
|
||||
"TypedArrays",
|
||||
"TypedArray",
|
||||
"Uint",
|
||||
"Uint8Array",
|
||||
"Base64",
|
||||
"b64",
|
||||
"Base32",
|
||||
"b32"
|
||||
],
|
||||
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
|
||||
"license": "(MIT OR Apache-2.0)",
|
||||
"bugs": {
|
||||
"url": "https://git.coolaj86.com/coolaj86/unibabel.js/issues"
|
||||
},
|
||||
"homepage": "https://git.coolaj86.com/coolaj86/unibabel.js#readme"
|
||||
}
|
142
unibabel.base32.js
Normal file
142
unibabel.base32.js
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
Copyright (c) 2011, Chris Umbel
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
(function (exports) {
|
||||
'use strict';
|
||||
|
||||
var charTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
var byteTable = [
|
||||
0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
||||
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
||||
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
|
||||
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
||||
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
||||
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
|
||||
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
];
|
||||
|
||||
function quintetCount(buff) {
|
||||
var quintets = Math.floor(buff.length / 5);
|
||||
return buff.length % 5 === 0 ? quintets: quintets + 1;
|
||||
}
|
||||
|
||||
exports.bufferToBase32 = function(plain) {
|
||||
// plain MUST come in either as Array or Uint8Array
|
||||
if('undefined' !== typeof Uint8Array) {
|
||||
if (!(plain instanceof Uint8Array)){
|
||||
plain = new Uint8Array(plain);
|
||||
}
|
||||
}
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
var shiftIndex = 0;
|
||||
var digit = 0;
|
||||
var encoded = new Array(quintetCount(plain) * 8);
|
||||
|
||||
/* byte by byte isn't as pretty as quintet by quintet but tests a bit
|
||||
faster. will have to revisit. */
|
||||
while(i < plain.length) {
|
||||
var current = plain[i];
|
||||
|
||||
if(shiftIndex > 3) {
|
||||
digit = current & (0xff >> shiftIndex);
|
||||
shiftIndex = (shiftIndex + 5) % 8;
|
||||
digit = (digit << shiftIndex) | ((i + 1 < plain.length) ?
|
||||
plain[i + 1] : 0) >> (8 - shiftIndex);
|
||||
i++;
|
||||
} else {
|
||||
digit = (current >> (8 - (shiftIndex + 5))) & 0x1f;
|
||||
shiftIndex = (shiftIndex + 5) % 8;
|
||||
if(shiftIndex === 0) { i++; }
|
||||
}
|
||||
|
||||
encoded[j] = charTable[digit];
|
||||
j++;
|
||||
}
|
||||
|
||||
for(i = j; i < encoded.length; i++) {
|
||||
encoded[i] = '=';
|
||||
}
|
||||
|
||||
return encoded.join('');
|
||||
};
|
||||
|
||||
exports.base32ToBuffer = function(encoded) {
|
||||
var shiftIndex = 0;
|
||||
var plainDigit = 0;
|
||||
var plainChar;
|
||||
var plainPos = 0;
|
||||
var len = Math.ceil(encoded.length * 5 / 8);
|
||||
var decoded;
|
||||
encoded = encoded.split('').map(function (ch) {
|
||||
return ch.charCodeAt(0);
|
||||
});
|
||||
if('undefined' !== typeof Uint8Array) {
|
||||
encoded = new Uint8Array(encoded);
|
||||
decoded = new Uint8Array(len);
|
||||
} else {
|
||||
decoded = new Array(len);
|
||||
}
|
||||
|
||||
/* byte by byte isn't as pretty as octet by octet but tests a bit
|
||||
faster. will have to revisit. */
|
||||
for(var i = 0; i < encoded.length; i++) {
|
||||
if(encoded[i] === 0x3d){ //'='
|
||||
break;
|
||||
}
|
||||
|
||||
var encodedByte = encoded[i] - 0x30;
|
||||
|
||||
if(encodedByte < byteTable.length) {
|
||||
plainDigit = byteTable[encodedByte];
|
||||
|
||||
if(shiftIndex <= 3) {
|
||||
shiftIndex = (shiftIndex + 5) % 8;
|
||||
|
||||
if(shiftIndex === 0) {
|
||||
plainChar |= plainDigit;
|
||||
decoded[plainPos] = plainChar;
|
||||
plainPos++;
|
||||
plainChar = 0;
|
||||
} else {
|
||||
plainChar |= 0xff & (plainDigit << (8 - shiftIndex));
|
||||
}
|
||||
} else {
|
||||
shiftIndex = (shiftIndex + 5) % 8;
|
||||
plainChar |= 0xff & (plainDigit >>> shiftIndex);
|
||||
decoded[plainPos] = plainChar;
|
||||
plainPos++;
|
||||
|
||||
plainChar = 0xff & (plainDigit << (8 - shiftIndex));
|
||||
}
|
||||
} else {
|
||||
throw new Error('Invalid input - it is not base32 encoded string');
|
||||
}
|
||||
}
|
||||
|
||||
if (decoded.slice) { // Array or TypedArray
|
||||
return decoded.slice(0, plainPos);
|
||||
} else { // Mobile Safari TypedArray
|
||||
return new Uint8Array(Array.prototype.slice.call(decoded, 0, plainPos));
|
||||
}
|
||||
};
|
||||
|
||||
}(window.Unibabel || window));
|
46
unibabel.hex.js
Normal file
46
unibabel.hex.js
Normal file
@ -0,0 +1,46 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function bufferToHex(arr) {
|
||||
var i;
|
||||
var len;
|
||||
var hex = '';
|
||||
var c;
|
||||
|
||||
for (i = 0, len = arr.length; i < len; i += 1) {
|
||||
c = arr[i].toString(16);
|
||||
if (c.length < 2) {
|
||||
c = '0' + c;
|
||||
}
|
||||
hex += c;
|
||||
}
|
||||
|
||||
return hex;
|
||||
}
|
||||
|
||||
function hexToBuffer(hex) {
|
||||
// TODO use Uint8Array or ArrayBuffer or DataView
|
||||
var i;
|
||||
var byteLen = hex.length / 2;
|
||||
var arr;
|
||||
var j = 0;
|
||||
|
||||
if (byteLen !== parseInt(byteLen, 10)) {
|
||||
throw new Error("Invalid hex length '" + hex.length + "'");
|
||||
}
|
||||
|
||||
arr = new Uint8Array(byteLen);
|
||||
|
||||
for (i = 0; i < byteLen; i += 1) {
|
||||
arr[i] = parseInt(hex[j] + hex[j + 1], 16);
|
||||
j += 2;
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
// Hex Convenience Functions
|
||||
window.Unibabel.hexToBuffer = hexToBuffer;
|
||||
window.Unibabel.bufferToHex = bufferToHex;
|
||||
|
||||
}());
|
Loading…
x
Reference in New Issue
Block a user