piclaw 0.0.20 → 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.
Files changed (245) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/defult-D5RLDUrI.js +1 -0
  3. package/.output/public/assets/{dist-D-Hc5HbQ.js → dist-BH_oa-kv.js} +1 -1
  4. package/.output/public/assets/index-7JvURuHy.js +204 -0
  5. package/.output/public/assets/index-K43slwjJ.css +1 -0
  6. package/.output/public/index.html +11 -2
  7. package/.output/server/_chunks/app.mjs +138 -104
  8. package/.output/server/_chunks/config.mjs +4 -0
  9. package/.output/server/_chunks/dummy.mjs +1 -1
  10. package/.output/server/_chunks/logger.mjs +1 -1
  11. package/.output/server/_chunks/notes.mjs +1 -3
  12. package/.output/server/_chunks/renderer-template.mjs +1 -1
  13. package/.output/server/_chunks/sandbox.mjs +217 -0
  14. package/.output/server/_chunks/server.mjs +411 -291
  15. package/.output/server/_chunks/terminal.mjs +47 -8
  16. package/.output/server/_chunks/virtual.mjs +192 -54
  17. package/.output/server/_id_.delete.mjs +5 -2
  18. package/.output/server/_id_2.delete.mjs +8 -0
  19. package/.output/server/_jid_.delete.mjs +0 -1
  20. package/.output/server/_jid_.patch.mjs +21 -3
  21. package/.output/server/_jid_2.delete.mjs +0 -1
  22. package/.output/server/_libs/@acemir/cssom+[...].mjs +2269 -1137
  23. package/.output/server/_libs/@google/genai.mjs +348 -284
  24. package/.output/server/_libs/@mariozechner/pi-agent-core+[...].mjs +381 -2073
  25. package/.output/server/_libs/@mariozechner/pi-coding-agent+[...].mjs +236 -136
  26. package/.output/server/_libs/_.mjs +3 -2
  27. package/.output/server/_libs/_10.mjs +2 -4
  28. package/.output/server/_libs/_11.mjs +2 -4
  29. package/.output/server/_libs/_12.mjs +2 -3
  30. package/.output/server/_libs/_13.mjs +2 -3
  31. package/.output/server/_libs/_14.mjs +2 -4
  32. package/.output/server/_libs/_15.mjs +2 -4
  33. package/.output/server/_libs/_16.mjs +2 -3
  34. package/.output/server/_libs/_17.mjs +2 -4
  35. package/.output/server/_libs/_18.mjs +2 -2
  36. package/.output/server/_libs/_19.mjs +2 -2
  37. package/.output/server/_libs/_2.mjs +3 -3
  38. package/.output/server/_libs/_20.mjs +2 -2
  39. package/.output/server/_libs/_21.mjs +2 -2
  40. package/.output/server/_libs/_22.mjs +2 -2
  41. package/.output/server/_libs/_23.mjs +2 -2
  42. package/.output/server/_libs/_24.mjs +2 -2
  43. package/.output/server/_libs/_25.mjs +2 -2
  44. package/.output/server/_libs/_26.mjs +2 -2
  45. package/.output/server/_libs/_27.mjs +2 -2
  46. package/.output/server/_libs/_28.mjs +2 -2
  47. package/.output/server/_libs/_29.mjs +2 -2
  48. package/.output/server/_libs/_3.mjs +3 -3
  49. package/.output/server/_libs/_30.mjs +2 -2
  50. package/.output/server/_libs/_31.mjs +2 -2
  51. package/.output/server/_libs/_32.mjs +2 -2
  52. package/.output/server/_libs/_33.mjs +2 -2
  53. package/.output/server/_libs/_34.mjs +2 -2
  54. package/.output/server/_libs/_35.mjs +2 -2
  55. package/.output/server/_libs/_36.mjs +2 -2
  56. package/.output/server/_libs/_37.mjs +2 -2
  57. package/.output/server/_libs/_38.mjs +2 -2
  58. package/.output/server/_libs/_39.mjs +2 -2
  59. package/.output/server/_libs/_4.mjs +4 -3
  60. package/.output/server/_libs/_40.mjs +2 -2
  61. package/.output/server/_libs/_41.mjs +2 -2
  62. package/.output/server/_libs/_42.mjs +2 -2
  63. package/.output/server/_libs/_43.mjs +2 -2
  64. package/.output/server/_libs/_44.mjs +2 -2
  65. package/.output/server/_libs/_45.mjs +2 -2
  66. package/.output/server/_libs/_46.mjs +2 -2
  67. package/.output/server/_libs/_47.mjs +2 -2
  68. package/.output/server/_libs/_48.mjs +2 -2
  69. package/.output/server/_libs/_49.mjs +2 -2
  70. package/.output/server/_libs/_5.mjs +2 -3
  71. package/.output/server/_libs/_50.mjs +2 -2
  72. package/.output/server/_libs/_51.mjs +2 -2
  73. package/.output/server/_libs/_52.mjs +2 -2
  74. package/.output/server/_libs/_53.mjs +2 -2
  75. package/.output/server/_libs/_54.mjs +2 -2
  76. package/.output/server/_libs/_55.mjs +2 -2
  77. package/.output/server/_libs/_56.mjs +2 -2
  78. package/.output/server/_libs/_57.mjs +2 -2
  79. package/.output/server/_libs/_58.mjs +2 -2
  80. package/.output/server/_libs/_59.mjs +2 -2
  81. package/.output/server/_libs/_6.mjs +2 -3
  82. package/.output/server/_libs/_60.mjs +2 -2
  83. package/.output/server/_libs/_61.mjs +2 -2
  84. package/.output/server/_libs/_62.mjs +2 -2
  85. package/.output/server/_libs/_63.mjs +2 -2
  86. package/.output/server/_libs/_64.mjs +2 -2
  87. package/.output/server/_libs/_65.mjs +2 -2
  88. package/.output/server/_libs/_66.mjs +2 -2
  89. package/.output/server/_libs/_67.mjs +2 -2
  90. package/.output/server/_libs/_68.mjs +2 -2
  91. package/.output/server/_libs/_69.mjs +2 -2
  92. package/.output/server/_libs/_7.mjs +2 -5
  93. package/.output/server/_libs/_70.mjs +2 -2
  94. package/.output/server/_libs/_71.mjs +2 -2
  95. package/.output/server/_libs/_72.mjs +2 -2
  96. package/.output/server/_libs/_73.mjs +2 -2
  97. package/.output/server/_libs/_74.mjs +2 -2
  98. package/.output/server/_libs/_75.mjs +2 -2
  99. package/.output/server/_libs/_76.mjs +2 -2
  100. package/.output/server/_libs/_77.mjs +2 -2
  101. package/.output/server/_libs/_78.mjs +2 -2
  102. package/.output/server/_libs/_79.mjs +2 -2
  103. package/.output/server/_libs/_8.mjs +2 -3
  104. package/.output/server/_libs/_80.mjs +2 -2
  105. package/.output/server/_libs/_81.mjs +2 -2
  106. package/.output/server/_libs/_82.mjs +2 -2
  107. package/.output/server/_libs/_83.mjs +2 -2
  108. package/.output/server/_libs/_84.mjs +2 -2
  109. package/.output/server/_libs/_85.mjs +2 -2
  110. package/.output/server/_libs/_86.mjs +2 -2
  111. package/.output/server/_libs/_87.mjs +2 -2
  112. package/.output/server/_libs/_88.mjs +2 -2
  113. package/.output/server/_libs/_89.mjs +2 -2
  114. package/.output/server/_libs/_9.mjs +2 -4
  115. package/.output/server/_libs/_90.mjs +5 -2
  116. package/.output/server/_libs/_91.mjs +3 -2
  117. package/.output/server/_libs/_92.mjs +2 -2
  118. package/.output/server/_libs/_93.mjs +2 -2
  119. package/.output/server/_libs/_94.mjs +2 -2
  120. package/.output/server/_libs/agent-base.mjs +1 -1
  121. package/.output/server/_libs/cheerio+[...].mjs +1 -1
  122. package/.output/server/_libs/data-uri-to-buffer.mjs +2 -67
  123. package/.output/server/_libs/data-urls+[...].mjs +1 -1
  124. package/.output/server/_libs/diff.mjs +1 -1
  125. package/.output/server/_libs/exodus__bytes.mjs +99 -81
  126. package/.output/server/_libs/fetch-blob+node-domexception.mjs +1 -1
  127. package/.output/server/_libs/h3+rou3+srvx.mjs +34 -4
  128. package/.output/server/_libs/html-encoding-sniffer.mjs +1 -1
  129. package/.output/server/_libs/https-proxy-agent.mjs +2 -2
  130. package/.output/server/_libs/jsdom.mjs +1 -1
  131. package/.output/server/_libs/just-bash+[...].mjs +4676 -3916
  132. package/.output/server/_libs/mariozechner__jiti.mjs +1 -1
  133. package/.output/server/_libs/mariozechner__pi-ai.mjs +1472 -0
  134. package/.output/server/_libs/md4x.mjs +1 -1
  135. package/.output/server/_libs/node-fetch.mjs +14 -14
  136. package/.output/server/_libs/node-liblzma.mjs +1 -1
  137. package/.output/server/_libs/silvia-odwyer__photon-node.mjs +1 -1
  138. package/.output/server/_routes/api/auth/status.mjs +25 -6
  139. package/.output/server/_routes/api/config2.mjs +2 -0
  140. package/.output/server/_routes/api/files/groups.mjs +0 -1
  141. package/.output/server/_routes/api/groups.mjs +4 -2
  142. package/.output/server/_routes/api/groups2.mjs +14 -5
  143. package/.output/server/_routes/api/health.mjs +0 -1
  144. package/.output/server/_routes/api/pi/apikey.mjs +0 -1
  145. package/.output/server/_routes/api/pi/apikey_providers.mjs +0 -1
  146. package/.output/server/_routes/api/pi/commands.mjs +1 -2
  147. package/.output/server/_routes/api/pi/login/events.mjs +0 -1
  148. package/.output/server/_routes/api/pi/login/respond.mjs +0 -1
  149. package/.output/server/_routes/api/pi/login.mjs +0 -1
  150. package/.output/server/_routes/api/pi/logout.mjs +0 -1
  151. package/.output/server/_routes/api/pi/models.mjs +0 -1
  152. package/.output/server/_routes/api/pi/status.mjs +0 -1
  153. package/.output/server/_routes/api/sandbox.mjs +26 -0
  154. package/.output/server/_routes/api/sandbox2.mjs +17 -0
  155. package/.output/server/_routes/api/send.mjs +12 -12
  156. package/.output/server/_routes/api/status.mjs +0 -1
  157. package/.output/server/_routes/api/stop.mjs +0 -1
  158. package/.output/server/_routes/api/tasks2.mjs +0 -1
  159. package/.output/server/_routes/api/telegram/setup.mjs +0 -1
  160. package/.output/server/_routes/api/telegram/status.mjs +0 -1
  161. package/.output/server/_routes/api/terminal2.mjs +2 -1
  162. package/.output/server/_routes/api/tunnel/setup.mjs +0 -1
  163. package/.output/server/_runtime.mjs +1 -2
  164. package/.output/server/index.mjs +1 -1
  165. package/.output/server/node_modules/amdefine/amdefine.js +301 -0
  166. package/.output/server/node_modules/amdefine/package.json +16 -0
  167. package/.output/server/node_modules/compressjs/lib/BWT.js +420 -0
  168. package/.output/server/node_modules/compressjs/lib/BWTC.js +234 -0
  169. package/.output/server/node_modules/compressjs/lib/BitStream.js +108 -0
  170. package/.output/server/node_modules/compressjs/lib/Bzip2.js +936 -0
  171. package/.output/server/node_modules/compressjs/lib/CRC32.js +105 -0
  172. package/.output/server/node_modules/compressjs/lib/Context1Model.js +56 -0
  173. package/.output/server/node_modules/compressjs/lib/DefSumModel.js +152 -0
  174. package/.output/server/node_modules/compressjs/lib/DeflateDistanceModel.js +55 -0
  175. package/.output/server/node_modules/compressjs/lib/Dmc.js +197 -0
  176. package/.output/server/node_modules/compressjs/lib/DummyRangeCoder.js +81 -0
  177. package/.output/server/node_modules/compressjs/lib/FenwickModel.js +194 -0
  178. package/.output/server/node_modules/compressjs/lib/Huffman.js +514 -0
  179. package/.output/server/node_modules/compressjs/lib/HuffmanAllocator.js +227 -0
  180. package/.output/server/node_modules/compressjs/lib/LogDistanceModel.js +46 -0
  181. package/.output/server/node_modules/compressjs/lib/Lzjb.js +300 -0
  182. package/.output/server/node_modules/compressjs/lib/LzjbR.js +241 -0
  183. package/.output/server/node_modules/compressjs/lib/Lzp3.js +273 -0
  184. package/.output/server/node_modules/compressjs/lib/MTFModel.js +208 -0
  185. package/.output/server/node_modules/compressjs/lib/NoModel.js +46 -0
  186. package/.output/server/node_modules/compressjs/lib/PPM.js +343 -0
  187. package/.output/server/node_modules/compressjs/lib/RangeCoder.js +238 -0
  188. package/.output/server/node_modules/compressjs/lib/Simple.js +111 -0
  189. package/.output/server/node_modules/compressjs/lib/Stream.js +53 -0
  190. package/.output/server/node_modules/compressjs/lib/Util.js +324 -0
  191. package/.output/server/node_modules/compressjs/lib/freeze.js +14 -0
  192. package/.output/server/node_modules/compressjs/main.js +29 -0
  193. package/.output/server/node_modules/compressjs/package.json +35 -0
  194. package/.output/server/package.json +2 -1
  195. package/README.md +10 -1
  196. package/lib/index.d.mts +1 -0
  197. package/lib/index.mjs +1 -0
  198. package/lib/piclaw.mjs +100 -0
  199. package/lib/utils.mjs +96 -0
  200. package/package.json +16 -11
  201. package/.output/public/assets/defult-DtwgaiMA.js +0 -1
  202. package/.output/public/assets/index-B5n0eraW.css +0 -1
  203. package/.output/public/assets/index-DUbn6fuj.js +0 -205
  204. package/.output/server/_libs/@aws-crypto/crc32+[...].mjs +0 -299
  205. package/.output/server/_libs/@aws-sdk/client-bedrock-runtime+[...].mjs +0 -17828
  206. package/.output/server/_libs/@aws-sdk/credential-provider-http+[...].mjs +0 -122
  207. package/.output/server/_libs/@aws-sdk/credential-provider-ini+[...].mjs +0 -417
  208. package/.output/server/_libs/@aws-sdk/credential-provider-process+[...].mjs +0 -54
  209. package/.output/server/_libs/@aws-sdk/credential-provider-sso+[...].mjs +0 -1151
  210. package/.output/server/_libs/@aws-sdk/credential-provider-web-identity+[...].mjs +0 -50
  211. package/.output/server/_libs/@smithy/credential-provider-imds+[...].mjs +0 -369
  212. package/.output/server/_libs/@tootallnate/quickjs-emscripten+[...].mjs +0 -3011
  213. package/.output/server/_libs/_100.mjs +0 -2
  214. package/.output/server/_libs/_101.mjs +0 -2
  215. package/.output/server/_libs/_102.mjs +0 -2
  216. package/.output/server/_libs/_103.mjs +0 -5
  217. package/.output/server/_libs/_104.mjs +0 -3
  218. package/.output/server/_libs/_105.mjs +0 -2
  219. package/.output/server/_libs/_106.mjs +0 -3
  220. package/.output/server/_libs/_107.mjs +0 -2
  221. package/.output/server/_libs/_108.mjs +0 -2
  222. package/.output/server/_libs/_95.mjs +0 -2
  223. package/.output/server/_libs/_96.mjs +0 -2
  224. package/.output/server/_libs/_97.mjs +0 -2
  225. package/.output/server/_libs/_98.mjs +0 -2
  226. package/.output/server/_libs/_99.mjs +0 -2
  227. package/.output/server/_libs/amdefine.mjs +0 -188
  228. package/.output/server/_libs/ast-types.mjs +0 -2270
  229. package/.output/server/_libs/aws-sdk__nested-clients.mjs +0 -3141
  230. package/.output/server/_libs/basic-ftp.mjs +0 -1906
  231. package/.output/server/_libs/compressjs.mjs +0 -50
  232. package/.output/server/_libs/degenerator+[...].mjs +0 -9964
  233. package/.output/server/_libs/get-uri.mjs +0 -413
  234. package/.output/server/_libs/http-proxy-agent.mjs +0 -123
  235. package/.output/server/_libs/ip-address.mjs +0 -1423
  236. package/.output/server/_libs/lru-cache.mjs +0 -732
  237. package/.output/server/_libs/netmask.mjs +0 -139
  238. package/.output/server/_libs/pac-proxy-agent+[...].mjs +0 -3104
  239. package/.output/server/_libs/proxy-agent+proxy-from-env.mjs +0 -204
  240. package/.output/server/_libs/smithy__core.mjs +0 -192
  241. package/.output/server/node_modules/tslib/modules/index.js +0 -70
  242. package/.output/server/node_modules/tslib/modules/package.json +0 -3
  243. package/.output/server/node_modules/tslib/package.json +0 -47
  244. package/.output/server/node_modules/tslib/tslib.js +0 -484
  245. package/bin/piclaw.mjs +0 -195
@@ -0,0 +1,936 @@
1
+ /*
2
+ An implementation of Bzip2 de/compression, including the ability to
3
+ seek within bzip2 data.
4
+
5
+ Copyright (C) 2013 C. Scott Ananian
6
+ Copyright (C) 2012 Eli Skeggs
7
+ Copyright (C) 2011 Kevin Kwok
8
+
9
+ This library is free software; you can redistribute it and/or
10
+ modify it under the terms of the GNU Lesser General Public
11
+ License as published by the Free Software Foundation; either
12
+ version 2.1 of the License, or (at your option) any later version.
13
+
14
+ This library is distributed in the hope that it will be useful,
15
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
+ Lesser General Public License for more details.
18
+
19
+ You should have received a copy of the GNU Lesser General Public
20
+ License along with this library; if not, see
21
+ http://www.gnu.org/licenses/lgpl-2.1.html
22
+
23
+ Adapted from node-bzip, copyright 2012 Eli Skeggs.
24
+ Adapted from bzip2.js, copyright 2011 Kevin Kwok (antimatter15@gmail.com).
25
+
26
+ Based on micro-bunzip by Rob Landley (rob@landley.net).
27
+
28
+ Based on bzip2 decompression code by Julian R Seward (jseward@acm.org),
29
+ which also acknowledges contributions by Mike Burrows, David Wheeler,
30
+ Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten,
31
+ Robert Sedgewick, and Jon L. Bentley.
32
+
33
+ BWT implementation based on work by Yuta Mori; see BWT.js for details.
34
+
35
+ bzip2 compression code inspired by https://code.google.com/p/jbzip2
36
+ */
37
+ if (typeof define !== 'function') { var define = require('amdefine')(module); }
38
+ define(['./freeze','./BitStream','./BWT','./CRC32','./HuffmanAllocator','./Stream','./Util'], function(freeze, BitStream, BWT, CRC32, HuffmanAllocator, Stream, Util) {
39
+
40
+ var MAX_HUFCODE_BITS = 20;
41
+ var MAX_SYMBOLS = 258;
42
+ var SYMBOL_RUNA = 0;
43
+ var SYMBOL_RUNB = 1;
44
+ var MIN_GROUPS = 2;
45
+ var MAX_GROUPS = 6;
46
+ var GROUP_SIZE = 50;
47
+
48
+ var WHOLEPI = 0x314159265359; // 48-bit integer
49
+ var SQRTPI = 0x177245385090; // 48-bit integer
50
+
51
+ var EOF = Stream.EOF;
52
+
53
+ var mtf = function(array, index) {
54
+ var src = array[index], i;
55
+ for (i = index; i > 0; i--) {
56
+ array[i] = array[i-1];
57
+ }
58
+ array[0] = src;
59
+ return src;
60
+ };
61
+
62
+ var Err = {
63
+ OK: 0,
64
+ LAST_BLOCK: -1,
65
+ NOT_BZIP_DATA: -2,
66
+ UNEXPECTED_INPUT_EOF: -3,
67
+ UNEXPECTED_OUTPUT_EOF: -4,
68
+ DATA_ERROR: -5,
69
+ OUT_OF_MEMORY: -6,
70
+ OBSOLETE_INPUT: -7,
71
+ END_OF_BLOCK: -8
72
+ };
73
+ var ErrorMessages = {};
74
+ ErrorMessages[Err.LAST_BLOCK] = "Bad file checksum";
75
+ ErrorMessages[Err.NOT_BZIP_DATA] = "Not bzip data";
76
+ ErrorMessages[Err.UNEXPECTED_INPUT_EOF] = "Unexpected input EOF";
77
+ ErrorMessages[Err.UNEXPECTED_OUTPUT_EOF] = "Unexpected output EOF";
78
+ ErrorMessages[Err.DATA_ERROR] = "Data error";
79
+ ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory";
80
+ ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported.";
81
+
82
+ var _throw = function(status, optDetail) {
83
+ var msg = ErrorMessages[status] || 'unknown error';
84
+ if (optDetail) { msg += ': '+optDetail; }
85
+ var e = new TypeError(msg);
86
+ e.errorCode = status;
87
+ throw e;
88
+ };
89
+
90
+ var Bunzip = function(inputStream, outputStream) {
91
+ this.writePos = this.writeCurrent = this.writeCount = 0;
92
+
93
+ this._start_bunzip(inputStream, outputStream);
94
+ };
95
+ Bunzip.prototype._init_block = function() {
96
+ var moreBlocks = this._get_next_block();
97
+ if ( !moreBlocks ) {
98
+ this.writeCount = -1;
99
+ return false; /* no more blocks */
100
+ }
101
+ this.blockCRC = new CRC32();
102
+ return true;
103
+ };
104
+ /* XXX micro-bunzip uses (inputStream, inputBuffer, len) as arguments */
105
+ Bunzip.prototype._start_bunzip = function(inputStream, outputStream) {
106
+ /* Ensure that file starts with "BZh['1'-'9']." */
107
+ var buf = Util.makeU8Buffer(4);
108
+ if (inputStream.read(buf, 0, 4) !== 4 ||
109
+ String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh')
110
+ _throw(Err.NOT_BZIP_DATA, 'bad magic');
111
+
112
+ var level = buf[3] - 0x30;
113
+ if (level < 1 || level > 9)
114
+ _throw(Err.NOT_BZIP_DATA, 'level out of range');
115
+
116
+ this.reader = new BitStream(inputStream);
117
+
118
+ /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of
119
+ uncompressed data. Allocate intermediate buffer for block. */
120
+ this.dbufSize = 100000 * level;
121
+ this.nextoutput = 0;
122
+ this.outputStream = outputStream;
123
+ this.streamCRC = 0;
124
+ };
125
+ Bunzip.prototype._get_next_block = function() {
126
+ var i, j, k;
127
+ var reader = this.reader;
128
+ // this is get_next_block() function from micro-bunzip:
129
+ /* Read in header signature and CRC, then validate signature.
130
+ (last block signature means CRC is for whole file, return now) */
131
+ var h = reader.readBits(48);
132
+ if (h === SQRTPI) { // last block
133
+ return false; /* no more blocks */
134
+ }
135
+ if (h !== WHOLEPI)
136
+ _throw(Err.NOT_BZIP_DATA);
137
+ this.targetBlockCRC = reader.readBits(32);
138
+ this.streamCRC = (this.targetBlockCRC ^
139
+ ((this.streamCRC << 1) | (this.streamCRC>>>31))) >>> 0;
140
+ /* We can add support for blockRandomised if anybody complains. There was
141
+ some code for this in busybox 1.0.0-pre3, but nobody ever noticed that
142
+ it didn't actually work. */
143
+ if (reader.readBits(1))
144
+ _throw(Err.OBSOLETE_INPUT);
145
+ var origPointer = reader.readBits(24);
146
+ if (origPointer > this.dbufSize)
147
+ _throw(Err.DATA_ERROR, 'initial position out of bounds');
148
+ /* mapping table: if some byte values are never used (encoding things
149
+ like ASCII text), the compression code removes the gaps to have fewer
150
+ symbols to deal with, and writes a sparse bitfield indicating which
151
+ values were present. We make a translation table to convert the symbols
152
+ back to the corresponding bytes. */
153
+ var t = reader.readBits(16);
154
+ var symToByte = Util.makeU8Buffer(256), symTotal = 0;
155
+ for (i = 0; i < 16; i++) {
156
+ if (t & (1 << (0xF - i))) {
157
+ var o = i * 16;
158
+ k = reader.readBits(16);
159
+ for (j = 0; j < 16; j++)
160
+ if (k & (1 << (0xF - j)))
161
+ symToByte[symTotal++] = o + j;
162
+ }
163
+ }
164
+
165
+ /* How many different Huffman coding groups does this block use? */
166
+ var groupCount = reader.readBits(3);
167
+ if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS)
168
+ _throw(Err.DATA_ERROR);
169
+ /* nSelectors: Every GROUP_SIZE many symbols we select a new Huffman coding
170
+ group. Read in the group selector list, which is stored as MTF encoded
171
+ bit runs. (MTF=Move To Front, as each value is used it's moved to the
172
+ start of the list.) */
173
+ var nSelectors = reader.readBits(15);
174
+ if (nSelectors === 0)
175
+ _throw(Err.DATA_ERROR);
176
+
177
+ var mtfSymbol = Util.makeU8Buffer(256);
178
+ for (i = 0; i < groupCount; i++)
179
+ mtfSymbol[i] = i;
180
+
181
+ var selectors = Util.makeU8Buffer(nSelectors); // was 32768...
182
+
183
+ for (i = 0; i < nSelectors; i++) {
184
+ /* Get next value */
185
+ for (j = 0; reader.readBits(1); j++)
186
+ if (j >= groupCount) _throw(Err.DATA_ERROR);
187
+ /* Decode MTF to get the next selector */
188
+ selectors[i] = mtf(mtfSymbol, j);
189
+ }
190
+
191
+ /* Read the Huffman coding tables for each group, which code for symTotal
192
+ literal symbols, plus two run symbols (RUNA, RUNB) */
193
+ var symCount = symTotal + 2;
194
+ var groups = [], hufGroup;
195
+ for (j = 0; j < groupCount; j++) {
196
+ var length = Util.makeU8Buffer(symCount), temp = Util.makeU16Buffer(MAX_HUFCODE_BITS + 1);
197
+ /* Read Huffman code lengths for each symbol. They're stored in
198
+ a way similar to MTF; record a starting value for the first symbol,
199
+ and an offset from the previous value for every symbol after that. */
200
+ t = reader.readBits(5); // lengths
201
+ for (i = 0; i < symCount; i++) {
202
+ for (;;) {
203
+ if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR);
204
+ /* If first bit is 0, stop. Else second bit indicates whether
205
+ to increment or decrement the value. */
206
+ if(!reader.readBits(1))
207
+ break;
208
+ if(!reader.readBits(1))
209
+ t++;
210
+ else
211
+ t--;
212
+ }
213
+ length[i] = t;
214
+ }
215
+
216
+ /* Find largest and smallest lengths in this group */
217
+ var minLen, maxLen;
218
+ minLen = maxLen = length[0];
219
+ for (i = 1; i < symCount; i++) {
220
+ if (length[i] > maxLen)
221
+ maxLen = length[i];
222
+ else if (length[i] < minLen)
223
+ minLen = length[i];
224
+ }
225
+
226
+ /* Calculate permute[], base[], and limit[] tables from length[].
227
+ *
228
+ * permute[] is the lookup table for converting Huffman coded symbols
229
+ * into decoded symbols. base[] is the amount to subtract from the
230
+ * value of a Huffman symbol of a given length when using permute[].
231
+ *
232
+ * limit[] indicates the largest numerical value a symbol with a given
233
+ * number of bits can have. This is how the Huffman codes can vary in
234
+ * length: each code with a value>limit[length] needs another bit.
235
+ */
236
+ hufGroup = {};
237
+ groups.push(hufGroup);
238
+ hufGroup.permute = Util.makeU16Buffer(MAX_SYMBOLS);
239
+ hufGroup.limit = Util.makeU32Buffer(MAX_HUFCODE_BITS + 2);
240
+ hufGroup.base = Util.makeU32Buffer(MAX_HUFCODE_BITS + 1);
241
+ hufGroup.minLen = minLen;
242
+ hufGroup.maxLen = maxLen;
243
+ /* Calculate permute[]. Concurrently, initialize temp[] and limit[]. */
244
+ var pp = 0;
245
+ for (i = minLen; i <= maxLen; i++) {
246
+ temp[i] = hufGroup.limit[i] = 0;
247
+ for (t = 0; t < symCount; t++)
248
+ if (length[t] === i)
249
+ hufGroup.permute[pp++] = t;
250
+ }
251
+ /* Count symbols coded for at each bit length */
252
+ for (i = 0; i < symCount; i++)
253
+ temp[length[i]]++;
254
+ /* Calculate limit[] (the largest symbol-coding value at each bit
255
+ * length, which is (previous limit<<1)+symbols at this level), and
256
+ * base[] (number of symbols to ignore at each bit length, which is
257
+ * limit minus the cumulative count of symbols coded for already). */
258
+ pp = t = 0;
259
+ for (i = minLen; i < maxLen; i++) {
260
+ pp += temp[i];
261
+ /* We read the largest possible symbol size and then unget bits
262
+ after determining how many we need, and those extra bits could
263
+ be set to anything. (They're noise from future symbols.) At
264
+ each level we're really only interested in the first few bits,
265
+ so here we set all the trailing to-be-ignored bits to 1 so they
266
+ don't affect the value>limit[length] comparison. */
267
+ hufGroup.limit[i] = pp - 1;
268
+ pp <<= 1;
269
+ t += temp[i];
270
+ hufGroup.base[i + 1] = pp - t;
271
+ }
272
+ hufGroup.limit[maxLen + 1] = Number.MAX_VALUE; /* Sentinel value for reading next sym. */
273
+ hufGroup.limit[maxLen] = pp + temp[maxLen] - 1;
274
+ hufGroup.base[minLen] = 0;
275
+ }
276
+ /* We've finished reading and digesting the block header. Now read this
277
+ block's Huffman coded symbols from the file and undo the Huffman coding
278
+ and run length encoding, saving the result into dbuf[dbufCount++]=uc */
279
+
280
+ /* Initialize symbol occurrence counters and symbol Move To Front table */
281
+ var byteCount = Util.makeU32Buffer(256);
282
+ for (i = 0; i < 256; i++)
283
+ mtfSymbol[i] = i;
284
+ /* Loop through compressed symbols. */
285
+ var runPos = 0, dbufCount = 0, selector = 0, uc;
286
+ var dbuf = this.dbuf = Util.makeU32Buffer(this.dbufSize);
287
+ symCount = 0;
288
+ for (;;) {
289
+ /* Determine which Huffman coding group to use. */
290
+ if (!(symCount--)) {
291
+ symCount = GROUP_SIZE - 1;
292
+ if (selector >= nSelectors) { _throw(Err.DATA_ERROR); }
293
+ hufGroup = groups[selectors[selector++]];
294
+ }
295
+ /* Read next Huffman-coded symbol. */
296
+ i = hufGroup.minLen;
297
+ j = reader.readBits(i);
298
+ for (;;i++) {
299
+ if (i > hufGroup.maxLen) { _throw(Err.DATA_ERROR); }
300
+ if (j <= hufGroup.limit[i])
301
+ break;
302
+ j = (j << 1) | reader.readBits(1);
303
+ }
304
+ /* Huffman decode value to get nextSym (with bounds checking) */
305
+ j -= hufGroup.base[i];
306
+ if (j < 0 || j >= MAX_SYMBOLS) { _throw(Err.DATA_ERROR); }
307
+ var nextSym = hufGroup.permute[j];
308
+ /* We have now decoded the symbol, which indicates either a new literal
309
+ byte, or a repeated run of the most recent literal byte. First,
310
+ check if nextSym indicates a repeated run, and if so loop collecting
311
+ how many times to repeat the last literal. */
312
+ if (nextSym === SYMBOL_RUNA || nextSym === SYMBOL_RUNB) {
313
+ /* If this is the start of a new run, zero out counter */
314
+ if (!runPos){
315
+ runPos = 1;
316
+ t = 0;
317
+ }
318
+ /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at
319
+ each bit position, add 1 or 2 instead. For example,
320
+ 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2.
321
+ You can make any bit pattern that way using 1 less symbol than
322
+ the basic or 0/1 method (except all bits 0, which would use no
323
+ symbols, but a run of length 0 doesn't mean anything in this
324
+ context). Thus space is saved. */
325
+ if (nextSym === SYMBOL_RUNA)
326
+ t += runPos;
327
+ else
328
+ t += 2 * runPos;
329
+ runPos <<= 1;
330
+ continue;
331
+ }
332
+ /* When we hit the first non-run symbol after a run, we now know
333
+ how many times to repeat the last literal, so append that many
334
+ copies to our buffer of decoded symbols (dbuf) now. (The last
335
+ literal used is the one at the head of the mtfSymbol array.) */
336
+ if (runPos){
337
+ runPos = 0;
338
+ if (dbufCount + t > this.dbufSize) { _throw(Err.DATA_ERROR); }
339
+ uc = symToByte[mtfSymbol[0]];
340
+ byteCount[uc] += t;
341
+ while (t--)
342
+ dbuf[dbufCount++] = uc;
343
+ }
344
+ /* Is this the terminating symbol? */
345
+ if (nextSym > symTotal)
346
+ break;
347
+ /* At this point, nextSym indicates a new literal character. Subtract
348
+ one to get the position in the MTF array at which this literal is
349
+ currently to be found. (Note that the result can't be -1 or 0,
350
+ because 0 and 1 are RUNA and RUNB. But another instance of the
351
+ first symbol in the MTF array, position 0, would have been handled
352
+ as part of a run above. Therefore 1 unused MTF position minus
353
+ 2 non-literal nextSym values equals -1.) */
354
+ if (dbufCount >= this.dbufSize) { _throw(Err.DATA_ERROR); }
355
+ i = nextSym - 1;
356
+ uc = mtf(mtfSymbol, i);
357
+ uc = symToByte[uc];
358
+ /* We have our literal byte. Save it into dbuf. */
359
+ byteCount[uc]++;
360
+ dbuf[dbufCount++] = uc;
361
+ }
362
+ /* At this point, we've read all the Huffman-coded symbols (and repeated
363
+ runs) for this block from the input stream, and decoded them into the
364
+ intermediate buffer. There are dbufCount many decoded bytes in dbuf[].
365
+ Now undo the Burrows-Wheeler transform on dbuf.
366
+ See http://dogma.net/markn/articles/bwt/bwt.htm
367
+ */
368
+ if (origPointer < 0 || origPointer >= dbufCount) { _throw(Err.DATA_ERROR); }
369
+ /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */
370
+ j = 0;
371
+ for (i = 0; i < 256; i++) {
372
+ k = j + byteCount[i];
373
+ byteCount[i] = j;
374
+ j = k;
375
+ }
376
+ /* Figure out what order dbuf would be in if we sorted it. */
377
+ for (i = 0; i < dbufCount; i++) {
378
+ uc = dbuf[i] & 0xff;
379
+ dbuf[byteCount[uc]] |= (i << 8);
380
+ byteCount[uc]++;
381
+ }
382
+ /* Decode first byte by hand to initialize "previous" byte. Note that it
383
+ doesn't get output, and if the first three characters are identical
384
+ it doesn't qualify as a run (hence writeRunCountdown=5). */
385
+ var pos = 0, current = 0, run = 0;
386
+ if (dbufCount) {
387
+ pos = dbuf[origPointer];
388
+ current = (pos & 0xff);
389
+ pos >>= 8;
390
+ run = -1;
391
+ }
392
+ this.writePos = pos;
393
+ this.writeCurrent = current;
394
+ this.writeCount = dbufCount;
395
+ this.writeRun = run;
396
+
397
+ return true; /* more blocks to come */
398
+ };
399
+ /* Undo burrows-wheeler transform on intermediate buffer to produce output.
400
+ If start_bunzip was initialized with out_fd=-1, then up to len bytes of
401
+ data are written to outbuf. Return value is number of bytes written or
402
+ error (all errors are negative numbers). If out_fd!=-1, outbuf and len
403
+ are ignored, data is written to out_fd and return is RETVAL_OK or error.
404
+ */
405
+ Bunzip.prototype._read_bunzip = function(outputBuffer, len) {
406
+ var copies, previous, outbyte;
407
+ /* james@jamestaylor.org: writeCount goes to -1 when the buffer is fully
408
+ decoded, which results in this returning RETVAL_LAST_BLOCK, also
409
+ equal to -1... Confusing, I'm returning 0 here to indicate no
410
+ bytes written into the buffer */
411
+ if (this.writeCount < 0) { return 0; }
412
+
413
+ var gotcount = 0;
414
+ var dbuf = this.dbuf, pos = this.writePos, current = this.writeCurrent;
415
+ var dbufCount = this.writeCount, outputsize = this.outputsize;
416
+ var run = this.writeRun;
417
+
418
+ while (dbufCount) {
419
+ dbufCount--;
420
+ previous = current;
421
+ pos = dbuf[pos];
422
+ current = pos & 0xff;
423
+ pos >>= 8;
424
+ if (run++ === 3){
425
+ copies = current;
426
+ outbyte = previous;
427
+ current = -1;
428
+ } else {
429
+ copies = 1;
430
+ outbyte = current;
431
+ }
432
+ this.blockCRC.updateCRCRun(outbyte, copies);
433
+ while (copies--) {
434
+ this.outputStream.writeByte(outbyte);
435
+ this.nextoutput++;
436
+ }
437
+ if (current != previous)
438
+ run = 0;
439
+ }
440
+ this.writeCount = dbufCount;
441
+ // check CRC
442
+ if (this.blockCRC.getCRC() !== this.targetBlockCRC) {
443
+ _throw(Err.DATA_ERROR, "Bad block CRC "+
444
+ "(got "+this.blockCRC.getCRC().toString(16)+
445
+ " expected "+this.targetBlockCRC.toString(16)+")");
446
+ }
447
+ return this.nextoutput;
448
+ };
449
+
450
+ /* Static helper functions */
451
+ Bunzip.Err = Err;
452
+ // 'input' can be a stream or a buffer
453
+ // 'output' can be a stream or a buffer or a number (buffer size)
454
+ Bunzip.decode = function(input, output, multistream) {
455
+ // make a stream from a buffer, if necessary
456
+ var inputStream = Util.coerceInputStream(input);
457
+ var o = Util.coerceOutputStream(output, output);
458
+ var outputStream = o.stream;
459
+
460
+ var bz = new Bunzip(inputStream, outputStream);
461
+ while (true) {
462
+ if ('eof' in inputStream && inputStream.eof()) break;
463
+ if (bz._init_block()) {
464
+ bz._read_bunzip();
465
+ } else {
466
+ var targetStreamCRC = bz.reader.readBits(32);
467
+ if (targetStreamCRC !== bz.streamCRC) {
468
+ _throw(Err.DATA_ERROR, "Bad stream CRC "+
469
+ "(got "+bz.streamCRC.toString(16)+
470
+ " expected "+targetStreamCRC.toString(16)+")");
471
+ }
472
+ if (multistream &&
473
+ 'eof' in inputStream &&
474
+ !inputStream.eof()) {
475
+ // note that start_bunzip will also resync the bit reader to next byte
476
+ bz._start_bunzip(inputStream, outputStream);
477
+ } else break;
478
+ }
479
+ }
480
+ return o.retval;
481
+ };
482
+ Bunzip.decodeBlock = function(input, pos, output) {
483
+ // make a stream from a buffer, if necessary
484
+ var inputStream = Util.coerceInputStream(input);
485
+ var o = Util.coerceOutputStream(output, output);
486
+ var outputStream = o.stream;
487
+ var bz = new Bunzip(inputStream, outputStream);
488
+ bz.reader.seekBit(pos);
489
+ /* Fill the decode buffer for the block */
490
+ var moreBlocks = bz._get_next_block();
491
+ if (moreBlocks) {
492
+ /* Init the CRC for writing */
493
+ bz.blockCRC = new CRC32();
494
+
495
+ /* Zero this so the current byte from before the seek is not written */
496
+ bz.writeCopies = 0;
497
+
498
+ /* Decompress the block and write to stdout */
499
+ bz._read_bunzip();
500
+ // XXX keep writing?
501
+ }
502
+ return o.retval;
503
+ };
504
+ /* Reads bzip2 file from stream or buffer `input`, and invoke
505
+ * `callback(position, size)` once for each bzip2 block,
506
+ * where position gives the starting position (in *bits*)
507
+ * and size gives uncompressed size of the block (in *bytes*). */
508
+ Bunzip.table = function(input, callback, multistream) {
509
+ // make a stream from a buffer, if necessary
510
+ var inputStream = new Stream();
511
+ inputStream.delegate = Util.coerceInputStream(input);
512
+ inputStream.pos = 0;
513
+ inputStream.readByte = function() {
514
+ this.pos++;
515
+ return this.delegate.readByte();
516
+ };
517
+ inputStream.tell = function() { return this.pos; };
518
+ if (inputStream.delegate.eof) {
519
+ inputStream.eof = inputStream.delegate.eof.bind(inputStream.delegate);
520
+ }
521
+ var outputStream = new Stream();
522
+ outputStream.pos = 0;
523
+ outputStream.writeByte = function() { this.pos++; };
524
+
525
+ var bz = new Bunzip(inputStream, outputStream);
526
+ var blockSize = bz.dbufSize;
527
+ while (true) {
528
+ if ('eof' in inputStream && inputStream.eof()) break;
529
+
530
+ var position = bz.reader.tellBit();
531
+
532
+ if (bz._init_block()) {
533
+ var start = outputStream.pos;
534
+ bz._read_bunzip();
535
+ callback(position, outputStream.pos - start);
536
+ } else {
537
+ var crc = bz.reader.readBits(32); // (but we ignore the crc)
538
+ if (multistream &&
539
+ 'eof' in inputStream &&
540
+ !inputStream.eof()) {
541
+ // note that start_bunzip will also resync the bit reader to next byte
542
+ bz._start_bunzip(inputStream, outputStream);
543
+ console.assert(bz.dbufSize === blockSize,
544
+ "shouldn't change block size within multistream file");
545
+ } else break;
546
+ }
547
+ }
548
+ };
549
+
550
+ // create a Huffman tree from the table of frequencies
551
+ var StaticHuffman = function(freq, alphabetSize) {
552
+ // As in BZip2HuffmanStageEncoder.java (from jbzip2):
553
+ // The Huffman allocator needs its input symbol frequencies to be
554
+ // sorted, but we need to return code lengths in the same order as
555
+ // the corresponding frequencies are passed in.
556
+ // The symbol frequency and index are merged into a single array of
557
+ // integers - frequency in the high 23 bits, index in the low 9
558
+ // bits.
559
+ // 2^23 = 8,388,608 which is higher than the maximum possible
560
+ // frequency for one symbol in a block
561
+ // 2^9 = 512 which is higher than the maximum possible
562
+ // alphabet size (== 258)
563
+ // Sorting this array simultaneously sorts the frequencies and
564
+ // leaves a lookup that can be used to cheaply invert the sort
565
+ var i, mergedFreq = [];
566
+ for (i=0; i<alphabetSize; i++) {
567
+ mergedFreq[i] = (freq[i] << 9) | i;
568
+ }
569
+ mergedFreq.sort(function(a,b) { return a-b; });
570
+ var sortedFreq = mergedFreq.map(function(v) { return v>>>9; });
571
+ // allocate code lengths in place. (result in sortedFreq array)
572
+ HuffmanAllocator.allocateHuffmanCodeLengths(sortedFreq, MAX_HUFCODE_BITS);
573
+ // reverse the sort to put codes & code lengths in order of input symbols
574
+ this.codeLengths = Util.makeU8Buffer(alphabetSize);
575
+ for (i=0; i<alphabetSize; i++) {
576
+ var sym = mergedFreq[i] & 0x1FF;
577
+ this.codeLengths[sym] = sortedFreq[i];
578
+ }
579
+ };
580
+ // compute canonical Huffman codes, given code lengths
581
+ StaticHuffman.prototype.computeCanonical = function() {
582
+ var alphabetSize = this.codeLengths.length;
583
+ // merge arrays; sort first by length then by symbol.
584
+ var i, merged = [];
585
+ for (i=0; i<alphabetSize; i++) {
586
+ merged[i] = (this.codeLengths[i] << 9) | i;
587
+ }
588
+ merged.sort(function(a,b) { return a-b; });
589
+ // use sorted lengths to assign codes
590
+ this.code = Util.makeU32Buffer(alphabetSize);
591
+ var code = 0, prevLen = 0;
592
+ for (i=0; i<alphabetSize; i++) {
593
+ var curLen = merged[i] >>> 9;
594
+ var sym = merged[i] & 0x1FF;
595
+ console.assert(prevLen <= curLen);
596
+ code <<= (curLen - prevLen);
597
+ this.code[sym] = code++;
598
+ prevLen = curLen;
599
+ }
600
+ };
601
+ // compute the cost of encoding the given range of symbols w/ this Huffman code
602
+ StaticHuffman.prototype.cost = function(array, offset, length) {
603
+ var i, cost = 0;
604
+ for (i=0; i<length; i++) {
605
+ cost += this.codeLengths[array[offset+i]];
606
+ }
607
+ return cost;
608
+ };
609
+ // emit the bit lengths used by this Huffman code
610
+ StaticHuffman.prototype.emit = function(outStream) {
611
+ // write the starting length
612
+ var i, currentLength = this.codeLengths[0];
613
+ outStream.writeBits(5, currentLength);
614
+ for (i=0; i<this.codeLengths.length; i++) {
615
+ var codeLength = this.codeLengths[i];
616
+ var value, delta;
617
+ console.assert(codeLength > 0 && codeLength <= MAX_HUFCODE_BITS);
618
+ if (currentLength < codeLength) {
619
+ value = 2; delta = codeLength - currentLength;
620
+ } else {
621
+ value = 3; delta = currentLength - codeLength;
622
+ }
623
+ while (delta-- > 0) {
624
+ outStream.writeBits(2, value);
625
+ }
626
+ outStream.writeBit(0);
627
+ currentLength = codeLength;
628
+ }
629
+ };
630
+ // encode the given symbol with this Huffman code
631
+ StaticHuffman.prototype.encode = function(outStream, symbol) {
632
+ outStream.writeBits(this.codeLengths[symbol], this.code[symbol]);
633
+ };
634
+
635
+ // read a block for bzip2 compression.
636
+ var readBlock = function(inStream, block, length, crc) {
637
+ var pos = 0;
638
+ var lastChar = -1;
639
+ var runLength = 0;
640
+ while (pos < length) {
641
+ if (runLength===4) {
642
+ block[pos++] = 0;
643
+ if (pos >= length) { break; }
644
+ }
645
+ var ch = inStream.readByte();
646
+ if (ch === EOF) {
647
+ break;
648
+ }
649
+ crc.updateCRC(ch);
650
+ if (ch !== lastChar) {
651
+ lastChar = ch;
652
+ runLength = 1;
653
+ } else {
654
+ runLength++;
655
+ if (runLength > 4) {
656
+ if (runLength < 256) {
657
+ block[pos-1]++;
658
+ continue;
659
+ } else {
660
+ runLength = 1;
661
+ }
662
+ }
663
+ }
664
+ block[pos++] = ch;
665
+ }
666
+ return pos;
667
+ };
668
+
669
+ // divide the input into groups at most GROUP_SIZE symbols long.
670
+ // assign each group to the Huffman table which compresses it best.
671
+ var assignSelectors = function(selectors, groups, input) {
672
+ var i, j, k;
673
+ for (i=0, k=0; i<input.length; i+=GROUP_SIZE) {
674
+ var groupSize = Math.min(GROUP_SIZE, input.length - i);
675
+ var best = 0, bestCost = groups[0].cost(input, i, groupSize);
676
+ for (j=1; j<groups.length; j++) {
677
+ var groupCost = groups[j].cost(input, i, groupSize);
678
+ if (groupCost < bestCost) {
679
+ best = j; bestCost = groupCost;
680
+ }
681
+ }
682
+ selectors[k++] = best;
683
+ }
684
+ };
685
+ var optimizeHuffmanGroups = function(groups, targetGroups, input,
686
+ selectors, alphabetSize) {
687
+ // until we've got "targetGroups" Huffman codes, pick the Huffman code which
688
+ // matches the largest # of groups and split it by picking the groups
689
+ // which require more than the median number of bits to encode.
690
+ // then recompute frequencies and reassign Huffman codes.
691
+ var i, j, k, groupCounts = [];
692
+ while (groups.length < targetGroups) {
693
+ assignSelectors(selectors, groups, input);
694
+ // which code gets used the most?
695
+ for (i=0; i<groups.length; i++) { groupCounts[i] = 0; }
696
+ for (i=0; i<selectors.length; i++) {
697
+ groupCounts[selectors[i]]++;
698
+ }
699
+ var which = groupCounts.indexOf(Math.max.apply(Math, groupCounts));
700
+ // ok, let's look at the size of those blocks
701
+ var splits = [];
702
+ for (i=0, j=0; i<selectors.length; i++) {
703
+ if (selectors[i] !== which) { continue; }
704
+ var start = i*GROUP_SIZE;
705
+ var end = Math.min(start + GROUP_SIZE, input.length);
706
+ splits.push({index: i, cost:groups[which].cost(input, start, end-start)});
707
+ }
708
+ // find the median. there are O(n) algorithms to do this, but we'll
709
+ // be lazy and use a full O(n ln n) sort.
710
+ splits.sort(function(s1, s2) { return s1.cost - s2.cost; });
711
+ // assign the groups in the top half to the "new" selector
712
+ for (i=(splits.length>>>1); i<splits.length; i++) {
713
+ selectors[splits[i].index] = groups.length;
714
+ }
715
+ groups.push(null);
716
+ // recompute frequencies
717
+ var freq = [], f;
718
+ for (i=0; i<groups.length; i++) {
719
+ f = freq[i] = [];
720
+ for (j=0; j<alphabetSize; j++) { f[j] = 0; }
721
+ }
722
+ for (i=0, j=0; i<input.length; ) {
723
+ f = freq[selectors[j++]];
724
+ for (k=0; k<GROUP_SIZE && i<input.length; k++) {
725
+ f[input[i++]]++;
726
+ }
727
+ }
728
+ // reconstruct Huffman codes
729
+ for (i=0; i<groups.length; i++) {
730
+ groups[i] = new StaticHuffman(freq[i], alphabetSize);
731
+ }
732
+ }
733
+ };
734
+
735
+ var compressBlock = function(block, length, outStream) {
736
+ var c, i, j, k;
737
+ // do BWT transform
738
+ var U = Util.makeU8Buffer(length);
739
+ var pidx = BWT.bwtransform2(block, U, length, 256);
740
+ outStream.writeBit(0); // not randomized
741
+ outStream.writeBits(24, pidx);
742
+ // track values used; write bitmap
743
+ var used = [], compact = [];
744
+ for (i=0; i<length; i++) {
745
+ c = block[i];
746
+ used[c] = true;
747
+ compact[c>>>4] = true;
748
+ }
749
+ for (i=0; i<16; i++) {
750
+ outStream.writeBit(!!compact[i]);
751
+ }
752
+ for (i=0; i<16; i++) {
753
+ if (compact[i]) {
754
+ for (j=0; j<16; j++) {
755
+ outStream.writeBit(!!used[(i<<4)|j]);
756
+ }
757
+ }
758
+ }
759
+ var alphabetSize = 0;
760
+ for (i=0; i<256; i++) {
761
+ if (used[i]) {
762
+ alphabetSize++;
763
+ }
764
+ }
765
+ // now MTF and RLE/2 encoding, while tracking symbol statistics.
766
+ // output can be one longer than length, because we include the
767
+ // end-of-block character at the end. Similarly, we need a U16
768
+ // array because the end-of-block character can be 256.
769
+ var A = Util.makeU16Buffer(length+1);
770
+ var endOfBlock = alphabetSize + 1;
771
+ var freq = [];
772
+ for (i=0; i<=endOfBlock; i++) { freq[i] = 0; }
773
+ var M = Util.makeU8Buffer(alphabetSize);
774
+ for (i=0, j=0; i<256; i++) {
775
+ if (used[i]) { M[j++] = i; }
776
+ }
777
+ used = null; compact = null;
778
+ var pos = 0, runLength = 0;
779
+ var emit = function(c) {
780
+ A[pos++] = c;
781
+ freq[c]++;
782
+ };
783
+ var emitLastRun = function() {
784
+ while (runLength !== 0) {
785
+ if (runLength & 1) {
786
+ emit(0); // RUNA
787
+ runLength -= 1;
788
+ } else {
789
+ emit(1); // RUNB
790
+ runLength -= 2;
791
+ }
792
+ runLength >>>= 1;
793
+ }
794
+ };
795
+ for (i=0; i<U.length; i++) {
796
+ c = U[i];
797
+ // look for C in M
798
+ for (j=0; j<alphabetSize; j++) {
799
+ if (M[j]===c) { break; }
800
+ }
801
+ console.assert(j!==alphabetSize);
802
+ // shift MTF array
803
+ mtf(M, j);
804
+ // emit j
805
+ if (j===0) {
806
+ runLength++;
807
+ } else {
808
+ emitLastRun();
809
+ emit(j+1);
810
+ runLength = 0;
811
+ }
812
+ }
813
+ emitLastRun();
814
+ emit(endOfBlock); // end of block symbol
815
+ A = A.subarray(0, pos);
816
+ // now A[0...pos) has the encoded output, and freq[0-alphabetSize] has the
817
+ // frequencies. Use these to construct Huffman tables.
818
+ // the canonical bzip2 encoder does some complicated optimization
819
+ // to attempt to select the best tables. We're going to simplify things:
820
+ // (unless the block is very short) we're always going to create MAX_GROUPS
821
+ // tables; 1 based on global frequencies, and the rest based on dividing the
822
+ // block into MAX_GROUPS-1 pieces.
823
+ var groups = [];
824
+ var targetGroups; // how many Huffman groups should we create?
825
+ // look at length of MTF-encoded block to pick a good number of groups
826
+ if (pos >= 2400) { targetGroups = 6; }
827
+ else if (pos >= 1200) { targetGroups = 5; }
828
+ else if (pos >= 600) { targetGroups = 4; }
829
+ else if (pos >= 200) { targetGroups = 3; }
830
+ else { targetGroups = 2; }
831
+ // start with two Huffman groups: one with the global frequencies, and
832
+ // a second with a flat frequency distribution (which is also the smallest
833
+ // possible Huffman table to encode, which is handy to prevent excessive
834
+ // bloat if the input file size is very small)
835
+ groups.push(new StaticHuffman(freq, endOfBlock+1));
836
+ for (i=0; i<=endOfBlock; i++) { freq[i] = 1; }
837
+ groups.push(new StaticHuffman(freq, endOfBlock+1));
838
+ freq = null;
839
+ // Now optimize the Huffman groups! this is a black art.
840
+ // we probably don't want to waste too much time on it, though.
841
+ var selectors = Util.makeU8Buffer(Math.ceil(pos / GROUP_SIZE));
842
+ optimizeHuffmanGroups(groups, targetGroups, A, selectors, endOfBlock+1);
843
+ assignSelectors(selectors, groups, A);
844
+
845
+ // okay, let's start writing out our Huffman tables
846
+ console.assert(groups.length >= MIN_GROUPS && groups.length <= MAX_GROUPS);
847
+ outStream.writeBits(3, groups.length);
848
+ // and write out the best selector for each group
849
+ outStream.writeBits(15, selectors.length);
850
+ for (i=0; i<groups.length; i++) { M[i] = i; } // initialize MTF table.
851
+ for (i=0; i<selectors.length; i++) {
852
+ var s = selectors[i];
853
+ // find selector in MTF list
854
+ for (j=0; j<groups.length; j++) { if (M[j]===s) { break; } }
855
+ console.assert(j<groups.length);
856
+ mtf(M, j);
857
+ // emit 'j' as a unary number
858
+ for (;j>0; j--) {
859
+ outStream.writeBit(1);
860
+ }
861
+ outStream.writeBit(0);
862
+ }
863
+ // okay, now emit the Huffman tables in order.
864
+ for (i=0; i<groups.length; i++) {
865
+ groups[i].emit(outStream);
866
+ groups[i].computeCanonical(); // get ready for next step while we're at it
867
+ }
868
+ // okay, now (finally!) emit the actual data!
869
+ for (i=0, k=0; i<pos; ) {
870
+ var huff = groups[selectors[k++]];
871
+ for (j=0; j<GROUP_SIZE && i<pos; j++) {
872
+ huff.encode(outStream, A[i++]);
873
+ }
874
+ }
875
+ // done.
876
+ };
877
+
878
+ var Bzip2 = Object.create(null);
879
+ Bzip2.compressFile = function(inStream, outStream, props) {
880
+ inStream = Util.coerceInputStream(inStream);
881
+ var o = Util.coerceOutputStream(outStream, outStream);
882
+ outStream = new BitStream(o.stream);
883
+
884
+ var blockSizeMultiplier = 9;
885
+ if (typeof(props)==='number') {
886
+ blockSizeMultiplier = props;
887
+ }
888
+ if (blockSizeMultiplier < 1 || blockSizeMultiplier > 9) {
889
+ throw new Error('Invalid block size multiplier');
890
+ }
891
+
892
+ var blockSize = blockSizeMultiplier * 100000;
893
+ // the C implementation always writes at least length-19 characters,
894
+ // but it reads ahead enough that if the last character written was part
895
+ // of a run, it writes out the full run.
896
+ // That's really annoying to implement.
897
+ // So instead just subtract 19 from the blockSize; in most cases (unless
898
+ // there's a run at the end of the block) this will yield block divisions
899
+ // matching the C implementation.
900
+ blockSize -= 19;
901
+
902
+ // write file magic
903
+ outStream.writeByte('B'.charCodeAt(0));
904
+ outStream.writeByte('Z'.charCodeAt(0));
905
+ outStream.writeByte('h'.charCodeAt(0)); // Huffman-coded bzip
906
+ outStream.writeByte('0'.charCodeAt(0) + blockSizeMultiplier);
907
+
908
+ // allocate a buffer for the block
909
+ var block = Util.makeU8Buffer(blockSize);
910
+ var streamCRC = 0;
911
+ var length;
912
+
913
+ do {
914
+ var crc = new CRC32();
915
+ length = readBlock(inStream, block, blockSize, crc);
916
+ if (length > 0) {
917
+ streamCRC = (((streamCRC << 1) | (streamCRC>>>31)) ^ crc.getCRC()) >>> 0;
918
+ outStream.writeBits(48, WHOLEPI);
919
+ outStream.writeBits(32, crc.getCRC());
920
+ compressBlock(block, length, outStream);
921
+ }
922
+ } while (length === blockSize);
923
+
924
+ // finish up
925
+ outStream.writeBits(48, SQRTPI);
926
+ outStream.writeBits(32, streamCRC);
927
+ outStream.flush(); // get the last bits flushed out
928
+ return o.retval;
929
+ };
930
+
931
+ Bzip2.decompressFile = Bunzip.decode;
932
+ Bzip2.decompressBlock = Bunzip.decodeBlock;
933
+ Bzip2.table = Bunzip.table;
934
+
935
+ return Bzip2;
936
+ });