Skip to content

Commit 35d59c5

Browse files
committed
version bump 1.0.6: performance
- `unsafe` option to `cfb_add` for bulk write (see #2) - use `lastIndexOf` to save operations in BFP queue
1 parent 17b1a8d commit 35d59c5

17 files changed

+71
-47
lines changed

Diff for: CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ This log is intended to keep track of backwards-incompatible changes, including
44
but not limited to API changes and file location changes. Minor behavioral
55
changes may not be included if they are not expected to break existing code.
66

7+
## 1.0.6 (2018-04-09)
8+
9+
* `lastIndexOf` in FAT builder enables larger file parsing at minor cost
10+
711
## 1.0.0 (2017-11-05)
812

913
* Actually walk mini-fat

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ accept a `name` argument strictly deal with absolute file names:
111111

112112
- `.cfb_new(?opts)` creates a new container object.
113113
- `.cfb_add(cfb, name, ?content, ?opts)` adds a new file to the `cfb`.
114+
Set the option `{unsafe:true}` to skip existence checks (for bulk additions)
114115
- `.cfb_del(cfb, name)` deletes the specified file
115116
- `.cfb_mov(cfb, old_name, new_name)` moves the old file to new path and name
116117

Diff for: bits/31_version.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
exports.version = '1.0.5';
1+
exports.version = '1.0.6';

Diff for: bits/43_rbtree.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ function build_full_paths(FI/*:CFBFileIndex*/, FP/*:Array<string>*/, Paths/*:Arr
1313
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
1414
}
1515
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
16-
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
17-
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
16+
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
17+
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
1818
}
1919
for(i=1; i < pl; ++i) if(dad[i] === i) {
2020
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];

Diff for: bits/85_api.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ function cfb_new(opts/*:?any*/)/*:CFBContainer*/ {
55
}
66

77
function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, opts/*:?any*/)/*:CFBEntry*/ {
8-
init_cfb(cfb);
9-
var file = CFB.find(cfb, name);
8+
var unsafe = opts && opts.unsafe;
9+
if(!unsafe) init_cfb(cfb);
10+
var file = !unsafe && CFB.find(cfb, name);
1011
if(!file) {
1112
var fpath/*:string*/ = cfb.FullPaths[0];
1213
if(name.slice(0, fpath.length) == fpath) fpath = name;
@@ -17,7 +18,7 @@ function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, o
1718
file = ({name: filename(name), type: 2}/*:any*/);
1819
cfb.FileIndex.push(file);
1920
cfb.FullPaths.push(fpath);
20-
CFB.utils.cfb_gc(cfb);
21+
if(!unsafe) CFB.utils.cfb_gc(cfb);
2122
}
2223
/*:: if(!file) throw new Error("unreachable"); */
2324
file.content = (content/*:any*/);

Diff for: cfb.flow.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ type CFBFiles = {[n:string]:CFBEntry};
177177
/* [MS-CFB] v20171201 */
178178
var CFB = (function _CFB(){
179179
var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/;
180-
exports.version = '1.0.5';
180+
exports.version = '1.0.6';
181181
/* [MS-CFB] 2.6.4 */
182182
function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
183183
var L = l.split("/"), R = r.split("/");
@@ -355,8 +355,8 @@ function build_full_paths(FI/*:CFBFileIndex*/, FP/*:Array<string>*/, Paths/*:Arr
355355
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
356356
}
357357
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
358-
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
359-
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
358+
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
359+
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
360360
}
361361
for(i=1; i < pl; ++i) if(dad[i] === i) {
362362
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
@@ -823,8 +823,9 @@ function cfb_new(opts/*:?any*/)/*:CFBContainer*/ {
823823
}
824824

825825
function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, opts/*:?any*/)/*:CFBEntry*/ {
826-
init_cfb(cfb);
827-
var file = CFB.find(cfb, name);
826+
var unsafe = opts && opts.unsafe;
827+
if(!unsafe) init_cfb(cfb);
828+
var file = !unsafe && CFB.find(cfb, name);
828829
if(!file) {
829830
var fpath/*:string*/ = cfb.FullPaths[0];
830831
if(name.slice(0, fpath.length) == fpath) fpath = name;
@@ -835,7 +836,7 @@ function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, o
835836
file = ({name: filename(name), type: 2}/*:any*/);
836837
cfb.FileIndex.push(file);
837838
cfb.FullPaths.push(fpath);
838-
CFB.utils.cfb_gc(cfb);
839+
if(!unsafe) CFB.utils.cfb_gc(cfb);
839840
}
840841
/*:: if(!file) throw new Error("unreachable"); */
841842
file.content = (content/*:any*/);

Diff for: cfb.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ function new_buf(sz) {
159159
/* [MS-CFB] v20171201 */
160160
var CFB = (function _CFB(){
161161
var exports = {};
162-
exports.version = '1.0.5';
162+
exports.version = '1.0.6';
163163
/* [MS-CFB] 2.6.4 */
164164
function namecmp(l, r) {
165165
var L = l.split("/"), R = r.split("/");
@@ -337,8 +337,8 @@ function build_full_paths(FI, FP, Paths) {
337337
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
338338
}
339339
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
340-
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
341-
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
340+
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
341+
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
342342
}
343343
for(i=1; i < pl; ++i) if(dad[i] === i) {
344344
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
@@ -799,8 +799,9 @@ function cfb_new(opts) {
799799
}
800800

801801
function cfb_add(cfb, name, content, opts) {
802-
init_cfb(cfb);
803-
var file = CFB.find(cfb, name);
802+
var unsafe = opts && opts.unsafe;
803+
if(!unsafe) init_cfb(cfb);
804+
var file = !unsafe && CFB.find(cfb, name);
804805
if(!file) {
805806
var fpath = cfb.FullPaths[0];
806807
if(name.slice(0, fpath.length) == fpath) fpath = name;
@@ -811,7 +812,7 @@ function cfb_add(cfb, name, content, opts) {
811812
file = ({name: filename(name), type: 2});
812813
cfb.FileIndex.push(file);
813814
cfb.FullPaths.push(fpath);
814-
CFB.utils.cfb_gc(cfb);
815+
if(!unsafe) CFB.utils.cfb_gc(cfb);
815816
}
816817
file.content = (content);
817818
file.size = content ? content.length : 0;

Diff for: dist/cfb.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ function new_buf(sz) {
159159
/* [MS-CFB] v20171201 */
160160
var CFB = (function _CFB(){
161161
var exports = {};
162-
exports.version = '1.0.5';
162+
exports.version = '1.0.6';
163163
/* [MS-CFB] 2.6.4 */
164164
function namecmp(l, r) {
165165
var L = l.split("/"), R = r.split("/");
@@ -337,8 +337,8 @@ function build_full_paths(FI, FP, Paths) {
337337
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
338338
}
339339
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
340-
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
341-
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
340+
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
341+
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
342342
}
343343
for(i=1; i < pl; ++i) if(dad[i] === i) {
344344
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
@@ -799,8 +799,9 @@ function cfb_new(opts) {
799799
}
800800

801801
function cfb_add(cfb, name, content, opts) {
802-
init_cfb(cfb);
803-
var file = CFB.find(cfb, name);
802+
var unsafe = opts && opts.unsafe;
803+
if(!unsafe) init_cfb(cfb);
804+
var file = !unsafe && CFB.find(cfb, name);
804805
if(!file) {
805806
var fpath = cfb.FullPaths[0];
806807
if(name.slice(0, fpath.length) == fpath) fpath = name;
@@ -811,7 +812,7 @@ function cfb_add(cfb, name, content, opts) {
811812
file = ({name: filename(name), type: 2});
812813
cfb.FileIndex.push(file);
813814
cfb.FullPaths.push(fpath);
814-
CFB.utils.cfb_gc(cfb);
815+
if(!unsafe) CFB.utils.cfb_gc(cfb);
815816
}
816817
file.content = (content);
817818
file.size = content ? content.length : 0;

Diff for: dist/cfb.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: dist/cfb.min.map

+1-1
Large diffs are not rendered by default.

Diff for: dist/xlscfb.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type CFBFiles = {[n:string]:CFBEntry};
3838
/* [MS-CFB] v20171201 */
3939
var CFB = (function _CFB(){
4040
var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/;
41-
exports.version = '1.0.5';
41+
exports.version = '1.0.6';
4242
/* [MS-CFB] 2.6.4 */
4343
function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
4444
var L = l.split("/"), R = r.split("/");
@@ -216,8 +216,8 @@ function build_full_paths(FI/*:CFBFileIndex*/, FP/*:Array<string>*/, Paths/*:Arr
216216
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
217217
}
218218
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
219-
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
220-
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
219+
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
220+
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
221221
}
222222
for(i=1; i < pl; ++i) if(dad[i] === i) {
223223
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
@@ -684,8 +684,9 @@ function cfb_new(opts/*:?any*/)/*:CFBContainer*/ {
684684
}
685685

686686
function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, opts/*:?any*/)/*:CFBEntry*/ {
687-
init_cfb(cfb);
688-
var file = CFB.find(cfb, name);
687+
var unsafe = opts && opts.unsafe;
688+
if(!unsafe) init_cfb(cfb);
689+
var file = !unsafe && CFB.find(cfb, name);
689690
if(!file) {
690691
var fpath/*:string*/ = cfb.FullPaths[0];
691692
if(name.slice(0, fpath.length) == fpath) fpath = name;
@@ -696,7 +697,7 @@ function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, o
696697
file = ({name: filename(name), type: 2}/*:any*/);
697698
cfb.FileIndex.push(file);
698699
cfb.FullPaths.push(fpath);
699-
CFB.utils.cfb_gc(cfb);
700+
if(!unsafe) CFB.utils.cfb_gc(cfb);
700701
}
701702
/*:: if(!file) throw new Error("unreachable"); */
702703
file.content = (content/*:any*/);

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cfb",
3-
"version": "1.0.5",
3+
"version": "1.0.6",
44
"author": "sheetjs",
55
"description": "Compound File Binary File Format extractor",
66
"keywords": [

Diff for: shim.js

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ if(!Array.prototype.indexOf) Array.prototype.indexOf = function(needle) {
1818
return -1;
1919
};
2020

21+
if(!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(needle) {
22+
var len = (this.length>>>0), i = len - 1;
23+
for(; i>=0; --i) if(this[i] === needle) return i;
24+
return -1;
25+
};
26+
2127
if(!Array.isArray) Array.isArray = function(obj) { return Object.prototype.toString.call(obj) === "[object Array]"; };
2228

2329
if(typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) ArrayBuffer.prototype.slice = function(start, end) {

Diff for: types/index.d.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,16 @@ export interface CFB$Container {
9191
};
9292
}
9393

94+
/** cfb_add options */
95+
export interface CFB$AddOpts {
96+
/** Skip existence and safety checks (best for bulk write operations) */
97+
unsafe?: boolean;
98+
}
99+
94100
/** General utilities */
95101
export interface CFB$Utils {
96102
cfb_new(opts?: any): CFB$Container;
97-
cfb_add(cfb: CFB$Container, name: string, content: any, opts?: any): CFB$Entry;
103+
cfb_add(cfb: CFB$Container, name: string, content: any, opts?: CFB$AddOpts): CFB$Entry;
98104
cfb_del(cfb: CFB$Container, name: string): boolean;
99105
cfb_mov(cfb: CFB$Container, old_name: string, new_name: string): boolean;
100106
cfb_gc(cfb: CFB$Container): void;

Diff for: types/roundtrip.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const old_cfb = CFB.read("t2.xls", {type:"file"});
6161
const new_cfb = CFB.utils.cfb_new({root:"R", clsid: old_cfb.FileIndex[0].clsid });
6262
old_cfb.FullPaths.forEach((p, i) => {
6363
if(p.slice(-1) === "/") return;
64-
CFB.utils.cfb_add(new_cfb, p.replace(/^[^/]*/,"R"), old_cfb.FileIndex[i].content);
64+
CFB.utils.cfb_add(new_cfb, p.replace(/^[^/]*/,"R"), old_cfb.FileIndex[i].content, {unsafe: true});
6565
});
6666
dumpit(new_cfb);
6767
CFB.writeFile(new_cfb, "t3.xls");

Diff for: xlscfb.flow.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type CFBFiles = {[n:string]:CFBEntry};
3838
/* [MS-CFB] v20171201 */
3939
var CFB = (function _CFB(){
4040
var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/;
41-
exports.version = '1.0.5';
41+
exports.version = '1.0.6';
4242
/* [MS-CFB] 2.6.4 */
4343
function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
4444
var L = l.split("/"), R = r.split("/");
@@ -216,8 +216,8 @@ function build_full_paths(FI/*:CFBFileIndex*/, FP/*:Array<string>*/, Paths/*:Arr
216216
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
217217
}
218218
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
219-
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
220-
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
219+
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
220+
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
221221
}
222222
for(i=1; i < pl; ++i) if(dad[i] === i) {
223223
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
@@ -684,8 +684,9 @@ function cfb_new(opts/*:?any*/)/*:CFBContainer*/ {
684684
}
685685

686686
function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, opts/*:?any*/)/*:CFBEntry*/ {
687-
init_cfb(cfb);
688-
var file = CFB.find(cfb, name);
687+
var unsafe = opts && opts.unsafe;
688+
if(!unsafe) init_cfb(cfb);
689+
var file = !unsafe && CFB.find(cfb, name);
689690
if(!file) {
690691
var fpath/*:string*/ = cfb.FullPaths[0];
691692
if(name.slice(0, fpath.length) == fpath) fpath = name;
@@ -696,7 +697,7 @@ function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, o
696697
file = ({name: filename(name), type: 2}/*:any*/);
697698
cfb.FileIndex.push(file);
698699
cfb.FullPaths.push(fpath);
699-
CFB.utils.cfb_gc(cfb);
700+
if(!unsafe) CFB.utils.cfb_gc(cfb);
700701
}
701702
/*:: if(!file) throw new Error("unreachable"); */
702703
file.content = (content/*:any*/);

Diff for: xlscfb.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ var DO_NOT_EXPORT_CFB = true;
88
/* [MS-CFB] v20171201 */
99
var CFB = (function _CFB(){
1010
var exports = {};
11-
exports.version = '1.0.5';
11+
exports.version = '1.0.6';
1212
/* [MS-CFB] 2.6.4 */
1313
function namecmp(l, r) {
1414
var L = l.split("/"), R = r.split("/");
@@ -186,8 +186,8 @@ function build_full_paths(FI, FP, Paths) {
186186
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
187187
}
188188
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
189-
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
190-
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
189+
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
190+
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
191191
}
192192
for(i=1; i < pl; ++i) if(dad[i] === i) {
193193
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
@@ -648,8 +648,9 @@ function cfb_new(opts) {
648648
}
649649

650650
function cfb_add(cfb, name, content, opts) {
651-
init_cfb(cfb);
652-
var file = CFB.find(cfb, name);
651+
var unsafe = opts && opts.unsafe;
652+
if(!unsafe) init_cfb(cfb);
653+
var file = !unsafe && CFB.find(cfb, name);
653654
if(!file) {
654655
var fpath = cfb.FullPaths[0];
655656
if(name.slice(0, fpath.length) == fpath) fpath = name;
@@ -660,7 +661,7 @@ function cfb_add(cfb, name, content, opts) {
660661
file = ({name: filename(name), type: 2});
661662
cfb.FileIndex.push(file);
662663
cfb.FullPaths.push(fpath);
663-
CFB.utils.cfb_gc(cfb);
664+
if(!unsafe) CFB.utils.cfb_gc(cfb);
664665
}
665666
file.content = (content);
666667
file.size = content ? content.length : 0;

0 commit comments

Comments
 (0)