version bump 1.0.0: rolling checksums

- browser tests work in IE6+
- miscellaneous adjustments to tooling
This commit is contained in:
SheetJS 2016-10-08 14:48:03 -04:00
parent e1c9c5e5cd
commit 1045f4f8e8
26 changed files with 765 additions and 220 deletions

@ -10,13 +10,18 @@
.*/perf/.*
.*/demo/browser.js
.*/shim.js
[include]
crc32.flow.js
.*/bin/.*.njs
.*/demo/browser.flow.js
[libs]
bits/10_types.js
misc/flow.js
misc/flowdeps.js
[options]
module.file_ext=.js
module.file_ext=.njs

@ -2,6 +2,7 @@ LIB=crc32
REQS=
ADDONS=
AUXTARGETS=demo/browser.js
CMDS=bin/crc32.njs
HTMLLINT=index.html
ULIB=$(shell echo $(LIB) | tr a-z A-Z)
@ -37,6 +38,7 @@ test mocha: test.js $(TARGET) baseline ## Run test suite
ctest: ## Build browser test (into ctest/ subdirectory)
cat misc/*.js > ctest/fixtures.js
cp -f test.js ctest/test.js
cp -f shim.js ctest/shim.js
cp -f $(TARGET) ctest/
.PHONY: ctestserv
@ -56,6 +58,7 @@ clean-baseline: ## Remove test baselines
.PHONY: lint
lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks
@jshint --show-non-errors $(TARGET) $(AUXTARGETS)
@jshint --show-non-errors $(CMDS)
@jshint --show-non-errors package.json
@jshint --show-non-errors --extract=always $(HTMLLINT)
@jscs $(TARGET) $(AUXTARGETS)

@ -1,52 +1,62 @@
# crc32
Standard CRC-32 algorithm implementation in JS (for the browser and nodejs).
Emphasis on correctness and performance.
Emphasis on correctness, performance, and IE6+ support.
## Installation
With [npm](https://www.npmjs.org/package/crc-32):
$ npm install crc-32
```bash
$ npm install crc-32
```
In the browser:
<script src="crc32.js"></script>
```html
<script src="crc32.js"></script>
```
The browser exposes a variable ADLER32
The browser exposes a variable `CRC32`.
When installed globally, npm installs a script `crc32` that computes the
checksum for a specified file or standard input.
The script will manipulate `module.exports` if available (e.g. in a CommonJS
`require` context). This is not always desirable. To prevent the behavior,
define `DO_NOT_EXPORT_CRC`
define `DO_NOT_EXPORT_CRC`.
## Usage
In all cases, the relevant function takes a single argument representing data.
In all cases, the relevant function takes an argument representing data and an
optional second argument representing the starting "seed" (for rolling CRC).
The return value is a signed 32-bit integer.
- `CRC32.buf(byte array or buffer)` assumes the argument is a set of 8-bit
unsigned integers (e.g. nodejs `Buffer` or simple array of ints).
- `CRC32.buf(byte array or buffer[, seed])` assumes the argument is a sequence
of 8-bit unsigned integers (e.g. nodejs `Buffer` or simple array of ints).
- `CRC32.bstr(binary string)` interprets the argument as a binary string where
the `i`-th byte is the low byte of the UCS-2 char: `str.charCodeAt(i) & 0xFF`
- `CRC32.bstr(binary string[, seed])` assumes the argument is a "binary" string
where byte `i` is the low byte of the UCS-2 char: `str.charCodeAt(i) & 0xFF`
- `CRC32.str(string)` interprets the argument as a standard JS string
- `CRC32.str(string[, seed])` assumes the argument is a standard string and
calculates the CRC32 of the UTF-8 encoding.
For example:
```js
> // var CRC32 = require('crc-32'); // uncomment this line if in node
> CRC32.str("SheetJS") // -1647298270
> CRC32.bstr("SheetJS") // -1647298270
> CRC32.buf([ 83, 104, 101, 101, 116, 74, 83 ]) // -1647298270
// var CRC32 = require('crc-32'); // uncomment this line if in node
CRC32.str("SheetJS") // -1647298270
CRC32.bstr("SheetJS") // -1647298270
CRC32.buf([ 83, 104, 101, 101, 116, 74, 83 ]) // -1647298270
> [CRC32.str("\u2603"), CRC32.str("\u0003")] // [ -1743909036, 1259060791 ]
> [CRC32.bstr("\u2603"), CRC32.bstr("\u0003")] // [ 1259060791, 1259060791 ]
> [CRC32.buf([0x2603]), CRC32.buf([0x0003])] // [ 1259060791, 1259060791 ]
crc32 = CRC32.buf([83, 104]) // -1826163454 "Sh"
crc32 = CRC32.str("eet", crc32) // 1191034598 "Sheet"
CRC32.bstr("JS", crc32) // -1647298270 "SheetJS"
[CRC32.str("\u2603"), CRC32.str("\u0003")] // [ -1743909036, 1259060791 ]
[CRC32.bstr("\u2603"), CRC32.bstr("\u0003")] // [ 1259060791, 1259060791 ]
[CRC32.buf([0x2603]), CRC32.buf([0x0003])] // [ 1259060791, 1259060791 ]
```
## Testing
@ -73,7 +83,7 @@ To generate the bits file, use the `crc32` function from python zlib:
The included `crc32.njs` script can process files or stdin:
```
```bash
$ echo "this is a test" > t.txt
$ bin/crc32.njs t.txt
1912935186
@ -81,7 +91,7 @@ $ bin/crc32.njs t.txt
For comparison, the included `crc32.py` script uses python zlib:
```
```bash
$ bin/crc32.py t.txt
1912935186
```

@ -2,36 +2,77 @@
/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2 ft=javascript: */
var X;
var X/*:CRC32Module*/;
try { X = require('../'); } catch(e) { X = require('crc-32'); }
function help()/*:number*/ {
[
"usage: crc32 [options] [filename]",
"",
"Options:",
" -h, --help output usage information",
" -V, --version output the version number",
" -S, --seed=<n> use integer seed as starting value (rolling CRC)",
" -H, --hex-seed=<h> use hex seed as starting value (rolling CRC)",
" -d, --signed print result with format `%d` (default)",
" -u, --unsigned print result with format `%u`",
" -x, --hex print result with format `%0.8x`",
" -X, --HEX print result with format `%0.8X`",
" -F, --format=<s> use specified printf format",
"",
"Set filename = '-' or pipe data into crc32 to read from stdin",
"Default output mode is signed (-d)",
""
].forEach(function(l) { console.log(l); });
return 0;
}
function version()/*:number*/ { console.log(X.version); return 0; }
var fs = require('fs');
require('exit-on-epipe');
var args = process.argv.slice(2);
function die(msg/*:string*/, ec/*:?number*/)/*:void*/ { console.error(msg); process.exit(ec || 0); }
var filename;
if(args[0]) filename = args[0];
var args/*:Array<string>*/ = process.argv.slice(2);
var filename/*:string*/ = "";
var fmt/*:string*/ = "";
var seed = 0, r = 10;
for(var i = 0; i < args.length; ++i) {
var arg = args[i];
if(arg.charCodeAt(0) != 45) { if(filename === "") filename = arg; continue; }
var m = arg.indexOf("=") == -1 ? arg : arg.substr(0, arg.indexOf("="));
switch(m) {
case "-": filename = "-"; break;
case "--help": case "-h": process.exit(help()); break;
case "--version": case "-V": process.exit(version()); break;
case "--signed": case "-d": fmt = "%d"; break;
case "--unsigned": case "-u": fmt = "%u"; break;
case "--hex": case "-x": fmt = "%0.8x"; break;
case "--HEX": case "-X": fmt = "%0.8X"; break;
case "--format": case "-F":
fmt = ((m!=arg) ? arg.substr(m.length+1) : args[++i])||""; break;
case "--hex-seed": case "-H": r = 16;
/* falls through */
case "--seed": case "-S":
seed=parseInt((m!=arg) ? arg.substr(m.length+1) : args[++i], r)||0; break;
default: die("crc32: unrecognized option `" + arg + "'", 22);
}
}
if(!process.stdin.isTTY) filename = filename || "-";
if(filename.length===0) die("crc32: must specify a filename ('-' for stdin)",1);
if(!filename) {
console.error("crc32: must specify a filename ('-' for stdin)");
process.exit(1);
}
if(filename === "-h" || filename === "--help") {
console.log("usage: " + process.argv[0] + " [filename]");
process.exit(0);
}
if(filename !== "-" && !fs.existsSync(filename)) {
console.error("crc32: " + filename + ": No such file or directory");
process.exit(2);
function process_data(data/*:Buffer*/) {
var out/*:CRC32Type*/ = X.buf(data, seed);
return console.log(fmt === "" ? out : require("printj").sprintf(fmt, out));
}
if(filename === "-") process.stdin.pipe(require('concat-stream')(process_data));
else process_data(fs.readFileSync(filename));
function process_data(data) {
console.log(X.buf(data));
}
else if(fs.existsSync(filename)) process_data(fs.readFileSync(filename));
else die("crc32: " + filename + ": No such file or directory", 2);

@ -1 +1 @@
CRC32.version = '0.4.1';
CRC32.version = '1.0.0';

@ -1,9 +1,9 @@
/*# charCodeAt is the best approach for binary strings */
/*global Buffer */
var use_buffer = typeof Buffer !== 'undefined';
function crc32_bstr(bstr/*:string*/)/*:CRC32Type*/ {
if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr));
var C = -1, L = bstr.length - 1;
function crc32_bstr(bstr/*:string*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr), seed);
var C = seed/*:: ? 0 : 0 */ ^ -1, L = bstr.length - 1;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
@ -12,9 +12,9 @@ function crc32_bstr(bstr/*:string*/)/*:CRC32Type*/ {
return C ^ -1;
}
function crc32_buf(buf/*:ABuf*/)/*:CRC32Type*/ {
if(buf.length > 10000) return crc32_buf_8(buf);
var C = -1, L = buf.length - 3;
function crc32_buf(buf/*:ABuf*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
if(buf.length > 10000) return crc32_buf_8(buf, seed);
var C = seed/*:: ? 0 : 0 */ ^ -1, L = buf.length - 3;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
@ -25,8 +25,8 @@ function crc32_buf(buf/*:ABuf*/)/*:CRC32Type*/ {
return C ^ -1;
}
function crc32_buf_8(buf/*:ABuf*/)/*:CRC32Type*/ {
var C = -1, L = buf.length - 7;
function crc32_buf_8(buf/*:ABuf*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
var C = seed/*:: ? 0 : 0 */ ^ -1, L = buf.length - 7;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
@ -42,8 +42,8 @@ function crc32_buf_8(buf/*:ABuf*/)/*:CRC32Type*/ {
}
/*# much much faster to intertwine utf8 and C */
function crc32_str(str/*:string*/)/*:CRC32Type*/ {
var C = -1;
function crc32_str(str/*:string*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
var C = seed/*:: ? 0 : 0 */ ^ -1;
for(var i = 0, L=str.length, c, d; i < L;) {
c = str.charCodeAt(i++);
if(c < 0x80) {

@ -23,7 +23,7 @@ var CRC32;
}
/*jshint ignore:end */
}(function(CRC32) {
CRC32.version = '0.4.1';
CRC32.version = '1.0.0';
/*::
type CRC32Type = number;
type ABuf = Array<number> | Buffer;
@ -54,9 +54,9 @@ var T = signed_crc_table();
/*# charCodeAt is the best approach for binary strings */
/*global Buffer */
var use_buffer = typeof Buffer !== 'undefined';
function crc32_bstr(bstr/*:string*/)/*:CRC32Type*/ {
if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr));
var C = -1, L = bstr.length - 1;
function crc32_bstr(bstr/*:string*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr), seed);
var C = seed/*:: ? 0 : 0 */ ^ -1, L = bstr.length - 1;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
@ -65,9 +65,9 @@ function crc32_bstr(bstr/*:string*/)/*:CRC32Type*/ {
return C ^ -1;
}
function crc32_buf(buf/*:ABuf*/)/*:CRC32Type*/ {
if(buf.length > 10000) return crc32_buf_8(buf);
var C = -1, L = buf.length - 3;
function crc32_buf(buf/*:ABuf*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
if(buf.length > 10000) return crc32_buf_8(buf, seed);
var C = seed/*:: ? 0 : 0 */ ^ -1, L = buf.length - 3;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
@ -78,8 +78,8 @@ function crc32_buf(buf/*:ABuf*/)/*:CRC32Type*/ {
return C ^ -1;
}
function crc32_buf_8(buf/*:ABuf*/)/*:CRC32Type*/ {
var C = -1, L = buf.length - 7;
function crc32_buf_8(buf/*:ABuf*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
var C = seed/*:: ? 0 : 0 */ ^ -1, L = buf.length - 7;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
@ -95,8 +95,8 @@ function crc32_buf_8(buf/*:ABuf*/)/*:CRC32Type*/ {
}
/*# much much faster to intertwine utf8 and C */
function crc32_str(str/*:string*/)/*:CRC32Type*/ {
var C = -1;
function crc32_str(str/*:string*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
var C = seed/*:: ? 0 : 0 */ ^ -1;
for(var i = 0, L=str.length, c, d; i < L;) {
c = str.charCodeAt(i++);
if(c < 0x80) {

@ -21,7 +21,7 @@ var CRC32;
}
/*jshint ignore:end */
}(function(CRC32) {
CRC32.version = '0.4.1';
CRC32.version = '1.0.0';
/* see perf/crc32table.js */
/*global Int32Array */
function signed_crc_table() {
@ -46,9 +46,9 @@ function signed_crc_table() {
var T = signed_crc_table();
/*global Buffer */
var use_buffer = typeof Buffer !== 'undefined';
function crc32_bstr(bstr) {
if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr));
var C = -1, L = bstr.length - 1;
function crc32_bstr(bstr, seed) {
if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr), seed);
var C = seed ^ -1, L = bstr.length - 1;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
@ -57,9 +57,9 @@ function crc32_bstr(bstr) {
return C ^ -1;
}
function crc32_buf(buf) {
if(buf.length > 10000) return crc32_buf_8(buf);
var C = -1, L = buf.length - 3;
function crc32_buf(buf, seed) {
if(buf.length > 10000) return crc32_buf_8(buf, seed);
var C = seed ^ -1, L = buf.length - 3;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
@ -70,8 +70,8 @@ function crc32_buf(buf) {
return C ^ -1;
}
function crc32_buf_8(buf) {
var C = -1, L = buf.length - 7;
function crc32_buf_8(buf, seed) {
var C = seed ^ -1, L = buf.length - 7;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
@ -86,8 +86,8 @@ function crc32_buf_8(buf) {
return C ^ -1;
}
function crc32_str(str) {
var C = -1;
function crc32_str(str, seed) {
var C = seed ^ -1;
for(var i = 0, L=str.length, c, d; i < L;) {
c = str.charCodeAt(i++);
if(c < 0x80) {

@ -21,7 +21,7 @@ var CRC32;
}
/*jshint ignore:end */
}(function(CRC32) {
CRC32.version = '0.4.1';
CRC32.version = '1.0.0';
/* see perf/crc32table.js */
/*global Int32Array */
function signed_crc_table() {
@ -46,9 +46,9 @@ function signed_crc_table() {
var T = signed_crc_table();
/*global Buffer */
var use_buffer = typeof Buffer !== 'undefined';
function crc32_bstr(bstr) {
if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr));
var C = -1, L = bstr.length - 1;
function crc32_bstr(bstr, seed) {
if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr), seed);
var C = seed ^ -1, L = bstr.length - 1;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
@ -57,9 +57,9 @@ function crc32_bstr(bstr) {
return C ^ -1;
}
function crc32_buf(buf) {
if(buf.length > 10000) return crc32_buf_8(buf);
var C = -1, L = buf.length - 3;
function crc32_buf(buf, seed) {
if(buf.length > 10000) return crc32_buf_8(buf, seed);
var C = seed ^ -1, L = buf.length - 3;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
@ -70,8 +70,8 @@ function crc32_buf(buf) {
return C ^ -1;
}
function crc32_buf_8(buf) {
var C = -1, L = buf.length - 7;
function crc32_buf_8(buf, seed) {
var C = seed ^ -1, L = buf.length - 7;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
@ -86,8 +86,8 @@ function crc32_buf_8(buf) {
return C ^ -1;
}
function crc32_str(str) {
var C = -1;
function crc32_str(str, seed) {
var C = seed ^ -1;
for(var i = 0, L=str.length, c, d; i < L;) {
c = str.charCodeAt(i++);
if(c < 0x80) {

@ -1,2 +1,2 @@
var assert = {};
assert.equal = function(x,y) { if(x !== y) throw x + " !== " + y; };
assert.equal = function(x,y) { if(x !== y) throw new Error(x + " !== " + y); };

@ -17,9 +17,22 @@ type Stringifier = {(d:ArrayLike):string};
declare class CRC32Module {
table:CRC32TableType;
bstr(s:string):CRC32Type;
buf(b:ABuf):CRC32Type;
str(s:string):CRC32Type;
bstr(s:string, seed:?CRC32Type):CRC32Type;
buf(b:ABuf, seed:?CRC32Type):CRC32Type;
str(s:string, seed:?CRC32Type):CRC32Type;
version:string;
};
*/
/*::
type _CB = {(data:Buffer):void;};
declare module 'concat-stream' {declare function exports(f:_CB):stream$Duplex;};
declare module 'exit-on-epipe' {};
declare module 'crc-32' { declare var exports:CRC32Module; };
declare module '../' { declare var exports:CRC32Module; };
declare module 'printj' {
declare function sprintf(fmt:string, ...args:any):string;
};
*/
/* vim: set ts=2: */
@ -33,13 +46,13 @@ var node_crc = require('./node-crc');
function z1(bstr) { return js_crc32.bstr(bstr); }
function z2(bstr) { return buffer_crc32.signed(bstr); }
function z3(bstr) { return crc32(bstr); }
function z4(bstr) { return node_crc.crc32(bstr);}
function z4(bstr) { return node_crc.crc32(bstr)|0;}
function z5(bstr) { return js_crc32_old.bstr(bstr); }
function b1(buf) { return js_crc32.buf(buf); }
function b2(buf) { return buffer_crc32.signed(buf); }
function b3(buf) { return crc32(buf); }
function b4(buf) { return node_crc.crc32(buf); }
function b4(buf) { return node_crc.crc32(buf)|0; }
function b5(buf) { return js_crc32_old.buf(buf); }
function u1(str) { return js_crc32.str(str); }
@ -97,14 +110,14 @@ if(btest) for(var j = 0; j != ntests; ++j) {
if(do_bstr) {
assert.equal(z1(bstr_tests[j][0]), z2(bstr_tests[j][0]));
assert.equal(z1(bstr_tests[j][0]), fix(z3(bstr_tests[j][0])));
assert.equal(z1(bstr_tests[j][0]), fix(z4(bstr_tests[j][0])));
assert.equal(z1(bstr_tests[j][0]), (z4(bstr_tests[j][0])));
assert.equal(z1(bstr_tests[j][0]), z5(bstr_tests[j][0]));
}
if(do_buf) {
assert.equal(b1(bstr_tests[j][1]), b2(bstr_tests[j][1]));
assert.equal(b1(bstr_tests[j][1]), fix(b3(bstr_tests[j][1])));
assert.equal(b1(bstr_tests[j][1]), fix(b4(bstr_tests[j][1])));
assert.equal(b1(bstr_tests[j][1]), (b4(bstr_tests[j][1])));
assert.equal(b1(bstr_tests[j][1]), b5(bstr_tests[j][1]));
}
}

@ -8,6 +8,7 @@
</head>
<body>
<div id="mocha"></div>
<script src="shim.js"></script>
<script src="crc32.js"></script>
<script src="fakeassert.js"></script>
<script src="mocha.js"></script>

237
ctest/shim.js Normal file

@ -0,0 +1,237 @@
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
if (!Object.keys) {
Object.keys = (function () {
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length;
return function (obj) {
if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');
var result = [];
for (var prop in obj) {
if (hasOwnProperty.call(obj, prop)) result.push(prop);
}
if (hasDontEnumBug) {
for (var i=0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
}
}
return result;
};
})();
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
if (!Array.prototype.filter)
{
Array.prototype.filter = function(fun /*, thisp */)
{
"use strict";
if (this == null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun != "function")
throw new TypeError();
var res = [];
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in t)
{
var val = t[i]; // in case fun mutates this
if (fun.call(thisp, val, i, t))
res.push(val);
}
}
return res;
};
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim
if (!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/g, '');
};
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
if (!Array.prototype.forEach)
{
Array.prototype.forEach = function(fun /*, thisArg */)
{
"use strict";
if (this === void 0 || this === null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== "function")
throw new TypeError();
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++)
{
if (i in t)
fun.call(thisArg, t[i], i, t);
}
};
}
// Production steps of ECMA-262, Edition 5, 15.4.4.19
// Reference: http://es5.github.com/#x15.4.4.19
if (!Array.prototype.map) {
Array.prototype.map = function(callback, thisArg) {
var T, A, k;
if (this == null) {
throw new TypeError(" this is null or not defined");
}
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if (typeof callback !== "function") {
throw new TypeError(callback + " is not a function");
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (thisArg) {
T = thisArg;
}
// 6. Let A be a new array created as if by the expression new Array(len) where Array is
// the standard built-in constructor with that name and len is the value of len.
A = new Array(len);
// 7. Let k be 0
k = 0;
// 8. Repeat, while k < len
while(k < len) {
var kValue, mappedValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
kValue = O[ k ];
// ii. Let mappedValue be the result of calling the Call internal method of callback
// with T as the this value and argument list containing kValue, k, and O.
mappedValue = callback.call(T, kValue, k, O);
// iii. Call the DefineOwnProperty internal method of A with arguments
// Pk, Property Descriptor {Value: mappedValue, : true, Enumerable: true, Configurable: true},
// and false.
// In browsers that support Object.defineProperty, use the following:
// Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
// For best browser support, use the following:
A[ k ] = mappedValue;
}
// d. Increase k by 1.
k++;
}
// 9. return A
return A;
};
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement, fromIndex) {
if ( this === undefined || this === null ) {
throw new TypeError( '"this" is null or not defined' );
}
var length = this.length >>> 0; // Hack to convert object.length to a UInt32
fromIndex = +fromIndex || 0;
if (Math.abs(fromIndex) === Infinity) {
fromIndex = 0;
}
if (fromIndex < 0) {
fromIndex += length;
if (fromIndex < 0) {
fromIndex = 0;
}
}
for (;fromIndex < length; fromIndex++) {
if (this[fromIndex] === searchElement) {
return fromIndex;
}
}
return -1;
};
}
// Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
if (! Array.isArray) {
Array.isArray = function(obj) {
return Object.prototype.toString.call(obj) === "[object Array]";
};
}
// https://github.com/ttaubert/node-arraybuffer-slice
// (c) 2013 Tim Taubert <tim@timtaubert.de>
// arraybuffer-slice may be freely distributed under the MIT license.
"use strict";
if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) {
ArrayBuffer.prototype.slice = function (begin, end) {
begin = (begin|0) || 0;
var num = this.byteLength;
end = end === (void 0) ? num : (end|0);
// Handle negative values.
if (begin < 0) begin += num;
if (end < 0) end += num;
if (num === 0 || begin >= num || begin >= end) {
return new ArrayBuffer(0);
}
var length = Math.min(num - begin, end - begin);
var target = new ArrayBuffer(length);
var targetArray = new Uint8Array(target);
targetArray.set(new Uint8Array(this, begin, length));
return target;
};
}

@ -10,6 +10,16 @@ if(typeof require !== 'undefined') {
function readlines(f) { return fs.readFileSync(f, "ascii").split("\n"); }
function msieversion()
{
if(typeof window == 'undefined') return Infinity;
if(typeof window.navigator == 'undefined') return Infinity;
var ua = window.navigator.userAgent
var msie = ua.indexOf ( "MSIE " )
if(msie < 0) return Infinity;
return parseInt (ua.substring (msie+5, ua.indexOf (".", msie )));
}
describe('crc32 table', function() {
it('should match fixed table', function() {
var overflow = 0;
@ -25,10 +35,25 @@ describe('crc32 bits', function() {
bits.forEach(function(i) {
var msg = i[0], l = i[0].length, L = i[1]|0;
if(l > 20) msg = i[0].substr(0,5) + "...(" + l + ")..." + i[0].substr(-5);
if(l > 100 && msieversion() < 7) return;
it(msg, function() {
if(i[2] === 1) assert.equal(X.bstr(i[0]), L);
assert.equal(X.str(i[0]), i[1]|0);
if(typeof Buffer !== 'undefined') assert.equal(X.buf(new Buffer(i[0])), L);
for(var x = 0; x < i[0].length; ++x) {
if(i[0].charCodeAt(x) >= 0xD800 && i[0].charCodeAt(x) < 0xE000) continue;
if(i[2] === 1) {
var bstrcrc = X.bstr(i[0].substr(x), X.bstr(i[0].substr(0, x)));
assert.equal(bstrcrc, L);
}
var strcrc = X.str(i[0].substr(x), X.str(i[0].substr(0, x)));
assert.equal(strcrc, i[1]|0);
if(typeof Buffer !== 'undefined') {
var buf = new Buffer(i[0]);
var bufcrc = X.buf(buf.slice(x), X.buf(buf.slice(0, x)));
assert.equal(bufcrc, L);
}
}
});
});
});
@ -46,9 +71,9 @@ if(typeof require !== 'undefined') describe("unicode", function() {
if(c.charCodeAt(0) >= 0xD800 && c.charCodeAt(0) < 0xE000) continue;
var cc = corpus[ucidx], dd = X.str(c);
assert.equal(dd, cc, ":" + ucidx + ":" + c + ":" + cc + ":" + dd);
var ee = X.buf(new Buffer(c, "utf8"));
assert.equal(ee, cc, ":" + ucidx + ":" + c + ":" + cc + ":" + ee);
if(typeof Buffer !== 'undefined') {
var ee = X.buf(new Buffer(c, "utf8"));
assert.equal(ee, cc, ":" + ucidx + ":" + c + ":" + cc + ":" + ee);
var ff = X.bstr(String.fromCharCode.apply(null, new Buffer(c, "utf8")));
assert.equal(ff, cc, ":" + ucidx + ":" + c + ":" + cc + ":" + ff);
}

@ -26,10 +26,10 @@ function make_chunk_buf_to_str(BType/*:function*/)/*:Stringifier*/ {
};
}
/*# buffer to binary string */
var bstrify/*:Stringifier*/ = make_chunk_buf_to_str(Uint8Array);
var bstrify/*:Stringifier*/ = make_chunk_buf_to_str(typeof Uint8Array !== 'undefined' ? Uint8Array : Array);
/*# readAsBinaryString support */
var rABS/*:boolean*/ = is_defined(FileReader, ['prototype', 'readAsBinaryString']);
var rABS/*:boolean*/ = typeof FileReader !== 'undefined' && is_defined(FileReader, ['prototype', 'readAsBinaryString']);
var userABS/*:HTMLInputElement*/ = (document.getElementsByName("userabs")[0]/*:any*/);
if(!rABS) {
userABS.disabled = true;
@ -37,7 +37,7 @@ if(!rABS) {
}
/*## Process Result */
/*:: declare class HTMLPreElement extends HTMLElement { innerText:string; } */
/*:: declare class HTMLPreElement extends HTMLElement { innerText?:string; } */
function process_value(val/*:CRC32Type*/) {
var output = [];
output[0] = "Signed : " + val;

@ -23,9 +23,9 @@ function make_chunk_buf_to_str(BType) {
return o;
};
}
var bstrify = make_chunk_buf_to_str(Uint8Array);
var bstrify = make_chunk_buf_to_str(typeof Uint8Array !== 'undefined' ? Uint8Array : Array);
var rABS = is_defined(FileReader, ['prototype', 'readAsBinaryString']);
var rABS = typeof FileReader !== 'undefined' && is_defined(FileReader, ['prototype', 'readAsBinaryString']);
var userABS = (document.getElementsByName("userabs")[0]);
if(!rABS) {
userABS.disabled = true;

@ -34,6 +34,7 @@ Use readAsBinaryString: (when available) <input type="checkbox" name="userabs" c
<pre id="out">.</pre>
<br />
<script type="text/javascript">/* jshint browser: true */</script>
<script src="shim.js"></script>
<script src="crc32.js"></script>
<script src="demo/browser.flow.js"></script>
<script type="text/javascript">

@ -4,8 +4,9 @@ type Stringifier = {(d:ArrayLike):string};
declare class CRC32Module {
table:CRC32TableType;
bstr(s:string):CRC32Type;
buf(b:ABuf):CRC32Type;
str(s:string):CRC32Type;
bstr(s:string, seed:?CRC32Type):CRC32Type;
buf(b:ABuf, seed:?CRC32Type):CRC32Type;
str(s:string, seed:?CRC32Type):CRC32Type;
version:string;
};
*/

12
misc/flowdeps.js Normal file

@ -0,0 +1,12 @@
/*::
type _CB = {(data:Buffer):void;};
declare module 'concat-stream' {declare function exports(f:_CB):stream$Duplex;};
declare module 'exit-on-epipe' {};
declare module 'crc-32' { declare var exports:CRC32Module; };
declare module '../' { declare var exports:CRC32Module; };
declare module 'printj' {
declare function sprintf(fmt:string, ...args:any):string;
};
*/

@ -9,13 +9,13 @@ var node_crc = require('./node-crc');
function z1(bstr) { return js_crc32.bstr(bstr); }
function z2(bstr) { return buffer_crc32.signed(bstr); }
function z3(bstr) { return crc32(bstr); }
function z4(bstr) { return node_crc.crc32(bstr);}
function z4(bstr) { return node_crc.crc32(bstr)|0;}
function z5(bstr) { return js_crc32_old.bstr(bstr); }
function b1(buf) { return js_crc32.buf(buf); }
function b2(buf) { return buffer_crc32.signed(buf); }
function b3(buf) { return crc32(buf); }
function b4(buf) { return node_crc.crc32(buf); }
function b4(buf) { return node_crc.crc32(buf)|0; }
function b5(buf) { return js_crc32_old.buf(buf); }
function u1(str) { return js_crc32.str(str); }
@ -73,14 +73,14 @@ if(btest) for(var j = 0; j != ntests; ++j) {
if(do_bstr) {
assert.equal(z1(bstr_tests[j][0]), z2(bstr_tests[j][0]));
assert.equal(z1(bstr_tests[j][0]), fix(z3(bstr_tests[j][0])));
assert.equal(z1(bstr_tests[j][0]), fix(z4(bstr_tests[j][0])));
assert.equal(z1(bstr_tests[j][0]), (z4(bstr_tests[j][0])));
assert.equal(z1(bstr_tests[j][0]), z5(bstr_tests[j][0]));
}
if(do_buf) {
assert.equal(b1(bstr_tests[j][1]), b2(bstr_tests[j][1]));
assert.equal(b1(bstr_tests[j][1]), fix(b3(bstr_tests[j][1])));
assert.equal(b1(bstr_tests[j][1]), fix(b4(bstr_tests[j][1])));
assert.equal(b1(bstr_tests[j][1]), (b4(bstr_tests[j][1])));
assert.equal(b1(bstr_tests[j][1]), b5(bstr_tests[j][1]));
}
}

@ -1,6 +1,6 @@
{
"name": "crc-32",
"version": "0.4.1",
"version": "1.0.0",
"author": "sheetjs",
"description": "Pure-JS CRC-32",
"keywords": [ "crc32", "checksum", "crc" ],
@ -10,6 +10,7 @@
"main": "./crc32",
"dependencies": {
"concat-stream":"",
"printj":"",
"exit-on-epipe":""
},
"devDependencies": {

@ -1,82 +0,0 @@
--- binary string (255) ---
✓ js-crc32 x 25.41 ops/sec ±0.40% (45 runs sampled)
✓ buffer-crc32 x 6.63 ops/sec ±1.09% (20 runs sampled)
✓ crc32 x 0.84 ops/sec ±1.17% (6 runs sampled)
✓ node_crc x 1.99 ops/sec ±0.59% (8 runs sampled)
Fastest is js-crc32
--- buffer (255) ---
✓ js-crc32 x 30.68 ops/sec ±0.40% (55 runs sampled)
✓ buffer-crc32 x 26.15 ops/sec ±0.36% (47 runs sampled)
✓ crc32 x 7.58 ops/sec ±0.61% (22 runs sampled)
✓ node_crc x 3.51 ops/sec ±0.56% (12 runs sampled)
Fastest is js-crc32
--- unicode string (255) ---
✓ js-crc32 x 11.65 ops/sec ±0.35% (32 runs sampled)
✓ buffer-crc32 x 3.17 ops/sec ±4.01% (12 runs sampled)
Fastest is js-crc32
--- binary string (1023) ---
✓ js-crc32 x 65.10 ops/sec ±0.36% (68 runs sampled)
✓ buffer-crc32 x 25.63 ops/sec ±3.38% (60 runs sampled)
✓ crc32 x 2.52 ops/sec ±0.65% (10 runs sampled)
✓ node_crc x 9.41 ops/sec ±0.55% (27 runs sampled)
Fastest is js-crc32
--- buffer (1023) ---
✓ js-crc32 x 78.58 ops/sec ±0.42% (82 runs sampled)
✓ buffer-crc32 x 73.15 ops/sec ±0.41% (76 runs sampled)
✓ crc32 x 21.28 ops/sec ±0.37% (39 runs sampled)
✓ node_crc x 12.46 ops/sec ±0.42% (34 runs sampled)
Fastest is js-crc32
--- unicode string (1023) ---
✓ js-crc32 x 29.07 ops/sec ±0.51% (51 runs sampled)
✓ buffer-crc32 x 9.25 ops/sec ±6.61% (35 runs sampled)
Fastest is js-crc32
--- binary string (4095) ---
✓ js-crc32 x 16.57 ops/sec ±0.47% (44 runs sampled)
✓ buffer-crc32 x 13.30 ops/sec ±8.05% (34 runs sampled)
✓ crc32 x 0.60 ops/sec ±0.46% (5 runs sampled)
✓ node_crc x 3.01 ops/sec ±0.52% (11 runs sampled)
Fastest is js-crc32
--- buffer (4095) ---
✓ js-crc32 x 20.35 ops/sec ±0.45% (37 runs sampled)
✓ buffer-crc32 x 18.86 ops/sec ±0.45% (50 runs sampled)
Fastest is js-crc32
--- unicode string (4095) ---
✓ js-crc32 x 7.20 ops/sec ±0.96% (22 runs sampled)
✓ buffer-crc32 x 4.20 ops/sec ±5.73% (13 runs sampled)
Fastest is js-crc32
--- binary string (16383) ---
✓ js-crc32 x 41.40 ops/sec ±0.15% (55 runs sampled)
✓ buffer-crc32 x 39.18 ops/sec ±5.86% (63 runs sampled)
Fastest is js-crc32
--- buffer (16383) ---
✓ js-crc32 x 51.36 ops/sec ±0.34% (67 runs sampled)
✓ buffer-crc32 x 47.72 ops/sec ±0.31% (63 runs sampled)
Fastest is js-crc32
--- unicode string (16383) ---
✓ js-crc32 x 18.47 ops/sec ±0.74% (49 runs sampled)
✓ buffer-crc32 x 11.29 ops/sec ±3.94% (31 runs sampled)
Fastest is js-crc32
--- binary string (65535) ---
✓ js-crc32 x 10.14 ops/sec ±4.43% (28 runs sampled)
✓ buffer-crc32 x 7.29 ops/sec ±5.49% (27 runs sampled)
Fastest is js-crc32
--- buffer (65535) ---
✓ js-crc32 x 12.34 ops/sec ±0.26% (34 runs sampled)
✓ buffer-crc32 x 11.29 ops/sec ±0.56% (32 runs sampled)
Fastest is js-crc32
--- unicode string (65535) ---
✓ js-crc32 x 4.28 ops/sec ±1.17% (14 runs sampled)
✓ buffer-crc32 x 2.73 ops/sec ±3.73% (10 runs sampled)
Fastest is js-crc32
--- binary string (262143) ---
✓ js-crc32 x 21.41 ops/sec ±3.43% (43 runs sampled)
✓ buffer-crc32 x 23.56 ops/sec ±4.02% (41 runs sampled)
Fastest is js-crc32
--- buffer (262143) ---
✓ js-crc32 x 31.51 ops/sec ±0.49% (55 runs sampled)
✓ buffer-crc32 x 27.56 ops/sec ±0.60% (51 runs sampled)
Fastest is js-crc32
--- unicode string (262143) ---
✓ js-crc32 x 11.00 ops/sec ±0.98% (31 runs sampled)
✓ buffer-crc32 x 6.70 ops/sec ±2.99% (19 runs sampled)
Fastest is js-crc32

@ -1,4 +1,6 @@
var table = require('../').table;
var old = require('crc-32').bstr;
var cur = require('../').bstr;
function strToArr(str) {
// sweet hack to turn string into a 'byte' array
@ -91,13 +93,17 @@ for(var i = 0; i !== w; ++i) {
assert.equal(node_crc32(foobar), sheetjs2(foobar));
assert.equal(node_crc32(foobar), sheetjs3(foobar));
assert.equal(node_crc32(foobar), sheetjs8(foobar));
assert.equal(node_crc32(foobar), old(foobar));
assert.equal(node_crc32(foobar), cur(foobar));
}
var BM = require('./bm');
var suite = new BM('binary string');
suite.add('npm crc32', function() { for(var j = 0; j !== w; ++j) node_crc32(b[j]); });
//suite.add('npm crc32', function() { for(var j = 0; j !== w; ++j) node_crc32(b[j]); });
suite.add('sheetjs 1', function() { for(var j = 0; j !== w; ++j) sheetjs1(b[j]); });
suite.add('sheetjs 2', function() { for(var j = 0; j !== w; ++j) sheetjs2(b[j]); });
suite.add('sheetjs 3', function() { for(var j = 0; j !== w; ++j) sheetjs3(b[j]); });
suite.add('sheetjs 8', function() { for(var j = 0; j !== w; ++j) sheetjs8(b[j]); });
suite.add('last vers', function() { for(var j = 0; j !== w; ++j) old(b[j]); });
suite.add('current v', function() { for(var j = 0; j !== w; ++j) cur(b[j]); });
suite.run();

@ -1,44 +1,53 @@
var table = require('../').table;
var T = require('../').table;
var old = require('crc-32').str;
var cur = require('../').str;
function sheetjs1(utf8) {
var buf = new Buffer(utf8);
for(var crc = -1, i = 0; i != buf.length; ++i) {
crc = (crc >>> 8) ^ table[(crc ^ buf[i]) & 0xFF];
for(var C = -1, i = 0; i != buf.length; ++i) {
C = (C >>> 8) ^ T[(C ^ buf[i]) & 0xFF];
}
return crc ^ -1;
return C ^ -1;
}
function sheetjs2(utf8) {
for(var crc = -1, i = 0, L=utf8.length, c, d; i < L;) {
c = utf8.charCodeAt(i++);
function sheetjs2(str) {
var C = -1;
for(var i = 0, L=str.length, c, d; i < L;) {
c = str.charCodeAt(i++);
if(c < 0x80) {
crc = (crc >>> 8) ^ table[(crc ^ c) & 0xFF];
C = (C>>>8) ^ T[(C ^ c)&0xFF];
} else if(c < 0x800) {
crc = (crc >>> 8) ^ table[(crc ^ (192|((c>>6)&31))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|(c&63))) & 0xFF];
C = (C>>>8) ^ T[(C ^ (192|((c>>6)&31)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF];
} else if(c >= 0xD800 && c < 0xE000) {
c = (c&1023)+64; d = utf8.charCodeAt(i++) & 1023;
crc = (crc >>> 8) ^ table[(crc ^ (240|((c>>8)&7))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|((c>>2)&63))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|((d>>6)&15)|(c&3))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|(d&63))) & 0xFF];
c = (c&1023)+64; d = str.charCodeAt(i++)&1023;
C = (C>>>8) ^ T[(C ^ (240|((c>>8)&7)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|((c>>2)&63)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|((d>>6)&15)|((c&3)<<4)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|(d&63)))&0xFF];
} else {
crc = (crc >>> 8) ^ table[(crc ^ (224|((c>>12)&15))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|((c>>6)&63))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|(c&63))) & 0xFF];
C = (C>>>8) ^ T[(C ^ (224|((c>>12)&15)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|((c>>6)&63)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF];
}
}
return crc ^ -1;
return C ^ -1;
}
var foobar = "foo bar baz٪☃🍣";
for(var i = 0; i != 4; ++i) foobar += " " + foobar;
var assert = require('assert');
{
assert.equal(sheetjs1(foobar), sheetjs2(foobar));
assert.equal(sheetjs1(foobar), old(foobar));
assert.equal(sheetjs1(foobar), cur(foobar));
}
var BM = require('./bm');
var suite = new BM('unicode string');
var foobar = "foo bar baz٪☃🍣";
for(var i = 0; i != 4; ++i) foobar += " " + foobar;
suite.add('sheetjs 1', function() { for(var j = 0; j != 1000; ++j) sheetjs1(foobar); });
suite.add('sheetjs 2', function() { for(var j = 0; j != 1000; ++j) sheetjs2(foobar); });
suite.run()
var assert = require('assert');
assert.equal(sheetjs1(foobar), sheetjs2(foobar));
suite.add('last vers', function() { for(var j = 0; j != 1000; ++j) old(foobar); });
suite.add('current v', function() { for(var j = 0; j != 1000; ++j) cur(foobar); });
suite.run();

237
shim.js Normal file

@ -0,0 +1,237 @@
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
if (!Object.keys) {
Object.keys = (function () {
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length;
return function (obj) {
if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');
var result = [];
for (var prop in obj) {
if (hasOwnProperty.call(obj, prop)) result.push(prop);
}
if (hasDontEnumBug) {
for (var i=0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
}
}
return result;
};
})();
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
if (!Array.prototype.filter)
{
Array.prototype.filter = function(fun /*, thisp */)
{
"use strict";
if (this == null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun != "function")
throw new TypeError();
var res = [];
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in t)
{
var val = t[i]; // in case fun mutates this
if (fun.call(thisp, val, i, t))
res.push(val);
}
}
return res;
};
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim
if (!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/g, '');
};
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
if (!Array.prototype.forEach)
{
Array.prototype.forEach = function(fun /*, thisArg */)
{
"use strict";
if (this === void 0 || this === null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== "function")
throw new TypeError();
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++)
{
if (i in t)
fun.call(thisArg, t[i], i, t);
}
};
}
// Production steps of ECMA-262, Edition 5, 15.4.4.19
// Reference: http://es5.github.com/#x15.4.4.19
if (!Array.prototype.map) {
Array.prototype.map = function(callback, thisArg) {
var T, A, k;
if (this == null) {
throw new TypeError(" this is null or not defined");
}
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if (typeof callback !== "function") {
throw new TypeError(callback + " is not a function");
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (thisArg) {
T = thisArg;
}
// 6. Let A be a new array created as if by the expression new Array(len) where Array is
// the standard built-in constructor with that name and len is the value of len.
A = new Array(len);
// 7. Let k be 0
k = 0;
// 8. Repeat, while k < len
while(k < len) {
var kValue, mappedValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
kValue = O[ k ];
// ii. Let mappedValue be the result of calling the Call internal method of callback
// with T as the this value and argument list containing kValue, k, and O.
mappedValue = callback.call(T, kValue, k, O);
// iii. Call the DefineOwnProperty internal method of A with arguments
// Pk, Property Descriptor {Value: mappedValue, : true, Enumerable: true, Configurable: true},
// and false.
// In browsers that support Object.defineProperty, use the following:
// Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
// For best browser support, use the following:
A[ k ] = mappedValue;
}
// d. Increase k by 1.
k++;
}
// 9. return A
return A;
};
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement, fromIndex) {
if ( this === undefined || this === null ) {
throw new TypeError( '"this" is null or not defined' );
}
var length = this.length >>> 0; // Hack to convert object.length to a UInt32
fromIndex = +fromIndex || 0;
if (Math.abs(fromIndex) === Infinity) {
fromIndex = 0;
}
if (fromIndex < 0) {
fromIndex += length;
if (fromIndex < 0) {
fromIndex = 0;
}
}
for (;fromIndex < length; fromIndex++) {
if (this[fromIndex] === searchElement) {
return fromIndex;
}
}
return -1;
};
}
// Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
if (! Array.isArray) {
Array.isArray = function(obj) {
return Object.prototype.toString.call(obj) === "[object Array]";
};
}
// https://github.com/ttaubert/node-arraybuffer-slice
// (c) 2013 Tim Taubert <tim@timtaubert.de>
// arraybuffer-slice may be freely distributed under the MIT license.
"use strict";
if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) {
ArrayBuffer.prototype.slice = function (begin, end) {
begin = (begin|0) || 0;
var num = this.byteLength;
end = end === (void 0) ? num : (end|0);
// Handle negative values.
if (begin < 0) begin += num;
if (end < 0) end += num;
if (num === 0 || begin >= num || begin >= end) {
return new ArrayBuffer(0);
}
var length = Math.min(num - begin, end - begin);
var target = new ArrayBuffer(length);
var targetArray = new Uint8Array(target);
targetArray.set(new Uint8Array(this, begin, length));
return target;
};
}

29
test.js

@ -10,6 +10,16 @@ if(typeof require !== 'undefined') {
function readlines(f) { return fs.readFileSync(f, "ascii").split("\n"); }
function msieversion()
{
if(typeof window == 'undefined') return Infinity;
if(typeof window.navigator == 'undefined') return Infinity;
var ua = window.navigator.userAgent
var msie = ua.indexOf ( "MSIE " )
if(msie < 0) return Infinity;
return parseInt (ua.substring (msie+5, ua.indexOf (".", msie )));
}
describe('crc32 table', function() {
it('should match fixed table', function() {
var overflow = 0;
@ -25,10 +35,25 @@ describe('crc32 bits', function() {
bits.forEach(function(i) {
var msg = i[0], l = i[0].length, L = i[1]|0;
if(l > 20) msg = i[0].substr(0,5) + "...(" + l + ")..." + i[0].substr(-5);
if(l > 100 && msieversion() < 7) return;
it(msg, function() {
if(i[2] === 1) assert.equal(X.bstr(i[0]), L);
assert.equal(X.str(i[0]), i[1]|0);
if(typeof Buffer !== 'undefined') assert.equal(X.buf(new Buffer(i[0])), L);
for(var x = 0; x < i[0].length; ++x) {
if(i[0].charCodeAt(x) >= 0xD800 && i[0].charCodeAt(x) < 0xE000) continue;
if(i[2] === 1) {
var bstrcrc = X.bstr(i[0].substr(x), X.bstr(i[0].substr(0, x)));
assert.equal(bstrcrc, L);
}
var strcrc = X.str(i[0].substr(x), X.str(i[0].substr(0, x)));
assert.equal(strcrc, i[1]|0);
if(typeof Buffer !== 'undefined') {
var buf = new Buffer(i[0]);
var bufcrc = X.buf(buf.slice(x), X.buf(buf.slice(0, x)));
assert.equal(bufcrc, L);
}
}
});
});
});
@ -46,9 +71,9 @@ if(typeof require !== 'undefined') describe("unicode", function() {
if(c.charCodeAt(0) >= 0xD800 && c.charCodeAt(0) < 0xE000) continue;
var cc = corpus[ucidx], dd = X.str(c);
assert.equal(dd, cc, ":" + ucidx + ":" + c + ":" + cc + ":" + dd);
var ee = X.buf(new Buffer(c, "utf8"));
assert.equal(ee, cc, ":" + ucidx + ":" + c + ":" + cc + ":" + ee);
if(typeof Buffer !== 'undefined') {
var ee = X.buf(new Buffer(c, "utf8"));
assert.equal(ee, cc, ":" + ucidx + ":" + c + ":" + cc + ":" + ee);
var ff = X.bstr(String.fromCharCode.apply(null, new Buffer(c, "utf8")));
assert.equal(ff, cc, ":" + ucidx + ":" + c + ":" + cc + ":" + ff);
}