├── .gitignore ├── LICENSE ├── LICENSE.GPLv2 ├── LICENSE.MIT ├── README.md ├── bin ├── deflate.js └── inflate.js ├── examples ├── index.html ├── main.js └── package.json ├── index.js ├── lib ├── rawdeflate.js └── rawinflate.js ├── package.json └── test ├── deflate.py ├── helpers.py ├── inflate.py ├── runner.py └── test-files ├── declaration.txt ├── helloWorld.txt ├── lorem.txt └── random.txt /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | pakmanaged* 3 | checks.json 4 | test-outs 5 | *.pyc 6 | *.deflate 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | All code in lib is licensed under the GPLv2. All other code (examples, test, etc) is licensed under the MIT license. 2 | 3 | Because of the nature of the GPL, this entire project is effectively under the GPLv2, except for the testing code, which is completely autonomous. 4 | 5 | For questions, please contact T. Jameson Little 6 | -------------------------------------------------------------------------------- /LICENSE.GPLv2: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /LICENSE.MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 T. Jameson Little 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Intro 2 | ===== 3 | 4 | Does deflate compression/decompression in the browser and node. 5 | 6 | This module is not meant to be run on node for any production code. The native version of deflate should be used instead because it is much faster. The main reason for this being node-compatible is for testing purposes. 7 | 8 | Currently deflate does not pass all tests, but inflate does. This should not be used for compressing data yet in production. 9 | 10 | Install 11 | ======= 12 | 13 | For node, deflate-js can be installed with npm: `npm install deflate-js` 14 | 15 | For the browser, deflate-js can be installed with pakmanager. 16 | 17 | API 18 | === 19 | 20 | Deflate: 21 | 22 | > *deflate(arr[, level])* 23 | > 24 | > **arr**- Byte array to compress 25 | > 26 | > **level**- 1-9 (compression level; optional) 27 | 28 | Inflate: 29 | 30 | > *inflate(arr)* 31 | > 32 | > 33 | > **arr**- Byte array to decompress 34 | 35 | The basic usage (no level) will suffice for most purposes. 36 | 37 | Basic Usage 38 | ----------- 39 | 40 | var deflate = require('deflate-js'), 41 | arr; 42 | 43 | arr = Array.prototype.map.call('Hello world', function (char) { 44 | return char.charCodeAt(0); 45 | }); 46 | 47 | // compress some text 48 | var compressed = deflate.deflate(arr); 49 | 50 | // decompress some text 51 | var decompressed = deflate.inflate(compressed); 52 | -------------------------------------------------------------------------------- /bin/deflate.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | (function () { 3 | 'use strict'; 4 | 5 | var fs = require('fs'), 6 | path = require('path'), 7 | optimist = require('optimist'), 8 | deflate = require('../index'), 9 | argv, 10 | out; 11 | 12 | argv = optimist.usage('Usage: $0 --file [filename] --level [1-9] --output [filename]') 13 | .alias({ 14 | 'f': 'file', 15 | 'o': 'output', 16 | 'l': 'level' 17 | }).default({ 18 | 'level': deflate.deflate.DEFAULT_LEVEL 19 | }).demand(['file']).argv; 20 | 21 | out = deflate.deflate(fs.readFileSync(argv.file), argv.level); 22 | 23 | if (!argv.output) { 24 | argv.output = path.basename(argv.file) + '.deflate'; 25 | } 26 | fs.writeFileSync(argv.output, new Buffer(out)); 27 | }()); 28 | -------------------------------------------------------------------------------- /bin/inflate.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | (function () { 3 | 'use strict'; 4 | 5 | var fs = require('fs'), 6 | path = require('path'), 7 | optimist = require('optimist'), 8 | deflate = require('../index'), 9 | argv, 10 | out; 11 | 12 | argv = optimist.usage('Usage: $0 --file [filename] --output [filename]') 13 | .alias({ 14 | 'f': 'file', 15 | 'o': 'output' 16 | }).demand(['file']).argv; 17 | 18 | out = deflate.inflate(fs.readFileSync(argv.file)); 19 | 20 | if (!argv.output) { 21 | argv.output = path.basename(argv.file).replace(/\.deflate$/, ''); 22 | } 23 | 24 | console.log(argv.output); 25 | 26 | fs.writeFileSync(argv.output, new Buffer(out)); 27 | }()); 28 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test 5 | 6 | 7 | 8 |

DEFLATE Test Page

9 |

Enter text into the first text box to encode it, or enter base64 encoded deflate-encoded text into the second to decode

10 |
11 |
Inflated + Base64-Decoded (Original Text):
12 |
13 |
Deflated + Base64-Encoded (Compressed Output):
14 |
15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/main.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var inflate = require('../lib/rawinflate.js'), 5 | deflate = require('../lib/rawdeflate.js'), 6 | ender = require('ender'); 7 | 8 | ender.domReady(function () { 9 | ender('#inflated').bind('keyup', function () { 10 | var self = this, dst = ender('#deflated'); 11 | 12 | setTimeout(function(){ 13 | var arr, 14 | str; 15 | 16 | arr = Array.prototype.map.call(self.value, function (char) { 17 | return char.charCodeAt(0); 18 | }); 19 | 20 | str = deflate(arr).map(function (byte) { 21 | return String.fromCharCode(byte); 22 | }).join(''); 23 | 24 | dst.val(btoa(str)); 25 | },0); 26 | }); 27 | ender('#deflated').bind('keyup', function () { 28 | var self = this, dst = ender('#inflated'); 29 | 30 | setTimeout(function(){ 31 | var str, 32 | arr; 33 | 34 | arr = Array.prototype.map.call(atob(self.value), function (char) { 35 | return char.charCodeAt(0); 36 | }); 37 | 38 | str = inflate(arr).map(function (byte) { 39 | return String.fromCharCode(byte); 40 | }).join(''); 41 | 42 | dst.val(str); 43 | }, 0); 44 | }); 45 | }); 46 | }()); 47 | -------------------------------------------------------------------------------- /examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "T. Jameson Little", 3 | "name": "test", 4 | "version": "0.1.0", 5 | "main": "./main.js", 6 | "repository": {}, 7 | "engines": {}, 8 | "dependencies": { 9 | "jeesh": "*" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | module.exports = { 5 | 'inflate': require('./lib/rawinflate.js'), 6 | 'deflate': require('./lib/rawdeflate.js') 7 | }; 8 | }()); 9 | -------------------------------------------------------------------------------- /lib/rawdeflate.js: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: rawdeflate.js,v 0.3 2009/03/01 19:05:05 dankogai Exp dankogai $ 3 | * 4 | * Original: 5 | * http://www.onicos.com/staff/iz/amuse/javascript/expert/deflate.txt 6 | */ 7 | 8 | /* Copyright (C) 1999 Masanao Izumo 9 | * Version: 1.0.1 10 | * LastModified: Dec 25 1999 11 | */ 12 | 13 | /* Interface: 14 | * data = deflate(src); 15 | */ 16 | 17 | (function () { 18 | /* constant parameters */ 19 | var WSIZE = 32768, // Sliding Window size 20 | STORED_BLOCK = 0, 21 | STATIC_TREES = 1, 22 | DYN_TREES = 2, 23 | 24 | /* for deflate */ 25 | DEFAULT_LEVEL = 6, 26 | FULL_SEARCH = false, 27 | INBUFSIZ = 32768, // Input buffer size 28 | //INBUF_EXTRA = 64, // Extra buffer 29 | OUTBUFSIZ = 1024 * 8, 30 | window_size = 2 * WSIZE, 31 | MIN_MATCH = 3, 32 | MAX_MATCH = 258, 33 | BITS = 16, 34 | // for SMALL_MEM 35 | LIT_BUFSIZE = 0x2000, 36 | // HASH_BITS = 13, 37 | //for MEDIUM_MEM 38 | // LIT_BUFSIZE = 0x4000, 39 | // HASH_BITS = 14, 40 | // for BIG_MEM 41 | // LIT_BUFSIZE = 0x8000, 42 | HASH_BITS = 15, 43 | DIST_BUFSIZE = LIT_BUFSIZE, 44 | HASH_SIZE = 1 << HASH_BITS, 45 | HASH_MASK = HASH_SIZE - 1, 46 | WMASK = WSIZE - 1, 47 | NIL = 0, // Tail of hash chains 48 | TOO_FAR = 4096, 49 | MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1, 50 | MAX_DIST = WSIZE - MIN_LOOKAHEAD, 51 | SMALLEST = 1, 52 | MAX_BITS = 15, 53 | MAX_BL_BITS = 7, 54 | LENGTH_CODES = 29, 55 | LITERALS = 256, 56 | END_BLOCK = 256, 57 | L_CODES = LITERALS + 1 + LENGTH_CODES, 58 | D_CODES = 30, 59 | BL_CODES = 19, 60 | REP_3_6 = 16, 61 | REPZ_3_10 = 17, 62 | REPZ_11_138 = 18, 63 | HEAP_SIZE = 2 * L_CODES + 1, 64 | H_SHIFT = parseInt((HASH_BITS + MIN_MATCH - 1) / MIN_MATCH, 10), 65 | 66 | /* variables */ 67 | free_queue, 68 | qhead, 69 | qtail, 70 | initflag, 71 | outbuf = null, 72 | outcnt, 73 | outoff, 74 | complete, 75 | window, 76 | d_buf, 77 | l_buf, 78 | prev, 79 | bi_buf, 80 | bi_valid, 81 | block_start, 82 | ins_h, 83 | hash_head, 84 | prev_match, 85 | match_available, 86 | match_length, 87 | prev_length, 88 | strstart, 89 | match_start, 90 | eofile, 91 | lookahead, 92 | max_chain_length, 93 | max_lazy_match, 94 | compr_level, 95 | good_match, 96 | nice_match, 97 | dyn_ltree, 98 | dyn_dtree, 99 | static_ltree, 100 | static_dtree, 101 | bl_tree, 102 | l_desc, 103 | d_desc, 104 | bl_desc, 105 | bl_count, 106 | heap, 107 | heap_len, 108 | heap_max, 109 | depth, 110 | length_code, 111 | dist_code, 112 | base_length, 113 | base_dist, 114 | flag_buf, 115 | last_lit, 116 | last_dist, 117 | last_flags, 118 | flags, 119 | flag_bit, 120 | opt_len, 121 | static_len, 122 | deflate_data, 123 | deflate_pos; 124 | 125 | if (LIT_BUFSIZE > INBUFSIZ) { 126 | console.error("error: INBUFSIZ is too small"); 127 | } 128 | if ((WSIZE << 1) > (1 << BITS)) { 129 | console.error("error: WSIZE is too large"); 130 | } 131 | if (HASH_BITS > BITS - 1) { 132 | console.error("error: HASH_BITS is too large"); 133 | } 134 | if (HASH_BITS < 8 || MAX_MATCH !== 258) { 135 | console.error("error: Code too clever"); 136 | } 137 | 138 | /* objects (deflate) */ 139 | 140 | function DeflateCT() { 141 | this.fc = 0; // frequency count or bit string 142 | this.dl = 0; // father node in Huffman tree or length of bit string 143 | } 144 | 145 | function DeflateTreeDesc() { 146 | this.dyn_tree = null; // the dynamic tree 147 | this.static_tree = null; // corresponding static tree or NULL 148 | this.extra_bits = null; // extra bits for each code or NULL 149 | this.extra_base = 0; // base index for extra_bits 150 | this.elems = 0; // max number of elements in the tree 151 | this.max_length = 0; // max bit length for the codes 152 | this.max_code = 0; // largest code with non zero frequency 153 | } 154 | 155 | /* Values for max_lazy_match, good_match and max_chain_length, depending on 156 | * the desired pack level (0..9). The values given below have been tuned to 157 | * exclude worst case performance for pathological files. Better values may be 158 | * found for specific files. 159 | */ 160 | function DeflateConfiguration(a, b, c, d) { 161 | this.good_length = a; // reduce lazy search above this match length 162 | this.max_lazy = b; // do not perform lazy search above this match length 163 | this.nice_length = c; // quit search above this match length 164 | this.max_chain = d; 165 | } 166 | 167 | function DeflateBuffer() { 168 | this.next = null; 169 | this.len = 0; 170 | this.ptr = []; // new Array(OUTBUFSIZ); // ptr.length is never read 171 | this.off = 0; 172 | } 173 | 174 | /* constant tables */ 175 | var extra_lbits = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0]; 176 | var extra_dbits = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13]; 177 | var extra_blbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7]; 178 | var bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; 179 | var configuration_table = [ 180 | new DeflateConfiguration(0, 0, 0, 0), 181 | new DeflateConfiguration(4, 4, 8, 4), 182 | new DeflateConfiguration(4, 5, 16, 8), 183 | new DeflateConfiguration(4, 6, 32, 32), 184 | new DeflateConfiguration(4, 4, 16, 16), 185 | new DeflateConfiguration(8, 16, 32, 32), 186 | new DeflateConfiguration(8, 16, 128, 128), 187 | new DeflateConfiguration(8, 32, 128, 256), 188 | new DeflateConfiguration(32, 128, 258, 1024), 189 | new DeflateConfiguration(32, 258, 258, 4096) 190 | ]; 191 | 192 | 193 | /* routines (deflate) */ 194 | 195 | function deflate_start(level) { 196 | var i; 197 | 198 | if (!level) { 199 | level = DEFAULT_LEVEL; 200 | } else if (level < 1) { 201 | level = 1; 202 | } else if (level > 9) { 203 | level = 9; 204 | } 205 | 206 | compr_level = level; 207 | initflag = false; 208 | eofile = false; 209 | if (outbuf !== null) { 210 | return; 211 | } 212 | 213 | free_queue = qhead = qtail = null; 214 | outbuf = []; // new Array(OUTBUFSIZ); // outbuf.length never called 215 | window = []; // new Array(window_size); // window.length never called 216 | d_buf = []; // new Array(DIST_BUFSIZE); // d_buf.length never called 217 | l_buf = []; // new Array(INBUFSIZ + INBUF_EXTRA); // l_buf.length never called 218 | prev = []; // new Array(1 << BITS); // prev.length never called 219 | 220 | dyn_ltree = []; 221 | for (i = 0; i < HEAP_SIZE; i++) { 222 | dyn_ltree[i] = new DeflateCT(); 223 | } 224 | dyn_dtree = []; 225 | for (i = 0; i < 2 * D_CODES + 1; i++) { 226 | dyn_dtree[i] = new DeflateCT(); 227 | } 228 | static_ltree = []; 229 | for (i = 0; i < L_CODES + 2; i++) { 230 | static_ltree[i] = new DeflateCT(); 231 | } 232 | static_dtree = []; 233 | for (i = 0; i < D_CODES; i++) { 234 | static_dtree[i] = new DeflateCT(); 235 | } 236 | bl_tree = []; 237 | for (i = 0; i < 2 * BL_CODES + 1; i++) { 238 | bl_tree[i] = new DeflateCT(); 239 | } 240 | l_desc = new DeflateTreeDesc(); 241 | d_desc = new DeflateTreeDesc(); 242 | bl_desc = new DeflateTreeDesc(); 243 | bl_count = []; // new Array(MAX_BITS+1); // bl_count.length never called 244 | heap = []; // new Array(2*L_CODES+1); // heap.length never called 245 | depth = []; // new Array(2*L_CODES+1); // depth.length never called 246 | length_code = []; // new Array(MAX_MATCH-MIN_MATCH+1); // length_code.length never called 247 | dist_code = []; // new Array(512); // dist_code.length never called 248 | base_length = []; // new Array(LENGTH_CODES); // base_length.length never called 249 | base_dist = []; // new Array(D_CODES); // base_dist.length never called 250 | flag_buf = []; // new Array(parseInt(LIT_BUFSIZE / 8, 10)); // flag_buf.length never called 251 | } 252 | 253 | function deflate_end() { 254 | free_queue = qhead = qtail = null; 255 | outbuf = null; 256 | window = null; 257 | d_buf = null; 258 | l_buf = null; 259 | prev = null; 260 | dyn_ltree = null; 261 | dyn_dtree = null; 262 | static_ltree = null; 263 | static_dtree = null; 264 | bl_tree = null; 265 | l_desc = null; 266 | d_desc = null; 267 | bl_desc = null; 268 | bl_count = null; 269 | heap = null; 270 | depth = null; 271 | length_code = null; 272 | dist_code = null; 273 | base_length = null; 274 | base_dist = null; 275 | flag_buf = null; 276 | } 277 | 278 | function reuse_queue(p) { 279 | p.next = free_queue; 280 | free_queue = p; 281 | } 282 | 283 | function new_queue() { 284 | var p; 285 | 286 | if (free_queue !== null) { 287 | p = free_queue; 288 | free_queue = free_queue.next; 289 | } else { 290 | p = new DeflateBuffer(); 291 | } 292 | p.next = null; 293 | p.len = p.off = 0; 294 | 295 | return p; 296 | } 297 | 298 | function head1(i) { 299 | return prev[WSIZE + i]; 300 | } 301 | 302 | function head2(i, val) { 303 | return (prev[WSIZE + i] = val); 304 | } 305 | 306 | /* put_byte is used for the compressed output, put_ubyte for the 307 | * uncompressed output. However unlzw() uses window for its 308 | * suffix table instead of its output buffer, so it does not use put_ubyte 309 | * (to be cleaned up). 310 | */ 311 | function put_byte(c) { 312 | outbuf[outoff + outcnt++] = c; 313 | if (outoff + outcnt === OUTBUFSIZ) { 314 | qoutbuf(); 315 | } 316 | } 317 | 318 | /* Output a 16 bit value, lsb first */ 319 | function put_short(w) { 320 | w &= 0xffff; 321 | if (outoff + outcnt < OUTBUFSIZ - 2) { 322 | outbuf[outoff + outcnt++] = (w & 0xff); 323 | outbuf[outoff + outcnt++] = (w >>> 8); 324 | } else { 325 | put_byte(w & 0xff); 326 | put_byte(w >>> 8); 327 | } 328 | } 329 | 330 | /* ========================================================================== 331 | * Insert string s in the dictionary and set match_head to the previous head 332 | * of the hash chain (the most recent string with same hash key). Return 333 | * the previous length of the hash chain. 334 | * IN assertion: all calls to to INSERT_STRING are made with consecutive 335 | * input characters and the first MIN_MATCH bytes of s are valid 336 | * (except for the last MIN_MATCH-1 bytes of the input file). 337 | */ 338 | function INSERT_STRING() { 339 | ins_h = ((ins_h << H_SHIFT) ^ (window[strstart + MIN_MATCH - 1] & 0xff)) & HASH_MASK; 340 | hash_head = head1(ins_h); 341 | prev[strstart & WMASK] = hash_head; 342 | head2(ins_h, strstart); 343 | } 344 | 345 | /* Send a code of the given tree. c and tree must not have side effects */ 346 | function SEND_CODE(c, tree) { 347 | send_bits(tree[c].fc, tree[c].dl); 348 | } 349 | 350 | /* Mapping from a distance to a distance code. dist is the distance - 1 and 351 | * must not have side effects. dist_code[256] and dist_code[257] are never 352 | * used. 353 | */ 354 | function D_CODE(dist) { 355 | return (dist < 256 ? dist_code[dist] : dist_code[256 + (dist >> 7)]) & 0xff; 356 | } 357 | 358 | /* ========================================================================== 359 | * Compares to subtrees, using the tree depth as tie breaker when 360 | * the subtrees have equal frequency. This minimizes the worst case length. 361 | */ 362 | function SMALLER(tree, n, m) { 363 | return tree[n].fc < tree[m].fc || (tree[n].fc === tree[m].fc && depth[n] <= depth[m]); 364 | } 365 | 366 | /* ========================================================================== 367 | * read string data 368 | */ 369 | function read_buff(buff, offset, n) { 370 | var i; 371 | for (i = 0; i < n && deflate_pos < deflate_data.length; i++) { 372 | buff[offset + i] = deflate_data[deflate_pos++] & 0xff; 373 | } 374 | return i; 375 | } 376 | 377 | /* ========================================================================== 378 | * Initialize the "longest match" routines for a new file 379 | */ 380 | function lm_init() { 381 | var j; 382 | 383 | // Initialize the hash table. */ 384 | for (j = 0; j < HASH_SIZE; j++) { 385 | // head2(j, NIL); 386 | prev[WSIZE + j] = 0; 387 | } 388 | // prev will be initialized on the fly */ 389 | 390 | // Set the default configuration parameters: 391 | max_lazy_match = configuration_table[compr_level].max_lazy; 392 | good_match = configuration_table[compr_level].good_length; 393 | if (!FULL_SEARCH) { 394 | nice_match = configuration_table[compr_level].nice_length; 395 | } 396 | max_chain_length = configuration_table[compr_level].max_chain; 397 | 398 | strstart = 0; 399 | block_start = 0; 400 | 401 | lookahead = read_buff(window, 0, 2 * WSIZE); 402 | if (lookahead <= 0) { 403 | eofile = true; 404 | lookahead = 0; 405 | return; 406 | } 407 | eofile = false; 408 | // Make sure that we always have enough lookahead. This is important 409 | // if input comes from a device such as a tty. 410 | while (lookahead < MIN_LOOKAHEAD && !eofile) { 411 | fill_window(); 412 | } 413 | 414 | // If lookahead < MIN_MATCH, ins_h is garbage, but this is 415 | // not important since only literal bytes will be emitted. 416 | ins_h = 0; 417 | for (j = 0; j < MIN_MATCH - 1; j++) { 418 | // UPDATE_HASH(ins_h, window[j]); 419 | ins_h = ((ins_h << H_SHIFT) ^ (window[j] & 0xff)) & HASH_MASK; 420 | } 421 | } 422 | 423 | /* ========================================================================== 424 | * Set match_start to the longest match starting at the given string and 425 | * return its length. Matches shorter or equal to prev_length are discarded, 426 | * in which case the result is equal to prev_length and match_start is 427 | * garbage. 428 | * IN assertions: cur_match is the head of the hash chain for the current 429 | * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 430 | */ 431 | function longest_match(cur_match) { 432 | var chain_length = max_chain_length; // max hash chain length 433 | var scanp = strstart; // current string 434 | var matchp; // matched string 435 | var len; // length of current match 436 | var best_len = prev_length; // best match length so far 437 | 438 | // Stop when cur_match becomes <= limit. To simplify the code, 439 | // we prevent matches with the string of window index 0. 440 | var limit = (strstart > MAX_DIST ? strstart - MAX_DIST : NIL); 441 | 442 | var strendp = strstart + MAX_MATCH; 443 | var scan_end1 = window[scanp + best_len - 1]; 444 | var scan_end = window[scanp + best_len]; 445 | 446 | var i, broke; 447 | 448 | // Do not waste too much time if we already have a good match: */ 449 | if (prev_length >= good_match) { 450 | chain_length >>= 2; 451 | } 452 | 453 | // Assert(encoder->strstart <= window_size-MIN_LOOKAHEAD, "insufficient lookahead"); 454 | 455 | do { 456 | // Assert(cur_match < encoder->strstart, "no future"); 457 | matchp = cur_match; 458 | 459 | // Skip to next match if the match length cannot increase 460 | // or if the match length is less than 2: 461 | if (window[matchp + best_len] !== scan_end || 462 | window[matchp + best_len - 1] !== scan_end1 || 463 | window[matchp] !== window[scanp] || 464 | window[++matchp] !== window[scanp + 1]) { 465 | continue; 466 | } 467 | 468 | // The check at best_len-1 can be removed because it will be made 469 | // again later. (This heuristic is not always a win.) 470 | // It is not necessary to compare scan[2] and match[2] since they 471 | // are always equal when the other bytes match, given that 472 | // the hash keys are equal and that HASH_BITS >= 8. 473 | scanp += 2; 474 | matchp++; 475 | 476 | // We check for insufficient lookahead only every 8th comparison; 477 | // the 256th check will be made at strstart+258. 478 | while (scanp < strendp) { 479 | broke = false; 480 | for (i = 0; i < 8; i += 1) { 481 | scanp += 1; 482 | matchp += 1; 483 | if (window[scanp] !== window[matchp]) { 484 | broke = true; 485 | break; 486 | } 487 | } 488 | 489 | if (broke) { 490 | break; 491 | } 492 | } 493 | 494 | len = MAX_MATCH - (strendp - scanp); 495 | scanp = strendp - MAX_MATCH; 496 | 497 | if (len > best_len) { 498 | match_start = cur_match; 499 | best_len = len; 500 | if (FULL_SEARCH) { 501 | if (len >= MAX_MATCH) { 502 | break; 503 | } 504 | } else { 505 | if (len >= nice_match) { 506 | break; 507 | } 508 | } 509 | 510 | scan_end1 = window[scanp + best_len - 1]; 511 | scan_end = window[scanp + best_len]; 512 | } 513 | } while ((cur_match = prev[cur_match & WMASK]) > limit && --chain_length !== 0); 514 | 515 | return best_len; 516 | } 517 | 518 | /* ========================================================================== 519 | * Fill the window when the lookahead becomes insufficient. 520 | * Updates strstart and lookahead, and sets eofile if end of input file. 521 | * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0 522 | * OUT assertions: at least one byte has been read, or eofile is set; 523 | * file reads are performed for at least two bytes (required for the 524 | * translate_eol option). 525 | */ 526 | function fill_window() { 527 | var n, m; 528 | 529 | // Amount of free space at the end of the window. 530 | var more = window_size - lookahead - strstart; 531 | 532 | // If the window is almost full and there is insufficient lookahead, 533 | // move the upper half to the lower one to make room in the upper half. 534 | if (more === -1) { 535 | // Very unlikely, but possible on 16 bit machine if strstart == 0 536 | // and lookahead == 1 (input done one byte at time) 537 | more--; 538 | } else if (strstart >= WSIZE + MAX_DIST) { 539 | // By the IN assertion, the window is not empty so we can't confuse 540 | // more == 0 with more == 64K on a 16 bit machine. 541 | // Assert(window_size == (ulg)2*WSIZE, "no sliding with BIG_MEM"); 542 | 543 | // System.arraycopy(window, WSIZE, window, 0, WSIZE); 544 | for (n = 0; n < WSIZE; n++) { 545 | window[n] = window[n + WSIZE]; 546 | } 547 | 548 | match_start -= WSIZE; 549 | strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */ 550 | block_start -= WSIZE; 551 | 552 | for (n = 0; n < HASH_SIZE; n++) { 553 | m = head1(n); 554 | head2(n, m >= WSIZE ? m - WSIZE : NIL); 555 | } 556 | for (n = 0; n < WSIZE; n++) { 557 | // If n is not on any hash chain, prev[n] is garbage but 558 | // its value will never be used. 559 | m = prev[n]; 560 | prev[n] = (m >= WSIZE ? m - WSIZE : NIL); 561 | } 562 | more += WSIZE; 563 | } 564 | // At this point, more >= 2 565 | if (!eofile) { 566 | n = read_buff(window, strstart + lookahead, more); 567 | if (n <= 0) { 568 | eofile = true; 569 | } else { 570 | lookahead += n; 571 | } 572 | } 573 | } 574 | 575 | /* ========================================================================== 576 | * Processes a new input file and return its compressed length. This 577 | * function does not perform lazy evaluationof matches and inserts 578 | * new strings in the dictionary only for unmatched strings or for short 579 | * matches. It is used only for the fast compression options. 580 | */ 581 | function deflate_fast() { 582 | while (lookahead !== 0 && qhead === null) { 583 | var flush; // set if current block must be flushed 584 | 585 | // Insert the string window[strstart .. strstart+2] in the 586 | // dictionary, and set hash_head to the head of the hash chain: 587 | INSERT_STRING(); 588 | 589 | // Find the longest match, discarding those <= prev_length. 590 | // At this point we have always match_length < MIN_MATCH 591 | if (hash_head !== NIL && strstart - hash_head <= MAX_DIST) { 592 | // To simplify the code, we prevent matches with the string 593 | // of window index 0 (in particular we have to avoid a match 594 | // of the string with itself at the start of the input file). 595 | match_length = longest_match(hash_head); 596 | // longest_match() sets match_start */ 597 | if (match_length > lookahead) { 598 | match_length = lookahead; 599 | } 600 | } 601 | if (match_length >= MIN_MATCH) { 602 | // check_match(strstart, match_start, match_length); 603 | 604 | flush = ct_tally(strstart - match_start, match_length - MIN_MATCH); 605 | lookahead -= match_length; 606 | 607 | // Insert new strings in the hash table only if the match length 608 | // is not too large. This saves time but degrades compression. 609 | if (match_length <= max_lazy_match) { 610 | match_length--; // string at strstart already in hash table 611 | do { 612 | strstart++; 613 | INSERT_STRING(); 614 | // strstart never exceeds WSIZE-MAX_MATCH, so there are 615 | // always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH 616 | // these bytes are garbage, but it does not matter since 617 | // the next lookahead bytes will be emitted as literals. 618 | } while (--match_length !== 0); 619 | strstart++; 620 | } else { 621 | strstart += match_length; 622 | match_length = 0; 623 | ins_h = window[strstart] & 0xff; 624 | // UPDATE_HASH(ins_h, window[strstart + 1]); 625 | ins_h = ((ins_h << H_SHIFT) ^ (window[strstart + 1] & 0xff)) & HASH_MASK; 626 | 627 | //#if MIN_MATCH !== 3 628 | // Call UPDATE_HASH() MIN_MATCH-3 more times 629 | //#endif 630 | 631 | } 632 | } else { 633 | // No match, output a literal byte */ 634 | flush = ct_tally(0, window[strstart] & 0xff); 635 | lookahead--; 636 | strstart++; 637 | } 638 | if (flush) { 639 | flush_block(0); 640 | block_start = strstart; 641 | } 642 | 643 | // Make sure that we always have enough lookahead, except 644 | // at the end of the input file. We need MAX_MATCH bytes 645 | // for the next match, plus MIN_MATCH bytes to insert the 646 | // string following the next match. 647 | while (lookahead < MIN_LOOKAHEAD && !eofile) { 648 | fill_window(); 649 | } 650 | } 651 | } 652 | 653 | function deflate_better() { 654 | // Process the input block. */ 655 | while (lookahead !== 0 && qhead === null) { 656 | // Insert the string window[strstart .. strstart+2] in the 657 | // dictionary, and set hash_head to the head of the hash chain: 658 | INSERT_STRING(); 659 | 660 | // Find the longest match, discarding those <= prev_length. 661 | prev_length = match_length; 662 | prev_match = match_start; 663 | match_length = MIN_MATCH - 1; 664 | 665 | if (hash_head !== NIL && prev_length < max_lazy_match && strstart - hash_head <= MAX_DIST) { 666 | // To simplify the code, we prevent matches with the string 667 | // of window index 0 (in particular we have to avoid a match 668 | // of the string with itself at the start of the input file). 669 | match_length = longest_match(hash_head); 670 | // longest_match() sets match_start */ 671 | if (match_length > lookahead) { 672 | match_length = lookahead; 673 | } 674 | 675 | // Ignore a length 3 match if it is too distant: */ 676 | if (match_length === MIN_MATCH && strstart - match_start > TOO_FAR) { 677 | // If prev_match is also MIN_MATCH, match_start is garbage 678 | // but we will ignore the current match anyway. 679 | match_length--; 680 | } 681 | } 682 | // If there was a match at the previous step and the current 683 | // match is not better, output the previous match: 684 | if (prev_length >= MIN_MATCH && match_length <= prev_length) { 685 | var flush; // set if current block must be flushed 686 | 687 | // check_match(strstart - 1, prev_match, prev_length); 688 | flush = ct_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH); 689 | 690 | // Insert in hash table all strings up to the end of the match. 691 | // strstart-1 and strstart are already inserted. 692 | lookahead -= prev_length - 1; 693 | prev_length -= 2; 694 | do { 695 | strstart++; 696 | INSERT_STRING(); 697 | // strstart never exceeds WSIZE-MAX_MATCH, so there are 698 | // always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH 699 | // these bytes are garbage, but it does not matter since the 700 | // next lookahead bytes will always be emitted as literals. 701 | } while (--prev_length !== 0); 702 | match_available = false; 703 | match_length = MIN_MATCH - 1; 704 | strstart++; 705 | if (flush) { 706 | flush_block(0); 707 | block_start = strstart; 708 | } 709 | } else if (match_available) { 710 | // If there was no match at the previous position, output a 711 | // single literal. If there was a match but the current match 712 | // is longer, truncate the previous match to a single literal. 713 | if (ct_tally(0, window[strstart - 1] & 0xff)) { 714 | flush_block(0); 715 | block_start = strstart; 716 | } 717 | strstart++; 718 | lookahead--; 719 | } else { 720 | // There is no previous match to compare with, wait for 721 | // the next step to decide. 722 | match_available = true; 723 | strstart++; 724 | lookahead--; 725 | } 726 | 727 | // Make sure that we always have enough lookahead, except 728 | // at the end of the input file. We need MAX_MATCH bytes 729 | // for the next match, plus MIN_MATCH bytes to insert the 730 | // string following the next match. 731 | while (lookahead < MIN_LOOKAHEAD && !eofile) { 732 | fill_window(); 733 | } 734 | } 735 | } 736 | 737 | function init_deflate() { 738 | if (eofile) { 739 | return; 740 | } 741 | bi_buf = 0; 742 | bi_valid = 0; 743 | ct_init(); 744 | lm_init(); 745 | 746 | qhead = null; 747 | outcnt = 0; 748 | outoff = 0; 749 | 750 | if (compr_level <= 3) { 751 | prev_length = MIN_MATCH - 1; 752 | match_length = 0; 753 | } else { 754 | match_length = MIN_MATCH - 1; 755 | match_available = false; 756 | } 757 | 758 | complete = false; 759 | } 760 | 761 | /* ========================================================================== 762 | * Same as above, but achieves better compression. We use a lazy 763 | * evaluation for matches: a match is finally adopted only if there is 764 | * no better match at the next window position. 765 | */ 766 | function deflate_internal(buff, off, buff_size) { 767 | var n; 768 | 769 | if (!initflag) { 770 | init_deflate(); 771 | initflag = true; 772 | if (lookahead === 0) { // empty 773 | complete = true; 774 | return 0; 775 | } 776 | } 777 | 778 | n = qcopy(buff, off, buff_size); 779 | if (n === buff_size) { 780 | return buff_size; 781 | } 782 | 783 | if (complete) { 784 | return n; 785 | } 786 | 787 | if (compr_level <= 3) { 788 | // optimized for speed 789 | deflate_fast(); 790 | } else { 791 | deflate_better(); 792 | } 793 | 794 | if (lookahead === 0) { 795 | if (match_available) { 796 | ct_tally(0, window[strstart - 1] & 0xff); 797 | } 798 | flush_block(1); 799 | complete = true; 800 | } 801 | 802 | return n + qcopy(buff, n + off, buff_size - n); 803 | } 804 | 805 | function qcopy(buff, off, buff_size) { 806 | var n, i, j; 807 | 808 | n = 0; 809 | while (qhead !== null && n < buff_size) { 810 | i = buff_size - n; 811 | if (i > qhead.len) { 812 | i = qhead.len; 813 | } 814 | // System.arraycopy(qhead.ptr, qhead.off, buff, off + n, i); 815 | for (j = 0; j < i; j++) { 816 | buff[off + n + j] = qhead.ptr[qhead.off + j]; 817 | } 818 | 819 | qhead.off += i; 820 | qhead.len -= i; 821 | n += i; 822 | if (qhead.len === 0) { 823 | var p; 824 | p = qhead; 825 | qhead = qhead.next; 826 | reuse_queue(p); 827 | } 828 | } 829 | 830 | if (n === buff_size) { 831 | return n; 832 | } 833 | 834 | if (outoff < outcnt) { 835 | i = buff_size - n; 836 | if (i > outcnt - outoff) { 837 | i = outcnt - outoff; 838 | } 839 | // System.arraycopy(outbuf, outoff, buff, off + n, i); 840 | for (j = 0; j < i; j++) { 841 | buff[off + n + j] = outbuf[outoff + j]; 842 | } 843 | outoff += i; 844 | n += i; 845 | if (outcnt === outoff) { 846 | outcnt = outoff = 0; 847 | } 848 | } 849 | return n; 850 | } 851 | 852 | /* ========================================================================== 853 | * Allocate the match buffer, initialize the various tables and save the 854 | * location of the internal file attribute (ascii/binary) and method 855 | * (DEFLATE/STORE). 856 | */ 857 | function ct_init() { 858 | var n; // iterates over tree elements 859 | var bits; // bit counter 860 | var length; // length value 861 | var code; // code value 862 | var dist; // distance index 863 | 864 | if (static_dtree[0].dl !== 0) { 865 | return; // ct_init already called 866 | } 867 | 868 | l_desc.dyn_tree = dyn_ltree; 869 | l_desc.static_tree = static_ltree; 870 | l_desc.extra_bits = extra_lbits; 871 | l_desc.extra_base = LITERALS + 1; 872 | l_desc.elems = L_CODES; 873 | l_desc.max_length = MAX_BITS; 874 | l_desc.max_code = 0; 875 | 876 | d_desc.dyn_tree = dyn_dtree; 877 | d_desc.static_tree = static_dtree; 878 | d_desc.extra_bits = extra_dbits; 879 | d_desc.extra_base = 0; 880 | d_desc.elems = D_CODES; 881 | d_desc.max_length = MAX_BITS; 882 | d_desc.max_code = 0; 883 | 884 | bl_desc.dyn_tree = bl_tree; 885 | bl_desc.static_tree = null; 886 | bl_desc.extra_bits = extra_blbits; 887 | bl_desc.extra_base = 0; 888 | bl_desc.elems = BL_CODES; 889 | bl_desc.max_length = MAX_BL_BITS; 890 | bl_desc.max_code = 0; 891 | 892 | // Initialize the mapping length (0..255) -> length code (0..28) 893 | length = 0; 894 | for (code = 0; code < LENGTH_CODES - 1; code++) { 895 | base_length[code] = length; 896 | for (n = 0; n < (1 << extra_lbits[code]); n++) { 897 | length_code[length++] = code; 898 | } 899 | } 900 | // Assert (length === 256, "ct_init: length !== 256"); 901 | 902 | // Note that the length 255 (match length 258) can be represented 903 | // in two different ways: code 284 + 5 bits or code 285, so we 904 | // overwrite length_code[255] to use the best encoding: 905 | length_code[length - 1] = code; 906 | 907 | // Initialize the mapping dist (0..32K) -> dist code (0..29) */ 908 | dist = 0; 909 | for (code = 0; code < 16; code++) { 910 | base_dist[code] = dist; 911 | for (n = 0; n < (1 << extra_dbits[code]); n++) { 912 | dist_code[dist++] = code; 913 | } 914 | } 915 | // Assert (dist === 256, "ct_init: dist !== 256"); 916 | // from now on, all distances are divided by 128 917 | for (dist >>= 7; code < D_CODES; code++) { 918 | base_dist[code] = dist << 7; 919 | for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { 920 | dist_code[256 + dist++] = code; 921 | } 922 | } 923 | // Assert (dist === 256, "ct_init: 256+dist !== 512"); 924 | 925 | // Construct the codes of the static literal tree 926 | for (bits = 0; bits <= MAX_BITS; bits++) { 927 | bl_count[bits] = 0; 928 | } 929 | n = 0; 930 | while (n <= 143) { 931 | static_ltree[n++].dl = 8; 932 | bl_count[8]++; 933 | } 934 | while (n <= 255) { 935 | static_ltree[n++].dl = 9; 936 | bl_count[9]++; 937 | } 938 | while (n <= 279) { 939 | static_ltree[n++].dl = 7; 940 | bl_count[7]++; 941 | } 942 | while (n <= 287) { 943 | static_ltree[n++].dl = 8; 944 | bl_count[8]++; 945 | } 946 | // Codes 286 and 287 do not exist, but we must include them in the 947 | // tree construction to get a canonical Huffman tree (longest code 948 | // all ones) 949 | gen_codes(static_ltree, L_CODES + 1); 950 | 951 | // The static distance tree is trivial: */ 952 | for (n = 0; n < D_CODES; n++) { 953 | static_dtree[n].dl = 5; 954 | static_dtree[n].fc = bi_reverse(n, 5); 955 | } 956 | 957 | // Initialize the first block of the first file: 958 | init_block(); 959 | } 960 | 961 | /* ========================================================================== 962 | * Initialize a new block. 963 | */ 964 | function init_block() { 965 | var n; // iterates over tree elements 966 | 967 | // Initialize the trees. 968 | for (n = 0; n < L_CODES; n++) { 969 | dyn_ltree[n].fc = 0; 970 | } 971 | for (n = 0; n < D_CODES; n++) { 972 | dyn_dtree[n].fc = 0; 973 | } 974 | for (n = 0; n < BL_CODES; n++) { 975 | bl_tree[n].fc = 0; 976 | } 977 | 978 | dyn_ltree[END_BLOCK].fc = 1; 979 | opt_len = static_len = 0; 980 | last_lit = last_dist = last_flags = 0; 981 | flags = 0; 982 | flag_bit = 1; 983 | } 984 | 985 | /* ========================================================================== 986 | * Restore the heap property by moving down the tree starting at node k, 987 | * exchanging a node with the smallest of its two sons if necessary, stopping 988 | * when the heap property is re-established (each father smaller than its 989 | * two sons). 990 | * 991 | * @param tree- tree to restore 992 | * @param k- node to move down 993 | */ 994 | function pqdownheap(tree, k) { 995 | var v = heap[k], 996 | j = k << 1; // left son of k 997 | 998 | while (j <= heap_len) { 999 | // Set j to the smallest of the two sons: 1000 | if (j < heap_len && SMALLER(tree, heap[j + 1], heap[j])) { 1001 | j++; 1002 | } 1003 | 1004 | // Exit if v is smaller than both sons 1005 | if (SMALLER(tree, v, heap[j])) { 1006 | break; 1007 | } 1008 | 1009 | // Exchange v with the smallest son 1010 | heap[k] = heap[j]; 1011 | k = j; 1012 | 1013 | // And continue down the tree, setting j to the left son of k 1014 | j <<= 1; 1015 | } 1016 | heap[k] = v; 1017 | } 1018 | 1019 | /* ========================================================================== 1020 | * Compute the optimal bit lengths for a tree and update the total bit length 1021 | * for the current block. 1022 | * IN assertion: the fields freq and dad are set, heap[heap_max] and 1023 | * above are the tree nodes sorted by increasing frequency. 1024 | * OUT assertions: the field len is set to the optimal bit length, the 1025 | * array bl_count contains the frequencies for each bit length. 1026 | * The length opt_len is updated; static_len is also updated if stree is 1027 | * not null. 1028 | */ 1029 | function gen_bitlen(desc) { // the tree descriptor 1030 | var tree = desc.dyn_tree; 1031 | var extra = desc.extra_bits; 1032 | var base = desc.extra_base; 1033 | var max_code = desc.max_code; 1034 | var max_length = desc.max_length; 1035 | var stree = desc.static_tree; 1036 | var h; // heap index 1037 | var n, m; // iterate over the tree elements 1038 | var bits; // bit length 1039 | var xbits; // extra bits 1040 | var f; // frequency 1041 | var overflow = 0; // number of elements with bit length too large 1042 | 1043 | for (bits = 0; bits <= MAX_BITS; bits++) { 1044 | bl_count[bits] = 0; 1045 | } 1046 | 1047 | // In a first pass, compute the optimal bit lengths (which may 1048 | // overflow in the case of the bit length tree). 1049 | tree[heap[heap_max]].dl = 0; // root of the heap 1050 | 1051 | for (h = heap_max + 1; h < HEAP_SIZE; h++) { 1052 | n = heap[h]; 1053 | bits = tree[tree[n].dl].dl + 1; 1054 | if (bits > max_length) { 1055 | bits = max_length; 1056 | overflow++; 1057 | } 1058 | tree[n].dl = bits; 1059 | // We overwrite tree[n].dl which is no longer needed 1060 | 1061 | if (n > max_code) { 1062 | continue; // not a leaf node 1063 | } 1064 | 1065 | bl_count[bits]++; 1066 | xbits = 0; 1067 | if (n >= base) { 1068 | xbits = extra[n - base]; 1069 | } 1070 | f = tree[n].fc; 1071 | opt_len += f * (bits + xbits); 1072 | if (stree !== null) { 1073 | static_len += f * (stree[n].dl + xbits); 1074 | } 1075 | } 1076 | if (overflow === 0) { 1077 | return; 1078 | } 1079 | 1080 | // This happens for example on obj2 and pic of the Calgary corpus 1081 | 1082 | // Find the first bit length which could increase: 1083 | do { 1084 | bits = max_length - 1; 1085 | while (bl_count[bits] === 0) { 1086 | bits--; 1087 | } 1088 | bl_count[bits]--; // move one leaf down the tree 1089 | bl_count[bits + 1] += 2; // move one overflow item as its brother 1090 | bl_count[max_length]--; 1091 | // The brother of the overflow item also moves one step up, 1092 | // but this does not affect bl_count[max_length] 1093 | overflow -= 2; 1094 | } while (overflow > 0); 1095 | 1096 | // Now recompute all bit lengths, scanning in increasing frequency. 1097 | // h is still equal to HEAP_SIZE. (It is simpler to reconstruct all 1098 | // lengths instead of fixing only the wrong ones. This idea is taken 1099 | // from 'ar' written by Haruhiko Okumura.) 1100 | for (bits = max_length; bits !== 0; bits--) { 1101 | n = bl_count[bits]; 1102 | while (n !== 0) { 1103 | m = heap[--h]; 1104 | if (m > max_code) { 1105 | continue; 1106 | } 1107 | if (tree[m].dl !== bits) { 1108 | opt_len += (bits - tree[m].dl) * tree[m].fc; 1109 | tree[m].fc = bits; 1110 | } 1111 | n--; 1112 | } 1113 | } 1114 | } 1115 | 1116 | /* ========================================================================== 1117 | * Generate the codes for a given tree and bit counts (which need not be 1118 | * optimal). 1119 | * IN assertion: the array bl_count contains the bit length statistics for 1120 | * the given tree and the field len is set for all tree elements. 1121 | * OUT assertion: the field code is set for all tree elements of non 1122 | * zero code length. 1123 | * @param tree- the tree to decorate 1124 | * @param max_code- largest code with non-zero frequency 1125 | */ 1126 | function gen_codes(tree, max_code) { 1127 | var next_code = []; // new Array(MAX_BITS + 1); // next code value for each bit length 1128 | var code = 0; // running code value 1129 | var bits; // bit index 1130 | var n; // code index 1131 | 1132 | // The distribution counts are first used to generate the code values 1133 | // without bit reversal. 1134 | for (bits = 1; bits <= MAX_BITS; bits++) { 1135 | code = ((code + bl_count[bits - 1]) << 1); 1136 | next_code[bits] = code; 1137 | } 1138 | 1139 | // Check that the bit counts in bl_count are consistent. The last code 1140 | // must be all ones. 1141 | // Assert (code + encoder->bl_count[MAX_BITS]-1 === (1<> 1; n >= 1; n--) { 1206 | pqdownheap(tree, n); 1207 | } 1208 | 1209 | // Construct the Huffman tree by repeatedly combining the least two 1210 | // frequent nodes. 1211 | do { 1212 | n = heap[SMALLEST]; 1213 | heap[SMALLEST] = heap[heap_len--]; 1214 | pqdownheap(tree, SMALLEST); 1215 | 1216 | m = heap[SMALLEST]; // m = node of next least frequency 1217 | 1218 | // keep the nodes sorted by frequency 1219 | heap[--heap_max] = n; 1220 | heap[--heap_max] = m; 1221 | 1222 | // Create a new node father of n and m 1223 | tree[node].fc = tree[n].fc + tree[m].fc; 1224 | // depth[node] = (char)(MAX(depth[n], depth[m]) + 1); 1225 | if (depth[n] > depth[m] + 1) { 1226 | depth[node] = depth[n]; 1227 | } else { 1228 | depth[node] = depth[m] + 1; 1229 | } 1230 | tree[n].dl = tree[m].dl = node; 1231 | 1232 | // and insert the new node in the heap 1233 | heap[SMALLEST] = node++; 1234 | pqdownheap(tree, SMALLEST); 1235 | 1236 | } while (heap_len >= 2); 1237 | 1238 | heap[--heap_max] = heap[SMALLEST]; 1239 | 1240 | // At this point, the fields freq and dad are set. We can now 1241 | // generate the bit lengths. 1242 | gen_bitlen(desc); 1243 | 1244 | // The field len is now set, we can generate the bit codes 1245 | gen_codes(tree, max_code); 1246 | } 1247 | 1248 | /* ========================================================================== 1249 | * Scan a literal or distance tree to determine the frequencies of the codes 1250 | * in the bit length tree. Updates opt_len to take into account the repeat 1251 | * counts. (The contribution of the bit length codes will be added later 1252 | * during the construction of bl_tree.) 1253 | * 1254 | * @param tree- the tree to be scanned 1255 | * @param max_code- and its largest code of non zero frequency 1256 | */ 1257 | function scan_tree(tree, max_code) { 1258 | var n, // iterates over all tree elements 1259 | prevlen = -1, // last emitted length 1260 | curlen, // length of current code 1261 | nextlen = tree[0].dl, // length of next code 1262 | count = 0, // repeat count of the current code 1263 | max_count = 7, // max repeat count 1264 | min_count = 4; // min repeat count 1265 | 1266 | if (nextlen === 0) { 1267 | max_count = 138; 1268 | min_count = 3; 1269 | } 1270 | tree[max_code + 1].dl = 0xffff; // guard 1271 | 1272 | for (n = 0; n <= max_code; n++) { 1273 | curlen = nextlen; 1274 | nextlen = tree[n + 1].dl; 1275 | if (++count < max_count && curlen === nextlen) { 1276 | continue; 1277 | } else if (count < min_count) { 1278 | bl_tree[curlen].fc += count; 1279 | } else if (curlen !== 0) { 1280 | if (curlen !== prevlen) { 1281 | bl_tree[curlen].fc++; 1282 | } 1283 | bl_tree[REP_3_6].fc++; 1284 | } else if (count <= 10) { 1285 | bl_tree[REPZ_3_10].fc++; 1286 | } else { 1287 | bl_tree[REPZ_11_138].fc++; 1288 | } 1289 | count = 0; prevlen = curlen; 1290 | if (nextlen === 0) { 1291 | max_count = 138; 1292 | min_count = 3; 1293 | } else if (curlen === nextlen) { 1294 | max_count = 6; 1295 | min_count = 3; 1296 | } else { 1297 | max_count = 7; 1298 | min_count = 4; 1299 | } 1300 | } 1301 | } 1302 | 1303 | /* ========================================================================== 1304 | * Send a literal or distance tree in compressed form, using the codes in 1305 | * bl_tree. 1306 | * 1307 | * @param tree- the tree to be scanned 1308 | * @param max_code- and its largest code of non zero frequency 1309 | */ 1310 | function send_tree(tree, max_code) { 1311 | var n; // iterates over all tree elements 1312 | var prevlen = -1; // last emitted length 1313 | var curlen; // length of current code 1314 | var nextlen = tree[0].dl; // length of next code 1315 | var count = 0; // repeat count of the current code 1316 | var max_count = 7; // max repeat count 1317 | var min_count = 4; // min repeat count 1318 | 1319 | // tree[max_code+1].dl = -1; */ /* guard already set */ 1320 | if (nextlen === 0) { 1321 | max_count = 138; 1322 | min_count = 3; 1323 | } 1324 | 1325 | for (n = 0; n <= max_code; n++) { 1326 | curlen = nextlen; 1327 | nextlen = tree[n + 1].dl; 1328 | if (++count < max_count && curlen === nextlen) { 1329 | continue; 1330 | } else if (count < min_count) { 1331 | do { 1332 | SEND_CODE(curlen, bl_tree); 1333 | } while (--count !== 0); 1334 | } else if (curlen !== 0) { 1335 | if (curlen !== prevlen) { 1336 | SEND_CODE(curlen, bl_tree); 1337 | count--; 1338 | } 1339 | // Assert(count >= 3 && count <= 6, " 3_6?"); 1340 | SEND_CODE(REP_3_6, bl_tree); 1341 | send_bits(count - 3, 2); 1342 | } else if (count <= 10) { 1343 | SEND_CODE(REPZ_3_10, bl_tree); 1344 | send_bits(count - 3, 3); 1345 | } else { 1346 | SEND_CODE(REPZ_11_138, bl_tree); 1347 | send_bits(count - 11, 7); 1348 | } 1349 | count = 0; 1350 | prevlen = curlen; 1351 | if (nextlen === 0) { 1352 | max_count = 138; 1353 | min_count = 3; 1354 | } else if (curlen === nextlen) { 1355 | max_count = 6; 1356 | min_count = 3; 1357 | } else { 1358 | max_count = 7; 1359 | min_count = 4; 1360 | } 1361 | } 1362 | } 1363 | 1364 | /* ========================================================================== 1365 | * Construct the Huffman tree for the bit lengths and return the index in 1366 | * bl_order of the last bit length code to send. 1367 | */ 1368 | function build_bl_tree() { 1369 | var max_blindex; // index of last bit length code of non zero freq 1370 | 1371 | // Determine the bit length frequencies for literal and distance trees 1372 | scan_tree(dyn_ltree, l_desc.max_code); 1373 | scan_tree(dyn_dtree, d_desc.max_code); 1374 | 1375 | // Build the bit length tree: 1376 | build_tree(bl_desc); 1377 | // opt_len now includes the length of the tree representations, except 1378 | // the lengths of the bit lengths codes and the 5+5+4 bits for the counts. 1379 | 1380 | // Determine the number of bit length codes to send. The pkzip format 1381 | // requires that at least 4 bit length codes be sent. (appnote.txt says 1382 | // 3 but the actual value used is 4.) 1383 | for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { 1384 | if (bl_tree[bl_order[max_blindex]].dl !== 0) { 1385 | break; 1386 | } 1387 | } 1388 | // Update opt_len to include the bit length tree and counts */ 1389 | opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; 1390 | // Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", 1391 | // encoder->opt_len, encoder->static_len)); 1392 | 1393 | return max_blindex; 1394 | } 1395 | 1396 | /* ========================================================================== 1397 | * Send the header for a block using dynamic Huffman trees: the counts, the 1398 | * lengths of the bit length codes, the literal tree and the distance tree. 1399 | * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. 1400 | */ 1401 | function send_all_trees(lcodes, dcodes, blcodes) { // number of codes for each tree 1402 | var rank; // index in bl_order 1403 | 1404 | // Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); 1405 | // Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); 1406 | // Tracev((stderr, "\nbl counts: ")); 1407 | send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt 1408 | send_bits(dcodes - 1, 5); 1409 | send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt 1410 | for (rank = 0; rank < blcodes; rank++) { 1411 | // Tracev((stderr, "\nbl code %2d ", bl_order[rank])); 1412 | send_bits(bl_tree[bl_order[rank]].dl, 3); 1413 | } 1414 | 1415 | // send the literal tree 1416 | send_tree(dyn_ltree, lcodes - 1); 1417 | 1418 | // send the distance tree 1419 | send_tree(dyn_dtree, dcodes - 1); 1420 | } 1421 | 1422 | /* ========================================================================== 1423 | * Determine the best encoding for the current block: dynamic trees, static 1424 | * trees or store, and output the encoded block to the zip file. 1425 | */ 1426 | function flush_block(eof) { // true if this is the last block for a file 1427 | var opt_lenb, static_lenb, // opt_len and static_len in bytes 1428 | max_blindex, // index of last bit length code of non zero freq 1429 | stored_len, // length of input block 1430 | i; 1431 | 1432 | stored_len = strstart - block_start; 1433 | flag_buf[last_flags] = flags; // Save the flags for the last 8 items 1434 | 1435 | // Construct the literal and distance trees 1436 | build_tree(l_desc); 1437 | // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", 1438 | // encoder->opt_len, encoder->static_len)); 1439 | 1440 | build_tree(d_desc); 1441 | // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", 1442 | // encoder->opt_len, encoder->static_len)); 1443 | // At this point, opt_len and static_len are the total bit lengths of 1444 | // the compressed block data, excluding the tree representations. 1445 | 1446 | // Build the bit length tree for the above two trees, and get the index 1447 | // in bl_order of the last bit length code to send. 1448 | max_blindex = build_bl_tree(); 1449 | 1450 | // Determine the best encoding. Compute first the block length in bytes 1451 | opt_lenb = (opt_len + 3 + 7) >> 3; 1452 | static_lenb = (static_len + 3 + 7) >> 3; 1453 | 1454 | // Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ", opt_lenb, encoder->opt_len, static_lenb, encoder->static_len, stored_len, encoder->last_lit, encoder->last_dist)); 1455 | 1456 | if (static_lenb <= opt_lenb) { 1457 | opt_lenb = static_lenb; 1458 | } 1459 | if (stored_len + 4 <= opt_lenb && block_start >= 0) { // 4: two words for the lengths 1460 | // The test buf !== NULL is only necessary if LIT_BUFSIZE > WSIZE. 1461 | // Otherwise we can't have processed more than WSIZE input bytes since 1462 | // the last block flush, because compression would have been 1463 | // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to 1464 | // transform a block into a stored block. 1465 | send_bits((STORED_BLOCK << 1) + eof, 3); /* send block type */ 1466 | bi_windup(); /* align on byte boundary */ 1467 | put_short(stored_len); 1468 | put_short(~stored_len); 1469 | 1470 | // copy block 1471 | /* 1472 | p = &window[block_start]; 1473 | for (i = 0; i < stored_len; i++) { 1474 | put_byte(p[i]); 1475 | } 1476 | */ 1477 | for (i = 0; i < stored_len; i++) { 1478 | put_byte(window[block_start + i]); 1479 | } 1480 | } else if (static_lenb === opt_lenb) { 1481 | send_bits((STATIC_TREES << 1) + eof, 3); 1482 | compress_block(static_ltree, static_dtree); 1483 | } else { 1484 | send_bits((DYN_TREES << 1) + eof, 3); 1485 | send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1); 1486 | compress_block(dyn_ltree, dyn_dtree); 1487 | } 1488 | 1489 | init_block(); 1490 | 1491 | if (eof !== 0) { 1492 | bi_windup(); 1493 | } 1494 | } 1495 | 1496 | /* ========================================================================== 1497 | * Save the match info and tally the frequency counts. Return true if 1498 | * the current block must be flushed. 1499 | * 1500 | * @param dist- distance of matched string 1501 | * @param lc- (match length - MIN_MATCH) or unmatched char (if dist === 0) 1502 | */ 1503 | function ct_tally(dist, lc) { 1504 | l_buf[last_lit++] = lc; 1505 | if (dist === 0) { 1506 | // lc is the unmatched char 1507 | dyn_ltree[lc].fc++; 1508 | } else { 1509 | // Here, lc is the match length - MIN_MATCH 1510 | dist--; // dist = match distance - 1 1511 | // Assert((ush)dist < (ush)MAX_DIST && (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)D_CODE(dist) < (ush)D_CODES, "ct_tally: bad match"); 1512 | 1513 | dyn_ltree[length_code[lc] + LITERALS + 1].fc++; 1514 | dyn_dtree[D_CODE(dist)].fc++; 1515 | 1516 | d_buf[last_dist++] = dist; 1517 | flags |= flag_bit; 1518 | } 1519 | flag_bit <<= 1; 1520 | 1521 | // Output the flags if they fill a byte 1522 | if ((last_lit & 7) === 0) { 1523 | flag_buf[last_flags++] = flags; 1524 | flags = 0; 1525 | flag_bit = 1; 1526 | } 1527 | // Try to guess if it is profitable to stop the current block here 1528 | if (compr_level > 2 && (last_lit & 0xfff) === 0) { 1529 | // Compute an upper bound for the compressed length 1530 | var out_length = last_lit * 8; 1531 | var in_length = strstart - block_start; 1532 | var dcode; 1533 | 1534 | for (dcode = 0; dcode < D_CODES; dcode++) { 1535 | out_length += dyn_dtree[dcode].fc * (5 + extra_dbits[dcode]); 1536 | } 1537 | out_length >>= 3; 1538 | // Trace((stderr,"\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ", encoder->last_lit, encoder->last_dist, in_length, out_length, 100L - out_length*100L/in_length)); 1539 | if (last_dist < parseInt(last_lit / 2, 10) && out_length < parseInt(in_length / 2, 10)) { 1540 | return true; 1541 | } 1542 | } 1543 | return (last_lit === LIT_BUFSIZE - 1 || last_dist === DIST_BUFSIZE); 1544 | // We avoid equality with LIT_BUFSIZE because of wraparound at 64K 1545 | // on 16 bit machines and because stored blocks are restricted to 1546 | // 64K-1 bytes. 1547 | } 1548 | 1549 | /* ========================================================================== 1550 | * Send the block data compressed using the given Huffman trees 1551 | * 1552 | * @param ltree- literal tree 1553 | * @param dtree- distance tree 1554 | */ 1555 | function compress_block(ltree, dtree) { 1556 | var dist; // distance of matched string 1557 | var lc; // match length or unmatched char (if dist === 0) 1558 | var lx = 0; // running index in l_buf 1559 | var dx = 0; // running index in d_buf 1560 | var fx = 0; // running index in flag_buf 1561 | var flag = 0; // current flags 1562 | var code; // the code to send 1563 | var extra; // number of extra bits to send 1564 | 1565 | if (last_lit !== 0) { 1566 | do { 1567 | if ((lx & 7) === 0) { 1568 | flag = flag_buf[fx++]; 1569 | } 1570 | lc = l_buf[lx++] & 0xff; 1571 | if ((flag & 1) === 0) { 1572 | SEND_CODE(lc, ltree); /* send a literal byte */ 1573 | // Tracecv(isgraph(lc), (stderr," '%c' ", lc)); 1574 | } else { 1575 | // Here, lc is the match length - MIN_MATCH 1576 | code = length_code[lc]; 1577 | SEND_CODE(code + LITERALS + 1, ltree); // send the length code 1578 | extra = extra_lbits[code]; 1579 | if (extra !== 0) { 1580 | lc -= base_length[code]; 1581 | send_bits(lc, extra); // send the extra length bits 1582 | } 1583 | dist = d_buf[dx++]; 1584 | // Here, dist is the match distance - 1 1585 | code = D_CODE(dist); 1586 | // Assert (code < D_CODES, "bad d_code"); 1587 | 1588 | SEND_CODE(code, dtree); // send the distance code 1589 | extra = extra_dbits[code]; 1590 | if (extra !== 0) { 1591 | dist -= base_dist[code]; 1592 | send_bits(dist, extra); // send the extra distance bits 1593 | } 1594 | } // literal or match pair ? 1595 | flag >>= 1; 1596 | } while (lx < last_lit); 1597 | } 1598 | 1599 | SEND_CODE(END_BLOCK, ltree); 1600 | } 1601 | 1602 | /* ========================================================================== 1603 | * Send a value on a given number of bits. 1604 | * IN assertion: length <= 16 and value fits in length bits. 1605 | * 1606 | * @param value- value to send 1607 | * @param length- number of bits 1608 | */ 1609 | var Buf_size = 16; // bit size of bi_buf 1610 | function send_bits(value, length) { 1611 | // If not enough room in bi_buf, use (valid) bits from bi_buf and 1612 | // (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) 1613 | // unused bits in value. 1614 | if (bi_valid > Buf_size - length) { 1615 | bi_buf |= (value << bi_valid); 1616 | put_short(bi_buf); 1617 | bi_buf = (value >> (Buf_size - bi_valid)); 1618 | bi_valid += length - Buf_size; 1619 | } else { 1620 | bi_buf |= value << bi_valid; 1621 | bi_valid += length; 1622 | } 1623 | } 1624 | 1625 | /* ========================================================================== 1626 | * Reverse the first len bits of a code, using straightforward code (a faster 1627 | * method would use a table) 1628 | * IN assertion: 1 <= len <= 15 1629 | * 1630 | * @param code- the value to invert 1631 | * @param len- its bit length 1632 | */ 1633 | function bi_reverse(code, len) { 1634 | var res = 0; 1635 | do { 1636 | res |= code & 1; 1637 | code >>= 1; 1638 | res <<= 1; 1639 | } while (--len > 0); 1640 | return res >> 1; 1641 | } 1642 | 1643 | /* ========================================================================== 1644 | * Write out any remaining bits in an incomplete byte. 1645 | */ 1646 | function bi_windup() { 1647 | if (bi_valid > 8) { 1648 | put_short(bi_buf); 1649 | } else if (bi_valid > 0) { 1650 | put_byte(bi_buf); 1651 | } 1652 | bi_buf = 0; 1653 | bi_valid = 0; 1654 | } 1655 | 1656 | function qoutbuf() { 1657 | var q, i; 1658 | if (outcnt !== 0) { 1659 | q = new_queue(); 1660 | if (qhead === null) { 1661 | qhead = qtail = q; 1662 | } else { 1663 | qtail = qtail.next = q; 1664 | } 1665 | q.len = outcnt - outoff; 1666 | // System.arraycopy(outbuf, outoff, q.ptr, 0, q.len); 1667 | for (i = 0; i < q.len; i++) { 1668 | q.ptr[i] = outbuf[outoff + i]; 1669 | } 1670 | outcnt = outoff = 0; 1671 | } 1672 | } 1673 | 1674 | function deflate(arr, level) { 1675 | var i, j, buff; 1676 | 1677 | deflate_data = arr; 1678 | deflate_pos = 0; 1679 | if (typeof level === "undefined") { 1680 | level = DEFAULT_LEVEL; 1681 | } 1682 | deflate_start(level); 1683 | 1684 | buff = []; 1685 | 1686 | do { 1687 | i = deflate_internal(buff, buff.length, 1024); 1688 | } while (i > 0); 1689 | 1690 | deflate_data = null; // G.C. 1691 | return buff; 1692 | } 1693 | 1694 | module.exports = deflate; 1695 | module.exports.DEFAULT_LEVEL = DEFAULT_LEVEL; 1696 | }()); 1697 | -------------------------------------------------------------------------------- /lib/rawinflate.js: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: rawinflate.js,v 0.2 2009/03/01 18:32:24 dankogai Exp $ 3 | * 4 | * original: 5 | * http://www.onicos.com/staff/iz/amuse/javascript/expert/inflate.txt 6 | */ 7 | 8 | /* Copyright (C) 1999 Masanao Izumo 9 | * Version: 1.0.0.1 10 | * LastModified: Dec 25 1999 11 | */ 12 | 13 | /* Interface: 14 | * data = inflate(src); 15 | */ 16 | 17 | (function () { 18 | /* constant parameters */ 19 | var WSIZE = 32768, // Sliding Window size 20 | STORED_BLOCK = 0, 21 | STATIC_TREES = 1, 22 | DYN_TREES = 2, 23 | 24 | /* for inflate */ 25 | lbits = 9, // bits in base literal/length lookup table 26 | dbits = 6, // bits in base distance lookup table 27 | 28 | /* variables (inflate) */ 29 | slide, 30 | wp, // current position in slide 31 | fixed_tl = null, // inflate static 32 | fixed_td, // inflate static 33 | fixed_bl, // inflate static 34 | fixed_bd, // inflate static 35 | bit_buf, // bit buffer 36 | bit_len, // bits in bit buffer 37 | method, 38 | eof, 39 | copy_leng, 40 | copy_dist, 41 | tl, // literal length decoder table 42 | td, // literal distance decoder table 43 | bl, // number of bits decoded by tl 44 | bd, // number of bits decoded by td 45 | 46 | inflate_data, 47 | inflate_pos, 48 | 49 | 50 | /* constant tables (inflate) */ 51 | MASK_BITS = [ 52 | 0x0000, 53 | 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 54 | 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff 55 | ], 56 | // Tables for deflate from PKZIP's appnote.txt. 57 | // Copy lengths for literal codes 257..285 58 | cplens = [ 59 | 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 60 | 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 61 | ], 62 | /* note: see note #13 above about the 258 in this list. */ 63 | // Extra bits for literal codes 257..285 64 | cplext = [ 65 | 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 66 | 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99 // 99==invalid 67 | ], 68 | // Copy offsets for distance codes 0..29 69 | cpdist = [ 70 | 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 71 | 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 72 | 8193, 12289, 16385, 24577 73 | ], 74 | // Extra bits for distance codes 75 | cpdext = [ 76 | 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 77 | 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 78 | 12, 12, 13, 13 79 | ], 80 | // Order of the bit length code lengths 81 | border = [ 82 | 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 83 | ]; 84 | /* objects (inflate) */ 85 | 86 | function HuftList() { 87 | this.next = null; 88 | this.list = null; 89 | } 90 | 91 | function HuftNode() { 92 | this.e = 0; // number of extra bits or operation 93 | this.b = 0; // number of bits in this code or subcode 94 | 95 | // union 96 | this.n = 0; // literal, length base, or distance base 97 | this.t = null; // (HuftNode) pointer to next level of table 98 | } 99 | 100 | /* 101 | * @param b- code lengths in bits (all assumed <= BMAX) 102 | * @param n- number of codes (assumed <= N_MAX) 103 | * @param s- number of simple-valued codes (0..s-1) 104 | * @param d- list of base values for non-simple codes 105 | * @param e- list of extra bits for non-simple codes 106 | * @param mm- maximum lookup bits 107 | */ 108 | function HuftBuild(b, n, s, d, e, mm) { 109 | this.BMAX = 16; // maximum bit length of any code 110 | this.N_MAX = 288; // maximum number of codes in any set 111 | this.status = 0; // 0: success, 1: incomplete table, 2: bad input 112 | this.root = null; // (HuftList) starting table 113 | this.m = 0; // maximum lookup bits, returns actual 114 | 115 | /* Given a list of code lengths and a maximum table size, make a set of 116 | tables to decode that set of codes. Return zero on success, one if 117 | the given code set is incomplete (the tables are still built in this 118 | case), two if the input is invalid (all zero length codes or an 119 | oversubscribed set of lengths), and three if not enough memory. 120 | The code with value 256 is special, and the tables are constructed 121 | so that no bits beyond that code are fetched when that code is 122 | decoded. */ 123 | var a; // counter for codes of length k 124 | var c = []; 125 | var el; // length of EOB code (value 256) 126 | var f; // i repeats in table every f entries 127 | var g; // maximum code length 128 | var h; // table level 129 | var i; // counter, current code 130 | var j; // counter 131 | var k; // number of bits in current code 132 | var lx = []; 133 | var p; // pointer into c[], b[], or v[] 134 | var pidx; // index of p 135 | var q; // (HuftNode) points to current table 136 | var r = new HuftNode(); // table entry for structure assignment 137 | var u = []; 138 | var v = []; 139 | var w; 140 | var x = []; 141 | var xp; // pointer into x or c 142 | var y; // number of dummy codes added 143 | var z; // number of entries in current table 144 | var o; 145 | var tail; // (HuftList) 146 | 147 | tail = this.root = null; 148 | 149 | // bit length count table 150 | for (i = 0; i < this.BMAX + 1; i++) { 151 | c[i] = 0; 152 | } 153 | // stack of bits per table 154 | for (i = 0; i < this.BMAX + 1; i++) { 155 | lx[i] = 0; 156 | } 157 | // HuftNode[BMAX][] table stack 158 | for (i = 0; i < this.BMAX; i++) { 159 | u[i] = null; 160 | } 161 | // values in order of bit length 162 | for (i = 0; i < this.N_MAX; i++) { 163 | v[i] = 0; 164 | } 165 | // bit offsets, then code stack 166 | for (i = 0; i < this.BMAX + 1; i++) { 167 | x[i] = 0; 168 | } 169 | 170 | // Generate counts for each bit length 171 | el = n > 256 ? b[256] : this.BMAX; // set length of EOB code, if any 172 | p = b; pidx = 0; 173 | i = n; 174 | do { 175 | c[p[pidx]]++; // assume all entries <= BMAX 176 | pidx++; 177 | } while (--i > 0); 178 | if (c[0] === n) { // null input--all zero length codes 179 | this.root = null; 180 | this.m = 0; 181 | this.status = 0; 182 | return; 183 | } 184 | 185 | // Find minimum and maximum length, bound *m by those 186 | for (j = 1; j <= this.BMAX; j++) { 187 | if (c[j] !== 0) { 188 | break; 189 | } 190 | } 191 | k = j; // minimum code length 192 | if (mm < j) { 193 | mm = j; 194 | } 195 | for (i = this.BMAX; i !== 0; i--) { 196 | if (c[i] !== 0) { 197 | break; 198 | } 199 | } 200 | g = i; // maximum code length 201 | if (mm > i) { 202 | mm = i; 203 | } 204 | 205 | // Adjust last length count to fill out codes, if needed 206 | for (y = 1 << j; j < i; j++, y <<= 1) { 207 | if ((y -= c[j]) < 0) { 208 | this.status = 2; // bad input: more codes than bits 209 | this.m = mm; 210 | return; 211 | } 212 | } 213 | if ((y -= c[i]) < 0) { 214 | this.status = 2; 215 | this.m = mm; 216 | return; 217 | } 218 | c[i] += y; 219 | 220 | // Generate starting offsets into the value table for each length 221 | x[1] = j = 0; 222 | p = c; 223 | pidx = 1; 224 | xp = 2; 225 | while (--i > 0) { // note that i == g from above 226 | x[xp++] = (j += p[pidx++]); 227 | } 228 | 229 | // Make a table of values in order of bit lengths 230 | p = b; pidx = 0; 231 | i = 0; 232 | do { 233 | if ((j = p[pidx++]) !== 0) { 234 | v[x[j]++] = i; 235 | } 236 | } while (++i < n); 237 | n = x[g]; // set n to length of v 238 | 239 | // Generate the Huffman codes and for each, make the table entries 240 | x[0] = i = 0; // first Huffman code is zero 241 | p = v; pidx = 0; // grab values in bit order 242 | h = -1; // no tables yet--level -1 243 | w = lx[0] = 0; // no bits decoded yet 244 | q = null; // ditto 245 | z = 0; // ditto 246 | 247 | // go through the bit lengths (k already is bits in shortest code) 248 | for (null; k <= g; k++) { 249 | a = c[k]; 250 | while (a-- > 0) { 251 | // here i is the Huffman code of length k bits for value p[pidx] 252 | // make tables up to required level 253 | while (k > w + lx[1 + h]) { 254 | w += lx[1 + h]; // add bits already decoded 255 | h++; 256 | 257 | // compute minimum size table less than or equal to *m bits 258 | z = (z = g - w) > mm ? mm : z; // upper limit 259 | if ((f = 1 << (j = k - w)) > a + 1) { // try a k-w bit table 260 | // too few codes for k-w bit table 261 | f -= a + 1; // deduct codes from patterns left 262 | xp = k; 263 | while (++j < z) { // try smaller tables up to z bits 264 | if ((f <<= 1) <= c[++xp]) { 265 | break; // enough codes to use up j bits 266 | } 267 | f -= c[xp]; // else deduct codes from patterns 268 | } 269 | } 270 | if (w + j > el && w < el) { 271 | j = el - w; // make EOB code end at table 272 | } 273 | z = 1 << j; // table entries for j-bit table 274 | lx[1 + h] = j; // set table size in stack 275 | 276 | // allocate and link in new table 277 | q = []; 278 | for (o = 0; o < z; o++) { 279 | q[o] = new HuftNode(); 280 | } 281 | 282 | if (!tail) { 283 | tail = this.root = new HuftList(); 284 | } else { 285 | tail = tail.next = new HuftList(); 286 | } 287 | tail.next = null; 288 | tail.list = q; 289 | u[h] = q; // table starts after link 290 | 291 | /* connect to last table, if there is one */ 292 | if (h > 0) { 293 | x[h] = i; // save pattern for backing up 294 | r.b = lx[h]; // bits to dump before this table 295 | r.e = 16 + j; // bits in this table 296 | r.t = q; // pointer to this table 297 | j = (i & ((1 << w) - 1)) >> (w - lx[h]); 298 | u[h - 1][j].e = r.e; 299 | u[h - 1][j].b = r.b; 300 | u[h - 1][j].n = r.n; 301 | u[h - 1][j].t = r.t; 302 | } 303 | } 304 | 305 | // set up table entry in r 306 | r.b = k - w; 307 | if (pidx >= n) { 308 | r.e = 99; // out of values--invalid code 309 | } else if (p[pidx] < s) { 310 | r.e = (p[pidx] < 256 ? 16 : 15); // 256 is end-of-block code 311 | r.n = p[pidx++]; // simple code is just the value 312 | } else { 313 | r.e = e[p[pidx] - s]; // non-simple--look up in lists 314 | r.n = d[p[pidx++] - s]; 315 | } 316 | 317 | // fill code-like entries with r // 318 | f = 1 << (k - w); 319 | for (j = i >> w; j < z; j += f) { 320 | q[j].e = r.e; 321 | q[j].b = r.b; 322 | q[j].n = r.n; 323 | q[j].t = r.t; 324 | } 325 | 326 | // backwards increment the k-bit code i 327 | for (j = 1 << (k - 1); (i & j) !== 0; j >>= 1) { 328 | i ^= j; 329 | } 330 | i ^= j; 331 | 332 | // backup over finished tables 333 | while ((i & ((1 << w) - 1)) !== x[h]) { 334 | w -= lx[h]; // don't need to update q 335 | h--; 336 | } 337 | } 338 | } 339 | 340 | /* return actual size of base table */ 341 | this.m = lx[1]; 342 | 343 | /* Return true (1) if we were given an incomplete table */ 344 | this.status = ((y !== 0 && g !== 1) ? 1 : 0); 345 | } 346 | 347 | 348 | /* routines (inflate) */ 349 | 350 | function GET_BYTE() { 351 | if (inflate_data.length === inflate_pos) { 352 | return -1; 353 | } 354 | return inflate_data[inflate_pos++] & 0xff; 355 | } 356 | 357 | function NEEDBITS(n) { 358 | while (bit_len < n) { 359 | bit_buf |= GET_BYTE() << bit_len; 360 | bit_len += 8; 361 | } 362 | } 363 | 364 | function GETBITS(n) { 365 | return bit_buf & MASK_BITS[n]; 366 | } 367 | 368 | function DUMPBITS(n) { 369 | bit_buf >>= n; 370 | bit_len -= n; 371 | } 372 | 373 | function inflate_codes(buff, off, size) { 374 | // inflate (decompress) the codes in a deflated (compressed) block. 375 | // Return an error code or zero if it all goes ok. 376 | var e; // table entry flag/number of extra bits 377 | var t; // (HuftNode) pointer to table entry 378 | var n; 379 | 380 | if (size === 0) { 381 | return 0; 382 | } 383 | 384 | // inflate the coded data 385 | n = 0; 386 | for (;;) { // do until end of block 387 | NEEDBITS(bl); 388 | t = tl.list[GETBITS(bl)]; 389 | e = t.e; 390 | while (e > 16) { 391 | if (e === 99) { 392 | return -1; 393 | } 394 | DUMPBITS(t.b); 395 | e -= 16; 396 | NEEDBITS(e); 397 | t = t.t[GETBITS(e)]; 398 | e = t.e; 399 | } 400 | DUMPBITS(t.b); 401 | 402 | if (e === 16) { // then it's a literal 403 | wp &= WSIZE - 1; 404 | buff[off + n++] = slide[wp++] = t.n; 405 | if (n === size) { 406 | return size; 407 | } 408 | continue; 409 | } 410 | 411 | // exit if end of block 412 | if (e === 15) { 413 | break; 414 | } 415 | 416 | // it's an EOB or a length 417 | 418 | // get length of block to copy 419 | NEEDBITS(e); 420 | copy_leng = t.n + GETBITS(e); 421 | DUMPBITS(e); 422 | 423 | // decode distance of block to copy 424 | NEEDBITS(bd); 425 | t = td.list[GETBITS(bd)]; 426 | e = t.e; 427 | 428 | while (e > 16) { 429 | if (e === 99) { 430 | return -1; 431 | } 432 | DUMPBITS(t.b); 433 | e -= 16; 434 | NEEDBITS(e); 435 | t = t.t[GETBITS(e)]; 436 | e = t.e; 437 | } 438 | DUMPBITS(t.b); 439 | NEEDBITS(e); 440 | copy_dist = wp - t.n - GETBITS(e); 441 | DUMPBITS(e); 442 | 443 | // do the copy 444 | while (copy_leng > 0 && n < size) { 445 | copy_leng--; 446 | copy_dist &= WSIZE - 1; 447 | wp &= WSIZE - 1; 448 | buff[off + n++] = slide[wp++] = slide[copy_dist++]; 449 | } 450 | 451 | if (n === size) { 452 | return size; 453 | } 454 | } 455 | 456 | method = -1; // done 457 | return n; 458 | } 459 | 460 | function inflate_stored(buff, off, size) { 461 | /* "decompress" an inflated type 0 (stored) block. */ 462 | var n; 463 | 464 | // go to byte boundary 465 | n = bit_len & 7; 466 | DUMPBITS(n); 467 | 468 | // get the length and its complement 469 | NEEDBITS(16); 470 | n = GETBITS(16); 471 | DUMPBITS(16); 472 | NEEDBITS(16); 473 | if (n !== ((~bit_buf) & 0xffff)) { 474 | return -1; // error in compressed data 475 | } 476 | DUMPBITS(16); 477 | 478 | // read and output the compressed data 479 | copy_leng = n; 480 | 481 | n = 0; 482 | while (copy_leng > 0 && n < size) { 483 | copy_leng--; 484 | wp &= WSIZE - 1; 485 | NEEDBITS(8); 486 | buff[off + n++] = slide[wp++] = GETBITS(8); 487 | DUMPBITS(8); 488 | } 489 | 490 | if (copy_leng === 0) { 491 | method = -1; // done 492 | } 493 | return n; 494 | } 495 | 496 | function inflate_fixed(buff, off, size) { 497 | // decompress an inflated type 1 (fixed Huffman codes) block. We should 498 | // either replace this with a custom decoder, or at least precompute the 499 | // Huffman tables. 500 | 501 | // if first time, set up tables for fixed blocks 502 | if (!fixed_tl) { 503 | var i; // temporary variable 504 | var l = []; // 288 length list for huft_build (initialized below) 505 | var h; // HuftBuild 506 | 507 | // literal table 508 | for (i = 0; i < 144; i++) { 509 | l[i] = 8; 510 | } 511 | for (null; i < 256; i++) { 512 | l[i] = 9; 513 | } 514 | for (null; i < 280; i++) { 515 | l[i] = 7; 516 | } 517 | for (null; i < 288; i++) { // make a complete, but wrong code set 518 | l[i] = 8; 519 | } 520 | fixed_bl = 7; 521 | 522 | h = new HuftBuild(l, 288, 257, cplens, cplext, fixed_bl); 523 | if (h.status !== 0) { 524 | console.error("HufBuild error: " + h.status); 525 | return -1; 526 | } 527 | fixed_tl = h.root; 528 | fixed_bl = h.m; 529 | 530 | // distance table 531 | for (i = 0; i < 30; i++) { // make an incomplete code set 532 | l[i] = 5; 533 | } 534 | fixed_bd = 5; 535 | 536 | h = new HuftBuild(l, 30, 0, cpdist, cpdext, fixed_bd); 537 | if (h.status > 1) { 538 | fixed_tl = null; 539 | console.error("HufBuild error: " + h.status); 540 | return -1; 541 | } 542 | fixed_td = h.root; 543 | fixed_bd = h.m; 544 | } 545 | 546 | tl = fixed_tl; 547 | td = fixed_td; 548 | bl = fixed_bl; 549 | bd = fixed_bd; 550 | return inflate_codes(buff, off, size); 551 | } 552 | 553 | function inflate_dynamic(buff, off, size) { 554 | // decompress an inflated type 2 (dynamic Huffman codes) block. 555 | var i; // temporary variables 556 | var j; 557 | var l; // last length 558 | var n; // number of lengths to get 559 | var t; // (HuftNode) literal/length code table 560 | var nb; // number of bit length codes 561 | var nl; // number of literal/length codes 562 | var nd; // number of distance codes 563 | var ll = []; 564 | var h; // (HuftBuild) 565 | 566 | // literal/length and distance code lengths 567 | for (i = 0; i < 286 + 30; i++) { 568 | ll[i] = 0; 569 | } 570 | 571 | // read in table lengths 572 | NEEDBITS(5); 573 | nl = 257 + GETBITS(5); // number of literal/length codes 574 | DUMPBITS(5); 575 | NEEDBITS(5); 576 | nd = 1 + GETBITS(5); // number of distance codes 577 | DUMPBITS(5); 578 | NEEDBITS(4); 579 | nb = 4 + GETBITS(4); // number of bit length codes 580 | DUMPBITS(4); 581 | if (nl > 286 || nd > 30) { 582 | return -1; // bad lengths 583 | } 584 | 585 | // read in bit-length-code lengths 586 | for (j = 0; j < nb; j++) { 587 | NEEDBITS(3); 588 | ll[border[j]] = GETBITS(3); 589 | DUMPBITS(3); 590 | } 591 | for (null; j < 19; j++) { 592 | ll[border[j]] = 0; 593 | } 594 | 595 | // build decoding table for trees--single level, 7 bit lookup 596 | bl = 7; 597 | h = new HuftBuild(ll, 19, 19, null, null, bl); 598 | if (h.status !== 0) { 599 | return -1; // incomplete code set 600 | } 601 | 602 | tl = h.root; 603 | bl = h.m; 604 | 605 | // read in literal and distance code lengths 606 | n = nl + nd; 607 | i = l = 0; 608 | while (i < n) { 609 | NEEDBITS(bl); 610 | t = tl.list[GETBITS(bl)]; 611 | j = t.b; 612 | DUMPBITS(j); 613 | j = t.n; 614 | if (j < 16) { // length of code in bits (0..15) 615 | ll[i++] = l = j; // save last length in l 616 | } else if (j === 16) { // repeat last length 3 to 6 times 617 | NEEDBITS(2); 618 | j = 3 + GETBITS(2); 619 | DUMPBITS(2); 620 | if (i + j > n) { 621 | return -1; 622 | } 623 | while (j-- > 0) { 624 | ll[i++] = l; 625 | } 626 | } else if (j === 17) { // 3 to 10 zero length codes 627 | NEEDBITS(3); 628 | j = 3 + GETBITS(3); 629 | DUMPBITS(3); 630 | if (i + j > n) { 631 | return -1; 632 | } 633 | while (j-- > 0) { 634 | ll[i++] = 0; 635 | } 636 | l = 0; 637 | } else { // j === 18: 11 to 138 zero length codes 638 | NEEDBITS(7); 639 | j = 11 + GETBITS(7); 640 | DUMPBITS(7); 641 | if (i + j > n) { 642 | return -1; 643 | } 644 | while (j-- > 0) { 645 | ll[i++] = 0; 646 | } 647 | l = 0; 648 | } 649 | } 650 | 651 | // build the decoding tables for literal/length and distance codes 652 | bl = lbits; 653 | h = new HuftBuild(ll, nl, 257, cplens, cplext, bl); 654 | if (bl === 0) { // no literals or lengths 655 | h.status = 1; 656 | } 657 | if (h.status !== 0) { 658 | if (h.status !== 1) { 659 | return -1; // incomplete code set 660 | } 661 | // **incomplete literal tree** 662 | } 663 | tl = h.root; 664 | bl = h.m; 665 | 666 | for (i = 0; i < nd; i++) { 667 | ll[i] = ll[i + nl]; 668 | } 669 | bd = dbits; 670 | h = new HuftBuild(ll, nd, 0, cpdist, cpdext, bd); 671 | td = h.root; 672 | bd = h.m; 673 | 674 | if (bd === 0 && nl > 257) { // lengths but no distances 675 | // **incomplete distance tree** 676 | return -1; 677 | } 678 | /* 679 | if (h.status === 1) { 680 | // **incomplete distance tree** 681 | } 682 | */ 683 | if (h.status !== 0) { 684 | return -1; 685 | } 686 | 687 | // decompress until an end-of-block code 688 | return inflate_codes(buff, off, size); 689 | } 690 | 691 | function inflate_start() { 692 | if (!slide) { 693 | slide = []; // new Array(2 * WSIZE); // slide.length is never called 694 | } 695 | wp = 0; 696 | bit_buf = 0; 697 | bit_len = 0; 698 | method = -1; 699 | eof = false; 700 | copy_leng = copy_dist = 0; 701 | tl = null; 702 | } 703 | 704 | function inflate_internal(buff, off, size) { 705 | // decompress an inflated entry 706 | var n, i; 707 | 708 | n = 0; 709 | while (n < size) { 710 | if (eof && method === -1) { 711 | return n; 712 | } 713 | 714 | if (copy_leng > 0) { 715 | if (method !== STORED_BLOCK) { 716 | // STATIC_TREES or DYN_TREES 717 | while (copy_leng > 0 && n < size) { 718 | copy_leng--; 719 | copy_dist &= WSIZE - 1; 720 | wp &= WSIZE - 1; 721 | buff[off + n++] = slide[wp++] = slide[copy_dist++]; 722 | } 723 | } else { 724 | while (copy_leng > 0 && n < size) { 725 | copy_leng--; 726 | wp &= WSIZE - 1; 727 | NEEDBITS(8); 728 | buff[off + n++] = slide[wp++] = GETBITS(8); 729 | DUMPBITS(8); 730 | } 731 | if (copy_leng === 0) { 732 | method = -1; // done 733 | } 734 | } 735 | if (n === size) { 736 | return n; 737 | } 738 | } 739 | 740 | if (method === -1) { 741 | if (eof) { 742 | break; 743 | } 744 | 745 | // read in last block bit 746 | NEEDBITS(1); 747 | if (GETBITS(1) !== 0) { 748 | eof = true; 749 | } 750 | DUMPBITS(1); 751 | 752 | // read in block type 753 | NEEDBITS(2); 754 | method = GETBITS(2); 755 | DUMPBITS(2); 756 | tl = null; 757 | copy_leng = 0; 758 | } 759 | 760 | switch (method) { 761 | case STORED_BLOCK: 762 | i = inflate_stored(buff, off + n, size - n); 763 | break; 764 | 765 | case STATIC_TREES: 766 | if (tl) { 767 | i = inflate_codes(buff, off + n, size - n); 768 | } else { 769 | i = inflate_fixed(buff, off + n, size - n); 770 | } 771 | break; 772 | 773 | case DYN_TREES: 774 | if (tl) { 775 | i = inflate_codes(buff, off + n, size - n); 776 | } else { 777 | i = inflate_dynamic(buff, off + n, size - n); 778 | } 779 | break; 780 | 781 | default: // error 782 | i = -1; 783 | break; 784 | } 785 | 786 | if (i === -1) { 787 | if (eof) { 788 | return 0; 789 | } 790 | return -1; 791 | } 792 | n += i; 793 | } 794 | return n; 795 | } 796 | 797 | function inflate(arr) { 798 | var buff = [], i; 799 | 800 | inflate_start(); 801 | inflate_data = arr; 802 | inflate_pos = 0; 803 | 804 | do { 805 | i = inflate_internal(buff, buff.length, 1024); 806 | } while (i > 0); 807 | inflate_data = null; // G.C. 808 | return buff; 809 | } 810 | 811 | module.exports = inflate; 812 | }()); 813 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Masanao Izumo ", 3 | "contributors": [ 4 | "T. Jameson Little ", 5 | "Dan Kogai " 6 | ], 7 | "name": "deflate-js", 8 | "description": "DEFLATE implemented in JavaScript (works in browser and Node)", 9 | "license": "GPL", 10 | "version": "0.2.3", 11 | "main": "./index.js", 12 | "bin": { 13 | "deflate-js": "./bin/deflate.js", 14 | "inflate-js": "./bin/inflate.js" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git://github.com/beatgammit/deflate-js.git" 19 | }, 20 | "scripts": { 21 | "test": "cd test ; ./runner.py; cd -" 22 | }, 23 | "engines": { 24 | "node": ">= 0.4.0" 25 | }, 26 | "dependencies": {}, 27 | "devDependencies": { 28 | "optimist": "~0.2" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/deflate.py: -------------------------------------------------------------------------------- 1 | import os 2 | from colorama import Fore 3 | from helpers import deflate, inflate, run_cmd 4 | 5 | outDirDefault = 'test-outs' 6 | testDirDefault = 'test-files' 7 | 8 | """ 9 | Run a single test 10 | 11 | @param tFile- required; the full path to the file to run 12 | @param level- optional (default: all); the compression level [1-9] 13 | @param delete- optional (default: True); whether to delete the gzipped files 14 | @return True if all tests passed; False if at least one test failed 15 | """ 16 | def runTest(tFile, level=None, delete=True, outDir=outDirDefault): 17 | passed = True 18 | if level == None: 19 | for x in range(1, 10): 20 | if runTest(tFile, x, delete) == False: 21 | passed = False 22 | 23 | return passed 24 | 25 | # make the test-outs directory 26 | try: 27 | os.mkdir(outDir) 28 | except: 29 | pass 30 | 31 | out1 = os.path.join(outDir, '%(file)s.%(level)d.deflate' % {'file': os.path.basename(tFile), 'level' : level}) 32 | out2 = os.path.join(outDir, '%(file)s.%(level)d.out.deflate' % {'file': os.path.basename(tFile), 'level' : level}) 33 | 34 | outData = deflate(tFile, outfile=out1, level=level) 35 | run_cmd('../bin/deflate.js --level %(level)d --file %(file)s --output %(output)s' % {'level' : level, 'file' : tFile, 'output' : out2}) 36 | 37 | result = run_cmd('diff %(file1)s %(file2)s' % {'file1' : out1, 'file2' : out2}) 38 | if result['returncode'] == 0: 39 | status = Fore.GREEN + 'PASSED' + Fore.RESET 40 | else: 41 | passed = False 42 | status = Fore.RED + 'FAILED' + Fore.RESET 43 | 44 | print 'Level %(level)d: %(status)s' % {'level' : level, 'status' : status} 45 | 46 | if delete == True: 47 | os.remove(out1) 48 | os.remove(out2) 49 | 50 | return passed 51 | 52 | """ 53 | Runs all tests on the given level. This iterates throuth the testDir directory defined above. 54 | 55 | @param level- The level to run on [1-9] (default: None, runs on all levels all) 56 | @param delete- Whether to delete output files after the test is run 57 | @return True if all levels passed, False if at least one failed 58 | """ 59 | def runAll(level=None, delete=True, testDir=testDirDefault, outDir=outDirDefault): 60 | # make the test-outs directory 61 | try: 62 | os.mkdir(outDir) 63 | except: 64 | pass 65 | 66 | passed = True 67 | for tFile in os.listdir(testDir): 68 | fullPath = os.path.join(testDir, tFile) 69 | 70 | print Fore.YELLOW + tFile + Fore.RESET 71 | 72 | if runTest(fullPath, level, delete) == False: 73 | passed = False 74 | 75 | print '' 76 | 77 | # if we deletede all the files that were created, delete the directory 78 | if delete == True: 79 | os.rmdir(outDir) 80 | return passed 81 | -------------------------------------------------------------------------------- /test/helpers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import zlib 4 | import subprocess as sp 5 | 6 | def deflate(filename, outfile=None, level=6): 7 | f = open(filename) 8 | data = f.read() 9 | f.close() 10 | 11 | compress = zlib.compressobj( 12 | level, # level: 0-9 13 | zlib.DEFLATED, # method: must be DEFLATED 14 | -zlib.MAX_WBITS, # window size in bits: 15 | # -15..-8: negate, suppress header 16 | # 8..15: normal 17 | # 16..30: subtract 16, gzip header 18 | zlib.DEF_MEM_LEVEL, # mem level: 1..8/9 19 | 0 # strategy: 20 | # 0 = Z_DEFAULT_STRATEGY 21 | # 1 = Z_FILTERED 22 | # 2 = Z_HUFFMAN_ONLY 23 | # 3 = Z_RLE 24 | # 4 = Z_FIXED 25 | ) 26 | deflated = compress.compress(data) 27 | deflated += compress.flush() 28 | 29 | if outfile != None: 30 | f = open(outfile, 'w') 31 | f.write(deflated) 32 | f.close() 33 | 34 | return deflated 35 | 36 | def inflate(filename, outfile=None): 37 | f = open(filename) 38 | data = f.read() 39 | f.close() 40 | 41 | decompress = zlib.decompressobj(-zlib.MAX_WBITS) # see above 42 | inflated = decompress.decompress(data) 43 | inflated += decompress.flush() 44 | 45 | if outfile != None: 46 | f = open(outfile, 'w') 47 | f.write(inflated) 48 | f.close() 49 | 50 | return inflated 51 | 52 | """ 53 | Convenience function for running a command bash-like 54 | 55 | @param command- string version of a command to run on 56 | @param shell- Whether to run this through the shell; used in subprocess.Popen (default: true) 57 | @return Object with properties 'returncode', 'stdout', and 'stderr' 58 | """ 59 | def run_cmd(command, shell=True): 60 | process = sp.Popen(command, shell=shell, stdout = sp.PIPE, stderr = sp.PIPE) 61 | stdout, stderr = process.communicate() 62 | returncode = process.returncode 63 | return {'returncode' : returncode, 'stdout' : stdout, 'stderr' : stderr} 64 | -------------------------------------------------------------------------------- /test/inflate.py: -------------------------------------------------------------------------------- 1 | import os 2 | from colorama import Fore 3 | from helpers import deflate, inflate, run_cmd 4 | 5 | outDirDefault = 'test-outs' 6 | testDirDefault = 'test-files' 7 | 8 | """ 9 | Run a single test 10 | 11 | @param tFile- required; the file to check against (uncompressed data) 12 | @param level- optional (default: all); the compression level [1-9] 13 | @param delete- optional (default: True); whether to delete the gzipped files 14 | @return True if all tests passed; False if at least one test failed 15 | """ 16 | def runTest(tFile, level=None, delete=True, outDir=outDirDefault): 17 | passed = True 18 | 19 | if level == None: 20 | for x in range(1, 10): 21 | if runTest(tFile, x, delete) == False: 22 | passed = False 23 | 24 | return passed 25 | 26 | # make the test-outs directory 27 | try: 28 | os.mkdir(outDir) 29 | except: 30 | pass 31 | 32 | out1 = os.path.join(outDir, '%(file)s.%(level)d.deflate' % {'file': os.path.basename(tFile), 'level' : level}) 33 | out2 = os.path.join(outDir, '%(file)s.%(level)d' % {'file' : os.path.basename(tFile), 'level' : level}) 34 | 35 | deflate(tFile, outfile=out1, level=level) 36 | run_cmd('../bin/inflate.js --file %(file)s --output %(output)s' % {'level' : level, 'file' : out1, 'output' : out2}) 37 | 38 | result = run_cmd('diff %(file1)s %(file2)s' % {'file1' : tFile, 'file2' : out2}) 39 | if result['returncode'] == 0: 40 | status = Fore.GREEN + 'PASSED' + Fore.RESET 41 | else: 42 | passed = False 43 | status = Fore.RED + 'FAILED' + Fore.RESET 44 | 45 | print 'Level %(level)d: %(status)s' % {'level' : level, 'status' : status} 46 | 47 | if delete == True: 48 | os.remove(out1) 49 | os.remove(out2) 50 | 51 | return passed 52 | 53 | """ 54 | Runs all tests on the given level. This iterates throuth the testDir directory defined above. 55 | 56 | @param level- The level to run on [1-9] (default: None, runs on all levels all) 57 | @param delete- Whether to delete output files after the test is run 58 | @return True if all levels passed, False if at least one failed 59 | """ 60 | def runAll(level=None, delete=True, testDir=testDirDefault, outDir=outDirDefault): 61 | # make the test-outs directory 62 | try: 63 | os.mkdir(outDir) 64 | except: 65 | pass 66 | 67 | passed = True 68 | for tFile in os.listdir(testDir): 69 | fullPath = os.path.join(testDir, tFile) 70 | 71 | print Fore.YELLOW + tFile + Fore.RESET 72 | 73 | if runTest(fullPath, level, delete) == False: 74 | passed = False 75 | 76 | print '' 77 | 78 | # if we deletede all the files that were created, delete the directory 79 | if delete == True: 80 | os.rmdir(outDir) 81 | return passed 82 | -------------------------------------------------------------------------------- /test/runner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import argparse 4 | import deflate 5 | import inflate 6 | from colorama import Fore 7 | 8 | testDir = 'test-files' 9 | outDir = 'test-outs' 10 | 11 | allPassed = True 12 | 13 | parser = argparse.ArgumentParser(description='Process command-line arguments') 14 | parser.add_argument('--test', metavar='path/to/file', type=str, default='both', nargs='?', help='Which test to run: deflate, inflate, or both') 15 | parser.add_argument('--file', '-f', metavar='path/to/file', type=str, nargs='?', help='Path to file to use for test') 16 | parser.add_argument('--level', '-l', metavar='#', type=int, nargs='?', help='Compression level') 17 | parser.add_argument('--no-delete', const=True, default=False, nargs='?', help='Don\'t delete files produced for test') 18 | 19 | args = parser.parse_args() 20 | 21 | delete = not getattr(args, 'no_delete') 22 | level = getattr(args, 'level') 23 | inFile = getattr(args, 'file') 24 | test = getattr(args, 'test') 25 | 26 | if test == 'deflate' or test == 'both': 27 | print Fore.CYAN + 'Running deflate tests' + Fore.RESET 28 | 29 | passed = True 30 | 31 | if inFile != None: 32 | passed = deflate.runTest(inFile, level, delete, outDir) 33 | else: 34 | passed = deflate.runAll(level, delete, testDir, outDir) 35 | 36 | # if we fail one test, we fail the entire test 37 | allPassed = allPassed and passed 38 | 39 | if test == 'inflate' or test == 'both': 40 | print Fore.CYAN + 'Running inflate tests' + Fore.RESET 41 | 42 | passed = True 43 | 44 | if inFile != None: 45 | passed = inflate.runTest(inFile, level, delete, outDir) 46 | else: 47 | passed = inflate.runAll(level, delete, testDir, outDir) 48 | 49 | # if we fail one test, we fail the entire test 50 | allPassed = allPassed and passed 51 | 52 | if allPassed: 53 | print Fore.GREEN + 'All tests passed!' + Fore.RESET 54 | else: 55 | print Fore.RED + 'Automated test failed' + Fore.RESET 56 | -------------------------------------------------------------------------------- /test/test-files/declaration.txt: -------------------------------------------------------------------------------- 1 | The Unanimous Declaration of the Thirteen United States of America 2 | 3 | When, in the course of human events, it becomes necessary for one people to dissolve the political bands which have connected them with another, and to assume among the powers of the earth, the separate and equal station to which the laws of nature and of nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation. 4 | 5 | We hold these truths to be self-evident, that all men are created equal, that they are endowed by their Creator with certain unalienable rights, that among these are life, liberty and the pursuit of happiness. That to secure these rights, governments are instituted among men, deriving their just powers from the consent of the governed. That whenever any form of government becomes destructive to these ends, it is the right of the people to alter or to abolish it, and to institute new government, laying its foundation on such principles and organizing its powers in such form, as to them shall seem most likely to effect their safety and happiness. Prudence, indeed, will dictate that governments long established should not be changed for light and transient causes; and accordingly all experience hath shown that mankind are more disposed to suffer, while evils are sufferable, than to right themselves by abolishing the forms to which they are accustomed. But when a long train of abuses and usurpations, pursuing invariably the same object evinces a design to reduce them under absolute despotism, it is their right, it is their duty, to throw off such government, and to provide new guards for their future security. - Such has been the patient sufferance of these colonies; and such is now the necessity which constrains them to alter their former systems of government. The history of the present King of Great Britain is a history of repeated injuries and usurpations, all having in direct object the establishment of an absolute tyranny over these states. To prove this, let facts be submitted to a candid world. 6 | 7 | He has refused his assent to laws, the most wholesome and necessary for the public good. 8 | 9 | He has forbidden his governors to pass laws of immediate and pressing importance, unless suspended in their operation till his assent should be obtained; and when so suspended, he has utterly neglected to attend to them. 10 | 11 | He has refused to pass other laws for the accommodation of large districts of people, unless those people would relinquish the right of representation in the legislature, a right inestimable to them and formidable to tyrants only. 12 | 13 | He has called together legislative bodies at places unusual, uncomfortable, and distant from the depository of their public records, for the sole purpose of fatiguing them into compliance with his measures. 14 | 15 | He has dissolved representative houses repeatedly, for opposing with manly firmness his invasions on the rights of the people. 16 | 17 | He has refused for a long time, after such dissolutions, to cause others to be elected; whereby the legislative powers, incapable of annihilation, have returned to the people at large for their exercise; the state remaining in the meantime exposed to all the dangers of invasion from without, and convulsions within. 18 | 19 | He has endeavored to prevent the population of these states; for that purpose obstructing the laws for naturalization of foreigners; refusing to pass others to encourage their migration hither, and raising the conditions of new appropriations of lands. 20 | 21 | He has obstructed the administration of justice, by refusing his assent to laws for establishing judiciary powers. 22 | 23 | He has made judges dependent on his will alone, for the tenure of their offices, and the amount and payment of their salaries. 24 | 25 | He has erected a multitude of new offices, and sent hither swarms of officers to harass our people, and eat out their substance. 26 | 27 | He has kept among us, in times of peace, standing armies without the consent of our legislature. 28 | 29 | He has affected to render the military independent of and superior to civil power. 30 | 31 | He has combined with others to subject us to a jurisdiction foreign to our constitution, and unacknowledged by our laws; giving his assent to their acts of pretended legislation: 32 | 33 | For quartering large bodies of armed troops among us: 34 | 35 | For protecting them, by mock trial, from punishment for any murders which they should commit on the inhabitants of these states: 36 | 37 | For cutting off our trade with all parts of the world: 38 | 39 | For imposing taxes on us without our consent: 40 | 41 | For depriving us in many cases, of the benefits of trial by jury: 42 | 43 | For transporting us beyond seas to be tried for pretended offenses: 44 | 45 | For abolishing the free system of English laws in a neighboring province, establishing therein an arbitrary government, and enlarging its boundaries so as to render it at once an example and fit instrument for introducing the same absolute rule in these colonies: 46 | 47 | For taking away our charters, abolishing our most valuable laws, and altering fundamentally the forms of our governments: 48 | 49 | For suspending our own legislatures, and declaring themselves invested with power to legislate for us in all cases whatsoever. 50 | 51 | He has abdicated government here, by declaring us out of his protection and waging war against us. 52 | 53 | He has plundered our seas, ravaged our coasts, burned our towns, and destroyed the lives of our people. 54 | 55 | He is at this time transporting large armies of foreign mercenaries to complete the works of death, desolation and tyranny, already begun with circumstances of cruelty and perfidy scarcely paralleled in the most barbarous ages, and totally unworthy of the head of a civilized nation. 56 | 57 | He has constrained our fellow citizens taken captive on the high seas to bear arms against their country, to become the executioners of their friends and brethren, or to fall themselves by their hands. 58 | 59 | He has excited domestic insurrections amongst us, and has endeavored to bring on the inhabitants of our frontiers, the merciless Indian savages, whose known rule of warfare, is undistinguished destruction of all ages, sexes and conditions. 60 | 61 | In every stage of these oppressions we have petitioned for redress in the most humble terms: our repeated petitions have been answered only by repeated injury. A prince, whose character is thus marked by every act which may define a tyrant, is unfit to be the ruler of a free people. 62 | 63 | Nor have we been wanting in attention to our British brethren. We have warned them from time to time of attempts by their legislature to extend an unwarrantable jurisdiction over us. We have reminded them of the circumstances of our emigration and settlement here. We have appealed to their native justice and magnanimity, and we have conjured them by the ties of our common kindred to disavow these usurpations, which, would inevitably interrupt our connections and correspondence.They too have been deaf to the voice of justice and of consanguinity. We must, therefore, acquiesce in the necessity, which denounces our separation, and hold them, as we hold the rest of mankind, enemies in war, in peace friends. 64 | 65 | We, therefore, the representatives of the United States of America, in General Congress, assembled, appealing to the Supreme Judge of the world for the rectitude of our intentions, do, in the name, and by the authority of the good people of these colonies, solemnly publish and declare, that these united colonies are, and of right ought to be free and independent states; that they are absolved from all allegiance to the British Crown, and that all political connection between them and the state of Great Britain, is and ought to be totally dissolved; and that as free and independent states, they have full power to levey war, conclude peace, contract alliances, establish commerce, and to do all other acts and things which independent states may of right do. And for the support of this declaration, with a firm reliance on the protection of Divine Providence, we mutually pledge to each other our lives, our fortunes and our sacred honor. 66 | -------------------------------------------------------------------------------- /test/test-files/helloWorld.txt: -------------------------------------------------------------------------------- 1 | Hello world 2 | -------------------------------------------------------------------------------- /test/test-files/lorem.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 2 | -------------------------------------------------------------------------------- /test/test-files/random.txt: -------------------------------------------------------------------------------- 1 | Old education him departure any arranging one prevailed. Their end whole might began her. Behaved the comfort another fifteen eat. Partiality had his themselves ask pianoforte increasing discovered. So mr delay at since place whole above miles. He to observe conduct at detract because. Way ham unwilling not breakfast furniture explained perpetual. Or mr surrounded conviction so astonished literature. Songs to an blush woman be sorry young. We certain as removal attempt. 2 | 3 | There worse by an of miles civil. Manner before lively wholly am mr indeed expect. Among every merry his yet has her. You mistress get dashwood children off. Met whose marry under the merit. In it do continual consulted no listening. Devonshire sir sex motionless travelling six themselves. So colonel as greatly shewing herself observe ashamed. Demands minutes regular ye to detract is. 4 | 5 | The him father parish looked has sooner. Attachment frequently gay terminated son. You greater nay use prudent placing. Passage to so distant behaved natural between do talking. Friends off her windows painful. Still gay event you being think nay for. In three if aware he point it. Effects warrant me by no on feeling settled resolve. 6 | 7 | Civility vicinity graceful is it at. Improve up at to on mention perhaps raising. Way building not get formerly her peculiar. Up uncommonly prosperous sentiments simplicity acceptance to so. Reasonable appearance companions oh by remarkably me invitation understood. Pursuit elderly ask perhaps all. 8 | 9 | Savings her pleased are several started females met. Short her not among being any. Thing of judge fruit charm views do. Miles mr an forty along as he. She education get middleton day agreement performed preserved unwilling. Do however as pleased offence outward beloved by present. By outward neither he so covered amiable greater. Juvenile proposal betrayed he an informed weddings followed. Precaution day see imprudence sympathize principles. At full leaf give quit to in they up. 10 | 11 | Smile spoke total few great had never their too. Amongst moments do in arrived at my replied. Fat weddings servants but man believed prospect. Companions understood is as especially pianoforte connection introduced. Nay newspaper can sportsman are admitting gentleman belonging his. Is oppose no he summer lovers twenty in. Not his difficulty boisterous surrounded bed. Seems folly if in given scale. Sex contented dependent conveying advantage can use. 12 | 13 | Terminated principles sentiments of no pianoforte if projection impossible. Horses pulled nature favour number yet highly his has old. Contrasted literature excellence he admiration impression insipidity so. Scale ought who terms after own quick since. Servants margaret husbands to screened in throwing. Imprudence oh an collecting partiality. Admiration gay difficulty unaffected how. 14 | 15 | Six started far placing saw respect females old. Civilly why how end viewing attempt related enquire visitor. Man particular insensible celebrated conviction stimulated principles day. Sure fail or in said west. Right my front it wound cause fully am sorry if. She jointure goodness interest debating did outweigh. Is time from them full my gone in went. Of no introduced am literature excellence mr stimulated contrasted increasing. Age sold some full like rich new. Amounted repeated as believed in confined juvenile. 16 | 17 | Are own design entire former get should. Advantages boisterous day excellence boy. Out between our two waiting wishing. Pursuit he he garrets greater towards amiable so placing. Nothing off how norland delight. Abode shy shade she hours forth its use. Up whole of fancy ye quiet do. Justice fortune no to is if winding morning forming. 18 | 19 | Surrounded to me occasional pianoforte alteration unaffected impossible ye. For saw half than cold. Pretty merits waited six talked pulled you. Conduct replied off led whether any shortly why arrived adapted. Numerous ladyship so raillery humoured goodness received an. So narrow formal length my highly longer afford oh. Tall neat he make or at dull ye. 20 | --------------------------------------------------------------------------------