var zero = '0'.charCodeAt(0); | |
var plus = '+'.charCodeAt(0); | |
var minus = '-'.charCodeAt(0); | |
function isWhitespace(code) { | |
return code <= 32; | |
} | |
function isDigit(code) { | |
return 48 <= code && code <= 57; | |
} | |
function isSign(code) { | |
return code === minus || code === plus; | |
} | |
module.exports = function (opts, a, b) { | |
var checkSign = opts.sign; | |
var ia = 0; | |
var ib = 0; | |
var ma = a.length; | |
var mb = b.length; | |
var ca, cb; // character code | |
var za, zb; // leading zero count | |
var na, nb; // number length | |
var sa, sb; // number sign | |
var ta, tb; // temporary | |
var bias; | |
while (ia < ma && ib < mb) { | |
ca = a.charCodeAt(ia); | |
cb = b.charCodeAt(ib); | |
za = zb = 0; | |
na = nb = 0; | |
sa = sb = true; | |
bias = 0; | |
// skip over leading spaces | |
while (isWhitespace(ca)) { | |
ia += 1; | |
ca = a.charCodeAt(ia); | |
} | |
while (isWhitespace(cb)) { | |
ib += 1; | |
cb = b.charCodeAt(ib); | |
} | |
// skip and save sign | |
if (checkSign) { | |
ta = a.charCodeAt(ia + 1); | |
if (isSign(ca) && isDigit(ta)) { | |
if (ca === minus) { | |
sa = false; | |
} | |
ia += 1; | |
ca = ta; | |
} | |
tb = b.charCodeAt(ib + 1); | |
if (isSign(cb) && isDigit(tb)) { | |
if (cb === minus) { | |
sb = false; | |
} | |
ib += 1; | |
cb = tb; | |
} | |
} | |
// compare digits with other symbols | |
if (isDigit(ca) && !isDigit(cb)) { | |
return -1; | |
} | |
if (!isDigit(ca) && isDigit(cb)) { | |
return 1; | |
} | |
// compare negative and positive | |
if (!sa && sb) { | |
return -1; | |
} | |
if (sa && !sb) { | |
return 1; | |
} | |
// count leading zeros | |
while (ca === zero) { | |
za += 1; | |
ia += 1; | |
ca = a.charCodeAt(ia); | |
} | |
while (cb === zero) { | |
zb += 1; | |
ib += 1; | |
cb = b.charCodeAt(ib); | |
} | |
// count numbers | |
while (isDigit(ca) || isDigit(cb)) { | |
if (isDigit(ca) && isDigit(cb) && bias === 0) { | |
if (sa) { | |
if (ca < cb) { | |
bias = -1; | |
} else if (ca > cb) { | |
bias = 1; | |
} | |
} else { | |
if (ca > cb) { | |
bias = -1; | |
} else if (ca < cb) { | |
bias = 1; | |
} | |
} | |
} | |
if (isDigit(ca)) { | |
ia += 1; | |
na += 1; | |
ca = a.charCodeAt(ia); | |
} | |
if (isDigit(cb)) { | |
ib += 1; | |
nb += 1; | |
cb = b.charCodeAt(ib); | |
} | |
} | |
// compare number length | |
if (sa) { | |
if (na < nb) { | |
return -1; | |
} | |
if (na > nb) { | |
return 1; | |
} | |
} else { | |
if (na > nb) { | |
return -1; | |
} | |
if (na < nb) { | |
return 1; | |
} | |
} | |
// compare numbers | |
if (bias) { | |
return bias; | |
} | |
// compare leading zeros | |
if (sa) { | |
if (za > zb) { | |
return -1; | |
} | |
if (za < zb) { | |
return 1; | |
} | |
} else { | |
if (za < zb) { | |
return -1; | |
} | |
if (za > zb) { | |
return 1; | |
} | |
} | |
// compare ascii codes | |
if (ca < cb) { | |
return -1; | |
} | |
if (ca > cb) { | |
return 1; | |
} | |
ia += 1; | |
ib += 1; | |
} | |
// compare length | |
if (ma < mb) { | |
return -1; | |
} | |
if (ma > mb) { | |
return 1; | |
} | |
}; |