version bump 1.0.6: performance
- `unsafe` option to `cfb_add` for bulk write (see #2) - use `lastIndexOf` to save operations in BFP queue
This commit is contained in:
parent
17b1a8de5a
commit
35d59c57bf
@ -4,6 +4,10 @@ This log is intended to keep track of backwards-incompatible changes, including
|
||||
but not limited to API changes and file location changes. Minor behavioral
|
||||
changes may not be included if they are not expected to break existing code.
|
||||
|
||||
## 1.0.6 (2018-04-09)
|
||||
|
||||
* `lastIndexOf` in FAT builder enables larger file parsing at minor cost
|
||||
|
||||
## 1.0.0 (2017-11-05)
|
||||
|
||||
* Actually walk mini-fat
|
||||
|
@ -111,6 +111,7 @@ accept a `name` argument strictly deal with absolute file names:
|
||||
|
||||
- `.cfb_new(?opts)` creates a new container object.
|
||||
- `.cfb_add(cfb, name, ?content, ?opts)` adds a new file to the `cfb`.
|
||||
Set the option `{unsafe:true}` to skip existence checks (for bulk additions)
|
||||
- `.cfb_del(cfb, name)` deletes the specified file
|
||||
- `.cfb_mov(cfb, old_name, new_name)` moves the old file to new path and name
|
||||
|
||||
|
@ -1 +1 @@
|
||||
exports.version = '1.0.5';
|
||||
exports.version = '1.0.6';
|
||||
|
@ -13,8 +13,8 @@ function build_full_paths(FI/*:CFBFileIndex*/, FP/*:Array<string>*/, Paths/*:Arr
|
||||
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
|
||||
}
|
||||
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
|
||||
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
|
||||
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
|
||||
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
|
||||
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
|
||||
}
|
||||
for(i=1; i < pl; ++i) if(dad[i] === i) {
|
||||
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
|
||||
|
@ -5,8 +5,9 @@ function cfb_new(opts/*:?any*/)/*:CFBContainer*/ {
|
||||
}
|
||||
|
||||
function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, opts/*:?any*/)/*:CFBEntry*/ {
|
||||
init_cfb(cfb);
|
||||
var file = CFB.find(cfb, name);
|
||||
var unsafe = opts && opts.unsafe;
|
||||
if(!unsafe) init_cfb(cfb);
|
||||
var file = !unsafe && CFB.find(cfb, name);
|
||||
if(!file) {
|
||||
var fpath/*:string*/ = cfb.FullPaths[0];
|
||||
if(name.slice(0, fpath.length) == fpath) fpath = name;
|
||||
@ -17,7 +18,7 @@ function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, o
|
||||
file = ({name: filename(name), type: 2}/*:any*/);
|
||||
cfb.FileIndex.push(file);
|
||||
cfb.FullPaths.push(fpath);
|
||||
CFB.utils.cfb_gc(cfb);
|
||||
if(!unsafe) CFB.utils.cfb_gc(cfb);
|
||||
}
|
||||
/*:: if(!file) throw new Error("unreachable"); */
|
||||
file.content = (content/*:any*/);
|
||||
|
13
cfb.flow.js
13
cfb.flow.js
@ -177,7 +177,7 @@ type CFBFiles = {[n:string]:CFBEntry};
|
||||
/* [MS-CFB] v20171201 */
|
||||
var CFB = (function _CFB(){
|
||||
var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/;
|
||||
exports.version = '1.0.5';
|
||||
exports.version = '1.0.6';
|
||||
/* [MS-CFB] 2.6.4 */
|
||||
function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
|
||||
var L = l.split("/"), R = r.split("/");
|
||||
@ -355,8 +355,8 @@ function build_full_paths(FI/*:CFBFileIndex*/, FP/*:Array<string>*/, Paths/*:Arr
|
||||
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
|
||||
}
|
||||
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
|
||||
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
|
||||
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
|
||||
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
|
||||
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
|
||||
}
|
||||
for(i=1; i < pl; ++i) if(dad[i] === i) {
|
||||
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
|
||||
@ -823,8 +823,9 @@ function cfb_new(opts/*:?any*/)/*:CFBContainer*/ {
|
||||
}
|
||||
|
||||
function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, opts/*:?any*/)/*:CFBEntry*/ {
|
||||
init_cfb(cfb);
|
||||
var file = CFB.find(cfb, name);
|
||||
var unsafe = opts && opts.unsafe;
|
||||
if(!unsafe) init_cfb(cfb);
|
||||
var file = !unsafe && CFB.find(cfb, name);
|
||||
if(!file) {
|
||||
var fpath/*:string*/ = cfb.FullPaths[0];
|
||||
if(name.slice(0, fpath.length) == fpath) fpath = name;
|
||||
@ -835,7 +836,7 @@ function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, o
|
||||
file = ({name: filename(name), type: 2}/*:any*/);
|
||||
cfb.FileIndex.push(file);
|
||||
cfb.FullPaths.push(fpath);
|
||||
CFB.utils.cfb_gc(cfb);
|
||||
if(!unsafe) CFB.utils.cfb_gc(cfb);
|
||||
}
|
||||
/*:: if(!file) throw new Error("unreachable"); */
|
||||
file.content = (content/*:any*/);
|
||||
|
13
cfb.js
13
cfb.js
@ -159,7 +159,7 @@ function new_buf(sz) {
|
||||
/* [MS-CFB] v20171201 */
|
||||
var CFB = (function _CFB(){
|
||||
var exports = {};
|
||||
exports.version = '1.0.5';
|
||||
exports.version = '1.0.6';
|
||||
/* [MS-CFB] 2.6.4 */
|
||||
function namecmp(l, r) {
|
||||
var L = l.split("/"), R = r.split("/");
|
||||
@ -337,8 +337,8 @@ function build_full_paths(FI, FP, Paths) {
|
||||
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
|
||||
}
|
||||
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
|
||||
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
|
||||
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
|
||||
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
|
||||
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
|
||||
}
|
||||
for(i=1; i < pl; ++i) if(dad[i] === i) {
|
||||
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
|
||||
@ -799,8 +799,9 @@ function cfb_new(opts) {
|
||||
}
|
||||
|
||||
function cfb_add(cfb, name, content, opts) {
|
||||
init_cfb(cfb);
|
||||
var file = CFB.find(cfb, name);
|
||||
var unsafe = opts && opts.unsafe;
|
||||
if(!unsafe) init_cfb(cfb);
|
||||
var file = !unsafe && CFB.find(cfb, name);
|
||||
if(!file) {
|
||||
var fpath = cfb.FullPaths[0];
|
||||
if(name.slice(0, fpath.length) == fpath) fpath = name;
|
||||
@ -811,7 +812,7 @@ function cfb_add(cfb, name, content, opts) {
|
||||
file = ({name: filename(name), type: 2});
|
||||
cfb.FileIndex.push(file);
|
||||
cfb.FullPaths.push(fpath);
|
||||
CFB.utils.cfb_gc(cfb);
|
||||
if(!unsafe) CFB.utils.cfb_gc(cfb);
|
||||
}
|
||||
file.content = (content);
|
||||
file.size = content ? content.length : 0;
|
||||
|
13
dist/cfb.js
vendored
13
dist/cfb.js
vendored
@ -159,7 +159,7 @@ function new_buf(sz) {
|
||||
/* [MS-CFB] v20171201 */
|
||||
var CFB = (function _CFB(){
|
||||
var exports = {};
|
||||
exports.version = '1.0.5';
|
||||
exports.version = '1.0.6';
|
||||
/* [MS-CFB] 2.6.4 */
|
||||
function namecmp(l, r) {
|
||||
var L = l.split("/"), R = r.split("/");
|
||||
@ -337,8 +337,8 @@ function build_full_paths(FI, FP, Paths) {
|
||||
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
|
||||
}
|
||||
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
|
||||
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
|
||||
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
|
||||
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
|
||||
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
|
||||
}
|
||||
for(i=1; i < pl; ++i) if(dad[i] === i) {
|
||||
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
|
||||
@ -799,8 +799,9 @@ function cfb_new(opts) {
|
||||
}
|
||||
|
||||
function cfb_add(cfb, name, content, opts) {
|
||||
init_cfb(cfb);
|
||||
var file = CFB.find(cfb, name);
|
||||
var unsafe = opts && opts.unsafe;
|
||||
if(!unsafe) init_cfb(cfb);
|
||||
var file = !unsafe && CFB.find(cfb, name);
|
||||
if(!file) {
|
||||
var fpath = cfb.FullPaths[0];
|
||||
if(name.slice(0, fpath.length) == fpath) fpath = name;
|
||||
@ -811,7 +812,7 @@ function cfb_add(cfb, name, content, opts) {
|
||||
file = ({name: filename(name), type: 2});
|
||||
cfb.FileIndex.push(file);
|
||||
cfb.FullPaths.push(fpath);
|
||||
CFB.utils.cfb_gc(cfb);
|
||||
if(!unsafe) CFB.utils.cfb_gc(cfb);
|
||||
}
|
||||
file.content = (content);
|
||||
file.size = content ? content.length : 0;
|
||||
|
2
dist/cfb.min.js
vendored
2
dist/cfb.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/cfb.min.map
vendored
2
dist/cfb.min.map
vendored
File diff suppressed because one or more lines are too long
13
dist/xlscfb.js
vendored
13
dist/xlscfb.js
vendored
@ -38,7 +38,7 @@ type CFBFiles = {[n:string]:CFBEntry};
|
||||
/* [MS-CFB] v20171201 */
|
||||
var CFB = (function _CFB(){
|
||||
var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/;
|
||||
exports.version = '1.0.5';
|
||||
exports.version = '1.0.6';
|
||||
/* [MS-CFB] 2.6.4 */
|
||||
function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
|
||||
var L = l.split("/"), R = r.split("/");
|
||||
@ -216,8 +216,8 @@ function build_full_paths(FI/*:CFBFileIndex*/, FP/*:Array<string>*/, Paths/*:Arr
|
||||
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
|
||||
}
|
||||
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
|
||||
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
|
||||
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
|
||||
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
|
||||
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
|
||||
}
|
||||
for(i=1; i < pl; ++i) if(dad[i] === i) {
|
||||
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
|
||||
@ -684,8 +684,9 @@ function cfb_new(opts/*:?any*/)/*:CFBContainer*/ {
|
||||
}
|
||||
|
||||
function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, opts/*:?any*/)/*:CFBEntry*/ {
|
||||
init_cfb(cfb);
|
||||
var file = CFB.find(cfb, name);
|
||||
var unsafe = opts && opts.unsafe;
|
||||
if(!unsafe) init_cfb(cfb);
|
||||
var file = !unsafe && CFB.find(cfb, name);
|
||||
if(!file) {
|
||||
var fpath/*:string*/ = cfb.FullPaths[0];
|
||||
if(name.slice(0, fpath.length) == fpath) fpath = name;
|
||||
@ -696,7 +697,7 @@ function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, o
|
||||
file = ({name: filename(name), type: 2}/*:any*/);
|
||||
cfb.FileIndex.push(file);
|
||||
cfb.FullPaths.push(fpath);
|
||||
CFB.utils.cfb_gc(cfb);
|
||||
if(!unsafe) CFB.utils.cfb_gc(cfb);
|
||||
}
|
||||
/*:: if(!file) throw new Error("unreachable"); */
|
||||
file.content = (content/*:any*/);
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cfb",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"author": "sheetjs",
|
||||
"description": "Compound File Binary File Format extractor",
|
||||
"keywords": [
|
||||
|
6
shim.js
6
shim.js
@ -18,6 +18,12 @@ if(!Array.prototype.indexOf) Array.prototype.indexOf = function(needle) {
|
||||
return -1;
|
||||
};
|
||||
|
||||
if(!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(needle) {
|
||||
var len = (this.length>>>0), i = len - 1;
|
||||
for(; i>=0; --i) if(this[i] === needle) return i;
|
||||
return -1;
|
||||
};
|
||||
|
||||
if(!Array.isArray) Array.isArray = function(obj) { return Object.prototype.toString.call(obj) === "[object Array]"; };
|
||||
|
||||
if(typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) ArrayBuffer.prototype.slice = function(start, end) {
|
||||
|
8
types/index.d.ts
vendored
8
types/index.d.ts
vendored
@ -91,10 +91,16 @@ export interface CFB$Container {
|
||||
};
|
||||
}
|
||||
|
||||
/** cfb_add options */
|
||||
export interface CFB$AddOpts {
|
||||
/** Skip existence and safety checks (best for bulk write operations) */
|
||||
unsafe?: boolean;
|
||||
}
|
||||
|
||||
/** General utilities */
|
||||
export interface CFB$Utils {
|
||||
cfb_new(opts?: any): CFB$Container;
|
||||
cfb_add(cfb: CFB$Container, name: string, content: any, opts?: any): CFB$Entry;
|
||||
cfb_add(cfb: CFB$Container, name: string, content: any, opts?: CFB$AddOpts): CFB$Entry;
|
||||
cfb_del(cfb: CFB$Container, name: string): boolean;
|
||||
cfb_mov(cfb: CFB$Container, old_name: string, new_name: string): boolean;
|
||||
cfb_gc(cfb: CFB$Container): void;
|
||||
|
@ -61,7 +61,7 @@ const old_cfb = CFB.read("t2.xls", {type:"file"});
|
||||
const new_cfb = CFB.utils.cfb_new({root:"R", clsid: old_cfb.FileIndex[0].clsid });
|
||||
old_cfb.FullPaths.forEach((p, i) => {
|
||||
if(p.slice(-1) === "/") return;
|
||||
CFB.utils.cfb_add(new_cfb, p.replace(/^[^/]*/,"R"), old_cfb.FileIndex[i].content);
|
||||
CFB.utils.cfb_add(new_cfb, p.replace(/^[^/]*/,"R"), old_cfb.FileIndex[i].content, {unsafe: true});
|
||||
});
|
||||
dumpit(new_cfb);
|
||||
CFB.writeFile(new_cfb, "t3.xls");
|
||||
|
@ -38,7 +38,7 @@ type CFBFiles = {[n:string]:CFBEntry};
|
||||
/* [MS-CFB] v20171201 */
|
||||
var CFB = (function _CFB(){
|
||||
var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/;
|
||||
exports.version = '1.0.5';
|
||||
exports.version = '1.0.6';
|
||||
/* [MS-CFB] 2.6.4 */
|
||||
function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
|
||||
var L = l.split("/"), R = r.split("/");
|
||||
@ -216,8 +216,8 @@ function build_full_paths(FI/*:CFBFileIndex*/, FP/*:Array<string>*/, Paths/*:Arr
|
||||
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
|
||||
}
|
||||
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
|
||||
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
|
||||
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
|
||||
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
|
||||
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
|
||||
}
|
||||
for(i=1; i < pl; ++i) if(dad[i] === i) {
|
||||
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
|
||||
@ -684,8 +684,9 @@ function cfb_new(opts/*:?any*/)/*:CFBContainer*/ {
|
||||
}
|
||||
|
||||
function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, opts/*:?any*/)/*:CFBEntry*/ {
|
||||
init_cfb(cfb);
|
||||
var file = CFB.find(cfb, name);
|
||||
var unsafe = opts && opts.unsafe;
|
||||
if(!unsafe) init_cfb(cfb);
|
||||
var file = !unsafe && CFB.find(cfb, name);
|
||||
if(!file) {
|
||||
var fpath/*:string*/ = cfb.FullPaths[0];
|
||||
if(name.slice(0, fpath.length) == fpath) fpath = name;
|
||||
@ -696,7 +697,7 @@ function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, o
|
||||
file = ({name: filename(name), type: 2}/*:any*/);
|
||||
cfb.FileIndex.push(file);
|
||||
cfb.FullPaths.push(fpath);
|
||||
CFB.utils.cfb_gc(cfb);
|
||||
if(!unsafe) CFB.utils.cfb_gc(cfb);
|
||||
}
|
||||
/*:: if(!file) throw new Error("unreachable"); */
|
||||
file.content = (content/*:any*/);
|
||||
|
13
xlscfb.js
13
xlscfb.js
@ -8,7 +8,7 @@ var DO_NOT_EXPORT_CFB = true;
|
||||
/* [MS-CFB] v20171201 */
|
||||
var CFB = (function _CFB(){
|
||||
var exports = {};
|
||||
exports.version = '1.0.5';
|
||||
exports.version = '1.0.6';
|
||||
/* [MS-CFB] 2.6.4 */
|
||||
function namecmp(l, r) {
|
||||
var L = l.split("/"), R = r.split("/");
|
||||
@ -186,8 +186,8 @@ function build_full_paths(FI, FP, Paths) {
|
||||
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
|
||||
}
|
||||
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
|
||||
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
|
||||
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
|
||||
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
|
||||
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
|
||||
}
|
||||
for(i=1; i < pl; ++i) if(dad[i] === i) {
|
||||
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
|
||||
@ -648,8 +648,9 @@ function cfb_new(opts) {
|
||||
}
|
||||
|
||||
function cfb_add(cfb, name, content, opts) {
|
||||
init_cfb(cfb);
|
||||
var file = CFB.find(cfb, name);
|
||||
var unsafe = opts && opts.unsafe;
|
||||
if(!unsafe) init_cfb(cfb);
|
||||
var file = !unsafe && CFB.find(cfb, name);
|
||||
if(!file) {
|
||||
var fpath = cfb.FullPaths[0];
|
||||
if(name.slice(0, fpath.length) == fpath) fpath = name;
|
||||
@ -660,7 +661,7 @@ function cfb_add(cfb, name, content, opts) {
|
||||
file = ({name: filename(name), type: 2});
|
||||
cfb.FileIndex.push(file);
|
||||
cfb.FullPaths.push(fpath);
|
||||
CFB.utils.cfb_gc(cfb);
|
||||
if(!unsafe) CFB.utils.cfb_gc(cfb);
|
||||
}
|
||||
file.content = (content);
|
||||
file.size = content ? content.length : 0;
|
||||
|
Loading…
Reference in New Issue
Block a user