piclaw 0.0.19 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.output/nitro.json +1 -1
- package/.output/public/assets/defult-D5RLDUrI.js +1 -0
- package/.output/public/assets/{dist-CMBqBOCp.js → dist-BH_oa-kv.js} +1 -1
- package/.output/public/assets/index-7JvURuHy.js +204 -0
- package/.output/public/assets/index-K43slwjJ.css +1 -0
- package/.output/public/index.html +11 -2
- package/.output/server/_...path_.get.mjs +16 -0
- package/.output/server/_chunks/app.mjs +261 -181
- package/.output/server/_chunks/browser.mjs +4 -1
- package/.output/server/_chunks/config.mjs +4 -0
- package/.output/server/_chunks/db.mjs +32 -28
- package/.output/server/_chunks/device-bus.mjs +123 -0
- package/.output/server/_chunks/dummy.mjs +1 -1
- package/.output/server/_chunks/logger.mjs +23 -0
- package/.output/server/_chunks/login.mjs +1 -1
- package/.output/server/_chunks/notes.mjs +1 -3
- package/.output/server/_chunks/renderer-template.mjs +1 -1
- package/.output/server/_chunks/sandbox.mjs +217 -0
- package/.output/server/_chunks/server.mjs +2302 -122
- package/.output/server/_chunks/terminal.mjs +63 -8
- package/.output/server/_chunks/uploads.mjs +60 -0
- package/.output/server/_chunks/virtual.mjs +192 -54
- package/.output/server/_id_.delete.mjs +5 -2
- package/.output/server/_id_.patch.mjs +2 -0
- package/.output/server/_id_2.delete.mjs +8 -0
- package/.output/server/_jid_.delete.mjs +5 -2
- package/.output/server/_jid_.patch.mjs +37 -4
- package/.output/server/_jid_2.delete.mjs +5 -2
- package/.output/server/_libs/@acemir/cssom+[...].mjs +2269 -1137
- package/.output/server/_libs/@google/genai.mjs +337 -273
- package/.output/server/_libs/@mariozechner/pi-agent-core+[...].mjs +381 -2073
- package/.output/server/_libs/@mariozechner/pi-coding-agent+[...].mjs +231 -131
- package/.output/server/_libs/_.mjs +3 -2
- package/.output/server/_libs/_10.mjs +2 -4
- package/.output/server/_libs/_11.mjs +2 -4
- package/.output/server/_libs/_12.mjs +2 -3
- package/.output/server/_libs/_13.mjs +2 -3
- package/.output/server/_libs/_14.mjs +2 -4
- package/.output/server/_libs/_15.mjs +2 -4
- package/.output/server/_libs/_16.mjs +2 -3
- package/.output/server/_libs/_17.mjs +2 -4
- package/.output/server/_libs/_18.mjs +2 -2
- package/.output/server/_libs/_19.mjs +2 -2
- package/.output/server/_libs/_2.mjs +3 -3
- package/.output/server/_libs/_20.mjs +2 -2
- package/.output/server/_libs/_21.mjs +2 -2
- package/.output/server/_libs/_22.mjs +2 -2
- package/.output/server/_libs/_23.mjs +2 -2
- package/.output/server/_libs/_24.mjs +2 -2
- package/.output/server/_libs/_25.mjs +2 -2
- package/.output/server/_libs/_26.mjs +2 -2
- package/.output/server/_libs/_27.mjs +2 -2
- package/.output/server/_libs/_28.mjs +2 -2
- package/.output/server/_libs/_29.mjs +2 -2
- package/.output/server/_libs/_3.mjs +3 -3
- package/.output/server/_libs/_30.mjs +2 -2
- package/.output/server/_libs/_31.mjs +2 -2
- package/.output/server/_libs/_32.mjs +2 -2
- package/.output/server/_libs/_33.mjs +2 -2
- package/.output/server/_libs/_34.mjs +2 -2
- package/.output/server/_libs/_35.mjs +2 -2
- package/.output/server/_libs/_36.mjs +2 -2
- package/.output/server/_libs/_37.mjs +2 -2
- package/.output/server/_libs/_38.mjs +2 -2
- package/.output/server/_libs/_39.mjs +2 -2
- package/.output/server/_libs/_4.mjs +4 -3
- package/.output/server/_libs/_40.mjs +2 -2
- package/.output/server/_libs/_41.mjs +2 -2
- package/.output/server/_libs/_42.mjs +2 -2
- package/.output/server/_libs/_43.mjs +2 -2
- package/.output/server/_libs/_44.mjs +2 -2
- package/.output/server/_libs/_45.mjs +2 -2
- package/.output/server/_libs/_46.mjs +2 -2
- package/.output/server/_libs/_47.mjs +2 -2
- package/.output/server/_libs/_48.mjs +2 -2
- package/.output/server/_libs/_49.mjs +2 -2
- package/.output/server/_libs/_5.mjs +2 -3
- package/.output/server/_libs/_50.mjs +2 -2
- package/.output/server/_libs/_51.mjs +2 -2
- package/.output/server/_libs/_52.mjs +2 -2
- package/.output/server/_libs/_53.mjs +2 -2
- package/.output/server/_libs/_54.mjs +2 -2
- package/.output/server/_libs/_55.mjs +2 -2
- package/.output/server/_libs/_56.mjs +2 -2
- package/.output/server/_libs/_57.mjs +2 -2
- package/.output/server/_libs/_58.mjs +2 -2
- package/.output/server/_libs/_59.mjs +2 -2
- package/.output/server/_libs/_6.mjs +2 -3
- package/.output/server/_libs/_60.mjs +2 -2
- package/.output/server/_libs/_61.mjs +2 -2
- package/.output/server/_libs/_62.mjs +2 -2
- package/.output/server/_libs/_63.mjs +2 -2
- package/.output/server/_libs/_64.mjs +2 -2
- package/.output/server/_libs/_65.mjs +2 -2
- package/.output/server/_libs/_66.mjs +2 -2
- package/.output/server/_libs/_67.mjs +2 -2
- package/.output/server/_libs/_68.mjs +2 -2
- package/.output/server/_libs/_69.mjs +2 -2
- package/.output/server/_libs/_7.mjs +2 -5
- package/.output/server/_libs/_70.mjs +2 -2
- package/.output/server/_libs/_71.mjs +2 -2
- package/.output/server/_libs/_72.mjs +2 -2
- package/.output/server/_libs/_73.mjs +2 -2
- package/.output/server/_libs/_74.mjs +2 -2
- package/.output/server/_libs/_75.mjs +2 -2
- package/.output/server/_libs/_76.mjs +2 -2
- package/.output/server/_libs/_77.mjs +2 -2
- package/.output/server/_libs/_78.mjs +2 -2
- package/.output/server/_libs/_79.mjs +2 -2
- package/.output/server/_libs/_8.mjs +2 -3
- package/.output/server/_libs/_80.mjs +2 -2
- package/.output/server/_libs/_81.mjs +2 -2
- package/.output/server/_libs/_82.mjs +2 -2
- package/.output/server/_libs/_83.mjs +2 -2
- package/.output/server/_libs/_84.mjs +2 -2
- package/.output/server/_libs/_85.mjs +2 -2
- package/.output/server/_libs/_86.mjs +2 -2
- package/.output/server/_libs/_87.mjs +2 -2
- package/.output/server/_libs/_88.mjs +2 -2
- package/.output/server/_libs/_89.mjs +2 -2
- package/.output/server/_libs/_9.mjs +2 -4
- package/.output/server/_libs/_90.mjs +5 -2
- package/.output/server/_libs/_91.mjs +3 -2
- package/.output/server/_libs/_92.mjs +2 -2
- package/.output/server/_libs/_93.mjs +2 -2
- package/.output/server/_libs/_94.mjs +2 -2
- package/.output/server/_libs/agent-base.mjs +1 -1
- package/.output/server/_libs/cheerio+[...].mjs +1 -1
- package/.output/server/_libs/data-uri-to-buffer.mjs +2 -67
- package/.output/server/_libs/data-urls+[...].mjs +1 -1
- package/.output/server/_libs/diff.mjs +1 -1
- package/.output/server/_libs/exodus__bytes.mjs +99 -81
- package/.output/server/_libs/fetch-blob+node-domexception.mjs +1 -1
- package/.output/server/_libs/h3+rou3+srvx.mjs +34 -4
- package/.output/server/_libs/html-encoding-sniffer.mjs +1 -1
- package/.output/server/_libs/https-proxy-agent.mjs +2 -2
- package/.output/server/_libs/jsdom.mjs +1 -1
- package/.output/server/_libs/just-bash+[...].mjs +4676 -3916
- package/.output/server/_libs/mariozechner__jiti.mjs +1 -1
- package/.output/server/_libs/mariozechner__pi-ai.mjs +1472 -0
- package/.output/server/_libs/md4x.mjs +1 -1
- package/.output/server/_libs/mime.mjs +838 -1
- package/.output/server/_libs/node-fetch.mjs +4 -4
- package/.output/server/_libs/node-liblzma.mjs +1 -1
- package/.output/server/_libs/silvia-odwyer__photon-node.mjs +1 -1
- package/.output/server/_routes/api/auth/approve.mjs +2 -0
- package/.output/server/_routes/api/auth/revoke.mjs +2 -0
- package/.output/server/_routes/api/auth/status.mjs +25 -6
- package/.output/server/_routes/api/browser2.mjs +1 -1
- package/.output/server/_routes/api/config2.mjs +2 -0
- package/.output/server/_routes/api/device_events.mjs +36 -0
- package/.output/server/_routes/api/files/groups.mjs +1 -2
- package/.output/server/_routes/api/files/raw.mjs +1 -1
- package/.output/server/_routes/api/groups.mjs +5 -3
- package/.output/server/_routes/api/groups2.mjs +18 -6
- package/.output/server/_routes/api/health.mjs +1 -2
- package/.output/server/_routes/api/messages.mjs +7 -1
- package/.output/server/_routes/api/notes/delete.mjs +4 -1
- package/.output/server/_routes/api/notes/write.mjs +2 -0
- package/.output/server/_routes/api/ntfy/setup.mjs +8 -0
- package/.output/server/_routes/api/pi/apikey.mjs +3 -2
- package/.output/server/_routes/api/pi/apikey_providers.mjs +1 -2
- package/.output/server/_routes/api/pi/commands.mjs +13 -3
- package/.output/server/_routes/api/pi/login/events.mjs +0 -1
- package/.output/server/_routes/api/pi/login/respond.mjs +2 -1
- package/.output/server/_routes/api/pi/login.mjs +1 -2
- package/.output/server/_routes/api/pi/logout.mjs +2 -1
- package/.output/server/_routes/api/pi/models.mjs +1 -2
- package/.output/server/_routes/api/pi/models_config2.mjs +2 -0
- package/.output/server/_routes/api/pi/settings2.mjs +2 -0
- package/.output/server/_routes/api/pi/status.mjs +1 -2
- package/.output/server/_routes/api/proxy.mjs +19 -1
- package/.output/server/_routes/api/sandbox.mjs +26 -0
- package/.output/server/_routes/api/sandbox2.mjs +17 -0
- package/.output/server/_routes/api/send.mjs +26 -18
- package/.output/server/_routes/api/status.mjs +1 -3
- package/.output/server/_routes/api/stop.mjs +11 -0
- package/.output/server/_routes/api/store/plugins.mjs +75 -0
- package/.output/server/_routes/api/store/skills.mjs +11 -0
- package/.output/server/_routes/api/tasks2.mjs +3 -2
- package/.output/server/_routes/api/telegram/setup.mjs +5 -2
- package/.output/server/_routes/api/telegram/status.mjs +1 -2
- package/.output/server/_routes/api/terminal2.mjs +2 -1
- package/.output/server/_routes/api/tunnel/setup.mjs +4 -2
- package/.output/server/_runtime.mjs +1 -2
- package/.output/server/_utils.mjs +10 -2
- package/.output/server/index.mjs +1 -1
- package/.output/server/node_modules/amdefine/amdefine.js +301 -0
- package/.output/server/node_modules/amdefine/package.json +16 -0
- package/.output/server/node_modules/compressjs/lib/BWT.js +420 -0
- package/.output/server/node_modules/compressjs/lib/BWTC.js +234 -0
- package/.output/server/node_modules/compressjs/lib/BitStream.js +108 -0
- package/.output/server/node_modules/compressjs/lib/Bzip2.js +936 -0
- package/.output/server/node_modules/compressjs/lib/CRC32.js +105 -0
- package/.output/server/node_modules/compressjs/lib/Context1Model.js +56 -0
- package/.output/server/node_modules/compressjs/lib/DefSumModel.js +152 -0
- package/.output/server/node_modules/compressjs/lib/DeflateDistanceModel.js +55 -0
- package/.output/server/node_modules/compressjs/lib/Dmc.js +197 -0
- package/.output/server/node_modules/compressjs/lib/DummyRangeCoder.js +81 -0
- package/.output/server/node_modules/compressjs/lib/FenwickModel.js +194 -0
- package/.output/server/node_modules/compressjs/lib/Huffman.js +514 -0
- package/.output/server/node_modules/compressjs/lib/HuffmanAllocator.js +227 -0
- package/.output/server/node_modules/compressjs/lib/LogDistanceModel.js +46 -0
- package/.output/server/node_modules/compressjs/lib/Lzjb.js +300 -0
- package/.output/server/node_modules/compressjs/lib/LzjbR.js +241 -0
- package/.output/server/node_modules/compressjs/lib/Lzp3.js +273 -0
- package/.output/server/node_modules/compressjs/lib/MTFModel.js +208 -0
- package/.output/server/node_modules/compressjs/lib/NoModel.js +46 -0
- package/.output/server/node_modules/compressjs/lib/PPM.js +343 -0
- package/.output/server/node_modules/compressjs/lib/RangeCoder.js +238 -0
- package/.output/server/node_modules/compressjs/lib/Simple.js +111 -0
- package/.output/server/node_modules/compressjs/lib/Stream.js +53 -0
- package/.output/server/node_modules/compressjs/lib/Util.js +324 -0
- package/.output/server/node_modules/compressjs/lib/freeze.js +14 -0
- package/.output/server/node_modules/compressjs/main.js +29 -0
- package/.output/server/node_modules/compressjs/package.json +35 -0
- package/.output/server/package.json +2 -1
- package/README.md +10 -1
- package/lib/index.d.mts +1 -0
- package/lib/index.mjs +1 -0
- package/lib/piclaw.mjs +100 -0
- package/lib/utils.mjs +96 -0
- package/package.json +16 -11
- package/.output/public/assets/defult-CMO6TZ5a.js +0 -1
- package/.output/public/assets/index-jdnbJw-M.js +0 -204
- package/.output/public/assets/index-ooXrRwgl.css +0 -1
- package/.output/server/_chunks/commands.mjs +0 -282
- package/.output/server/_chunks/pi.mjs +0 -202
- package/.output/server/_chunks/session.mjs +0 -1114
- package/.output/server/_libs/@aws-crypto/crc32+[...].mjs +0 -299
- package/.output/server/_libs/@aws-sdk/client-bedrock-runtime+[...].mjs +0 -17828
- package/.output/server/_libs/@aws-sdk/credential-provider-http+[...].mjs +0 -122
- package/.output/server/_libs/@aws-sdk/credential-provider-ini+[...].mjs +0 -417
- package/.output/server/_libs/@aws-sdk/credential-provider-process+[...].mjs +0 -54
- package/.output/server/_libs/@aws-sdk/credential-provider-sso+[...].mjs +0 -1151
- package/.output/server/_libs/@aws-sdk/credential-provider-web-identity+[...].mjs +0 -50
- package/.output/server/_libs/@smithy/credential-provider-imds+[...].mjs +0 -369
- package/.output/server/_libs/@tootallnate/quickjs-emscripten+[...].mjs +0 -3011
- package/.output/server/_libs/_100.mjs +0 -2
- package/.output/server/_libs/_101.mjs +0 -2
- package/.output/server/_libs/_102.mjs +0 -5
- package/.output/server/_libs/_103.mjs +0 -3
- package/.output/server/_libs/_104.mjs +0 -2
- package/.output/server/_libs/_105.mjs +0 -3
- package/.output/server/_libs/_106.mjs +0 -2
- package/.output/server/_libs/_107.mjs +0 -2
- package/.output/server/_libs/_95.mjs +0 -2
- package/.output/server/_libs/_96.mjs +0 -2
- package/.output/server/_libs/_97.mjs +0 -2
- package/.output/server/_libs/_98.mjs +0 -2
- package/.output/server/_libs/_99.mjs +0 -2
- package/.output/server/_libs/amdefine.mjs +0 -188
- package/.output/server/_libs/ast-types.mjs +0 -2270
- package/.output/server/_libs/aws-sdk__nested-clients.mjs +0 -3141
- package/.output/server/_libs/basic-ftp.mjs +0 -1906
- package/.output/server/_libs/compressjs.mjs +0 -50
- package/.output/server/_libs/degenerator+[...].mjs +0 -9964
- package/.output/server/_libs/get-uri.mjs +0 -413
- package/.output/server/_libs/http-proxy-agent.mjs +0 -123
- package/.output/server/_libs/ip-address.mjs +0 -1423
- package/.output/server/_libs/lru-cache.mjs +0 -732
- package/.output/server/_libs/netmask.mjs +0 -139
- package/.output/server/_libs/pac-proxy-agent+[...].mjs +0 -3104
- package/.output/server/_libs/proxy-agent+proxy-from-env.mjs +0 -204
- package/.output/server/_libs/smithy__core.mjs +0 -192
- package/.output/server/node_modules/tslib/modules/index.js +0 -70
- package/.output/server/node_modules/tslib/modules/package.json +0 -3
- package/.output/server/node_modules/tslib/package.json +0 -47
- package/.output/server/node_modules/tslib/tslib.js +0 -484
- package/bin/piclaw.mjs +0 -195
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/** Range coding model based on Fenwick trees for O(ln N) query/update. */
|
|
2
|
+
if (typeof define !== 'function') { var define = require('amdefine')(module); }
|
|
3
|
+
define(['./RangeCoder','./Stream','./Util'],function(RangeCoder,Stream,Util){
|
|
4
|
+
|
|
5
|
+
/** We store two probabilities in a U32, so max prob is going to be 0xFFFF */
|
|
6
|
+
var DEFAULT_MAX_PROB = 0xFF00;
|
|
7
|
+
var DEFAULT_INCREMENT= 0x0100;
|
|
8
|
+
|
|
9
|
+
var ESC_MASK = 0x0000FFFF, ESC_SHIFT = 0;
|
|
10
|
+
var SYM_MASK = 0xFFFF0000, SYM_SHIFT = 16;
|
|
11
|
+
var SCALE_MASK=0xFFFEFFFE;
|
|
12
|
+
|
|
13
|
+
var FenwickModel = function(coder, size, max_prob, increment) {
|
|
14
|
+
this.coder = coder;
|
|
15
|
+
this.numSyms = size + 1; // save space for an escape symbol
|
|
16
|
+
this.tree = Util.makeU32Buffer(this.numSyms*2);
|
|
17
|
+
this.increment = (+increment) || DEFAULT_INCREMENT;
|
|
18
|
+
this.max_prob = (+max_prob) || DEFAULT_MAX_PROB;
|
|
19
|
+
// sanity-check to prevent overflow.
|
|
20
|
+
console.assert((this.max_prob + (this.increment-1)) <= 0xFFFF);
|
|
21
|
+
console.assert(size <= 0xFFFF);
|
|
22
|
+
// record escape probability as 1.
|
|
23
|
+
var i;
|
|
24
|
+
for (i=0; i<size; i++) {
|
|
25
|
+
this.tree[this.numSyms + i] = // escape prob=1, sym prob = 0
|
|
26
|
+
(1 << ESC_SHIFT) | (0 << SYM_SHIFT);
|
|
27
|
+
}
|
|
28
|
+
this.tree[this.numSyms + i] = // escape prob = 0, sym prob = 1
|
|
29
|
+
(0 << ESC_SHIFT) | (this.increment << SYM_SHIFT);
|
|
30
|
+
this._sumTree();
|
|
31
|
+
// probability sums are in this.tree[1]. this.tree[0] is unused.
|
|
32
|
+
};
|
|
33
|
+
FenwickModel.factory = function(coder, max_prob, increment) {
|
|
34
|
+
return function(size) {
|
|
35
|
+
return new FenwickModel(coder, size, max_prob, increment);
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
FenwickModel.prototype.clone = function() {
|
|
39
|
+
var newModel = new FenwickModel(this.coder, this.size,
|
|
40
|
+
this.max_prob, this.increment);
|
|
41
|
+
var i;
|
|
42
|
+
for (i=1; i<this.tree.length; i++) {
|
|
43
|
+
newModel.tree[i] = this.tree[i];
|
|
44
|
+
}
|
|
45
|
+
return newModel;
|
|
46
|
+
};
|
|
47
|
+
FenwickModel.prototype.encode = function(symbol) {
|
|
48
|
+
var i = this.numSyms + symbol;
|
|
49
|
+
var sy_f = this.tree[i];
|
|
50
|
+
var mask = SYM_MASK, shift = SYM_SHIFT;
|
|
51
|
+
var update = (this.increment << SYM_SHIFT);
|
|
52
|
+
|
|
53
|
+
if ((sy_f & SYM_MASK) === 0) { // escape!
|
|
54
|
+
this.encode(this.numSyms-1);
|
|
55
|
+
mask = ESC_MASK;
|
|
56
|
+
update -= (1<<ESC_SHIFT); // not going to escape no mo'
|
|
57
|
+
shift = ESC_SHIFT;
|
|
58
|
+
} else if (symbol === (this.numSyms-1) &&
|
|
59
|
+
((this.tree[1] & ESC_MASK) >>> ESC_SHIFT) === 1) {
|
|
60
|
+
// this is the last escape, zero it out
|
|
61
|
+
update = -this.tree[i];
|
|
62
|
+
}
|
|
63
|
+
// sum up the proper lt_f
|
|
64
|
+
var lt_f = 0;
|
|
65
|
+
while (i > 1) {
|
|
66
|
+
var isRight = (i & 1);
|
|
67
|
+
var parent = (i >>> 1);
|
|
68
|
+
// if we're the right child, we need to
|
|
69
|
+
// add the prob from the left child
|
|
70
|
+
if (isRight) {
|
|
71
|
+
lt_f += this.tree[2*parent];
|
|
72
|
+
}
|
|
73
|
+
// update sums
|
|
74
|
+
this.tree[i] += update; // increase sym / decrease esc
|
|
75
|
+
i = parent;
|
|
76
|
+
}
|
|
77
|
+
var tot_f = this.tree[1];
|
|
78
|
+
this.tree[1] += update; // update prob in root
|
|
79
|
+
sy_f = (sy_f & mask) >>> shift;
|
|
80
|
+
lt_f = (lt_f & mask) >>> shift;
|
|
81
|
+
tot_f =(tot_f& mask) >>> shift;
|
|
82
|
+
this.coder.encodeFreq(sy_f, lt_f, tot_f);
|
|
83
|
+
// rescale?
|
|
84
|
+
if ((( this.tree[1] & SYM_MASK ) >>> SYM_SHIFT) >= this.max_prob) {
|
|
85
|
+
this._rescale();
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
FenwickModel.prototype._decode = function(isEscape) {
|
|
89
|
+
var mask = SYM_MASK, shift = SYM_SHIFT;
|
|
90
|
+
var update = (this.increment << SYM_SHIFT);
|
|
91
|
+
if (isEscape) {
|
|
92
|
+
mask = ESC_MASK;
|
|
93
|
+
update -= (1 << ESC_SHIFT);
|
|
94
|
+
shift = ESC_SHIFT;
|
|
95
|
+
}
|
|
96
|
+
var tot_f = (this.tree[1] & mask) >>> shift;
|
|
97
|
+
var prob = this.coder.decodeCulFreq(tot_f);
|
|
98
|
+
// travel down the tree looking for this
|
|
99
|
+
var i = 1, lt_f = 0;
|
|
100
|
+
while (i < this.numSyms) {
|
|
101
|
+
this.tree[i] += update;
|
|
102
|
+
// look at probability in left child.
|
|
103
|
+
var leftProb = (this.tree[2*i] & mask) >>> shift;
|
|
104
|
+
i *= 2;
|
|
105
|
+
if ((prob-lt_f) >= leftProb) {
|
|
106
|
+
lt_f += leftProb;
|
|
107
|
+
i++; // take the right child.
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
var symbol = i - this.numSyms;
|
|
111
|
+
var sy_f = (this.tree[i] & mask) >>> shift;
|
|
112
|
+
this.tree[i] += update;
|
|
113
|
+
this.coder.decodeUpdate(sy_f, lt_f, tot_f);
|
|
114
|
+
// was this the last escape?
|
|
115
|
+
if (symbol === (this.numSyms-1) &&
|
|
116
|
+
((this.tree[1] & ESC_MASK) >>> ESC_SHIFT) === 1) {
|
|
117
|
+
update = -this.tree[i]; // zero it out
|
|
118
|
+
while (i >= 1) {
|
|
119
|
+
this.tree[i] += update;
|
|
120
|
+
i = (i >>> 1); // parent
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// rescale?
|
|
124
|
+
if ((( this.tree[1] & SYM_MASK ) >>> SYM_SHIFT) >= this.max_prob) {
|
|
125
|
+
this._rescale();
|
|
126
|
+
}
|
|
127
|
+
return symbol;
|
|
128
|
+
};
|
|
129
|
+
FenwickModel.prototype.decode = function() {
|
|
130
|
+
var symbol = this._decode(false); // not escape
|
|
131
|
+
if (symbol === (this.numSyms-1)) {
|
|
132
|
+
// this was an escape!
|
|
133
|
+
symbol = this._decode(true); // an escape!
|
|
134
|
+
}
|
|
135
|
+
return symbol;
|
|
136
|
+
};
|
|
137
|
+
FenwickModel.prototype._rescale = function() {
|
|
138
|
+
var i, prob, noEscape = true;
|
|
139
|
+
// scale symbols (possible causing them to escape)
|
|
140
|
+
for (i=0; i < this.numSyms-1; i++) {
|
|
141
|
+
prob = this.tree[this.numSyms + i];
|
|
142
|
+
if ((prob & ESC_MASK) !== 0) {
|
|
143
|
+
// this symbol escapes
|
|
144
|
+
noEscape = false;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
prob = (prob & SCALE_MASK) >>> 1;
|
|
148
|
+
if (prob === 0) {
|
|
149
|
+
// this symbol newly escapes
|
|
150
|
+
prob = (1 << ESC_SHIFT);
|
|
151
|
+
noEscape = false;
|
|
152
|
+
}
|
|
153
|
+
this.tree[this.numSyms + i] = prob;
|
|
154
|
+
}
|
|
155
|
+
// scale the escape symbol
|
|
156
|
+
prob = this.tree[this.numSyms + i];
|
|
157
|
+
prob = (prob & SCALE_MASK) >>> 1;
|
|
158
|
+
// prob should be zero if there are no escaping symbols, otherwise
|
|
159
|
+
// it must be at least 1.
|
|
160
|
+
if (noEscape) { prob = 0; }
|
|
161
|
+
else if (prob === 0) { prob = (1 << SYM_SHIFT); }
|
|
162
|
+
this.tree[this.numSyms + i] = prob;
|
|
163
|
+
// sum it all up afresh
|
|
164
|
+
this._sumTree();
|
|
165
|
+
};
|
|
166
|
+
FenwickModel.prototype._sumTree = function() {
|
|
167
|
+
var i;
|
|
168
|
+
// sum it all. (we know we won't overflow)
|
|
169
|
+
for (i=this.numSyms - 1; i > 0; i--) {
|
|
170
|
+
this.tree[i] = this.tree[2*i] + this.tree[2*i + 1];
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
FenwickModel.MAGIC = 'fenw';
|
|
175
|
+
/** Simple order-0 compressor, as self-test. */
|
|
176
|
+
FenwickModel.compressFile = Util.compressFileHelper(FenwickModel.MAGIC, function(inStream, outStream, fileSize, props, finalByte) {
|
|
177
|
+
var range = new RangeCoder(outStream);
|
|
178
|
+
range.encodeStart(finalByte, 1);
|
|
179
|
+
var model = new FenwickModel(range, (fileSize<0) ? 257 : 256);
|
|
180
|
+
Util.compressWithModel(inStream, fileSize, model);
|
|
181
|
+
range.encodeFinish();
|
|
182
|
+
}, true);
|
|
183
|
+
|
|
184
|
+
/** Simple order-0 decompresser, as self-test. */
|
|
185
|
+
FenwickModel.decompressFile = Util.decompressFileHelper(FenwickModel.MAGIC, function(inStream, outStream, fileSize) {
|
|
186
|
+
var range = new RangeCoder(inStream);
|
|
187
|
+
range.decodeStart(true/*already read the final byte*/);
|
|
188
|
+
var model = new FenwickModel(range, (fileSize<0) ? 257 : 256);
|
|
189
|
+
Util.decompressWithModel(outStream, fileSize, model);
|
|
190
|
+
range.decodeFinish();
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
return FenwickModel;
|
|
194
|
+
});
|
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
/* Adaptive Huffman code, using Vitter's algorithm ported from
|
|
2
|
+
* vitter.c at http://code.google.com/p/compression-code/downloads/list
|
|
3
|
+
* The original code was placed in the public domain, and so I
|
|
4
|
+
* also place this JavaScript port in the public domain.
|
|
5
|
+
* -- C. Scott Ananian <cscott@cscott.net>, 2013
|
|
6
|
+
* ps. some truly grotty C code in the originally, faithfully ported to
|
|
7
|
+
* evil comma-operator-using, assignment-in-if-condition JavaScript.
|
|
8
|
+
*/
|
|
9
|
+
if (typeof define !== 'function') { var define = require('amdefine')(module); }
|
|
10
|
+
define(['./BitStream','./Util'],function(BitStream,Util) {
|
|
11
|
+
// This code is adapted from Professor Vitter's
|
|
12
|
+
// article, Design and Analysis of Dynamic Huffman Codes,
|
|
13
|
+
// which appeared in JACM October 1987
|
|
14
|
+
|
|
15
|
+
// A design trade-off has been made to simplify the
|
|
16
|
+
// code: a node's block is determined dynamically,
|
|
17
|
+
// and the implicit tree structure is maintained,
|
|
18
|
+
// e.g. explicit node numbers are also implicit.
|
|
19
|
+
|
|
20
|
+
// Dynamic Huffman table weight ranking
|
|
21
|
+
// is maintained per Professor Vitter's
|
|
22
|
+
// invariant (*) for algorithm FGK:
|
|
23
|
+
|
|
24
|
+
// leaves precede internal nodes of the
|
|
25
|
+
// same weight in a non-decreasing ranking
|
|
26
|
+
// of weights using implicit node numbers:
|
|
27
|
+
|
|
28
|
+
// 1) leaves slide over internal nodes, internal nodes
|
|
29
|
+
// swap over groups of leaves, leaves are swapped
|
|
30
|
+
// into group leader position, but two internal
|
|
31
|
+
// nodes never change positions relative
|
|
32
|
+
// to one another.
|
|
33
|
+
|
|
34
|
+
// 2) weights are incremented by 2:
|
|
35
|
+
// leaves always have even weight values;
|
|
36
|
+
// internal nodes always have odd values.
|
|
37
|
+
|
|
38
|
+
// 3) even node numbers are always right children;
|
|
39
|
+
// odd numbers are left children in the tree.
|
|
40
|
+
|
|
41
|
+
// node 2 * HuffSize - 1 is always the tree root;
|
|
42
|
+
// node HuffEsc is the escape node;
|
|
43
|
+
|
|
44
|
+
// the tree is initialized by creating an
|
|
45
|
+
// escape node as the root.
|
|
46
|
+
|
|
47
|
+
// each new leaf symbol is paired with a new escape
|
|
48
|
+
// node into the previous escape node in the tree,
|
|
49
|
+
// until the last symbol which takes over the
|
|
50
|
+
// tree position of the escape node, and
|
|
51
|
+
// HuffEsc is left at zero.
|
|
52
|
+
|
|
53
|
+
// overall table size: 2 * HuffSize
|
|
54
|
+
|
|
55
|
+
// huff_init(alphabet_size, potential symbols used)
|
|
56
|
+
// huff_encode(next_symbol)
|
|
57
|
+
// next_symbol = huff_decode()
|
|
58
|
+
|
|
59
|
+
// huff_scale(by_bits) -- scale weights and re-balance tree
|
|
60
|
+
|
|
61
|
+
var HTable = function(up, down, symbol, weight) {
|
|
62
|
+
this.up = up; // next node up the tree
|
|
63
|
+
this.down = down; // pair of down nodes
|
|
64
|
+
this.symbol = symbol; // node symbol value
|
|
65
|
+
this.weight = weight; // node weight
|
|
66
|
+
};
|
|
67
|
+
HTable.prototype.clone = function() {
|
|
68
|
+
return new HTable(this.up, this.down, this.symbol, this.weight);
|
|
69
|
+
};
|
|
70
|
+
HTable.prototype.set = function(htable) {
|
|
71
|
+
this.up = htable.up;
|
|
72
|
+
this.down = htable.down;
|
|
73
|
+
this.symbol = htable.symbol;
|
|
74
|
+
this.weight = htable.weight;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// initialize an adaptive coder
|
|
78
|
+
// for alphabet size, and count
|
|
79
|
+
// of nodes to be used
|
|
80
|
+
var Huffman = function(size, root, bitstream, max_weight) {
|
|
81
|
+
var i;
|
|
82
|
+
// default: all alphabet symbols are used
|
|
83
|
+
|
|
84
|
+
console.assert(size && typeof(size)==='number');
|
|
85
|
+
if( !root || root > size )
|
|
86
|
+
root = size;
|
|
87
|
+
|
|
88
|
+
// create the initial escape node
|
|
89
|
+
// at the tree root
|
|
90
|
+
|
|
91
|
+
if ( root <<= 1 ) {
|
|
92
|
+
root--;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// create root+1 htables (coding table)
|
|
96
|
+
// XXX this could be views on a backing Uint32 array?
|
|
97
|
+
this.table = [];
|
|
98
|
+
for (i=0; i<=root; i++) {
|
|
99
|
+
this.table[i] = new HTable(0,0,0,0);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// this.map => mapping for symbols to nodes
|
|
103
|
+
this.map = [];
|
|
104
|
+
// this.size => the alphabet size
|
|
105
|
+
if( this.size = size ) {
|
|
106
|
+
for (i=0; i<size; i++) {
|
|
107
|
+
this.map[i] = 0;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// this.esc => the current tree height
|
|
112
|
+
// this.root => the root of the tree
|
|
113
|
+
this.esc = this.root = root;
|
|
114
|
+
|
|
115
|
+
if (bitstream) {
|
|
116
|
+
this.readBit = bitstream.readBit.bind(bitstream);
|
|
117
|
+
this.writeBit = bitstream.writeBit.bind(bitstream);
|
|
118
|
+
}
|
|
119
|
+
this.max_weight = max_weight; // may be null or undefined
|
|
120
|
+
}
|
|
121
|
+
// factory interface
|
|
122
|
+
Huffman.factory = function(bitstream, max_weight) {
|
|
123
|
+
return function(size) {
|
|
124
|
+
return new Huffman(size, size, bitstream, max_weight);
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
// split escape node to incorporate new symbol
|
|
130
|
+
|
|
131
|
+
Huffman.prototype.split = function(symbol) {
|
|
132
|
+
var pair, node;
|
|
133
|
+
|
|
134
|
+
// is the tree already full???
|
|
135
|
+
|
|
136
|
+
if( pair = this.esc ) {
|
|
137
|
+
this.esc--;
|
|
138
|
+
} else {
|
|
139
|
+
console.assert(false);
|
|
140
|
+
return 0;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// if this is the last symbol, it moves into
|
|
144
|
+
// the escape node's old position, and
|
|
145
|
+
// this.esc is set to zero.
|
|
146
|
+
|
|
147
|
+
// otherwise, the escape node is promoted to
|
|
148
|
+
// parent a new escape node and the new symbol.
|
|
149
|
+
|
|
150
|
+
if( node = this.esc ) {
|
|
151
|
+
this.table[pair].down = node;
|
|
152
|
+
this.table[pair].weight = 1;
|
|
153
|
+
this.table[node].up = pair;
|
|
154
|
+
this.esc--;
|
|
155
|
+
} else {
|
|
156
|
+
pair = 0;
|
|
157
|
+
node = 1;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// initialize the new symbol node
|
|
161
|
+
|
|
162
|
+
this.table[node].symbol = symbol;
|
|
163
|
+
this.table[node].weight = 0;
|
|
164
|
+
this.table[node].down = 0;
|
|
165
|
+
this.map[symbol] = node;
|
|
166
|
+
|
|
167
|
+
// initialize a new escape node.
|
|
168
|
+
|
|
169
|
+
this.table[this.esc].weight = 0;
|
|
170
|
+
this.table[this.esc].down = 0;
|
|
171
|
+
this.table[this.esc].up = pair;
|
|
172
|
+
return node;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
// swap leaf to group leader position
|
|
176
|
+
// return symbol's new node
|
|
177
|
+
|
|
178
|
+
Huffman.prototype.leader = function(node) {
|
|
179
|
+
var weight = this.table[node].weight;
|
|
180
|
+
var leader = node, prev, symbol;
|
|
181
|
+
|
|
182
|
+
while( weight === this.table[leader + 1].weight ) {
|
|
183
|
+
leader++;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if( leader === node ) {
|
|
187
|
+
return node;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// swap the leaf nodes
|
|
191
|
+
|
|
192
|
+
symbol = this.table[node].symbol;
|
|
193
|
+
prev = this.table[leader].symbol;
|
|
194
|
+
|
|
195
|
+
this.table[leader].symbol = symbol;
|
|
196
|
+
this.table[node].symbol = prev;
|
|
197
|
+
this.map[symbol] = leader;
|
|
198
|
+
this.map[prev] = node;
|
|
199
|
+
return leader;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// slide internal node up over all leaves of equal weight;
|
|
203
|
+
// or exchange leaf with next smaller weight internal node
|
|
204
|
+
|
|
205
|
+
// return node's new position
|
|
206
|
+
|
|
207
|
+
Huffman.prototype.slide = function(node) {
|
|
208
|
+
var next = node;
|
|
209
|
+
var swap;
|
|
210
|
+
|
|
211
|
+
swap = this.table[next++].clone();
|
|
212
|
+
|
|
213
|
+
// if we're sliding an internal node, find the
|
|
214
|
+
// highest possible leaf to exchange with
|
|
215
|
+
|
|
216
|
+
if( swap.weight & 1 ) {
|
|
217
|
+
while( swap.weight > this.table[next + 1].weight ) {
|
|
218
|
+
next++;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// swap the two nodes
|
|
223
|
+
|
|
224
|
+
this.table[node].set(this.table[next]);
|
|
225
|
+
this.table[next].set(swap);
|
|
226
|
+
|
|
227
|
+
this.table[next].up = this.table[node].up;
|
|
228
|
+
this.table[node].up = swap.up;
|
|
229
|
+
|
|
230
|
+
// repair the symbol map and tree structure
|
|
231
|
+
|
|
232
|
+
if( swap.weight & 1 ) {
|
|
233
|
+
this.table[swap.down].up = next;
|
|
234
|
+
this.table[swap.down - 1].up = next;
|
|
235
|
+
this.map[this.table[node].symbol] = node;
|
|
236
|
+
} else {
|
|
237
|
+
this.table[this.table[node].down - 1].up = node;
|
|
238
|
+
this.table[this.table[node].down].up = node;
|
|
239
|
+
this.map[swap.symbol] = next;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return next;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
// increment symbol weight and re balance the tree.
|
|
246
|
+
|
|
247
|
+
Huffman.prototype.increment = function(node) {
|
|
248
|
+
var up;
|
|
249
|
+
|
|
250
|
+
// obviate swapping a parent with its child:
|
|
251
|
+
// increment the leaf and proceed
|
|
252
|
+
// directly to its parent.
|
|
253
|
+
|
|
254
|
+
// otherwise, promote leaf to group leader position in the tree
|
|
255
|
+
|
|
256
|
+
if( this.table[node].up === node + 1 ) {
|
|
257
|
+
this.table[node].weight += 2;
|
|
258
|
+
node++;
|
|
259
|
+
} else {
|
|
260
|
+
node = this.leader (node);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// increase the weight of each node and slide
|
|
264
|
+
// over any smaller weights ahead of it
|
|
265
|
+
// until reaching the root
|
|
266
|
+
|
|
267
|
+
// internal nodes work upwards from
|
|
268
|
+
// their initial positions; while
|
|
269
|
+
// symbol nodes slide over first,
|
|
270
|
+
// then work up from their final
|
|
271
|
+
// positions.
|
|
272
|
+
|
|
273
|
+
while( this.table[node].weight += 2, up = this.table[node].up ) {
|
|
274
|
+
while( this.table[node].weight > this.table[node + 1].weight ) {
|
|
275
|
+
node = this.slide (node);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if( this.table[node].weight & 1 ) {
|
|
279
|
+
node = up;
|
|
280
|
+
} else {
|
|
281
|
+
node = this.table[node].up;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/* Re-scale if necessary. */
|
|
286
|
+
if (this.max_weight) {
|
|
287
|
+
if (this.table[this.root].weight >= this.max_weight) {
|
|
288
|
+
this.scale(1);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
// scale all weights and re-balance the tree
|
|
294
|
+
|
|
295
|
+
// zero weight nodes are removed from the tree
|
|
296
|
+
// by sliding them out the left of the rank list
|
|
297
|
+
|
|
298
|
+
Huffman.prototype.scale = function(bits) {
|
|
299
|
+
var node = this.esc, weight, prev;
|
|
300
|
+
|
|
301
|
+
// work up the tree from the escape node
|
|
302
|
+
// scaling weights by the value of bits
|
|
303
|
+
|
|
304
|
+
while( ++node <= this.root ) {
|
|
305
|
+
// recompute the weight of internal nodes;
|
|
306
|
+
// slide down and out any unused ones
|
|
307
|
+
|
|
308
|
+
if( this.table[node].weight & 1 ) {
|
|
309
|
+
if( weight = this.table[this.table[node].down].weight & ~1 ) {
|
|
310
|
+
weight += this.table[this.table[node].down - 1].weight | 1;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// remove zero weight leaves by incrementing HuffEsc
|
|
314
|
+
// and removing them from the symbol map. take care
|
|
315
|
+
|
|
316
|
+
} else if( !(weight = this.table[node].weight >> bits & ~1) ) {
|
|
317
|
+
if( this.map[this.table[node].symbol] = 0, this.esc++ ) {
|
|
318
|
+
this.esc++;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// slide the scaled node back down over any
|
|
323
|
+
// previous nodes with larger weights
|
|
324
|
+
|
|
325
|
+
this.table[node].weight = weight;
|
|
326
|
+
prev = node;
|
|
327
|
+
|
|
328
|
+
while( weight < this.table[--prev].weight ) {
|
|
329
|
+
this.slide(prev);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// prepare a new escape node
|
|
334
|
+
|
|
335
|
+
this.table[this.esc].down = 0;
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
// send the bits for an escaped symbol
|
|
339
|
+
|
|
340
|
+
Huffman.prototype.sendid = function(symbol) {
|
|
341
|
+
var empty = 0, max;
|
|
342
|
+
|
|
343
|
+
// count the number of empty symbols
|
|
344
|
+
// before the symbol in the table
|
|
345
|
+
|
|
346
|
+
while( symbol-- ) {
|
|
347
|
+
if( !this.map[symbol] ) {
|
|
348
|
+
empty++;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// send LSB of this count first, using
|
|
353
|
+
// as many bits as are required for
|
|
354
|
+
// the maximum possible count
|
|
355
|
+
|
|
356
|
+
if( max = this.size - Math.floor((this.root - this.esc) / 2) - 1 ) {
|
|
357
|
+
do {
|
|
358
|
+
this.writeBit(empty & 1);
|
|
359
|
+
empty >>= 1;
|
|
360
|
+
} while( max >>= 1 );
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
// encode the next symbol
|
|
365
|
+
|
|
366
|
+
Huffman.prototype.encode = function(symbol) {
|
|
367
|
+
var emit = 1, bit;
|
|
368
|
+
var up, idx, node;
|
|
369
|
+
|
|
370
|
+
if( symbol < this.size ) {
|
|
371
|
+
node = this.map[symbol];
|
|
372
|
+
} else {
|
|
373
|
+
console.assert(false);
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// for a new symbol, direct the receiver to the escape node
|
|
378
|
+
// but refuse input if table is already full.
|
|
379
|
+
|
|
380
|
+
if( !(idx = node) ) {
|
|
381
|
+
if( !(idx = this.esc) ) {
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// accumulate the code bits by
|
|
387
|
+
// working up the tree from
|
|
388
|
+
// the node to the root
|
|
389
|
+
|
|
390
|
+
while( up = this.table[idx].up ) {
|
|
391
|
+
emit <<= 1; emit |= idx & 1; idx = up;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// send the code, root selector bit first
|
|
395
|
+
|
|
396
|
+
while( bit = emit & 1, emit >>= 1 ) {
|
|
397
|
+
this.writeBit(bit);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// send identification and incorporate
|
|
401
|
+
// new symbols into the tree
|
|
402
|
+
|
|
403
|
+
if( !node ) {
|
|
404
|
+
this.sendid(symbol);
|
|
405
|
+
node = this.split(symbol);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// adjust and re-balance the tree
|
|
409
|
+
|
|
410
|
+
this.increment(node);
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
// read the identification bits
|
|
414
|
+
// for an escaped symbol
|
|
415
|
+
|
|
416
|
+
Huffman.prototype.readid = function() {
|
|
417
|
+
var empty = 0, bit = 1, max, symbol;
|
|
418
|
+
|
|
419
|
+
// receive the symbol, LSB first, reading
|
|
420
|
+
// only the number of bits necessary to
|
|
421
|
+
// transmit the maximum possible symbol value
|
|
422
|
+
|
|
423
|
+
if( max = this.size - Math.floor((this.root - this.esc) / 2) - 1 ) {
|
|
424
|
+
do {
|
|
425
|
+
empty |= this.readBit() ? bit : 0;
|
|
426
|
+
bit <<= 1;
|
|
427
|
+
} while( max >>= 1 );
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// the count is of unmapped symbols
|
|
431
|
+
// in the table before the new one
|
|
432
|
+
|
|
433
|
+
for( symbol = 0; symbol < this.size; symbol++ ) {
|
|
434
|
+
if( !this.map[symbol] ) {
|
|
435
|
+
if( !empty-- ) {
|
|
436
|
+
return symbol;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// oops! our count is too big, either due
|
|
442
|
+
// to a bit error, or a short node count
|
|
443
|
+
// given to huff_init.
|
|
444
|
+
|
|
445
|
+
console.assert(false);
|
|
446
|
+
return 0;
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
// decode the next symbol
|
|
450
|
+
|
|
451
|
+
Huffman.prototype.decode = function() {
|
|
452
|
+
var node = this.root;
|
|
453
|
+
var symbol, down;
|
|
454
|
+
|
|
455
|
+
// work down the tree from the root
|
|
456
|
+
// until reaching either a leaf
|
|
457
|
+
// or the escape node. A one
|
|
458
|
+
// bit means go left, a zero
|
|
459
|
+
// means go right.
|
|
460
|
+
|
|
461
|
+
while( down = this.table[node].down ) {
|
|
462
|
+
if( this.readBit() ) {
|
|
463
|
+
node = down - 1; // the left child precedes the right child
|
|
464
|
+
} else {
|
|
465
|
+
node = down;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// sent to the escape node???
|
|
470
|
+
// refuse to add to a full tree
|
|
471
|
+
|
|
472
|
+
if( node === this.esc ) {
|
|
473
|
+
if( this.esc ) {
|
|
474
|
+
symbol = this.readid ();
|
|
475
|
+
node = this.split (symbol);
|
|
476
|
+
} else {
|
|
477
|
+
console.assert(false);
|
|
478
|
+
return 0;
|
|
479
|
+
}
|
|
480
|
+
} else {
|
|
481
|
+
symbol = this.table[node].symbol;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// increment weights and re-balance
|
|
485
|
+
// the coding tree
|
|
486
|
+
|
|
487
|
+
this.increment (node);
|
|
488
|
+
return symbol;
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
// stand alone compressor, mostly for testing
|
|
492
|
+
Huffman.MAGIC = 'huff';
|
|
493
|
+
Huffman.compressFile = Util.compressFileHelper(Huffman.MAGIC, function(input, output, size, props) {
|
|
494
|
+
var bitstream = new BitStream(output);
|
|
495
|
+
|
|
496
|
+
var alphabetSize = 256;
|
|
497
|
+
if (size < 0) { alphabetSize++; }
|
|
498
|
+
var huff = new Huffman(257, alphabetSize, bitstream, 8191);
|
|
499
|
+
Util.compressWithModel(input, size, huff);
|
|
500
|
+
bitstream.flush();
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
// stand alone decompresser, again for testing
|
|
504
|
+
Huffman.decompressFile = Util.decompressFileHelper(Huffman.MAGIC, function(input, output, size) {
|
|
505
|
+
var bitstream = new BitStream(input);
|
|
506
|
+
|
|
507
|
+
var alphabetSize = 256;
|
|
508
|
+
if (size < 0) { alphabetSize++; }
|
|
509
|
+
var huff = new Huffman(257, alphabetSize, bitstream, 8191);
|
|
510
|
+
Util.decompressWithModel(output, size, huff);
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
return Huffman;
|
|
514
|
+
});
|