Comparing version 0.1.3 to 1.0.0
@@ -1,10 +0,27 @@ | ||
var stream = require('stream'); | ||
var alphabets = require('./alphabets'); | ||
var ENC_START = '<~'; | ||
var ENC_END = '~>'; | ||
var NUM_MAXVALUE = Math.pow(2, 32) - 1; | ||
var QUAD85 = 85 * 85 * 85 * 85; | ||
var TRIO85 = 85 * 85 * 85; | ||
var DUO85 = 85 * 85; | ||
var SING85 = 85; | ||
function encode_buffer(buffer) | ||
var DEFAULT_ENCODING = 'z85'; | ||
/* Characters to allow (and ignore) in an encoded buffer */ | ||
var IGNORE_CHARS = [ | ||
0x09, /* horizontal tab */ | ||
0x0a, /* line feed, new line */ | ||
0x0b, /* vertical tab */ | ||
0x0c, /* form feed, new page */ | ||
0x0d, /* carriage return */ | ||
0x20 /* space */ | ||
]; | ||
var ASCII85_ENC_START = '<~'; | ||
var ASCII85_ENC_END = '~>'; | ||
function encode_buffer(buffer, encoding) | ||
{ | ||
var enctable = alphabets[encoding].enc; | ||
var padding = (buffer.length % 4 === 0) ? 0 : 4 - buffer.length % 4; | ||
@@ -21,7 +38,6 @@ | ||
/* Create 5 characters from '!' to 'u' alphabet */ | ||
var block = []; | ||
for (var j = 0; j < 5; ++j) { | ||
block.unshift(String.fromCharCode(num % 85 + 33)); | ||
block.unshift(enctable[num % 85]); | ||
num = Math.floor(num / 85); | ||
@@ -34,21 +50,25 @@ } | ||
return ENC_START + result.substring(0, result.length - padding) + ENC_END; | ||
return (('ascii85' === encoding) ? ASCII85_ENC_START : '') + | ||
result.substring(0, result.length - padding) + | ||
(('ascii85' === encoding) ? ASCII85_ENC_END : ''); | ||
} | ||
function encode_string(string) | ||
function encode_string(string, encoding) | ||
{ | ||
var buffer = new Buffer(string, 'utf8'); // utf8 at all times? | ||
return encode_buffer(buffer); | ||
return encode_buffer(buffer, encoding); | ||
} | ||
function decode_buffer(buffer) | ||
function decode_buffer(buffer, encoding) | ||
{ | ||
if (buffer.length < 4) { | ||
return false; | ||
var dectable = alphabets[encoding].dec; | ||
var dataLength = buffer.length; | ||
if ('ascii85' === encoding) { | ||
dataLength -= (ASCII85_ENC_START.length + ASCII85_ENC_END.length); | ||
} | ||
var dataLength = buffer.length - ENC_START.length - ENC_END.length; | ||
var padding = (dataLength % 5 === 0) ? 0 : 5 - dataLength % 5; | ||
var bufferStart = ENC_START.length; | ||
var bufferStart = ('ascii85' === encoding) ? ASCII85_ENC_START.length : 0; | ||
var bufferEnd = bufferStart + dataLength; | ||
@@ -60,3 +80,3 @@ | ||
if (index < bufferEnd) | ||
while (-1 !== [0x0a, 0x20, 0x0d, 0x09, 0x0b, 0x0c].indexOf(buffer[index])) { | ||
while (-1 !== IGNORE_CHARS.indexOf(buffer[index])) { | ||
padding = (padding + 1) % 5; | ||
@@ -73,15 +93,15 @@ index++; // skip newline character | ||
i = nextValidByte(i); | ||
num = ((buffer[i] - 33) * 85 * 85 * 85 * 85); | ||
num = (dectable[buffer[i]]) * QUAD85; | ||
i = nextValidByte(i + 1); | ||
num += ((i >= bufferEnd ? 84 : (buffer[i] - 33)) * 85 * 85 * 85); | ||
num += (i >= bufferEnd ? 84 : dectable[buffer[i]]) * TRIO85; | ||
i = nextValidByte(i + 1); | ||
num += ((i >= bufferEnd ? 84 : (buffer[i] - 33)) * 85 * 85); | ||
num += (i >= bufferEnd ? 84 : dectable[buffer[i]]) * DUO85; | ||
i = nextValidByte(i + 1); | ||
num += ((i >= bufferEnd ? 84 : (buffer[i] - 33)) * 85); | ||
num += (i >= bufferEnd ? 84 : dectable[buffer[i]]) * SING85; | ||
i = nextValidByte(i + 1); | ||
num += ((i >= bufferEnd ? 84 : (buffer[i] - 33))); | ||
num += (i >= bufferEnd ? 84 : dectable[buffer[i]]); | ||
@@ -102,15 +122,20 @@ i = nextValidByte(i + 1); | ||
function decode_string(string) | ||
function decode_string(string, encoding) | ||
{ | ||
var buffer = new Buffer(string, 'utf8'); // utf8 at all times? | ||
return decode_buffer(buffer); | ||
return decode_buffer(buffer, encoding); | ||
} | ||
module.exports = { | ||
encode : function(data) { | ||
encode : function(data, encoding) { | ||
var encoding = encoding || DEFAULT_ENCODING; | ||
if (-1 === [ 'ascii85', 'z85' ].indexOf(encoding)) { | ||
return false; | ||
} | ||
if (data instanceof Buffer) | ||
return encode_buffer(data); | ||
return encode_buffer(data, encoding); | ||
if (typeof data === 'string') | ||
return encode_string(data); | ||
return encode_string(data, encoding); | ||
@@ -120,8 +145,13 @@ return false; | ||
decode : function(data) { | ||
decode : function(data, encoding) { | ||
var encoding = encoding || DEFAULT_ENCODING; | ||
if (-1 === [ 'ascii85', 'z85' ].indexOf(encoding)) { | ||
return false; | ||
} | ||
if (data instanceof Buffer) | ||
return decode_buffer(data); | ||
return decode_buffer(data, encoding); | ||
if (typeof data === 'string') | ||
return decode_string(data); | ||
return decode_string(data, encoding); | ||
@@ -128,0 +158,0 @@ return false; |
{ | ||
"name": "base85", | ||
"version": "0.1.3", | ||
"version": "1.0.0", | ||
"description": "Base85 (Ascii85) encode and decode functionality", | ||
@@ -5,0 +5,0 @@ "main": "lib/base85.js", |
@@ -8,6 +8,12 @@ [![Build Status](https://travis-ci.org/noseglid/base85.png?branch=master)](https://travis-ci.org/noseglid/base85) | ||
alphabet includes characters that might not be as friendly as the base64 alphabet. | ||
While it's still only printable characters (ASCII 33 '!' to ASCII 117 'u'), it contains | ||
quotes, both ' and " and other characters which might appear problematic in some | ||
applications. | ||
While it's still only printable characters, the [Ascii85][Base85] specification contains | ||
quotes (`'` and `"`) which needs escaping in many programming languages, | ||
and the [ZeroMQ][Base85ZeroMQ] specification contains `<` and `>` which need escaping | ||
in most (all?) [SGML][SGML] languages. | ||
Supported encoding specifications | ||
* [Ascii85][Base85] | ||
* [ZeroMQ][Base85ZeroMQ] | ||
## Installation | ||
@@ -23,35 +29,43 @@ | ||
var base85 = require('base85'); | ||
console.log(base85.encode('Hello, world!')); | ||
console.log(base85.encode('Hello, world!')); // 'nm=QNz.92Pz/PV8aP' | ||
console.log(base85.encode('Hello, world!', 'ascii85')); // ' <~87cURD_*#TDfTZ)+T~>' | ||
Output: `<~87cURD_*#TDfTZ)+T~>` | ||
For decoding: | ||
var base85 = require('base85'); | ||
var decoded = base85.decode('<~@;Ka&GAhM;+CT.u+Du*?E,8s.+DkP&ATJu/@:O\'q@3B*\'Cht5\'Dg;~>'); | ||
console.log(decoded.toString('ascii')); | ||
var decoded = base85.decode('vqG:5Cw?IqayPd#az#9uAbn%daz>L5wPF#evpK6}vix96y?$k6z*q'); | ||
console.log(decoded.toString('utf8')); // 'all work and no play makes jack a dull boy' | ||
Output: `all work and no play makes jack a dull boy` | ||
## Bugs | ||
Doesn't support the z-abbreviation as for now. | ||
Doesn't support the z-abbreviation for [Ascii85][Base85]. This means that data encoded with this | ||
support will cause the library to return false. An all-zero input buffer will be encoded | ||
as `<~!!!!!~>`, rather than `<~z~>` | ||
Doesn't support [IPv6 encoding specification (RFC1924)][Base85IPv6] for now. This baby requires | ||
requires 128-bit arithmetic, which is rather problematic. I'm thrilled to see that the author | ||
of the RFC took this in consideration, specifically - quote from the [RFC][Base85IPv6]: "This is not | ||
considered a serious drawback in the representation, but a flaw of the processor designs." | ||
Silly processor designers. | ||
## API | ||
### `encode(data)` | ||
### `encode(data[, encoding])` | ||
> _Encodes the specified data. The encoded data will be prepended | ||
> with `<~` and appended with `~>`. This is actually following Adobes version | ||
> which seems to be the common practice for base85._ | ||
> _Encodes the specified data. If encoding is `ascii85`, the encoded data will be prepended | ||
> with `<~` and appended with `~>`._ | ||
> | ||
> **data** The data to encode, may be a `String` or a [Buffer][NodeBuffer]. | ||
> | ||
> **encoding** Which specification to use when encoding `data`. May be either | ||
> `ascii85` ([Adobe][Base85]) or `z85` ([ZeroMQ][Base85ZeroMQ]). | ||
> Default is `z85`. | ||
> | ||
> **returns** A `String` with the encoded data. | ||
### `decode(data)` | ||
### `decode(data[, encoding])` | ||
> _Decodes the specified data. The data is expected to start with `<~` and | ||
> and end with `~>`. No checks are actually made for this, but output will | ||
> be unexpected if this is not the case._ | ||
> _Decodes the specified data. If encoding is `ascii85`, the data is expected | ||
> to start with `<~` and and end with `~>`. No checks are actually made for | ||
> this, but output will be unexpected if this is not the case._ | ||
> | ||
@@ -65,4 +79,8 @@ > _A buffer is always returned as data may not be representable in a string. | ||
> | ||
> **returns** A [Buffer][NodeBuffer] With the decoded data. | ||
> **encoding** Which specification `data` is encoded with. May be either | ||
> `ascii85` ([Adobe][Base85]) or `z85` ([ZeroMQ][Base85ZeroMQ]). | ||
> Default is `z85`. | ||
> | ||
> **returns** A [Buffer][NodeBuffer] With the decoded data, or **boolean** `false` if the buffer could not be decoded. When testing if the result succeeded, [always use operators with 3 characters][JSCompare] ('===' or '!==='). | ||
> | ||
@@ -73,2 +91,5 @@ [Base64]: http://en.wikipedia.org/wiki/Base64 | ||
[NodeBufferToString]: http://nodejs.org/api/buffer.html#buffer_buf_tostring_encoding_start_end | ||
[Base85ZeroMQ]: http://rfc.zeromq.org/spec:32 | ||
[Base85IPv6]: http://tools.ietf.org/html/rfc1924 | ||
[JSCompare]: http://stackoverflow.com/questions/359494/does-it-matter-which-equals-operator-vs-i-use-in-javascript-comparisons | ||
[SGML]: https://en.wikipedia.org/wiki/Standard_Generalized_Markup_Language |
exports.data = [ | ||
{ | ||
'raw' : new Buffer('Man ', 'ascii'), | ||
'enc' : '<~9jqo^~>' | ||
'enc' : { | ||
'ascii85' : '<~9jqo^~>', | ||
'z85' : 'o<}]Z' | ||
} | ||
}, | ||
{ | ||
'raw' : new Buffer('Man a', 'ascii'), | ||
'enc' : '<~9jqo^@/~>' | ||
'enc' : { | ||
'ascii85' : '<~9jqo^@/~>', | ||
'z85': 'o<}]Zve' | ||
} | ||
}, | ||
{ | ||
'raw' : new Buffer('Man ab', 'ascii'), | ||
'enc' : '<~9jqo^@:B~>' | ||
'enc' : { | ||
'ascii85' : '<~9jqo^@:B~>', | ||
'z85': 'o<}]Zvpx', | ||
} | ||
}, | ||
{ | ||
'raw' : new Buffer('Man abc', 'ascii'), | ||
'enc' : '<~9jqo^@:E^~>' | ||
'enc' : { | ||
'ascii85' : '<~9jqo^@:E^~>', | ||
'z85' : 'o<}]ZvpAZ' | ||
} | ||
}, | ||
{ | ||
'raw' : new Buffer('Man abcd', 'ascii'), | ||
'enc' : '<~9jqo^@:E_W~>' | ||
'enc' : { | ||
'ascii85' : '<~9jqo^@:E_W~>', | ||
'z85' : 'o<}]ZvpA.S' | ||
} | ||
}, | ||
{ | ||
'raw' : new Buffer('Hello, world!', 'ascii'), | ||
'enc' : '<~87cURD_*#TDfTZ)+T~>' | ||
'raw' : new Buffer('Hello, world!!!!', 'ascii'), | ||
'enc' : { | ||
'ascii85' : '<~87cURD_*#TDfTZ)+X&!P~>', | ||
'z85' : 'nm=QNz.92Pz/PV8aT50L' | ||
} | ||
}, | ||
{ | ||
'raw' : 'Hello, world!', | ||
'enc' : '<~87cURD_*#TDfTZ)+T~>' | ||
}, | ||
{ | ||
'raw' : new Buffer('', 'ascii'), | ||
'enc' : '<~~>' | ||
'enc' : { | ||
'ascii85' : '<~~>', | ||
'z85' : '' | ||
} | ||
}, | ||
{ | ||
'raw' : new Buffer('Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.', 'ascii'), | ||
'enc' : '<~9jqo^BlbD-BleB1DJ+*+F(f,q/0JhKF<GL>Cj@.4Gp$d7F!,L7@<6@)/0JDEF<G%<+EV:2F!,O<DJ+*.@<*K0@<6L(Df-\\0Ec5e;DffZ(EZee.Bl.9pF"AGXBPCsi+DGm>@3BB/F*&OCAfu2/AKYi(DIb:@FD,*)+C]U=@3BN#EcYf8ATD3s@q?d$AftVqCh[NqF<G:8+EV:.+Cf>-FD5W8ARlolDIal(DId<j@<?3r@:F%a+D58\'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G>uD.RTpAKYo\'+CT/5+Cei#DII?(E,9)oF*2M7/c~>' | ||
'raw' : new Buffer('Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure', 'ascii'), | ||
'enc' : { | ||
'ascii85' : '<~9jqo^BlbD-BleB1DJ+*+F(f,q/0JhKF<GL>Cj@.4Gp$d7F!,L7@<6@)/0JDEF<G%<+EV:2F!,O<DJ+*.@<*K0@<6L(Df-\\0Ec5e;DffZ(EZee.Bl.9pF"AGXBPCsi+DGm>@3BB/F*&OCAfu2/AKYi(DIb:@FD,*)+C]U=@3BN#EcYf8ATD3s@q?d$AftVqCh[NqF<G:8+EV:.+Cf>-FD5W8ARlolDIal(DId<j@<?3r@:F%a+D58\'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G>uD.RTpAKYo\'+CT/5+Cei#DII?(E,9)oF*2M7~>', | ||
'z85' : 'o<}]Zx(+zcx(!xgzFa9aB7/b}efF?GBrCHty<vdjC{3^mB0bHmvrlv8efFzABrC4raARphB0bKrzFa9dvr9GfvrlH7z/cXfA=k!qz//V7AV!!dx(do{B1wCTxLy%&azC)tvixxeB95Kyw/#hewGU&7zE+pvBzb98ayYQsvixJ2A=U/nwPzi%v}u^3w/$R}y?WJ}BrCpnaARpday/tcBzkSnwN(](zE:(7zE^r<vrui@vpB4:azkn6wPzj3x(v(iz!pbczF%-nwN]B+efFIGv}xjZB0bNrwGV5cz/P}xC4Ct#zdNP{wGU]6ayPekay!&2zEEu7Abo8]B9hIm' | ||
} | ||
}, | ||
{ | ||
'raw' : new Buffer([0xff]), | ||
'enc' : '<~rr~>' | ||
'enc' : { | ||
'ascii85' : '<~rr~>', | ||
'z85' : '@@' | ||
} | ||
}, | ||
{ | ||
'raw' : new Buffer([0xff, 0xff, 0xff, 0xff]), | ||
'enc' : '<~s8W-!~>' | ||
'enc' : { | ||
'ascii85' : '<~s8W-!~>', | ||
'z85': '%nSc0' | ||
} | ||
}, | ||
{ | ||
'raw' : new Buffer(' '), | ||
'enc' : '<~+9~>' | ||
'enc' : { | ||
'ascii85' : '<~+9~>', | ||
'z85': 'ao' | ||
} | ||
}, | ||
{ | ||
'raw' : new Buffer([0x0, 0x0, 0x0, 0x0]), | ||
'enc' : { | ||
'ascii85' : '<~!!!!!~>', | ||
'z85' : '00000' | ||
} | ||
} | ||
]; |
@@ -8,5 +8,5 @@ var _ = require('underscore'); | ||
{ | ||
test.equal(base85.decode(1234), false) | ||
test.equal(base85.decode('<~u~>'), false); | ||
test.equal(base85.decode('<~uuuuu~>'), false); | ||
test.equal(base85.decode(1234, 'ascii85'), false) | ||
test.equal(base85.decode('<~u~>', 'ascii85'), false); | ||
test.equal(base85.decode('<~uuuuu~>', 'ascii85'), false); | ||
test.done(); | ||
@@ -17,7 +17,10 @@ } | ||
{ | ||
test.expect(data.length); | ||
var encodings = [ 'ascii85', 'z85' ]; | ||
test.expect(data.length * encodings.length); | ||
_.each(data, function (tc) { | ||
var exp = typeof tc.raw === 'string' ? new Buffer(tc.raw) : tc.raw; | ||
test.deepEqual(base85.decode(tc.enc), exp); | ||
_.each(encodings, function(encoding) { | ||
_.each(data, function (tc) { | ||
var exp = typeof tc.raw === 'string' ? new Buffer(tc.raw) : tc.raw; | ||
test.deepEqual(base85.decode(tc.enc[encoding], encoding), exp); | ||
}); | ||
}); | ||
@@ -30,7 +33,7 @@ | ||
{ | ||
test.deepEqual(base85.decode("<~\n@p\ns7\ntD.3~>"), new Buffer('canumb')); | ||
test.deepEqual(base85.decode("<~\n @ p \ns7 \n t D .3~>"), new Buffer('canumb')); | ||
test.deepEqual(base85.decode("<~\n @ p \ns7 \n t D .3 ~>"), new Buffer('canumb')); | ||
test.deepEqual(base85.decode("<~@ps7tD.3 \n ~>"), new Buffer('canumb')); | ||
test.deepEqual(base85.decode("<~ @ps7tD.3 \n ~>"), new Buffer('canumb')); | ||
test.deepEqual(base85.decode("<~\n@p\ns7\ntD.3~>", 'ascii85'), new Buffer('canumb')); | ||
test.deepEqual(base85.decode("<~\n @ p \ns7 \n t D .3~>", 'ascii85'), new Buffer('canumb')); | ||
test.deepEqual(base85.decode("<~\n @ p \ns7 \n t D .3 ~>", 'ascii85'), new Buffer('canumb')); | ||
test.deepEqual(base85.decode("<~@ps7tD.3 \n ~>", 'ascii85'), new Buffer('canumb')); | ||
test.deepEqual(base85.decode("<~ @ps7tD.3 \n ~>", 'ascii85'), new Buffer('canumb')); | ||
test.done(); | ||
@@ -43,4 +46,4 @@ } | ||
var enc = new Buffer(fs.readFileSync('./tests/loremipsum.base85')); | ||
var decoded = base85.decode(enc); | ||
var encoded = base85.encode(raw); | ||
var decoded = base85.decode(enc, 'ascii85'); | ||
var encoded = base85.encode(raw, 'ascii85'); | ||
@@ -47,0 +50,0 @@ test.deepEqual(decoded, raw); |
@@ -7,3 +7,3 @@ var _ = require('underscore'); | ||
{ | ||
test.equal(base85.encode(1234), false); | ||
test.equal(base85.encode(1234, 'ascii85'), false); | ||
test.done(); | ||
@@ -14,6 +14,9 @@ } | ||
{ | ||
test.expect(data.length); | ||
var encodings = [ 'ascii85', 'z85' ]; | ||
test.expect(data.length * encodings.length); | ||
_.each(data, function (tc) { | ||
test.equal(base85.encode(tc.raw), tc.enc); | ||
_.each(encodings, function(encoding) { | ||
_.each(data, function (tc) { | ||
test.equal(base85.encode(tc.raw, encoding), tc.enc[encoding]); | ||
}); | ||
}); | ||
@@ -20,0 +23,0 @@ |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
220782
12
462
0
92
1