diff --git a/.flowconfig b/.flowconfig
index 67bebf7..1a3ec98 100644
--- a/.flowconfig
+++ b/.flowconfig
@@ -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
diff --git a/Makefile b/Makefile
index a37ea6f..302fd6b 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
diff --git a/README.md b/README.md
index fb81efc..e879afd 100644
--- a/README.md
+++ b/README.md
@@ -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:
-
+```html
+
+```
-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
```
diff --git a/bin/crc32.njs b/bin/crc32.njs
index c107e30..41a9ea0 100755
--- a/bin/crc32.njs
+++ b/bin/crc32.njs
@@ -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= use integer seed as starting value (rolling CRC)",
+" -H, --hex-seed= 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= 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*/ = 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);
diff --git a/bits/01_version.js b/bits/01_version.js
index faa6d9c..d9dd0f3 100644
--- a/bits/01_version.js
+++ b/bits/01_version.js
@@ -1 +1 @@
-CRC32.version = '0.4.1';
+CRC32.version = '1.0.0';
diff --git a/bits/40_crc.js b/bits/40_crc.js
index 1153876..bd2cbb6 100644
--- a/bits/40_crc.js
+++ b/bits/40_crc.js
@@ -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) {
diff --git a/crc32.flow.js b/crc32.flow.js
index 74d6de5..422724c 100644
--- a/crc32.flow.js
+++ b/crc32.flow.js
@@ -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 | 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) {
diff --git a/crc32.js b/crc32.js
index 19af237..5bf1634 100644
--- a/crc32.js
+++ b/crc32.js
@@ -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) {
diff --git a/ctest/crc32.js b/ctest/crc32.js
index 19af237..5bf1634 100644
--- a/ctest/crc32.js
+++ b/ctest/crc32.js
@@ -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) {
diff --git a/ctest/fakeassert.js b/ctest/fakeassert.js
index dd20b48..16eb822 100644
--- a/ctest/fakeassert.js
+++ b/ctest/fakeassert.js
@@ -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); };
diff --git a/ctest/fixtures.js b/ctest/fixtures.js
index 0132362..78c2533 100644
--- a/ctest/fixtures.js
+++ b/ctest/fixtures.js
@@ -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]));
}
}
diff --git a/ctest/index.html b/ctest/index.html
index 417db5f..b275f3f 100644
--- a/ctest/index.html
+++ b/ctest/index.html
@@ -8,6 +8,7 @@
+
diff --git a/ctest/shim.js b/ctest/shim.js
new file mode 100644
index 0000000..e3d7840
--- /dev/null
+++ b/ctest/shim.js
@@ -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
+// 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;
+ };
+}
diff --git a/ctest/test.js b/ctest/test.js
index 319fb60..ace7a20 100644
--- a/ctest/test.js
+++ b/ctest/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);
}
diff --git a/demo/browser.flow.js b/demo/browser.flow.js
index 7ad9d77..31b9504 100644
--- a/demo/browser.flow.js
+++ b/demo/browser.flow.js
@@ -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;
diff --git a/demo/browser.js b/demo/browser.js
index 1645f3f..d3d2933 100644
--- a/demo/browser.js
+++ b/demo/browser.js
@@ -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;
diff --git a/index.html b/index.html
index 6dfdc53..fbd5138 100644
--- a/index.html
+++ b/index.html
@@ -34,6 +34,7 @@ Use readAsBinaryString: (when available) .
+