diff --git a/Makefile b/Makefile index cee5833..eb26e01 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ LIB=crc32 REQS= ADDONS= -AUXTARGETS=demo/browser.js +AUXTARGETS=crc32c.js demo/browser.js CMDS=bin/crc32.njs HTMLLINT=index.html @@ -30,6 +30,9 @@ bits/01_version.js: package.json clean: clean-baseline ## Remove targets and build artifacts rm -f $(TARGET) $(FLOWTARGET) +crc32c.flow.js: crc32.flow.js + cat $^ | sed 's/-306674912/-2097792136/g' > $@ + ## Testing .PHONY: test mocha diff --git a/bin/crc32.njs b/bin/crc32.njs index 657291a..b5b02a1 100755 --- a/bin/crc32.njs +++ b/bin/crc32.njs @@ -20,6 +20,7 @@ function help()/*:number*/ { " -u, --unsigned print result with format `%u`", " -x, --hex print result with format `%0.8x`", " -X, --HEX print result with format `%0.8X`", +" -c, --crc32c use CRC32C (Castagnoli)", " -F, --format= use specified printf format", "", "Set filename = '-' or pipe data into crc32 to read from stdin", @@ -51,6 +52,8 @@ for(var i = 0; i < args.length; ++i) { case "--help": case "-h": process.exit(help()); break; case "--version": case "-V": process.exit(version()); break; + case "--crc32c": case "-c": try { X = require('../crc32c'); } catch(e) { X = require('crc-32/crc32c'); } break; + case "--signed": case "-d": fmt = "%d"; break; case "--unsigned": case "-u": fmt = "%u"; break; case "--hex": case "-x": fmt = "%0.8x"; break; diff --git a/crc32c.flow.js b/crc32c.flow.js new file mode 100644 index 0000000..221e826 --- /dev/null +++ b/crc32c.flow.js @@ -0,0 +1,127 @@ +/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */ +/* vim: set ts=2: */ +/*exported CRC32 */ +/*:: declare var DO_NOT_EXPORT_CRC:?boolean; */ +/*:: declare function define(cb:()=>any):void; */ +var CRC32/*:CRC32Module*/; +(function (factory/*:(a:any)=>void*/)/*:void*/ { + /*jshint ignore:start */ + /*eslint-disable */ + if(typeof DO_NOT_EXPORT_CRC === 'undefined') { + if('object' === typeof exports) { + factory(exports); + } else if ('function' === typeof define && define.amd) { + define(function () { + var module/*:CRC32Module*/ = /*::(*/{}/*:: :any)*/; + factory(module); + return module; + }); + } else { + factory(CRC32 = /*::(*/{}/*:: :any)*/); + } + } else { + factory(CRC32 = /*::(*/{}/*:: :any)*/); + } + /*eslint-enable */ + /*jshint ignore:end */ +}(function(CRC32/*:CRC32Module*/) { +CRC32.version = '1.2.0'; +/*:: +type CRC32Type = number; +type ABuf = Array | Buffer | Uint8Array; +type CRC32TableType = Array | Int32Array; +*/ +/* see perf/crc32table.js */ +/*global Int32Array */ +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) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + table[n] = c; + } + + return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table; +} + +var T = signed_crc_table(); +/*# charCodeAt is the best approach for binary strings */ +function crc32_bstr(bstr/*:string*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ { + 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]; + } + if(i === L) C = (C>>>8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF]; + return C ^ -1; +} + +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]; + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + } + while(i < L+3) C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + return C ^ -1; +} + +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]; + 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) C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + return C ^ -1; +} + +/*# much much faster to intertwine utf8 and crc */ +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) { + C = (C>>>8) ^ T[(C ^ c)&0xFF]; + } else if(c < 0x800) { + 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; + 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 { + 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 C ^ -1; +} +CRC32.table = T; +// $FlowIgnore +CRC32.bstr = crc32_bstr; +// $FlowIgnore +CRC32.buf = crc32_buf; +// $FlowIgnore +CRC32.str = crc32_str; +})); diff --git a/crc32c.js b/crc32c.js new file mode 100644 index 0000000..0cd8ffb --- /dev/null +++ b/crc32c.js @@ -0,0 +1,118 @@ +/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */ +/* vim: set ts=2: */ +/*exported CRC32 */ +var CRC32; +(function (factory) { + /*jshint ignore:start */ + /*eslint-disable */ + if(typeof DO_NOT_EXPORT_CRC === 'undefined') { + if('object' === typeof exports) { + factory(exports); + } else if ('function' === typeof define && define.amd) { + define(function () { + var module = {}; + factory(module); + return module; + }); + } else { + factory(CRC32 = {}); + } + } else { + factory(CRC32 = {}); + } + /*eslint-enable */ + /*jshint ignore:end */ +}(function(CRC32) { +CRC32.version = '1.2.0'; +/* see perf/crc32table.js */ +/*global Int32Array */ +function signed_crc_table() { + var c = 0, table = new Array(256); + + for(var n =0; n != 256; ++n){ + c = n; + c = ((c&1) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-2097792136 ^ (c >>> 1)) : (c >>> 1)); + table[n] = c; + } + + return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table; +} + +var T = signed_crc_table(); +function crc32_bstr(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]; + } + if(i === L) C = (C>>>8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF]; + return C ^ -1; +} + +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]; + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + } + while(i < L+3) C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + return C ^ -1; +} + +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]; + 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) C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + return 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) { + C = (C>>>8) ^ T[(C ^ c)&0xFF]; + } else if(c < 0x800) { + 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; + 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 { + 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 C ^ -1; +} +CRC32.table = T; +// $FlowIgnore +CRC32.bstr = crc32_bstr; +// $FlowIgnore +CRC32.buf = crc32_buf; +// $FlowIgnore +CRC32.str = crc32_str; +})); diff --git a/package.json b/package.json index 5f3655e..80de338 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,13 @@ "description": "Pure-JS CRC-32", "keywords": [ "crc", "crc32", "checksum" ], "bin": { - "crc32": "./bin/crc32.njs" + "crc32": "bin/crc32.njs" }, "main": "crc32.js", "types": "types/index.d.ts", + "typesVersions": { "*": { "*": ["types/index.d.ts" ] } }, "dependencies": { - "printj": "~1.1.0", + "printj": "~1.3.1", "exit-on-epipe": "~1.0.1" }, "devDependencies": { @@ -35,7 +36,7 @@ } }, "homepage": "http://sheetjs.com/opensource", - "files": ["crc32.js", "bin/crc32.njs", "LICENSE", "README.md", "types/index.d.ts", "types/*.json"], + "files": ["crc32.js", "crc32c.js", "bin/crc32.njs", "LICENSE", "README.md", "types/index.d.ts", "types/*.json"], "bugs": { "url": "https://github.com/SheetJS/js-crc32/issues" }, "license": "Apache-2.0", "engines": { "node": ">=0.8" }