diff --git a/.flowconfig b/.flowconfig
new file mode 100644
index 0000000..9338415
--- /dev/null
+++ b/.flowconfig
@@ -0,0 +1,17 @@
+[ignore]
+.*/node_modules/.*
+.*/dist/.*
+.*/test.js
+.*/crc32.js
+
+.*/bits/.*
+.*/ctest/.*
+.*/misc/.*
+.*/perf/.*
+
+[include]
+crc32.flow.js
+
+[libs]
+
+[options]
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..5cd205b
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,4 @@
+{
+ "bitwise": false,
+ "curly": false
+}
diff --git a/Makefile b/Makefile
index 59428c2..b87f11e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,20 @@
LIB=crc32
+REQS=
+ADDONS=
+AUXTARGETS=
+
+ULIB=$(shell echo $(LIB) | tr a-z A-Z)
DEPS=$(sort $(wildcard bits/*.js))
TARGET=$(LIB).js
-$(TARGET): $(DEPS)
+.PHONY: all
+all: $(TARGET) $(AUXTARGETS)
+
+$(TARGET) $(AUXTARGETS): %.js : %.flow.js
+ node -e 'process.stdout.write(require("fs").readFileSync("$<","utf8").replace(/^\s*\/\*:[^*]*\*\/\s*(\n)?/gm,"").replace(/\/\*:[^*]*\*\//gm,""))' > $@
+
+$(LIB).flow.js: $(DEPS)
cat $^ | tr -d '\15\32' > $@
- cp -f $@ ctest/
bits/01_version.js: package.json
echo "CRC32.version = '"`grep version package.json | awk '{gsub(/[^0-9a-z\.-]/,"",$$2); print $$2}'`"';" > $@
@@ -15,18 +25,23 @@ clean:
.PHONY: test mocha
test mocha: test.js
- mocha -R spec
+ mocha -R spec -t 20000
.PHONY: ctest
ctest:
cat misc/*.js > ctest/fixtures.js
cp -f test.js ctest/test.js
- cp -f $(TARGET) ctest/
+ cp -f $(TARGET) ctest/
.PHONY: lint
-lint: $(TARGET)
- jshint --show-non-errors $(TARGET)
- jscs $(TARGET)
+lint: $(TARGET) $(AUXTARGETS)
+ jshint --show-non-errors $(TARGET) $(AUXTARGETS)
+ jshint --show-non-errors package.json
+ jscs $(TARGET) $(AUXTARGETS)
+
+.PHONY: flow
+flow: lint
+ flow check --all --show-all-errors
.PHONY: cov cov-spin
cov: misc/coverage.html
@@ -39,11 +54,11 @@ $(COVFMT): cov_%:
FMTS=$* make cov
misc/coverage.html: $(TARGET) test.js
- mocha --require blanket -R html-cov > $@
+ mocha --require blanket -R html-cov -t 20000 > $@
.PHONY: coveralls coveralls-spin
coveralls:
- mocha --require blanket --reporter mocha-lcov-reporter | ./node_modules/coveralls/bin/coveralls.js
+ mocha --require blanket --reporter mocha-lcov-reporter -t 20000 | ./node_modules/coveralls/bin/coveralls.js
coveralls-spin:
make coveralls & bash misc/spin.sh $$!
diff --git a/README.md b/README.md
index 830cb6f..beb5476 100644
--- a/README.md
+++ b/README.md
@@ -5,59 +5,61 @@ Emphasis on correctness and performance.
## Installation
-In [nodejs](https://www.npmjs.org/package/crc-32):
+With [npm](https://www.npmjs.org/package/crc-32):
- npm install crc-32
+ $ npm install crc-32
In the browser:
-
+
-The browser exposes a variable CRC32
+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`
## Usage
-- `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)
+In all cases, the relevant function takes a single argument representing data.
+
+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.bstr(binary string)` interprets the argument as a binary string where
- the `i`-th byte is `str.charCodeAt(i)`
+ the `i`-th byte is the low byte of the UCS-2 char: `str.charCodeAt(i) & 0xFF`
- `CRC32.str(string)` interprets the argument as a standard JS string
+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
+
+> [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
-`make test` will run the nodejs-based test. To run the in-browser tests, run a
-local server and go to the `ctest` directory. To update the browser artifacts,
-run `make ctest`.
+`make test` will run the node-based tests.
-## Performance
-
-`make perf` will run algorithmic performance tests (which should justify certain
-decisions in the code).
-
-`make perf-all` compares the performance of various crc-32 algorithms that
-implement the correct form (note that the SSE intrinsic is designed for the
-CRC32C checksum and uses a different polynomial).
-
-Unexpected code patterns were based on performance testing in node and browser:
-
-- [Loop unrolling helps!](http://jsperf.com/crc32-table/2)
-
-## In the future ...
-
-- Specifying an arbitrary initial CRC value
-
-- Supporting different polynomials (e.g. CRC32C)
+To run the in-browser tests, run a local server and go to the `ctest` directory.
+To update the browser artifacts, run `make ctest`.
## License
Please consult the attached LICENSE file for details. All rights not explicitly
granted by the Apache 2.0 license are reserved by the Original Author.
+## Badges
+
[](https://travis-ci.org/SheetJS/js-crc32)
-[](https://coveralls.io/r/SheetJS/js-crc32?branch=master)
-
-[](http://githalytics.com/SheetJS/js-crc32)
+[](https://coveralls.io/r/SheetJS/js-crc32?branch=master)
+[](https://github.com/SheetJS/js-crc32)
diff --git a/bits/00_header.js b/bits/00_header.js
index b204b48..8d5d5da 100644
--- a/bits/00_header.js
+++ b/bits/00_header.js
@@ -1,4 +1,5 @@
/* crc32.js (C) 2014 SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
var CRC32 = {};
+/*:: declare var DO_NOT_EXPORT_CRC: any; */
(function(CRC32) {
diff --git a/bits/01_version.js b/bits/01_version.js
index 73f41d5..c88838f 100644
--- a/bits/01_version.js
+++ b/bits/01_version.js
@@ -1 +1 @@
-CRC32.version = '0.2.2';
+CRC32.version = '0.3.0';
diff --git a/bits/10_types.js b/bits/10_types.js
new file mode 100644
index 0000000..2d11289
--- /dev/null
+++ b/bits/10_types.js
@@ -0,0 +1,5 @@
+/*::
+type CRC32Type = number;
+type ABuf = Array | Buffer;
+type CRC32TableType = Array | Int32Array;
+*/
diff --git a/bits/20_crctable.js b/bits/20_crctable.js
index 57cdb60..cd7d108 100644
--- a/bits/20_crctable.js
+++ b/bits/20_crctable.js
@@ -1,6 +1,6 @@
/* see perf/crc32table.js */
-function signed_crc_table() {
- var c, table = new Array(256);
+function signed_crc_table()/*:CRC32TableType*/ {
+ var c = 0, table/*:Array*/ = new Array(256);
for(var n =0; n != 256; ++n){
c = n;
diff --git a/bits/40_crc.js b/bits/40_crc.js
index d378abc..cf8a719 100644
--- a/bits/40_crc.js
+++ b/bits/40_crc.js
@@ -1,7 +1,7 @@
/* charCodeAt is the best approach for binary strings */
var use_buffer = typeof Buffer !== 'undefined';
-function crc32_bstr(bstr) {
- if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(Buffer(bstr));
+function crc32_bstr(bstr/*:string*/)/*:CRC32Type*/ {
+ if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr));
var crc = -1, L = bstr.length - 1;
for(var i = 0; i < L;) {
crc = table[(crc ^ bstr.charCodeAt(i++)) & 0xFF] ^ (crc >>> 8);
@@ -11,7 +11,7 @@ function crc32_bstr(bstr) {
return crc ^ -1;
}
-function crc32_buf(buf) {
+function crc32_buf(buf/*:ABuf*/)/*:CRC32Type*/ {
if(buf.length > 10000) return crc32_buf_8(buf);
for(var crc = -1, i = 0, L=buf.length-3; i < L;) {
crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
@@ -23,7 +23,7 @@ function crc32_buf(buf) {
return crc ^ -1;
}
-function crc32_buf_8(buf) {
+function crc32_buf_8(buf/*:ABuf*/)/*:CRC32Type*/ {
for(var crc = -1, i = 0, L=buf.length-7; i < L;) {
crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
@@ -39,7 +39,7 @@ function crc32_buf_8(buf) {
}
/* much much faster to intertwine utf8 and crc */
-function crc32_str(str) {
+function crc32_str(str/*:string*/)/*:CRC32Type*/ {
for(var crc = -1, i = 0, L=str.length, c, d; i < L;) {
c = str.charCodeAt(i++);
if(c < 0x80) {
diff --git a/crc32.flow.js b/crc32.flow.js
new file mode 100644
index 0000000..8f62636
--- /dev/null
+++ b/crc32.flow.js
@@ -0,0 +1,100 @@
+/* crc32.js (C) 2014 SheetJS -- http://sheetjs.com */
+/* vim: set ts=2: */
+var CRC32 = {};
+/*:: declare var DO_NOT_EXPORT_CRC: any; */
+(function(CRC32) {
+CRC32.version = '0.3.0';
+/*::
+type CRC32Type = number;
+type ABuf = Array | Buffer;
+type CRC32TableType = Array | Int32Array;
+*/
+/* see perf/crc32table.js */
+function signed_crc_table()/*:CRC32TableType*/ {
+ var c = 0, table/*:Array*/ = new Array(256);
+
+ for(var n =0; n != 256; ++n){
+ c = n;
+ c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
+ c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
+ c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
+ c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
+ c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
+ c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
+ c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
+ c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
+ table[n] = c;
+ }
+
+ return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table;
+}
+
+var table = signed_crc_table();
+/* charCodeAt is the best approach for binary strings */
+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 crc = -1, L = bstr.length - 1;
+ for(var i = 0; i < L;) {
+ crc = table[(crc ^ bstr.charCodeAt(i++)) & 0xFF] ^ (crc >>> 8);
+ crc = table[(crc ^ bstr.charCodeAt(i++)) & 0xFF] ^ (crc >>> 8);
+ }
+ if(i === L) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i)) & 0xFF];
+ return crc ^ -1;
+}
+
+function crc32_buf(buf/*:ABuf*/)/*:CRC32Type*/ {
+ if(buf.length > 10000) return crc32_buf_8(buf);
+ for(var crc = -1, i = 0, L=buf.length-3; i < L;) {
+ crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
+ crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
+ crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
+ crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
+ }
+ while(i < L+3) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
+ return crc ^ -1;
+}
+
+function crc32_buf_8(buf/*:ABuf*/)/*:CRC32Type*/ {
+ for(var crc = -1, i = 0, L=buf.length-7; i < L;) {
+ crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
+ crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
+ crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
+ crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
+ crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
+ crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
+ crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
+ crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
+ }
+ while(i < L+7) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
+ return crc ^ -1;
+}
+
+/* much much faster to intertwine utf8 and crc */
+function crc32_str(str/*:string*/)/*:CRC32Type*/ {
+ for(var crc = -1, i = 0, L=str.length, c, d; i < L;) {
+ c = str.charCodeAt(i++);
+ if(c < 0x80) {
+ crc = (crc >>> 8) ^ table[(crc ^ 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];
+ } else if(c >= 0xD800 && c < 0xE000) {
+ c = (c&1023)+64; d = str.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];
+ } 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];
+ }
+ }
+ return crc ^ -1;
+}
+CRC32.table = table;
+CRC32.bstr = crc32_bstr;
+CRC32.buf = crc32_buf;
+CRC32.str = crc32_str;
+})(typeof exports !== "undefined" && typeof DO_NOT_EXPORT_CRC === 'undefined' ? exports : CRC32);
diff --git a/crc32.js b/crc32.js
index ea4527b..3f00ceb 100644
--- a/crc32.js
+++ b/crc32.js
@@ -2,10 +2,10 @@
/* vim: set ts=2: */
var CRC32 = {};
(function(CRC32) {
-CRC32.version = '0.2.2';
+CRC32.version = '0.3.0';
/* see perf/crc32table.js */
function signed_crc_table() {
- var c, table = new Array(256);
+ var c = 0, table = new Array(256);
for(var n =0; n != 256; ++n){
c = n;
@@ -27,7 +27,7 @@ var table = signed_crc_table();
/* charCodeAt is the best approach for binary strings */
var use_buffer = typeof Buffer !== 'undefined';
function crc32_bstr(bstr) {
- if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(Buffer(bstr));
+ if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr));
var crc = -1, L = bstr.length - 1;
for(var i = 0; i < L;) {
crc = table[(crc ^ bstr.charCodeAt(i++)) & 0xFF] ^ (crc >>> 8);
diff --git a/ctest/crc32.js b/ctest/crc32.js
index ea4527b..3f00ceb 100644
--- a/ctest/crc32.js
+++ b/ctest/crc32.js
@@ -2,10 +2,10 @@
/* vim: set ts=2: */
var CRC32 = {};
(function(CRC32) {
-CRC32.version = '0.2.2';
+CRC32.version = '0.3.0';
/* see perf/crc32table.js */
function signed_crc_table() {
- var c, table = new Array(256);
+ var c = 0, table = new Array(256);
for(var n =0; n != 256; ++n){
c = n;
@@ -27,7 +27,7 @@ var table = signed_crc_table();
/* charCodeAt is the best approach for binary strings */
var use_buffer = typeof Buffer !== 'undefined';
function crc32_bstr(bstr) {
- if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(Buffer(bstr));
+ if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr));
var crc = -1, L = bstr.length - 1;
for(var i = 0; i < L;) {
crc = table[(crc ^ bstr.charCodeAt(i++)) & 0xFF] ^ (crc >>> 8);
diff --git a/package.json b/package.json
index c0879b5..384b031 100644
--- a/package.json
+++ b/package.json
@@ -1,15 +1,13 @@
{
"name": "crc-32",
- "version": "0.2.2",
+ "version": "0.3.0",
"author": "sheetjs",
"description": "Pure-JS CRC-32",
"keywords": [ "crc32", "checksum", "crc" ],
"main": "./crc32",
"devDependencies": {
"mocha":"",
- "xlsjs":"",
- "uglify-js":"",
- "codepage":""
+ "uglify-js":""
},
"repository": { "type":"git", "url":"git://github.com/SheetJS/js-crc32.git" },
"scripts": {