mj-v1.14.3
domi41 3 years ago
parent 79e87aa5de
commit e7eb1acca9

275
package-lock.json generated

@ -996,11 +996,12 @@
} }
}, },
"@npmcli/move-file": { "@npmcli/move-file": {
"version": "1.0.1", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.0.1.tgz", "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz",
"integrity": "sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw==", "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==",
"requires": { "requires": {
"mkdirp": "^1.0.4" "mkdirp": "^1.0.4",
"rimraf": "^3.0.2"
} }
}, },
"@primer/octicons": { "@primer/octicons": {
@ -1606,9 +1607,9 @@
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
}, },
"cacache": { "cacache": {
"version": "15.0.5", "version": "15.2.0",
"resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.2.0.tgz",
"integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", "integrity": "sha512-uKoJSHmnrqXgthDFx/IU6ED/5xd+NNGe+Bb+kLZy7Ku4P+BaiWEUflAKPZ7eAzsYGcsAGASJZsybXp+quEcHTw==",
"requires": { "requires": {
"@npmcli/move-file": "^1.0.1", "@npmcli/move-file": "^1.0.1",
"chownr": "^2.0.0", "chownr": "^2.0.0",
@ -1624,7 +1625,7 @@
"p-map": "^4.0.0", "p-map": "^4.0.0",
"promise-inflight": "^1.0.1", "promise-inflight": "^1.0.1",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"ssri": "^8.0.0", "ssri": "^8.0.1",
"tar": "^6.0.2", "tar": "^6.0.2",
"unique-filename": "^1.1.1" "unique-filename": "^1.1.1"
} }
@ -1704,9 +1705,9 @@
} }
}, },
"caniuse-lite": { "caniuse-lite": {
"version": "1.0.30001170", "version": "1.0.30001239",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001170.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001239.tgz",
"integrity": "sha512-Dd4d/+0tsK0UNLrZs3CvNukqalnVTRrxb5mcQm8rHL49t7V5ZaTygwXkrq+FB+dVDf++4ri8eJnFEJAB8332PA==" "integrity": "sha512-cyBkXJDMeI4wthy8xJ2FvDU6+0dtcZSJW3voUF8+e9f1bBeuvyZfc3PNbkOETyhbR+dGCPzn9E7MA3iwzusOhQ=="
}, },
"chalk": { "chalk": {
"version": "2.4.2", "version": "2.4.2",
@ -1849,9 +1850,9 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
}, },
"color-string": { "color-string": {
"version": "1.5.4", "version": "1.5.5",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz",
"integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==", "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==",
"requires": { "requires": {
"color-name": "^1.0.0", "color-name": "^1.0.0",
"simple-swizzle": "^0.2.2" "simple-swizzle": "^0.2.2"
@ -1969,9 +1970,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -2043,9 +2044,9 @@
} }
}, },
"css-minimizer-webpack-plugin": { "css-minimizer-webpack-plugin": {
"version": "1.1.5", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-1.1.5.tgz", "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-1.2.0.tgz",
"integrity": "sha512-mXgaoFjNpIudZfxD49N1aPtLxfXGJt+BVPVjQ+H66I48b5n4wJtFpYfffVr7izK8W6fD01J7K0kUcP6HGjw90w==", "integrity": "sha512-XU4+PXw7QKAlRGU+fB386YiczAAPtk0kVsB/Qf2nX8GJaOXgTsk/PST8YBExeoD299wheG//MCCKlCD5fykb7Q==",
"requires": { "requires": {
"cacache": "^15.0.5", "cacache": "^15.0.5",
"cssnano": "^4.1.10", "cssnano": "^4.1.10",
@ -2126,20 +2127,20 @@
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="
}, },
"cssnano": { "cssnano": {
"version": "4.1.10", "version": "4.1.11",
"resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.11.tgz",
"integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", "integrity": "sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g==",
"requires": { "requires": {
"cosmiconfig": "^5.0.0", "cosmiconfig": "^5.0.0",
"cssnano-preset-default": "^4.0.7", "cssnano-preset-default": "^4.0.8",
"is-resolvable": "^1.0.0", "is-resolvable": "^1.0.0",
"postcss": "^7.0.0" "postcss": "^7.0.0"
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -2162,9 +2163,9 @@
} }
}, },
"cssnano-preset-default": { "cssnano-preset-default": {
"version": "4.0.7", "version": "4.0.8",
"resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz",
"integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", "integrity": "sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ==",
"requires": { "requires": {
"css-declaration-sorter": "^4.0.1", "css-declaration-sorter": "^4.0.1",
"cssnano-util-raw-cache": "^4.0.1", "cssnano-util-raw-cache": "^4.0.1",
@ -2194,14 +2195,14 @@
"postcss-ordered-values": "^4.1.2", "postcss-ordered-values": "^4.1.2",
"postcss-reduce-initial": "^4.0.3", "postcss-reduce-initial": "^4.0.3",
"postcss-reduce-transforms": "^4.0.2", "postcss-reduce-transforms": "^4.0.2",
"postcss-svgo": "^4.0.2", "postcss-svgo": "^4.0.3",
"postcss-unique-selectors": "^4.0.1" "postcss-unique-selectors": "^4.0.1"
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -2242,9 +2243,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -3777,11 +3778,6 @@
"resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz",
"integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=" "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg="
}, },
"html-comment-regex": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz",
"integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ=="
},
"html-minifier": { "html-minifier": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz", "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz",
@ -4120,14 +4116,6 @@
"integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
"dev": true "dev": true
}, },
"is-svg": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz",
"integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==",
"requires": {
"html-comment-regex": "^1.1.0"
}
},
"is-symbol": { "is-symbol": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
@ -5398,9 +5386,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -5435,9 +5423,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -5474,9 +5462,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -5512,9 +5500,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -5545,9 +5533,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -5578,9 +5566,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -5611,9 +5599,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -5730,9 +5718,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -5773,9 +5761,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -5817,9 +5805,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -5858,9 +5846,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -5901,9 +5889,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -5942,9 +5930,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -6016,9 +6004,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -6051,9 +6039,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -6092,9 +6080,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -6133,9 +6121,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -6173,9 +6161,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -6213,9 +6201,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -6253,9 +6241,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -6294,9 +6282,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -6333,9 +6321,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -6373,9 +6361,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -6414,9 +6402,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -6450,9 +6438,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -6609,20 +6597,19 @@
} }
}, },
"postcss-svgo": { "postcss-svgo": {
"version": "4.0.2", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.3.tgz",
"integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", "integrity": "sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw==",
"requires": { "requires": {
"is-svg": "^3.0.0",
"postcss": "^7.0.0", "postcss": "^7.0.0",
"postcss-value-parser": "^3.0.0", "postcss-value-parser": "^3.0.0",
"svgo": "^1.0.0" "svgo": "^1.0.0"
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -6666,9 +6653,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -7314,9 +7301,9 @@
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
}, },
"ssri": { "ssri": {
"version": "8.0.0", "version": "8.0.1",
"resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
"integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==", "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
"requires": { "requires": {
"minipass": "^3.1.1" "minipass": "^3.1.1"
} }
@ -7422,9 +7409,9 @@
}, },
"dependencies": { "dependencies": {
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@ -7833,9 +7820,9 @@
"integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==" "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw=="
}, },
"tar": { "tar": {
"version": "6.0.5", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.0.5.tgz", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
"integrity": "sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==", "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==",
"requires": { "requires": {
"chownr": "^2.0.0", "chownr": "^2.0.0",
"fs-minipass": "^2.0.0", "fs-minipass": "^2.0.0",

@ -121,7 +121,7 @@ func encodeMlen(length uint, bits *uint64, numbits *uint, nibblesbits *uint64) {
*bits = uint64(length) - 1 *bits = uint64(length) - 1
} }
func storeCommandExtra(cmd *command, bw *bitWriter) { func storeCommandExtra(cmd *command, storage_ix *uint, storage []byte) {
var copylen_code uint32 = commandCopyLenCode(cmd) var copylen_code uint32 = commandCopyLenCode(cmd)
var inscode uint16 = getInsertLengthCode(uint(cmd.insert_len_)) var inscode uint16 = getInsertLengthCode(uint(cmd.insert_len_))
var copycode uint16 = getCopyLengthCode(uint(copylen_code)) var copycode uint16 = getCopyLengthCode(uint(copylen_code))
@ -129,7 +129,7 @@ func storeCommandExtra(cmd *command, bw *bitWriter) {
var insextraval uint64 = uint64(cmd.insert_len_) - uint64(getInsertBase(inscode)) var insextraval uint64 = uint64(cmd.insert_len_) - uint64(getInsertBase(inscode))
var copyextraval uint64 = uint64(copylen_code) - uint64(getCopyBase(copycode)) var copyextraval uint64 = uint64(copylen_code) - uint64(getCopyBase(copycode))
var bits uint64 = copyextraval<<insnumextra | insextraval var bits uint64 = copyextraval<<insnumextra | insextraval
bw.writeBits(uint(insnumextra+getCopyExtra(copycode)), bits) writeBits(uint(insnumextra+getCopyExtra(copycode)), bits, storage_ix, storage)
} }
/* Data structure that stores almost everything that is needed to encode each /* Data structure that stores almost everything that is needed to encode each
@ -143,21 +143,21 @@ type blockSplitCode struct {
} }
/* Stores a number between 0 and 255. */ /* Stores a number between 0 and 255. */
func storeVarLenUint8(n uint, bw *bitWriter) { func storeVarLenUint8(n uint, storage_ix *uint, storage []byte) {
if n == 0 { if n == 0 {
bw.writeBits(1, 0) writeBits(1, 0, storage_ix, storage)
} else { } else {
var nbits uint = uint(log2FloorNonZero(n)) var nbits uint = uint(log2FloorNonZero(n))
bw.writeBits(1, 1) writeBits(1, 1, storage_ix, storage)
bw.writeBits(3, uint64(nbits)) writeBits(3, uint64(nbits), storage_ix, storage)
bw.writeBits(nbits, uint64(n)-(uint64(uint(1))<<nbits)) writeBits(nbits, uint64(n)-(uint64(uint(1))<<nbits), storage_ix, storage)
} }
} }
/* Stores the compressed meta-block header. /* Stores the compressed meta-block header.
REQUIRES: length > 0 REQUIRES: length > 0
REQUIRES: length <= (1 << 24) */ REQUIRES: length <= (1 << 24) */
func storeCompressedMetaBlockHeader(is_final_block bool, length uint, bw *bitWriter) { func storeCompressedMetaBlockHeader(is_final_block bool, length uint, storage_ix *uint, storage []byte) {
var lenbits uint64 var lenbits uint64
var nlenbits uint var nlenbits uint
var nibblesbits uint64 var nibblesbits uint64
@ -169,41 +169,41 @@ func storeCompressedMetaBlockHeader(is_final_block bool, length uint, bw *bitWri
} }
/* Write ISLAST bit. */ /* Write ISLAST bit. */
bw.writeBits(1, is_final) writeBits(1, is_final, storage_ix, storage)
/* Write ISEMPTY bit. */ /* Write ISEMPTY bit. */
if is_final_block { if is_final_block {
bw.writeBits(1, 0) writeBits(1, 0, storage_ix, storage)
} }
encodeMlen(length, &lenbits, &nlenbits, &nibblesbits) encodeMlen(length, &lenbits, &nlenbits, &nibblesbits)
bw.writeBits(2, nibblesbits) writeBits(2, nibblesbits, storage_ix, storage)
bw.writeBits(nlenbits, lenbits) writeBits(nlenbits, lenbits, storage_ix, storage)
if !is_final_block { if !is_final_block {
/* Write ISUNCOMPRESSED bit. */ /* Write ISUNCOMPRESSED bit. */
bw.writeBits(1, 0) writeBits(1, 0, storage_ix, storage)
} }
} }
/* Stores the uncompressed meta-block header. /* Stores the uncompressed meta-block header.
REQUIRES: length > 0 REQUIRES: length > 0
REQUIRES: length <= (1 << 24) */ REQUIRES: length <= (1 << 24) */
func storeUncompressedMetaBlockHeader(length uint, bw *bitWriter) { func storeUncompressedMetaBlockHeader(length uint, storage_ix *uint, storage []byte) {
var lenbits uint64 var lenbits uint64
var nlenbits uint var nlenbits uint
var nibblesbits uint64 var nibblesbits uint64
/* Write ISLAST bit. /* Write ISLAST bit.
Uncompressed block cannot be the last one, so set to 0. */ Uncompressed block cannot be the last one, so set to 0. */
bw.writeBits(1, 0) writeBits(1, 0, storage_ix, storage)
encodeMlen(length, &lenbits, &nlenbits, &nibblesbits) encodeMlen(length, &lenbits, &nlenbits, &nibblesbits)
bw.writeBits(2, nibblesbits) writeBits(2, nibblesbits, storage_ix, storage)
bw.writeBits(nlenbits, lenbits) writeBits(nlenbits, lenbits, storage_ix, storage)
/* Write ISUNCOMPRESSED bit. */ /* Write ISUNCOMPRESSED bit. */
bw.writeBits(1, 1) writeBits(1, 1, storage_ix, storage)
} }
var storeHuffmanTreeOfHuffmanTreeToBitMask_kStorageOrder = [codeLengthCodes]byte{1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15} var storeHuffmanTreeOfHuffmanTreeToBitMask_kStorageOrder = [codeLengthCodes]byte{1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15}
@ -211,7 +211,7 @@ var storeHuffmanTreeOfHuffmanTreeToBitMask_kStorageOrder = [codeLengthCodes]byte
var storeHuffmanTreeOfHuffmanTreeToBitMask_kHuffmanBitLengthHuffmanCodeSymbols = [6]byte{0, 7, 3, 2, 1, 15} var storeHuffmanTreeOfHuffmanTreeToBitMask_kHuffmanBitLengthHuffmanCodeSymbols = [6]byte{0, 7, 3, 2, 1, 15}
var storeHuffmanTreeOfHuffmanTreeToBitMask_kHuffmanBitLengthHuffmanCodeBitLengths = [6]byte{2, 4, 3, 2, 2, 4} var storeHuffmanTreeOfHuffmanTreeToBitMask_kHuffmanBitLengthHuffmanCodeBitLengths = [6]byte{2, 4, 3, 2, 2, 4}
func storeHuffmanTreeOfHuffmanTreeToBitMask(num_codes int, code_length_bitdepth []byte, bw *bitWriter) { func storeHuffmanTreeOfHuffmanTreeToBitMask(num_codes int, code_length_bitdepth []byte, storage_ix *uint, storage []byte) {
var skip_some uint = 0 var skip_some uint = 0
var codes_to_store uint = codeLengthCodes var codes_to_store uint = codeLengthCodes
/* The bit lengths of the Huffman code over the code length alphabet /* The bit lengths of the Huffman code over the code length alphabet
@ -241,38 +241,38 @@ func storeHuffmanTreeOfHuffmanTreeToBitMask(num_codes int, code_length_bitdepth
} }
} }
bw.writeBits(2, uint64(skip_some)) writeBits(2, uint64(skip_some), storage_ix, storage)
{ {
var i uint var i uint
for i = skip_some; i < codes_to_store; i++ { for i = skip_some; i < codes_to_store; i++ {
var l uint = uint(code_length_bitdepth[storeHuffmanTreeOfHuffmanTreeToBitMask_kStorageOrder[i]]) var l uint = uint(code_length_bitdepth[storeHuffmanTreeOfHuffmanTreeToBitMask_kStorageOrder[i]])
bw.writeBits(uint(storeHuffmanTreeOfHuffmanTreeToBitMask_kHuffmanBitLengthHuffmanCodeBitLengths[l]), uint64(storeHuffmanTreeOfHuffmanTreeToBitMask_kHuffmanBitLengthHuffmanCodeSymbols[l])) writeBits(uint(storeHuffmanTreeOfHuffmanTreeToBitMask_kHuffmanBitLengthHuffmanCodeBitLengths[l]), uint64(storeHuffmanTreeOfHuffmanTreeToBitMask_kHuffmanBitLengthHuffmanCodeSymbols[l]), storage_ix, storage)
} }
} }
} }
func storeHuffmanTreeToBitMask(huffman_tree_size uint, huffman_tree []byte, huffman_tree_extra_bits []byte, code_length_bitdepth []byte, code_length_bitdepth_symbols []uint16, bw *bitWriter) { func storeHuffmanTreeToBitMask(huffman_tree_size uint, huffman_tree []byte, huffman_tree_extra_bits []byte, code_length_bitdepth []byte, code_length_bitdepth_symbols []uint16, storage_ix *uint, storage []byte) {
var i uint var i uint
for i = 0; i < huffman_tree_size; i++ { for i = 0; i < huffman_tree_size; i++ {
var ix uint = uint(huffman_tree[i]) var ix uint = uint(huffman_tree[i])
bw.writeBits(uint(code_length_bitdepth[ix]), uint64(code_length_bitdepth_symbols[ix])) writeBits(uint(code_length_bitdepth[ix]), uint64(code_length_bitdepth_symbols[ix]), storage_ix, storage)
/* Extra bits */ /* Extra bits */
switch ix { switch ix {
case repeatPreviousCodeLength: case repeatPreviousCodeLength:
bw.writeBits(2, uint64(huffman_tree_extra_bits[i])) writeBits(2, uint64(huffman_tree_extra_bits[i]), storage_ix, storage)
case repeatZeroCodeLength: case repeatZeroCodeLength:
bw.writeBits(3, uint64(huffman_tree_extra_bits[i])) writeBits(3, uint64(huffman_tree_extra_bits[i]), storage_ix, storage)
} }
} }
} }
func storeSimpleHuffmanTree(depths []byte, symbols []uint, num_symbols uint, max_bits uint, bw *bitWriter) { func storeSimpleHuffmanTree(depths []byte, symbols []uint, num_symbols uint, max_bits uint, storage_ix *uint, storage []byte) {
/* value of 1 indicates a simple Huffman code */ /* value of 1 indicates a simple Huffman code */
bw.writeBits(2, 1) writeBits(2, 1, storage_ix, storage)
bw.writeBits(2, uint64(num_symbols)-1) /* NSYM - 1 */ writeBits(2, uint64(num_symbols)-1, storage_ix, storage) /* NSYM - 1 */
{ {
/* Sort */ /* Sort */
var i uint var i uint
@ -289,17 +289,17 @@ func storeSimpleHuffmanTree(depths []byte, symbols []uint, num_symbols uint, max
} }
if num_symbols == 2 { if num_symbols == 2 {
bw.writeBits(max_bits, uint64(symbols[0])) writeBits(max_bits, uint64(symbols[0]), storage_ix, storage)
bw.writeBits(max_bits, uint64(symbols[1])) writeBits(max_bits, uint64(symbols[1]), storage_ix, storage)
} else if num_symbols == 3 { } else if num_symbols == 3 {
bw.writeBits(max_bits, uint64(symbols[0])) writeBits(max_bits, uint64(symbols[0]), storage_ix, storage)
bw.writeBits(max_bits, uint64(symbols[1])) writeBits(max_bits, uint64(symbols[1]), storage_ix, storage)
bw.writeBits(max_bits, uint64(symbols[2])) writeBits(max_bits, uint64(symbols[2]), storage_ix, storage)
} else { } else {
bw.writeBits(max_bits, uint64(symbols[0])) writeBits(max_bits, uint64(symbols[0]), storage_ix, storage)
bw.writeBits(max_bits, uint64(symbols[1])) writeBits(max_bits, uint64(symbols[1]), storage_ix, storage)
bw.writeBits(max_bits, uint64(symbols[2])) writeBits(max_bits, uint64(symbols[2]), storage_ix, storage)
bw.writeBits(max_bits, uint64(symbols[3])) writeBits(max_bits, uint64(symbols[3]), storage_ix, storage)
/* tree-select */ /* tree-select */
var tmp int var tmp int
@ -308,13 +308,13 @@ func storeSimpleHuffmanTree(depths []byte, symbols []uint, num_symbols uint, max
} else { } else {
tmp = 0 tmp = 0
} }
bw.writeBits(1, uint64(tmp)) writeBits(1, uint64(tmp), storage_ix, storage)
} }
} }
/* num = alphabet size /* num = alphabet size
depths = symbol depths */ depths = symbol depths */
func storeHuffmanTree(depths []byte, num uint, tree []huffmanTree, bw *bitWriter) { func storeHuffmanTree(depths []byte, num uint, tree []huffmanTree, storage_ix *uint, storage []byte) {
var huffman_tree [numCommandSymbols]byte var huffman_tree [numCommandSymbols]byte
var huffman_tree_extra_bits [numCommandSymbols]byte var huffman_tree_extra_bits [numCommandSymbols]byte
var huffman_tree_size uint = 0 var huffman_tree_size uint = 0
@ -357,19 +357,19 @@ func storeHuffmanTree(depths []byte, num uint, tree []huffmanTree, bw *bitWriter
convertBitDepthsToSymbols(code_length_bitdepth[:], codeLengthCodes, code_length_bitdepth_symbols[:]) convertBitDepthsToSymbols(code_length_bitdepth[:], codeLengthCodes, code_length_bitdepth_symbols[:])
/* Now, we have all the data, let's start storing it */ /* Now, we have all the data, let's start storing it */
storeHuffmanTreeOfHuffmanTreeToBitMask(num_codes, code_length_bitdepth[:], bw) storeHuffmanTreeOfHuffmanTreeToBitMask(num_codes, code_length_bitdepth[:], storage_ix, storage)
if num_codes == 1 { if num_codes == 1 {
code_length_bitdepth[code] = 0 code_length_bitdepth[code] = 0
} }
/* Store the real Huffman tree now. */ /* Store the real Huffman tree now. */
storeHuffmanTreeToBitMask(huffman_tree_size, huffman_tree[:], huffman_tree_extra_bits[:], code_length_bitdepth[:], code_length_bitdepth_symbols[:], bw) storeHuffmanTreeToBitMask(huffman_tree_size, huffman_tree[:], huffman_tree_extra_bits[:], code_length_bitdepth[:], code_length_bitdepth_symbols[:], storage_ix, storage)
} }
/* Builds a Huffman tree from histogram[0:length] into depth[0:length] and /* Builds a Huffman tree from histogram[0:length] into depth[0:length] and
bits[0:length] and stores the encoded tree to the bit stream. */ bits[0:length] and stores the encoded tree to the bit stream. */
func buildAndStoreHuffmanTree(histogram []uint32, histogram_length uint, alphabet_size uint, tree []huffmanTree, depth []byte, bits []uint16, bw *bitWriter) { func buildAndStoreHuffmanTree(histogram []uint32, histogram_length uint, alphabet_size uint, tree []huffmanTree, depth []byte, bits []uint16, storage_ix *uint, storage []byte) {
var count uint = 0 var count uint = 0
var s4 = [4]uint{0} var s4 = [4]uint{0}
var i uint var i uint
@ -394,8 +394,8 @@ func buildAndStoreHuffmanTree(histogram []uint32, histogram_length uint, alphabe
} }
if count <= 1 { if count <= 1 {
bw.writeBits(4, 1) writeBits(4, 1, storage_ix, storage)
bw.writeBits(max_bits, uint64(s4[0])) writeBits(max_bits, uint64(s4[0]), storage_ix, storage)
depth[s4[0]] = 0 depth[s4[0]] = 0
bits[s4[0]] = 0 bits[s4[0]] = 0
return return
@ -408,9 +408,9 @@ func buildAndStoreHuffmanTree(histogram []uint32, histogram_length uint, alphabe
convertBitDepthsToSymbols(depth, histogram_length, bits) convertBitDepthsToSymbols(depth, histogram_length, bits)
if count <= 4 { if count <= 4 {
storeSimpleHuffmanTree(depth, s4[:], count, max_bits, bw) storeSimpleHuffmanTree(depth, s4[:], count, max_bits, storage_ix, storage)
} else { } else {
storeHuffmanTree(depth, histogram_length, tree, bw) storeHuffmanTree(depth, histogram_length, tree, storage_ix, storage)
} }
} }
@ -420,7 +420,7 @@ func sortHuffmanTree1(v0 huffmanTree, v1 huffmanTree) bool {
var huffmanTreePool sync.Pool var huffmanTreePool sync.Pool
func buildAndStoreHuffmanTreeFast(histogram []uint32, histogram_total uint, max_bits uint, depth []byte, bits []uint16, bw *bitWriter) { func buildAndStoreHuffmanTreeFast(histogram []uint32, histogram_total uint, max_bits uint, depth []byte, bits []uint16, storage_ix *uint, storage []byte) {
var count uint = 0 var count uint = 0
var symbols = [4]uint{0} var symbols = [4]uint{0}
var length uint = 0 var length uint = 0
@ -439,8 +439,8 @@ func buildAndStoreHuffmanTreeFast(histogram []uint32, histogram_total uint, max_
} }
if count <= 1 { if count <= 1 {
bw.writeBits(4, 1) writeBits(4, 1, storage_ix, storage)
bw.writeBits(max_bits, uint64(symbols[0])) writeBits(max_bits, uint64(symbols[0]), storage_ix, storage)
depth[symbols[0]] = 0 depth[symbols[0]] = 0
bits[symbols[0]] = 0 bits[symbols[0]] = 0
return return
@ -544,9 +544,9 @@ func buildAndStoreHuffmanTreeFast(histogram []uint32, histogram_total uint, max_
var i uint var i uint
/* value of 1 indicates a simple Huffman code */ /* value of 1 indicates a simple Huffman code */
bw.writeBits(2, 1) writeBits(2, 1, storage_ix, storage)
bw.writeBits(2, uint64(count)-1) /* NSYM - 1 */ writeBits(2, uint64(count)-1, storage_ix, storage) /* NSYM - 1 */
/* Sort */ /* Sort */
for i = 0; i < count; i++ { for i = 0; i < count; i++ {
@ -561,27 +561,33 @@ func buildAndStoreHuffmanTreeFast(histogram []uint32, histogram_total uint, max_
} }
if count == 2 { if count == 2 {
bw.writeBits(max_bits, uint64(symbols[0])) writeBits(max_bits, uint64(symbols[0]), storage_ix, storage)
bw.writeBits(max_bits, uint64(symbols[1])) writeBits(max_bits, uint64(symbols[1]), storage_ix, storage)
} else if count == 3 { } else if count == 3 {
bw.writeBits(max_bits, uint64(symbols[0])) writeBits(max_bits, uint64(symbols[0]), storage_ix, storage)
bw.writeBits(max_bits, uint64(symbols[1])) writeBits(max_bits, uint64(symbols[1]), storage_ix, storage)
bw.writeBits(max_bits, uint64(symbols[2])) writeBits(max_bits, uint64(symbols[2]), storage_ix, storage)
} else { } else {
bw.writeBits(max_bits, uint64(symbols[0])) writeBits(max_bits, uint64(symbols[0]), storage_ix, storage)
bw.writeBits(max_bits, uint64(symbols[1])) writeBits(max_bits, uint64(symbols[1]), storage_ix, storage)
bw.writeBits(max_bits, uint64(symbols[2])) writeBits(max_bits, uint64(symbols[2]), storage_ix, storage)
bw.writeBits(max_bits, uint64(symbols[3])) writeBits(max_bits, uint64(symbols[3]), storage_ix, storage)
/* tree-select */ /* tree-select */
bw.writeSingleBit(depth[symbols[0]] == 1) var tmp int
if depth[symbols[0]] == 1 {
tmp = 1
} else {
tmp = 0
}
writeBits(1, uint64(tmp), storage_ix, storage)
} }
} else { } else {
var previous_value byte = 8 var previous_value byte = 8
var i uint var i uint
/* Complex Huffman Tree */ /* Complex Huffman Tree */
storeStaticCodeLengthCode(bw) storeStaticCodeLengthCode(storage_ix, storage)
/* Actual RLE coding. */ /* Actual RLE coding. */
for i = 0; i < length; { for i = 0; i < length; {
@ -594,21 +600,21 @@ func buildAndStoreHuffmanTreeFast(histogram []uint32, histogram_total uint, max_
i += reps i += reps
if value == 0 { if value == 0 {
bw.writeBits(uint(kZeroRepsDepth[reps]), kZeroRepsBits[reps]) writeBits(uint(kZeroRepsDepth[reps]), kZeroRepsBits[reps], storage_ix, storage)
} else { } else {
if previous_value != value { if previous_value != value {
bw.writeBits(uint(kCodeLengthDepth[value]), uint64(kCodeLengthBits[value])) writeBits(uint(kCodeLengthDepth[value]), uint64(kCodeLengthBits[value]), storage_ix, storage)
reps-- reps--
} }
if reps < 3 { if reps < 3 {
for reps != 0 { for reps != 0 {
reps-- reps--
bw.writeBits(uint(kCodeLengthDepth[value]), uint64(kCodeLengthBits[value])) writeBits(uint(kCodeLengthDepth[value]), uint64(kCodeLengthBits[value]), storage_ix, storage)
} }
} else { } else {
reps -= 3 reps -= 3
bw.writeBits(uint(kNonZeroRepsDepth[reps]), kNonZeroRepsBits[reps]) writeBits(uint(kNonZeroRepsDepth[reps]), kNonZeroRepsBits[reps], storage_ix, storage)
} }
previous_value = value previous_value = value
@ -733,7 +739,7 @@ const symbolBits = 9
var encodeContextMap_kSymbolMask uint32 = (1 << symbolBits) - 1 var encodeContextMap_kSymbolMask uint32 = (1 << symbolBits) - 1
func encodeContextMap(context_map []uint32, context_map_size uint, num_clusters uint, tree []huffmanTree, bw *bitWriter) { func encodeContextMap(context_map []uint32, context_map_size uint, num_clusters uint, tree []huffmanTree, storage_ix *uint, storage []byte) {
var i uint var i uint
var rle_symbols []uint32 var rle_symbols []uint32
var max_run_length_prefix uint32 = 6 var max_run_length_prefix uint32 = 6
@ -742,7 +748,7 @@ func encodeContextMap(context_map []uint32, context_map_size uint, num_clusters
var depths [maxContextMapSymbols]byte var depths [maxContextMapSymbols]byte
var bits [maxContextMapSymbols]uint16 var bits [maxContextMapSymbols]uint16
storeVarLenUint8(num_clusters-1, bw) storeVarLenUint8(num_clusters-1, storage_ix, storage)
if num_clusters == 1 { if num_clusters == 1 {
return return
@ -757,45 +763,45 @@ func encodeContextMap(context_map []uint32, context_map_size uint, num_clusters
} }
{ {
var use_rle bool = (max_run_length_prefix > 0) var use_rle bool = (max_run_length_prefix > 0)
bw.writeSingleBit(use_rle) writeSingleBit(use_rle, storage_ix, storage)
if use_rle { if use_rle {
bw.writeBits(4, uint64(max_run_length_prefix)-1) writeBits(4, uint64(max_run_length_prefix)-1, storage_ix, storage)
} }
} }
buildAndStoreHuffmanTree(histogram[:], uint(uint32(num_clusters)+max_run_length_prefix), uint(uint32(num_clusters)+max_run_length_prefix), tree, depths[:], bits[:], bw) buildAndStoreHuffmanTree(histogram[:], uint(uint32(num_clusters)+max_run_length_prefix), uint(uint32(num_clusters)+max_run_length_prefix), tree, depths[:], bits[:], storage_ix, storage)
for i = 0; i < num_rle_symbols; i++ { for i = 0; i < num_rle_symbols; i++ {
var rle_symbol uint32 = rle_symbols[i] & encodeContextMap_kSymbolMask var rle_symbol uint32 = rle_symbols[i] & encodeContextMap_kSymbolMask
var extra_bits_val uint32 = rle_symbols[i] >> symbolBits var extra_bits_val uint32 = rle_symbols[i] >> symbolBits
bw.writeBits(uint(depths[rle_symbol]), uint64(bits[rle_symbol])) writeBits(uint(depths[rle_symbol]), uint64(bits[rle_symbol]), storage_ix, storage)
if rle_symbol > 0 && rle_symbol <= max_run_length_prefix { if rle_symbol > 0 && rle_symbol <= max_run_length_prefix {
bw.writeBits(uint(rle_symbol), uint64(extra_bits_val)) writeBits(uint(rle_symbol), uint64(extra_bits_val), storage_ix, storage)
} }
} }
bw.writeBits(1, 1) /* use move-to-front */ writeBits(1, 1, storage_ix, storage) /* use move-to-front */
rle_symbols = nil rle_symbols = nil
} }
/* Stores the block switch command with index block_ix to the bit stream. */ /* Stores the block switch command with index block_ix to the bit stream. */
func storeBlockSwitch(code *blockSplitCode, block_len uint32, block_type byte, is_first_block bool, bw *bitWriter) { func storeBlockSwitch(code *blockSplitCode, block_len uint32, block_type byte, is_first_block bool, storage_ix *uint, storage []byte) {
var typecode uint = nextBlockTypeCode(&code.type_code_calculator, block_type) var typecode uint = nextBlockTypeCode(&code.type_code_calculator, block_type)
var lencode uint var lencode uint
var len_nextra uint32 var len_nextra uint32
var len_extra uint32 var len_extra uint32
if !is_first_block { if !is_first_block {
bw.writeBits(uint(code.type_depths[typecode]), uint64(code.type_bits[typecode])) writeBits(uint(code.type_depths[typecode]), uint64(code.type_bits[typecode]), storage_ix, storage)
} }
getBlockLengthPrefixCode(block_len, &lencode, &len_nextra, &len_extra) getBlockLengthPrefixCode(block_len, &lencode, &len_nextra, &len_extra)
bw.writeBits(uint(code.length_depths[lencode]), uint64(code.length_bits[lencode])) writeBits(uint(code.length_depths[lencode]), uint64(code.length_bits[lencode]), storage_ix, storage)
bw.writeBits(uint(len_nextra), uint64(len_extra)) writeBits(uint(len_nextra), uint64(len_extra), storage_ix, storage)
} }
/* Builds a BlockSplitCode data structure from the block split given by the /* Builds a BlockSplitCode data structure from the block split given by the
vector of block types and block lengths and stores it to the bit stream. */ vector of block types and block lengths and stores it to the bit stream. */
func buildAndStoreBlockSplitCode(types []byte, lengths []uint32, num_blocks uint, num_types uint, tree []huffmanTree, code *blockSplitCode, bw *bitWriter) { func buildAndStoreBlockSplitCode(types []byte, lengths []uint32, num_blocks uint, num_types uint, tree []huffmanTree, code *blockSplitCode, storage_ix *uint, storage []byte) {
var type_histo [maxBlockTypeSymbols]uint32 var type_histo [maxBlockTypeSymbols]uint32
var length_histo [numBlockLenSymbols]uint32 var length_histo [numBlockLenSymbols]uint32
var i uint var i uint
@ -813,17 +819,17 @@ func buildAndStoreBlockSplitCode(types []byte, lengths []uint32, num_blocks uint
length_histo[blockLengthPrefixCode(lengths[i])]++ length_histo[blockLengthPrefixCode(lengths[i])]++
} }
storeVarLenUint8(num_types-1, bw) storeVarLenUint8(num_types-1, storage_ix, storage)
if num_types > 1 { /* TODO: else? could StoreBlockSwitch occur? */ if num_types > 1 { /* TODO: else? could StoreBlockSwitch occur? */
buildAndStoreHuffmanTree(type_histo[0:], num_types+2, num_types+2, tree, code.type_depths[0:], code.type_bits[0:], bw) buildAndStoreHuffmanTree(type_histo[0:], num_types+2, num_types+2, tree, code.type_depths[0:], code.type_bits[0:], storage_ix, storage)
buildAndStoreHuffmanTree(length_histo[0:], numBlockLenSymbols, numBlockLenSymbols, tree, code.length_depths[0:], code.length_bits[0:], bw) buildAndStoreHuffmanTree(length_histo[0:], numBlockLenSymbols, numBlockLenSymbols, tree, code.length_depths[0:], code.length_bits[0:], storage_ix, storage)
storeBlockSwitch(code, lengths[0], types[0], true, bw) storeBlockSwitch(code, lengths[0], types[0], true, storage_ix, storage)
} }
} }
/* Stores a context map where the histogram type is always the block type. */ /* Stores a context map where the histogram type is always the block type. */
func storeTrivialContextMap(num_types uint, context_bits uint, tree []huffmanTree, bw *bitWriter) { func storeTrivialContextMap(num_types uint, context_bits uint, tree []huffmanTree, storage_ix *uint, storage []byte) {
storeVarLenUint8(num_types-1, bw) storeVarLenUint8(num_types-1, storage_ix, storage)
if num_types > 1 { if num_types > 1 {
var repeat_code uint = context_bits - 1 var repeat_code uint = context_bits - 1
var repeat_bits uint = (1 << repeat_code) - 1 var repeat_bits uint = (1 << repeat_code) - 1
@ -837,16 +843,16 @@ func storeTrivialContextMap(num_types uint, context_bits uint, tree []huffmanTre
} }
/* Write RLEMAX. */ /* Write RLEMAX. */
bw.writeBits(1, 1) writeBits(1, 1, storage_ix, storage)
bw.writeBits(4, uint64(repeat_code)-1) writeBits(4, uint64(repeat_code)-1, storage_ix, storage)
histogram[repeat_code] = uint32(num_types) histogram[repeat_code] = uint32(num_types)
histogram[0] = 1 histogram[0] = 1
for i = context_bits; i < alphabet_size; i++ { for i = context_bits; i < alphabet_size; i++ {
histogram[i] = 1 histogram[i] = 1
} }
buildAndStoreHuffmanTree(histogram[:], alphabet_size, alphabet_size, tree, depths[:], bits[:], bw) buildAndStoreHuffmanTree(histogram[:], alphabet_size, alphabet_size, tree, depths[:], bits[:], storage_ix, storage)
for i = 0; i < num_types; i++ { for i = 0; i < num_types; i++ {
var tmp uint var tmp uint
if i == 0 { if i == 0 {
@ -855,13 +861,13 @@ func storeTrivialContextMap(num_types uint, context_bits uint, tree []huffmanTre
tmp = i + context_bits - 1 tmp = i + context_bits - 1
} }
var code uint = tmp var code uint = tmp
bw.writeBits(uint(depths[code]), uint64(bits[code])) writeBits(uint(depths[code]), uint64(bits[code]), storage_ix, storage)
bw.writeBits(uint(depths[repeat_code]), uint64(bits[repeat_code])) writeBits(uint(depths[repeat_code]), uint64(bits[repeat_code]), storage_ix, storage)
bw.writeBits(repeat_code, uint64(repeat_bits)) writeBits(repeat_code, uint64(repeat_bits), storage_ix, storage)
} }
/* Write IMTF (inverse-move-to-front) bit. */ /* Write IMTF (inverse-move-to-front) bit. */
bw.writeBits(1, 1) writeBits(1, 1, storage_ix, storage)
} }
} }
@ -915,13 +921,13 @@ func cleanupBlockEncoder(self *blockEncoder) {
/* Creates entropy codes of block lengths and block types and stores them /* Creates entropy codes of block lengths and block types and stores them
to the bit stream. */ to the bit stream. */
func buildAndStoreBlockSwitchEntropyCodes(self *blockEncoder, tree []huffmanTree, bw *bitWriter) { func buildAndStoreBlockSwitchEntropyCodes(self *blockEncoder, tree []huffmanTree, storage_ix *uint, storage []byte) {
buildAndStoreBlockSplitCode(self.block_types_, self.block_lengths_, self.num_blocks_, self.num_block_types_, tree, &self.block_split_code_, bw) buildAndStoreBlockSplitCode(self.block_types_, self.block_lengths_, self.num_blocks_, self.num_block_types_, tree, &self.block_split_code_, storage_ix, storage)
} }
/* Stores the next symbol with the entropy code of the current block type. /* Stores the next symbol with the entropy code of the current block type.
Updates the block type and block length at block boundaries. */ Updates the block type and block length at block boundaries. */
func storeSymbol(self *blockEncoder, symbol uint, bw *bitWriter) { func storeSymbol(self *blockEncoder, symbol uint, storage_ix *uint, storage []byte) {
if self.block_len_ == 0 { if self.block_len_ == 0 {
self.block_ix_++ self.block_ix_++
var block_ix uint = self.block_ix_ var block_ix uint = self.block_ix_
@ -929,20 +935,20 @@ func storeSymbol(self *blockEncoder, symbol uint, bw *bitWriter) {
var block_type byte = self.block_types_[block_ix] var block_type byte = self.block_types_[block_ix]
self.block_len_ = uint(block_len) self.block_len_ = uint(block_len)
self.entropy_ix_ = uint(block_type) * self.histogram_length_ self.entropy_ix_ = uint(block_type) * self.histogram_length_
storeBlockSwitch(&self.block_split_code_, block_len, block_type, false, bw) storeBlockSwitch(&self.block_split_code_, block_len, block_type, false, storage_ix, storage)
} }
self.block_len_-- self.block_len_--
{ {
var ix uint = self.entropy_ix_ + symbol var ix uint = self.entropy_ix_ + symbol
bw.writeBits(uint(self.depths_[ix]), uint64(self.bits_[ix])) writeBits(uint(self.depths_[ix]), uint64(self.bits_[ix]), storage_ix, storage)
} }
} }
/* Stores the next symbol with the entropy code of the current block type and /* Stores the next symbol with the entropy code of the current block type and
context value. context value.
Updates the block type and block length at block boundaries. */ Updates the block type and block length at block boundaries. */
func storeSymbolWithContext(self *blockEncoder, symbol uint, context uint, context_map []uint32, bw *bitWriter, context_bits uint) { func storeSymbolWithContext(self *blockEncoder, symbol uint, context uint, context_map []uint32, storage_ix *uint, storage []byte, context_bits uint) {
if self.block_len_ == 0 { if self.block_len_ == 0 {
self.block_ix_++ self.block_ix_++
var block_ix uint = self.block_ix_ var block_ix uint = self.block_ix_
@ -950,18 +956,18 @@ func storeSymbolWithContext(self *blockEncoder, symbol uint, context uint, conte
var block_type byte = self.block_types_[block_ix] var block_type byte = self.block_types_[block_ix]
self.block_len_ = uint(block_len) self.block_len_ = uint(block_len)
self.entropy_ix_ = uint(block_type) << context_bits self.entropy_ix_ = uint(block_type) << context_bits
storeBlockSwitch(&self.block_split_code_, block_len, block_type, false, bw) storeBlockSwitch(&self.block_split_code_, block_len, block_type, false, storage_ix, storage)
} }
self.block_len_-- self.block_len_--
{ {
var histo_ix uint = uint(context_map[self.entropy_ix_+context]) var histo_ix uint = uint(context_map[self.entropy_ix_+context])
var ix uint = histo_ix*self.histogram_length_ + symbol var ix uint = histo_ix*self.histogram_length_ + symbol
bw.writeBits(uint(self.depths_[ix]), uint64(self.bits_[ix])) writeBits(uint(self.depths_[ix]), uint64(self.bits_[ix]), storage_ix, storage)
} }
} }
func buildAndStoreEntropyCodesLiteral(self *blockEncoder, histograms []histogramLiteral, histograms_size uint, alphabet_size uint, tree []huffmanTree, bw *bitWriter) { func buildAndStoreEntropyCodesLiteral(self *blockEncoder, histograms []histogramLiteral, histograms_size uint, alphabet_size uint, tree []huffmanTree, storage_ix *uint, storage []byte) {
var table_size uint = histograms_size * self.histogram_length_ var table_size uint = histograms_size * self.histogram_length_
if cap(self.depths_) < int(table_size) { if cap(self.depths_) < int(table_size) {
self.depths_ = make([]byte, table_size) self.depths_ = make([]byte, table_size)
@ -977,12 +983,12 @@ func buildAndStoreEntropyCodesLiteral(self *blockEncoder, histograms []histogram
var i uint var i uint
for i = 0; i < histograms_size; i++ { for i = 0; i < histograms_size; i++ {
var ix uint = i * self.histogram_length_ var ix uint = i * self.histogram_length_
buildAndStoreHuffmanTree(histograms[i].data_[0:], self.histogram_length_, alphabet_size, tree, self.depths_[ix:], self.bits_[ix:], bw) buildAndStoreHuffmanTree(histograms[i].data_[0:], self.histogram_length_, alphabet_size, tree, self.depths_[ix:], self.bits_[ix:], storage_ix, storage)
} }
} }
} }
func buildAndStoreEntropyCodesCommand(self *blockEncoder, histograms []histogramCommand, histograms_size uint, alphabet_size uint, tree []huffmanTree, bw *bitWriter) { func buildAndStoreEntropyCodesCommand(self *blockEncoder, histograms []histogramCommand, histograms_size uint, alphabet_size uint, tree []huffmanTree, storage_ix *uint, storage []byte) {
var table_size uint = histograms_size * self.histogram_length_ var table_size uint = histograms_size * self.histogram_length_
if cap(self.depths_) < int(table_size) { if cap(self.depths_) < int(table_size) {
self.depths_ = make([]byte, table_size) self.depths_ = make([]byte, table_size)
@ -998,12 +1004,12 @@ func buildAndStoreEntropyCodesCommand(self *blockEncoder, histograms []histogram
var i uint var i uint
for i = 0; i < histograms_size; i++ { for i = 0; i < histograms_size; i++ {
var ix uint = i * self.histogram_length_ var ix uint = i * self.histogram_length_
buildAndStoreHuffmanTree(histograms[i].data_[0:], self.histogram_length_, alphabet_size, tree, self.depths_[ix:], self.bits_[ix:], bw) buildAndStoreHuffmanTree(histograms[i].data_[0:], self.histogram_length_, alphabet_size, tree, self.depths_[ix:], self.bits_[ix:], storage_ix, storage)
} }
} }
} }
func buildAndStoreEntropyCodesDistance(self *blockEncoder, histograms []histogramDistance, histograms_size uint, alphabet_size uint, tree []huffmanTree, bw *bitWriter) { func buildAndStoreEntropyCodesDistance(self *blockEncoder, histograms []histogramDistance, histograms_size uint, alphabet_size uint, tree []huffmanTree, storage_ix *uint, storage []byte) {
var table_size uint = histograms_size * self.histogram_length_ var table_size uint = histograms_size * self.histogram_length_
if cap(self.depths_) < int(table_size) { if cap(self.depths_) < int(table_size) {
self.depths_ = make([]byte, table_size) self.depths_ = make([]byte, table_size)
@ -1019,12 +1025,17 @@ func buildAndStoreEntropyCodesDistance(self *blockEncoder, histograms []histogra
var i uint var i uint
for i = 0; i < histograms_size; i++ { for i = 0; i < histograms_size; i++ {
var ix uint = i * self.histogram_length_ var ix uint = i * self.histogram_length_
buildAndStoreHuffmanTree(histograms[i].data_[0:], self.histogram_length_, alphabet_size, tree, self.depths_[ix:], self.bits_[ix:], bw) buildAndStoreHuffmanTree(histograms[i].data_[0:], self.histogram_length_, alphabet_size, tree, self.depths_[ix:], self.bits_[ix:], storage_ix, storage)
} }
} }
} }
func storeMetaBlock(input []byte, start_pos uint, length uint, mask uint, prev_byte byte, prev_byte2 byte, is_last bool, params *encoderParams, literal_context_mode int, commands []command, mb *metaBlockSplit, bw *bitWriter) { func jumpToByteBoundary(storage_ix *uint, storage []byte) {
*storage_ix = (*storage_ix + 7) &^ 7
storage[*storage_ix>>3] = 0
}
func storeMetaBlock(input []byte, start_pos uint, length uint, mask uint, prev_byte byte, prev_byte2 byte, is_last bool, params *encoderParams, literal_context_mode int, commands []command, mb *metaBlockSplit, storage_ix *uint, storage []byte) {
var pos uint = start_pos var pos uint = start_pos
var i uint var i uint
var num_distance_symbols uint32 = params.dist.alphabet_size var num_distance_symbols uint32 = params.dist.alphabet_size
@ -1036,48 +1047,48 @@ func storeMetaBlock(input []byte, start_pos uint, length uint, mask uint, prev_b
num_effective_distance_symbols = numHistogramDistanceSymbols num_effective_distance_symbols = numHistogramDistanceSymbols
} }
storeCompressedMetaBlockHeader(is_last, length, bw) storeCompressedMetaBlockHeader(is_last, length, storage_ix, storage)
tree = make([]huffmanTree, maxHuffmanTreeSize) tree = make([]huffmanTree, maxHuffmanTreeSize)
literal_enc := getBlockEncoder(numLiteralSymbols, mb.literal_split.num_types, mb.literal_split.types, mb.literal_split.lengths, mb.literal_split.num_blocks) literal_enc := getBlockEncoder(numLiteralSymbols, mb.literal_split.num_types, mb.literal_split.types, mb.literal_split.lengths, mb.literal_split.num_blocks)
command_enc := getBlockEncoder(numCommandSymbols, mb.command_split.num_types, mb.command_split.types, mb.command_split.lengths, mb.command_split.num_blocks) command_enc := getBlockEncoder(numCommandSymbols, mb.command_split.num_types, mb.command_split.types, mb.command_split.lengths, mb.command_split.num_blocks)
distance_enc := getBlockEncoder(uint(num_effective_distance_symbols), mb.distance_split.num_types, mb.distance_split.types, mb.distance_split.lengths, mb.distance_split.num_blocks) distance_enc := getBlockEncoder(uint(num_effective_distance_symbols), mb.distance_split.num_types, mb.distance_split.types, mb.distance_split.lengths, mb.distance_split.num_blocks)
buildAndStoreBlockSwitchEntropyCodes(literal_enc, tree, bw) buildAndStoreBlockSwitchEntropyCodes(literal_enc, tree, storage_ix, storage)
buildAndStoreBlockSwitchEntropyCodes(command_enc, tree, bw) buildAndStoreBlockSwitchEntropyCodes(command_enc, tree, storage_ix, storage)
buildAndStoreBlockSwitchEntropyCodes(distance_enc, tree, bw) buildAndStoreBlockSwitchEntropyCodes(distance_enc, tree, storage_ix, storage)
bw.writeBits(2, uint64(dist.distance_postfix_bits)) writeBits(2, uint64(dist.distance_postfix_bits), storage_ix, storage)
bw.writeBits(4, uint64(dist.num_direct_distance_codes)>>dist.distance_postfix_bits) writeBits(4, uint64(dist.num_direct_distance_codes)>>dist.distance_postfix_bits, storage_ix, storage)
for i = 0; i < mb.literal_split.num_types; i++ { for i = 0; i < mb.literal_split.num_types; i++ {
bw.writeBits(2, uint64(literal_context_mode)) writeBits(2, uint64(literal_context_mode), storage_ix, storage)
} }
if mb.literal_context_map_size == 0 { if mb.literal_context_map_size == 0 {
storeTrivialContextMap(mb.literal_histograms_size, literalContextBits, tree, bw) storeTrivialContextMap(mb.literal_histograms_size, literalContextBits, tree, storage_ix, storage)
} else { } else {
encodeContextMap(mb.literal_context_map, mb.literal_context_map_size, mb.literal_histograms_size, tree, bw) encodeContextMap(mb.literal_context_map, mb.literal_context_map_size, mb.literal_histograms_size, tree, storage_ix, storage)
} }
if mb.distance_context_map_size == 0 { if mb.distance_context_map_size == 0 {
storeTrivialContextMap(mb.distance_histograms_size, distanceContextBits, tree, bw) storeTrivialContextMap(mb.distance_histograms_size, distanceContextBits, tree, storage_ix, storage)
} else { } else {
encodeContextMap(mb.distance_context_map, mb.distance_context_map_size, mb.distance_histograms_size, tree, bw) encodeContextMap(mb.distance_context_map, mb.distance_context_map_size, mb.distance_histograms_size, tree, storage_ix, storage)
} }
buildAndStoreEntropyCodesLiteral(literal_enc, mb.literal_histograms, mb.literal_histograms_size, numLiteralSymbols, tree, bw) buildAndStoreEntropyCodesLiteral(literal_enc, mb.literal_histograms, mb.literal_histograms_size, numLiteralSymbols, tree, storage_ix, storage)
buildAndStoreEntropyCodesCommand(command_enc, mb.command_histograms, mb.command_histograms_size, numCommandSymbols, tree, bw) buildAndStoreEntropyCodesCommand(command_enc, mb.command_histograms, mb.command_histograms_size, numCommandSymbols, tree, storage_ix, storage)
buildAndStoreEntropyCodesDistance(distance_enc, mb.distance_histograms, mb.distance_histograms_size, uint(num_distance_symbols), tree, bw) buildAndStoreEntropyCodesDistance(distance_enc, mb.distance_histograms, mb.distance_histograms_size, uint(num_distance_symbols), tree, storage_ix, storage)
tree = nil tree = nil
for _, cmd := range commands { for _, cmd := range commands {
var cmd_code uint = uint(cmd.cmd_prefix_) var cmd_code uint = uint(cmd.cmd_prefix_)
storeSymbol(command_enc, cmd_code, bw) storeSymbol(command_enc, cmd_code, storage_ix, storage)
storeCommandExtra(&cmd, bw) storeCommandExtra(&cmd, storage_ix, storage)
if mb.literal_context_map_size == 0 { if mb.literal_context_map_size == 0 {
var j uint var j uint
for j = uint(cmd.insert_len_); j != 0; j-- { for j = uint(cmd.insert_len_); j != 0; j-- {
storeSymbol(literal_enc, uint(input[pos&mask]), bw) storeSymbol(literal_enc, uint(input[pos&mask]), storage_ix, storage)
pos++ pos++
} }
} else { } else {
@ -1085,7 +1096,7 @@ func storeMetaBlock(input []byte, start_pos uint, length uint, mask uint, prev_b
for j = uint(cmd.insert_len_); j != 0; j-- { for j = uint(cmd.insert_len_); j != 0; j-- {
var context uint = uint(getContext(prev_byte, prev_byte2, literal_context_lut)) var context uint = uint(getContext(prev_byte, prev_byte2, literal_context_lut))
var literal byte = input[pos&mask] var literal byte = input[pos&mask]
storeSymbolWithContext(literal_enc, uint(literal), context, mb.literal_context_map, bw, literalContextBits) storeSymbolWithContext(literal_enc, uint(literal), context, mb.literal_context_map, storage_ix, storage, literalContextBits)
prev_byte2 = prev_byte prev_byte2 = prev_byte
prev_byte = literal prev_byte = literal
pos++ pos++
@ -1101,13 +1112,13 @@ func storeMetaBlock(input []byte, start_pos uint, length uint, mask uint, prev_b
var distnumextra uint32 = uint32(cmd.dist_prefix_) >> 10 var distnumextra uint32 = uint32(cmd.dist_prefix_) >> 10
var distextra uint64 = uint64(cmd.dist_extra_) var distextra uint64 = uint64(cmd.dist_extra_)
if mb.distance_context_map_size == 0 { if mb.distance_context_map_size == 0 {
storeSymbol(distance_enc, dist_code, bw) storeSymbol(distance_enc, dist_code, storage_ix, storage)
} else { } else {
var context uint = uint(commandDistanceContext(&cmd)) var context uint = uint(commandDistanceContext(&cmd))
storeSymbolWithContext(distance_enc, dist_code, context, mb.distance_context_map, bw, distanceContextBits) storeSymbolWithContext(distance_enc, dist_code, context, mb.distance_context_map, storage_ix, storage, distanceContextBits)
} }
bw.writeBits(uint(distnumextra), distextra) writeBits(uint(distnumextra), distextra, storage_ix, storage)
} }
} }
} }
@ -1116,7 +1127,7 @@ func storeMetaBlock(input []byte, start_pos uint, length uint, mask uint, prev_b
cleanupBlockEncoder(command_enc) cleanupBlockEncoder(command_enc)
cleanupBlockEncoder(literal_enc) cleanupBlockEncoder(literal_enc)
if is_last { if is_last {
bw.jumpToByteBoundary() jumpToByteBoundary(storage_ix, storage)
} }
} }
@ -1137,16 +1148,16 @@ func buildHistograms(input []byte, start_pos uint, mask uint, commands []command
} }
} }
func storeDataWithHuffmanCodes(input []byte, start_pos uint, mask uint, commands []command, lit_depth []byte, lit_bits []uint16, cmd_depth []byte, cmd_bits []uint16, dist_depth []byte, dist_bits []uint16, bw *bitWriter) { func storeDataWithHuffmanCodes(input []byte, start_pos uint, mask uint, commands []command, lit_depth []byte, lit_bits []uint16, cmd_depth []byte, cmd_bits []uint16, dist_depth []byte, dist_bits []uint16, storage_ix *uint, storage []byte) {
var pos uint = start_pos var pos uint = start_pos
for _, cmd := range commands { for _, cmd := range commands {
var cmd_code uint = uint(cmd.cmd_prefix_) var cmd_code uint = uint(cmd.cmd_prefix_)
var j uint var j uint
bw.writeBits(uint(cmd_depth[cmd_code]), uint64(cmd_bits[cmd_code])) writeBits(uint(cmd_depth[cmd_code]), uint64(cmd_bits[cmd_code]), storage_ix, storage)
storeCommandExtra(&cmd, bw) storeCommandExtra(&cmd, storage_ix, storage)
for j = uint(cmd.insert_len_); j != 0; j-- { for j = uint(cmd.insert_len_); j != 0; j-- {
var literal byte = input[pos&mask] var literal byte = input[pos&mask]
bw.writeBits(uint(lit_depth[literal]), uint64(lit_bits[literal])) writeBits(uint(lit_depth[literal]), uint64(lit_bits[literal]), storage_ix, storage)
pos++ pos++
} }
@ -1155,13 +1166,13 @@ func storeDataWithHuffmanCodes(input []byte, start_pos uint, mask uint, commands
var dist_code uint = uint(cmd.dist_prefix_) & 0x3FF var dist_code uint = uint(cmd.dist_prefix_) & 0x3FF
var distnumextra uint32 = uint32(cmd.dist_prefix_) >> 10 var distnumextra uint32 = uint32(cmd.dist_prefix_) >> 10
var distextra uint32 = cmd.dist_extra_ var distextra uint32 = cmd.dist_extra_
bw.writeBits(uint(dist_depth[dist_code]), uint64(dist_bits[dist_code])) writeBits(uint(dist_depth[dist_code]), uint64(dist_bits[dist_code]), storage_ix, storage)
bw.writeBits(uint(distnumextra), uint64(distextra)) writeBits(uint(distnumextra), uint64(distextra), storage_ix, storage)
} }
} }
} }
func storeMetaBlockTrivial(input []byte, start_pos uint, length uint, mask uint, is_last bool, params *encoderParams, commands []command, bw *bitWriter) { func storeMetaBlockTrivial(input []byte, start_pos uint, length uint, mask uint, is_last bool, params *encoderParams, commands []command, storage_ix *uint, storage []byte) {
var lit_histo histogramLiteral var lit_histo histogramLiteral
var cmd_histo histogramCommand var cmd_histo histogramCommand
var dist_histo histogramDistance var dist_histo histogramDistance
@ -1174,7 +1185,7 @@ func storeMetaBlockTrivial(input []byte, start_pos uint, length uint, mask uint,
var tree []huffmanTree var tree []huffmanTree
var num_distance_symbols uint32 = params.dist.alphabet_size var num_distance_symbols uint32 = params.dist.alphabet_size
storeCompressedMetaBlockHeader(is_last, length, bw) storeCompressedMetaBlockHeader(is_last, length, storage_ix, storage)
histogramClearLiteral(&lit_histo) histogramClearLiteral(&lit_histo)
histogramClearCommand(&cmd_histo) histogramClearCommand(&cmd_histo)
@ -1182,26 +1193,26 @@ func storeMetaBlockTrivial(input []byte, start_pos uint, length uint, mask uint,
buildHistograms(input, start_pos, mask, commands, &lit_histo, &cmd_histo, &dist_histo) buildHistograms(input, start_pos, mask, commands, &lit_histo, &cmd_histo, &dist_histo)
bw.writeBits(13, 0) writeBits(13, 0, storage_ix, storage)
tree = make([]huffmanTree, maxHuffmanTreeSize) tree = make([]huffmanTree, maxHuffmanTreeSize)
buildAndStoreHuffmanTree(lit_histo.data_[:], numLiteralSymbols, numLiteralSymbols, tree, lit_depth[:], lit_bits[:], bw) buildAndStoreHuffmanTree(lit_histo.data_[:], numLiteralSymbols, numLiteralSymbols, tree, lit_depth[:], lit_bits[:], storage_ix, storage)
buildAndStoreHuffmanTree(cmd_histo.data_[:], numCommandSymbols, numCommandSymbols, tree, cmd_depth[:], cmd_bits[:], bw) buildAndStoreHuffmanTree(cmd_histo.data_[:], numCommandSymbols, numCommandSymbols, tree, cmd_depth[:], cmd_bits[:], storage_ix, storage)
buildAndStoreHuffmanTree(dist_histo.data_[:], maxSimpleDistanceAlphabetSize, uint(num_distance_symbols), tree, dist_depth[:], dist_bits[:], bw) buildAndStoreHuffmanTree(dist_histo.data_[:], maxSimpleDistanceAlphabetSize, uint(num_distance_symbols), tree, dist_depth[:], dist_bits[:], storage_ix, storage)
tree = nil tree = nil
storeDataWithHuffmanCodes(input, start_pos, mask, commands, lit_depth[:], lit_bits[:], cmd_depth[:], cmd_bits[:], dist_depth[:], dist_bits[:], bw) storeDataWithHuffmanCodes(input, start_pos, mask, commands, lit_depth[:], lit_bits[:], cmd_depth[:], cmd_bits[:], dist_depth[:], dist_bits[:], storage_ix, storage)
if is_last { if is_last {
bw.jumpToByteBoundary() jumpToByteBoundary(storage_ix, storage)
} }
} }
func storeMetaBlockFast(input []byte, start_pos uint, length uint, mask uint, is_last bool, params *encoderParams, commands []command, bw *bitWriter) { func storeMetaBlockFast(input []byte, start_pos uint, length uint, mask uint, is_last bool, params *encoderParams, commands []command, storage_ix *uint, storage []byte) {
var num_distance_symbols uint32 = params.dist.alphabet_size var num_distance_symbols uint32 = params.dist.alphabet_size
var distance_alphabet_bits uint32 = log2FloorNonZero(uint(num_distance_symbols-1)) + 1 var distance_alphabet_bits uint32 = log2FloorNonZero(uint(num_distance_symbols-1)) + 1
storeCompressedMetaBlockHeader(is_last, length, bw) storeCompressedMetaBlockHeader(is_last, length, storage_ix, storage)
bw.writeBits(13, 0) writeBits(13, 0, storage_ix, storage)
if len(commands) <= 128 { if len(commands) <= 128 {
var histogram = [numLiteralSymbols]uint32{0} var histogram = [numLiteralSymbols]uint32{0}
@ -1221,11 +1232,11 @@ func storeMetaBlockFast(input []byte, start_pos uint, length uint, mask uint, is
} }
buildAndStoreHuffmanTreeFast(histogram[:], num_literals, /* max_bits = */ buildAndStoreHuffmanTreeFast(histogram[:], num_literals, /* max_bits = */
8, lit_depth[:], lit_bits[:], bw) 8, lit_depth[:], lit_bits[:], storage_ix, storage)
storeStaticCommandHuffmanTree(bw) storeStaticCommandHuffmanTree(storage_ix, storage)
storeStaticDistanceHuffmanTree(bw) storeStaticDistanceHuffmanTree(storage_ix, storage)
storeDataWithHuffmanCodes(input, start_pos, mask, commands, lit_depth[:], lit_bits[:], kStaticCommandCodeDepth[:], kStaticCommandCodeBits[:], kStaticDistanceCodeDepth[:], kStaticDistanceCodeBits[:], bw) storeDataWithHuffmanCodes(input, start_pos, mask, commands, lit_depth[:], lit_bits[:], kStaticCommandCodeDepth[:], kStaticCommandCodeBits[:], kStaticDistanceCodeDepth[:], kStaticDistanceCodeBits[:], storage_ix, storage)
} else { } else {
var lit_histo histogramLiteral var lit_histo histogramLiteral
var cmd_histo histogramCommand var cmd_histo histogramCommand
@ -1241,43 +1252,49 @@ func storeMetaBlockFast(input []byte, start_pos uint, length uint, mask uint, is
histogramClearDistance(&dist_histo) histogramClearDistance(&dist_histo)
buildHistograms(input, start_pos, mask, commands, &lit_histo, &cmd_histo, &dist_histo) buildHistograms(input, start_pos, mask, commands, &lit_histo, &cmd_histo, &dist_histo)
buildAndStoreHuffmanTreeFast(lit_histo.data_[:], lit_histo.total_count_, /* max_bits = */ buildAndStoreHuffmanTreeFast(lit_histo.data_[:], lit_histo.total_count_, /* max_bits = */
8, lit_depth[:], lit_bits[:], bw) 8, lit_depth[:], lit_bits[:], storage_ix, storage)
buildAndStoreHuffmanTreeFast(cmd_histo.data_[:], cmd_histo.total_count_, /* max_bits = */ buildAndStoreHuffmanTreeFast(cmd_histo.data_[:], cmd_histo.total_count_, /* max_bits = */
10, cmd_depth[:], cmd_bits[:], bw) 10, cmd_depth[:], cmd_bits[:], storage_ix, storage)
buildAndStoreHuffmanTreeFast(dist_histo.data_[:], dist_histo.total_count_, /* max_bits = */ buildAndStoreHuffmanTreeFast(dist_histo.data_[:], dist_histo.total_count_, /* max_bits = */
uint(distance_alphabet_bits), dist_depth[:], dist_bits[:], bw) uint(distance_alphabet_bits), dist_depth[:], dist_bits[:], storage_ix, storage)
storeDataWithHuffmanCodes(input, start_pos, mask, commands, lit_depth[:], lit_bits[:], cmd_depth[:], cmd_bits[:], dist_depth[:], dist_bits[:], bw) storeDataWithHuffmanCodes(input, start_pos, mask, commands, lit_depth[:], lit_bits[:], cmd_depth[:], cmd_bits[:], dist_depth[:], dist_bits[:], storage_ix, storage)
} }
if is_last { if is_last {
bw.jumpToByteBoundary() jumpToByteBoundary(storage_ix, storage)
} }
} }
/* This is for storing uncompressed blocks (simple raw storage of /* This is for storing uncompressed blocks (simple raw storage of
bytes-as-bytes). */ bytes-as-bytes). */
func storeUncompressedMetaBlock(is_final_block bool, input []byte, position uint, mask uint, len uint, bw *bitWriter) { func storeUncompressedMetaBlock(is_final_block bool, input []byte, position uint, mask uint, len uint, storage_ix *uint, storage []byte) {
var masked_pos uint = position & mask var masked_pos uint = position & mask
storeUncompressedMetaBlockHeader(uint(len), bw) storeUncompressedMetaBlockHeader(uint(len), storage_ix, storage)
bw.jumpToByteBoundary() jumpToByteBoundary(storage_ix, storage)
if masked_pos+len > mask+1 { if masked_pos+len > mask+1 {
var len1 uint = mask + 1 - masked_pos var len1 uint = mask + 1 - masked_pos
bw.writeBytes(input[masked_pos:][:len1]) copy(storage[*storage_ix>>3:], input[masked_pos:][:len1])
*storage_ix += len1 << 3
len -= len1 len -= len1
masked_pos = 0 masked_pos = 0
} }
bw.writeBytes(input[masked_pos:][:len]) copy(storage[*storage_ix>>3:], input[masked_pos:][:len])
*storage_ix += uint(len << 3)
/* We need to clear the next 4 bytes to continue to be
compatible with BrotliWriteBits. */
writeBitsPrepareStorage(*storage_ix, storage)
/* Since the uncompressed block itself may not be the final block, add an /* Since the uncompressed block itself may not be the final block, add an
empty one after this. */ empty one after this. */
if is_final_block { if is_final_block {
bw.writeBits(1, 1) /* islast */ writeBits(1, 1, storage_ix, storage) /* islast */
bw.writeBits(1, 1) /* isempty */ writeBits(1, 1, storage_ix, storage) /* isempty */
bw.jumpToByteBoundary() jumpToByteBoundary(storage_ix, storage)
} }
} }

@ -45,7 +45,7 @@ func isMatch5(p1 []byte, p2 []byte) bool {
and thus have to assign a non-zero depth for each literal. and thus have to assign a non-zero depth for each literal.
Returns estimated compression ratio millibytes/char for encoding given input Returns estimated compression ratio millibytes/char for encoding given input
with generated code. */ with generated code. */
func buildAndStoreLiteralPrefixCode(input []byte, input_size uint, depths []byte, bits []uint16, bw *bitWriter) uint { func buildAndStoreLiteralPrefixCode(input []byte, input_size uint, depths []byte, bits []uint16, storage_ix *uint, storage []byte) uint {
var histogram = [256]uint32{0} var histogram = [256]uint32{0}
var histogram_total uint var histogram_total uint
var i uint var i uint
@ -82,7 +82,7 @@ func buildAndStoreLiteralPrefixCode(input []byte, input_size uint, depths []byte
} }
buildAndStoreHuffmanTreeFast(histogram[:], histogram_total, /* max_bits = */ buildAndStoreHuffmanTreeFast(histogram[:], histogram_total, /* max_bits = */
8, depths, bits, bw) 8, depths, bits, storage_ix, storage)
{ {
var literal_ratio uint = 0 var literal_ratio uint = 0
for i = 0; i < 256; i++ { for i = 0; i < 256; i++ {
@ -98,7 +98,7 @@ func buildAndStoreLiteralPrefixCode(input []byte, input_size uint, depths []byte
/* Builds a command and distance prefix code (each 64 symbols) into "depth" and /* Builds a command and distance prefix code (each 64 symbols) into "depth" and
"bits" based on "histogram" and stores it into the bit stream. */ "bits" based on "histogram" and stores it into the bit stream. */
func buildAndStoreCommandPrefixCode1(histogram []uint32, depth []byte, bits []uint16, bw *bitWriter) { func buildAndStoreCommandPrefixCode1(histogram []uint32, depth []byte, bits []uint16, storage_ix *uint, storage []byte) {
var tree [129]huffmanTree var tree [129]huffmanTree
var cmd_depth = [numCommandSymbols]byte{0} var cmd_depth = [numCommandSymbols]byte{0}
/* Tree size for building a tree over 64 symbols is 2 * 64 + 1. */ /* Tree size for building a tree over 64 symbols is 2 * 64 + 1. */
@ -145,141 +145,141 @@ func buildAndStoreCommandPrefixCode1(histogram []uint32, depth []byte, bits []ui
cmd_depth[448+8*i] = depth[56+i] cmd_depth[448+8*i] = depth[56+i]
} }
storeHuffmanTree(cmd_depth[:], numCommandSymbols, tree[:], bw) storeHuffmanTree(cmd_depth[:], numCommandSymbols, tree[:], storage_ix, storage)
} }
storeHuffmanTree(depth[64:], 64, tree[:], bw) storeHuffmanTree(depth[64:], 64, tree[:], storage_ix, storage)
} }
/* REQUIRES: insertlen < 6210 */ /* REQUIRES: insertlen < 6210 */
func emitInsertLen1(insertlen uint, depth []byte, bits []uint16, histo []uint32, bw *bitWriter) { func emitInsertLen1(insertlen uint, depth []byte, bits []uint16, histo []uint32, storage_ix *uint, storage []byte) {
if insertlen < 6 { if insertlen < 6 {
var code uint = insertlen + 40 var code uint = insertlen + 40
bw.writeBits(uint(depth[code]), uint64(bits[code])) writeBits(uint(depth[code]), uint64(bits[code]), storage_ix, storage)
histo[code]++ histo[code]++
} else if insertlen < 130 { } else if insertlen < 130 {
var tail uint = insertlen - 2 var tail uint = insertlen - 2
var nbits uint32 = log2FloorNonZero(tail) - 1 var nbits uint32 = log2FloorNonZero(tail) - 1
var prefix uint = tail >> nbits var prefix uint = tail >> nbits
var inscode uint = uint((nbits << 1) + uint32(prefix) + 42) var inscode uint = uint((nbits << 1) + uint32(prefix) + 42)
bw.writeBits(uint(depth[inscode]), uint64(bits[inscode])) writeBits(uint(depth[inscode]), uint64(bits[inscode]), storage_ix, storage)
bw.writeBits(uint(nbits), uint64(tail)-(uint64(prefix)<<nbits)) writeBits(uint(nbits), uint64(tail)-(uint64(prefix)<<nbits), storage_ix, storage)
histo[inscode]++ histo[inscode]++
} else if insertlen < 2114 { } else if insertlen < 2114 {
var tail uint = insertlen - 66 var tail uint = insertlen - 66
var nbits uint32 = log2FloorNonZero(tail) var nbits uint32 = log2FloorNonZero(tail)
var code uint = uint(nbits + 50) var code uint = uint(nbits + 50)
bw.writeBits(uint(depth[code]), uint64(bits[code])) writeBits(uint(depth[code]), uint64(bits[code]), storage_ix, storage)
bw.writeBits(uint(nbits), uint64(tail)-(uint64(uint(1))<<nbits)) writeBits(uint(nbits), uint64(tail)-(uint64(uint(1))<<nbits), storage_ix, storage)
histo[code]++ histo[code]++
} else { } else {
bw.writeBits(uint(depth[61]), uint64(bits[61])) writeBits(uint(depth[61]), uint64(bits[61]), storage_ix, storage)
bw.writeBits(12, uint64(insertlen)-2114) writeBits(12, uint64(insertlen)-2114, storage_ix, storage)
histo[61]++ histo[61]++
} }
} }
func emitLongInsertLen(insertlen uint, depth []byte, bits []uint16, histo []uint32, bw *bitWriter) { func emitLongInsertLen(insertlen uint, depth []byte, bits []uint16, histo []uint32, storage_ix *uint, storage []byte) {
if insertlen < 22594 { if insertlen < 22594 {
bw.writeBits(uint(depth[62]), uint64(bits[62])) writeBits(uint(depth[62]), uint64(bits[62]), storage_ix, storage)
bw.writeBits(14, uint64(insertlen)-6210) writeBits(14, uint64(insertlen)-6210, storage_ix, storage)
histo[62]++ histo[62]++
} else { } else {
bw.writeBits(uint(depth[63]), uint64(bits[63])) writeBits(uint(depth[63]), uint64(bits[63]), storage_ix, storage)
bw.writeBits(24, uint64(insertlen)-22594) writeBits(24, uint64(insertlen)-22594, storage_ix, storage)
histo[63]++ histo[63]++
} }
} }
func emitCopyLen1(copylen uint, depth []byte, bits []uint16, histo []uint32, bw *bitWriter) { func emitCopyLen1(copylen uint, depth []byte, bits []uint16, histo []uint32, storage_ix *uint, storage []byte) {
if copylen < 10 { if copylen < 10 {
bw.writeBits(uint(depth[copylen+14]), uint64(bits[copylen+14])) writeBits(uint(depth[copylen+14]), uint64(bits[copylen+14]), storage_ix, storage)
histo[copylen+14]++ histo[copylen+14]++
} else if copylen < 134 { } else if copylen < 134 {
var tail uint = copylen - 6 var tail uint = copylen - 6
var nbits uint32 = log2FloorNonZero(tail) - 1 var nbits uint32 = log2FloorNonZero(tail) - 1
var prefix uint = tail >> nbits var prefix uint = tail >> nbits
var code uint = uint((nbits << 1) + uint32(prefix) + 20) var code uint = uint((nbits << 1) + uint32(prefix) + 20)
bw.writeBits(uint(depth[code]), uint64(bits[code])) writeBits(uint(depth[code]), uint64(bits[code]), storage_ix, storage)
bw.writeBits(uint(nbits), uint64(tail)-(uint64(prefix)<<nbits)) writeBits(uint(nbits), uint64(tail)-(uint64(prefix)<<nbits), storage_ix, storage)
histo[code]++ histo[code]++
} else if copylen < 2118 { } else if copylen < 2118 {
var tail uint = copylen - 70 var tail uint = copylen - 70
var nbits uint32 = log2FloorNonZero(tail) var nbits uint32 = log2FloorNonZero(tail)
var code uint = uint(nbits + 28) var code uint = uint(nbits + 28)
bw.writeBits(uint(depth[code]), uint64(bits[code])) writeBits(uint(depth[code]), uint64(bits[code]), storage_ix, storage)
bw.writeBits(uint(nbits), uint64(tail)-(uint64(uint(1))<<nbits)) writeBits(uint(nbits), uint64(tail)-(uint64(uint(1))<<nbits), storage_ix, storage)
histo[code]++ histo[code]++
} else { } else {
bw.writeBits(uint(depth[39]), uint64(bits[39])) writeBits(uint(depth[39]), uint64(bits[39]), storage_ix, storage)
bw.writeBits(24, uint64(copylen)-2118) writeBits(24, uint64(copylen)-2118, storage_ix, storage)
histo[39]++ histo[39]++
} }
} }
func emitCopyLenLastDistance1(copylen uint, depth []byte, bits []uint16, histo []uint32, bw *bitWriter) { func emitCopyLenLastDistance1(copylen uint, depth []byte, bits []uint16, histo []uint32, storage_ix *uint, storage []byte) {
if copylen < 12 { if copylen < 12 {
bw.writeBits(uint(depth[copylen-4]), uint64(bits[copylen-4])) writeBits(uint(depth[copylen-4]), uint64(bits[copylen-4]), storage_ix, storage)
histo[copylen-4]++ histo[copylen-4]++
} else if copylen < 72 { } else if copylen < 72 {
var tail uint = copylen - 8 var tail uint = copylen - 8
var nbits uint32 = log2FloorNonZero(tail) - 1 var nbits uint32 = log2FloorNonZero(tail) - 1
var prefix uint = tail >> nbits var prefix uint = tail >> nbits
var code uint = uint((nbits << 1) + uint32(prefix) + 4) var code uint = uint((nbits << 1) + uint32(prefix) + 4)
bw.writeBits(uint(depth[code]), uint64(bits[code])) writeBits(uint(depth[code]), uint64(bits[code]), storage_ix, storage)
bw.writeBits(uint(nbits), uint64(tail)-(uint64(prefix)<<nbits)) writeBits(uint(nbits), uint64(tail)-(uint64(prefix)<<nbits), storage_ix, storage)
histo[code]++ histo[code]++
} else if copylen < 136 { } else if copylen < 136 {
var tail uint = copylen - 8 var tail uint = copylen - 8
var code uint = (tail >> 5) + 30 var code uint = (tail >> 5) + 30
bw.writeBits(uint(depth[code]), uint64(bits[code])) writeBits(uint(depth[code]), uint64(bits[code]), storage_ix, storage)
bw.writeBits(5, uint64(tail)&31) writeBits(5, uint64(tail)&31, storage_ix, storage)
bw.writeBits(uint(depth[64]), uint64(bits[64])) writeBits(uint(depth[64]), uint64(bits[64]), storage_ix, storage)
histo[code]++ histo[code]++
histo[64]++ histo[64]++
} else if copylen < 2120 { } else if copylen < 2120 {
var tail uint = copylen - 72 var tail uint = copylen - 72
var nbits uint32 = log2FloorNonZero(tail) var nbits uint32 = log2FloorNonZero(tail)
var code uint = uint(nbits + 28) var code uint = uint(nbits + 28)
bw.writeBits(uint(depth[code]), uint64(bits[code])) writeBits(uint(depth[code]), uint64(bits[code]), storage_ix, storage)
bw.writeBits(uint(nbits), uint64(tail)-(uint64(uint(1))<<nbits)) writeBits(uint(nbits), uint64(tail)-(uint64(uint(1))<<nbits), storage_ix, storage)
bw.writeBits(uint(depth[64]), uint64(bits[64])) writeBits(uint(depth[64]), uint64(bits[64]), storage_ix, storage)
histo[code]++ histo[code]++
histo[64]++ histo[64]++
} else { } else {
bw.writeBits(uint(depth[39]), uint64(bits[39])) writeBits(uint(depth[39]), uint64(bits[39]), storage_ix, storage)
bw.writeBits(24, uint64(copylen)-2120) writeBits(24, uint64(copylen)-2120, storage_ix, storage)
bw.writeBits(uint(depth[64]), uint64(bits[64])) writeBits(uint(depth[64]), uint64(bits[64]), storage_ix, storage)
histo[39]++ histo[39]++
histo[64]++ histo[64]++
} }
} }
func emitDistance1(distance uint, depth []byte, bits []uint16, histo []uint32, bw *bitWriter) { func emitDistance1(distance uint, depth []byte, bits []uint16, histo []uint32, storage_ix *uint, storage []byte) {
var d uint = distance + 3 var d uint = distance + 3
var nbits uint32 = log2FloorNonZero(d) - 1 var nbits uint32 = log2FloorNonZero(d) - 1
var prefix uint = (d >> nbits) & 1 var prefix uint = (d >> nbits) & 1
var offset uint = (2 + prefix) << nbits var offset uint = (2 + prefix) << nbits
var distcode uint = uint(2*(nbits-1) + uint32(prefix) + 80) var distcode uint = uint(2*(nbits-1) + uint32(prefix) + 80)
bw.writeBits(uint(depth[distcode]), uint64(bits[distcode])) writeBits(uint(depth[distcode]), uint64(bits[distcode]), storage_ix, storage)
bw.writeBits(uint(nbits), uint64(d)-uint64(offset)) writeBits(uint(nbits), uint64(d)-uint64(offset), storage_ix, storage)
histo[distcode]++ histo[distcode]++
} }
func emitLiterals(input []byte, len uint, depth []byte, bits []uint16, bw *bitWriter) { func emitLiterals(input []byte, len uint, depth []byte, bits []uint16, storage_ix *uint, storage []byte) {
var j uint var j uint
for j = 0; j < len; j++ { for j = 0; j < len; j++ {
var lit byte = input[j] var lit byte = input[j]
bw.writeBits(uint(depth[lit]), uint64(bits[lit])) writeBits(uint(depth[lit]), uint64(bits[lit]), storage_ix, storage)
} }
} }
/* REQUIRES: len <= 1 << 24. */ /* REQUIRES: len <= 1 << 24. */
func storeMetaBlockHeader1(len uint, is_uncompressed bool, bw *bitWriter) { func storeMetaBlockHeader1(len uint, is_uncompressed bool, storage_ix *uint, storage []byte) {
var nibbles uint = 6 var nibbles uint = 6
/* ISLAST */ /* ISLAST */
bw.writeBits(1, 0) writeBits(1, 0, storage_ix, storage)
if len <= 1<<16 { if len <= 1<<16 {
nibbles = 4 nibbles = 4
@ -287,11 +287,34 @@ func storeMetaBlockHeader1(len uint, is_uncompressed bool, bw *bitWriter) {
nibbles = 5 nibbles = 5
} }
bw.writeBits(2, uint64(nibbles)-4) writeBits(2, uint64(nibbles)-4, storage_ix, storage)
bw.writeBits(nibbles*4, uint64(len)-1) writeBits(nibbles*4, uint64(len)-1, storage_ix, storage)
/* ISUNCOMPRESSED */ /* ISUNCOMPRESSED */
bw.writeSingleBit(is_uncompressed) writeSingleBit(is_uncompressed, storage_ix, storage)
}
func updateBits(n_bits uint, bits uint32, pos uint, array []byte) {
for n_bits > 0 {
var byte_pos uint = pos >> 3
var n_unchanged_bits uint = pos & 7
var n_changed_bits uint = brotli_min_size_t(n_bits, 8-n_unchanged_bits)
var total_bits uint = n_unchanged_bits + n_changed_bits
var mask uint32 = (^((1 << total_bits) - 1)) | ((1 << n_unchanged_bits) - 1)
var unchanged_bits uint32 = uint32(array[byte_pos]) & mask
var changed_bits uint32 = bits & ((1 << n_changed_bits) - 1)
array[byte_pos] = byte(changed_bits<<n_unchanged_bits | unchanged_bits)
n_bits -= n_changed_bits
bits >>= n_changed_bits
pos += n_changed_bits
}
}
func rewindBitPosition1(new_storage_ix uint, storage_ix *uint, storage []byte) {
var bitpos uint = new_storage_ix & 7
var mask uint = (1 << bitpos) - 1
storage[new_storage_ix>>3] &= byte(mask)
*storage_ix = new_storage_ix
} }
var shouldMergeBlock_kSampleRate uint = 43 var shouldMergeBlock_kSampleRate uint = 43
@ -322,26 +345,151 @@ func shouldUseUncompressedMode(metablock_start []byte, next_emit []byte, insertl
} }
} }
func emitUncompressedMetaBlock1(data []byte, storage_ix_start uint, bw *bitWriter) { func emitUncompressedMetaBlock1(begin []byte, end []byte, storage_ix_start uint, storage_ix *uint, storage []byte) {
bw.rewind(storage_ix_start) var len uint = uint(-cap(end) + cap(begin))
storeMetaBlockHeader1(uint(len(data)), true, bw) rewindBitPosition1(storage_ix_start, storage_ix, storage)
bw.jumpToByteBoundary() storeMetaBlockHeader1(uint(len), true, storage_ix, storage)
bw.writeBytes(data) *storage_ix = (*storage_ix + 7) &^ 7
copy(storage[*storage_ix>>3:], begin[:len])
*storage_ix += uint(len << 3)
storage[*storage_ix>>3] = 0
} }
var kCmdHistoSeed = [128]uint32{ var kCmdHistoSeed = [128]uint32{
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
0,
} }
var compressFragmentFastImpl_kFirstBlockSize uint = 3 << 15 var compressFragmentFastImpl_kFirstBlockSize uint = 3 << 15
var compressFragmentFastImpl_kMergeBlockSize uint = 1 << 16 var compressFragmentFastImpl_kMergeBlockSize uint = 1 << 16
func compressFragmentFastImpl(in []byte, input_size uint, is_last bool, table []int, table_bits uint, cmd_depth []byte, cmd_bits []uint16, cmd_code_numbits *uint, cmd_code []byte, bw *bitWriter) { func compressFragmentFastImpl(in []byte, input_size uint, is_last bool, table []int, table_bits uint, cmd_depth []byte, cmd_bits []uint16, cmd_code_numbits *uint, cmd_code []byte, storage_ix *uint, storage []byte) {
var cmd_histo [128]uint32 var cmd_histo [128]uint32
var ip_end int var ip_end int
var next_emit int = 0 var next_emit int = 0
@ -352,7 +500,7 @@ func compressFragmentFastImpl(in []byte, input_size uint, is_last bool, table []
var metablock_start int = input var metablock_start int = input
var block_size uint = brotli_min_size_t(input_size, compressFragmentFastImpl_kFirstBlockSize) var block_size uint = brotli_min_size_t(input_size, compressFragmentFastImpl_kFirstBlockSize)
var total_block_size uint = block_size var total_block_size uint = block_size
var mlen_storage_ix uint = bw.getPos() + 3 var mlen_storage_ix uint = *storage_ix + 3
var lit_depth [256]byte var lit_depth [256]byte
var lit_bits [256]uint16 var lit_bits [256]uint16
var literal_ratio uint var literal_ratio uint
@ -369,21 +517,21 @@ func compressFragmentFastImpl(in []byte, input_size uint, is_last bool, table []
/* Save the bit position of the MLEN field of the meta-block header, so that /* Save the bit position of the MLEN field of the meta-block header, so that
we can update it later if we decide to extend this meta-block. */ we can update it later if we decide to extend this meta-block. */
storeMetaBlockHeader1(block_size, false, bw) storeMetaBlockHeader1(block_size, false, storage_ix, storage)
/* No block splits, no contexts. */ /* No block splits, no contexts. */
bw.writeBits(13, 0) writeBits(13, 0, storage_ix, storage)
literal_ratio = buildAndStoreLiteralPrefixCode(in[input:], block_size, lit_depth[:], lit_bits[:], bw) literal_ratio = buildAndStoreLiteralPrefixCode(in[input:], block_size, lit_depth[:], lit_bits[:], storage_ix, storage)
{ {
/* Store the pre-compressed command and distance prefix codes. */ /* Store the pre-compressed command and distance prefix codes. */
var i uint var i uint
for i = 0; i+7 < *cmd_code_numbits; i += 8 { for i = 0; i+7 < *cmd_code_numbits; i += 8 {
bw.writeBits(8, uint64(cmd_code[i>>3])) writeBits(8, uint64(cmd_code[i>>3]), storage_ix, storage)
} }
} }
bw.writeBits(*cmd_code_numbits&7, uint64(cmd_code[*cmd_code_numbits>>3])) writeBits(*cmd_code_numbits&7, uint64(cmd_code[*cmd_code_numbits>>3]), storage_ix, storage)
/* Initialize the command and distance histograms. We will gather /* Initialize the command and distance histograms. We will gather
statistics of command and distance codes during the processing statistics of command and distance codes during the processing
@ -482,27 +630,27 @@ emit_commands:
var insert uint = uint(base - next_emit) var insert uint = uint(base - next_emit)
ip += int(matched) ip += int(matched)
if insert < 6210 { if insert < 6210 {
emitInsertLen1(insert, cmd_depth, cmd_bits, cmd_histo[:], bw) emitInsertLen1(insert, cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage)
} else if shouldUseUncompressedMode(in[metablock_start:], in[next_emit:], insert, literal_ratio) { } else if shouldUseUncompressedMode(in[metablock_start:], in[next_emit:], insert, literal_ratio) {
emitUncompressedMetaBlock1(in[metablock_start:base], mlen_storage_ix-3, bw) emitUncompressedMetaBlock1(in[metablock_start:], in[base:], mlen_storage_ix-3, storage_ix, storage)
input_size -= uint(base - input) input_size -= uint(base - input)
input = base input = base
next_emit = input next_emit = input
goto next_block goto next_block
} else { } else {
emitLongInsertLen(insert, cmd_depth, cmd_bits, cmd_histo[:], bw) emitLongInsertLen(insert, cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage)
} }
emitLiterals(in[next_emit:], insert, lit_depth[:], lit_bits[:], bw) emitLiterals(in[next_emit:], insert, lit_depth[:], lit_bits[:], storage_ix, storage)
if distance == last_distance { if distance == last_distance {
bw.writeBits(uint(cmd_depth[64]), uint64(cmd_bits[64])) writeBits(uint(cmd_depth[64]), uint64(cmd_bits[64]), storage_ix, storage)
cmd_histo[64]++ cmd_histo[64]++
} else { } else {
emitDistance1(uint(distance), cmd_depth, cmd_bits, cmd_histo[:], bw) emitDistance1(uint(distance), cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage)
last_distance = distance last_distance = distance
} }
emitCopyLenLastDistance1(matched, cmd_depth, cmd_bits, cmd_histo[:], bw) emitCopyLenLastDistance1(matched, cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage)
next_emit = ip next_emit = ip
if ip >= ip_limit { if ip >= ip_limit {
@ -538,8 +686,8 @@ emit_commands:
} }
ip += int(matched) ip += int(matched)
last_distance = int(base - candidate) /* > 0 */ last_distance = int(base - candidate) /* > 0 */
emitCopyLen1(matched, cmd_depth, cmd_bits, cmd_histo[:], bw) emitCopyLen1(matched, cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage)
emitDistance1(uint(last_distance), cmd_depth, cmd_bits, cmd_histo[:], bw) emitDistance1(uint(last_distance), cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage)
next_emit = ip next_emit = ip
if ip >= ip_limit { if ip >= ip_limit {
@ -585,7 +733,7 @@ emit_remainder:
nibbles. */ nibbles. */
total_block_size += block_size total_block_size += block_size
bw.updateBits(20, uint32(total_block_size-1), mlen_storage_ix) updateBits(20, uint32(total_block_size-1), mlen_storage_ix, storage)
goto emit_commands goto emit_commands
} }
@ -593,13 +741,13 @@ emit_remainder:
if next_emit < ip_end { if next_emit < ip_end {
var insert uint = uint(ip_end - next_emit) var insert uint = uint(ip_end - next_emit)
if insert < 6210 { if insert < 6210 {
emitInsertLen1(insert, cmd_depth, cmd_bits, cmd_histo[:], bw) emitInsertLen1(insert, cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage)
emitLiterals(in[next_emit:], insert, lit_depth[:], lit_bits[:], bw) emitLiterals(in[next_emit:], insert, lit_depth[:], lit_bits[:], storage_ix, storage)
} else if shouldUseUncompressedMode(in[metablock_start:], in[next_emit:], insert, literal_ratio) { } else if shouldUseUncompressedMode(in[metablock_start:], in[next_emit:], insert, literal_ratio) {
emitUncompressedMetaBlock1(in[metablock_start:ip_end], mlen_storage_ix-3, bw) emitUncompressedMetaBlock1(in[metablock_start:], in[ip_end:], mlen_storage_ix-3, storage_ix, storage)
} else { } else {
emitLongInsertLen(insert, cmd_depth, cmd_bits, cmd_histo[:], bw) emitLongInsertLen(insert, cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage)
emitLiterals(in[next_emit:], insert, lit_depth[:], lit_bits[:], bw) emitLiterals(in[next_emit:], insert, lit_depth[:], lit_bits[:], storage_ix, storage)
} }
} }
@ -615,29 +763,30 @@ next_block:
/* Save the bit position of the MLEN field of the meta-block header, so that /* Save the bit position of the MLEN field of the meta-block header, so that
we can update it later if we decide to extend this meta-block. */ we can update it later if we decide to extend this meta-block. */
mlen_storage_ix = bw.getPos() + 3 mlen_storage_ix = *storage_ix + 3
storeMetaBlockHeader1(block_size, false, bw) storeMetaBlockHeader1(block_size, false, storage_ix, storage)
/* No block splits, no contexts. */ /* No block splits, no contexts. */
bw.writeBits(13, 0) writeBits(13, 0, storage_ix, storage)
literal_ratio = buildAndStoreLiteralPrefixCode(in[input:], block_size, lit_depth[:], lit_bits[:], bw) literal_ratio = buildAndStoreLiteralPrefixCode(in[input:], block_size, lit_depth[:], lit_bits[:], storage_ix, storage)
buildAndStoreCommandPrefixCode1(cmd_histo[:], cmd_depth, cmd_bits, bw) buildAndStoreCommandPrefixCode1(cmd_histo[:], cmd_depth, cmd_bits, storage_ix, storage)
goto emit_commands goto emit_commands
} }
if !is_last { if !is_last {
/* If this is not the last block, update the command and distance prefix /* If this is not the last block, update the command and distance prefix
codes for the next block and store the compressed forms. */ codes for the next block and store the compressed forms. */
var bw bitWriter cmd_code[0] = 0
bw.dst = cmd_code
buildAndStoreCommandPrefixCode1(cmd_histo[:], cmd_depth, cmd_bits, &bw) *cmd_code_numbits = 0
*cmd_code_numbits = bw.getPos() buildAndStoreCommandPrefixCode1(cmd_histo[:], cmd_depth, cmd_bits, cmd_code_numbits, cmd_code)
} }
} }
/* Compresses "input" string to bw as one or more complete meta-blocks. /* Compresses "input" string to the "*storage" buffer as one or more complete
meta-blocks, and updates the "*storage_ix" bit position.
If "is_last" is 1, emits an additional empty last meta-block. If "is_last" is 1, emits an additional empty last meta-block.
@ -658,28 +807,28 @@ next_block:
REQUIRES: "table_size" is an odd (9, 11, 13, 15) power of two REQUIRES: "table_size" is an odd (9, 11, 13, 15) power of two
OUTPUT: maximal copy distance <= |input_size| OUTPUT: maximal copy distance <= |input_size|
OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) */ OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) */
func compressFragmentFast(input []byte, input_size uint, is_last bool, table []int, table_size uint, cmd_depth []byte, cmd_bits []uint16, cmd_code_numbits *uint, cmd_code []byte, bw *bitWriter) { func compressFragmentFast(input []byte, input_size uint, is_last bool, table []int, table_size uint, cmd_depth []byte, cmd_bits []uint16, cmd_code_numbits *uint, cmd_code []byte, storage_ix *uint, storage []byte) {
var initial_storage_ix uint = bw.getPos() var initial_storage_ix uint = *storage_ix
var table_bits uint = uint(log2FloorNonZero(table_size)) var table_bits uint = uint(log2FloorNonZero(table_size))
if input_size == 0 { if input_size == 0 {
assert(is_last) assert(is_last)
bw.writeBits(1, 1) /* islast */ writeBits(1, 1, storage_ix, storage) /* islast */
bw.writeBits(1, 1) /* isempty */ writeBits(1, 1, storage_ix, storage) /* isempty */
bw.jumpToByteBoundary() *storage_ix = (*storage_ix + 7) &^ 7
return return
} }
compressFragmentFastImpl(input, input_size, is_last, table, table_bits, cmd_depth, cmd_bits, cmd_code_numbits, cmd_code, bw) compressFragmentFastImpl(input, input_size, is_last, table, table_bits, cmd_depth, cmd_bits, cmd_code_numbits, cmd_code, storage_ix, storage)
/* If output is larger than single uncompressed block, rewrite it. */ /* If output is larger than single uncompressed block, rewrite it. */
if bw.getPos()-initial_storage_ix > 31+(input_size<<3) { if *storage_ix-initial_storage_ix > 31+(input_size<<3) {
emitUncompressedMetaBlock1(input[:input_size], initial_storage_ix, bw) emitUncompressedMetaBlock1(input, input[input_size:], initial_storage_ix, storage_ix, storage)
} }
if is_last { if is_last {
bw.writeBits(1, 1) /* islast */ writeBits(1, 1, storage_ix, storage) /* islast */
bw.writeBits(1, 1) /* isempty */ writeBits(1, 1, storage_ix, storage) /* isempty */
bw.jumpToByteBoundary() *storage_ix = (*storage_ix + 7) &^ 7
} }
} }

@ -41,7 +41,7 @@ func isMatch1(p1 []byte, p2 []byte, length uint) bool {
/* Builds a command and distance prefix code (each 64 symbols) into "depth" and /* Builds a command and distance prefix code (each 64 symbols) into "depth" and
"bits" based on "histogram" and stores it into the bit stream. */ "bits" based on "histogram" and stores it into the bit stream. */
func buildAndStoreCommandPrefixCode(histogram []uint32, depth []byte, bits []uint16, bw *bitWriter) { func buildAndStoreCommandPrefixCode(histogram []uint32, depth []byte, bits []uint16, storage_ix *uint, storage []byte) {
var tree [129]huffmanTree var tree [129]huffmanTree
var cmd_depth = [numCommandSymbols]byte{0} var cmd_depth = [numCommandSymbols]byte{0}
/* Tree size for building a tree over 64 symbols is 2 * 64 + 1. */ /* Tree size for building a tree over 64 symbols is 2 * 64 + 1. */
@ -87,10 +87,10 @@ func buildAndStoreCommandPrefixCode(histogram []uint32, depth []byte, bits []uin
cmd_depth[448+8*i] = depth[16+i] cmd_depth[448+8*i] = depth[16+i]
} }
storeHuffmanTree(cmd_depth[:], numCommandSymbols, tree[:], bw) storeHuffmanTree(cmd_depth[:], numCommandSymbols, tree[:], storage_ix, storage)
} }
storeHuffmanTree(depth[64:], 64, tree[:], bw) storeHuffmanTree(depth[64:], 64, tree[:], storage_ix, storage)
} }
func emitInsertLen(insertlen uint32, commands *[]uint32) { func emitInsertLen(insertlen uint32, commands *[]uint32) {
@ -197,11 +197,11 @@ func emitDistance(distance uint32, commands *[]uint32) {
} }
/* REQUIRES: len <= 1 << 24. */ /* REQUIRES: len <= 1 << 24. */
func storeMetaBlockHeader(len uint, is_uncompressed bool, bw *bitWriter) { func storeMetaBlockHeader(len uint, is_uncompressed bool, storage_ix *uint, storage []byte) {
var nibbles uint = 6 var nibbles uint = 6
/* ISLAST */ /* ISLAST */
bw.writeBits(1, 0) writeBits(1, 0, storage_ix, storage)
if len <= 1<<16 { if len <= 1<<16 {
nibbles = 4 nibbles = 4
@ -209,11 +209,11 @@ func storeMetaBlockHeader(len uint, is_uncompressed bool, bw *bitWriter) {
nibbles = 5 nibbles = 5
} }
bw.writeBits(2, uint64(nibbles)-4) writeBits(2, uint64(nibbles)-4, storage_ix, storage)
bw.writeBits(nibbles*4, uint64(len)-1) writeBits(nibbles*4, uint64(len)-1, storage_ix, storage)
/* ISUNCOMPRESSED */ /* ISUNCOMPRESSED */
bw.writeSingleBit(is_uncompressed) writeSingleBit(is_uncompressed, storage_ix, storage)
} }
func createCommands(input []byte, block_size uint, input_size uint, base_ip_ptr []byte, table []int, table_bits uint, min_match uint, literals *[]byte, commands *[]uint32) { func createCommands(input []byte, block_size uint, input_size uint, base_ip_ptr []byte, table []int, table_bits uint, min_match uint, literals *[]byte, commands *[]uint32) {
@ -440,20 +440,163 @@ emit_remainder:
} }
var storeCommands_kNumExtraBits = [128]uint32{ var storeCommands_kNumExtraBits = [128]uint32{
0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 12, 14, 24, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 24, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 0,
9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 0,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 1,
1,
2,
2,
3,
3,
4,
4,
5,
5,
6,
7,
8,
9,
10,
12,
14,
24,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
2,
2,
3,
3,
4,
4,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
2,
2,
3,
3,
4,
4,
5,
5,
6,
7,
8,
9,
10,
24,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
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,
14,
14,
15,
15,
16,
16,
17,
17,
18,
18,
19,
19,
20,
20,
21,
21,
22,
22,
23,
23,
24,
24,
} }
var storeCommands_kInsertOffset = [24]uint32{ var storeCommands_kInsertOffset = [24]uint32{
0, 1, 2, 3, 4, 5, 6, 8, 10, 14, 18, 26, 34, 50, 66, 98, 130, 194, 322, 578, 0,
1090, 2114, 6210, 22594, 1,
2,
3,
4,
5,
6,
8,
10,
14,
18,
26,
34,
50,
66,
98,
130,
194,
322,
578,
1090,
2114,
6210,
22594,
} }
func storeCommands(literals []byte, num_literals uint, commands []uint32, num_commands uint, bw *bitWriter) { func storeCommands(literals []byte, num_literals uint, commands []uint32, num_commands uint, storage_ix *uint, storage []byte) {
var lit_depths [256]byte var lit_depths [256]byte
var lit_bits [256]uint16 var lit_bits [256]uint16
var lit_histo = [256]uint32{0} var lit_histo = [256]uint32{0}
@ -466,7 +609,7 @@ func storeCommands(literals []byte, num_literals uint, commands []uint32, num_co
} }
buildAndStoreHuffmanTreeFast(lit_histo[:], num_literals, /* max_bits = */ buildAndStoreHuffmanTreeFast(lit_histo[:], num_literals, /* max_bits = */
8, lit_depths[:], lit_bits[:], bw) 8, lit_depths[:], lit_bits[:], storage_ix, storage)
for i = 0; i < num_commands; i++ { for i = 0; i < num_commands; i++ {
var code uint32 = commands[i] & 0xFF var code uint32 = commands[i] & 0xFF
@ -478,21 +621,21 @@ func storeCommands(literals []byte, num_literals uint, commands []uint32, num_co
cmd_histo[2] += 1 cmd_histo[2] += 1
cmd_histo[64] += 1 cmd_histo[64] += 1
cmd_histo[84] += 1 cmd_histo[84] += 1
buildAndStoreCommandPrefixCode(cmd_histo[:], cmd_depths[:], cmd_bits[:], bw) buildAndStoreCommandPrefixCode(cmd_histo[:], cmd_depths[:], cmd_bits[:], storage_ix, storage)
for i = 0; i < num_commands; i++ { for i = 0; i < num_commands; i++ {
var cmd uint32 = commands[i] var cmd uint32 = commands[i]
var code uint32 = cmd & 0xFF var code uint32 = cmd & 0xFF
var extra uint32 = cmd >> 8 var extra uint32 = cmd >> 8
assert(code < 128) assert(code < 128)
bw.writeBits(uint(cmd_depths[code]), uint64(cmd_bits[code])) writeBits(uint(cmd_depths[code]), uint64(cmd_bits[code]), storage_ix, storage)
bw.writeBits(uint(storeCommands_kNumExtraBits[code]), uint64(extra)) writeBits(uint(storeCommands_kNumExtraBits[code]), uint64(extra), storage_ix, storage)
if code < 24 { if code < 24 {
var insert uint32 = storeCommands_kInsertOffset[code] + extra var insert uint32 = storeCommands_kInsertOffset[code] + extra
var j uint32 var j uint32
for j = 0; j < insert; j++ { for j = 0; j < insert; j++ {
var lit byte = literals[0] var lit byte = literals[0]
bw.writeBits(uint(lit_depths[lit]), uint64(lit_bits[lit])) writeBits(uint(lit_depths[lit]), uint64(lit_bits[lit]), storage_ix, storage)
literals = literals[1:] literals = literals[1:]
} }
} }
@ -520,13 +663,22 @@ func shouldCompress(input []byte, input_size uint, num_literals uint) bool {
} }
} }
func emitUncompressedMetaBlock(input []byte, input_size uint, bw *bitWriter) { func rewindBitPosition(new_storage_ix uint, storage_ix *uint, storage []byte) {
storeMetaBlockHeader(input_size, true, bw) var bitpos uint = new_storage_ix & 7
bw.jumpToByteBoundary() var mask uint = (1 << bitpos) - 1
bw.writeBytes(input[:input_size]) storage[new_storage_ix>>3] &= byte(mask)
*storage_ix = new_storage_ix
} }
func compressFragmentTwoPassImpl(input []byte, input_size uint, is_last bool, command_buf []uint32, literal_buf []byte, table []int, table_bits uint, min_match uint, bw *bitWriter) { func emitUncompressedMetaBlock(input []byte, input_size uint, storage_ix *uint, storage []byte) {
storeMetaBlockHeader(input_size, true, storage_ix, storage)
*storage_ix = (*storage_ix + 7) &^ 7
copy(storage[*storage_ix>>3:], input[:input_size])
*storage_ix += input_size << 3
storage[*storage_ix>>3] = 0
}
func compressFragmentTwoPassImpl(input []byte, input_size uint, is_last bool, command_buf []uint32, literal_buf []byte, table []int, table_bits uint, min_match uint, storage_ix *uint, storage []byte) {
/* Save the start of the first block for position and distance computations. /* Save the start of the first block for position and distance computations.
*/ */
var base_ip []byte = input var base_ip []byte = input
@ -540,17 +692,17 @@ func compressFragmentTwoPassImpl(input []byte, input_size uint, is_last bool, co
num_literals = uint(-cap(literals) + cap(literal_buf)) num_literals = uint(-cap(literals) + cap(literal_buf))
if shouldCompress(input, block_size, num_literals) { if shouldCompress(input, block_size, num_literals) {
var num_commands uint = uint(-cap(commands) + cap(command_buf)) var num_commands uint = uint(-cap(commands) + cap(command_buf))
storeMetaBlockHeader(block_size, false, bw) storeMetaBlockHeader(block_size, false, storage_ix, storage)
/* No block splits, no contexts. */ /* No block splits, no contexts. */
bw.writeBits(13, 0) writeBits(13, 0, storage_ix, storage)
storeCommands(literal_buf, num_literals, command_buf, num_commands, bw) storeCommands(literal_buf, num_literals, command_buf, num_commands, storage_ix, storage)
} else { } else {
/* Since we did not find many backward references and the entropy of /* Since we did not find many backward references and the entropy of
the data is close to 8 bits, we can simply emit an uncompressed block. the data is close to 8 bits, we can simply emit an uncompressed block.
This makes compression speed of uncompressible data about 3x faster. */ This makes compression speed of uncompressible data about 3x faster. */
emitUncompressedMetaBlock(input, block_size, bw) emitUncompressedMetaBlock(input, block_size, storage_ix, storage)
} }
input = input[block_size:] input = input[block_size:]
@ -558,7 +710,8 @@ func compressFragmentTwoPassImpl(input []byte, input_size uint, is_last bool, co
} }
} }
/* Compresses "input" string to bw as one or more complete meta-blocks. /* Compresses "input" string to the "*storage" buffer as one or more complete
meta-blocks, and updates the "*storage_ix" bit position.
If "is_last" is 1, emits an additional empty last meta-block. If "is_last" is 1, emits an additional empty last meta-block.
@ -570,8 +723,8 @@ func compressFragmentTwoPassImpl(input []byte, input_size uint, is_last bool, co
REQUIRES: "table_size" is a power of two REQUIRES: "table_size" is a power of two
OUTPUT: maximal copy distance <= |input_size| OUTPUT: maximal copy distance <= |input_size|
OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) */ OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) */
func compressFragmentTwoPass(input []byte, input_size uint, is_last bool, command_buf []uint32, literal_buf []byte, table []int, table_size uint, bw *bitWriter) { func compressFragmentTwoPass(input []byte, input_size uint, is_last bool, command_buf []uint32, literal_buf []byte, table []int, table_size uint, storage_ix *uint, storage []byte) {
var initial_storage_ix uint = bw.getPos() var initial_storage_ix uint = *storage_ix
var table_bits uint = uint(log2FloorNonZero(table_size)) var table_bits uint = uint(log2FloorNonZero(table_size))
var min_match uint var min_match uint
if table_bits <= 15 { if table_bits <= 15 {
@ -579,17 +732,17 @@ func compressFragmentTwoPass(input []byte, input_size uint, is_last bool, comman
} else { } else {
min_match = 6 min_match = 6
} }
compressFragmentTwoPassImpl(input, input_size, is_last, command_buf, literal_buf, table, table_bits, min_match, bw) compressFragmentTwoPassImpl(input, input_size, is_last, command_buf, literal_buf, table, table_bits, min_match, storage_ix, storage)
/* If output is larger than single uncompressed block, rewrite it. */ /* If output is larger than single uncompressed block, rewrite it. */
if bw.getPos()-initial_storage_ix > 31+(input_size<<3) { if *storage_ix-initial_storage_ix > 31+(input_size<<3) {
bw.rewind(initial_storage_ix) rewindBitPosition(initial_storage_ix, storage_ix, storage)
emitUncompressedMetaBlock(input, input_size, bw) emitUncompressedMetaBlock(input, input_size, storage_ix, storage)
} }
if is_last { if is_last {
bw.writeBits(1, 1) /* islast */ writeBits(1, 1, storage_ix, storage) /* islast */
bw.writeBits(1, 1) /* isempty */ writeBits(1, 1, storage_ix, storage) /* isempty */
bw.jumpToByteBoundary() *storage_ix = (*storage_ix + 7) &^ 7
} }
} }

@ -87,9 +87,11 @@ type Writer struct {
last_processed_pos_ uint64 last_processed_pos_ uint64
dist_cache_ [numDistanceShortCodes]int dist_cache_ [numDistanceShortCodes]int
saved_dist_cache_ [4]int saved_dist_cache_ [4]int
last_bytes_ uint16
last_bytes_bits_ byte
prev_byte_ byte prev_byte_ byte
prev_byte2_ byte prev_byte2_ byte
bw bitWriter storage []byte
small_table_ [1 << 10]int small_table_ [1 << 10]int
large_table_ []int large_table_ []int
large_table_size_ uint large_table_size_ uint
@ -139,6 +141,14 @@ func wrapPosition(position uint64) uint32 {
return result return result
} }
func (s *Writer) getStorage(size int) []byte {
if len(s.storage) < size {
s.storage = make([]byte, size)
}
return s.storage
}
func hashTableSize(max_table_size uint, input_size uint) uint { func hashTableSize(max_table_size uint, input_size uint) uint {
var htsize uint = 256 var htsize uint = 256
for htsize < max_table_size && htsize < input_size { for htsize < max_table_size && htsize < input_size {
@ -184,18 +194,23 @@ func getHashTable(s *Writer, quality int, input_size uint, table_size *uint) []i
return table return table
} }
func encodeWindowBits(lgwin int, large_window bool, bw *bitWriter) { func encodeWindowBits(lgwin int, large_window bool, last_bytes *uint16, last_bytes_bits *byte) {
if large_window { if large_window {
bw.writeBits(14, uint64((lgwin&0x3F)<<8|0x11)) *last_bytes = uint16((lgwin&0x3F)<<8 | 0x11)
*last_bytes_bits = 14
} else { } else {
if lgwin == 16 { if lgwin == 16 {
bw.writeBits(1, 0) *last_bytes = 0
*last_bytes_bits = 1
} else if lgwin == 17 { } else if lgwin == 17 {
bw.writeBits(7, 1) *last_bytes = 1
*last_bytes_bits = 7
} else if lgwin > 17 { } else if lgwin > 17 {
bw.writeBits(4, uint64((lgwin-17)<<1|0x01)) *last_bytes = uint16((lgwin-17)<<1 | 0x01)
*last_bytes_bits = 4
} else { } else {
bw.writeBits(7, uint64((lgwin-8)<<4|0x01)) *last_bytes = uint16((lgwin-8)<<4 | 0x01)
*last_bytes_bits = 7
} }
} }
} }
@ -417,15 +432,18 @@ func chooseContextMode(params *encoderParams, data []byte, pos uint, mask uint,
return contextUTF8 return contextUTF8
} }
func writeMetaBlockInternal(data []byte, mask uint, last_flush_pos uint64, bytes uint, is_last bool, literal_context_mode int, params *encoderParams, prev_byte byte, prev_byte2 byte, num_literals uint, commands []command, saved_dist_cache []int, dist_cache []int, bw *bitWriter) { func writeMetaBlockInternal(data []byte, mask uint, last_flush_pos uint64, bytes uint, is_last bool, literal_context_mode int, params *encoderParams, prev_byte byte, prev_byte2 byte, num_literals uint, commands []command, saved_dist_cache []int, dist_cache []int, storage_ix *uint, storage []byte) {
var wrapped_last_flush_pos uint32 = wrapPosition(last_flush_pos) var wrapped_last_flush_pos uint32 = wrapPosition(last_flush_pos)
var last_bytes uint16
var last_bytes_bits byte
var literal_context_lut contextLUT = getContextLUT(literal_context_mode) var literal_context_lut contextLUT = getContextLUT(literal_context_mode)
var block_params encoderParams = *params var block_params encoderParams = *params
if bytes == 0 { if bytes == 0 {
/* Write the ISLAST and ISEMPTY bits. */ /* Write the ISLAST and ISEMPTY bits. */
bw.writeBits(2, 3) writeBits(2, 3, storage_ix, storage)
bw.jumpToByteBoundary()
*storage_ix = (*storage_ix + 7) &^ 7
return return
} }
@ -434,15 +452,17 @@ func writeMetaBlockInternal(data []byte, mask uint, last_flush_pos uint64, bytes
CreateBackwardReferences is now unused. */ CreateBackwardReferences is now unused. */
copy(dist_cache, saved_dist_cache[:4]) copy(dist_cache, saved_dist_cache[:4])
storeUncompressedMetaBlock(is_last, data, uint(wrapped_last_flush_pos), mask, bytes, bw) storeUncompressedMetaBlock(is_last, data, uint(wrapped_last_flush_pos), mask, bytes, storage_ix, storage)
return return
} }
savedPos := bw.getPos() assert(*storage_ix <= 14)
last_bytes = uint16(storage[1])<<8 | uint16(storage[0])
last_bytes_bits = byte(*storage_ix)
if params.quality <= maxQualityForStaticEntropyCodes { if params.quality <= maxQualityForStaticEntropyCodes {
storeMetaBlockFast(data, uint(wrapped_last_flush_pos), bytes, mask, is_last, params, commands, bw) storeMetaBlockFast(data, uint(wrapped_last_flush_pos), bytes, mask, is_last, params, commands, storage_ix, storage)
} else if params.quality < minQualityForBlockSplit { } else if params.quality < minQualityForBlockSplit {
storeMetaBlockTrivial(data, uint(wrapped_last_flush_pos), bytes, mask, is_last, params, commands, bw) storeMetaBlockTrivial(data, uint(wrapped_last_flush_pos), bytes, mask, is_last, params, commands, storage_ix, storage)
} else { } else {
mb := getMetaBlockSplit() mb := getMetaBlockSplit()
if params.quality < minQualityForHqBlockSplitting { if params.quality < minQualityForHqBlockSplitting {
@ -469,15 +489,18 @@ func writeMetaBlockInternal(data []byte, mask uint, last_flush_pos uint64, bytes
optimizeHistograms(num_effective_dist_codes, mb) optimizeHistograms(num_effective_dist_codes, mb)
} }
storeMetaBlock(data, uint(wrapped_last_flush_pos), bytes, mask, prev_byte, prev_byte2, is_last, &block_params, literal_context_mode, commands, mb, bw) storeMetaBlock(data, uint(wrapped_last_flush_pos), bytes, mask, prev_byte, prev_byte2, is_last, &block_params, literal_context_mode, commands, mb, storage_ix, storage)
freeMetaBlockSplit(mb) freeMetaBlockSplit(mb)
} }
if bytes+4 < bw.getPos()>>3 { if bytes+4 < *storage_ix>>3 {
/* Restore the distance cache and last byte. */ /* Restore the distance cache and last byte. */
copy(dist_cache, saved_dist_cache[:4]) copy(dist_cache, saved_dist_cache[:4])
bw.rewind(savedPos)
storeUncompressedMetaBlock(is_last, data, uint(wrapped_last_flush_pos), mask, bytes, bw) storage[0] = byte(last_bytes)
storage[1] = byte(last_bytes >> 8)
*storage_ix = uint(last_bytes_bits)
storeUncompressedMetaBlock(is_last, data, uint(wrapped_last_flush_pos), mask, bytes, storage_ix, storage)
} }
} }
@ -510,10 +533,8 @@ func ensureInitialized(s *Writer) bool {
return true return true
} }
s.bw.bits = 0 s.last_bytes_bits_ = 0
s.bw.nbits = 0 s.last_bytes_ = 0
s.bw.dst = s.bw.dst[:0]
s.remaining_metadata_bytes_ = math.MaxUint32 s.remaining_metadata_bytes_ = math.MaxUint32
sanitizeParams(&s.params) sanitizeParams(&s.params)
@ -529,7 +550,7 @@ func ensureInitialized(s *Writer) bool {
lgwin = brotli_max_int(lgwin, 18) lgwin = brotli_max_int(lgwin, 18)
} }
encodeWindowBits(lgwin, s.params.large_window, &s.bw) encodeWindowBits(lgwin, s.params.large_window, &s.last_bytes_, &s.last_bytes_bits_)
} }
if s.params.quality == fastOnePassCompressionQuality { if s.params.quality == fastOnePassCompressionQuality {
@ -761,6 +782,8 @@ func encodeData(s *Writer, is_last bool, force_flush bool) bool {
} }
if s.params.quality == fastOnePassCompressionQuality || s.params.quality == fastTwoPassCompressionQuality { if s.params.quality == fastOnePassCompressionQuality || s.params.quality == fastTwoPassCompressionQuality {
var storage []byte
var storage_ix uint = uint(s.last_bytes_bits_)
var table_size uint var table_size uint
var table []int var table []int
@ -770,16 +793,20 @@ func encodeData(s *Writer, is_last bool, force_flush bool) bool {
return true return true
} }
storage = s.getStorage(int(2*bytes + 503))
storage[0] = byte(s.last_bytes_)
storage[1] = byte(s.last_bytes_ >> 8)
table = getHashTable(s, s.params.quality, uint(bytes), &table_size) table = getHashTable(s, s.params.quality, uint(bytes), &table_size)
if s.params.quality == fastOnePassCompressionQuality { if s.params.quality == fastOnePassCompressionQuality {
compressFragmentFast(data[wrapped_last_processed_pos&mask:], uint(bytes), is_last, table, table_size, s.cmd_depths_[:], s.cmd_bits_[:], &s.cmd_code_numbits_, s.cmd_code_[:], &s.bw) compressFragmentFast(data[wrapped_last_processed_pos&mask:], uint(bytes), is_last, table, table_size, s.cmd_depths_[:], s.cmd_bits_[:], &s.cmd_code_numbits_, s.cmd_code_[:], &storage_ix, storage)
} else { } else {
compressFragmentTwoPass(data[wrapped_last_processed_pos&mask:], uint(bytes), is_last, s.command_buf_, s.literal_buf_, table, table_size, &s.bw) compressFragmentTwoPass(data[wrapped_last_processed_pos&mask:], uint(bytes), is_last, s.command_buf_, s.literal_buf_, table, table_size, &storage_ix, storage)
} }
s.last_bytes_ = uint16(storage[storage_ix>>3])
s.last_bytes_bits_ = byte(storage_ix & 7)
updateLastProcessedPos(s) updateLastProcessedPos(s)
s.writeOutput(s.bw.dst) s.writeOutput(storage[:storage_ix>>3])
s.bw.dst = s.bw.dst[:0]
return true return true
} }
{ {
@ -856,7 +883,13 @@ func encodeData(s *Writer, is_last bool, force_flush bool) bool {
assert(s.input_pos_-s.last_flush_pos_ <= 1<<24) assert(s.input_pos_-s.last_flush_pos_ <= 1<<24)
{ {
var metablock_size uint32 = uint32(s.input_pos_ - s.last_flush_pos_) var metablock_size uint32 = uint32(s.input_pos_ - s.last_flush_pos_)
writeMetaBlockInternal(data, uint(mask), s.last_flush_pos_, uint(metablock_size), is_last, literal_context_mode, &s.params, s.prev_byte_, s.prev_byte2_, s.num_literals_, s.commands, s.saved_dist_cache_[:], s.dist_cache_[:], &s.bw) var storage []byte = s.getStorage(int(2*metablock_size + 503))
var storage_ix uint = uint(s.last_bytes_bits_)
storage[0] = byte(s.last_bytes_)
storage[1] = byte(s.last_bytes_ >> 8)
writeMetaBlockInternal(data, uint(mask), s.last_flush_pos_, uint(metablock_size), is_last, literal_context_mode, &s.params, s.prev_byte_, s.prev_byte2_, s.num_literals_, s.commands, s.saved_dist_cache_[:], s.dist_cache_[:], &storage_ix, storage)
s.last_bytes_ = uint16(storage[storage_ix>>3])
s.last_bytes_bits_ = byte(storage_ix & 7)
s.last_flush_pos_ = s.input_pos_ s.last_flush_pos_ = s.input_pos_
if updateLastProcessedPos(s) { if updateLastProcessedPos(s) {
hasherReset(s.hasher_) hasherReset(s.hasher_)
@ -877,22 +910,28 @@ func encodeData(s *Writer, is_last bool, force_flush bool) bool {
emitting an uncompressed block. */ emitting an uncompressed block. */
copy(s.saved_dist_cache_[:], s.dist_cache_[:]) copy(s.saved_dist_cache_[:], s.dist_cache_[:])
s.writeOutput(s.bw.dst) s.writeOutput(storage[:storage_ix>>3])
s.bw.dst = s.bw.dst[:0]
return true return true
} }
} }
/* Dumps remaining output bits and metadata header to s.bw. /* Dumps remaining output bits and metadata header to |header|.
Returns number of produced bytes.
REQUIRED: |header| should be 8-byte aligned and at least 16 bytes long.
REQUIRED: |block_size| <= (1 << 24). */ REQUIRED: |block_size| <= (1 << 24). */
func writeMetadataHeader(s *Writer, block_size uint) { func writeMetadataHeader(s *Writer, block_size uint, header []byte) uint {
bw := &s.bw var storage_ix uint
storage_ix = uint(s.last_bytes_bits_)
bw.writeBits(1, 0) header[0] = byte(s.last_bytes_)
bw.writeBits(2, 3) header[1] = byte(s.last_bytes_ >> 8)
bw.writeBits(1, 0) s.last_bytes_ = 0
s.last_bytes_bits_ = 0
writeBits(1, 0, &storage_ix, header)
writeBits(2, 3, &storage_ix, header)
writeBits(1, 0, &storage_ix, header)
if block_size == 0 { if block_size == 0 {
bw.writeBits(2, 0) writeBits(2, 0, &storage_ix, header)
} else { } else {
var nbits uint32 var nbits uint32
if block_size == 1 { if block_size == 1 {
@ -901,19 +940,34 @@ func writeMetadataHeader(s *Writer, block_size uint) {
nbits = log2FloorNonZero(uint(uint32(block_size)-1)) + 1 nbits = log2FloorNonZero(uint(uint32(block_size)-1)) + 1
} }
var nbytes uint32 = (nbits + 7) / 8 var nbytes uint32 = (nbits + 7) / 8
bw.writeBits(2, uint64(nbytes)) writeBits(2, uint64(nbytes), &storage_ix, header)
bw.writeBits(uint(8*nbytes), uint64(block_size)-1) writeBits(uint(8*nbytes), uint64(block_size)-1, &storage_ix, header)
} }
bw.jumpToByteBoundary() return (storage_ix + 7) >> 3
} }
func injectBytePaddingBlock(s *Writer) { func injectBytePaddingBlock(s *Writer) {
var seal uint32 = uint32(s.last_bytes_)
var seal_bits uint = uint(s.last_bytes_bits_)
s.last_bytes_ = 0
s.last_bytes_bits_ = 0
/* is_last = 0, data_nibbles = 11, reserved = 0, meta_nibbles = 00 */ /* is_last = 0, data_nibbles = 11, reserved = 0, meta_nibbles = 00 */
s.bw.writeBits(6, 0x6) seal |= 0x6 << seal_bits
s.bw.jumpToByteBoundary()
s.writeOutput(s.bw.dst) seal_bits += 6
s.bw.dst = s.bw.dst[:0]
destination := s.tiny_buf_.u8[:]
destination[0] = byte(seal)
if seal_bits > 8 {
destination[1] = byte(seal >> 8)
}
if seal_bits > 16 {
destination[2] = byte(seal >> 16)
}
s.writeOutput(destination[:(seal_bits+7)>>3])
} }
func checkFlushComplete(s *Writer) { func checkFlushComplete(s *Writer) {
@ -945,7 +999,7 @@ func encoderCompressStreamFast(s *Writer, op int, available_in *uint, next_in *[
} }
for { for {
if s.stream_state_ == streamFlushRequested && s.bw.nbits&7 != 0 { if s.stream_state_ == streamFlushRequested && s.last_bytes_bits_ != 0 {
injectBytePaddingBlock(s) injectBytePaddingBlock(s)
continue continue
} }
@ -957,6 +1011,9 @@ func encoderCompressStreamFast(s *Writer, op int, available_in *uint, next_in *[
var block_size uint = brotli_min_size_t(block_size_limit, *available_in) var block_size uint = brotli_min_size_t(block_size_limit, *available_in)
var is_last bool = (*available_in == block_size) && (op == int(operationFinish)) var is_last bool = (*available_in == block_size) && (op == int(operationFinish))
var force_flush bool = (*available_in == block_size) && (op == int(operationFlush)) var force_flush bool = (*available_in == block_size) && (op == int(operationFlush))
var max_out_size uint = 2*block_size + 503
var storage []byte = nil
var storage_ix uint = uint(s.last_bytes_bits_)
var table_size uint var table_size uint
var table []int var table []int
@ -965,18 +1022,25 @@ func encoderCompressStreamFast(s *Writer, op int, available_in *uint, next_in *[
continue continue
} }
storage = s.getStorage(int(max_out_size))
storage[0] = byte(s.last_bytes_)
storage[1] = byte(s.last_bytes_ >> 8)
table = getHashTable(s, s.params.quality, block_size, &table_size) table = getHashTable(s, s.params.quality, block_size, &table_size)
if s.params.quality == fastOnePassCompressionQuality { if s.params.quality == fastOnePassCompressionQuality {
compressFragmentFast(*next_in, block_size, is_last, table, table_size, s.cmd_depths_[:], s.cmd_bits_[:], &s.cmd_code_numbits_, s.cmd_code_[:], &s.bw) compressFragmentFast(*next_in, block_size, is_last, table, table_size, s.cmd_depths_[:], s.cmd_bits_[:], &s.cmd_code_numbits_, s.cmd_code_[:], &storage_ix, storage)
} else { } else {
compressFragmentTwoPass(*next_in, block_size, is_last, command_buf, literal_buf, table, table_size, &s.bw) compressFragmentTwoPass(*next_in, block_size, is_last, command_buf, literal_buf, table, table_size, &storage_ix, storage)
} }
*next_in = (*next_in)[block_size:] *next_in = (*next_in)[block_size:]
*available_in -= block_size *available_in -= block_size
s.writeOutput(s.bw.dst) var out_bytes uint = storage_ix >> 3
s.bw.dst = s.bw.dst[:0] s.writeOutput(storage[:out_bytes])
s.last_bytes_ = uint16(storage[storage_ix>>3])
s.last_bytes_bits_ = byte(storage_ix & 7)
if force_flush { if force_flush {
s.stream_state_ = streamFlushRequested s.stream_state_ = streamFlushRequested
@ -1010,7 +1074,7 @@ func processMetadata(s *Writer, available_in *uint, next_in *[]byte) bool {
} }
for { for {
if s.stream_state_ == streamFlushRequested && s.bw.nbits&7 != 0 { if s.stream_state_ == streamFlushRequested && s.last_bytes_bits_ != 0 {
injectBytePaddingBlock(s) injectBytePaddingBlock(s)
continue continue
} }
@ -1024,9 +1088,8 @@ func processMetadata(s *Writer, available_in *uint, next_in *[]byte) bool {
} }
if s.stream_state_ == streamMetadataHead { if s.stream_state_ == streamMetadataHead {
writeMetadataHeader(s, uint(s.remaining_metadata_bytes_)) n := writeMetadataHeader(s, uint(s.remaining_metadata_bytes_), s.tiny_buf_.u8[:])
s.writeOutput(s.bw.dst) s.writeOutput(s.tiny_buf_.u8[:n])
s.bw.dst = s.bw.dst[:0]
s.stream_state_ = streamMetadataBody s.stream_state_ = streamMetadataBody
continue continue
} else { } else {
@ -1112,7 +1175,7 @@ func encoderCompressStream(s *Writer, op int, available_in *uint, next_in *[]byt
continue continue
} }
if s.stream_state_ == streamFlushRequested && s.bw.nbits&7 != 0 { if s.stream_state_ == streamFlushRequested && s.last_bytes_bits_ != 0 {
injectBytePaddingBlock(s) injectBytePaddingBlock(s)
continue continue
} }

@ -778,9 +778,8 @@ var kStaticDistanceCodeDepth = [64]byte{
var kCodeLengthBits = [18]uint32{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 15, 31, 0, 11, 7} var kCodeLengthBits = [18]uint32{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 15, 31, 0, 11, 7}
func storeStaticCodeLengthCode(bw *bitWriter) { func storeStaticCodeLengthCode(storage_ix *uint, storage []byte) {
bw.writeBits(32, 0x55555554) writeBits(40, 0x0000FF55555554, storage_ix, storage)
bw.writeBits(8, 0xFF)
} }
var kZeroRepsBits = [numCommandSymbols]uint64{ var kZeroRepsBits = [numCommandSymbols]uint64{
@ -4318,10 +4317,9 @@ var kStaticCommandCodeBits = [numCommandSymbols]uint16{
2047, 2047,
} }
func storeStaticCommandHuffmanTree(bw *bitWriter) { func storeStaticCommandHuffmanTree(storage_ix *uint, storage []byte) {
bw.writeBits(32, 0x16307003) writeBits(56, 0x92624416307003, storage_ix, storage)
bw.writeBits(24, 0x926244) writeBits(3, 0x00000000, storage_ix, storage)
bw.writeBits(3, 0x00000000)
} }
var kStaticDistanceCodeBits = [64]uint16{ var kStaticDistanceCodeBits = [64]uint16{
@ -4391,6 +4389,6 @@ var kStaticDistanceCodeBits = [64]uint16{
63, 63,
} }
func storeStaticDistanceHuffmanTree(bw *bitWriter) { func storeStaticDistanceHuffmanTree(storage_ix *uint, storage []byte) {
bw.writeBits(28, 0x0369DC03) writeBits(28, 0x0369DC03, storage_ix, storage)
} }

@ -1,3 +1,5 @@
module github.com/andybalholm/brotli module github.com/andybalholm/brotli
go 1.12 go 1.12
retract v1.0.1 // occasional panics and data corruption

@ -33,7 +33,9 @@ func NewReader(src io.Reader) *Reader {
func (r *Reader) Reset(src io.Reader) error { func (r *Reader) Reset(src io.Reader) error {
decoderStateInit(r) decoderStateInit(r)
r.src = src r.src = src
r.buf = make([]byte, readBufSize) if r.buf == nil {
r.buf = make([]byte, readBufSize)
}
return nil return nil
} }

@ -1,5 +1,7 @@
package brotli package brotli
import "encoding/binary"
/* Copyright 2010 Google Inc. All Rights Reserved. /* Copyright 2010 Google Inc. All Rights Reserved.
Distributed under MIT license. Distributed under MIT license.
@ -8,87 +10,43 @@ package brotli
/* Write bits into a byte array. */ /* Write bits into a byte array. */
type bitWriter struct { /* This function writes bits into bytes in increasing addresses, and within
dst []byte a byte least-significant-bit first.
// Data waiting to be written is the low nbits of bits.
bits uint64
nbits uint
}
func (w *bitWriter) writeBits(nb uint, b uint64) { The function can write up to 56 bits in one go with WriteBits
w.bits |= b << w.nbits Example: let's assume that 3 bits (Rs below) have been written already:
w.nbits += nb
if w.nbits >= 32 {
bits := w.bits
w.bits >>= 32
w.nbits -= 32
w.dst = append(w.dst,
byte(bits),
byte(bits>>8),
byte(bits>>16),
byte(bits>>24),
)
}
}
func (w *bitWriter) writeSingleBit(bit bool) { BYTE-0 BYTE+1 BYTE+2
if bit {
w.writeBits(1, 1)
} else {
w.writeBits(1, 0)
}
}
func (w *bitWriter) jumpToByteBoundary() { 0000 0RRR 0000 0000 0000 0000
dst := w.dst
for w.nbits != 0 {
dst = append(dst, byte(w.bits))
w.bits >>= 8
if w.nbits > 8 { // Avoid underflow
w.nbits -= 8
} else {
w.nbits = 0
}
}
w.bits = 0
w.dst = dst
}
func (w *bitWriter) writeBytes(b []byte) { Now, we could write 5 or less bits in MSB by just sifting by 3
if w.nbits&7 != 0 { and OR'ing to BYTE-0.
panic("writeBytes with unfinished bits")
}
for w.nbits != 0 {
w.dst = append(w.dst, byte(w.bits))
w.bits >>= 8
w.nbits -= 8
}
w.dst = append(w.dst, b...)
}
func (w *bitWriter) getPos() uint { For n bits, we take the last 5 bits, OR that with high bits in BYTE-0,
return uint(len(w.dst)<<3) + w.nbits and locate the rest in BYTE+1, BYTE+2, etc. */
func writeBits(n_bits uint, bits uint64, pos *uint, array []byte) {
/* This branch of the code can write up to 56 bits at a time,
7 bits are lost by being perhaps already in *p and at least
1 bit is needed to initialize the bit-stream ahead (i.e. if 7
bits are in *p and we write 57 bits, then the next write will
access a byte that was never initialized). */
p := array[*pos>>3:]
v := uint64(p[0])
v |= bits << (*pos & 7)
binary.LittleEndian.PutUint64(p, v)
*pos += n_bits
} }
func (w *bitWriter) rewind(p uint) { func writeSingleBit(bit bool, pos *uint, array []byte) {
w.bits = uint64(w.dst[p>>3] & byte((1<<(p&7))-1)) if bit {
w.nbits = p & 7 writeBits(1, 1, pos, array)
w.dst = w.dst[:p>>3] } else {
writeBits(1, 0, pos, array)
}
} }
func (w *bitWriter) updateBits(n_bits uint, bits uint32, pos uint) { func writeBitsPrepareStorage(pos uint, array []byte) {
for n_bits > 0 { assert(pos&7 == 0)
var byte_pos uint = pos >> 3 array[pos>>3] = 0
var n_unchanged_bits uint = pos & 7
var n_changed_bits uint = brotli_min_size_t(n_bits, 8-n_unchanged_bits)
var total_bits uint = n_unchanged_bits + n_changed_bits
var mask uint32 = (^((1 << total_bits) - 1)) | ((1 << n_unchanged_bits) - 1)
var unchanged_bits uint32 = uint32(w.dst[byte_pos]) & mask
var changed_bits uint32 = bits & ((1 << n_changed_bits) - 1)
w.dst[byte_pos] = byte(changed_bits<<n_unchanged_bits | unchanged_bits)
n_bits -= n_changed_bits
bits >>= n_changed_bits
pos += n_changed_bits
}
} }

@ -80,7 +80,7 @@ github.com/alecthomas/chroma/lexers/x
github.com/alecthomas/chroma/lexers/y github.com/alecthomas/chroma/lexers/y
github.com/alecthomas/chroma/lexers/z github.com/alecthomas/chroma/lexers/z
github.com/alecthomas/chroma/styles github.com/alecthomas/chroma/styles
# github.com/andybalholm/brotli v1.0.1 # github.com/andybalholm/brotli v1.0.3
## explicit ## explicit
github.com/andybalholm/brotli github.com/andybalholm/brotli
# github.com/andybalholm/cascadia v1.1.0 # github.com/andybalholm/cascadia v1.1.0

Loading…
Cancel
Save