version bump 0.4.1

- normalized crc iteration logic
- added browser demo
- added command line tool crc32
- fixed unicode baseline script (node 6 changed default array printing)
- fixed performance tests (benchmark module changed behavior)
- updated travis versions for test
- miscellaneous adjustments to tooling
This commit is contained in:
SheetJS 2016-06-16 16:49:46 -04:00
parent 79a265b662
commit e1c9c5e5cd
31 changed files with 805 additions and 266 deletions

@ -9,9 +9,14 @@
.*/misc/.*
.*/perf/.*
.*/demo/browser.js
[include]
crc32.flow.js
.*/demo/browser.flow.js
[libs]
bits/10_types.js
misc/flow.js
[options]

1
.gitignore vendored

@ -3,4 +3,3 @@ test_files/*.py
test_files/*.js
test_files/baseline*
misc/coverage.html
misc/*/

@ -1,16 +1,17 @@
language: node_js
node_js:
- "5.0"
- "4.2"
- "6"
- "5"
- "4"
- "0.12"
- "0.10"
- "0.8"
before_install:
- "npm install -g npm@next"
- "npm install -g mocha crc-32 benchmark ansi"
- "npm install -g mocha"
- "npm install codepage"
- "npm install blanket"
- "npm install coveralls mocha-lcov-reporter"
after_success:
- "make coveralls-spin"
- "make perf-all"
# - "make perf-all"

@ -1,79 +1,88 @@
LIB=crc32
REQS=
ADDONS=
AUXTARGETS=
AUXTARGETS=demo/browser.js
HTMLLINT=index.html
ULIB=$(shell echo $(LIB) | tr a-z A-Z)
DEPS=$(sort $(wildcard bits/*.js))
TARGET=$(LIB).js
FLOWTARGET=$(LIB).flow.js
## Main Targets
.PHONY: all
all: $(TARGET) $(AUXTARGETS)
all: $(TARGET) $(AUXTARGETS) ## Build library and auxiliary scripts
$(TARGET) $(AUXTARGETS): %.js : %.flow.js
node -e 'process.stdout.write(require("fs").readFileSync("$<","utf8").replace(/^\s*\/\*:[^*]*\*\/\s*(\n)?/gm,"").replace(/\/\*:[^*]*\*\//gm,""))' > $@
node -e 'process.stdout.write(require("fs").readFileSync("$<","utf8").replace(/^[ \t]*\/\*[:#][^*]*\*\/\s*(\n)?/gm,"").replace(/\/\*[:#][^*]*\*\//gm,""))' > $@
$(LIB).flow.js: $(DEPS)
$(FLOWTARGET): $(DEPS)
cat $^ | tr -d '\15\32' > $@
bits/01_version.js: package.json
echo "CRC32.version = '"`grep version package.json | awk '{gsub(/[^0-9a-z\.-]/,"",$$2); print $$2}'`"';" > $@
.PHONY: clean
clean: clean-baseline
rm -f $(TARGET)
clean: clean-baseline ## Remove targets and build artifacts
rm -f $(TARGET) $(FLOWTARGET)
## Testing
.PHONY: test mocha
test mocha: test.js $(TARGET) baseline
test mocha: test.js $(TARGET) baseline ## Run test suite
mocha -R spec -t 20000
.PHONY: ctest
ctest:
ctest: ## Build browser test (into ctest/ subdirectory)
cat misc/*.js > ctest/fixtures.js
cp -f test.js ctest/test.js
cp -f $(TARGET) ctest/
.PHONY: ctestserv
ctestserv: ## Start a test server on port 8000
@cd ctest && python -mSimpleHTTPServer
.PHONY: baseline
baseline: ## Build test baselines
@bash ./misc/make_baseline.sh
.PHONY: clean-baseline
clean-baseline: ## Remove test baselines
@bash ./misc/make_baseline.sh clean
## Code Checking
.PHONY: lint
lint: $(TARGET) $(AUXTARGETS)
jshint --show-non-errors $(TARGET) $(AUXTARGETS)
jshint --show-non-errors package.json
jscs $(TARGET) $(AUXTARGETS)
lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks
@jshint --show-non-errors $(TARGET) $(AUXTARGETS)
@jshint --show-non-errors package.json
@jshint --show-non-errors --extract=always $(HTMLLINT)
@jscs $(TARGET) $(AUXTARGETS)
.PHONY: flow
flow: lint
flow check --all --show-all-errors
flow: lint ## Run flow checker
@flow check --all --show-all-errors
.PHONY: cov cov-spin
cov: misc/coverage.html
cov-spin:
make cov & bash misc/spin.sh $$!
COVFMT=$(patsubst %,cov_%,$(FMT))
.PHONY: $(COVFMT)
$(COVFMT): cov_%:
FMTS=$* make cov
.PHONY: cov
cov: misc/coverage.html ## Run coverage test
misc/coverage.html: $(TARGET) test.js
mocha --require blanket -R html-cov -t 20000 > $@
.PHONY: coveralls coveralls-spin
coveralls:
mocha --require blanket --reporter mocha-lcov-reporter -t 20000 | ./node_modules/coveralls/bin/coveralls.js
coveralls-spin:
make coveralls & bash misc/spin.sh $$!
.PHONY: coveralls
coveralls: ## Coverage Test + Send to coveralls.io
mocha --require blanket --reporter mocha-lcov-reporter -t 20000 | node ./node_modules/coveralls/bin/coveralls.js
.PHONY: perf
perf:
bash perf/perf.sh
perf: ## Run Performance Tests
@bash perf/perf.sh
.PHONY: perf-all
perf-all:
bash misc/perf.sh
.PHONY: baseline clean-baseline
baseline:
./misc/make_baseline.sh
.PHONY: help
help:
@grep -hE '(^[a-zA-Z_-][ a-zA-Z_-]*:.*?|^#[#*])' $(MAKEFILE_LIST) | bash misc/help.sh
clean-baseline:
rm -f test_files/*.*
#* To show a spinner, append "-spin" to any target e.g. cov-spin
%-spin:
@make $* & bash misc/spin.sh $$!

@ -13,6 +13,11 @@ In the browser:
<script src="crc32.js"></script>
The browser exposes a variable ADLER32
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`
@ -46,13 +51,47 @@ For example:
## Testing
`make test` will run the node-based tests.
`make test` will run the nodejs-based test.
To run the in-browser tests, run a local server and go to the `ctest` directory.
`make ctestserv` will start a python `SimpleHTTPServer` server on port 8000.
To update the browser artifacts, run `make ctest`.
`make baseline` will generate baseline files based on the unicode mapping at
<http://mathias.html5.org>
To generate the bits file, use the `crc32` function from python zlib:
```python
>>> from zlib import crc32
>>> x="foo bar baz٪☃🍣"
>>> crc32(x)
1531648243
>>> crc32(x+x)
-218791105
>>> crc32(x+x+x)
1834240887
```
The included `crc32.njs` script can process files or stdin:
```
$ echo "this is a test" > t.txt
$ bin/crc32.njs t.txt
1912935186
```
For comparison, the included `crc32.py` script uses python zlib:
```
$ bin/crc32.py t.txt
1912935186
```
## Performance
`make perf` will run algorithmic performance tests (which should justify certain
decisions in the code).
[js-adler32](http://git.io/adler32) has more performance notes
## License

37
bin/crc32.njs Executable file

@ -0,0 +1,37 @@
#!/usr/bin/env node
/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2 ft=javascript: */
var X;
try { X = require('../'); } catch(e) { X = require('crc-32'); }
var fs = require('fs');
require('exit-on-epipe');
var args = process.argv.slice(2);
var filename;
if(args[0]) filename = args[0];
if(!process.stdin.isTTY) filename = filename || "-";
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);
}
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));
}

15
bin/crc32.py Executable file

@ -0,0 +1,15 @@
#!/usr/bin/env python
# crc32.py -- calculate crc32 checksum of data
# Copyright (C) 2016-present SheetJS
from zlib import crc32
from sys import argv, stdin
args=argv[1:]
payload=""
if len(args) == 0 or args[0] == "-":
payload = stdin.read()
else:
payload = open(args[0],"rb").read()
# NOTE: python 2 returns a signed value; python3 is unsigned
print crc32(payload)

@ -1,9 +1,11 @@
/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*exported CRC32 */
var CRC32;
/*:: declare var DO_NOT_EXPORT_CRC: any; */
/*:: declare var define: any; */
(function (factory) {
/*jshint ignore:start */
if(typeof DO_NOT_EXPORT_CRC === 'undefined') {
if('object' === typeof exports) {
factory(exports);
@ -19,4 +21,5 @@ var CRC32;
} else {
factory(CRC32 = {});
}
/*jshint ignore:end */
}(function(CRC32) {

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

@ -1,4 +1,5 @@
/* see perf/crc32table.js */
/*global Int32Array */
function signed_crc_table()/*:CRC32TableType*/ {
var c = 0, table/*:Array<number>*/ = new Array(256);
@ -18,4 +19,4 @@ function signed_crc_table()/*:CRC32TableType*/ {
return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table;
}
var table = signed_crc_table();
var T = signed_crc_table();

@ -1,63 +1,67 @@
/* charCodeAt is the best approach for binary strings */
/*# 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 crc = -1, L = bstr.length - 1;
var C = -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);
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
}
if(i === L) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i)) & 0xFF];
return crc ^ -1;
if(i === L) C = (C>>>8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF];
return C ^ -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];
var C = -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];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
}
while(i < L+3) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
return crc ^ -1;
while(i < L+3) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
return C ^ -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];
var C = -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];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
}
while(i < L+7) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
return crc ^ -1;
while(i < L+7) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
return C ^ -1;
}
/* much much faster to intertwine utf8 and crc */
/*# much much faster to intertwine utf8 and C */
function crc32_str(str/*:string*/)/*:CRC32Type*/ {
for(var crc = -1, i = 0, L=str.length, c, d; i < L;) {
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 = 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)<<4))) & 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;
}

@ -1,4 +1,4 @@
CRC32.table = table;
CRC32.table = T;
CRC32.bstr = crc32_bstr;
CRC32.buf = crc32_buf;
CRC32.str = crc32_str;

@ -1,9 +1,11 @@
/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*exported CRC32 */
var CRC32;
/*:: declare var DO_NOT_EXPORT_CRC: any; */
/*:: declare var define: any; */
(function (factory) {
/*jshint ignore:start */
if(typeof DO_NOT_EXPORT_CRC === 'undefined') {
if('object' === typeof exports) {
factory(exports);
@ -19,14 +21,16 @@ var CRC32;
} else {
factory(CRC32 = {});
}
/*jshint ignore:end */
}(function(CRC32) {
CRC32.version = '0.4.0';
CRC32.version = '0.4.1';
/*::
type CRC32Type = number;
type ABuf = Array<number> | Buffer;
type CRC32TableType = Array<number> | Int32Array;
*/
/* see perf/crc32table.js */
/*global Int32Array */
function signed_crc_table()/*:CRC32TableType*/ {
var c = 0, table/*:Array<number>*/ = new Array(256);
@ -46,71 +50,75 @@ function signed_crc_table()/*:CRC32TableType*/ {
return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table;
}
var table = signed_crc_table();
/* charCodeAt is the best approach for binary strings */
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 crc = -1, L = bstr.length - 1;
var C = -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);
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
}
if(i === L) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i)) & 0xFF];
return crc ^ -1;
if(i === L) C = (C>>>8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF];
return C ^ -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];
var C = -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];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
}
while(i < L+3) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
return crc ^ -1;
while(i < L+3) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
return C ^ -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];
var C = -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];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
}
while(i < L+7) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
return crc ^ -1;
while(i < L+7) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
return C ^ -1;
}
/* much much faster to intertwine utf8 and crc */
/*# much much faster to intertwine utf8 and C */
function crc32_str(str/*:string*/)/*:CRC32Type*/ {
for(var crc = -1, i = 0, L=str.length, c, d; i < L;) {
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 = 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)<<4))) & 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;
}
CRC32.table = table;
CRC32.table = T;
CRC32.bstr = crc32_bstr;
CRC32.buf = crc32_buf;
CRC32.str = crc32_str;

@ -1,7 +1,9 @@
/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*exported CRC32 */
var CRC32;
(function (factory) {
/*jshint ignore:start */
if(typeof DO_NOT_EXPORT_CRC === 'undefined') {
if('object' === typeof exports) {
factory(exports);
@ -17,9 +19,11 @@ var CRC32;
} else {
factory(CRC32 = {});
}
/*jshint ignore:end */
}(function(CRC32) {
CRC32.version = '0.4.0';
CRC32.version = '0.4.1';
/* see perf/crc32table.js */
/*global Int32Array */
function signed_crc_table() {
var c = 0, table = new Array(256);
@ -39,71 +43,73 @@ function signed_crc_table() {
return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table;
}
var table = signed_crc_table();
/* charCodeAt is the best approach for binary strings */
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 crc = -1, L = bstr.length - 1;
var C = -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);
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
}
if(i === L) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i)) & 0xFF];
return crc ^ -1;
if(i === L) C = (C>>>8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF];
return C ^ -1;
}
function crc32_buf(buf) {
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];
var C = -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];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
}
while(i < L+3) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
return crc ^ -1;
while(i < L+3) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
return C ^ -1;
}
function crc32_buf_8(buf) {
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];
var C = -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];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
}
while(i < L+7) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
return crc ^ -1;
while(i < L+7) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
return C ^ -1;
}
/* much much faster to intertwine utf8 and crc */
function crc32_str(str) {
for(var crc = -1, i = 0, L=str.length, c, d; i < L;) {
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 = 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)<<4))) & 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;
}
CRC32.table = table;
CRC32.table = T;
CRC32.bstr = crc32_bstr;
CRC32.buf = crc32_buf;
CRC32.str = crc32_str;

@ -1,7 +1,9 @@
/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*exported CRC32 */
var CRC32;
(function (factory) {
/*jshint ignore:start */
if(typeof DO_NOT_EXPORT_CRC === 'undefined') {
if('object' === typeof exports) {
factory(exports);
@ -17,9 +19,11 @@ var CRC32;
} else {
factory(CRC32 = {});
}
/*jshint ignore:end */
}(function(CRC32) {
CRC32.version = '0.4.0';
CRC32.version = '0.4.1';
/* see perf/crc32table.js */
/*global Int32Array */
function signed_crc_table() {
var c = 0, table = new Array(256);
@ -39,71 +43,73 @@ function signed_crc_table() {
return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table;
}
var table = signed_crc_table();
/* charCodeAt is the best approach for binary strings */
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 crc = -1, L = bstr.length - 1;
var C = -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);
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
}
if(i === L) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i)) & 0xFF];
return crc ^ -1;
if(i === L) C = (C>>>8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF];
return C ^ -1;
}
function crc32_buf(buf) {
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];
var C = -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];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
}
while(i < L+3) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
return crc ^ -1;
while(i < L+3) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
return C ^ -1;
}
function crc32_buf_8(buf) {
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];
var C = -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];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
}
while(i < L+7) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF];
return crc ^ -1;
while(i < L+7) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
return C ^ -1;
}
/* much much faster to intertwine utf8 and crc */
function crc32_str(str) {
for(var crc = -1, i = 0, L=str.length, c, d; i < L;) {
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 = 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)<<4))) & 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;
}
CRC32.table = table;
CRC32.table = T;
CRC32.bstr = crc32_bstr;
CRC32.buf = crc32_buf;
CRC32.str = crc32_str;

@ -1,13 +1,27 @@
var o = "foo bar baz٪☃🍣";
var m = "foobar"; for(var i = 0; i != 11; ++i) m+=m;
var bits = [
[ "foobar", -1628037227, 1 ],
[ "foo bar baz", -228401567, 1 ],
[ "foo bar baz٪", 984445192 ],
[ "foo bar baz٪☃", 140429620],
[ "foo bar baz٪☃🍣", 1531648243],
[ m, 40270464, 1 ]
[ m, 40270464, 1 ],
[ o, 1531648243],
[ o+o, -218791105 ],
[ o+o+o, 1834240887 ]
];
if(typeof module !== "undefined") module.exports = bits;
/*::
type ArrayLike = any;
type Stringifier = {(d:ArrayLike):string};
declare class CRC32Module {
table:CRC32TableType;
bstr(s:string):CRC32Type;
buf(b:ABuf):CRC32Type;
str(s:string):CRC32Type;
};
*/
/* vim: set ts=2: */
if(typeof require !== 'undefined') {
var js_crc32 = require('../');

@ -8,45 +8,59 @@ if(typeof require !== 'undefined') {
fs = require("fs");
} else { X = CRC32; }
function readlines(f) { return fs.readFileSync(f, "ascii").split("\n").filter(function(f) { return !!f; }); }
function readlines(f) { return fs.readFileSync(f, "ascii").split("\n"); }
describe('crc32 table', function() {
it('should match fixed table', function() {
var badness = 0;
var overflow = 0;
for(var i = 0; i != crc32table.length; ++i) {
assert.equal(crc32table[i]|0, X.table[i]);
if(crc32table[i] !== X.table[i]) ++badness;
if(crc32table[i] !== X.table[i]) ++overflow;
}
assert.equal(badness, 128);
assert.equal(overflow, 128);
});
});
describe('crc32 bits', function() {
bits.forEach(function(i) {
var l = i[0].length;
var msg = i[0];
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);
it(msg, function() {
if(i[2] === 1) assert.equal(X.bstr(i[0]), i[1]|0);
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])), i[1]|0);
if(typeof Buffer !== 'undefined') assert.equal(X.buf(new Buffer(i[0])), L);
});
});
});
if(typeof require !== 'undefined') describe("unicode", function() {
if(!fs.existsSync("./test_files/uccat.txt")) return;;
if(!fs.existsSync("./test_files/uccat.txt")) return;
var uccat = readlines("./test_files/uccat.txt");
uccat.forEach(function(cat) {
it("Category " + cat, function() {
if(!fs.existsSync("./test_files/baseline." + cat + ".txt")) return;
var corpus = readlines("./test_files/baseline." + cat + ".txt");
var uctable = require("./test_files/uctable." + cat + ".js");
uctable.forEach(function(c, i) {
for(var ucidx = 0; ucidx < uctable.length; ++ucidx) {
var c = uctable[ucidx];
/* since the baselines are passed via utf8, discard invalid codes */
if(c.charCodeAt(0) >= 0xD800 && c.charCodeAt(0) < 0xE000) return;
var cc = corpus[i], dd = X.str(c);
assert.equal(dd, cc, ":" + i + ":" + c + ":" + cc + ":" + dd);
});
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 ff = X.bstr(String.fromCharCode.apply(null, new Buffer(c, "utf8")));
assert.equal(ff, cc, ":" + ucidx + ":" + c + ":" + cc + ":" + ff);
}
};
});
});
});
if(typeof require !== 'undefined') describe("corpora", function() {
require("./test_files/corpus.json").forEach(function(text) {
if(!fs.existsSync(text[1])) return;
it("should match '" + text[0] + "' (" + text[2] + ")", function() {
assert.equal(text[2], X.buf(fs.readFileSync(text[1])));
});
});
});

117
demo/browser.flow.js Normal file

@ -0,0 +1,117 @@
/*jshint browser:true */
/*global CRC32, console */
/*:: declare var CRC32: CRC32Module; */
var X = CRC32;
function console_log() { if(typeof console !== 'undefined') console.log.apply(console, [].slice.call(arguments)); }
function lpad(s/*:string*/, len/*:number*/, chr/*:?string*/)/*:string*/{
var L/*:number*/ = len - s.length, C/*:string*/ = chr || " ";
if(L <= 0) return s;
return new Array(L+1).join(C) + s;
}
function is_defined(val/*:any*/, keys/*:Array<string>*/)/*:boolean*/ {
if(typeof val === "undefined") return false;
return keys.length === 0 || is_defined(val[keys[0]], keys.slice(1));
}
/*# buffer to string; IE String.fromCharCode.apply limit, manual chunk */
function make_chunk_buf_to_str(BType/*:function*/)/*:Stringifier*/ {
return function(data/*:any*/)/*:string*/ {
var o = "", l = 0, w = 10240, L = data.byteLength/w;
for(; l<L; ++l) o+=String.fromCharCode.apply(null, ((new BType(data.slice(l*w,l*w+w)))/*:any*/));
o+=String.fromCharCode.apply(null, ((new BType(data.slice(l*w)))/*:any*/));
return o;
};
}
/*# buffer to binary string */
var bstrify/*:Stringifier*/ = make_chunk_buf_to_str(Uint8Array);
/*# readAsBinaryString support */
var rABS/*:boolean*/ = is_defined(FileReader, ['prototype', 'readAsBinaryString']);
var userABS/*:HTMLInputElement*/ = (document.getElementsByName("userabs")[0]/*:any*/);
if(!rABS) {
userABS.disabled = true;
userABS.checked = false;
}
/*## Process Result */
/*:: declare class HTMLPreElement extends HTMLElement { innerText:string; } */
function process_value(val/*:CRC32Type*/) {
var output = [];
output[0] = "Signed : " + val;
output[1] = "Unsigned : " + (val>>>0);
output[2] = "Hex value : " + lpad((val>>>0).toString(16),8,'0');
var out/*:HTMLPreElement*/ = (document.getElementById('out')/*:any*/);
var o = output.join("\n");
if(typeof out.innerText == "undefined") out.textContent = o;
else out.innerText = o;
console_log("output", new Date());
}
/*## Raw Text */
var dotxt/*:HTMLInputElement*/ = (document.getElementById('dotext')/*:any*/);
dotxt.onclick = function() {
var txt/*:HTMLTextAreaElement*/=(document.getElementById('rawdata')/*:any*/);
console_log("onload", new Date());
var wb/*:CRC32Type*/ = X.str(txt.value);
process_value(wb);
};
/*# HTML5 */
var readcb = function(e/*:Event*/) {
console_log("onload", new Date(), rABS, false);
var target/*:FileReader*/ = (e.target/*:any*/);
var data = target.result;
var val/*:CRC32Type*/ = rABS ? X.bstr(data) : X.str(bstrify(data));
process_value(val);
};
/*## File Input */
var handle_file = function(e/*:Event*/) {
rABS = userABS.checked;
var otarget/*:HTMLInputElement*/ = (e.target/*:any*/);
var files/*:FileList*/ = otarget.files;
var f/*:File*/ = files[0];
var reader/*:FileReader*/ = new FileReader();
reader.onload = readcb;
if(rABS) (reader/*:any*/).readAsBinaryString(f);
else reader.readAsArrayBuffer(f);
};
var xlf/*:HTMLInputElement*/ = (document.getElementById('xlf')/*:any*/);
if(xlf.addEventListener) xlf.addEventListener('change', handle_file, false);
/*## Drag and Drop File */
var handle_drop/*:EventHandler*/ = (function(e/*:DragEvent*/) {
e.stopPropagation();
e.preventDefault();
rABS = userABS.checked;
if(!e.dataTransfer) return;
var files/*:FileList*/ = e.dataTransfer.files;
var f/*:File*/ = files[0];
var reader/*:FileReader*/ = new FileReader();
reader.onload = readcb;
if(rABS) (reader/*:any*/).readAsBinaryString(f);
else reader.readAsArrayBuffer(f);
}/*:any*/);
var handle_drag/*:EventHandler*/ = (function (e/*:DragEvent*/) {
e.stopPropagation();
e.preventDefault();
if(e.dataTransfer) e.dataTransfer.dropEffect = 'copy';
}/*:any*/);
var drop/*:HTMLDivElement*/ = (document.getElementById('drop')/*:any*/);
if(drop.addEventListener) {
drop.addEventListener('dragenter', handle_drag, false);
drop.addEventListener('dragover', handle_drag, false);
drop.addEventListener('drop', handle_drop, false);
}

106
demo/browser.js Normal file

@ -0,0 +1,106 @@
/*jshint browser:true */
/*global CRC32, console */
var X = CRC32;
function console_log() { if(typeof console !== 'undefined') console.log.apply(console, [].slice.call(arguments)); }
function lpad(s, len, chr){
var L = len - s.length, C = chr || " ";
if(L <= 0) return s;
return new Array(L+1).join(C) + s;
}
function is_defined(val, keys) {
if(typeof val === "undefined") return false;
return keys.length === 0 || is_defined(val[keys[0]], keys.slice(1));
}
function make_chunk_buf_to_str(BType) {
return function(data) {
var o = "", l = 0, w = 10240, L = data.byteLength/w;
for(; l<L; ++l) o+=String.fromCharCode.apply(null, ((new BType(data.slice(l*w,l*w+w)))));
o+=String.fromCharCode.apply(null, ((new BType(data.slice(l*w)))));
return o;
};
}
var bstrify = make_chunk_buf_to_str(Uint8Array);
var rABS = is_defined(FileReader, ['prototype', 'readAsBinaryString']);
var userABS = (document.getElementsByName("userabs")[0]);
if(!rABS) {
userABS.disabled = true;
userABS.checked = false;
}
function process_value(val) {
var output = [];
output[0] = "Signed : " + val;
output[1] = "Unsigned : " + (val>>>0);
output[2] = "Hex value : " + lpad((val>>>0).toString(16),8,'0');
var out = (document.getElementById('out'));
var o = output.join("\n");
if(typeof out.innerText == "undefined") out.textContent = o;
else out.innerText = o;
console_log("output", new Date());
}
var dotxt = (document.getElementById('dotext'));
dotxt.onclick = function() {
var txt=(document.getElementById('rawdata'));
console_log("onload", new Date());
var wb = X.str(txt.value);
process_value(wb);
};
var readcb = function(e) {
console_log("onload", new Date(), rABS, false);
var target = (e.target);
var data = target.result;
var val = rABS ? X.bstr(data) : X.str(bstrify(data));
process_value(val);
};
var handle_file = function(e) {
rABS = userABS.checked;
var otarget = (e.target);
var files = otarget.files;
var f = files[0];
var reader = new FileReader();
reader.onload = readcb;
if(rABS) (reader).readAsBinaryString(f);
else reader.readAsArrayBuffer(f);
};
var xlf = (document.getElementById('xlf'));
if(xlf.addEventListener) xlf.addEventListener('change', handle_file, false);
var handle_drop = (function(e) {
e.stopPropagation();
e.preventDefault();
rABS = userABS.checked;
if(!e.dataTransfer) return;
var files = e.dataTransfer.files;
var f = files[0];
var reader = new FileReader();
reader.onload = readcb;
if(rABS) (reader).readAsBinaryString(f);
else reader.readAsArrayBuffer(f);
});
var handle_drag = (function (e) {
e.stopPropagation();
e.preventDefault();
if(e.dataTransfer) e.dataTransfer.dropEffect = 'copy';
});
var drop = (document.getElementById('drop'));
if(drop.addEventListener) {
drop.addEventListener('dragenter', handle_drag, false);
drop.addEventListener('dragover', handle_drag, false);
drop.addEventListener('drop', handle_drop, false);
}

51
index.html Normal file

@ -0,0 +1,51 @@
<!DOCTYPE html>
<!-- crc32.js (C) 2014-present SheetJS http://sheetjs.com -->
<!-- vim: set ts=2: -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>JS-CRC32 Live Demo</title>
<style>
#drop{
border:2px dashed #bbb;
-moz-border-radius:5px;
-webkit-border-radius:5px;
border-radius:5px;
padding:25px;
text-align:center;
font:20pt bold,"Vollkorn";color:#bbb
}
#rawdata{
width:100%;
}
</style>
</head>
<body>
<b>JS-CRC32 Live Demo</b><br />
<a href="https://git.io/crc32">Source Code Repo</a><br />
<a href="https://git.io/crc32_issues">Issues? Something look weird? Click here and report an issue</a><br />
<div id="drop">Drop a text file to compute the CRC-32 checksum</div>
<p><input type="file" name="xlfile" id="xlf" /> ... or click here to select a file</p>
<textarea id="rawdata">... or paste text here ......</textarea>
<input type="button" id="dotext" value="Click here to process the text"/><br />
Advanced Demo Options: <br />
Use readAsBinaryString: (when available) <input type="checkbox" name="userabs" checked><br />
<pre id="out">.</pre>
<br />
<script type="text/javascript">/* jshint browser: true */</script>
<script src="crc32.js"></script>
<script src="demo/browser.flow.js"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-36810333-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body>
</html>

@ -1,10 +1,13 @@
var o = "foo bar baz٪☃🍣";
var m = "foobar"; for(var i = 0; i != 11; ++i) m+=m;
var bits = [
[ "foobar", -1628037227, 1 ],
[ "foo bar baz", -228401567, 1 ],
[ "foo bar baz٪", 984445192 ],
[ "foo bar baz٪☃", 140429620],
[ "foo bar baz٪☃🍣", 1531648243],
[ m, 40270464, 1 ]
[ m, 40270464, 1 ],
[ o, 1531648243],
[ o+o, -218791105 ],
[ o+o+o, 1834240887 ]
];
if(typeof module !== "undefined") module.exports = bits;

11
misc/flow.js Normal file

@ -0,0 +1,11 @@
/*::
type ArrayLike = any;
type Stringifier = {(d:ArrayLike):string};
declare class CRC32Module {
table:CRC32TableType;
bstr(s:string):CRC32Type;
buf(b:ABuf):CRC32Type;
str(s:string):CRC32Type;
};
*/

42
misc/help.sh Executable file

@ -0,0 +1,42 @@
#!/bin/bash
# make_help.sh -- process listing of targets and special items in Makefile
# Copyright (C) 2016-present SheetJS
#
# usage in makefile: pipe the output of the following command:
# @grep -hE '(^[a-zA-Z_-][ a-zA-Z_-]*:.*?|^#[#*])' $(MAKEFILE_LIST)
#
# lines starting with "## " are treated as subtitles
# lines starting with "#* " are treated as plaintext comments
# multiple targets with "## " after the ":" are rendered as separate targets
# if the presumed default target is labeled, it will be assigned a unique color
awk '
BEGIN{recipes=0;}
!/#[#*] .*$/ {next;}
{multi=0; isrecipe=0;}
/^[^#]*:/ {isrecipe=1; ++recipes;}
/^[^ :]* .*:/ {multi=1}
multi==0 && isrecipe>0 { if(recipes > 1) print; else print $0, "[default]"; next}
isrecipe == 0 {print; next}
multi>0 {
k=split($0, msg, "##"); m=split($0, a, ":"); n=split(a[1], b, " ");
for(i=1; i<=n; ++i) print b[i] ":", "##" msg[2], (recipes==1 && i==1 ? "[default]" : "")
}
END {}
' | if [[ -t 1 ]]; then
awk '
BEGIN {FS = ":.*?## "}
{color=36}
/\[default\]/ {color=35}
NF==1 && /^##/ {color=34}
NF==1 && /^#\*/ {color=20; $1 = substr($1, 4)}
{printf "\033[" color "m%-20s\033[0m %s\n", $1, $2;}
END{}' -
else
awk '
BEGIN {FS = ":.*?## "}
/^#\* / {$1 = substr($1, 4)}
{printf "%-20s %s\n", $1, $2;}
END{}' -
fi

@ -5,35 +5,44 @@ OUTD=../test_files
CATURL=https://mathias.html5.org/data/unicode/8.0.0/categories/
CATF=$OUTD/uccat.txt
ECHORED() { echo -ne '\x1B[0;31m'; echo -n $1; echo -ne '\x1B[0m'; echo; }
ECHORED() { echo -ne '\x1B[0;31m'; echo -n "$1"; echo -ne '\x1B[0m'; echo; }
if [[ "$1" == "clean" ]]; then
if [ ! -d test_files ]; then cd ..; fi
if [ -d test_files ]; then cd test_files; fi
rm -f uccat.txt baseline.*.txt uctable.*.js uctable_*.py
exit
fi
# shellcheck disable=SC2164
if [ -d misc ]; then cd misc; fi
mkdir -p $OUTD
if [ ! -e $CATF ]; then curl "$CATURL" | grep "code-points" | sed 's/.*="//g;s/-.*//g' > $CATF; fi
while read line; do
while read -r line; do
JSF=uctable.${line}.js
PYF=uctable_${line}.py
BLF=baseline.${line}.txt
JSURL="https://mathias.html5.org/data/unicode/format?version=8.0.0&category=${line}&type=symbols&prepend=var+unicode%20%3D%20&append=%3Bif(typeof%20module%20!%3D%3D%20'undefined')%20module.exports%20%3D%20unicode%3B"
if [[ ! -e $OUTD/$JSF || ! -e $OUTD/$PYF || ! -e $OUTD/$BLF ]]; then
ECHORED "Processing ${line}"
if [ ! -e $JSF ]; then
rm -f $PYF $BLF ${PYF}c
for i in $JSF $PYF $BLF; do if [[ ! -e $i && -e $OUTD/$i ]]; then mv $OUTD/"$i" .; fi done
if [ ! -e "$JSF" ]; then
rm -f "$PYF" "$BLF" "${PYF}c"
echo "Downloading JS"
</dev/null curl -o $JSF "$JSURL"
</dev/null curl -o "$JSF" "$JSURL"
fi
if [ ! -e $PYF ]; then
if [ ! -e "$PYF" ]; then
echo "Building Python script"
rm -f $BLF ${PYF}c
</dev/null node make_unicode_crc.njs ${line} | sed 's/\[ \[/uctable = \[ \[/' > $PYF
rm -f "$BLF" "${PYF}c"
</dev/null node make_unicode.njs "${line}" | sed 's/\[ \[/uctable = \[ \[/' > "$PYF"
fi
if [ ! -e $BLF ]; then
if [ ! -e "$BLF" ]; then
echo "Building Baseline text"
python make_unicode_crc.py ${line} > baseline.${line}.txt
python make_unicode_crc.py "${line}" > "baseline.${line}.txt"
fi
for i in $JSF $PYF $BLF; do if [ -e $i ]; then mv $i $OUTD/; fi; done
rm -f uctable_${line}.pyc
for i in $JSF $PYF $BLF; do if [ -e "$i" ]; then mv "$i" $OUTD/; fi; done
rm -f "uctable_${line}.pyc"
fi
done < $CATF

14
misc/make_unicode.njs Normal file

@ -0,0 +1,14 @@
#!/usr/bin/env node
/* make_unicode.njs -- generate baselines for tests
* Copyright (C) 2016-present SheetJS
* vim: set ft=javascript: */
var argv = process.argv.slice(2);
var enc = require('codepage').utils.encode;
function arr(x) { return [].slice.call(enc(65001, x)); }
var o = require('./uctable.' + argv[0]).map(arr);
/* node 6 changed default behavior for arrays */
if(+process.version.replace(/v(\d)+\..*/,"$1") >= 6) o = require("util").inspect(o, {maxArrayLength: null});
console.log(o);

@ -1,5 +0,0 @@
#!/usr/bin/env node
argv = process.argv.slice(2);
var enc = require('codepage').utils.encode;
function arr(x) { return [].slice.call(enc(65001, x)); }
console.log(require('./uctable.' + argv[0]).map(arr));

@ -1,14 +1,20 @@
{
"name": "crc-32",
"version": "0.4.0",
"version": "0.4.1",
"author": "sheetjs",
"description": "Pure-JS CRC-32",
"keywords": [ "crc32", "checksum", "crc" ],
"bin": {
"crc32": "./bin/crc32.njs"
},
"main": "./crc32",
"dependencies": {
"concat-stream":"",
"exit-on-epipe":""
},
"devDependencies": {
"codepage":"",
"mocha":"",
"uglify-js":""
"codepage":""
},
"repository": { "type":"git", "url":"git://github.com/SheetJS/js-crc32.git" },
"scripts": {
@ -20,6 +26,7 @@
"pattern": "crc32.js"
}
},
"files": ["crc32.js", "bin/crc32.njs", "LICENSE", "README.md"],
"bugs": { "url": "https://github.com/SheetJS/js-crc32/issues" },
"license": "Apache-2.0",
"engines": { "node": ">=0.8" }

@ -4,7 +4,11 @@ var c = require('ansi')(process.stdout);
function test_end(e) { c.horizontalAbsolute(0).write("✓ "+e.target); c.write('\n'); }
function suite_end() { console.log('Fastest is ' + this.filter('fastest').pluck('name')); }
function suite_end() {
var o = this.filter('fastest');
var m = typeof o.pluck === 'undefined' ? o.map('name') : o.pluck('name');
console.log('Fastest is ' + m);
}
function test_cycle(e) { c.horizontalAbsolute(0); c.eraseLine(); c.write("→ "+e.target); }
@ -25,9 +29,9 @@ BM.prototype.run = function(skip) {
BM.prototype.add = function(msg, test) {
this.suites.push([msg, {
onCycle: test_cycle,
onCycle: test_cycle,
onComplete: test_end,
defer: false,
defer: false,
fn: test
}]);
this.maxlen = Math.max(this.maxlen, msg.length);

42
test.js

@ -8,45 +8,59 @@ if(typeof require !== 'undefined') {
fs = require("fs");
} else { X = CRC32; }
function readlines(f) { return fs.readFileSync(f, "ascii").split("\n").filter(function(f) { return !!f; }); }
function readlines(f) { return fs.readFileSync(f, "ascii").split("\n"); }
describe('crc32 table', function() {
it('should match fixed table', function() {
var badness = 0;
var overflow = 0;
for(var i = 0; i != crc32table.length; ++i) {
assert.equal(crc32table[i]|0, X.table[i]);
if(crc32table[i] !== X.table[i]) ++badness;
if(crc32table[i] !== X.table[i]) ++overflow;
}
assert.equal(badness, 128);
assert.equal(overflow, 128);
});
});
describe('crc32 bits', function() {
bits.forEach(function(i) {
var l = i[0].length;
var msg = i[0];
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);
it(msg, function() {
if(i[2] === 1) assert.equal(X.bstr(i[0]), i[1]|0);
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])), i[1]|0);
if(typeof Buffer !== 'undefined') assert.equal(X.buf(new Buffer(i[0])), L);
});
});
});
if(typeof require !== 'undefined') describe("unicode", function() {
if(!fs.existsSync("./test_files/uccat.txt")) return;;
if(!fs.existsSync("./test_files/uccat.txt")) return;
var uccat = readlines("./test_files/uccat.txt");
uccat.forEach(function(cat) {
it("Category " + cat, function() {
if(!fs.existsSync("./test_files/baseline." + cat + ".txt")) return;
var corpus = readlines("./test_files/baseline." + cat + ".txt");
var uctable = require("./test_files/uctable." + cat + ".js");
uctable.forEach(function(c, i) {
for(var ucidx = 0; ucidx < uctable.length; ++ucidx) {
var c = uctable[ucidx];
/* since the baselines are passed via utf8, discard invalid codes */
if(c.charCodeAt(0) >= 0xD800 && c.charCodeAt(0) < 0xE000) return;
var cc = corpus[i], dd = X.str(c);
assert.equal(dd, cc, ":" + i + ":" + c + ":" + cc + ":" + dd);
});
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 ff = X.bstr(String.fromCharCode.apply(null, new Buffer(c, "utf8")));
assert.equal(ff, cc, ":" + ucidx + ":" + c + ":" + cc + ":" + ff);
}
};
});
});
});
if(typeof require !== 'undefined') describe("corpora", function() {
require("./test_files/corpus.json").forEach(function(text) {
if(!fs.existsSync(text[1])) return;
it("should match '" + text[0] + "' (" + text[2] + ")", function() {
assert.equal(text[2], X.buf(fs.readFileSync(text[1])));
});
});
});

3
test_files/corpus.json Normal file

@ -0,0 +1,3 @@
[
["UTF-8 Corpus", "./test_files/utf8.corpus", -106649927]
]

2
test_files/utf8.corpus Normal file

File diff suppressed because one or more lines are too long