Skip to content

Commit 1045f4f

Browse files
committed
version bump 1.0.0: rolling checksums
- browser tests work in IE6+ - miscellaneous adjustments to tooling
1 parent e1c9c5e commit 1045f4f

26 files changed

+764
-219
lines changed

.flowconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,18 @@
1010
.*/perf/.*
1111

1212
.*/demo/browser.js
13+
.*/shim.js
1314

1415
[include]
1516
crc32.flow.js
17+
.*/bin/.*.njs
1618
.*/demo/browser.flow.js
1719

1820
[libs]
1921
bits/10_types.js
2022
misc/flow.js
23+
misc/flowdeps.js
2124

2225
[options]
26+
module.file_ext=.js
27+
module.file_ext=.njs

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ LIB=crc32
22
REQS=
33
ADDONS=
44
AUXTARGETS=demo/browser.js
5+
CMDS=bin/crc32.njs
56
HTMLLINT=index.html
67

78
ULIB=$(shell echo $(LIB) | tr a-z A-Z)
@@ -37,6 +38,7 @@ test mocha: test.js $(TARGET) baseline ## Run test suite
3738
ctest: ## Build browser test (into ctest/ subdirectory)
3839
cat misc/*.js > ctest/fixtures.js
3940
cp -f test.js ctest/test.js
41+
cp -f shim.js ctest/shim.js
4042
cp -f $(TARGET) ctest/
4143

4244
.PHONY: ctestserv
@@ -56,6 +58,7 @@ clean-baseline: ## Remove test baselines
5658
.PHONY: lint
5759
lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks
5860
@jshint --show-non-errors $(TARGET) $(AUXTARGETS)
61+
@jshint --show-non-errors $(CMDS)
5962
@jshint --show-non-errors package.json
6063
@jshint --show-non-errors --extract=always $(HTMLLINT)
6164
@jscs $(TARGET) $(AUXTARGETS)

README.md

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,62 @@
11
# crc32
22

33
Standard CRC-32 algorithm implementation in JS (for the browser and nodejs).
4-
Emphasis on correctness and performance.
4+
Emphasis on correctness, performance, and IE6+ support.
55

66
## Installation
77

88
With [npm](https://www.npmjs.org/package/crc-32):
99

10-
$ npm install crc-32
10+
```bash
11+
$ npm install crc-32
12+
```
1113

1214
In the browser:
1315

14-
<script src="crc32.js"></script>
16+
```html
17+
<script src="crc32.js"></script>
18+
```
1519

16-
The browser exposes a variable ADLER32
20+
The browser exposes a variable `CRC32`.
1721

1822
When installed globally, npm installs a script `crc32` that computes the
1923
checksum for a specified file or standard input.
2024

2125
The script will manipulate `module.exports` if available (e.g. in a CommonJS
2226
`require` context). This is not always desirable. To prevent the behavior,
23-
define `DO_NOT_EXPORT_CRC`
27+
define `DO_NOT_EXPORT_CRC`.
2428

2529
## Usage
2630

27-
In all cases, the relevant function takes a single argument representing data.
31+
In all cases, the relevant function takes an argument representing data and an
32+
optional second argument representing the starting "seed" (for rolling CRC).
2833

2934
The return value is a signed 32-bit integer.
3035

31-
- `CRC32.buf(byte array or buffer)` assumes the argument is a set of 8-bit
32-
unsigned integers (e.g. nodejs `Buffer` or simple array of ints).
36+
- `CRC32.buf(byte array or buffer[, seed])` assumes the argument is a sequence
37+
of 8-bit unsigned integers (e.g. nodejs `Buffer` or simple array of ints).
3338

34-
- `CRC32.bstr(binary string)` interprets the argument as a binary string where
35-
the `i`-th byte is the low byte of the UCS-2 char: `str.charCodeAt(i) & 0xFF`
39+
- `CRC32.bstr(binary string[, seed])` assumes the argument is a "binary" string
40+
where byte `i` is the low byte of the UCS-2 char: `str.charCodeAt(i) & 0xFF`
3641

37-
- `CRC32.str(string)` interprets the argument as a standard JS string
42+
- `CRC32.str(string[, seed])` assumes the argument is a standard string and
43+
calculates the CRC32 of the UTF-8 encoding.
3844

3945
For example:
4046

4147
```js
42-
> // var CRC32 = require('crc-32'); // uncomment this line if in node
43-
> CRC32.str("SheetJS") // -1647298270
44-
> CRC32.bstr("SheetJS") // -1647298270
45-
> CRC32.buf([ 83, 104, 101, 101, 116, 74, 83 ]) // -1647298270
46-
47-
> [CRC32.str("\u2603"), CRC32.str("\u0003")] // [ -1743909036, 1259060791 ]
48-
> [CRC32.bstr("\u2603"), CRC32.bstr("\u0003")] // [ 1259060791, 1259060791 ]
49-
> [CRC32.buf([0x2603]), CRC32.buf([0x0003])] // [ 1259060791, 1259060791 ]
48+
// var CRC32 = require('crc-32'); // uncomment this line if in node
49+
CRC32.str("SheetJS") // -1647298270
50+
CRC32.bstr("SheetJS") // -1647298270
51+
CRC32.buf([ 83, 104, 101, 101, 116, 74, 83 ]) // -1647298270
52+
53+
crc32 = CRC32.buf([83, 104]) // -1826163454 "Sh"
54+
crc32 = CRC32.str("eet", crc32) // 1191034598 "Sheet"
55+
CRC32.bstr("JS", crc32) // -1647298270 "SheetJS"
56+
57+
[CRC32.str("\u2603"), CRC32.str("\u0003")] // [ -1743909036, 1259060791 ]
58+
[CRC32.bstr("\u2603"), CRC32.bstr("\u0003")] // [ 1259060791, 1259060791 ]
59+
[CRC32.buf([0x2603]), CRC32.buf([0x0003])] // [ 1259060791, 1259060791 ]
5060
```
5161

5262
## Testing
@@ -73,15 +83,15 @@ To generate the bits file, use the `crc32` function from python zlib:
7383

7484
The included `crc32.njs` script can process files or stdin:
7585

76-
```
86+
```bash
7787
$ echo "this is a test" > t.txt
7888
$ bin/crc32.njs t.txt
7989
1912935186
8090
```
8191

8292
For comparison, the included `crc32.py` script uses python zlib:
8393

84-
```
94+
```bash
8595
$ bin/crc32.py t.txt
8696
1912935186
8797
```

bin/crc32.njs

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,77 @@
22
/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
33
/* vim: set ts=2 ft=javascript: */
44

5-
var X;
5+
var X/*:CRC32Module*/;
66
try { X = require('../'); } catch(e) { X = require('crc-32'); }
7+
8+
function help()/*:number*/ {
9+
[
10+
"usage: crc32 [options] [filename]",
11+
"",
12+
"Options:",
13+
" -h, --help output usage information",
14+
" -V, --version output the version number",
15+
" -S, --seed=<n> use integer seed as starting value (rolling CRC)",
16+
" -H, --hex-seed=<h> use hex seed as starting value (rolling CRC)",
17+
" -d, --signed print result with format `%d` (default)",
18+
" -u, --unsigned print result with format `%u`",
19+
" -x, --hex print result with format `%0.8x`",
20+
" -X, --HEX print result with format `%0.8X`",
21+
" -F, --format=<s> use specified printf format",
22+
"",
23+
"Set filename = '-' or pipe data into crc32 to read from stdin",
24+
"Default output mode is signed (-d)",
25+
""
26+
].forEach(function(l) { console.log(l); });
27+
return 0;
28+
}
29+
30+
function version()/*:number*/ { console.log(X.version); return 0; }
31+
732
var fs = require('fs');
833
require('exit-on-epipe');
934

10-
var args = process.argv.slice(2);
35+
function die(msg/*:string*/, ec/*:?number*/)/*:void*/ { console.error(msg); process.exit(ec || 0); }
1136

12-
var filename;
13-
if(args[0]) filename = args[0];
37+
var args/*:Array<string>*/ = process.argv.slice(2);
38+
var filename/*:string*/ = "";
39+
var fmt/*:string*/ = "";
40+
var seed = 0, r = 10;
1441

15-
if(!process.stdin.isTTY) filename = filename || "-";
42+
for(var i = 0; i < args.length; ++i) {
43+
var arg = args[i];
44+
if(arg.charCodeAt(0) != 45) { if(filename === "") filename = arg; continue; }
45+
var m = arg.indexOf("=") == -1 ? arg : arg.substr(0, arg.indexOf("="));
46+
switch(m) {
47+
case "-": filename = "-"; break;
1648

17-
if(!filename) {
18-
console.error("crc32: must specify a filename ('-' for stdin)");
19-
process.exit(1);
20-
}
49+
case "--help": case "-h": process.exit(help()); break;
50+
case "--version": case "-V": process.exit(version()); break;
2151

22-
if(filename === "-h" || filename === "--help") {
23-
console.log("usage: " + process.argv[0] + " [filename]");
24-
process.exit(0);
25-
}
52+
case "--signed": case "-d": fmt = "%d"; break;
53+
case "--unsigned": case "-u": fmt = "%u"; break;
54+
case "--hex": case "-x": fmt = "%0.8x"; break;
55+
case "--HEX": case "-X": fmt = "%0.8X"; break;
56+
case "--format": case "-F":
57+
fmt = ((m!=arg) ? arg.substr(m.length+1) : args[++i])||""; break;
58+
59+
case "--hex-seed": case "-H": r = 16;
60+
/* falls through */
61+
case "--seed": case "-S":
62+
seed=parseInt((m!=arg) ? arg.substr(m.length+1) : args[++i], r)||0; break;
2663

27-
if(filename !== "-" && !fs.existsSync(filename)) {
28-
console.error("crc32: " + filename + ": No such file or directory");
29-
process.exit(2);
64+
default: die("crc32: unrecognized option `" + arg + "'", 22);
65+
}
3066
}
3167

32-
if(filename === "-") process.stdin.pipe(require('concat-stream')(process_data));
33-
else process_data(fs.readFileSync(filename));
68+
if(!process.stdin.isTTY) filename = filename || "-";
69+
if(filename.length===0) die("crc32: must specify a filename ('-' for stdin)",1);
3470

35-
function process_data(data) {
36-
console.log(X.buf(data));
71+
function process_data(data/*:Buffer*/) {
72+
var out/*:CRC32Type*/ = X.buf(data, seed);
73+
return console.log(fmt === "" ? out : require("printj").sprintf(fmt, out));
3774
}
75+
76+
if(filename === "-") process.stdin.pipe(require('concat-stream')(process_data));
77+
else if(fs.existsSync(filename)) process_data(fs.readFileSync(filename));
78+
else die("crc32: " + filename + ": No such file or directory", 2);

bits/01_version.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
CRC32.version = '0.4.1';
1+
CRC32.version = '1.0.0';

bits/40_crc.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/*# charCodeAt is the best approach for binary strings */
22
/*global Buffer */
33
var use_buffer = typeof Buffer !== 'undefined';
4-
function crc32_bstr(bstr/*:string*/)/*:CRC32Type*/ {
5-
if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr));
6-
var C = -1, L = bstr.length - 1;
4+
function crc32_bstr(bstr/*:string*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
5+
if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr), seed);
6+
var C = seed/*:: ? 0 : 0 */ ^ -1, L = bstr.length - 1;
77
for(var i = 0; i < L;) {
88
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
99
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
@@ -12,9 +12,9 @@ function crc32_bstr(bstr/*:string*/)/*:CRC32Type*/ {
1212
return C ^ -1;
1313
}
1414

15-
function crc32_buf(buf/*:ABuf*/)/*:CRC32Type*/ {
16-
if(buf.length > 10000) return crc32_buf_8(buf);
17-
var C = -1, L = buf.length - 3;
15+
function crc32_buf(buf/*:ABuf*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
16+
if(buf.length > 10000) return crc32_buf_8(buf, seed);
17+
var C = seed/*:: ? 0 : 0 */ ^ -1, L = buf.length - 3;
1818
for(var i = 0; i < L;) {
1919
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
2020
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
@@ -25,8 +25,8 @@ function crc32_buf(buf/*:ABuf*/)/*:CRC32Type*/ {
2525
return C ^ -1;
2626
}
2727

28-
function crc32_buf_8(buf/*:ABuf*/)/*:CRC32Type*/ {
29-
var C = -1, L = buf.length - 7;
28+
function crc32_buf_8(buf/*:ABuf*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
29+
var C = seed/*:: ? 0 : 0 */ ^ -1, L = buf.length - 7;
3030
for(var i = 0; i < L;) {
3131
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
3232
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
@@ -42,8 +42,8 @@ function crc32_buf_8(buf/*:ABuf*/)/*:CRC32Type*/ {
4242
}
4343

4444
/*# much much faster to intertwine utf8 and C */
45-
function crc32_str(str/*:string*/)/*:CRC32Type*/ {
46-
var C = -1;
45+
function crc32_str(str/*:string*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
46+
var C = seed/*:: ? 0 : 0 */ ^ -1;
4747
for(var i = 0, L=str.length, c, d; i < L;) {
4848
c = str.charCodeAt(i++);
4949
if(c < 0x80) {

crc32.flow.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ var CRC32;
2323
}
2424
/*jshint ignore:end */
2525
}(function(CRC32) {
26-
CRC32.version = '0.4.1';
26+
CRC32.version = '1.0.0';
2727
/*::
2828
type CRC32Type = number;
2929
type ABuf = Array<number> | Buffer;
@@ -54,9 +54,9 @@ var T = signed_crc_table();
5454
/*# charCodeAt is the best approach for binary strings */
5555
/*global Buffer */
5656
var use_buffer = typeof Buffer !== 'undefined';
57-
function crc32_bstr(bstr/*:string*/)/*:CRC32Type*/ {
58-
if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr));
59-
var C = -1, L = bstr.length - 1;
57+
function crc32_bstr(bstr/*:string*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
58+
if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr), seed);
59+
var C = seed/*:: ? 0 : 0 */ ^ -1, L = bstr.length - 1;
6060
for(var i = 0; i < L;) {
6161
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
6262
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
@@ -65,9 +65,9 @@ function crc32_bstr(bstr/*:string*/)/*:CRC32Type*/ {
6565
return C ^ -1;
6666
}
6767

68-
function crc32_buf(buf/*:ABuf*/)/*:CRC32Type*/ {
69-
if(buf.length > 10000) return crc32_buf_8(buf);
70-
var C = -1, L = buf.length - 3;
68+
function crc32_buf(buf/*:ABuf*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
69+
if(buf.length > 10000) return crc32_buf_8(buf, seed);
70+
var C = seed/*:: ? 0 : 0 */ ^ -1, L = buf.length - 3;
7171
for(var i = 0; i < L;) {
7272
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
7373
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
@@ -78,8 +78,8 @@ function crc32_buf(buf/*:ABuf*/)/*:CRC32Type*/ {
7878
return C ^ -1;
7979
}
8080

81-
function crc32_buf_8(buf/*:ABuf*/)/*:CRC32Type*/ {
82-
var C = -1, L = buf.length - 7;
81+
function crc32_buf_8(buf/*:ABuf*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
82+
var C = seed/*:: ? 0 : 0 */ ^ -1, L = buf.length - 7;
8383
for(var i = 0; i < L;) {
8484
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
8585
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
@@ -95,8 +95,8 @@ function crc32_buf_8(buf/*:ABuf*/)/*:CRC32Type*/ {
9595
}
9696

9797
/*# much much faster to intertwine utf8 and C */
98-
function crc32_str(str/*:string*/)/*:CRC32Type*/ {
99-
var C = -1;
98+
function crc32_str(str/*:string*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ {
99+
var C = seed/*:: ? 0 : 0 */ ^ -1;
100100
for(var i = 0, L=str.length, c, d; i < L;) {
101101
c = str.charCodeAt(i++);
102102
if(c < 0x80) {

0 commit comments

Comments
 (0)