Skip to content

Commit

Permalink
implement encode method from iojs, closes #77
Browse files Browse the repository at this point in the history
  • Loading branch information
nlf committed May 22, 2015
1 parent 8e299ca commit 0c6f2a6
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 9 deletions.
4 changes: 2 additions & 2 deletions lib/stringify.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ internals.stringify = function (obj, prefix, generateArrayPrefix, strictNullHand
}
else if (obj === null) {
if (strictNullHandling) {
return Utils.fixedEncodeURIComponent(prefix);
return Utils.encode(prefix);
}

obj = '';
Expand All @@ -48,7 +48,7 @@ internals.stringify = function (obj, prefix, generateArrayPrefix, strictNullHand
typeof obj === 'number' ||
typeof obj === 'boolean') {

return [Utils.fixedEncodeURIComponent(prefix) + '=' + Utils.fixedEncodeURIComponent(obj)];
return [Utils.encode(prefix) + '=' + Utils.encode(obj)];
}

var values = [];
Expand Down
59 changes: 52 additions & 7 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
// Declare internals

var internals = {};
internals.hexTable = new Array(256);
for (var i = 0; i < 256; ++i) {
internals.hexTable[i] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase();
}


exports.arrayToObject = function (source) {
Expand Down Expand Up @@ -77,14 +81,55 @@ exports.decode = function (str) {
}
};

exports.fixedEncodeURIComponent = function (str) {
exports.encode = function (str) {

// To be more stringent in adhering to RFC 3986
return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
// This code was originally written by Brian White (mscdex) for the io.js core querystring library.
// It has been adapted here for stricter adherence to RFC 3986
if (str.length === 0) {
return str;
}

if (typeof str !== 'string') {
str = '' + str;
}

var out = '';
for (var i = 0, il = str.length; i < il; ++i) {
var c = str.charCodeAt(i);

if (c === 0x2D || // -
c === 0x2E || // .
c === 0x5F || // _
c === 0x7E || // ~
(c >= 0x30 && c <= 0x39) || // 0-9
(c >= 0x41 && c <= 0x5A) || // a-z
(c >= 0x61 && c <= 0x7A)) { // A-Z

out += str[i];
continue;
}

return '%' + c.charCodeAt(0).toString(16);
});
if (c < 0x80) {
out += internals.hexTable[c];
continue;
}

if (c < 0x800) {
out += internals.hexTable[0xC0 | (c >> 6)] + internals.hexTable[0x80 | (c & 0x3F)];
continue;
}

if (c < 0xD800 || c >= 0xE000) {
out += internals.hexTable[0xE0 | (c >> 12)] + internals.hexTable[0x80 | ((c >> 6) & 0x3F)] + internals.hexTable[0x80 | (c & 0x3F)];
continue;
}

++i;
c = 0x10000 + (((c & 0x3FF) << 10) | (str.charCodeAt(i) & 0x3FF));
out += internals.hexTable[0xF0 | (c >> 18)] + internals.hexTable[0x80 | ((c >> 12) & 0x3F)] + internals.hexTable[0x80 | ((c >> 6) & 0x3F)] + internals.hexTable[0x80 | (c & 0x3F)];
}

return out;
};

exports.compact = function (obj, refs) {
Expand Down Expand Up @@ -140,6 +185,6 @@ exports.isBuffer = function (obj) {
}

return !!(obj.constructor &&
obj.constructor.isBuffer &&
obj.constructor.isBuffer(obj));
obj.constructor.isBuffer &&
obj.constructor.isBuffer(obj));
};
5 changes: 5 additions & 0 deletions test/stringify.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ describe('stringify()', function () {
expect(Qs.stringify({ a: 'b' })).to.equal('a=b');
expect(Qs.stringify({ a: 1 })).to.equal('a=1');
expect(Qs.stringify({ a: 1, b: 2 })).to.equal('a=1&b=2');
expect(Qs.stringify({ a: 'A_Z' })).to.equal('a=A_Z');
expect(Qs.stringify({ a: '€' })).to.equal('a=%E2%82%AC');
expect(Qs.stringify({ a: '' })).to.equal('a=%EE%80%80');
expect(Qs.stringify({ a: 'א' })).to.equal('a=%D7%90');
expect(Qs.stringify({ a: '𐐷' })).to.equal('a=%F0%90%90%B7');
done();
});

Expand Down

0 comments on commit 0c6f2a6

Please sign in to comment.