- commit
- 7434ff79bd7a5e08378771867d1b230b79bbfe68
- parent
- e5abb49dcced9af631279330025775c317b8d24b
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2024-05-29 13:35
use native gzip compression
Diffstat
| M | static/gzip.js | 24 | ++++++++---------------- |
| D | static/lzw.js | 128 | ------------------------------------------------------------ |
| M | static/main.js | 22 | +++++++++++----------- |
3 files changed, 19 insertions, 155 deletions
diff --git a/static/gzip.js b/static/gzip.js
@@ -1,27 +1,19 @@1 -1 export async function compress(bytes) {2 -1 var compressionStream = new CompressionStream('gzip');3 -1 var writableStream = new WritableStream();-1 1 async function applyStream(bytes, stream) { 4 2 var readableStream = new ReadableStream({ 5 3 start(controller) { 6 4 controller.enqueue(bytes); 7 5 controller.close(); 8 6 } 9 7 });10 -1 await readableStream.pipeThrough(compressionStream).pipeTo(writableStream);11 -1 var result = await new Response(writableStream).arrayBuffer();-1 8 var resultStream = await readableStream.pipeThrough(stream); -1 9 var result = await new Response(resultStream).arrayBuffer(); 12 10 return new Uint8Array(result); 13 11 } 14 12 -1 13 export async function compress(bytes) { -1 14 return await applyStream(bytes, new CompressionStream('gzip')); -1 15 } -1 16 15 17 export async function decompress(bytes) {16 -1 var decompressionStream = new DecompressionStream('gzip');17 -1 var writableStream = new WritableStream();18 -1 var readableStream = new ReadableStream({19 -1 start(controller) {20 -1 controller.enqueue(bytes);21 -1 controller.close();22 -1 }23 -1 });24 -1 await readableStream.pipeThrough(decompressionStream).pipeTo(writableStream);25 -1 var result = await new Response(writableStream).arrayBuffer();26 -1 return new Uint8Array(result);-1 18 return await applyStream(bytes, new DecompressionStream('gzip')); 27 19 }
diff --git a/static/lzw.js b/static/lzw.js
@@ -1,128 +0,0 @@1 -1 class Buffer {2 -1 constructor(bytes) {3 -1 this.bytes = bytes;4 -1 this.i_byte = 0;5 -1 this.i_bit = 0;6 -1 }7 -18 -1 next() {9 -1 if (this.i_bit < 7) {10 -1 this.i_bit += 1;11 -1 } else {12 -1 this.i_byte += 1;13 -1 this.i_bit = 0;14 -1 }15 -1 }16 -117 -1 read(size) {18 -1 var bits = 0;19 -1 for (let i = 0; i < size; i++) {20 -1 if (this.bytes.length <= this.i_byte) {21 -1 throw new RangeError();22 -1 }23 -1 bits <<= 1;24 -1 if (this.bytes[this.i_byte] & (1 << (7 - this.i_bit))) {25 -1 bits |= 1;26 -1 }27 -1 this.next();28 -1 }29 -1 return bits;30 -1 }31 -132 -1 write(bits, size) {33 -1 for (let i = 0; i < size; i++) {34 -1 if (this.bytes.length <= this.i_byte) {35 -1 this.bytes.push(0);36 -1 }37 -1 if (bits & (1 << (size - i - 1))) {38 -1 this.bytes[this.i_byte] |= 1 << (7 - this.i_bit);39 -1 }40 -1 this.next();41 -1 }42 -1 }43 -1 }44 -145 -1 var sIndexOf = function(dict, value) {46 -1 var s = value.toString();47 -1 for (let i = 0; i < dict.length; i++) {48 -1 if (s === dict[i].toString()) {49 -1 return i;50 -1 }51 -1 }52 -1 return -1;53 -1 };54 -155 -1 export var compress = function(bytes) {56 -1 var result = [];57 -1 var buf = new Buffer(result);58 -159 -1 var field_size = 9;60 -1 var dict = [];61 -1 dict.push('end');62 -1 for (let i = 0; i < 256; i++) {63 -1 dict.push([i]);64 -1 }65 -166 -1 var win = [];67 -1 var i = 0;68 -1 while (i < bytes.length) {69 -1 var tmp = [...win, bytes[i]];70 -1 if (sIndexOf(dict, tmp) === -1) {71 -1 buf.write(sIndexOf(dict, win), field_size);72 -1 win = [];73 -1 if (dict.length >> field_size) {74 -1 field_size += 1;75 -1 }76 -1 dict.push(tmp);77 -1 } else {78 -1 win = tmp;79 -1 i += 1;80 -1 }81 -1 }82 -1 buf.write(sIndexOf(dict, win), field_size);83 -1 buf.write(sIndexOf(dict, 'end'), field_size);84 -185 -1 return new Uint8Array(result);86 -1 };87 -188 -1 export var decompress = function(bytes) {89 -1 var result = [];90 -1 var buf = new Buffer(bytes);91 -1 var prev = null;92 -193 -1 var field_size = 9;94 -1 var dict = [];95 -1 dict.push('end');96 -1 for (let i = 0; i < 256; i++) {97 -1 dict.push([i]);98 -1 }99 -1100 -1 while (true) {101 -1 var index = buf.read(field_size);102 -1 var value = dict[index];103 -1 if (dict.length >> field_size) {104 -1 field_size += 1;105 -1 }106 -1107 -1 if (value === 'end') {108 -1 break;109 -1 }110 -1111 -1 // push to dict with one cycle delay because we need the first112 -1 // item from the next entry.113 -1 //114 -1 // If value is undefined, the next entry is the not-yet-pushed one.115 -1 // Fortunately, we know that its first item is the same as in the entry116 -1 // before that.117 -1 if (!value) {118 -1 value = [...prev, prev[0]];119 -1 }120 -1 result = result.concat(value);121 -1 if (prev) {122 -1 dict.push([...prev, value[0]]);123 -1 }124 -1 prev = value;125 -1 }126 -1127 -1 return new Uint8Array(result);128 -1 };
diff --git a/static/main.js b/static/main.js
@@ -1,26 +1,26 @@ 1 1 import * as base64 from './base64.js';2 -1 import * as lzw from './lzw.js';-1 2 import * as gzip from './gzip.js'; 3 34 -1 var encode = function(text) {-1 4 var encode = async function(text) { 5 5 var encoder = new TextEncoder(); 6 6 var bytes = encoder.encode(text);7 -1 return base64.encode(lzw.compress(bytes));-1 7 return base64.encode(await gzip.compress(bytes)); 8 8 }; 9 910 -1 var decode = function(string) {-1 10 var decode = async function(string) { 11 11 var decoder = new TextDecoder();12 -1 var bytes = lzw.decompress(base64.decode(string));-1 12 var bytes = await gzip.decompress(base64.decode(string)); 13 13 return decoder.decode(bytes); 14 14 }; 15 15 16 16 var textarea = document.querySelector('textarea'); 17 1718 -1 try {19 -1 textarea.value = decode(location.hash.substr(1));20 -1 } catch (e) {21 -1 console.exception(e);22 -1 }-1 18 decode(location.hash.substr(1)).then(text => { -1 19 textarea.value = text; -1 20 }); 23 21 24 22 textarea.addEventListener('input', event => {25 -1 history.replaceState(null, '', '#' + encode(textarea.value));-1 23 encode(textarea.value).then(data => { -1 24 history.replaceState(null, '', `#${data}`); -1 25 }); 26 26 });