Initial commit

This commit is contained in:
SheetJS 2014-06-16 17:27:47 -04:00
commit 35003c5bda
29 changed files with 6981 additions and 0 deletions

2
.gitignore vendored Normal file

@ -0,0 +1,2 @@
node_modules
misc/coverage.html

6
.jscs.json Normal file

@ -0,0 +1,6 @@
{
"requireCommaBeforeLineBreak": true,
"disallowTrailingWhitespace": true,
"disallowTrailingComma": true
}

11
.travis.yml Normal file

@ -0,0 +1,11 @@
language: node_js
node_js:
- "0.11"
- "0.10"
- "0.8"
before_install:
- "npm install -g mocha"
- "npm install blanket"
- "npm install coveralls mocha-lcov-reporter"
after_success:
- "make coveralls-spin"

14
LICENSE Normal file

@ -0,0 +1,14 @@
Copyright (C) 2014 SheetJS
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

53
Makefile Normal file

@ -0,0 +1,53 @@
LIB=crc32
DEPS=$(sort $(wildcard bits/*.js))
TARGET=$(LIB).js
$(TARGET): $(DEPS)
cat $^ | tr -d '\15\32' > $@
cp -f $@ ctest/
bits/01_version.js: package.json
echo "CRC32.version = '"`grep version package.json | awk '{gsub(/[^0-9a-z\.-]/,"",$$2); print $$2}'`"';" > $@
.PHONY: clean
clean:
rm -f $(TARGET)
.PHONY: test mocha
test mocha: test.js
mocha -R spec
.PHONY: ctest
ctest:
cat misc/*.js > ctest/fixtures.js
cp -f test.js ctest/test.js
cp -f $(TARGET) ctest/
.PHONY: lint
lint: $(TARGET)
jshint --show-non-errors $(TARGET)
jscs $(TARGET)
.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
misc/coverage.html: $(TARGET) test.js
mocha --require blanket -R html-cov > $@
.PHONY: coveralls coveralls-spin
coveralls:
mocha --require blanket --reporter mocha-lcov-reporter | ./node_modules/coveralls/bin/coveralls.js
coveralls-spin:
make coveralls & bash misc/spin.sh $$!
.PHONY: perf
perf:
bash perf/perf.sh

54
README.md Normal file

@ -0,0 +1,54 @@
# crc32
Standard CRC-32 algorithm implementation in JS (for the browser and nodejs).
Emphasis on correctness and performance.
## Installation
In [nodejs](https://www.npmjs.org/package/crc-32):
npm install crc-32
In the browser:
<script lang="javascript" src="crc32.js"></script>
The browser exposes a variable CRC32
## Usage
- `CRC32.buf(byte array or buffer)` assumes the argument is a set of 8 bit
unsigned integers (e.g. nodejs `Buffer` or simple array of ints)
- `CRC32.bstr(binary string)` interprets the argument as a binary string where
the `i`-th byte is `str.charCodeAt(i)`
- `CRC32.str(string)` interprets the argument as a standard JS string
## Testing
`make test` will run the nodejs-based test. To run the in-browser tests, run a
local server and go to the `ctest` directory. To update the browser artifacts,
run `make ctest`.
## Performance
`make perf` will run performance tests.
## In the future ...
- Specifying an arbitrary initial CRC value
- Supporting different polynomials (e.g. CRC32C)
## License
Please consult the attached LICENSE file for details. All rights not explicitly
granted by the Apache 2.0 license are reserved by the Original Author.
[![Build Status](https://travis-ci.org/SheetJS/js-crc32.png?branch=master)](https://travis-ci.org/SheetJS/js-crc32)
[![Coverage Status](https://coveralls.io/repos/SheetJS/js-crc32/badge.png?branch=master)](https://coveralls.io/r/SheetJS/js-crc32?branch=master)
[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/ee0e89f8b1d5b861ffbf264b8ce329a6 "githalytics.com")](http://githalytics.com/SheetJS/js-crc32)

4
bits/00_header.js Normal file

@ -0,0 +1,4 @@
/* crc32.js (C) 2014 SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
var CRC32 = {};
(function(CRC32) {

1
bits/01_version.js Normal file

@ -0,0 +1 @@
CRC32.version = '0.1.0';

21
bits/20_crctable.js Normal file

@ -0,0 +1,21 @@
/* see perf/crc32table.js */
function signed_crc_table() {
var c, table = new Array(256);
for(var n =0; n != 256; ++n){
c = n;
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
table[n] = c;
}
return table;
}
var table = signed_crc_table();

40
bits/40_crc.js Normal file

@ -0,0 +1,40 @@
/* charCodeAt is the best approach for binary strings */
function crc32_bstr(bstr) {
for(var crc = -1, i = 0, L=bstr.length-1; i < L;) {
crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
}
if(i === L) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
return crc ^ -1;
}
function crc32_buf(buf) {
for(var crc = -1, i = 0; i != buf.length; ++i) {
crc = (crc >>> 8) ^ table[(crc ^ buf[i]) & 0xFF];
}
return crc ^ -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;) {
c = str.charCodeAt(i++);
if(c < 0x80) {
crc = (crc >>> 8) ^ table[(crc ^ c) & 0xFF];
} else if(c < 0x800) {
crc = (crc >>> 8) ^ table[(crc ^ (192|((c>>6)&31))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|(c&63))) & 0xFF];
} else if(c >= 0xD800 && c < 0xE000) {
c = (c&1023)+64; d = str.charCodeAt(i++) & 1023;
crc = (crc >>> 8) ^ table[(crc ^ (240|((c>>8)&7))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|((c>>2)&63))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|((d>>6)&15)|(c&3))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|(d&63))) & 0xFF];
} else {
crc = (crc >>> 8) ^ table[(crc ^ (224|((c>>12)&15))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|((c>>6)&63))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|(c&63))) & 0xFF];
}
}
return crc ^ -1;
}

4
bits/90_exports.js Normal file

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

1
bits/99_footer.js Normal file

@ -0,0 +1 @@
})(typeof exports !== "undefined" && typeof DO_NOT_EXPORT_CRC === 'undefined' ? exports : CRC32);

71
crc32.js Normal file

@ -0,0 +1,71 @@
/* crc32.js (C) 2014 SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
var CRC32 = {};
(function(CRC32) {
CRC32.version = '0.1.0';
/* see perf/crc32table.js */
function signed_crc_table() {
var c, table = new Array(256);
for(var n =0; n != 256; ++n){
c = n;
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
table[n] = c;
}
return table;
}
var table = signed_crc_table();
/* charCodeAt is the best approach for binary strings */
function crc32_bstr(bstr) {
for(var crc = -1, i = 0, L=bstr.length-1; i < L;) {
crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
}
if(i === L) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
return crc ^ -1;
}
function crc32_buf(buf) {
for(var crc = -1, i = 0; i != buf.length; ++i) {
crc = (crc >>> 8) ^ table[(crc ^ buf[i]) & 0xFF];
}
return crc ^ -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;) {
c = str.charCodeAt(i++);
if(c < 0x80) {
crc = (crc >>> 8) ^ table[(crc ^ c) & 0xFF];
} else if(c < 0x800) {
crc = (crc >>> 8) ^ table[(crc ^ (192|((c>>6)&31))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|(c&63))) & 0xFF];
} else if(c >= 0xD800 && c < 0xE000) {
c = (c&1023)+64; d = str.charCodeAt(i++) & 1023;
crc = (crc >>> 8) ^ table[(crc ^ (240|((c>>8)&7))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|((c>>2)&63))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|((d>>6)&15)|(c&3))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|(d&63))) & 0xFF];
} else {
crc = (crc >>> 8) ^ table[(crc ^ (224|((c>>12)&15))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|((c>>6)&63))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|(c&63))) & 0xFF];
}
}
return crc ^ -1;
}
CRC32.table = table;
CRC32.bstr = crc32_bstr;
CRC32.buf = crc32_buf;
CRC32.str = crc32_str;
})(typeof exports !== "undefined" && typeof DO_NOT_EXPORT_CRC === 'undefined' ? exports : CRC32);

71
ctest/crc32.js Normal file

@ -0,0 +1,71 @@
/* crc32.js (C) 2014 SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
var CRC32 = {};
(function(CRC32) {
CRC32.version = '0.1.0';
/* see perf/crc32table.js */
function signed_crc_table() {
var c, table = new Array(256);
for(var n =0; n != 256; ++n){
c = n;
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
table[n] = c;
}
return table;
}
var table = signed_crc_table();
/* charCodeAt is the best approach for binary strings */
function crc32_bstr(bstr) {
for(var crc = -1, i = 0, L=bstr.length-1; i < L;) {
crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
}
if(i === L) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
return crc ^ -1;
}
function crc32_buf(buf) {
for(var crc = -1, i = 0; i != buf.length; ++i) {
crc = (crc >>> 8) ^ table[(crc ^ buf[i]) & 0xFF];
}
return crc ^ -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;) {
c = str.charCodeAt(i++);
if(c < 0x80) {
crc = (crc >>> 8) ^ table[(crc ^ c) & 0xFF];
} else if(c < 0x800) {
crc = (crc >>> 8) ^ table[(crc ^ (192|((c>>6)&31))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|(c&63))) & 0xFF];
} else if(c >= 0xD800 && c < 0xE000) {
c = (c&1023)+64; d = str.charCodeAt(i++) & 1023;
crc = (crc >>> 8) ^ table[(crc ^ (240|((c>>8)&7))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|((c>>2)&63))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|((d>>6)&15)|(c&3))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|(d&63))) & 0xFF];
} else {
crc = (crc >>> 8) ^ table[(crc ^ (224|((c>>12)&15))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|((c>>6)&63))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|(c&63))) & 0xFF];
}
}
return crc ^ -1;
}
CRC32.table = table;
CRC32.bstr = crc32_bstr;
CRC32.buf = crc32_buf;
CRC32.str = crc32_str;
})(typeof exports !== "undefined" && typeof DO_NOT_EXPORT_CRC === 'undefined' ? exports : CRC32);

2
ctest/fakeassert.js Normal file

@ -0,0 +1,2 @@
var assert = {};
assert.equal = function(x,y) { if(x !== y) throw x + " !== " + y; };

75
ctest/fixtures.js Normal file

@ -0,0 +1,75 @@
var bits = [
[ "foobar", -1628037227, 1 ],
[ "foo bar baz", -228401567, 1 ],
[ "foo bar baz٪", 984445192 ],
[ "foo bar baz٪☃", 140429620],
[ "foo bar baz٪☃🍣", 1531648243]
];
if(typeof module !== "undefined") module.exports = bits;
crc32table = [
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
];
if(typeof module !== 'undefined') module.exports = crc32table;

21
ctest/index.html Normal file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<title>Mocha</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="mocha.css" />
</head>
<body>
<div id="mocha"></div>
<script src="crc32.js"></script>
<script src="fakeassert.js"></script>
<script src="mocha.js"></script>
<script src="fixtures.js"></script>
<script>mocha.setup('bdd')</script>
<script src="test.js"></script>
<script>
mocha.run();
</script>
</body>
</html>

270
ctest/mocha.css Normal file

@ -0,0 +1,270 @@
@charset "utf-8";
body {
margin:0;
}
#mocha {
font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 60px 50px;
}
#mocha ul,
#mocha li {
margin: 0;
padding: 0;
}
#mocha ul {
list-style: none;
}
#mocha h1,
#mocha h2 {
margin: 0;
}
#mocha h1 {
margin-top: 15px;
font-size: 1em;
font-weight: 200;
}
#mocha h1 a {
text-decoration: none;
color: inherit;
}
#mocha h1 a:hover {
text-decoration: underline;
}
#mocha .suite .suite h1 {
margin-top: 0;
font-size: .8em;
}
#mocha .hidden {
display: none;
}
#mocha h2 {
font-size: 12px;
font-weight: normal;
cursor: pointer;
}
#mocha .suite {
margin-left: 15px;
}
#mocha .test {
margin-left: 15px;
overflow: hidden;
}
#mocha .test.pending:hover h2::after {
content: '(pending)';
font-family: arial, sans-serif;
}
#mocha .test.pass.medium .duration {
background: #c09853;
}
#mocha .test.pass.slow .duration {
background: #b94a48;
}
#mocha .test.pass::before {
content: '✓';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #00d6b2;
}
#mocha .test.pass .duration {
font-size: 9px;
margin-left: 5px;
padding: 2px 5px;
color: #fff;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
}
#mocha .test.pass.fast .duration {
display: none;
}
#mocha .test.pending {
color: #0b97c4;
}
#mocha .test.pending::before {
content: '◦';
color: #0b97c4;
}
#mocha .test.fail {
color: #c00;
}
#mocha .test.fail pre {
color: black;
}
#mocha .test.fail::before {
content: '✖';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #c00;
}
#mocha .test pre.error {
color: #c00;
max-height: 300px;
overflow: auto;
}
/**
* (1): approximate for browsers not supporting calc
* (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border)
* ^^ seriously
*/
#mocha .test pre {
display: block;
float: left;
clear: left;
font: 12px/1.5 monaco, monospace;
margin: 5px;
padding: 15px;
border: 1px solid #eee;
max-width: 85%; /*(1)*/
max-width: calc(100% - 42px); /*(2)*/
word-wrap: break-word;
border-bottom-color: #ddd;
-webkit-border-radius: 3px;
-webkit-box-shadow: 0 1px 3px #eee;
-moz-border-radius: 3px;
-moz-box-shadow: 0 1px 3px #eee;
border-radius: 3px;
}
#mocha .test h2 {
position: relative;
}
#mocha .test a.replay {
position: absolute;
top: 3px;
right: 0;
text-decoration: none;
vertical-align: middle;
display: block;
width: 15px;
height: 15px;
line-height: 15px;
text-align: center;
background: #eee;
font-size: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
-webkit-transition: opacity 200ms;
-moz-transition: opacity 200ms;
transition: opacity 200ms;
opacity: 0.3;
color: #888;
}
#mocha .test:hover a.replay {
opacity: 1;
}
#mocha-report.pass .test.fail {
display: none;
}
#mocha-report.fail .test.pass {
display: none;
}
#mocha-report.pending .test.pass,
#mocha-report.pending .test.fail {
display: none;
}
#mocha-report.pending .test.pass.pending {
display: block;
}
#mocha-error {
color: #c00;
font-size: 1.5em;
font-weight: 100;
letter-spacing: 1px;
}
#mocha-stats {
position: fixed;
top: 15px;
right: 10px;
font-size: 12px;
margin: 0;
color: #888;
z-index: 1;
}
#mocha-stats .progress {
float: right;
padding-top: 0;
}
#mocha-stats em {
color: black;
}
#mocha-stats a {
text-decoration: none;
color: inherit;
}
#mocha-stats a:hover {
border-bottom: 1px solid #eee;
}
#mocha-stats li {
display: inline-block;
margin: 0 5px;
list-style: none;
padding-top: 11px;
}
#mocha-stats canvas {
width: 40px;
height: 40px;
}
#mocha code .comment { color: #ddd; }
#mocha code .init { color: #2f6fad; }
#mocha code .string { color: #5890ad; }
#mocha code .keyword { color: #8a6343; }
#mocha code .number { color: #2f6fad; }
@media screen and (max-device-width: 480px) {
#mocha {
margin: 60px 0px;
}
#mocha #stats {
position: absolute;
}
}

5842
ctest/mocha.js Normal file

File diff suppressed because it is too large Load Diff

33
ctest/test.js Normal file

@ -0,0 +1,33 @@
/* vim: set ts=2: */
var X;
if(typeof require !== 'undefined') {
assert = require('assert');
describe('source',function(){it('should load',function(){X=require('./');});});
bits = require('./misc/bits.js');
crc32table = require('./misc/table.js');
} else { X = CRC32; }
describe('crc32 table', function() {
it('should match fixed table', function() {
var badness = 0;
for(var i = 0; i != crc32table.length; ++i) {
assert.equal(crc32table[i]|0, X.table[i]);
if(crc32table[i] !== X.table[i]) ++badness;
}
assert.equal(badness, 128);
});
});
describe('crc32 bits', function() {
bits.forEach(function(i) {
var l = i[0].length;
var msg = i[0];
if(l > 20) 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);
assert.equal(X.str(i[0]), i[1]|0);
if(typeof Buffer !== 'undefined') assert.equal(X.buf(new Buffer(i[0])), i[1]|0);
});
});
});

8
misc/bits.js Normal file

@ -0,0 +1,8 @@
var bits = [
[ "foobar", -1628037227, 1 ],
[ "foo bar baz", -228401567, 1 ],
[ "foo bar baz٪", 984445192 ],
[ "foo bar baz٪☃", 140429620],
[ "foo bar baz٪☃🍣", 1531648243]
];
if(typeof module !== "undefined") module.exports = bits;

67
misc/table.js Normal file

@ -0,0 +1,67 @@
crc32table = [
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
];
if(typeof module !== 'undefined') module.exports = crc32table;

27
package.json Normal file

@ -0,0 +1,27 @@
{
"name": "crc-32",
"version": "0.1.0",
"author": "sheetjs",
"description": "Pure-JS CRC-32",
"keywords": [ "crc32", "checksum", "crc" ],
"main": "./crc32",
"devDependencies": {
"mocha":"",
"xlsjs":"",
"uglify-js":"",
"codepage":""
},
"repository": { "type":"git", "url":"git://github.com/SheetJS/js-crc32.git" },
"scripts": {
"pretest": "git submodule init && git submodule update",
"test": "make test"
},
"config": {
"blanket": {
"pattern": "crc32.js"
}
},
"bugs": { "url": "https://github.com/SheetJS/js-crc32/issues" },
"license": "Apache-2.0",
"engines": { "node": ">=0.8" }
}

28
perf/bm.js Normal file

@ -0,0 +1,28 @@
/* ssf.js (C) 2014 SheetJS -- http://sheetjs.com */
var Benchmark = require('benchmark');
var c = require('ansi')(process.stdout);
function test_end() { c.horizontalAbsolute(0).write("✓"); c.write('\n'); }
function suite_end() { console.log('Fastest is ' + this.filter('fastest').pluck('name')); }
function test_cycle(e) { c.horizontalAbsolute(0); c.eraseLine(); c.write("→ "+e.target); }
function BM(name) {
if(!(this instanceof BM)) return new BM(name);
console.log("--- " + name + " ---");
this.suite = new Benchmark.Suite(name, { onComplete: suite_end });
}
BM.prototype.run = function() { this.suite.run(); };
BM.prototype.add = function(msg, test) {
this.suite.add(msg, {
onCycle: test_cycle,
onComplete: test_end,
defer: false,
fn: test
});
};
module.exports = BM;

83
perf/bstr.js Normal file

@ -0,0 +1,83 @@
var table = require('../').table;
function strToArr(str) {
// sweet hack to turn string into a 'byte' array
return Array.prototype.map.call(str, function (c) {
return c.charCodeAt(0);
});
}
function crcTable(arr, append) {
var crc, i, l;
// if we're in append mode, don't reset crc
// if arr is null or undefined, reset table and return
if (typeof crcTable.crc === 'undefined' || !append || !arr) {
crcTable.crc = 0 ^ -1;
if (!arr) {
return;
}
}
// store in temp variable for minor speed gain
crc = crcTable.crc;
for (i = 0, l = arr.length; i < l; i += 1) {
crc = (crc >>> 8) ^ table[(crc ^ arr[i]) & 0xff];
}
crcTable.crc = crc;
return crc ^ -1;
}
function node_crc32(bstr) {
return crcTable(strToArr(bstr));
}
function sheetjs1(bstr) {
for(var crc = -1, i = 0; i != bstr.length; ++i) {
crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i)) & 0xFF];
}
return crc ^ -1;
}
function sheetjs2(bstr) {
for(var crc = -1, i = 0, L=bstr.length-1; i < L;) {
crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
}
if(i === L) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
return crc ^ -1;
}
function sheetjs3(bstr) {
for(var crc = -1, i = 0, L=bstr.length-2; i < L;) {
crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
}
if(i === L++) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
if(i === L++) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF];
return crc ^ -1;
}
var BM = require('./bm');
var suite = new BM('binary string');
var foobar = "foobarbazqux";
foobar += " " + foobar;
foobar += " " + foobar;
foobar += " " + foobar;
foobar += " " + foobar;
suite.add('npm crc32', function() { for(var j = 0; j != 1000; ++j) node_crc32(foobar); });
suite.add('sheetjs 1', function() { for(var j = 0; j != 1000; ++j) sheetjs1(foobar); });
suite.add('sheetjs 2', function() { for(var j = 0; j != 1000; ++j) sheetjs2(foobar); });
suite.add('sheetjs 3', function() { for(var j = 0; j != 1000; ++j) sheetjs3(foobar); });
suite.run();
var assert = require('assert');
assert.equal(node_crc32(foobar), sheetjs1(foobar));
assert.equal(node_crc32(foobar), sheetjs2(foobar));
assert.equal(node_crc32(foobar), sheetjs3(foobar));

86
perf/crc32table.js Normal file

@ -0,0 +1,86 @@
var t=[], poly = 0xEDB88320;
function node_crc32() {
var c, n, k;
for (n = 0; n < 256; n += 1) {
c = n;
for (k = 0; k < 8; k += 1) {
if (c & 1) {
c = poly ^ (c >>> 1);
} else {
c = c >>> 1;
}
}
t[n] = c >>> 0;
}
}
function node_pako() {
var c, table = [];
for(var n =0; n < 256; n++){
c = n;
for(var k =0; k < 8; k++){
c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
}
table[n] = c;
}
return table;
}
function sheetjs1() {
var c, table = [];
for(var n =0; n != 256; ++n){
c = n;
c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
table[n] = c;
}
return table;
}
function sheetjs2() {
var c, table = new Array(256);
for(var n =0; n != 256; ++n){
c = n;
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
table[n] = c;
}
return table;
}
var BM = require('./bm');
var suite = new BM('building crc32 table');
suite.add('npm crc32', function() { for(var j = 0; j != 1000; ++j) node_crc32(); });
suite.add('npm pako', function() { for(var j = 0; j != 1000; ++j) node_pako(); });
suite.add('sheetjs 1', function() { for(var j = 0; j != 1000; ++j) sheetjs1(); });
suite.add('sheetjs 2', function() { for(var j = 0; j != 1000; ++j) sheetjs2(); });
suite.run()
var assert = require('assert');
var m1 = (node_pako());
var m2 = (sheetjs1());
var m3 = (sheetjs2());
assert.equal(m1.length, m2.length);
assert.equal(m1.length, m3.length);
for(var i = 0; i != m1.length; ++i) { assert.equal(m1[i], m2[i]); assert.equal(m1[i], m3[i]); }

6
perf/perf.sh Executable file

@ -0,0 +1,6 @@
#!/bin/bash
node perf/crc32table.js
node perf/bstr.js
node perf/utf8.js

47
perf/utf8.js Normal file

@ -0,0 +1,47 @@
var table = require('../').table;
function sheetjs1(utf8) {
var buf = new Buffer(utf8);
for(var crc = -1, i = 0; i != buf.length; ++i) {
crc = (crc >>> 8) ^ table[(crc ^ buf[i]) & 0xFF];
}
return crc ^ -1;
}
function sheetjs2(utf8) {
for(var crc = -1, i = 0, L=utf8.length, c, d; i < L;) {
c = utf8.charCodeAt(i++);
if(c < 0x80) {
crc = (crc >>> 8) ^ table[(crc ^ c) & 0xFF];
} else if(c < 0x800) {
crc = (crc >>> 8) ^ table[(crc ^ (192|((c>>6)&31))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|(c&63))) & 0xFF];
} else if(c >= 0xD800 && c < 0xE000) {
c = (c&1023)+64; d = utf8.charCodeAt(i++) & 1023;
crc = (crc >>> 8) ^ table[(crc ^ (240|((c>>8)&7))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|((c>>2)&63))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|((d>>6)&15)|(c&3))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|(d&63))) & 0xFF];
} else {
crc = (crc >>> 8) ^ table[(crc ^ (224|((c>>12)&15))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|((c>>6)&63))) & 0xFF];
crc = (crc >>> 8) ^ table[(crc ^ (128|(c&63))) & 0xFF];
}
}
return crc ^ -1;
}
var BM = require('./bm');
var suite = new BM('unicode string');
var foobar = "foo bar baz٪☃🍣";
foobar += " " + foobar;
foobar += " " + foobar;
foobar += " " + foobar;
foobar += " " + foobar;
suite.add('sheetjs 1', function() { for(var j = 0; j != 1000; ++j) sheetjs1(foobar); });
suite.add('sheetjs 2', function() { for(var j = 0; j != 1000; ++j) sheetjs2(foobar); });
suite.run()
var assert = require('assert');
assert.equal(sheetjs1(foobar), sheetjs2(foobar));

33
test.js Normal file

@ -0,0 +1,33 @@
/* vim: set ts=2: */
var X;
if(typeof require !== 'undefined') {
assert = require('assert');
describe('source',function(){it('should load',function(){X=require('./');});});
bits = require('./misc/bits.js');
crc32table = require('./misc/table.js');
} else { X = CRC32; }
describe('crc32 table', function() {
it('should match fixed table', function() {
var badness = 0;
for(var i = 0; i != crc32table.length; ++i) {
assert.equal(crc32table[i]|0, X.table[i]);
if(crc32table[i] !== X.table[i]) ++badness;
}
assert.equal(badness, 128);
});
});
describe('crc32 bits', function() {
bits.forEach(function(i) {
var l = i[0].length;
var msg = i[0];
if(l > 20) 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);
assert.equal(X.str(i[0]), i[1]|0);
if(typeof Buffer !== 'undefined') assert.equal(X.buf(new Buffer(i[0])), i[1]|0);
});
});
});