Initial commit

This commit is contained in:
SheetJS 2014-06-18 13:58:20 -04:00
commit a7891dc881
27 changed files with 6746 additions and 0 deletions

3
.gitignore vendored Normal file
View File

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

6
.jscs.json Normal file
View File

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

11
.travis.yml Normal file
View 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
View 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
View File

@ -0,0 +1,53 @@
LIB=adler32
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 "ADLER32.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

76
README.md Normal file
View File

@ -0,0 +1,76 @@
# adler32
Signed ADLER-32 algorithm implementation in JS (for the browser and nodejs).
Emphasis on correctness and performance.
## Installation
In [nodejs](https://www.npmjs.org/package/adler-32):
npm install adler-32
In the browser:
<script lang="javascript" src="adler32.js"></script>
The browser exposes a variable ADLER32
## Usage
- `ADLER32.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)
- `ADLER32.bstr(binary string)` interprets the argument as a binary string where
the `i`-th byte is `str.charCodeAt(i)`
- `ADLER32.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`.
To generate the bits file, use the `adler32` function from python zlib:
```
>>> from zlib import adler32
>>> x="foo bar baz٪☃🍣"
>>> adler32(x)
1543572022
>>> adler32(x+x)
-2076896149
>>> adler32(x+x+x)
2023497376
```
## Performance
`make perf` will run algorithmic performance tests (which should justify certain
decisions in the code).
[js-crc](http://git.io/crc32) has more performance notes
## Magic Number
The magic numbers were chosen so as to not overflow a 31-bit integer:
```
F[n_] := Reduce[x*(x + 1)*n/2 + (x + 1)*(65521) < (2^31 - 1) && x > 0, x, Integers]
F[255] (* bstr: x \[Element] Integers && 1 <= x <= 3854 *)
F[127] (* ascii: x \[Element] Integers && 1 <= x <= 5321 *)
```
Subtract up to 4 elements for the unicode case.
## 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-adler32.svg?branch=master)](https://travis-ci.org/SheetJS/js-adler32)
[![Coverage Status](https://coveralls.io/repos/SheetJS/js-adler32/badge.png?branch=master)](https://coveralls.io/r/SheetJS/js-adler32?branch=master)
[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/8827aa40b3fdbca7c7ad0f51c68b3379 "githalytics.com")](http://githalytics.com/SheetJS/js-adler32)

69
adler32.js Normal file
View File

@ -0,0 +1,69 @@
/* adler32.js (C) 2014 SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
var ADLER32 = {};
(function(ADLER32) {
ADLER32.version = '0.2.0';
/* consult README.md for the magic number */
/* charCodeAt is the best approach for binary strings */
var use_buffer = typeof Buffer !== 'undefined';
function adler32_bstr(bstr) {
if(bstr.length > 32768) if(use_buffer) return adler32_buf(Buffer(bstr));
var a = 1, b = 0, L = bstr.length, M;
for(var i = 0; i < L;) {
M = Math.min(L-i, 3854);
for(;M>0;--M) {
a += bstr.charCodeAt(i++);
b += a;
}
a %= 65521;
b %= 65521;
}
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
}
function adler32_buf(buf) {
var a = 1, b = 0, L = buf.length, M;
for(var i = 0; i < L;) {
M = Math.min(L-i, 3854);
for(;M>0;--M) {
a += buf[i++];
b += a;
}
a %= 65521;
b %= 65521;
}
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
}
/* much much faster to intertwine utf8 and adler */
function adler32_str(str) {
var a = 1, b = 0, L = str.length, M, c, d;
for(var i = 0; i < L;) {
M = Math.min(L-i, 3850);
while(M>0) {
c = str.charCodeAt(i++);
if(c < 0x80) { a += c; b += a; --M; }
else if(c < 0x800) {
a += 192|((c>>6)&31); b += a; --M;
a += 128|(c&63); b += a; --M;
} else if(c >= 0xD800 && c < 0xE000) {
c = (c&1023)+64; d = str.charCodeAt(i++) & 1023;
a += 240|((c>>8)&7); b += a; --M;
a += 128|((c>>2)&63); b += a; --M;
a += 128|((d>>6)&15)|(c&3); b += a; --M;
a += 128|(d&63); b += a; --M;
} else {
a += 224|((c>>12)&15); b += a; --M;
a += 128|((c>>6)&63); b += a; --M;
a += 128|(c&63); b += a; --M;
}
}
a %= 65521;
b %= 65521;
}
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
}
ADLER32.bstr = adler32_bstr;
ADLER32.buf = adler32_buf;
ADLER32.str = adler32_str;
})(typeof exports !== "undefined" && typeof DO_NOT_EXPORT_ADLER === 'undefined' ? exports : ADLER32);

4
bits/00_header.js Normal file
View File

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

1
bits/01_version.js Normal file
View File

@ -0,0 +1 @@
ADLER32.version = '0.2.0';

60
bits/40_adler.js Normal file
View File

@ -0,0 +1,60 @@
/* consult README.md for the magic number */
/* charCodeAt is the best approach for binary strings */
var use_buffer = typeof Buffer !== 'undefined';
function adler32_bstr(bstr) {
if(bstr.length > 32768) if(use_buffer) return adler32_buf(Buffer(bstr));
var a = 1, b = 0, L = bstr.length, M;
for(var i = 0; i < L;) {
M = Math.min(L-i, 3854);
for(;M>0;--M) {
a += bstr.charCodeAt(i++);
b += a;
}
a %= 65521;
b %= 65521;
}
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
}
function adler32_buf(buf) {
var a = 1, b = 0, L = buf.length, M;
for(var i = 0; i < L;) {
M = Math.min(L-i, 3854);
for(;M>0;--M) {
a += buf[i++];
b += a;
}
a %= 65521;
b %= 65521;
}
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
}
/* much much faster to intertwine utf8 and adler */
function adler32_str(str) {
var a = 1, b = 0, L = str.length, M, c, d;
for(var i = 0; i < L;) {
M = Math.min(L-i, 3850);
while(M>0) {
c = str.charCodeAt(i++);
if(c < 0x80) { a += c; b += a; --M; }
else if(c < 0x800) {
a += 192|((c>>6)&31); b += a; --M;
a += 128|(c&63); b += a; --M;
} else if(c >= 0xD800 && c < 0xE000) {
c = (c&1023)+64; d = str.charCodeAt(i++) & 1023;
a += 240|((c>>8)&7); b += a; --M;
a += 128|((c>>2)&63); b += a; --M;
a += 128|((d>>6)&15)|(c&3); b += a; --M;
a += 128|(d&63); b += a; --M;
} else {
a += 224|((c>>12)&15); b += a; --M;
a += 128|((c>>6)&63); b += a; --M;
a += 128|(c&63); b += a; --M;
}
}
a %= 65521;
b %= 65521;
}
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
}

3
bits/90_exports.js Normal file
View File

@ -0,0 +1,3 @@
ADLER32.bstr = adler32_bstr;
ADLER32.buf = adler32_buf;
ADLER32.str = adler32_str;

1
bits/99_footer.js Normal file
View File

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

69
ctest/adler32.js Normal file
View File

@ -0,0 +1,69 @@
/* adler32.js (C) 2014 SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
var ADLER32 = {};
(function(ADLER32) {
ADLER32.version = '0.2.0';
/* consult README.md for the magic number */
/* charCodeAt is the best approach for binary strings */
var use_buffer = typeof Buffer !== 'undefined';
function adler32_bstr(bstr) {
if(bstr.length > 32768) if(use_buffer) return adler32_buf(Buffer(bstr));
var a = 1, b = 0, L = bstr.length, M;
for(var i = 0; i < L;) {
M = Math.min(L-i, 3854);
for(;M>0;--M) {
a += bstr.charCodeAt(i++);
b += a;
}
a %= 65521;
b %= 65521;
}
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
}
function adler32_buf(buf) {
var a = 1, b = 0, L = buf.length, M;
for(var i = 0; i < L;) {
M = Math.min(L-i, 3854);
for(;M>0;--M) {
a += buf[i++];
b += a;
}
a %= 65521;
b %= 65521;
}
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
}
/* much much faster to intertwine utf8 and adler */
function adler32_str(str) {
var a = 1, b = 0, L = str.length, M, c, d;
for(var i = 0; i < L;) {
M = Math.min(L-i, 3850);
while(M>0) {
c = str.charCodeAt(i++);
if(c < 0x80) { a += c; b += a; --M; }
else if(c < 0x800) {
a += 192|((c>>6)&31); b += a; --M;
a += 128|(c&63); b += a; --M;
} else if(c >= 0xD800 && c < 0xE000) {
c = (c&1023)+64; d = str.charCodeAt(i++) & 1023;
a += 240|((c>>8)&7); b += a; --M;
a += 128|((c>>2)&63); b += a; --M;
a += 128|((d>>6)&15)|(c&3); b += a; --M;
a += 128|(d&63); b += a; --M;
} else {
a += 224|((c>>12)&15); b += a; --M;
a += 128|((c>>6)&63); b += a; --M;
a += 128|(c&63); b += a; --M;
}
}
a %= 65521;
b %= 65521;
}
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
}
ADLER32.bstr = adler32_bstr;
ADLER32.buf = adler32_buf;
ADLER32.str = adler32_str;
})(typeof exports !== "undefined" && typeof DO_NOT_EXPORT_ADLER === 'undefined' ? exports : ADLER32);

2
ctest/fakeassert.js Normal file
View File

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

11
ctest/fixtures.js Normal file
View File

@ -0,0 +1,11 @@
var o = "foo bar baz٪☃🍣";
var bits = [
[ "Wikipedia", 300286872, 1 ],
[ "foo bar baz", 398066679, 1 ],
[ "foo bar baz٪", 570688890 ],
[ "foo bar baz٪☃", 919275383],
[ "foo bar baz٪☃🍣", 1543572022],
[ o+o, -2076896149 ],
[ o+o+o, 2023497376 ]
];
if(typeof module !== "undefined") module.exports = bits;

21
ctest/index.html Normal file
View 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="adler32.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
View 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

21
ctest/test.js Normal file
View File

@ -0,0 +1,21 @@
/* 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');
} else { X = ADLER32; }
describe('adler32 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);
});
});
});

11
misc/bits.js Normal file
View File

@ -0,0 +1,11 @@
var o = "foo bar baz٪☃🍣";
var bits = [
[ "Wikipedia", 300286872, 1 ],
[ "foo bar baz", 398066679, 1 ],
[ "foo bar baz٪", 570688890 ],
[ "foo bar baz٪☃", 919275383],
[ "foo bar baz٪☃🍣", 1543572022],
[ o+o, -2076896149 ],
[ o+o+o, 2023497376 ]
];
if(typeof module !== "undefined") module.exports = bits;

14
misc/spin.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/bash
# spin.sh -- show a spinner (for coverage test)
# Copyright (C) 2014 SheetJS
wpid=$1
delay=1
str="|/-\\"
while [ $(ps -a|awk '$1=='$wpid' {print $1}') ]; do
t=${str#?}
printf " [%c]" "$str"
str=$t${str%"$t"}
sleep $delay
printf "\b\b\b\b"
done

28
package.json Normal file
View File

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

35
perf/bm.js Normal file
View File

@ -0,0 +1,35 @@
/* bm.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 });
this.suites = [];
this.maxlen = 0;
}
BM.prototype.run = function() {
var maxlen = this.maxlen, ss = this.suite;
this.suites.forEach(function(s) { ss.add(s[0] + new Array(maxlen-s[0].length+1).join(" "), s[1]); });
if(this.suites.length > 0) this.suite.run();
};
BM.prototype.add = function(msg, test) {
this.suites.push([msg, {
onCycle: test_cycle,
onComplete: test_end,
defer: false,
fn: test
}]);
this.maxlen = Math.max(this.maxlen, msg.length);
};
module.exports = BM;

38
perf/bstr.js Normal file
View File

@ -0,0 +1,38 @@
var table = require('../').table;
function sheetjs1(bstr) {
var a = 1, b = 0, L = bstr.length;
for(var i = 0; i < L;) {
a += bstr.charCodeAt(i++);
a %= 65521;
b += a;
b %= 65521;
}
return (b << 16) | a;
}
function sheetjs2(bstr) {
var a = 1, b = 0, L = bstr.length, M;
for(var i = 0; i < L;) {
M = Math.min(L-i, 3854);
for(;M>0;--M) {
a += bstr.charCodeAt(i++);
b += a;
}
a %= 65521;
b %= 65521;
}
return (b << 16) | a;
}
var foobar = "foobarbazqux";
for(var i = 0; i != 11; ++i) foobar += " " + foobar;
var assert = require('assert');
assert.equal(sheetjs1(foobar), sheetjs2(foobar));
var BM = require('./bm');
var suite = new BM('binary string');
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();

5
perf/perf.sh Executable file
View File

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

57
perf/utf8.js Normal file
View File

@ -0,0 +1,57 @@
var table = require('../').table;
function sheetjs1(utf8) {
var buf = Buffer(utf8);
var a = 1, b = 0, L = buf.length, M;
for(var i = 0; i < L;) {
M = Math.min(L-i, 3854);
for(;M>0;--M) {
a += buf[i++];
b += a;
}
a %= 65521;
b %= 65521;
}
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
}
function sheetjs2(utf8) {
var a = 1, b = 0, L = utf8.length, M, c, d;
for(var i = 0; i < L;) {
M = Math.min(L-i, 3850);
while(M>0) {
c = utf8.charCodeAt(i++);
if(c < 0x80) { a += c; b += a; --M; }
else if(c < 0x800) {
a += 192|((c>>6)&31); b += a; --M;
a += 128|(c&63); b += a; --M;
} else if(c >= 0xD800 && c < 0xE000) {
c = (c&1023)+64; d = utf8.charCodeAt(i++) & 1023;
a += 240|((c>>8)&7); b += a; --M;
a += 128|((c>>2)&63); b += a; --M;
a += 128|((d>>6)&15)|(c&3); b += a; --M;
a += 128|(d&63); b += a; --M;
} else {
a += 224|((c>>12)&15); b += a; --M;
a += 128|((c>>6)&63); b += a; --M;
a += 128|(c&63); b += a; --M;
}
}
a %= 65521;
b %= 65521;
}
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
}
var foobar = "foo bar baz٪☃🍣";
for(var i = 0; i != 11; ++i) foobar += " " + foobar;
var assert = require('assert');
sheetjs1(foobar); sheetjs2(foobar);
assert.equal(sheetjs1(foobar), sheetjs2(foobar));
var BM = require('./bm');
var suite = new BM('unicode string');
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();

21
test.js Normal file
View File

@ -0,0 +1,21 @@
/* 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');
} else { X = ADLER32; }
describe('adler32 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);
});
});
});