diff --git a/.gitignore b/.gitignore index f0e9b6b15d4c69..323ae2859bc1cb 100644 --- a/.gitignore +++ b/.gitignore @@ -36,7 +36,6 @@ /*.exe /*.swp /out -/*.txt # === Rules for artifacts of `./configure` === /icu_config.gypi diff --git a/BUILDING.md b/BUILDING.md index 9b0211db7e259e..a6cb0695bfdc0a 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -202,7 +202,7 @@ For use of AVX2, * nasm version 2.10 or higher in Windows Please refer to - https://www.openssl.org/docs/man1.1.1/man3/OPENSSL_ia32cap.html for details. + for details. If compiling without one of the above, use `configure` with the `--openssl-no-asm` flag. Otherwise, `configure` will fail. @@ -226,7 +226,7 @@ The Node.js project uses Python as part of its build process and has historically only been Python 2 compatible. Python 2 will reach its _end-of-life_ at the end of 2019 at which point the -interpreter will cease receiving updates. See https://python3statement.org/ +interpreter will cease receiving updates. See for more information. The Node.js project is in the process of transitioning its Python code to @@ -283,7 +283,7 @@ $ make -j4 If you run into a `No module named 'distutils.spawn'` error when executing `./configure`, please try `python3 -m pip install --upgrade setuptools` or `sudo apt install python3-distutils -y`. -For more information, see https://github.com/nodejs/node/issues/30189. +For more information, see . The `-j4` option will cause `make` to run 4 simultaneous compilation jobs which may reduce build time. For more information, see the diff --git a/CHANGELOG.md b/CHANGELOG.md index 826d8b9c3ad7d6..ce3f628efd53b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,8 @@ release. -12.16.3
+12.17.0
+12.16.3
12.16.2
12.16.1
12.16.0
diff --git a/LICENSE b/LICENSE index db59472ba13151..6b30de0fa9dec5 100644 --- a/LICENSE +++ b/LICENSE @@ -141,7 +141,7 @@ The externally maintained libraries used by Node.js are: """ COPYRIGHT AND PERMISSION NOTICE (ICU 58 and later) - Copyright © 1991-2019 Unicode, Inc. All rights reserved. + Copyright © 1991-2020 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in https://www.unicode.org/copyright.html. Permission is hereby granted, free of charge, to any person obtaining diff --git a/README.md b/README.md index 8ed51a91375928..af3a57ccaac992 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +

-Each directory name and filename contains a date (in UTC time) and the commit +Each directory name and filename contains a date (in UTC) and the commit SHA at the HEAD of the release. #### API Documentation @@ -331,6 +332,8 @@ For information about the governance of the Node.js project, see **João Reis** <reis@janeasystems.com> * [joyeecheung](https://github.com/joyeecheung) - **Joyee Cheung** <joyeec9h3@gmail.com> (she/her) +* [juanarbol](https://github.com/juanarbol) - +**Juan José Arboleda** <soyjuanarbol@gmail.com> (he/him) * [JungMinu](https://github.com/JungMinu) - **Minwoo Jung** <nodecorelab@gmail.com> (he/him) * [kfarnung](https://github.com/kfarnung) - @@ -367,6 +370,8 @@ For information about the governance of the Node.js project, see **Ouyang Yadong** <oyydoibh@gmail.com> (he/him) * [psmarshall](https://github.com/psmarshall) - **Peter Marshall** <petermarshall@chromium.org> (he/him) +* [puzpuzpuz](https://github.com/puzpuzpuz) - +**Andrey Pechkurov** <apechkurov@gmail.com> (he/him) * [Qard](https://github.com/Qard) - **Stephen Belanger** <admin@stephenbelanger.com> (he/him) * [refack](https://github.com/refack) - @@ -546,7 +551,7 @@ maintaining the Node.js project. ### Release Keys -GPG keys used to sign Node.js releases: +Primary GPG keys for Node.js Releasers (some Releasers sign with subkeys): * **Beth Griggs** <bethany.griggs@uk.ibm.com> `4ED778F539E3634C779C87C6D7062848A1AB005C` diff --git a/SECURITY.md b/SECURITY.md index 3196055ccb78e5..64714043db7e3b 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -11,8 +11,7 @@ handling your submission. After the initial reply to your report, the security team will endeavor to keep you informed of the progress being made towards a fix and full announcement, and may ask for additional information or guidance surrounding the reported -issue. These updates will be sent at least every five days; in practice, this -is more likely to be every 24-48 hours. +issue. ### Node.js Bug Bounty Program diff --git a/benchmark/.eslintrc.yaml b/benchmark/.eslintrc.yaml index 7de962dc9002af..8ce0f9f6e148c1 100644 --- a/benchmark/.eslintrc.yaml +++ b/benchmark/.eslintrc.yaml @@ -5,6 +5,7 @@ env: es6: true rules: + no-var: error comma-dangle: - error - arrays: 'always-multiline' diff --git a/benchmark/_cli.js b/benchmark/_cli.js index 771cc72bff1964..eb6c4add9799a4 100644 --- a/benchmark/_cli.js +++ b/benchmark/_cli.js @@ -6,15 +6,16 @@ const path = require('path'); // Create an object of all benchmark scripts const benchmarks = {}; fs.readdirSync(__dirname) - .filter((name) => fs.statSync(path.resolve(__dirname, name)).isDirectory()) + .filter((name) => { + return name !== 'fixtures' && + fs.statSync(path.resolve(__dirname, name)).isDirectory(); + }) .forEach((category) => { benchmarks[category] = fs.readdirSync(path.resolve(__dirname, category)) .filter((filename) => filename[0] !== '.' && filename[0] !== '_'); }); function CLI(usage, settings) { - if (!(this instanceof CLI)) return new CLI(usage, settings); - if (process.argv.length < 3) { this.abort(usage); // Abort will exit the process } @@ -22,6 +23,7 @@ function CLI(usage, settings) { this.usage = usage; this.optional = {}; this.items = []; + this.test = false; for (const argName of settings.arrayArgs) { this.optional[argName] = []; @@ -34,7 +36,7 @@ function CLI(usage, settings) { if (arg === '--') { // Only items can follow -- mode = 'item'; - } else if ('both' === mode && arg[0] === '-') { + } else if (mode === 'both' && arg[0] === '-') { // Optional arguments declaration if (arg[1] === '-') { @@ -61,6 +63,8 @@ function CLI(usage, settings) { // The next value can be either an option or an item mode = 'both'; + } else if (arg === 'test') { + this.test = true; } else if (['both', 'item'].includes(mode)) { // item arguments this.items.push(arg); @@ -83,9 +87,15 @@ CLI.prototype.abort = function(msg) { CLI.prototype.benchmarks = function() { const paths = []; + if (this.items.includes('all')) { + this.items = Object.keys(benchmarks); + } + for (const category of this.items) { - if (benchmarks[category] === undefined) - continue; + if (benchmarks[category] === undefined) { + console.error(`The "${category}" category does not exist.`); + process.exit(1); + } for (const scripts of benchmarks[category]) { if (this.shouldSkip(scripts)) continue; diff --git a/benchmark/_http-benchmarkers.js b/benchmark/_http-benchmarkers.js index 821dab2d55e683..d0f192e75948b6 100644 --- a/benchmark/_http-benchmarkers.js +++ b/benchmark/_http-benchmarkers.js @@ -43,9 +43,8 @@ class AutocannonBenchmarker { } if (!result || !result.requests || !result.requests.average) { return undefined; - } else { - return result.requests.average; } + return result.requests.average; } } @@ -58,10 +57,13 @@ class WrkBenchmarker { } create(options) { + const duration = typeof options.duration === 'number' ? + Math.max(options.duration, 1) : + options.duration; const args = [ - '-d', options.duration, + '-d', duration, '-c', options.connections, - '-t', 8, + '-t', Math.min(options.connections, require('os').cpus().length || 8), `http://127.0.0.1:${options.port}${options.path}`, ]; for (const field in options.headers) { @@ -77,9 +79,8 @@ class WrkBenchmarker { const throughput = match && +match[1]; if (!isFinite(throughput)) { return undefined; - } else { - return throughput; } + return throughput; } } @@ -89,7 +90,8 @@ class WrkBenchmarker { */ class TestDoubleBenchmarker { constructor(type) { - // `type` is the type ofbenchmarker. Possible values are 'http' and 'http2'. + // `type` is the type of benchmarker. Possible values are 'http' and + // 'http2'. this.name = `test-double-${type}`; this.executable = path.resolve(__dirname, '_test-double-benchmarker.js'); this.present = fs.existsSync(this.executable); @@ -97,10 +99,12 @@ class TestDoubleBenchmarker { } create(options) { - const env = Object.assign({ - duration: options.duration, + process.env.duration = process.env.duration || options.duration || 5; + + const env = { test_url: `http://127.0.0.1:${options.port}${options.path}`, - }, process.env); + ...process.env + }; const child = child_process.fork(this.executable, [this.type], @@ -189,13 +193,14 @@ http_benchmarkers.forEach((benchmarker) => { }); exports.run = function(options, callback) { - options = Object.assign({ + options = { port: exports.PORT, path: '/', connections: 100, duration: 5, benchmarker: exports.default_http_benchmarker, - }, options); + ...options + }; if (!options.benchmarker) { callback(new Error('Could not locate required http benchmarker. See ' + `${requirementsURL} for further instructions.`)); @@ -220,7 +225,8 @@ exports.run = function(options, callback) { child.stderr.pipe(process.stderr); let stdout = ''; - child.stdout.on('data', (chunk) => stdout += chunk.toString()); + child.stdout.setEncoding('utf8'); + child.stdout.on('data', (chunk) => stdout += chunk); child.once('close', (code) => { const elapsed = process.hrtime(benchmarker_start); diff --git a/benchmark/_test-double-benchmarker.js b/benchmark/_test-double-benchmarker.js index b9379b907ffa07..60264dfd46a606 100644 --- a/benchmark/_test-double-benchmarker.js +++ b/benchmark/_test-double-benchmarker.js @@ -7,7 +7,7 @@ if (!['http', 'http2'].includes(myModule)) { const http = require(myModule); -const duration = process.env.duration || 0; +const duration = +process.env.duration; const url = process.env.test_url; const start = process.hrtime(); @@ -18,13 +18,15 @@ function request(res, client) { res.on('error', () => {}); res.on('end', () => { throughput++; - const diff = process.hrtime(start); - if (duration > 0 && diff[0] < duration) { + const [sec, nanosec] = process.hrtime(start); + const ms = sec * 1000 + nanosec / 1e6; + if (ms < duration * 1000) { run(); } else { console.log(JSON.stringify({ throughput })); if (client) { client.destroy(); + process.exit(0); } } }); @@ -33,7 +35,7 @@ function request(res, client) { function run() { if (http.get) { // HTTP http.get(url, request); - } else { // HTTP/2 + } else { // HTTP/2 const client = http.connect(url); client.on('error', (e) => { throw e; }); request(client.request(), client); diff --git a/benchmark/async_hooks/async-resource-vs-destroy.js b/benchmark/async_hooks/async-resource-vs-destroy.js new file mode 100644 index 00000000000000..52e5e543a6a08d --- /dev/null +++ b/benchmark/async_hooks/async-resource-vs-destroy.js @@ -0,0 +1,184 @@ +'use strict'; + +const { promisify } = require('util'); +const { readFile } = require('fs'); +const sleep = promisify(setTimeout); +const read = promisify(readFile); +const common = require('../common.js'); +const { + createHook, + executionAsyncResource, + executionAsyncId, + AsyncLocalStorage +} = require('async_hooks'); +const { createServer } = require('http'); + +const bench = common.createBenchmark(main, { + type: ['async-resource', 'destroy', 'async-local-storage'], + asyncMethod: ['callbacks', 'async'], + path: '/', + connections: 500, + duration: 5, + n: [1e6] +}); + +function buildCurrentResource(getServe) { + const server = createServer(getServe(getCLS, setCLS)); + const hook = createHook({ init }); + const cls = Symbol('cls'); + hook.enable(); + + return { + server, + close + }; + + function getCLS() { + const resource = executionAsyncResource(); + if (!resource[cls]) { + return null; + } + return resource[cls].state; + } + + function setCLS(state) { + const resource = executionAsyncResource(); + if (!resource[cls]) { + resource[cls] = { state }; + } else { + resource[cls].state = state; + } + } + + function init(asyncId, type, triggerAsyncId, resource) { + const cr = executionAsyncResource(); + if (cr !== null) { + resource[cls] = cr[cls]; + } + } + + function close() { + hook.disable(); + server.close(); + } +} + +function buildDestroy(getServe) { + const transactions = new Map(); + const server = createServer(getServe(getCLS, setCLS)); + const hook = createHook({ init, destroy }); + hook.enable(); + + return { + server, + close + }; + + function getCLS() { + const asyncId = executionAsyncId(); + return transactions.has(asyncId) ? transactions.get(asyncId) : null; + } + + function setCLS(value) { + const asyncId = executionAsyncId(); + transactions.set(asyncId, value); + } + + function init(asyncId, type, triggerAsyncId, resource) { + transactions.set(asyncId, getCLS()); + } + + function destroy(asyncId) { + transactions.delete(asyncId); + } + + function close() { + hook.disable(); + server.close(); + } +} + +function buildAsyncLocalStorage(getServe) { + const asyncLocalStorage = new AsyncLocalStorage(); + const server = createServer((req, res) => { + asyncLocalStorage.run({}, () => { + getServe(getCLS, setCLS)(req, res); + }); + }); + + return { + server, + close + }; + + function getCLS() { + const store = asyncLocalStorage.getStore(); + if (store === undefined) { + return null; + } + return store.state; + } + + function setCLS(state) { + const store = asyncLocalStorage.getStore(); + if (store === undefined) { + return; + } + store.state = state; + } + + function close() { + asyncLocalStorage.disable(); + server.close(); + } +} + +function getServeAwait(getCLS, setCLS) { + return async function serve(req, res) { + setCLS(Math.random()); + await sleep(10); + await read(__filename); + res.setHeader('content-type', 'application/json'); + res.end(JSON.stringify({ cls: getCLS() })); + }; +} + +function getServeCallbacks(getCLS, setCLS) { + return function serve(req, res) { + setCLS(Math.random()); + setTimeout(() => { + readFile(__filename, () => { + res.setHeader('content-type', 'application/json'); + res.end(JSON.stringify({ cls: getCLS() })); + }); + }, 10); + }; +} + +const types = { + 'async-resource': buildCurrentResource, + 'destroy': buildDestroy, + 'async-local-storage': buildAsyncLocalStorage +}; + +const asyncMethods = { + 'callbacks': getServeCallbacks, + 'async': getServeAwait +}; + +function main({ type, asyncMethod, connections, duration, path }) { + const { server, close } = types[type](asyncMethods[asyncMethod]); + + server + .listen(common.PORT) + .on('listening', () => { + + bench.http({ + path, + connections, + duration + }, () => { + close(); + }); + }); +} diff --git a/benchmark/async_hooks/http-server.js b/benchmark/async_hooks/http-server.js index 9e1c1214240eaa..c8e44849b7466f 100644 --- a/benchmark/async_hooks/http-server.js +++ b/benchmark/async_hooks/http-server.js @@ -3,10 +3,11 @@ const common = require('../common.js'); const bench = common.createBenchmark(main, { asyncHooks: ['init', 'before', 'after', 'all', 'disabled', 'none'], - connections: [50, 500] + connections: [50, 500], + duration: 5 }); -function main({ asyncHooks, connections }) { +function main({ asyncHooks, connections, duration }) { if (asyncHooks !== 'none') { let hooks = { init() {}, @@ -33,6 +34,7 @@ function main({ asyncHooks, connections }) { bench.http({ connections, path, + duration }, () => { server.close(); }); diff --git a/benchmark/buffers/buffer-base64-encode.js b/benchmark/buffers/buffer-base64-encode.js index d8b601bbd181f4..9837828a353c2d 100644 --- a/benchmark/buffers/buffer-base64-encode.js +++ b/benchmark/buffers/buffer-base64-encode.js @@ -25,6 +25,8 @@ const common = require('../common.js'); const bench = common.createBenchmark(main, { len: [64 * 1024 * 1024], n: [32] +}, { + test: { len: 256 } }); function main({ n, len }) { diff --git a/benchmark/buffers/buffer-swap.js b/benchmark/buffers/buffer-swap.js index 87eb13f48ffae6..e43957efbdb095 100644 --- a/benchmark/buffers/buffer-swap.js +++ b/benchmark/buffers/buffer-swap.js @@ -7,6 +7,8 @@ const bench = common.createBenchmark(main, { method: ['swap16', 'swap32', 'swap64'/* , 'htons', 'htonl', 'htonll' */], len: [64, 256, 768, 1024, 2056, 8192], n: [1e6] +}, { + test: { len: 16 } }); // The htons and htonl methods below are used to benchmark the diff --git a/benchmark/common.js b/benchmark/common.js index 62cd4023c1d860..701a8d6c34f07f 100644 --- a/benchmark/common.js +++ b/benchmark/common.js @@ -4,43 +4,83 @@ const child_process = require('child_process'); const http_benchmarkers = require('./_http-benchmarkers.js'); class Benchmark { - constructor(fn, configs, options) { - // Use the file name as the name of the benchmark - this.name = require.main.filename.slice(__dirname.length + 1); + // Used to make sure a benchmark only start a timer once + #started = false; + + // Indicate that the benchmark ended + #ended = false; + + // Holds process.hrtime value + #time = [0, 0]; + + // Use the file name as the name of the benchmark + name = require.main.filename.slice(__dirname.length + 1); + + // Execution arguments i.e. flags used to run the jobs + flags = process.env.NODE_BENCHMARK_FLAGS ? + process.env.NODE_BENCHMARK_FLAGS.split(/\s+/) : + []; + + constructor(fn, configs, options = {}) { // Parse job-specific configuration from the command line arguments - const parsed_args = this._parseArgs(process.argv.slice(2), configs); + const argv = process.argv.slice(2); + const parsed_args = this._parseArgs(argv, configs, options); this.options = parsed_args.cli; this.extra_options = parsed_args.extra; + if (options.flags) { + this.flags = this.flags.concat(options.flags); + } + // The configuration list as a queue of jobs this.queue = this._queue(this.options); + // The configuration of the current job, head of the queue this.config = this.queue[0]; - // Execution arguments i.e. flags used to run the jobs - this.flags = []; - if (options && options.flags) { - this.flags = this.flags.concat(options.flags); - } - if (process.env.NODE_BENCHMARK_FLAGS) { - const flags = process.env.NODE_BENCHMARK_FLAGS.split(/\s+/); - this.flags = this.flags.concat(flags); - } - // Holds process.hrtime value - this._time = [0, 0]; - // Used to make sure a benchmark only start a timer once - this._started = false; - this._ended = false; - - // this._run will use fork() to create a new process for each configuration - // combination. - if (process.env.hasOwnProperty('NODE_RUN_BENCHMARK_FN')) { - process.nextTick(() => fn(this.config)); - } else { - process.nextTick(() => this._run()); - } + + process.nextTick(() => { + if (process.env.hasOwnProperty('NODE_RUN_BENCHMARK_FN')) { + fn(this.config); + } else { + // _run will use fork() to create a new process for each configuration + // combination. + this._run(); + } + }); } - _parseArgs(argv, configs) { + _parseArgs(argv, configs, options) { const cliOptions = {}; + + // Check for the test mode first. + const testIndex = argv.indexOf('--test'); + if (testIndex !== -1) { + for (const [key, rawValue] of Object.entries(configs)) { + let value = Array.isArray(rawValue) ? rawValue[0] : rawValue; + // Set numbers to one by default to reduce the runtime. + if (typeof value === 'number') { + if (key === 'dur' || key === 'duration') { + value = 0.05; + } else if (value > 1) { + value = 1; + } + } + cliOptions[key] = [value]; + } + // Override specific test options. + if (options.test) { + for (const [key, value] of Object.entries(options.test)) { + cliOptions[key] = Array.isArray(value) ? value : [value]; + } + } + argv.splice(testIndex, 1); + } else { + // Accept single values instead of arrays. + for (const [key, value] of Object.entries(configs)) { + if (!Array.isArray(value)) + configs[key] = [value]; + } + } + const extraOptions = {}; const validArgRE = /^(.+?)=([\s\S]*)$/; // Parse configuration arguments @@ -50,45 +90,43 @@ class Benchmark { console.error(`bad argument: ${arg}`); process.exit(1); } - const config = match[1]; - - if (configs[config]) { - // Infer the type from the config object and parse accordingly - const isNumber = typeof configs[config][0] === 'number'; - const value = isNumber ? +match[2] : match[2]; - if (!cliOptions[config]) - cliOptions[config] = []; - cliOptions[config].push(value); + const [, key, value] = match; + if (Object.prototype.hasOwnProperty.call(configs, key)) { + if (!cliOptions[key]) + cliOptions[key] = []; + cliOptions[key].push( + // Infer the type from the config object and parse accordingly + typeof configs[key][0] === 'number' ? +value : value + ); } else { - extraOptions[config] = match[2]; + extraOptions[key] = value; } } - return { cli: Object.assign({}, configs, cliOptions), extra: extraOptions }; + return { cli: { ...configs, ...cliOptions }, extra: extraOptions }; } _queue(options) { const queue = []; const keys = Object.keys(options); - // Perform a depth-first walk though all options to generate a + // Perform a depth-first walk through all options to generate a // configuration list that contains all combinations. function recursive(keyIndex, prevConfig) { const key = keys[keyIndex]; const values = options[key]; - const type = typeof values[0]; for (const value of values) { if (typeof value !== 'number' && typeof value !== 'string') { throw new TypeError( `configuration "${key}" had type ${typeof value}`); } - if (typeof value !== type) { + if (typeof value !== typeof values[0]) { // This is a requirement for being able to consistently and // predictably parse CLI provided configuration values. throw new TypeError(`configuration "${key}" has mixed types`); } - const currConfig = Object.assign({ [key]: value }, prevConfig); + const currConfig = { [key]: value, ...prevConfig }; if (keyIndex + 1 < keys.length) { recursive(keyIndex + 1, currConfig); @@ -108,12 +146,11 @@ class Benchmark { } http(options, cb) { - const self = this; - const http_options = Object.assign({ }, options); + const http_options = { ...options }; http_options.benchmarker = http_options.benchmarker || - self.config.benchmarker || - self.extra_options.benchmarker || - exports.default_http_benchmarker; + this.config.benchmarker || + this.extra_options.benchmarker || + http_benchmarkers.default_http_benchmarker; http_benchmarkers.run( http_options, (error, code, used_benchmarker, result, elapsed) => { if (cb) { @@ -123,14 +160,13 @@ class Benchmark { console.error(error); process.exit(code || 1); } - self.config.benchmarker = used_benchmarker; - self.report(result, elapsed); + this.config.benchmarker = used_benchmarker; + this.report(result, elapsed); } ); } _run() { - const self = this; // If forked, report to the parent. if (process.send) { process.send({ @@ -140,27 +176,27 @@ class Benchmark { }); } - (function recursive(queueIndex) { - const config = self.queue[queueIndex]; + const recursive = (queueIndex) => { + const config = this.queue[queueIndex]; // Set NODE_RUN_BENCHMARK_FN to indicate that the child shouldn't // construct a configuration queue, but just execute the benchmark // function. - const childEnv = Object.assign({}, process.env); + const childEnv = { ...process.env }; childEnv.NODE_RUN_BENCHMARK_FN = ''; // Create configuration arguments const childArgs = []; - for (const key of Object.keys(config)) { - childArgs.push(`${key}=${config[key]}`); + for (const [key, value] of Object.entries(config)) { + childArgs.push(`${key}=${value}`); } - for (const key of Object.keys(self.extra_options)) { - childArgs.push(`${key}=${self.extra_options[key]}`); + for (const [key, value] of Object.entries(this.extra_options)) { + childArgs.push(`${key}=${value}`); } const child = child_process.fork(require.main.filename, childArgs, { env: childEnv, - execArgv: self.flags.concat(process.execArgv), + execArgv: this.flags.concat(process.execArgv), }); child.on('message', sendResult); child.on('close', (code) => { @@ -168,29 +204,31 @@ class Benchmark { process.exit(code); } - if (queueIndex + 1 < self.queue.length) { + if (queueIndex + 1 < this.queue.length) { recursive(queueIndex + 1); } }); - })(0); + }; + + recursive(0); } start() { - if (this._started) { + if (this.#started) { throw new Error('Called start more than once in a single benchmark'); } - this._started = true; - this._time = process.hrtime(); + this.#started = true; + this.#time = process.hrtime(); } end(operations) { // Get elapsed time now and do error checking later for accuracy. - const elapsed = process.hrtime(this._time); + const elapsed = process.hrtime(this.#time); - if (!this._started) { + if (!this.#started) { throw new Error('called end without start'); } - if (this._ended) { + if (this.#ended) { throw new Error('called end multiple times'); } if (typeof operations !== 'number') { @@ -206,7 +244,7 @@ class Benchmark { elapsed[1] = 1; } - this._ended = true; + this.#ended = true; const time = elapsed[0] + elapsed[1] / 1e9; const rate = operations / time; this.report(rate, elapsed); @@ -216,7 +254,7 @@ class Benchmark { sendResult({ name: this.name, conf: this.config, - rate: rate, + rate, time: elapsed[0] + elapsed[1] / 1e9, type: 'report', }); @@ -230,7 +268,7 @@ function formatResult(data) { conf += ` ${key}=${JSON.stringify(data.conf[key])}`; } - var rate = data.rate.toString().split('.'); + let rate = data.rate.toString().split('.'); rate[0] = rate[0].replace(/(\d)(?=(?:\d\d\d)+(?!\d))/g, '$1,'); rate = (rate[1] ? rate.join('.') : rate[0]); return `${data.name}${conf}: ${rate}`; @@ -334,6 +372,7 @@ function bakeUrlData(type, e = 0, withBase = false, asUrl = false) { } module.exports = { + Benchmark, PORT: http_benchmarkers.PORT, bakeUrlData, binding(bindingName) { @@ -349,8 +388,6 @@ module.exports = { createBenchmark(fn, configs, options) { return new Benchmark(fn, configs, options); }, - // Benchmark an http server. - default_http_benchmarker: http_benchmarkers.default_http_benchmarker, sendResult, searchParams, urlDataTypes: Object.keys(urls).concat(['wpt']), diff --git a/benchmark/compare.js b/benchmark/compare.js index 53f82bb4b9f1b9..5c9cd03be3fdee 100644 --- a/benchmark/compare.js +++ b/benchmark/compare.js @@ -9,7 +9,7 @@ const BenchmarkProgress = require('./_benchmark_progress.js'); // // Parse arguments // -const cli = CLI(`usage: ./node compare.js [options] [--] ... +const cli = new CLI(`usage: ./node compare.js [options] [--] ... Run each benchmark in the directory many times using two different node versions. More than one directory can be specified. The output is formatted as csv, which can be processed using for diff --git a/benchmark/crypto/cipher-stream.js b/benchmark/crypto/cipher-stream.js index a51f72be8b8d17..47a8931a540447 100644 --- a/benchmark/crypto/cipher-stream.js +++ b/benchmark/crypto/cipher-stream.js @@ -7,6 +7,8 @@ const bench = common.createBenchmark(main, { type: ['asc', 'utf', 'buf'], len: [2, 1024, 102400, 1024 * 1024], api: ['legacy', 'stream'] +}, { + flags: ['--no-warnings'] }); function main({ api, cipher, type, len, writes }) { diff --git a/benchmark/dns/lookup.js b/benchmark/dns/lookup.js index 164e490bd3bc24..691daa8a879e2b 100644 --- a/benchmark/dns/lookup.js +++ b/benchmark/dns/lookup.js @@ -10,7 +10,7 @@ const bench = common.createBenchmark(main, { }); function main({ name, n, all }) { - var i = 0; + let i = 0; if (all === 'true') { const opts = { all: true }; diff --git a/benchmark/fs/read-stream-throughput.js b/benchmark/fs/read-stream-throughput.js index de840d2d2fa3e1..c6b4ecb166ac65 100644 --- a/benchmark/fs/read-stream-throughput.js +++ b/benchmark/fs/read-stream-throughput.js @@ -8,19 +8,18 @@ const filename = path.resolve(process.env.NODE_TMPDIR || __dirname, const fs = require('fs'); const assert = require('assert'); -let encodingType, encoding, size, filesize; - const bench = common.createBenchmark(main, { encodingType: ['buf', 'asc', 'utf'], - filesize: [1000 * 1024 * 1024], - size: [1024, 4096, 65535, 1024 * 1024] + filesize: [1000 * 1024], + highWaterMark: [1024, 4096, 65535, 1024 * 1024], + n: 1024 }); function main(conf) { - encodingType = conf.encodingType; - size = conf.size; - filesize = conf.filesize; + const { encodingType, highWaterMark, filesize } = conf; + let { n } = conf; + let encoding = ''; switch (encodingType) { case 'buf': encoding = null; @@ -35,34 +34,8 @@ function main(conf) { throw new Error(`invalid encodingType: ${encodingType}`); } - makeFile(); -} - -function runTest() { - assert(fs.statSync(filename).size === filesize); - const rs = fs.createReadStream(filename, { - highWaterMark: size, - encoding: encoding - }); - - rs.on('open', () => { - bench.start(); - }); - - let bytes = 0; - rs.on('data', (chunk) => { - bytes += chunk.length; - }); - - rs.on('end', () => { - try { fs.unlinkSync(filename); } catch {} - // MB/sec - bench.end(bytes / (1024 * 1024)); - }); -} - -function makeFile() { - const buf = Buffer.allocUnsafe(filesize / 1024); + // Make file + const buf = Buffer.allocUnsafe(filesize); if (encoding === 'utf8') { // ü for (let i = 0; i < buf.length; i++) { @@ -75,16 +48,38 @@ function makeFile() { } try { fs.unlinkSync(filename); } catch {} - let w = 1024; const ws = fs.createWriteStream(filename); - ws.on('close', runTest); + ws.on('close', runTest.bind(null, filesize, highWaterMark, encoding, n)); ws.on('drain', write); write(); function write() { do { - w--; - } while (false !== ws.write(buf) && w > 0); - if (w === 0) + n--; + } while (false !== ws.write(buf) && n > 0); + if (n === 0) ws.end(); } } + +function runTest(filesize, highWaterMark, encoding, n) { + assert(fs.statSync(filename).size === filesize * n); + const rs = fs.createReadStream(filename, { + highWaterMark, + encoding + }); + + rs.on('open', () => { + bench.start(); + }); + + let bytes = 0; + rs.on('data', (chunk) => { + bytes += chunk.length; + }); + + rs.on('end', () => { + try { fs.unlinkSync(filename); } catch {} + // MB/sec + bench.end(bytes / (1024 * 1024)); + }); +} diff --git a/benchmark/fs/readfile.js b/benchmark/fs/readfile.js index 43393bf1b33ef3..25d87622bcba02 100644 --- a/benchmark/fs/readfile.js +++ b/benchmark/fs/readfile.js @@ -11,12 +11,12 @@ const fs = require('fs'); const assert = require('assert'); const bench = common.createBenchmark(main, { - dur: [5], + duration: [5], len: [1024, 16 * 1024 * 1024], concurrent: [1, 10] }); -function main({ len, dur, concurrent }) { +function main({ len, duration, concurrent }) { try { fs.unlinkSync(filename); } catch {} let data = Buffer.alloc(len, 'x'); fs.writeFileSync(filename, data); @@ -30,7 +30,7 @@ function main({ len, dur, concurrent }) { bench.end(reads); try { fs.unlinkSync(filename); } catch {} process.exit(0); - }, dur * 1000); + }, duration * 1000); function read() { fs.readFile(filename, afterRead); diff --git a/benchmark/http/chunked.js b/benchmark/http/chunked.js index 52b4605715c322..9ae7bb7495f29a 100644 --- a/benchmark/http/chunked.js +++ b/benchmark/http/chunked.js @@ -13,10 +13,11 @@ const common = require('../common.js'); const bench = common.createBenchmark(main, { n: [1, 4, 8, 16], len: [1, 64, 256], - c: [100] + c: [100], + duration: 5 }); -function main({ len, n, c }) { +function main({ len, n, c, duration }) { const http = require('http'); const chunk = Buffer.alloc(len, '8'); @@ -33,7 +34,8 @@ function main({ len, n, c }) { server.listen(common.PORT, () => { bench.http({ - connections: c + connections: c, + duration }, () => { server.close(); }); diff --git a/benchmark/http/cluster.js b/benchmark/http/cluster.js index 3bcd061a0894c5..0d97b516ec506b 100644 --- a/benchmark/http/cluster.js +++ b/benchmark/http/cluster.js @@ -9,14 +9,15 @@ if (cluster.isMaster) { // Unicode confuses ab on os x. type: ['bytes', 'buffer'], len: [4, 1024, 102400], - c: [50, 500] + c: [50, 500], + duration: 5, }); } else { const port = parseInt(process.env.PORT || PORT); require('../fixtures/simple-http-server.js').listen(port); } -function main({ type, len, c }) { +function main({ type, len, c, duration }) { process.env.PORT = PORT; let workers = 0; const w1 = cluster.fork(); @@ -32,7 +33,8 @@ function main({ type, len, c }) { bench.http({ path: path, - connections: c + connections: c, + duration }, () => { w1.destroy(); w2.destroy(); diff --git a/benchmark/http/end-vs-write-end.js b/benchmark/http/end-vs-write-end.js index 38e9b89a97a6b4..60174ef3adf4f2 100644 --- a/benchmark/http/end-vs-write-end.js +++ b/benchmark/http/end-vs-write-end.js @@ -14,10 +14,11 @@ const bench = common.createBenchmark(main, { type: ['asc', 'utf', 'buf'], len: [64 * 1024, 128 * 1024, 256 * 1024, 1024 * 1024], c: [100], - method: ['write', 'end'] + method: ['write', 'end'], + duration: 5 }); -function main({ len, type, method, c }) { +function main({ len, type, method, c, duration }) { const http = require('http'); let chunk; switch (type) { @@ -49,7 +50,8 @@ function main({ len, type, method, c }) { server.listen(common.PORT, () => { bench.http({ - connections: c + connections: c, + duration }, () => { server.close(); }); diff --git a/benchmark/http/headers.js b/benchmark/http/headers.js index f8014a6a085d19..b83ac17e742a2e 100644 --- a/benchmark/http/headers.js +++ b/benchmark/http/headers.js @@ -6,9 +6,10 @@ const http = require('http'); const bench = common.createBenchmark(main, { n: [10, 1000], len: [1, 100], + duration: 5 }); -function main({ len, n }) { +function main({ len, n, duration }) { const headers = { 'Connection': 'keep-alive', 'Transfer-Encoding': 'chunked', @@ -29,7 +30,8 @@ function main({ len, n }) { server.listen(common.PORT, () => { bench.http({ path: '/', - connections: 10 + connections: 10, + duration }, () => { server.close(); }); diff --git a/benchmark/http/incoming_headers.js b/benchmark/http/incoming_headers.js index 810c92687bd981..983bd5632fcb7d 100644 --- a/benchmark/http/incoming_headers.js +++ b/benchmark/http/incoming_headers.js @@ -3,12 +3,13 @@ const common = require('../common.js'); const http = require('http'); const bench = common.createBenchmark(main, { - c: [50], // Concurrent connections - n: [20], // Number of header lines to append after the common headers - w: [0, 6], // Amount of trailing whitespace + connections: [50], // Concurrent connections + headers: [20], // Number of header lines to append after the common headers + w: [0, 6], // Amount of trailing whitespace + duration: 5 }); -function main({ c, n, w }) { +function main({ connections, headers, w, duration }) { const server = http.createServer((req, res) => { res.end(); }); @@ -21,7 +22,7 @@ function main({ c, n, w }) { 'Date': new Date().toString(), 'Cache-Control': 'no-cache' }; - for (let i = 0; i < n; i++) { + for (let i = 0; i < headers; i++) { // Note: // - autocannon does not send header values with OWS // - wrk can only send trailing OWS. This is a side-effect of wrk @@ -31,8 +32,9 @@ function main({ c, n, w }) { } bench.http({ path: '/', - connections: c, - headers + connections, + headers, + duration }, () => { server.close(); }); diff --git a/benchmark/http/set-header.js b/benchmark/http/set-header.js index 1909c0991dfc71..48e0163a6ced10 100644 --- a/benchmark/http/set-header.js +++ b/benchmark/http/set-header.js @@ -3,7 +3,8 @@ const common = require('../common.js'); const PORT = common.PORT; const bench = common.createBenchmark(main, { - res: ['normal', 'setHeader', 'setHeaderWH'] + res: ['normal', 'setHeader', 'setHeaderWH'], + duration: 5 }); const type = 'bytes'; @@ -15,16 +16,17 @@ const c = 50; // normal: writeHead(status, {...}) // setHeader: statusCode = status, setHeader(...) x2 // setHeaderWH: setHeader(...), writeHead(status, ...) -function main({ res }) { +function main({ res, duration }) { process.env.PORT = PORT; const server = require('../fixtures/simple-http-server.js') .listen(PORT) .on('listening', () => { - const path = `/${type}/${len}/${chunks}/normal/${chunkedEnc}`; + const path = `/${type}/${len}/${chunks}/${res}/${chunkedEnc}`; bench.http({ path: path, - connections: c + connections: c, + duration }, () => { server.close(); }); diff --git a/benchmark/http/simple.js b/benchmark/http/simple.js index 95409faa9a869c..095b15ca4465fb 100644 --- a/benchmark/http/simple.js +++ b/benchmark/http/simple.js @@ -7,18 +7,20 @@ const bench = common.createBenchmark(main, { len: [4, 1024, 102400], chunks: [1, 4], c: [50, 500], - chunkedEnc: [1, 0] + chunkedEnc: [1, 0], + duration: 5 }); -function main({ type, len, chunks, c, chunkedEnc, res }) { +function main({ type, len, chunks, c, chunkedEnc, duration }) { const server = require('../fixtures/simple-http-server.js') .listen(common.PORT) .on('listening', () => { const path = `/${type}/${len}/${chunks}/normal/${chunkedEnc}`; bench.http({ - path: path, - connections: c + path, + connections: c, + duration }, () => { server.close(); }); diff --git a/benchmark/http2/compat.js b/benchmark/http2/compat.js index 5d06ccf3178257..2c7e732b07f0a5 100644 --- a/benchmark/http2/compat.js +++ b/benchmark/http2/compat.js @@ -9,10 +9,11 @@ const bench = common.createBenchmark(main, { requests: [100, 1000, 5000], streams: [1, 10, 20, 40, 100, 200], clients: [2], - benchmarker: ['h2load'] + benchmarker: ['test-double-http2'], + duration: 5 }, { flags: ['--no-warnings'] }); -function main({ requests, streams, clients }) { +function main({ requests, streams, clients, duration }) { const http2 = require('http2'); const server = http2.createServer(); server.on('request', (req, res) => { @@ -29,7 +30,8 @@ function main({ requests, streams, clients }) { requests, maxConcurrentStreams: streams, clients, - threads: clients + threads: clients, + duration }, () => { server.close(); }); }); } diff --git a/benchmark/http2/respond-with-fd.js b/benchmark/http2/respond-with-fd.js index 35856490f7e4a2..5bf5988d16a64c 100644 --- a/benchmark/http2/respond-with-fd.js +++ b/benchmark/http2/respond-with-fd.js @@ -10,10 +10,11 @@ const bench = common.createBenchmark(main, { requests: [100, 1000, 5000], streams: [1, 10, 20, 40, 100, 200], clients: [2], - benchmarker: ['h2load'] + benchmarker: ['test-double-http2'], + duration: 5 }, { flags: ['--no-warnings'] }); -function main({ requests, streams, clients }) { +function main({ requests, streams, clients, duration }) { fs.open(file, 'r', (err, fd) => { if (err) throw err; @@ -30,6 +31,7 @@ function main({ requests, streams, clients }) { requests, maxConcurrentStreams: streams, clients, + duration, threads: clients }, () => server.close()); }); diff --git a/benchmark/http2/simple.js b/benchmark/http2/simple.js index aab7c6b609b715..929c4c655e1295 100644 --- a/benchmark/http2/simple.js +++ b/benchmark/http2/simple.js @@ -9,10 +9,11 @@ const bench = common.createBenchmark(main, { requests: [100, 1000, 5000], streams: [1, 10, 20, 40, 100, 200], clients: [2], - benchmarker: ['h2load'] + benchmarker: ['test-double-http2'], + duration: 5 }, { flags: ['--no-warnings'] }); -function main({ requests, streams, clients }) { +function main({ requests, streams, clients, duration }) { const http2 = require('http2'); const server = http2.createServer(); server.on('stream', (stream) => { @@ -27,6 +28,7 @@ function main({ requests, streams, clients }) { requests, maxConcurrentStreams: streams, clients, + duration, threads: clients }, () => { server.close(); }); }); diff --git a/benchmark/http2/write.js b/benchmark/http2/write.js index fc3203c6e55451..7ea8b2c02da650 100644 --- a/benchmark/http2/write.js +++ b/benchmark/http2/write.js @@ -6,10 +6,11 @@ const bench = common.createBenchmark(main, { streams: [100, 200, 1000], length: [64 * 1024, 128 * 1024, 256 * 1024, 1024 * 1024], size: [100000], - benchmarker: ['h2load'] + benchmarker: ['test-double-http2'], + duration: 5 }, { flags: ['--no-warnings'] }); -function main({ streams, length, size }) { +function main({ streams, length, size, duration }) { const http2 = require('http2'); const server = http2.createServer(); server.on('stream', (stream) => { @@ -29,6 +30,7 @@ function main({ streams, length, size }) { bench.http({ path: '/', requests: 10000, + duration, maxConcurrentStreams: streams, }, () => { server.close(); }); }); diff --git a/benchmark/misc/trace.js b/benchmark/misc/trace.js index 3808375579bfa6..8620e99329b224 100644 --- a/benchmark/misc/trace.js +++ b/benchmark/misc/trace.js @@ -6,7 +6,11 @@ const bench = common.createBenchmark(main, { n: [100000], method: ['trace', 'isTraceCategoryEnabled'] }, { - flags: ['--expose-internals', '--trace-event-categories', 'foo'] + flags: [ + '--expose-internals', + '--no-warnings', + '--trace-event-categories', 'foo', + ] }); const { diff --git a/benchmark/net/net-c2s.js b/benchmark/net/net-c2s.js index cacd6815630b2e..424c8f6dd072b3 100644 --- a/benchmark/net/net-c2s.js +++ b/benchmark/net/net-c2s.js @@ -9,6 +9,8 @@ const bench = common.createBenchmark(main, { len: [64, 102400, 1024 * 1024 * 16], type: ['utf', 'asc', 'buf'], dur: [5], +}, { + test: { len: 1024 } }); let chunk; diff --git a/benchmark/net/net-pipe.js b/benchmark/net/net-pipe.js index d86ff73041d845..32e1085299a2ce 100644 --- a/benchmark/net/net-pipe.js +++ b/benchmark/net/net-pipe.js @@ -9,6 +9,8 @@ const bench = common.createBenchmark(main, { len: [2, 64, 102400, 1024 * 1024 * 16], type: ['utf', 'asc', 'buf'], dur: [5], +}, { + test: { len: 1024 } }); let chunk; diff --git a/benchmark/net/net-s2c.js b/benchmark/net/net-s2c.js index 789eadf0a18dba..835cc67567bcf2 100644 --- a/benchmark/net/net-s2c.js +++ b/benchmark/net/net-s2c.js @@ -10,6 +10,8 @@ const bench = common.createBenchmark(main, { recvbuflen: [0, 64 * 1024, 1024 * 1024], recvbufgenfn: ['true', 'false'], dur: [5] +}, { + test: { sendchunklen: 256 } }); let chunk; diff --git a/benchmark/net/net-wrap-js-stream-passthrough.js b/benchmark/net/net-wrap-js-stream-passthrough.js index 0d7be36c6aa545..3824cfb9c0e03c 100644 --- a/benchmark/net/net-wrap-js-stream-passthrough.js +++ b/benchmark/net/net-wrap-js-stream-passthrough.js @@ -9,6 +9,7 @@ const bench = common.createBenchmark(main, { type: ['utf', 'asc', 'buf'], dur: [5], }, { + test: { len: 64 }, flags: ['--expose-internals'] }); diff --git a/benchmark/net/tcp-raw-c2s.js b/benchmark/net/tcp-raw-c2s.js index b8af124a7f40fc..9547c01f38bc32 100644 --- a/benchmark/net/tcp-raw-c2s.js +++ b/benchmark/net/tcp-raw-c2s.js @@ -12,7 +12,10 @@ const bench = common.createBenchmark(main, { len: [102400, 1024 * 1024 * 16], type: ['utf', 'asc', 'buf'], dur: [5] -}, { flags: [ '--expose-internals', '--no-warnings' ] }); +}, { + test: { len: 1024 }, + flags: [ '--expose-internals', '--no-warnings' ] +}); function main({ dur, len, type }) { const { diff --git a/benchmark/net/tcp-raw-pipe.js b/benchmark/net/tcp-raw-pipe.js index 249b61046a84cf..e422ff749fd545 100644 --- a/benchmark/net/tcp-raw-pipe.js +++ b/benchmark/net/tcp-raw-pipe.js @@ -13,6 +13,7 @@ const bench = common.createBenchmark(main, { type: ['utf', 'asc', 'buf'], dur: [5] }, { + test: { len: 1024 }, flags: [ '--expose-internals', '--no-warnings' ] }); diff --git a/benchmark/net/tcp-raw-s2c.js b/benchmark/net/tcp-raw-s2c.js index 393cf060489cb8..be7279ca0c315c 100644 --- a/benchmark/net/tcp-raw-s2c.js +++ b/benchmark/net/tcp-raw-s2c.js @@ -13,6 +13,7 @@ const bench = common.createBenchmark(main, { type: ['utf', 'asc', 'buf'], dur: [5] }, { + test: { len: 1024 }, flags: [ '--expose-internals', '--no-warnings' ] }); diff --git a/benchmark/run.js b/benchmark/run.js index 8e81a2c5e16ab7..aa7c71bdd4ecd3 100644 --- a/benchmark/run.js +++ b/benchmark/run.js @@ -4,7 +4,7 @@ const path = require('path'); const fork = require('child_process').fork; const CLI = require('./_cli.js'); -const cli = CLI(`usage: ./node run.js [options] [--] ... +const cli = new CLI(`usage: ./node run.js [options] [--] ... Run each benchmark in the directory a single time, more than one directory can be specified. @@ -14,6 +14,9 @@ const cli = CLI(`usage: ./node run.js [options] [--] ... repeated) --set variable=value set benchmark variable (can be repeated) --format [simple|csv] optional value that specifies the output format + test only run a single configuration from the options + matrix + all each benchmark category is run one after the other `, { arrayArgs: ['set', 'filter', 'exclude'] }); const benchmarks = cli.benchmarks(); @@ -37,7 +40,11 @@ if (format === 'csv') { (function recursive(i) { const filename = benchmarks[i]; - const child = fork(path.resolve(__dirname, filename), cli.optional.set); + const child = fork( + path.resolve(__dirname, filename), + cli.test ? ['--test'] : [], + cli.optional.set + ); if (format !== 'csv') { console.log(); @@ -51,16 +58,16 @@ if (format === 'csv') { // Construct configuration string, " A=a, B=b, ..." let conf = ''; for (const key of Object.keys(data.conf)) { - conf += ` ${key}=${JSON.stringify(data.conf[key])}`; + if (conf !== '') + conf += ' '; + conf += `${key}=${JSON.stringify(data.conf[key])}`; } - // Delete first space of the configuration - conf = conf.slice(1); if (format === 'csv') { // Escape quotes (") for correct csv formatting conf = conf.replace(/"/g, '""'); console.log(`"${data.name}", "${conf}", ${data.rate}, ${data.time}`); } else { - var rate = data.rate.toString().split('.'); + let rate = data.rate.toString().split('.'); rate[0] = rate[0].replace(/(\d)(?=(?:\d\d\d)+(?!\d))/g, '$1,'); rate = (rate[1] ? rate.join('.') : rate[0]); console.log(`${data.name} ${conf}: ${rate}`); diff --git a/benchmark/scatter.js b/benchmark/scatter.js index 10649e6bb51e97..ecbf8e0041c837 100644 --- a/benchmark/scatter.js +++ b/benchmark/scatter.js @@ -7,7 +7,7 @@ const CLI = require('./_cli.js'); // // Parse arguments // -const cli = CLI(`usage: ./node scatter.js [options] [--] +const cli = new CLI(`usage: ./node scatter.js [options] [--] Run the benchmark script many times and output the rate (ops/s) together with the benchmark variables as a csv. diff --git a/benchmark/timers/immediate.js b/benchmark/timers/immediate.js index d12106a0e030fc..3bd4c097dce5a0 100644 --- a/benchmark/timers/immediate.js +++ b/benchmark/timers/immediate.js @@ -31,7 +31,7 @@ function main({ n, type }) { // setImmediate tail recursion, 0 arguments function depth(N) { - var n = 0; + let n = 0; bench.start(); setImmediate(cb); function cb() { @@ -45,7 +45,7 @@ function depth(N) { // setImmediate tail recursion, 1 argument function depth1(N) { - var n = 0; + let n = 0; bench.start(); setImmediate(cb, 1); function cb(a1) { @@ -59,7 +59,7 @@ function depth1(N) { // Concurrent setImmediate, 0 arguments function breadth(N) { - var n = 0; + let n = 0; bench.start(); function cb() { n++; @@ -73,7 +73,7 @@ function breadth(N) { // Concurrent setImmediate, 1 argument function breadth1(N) { - var n = 0; + let n = 0; bench.start(); function cb(a1) { n++; @@ -88,7 +88,7 @@ function breadth1(N) { // Concurrent setImmediate, 4 arguments function breadth4(N) { N /= 2; - var n = 0; + let n = 0; bench.start(); function cb(a1, a2, a3, a4) { n++; diff --git a/benchmark/timers/timers-breadth-args.js b/benchmark/timers/timers-breadth-args.js index 63a301dc9bc7dc..bf1727ab865b6d 100644 --- a/benchmark/timers/timers-breadth-args.js +++ b/benchmark/timers/timers-breadth-args.js @@ -6,7 +6,7 @@ const bench = common.createBenchmark(main, { }); function main({ n }) { - var j = 0; + let j = 0; function cb1(arg1) { j++; if (j === n) diff --git a/benchmark/timers/timers-breadth.js b/benchmark/timers/timers-breadth.js index 78bd5a97ae84b8..7af5d380018898 100644 --- a/benchmark/timers/timers-breadth.js +++ b/benchmark/timers/timers-breadth.js @@ -6,7 +6,7 @@ const bench = common.createBenchmark(main, { }); function main({ n }) { - var j = 0; + let j = 0; bench.start(); function cb() { j++; diff --git a/benchmark/timers/timers-cancel-pooled.js b/benchmark/timers/timers-cancel-pooled.js index 5045983210263e..30dbd7bc007d7a 100644 --- a/benchmark/timers/timers-cancel-pooled.js +++ b/benchmark/timers/timers-cancel-pooled.js @@ -8,11 +8,11 @@ const bench = common.createBenchmark(main, { function main({ n }) { - var timer = setTimeout(() => {}, 1); + let timer = setTimeout(() => {}, 1); for (let i = 0; i < n; i++) { setTimeout(cb, 1); } - var next = timer._idlePrev; + let next = timer._idlePrev; clearTimeout(timer); bench.start(); diff --git a/benchmark/timers/timers-cancel-unpooled.js b/benchmark/timers/timers-cancel-unpooled.js index df203ee4810b1d..70f8fd96c9cbf1 100644 --- a/benchmark/timers/timers-cancel-unpooled.js +++ b/benchmark/timers/timers-cancel-unpooled.js @@ -14,14 +14,13 @@ function main({ n, direction }) { timersList.push(setTimeout(cb, i + 1)); } - var j; bench.start(); if (direction === 'start') { - for (j = 0; j < n; j++) { + for (let j = 0; j < n; j++) { clearTimeout(timersList[j]); } } else { - for (j = n - 1; j >= 0; j--) { + for (let j = n - 1; j >= 0; j--) { clearTimeout(timersList[j]); } } diff --git a/benchmark/timers/timers-depth.js b/benchmark/timers/timers-depth.js index bfc6dd02cf5c65..766733ba1862a9 100644 --- a/benchmark/timers/timers-depth.js +++ b/benchmark/timers/timers-depth.js @@ -6,7 +6,7 @@ const bench = common.createBenchmark(main, { }); function main({ n }) { - var i = 0; + let i = 0; bench.start(); setTimeout(cb, 1); function cb() { diff --git a/benchmark/timers/timers-insert-unpooled.js b/benchmark/timers/timers-insert-unpooled.js index 11d25d5fe79670..5ee255b5e15fd2 100644 --- a/benchmark/timers/timers-insert-unpooled.js +++ b/benchmark/timers/timers-insert-unpooled.js @@ -10,14 +10,13 @@ const bench = common.createBenchmark(main, { function main({ direction, n }) { const timersList = []; - var i; bench.start(); if (direction === 'start') { - for (i = 1; i <= n; i++) { + for (let i = 1; i <= n; i++) { timersList.push(setTimeout(cb, i)); } } else { - for (i = n; i > 0; i--) { + for (let i = n; i > 0; i--) { timersList.push(setTimeout(cb, i)); } } diff --git a/benchmark/tls/convertprotocols.js b/benchmark/tls/convertprotocols.js index 74bb942bfcec4f..87c447436a44db 100644 --- a/benchmark/tls/convertprotocols.js +++ b/benchmark/tls/convertprotocols.js @@ -9,7 +9,7 @@ const bench = common.createBenchmark(main, { function main({ n }) { const input = ['ABC', 'XYZ123', 'FOO']; - var m = {}; + let m = {}; // First call dominates results if (n > 1) { tls.convertALPNProtocols(input, m); diff --git a/benchmark/tls/secure-pair.js b/benchmark/tls/secure-pair.js index bb7933d837f999..76658fc3c42ad7 100644 --- a/benchmark/tls/secure-pair.js +++ b/benchmark/tls/secure-pair.js @@ -4,6 +4,8 @@ const bench = common.createBenchmark(main, { dur: [5], securing: ['SecurePair', 'TLSSocket', 'clear'], size: [100, 1024, 1024 * 1024] +}, { + flags: ['--no-warnings'] }); const fixtures = require('../../test/common/fixtures'); diff --git a/benchmark/tls/throughput.js b/benchmark/tls/throughput.js index 3ea84aa84ef453..f3a96abcbc0174 100644 --- a/benchmark/tls/throughput.js +++ b/benchmark/tls/throughput.js @@ -7,12 +7,12 @@ const bench = common.createBenchmark(main, { }); const fixtures = require('../../test/common/fixtures'); -var options; +let options; const tls = require('tls'); function main({ dur, type, size }) { - var encoding; - var chunk; + let encoding; + let chunk; switch (type) { case 'buf': chunk = Buffer.alloc(size, 'b'); @@ -37,7 +37,7 @@ function main({ dur, type, size }) { }; const server = tls.createServer(options, onConnection); - var conn; + let conn; server.listen(common.PORT, () => { const opt = { port: common.PORT, rejectUnauthorized: false }; conn = tls.connect(opt, () => { @@ -52,7 +52,7 @@ function main({ dur, type, size }) { } }); - var received = 0; + let received = 0; function onConnection(conn) { conn.on('data', (chunk) => { received += chunk.length; diff --git a/benchmark/tls/tls-connect.js b/benchmark/tls/tls-connect.js index 1cb04d98a52721..3fc2ecb614978b 100644 --- a/benchmark/tls/tls-connect.js +++ b/benchmark/tls/tls-connect.js @@ -8,11 +8,11 @@ const bench = common.createBenchmark(main, { dur: [5] }); -var clientConn = 0; -var serverConn = 0; -var dur; -var concurrency; -var running = true; +let clientConn = 0; +let serverConn = 0; +let dur; +let concurrency; +let running = true; function main(conf) { dur = conf.dur; diff --git a/benchmark/url/legacy-vs-whatwg-url-parse.js b/benchmark/url/legacy-vs-whatwg-url-parse.js index 6e5e25d231242f..94115d1305bb95 100644 --- a/benchmark/url/legacy-vs-whatwg-url-parse.js +++ b/benchmark/url/legacy-vs-whatwg-url-parse.js @@ -13,7 +13,7 @@ const bench = common.createBenchmark(main, { function useLegacy(data) { const len = data.length; - var result = url.parse(data[0]); // Avoid dead code elimination + let result = url.parse(data[0]); // Avoid dead code elimination bench.start(); for (let i = 0; i < len; ++i) { result = url.parse(data[i]); @@ -24,7 +24,7 @@ function useLegacy(data) { function useWHATWGWithBase(data) { const len = data.length; - var result = new URL(data[0][0], data[0][1]); // Avoid dead code elimination + let result = new URL(data[0][0], data[0][1]); // Avoid dead code elimination bench.start(); for (let i = 0; i < len; ++i) { const item = data[i]; @@ -36,7 +36,7 @@ function useWHATWGWithBase(data) { function useWHATWGWithoutBase(data) { const len = data.length; - var result = new URL(data[0]); // Avoid dead code elimination + let result = new URL(data[0]); // Avoid dead code elimination bench.start(); for (let i = 0; i < len; ++i) { result = new URL(data[i]); @@ -47,8 +47,8 @@ function useWHATWGWithoutBase(data) { function main({ e, method, type, withBase }) { withBase = withBase === 'true'; - var noDead; // Avoid dead code elimination. - var data; + let noDead; // Avoid dead code elimination. + let data; switch (method) { case 'legacy': data = common.bakeUrlData(type, e, false, false); diff --git a/benchmark/url/legacy-vs-whatwg-url-serialize.js b/benchmark/url/legacy-vs-whatwg-url-serialize.js index 5523e549ceb233..e3254ede3acee8 100644 --- a/benchmark/url/legacy-vs-whatwg-url-serialize.js +++ b/benchmark/url/legacy-vs-whatwg-url-serialize.js @@ -13,7 +13,7 @@ const bench = common.createBenchmark(main, { function useLegacy(data) { const obj = url.parse(data[0]); const len = data.length; - var noDead = url.format(obj); + let noDead = url.format(obj); bench.start(); for (let i = 0; i < len; i++) { noDead = data[i].toString(); @@ -25,7 +25,7 @@ function useLegacy(data) { function useWHATWG(data) { const obj = new URL(data[0]); const len = data.length; - var noDead = obj.toString(); + let noDead = obj.toString(); bench.start(); for (let i = 0; i < len; i++) { noDead = data[i].toString(); @@ -37,7 +37,7 @@ function useWHATWG(data) { function main({ type, e, method }) { const data = common.bakeUrlData(type, e, false, false); - var noDead; // Avoid dead code elimination. + let noDead; // Avoid dead code elimination. switch (method) { case 'legacy': noDead = useLegacy(data); diff --git a/benchmark/url/whatwg-url-properties.js b/benchmark/url/whatwg-url-properties.js index ac71ff4f636d66..f0ba2931e51f1e 100644 --- a/benchmark/url/whatwg-url-properties.js +++ b/benchmark/url/whatwg-url-properties.js @@ -12,7 +12,7 @@ const bench = common.createBenchmark(main, { function setAndGet(data, prop) { const len = data.length; - var result = data[0][prop]; + let result = data[0][prop]; bench.start(); for (let i = 0; i < len; ++i) { result = data[i][prop]; @@ -24,7 +24,7 @@ function setAndGet(data, prop) { function get(data, prop) { const len = data.length; - var result = data[0][prop]; + let result = data[0][prop]; bench.start(); for (let i = 0; i < len; ++i) { result = data[i][prop]; // get diff --git a/benchmark/util/inspect-array.js b/benchmark/util/inspect-array.js index 987b40479184d2..958030d99bd192 100644 --- a/benchmark/util/inspect-array.js +++ b/benchmark/util/inspect-array.js @@ -15,8 +15,8 @@ const bench = common.createBenchmark(main, { }); function main({ n, len, type }) { - var arr = Array(len); - var i, opts; + let arr = Array(len); + let opts; switch (type) { case 'denseArray_showHidden': @@ -29,14 +29,14 @@ function main({ n, len, type }) { case 'sparseArray': break; case 'mixedArray': - for (i = 0; i < n; i += 2) + for (let i = 0; i < n; i += 2) arr[i] = i; break; default: throw new Error(`Unsupported type ${type}`); } bench.start(); - for (i = 0; i < n; i++) { + for (let i = 0; i < n; i++) { util.inspect(arr, opts); } bench.end(n); diff --git a/benchmark/util/inspect.js b/benchmark/util/inspect.js index 159d831f762884..0a19e65ea234be 100644 --- a/benchmark/util/inspect.js +++ b/benchmark/util/inspect.js @@ -37,7 +37,7 @@ function benchmark(n, obj, options) { } function main({ method, n, option }) { - var obj; + let obj; const options = opts[option]; switch (method) { case 'Object': diff --git a/benchmark/util/normalize-encoding.js b/benchmark/util/normalize-encoding.js index 464bda52f35c44..03769cb3b229cb 100644 --- a/benchmark/util/normalize-encoding.js +++ b/benchmark/util/normalize-encoding.js @@ -46,11 +46,11 @@ function getInput(input) { function main({ input, n }) { const { normalizeEncoding } = require('internal/util'); const inputs = getInput(input); - var noDead = ''; + let noDead = ''; bench.start(); - for (var i = 0; i < n; ++i) { - for (var j = 0; j < inputs.length; ++j) { + for (let i = 0; i < n; ++i) { + for (let j = 0; j < inputs.length; ++j) { noDead = normalizeEncoding(inputs[j]); } } diff --git a/benchmark/util/type-check.js b/benchmark/util/type-check.js index 49cef48fe144db..792f61cf6fb217 100644 --- a/benchmark/util/type-check.js +++ b/benchmark/util/type-check.js @@ -31,7 +31,7 @@ const bench = common.createBenchmark(main, { argument: ['true', 'false-primitive', 'false-object'], n: [1e5] }, { - flags: ['--expose-internals'] + flags: ['--expose-internals', '--no-warnings'] }); function main({ type, argument, version, n }) { diff --git a/benchmark/worker/echo.js b/benchmark/worker/echo.js index 8d45a1f76b5eac..7988ffc7e121eb 100644 --- a/benchmark/worker/echo.js +++ b/benchmark/worker/echo.js @@ -55,7 +55,7 @@ function main({ n, workers, sendsPerBroadcast: sends, payload: payloadType }) { return; } for (const worker of workerObjs) { - for (var i = 0; i < sends; ++i) + for (let i = 0; i < sends; ++i) worker.postMessage(payload); } } diff --git a/benchmark/zlib/createInflate.js b/benchmark/zlib/createInflate.js new file mode 100644 index 00000000000000..30ccaef7a14fb2 --- /dev/null +++ b/benchmark/zlib/createInflate.js @@ -0,0 +1,32 @@ +'use strict'; +const common = require('../common.js'); +const zlib = require('zlib'); + +const bench = common.createBenchmark(main, { + inputLen: [16 * 1024 * 1024], + chunkLen: [1024], + n: [1e2] +}); + +function main({ n, inputLen, chunkLen }) { + const input = zlib.deflateSync(Buffer.alloc(inputLen, 'a')); + + let i = 0; + bench.start(); + (function next() { + let p = 0; + const inflater = zlib.createInflate(); + inflater.resume(); + inflater.on('finish', () => { + if (i++ === n) + return bench.end(n); + next(); + }); + + (function nextChunk() { + if (p >= input.length) + return inflater.end(); + inflater.write(input.slice(p, p += chunkLen), nextChunk); + })(); + })(); +} diff --git a/benchmark/zlib/creation.js b/benchmark/zlib/creation.js index 30e6afe6b4355f..c2d063c20d8d02 100644 --- a/benchmark/zlib/creation.js +++ b/benchmark/zlib/creation.js @@ -15,17 +15,16 @@ function main({ n, type, options }) { const fn = zlib[`create${type}`]; if (typeof fn !== 'function') throw new Error('Invalid zlib type'); - var i = 0; if (options === 'true') { const opts = {}; bench.start(); - for (; i < n; ++i) + for (let i = 0; i < n; ++i) fn(opts); bench.end(n); } else { bench.start(); - for (; i < n; ++i) + for (let i = 0; i < n; ++i) fn(); bench.end(n); } diff --git a/benchmark/zlib/deflate.js b/benchmark/zlib/deflate.js index 5e86d659803747..5baedc924d4bc8 100644 --- a/benchmark/zlib/deflate.js +++ b/benchmark/zlib/deflate.js @@ -9,13 +9,15 @@ const bench = common.createBenchmark(main, { }); function main({ n, method, inputLen }) { + // Default method value for testing. + method = method || 'deflate'; const chunk = Buffer.alloc(inputLen, 'a'); - var i = 0; switch (method) { // Performs `n` writes for a single deflate stream - case 'createDeflate': - var deflater = zlib.createDeflate(); + case 'createDeflate': { + let i = 0; + const deflater = zlib.createDeflate(); deflater.resume(); deflater.on('finish', () => { bench.end(n); @@ -28,9 +30,11 @@ function main({ n, method, inputLen }) { deflater.write(chunk, next); })(); break; + } // Performs `n` single deflate operations - case 'deflate': - var deflate = zlib.deflate; + case 'deflate': { + let i = 0; + const deflate = zlib.deflate; bench.start(); (function next(err, result) { if (i++ === n) @@ -38,14 +42,16 @@ function main({ n, method, inputLen }) { deflate(chunk, next); })(); break; + } // Performs `n` single deflateSync operations - case 'deflateSync': - var deflateSync = zlib.deflateSync; + case 'deflateSync': { + const deflateSync = zlib.deflateSync; bench.start(); - for (; i < n; ++i) + for (let i = 0; i < n; ++i) deflateSync(chunk); bench.end(n); break; + } default: throw new Error('Unsupported deflate method'); } diff --git a/benchmark/zlib/inflate.js b/benchmark/zlib/inflate.js new file mode 100644 index 00000000000000..09379c00c1250b --- /dev/null +++ b/benchmark/zlib/inflate.js @@ -0,0 +1,39 @@ +'use strict'; +const common = require('../common.js'); +const zlib = require('zlib'); + +const bench = common.createBenchmark(main, { + method: ['inflate', 'inflateSync'], + inputLen: [1024], + n: [4e5] +}); + +function main({ n, method, inputLen }) { + // Default method value for tests. + method = method || 'inflate'; + const chunk = zlib.deflateSync(Buffer.alloc(inputLen, 'a')); + + let i = 0; + switch (method) { + // Performs `n` single inflate operations + case 'inflate': + const inflate = zlib.inflate; + bench.start(); + (function next(err, result) { + if (i++ === n) + return bench.end(n); + inflate(chunk, next); + })(); + break; + // Performs `n` single inflateSync operations + case 'inflateSync': + const inflateSync = zlib.inflateSync; + bench.start(); + for (; i < n; ++i) + inflateSync(chunk); + bench.end(n); + break; + default: + throw new Error('Unsupported inflate method'); + } +} diff --git a/benchmark/zlib/pipe.js b/benchmark/zlib/pipe.js index 6a1c427bc8380b..76b0ddc6c65a25 100644 --- a/benchmark/zlib/pipe.js +++ b/benchmark/zlib/pipe.js @@ -8,6 +8,11 @@ const bench = common.createBenchmark(main, { duration: [5], type: ['string', 'buffer'], algorithm: ['gzip', 'brotli'] +}, { + test: { + inputLen: 1024, + duration: 0.2 + } }); function main({ inputLen, duration, type, algorithm }) { diff --git a/common.gypi b/common.gypi index fd3c4738baea1c..7b97fbebe2deac 100644 --- a/common.gypi +++ b/common.gypi @@ -34,7 +34,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.35', + 'v8_embedder_string': '-node.37', ##### V8 defaults for Node.js ##### @@ -235,7 +235,10 @@ 'RuntimeLibrary': '<(MSVC_runtimeType)', 'RuntimeTypeInfo': 'false', } - } + }, + 'xcode_settings': { + 'GCC_OPTIMIZATION_LEVEL': '3', # stop gyp from defaulting to -Os + }, } }, @@ -315,8 +318,9 @@ 'cflags+': [ '-fno-omit-frame-pointer', '-fsanitize=address', - '-DLEAK_SANITIZER' + '-fsanitize-address-use-after-scope', ], + 'defines': [ 'LEAK_SANITIZER', 'V8_USE_ADDRESS_SANITIZER' ], 'cflags!': [ '-fomit-frame-pointer' ], 'ldflags': [ '-fsanitize=address' ], }], diff --git a/configure.py b/configure.py index af20d6108e48ac..0e72ed24ccecbe 100755 --- a/configure.py +++ b/configure.py @@ -427,13 +427,12 @@ parser.add_option('--use-largepages', action='store_true', dest='node_use_large_pages', - help='build with Large Pages support. This feature is supported only on Linux kernel' + - '>= 2.6.38 with Transparent Huge pages enabled and FreeBSD') + help='This option has no effect. --use-largepages is now a runtime option.') parser.add_option('--use-largepages-script-lld', action='store_true', dest='node_use_large_pages_script_lld', - help='link against the LLVM ld linker script. Implies -fuse-ld=lld in the linker flags') + help='This option has no effect. --use-largepages is now a runtime option.') intl_optgroup.add_option('--with-intl', action='store', @@ -533,12 +532,12 @@ dest='without_npm', help='do not install the bundled npm (package manager)') +# Dummy option for backwards compatibility parser.add_option('--without-report', action='store_true', - dest='without_report', - help='build without report') + dest='unused_without_report', + help=optparse.SUPPRESS_HELP) -# Dummy option for backwards compatibility parser.add_option('--with-snapshot', action='store_true', dest='unused_with_snapshot', @@ -630,6 +629,18 @@ default=False, help='compile V8 with minimal optimizations and with runtime checks') +parser.add_option('--v8-with-dchecks', + action='store_true', + dest='v8_with_dchecks', + default=False, + help='compile V8 with debug checks and runtime debugging features enabled') + +parser.add_option('--node-builtin-modules-path', + action='store', + dest='node_builtin_modules_path', + default=False, + help='node will load builtin modules from disk instead of from binary') + # Create compile_commands.json in out/Debug and out/Release. parser.add_option('-C', action='store_true', @@ -999,7 +1010,6 @@ def configure_node(o): o['variables']['OS'] = 'android' o['variables']['node_prefix'] = options.prefix o['variables']['node_install_npm'] = b(not options.without_npm) - o['variables']['node_report'] = b(not options.without_report) o['variables']['debug_node'] = b(options.debug_node) o['default_configuration'] = 'Debug' if options.debug else 'Release' @@ -1023,18 +1033,18 @@ def configure_node(o): o['variables']['want_separate_host_toolset'] = int( cross_compiling and want_snapshots) - if not options.without_node_snapshot: + if options.without_node_snapshot or options.node_builtin_modules_path: + o['variables']['node_use_node_snapshot'] = 'false' + else: o['variables']['node_use_node_snapshot'] = b( not cross_compiling and want_snapshots and not options.shared) - else: - o['variables']['node_use_node_snapshot'] = 'false' - if not options.without_node_code_cache: + if options.without_node_code_cache or options.node_builtin_modules_path: + o['variables']['node_use_node_code_cache'] = 'false' + else: # TODO(refack): fix this when implementing embedded code-cache when cross-compiling. o['variables']['node_use_node_code_cache'] = b( not cross_compiling and not options.shared) - else: - o['variables']['node_use_node_code_cache'] = 'false' if target_arch == 'arm': configure_arm(o) @@ -1098,27 +1108,12 @@ def configure_node(o): else: o['variables']['node_use_dtrace'] = 'false' - if options.node_use_large_pages and not flavor in ('linux', 'freebsd', 'mac'): - raise Exception( - 'Large pages are supported only on Linux, FreeBSD and MacOS Systems.') - if options.node_use_large_pages and flavor in ('linux', 'freebsd', 'mac'): - if options.shared or options.enable_static: - raise Exception( - 'Large pages are supported only while creating node executable.') - if target_arch!="x64": - raise Exception( - 'Large pages are supported only x64 platform.') - if flavor == 'mac': - info('macOS server with 32GB or more is recommended') - if flavor == 'linux': - # Example full version string: 2.6.32-696.28.1.el6.x86_64 - FULL_KERNEL_VERSION=os.uname()[2] - KERNEL_VERSION=FULL_KERNEL_VERSION.split('-')[0] - if KERNEL_VERSION < "2.6.38" and flavor == 'linux': - raise Exception( - 'Large pages need Linux kernel version >= 2.6.38') - o['variables']['node_use_large_pages'] = b(options.node_use_large_pages) - o['variables']['node_use_large_pages_script_lld'] = b(options.node_use_large_pages_script_lld) + if options.node_use_large_pages or options.node_use_large_pages_script_lld: + warn('''The `--use-largepages` and `--use-largepages-script-lld` options + have no effect during build time. Support for mapping to large pages is + now a runtime option of Node.js. Run `node --use-largepages` or add + `--use-largepages` to the `NODE_OPTIONS` environment variable once + Node.js is built to enable mapping to large pages.''') if options.no_ifaddrs: o['defines'] += ['SUNOS_NO_IFADDRS'] @@ -1191,6 +1186,10 @@ def configure_node(o): else: o['variables']['node_target_type'] = 'executable' + if options.node_builtin_modules_path: + print('Warning! Loading builtin modules from disk is for development') + o['variables']['node_builtin_modules_path'] = options.node_builtin_modules_path + def configure_napi(output): version = getnapibuildversion.get_napi_version() output['variables']['napi_build_version'] = version @@ -1235,6 +1234,7 @@ def configure_v8(o): o['variables']['v8_enable_gdbjit'] = 1 if options.gdb else 0 o['variables']['v8_no_strict_aliasing'] = 1 # Work around compiler bugs. o['variables']['v8_optimized_debug'] = 0 if options.v8_non_optimized_debug else 1 + o['variables']['dcheck_always_on'] = 1 if options.v8_with_dchecks else 0 o['variables']['v8_random_seed'] = 0 # Use a random seed for hash tables. o['variables']['v8_promise_internal_field_count'] = 1 # Add internal field to promises for async hooks. o['variables']['v8_use_siphash'] = 0 if options.without_siphash else 1 diff --git a/deps/icu-small/LICENSE b/deps/icu-small/LICENSE index 2e01e368768a4b..e7f98ed18391b8 100644 --- a/deps/icu-small/LICENSE +++ b/deps/icu-small/LICENSE @@ -1,6 +1,6 @@ COPYRIGHT AND PERMISSION NOTICE (ICU 58 and later) -Copyright © 1991-2019 Unicode, Inc. All rights reserved. +Copyright © 1991-2020 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in https://www.unicode.org/copyright.html. Permission is hereby granted, free of charge, to any person obtaining diff --git a/deps/icu-small/README-SMALL-ICU.txt b/deps/icu-small/README-SMALL-ICU.txt index 5530235095c8fd..b1aeabe031187c 100644 --- a/deps/icu-small/README-SMALL-ICU.txt +++ b/deps/icu-small/README-SMALL-ICU.txt @@ -1,8 +1,8 @@ Small ICU sources - auto generated by shrink-icu-src.py This directory contains the ICU subset used by --with-intl=small-icu (the default) -It is a strict subset of ICU 65 source files with the following exception(s): -* deps/icu-small/source/data/in/icudt65l.dat : Reduced-size data file - +It is a strict subset of ICU 67 source files with the following exception(s): +* deps/icu-small/source/data/in/icudt67l.dat : Reduced-size data file +* deps/icu-small/source/common/uassert.h : Manual backport of ICU-21081 To rebuild this directory, see ../../tools/icu/README.md diff --git a/deps/icu-small/source/common/brkiter.cpp b/deps/icu-small/source/common/brkiter.cpp index 2fc4c345c7a038..7b8bff4b921c78 100644 --- a/deps/icu-small/source/common/brkiter.cpp +++ b/deps/icu-small/source/common/brkiter.cpp @@ -38,6 +38,7 @@ #include "uresimp.h" #include "uassert.h" #include "ubrkimpl.h" +#include "utracimp.h" #include "charstr.h" // ***************************************************************************** @@ -412,14 +413,23 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status) BreakIterator *result = NULL; switch (kind) { case UBRK_CHARACTER: - result = BreakIterator::buildInstance(loc, "grapheme", status); + { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_CHARACTER); + result = BreakIterator::buildInstance(loc, "grapheme", status); + UTRACE_EXIT_STATUS(status); + } break; case UBRK_WORD: - result = BreakIterator::buildInstance(loc, "word", status); + { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_WORD); + result = BreakIterator::buildInstance(loc, "word", status); + UTRACE_EXIT_STATUS(status); + } break; case UBRK_LINE: - uprv_strcpy(lbType, "line"); { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_LINE); + uprv_strcpy(lbType, "line"); char lbKeyValue[kKeyValueLenMax] = {0}; UErrorCode kvStatus = U_ZERO_ERROR; int32_t kLen = loc.getKeywordValue("lb", lbKeyValue, kKeyValueLenMax, kvStatus); @@ -427,13 +437,17 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status) uprv_strcat(lbType, "_"); uprv_strcat(lbType, lbKeyValue); } + result = BreakIterator::buildInstance(loc, lbType, status); + + UTRACE_DATA1(UTRACE_INFO, "lb=%s", lbKeyValue); + UTRACE_EXIT_STATUS(status); } - result = BreakIterator::buildInstance(loc, lbType, status); break; case UBRK_SENTENCE: - result = BreakIterator::buildInstance(loc, "sentence", status); -#if !UCONFIG_NO_FILTERED_BREAK_ITERATION { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_SENTENCE); + result = BreakIterator::buildInstance(loc, "sentence", status); +#if !UCONFIG_NO_FILTERED_BREAK_ITERATION char ssKeyValue[kKeyValueLenMax] = {0}; UErrorCode kvStatus = U_ZERO_ERROR; int32_t kLen = loc.getKeywordValue("ss", ssKeyValue, kKeyValueLenMax, kvStatus); @@ -444,11 +458,16 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status) delete fbiBuilder; } } - } #endif + UTRACE_EXIT_STATUS(status); + } break; case UBRK_TITLE: - result = BreakIterator::buildInstance(loc, "title", status); + { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_TITLE); + result = BreakIterator::buildInstance(loc, "title", status); + UTRACE_EXIT_STATUS(status); + } break; default: status = U_ILLEGAL_ARGUMENT_ERROR; diff --git a/deps/icu-small/source/common/cmemory.h b/deps/icu-small/source/common/cmemory.h index b24bd0ead2761c..38f99179631b10 100644 --- a/deps/icu-small/source/common/cmemory.h +++ b/deps/icu-small/source/common/cmemory.h @@ -274,7 +274,10 @@ inline T *LocalMemory::allocateInsteadAndCopy(int32_t newCapacity, int32_t le * * WARNING: MaybeStackArray only works with primitive (plain-old data) types. * It does NOT know how to call a destructor! If you work with classes with - * destructors, consider LocalArray in localpointer.h or MemoryPool. + * destructors, consider: + * + * - LocalArray in localpointer.h if you know the length ahead of time + * - MaybeStackVector if you know the length at runtime */ template class MaybeStackArray { @@ -684,26 +687,26 @@ inline H *MaybeStackHeaderAndArray::orphanOrClone(int32_t l template class MemoryPool : public UMemory { public: - MemoryPool() : count(0), pool() {} + MemoryPool() : fCount(0), fPool() {} ~MemoryPool() { - for (int32_t i = 0; i < count; ++i) { - delete pool[i]; + for (int32_t i = 0; i < fCount; ++i) { + delete fPool[i]; } } MemoryPool(const MemoryPool&) = delete; MemoryPool& operator=(const MemoryPool&) = delete; - MemoryPool(MemoryPool&& other) U_NOEXCEPT : count(other.count), - pool(std::move(other.pool)) { - other.count = 0; + MemoryPool(MemoryPool&& other) U_NOEXCEPT : fCount(other.fCount), + fPool(std::move(other.fPool)) { + other.fCount = 0; } MemoryPool& operator=(MemoryPool&& other) U_NOEXCEPT { - count = other.count; - pool = std::move(other.pool); - other.count = 0; + fCount = other.fCount; + fPool = std::move(other.fPool); + other.fCount = 0; return *this; } @@ -716,20 +719,101 @@ class MemoryPool : public UMemory { */ template T* create(Args&&... args) { - int32_t capacity = pool.getCapacity(); - if (count == capacity && - pool.resize(capacity == stackCapacity ? 4 * capacity : 2 * capacity, - capacity) == nullptr) { + int32_t capacity = fPool.getCapacity(); + if (fCount == capacity && + fPool.resize(capacity == stackCapacity ? 4 * capacity : 2 * capacity, + capacity) == nullptr) { return nullptr; } - return pool[count++] = new T(std::forward(args)...); + return fPool[fCount++] = new T(std::forward(args)...); } -private: - int32_t count; - MaybeStackArray pool; + /** + * @return Number of elements that have been allocated. + */ + int32_t count() const { + return fCount; + } + +protected: + int32_t fCount; + MaybeStackArray fPool; +}; + +/** + * An internal Vector-like implementation based on MemoryPool. + * + * Heap-allocates each element and stores pointers. + * + * To append an item to the vector, use emplaceBack. + * + * MaybeStackVector vector; + * MyType* element = vector.emplaceBack(); + * if (!element) { + * status = U_MEMORY_ALLOCATION_ERROR; + * } + * // do stuff with element + * + * To loop over the vector, use a for loop with indices: + * + * for (int32_t i = 0; i < vector.length(); i++) { + * MyType* element = vector[i]; + * } + */ +template +class MaybeStackVector : protected MemoryPool { +public: + using MemoryPool::MemoryPool; + using MemoryPool::operator=; + + template + T* emplaceBack(Args&&... args) { + return this->create(args...); + } + + int32_t length() const { + return this->fCount; + } + + T** getAlias() { + return this->fPool.getAlias(); + } + + /** + * Array item access (read-only). + * No index bounds check. + * @param i array index + * @return reference to the array item + */ + const T* operator[](ptrdiff_t i) const { + return this->fPool[i]; + } + + /** + * Array item access (writable). + * No index bounds check. + * @param i array index + * @return reference to the array item + */ + T* operator[](ptrdiff_t i) { + return this->fPool[i]; + } + + /** + * Append all the items from another MaybeStackVector to this one. + */ + void appendAll(const MaybeStackVector& other, UErrorCode& status) { + for (int32_t i = 0; i < other.fCount; i++) { + T* item = emplaceBack(*other[i]); + if (!item) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + } + } }; + U_NAMESPACE_END #endif /* __cplusplus */ diff --git a/deps/icu-small/source/common/cstring.h b/deps/icu-small/source/common/cstring.h index ed0b1a7c8b0be8..3a14e4216c8e51 100644 --- a/deps/icu-small/source/common/cstring.h +++ b/deps/icu-small/source/common/cstring.h @@ -52,6 +52,8 @@ U_CAPI UBool U_EXPORT2 uprv_isASCIILetter(char c); +// NOTE: For u_asciiToUpper that takes a UChar, see ustr_imp.h + U_CAPI char U_EXPORT2 uprv_toupper(char c); diff --git a/deps/icu-small/source/common/dictbe.cpp b/deps/icu-small/source/common/dictbe.cpp index 6ceba21a244047..6d3bc878078847 100644 --- a/deps/icu-small/source/common/dictbe.cpp +++ b/deps/icu-small/source/common/dictbe.cpp @@ -18,6 +18,7 @@ #include "unicode/uniset.h" #include "unicode/chariter.h" #include "unicode/ubrk.h" +#include "utracimp.h" #include "uvectr32.h" #include "uvector.h" #include "uassert.h" @@ -194,6 +195,8 @@ ThaiBreakEngine::ThaiBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCode : DictionaryBreakEngine(), fDictionary(adoptDictionary) { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); + UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Thai"); fThaiWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Thai:]&[:LineBreak=SA:]]"), status); if (U_SUCCESS(status)) { setCharacters(fThaiWordSet); @@ -213,6 +216,7 @@ ThaiBreakEngine::ThaiBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCode fEndWordSet.compact(); fBeginWordSet.compact(); fSuffixSet.compact(); + UTRACE_EXIT_STATUS(status); } ThaiBreakEngine::~ThaiBreakEngine() { @@ -436,6 +440,8 @@ LaoBreakEngine::LaoBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCode &s : DictionaryBreakEngine(), fDictionary(adoptDictionary) { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); + UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Laoo"); fLaoWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Laoo:]&[:LineBreak=SA:]]"), status); if (U_SUCCESS(status)) { setCharacters(fLaoWordSet); @@ -452,6 +458,7 @@ LaoBreakEngine::LaoBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCode &s fMarkSet.compact(); fEndWordSet.compact(); fBeginWordSet.compact(); + UTRACE_EXIT_STATUS(status); } LaoBreakEngine::~LaoBreakEngine() { @@ -632,6 +639,8 @@ BurmeseBreakEngine::BurmeseBreakEngine(DictionaryMatcher *adoptDictionary, UErro : DictionaryBreakEngine(), fDictionary(adoptDictionary) { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); + UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Mymr"); fBurmeseWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Mymr:]&[:LineBreak=SA:]]"), status); if (U_SUCCESS(status)) { setCharacters(fBurmeseWordSet); @@ -645,6 +654,7 @@ BurmeseBreakEngine::BurmeseBreakEngine(DictionaryMatcher *adoptDictionary, UErro fMarkSet.compact(); fEndWordSet.compact(); fBeginWordSet.compact(); + UTRACE_EXIT_STATUS(status); } BurmeseBreakEngine::~BurmeseBreakEngine() { @@ -825,6 +835,8 @@ KhmerBreakEngine::KhmerBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCod : DictionaryBreakEngine(), fDictionary(adoptDictionary) { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); + UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Khmr"); fKhmerWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Khmr:]&[:LineBreak=SA:]]"), status); if (U_SUCCESS(status)) { setCharacters(fKhmerWordSet); @@ -850,6 +862,7 @@ KhmerBreakEngine::KhmerBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCod fEndWordSet.compact(); fBeginWordSet.compact(); // fSuffixSet.compact(); + UTRACE_EXIT_STATUS(status); } KhmerBreakEngine::~KhmerBreakEngine() { @@ -1045,6 +1058,8 @@ KhmerBreakEngine::divideUpDictionaryRange( UText *text, static const uint32_t kuint32max = 0xFFFFFFFF; CjkBreakEngine::CjkBreakEngine(DictionaryMatcher *adoptDictionary, LanguageType type, UErrorCode &status) : DictionaryBreakEngine(), fDictionary(adoptDictionary) { + UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); + UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Hani"); // Korean dictionary only includes Hangul syllables fHangulWordSet.applyPattern(UNICODE_STRING_SIMPLE("[\\uac00-\\ud7a3]"), status); fHanWordSet.applyPattern(UNICODE_STRING_SIMPLE("[:Han:]"), status); @@ -1066,6 +1081,7 @@ CjkBreakEngine::CjkBreakEngine(DictionaryMatcher *adoptDictionary, LanguageType setCharacters(cjSet); } } + UTRACE_EXIT_STATUS(status); } CjkBreakEngine::~CjkBreakEngine(){ diff --git a/deps/icu-small/source/common/localematcher.cpp b/deps/icu-small/source/common/localematcher.cpp index d975fe759b4ce1..85db8c8bf3246d 100644 --- a/deps/icu-small/source/common/localematcher.cpp +++ b/deps/icu-small/source/common/localematcher.cpp @@ -12,6 +12,7 @@ #include "unicode/localematcher.h" #include "unicode/locid.h" #include "unicode/stringpiece.h" +#include "unicode/uloc.h" #include "unicode/uobject.h" #include "cstring.h" #include "localeprioritylist.h" @@ -20,9 +21,10 @@ #include "lsr.h" #include "uassert.h" #include "uhash.h" +#include "ustr_imp.h" #include "uvector.h" -#define UND_LSR LSR("und", "", "") +#define UND_LSR LSR("und", "", "", LSR::EXPLICIT_LSR) /** * Indicator for the lifetime of desired-locale objects passed into the LocaleMatcher. @@ -129,7 +131,8 @@ LocaleMatcher::Builder::Builder(LocaleMatcher::Builder &&src) U_NOEXCEPT : thresholdDistance_(src.thresholdDistance_), demotion_(src.demotion_), defaultLocale_(src.defaultLocale_), - favor_(src.favor_) { + favor_(src.favor_), + direction_(src.direction_) { src.supportedLocales_ = nullptr; src.defaultLocale_ = nullptr; } @@ -148,6 +151,7 @@ LocaleMatcher::Builder &LocaleMatcher::Builder::operator=(LocaleMatcher::Builder demotion_ = src.demotion_; defaultLocale_ = src.defaultLocale_; favor_ = src.favor_; + direction_ = src.direction_; src.supportedLocales_ = nullptr; src.defaultLocale_ = nullptr; @@ -308,38 +312,53 @@ UBool compareLSRs(const UHashTok t1, const UHashTok t2) { return *lsr1 == *lsr2; } -bool putIfAbsent(UHashtable *lsrToIndex, const LSR &lsr, int32_t i, UErrorCode &errorCode) { - if (U_FAILURE(errorCode)) { return false; } - U_ASSERT(i > 0); - int32_t index = uhash_geti(lsrToIndex, &lsr); - if (index != 0) { - return false; - } else { - uhash_puti(lsrToIndex, const_cast(&lsr), i, &errorCode); - return U_SUCCESS(errorCode); +} // namespace + +int32_t LocaleMatcher::putIfAbsent(const LSR &lsr, int32_t i, int32_t suppLength, + UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return suppLength; } + int32_t index = uhash_geti(supportedLsrToIndex, &lsr); + if (index == 0) { + uhash_puti(supportedLsrToIndex, const_cast(&lsr), i + 1, &errorCode); + if (U_SUCCESS(errorCode)) { + supportedLSRs[suppLength] = &lsr; + supportedIndexes[suppLength++] = i; + } } + return suppLength; } -} // namespace - LocaleMatcher::LocaleMatcher(const Builder &builder, UErrorCode &errorCode) : likelySubtags(*XLikelySubtags::getSingleton(errorCode)), localeDistance(*LocaleDistance::getSingleton(errorCode)), thresholdDistance(builder.thresholdDistance_), demotionPerDesiredLocale(0), favorSubtag(builder.favor_), + direction(builder.direction_), supportedLocales(nullptr), lsrs(nullptr), supportedLocalesLength(0), supportedLsrToIndex(nullptr), supportedLSRs(nullptr), supportedIndexes(nullptr), supportedLSRsLength(0), - ownedDefaultLocale(nullptr), defaultLocale(nullptr), defaultLocaleIndex(-1) { + ownedDefaultLocale(nullptr), defaultLocale(nullptr) { if (U_FAILURE(errorCode)) { return; } if (thresholdDistance < 0) { thresholdDistance = localeDistance.getDefaultScriptDistance(); } + const Locale *def = builder.defaultLocale_; + LSR builderDefaultLSR; + const LSR *defLSR = nullptr; + if (def != nullptr) { + ownedDefaultLocale = def->clone(); + if (ownedDefaultLocale == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + def = ownedDefaultLocale; + builderDefaultLSR = getMaximalLsrOrUnd(likelySubtags, *def, errorCode); + if (U_FAILURE(errorCode)) { return; } + defLSR = &builderDefaultLSR; + } supportedLocalesLength = builder.supportedLocales_ != nullptr ? builder.supportedLocales_->size() : 0; - const Locale *def = builder.defaultLocale_; - int32_t idef = -1; if (supportedLocalesLength > 0) { // Store the supported locales in input order, // so that when different types are used (e.g., language tag strings) @@ -356,15 +375,6 @@ LocaleMatcher::LocaleMatcher(const Builder &builder, UErrorCode &errorCode) : } // If the constructor fails partway, we need null pointers for destructibility. uprv_memset(supportedLocales, 0, supportedLocalesLength * sizeof(const Locale *)); - // Also find the first supported locale whose LSR is - // the same as that for the default locale. - LSR builderDefaultLSR; - const LSR *defLSR = nullptr; - if (def != nullptr) { - builderDefaultLSR = getMaximalLsrOrUnd(likelySubtags, *def, errorCode); - if (U_FAILURE(errorCode)) { return; } - defLSR = &builderDefaultLSR; - } for (int32_t i = 0; i < supportedLocalesLength; ++i) { const Locale &locale = *static_cast(builder.supportedLocales_->elementAt(i)); supportedLocales[i] = locale.clone(); @@ -376,103 +386,74 @@ LocaleMatcher::LocaleMatcher(const Builder &builder, UErrorCode &errorCode) : LSR &lsr = lsrs[i] = getMaximalLsrOrUnd(likelySubtags, supportedLocale, errorCode); lsr.setHashCode(); if (U_FAILURE(errorCode)) { return; } - if (idef < 0 && defLSR != nullptr && lsr == *defLSR) { - idef = i; - defLSR = &lsr; // owned pointer to put into supportedLsrToIndex - if (*def == supportedLocale) { - def = &supportedLocale; // owned pointer to keep - } - } } // We need an unordered map from LSR to first supported locale with that LSR, - // and an ordered list of (LSR, supported index). - // We insert the supported locales in the following order: + // and an ordered list of (LSR, supported index) for + // the supported locales in the following order: // 1. Default locale, if it is supported. // 2. Priority locales (aka "paradigm locales") in builder order. // 3. Remaining locales in builder order. - // In Java, we use a LinkedHashMap for both map & ordered lists. - // In C++, we use separate structures. - // We over-allocate arrays of LSRs and indexes for simplicity. - // We reserve slots at the array starts for the default and paradigm locales, - // plus enough for all supported locales. - // If there are few paradigm locales and few duplicate supported LSRs, - // then the amount of wasted space is small. supportedLsrToIndex = uhash_openSize(hashLSR, compareLSRs, uhash_compareLong, supportedLocalesLength, &errorCode); if (U_FAILURE(errorCode)) { return; } - int32_t paradigmLimit = 1 + localeDistance.getParadigmLSRsLength(); - int32_t suppLSRsCapacity = paradigmLimit + supportedLocalesLength; supportedLSRs = static_cast( - uprv_malloc(suppLSRsCapacity * sizeof(const LSR *))); + uprv_malloc(supportedLocalesLength * sizeof(const LSR *))); supportedIndexes = static_cast( - uprv_malloc(suppLSRsCapacity * sizeof(int32_t))); + uprv_malloc(supportedLocalesLength * sizeof(int32_t))); if (supportedLSRs == nullptr || supportedIndexes == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; return; } - int32_t paradigmIndex = 0; - int32_t otherIndex = paradigmLimit; - if (idef >= 0) { - uhash_puti(supportedLsrToIndex, const_cast(defLSR), idef + 1, &errorCode); - supportedLSRs[0] = defLSR; - supportedIndexes[0] = idef; - paradigmIndex = 1; + int32_t suppLength = 0; + // Determine insertion order. + // Add locales immediately that are equivalent to the default. + MaybeStackArray order(supportedLocalesLength); + if (order.getAlias() == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; } + int32_t numParadigms = 0; for (int32_t i = 0; i < supportedLocalesLength; ++i) { - if (i == idef) { continue; } const Locale &locale = *supportedLocales[i]; const LSR &lsr = lsrs[i]; if (defLSR == nullptr) { U_ASSERT(i == 0); def = &locale; defLSR = &lsr; - idef = 0; - uhash_puti(supportedLsrToIndex, const_cast(&lsr), 0 + 1, &errorCode); - supportedLSRs[0] = &lsr; - supportedIndexes[0] = 0; - paradigmIndex = 1; - } else if (idef >= 0 && lsr == *defLSR) { - // lsr == *defLSR means that this supported locale is - // a duplicate of the default locale. - // Either an explicit default locale is supported, and we added it before the loop, - // or there is no explicit default locale, and this is - // a duplicate of the first supported locale. - // In both cases, idef >= 0 now, so otherwise we can skip the comparison. - // For a duplicate, putIfAbsent() is a no-op, so nothing to do. + order[i] = 1; + suppLength = putIfAbsent(lsr, 0, suppLength, errorCode); + } else if (lsr.isEquivalentTo(*defLSR)) { + order[i] = 1; + suppLength = putIfAbsent(lsr, i, suppLength, errorCode); + } else if (localeDistance.isParadigmLSR(lsr)) { + order[i] = 2; + ++numParadigms; } else { - if (putIfAbsent(supportedLsrToIndex, lsr, i + 1, errorCode)) { - if (localeDistance.isParadigmLSR(lsr)) { - supportedLSRs[paradigmIndex] = &lsr; - supportedIndexes[paradigmIndex++] = i; - } else { - supportedLSRs[otherIndex] = &lsr; - supportedIndexes[otherIndex++] = i; - } - } + order[i] = 3; } if (U_FAILURE(errorCode)) { return; } } - // Squeeze out unused array slots. - if (paradigmIndex < paradigmLimit && paradigmLimit < otherIndex) { - uprv_memmove(supportedLSRs + paradigmIndex, supportedLSRs + paradigmLimit, - (otherIndex - paradigmLimit) * sizeof(const LSR *)); - uprv_memmove(supportedIndexes + paradigmIndex, supportedIndexes + paradigmLimit, - (otherIndex - paradigmLimit) * sizeof(int32_t)); + // Add supported paradigm locales. + int32_t paradigmLimit = suppLength + numParadigms; + for (int32_t i = 0; i < supportedLocalesLength && suppLength < paradigmLimit; ++i) { + if (order[i] == 2) { + suppLength = putIfAbsent(lsrs[i], i, suppLength, errorCode); + } } - supportedLSRsLength = otherIndex - (paradigmLimit - paradigmIndex); - } - - if (def != nullptr && (idef < 0 || def != supportedLocales[idef])) { - ownedDefaultLocale = def->clone(); - if (ownedDefaultLocale == nullptr) { - errorCode = U_MEMORY_ALLOCATION_ERROR; - return; + // Add remaining supported locales. + for (int32_t i = 0; i < supportedLocalesLength; ++i) { + if (order[i] == 3) { + suppLength = putIfAbsent(lsrs[i], i, suppLength, errorCode); + } } - def = ownedDefaultLocale; + supportedLSRsLength = suppLength; + // If supportedLSRsLength < supportedLocalesLength then + // we waste as many array slots as there are duplicate supported LSRs, + // but the amount of wasted space is small as long as there are few duplicates. } + defaultLocale = def; - defaultLocaleIndex = idef; if (builder.demotion_ == ULOCMATCH_DEMOTION_REGION) { demotionPerDesiredLocale = localeDistance.getDefaultDemotionPerDesiredLocale(); @@ -485,14 +466,14 @@ LocaleMatcher::LocaleMatcher(LocaleMatcher &&src) U_NOEXCEPT : thresholdDistance(src.thresholdDistance), demotionPerDesiredLocale(src.demotionPerDesiredLocale), favorSubtag(src.favorSubtag), + direction(src.direction), supportedLocales(src.supportedLocales), lsrs(src.lsrs), supportedLocalesLength(src.supportedLocalesLength), supportedLsrToIndex(src.supportedLsrToIndex), supportedLSRs(src.supportedLSRs), supportedIndexes(src.supportedIndexes), supportedLSRsLength(src.supportedLSRsLength), - ownedDefaultLocale(src.ownedDefaultLocale), defaultLocale(src.defaultLocale), - defaultLocaleIndex(src.defaultLocaleIndex) { + ownedDefaultLocale(src.ownedDefaultLocale), defaultLocale(src.defaultLocale) { src.supportedLocales = nullptr; src.lsrs = nullptr; src.supportedLocalesLength = 0; @@ -502,7 +483,6 @@ LocaleMatcher::LocaleMatcher(LocaleMatcher &&src) U_NOEXCEPT : src.supportedLSRsLength = 0; src.ownedDefaultLocale = nullptr; src.defaultLocale = nullptr; - src.defaultLocaleIndex = -1; } LocaleMatcher::~LocaleMatcher() { @@ -523,6 +503,7 @@ LocaleMatcher &LocaleMatcher::operator=(LocaleMatcher &&src) U_NOEXCEPT { thresholdDistance = src.thresholdDistance; demotionPerDesiredLocale = src.demotionPerDesiredLocale; favorSubtag = src.favorSubtag; + direction = src.direction; supportedLocales = src.supportedLocales; lsrs = src.lsrs; supportedLocalesLength = src.supportedLocalesLength; @@ -532,7 +513,6 @@ LocaleMatcher &LocaleMatcher::operator=(LocaleMatcher &&src) U_NOEXCEPT { supportedLSRsLength = src.supportedLSRsLength; ownedDefaultLocale = src.ownedDefaultLocale; defaultLocale = src.defaultLocale; - defaultLocaleIndex = src.defaultLocaleIndex; src.supportedLocales = nullptr; src.lsrs = nullptr; @@ -543,7 +523,6 @@ LocaleMatcher &LocaleMatcher::operator=(LocaleMatcher &&src) U_NOEXCEPT { src.supportedLSRsLength = 0; src.ownedDefaultLocale = nullptr; src.defaultLocale = nullptr; - src.defaultLocaleIndex = -1; return *this; } @@ -630,13 +609,13 @@ const Locale *LocaleMatcher::getBestMatchForListString( LocaleMatcher::Result LocaleMatcher::getBestMatchResult( const Locale &desiredLocale, UErrorCode &errorCode) const { if (U_FAILURE(errorCode)) { - return Result(nullptr, defaultLocale, -1, defaultLocaleIndex, FALSE); + return Result(nullptr, defaultLocale, -1, -1, FALSE); } int32_t suppIndex = getBestSuppIndex( getMaximalLsrOrUnd(likelySubtags, desiredLocale, errorCode), nullptr, errorCode); if (U_FAILURE(errorCode) || suppIndex < 0) { - return Result(nullptr, defaultLocale, -1, defaultLocaleIndex, FALSE); + return Result(nullptr, defaultLocale, -1, -1, FALSE); } else { return Result(&desiredLocale, supportedLocales[suppIndex], 0, suppIndex, FALSE); } @@ -645,12 +624,12 @@ LocaleMatcher::Result LocaleMatcher::getBestMatchResult( LocaleMatcher::Result LocaleMatcher::getBestMatchResult( Locale::Iterator &desiredLocales, UErrorCode &errorCode) const { if (U_FAILURE(errorCode) || !desiredLocales.hasNext()) { - return Result(nullptr, defaultLocale, -1, defaultLocaleIndex, FALSE); + return Result(nullptr, defaultLocale, -1, -1, FALSE); } LocaleLsrIterator lsrIter(likelySubtags, desiredLocales, ULOCMATCH_TEMPORARY_LOCALES); int32_t suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode); if (U_FAILURE(errorCode) || suppIndex < 0) { - return Result(nullptr, defaultLocale, -1, defaultLocaleIndex, FALSE); + return Result(nullptr, defaultLocale, -1, -1, FALSE); } else { return Result(lsrIter.orphanRemembered(), supportedLocales[suppIndex], lsrIter.getBestDesiredIndex(), suppIndex, TRUE); @@ -662,7 +641,7 @@ int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remai if (U_FAILURE(errorCode)) { return -1; } int32_t desiredIndex = 0; int32_t bestSupportedLsrIndex = -1; - for (int32_t bestDistance = thresholdDistance;;) { + for (int32_t bestShiftedDistance = LocaleDistance::shiftDistance(thresholdDistance);;) { // Quick check for exact maximized LSR. // Returns suppIndex+1 where 0 means not found. if (supportedLsrToIndex != nullptr) { @@ -677,16 +656,17 @@ int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remai } } int32_t bestIndexAndDistance = localeDistance.getBestIndexAndDistance( - desiredLSR, supportedLSRs, supportedLSRsLength, bestDistance, favorSubtag); + desiredLSR, supportedLSRs, supportedLSRsLength, + bestShiftedDistance, favorSubtag, direction); if (bestIndexAndDistance >= 0) { - bestDistance = bestIndexAndDistance & 0xff; + bestShiftedDistance = LocaleDistance::getShiftedDistance(bestIndexAndDistance); if (remainingIter != nullptr) { remainingIter->rememberCurrent(desiredIndex, errorCode); if (U_FAILURE(errorCode)) { return -1; } } - bestSupportedLsrIndex = bestIndexAndDistance >= 0 ? bestIndexAndDistance >> 8 : -1; + bestSupportedLsrIndex = LocaleDistance::getIndex(bestIndexAndDistance); } - if ((bestDistance -= demotionPerDesiredLocale) <= 0) { + if ((bestShiftedDistance -= LocaleDistance::shiftDistance(demotionPerDesiredLocale)) <= 0) { break; } if (remainingIter == nullptr || !remainingIter->hasNext()) { @@ -708,13 +688,107 @@ double LocaleMatcher::internalMatch(const Locale &desired, const Locale &support LSR suppLSR = getMaximalLsrOrUnd(likelySubtags, supported, errorCode); if (U_FAILURE(errorCode)) { return 0; } const LSR *pSuppLSR = &suppLSR; - int32_t distance = localeDistance.getBestIndexAndDistance( + int32_t indexAndDistance = localeDistance.getBestIndexAndDistance( getMaximalLsrOrUnd(likelySubtags, desired, errorCode), &pSuppLSR, 1, - thresholdDistance, favorSubtag) & 0xff; - return (100 - distance) / 100.0; + LocaleDistance::shiftDistance(thresholdDistance), favorSubtag, direction); + double distance = LocaleDistance::getDistanceDouble(indexAndDistance); + return (100.0 - distance) / 100.0; } U_NAMESPACE_END +// uloc_acceptLanguage() --------------------------------------------------- *** + +U_NAMESPACE_USE + +namespace { + +class LocaleFromTag { +public: + LocaleFromTag() : locale(Locale::getRoot()) {} + const Locale &operator()(const char *tag) { return locale = Locale(tag); } + +private: + // Store the locale in the converter, rather than return a reference to a temporary, + // or a value which could go out of scope with the caller's reference to it. + Locale locale; +}; + +int32_t acceptLanguage(UEnumeration &supportedLocales, Locale::Iterator &desiredLocales, + char *dest, int32_t capacity, UAcceptResult *acceptResult, + UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return 0; } + LocaleMatcher::Builder builder; + const char *locString; + while ((locString = uenum_next(&supportedLocales, nullptr, &errorCode)) != nullptr) { + Locale loc(locString); + if (loc.isBogus()) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + builder.addSupportedLocale(loc); + } + LocaleMatcher matcher = builder.build(errorCode); + LocaleMatcher::Result result = matcher.getBestMatchResult(desiredLocales, errorCode); + if (U_FAILURE(errorCode)) { return 0; } + if (result.getDesiredIndex() >= 0) { + if (acceptResult != nullptr) { + *acceptResult = *result.getDesiredLocale() == *result.getSupportedLocale() ? + ULOC_ACCEPT_VALID : ULOC_ACCEPT_FALLBACK; + } + const char *bestStr = result.getSupportedLocale()->getName(); + int32_t bestLength = (int32_t)uprv_strlen(bestStr); + if (bestLength <= capacity) { + uprv_memcpy(dest, bestStr, bestLength); + } + return u_terminateChars(dest, capacity, bestLength, &errorCode); + } else { + if (acceptResult != nullptr) { + *acceptResult = ULOC_ACCEPT_FAILED; + } + return u_terminateChars(dest, capacity, 0, &errorCode); + } +} + +} // namespace + +U_CAPI int32_t U_EXPORT2 +uloc_acceptLanguage(char *result, int32_t resultAvailable, + UAcceptResult *outResult, + const char **acceptList, int32_t acceptListCount, + UEnumeration *availableLocales, + UErrorCode *status) { + if (U_FAILURE(*status)) { return 0; } + if ((result == nullptr ? resultAvailable != 0 : resultAvailable < 0) || + (acceptList == nullptr ? acceptListCount != 0 : acceptListCount < 0) || + availableLocales == nullptr) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + LocaleFromTag converter; + Locale::ConvertingIterator desiredLocales( + acceptList, acceptList + acceptListCount, converter); + return acceptLanguage(*availableLocales, desiredLocales, + result, resultAvailable, outResult, *status); +} + +U_CAPI int32_t U_EXPORT2 +uloc_acceptLanguageFromHTTP(char *result, int32_t resultAvailable, + UAcceptResult *outResult, + const char *httpAcceptLanguage, + UEnumeration *availableLocales, + UErrorCode *status) { + if (U_FAILURE(*status)) { return 0; } + if ((result == nullptr ? resultAvailable != 0 : resultAvailable < 0) || + httpAcceptLanguage == nullptr || availableLocales == nullptr) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + LocalePriorityList list(httpAcceptLanguage, *status); + LocalePriorityList::Iterator desiredLocales = list.iterator(); + return acceptLanguage(*availableLocales, desiredLocales, + result, resultAvailable, outResult, *status); +} + #endif // __LOCMATCHER_H__ diff --git a/deps/icu-small/source/common/localeprioritylist.cpp b/deps/icu-small/source/common/localeprioritylist.cpp index 06442fb46a83ad..cee408269c9b39 100644 --- a/deps/icu-small/source/common/localeprioritylist.cpp +++ b/deps/icu-small/source/common/localeprioritylist.cpp @@ -133,7 +133,7 @@ LocalePriorityList::LocalePriorityList(StringPiece s, UErrorCode &errorCode) { if (U_FAILURE(errorCode)) { return; } Locale locale = Locale(tag.data()); if (locale.isBogus()) { - errorCode = U_MEMORY_ALLOCATION_ERROR; + errorCode = U_ILLEGAL_ARGUMENT_ERROR; return; } int32_t weight = WEIGHT_ONE; diff --git a/deps/icu-small/source/common/locdistance.cpp b/deps/icu-small/source/common/locdistance.cpp index 800d0eacf2b605..18e4d91bce921b 100644 --- a/deps/icu-small/source/common/locdistance.cpp +++ b/deps/icu-small/source/common/locdistance.cpp @@ -69,7 +69,7 @@ void U_CALLCONV LocaleDistance::initLocaleDistance(UErrorCode &errorCode) { errorCode = U_MISSING_RESOURCE_ERROR; return; } - gLocaleDistance = new LocaleDistance(data); + gLocaleDistance = new LocaleDistance(data, likely); if (gLocaleDistance == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; return; @@ -83,7 +83,8 @@ const LocaleDistance *LocaleDistance::getSingleton(UErrorCode &errorCode) { return gLocaleDistance; } -LocaleDistance::LocaleDistance(const LocaleDistanceData &data) : +LocaleDistance::LocaleDistance(const LocaleDistanceData &data, const XLikelySubtags &likely) : + likelySubtags(likely), trie(data.distanceTrieBytes), regionToPartitionsIndex(data.regionToPartitions), partitionArrays(data.partitions), paradigmLSRs(data.paradigms), paradigmLSRsLength(data.paradigmsLength), @@ -97,17 +98,19 @@ LocaleDistance::LocaleDistance(const LocaleDistanceData &data) : // a mere region difference for one desired locale // is as good as a perfect match for the next following desired locale. // As of CLDR 36, we have . - LSR en("en", "Latn", "US"); - LSR enGB("en", "Latn", "GB"); + LSR en("en", "Latn", "US", LSR::EXPLICIT_LSR); + LSR enGB("en", "Latn", "GB", LSR::EXPLICIT_LSR); const LSR *p_enGB = &enGB; - defaultDemotionPerDesiredLocale = getBestIndexAndDistance(en, &p_enGB, 1, - 50, ULOCMATCH_FAVOR_LANGUAGE) & 0xff; + int32_t indexAndDistance = getBestIndexAndDistance(en, &p_enGB, 1, + shiftDistance(50), ULOCMATCH_FAVOR_LANGUAGE, ULOCMATCH_DIRECTION_WITH_ONE_WAY); + defaultDemotionPerDesiredLocale = getDistanceFloor(indexAndDistance); } int32_t LocaleDistance::getBestIndexAndDistance( const LSR &desired, const LSR **supportedLSRs, int32_t supportedLSRsLength, - int32_t threshold, ULocMatchFavorSubtag favorSubtag) const { + int32_t shiftedThreshold, + ULocMatchFavorSubtag favorSubtag, ULocMatchDirection direction) const { BytesTrie iter(trie); // Look up the desired language only once for all supported LSRs. // Its "distance" is either a match point value of 0, or a non-match negative value. @@ -116,6 +119,8 @@ int32_t LocaleDistance::getBestIndexAndDistance( uint64_t desLangState = desLangDistance >= 0 && supportedLSRsLength > 1 ? iter.getState64() : 0; // Index of the supported LSR with the lowest distance. int32_t bestIndex = -1; + // Cached lookup info from XLikelySubtags.compareLikely(). + int32_t bestLikelyInfo = -1; for (int32_t slIndex = 0; slIndex < supportedLSRsLength; ++slIndex) { const LSR &supported = *supportedLSRs[slIndex]; bool star = false; @@ -145,6 +150,11 @@ int32_t LocaleDistance::getBestIndexAndDistance( star = true; } U_ASSERT(0 <= distance && distance <= 100); + // Round up the shifted threshold (if fraction bits are not 0) + // for comparison with un-shifted distances until we need fraction bits. + // (If we simply shifted non-zero fraction bits away, then we might ignore a language + // when it's really still a micro distance below the threshold.) + int32_t roundedThreshold = (shiftedThreshold + DISTANCE_FRACTION_MASK) >> DISTANCE_SHIFT; // We implement "favor subtag" by reducing the language subtag distance // (unscientifically reducing it to a quarter of the normal value), // so that the script distance is relatively more important. @@ -153,7 +163,9 @@ int32_t LocaleDistance::getBestIndexAndDistance( if (favorSubtag == ULOCMATCH_FAVOR_SCRIPT) { distance >>= 2; } - if (distance >= threshold) { + // Let distance == roundedThreshold pass until the tie-breaker logic + // at the end of the loop. + if (distance > roundedThreshold) { continue; } @@ -171,7 +183,7 @@ int32_t LocaleDistance::getBestIndexAndDistance( scriptDistance &= ~DISTANCE_IS_FINAL; } distance += scriptDistance; - if (distance >= threshold) { + if (distance > roundedThreshold) { continue; } @@ -180,8 +192,8 @@ int32_t LocaleDistance::getBestIndexAndDistance( } else if (star || (flags & DISTANCE_IS_FINAL) != 0) { distance += defaultRegionDistance; } else { - int32_t remainingThreshold = threshold - distance; - if (minRegionDistance >= remainingThreshold) { + int32_t remainingThreshold = roundedThreshold - distance; + if (minRegionDistance > remainingThreshold) { continue; } @@ -196,15 +208,51 @@ int32_t LocaleDistance::getBestIndexAndDistance( partitionsForRegion(supported), remainingThreshold); } - if (distance < threshold) { - if (distance == 0) { - return slIndex << 8; + int32_t shiftedDistance = shiftDistance(distance); + if (shiftedDistance == 0) { + // Distinguish between equivalent but originally unequal locales via an + // additional micro distance. + shiftedDistance |= (desired.flags ^ supported.flags); + if (shiftedDistance < shiftedThreshold) { + if (direction != ULOCMATCH_DIRECTION_ONLY_TWO_WAY || + // Is there also a match when we swap desired/supported? + isMatch(supported, desired, shiftedThreshold, favorSubtag)) { + if (shiftedDistance == 0) { + return slIndex << INDEX_SHIFT; + } + bestIndex = slIndex; + shiftedThreshold = shiftedDistance; + bestLikelyInfo = -1; + } + } + } else { + if (shiftedDistance < shiftedThreshold) { + if (direction != ULOCMATCH_DIRECTION_ONLY_TWO_WAY || + // Is there also a match when we swap desired/supported? + isMatch(supported, desired, shiftedThreshold, favorSubtag)) { + bestIndex = slIndex; + shiftedThreshold = shiftedDistance; + bestLikelyInfo = -1; + } + } else if (shiftedDistance == shiftedThreshold && bestIndex >= 0) { + if (direction != ULOCMATCH_DIRECTION_ONLY_TWO_WAY || + // Is there also a match when we swap desired/supported? + isMatch(supported, desired, shiftedThreshold, favorSubtag)) { + bestLikelyInfo = likelySubtags.compareLikely( + supported, *supportedLSRs[bestIndex], bestLikelyInfo); + if ((bestLikelyInfo & 1) != 0) { + // This supported locale matches as well as the previous best match, + // and neither matches perfectly, + // but this one is "more likely" (has more-default subtags). + bestIndex = slIndex; + } + } } - bestIndex = slIndex; - threshold = distance; } } - return bestIndex >= 0 ? (bestIndex << 8) | threshold : 0xffffff00 | ABOVE_THRESHOLD; + return bestIndex >= 0 ? + (bestIndex << INDEX_SHIFT) | shiftedThreshold : + INDEX_NEG_1 | shiftDistance(ABOVE_THRESHOLD); } int32_t LocaleDistance::getDesSuppScriptDistance( @@ -273,7 +321,7 @@ int32_t LocaleDistance::getRegionPartitionsDistance( d = getFallbackRegionDistance(iter, startState); star = true; } - if (d >= threshold) { + if (d > threshold) { return d; } else if (regionDistance < d) { regionDistance = d; @@ -286,7 +334,7 @@ int32_t LocaleDistance::getRegionPartitionsDistance( } } else if (!star) { int32_t d = getFallbackRegionDistance(iter, startState); - if (d >= threshold) { + if (d > threshold) { return d; } else if (regionDistance < d) { regionDistance = d; @@ -352,11 +400,14 @@ int32_t LocaleDistance::trieNext(BytesTrie &iter, const char *s, bool wantValue) } UBool LocaleDistance::isParadigmLSR(const LSR &lsr) const { - // Linear search for a very short list (length 6 as of 2019). - // If there are many paradigm LSRs we should use a hash set. + // Linear search for a very short list (length 6 as of 2019), + // because we look for equivalence not equality, and + // because it's easy. + // If there are many paradigm LSRs we should use a hash set + // with custom comparator and hasher. U_ASSERT(paradigmLSRsLength <= 15); for (int32_t i = 0; i < paradigmLSRsLength; ++i) { - if (lsr == paradigmLSRs[i]) { return true; } + if (lsr.isEquivalentTo(paradigmLSRs[i])) { return true; } } return false; } diff --git a/deps/icu-small/source/common/locdistance.h b/deps/icu-small/source/common/locdistance.h index 7439f51c56bf8c..ad8415138333dc 100644 --- a/deps/icu-small/source/common/locdistance.h +++ b/deps/icu-small/source/common/locdistance.h @@ -26,19 +26,37 @@ class LocaleDistance final : public UMemory { public: static const LocaleDistance *getSingleton(UErrorCode &errorCode); + static int32_t shiftDistance(int32_t distance) { + return distance << DISTANCE_SHIFT; + } + + static int32_t getShiftedDistance(int32_t indexAndDistance) { + return indexAndDistance & DISTANCE_MASK; + } + + static double getDistanceDouble(int32_t indexAndDistance) { + double shiftedDistance = getShiftedDistance(indexAndDistance); + return shiftedDistance / (1 << DISTANCE_SHIFT); + } + + static int32_t getIndex(int32_t indexAndDistance) { + // assert indexAndDistance >= 0; + return indexAndDistance >> INDEX_SHIFT; + } + /** * Finds the supported LSR with the smallest distance from the desired one. * Equivalent LSR subtags must be normalized into a canonical form. * - *

Returns the index of the lowest-distance supported LSR in bits 31..8 + *

Returns the index of the lowest-distance supported LSR in the high bits * (negative if none has a distance below the threshold), - * and its distance (0..ABOVE_THRESHOLD) in bits 7..0. + * and its distance (0..ABOVE_THRESHOLD) in the low bits. */ int32_t getBestIndexAndDistance(const LSR &desired, const LSR **supportedLSRs, int32_t supportedLSRsLength, - int32_t threshold, ULocMatchFavorSubtag favorSubtag) const; - - int32_t getParadigmLSRsLength() const { return paradigmLSRsLength; } + int32_t shiftedThreshold, + ULocMatchFavorSubtag favorSubtag, + ULocMatchDirection direction) const; UBool isParadigmLSR(const LSR &lsr) const; @@ -51,12 +69,34 @@ class LocaleDistance final : public UMemory { } private: - LocaleDistance(const LocaleDistanceData &data); + // The distance is shifted left to gain some fraction bits. + static constexpr int32_t DISTANCE_SHIFT = 3; + static constexpr int32_t DISTANCE_FRACTION_MASK = 7; + // 7 bits for 0..100 + static constexpr int32_t DISTANCE_INT_SHIFT = 7; + static constexpr int32_t INDEX_SHIFT = DISTANCE_INT_SHIFT + DISTANCE_SHIFT; + static constexpr int32_t DISTANCE_MASK = 0x3ff; + // tic constexpr int32_t MAX_INDEX = 0x1fffff; // avoids sign bit + static constexpr int32_t INDEX_NEG_1 = 0xfffffc00; + + static int32_t getDistanceFloor(int32_t indexAndDistance) { + return (indexAndDistance & DISTANCE_MASK) >> DISTANCE_SHIFT; + } + + LocaleDistance(const LocaleDistanceData &data, const XLikelySubtags &likely); LocaleDistance(const LocaleDistance &other) = delete; LocaleDistance &operator=(const LocaleDistance &other) = delete; static void initLocaleDistance(UErrorCode &errorCode); + UBool isMatch(const LSR &desired, const LSR &supported, + int32_t shiftedThreshold, ULocMatchFavorSubtag favorSubtag) const { + const LSR *pSupp = &supported; + return getBestIndexAndDistance( + desired, &pSupp, 1, + shiftedThreshold, favorSubtag, ULOCMATCH_DIRECTION_WITH_ONE_WAY) >= 0; + } + static int32_t getDesSuppScriptDistance(BytesTrie &iter, uint64_t startState, const char *desired, const char *supported); @@ -79,6 +119,8 @@ class LocaleDistance final : public UMemory { return defaultRegionDistance; } + const XLikelySubtags &likelySubtags; + // The trie maps each dlang+slang+dscript+sscript+dregion+sregion // (encoded in ASCII with bit 7 set on the last character of each subtag) to a distance. // There is also a trie value for each subsequence of whole subtags. diff --git a/deps/icu-small/source/common/locid.cpp b/deps/icu-small/source/common/locid.cpp index c6d3f88fc3be07..753a452120ee62 100644 --- a/deps/icu-small/source/common/locid.cpp +++ b/deps/icu-small/source/common/locid.cpp @@ -38,6 +38,7 @@ #include "unicode/strenum.h" #include "unicode/stringpiece.h" #include "unicode/uloc.h" +#include "unicode/ures.h" #include "bytesinkutil.h" #include "charstr.h" @@ -104,7 +105,6 @@ typedef enum ELocalePos { U_CFUNC int32_t locale_getKeywords(const char *localeID, char prev, char *keywords, int32_t keywordCapacity, - char *values, int32_t valuesCapacity, int32_t *valLen, UBool valuesToo, UErrorCode *status); @@ -184,17 +184,16 @@ Locale *locale_set_default_internal(const char *id, UErrorCode& status) { canonicalize = TRUE; // always canonicalize host ID } - char localeNameBuf[512]; - - if (canonicalize) { - uloc_canonicalize(id, localeNameBuf, sizeof(localeNameBuf)-1, &status); - } else { - uloc_getName(id, localeNameBuf, sizeof(localeNameBuf)-1, &status); + CharString localeNameBuf; + { + CharStringByteSink sink(&localeNameBuf); + if (canonicalize) { + ulocimp_canonicalize(id, sink, &status); + } else { + ulocimp_getName(id, sink, &status); + } } - localeNameBuf[sizeof(localeNameBuf)-1] = 0; // Force null termination in event of - // a long name filling the buffer. - // (long names are truncated.) - // + if (U_FAILURE(status)) { return gDefaultLocale; } @@ -208,14 +207,14 @@ Locale *locale_set_default_internal(const char *id, UErrorCode& status) { ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup); } - Locale *newDefault = (Locale *)uhash_get(gDefaultLocalesHashT, localeNameBuf); + Locale *newDefault = (Locale *)uhash_get(gDefaultLocalesHashT, localeNameBuf.data()); if (newDefault == NULL) { newDefault = new Locale(Locale::eBOGUS); if (newDefault == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return gDefaultLocale; } - newDefault->init(localeNameBuf, FALSE); + newDefault->init(localeNameBuf.data(), FALSE); uhash_put(gDefaultLocalesHashT, (char*) newDefault->getName(), newDefault, &status); if (U_FAILURE(status)) { return gDefaultLocale; @@ -509,6 +508,36 @@ Locale::operator==( const Locale& other) const #define ISASCIIALPHA(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) +namespace { + +CharString& AppendLSCVE(CharString& out, const char* language, const char* script, + const char* country, const char* variants, const char* extension, + UErrorCode& status) { + out.append(language, status); + if (script && script[0] != '\0') { + out.append('_', status); + out.append(script, status); + } + if (country && country[0] != '\0') { + out.append('_', status); + out.append(country, status); + } + if (variants && variants[0] != '\0') { + if ((script == nullptr || script[0] == '\0') && + (country == nullptr || country[0] == '\0')) { + out.append('_', status); + } + out.append('_', status); + out.append(variants, status); + } + if (extension && extension[0] != '\0') { + out.append(extension, status); + } + return out; +} + +} // namespace + /*This function initializes a Locale from a C locale ID*/ Locale& Locale::init(const char* localeID, UBool canonicalize) { @@ -632,6 +661,195 @@ Locale& Locale::init(const char* localeID, UBool canonicalize) break; } + if (canonicalize) { + UErrorCode status = U_ZERO_ERROR; + // TODO: Try to use ResourceDataValue and ures_getValueWithFallback() etc. + LocalUResourceBundlePointer metadata(ures_openDirect(NULL, "metadata", &status)); + LocalUResourceBundlePointer metadataAlias(ures_getByKey(metadata.getAlias(), "alias", NULL, &status)); + // Look up the metadata:alias:language:$key:replacement entries + // key could be one of the following: + // language + // language_Script_REGION + // language_REGION + // language_variant + do { + // The resource structure looks like + // metadata { + // alias { + // language { + // art_lojban { + // replacement{"jbo"} + // } + // ... + // ks_Arab_IN { + // replacement{"ks_IN"} + // } + // ... + // no { + // replacement{"nb"} + // } + // .... + // zh_CN { + // replacement{"zh_Hans_CN"} + // } + // } + // ... + // } + // } + LocalUResourceBundlePointer languageAlias(ures_getByKey(metadataAlias.getAlias(), "language", NULL, &status)); + if (U_FAILURE(status)) + break; + CharString temp; + // Handle cases of key pattern "language _ variant" + // ex: Map "art_lojban" to "jbo" + const char* variants = getVariant(); + if (variants != nullptr && variants[0] != '\0') { + const char* begin = variants; + const char* end = begin; + // We may have multiple variants, need to look at each of + // them. + do { + status = U_ZERO_ERROR; + end = uprv_strchr(begin, '_'); + int32_t len = (end == nullptr) ? int32_t(uprv_strlen(begin)) : int32_t(end - begin); + temp.clear().append(getLanguage(), status).append("_", status).append(begin, len, status); + LocalUResourceBundlePointer languageVariantAlias( + ures_getByKey(languageAlias.getAlias(), + temp.data(), + NULL, &status)); + temp.clear().appendInvariantChars( + UnicodeString(ures_getStringByKey(languageVariantAlias.getAlias(), "replacement", nullptr, &status)), status); + if (U_SUCCESS(status)) { + CharString newVar; + if (begin != variants) { + newVar.append(variants, static_cast(begin - variants - 1), status); + } + if (end != nullptr) { + if (begin != variants) { + newVar.append("_", status); + } + newVar.append(end + 1, status); + } + Locale l(temp.data()); + init(AppendLSCVE(temp.clear(), + l.getLanguage(), + (getScript() != nullptr && getScript()[0] != '\0') ? getScript() : l.getScript(), + (getCountry() != nullptr && getCountry()[0] != '\0') ? getCountry() : l.getCountry(), + newVar.data(), + uprv_strchr(fullName, '@'), status).data(), false); + break; + } + begin = end + 1; + } while (end != nullptr); + } // End of handle language _ variant + // Handle cases of key pattern "language _ Script _ REGION" + // ex: Map "ks_Arab_IN" to "ks_IN" + if (getScript() != nullptr && getScript()[0] != '\0' && + getCountry() != nullptr && getCountry()[0] != '\0') { + status = U_ZERO_ERROR; + LocalUResourceBundlePointer replacedAlias( + ures_getByKey(languageAlias.getAlias(), + AppendLSCVE(temp.clear(), getLanguage(), getScript(), getCountry(), + nullptr, nullptr, status).data(), NULL, &status)); + temp.clear().appendInvariantChars( + UnicodeString(ures_getStringByKey(replacedAlias.getAlias(), "replacement", nullptr, &status)), status); + if (U_SUCCESS(status)) { + Locale l(temp.data()); + init(AppendLSCVE(temp.clear(), + l.getLanguage(), + l.getScript(), + l.getCountry(), + getVariant(), + uprv_strchr(fullName, '@'), status).data(), false); + } + } // End of handle language _ Script _ REGION + // Handle cases of key pattern "language _ REGION" + // ex: Map "zh_CN" to "zh_Hans_CN" + if (getCountry() != nullptr && getCountry()[0] != '\0') { + status = U_ZERO_ERROR; + LocalUResourceBundlePointer replacedAlias( + ures_getByKey(languageAlias.getAlias(), + AppendLSCVE(temp.clear(), getLanguage(), nullptr, getCountry(), + nullptr, nullptr, status).data(), NULL, &status)); + temp.clear().appendInvariantChars( + UnicodeString(ures_getStringByKey(replacedAlias.getAlias(), "replacement", nullptr, &status)), status); + if (U_SUCCESS(status)) { + Locale l(temp.data()); + init(AppendLSCVE(temp.clear(), + l.getLanguage(), + (getScript() != nullptr && getScript()[0] != '\0') ? getScript() : l.getScript(), + l.getCountry(), + getVariant(), + uprv_strchr(fullName, '@'), status).data(), false); + } + } // End of handle "language _ REGION" + // Handle cases of key pattern "language" + // ex: Map "no" to "nb" + { + status = U_ZERO_ERROR; + LocalUResourceBundlePointer replaceLanguageAlias(ures_getByKey(languageAlias.getAlias(), getLanguage(), NULL, &status)); + temp.clear().appendInvariantChars( + UnicodeString(ures_getStringByKey(replaceLanguageAlias.getAlias(), "replacement", nullptr, &status)), status); + if (U_SUCCESS(status)) { + Locale l(temp.data()); + init(AppendLSCVE(temp.clear(), + l.getLanguage(), + (getScript() != nullptr && getScript()[0] != '\0') ? getScript() : l.getScript(), + (getCountry() != nullptr && getCountry()[0] != '\0') ? getCountry() : l.getCountry(), + getVariant(), + uprv_strchr(fullName, '@'), status).data(), false); + } + } // End of handle "language" + + // Look up the metadata:alias:territory:$key:replacement entries + // key is region code. + if (getCountry() != nullptr) { + status = U_ZERO_ERROR; + // The resource structure looks like + // metadata { + // alias { + // ... + // territory: { + // 172 { + // replacement{"RU AM AZ BY GE KG KZ MD TJ TM UA UZ"} + // } + // ... + // 554 { + // replacement{"NZ"} + // } + // } + // } + // } + LocalUResourceBundlePointer territoryAlias(ures_getByKey(metadataAlias.getAlias(), "territory", NULL, &status)); + LocalUResourceBundlePointer countryAlias(ures_getByKey(territoryAlias.getAlias(), getCountry(), NULL, &status)); + UnicodeString replacements( + ures_getStringByKey(countryAlias.getAlias(), "replacement", nullptr, &status)); + if (U_SUCCESS(status)) { + CharString replacedCountry; + int32_t delPos = replacements.indexOf(' '); + if (delPos == -1) { + replacedCountry.appendInvariantChars(replacements, status); + } else { + Locale l(AppendLSCVE(temp.clear(), getLanguage(), nullptr, getScript(), + nullptr, nullptr, status).data()); + l.addLikelySubtags(status); + if (replacements.indexOf(UnicodeString(l.getCountry())) != -1) { + replacedCountry.append(l.getCountry(), status); + } else { + replacedCountry.appendInvariantChars(replacements.getBuffer(), delPos, status); + } + } + init(AppendLSCVE(temp.clear(), + getLanguage(), + getScript(), + replacedCountry.data(), + getVariant(), + uprv_strchr(fullName, '@'), status).data(), false); + } + } // End of handle REGION + } while (0); + } // if (canonicalize) { + // successful end of init() return *this; } while(0); /*loop doesn't iterate*/ @@ -778,6 +996,25 @@ Locale::minimizeSubtags(UErrorCode& status) { } } +void +Locale::canonicalize(UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } + if (isBogus()) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + CharString uncanonicalized(fullName, status); + if (U_FAILURE(status)) { + return; + } + init(uncanonicalized.data(), /*canonicalize=*/TRUE); + if (isBogus()) { + status = U_ILLEGAL_ARGUMENT_ERROR; + } +} + Locale U_EXPORT2 Locale::forLanguageTag(StringPiece tag, UErrorCode& status) { @@ -1189,7 +1426,7 @@ Locale::createKeywords(UErrorCode &status) const const char* assignment = uprv_strchr(fullName, '='); if(variantStart) { if(assignment > variantStart) { - int32_t keyLen = locale_getKeywords(variantStart+1, '@', keywords, keywordCapacity, NULL, 0, NULL, FALSE, &status); + int32_t keyLen = locale_getKeywords(variantStart+1, '@', keywords, keywordCapacity, FALSE, &status); if(U_SUCCESS(status) && keyLen) { result = new KeywordEnumeration(keywords, keyLen, 0, status); if (!result) { @@ -1218,7 +1455,7 @@ Locale::createUnicodeKeywords(UErrorCode &status) const const char* assignment = uprv_strchr(fullName, '='); if(variantStart) { if(assignment > variantStart) { - int32_t keyLen = locale_getKeywords(variantStart+1, '@', keywords, keywordCapacity, NULL, 0, NULL, FALSE, &status); + int32_t keyLen = locale_getKeywords(variantStart+1, '@', keywords, keywordCapacity, FALSE, &status); if(U_SUCCESS(status) && keyLen) { result = new UnicodeKeywordEnumeration(keywords, keyLen, 0, status); if (!result) { @@ -1340,7 +1577,31 @@ Locale::getUnicodeKeywordValue(StringPiece keywordName, void Locale::setKeywordValue(const char* keywordName, const char* keywordValue, UErrorCode &status) { - uloc_setKeywordValue(keywordName, keywordValue, fullName, ULOC_FULLNAME_CAPACITY, &status); + if (U_FAILURE(status)) { + return; + } + int32_t bufferLength = uprv_max((int32_t)(uprv_strlen(fullName) + 1), ULOC_FULLNAME_CAPACITY); + int32_t newLength = uloc_setKeywordValue(keywordName, keywordValue, fullName, + bufferLength, &status) + 1; + /* Handle the case the current buffer is not enough to hold the new id */ + if (status == U_BUFFER_OVERFLOW_ERROR) { + U_ASSERT(newLength > bufferLength); + char* newFullName = (char *)uprv_malloc(newLength); + if (newFullName == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + uprv_strcpy(newFullName, fullName); + if (fullName != fullNameBuffer) { + // if full Name is already on the heap, need to free it. + uprv_free(fullName); + } + fullName = newFullName; + status = U_ZERO_ERROR; + uloc_setKeywordValue(keywordName, keywordValue, fullName, newLength, &status); + } else { + U_ASSERT(newLength <= bufferLength); + } if (U_SUCCESS(status) && baseName == fullName) { // May have added the first keyword, meaning that the fullName is no longer also the baseName. initBaseName(status); diff --git a/deps/icu-small/source/common/loclikelysubtags.cpp b/deps/icu-small/source/common/loclikelysubtags.cpp index d7f5e124c2c790..1fbf1a1463299f 100644 --- a/deps/icu-small/source/common/loclikelysubtags.cpp +++ b/deps/icu-small/source/common/loclikelysubtags.cpp @@ -250,7 +250,8 @@ struct XLikelySubtagsData { for (int32_t i = 0, j = 0; i < lsrSubtagsLength; i += 3, ++j) { lsrs[j] = LSR(strings.get(lsrSubtagIndexes[i]), strings.get(lsrSubtagIndexes[i + 1]), - strings.get(lsrSubtagIndexes[i + 2])); + strings.get(lsrSubtagIndexes[i + 2]), + LSR::IMPLICIT_LSR); } if (partitionsLength > 0) { @@ -275,7 +276,8 @@ struct XLikelySubtagsData { for (int32_t i = 0, j = 0; i < paradigmSubtagsLength; i += 3, ++j) { paradigms[j] = LSR(strings.get(paradigmSubtagIndexes[i]), strings.get(paradigmSubtagIndexes[i + 1]), - strings.get(paradigmSubtagIndexes[i + 2])); + strings.get(paradigmSubtagIndexes[i + 2]), + LSR::DONT_CARE_FLAGS); } distanceData.paradigms = paradigms; } @@ -383,7 +385,7 @@ LSR XLikelySubtags::makeMaximizedLsrFrom(const Locale &locale, UErrorCode &error const char *name = locale.getName(); if (uprv_isAtSign(name[0]) && name[1] == 'x' && name[2] == '=') { // name.startsWith("@x=") // Private use language tag x-subtag-subtag... - return LSR(name, "", ""); + return LSR(name, "", "", LSR::EXPLICIT_LSR); } return makeMaximizedLsr(locale.getLanguage(), locale.getScript(), locale.getCountry(), locale.getVariant(), errorCode); @@ -407,26 +409,31 @@ LSR XLikelySubtags::makeMaximizedLsr(const char *language, const char *script, c if (region[0] == 'X' && (c1 = region[1]) != 0 && region[2] == 0) { switch (c1) { case 'A': - return LSR(PSEUDO_ACCENTS_PREFIX, language, script, region, errorCode); + return LSR(PSEUDO_ACCENTS_PREFIX, language, script, region, + LSR::EXPLICIT_LSR, errorCode); case 'B': - return LSR(PSEUDO_BIDI_PREFIX, language, script, region, errorCode); + return LSR(PSEUDO_BIDI_PREFIX, language, script, region, + LSR::EXPLICIT_LSR, errorCode); case 'C': - return LSR(PSEUDO_CRACKED_PREFIX, language, script, region, errorCode); + return LSR(PSEUDO_CRACKED_PREFIX, language, script, region, + LSR::EXPLICIT_LSR, errorCode); default: // normal locale break; } } if (variant[0] == 'P' && variant[1] == 'S') { + int32_t lsrFlags = *region == 0 ? + LSR::EXPLICIT_LANGUAGE | LSR::EXPLICIT_SCRIPT : LSR::EXPLICIT_LSR; if (uprv_strcmp(variant, "PSACCENT") == 0) { return LSR(PSEUDO_ACCENTS_PREFIX, language, script, - *region == 0 ? "XA" : region, errorCode); + *region == 0 ? "XA" : region, lsrFlags, errorCode); } else if (uprv_strcmp(variant, "PSBIDI") == 0) { return LSR(PSEUDO_BIDI_PREFIX, language, script, - *region == 0 ? "XB" : region, errorCode); + *region == 0 ? "XB" : region, lsrFlags, errorCode); } else if (uprv_strcmp(variant, "PSCRACK") == 0) { return LSR(PSEUDO_CRACKED_PREFIX, language, script, - *region == 0 ? "XC" : region, errorCode); + *region == 0 ? "XC" : region, lsrFlags, errorCode); } // else normal locale } @@ -448,7 +455,7 @@ LSR XLikelySubtags::maximize(const char *language, const char *script, const cha region = ""; } if (*script != 0 && *region != 0 && *language != 0) { - return LSR(language, script, region); // already maximized + return LSR(language, script, region, LSR::EXPLICIT_LSR); // already maximized } uint32_t retainOldMask = 0; @@ -535,7 +542,7 @@ LSR XLikelySubtags::maximize(const char *language, const char *script, const cha if (retainOldMask == 0) { // Quickly return a copy of the lookup-result LSR // without new allocation of the subtags. - return LSR(result.language, result.script, result.region); + return LSR(result.language, result.script, result.region, result.flags); } if ((retainOldMask & 4) == 0) { language = result.language; @@ -546,7 +553,108 @@ LSR XLikelySubtags::maximize(const char *language, const char *script, const cha if ((retainOldMask & 1) == 0) { region = result.region; } - return LSR(language, script, region); + // retainOldMask flags = LSR explicit-subtag flags + return LSR(language, script, region, retainOldMask); +} + +int32_t XLikelySubtags::compareLikely(const LSR &lsr, const LSR &other, int32_t likelyInfo) const { + // If likelyInfo >= 0: + // likelyInfo bit 1 is set if the previous comparison with lsr + // was for equal language and script. + // Otherwise the scripts differed. + if (uprv_strcmp(lsr.language, other.language) != 0) { + return 0xfffffffc; // negative, lsr not better than other + } + if (uprv_strcmp(lsr.script, other.script) != 0) { + int32_t index; + if (likelyInfo >= 0 && (likelyInfo & 2) == 0) { + index = likelyInfo >> 2; + } else { + index = getLikelyIndex(lsr.language, ""); + likelyInfo = index << 2; + } + const LSR &likely = lsrs[index]; + if (uprv_strcmp(lsr.script, likely.script) == 0) { + return likelyInfo | 1; + } else { + return likelyInfo & ~1; + } + } + if (uprv_strcmp(lsr.region, other.region) != 0) { + int32_t index; + if (likelyInfo >= 0 && (likelyInfo & 2) != 0) { + index = likelyInfo >> 2; + } else { + index = getLikelyIndex(lsr.language, lsr.region); + likelyInfo = (index << 2) | 2; + } + const LSR &likely = lsrs[index]; + if (uprv_strcmp(lsr.region, likely.region) == 0) { + return likelyInfo | 1; + } else { + return likelyInfo & ~1; + } + } + return likelyInfo & ~1; // lsr not better than other +} + +// Subset of maximize(). +int32_t XLikelySubtags::getLikelyIndex(const char *language, const char *script) const { + if (uprv_strcmp(language, "und") == 0) { + language = ""; + } + if (uprv_strcmp(script, "Zzzz") == 0) { + script = ""; + } + + BytesTrie iter(trie); + uint64_t state; + int32_t value; + // Small optimization: Array lookup for first language letter. + int32_t c0; + if (0 <= (c0 = uprv_lowerOrdinal(language[0])) && c0 <= 25 && + language[1] != 0 && // language.length() >= 2 + (state = trieFirstLetterStates[c0]) != 0) { + value = trieNext(iter.resetToState64(state), language, 1); + } else { + value = trieNext(iter, language, 0); + } + if (value >= 0) { + state = iter.getState64(); + } else { + iter.resetToState64(trieUndState); // "und" ("*") + state = 0; + } + + if (value > 0) { + // Intermediate or final value from just language. + if (value == SKIP_SCRIPT) { + value = 0; + } + } else { + value = trieNext(iter, script, 0); + if (value >= 0) { + state = iter.getState64(); + } else { + if (state == 0) { + iter.resetToState64(trieUndZzzzState); // "und-Zzzz" ("**") + } else { + iter.resetToState64(state); + value = trieNext(iter, "", 0); + U_ASSERT(value >= 0); + state = iter.getState64(); + } + } + } + + if (value > 0) { + // Final value from just language or language+script. + } else { + value = trieNext(iter, "", 0); + U_ASSERT(value > 0); + } + U_ASSERT(value < lsrsLength); + return value; } int32_t XLikelySubtags::trieNext(BytesTrie &iter, const char *s, int32_t i) { @@ -615,9 +723,9 @@ LSR XLikelySubtags::minimizeSubtags(const char *languageIn, const char *scriptIn boolean favorRegionOk = false; if (result.script.equals(value00.script)) { //script is default if (result.region.equals(value00.region)) { - return new LSR(result.language, "", ""); + return new LSR(result.language, "", "", LSR.DONT_CARE_FLAGS); } else if (fieldToFavor == ULocale.Minimize.FAVOR_REGION) { - return new LSR(result.language, "", result.region); + return new LSR(result.language, "", result.region, LSR.DONT_CARE_FLAGS); } else { favorRegionOk = true; } @@ -627,9 +735,9 @@ LSR XLikelySubtags::minimizeSubtags(const char *languageIn, const char *scriptIn // Maybe do later, but for now use the straightforward code. LSR result2 = maximize(languageIn, scriptIn, ""); if (result2.equals(result)) { - return new LSR(result.language, result.script, ""); + return new LSR(result.language, result.script, "", LSR.DONT_CARE_FLAGS); } else if (favorRegionOk) { - return new LSR(result.language, "", result.region); + return new LSR(result.language, "", result.region, LSR.DONT_CARE_FLAGS); } return result; } diff --git a/deps/icu-small/source/common/loclikelysubtags.h b/deps/icu-small/source/common/loclikelysubtags.h index 8c8a08ac5e314e..90ddfffaca672d 100644 --- a/deps/icu-small/source/common/loclikelysubtags.h +++ b/deps/icu-small/source/common/loclikelysubtags.h @@ -85,6 +85,18 @@ class XLikelySubtags final : public UMemory { // VisibleForTesting LSR makeMaximizedLsrFrom(const Locale &locale, UErrorCode &errorCode) const; + /** + * Tests whether lsr is "more likely" than other. + * For example, fr-Latn-FR is more likely than fr-Latn-CH because + * FR is the default region for fr-Latn. + * + * The likelyInfo caches lookup information between calls. + * The return value is an updated likelyInfo value, + * with bit 0 set if lsr is "more likely". + * The initial value of likelyInfo must be negative. + */ + int32_t compareLikely(const LSR &lsr, const LSR &other, int32_t likelyInfo) const; + // TODO(ICU-20777): Switch Locale/uloc_ likely-subtags API from the old code // in loclikely.cpp to this new code, including activating this // minimizeSubtags() function. The LocaleMatcher does not minimize. @@ -111,6 +123,8 @@ class XLikelySubtags final : public UMemory { */ LSR maximize(const char *language, const char *script, const char *region) const; + int32_t getLikelyIndex(const char *language, const char *script) const; + static int32_t trieNext(BytesTrie &iter, const char *s, int32_t i); UResourceBundle *langInfoBundle; diff --git a/deps/icu-small/source/common/lsr.cpp b/deps/icu-small/source/common/lsr.cpp index 0c28eeda1bc7b6..d4308ad0275428 100644 --- a/deps/icu-small/source/common/lsr.cpp +++ b/deps/icu-small/source/common/lsr.cpp @@ -14,9 +14,10 @@ U_NAMESPACE_BEGIN -LSR::LSR(char prefix, const char *lang, const char *scr, const char *r, UErrorCode &errorCode) : +LSR::LSR(char prefix, const char *lang, const char *scr, const char *r, int32_t f, + UErrorCode &errorCode) : language(nullptr), script(nullptr), region(r), - regionIndex(indexForRegion(region)) { + regionIndex(indexForRegion(region)), flags(f) { if (U_SUCCESS(errorCode)) { CharString langScript; langScript.append(prefix, errorCode).append(lang, errorCode).append('\0', errorCode); @@ -32,7 +33,8 @@ LSR::LSR(char prefix, const char *lang, const char *scr, const char *r, UErrorCo LSR::LSR(LSR &&other) U_NOEXCEPT : language(other.language), script(other.script), region(other.region), owned(other.owned), - regionIndex(other.regionIndex), hashCode(other.hashCode) { + regionIndex(other.regionIndex), flags(other.flags), + hashCode(other.hashCode) { if (owned != nullptr) { other.language = other.script = ""; other.owned = nullptr; @@ -50,6 +52,7 @@ LSR &LSR::operator=(LSR &&other) U_NOEXCEPT { script = other.script; region = other.region; regionIndex = other.regionIndex; + flags = other.flags; owned = other.owned; hashCode = other.hashCode; if (owned != nullptr) { @@ -60,7 +63,7 @@ LSR &LSR::operator=(LSR &&other) U_NOEXCEPT { return *this; } -UBool LSR::operator==(const LSR &other) const { +UBool LSR::isEquivalentTo(const LSR &other) const { return uprv_strcmp(language, other.language) == 0 && uprv_strcmp(script, other.script) == 0 && @@ -69,6 +72,16 @@ UBool LSR::operator==(const LSR &other) const { (regionIndex > 0 || uprv_strcmp(region, other.region) == 0); } +UBool LSR::operator==(const LSR &other) const { + return + uprv_strcmp(language, other.language) == 0 && + uprv_strcmp(script, other.script) == 0 && + regionIndex == other.regionIndex && + // Compare regions if both are ill-formed (and their indexes are 0). + (regionIndex > 0 || uprv_strcmp(region, other.region) == 0) && + flags == other.flags; +} + int32_t LSR::indexForRegion(const char *region) { int32_t c = region[0]; int32_t a = c - '0'; @@ -90,10 +103,10 @@ int32_t LSR::indexForRegion(const char *region) { LSR &LSR::setHashCode() { if (hashCode == 0) { - hashCode = - (ustr_hashCharsN(language, static_cast(uprv_strlen(language))) * 37 + - ustr_hashCharsN(script, static_cast(uprv_strlen(script)))) * 37 + - regionIndex; + uint32_t h = ustr_hashCharsN(language, static_cast(uprv_strlen(language))); + h = h * 37 + ustr_hashCharsN(script, static_cast(uprv_strlen(script))); + h = h * 37 + regionIndex; + hashCode = h * 37 + flags; } return *this; } diff --git a/deps/icu-small/source/common/lsr.h b/deps/icu-small/source/common/lsr.h index db6cf938f47d02..d535e5b0376cd3 100644 --- a/deps/icu-small/source/common/lsr.h +++ b/deps/icu-small/source/common/lsr.h @@ -16,26 +16,35 @@ U_NAMESPACE_BEGIN struct LSR final : public UMemory { static constexpr int32_t REGION_INDEX_LIMIT = 1001 + 26 * 26; + static constexpr int32_t EXPLICIT_LSR = 7; + static constexpr int32_t EXPLICIT_LANGUAGE = 4; + static constexpr int32_t EXPLICIT_SCRIPT = 2; + static constexpr int32_t EXPLICIT_REGION = 1; + static constexpr int32_t IMPLICIT_LSR = 0; + static constexpr int32_t DONT_CARE_FLAGS = 0; + const char *language; const char *script; const char *region; char *owned = nullptr; /** Index for region, 0 if ill-formed. @see indexForRegion */ int32_t regionIndex = 0; + int32_t flags = 0; /** Only set for LSRs that will be used in a hash table. */ int32_t hashCode = 0; LSR() : language("und"), script(""), region("") {} /** Constructor which aliases all subtag pointers. */ - LSR(const char *lang, const char *scr, const char *r) : + LSR(const char *lang, const char *scr, const char *r, int32_t f) : language(lang), script(scr), region(r), - regionIndex(indexForRegion(region)) {} + regionIndex(indexForRegion(region)), flags(f) {} /** * Constructor which prepends the prefix to the language and script, * copies those into owned memory, and aliases the region. */ - LSR(char prefix, const char *lang, const char *scr, const char *r, UErrorCode &errorCode); + LSR(char prefix, const char *lang, const char *scr, const char *r, int32_t f, + UErrorCode &errorCode); LSR(LSR &&other) U_NOEXCEPT; LSR(const LSR &other) = delete; inline ~LSR() { @@ -55,6 +64,7 @@ struct LSR final : public UMemory { */ static int32_t indexForRegion(const char *region); + UBool isEquivalentTo(const LSR &other) const; UBool operator==(const LSR &other) const; inline UBool operator!=(const LSR &other) const { diff --git a/deps/icu-small/source/common/norm2_nfc_data.h b/deps/icu-small/source/common/norm2_nfc_data.h index c04bdac5ead393..455cc0c42850ae 100644 --- a/deps/icu-small/source/common/norm2_nfc_data.h +++ b/deps/icu-small/source/common/norm2_nfc_data.h @@ -12,27 +12,27 @@ #ifdef INCLUDED_FROM_NORMALIZER2_CPP static const UVersionInfo norm2_nfc_data_formatVersion={4,0,0,0}; -static const UVersionInfo norm2_nfc_data_dataVersion={0xc,1,0,0}; +static const UVersionInfo norm2_nfc_data_dataVersion={0xd,0,0,0}; static const int32_t norm2_nfc_data_indexes[Normalizer2Impl::IX_COUNT]={ -0x50,0x4ae0,0x8738,0x8838,0x8838,0x8838,0x8838,0x8838,0xc0,0x300,0xadc,0x29d0,0x3c56,0xfc00,0x1282,0x3b8c, -0x3c24,0x3c56,0x300,0 +0x50,0x4bac,0x8814,0x8914,0x8914,0x8914,0x8914,0x8914,0xc0,0x300,0xae2,0x29e0,0x3c66,0xfc00,0x1288,0x3b9c, +0x3c34,0x3c66,0x300,0 }; -static const uint16_t norm2_nfc_data_trieIndex[1712]={ +static const uint16_t norm2_nfc_data_trieIndex[1746]={ 0,0x40,0x7b,0xbb,0xfb,0x13a,0x17a,0x1b2,0x1f2,0x226,0x254,0x226,0x294,0x2d4,0x313,0x353, 0x393,0x3d2,0x40f,0x44e,0x226,0x226,0x488,0x4c8,0x4f8,0x530,0x226,0x570,0x59f,0x5de,0x226,0x5f3, 0x631,0x65f,0x226,0x68c,0x6cc,0x709,0x729,0x768,0x7a7,0x7e4,0x803,0x840,0x729,0x879,0x8a7,0x8e6, 0x226,0x920,0x937,0x977,0x98e,0x9cd,0x226,0xa03,0xa23,0xa5e,0xa6a,0xaa5,0xacd,0xb0a,0xb4a,0xb84, 0xb9f,0x226,0xbda,0x226,0xc1a,0xc39,0xc6f,0xcac,0x226,0x226,0x226,0x226,0x226,0xccf,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0xcfb,0x226,0x226,0xd30, -0x226,0x226,0xd4e,0x226,0xd78,0x226,0x226,0x226,0xdb4,0xdd4,0xe14,0x226,0xe52,0xe92,0xec6,0xef2, -0x808,0x226,0x226,0xf26,0x226,0x226,0x226,0xf66,0xfa6,0xfe6,0x1026,0x1066,0x10a6,0x10e6,0x1126,0x1166, -0x11a6,0x226,0x226,0x11d6,0x1207,0x226,0x1237,0x126a,0x12a7,0x12e6,0x1326,0x135c,0x138a,0x226,0x226,0x226, +0x226,0x226,0xd4e,0x226,0xd78,0x226,0x226,0x226,0xdb4,0xdd4,0xe14,0xe53,0xe8e,0xece,0xf02,0xf2e, +0x808,0x226,0x226,0xf62,0x226,0x226,0x226,0xfa2,0xfe2,0x1022,0x1062,0x10a2,0x10e2,0x1122,0x1162,0x11a2, +0x11e2,0x226,0x226,0x1212,0x1243,0x226,0x1273,0x12a6,0x12e3,0x1322,0x1362,0x1398,0x13c6,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x13b5,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0xcbd,0x226,0x13d2,0x226,0x1412,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x1452,0x148c,0x14ca,0x150a,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x13f1,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0xcbd,0x226,0x140e,0x226,0x144e,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x148e,0x14c8,0x1506,0x1546,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, @@ -61,20 +61,20 @@ static const uint16_t norm2_nfc_data_trieIndex[1712]={ 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1549,0x1587,0x15a7,0x226,0x226,0x226,0x226, -0x15e1,0x226,0x226,0x161d,0x164f,0x167d,0x80c,0x1690,0x226,0x226,0x16a0,0x16e0,0x226,0x226,0x226,0x13e4, -0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728, -0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738, -0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c, -0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x1734,0x1720, -0x1728,0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728,0x1730, -0x1738,0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738,0x1724, -0x172c,0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x1734, -0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728, -0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738, -0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c, -0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x1734,0x1720,0x1728,0x1730,0x1738,0x1724,0x172c,0x176c,0x226, -0x17ac,0x17e7,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1585,0x15c3,0x15e3,0x226,0x226,0x226,0x226, +0x161d,0x226,0x226,0x1645,0x1677,0x16a5,0x80c,0x16b8,0x226,0x226,0x16c8,0x1708,0x226,0x226,0x226,0x1420, +0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750, +0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760, +0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754, +0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x175c,0x1748, +0x1750,0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750,0x1758, +0x1760,0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760,0x174c, +0x1754,0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x175c, +0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750, +0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760, +0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754, +0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x175c,0x1748,0x1750,0x1758,0x1760,0x174c,0x1754,0x1794,0x226, +0x17d4,0x180f,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, @@ -82,54 +82,57 @@ static const uint16_t norm2_nfc_data_trieIndex[1712]={ 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x1827,0x1867,0x18a7,0x18e7,0x1927,0x1967,0x19a7,0x19e7,0x1a0a,0x1a4a,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1a6a,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x635,0x644,0x65a,0x679,0x68e,0x68e,0x68e,0x692,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x184f,0x188f,0x18cf,0x190f,0x194f,0x198f,0x19cf,0x1a0f,0x1a32,0x1a72,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1a92,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x655,0x664,0x67c,0x69b,0x6b0,0x6b0,0x6b0,0x6b4,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0xbda,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x54f,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x40c, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1a9d,0x226,0x226,0x1aad,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1ac5,0x226,0x226,0x1ad5,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0xdc6,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1abd,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1ac7,0x54f, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x7eb,0x226,0x226,0x9ba,0x226,0x1ad7, -0x1ae4,0x1af0,0x226,0x226,0x226,0x226,0x414,0x226,0x1afb,0x1b0b,0x226,0x226,0x226,0x7e0,0x226,0x226, -0x226,0x226,0x1b1b,0x226,0x226,0x226,0x1b26,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x1b2d,0x226,0x226,0x226,0x226,0x1b38,0x1b47,0x8f6,0x1b55,0x412,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x1b63,0x798,0x226,0x226,0x226,0x226,0x226,0x1b73,0x1b82,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x8d6,0x1b8a,0x1b9a,0x226,0x226,0x226,0x9ba, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1ba4,0x226,0x226,0x226,0x226,0x226,0x226,0x7e6,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1ba1,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1ae5,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x15d6,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x1aef,0x54f,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x7eb,0x226,0x226, +0x9ba,0x226,0x1aff,0x1b0c,0x1b18,0x226,0x226,0x226,0x226,0x414,0x226,0x1b23,0x1b33,0x226,0x226,0x226, +0x7e0,0x226,0x226,0x226,0x226,0x1b43,0x226,0x226,0x226,0x1b4e,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x1b55,0x226,0x226,0x226,0x226,0x1b60,0x1b6f,0x8f6,0x1b7d,0x412,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x1b8b,0x798,0x226,0x226,0x226,0x226,0x226,0x1b9b,0x1baa,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x8d6,0x1bb2,0x1bc2,0x226, +0x226,0x226,0x9ba,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1bcc,0x226,0x226,0x226,0x226,0x226, +0x226,0x7e6,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1bc9, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1bdc, +0x7e0,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x84d,0x226,0x226,0x226,0x7ed,0x7ea, +0x226,0x226,0x226,0x226,0x7e8,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x9ba,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0xbd4,0x226,0x226,0x226, +0x226,0x7ea,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x1bec,0x226,0x226,0x226,0xefb,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x84d,0x226,0x226,0x226,0x7ed,0x7ea,0x226,0x226,0x226, -0x226,0x7e8,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x9ba,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0xbd4,0x226,0x226,0x226,0x226,0x7ea,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1bb4,0x226, -0x226,0x226,0xebf,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1bb9, +0x226,0x226,0x226,0x226,0x226,0x1bfc,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1bfe, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x1bc8,0x1bd8,0x1be6,0x1bf3,0x226,0x1bff,0x1c0d,0x1c1d,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x1c0d,0x1c1d,0x1c2b,0x1c38,0x226,0x1c44,0x1c52,0x1c62,0x226,0x226, 0x226,0x226,0xcea,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1c2d,0x1c35, -0x1c43,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0xebf,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1c72,0x1c7a, +0x1c88,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0xefb,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x4fc,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x1c53,0x226,0x226,0x226,0x226,0x226,0x226,0x1c5f,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x1c6f,0x1c7f,0x1c8f,0x1c9f,0x1caf,0x1cbf,0x1ccf,0x1cdf,0x1cef,0x1cff,0x1d0f, -0x1d1f,0x1d2f,0x1d3f,0x1d4f,0x1d5f,0x1d6f,0x1d7f,0x1d8f,0x1d9f,0x1daf,0x1dbf,0x1dcf,0x1ddf,0x1def,0x1dff,0x1e0f, -0x1e1f,0x1e2f,0x1e3f,0x1e4f,0x1e5f,0x1e6f,0x1e7f,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x1c98,0x226,0x226,0x226,0x226,0x226,0x226,0x1ca4,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x1cb4,0x1cc4,0x1cd4,0x1ce4,0x1cf4,0x1d04,0x1d14,0x1d24,0x1d34,0x1d44,0x1d54, +0x1d64,0x1d74,0x1d84,0x1d94,0x1da4,0x1db4,0x1dc4,0x1dd4,0x1de4,0x1df4,0x1e04,0x1e14,0x1e24,0x1e34,0x1e44,0x1e54, +0x1e64,0x1e74,0x1e84,0x1e94,0x1ea4,0x1eb4,0x1ec4,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, 0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, -0x226,0x226,0x226,0x226,0x226,0x408,0x428,0xc4,0xc4,0xc4,0x448,0x457,0x46a,0x486,0x4a3,0x4bf, -0x4dc,0x4f9,0x518,0x535,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, -0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0x54f,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, +0x226,0x226,0x226,0x226,0x226,0x408,0x428,0xc4,0xc4,0xc4,0x448,0x457,0x46d,0x489,0x4a6,0x4c2, +0x4df,0x4fc,0x51b,0x538,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, +0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0x552,0xc4,0x566,0xc4,0xc4,0xc4,0xc4, 0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, -0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0x566,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, -0xc4,0x571,0x58e,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0x5ae,0x5c2,0xc4,0xc4,0x5d5,0xc4,0xc4, +0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0x586,0xc4,0xc4,0xc4,0xc4,0xc4, +0xc4,0xc4,0xc4,0x591,0x5ae,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0x5ce,0x5e2,0xc4,0xc4,0x5f5, 0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, -0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0x5f5,0x615 +0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, +0x615,0x635 }; -static const uint16_t norm2_nfc_data_trieData[7824]={ +static const uint16_t norm2_nfc_data_trieData[7892]={ 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,1,1, @@ -141,30 +144,30 @@ static const uint16_t norm2_nfc_data_trieData[7824]={ 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,0x5e8,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0x1284,0x128a,0xade,0x1290,0xaf4, -0xafe,0x5f4,0xb08,0x1296,0x129c,0xb12,0x12a2,0x12a8,0x12ae,0x12b4,0xb28,1,0x12ba,0x12c0,0x12c6,0xb32, -0xb48,0xb5a,1,0x5fc,0x12cc,0x12d2,0x12d8,0xb64,0x12de,1,1,0x12e4,0x12ea,0xb7a,0x12f0,0xb90, -0xb9a,0x600,0xba4,0x12f6,0x12fc,0xbae,0x1302,0x1308,0x130e,0x1314,0xbc4,1,0x131a,0x1320,0x1326,0xbce, -0xbe4,0xbf6,1,0x608,0x132c,0x1332,0x1338,0xc00,0x133e,1,0x1344,0x134a,0x1350,0xc16,0xc2c,0x1357, -0x135d,0x1362,0x1368,0x136e,0x1374,0x137a,0x1380,0x1386,0x138c,0x1392,0x1398,1,1,0xc42,0xc50,0x139e, -0x13a4,0x13aa,0x13b0,0x13b7,0x13bd,0x13c2,0x13c8,0x13ce,0x13d4,0x13da,0x13e0,0x13e6,0x13ec,0x13f3,0x13f9,0x13fe, -0x1404,1,1,0x140a,0x1410,0x1416,0x141c,0x1422,0x1428,0x142f,0x1435,0x143a,1,1,1,0x1441, -0x1447,0x144d,0x1453,1,0x1458,0x145e,0x1465,0x146b,0x1470,0x1476,1,1,1,0x147c,0x1482,0x1489, -0x148f,0x1494,0x149a,1,1,1,0xc5e,0xc6c,0x14a0,0x14a6,0x14ac,0x14b2,1,1,0x14b8,0x14be, -0x14c5,0x14cb,0x14d0,0x14d6,0xc7a,0xc84,0x14dc,0x14e2,0x14e9,0x14ef,0xc8e,0xc98,0x14f5,0x14fb,0x1500,0x1506, -1,1,0xca2,0xcac,0xcb6,0xcc0,0x150c,0x1512,0x1518,0x151e,0x1524,0x152a,0x1531,0x1537,0x153c,0x1542, -0x1548,0x154e,0x1554,0x155a,0x1560,0x1566,0x156c,0x1572,0x1578,0x60c,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,0xcca,0xce4,1,1,1,1, -1,1,1,1,1,1,1,1,1,0xcfe,0xd18,1,1,1,1,1, -1,0x610,1,1,1,1,1,1,1,1,1,1,1,1,1,0x157e, -0x1584,0x158a,0x1590,0x1596,0x159c,0x15a2,0x15a8,0x15b0,0x15ba,0x15c4,0x15ce,0x15d8,0x15e2,0x15ec,0x15f6,1, -0x1600,0x160a,0x1614,0x161e,0x1627,0x162d,1,1,0x1632,0x1638,0x163e,0x1644,0xd32,0xd3c,0x164d,0x1657, -0x165f,0x1665,0x166b,1,1,1,0x1670,0x1676,1,1,0x167c,0x1682,0x168a,0x1694,0x169d,0x16a3, -0x16a9,0x16af,0x16b4,0x16ba,0x16c0,0x16c6,0x16cc,0x16d2,0x16d8,0x16de,0x16e4,0x16ea,0x16f0,0x16f6,0x16fc,0x1702, -0x1708,0x170e,0x1714,0x171a,0x1720,0x1726,0x172c,0x1732,0x1738,0x173e,0x1744,0x174a,0x1750,0x1756,1,1, -0x175c,0x1762,1,1,1,1,1,1,0xd46,0xd50,0xd5a,0xd64,0x176a,0x1774,0x177e,0x1788, -0xd6e,0xd78,0x1792,0x179c,0x17a4,0x17aa,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0x128a,0x1290,0xae4,0x1296,0xafa, +0xb04,0x5f4,0xb0e,0x129c,0x12a2,0xb18,0x12a8,0x12ae,0x12b4,0x12ba,0xb2e,1,0x12c0,0x12c6,0x12cc,0xb38, +0xb4e,0xb60,1,0x5fc,0x12d2,0x12d8,0x12de,0xb6a,0x12e4,1,1,0x12ea,0x12f0,0xb80,0x12f6,0xb96, +0xba0,0x600,0xbaa,0x12fc,0x1302,0xbb4,0x1308,0x130e,0x1314,0x131a,0xbca,1,0x1320,0x1326,0x132c,0xbd4, +0xbea,0xbfc,1,0x608,0x1332,0x1338,0x133e,0xc06,0x1344,1,0x134a,0x1350,0x1356,0xc1c,0xc32,0x135d, +0x1363,0x1368,0x136e,0x1374,0x137a,0x1380,0x1386,0x138c,0x1392,0x1398,0x139e,1,1,0xc48,0xc56,0x13a4, +0x13aa,0x13b0,0x13b6,0x13bd,0x13c3,0x13c8,0x13ce,0x13d4,0x13da,0x13e0,0x13e6,0x13ec,0x13f2,0x13f9,0x13ff,0x1404, +0x140a,1,1,0x1410,0x1416,0x141c,0x1422,0x1428,0x142e,0x1435,0x143b,0x1440,1,1,1,0x1447, +0x144d,0x1453,0x1459,1,0x145e,0x1464,0x146b,0x1471,0x1476,0x147c,1,1,1,0x1482,0x1488,0x148f, +0x1495,0x149a,0x14a0,1,1,1,0xc64,0xc72,0x14a6,0x14ac,0x14b2,0x14b8,1,1,0x14be,0x14c4, +0x14cb,0x14d1,0x14d6,0x14dc,0xc80,0xc8a,0x14e2,0x14e8,0x14ef,0x14f5,0xc94,0xc9e,0x14fb,0x1501,0x1506,0x150c, +1,1,0xca8,0xcb2,0xcbc,0xcc6,0x1512,0x1518,0x151e,0x1524,0x152a,0x1530,0x1537,0x153d,0x1542,0x1548, +0x154e,0x1554,0x155a,0x1560,0x1566,0x156c,0x1572,0x1578,0x157e,0x60c,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,0xcd0,0xcea,1,1,1,1, +1,1,1,1,1,1,1,1,1,0xd04,0xd1e,1,1,1,1,1, +1,0x610,1,1,1,1,1,1,1,1,1,1,1,1,1,0x1584, +0x158a,0x1590,0x1596,0x159c,0x15a2,0x15a8,0x15ae,0x15b6,0x15c0,0x15ca,0x15d4,0x15de,0x15e8,0x15f2,0x15fc,1, +0x1606,0x1610,0x161a,0x1624,0x162d,0x1633,1,1,0x1638,0x163e,0x1644,0x164a,0xd38,0xd42,0x1653,0x165d, +0x1665,0x166b,0x1671,1,1,1,0x1676,0x167c,1,1,0x1682,0x1688,0x1690,0x169a,0x16a3,0x16a9, +0x16af,0x16b5,0x16ba,0x16c0,0x16c6,0x16cc,0x16d2,0x16d8,0x16de,0x16e4,0x16ea,0x16f0,0x16f6,0x16fc,0x1702,0x1708, +0x170e,0x1714,0x171a,0x1720,0x1726,0x172c,0x1732,0x1738,0x173e,0x1744,0x174a,0x1750,0x1756,0x175c,1,1, +0x1762,0x1768,1,1,1,1,1,1,0xd4c,0xd56,0xd60,0xd6a,0x1770,0x177a,0x1784,0x178e, +0xd74,0xd7e,0x1798,0x17a2,0x17aa,0x17b0,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,1,1,1,1,1,1,1,1,1,1,1,1, @@ -175,34 +178,34 @@ static const uint16_t norm2_nfc_data_trieData[7824]={ 0xfdcc,0xffcc,0xffcc,0xfdcc,0xffcc,0xfdcc,0xffcc,0xfdcc,0xfdcc,0xffd0,0xffb8,0xffb8,0xffb8,0xffb8,0xffd0,0xfdb0, 0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xff94,0xff94,0xfdb8,0xfdb8,0xfdb8,0xfdb8,0xfd94,0xfd94,0xffb8,0xffb8,0xffb8, 0xffb8,0xfdb8,0xfdb8,0xffb8,0xfdb8,0xfdb8,0xffb8,0xffb8,0xfe02,0xfe02,0xfe02,0xfe02,0xfc02,0xffb8,0xffb8,0xffb8, -0xffb8,0xffcc,0xffcc,0xffcc,0x3c26,0x3c2c,0xfdcc,0x3c32,0x3c38,0xfde0,0xffcc,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc, +0xffb8,0xffcc,0xffcc,0xffcc,0x3c36,0x3c3c,0xfdcc,0x3c42,0x3c48,0xfde0,0xffcc,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc, 0xffcc,0xffb8,0xffb8,1,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,0xffd0,0xffb8,0xffb8,0xffcc, 0xffd2,0xffd4,0xffd4,0xffd2,0xffd4,0xffd4,0xffd2,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,0x29d1,1,1,1,1,1,1,1, -1,1,0x29d5,1,1,1,1,1,0x17b1,0x17b7,0x29d9,0x17bd,0x17c3,0x17c9,1,0x17cf, -1,0x17d5,0x17db,0x17e3,0x618,1,1,1,0x634,1,0x644,1,0x658,1,1,1, -1,1,0x674,1,0x684,1,1,1,0x688,1,1,1,0x6a0,0x17eb,0x17f1,0xd82, -0x17f7,0xd8c,0x17fd,0x1805,0x6b4,1,1,1,0x6d4,1,0x6e4,1,0x6fc,1,1,1, -1,1,0x71c,1,0x72c,1,1,1,0x734,1,1,1,0x754,0xd96,0xda8,0x180d, -0x1813,0xdba,1,1,1,0x76c,0x1819,0x181f,1,1,1,1,1,1,1,1, +0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,0x29e1,1,1,1,1,1,1,1, +1,1,0x29e5,1,1,1,1,1,0x17b7,0x17bd,0x29e9,0x17c3,0x17c9,0x17cf,1,0x17d5, +1,0x17db,0x17e1,0x17e9,0x618,1,1,1,0x634,1,0x644,1,0x658,1,1,1, +1,1,0x674,1,0x684,1,1,1,0x688,1,1,1,0x6a0,0x17f1,0x17f7,0xd88, +0x17fd,0xd92,0x1803,0x180b,0x6b4,1,1,1,0x6d4,1,0x6e4,1,0x6fc,1,1,1, +1,1,0x71c,1,0x72c,1,1,1,0x734,1,1,1,0x754,0xd9c,0xdae,0x1813, +0x1819,0xdc0,1,1,1,0x76c,0x181f,0x1825,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,0x1825,0x182b,1,0x1831,1,1,0x774,0x1837,1,1,1,1,0x183d, -0x1843,0x1849,1,0x778,1,1,0x780,1,0x784,0x790,0x798,0x79c,0x184f,0x7ac,1,1, +1,1,1,0x182b,0x1831,1,0x1837,1,1,0x774,0x183d,1,1,1,1,0x1843, +0x1849,0x184f,1,0x778,1,1,0x780,1,0x784,0x790,0x798,0x79c,0x1855,0x7ac,1,1, 1,0x7b0,1,1,1,1,0x7b4,1,1,1,0x7c4,1,1,1,0x7c8,1, -0x7cc,1,1,0x7d0,1,1,0x7d8,1,0x7dc,0x7e8,0x7f0,0x7f4,0x1855,0x804,1,1, +0x7cc,1,1,0x7d0,1,1,0x7d8,1,0x7dc,0x7e8,0x7f0,0x7f4,0x185b,0x804,1,1, 1,0x808,1,1,1,0x80c,1,1,1,0x81c,1,1,1,0x820,1,0x824, -1,1,0x185b,0x1861,1,0x1867,1,1,0x828,0x186d,1,1,1,1,0x1873,0x1879, -0x187f,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0x82c,0x830,0x1885,0x188b,1,1,1,1,1,1, +1,1,0x1861,0x1867,1,0x186d,1,1,0x828,0x1873,1,1,1,1,0x1879,0x187f, +0x1885,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0x82c,0x830,0x188b,0x1891,1,1,1,1,1,1, 1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,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,1,1,1,1,1,1,1,1,1,1,0x1891, -0x1897,1,1,1,1,1,1,1,1,1,1,1,1,1,0x189d,0x18a3, -0x18a9,0x18af,1,1,0x18b5,0x18bb,0x834,0x838,0x18c1,0x18c7,0x18cd,0x18d3,0x18d9,0x18df,1,1, -0x18e5,0x18eb,0x18f1,0x18f7,0x18fd,0x1903,0x83c,0x840,0x1909,0x190f,0x1915,0x191b,0x1921,0x1927,0x192d,0x1933, -0x1939,0x193f,0x1945,0x194b,1,1,0x1951,0x1957,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x1897, +0x189d,1,1,1,1,1,1,1,1,1,1,1,1,1,0x18a3,0x18a9, +0x18af,0x18b5,1,1,0x18bb,0x18c1,0x834,0x838,0x18c7,0x18cd,0x18d3,0x18d9,0x18df,0x18e5,1,1, +0x18eb,0x18f1,0x18f7,0x18fd,0x1903,0x1909,0x83c,0x840,0x190f,0x1915,0x191b,0x1921,0x1927,0x192d,0x1933,0x1939, +0x193f,0x1945,0x194b,0x1951,1,1,0x1957,0x195d,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc, 0xffcc,0xffcc,0xffbc,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8, 0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffbc,0xffc8,0xffcc,0xfe14,0xfe16,0xfe18,0xfe1a,0xfe1c,0xfe1e,0xfe20,0xfe22, @@ -211,14 +214,14 @@ static const uint16_t norm2_nfc_data_trieData[7824]={ 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,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xfe3c,0xfe3e,0xfe40,1,1,1,1,1,1,1,0x195c,0x1962,0x1969,0x196f,0x1975,0x844, +0xfe3c,0xfe3e,0xfe40,1,1,1,1,1,1,1,0x1962,0x1968,0x196f,0x1975,0x197b,0x844, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,0x850,1,0x854,0xfe36,0xfe38,0xfe3a,0xfe3c,0xfe3e, 0xfe40,0xfe42,0xfe44,0xfdcc,0xfdcc,0xfdb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffb8, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0xfe46,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0x197b,0x858,0x1981,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,0x85c,0x1987,1,0x860,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,0xffcc, +0x1981,0x858,0x1987,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,0x85c,0x198d,1,0x860,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,0xffcc, 0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,1,1,0xffcc,0xffcc,1,0xffb8,0xffcc,0xffcc,0xffb8,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0xfe48,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -241,24 +244,24 @@ static const uint16_t norm2_nfc_data_trieData[7824]={ 0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,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,0x864,0x198d,1,1,1,1,1,1,0x868,0x1993,1,0x86c, -0x1999,1,1,1,1,1,1,1,0xfc0e,1,1,1,1,1,1,1, +1,1,1,1,0x864,0x1993,1,1,1,1,1,1,0x868,0x1999,1,0x86c, +0x199f,1,1,1,1,1,1,1,0xfc0e,1,1,1,1,1,1,1, 1,1,1,1,1,1,0xfe12,1,1,1,0xffcc,0xffb8,0xffcc,0xffcc,1,1, -1,0x29dc,0x29e2,0x29e8,0x29ee,0x29f4,0x29fa,0x2a00,0x2a06,1,1,1,1,1,1,1, +1,0x29ec,0x29f2,0x29f8,0x29fe,0x2a04,0x2a0a,0x2a10,0x2a16,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,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,0xfe0e,1,0xfc00,1,1,1,1,1,1,1,0x870, -1,1,1,0x199f,0x19a5,0xfe12,1,1,1,1,1,1,1,1,1,0xfc00, -1,1,1,1,0x2a0c,0x2a12,1,0x2a18,1,1,1,1,1,1,1,1, +1,1,1,0x19a5,0x19ab,0xfe12,1,1,1,1,1,1,1,1,1,0xfc00, +1,1,1,1,0x2a1c,0x2a22,1,0x2a28,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,0xffcc,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,1,1,1,1,1,0x2a1e,1,1,0x2a24,1,1, +1,1,1,1,1,1,1,1,1,1,0x2a2e,1,1,0x2a34,1,1, 1,1,1,0xfe0e,1,1,1,1,1,1,1,1,1,1,1,1, -1,0xfe12,1,1,1,1,1,1,1,1,1,1,1,0x2a2a,0x2a30,0x2a36, -1,1,0x2a3c,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,0xfe12,1,1,1,1,1,1,1,1,1,1,1,0x2a3a,0x2a40,0x2a46, +1,1,0x2a4c,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,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe0e, @@ -266,33 +269,33 @@ static const uint16_t norm2_nfc_data_trieData[7824]={ 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,1,1, -0x878,0x19ab,1,1,0x19b1,0x19b7,0xfe12,1,1,1,1,1,1,1,1,0xfc00, -0xfc00,1,1,1,1,0x2a42,0x2a48,1,1,1,1,1,1,1,1,1, +0x878,0x19b1,1,1,0x19b7,0x19bd,0xfe12,1,1,1,1,1,1,1,1,0xfc00, +0xfc00,1,1,1,1,0x2a52,0x2a58,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,0x884,1,0x19bd,1,1,1,1, +1,1,1,1,1,1,1,1,1,0x884,1,0x19c3,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,0xfc00,1,1,1,1,1,1,0x888,0x890,1,1, -0x19c3,0x19c9,0x19cf,0xfe12,1,1,1,1,1,1,1,1,1,0xfc00,1,1, +0x19c9,0x19cf,0x19d5,0xfe12,1,1,1,1,1,1,1,1,1,0xfc00,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,0x894,1,0x19d5,1,1,1,1,0xfe12,1,1, +1,1,1,1,1,1,0x894,1,0x19db,1,1,1,1,0xfe12,1,1, 1,1,1,1,1,0xfea8,0xfcb6,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,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xfe0e,1,1,0x898,0x19db,1,0xfc00,1,1,1,0x89c,0x19e1,0x19e7, -1,0xdc4,0x19ef,1,0xfe12,1,1,1,1,1,1,1,0xfc00,0xfc00,1,1, +1,1,1,0xfe0e,1,1,0x898,0x19e1,1,0xfc00,1,1,1,0x89c,0x19e7,0x19ed, +1,0xdca,0x19f5,1,0xfe12,1,1,1,1,1,1,1,0xfc00,0xfc00,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,1,1,1,1, 1,1,1,1,1,1,1,1,1,0xfe12,0xfe12,1,0xfc00,1,1,1, -1,1,1,0x8a8,0x8b0,1,1,0x19f7,0x19fd,0x1a03,0xfe12,1,1,1,1,1, +1,1,1,0x8a8,0x8b0,1,1,0x19fd,0x1a03,0x1a09,0xfe12,1,1,1,1,1, 1,1,1,1,0xfc00,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,0xfc12,1,1, -1,1,0xfc00,1,1,1,1,1,1,1,1,1,0x8b4,0x1a09,1,0xdce, -0x1a11,0x1a19,0xfc00,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,0xfc00,1,1,1,1,1,1,1,1,1,0x8b4,0x1a0f,1,0xdd4, +0x1a17,0x1a1f,0xfc00,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,1,1,1,1,1,1,1,1,1,1,0xfece,0xfece,0xfe12,1,1, @@ -306,19 +309,19 @@ static const uint16_t norm2_nfc_data_trieData[7824]={ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,0xffb8,0xffb8,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,0xffb8,1,0xffb8,1,0xffb0,1,1,1,1,1,1,0x2a4f,1,1, -1,1,1,1,1,1,1,0x2a55,1,1,1,1,0x2a5b,1,1,1, -1,0x2a61,1,1,1,1,0x2a67,1,1,1,1,1,1,1,1,1, -1,1,1,0x2a6d,1,1,1,1,1,1,1,0xff02,0xff04,0x3c40,0xff08,0x3c48, -0x2a72,1,0x2a78,1,0xff04,0xff04,0xff04,0xff04,1,1,0xff04,0x3c50,0xffcc,0xffcc,0xfe12,1, -0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,0x2a7f,1,1, -1,1,1,1,1,1,1,0x2a85,1,1,1,1,0x2a8b,1,1,1, -1,0x2a91,1,1,1,1,0x2a97,1,1,1,1,1,1,1,1,1, -1,1,1,0x2a9d,1,1,1,1,1,1,0xffb8,1,1,1,1,1, +1,1,0xffb8,1,0xffb8,1,0xffb0,1,1,1,1,1,1,0x2a5f,1,1, +1,1,1,1,1,1,1,0x2a65,1,1,1,1,0x2a6b,1,1,1, +1,0x2a71,1,1,1,1,0x2a77,1,1,1,1,1,1,1,1,1, +1,1,1,0x2a7d,1,1,1,1,1,1,1,0xff02,0xff04,0x3c50,0xff08,0x3c58, +0x2a82,1,0x2a88,1,0xff04,0xff04,0xff04,0xff04,1,1,0xff04,0x3c60,0xffcc,0xffcc,0xfe12,1, +0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,0x2a8f,1,1, +1,1,1,1,1,1,1,0x2a95,1,1,1,1,0x2a9b,1,1,1, +1,0x2aa1,1,1,1,1,0x2aa7,1,1,1,1,1,1,1,1,1, +1,1,1,0x2aad,1,1,1,1,1,1,0xffb8,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,1,1,1,1,1,1,1, -1,1,1,1,0x8c0,0x1a1f,1,1,1,1,1,1,1,0xfc00,1,1, +1,1,1,1,0x8c0,0x1a25,1,1,1,1,1,1,1,0xfc00,1,1, 1,1,1,1,1,1,0xfe0e,1,0xfe12,0xfe12,1,1,1,1,1,1, 1,1,1,1,1,1,1,0xffb8,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -359,272 +362,277 @@ static const uint16_t norm2_nfc_data_trieData[7824]={ 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,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc, -0xffcc,0xffb8,1,1,1,1,1,0x8c4,0x1a25,0x8c8,0x1a2b,0x8cc,0x1a31,0x8d0,0x1a37,0x8d4, -0x1a3d,1,1,0x8d8,0x1a43,1,1,1,1,1,1,1,1,1,1,1, +0xffcc,0xffb8,1,0xffb8,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,0xfe0e,0xfc00,1,1,1,1,0x8dc,0x1a49,0x8e0,0x1a4f, -0x8e4,0x8e8,0x1a55,0x1a5b,0x8ec,0x1a61,0xfe12,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,0xffcc,0xffb8,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,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,0x8c4,0x1a2b,0x8c8,0x1a31,0x8cc,0x1a37,0x8d0,0x1a3d,0x8d4,0x1a43,1,1,0x8d8, +0x1a49,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,0xfe0e,0xfc00,1,1,1,1,0x8dc,0x1a4f,0x8e0,0x1a55,0x8e4,0x8e8,0x1a5b,0x1a61, +0x8ec,0x1a67,0xfe12,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,0xffcc,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,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,0xfe12,0xfe12,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xfe12,0xfe12,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,0xfe0e,1,1,1,1,1,1,1, -1,1,1,1,0xfe12,0xfe12,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,1,0xfe02,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8, -0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,1,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,1, -1,1,1,0xffb8,1,1,1,1,1,1,0xffcc,1,1,1,0xffcc,0xffcc, -1,1,1,1,1,1,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffb8,0xffcc,0xffcc,0xffd4,0xffac,0xffb8,0xff94,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +1,1,1,1,0xfe0e,1,1,1,1,1,1,1,1,1,1,1, +0xfe12,0xfe12,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,0xffcc,0xffcc,0xffcc,1,0xfe02,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc,0xffb8,0xffb8, +0xffb8,0xffb8,0xffcc,1,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,1,1,1,1,0xffb8, +1,1,1,1,1,1,0xffcc,1,1,1,0xffcc,0xffcc,1,1,1,1, +1,1,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffd4, +0xffac,0xffb8,0xff94,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, 0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffd0,0xffc8,0xffc8,0xffb8, -1,0xffcc,0xffd2,0xffb8,0xffcc,0xffb8,0x1a66,0x1a6c,0x1a72,0x1a78,0x1a7f,0x1a85,0x1a8b,0x1a91,0x1a99,0x1aa3, -0x1aaa,0x1ab0,0x1ab6,0x1abc,0x1ac2,0x1ac8,0x1acf,0x1ad5,0x1ada,0x1ae0,0x1ae8,0x1af2,0x1afc,0x1b06,0x1b0e,0x1b14, -0x1b1a,0x1b20,0x1b29,0x1b33,0x1b3b,0x1b41,0x1b46,0x1b4c,0x1b52,0x1b58,0x1b5e,0x1b64,0x1b6a,0x1b70,0x1b77,0x1b7d, -0x1b82,0x1b88,0x1b8e,0x1b94,0x1b9c,0x1ba6,0x1bae,0x1bb4,0x1bba,0x1bc0,0x1bc6,0x1bcc,0xdd8,0xde2,0x1bd4,0x1bde, -0x1be6,0x1bec,0x1bf2,0x1bf8,0x1bfe,0x1c04,0x1c0a,0x1c10,0x1c17,0x1c1d,0x1c22,0x1c28,0x1c2e,0x1c34,0x1c3a,0x1c40, -0x1c46,0x1c4c,0x1c54,0x1c5e,0x1c68,0x1c72,0x1c7c,0x1c86,0x1c90,0x1c9a,0x1ca3,0x1ca9,0x1caf,0x1cb5,0x1cba,0x1cc0, -0xdec,0xdf6,0x1cc8,0x1cd2,0x1cda,0x1ce0,0x1ce6,0x1cec,0xe00,0xe0a,0x1cf4,0x1cfe,0x1d08,0x1d12,0x1d1c,0x1d26, -0x1d2e,0x1d34,0x1d3a,0x1d40,0x1d46,0x1d4c,0x1d52,0x1d58,0x1d5e,0x1d64,0x1d6a,0x1d70,0x1d76,0x1d7c,0x1d84,0x1d8e, -0x1d98,0x1da2,0x1daa,0x1db0,0x1db7,0x1dbd,0x1dc2,0x1dc8,0x1dce,0x1dd4,0x1dda,0x1de0,0x1de6,0x1dec,0x1df3,0x1df9, -0x1dff,0x1e05,0x1e0b,0x1e11,0x1e16,0x1e1c,0x1e22,0x1e28,0x1e2f,0x1e35,0x1e3b,0x1e41,0x1e46,0x1e4c,0x1e52,0x1e58, -1,0x1e5f,1,1,1,1,0xe14,0xe22,0x1e64,0x1e6a,0x1e72,0x1e7c,0x1e86,0x1e90,0x1e9a,0x1ea4, -0x1eae,0x1eb8,0x1ec2,0x1ecc,0x1ed6,0x1ee0,0x1eea,0x1ef4,0x1efe,0x1f08,0x1f12,0x1f1c,0x1f26,0x1f30,0xe30,0xe3a, -0x1f38,0x1f3e,0x1f44,0x1f4a,0x1f52,0x1f5c,0x1f66,0x1f70,0x1f7a,0x1f84,0x1f8e,0x1f98,0x1fa2,0x1fac,0x1fb4,0x1fba, -0x1fc0,0x1fc6,0xe44,0xe4e,0x1fcc,0x1fd2,0x1fda,0x1fe4,0x1fee,0x1ff8,0x2002,0x200c,0x2016,0x2020,0x202a,0x2034, -0x203e,0x2048,0x2052,0x205c,0x2066,0x2070,0x207a,0x2084,0x208e,0x2098,0x20a0,0x20a6,0x20ac,0x20b2,0x20ba,0x20c4, -0x20ce,0x20d8,0x20e2,0x20ec,0x20f6,0x2100,0x210a,0x2114,0x211c,0x2122,0x2129,0x212f,0x2134,0x213a,0x2140,0x2146, -1,1,1,1,1,1,0xe58,0xe6e,0xe86,0xe94,0xea2,0xeb0,0xebe,0xecc,0xed8,0xeee, -0xf06,0xf14,0xf22,0xf30,0xf3e,0xf4c,0xf58,0xf66,0x214f,0x2159,0x2163,0x216d,1,1,0xf74,0xf82, -0x2177,0x2181,0x218b,0x2195,1,1,0xf90,0xfa6,0xfbe,0xfcc,0xfda,0xfe8,0xff6,0x1004,0x1010,0x1026, -0x103e,0x104c,0x105a,0x1068,0x1076,0x1084,0x1090,0x10a2,0x219f,0x21a9,0x21b3,0x21bd,0x21c7,0x21d1,0x10b4,0x10c6, -0x21db,0x21e5,0x21ef,0x21f9,0x2203,0x220d,0x10d8,0x10e6,0x2217,0x2221,0x222b,0x2235,1,1,0x10f4,0x1102, -0x223f,0x2249,0x2253,0x225d,1,1,0x1110,0x1122,0x2267,0x2271,0x227b,0x2285,0x228f,0x2299,1,0x1134, -1,0x22a3,1,0x22ad,1,0x22b7,0x1146,0x115c,0x1174,0x1182,0x1190,0x119e,0x11ac,0x11ba,0x11c6,0x11dc, -0x11f4,0x1202,0x1210,0x121e,0x122c,0x123a,0x1246,0x3b8e,0x22bf,0x3b96,0x1250,0x3b9e,0x22c5,0x3ba6,0x22cb,0x3bae, -0x22d1,0x3bb6,0x125a,0x3bbe,1,1,0x22d8,0x22e2,0x22f1,0x2301,0x2311,0x2321,0x2331,0x2341,0x234c,0x2356, -0x2365,0x2375,0x2385,0x2395,0x23a5,0x23b5,0x23c0,0x23ca,0x23d9,0x23e9,0x23f9,0x2409,0x2419,0x2429,0x2434,0x243e, -0x244d,0x245d,0x246d,0x247d,0x248d,0x249d,0x24a8,0x24b2,0x24c1,0x24d1,0x24e1,0x24f1,0x2501,0x2511,0x251c,0x2526, -0x2535,0x2545,0x2555,0x2565,0x2575,0x2585,0x258f,0x2595,0x259d,0x25a4,0x25ad,1,0x1264,0x25b7,0x25bf,0x25c5, -0x25cb,0x3bc6,0x25d0,1,0x2aa2,0x8f0,1,0x25d7,0x25df,0x25e6,0x25ef,1,0x126e,0x25f9,0x2601,0x3bce, -0x2607,0x3bd6,0x260c,0x2613,0x2619,0x261f,0x2625,0x262b,0x2633,0x3be0,1,1,0x263b,0x2643,0x264b,0x2651, -0x2657,0x3bea,1,0x265d,0x2663,0x2669,0x266f,0x2675,0x267d,0x3bf4,0x2685,0x268b,0x2691,0x2699,0x26a1,0x26a7, -0x26ad,0x3bfe,0x26b3,0x26b9,0x3c06,0x2aa7,1,1,0x26c1,0x26c8,0x26d1,1,0x1278,0x26db,0x26e3,0x3c0e, -0x26e9,0x3c16,0x26ee,0x2aab,0x8fc,1,0xfa09,0xfa09,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,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0xffcc,0xffcc,0xfe02,0xfe02,0xffcc,0xffcc,0xffcc,0xffcc,0xfe02,0xfe02, -0xfe02,0xffcc,0xffcc,1,1,1,1,0xffcc,1,1,1,0xfe02,0xfe02,0xffcc,0xffb8,0xffcc, -0xfe02,0xfe02,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,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,0x2aae,1,1, -1,0x2ab2,0x3c1e,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0x908,1,0x90c,1,0x910,1,1,1,1, -1,0x26f5,0x26fb,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0x2701,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0x2707,0x270d,0x2713,0x914,1,0x918,1,0x91c,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,0x920,0x2719,1,1,1,0x924, -0x271f,1,0x928,0x2725,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0x92c,0x272b,0x930,0x2731,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0x934,1,1,1,0x2737,1,0x938,0x273d,0x93c,1,0x2743,0x940,0x2749, -1,1,1,0x944,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0x274f,0x948,0x2755,1,0x94c,0x950,1,1,1,1, -1,1,1,0x275b,0x2761,0x2767,0x276d,0x2773,0x954,0x958,0x2779,0x277f,0x95c,0x960,0x2785,0x278b, -0x964,0x968,0x96c,0x970,1,1,0x2791,0x2797,0x974,0x978,0x279d,0x27a3,0x97c,0x980,0x27a9,0x27af, -1,1,1,1,1,1,1,0x984,0x988,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0x98c,1,1,1,1,1,0x990,0x994, -1,0x998,0x27b5,0x27bb,0x27c1,0x27c7,1,1,0x99c,0x9a0,0x9a4,0x9a8,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,0x27cd,0x27d3,0x27d9,0x27df, -1,1,1,1,1,1,0x27e5,0x27eb,0x27f1,0x27f7,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,0x2ab7,0x2abb,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,0x2abf,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, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,0xfe12,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,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffd0,0xffc8,0xffc8,0xffb8,1,0xffcc,0xffd2,0xffb8, +0xffcc,0xffb8,0x1a6c,0x1a72,0x1a78,0x1a7e,0x1a85,0x1a8b,0x1a91,0x1a97,0x1a9f,0x1aa9,0x1ab0,0x1ab6,0x1abc,0x1ac2, +0x1ac8,0x1ace,0x1ad5,0x1adb,0x1ae0,0x1ae6,0x1aee,0x1af8,0x1b02,0x1b0c,0x1b14,0x1b1a,0x1b20,0x1b26,0x1b2f,0x1b39, +0x1b41,0x1b47,0x1b4c,0x1b52,0x1b58,0x1b5e,0x1b64,0x1b6a,0x1b70,0x1b76,0x1b7d,0x1b83,0x1b88,0x1b8e,0x1b94,0x1b9a, +0x1ba2,0x1bac,0x1bb4,0x1bba,0x1bc0,0x1bc6,0x1bcc,0x1bd2,0xdde,0xde8,0x1bda,0x1be4,0x1bec,0x1bf2,0x1bf8,0x1bfe, +0x1c04,0x1c0a,0x1c10,0x1c16,0x1c1d,0x1c23,0x1c28,0x1c2e,0x1c34,0x1c3a,0x1c40,0x1c46,0x1c4c,0x1c52,0x1c5a,0x1c64, +0x1c6e,0x1c78,0x1c82,0x1c8c,0x1c96,0x1ca0,0x1ca9,0x1caf,0x1cb5,0x1cbb,0x1cc0,0x1cc6,0xdf2,0xdfc,0x1cce,0x1cd8, +0x1ce0,0x1ce6,0x1cec,0x1cf2,0xe06,0xe10,0x1cfa,0x1d04,0x1d0e,0x1d18,0x1d22,0x1d2c,0x1d34,0x1d3a,0x1d40,0x1d46, +0x1d4c,0x1d52,0x1d58,0x1d5e,0x1d64,0x1d6a,0x1d70,0x1d76,0x1d7c,0x1d82,0x1d8a,0x1d94,0x1d9e,0x1da8,0x1db0,0x1db6, +0x1dbd,0x1dc3,0x1dc8,0x1dce,0x1dd4,0x1dda,0x1de0,0x1de6,0x1dec,0x1df2,0x1df9,0x1dff,0x1e05,0x1e0b,0x1e11,0x1e17, +0x1e1c,0x1e22,0x1e28,0x1e2e,0x1e35,0x1e3b,0x1e41,0x1e47,0x1e4c,0x1e52,0x1e58,0x1e5e,1,0x1e65,1,1, +1,1,0xe1a,0xe28,0x1e6a,0x1e70,0x1e78,0x1e82,0x1e8c,0x1e96,0x1ea0,0x1eaa,0x1eb4,0x1ebe,0x1ec8,0x1ed2, +0x1edc,0x1ee6,0x1ef0,0x1efa,0x1f04,0x1f0e,0x1f18,0x1f22,0x1f2c,0x1f36,0xe36,0xe40,0x1f3e,0x1f44,0x1f4a,0x1f50, +0x1f58,0x1f62,0x1f6c,0x1f76,0x1f80,0x1f8a,0x1f94,0x1f9e,0x1fa8,0x1fb2,0x1fba,0x1fc0,0x1fc6,0x1fcc,0xe4a,0xe54, +0x1fd2,0x1fd8,0x1fe0,0x1fea,0x1ff4,0x1ffe,0x2008,0x2012,0x201c,0x2026,0x2030,0x203a,0x2044,0x204e,0x2058,0x2062, +0x206c,0x2076,0x2080,0x208a,0x2094,0x209e,0x20a6,0x20ac,0x20b2,0x20b8,0x20c0,0x20ca,0x20d4,0x20de,0x20e8,0x20f2, +0x20fc,0x2106,0x2110,0x211a,0x2122,0x2128,0x212f,0x2135,0x213a,0x2140,0x2146,0x214c,1,1,1,1, +1,1,0xe5e,0xe74,0xe8c,0xe9a,0xea8,0xeb6,0xec4,0xed2,0xede,0xef4,0xf0c,0xf1a,0xf28,0xf36, +0xf44,0xf52,0xf5e,0xf6c,0x2155,0x215f,0x2169,0x2173,1,1,0xf7a,0xf88,0x217d,0x2187,0x2191,0x219b, +1,1,0xf96,0xfac,0xfc4,0xfd2,0xfe0,0xfee,0xffc,0x100a,0x1016,0x102c,0x1044,0x1052,0x1060,0x106e, +0x107c,0x108a,0x1096,0x10a8,0x21a5,0x21af,0x21b9,0x21c3,0x21cd,0x21d7,0x10ba,0x10cc,0x21e1,0x21eb,0x21f5,0x21ff, +0x2209,0x2213,0x10de,0x10ec,0x221d,0x2227,0x2231,0x223b,1,1,0x10fa,0x1108,0x2245,0x224f,0x2259,0x2263, +1,1,0x1116,0x1128,0x226d,0x2277,0x2281,0x228b,0x2295,0x229f,1,0x113a,1,0x22a9,1,0x22b3, +1,0x22bd,0x114c,0x1162,0x117a,0x1188,0x1196,0x11a4,0x11b2,0x11c0,0x11cc,0x11e2,0x11fa,0x1208,0x1216,0x1224, +0x1232,0x1240,0x124c,0x3b9e,0x22c5,0x3ba6,0x1256,0x3bae,0x22cb,0x3bb6,0x22d1,0x3bbe,0x22d7,0x3bc6,0x1260,0x3bce, +1,1,0x22de,0x22e8,0x22f7,0x2307,0x2317,0x2327,0x2337,0x2347,0x2352,0x235c,0x236b,0x237b,0x238b,0x239b, +0x23ab,0x23bb,0x23c6,0x23d0,0x23df,0x23ef,0x23ff,0x240f,0x241f,0x242f,0x243a,0x2444,0x2453,0x2463,0x2473,0x2483, +0x2493,0x24a3,0x24ae,0x24b8,0x24c7,0x24d7,0x24e7,0x24f7,0x2507,0x2517,0x2522,0x252c,0x253b,0x254b,0x255b,0x256b, +0x257b,0x258b,0x2595,0x259b,0x25a3,0x25aa,0x25b3,1,0x126a,0x25bd,0x25c5,0x25cb,0x25d1,0x3bd6,0x25d6,1, +0x2ab2,0x8f0,1,0x25dd,0x25e5,0x25ec,0x25f5,1,0x1274,0x25ff,0x2607,0x3bde,0x260d,0x3be6,0x2612,0x2619, +0x261f,0x2625,0x262b,0x2631,0x2639,0x3bf0,1,1,0x2641,0x2649,0x2651,0x2657,0x265d,0x3bfa,1,0x2663, +0x2669,0x266f,0x2675,0x267b,0x2683,0x3c04,0x268b,0x2691,0x2697,0x269f,0x26a7,0x26ad,0x26b3,0x3c0e,0x26b9,0x26bf, +0x3c16,0x2ab7,1,1,0x26c7,0x26ce,0x26d7,1,0x127e,0x26e1,0x26e9,0x3c1e,0x26ef,0x3c26,0x26f4,0x2abb, +0x8fc,1,0xfa09,0xfa09,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,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,0xffcc,0xffcc,0xfe02,0xfe02,0xffcc,0xffcc,0xffcc,0xffcc,0xfe02,0xfe02,0xfe02,0xffcc,0xffcc,1, +1,1,1,0xffcc,1,1,1,0xfe02,0xfe02,0xffcc,0xffb8,0xffcc,0xfe02,0xfe02,0xffb8,0xffb8, +0xffb8,0xffb8,0xffcc,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,0x2abe,1,1,1,0x2ac2,0x3c2e,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,0x908,1,0x90c,1,0x910,1,1,1,1,1,0x26fb,0x2701,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,0x2707,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,0x270d,0x2713,0x2719,0x914,1,0x918,1,0x91c,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,0x920,0x271f,1,1,1,0x924,0x2725,1,0x928,0x272b, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0x92c,0x2731,0x930,0x2737,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x934, +1,1,1,0x273d,1,0x938,0x2743,0x93c,1,0x2749,0x940,0x274f,1,1,1,0x944, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,0x2755,0x948,0x275b,1,0x94c,0x950,1,1,1,1,1,1,1,0x2761, +0x2767,0x276d,0x2773,0x2779,0x954,0x958,0x277f,0x2785,0x95c,0x960,0x278b,0x2791,0x964,0x968,0x96c,0x970, +1,1,0x2797,0x279d,0x974,0x978,0x27a3,0x27a9,0x97c,0x980,0x27af,0x27b5,1,1,1,1, +1,1,1,0x984,0x988,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0x98c,1,1,1,1,1,0x990,0x994,1,0x998,0x27bb,0x27c1, +0x27c7,0x27cd,1,1,0x99c,0x9a0,0x9a4,0x9a8,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,0x27d3,0x27d9,0x27df,0x27e5,1,1,1,1, +1,1,0x27eb,0x27f1,0x27f7,0x27fd,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,0x2ac7, +0x2acb,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,0x2acf,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,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12,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,0xffcc,0xffcc, 0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,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,0xffb4,0xffc8,0xffd0,0xffbc,0xffc0,0xffc0,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x9ac,1, +1,1,1,0x9b0,0x2803,0x9b4,0x2809,0x9b8,0x280f,0x9bc,0x2815,0x9c0,0x281b,0x9c4,0x2821,0x9c8, +0x2827,0x9cc,0x282d,0x9d0,0x2833,0x9d4,0x2839,0x9d8,0x283f,0x9dc,0x2845,1,0x9e0,0x284b,0x9e4,0x2851, +0x9e8,0x2857,1,1,1,1,1,0x9ec,0x285d,0x2863,0x9f4,0x2869,0x286f,0x9fc,0x2875,0x287b, +0xa04,0x2881,0x2887,0xa0c,0x288d,0x2893,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,0x2899,1,1,1,1,0xfc10, +0xfc10,1,1,0xa14,0x289f,1,1,1,1,1,1,1,0xa18,1,1,1, +1,0xa1c,0x28a5,0xa20,0x28ab,0xa24,0x28b1,0xa28,0x28b7,0xa2c,0x28bd,0xa30,0x28c3,0xa34,0x28c9,0xa38, +0x28cf,0xa3c,0x28d5,0xa40,0x28db,0xa44,0x28e1,0xa48,0x28e7,1,0xa4c,0x28ed,0xa50,0x28f3,0xa54,0x28f9, +1,1,1,1,1,0xa58,0x28ff,0x2905,0xa60,0x290b,0x2911,0xa68,0x2917,0x291d,0xa70,0x2923, +0x2929,0xa78,0x292f,0x2935,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0xa80,0xa84,0xa88,0xa8c,1,0x293b,1,1,0x2941,0x2947,0x294d, +0x2953,1,1,0xa90,0x2959,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,1,0xffcc,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,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,0xffb4,0xffc8,0xffd0,0xffbc, -0xffc0,0xffc0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,0x9ac,1,1,1,1,0x9b0,0x27fd,0x9b4,0x2803,0x9b8,0x2809,0x9bc,0x280f,0x9c0, -0x2815,0x9c4,0x281b,0x9c8,0x2821,0x9cc,0x2827,0x9d0,0x282d,0x9d4,0x2833,0x9d8,0x2839,0x9dc,0x283f,1, -0x9e0,0x2845,0x9e4,0x284b,0x9e8,0x2851,1,1,1,1,1,0x9ec,0x2857,0x285d,0x9f4,0x2863, -0x2869,0x9fc,0x286f,0x2875,0xa04,0x287b,0x2881,0xa0c,0x2887,0x288d,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x2893,1, -1,1,1,0xfc10,0xfc10,1,1,0xa14,0x2899,1,1,1,1,1,1,1, -0xa18,1,1,1,1,0xa1c,0x289f,0xa20,0x28a5,0xa24,0x28ab,0xa28,0x28b1,0xa2c,0x28b7,0xa30, -0x28bd,0xa34,0x28c3,0xa38,0x28c9,0xa3c,0x28cf,0xa40,0x28d5,0xa44,0x28db,0xa48,0x28e1,1,0xa4c,0x28e7, -0xa50,0x28ed,0xa54,0x28f3,1,1,1,1,1,0xa58,0x28f9,0x28ff,0xa60,0x2905,0x290b,0xa68, -0x2911,0x2917,0xa70,0x291d,0x2923,0xa78,0x2929,0x292f,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,0xa80,0xa84,0xa88,0xa8c,1,0x2935,1, -1,0x293b,0x2941,0x2947,0x294d,1,1,0xa90,0x2953,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,1,0xffcc,1,1,1,1,0xffcc,0xffcc,0xffcc, +1,0xffcc,0xffcc,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,1,1,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,0xfe12,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,0xfe12,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,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, 0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,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,0xffcc,0xffcc,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,1,1,0xffcc,0xffcc,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0xfe12,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,1,1,1,1,1,1,1,1,1,1, -1,0xfe12,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,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,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,0xffb8,0xffb8,0xffb8,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xfe12,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,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xffcc,1,0xffcc,0xffcc,0xffb8,1,1,0xffcc,0xffcc,1,1,1,1,1,0xffcc,0xffcc, -1,0xffcc,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, -1,1,1,1,1,1,0xfe12,1,1,1,1,1,1,1,1,1, -0xadc,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283, -0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0xadc,0x1283,0x1283,0x1283, -0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283, -0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0xadc,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283, -0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283, -0x1283,0x1283,0x1283,0x1283,0xadc,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283, -0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283, -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,0x3c56,1,0x3c56,0x3c56, -0x3c56,0x3c56,0x3c56,0x3c56,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0x3c56,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0x3c56,1,1,1,1, -0x3c56,1,1,1,0x3c56,1,0x3c56,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,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0x3b87,1,0x2ac5,0x2ac9,0x2acd,0x2ad1,0x2ad5,0x2ad9,0x2add,0x2ae1,0x2ae1, -0x2ae5,0x2ae9,0x2aed,0x2af1,0x2af5,0x2af9,0x2afd,0x2b01,0x2b05,0x2b09,0x2b0d,0x2b11,0x2b15,0x2b19,0x2b1d,0x2b21, -0x2b25,0x2b29,0x2b2d,0x2b31,0x2b35,0x2b39,0x2b3d,0x2b41,0x2b45,0x2b49,0x2b4d,0x2b51,0x2b55,0x2b59,0x2b5d,0x2b61, -0x2b65,0x2b69,0x2b6d,0x2b71,0x2b75,0x2b79,0x2b7d,0x2b81,0x2b85,0x2b89,0x2b8d,0x2b91,0x2b95,0x2b99,0x2b9d,0x2ba1, -0x2ba5,0x2ba9,0x2bad,0x2bb1,0x2bb5,0x2bb9,0x2bbd,0x2bc1,0x2bc5,0x2bc9,0x2bcd,0x2bd1,0x2bd5,0x2bd9,0x2bdd,0x2be1, -0x2be5,0x2be9,0x2bed,0x2bf1,0x2bf5,0x2bf9,0x2bfd,0x2c01,0x2c05,0x2c09,0x2c0d,0x2c11,0x2c15,0x2c19,0x2c1d,0x2c21, -0x2c25,0x2c29,0x2c2d,0x2b11,0x2c31,0x2c35,0x2c39,0x2c3d,0x2c41,0x2c45,0x2c49,0x2c4d,0x2c51,0x2c55,0x2c59,0x2c5d, -0x2c61,0x2c65,0x2c69,0x2c6d,0x2c71,0x2c75,0x2c79,0x2c7d,0x2c81,0x2c85,0x2c89,0x2c8d,0x2c91,0x2c95,0x2c99,0x2c9d, -0x2ca1,0x2ca5,0x2ca9,0x2cad,0x2cb1,0x2cb5,0x2cb9,0x2cbd,0x2cc1,0x2cc5,0x2cc9,0x2ccd,0x2cd1,0x2cd5,0x2cd9,0x2cdd, -0x2ce1,0x2ce5,0x2ce9,0x2ced,0x2cf1,0x2cf5,0x2cf9,0x2cfd,0x2d01,0x2d05,0x2d09,0x2d0d,0x2d11,0x2d15,0x2d19,0x2d1d, -0x2d21,0x2d25,0x2d29,0x2d2d,0x2d31,0x2d35,0x2d39,0x2d3d,0x2c79,0x2d41,0x2d45,0x2d49,0x2d4d,0x2d51,0x2d55,0x2d59, -0x2d5d,0x2c39,0x2d61,0x2d65,0x2d69,0x2d6d,0x2d71,0x2d75,0x2d79,0x2d7d,0x2d81,0x2d85,0x2d89,0x2d8d,0x2d91,0x2d95, -0x2d99,0x2d9d,0x2da1,0x2da5,0x2da9,0x2dad,0x2b11,0x2db1,0x2db5,0x2db9,0x2dbd,0x2dc1,0x2dc5,0x2dc9,0x2dcd,0x2dd1, -0x2dd5,0x2dd9,0x2ddd,0x2de1,0x2de5,0x2de9,0x2ded,0x2df1,0x2df5,0x2df9,0x2dfd,0x2e01,0x2e05,0x2e09,0x2e0d,0x2e11, -0x2e15,0x2e19,0x2c41,0x2e1d,0x2e21,0x2e25,0x2e29,0x2e2d,0x2e31,0x2e35,0x2e39,0x2e3d,0x2e41,0x2e45,0x2e49,0x2e4d, -0x2e51,0x2e55,0x2e59,0x2e5d,0x2e61,0x2e65,0x2e69,0x2e6d,0x2e71,0x2e75,0x2e79,0x2e7d,0x2e81,0x2e85,0x2e89,0x2e8d, -0x2e91,0x2e95,0x2e99,0x2e9d,0x2ea1,0x2ea5,0x2ea9,0x2ead,0x2eb1,0x2eb5,0x2eb9,0x2ebd,0x2ec1,0x2ec5,0x2ec9,0x2ecd, -0x2ed1,0x2ed5,0x2ed9,0x2edd,0x2ee1,1,1,0x2ee5,1,0x2ee9,1,1,0x2eed,0x2ef1,0x2ef5,0x2ef9, -0x2efd,0x2f01,0x2f05,0x2f09,0x2f0d,0x2f11,1,0x2f15,1,0x2f19,1,1,0x2f1d,0x2f21,1,1, -1,0x2f25,0x2f29,0x2f2d,0x2f31,0x2f35,0x2f39,0x2f3d,0x2f41,0x2f45,0x2f49,0x2f4d,0x2f51,0x2f55,0x2f59,0x2f5d, -0x2f61,0x2f65,0x2f69,0x2f6d,0x2f71,0x2f75,0x2f79,0x2f7d,0x2f81,0x2f85,0x2f89,0x2f8d,0x2f91,0x2f95,0x2f99,0x2f9d, -0x2fa1,0x2fa5,0x2fa9,0x2fad,0x2fb1,0x2fb5,0x2fb9,0x2fbd,0x2fc1,0x2fc5,0x2fc9,0x2fcd,0x2fd1,0x2fd5,0x2d15,0x2fd9, -0x2fdd,0x2fe1,0x2fe5,0x2fe9,0x2fed,0x2fed,0x2ff1,0x2ff5,0x2ff9,0x2ffd,0x3001,0x3005,0x3009,0x300d,0x2f1d,0x3011, -0x3015,0x3019,0x301d,0x3021,0x3027,1,1,0x302b,0x302f,0x3033,0x3037,0x303b,0x303f,0x3043,0x3047,0x2f55, -0x304b,0x304f,0x3053,0x2ee5,0x3057,0x305b,0x305f,0x3063,0x3067,0x306b,0x306f,0x3073,0x3077,0x307b,0x307f,0x3083, -0x2f79,0x3087,0x2f7d,0x308b,0x308f,0x3093,0x3097,0x309b,0x2ee9,0x2b65,0x309f,0x30a3,0x30a7,0x2c7d,0x2dd9,0x30ab, -0x30af,0x2f99,0x30b3,0x2f9d,0x30b7,0x30bb,0x30bf,0x2ef1,0x30c3,0x30c7,0x30cb,0x30cf,0x30d3,0x2ef5,0x30d7,0x30db, -0x30df,0x30e3,0x30e7,0x30eb,0x2fd5,0x30ef,0x30f3,0x2d15,0x30f7,0x2fe5,0x30fb,0x30ff,0x3103,0x3107,0x310b,0x2ff9, -0x310f,0x2f19,0x3113,0x2ffd,0x2c31,0x3117,0x3001,0x311b,0x3009,0x311f,0x3123,0x3127,0x312b,0x312f,0x3011,0x2f09, -0x3133,0x3015,0x3137,0x3019,0x313b,0x2ae1,0x313f,0x3145,0x314b,0x3151,0x3155,0x3159,0x315d,0x3163,0x3169,0x316f, -0x3173,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,0x3176,0xfe34,0x317c,1,1,1,1,1,1, -1,1,1,1,0x3182,0x3188,0x3190,0x319a,0x31a2,0x31a8,0x31ae,0x31b4,0x31ba,0x31c0,0x31c6,0x31cc, -0x31d2,1,0x31d8,0x31de,0x31e4,0x31ea,0x31f0,1,0x31f6,1,0x31fc,0x3202,1,0x3208,0x320e,1, -0x3214,0x321a,0x3220,0x3226,0x322c,0x3232,0x3238,0x323e,0x3244,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,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0xffb8,1,0xffcc,1,1,1, -1,1,1,1,1,0xffcc,0xfe02,0xffb8,1,1,1,1,0xfe12,1,1,1, -1,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,0xffb8,0xffb8,0xffcc, -0xffcc,0xffcc,0xffb8,0xffcc,0xffb8,0xffb8,0xffb8,1,1,1,1,1,1,1,1,1, -0xa94,0x2959,0xa9a,0x2963,1,1,1,1,1,0xaa0,1,1,1,1,1,0x296d, -1,1,1,1,1,1,1,1,1,0xfe12,0xfc0e,1,1,1,1,1, -1,1,0xfc00,1,1,1,1,1,1,0x2977,0x2981,1,0xaa6,0xaac,0xfe12,0xfe12, -1,1,1,1,1,1,1,1,1,1,1,0xfe12,1,1,1,1, -1,1,1,1,1,0xfe0e,1,1,1,1,1,0xfe12,0xfe0e,1,1,1, -1,1,1,1,1,1,0xfe0e,0xfe12,1,1,1,1,1,1,1,1, -1,1,1,0xfe0e,0xfe0e,1,0xfc00,1,1,1,1,1,1,1,0xab2,1, -1,1,0x298b,0x2995,0xfe12,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,1,1,1,0xfe12,1,1,1,0xfe0e,1,1,1,1,1,1, -1,1,1,0xfc00,1,1,1,1,1,1,1,1,0xabe,0xfc00,0x299f,0x29a9, -0xfc00,0x29b3,1,1,0xfe12,0xfe0e,1,1,1,1,1,1,1,1,1,1, -1,1,0xad0,0xad6,0x29bd,0x29c7,1,1,1,0xfe12,0xfe0e,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0xfe12,0xfe0e,1,1,1,1, -1,1,1,1,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0xfe02,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0x324a,0x3254,0x3268,0x3280,0x3298,0x32b0,0x32c8,0xffb0,0xffb0,0xfe02, -0xfe02,0xfe02,1,1,1,0xffc4,0xffb0,0xffb0,0xffb0,1,1,1,1,1,1,1, -1,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,1, -1,1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1, -1,1,1,1,1,1,1,1,0x32d6,0x32e0,0x32f4,0x330c,0x3324,0x333c,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1, -1,1,1,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,1,1,1,1,1,1, -1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xfe0e,1,1,1,1,1,0x334b, -0x334f,0x3353,0x3357,0x335d,0x2f3d,0x3361,0x3365,0x3369,0x336d,0x2f41,0x3371,0x3375,0x3379,0x2f45,0x337f,0x3383, -0x3387,0x338b,0x3391,0x3395,0x3399,0x339d,0x33a3,0x33a7,0x33ab,0x33af,0x302f,0x33b3,0x33b9,0x33bd,0x33c1,0x33c5, -0x33c9,0x33cd,0x33d1,0x33d5,0x3043,0x2f49,0x2f4d,0x3047,0x33d9,0x33dd,0x2c49,0x33e1,0x2f51,0x33e5,0x33e9,0x33ed, -0x33f1,0x33f1,0x33f1,0x33f5,0x33fb,0x33ff,0x3403,0x3407,0x340d,0x3411,0x3415,0x3419,0x341d,0x3421,0x3425,0x3429, -0x342d,0x3431,0x3435,0x3439,0x343d,0x343d,0x304f,0x3441,0x3445,0x3449,0x344d,0x2f59,0x3451,0x3455,0x3459,0x2ead, -0x345d,0x3461,0x3465,0x3469,0x346d,0x3471,0x3475,0x3479,0x347d,0x3483,0x3487,0x348b,0x348f,0x3493,0x3497,0x349b, -0x34a1,0x34a7,0x34ab,0x34af,0x34b3,0x34b7,0x34bb,0x34bf,0x34c3,0x34c7,0x34c7,0x34cb,0x34d1,0x34d5,0x2c39,0x34d9, -0x34dd,0x34e3,0x34e7,0x34eb,0x34ef,0x34f3,0x34f7,0x2f6d,0x34fb,0x34ff,0x3503,0x3509,0x350d,0x3513,0x3517,0x351b, -0x351f,0x3523,0x3527,0x352b,0x352f,0x3533,0x3537,0x353b,0x353f,0x3545,0x3549,0x354d,0x3551,0x2b61,0x3555,0x355b, -0x355f,0x355f,0x3565,0x3569,0x3569,0x356d,0x3571,0x3577,0x357d,0x3581,0x3585,0x3589,0x358d,0x3591,0x3595,0x3599, -0x359d,0x35a1,0x2f71,0x35a5,0x35ab,0x35af,0x35b3,0x307f,0x35b3,0x35b7,0x2f79,0x35bb,0x35bf,0x35c3,0x35c7,0x2f7d, -0x2af5,0x35cb,0x35cf,0x35d3,0x35d7,0x35db,0x35df,0x35e3,0x35e9,0x35ed,0x35f1,0x35f5,0x35f9,0x35fd,0x3603,0x3607, -0x360b,0x360f,0x3613,0x3617,0x361b,0x361f,0x3623,0x2f81,0x3627,0x362b,0x3631,0x3635,0x3639,0x363d,0x2f89,0x3641, -0x3645,0x3649,0x364d,0x3651,0x3655,0x3659,0x365d,0x2b65,0x309f,0x3661,0x3665,0x3669,0x366d,0x3673,0x3677,0x367b, -0x367f,0x2f8d,0x3683,0x3689,0x368d,0x3691,0x3151,0x3695,0x3699,0x369d,0x36a1,0x36a5,0x36ab,0x36af,0x36b3,0x36b7, -0x36bd,0x36c1,0x36c5,0x36c9,0x2c7d,0x36cd,0x36d1,0x36d7,0x36dd,0x36e3,0x36e7,0x36ed,0x36f1,0x36f5,0x36f9,0x36fd, -0x2f91,0x2dd9,0x3701,0x3705,0x3709,0x370d,0x3713,0x3717,0x371b,0x371f,0x30af,0x3723,0x3727,0x372d,0x3731,0x3735, -0x373b,0x3741,0x3745,0x30b3,0x3749,0x374d,0x3751,0x3755,0x3759,0x375d,0x3761,0x3767,0x376b,0x3771,0x3775,0x377b, -0x30bb,0x377f,0x3783,0x3789,0x378d,0x3791,0x3797,0x379d,0x37a1,0x37a5,0x37a9,0x37ad,0x37ad,0x37b1,0x37b5,0x30c3, -0x37b9,0x37bd,0x37c1,0x37c5,0x37c9,0x37cf,0x37d3,0x2c45,0x37d9,0x37df,0x37e3,0x37e9,0x37ef,0x37f5,0x37f9,0x30db, -0x37fd,0x3803,0x3809,0x380f,0x3815,0x3819,0x3819,0x30df,0x3159,0x381d,0x3821,0x3825,0x3829,0x382f,0x2bad,0x30e7, -0x3833,0x3837,0x2fbd,0x383d,0x3843,0x2f05,0x3849,0x384d,0x2fcd,0x3851,0x3855,0x3859,0x385f,0x385f,0x3865,0x3869, -0x386d,0x3873,0x3877,0x387b,0x387f,0x3885,0x3889,0x388d,0x3891,0x3895,0x3899,0x389f,0x38a3,0x38a7,0x38ab,0x38af, -0x38b3,0x38b7,0x38bd,0x38c3,0x38c7,0x38cd,0x38d1,0x38d7,0x38db,0x2fe5,0x38df,0x38e5,0x38eb,0x38ef,0x38f5,0x38f9, -0x38ff,0x3903,0x3907,0x390b,0x390f,0x3913,0x3917,0x391d,0x3923,0x3929,0x3565,0x392f,0x3933,0x3937,0x393b,0x393f, -0x3943,0x3947,0x394b,0x394f,0x3953,0x3957,0x395b,0x2c8d,0x3961,0x3965,0x3969,0x396d,0x3971,0x3975,0x2ff1,0x3979, -0x397d,0x3981,0x3985,0x3989,0x398f,0x3995,0x399b,0x399f,0x39a3,0x39a7,0x39ab,0x39b1,0x39b5,0x39bb,0x39bf,0x39c3, -0x39c9,0x39cf,0x39d3,0x2b99,0x39d7,0x39db,0x39df,0x39e3,0x39e7,0x39eb,0x3103,0x39ef,0x39f3,0x39f7,0x39fb,0x39ff, -0x3a03,0x3a07,0x3a0b,0x3a0f,0x3a13,0x3a19,0x3a1d,0x3a21,0x3a25,0x3a29,0x3a2d,0x3a33,0x3a39,0x3a3d,0x3a41,0x3117, -0x311b,0x3a45,0x3a49,0x3a4f,0x3a53,0x3a57,0x3a5b,0x3a5f,0x3a65,0x3a6b,0x3a6f,0x3a73,0x3a77,0x3a7d,0x311f,0x3a81, -0x3a87,0x3a8d,0x3a91,0x3a95,0x3a99,0x3a9f,0x3aa3,0x3aa7,0x3aab,0x3aaf,0x3ab3,0x3ab7,0x3abb,0x3ac1,0x3ac5,0x3ac9, -0x3acd,0x3ad3,0x3ad7,0x3adb,0x3adf,0x3ae3,0x3ae9,0x3aef,0x3af3,0x3af7,0x3afb,0x3b01,0x3b05,0x3137,0x3137,0x3b0b, -0x3b0f,0x3b15,0x3b19,0x3b1d,0x3b21,0x3b25,0x3b29,0x3b2d,0x3b31,0x313b,0x3b37,0x3b3b,0x3b3f,0x3b43,0x3b47,0x3b4b, -0x3b51,0x3b55,0x3b5b,0x3b61,0x3b67,0x3b6b,0x3b6f,0x3b73,0x3b77,0x3b7b,0x3b7f,0x3b83,0x3b87,1,1,1 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,0xffb8,0xffb8,0xffb8,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0xfe12,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,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0xffcc,1,0xffcc,0xffcc,0xffb8,1,1,0xffcc, +0xffcc,1,1,1,1,1,0xffcc,0xffcc,1,0xffcc,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,1,1,1,1,1,1,0xfe12,1, +1,1,1,1,1,1,1,1,0xae2,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289, +0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289, +0x1289,0x1289,0x1289,0x1289,0xae2,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289, +0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289, +0xae2,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289, +0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0xae2,0x1289,0x1289,0x1289, +0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289, +0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,0x1289,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,0x3c66,1,0x3c66,0x3c66,0x3c66,0x3c66,0x3c66,0x3c66,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x3c66,0x3c66, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,0x3c66,1,1,1,1,0x3c66,1,1,1,0x3c66,1,0x3c66,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,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,0x3b97,1,0x2ad5, +0x2ad9,0x2add,0x2ae1,0x2ae5,0x2ae9,0x2aed,0x2af1,0x2af1,0x2af5,0x2af9,0x2afd,0x2b01,0x2b05,0x2b09,0x2b0d,0x2b11, +0x2b15,0x2b19,0x2b1d,0x2b21,0x2b25,0x2b29,0x2b2d,0x2b31,0x2b35,0x2b39,0x2b3d,0x2b41,0x2b45,0x2b49,0x2b4d,0x2b51, +0x2b55,0x2b59,0x2b5d,0x2b61,0x2b65,0x2b69,0x2b6d,0x2b71,0x2b75,0x2b79,0x2b7d,0x2b81,0x2b85,0x2b89,0x2b8d,0x2b91, +0x2b95,0x2b99,0x2b9d,0x2ba1,0x2ba5,0x2ba9,0x2bad,0x2bb1,0x2bb5,0x2bb9,0x2bbd,0x2bc1,0x2bc5,0x2bc9,0x2bcd,0x2bd1, +0x2bd5,0x2bd9,0x2bdd,0x2be1,0x2be5,0x2be9,0x2bed,0x2bf1,0x2bf5,0x2bf9,0x2bfd,0x2c01,0x2c05,0x2c09,0x2c0d,0x2c11, +0x2c15,0x2c19,0x2c1d,0x2c21,0x2c25,0x2c29,0x2c2d,0x2c31,0x2c35,0x2c39,0x2c3d,0x2b21,0x2c41,0x2c45,0x2c49,0x2c4d, +0x2c51,0x2c55,0x2c59,0x2c5d,0x2c61,0x2c65,0x2c69,0x2c6d,0x2c71,0x2c75,0x2c79,0x2c7d,0x2c81,0x2c85,0x2c89,0x2c8d, +0x2c91,0x2c95,0x2c99,0x2c9d,0x2ca1,0x2ca5,0x2ca9,0x2cad,0x2cb1,0x2cb5,0x2cb9,0x2cbd,0x2cc1,0x2cc5,0x2cc9,0x2ccd, +0x2cd1,0x2cd5,0x2cd9,0x2cdd,0x2ce1,0x2ce5,0x2ce9,0x2ced,0x2cf1,0x2cf5,0x2cf9,0x2cfd,0x2d01,0x2d05,0x2d09,0x2d0d, +0x2d11,0x2d15,0x2d19,0x2d1d,0x2d21,0x2d25,0x2d29,0x2d2d,0x2d31,0x2d35,0x2d39,0x2d3d,0x2d41,0x2d45,0x2d49,0x2d4d, +0x2c89,0x2d51,0x2d55,0x2d59,0x2d5d,0x2d61,0x2d65,0x2d69,0x2d6d,0x2c49,0x2d71,0x2d75,0x2d79,0x2d7d,0x2d81,0x2d85, +0x2d89,0x2d8d,0x2d91,0x2d95,0x2d99,0x2d9d,0x2da1,0x2da5,0x2da9,0x2dad,0x2db1,0x2db5,0x2db9,0x2dbd,0x2b21,0x2dc1, +0x2dc5,0x2dc9,0x2dcd,0x2dd1,0x2dd5,0x2dd9,0x2ddd,0x2de1,0x2de5,0x2de9,0x2ded,0x2df1,0x2df5,0x2df9,0x2dfd,0x2e01, +0x2e05,0x2e09,0x2e0d,0x2e11,0x2e15,0x2e19,0x2e1d,0x2e21,0x2e25,0x2e29,0x2c51,0x2e2d,0x2e31,0x2e35,0x2e39,0x2e3d, +0x2e41,0x2e45,0x2e49,0x2e4d,0x2e51,0x2e55,0x2e59,0x2e5d,0x2e61,0x2e65,0x2e69,0x2e6d,0x2e71,0x2e75,0x2e79,0x2e7d, +0x2e81,0x2e85,0x2e89,0x2e8d,0x2e91,0x2e95,0x2e99,0x2e9d,0x2ea1,0x2ea5,0x2ea9,0x2ead,0x2eb1,0x2eb5,0x2eb9,0x2ebd, +0x2ec1,0x2ec5,0x2ec9,0x2ecd,0x2ed1,0x2ed5,0x2ed9,0x2edd,0x2ee1,0x2ee5,0x2ee9,0x2eed,0x2ef1,1,1,0x2ef5, +1,0x2ef9,1,1,0x2efd,0x2f01,0x2f05,0x2f09,0x2f0d,0x2f11,0x2f15,0x2f19,0x2f1d,0x2f21,1,0x2f25, +1,0x2f29,1,1,0x2f2d,0x2f31,1,1,1,0x2f35,0x2f39,0x2f3d,0x2f41,0x2f45,0x2f49,0x2f4d, +0x2f51,0x2f55,0x2f59,0x2f5d,0x2f61,0x2f65,0x2f69,0x2f6d,0x2f71,0x2f75,0x2f79,0x2f7d,0x2f81,0x2f85,0x2f89,0x2f8d, +0x2f91,0x2f95,0x2f99,0x2f9d,0x2fa1,0x2fa5,0x2fa9,0x2fad,0x2fb1,0x2fb5,0x2fb9,0x2fbd,0x2fc1,0x2fc5,0x2fc9,0x2fcd, +0x2fd1,0x2fd5,0x2fd9,0x2fdd,0x2fe1,0x2fe5,0x2d25,0x2fe9,0x2fed,0x2ff1,0x2ff5,0x2ff9,0x2ffd,0x2ffd,0x3001,0x3005, +0x3009,0x300d,0x3011,0x3015,0x3019,0x301d,0x2f2d,0x3021,0x3025,0x3029,0x302d,0x3031,0x3037,1,1,0x303b, +0x303f,0x3043,0x3047,0x304b,0x304f,0x3053,0x3057,0x2f65,0x305b,0x305f,0x3063,0x2ef5,0x3067,0x306b,0x306f,0x3073, +0x3077,0x307b,0x307f,0x3083,0x3087,0x308b,0x308f,0x3093,0x2f89,0x3097,0x2f8d,0x309b,0x309f,0x30a3,0x30a7,0x30ab, +0x2ef9,0x2b75,0x30af,0x30b3,0x30b7,0x2c8d,0x2de9,0x30bb,0x30bf,0x2fa9,0x30c3,0x2fad,0x30c7,0x30cb,0x30cf,0x2f01, +0x30d3,0x30d7,0x30db,0x30df,0x30e3,0x2f05,0x30e7,0x30eb,0x30ef,0x30f3,0x30f7,0x30fb,0x2fe5,0x30ff,0x3103,0x2d25, +0x3107,0x2ff5,0x310b,0x310f,0x3113,0x3117,0x311b,0x3009,0x311f,0x2f29,0x3123,0x300d,0x2c41,0x3127,0x3011,0x312b, +0x3019,0x312f,0x3133,0x3137,0x313b,0x313f,0x3021,0x2f19,0x3143,0x3025,0x3147,0x3029,0x314b,0x2af1,0x314f,0x3155, +0x315b,0x3161,0x3165,0x3169,0x316d,0x3173,0x3179,0x317f,0x3183,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,0x3186, +0xfe34,0x318c,1,1,1,1,1,1,1,1,1,1,0x3192,0x3198,0x31a0,0x31aa, +0x31b2,0x31b8,0x31be,0x31c4,0x31ca,0x31d0,0x31d6,0x31dc,0x31e2,1,0x31e8,0x31ee,0x31f4,0x31fa,0x3200,1, +0x3206,1,0x320c,0x3212,1,0x3218,0x321e,1,0x3224,0x322a,0x3230,0x3236,0x323c,0x3242,0x3248,0x324e, +0x3254,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,1, +1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8, +0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,0xffb8,1,0xffcc,1,1,1,1,1,1,1,1,0xffcc,0xfe02,0xffb8, +1,1,1,1,0xfe12,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1, +1,1,1,1,1,0xffb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,0xffb8,0xffb8,0xffb8,1, +1,1,1,1,1,1,1,1,0xa94,0x295f,0xa9a,0x2969,1,1,1,1, +1,0xaa0,1,1,1,1,1,0x2973,1,1,1,1,1,1,1,1, +1,0xfe12,0xfc0e,1,1,1,1,1,1,1,0xfc00,1,1,1,1,1, +1,0x297d,0x2987,1,0xaa6,0xaac,0xfe12,0xfe12,1,1,1,1,1,1,1,1, +1,1,1,0xfe12,1,1,1,1,1,1,1,1,1,0xfe0e,1,1, +1,1,1,0xfe12,0xfe0e,1,1,1,1,1,1,1,1,1,0xfe0e,0xfe12, +1,1,1,1,1,1,1,1,1,1,1,0xfe0e,0xfe0e,1,0xfc00,1, +1,1,1,1,1,1,0xab2,1,1,1,0x2991,0x299b,0xfe12,1,1,1, +1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,0xfe12,1,1, +1,0xfe0e,1,1,1,1,1,1,1,1,1,0xfc00,1,1,1,1, +1,1,1,1,0xabe,0xfc00,0x29a5,0x29af,0xfc00,0x29b9,1,1,0xfe12,0xfe0e,1,1, +1,1,1,1,1,1,1,1,1,1,0xad0,0xad6,0x29c3,0x29cd,1,1, +1,0xfe12,0xfe0e,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,0xfe12,0xfe0e,1,1,1,1,1,1,1,1,0xfc00,1,1,1, +1,0xadc,1,1,0x29d7,1,1,1,1,0xfe12,0xfe12,1,0xfe02,0xfe02,0xfe02,0xfe02, +0xfe02,1,1,1,1,1,1,1,1,1,1,1,0xfe0c,0xfe0c,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,0xfe02,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0x325a,0x3264,0x3278,0x3290,0x32a8, +0x32c0,0x32d8,0xffb0,0xffb0,0xfe02,0xfe02,0xfe02,1,1,1,0xffc4,0xffb0,0xffb0,0xffb0,1,1, +1,1,1,1,1,1,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,1,1,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffb8,0xffb8,1,1,1,1,1,1,1,1,1,1,0xffcc,0xffcc, +0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,0x32e6,0x32f0,0x3304, +0x331c,0x3334,0x334c,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,1,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,1,1,1,1,1,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,1, +1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xfe0e,1, +1,1,1,1,0x335b,0x335f,0x3363,0x3367,0x336d,0x2f4d,0x3371,0x3375,0x3379,0x337d,0x2f51,0x3381, +0x3385,0x3389,0x2f55,0x338f,0x3393,0x3397,0x339b,0x33a1,0x33a5,0x33a9,0x33ad,0x33b3,0x33b7,0x33bb,0x33bf,0x303f, +0x33c3,0x33c9,0x33cd,0x33d1,0x33d5,0x33d9,0x33dd,0x33e1,0x33e5,0x3053,0x2f59,0x2f5d,0x3057,0x33e9,0x33ed,0x2c59, +0x33f1,0x2f61,0x33f5,0x33f9,0x33fd,0x3401,0x3401,0x3401,0x3405,0x340b,0x340f,0x3413,0x3417,0x341d,0x3421,0x3425, +0x3429,0x342d,0x3431,0x3435,0x3439,0x343d,0x3441,0x3445,0x3449,0x344d,0x344d,0x305f,0x3451,0x3455,0x3459,0x345d, +0x2f69,0x3461,0x3465,0x3469,0x2ebd,0x346d,0x3471,0x3475,0x3479,0x347d,0x3481,0x3485,0x3489,0x348d,0x3493,0x3497, +0x349b,0x349f,0x34a3,0x34a7,0x34ab,0x34b1,0x34b7,0x34bb,0x34bf,0x34c3,0x34c7,0x34cb,0x34cf,0x34d3,0x34d7,0x34d7, +0x34db,0x34e1,0x34e5,0x2c49,0x34e9,0x34ed,0x34f3,0x34f7,0x34fb,0x34ff,0x3503,0x3507,0x2f7d,0x350b,0x350f,0x3513, +0x3519,0x351d,0x3523,0x3527,0x352b,0x352f,0x3533,0x3537,0x353b,0x353f,0x3543,0x3547,0x354b,0x354f,0x3555,0x3559, +0x355d,0x3561,0x2b71,0x3565,0x356b,0x356f,0x356f,0x3575,0x3579,0x3579,0x357d,0x3581,0x3587,0x358d,0x3591,0x3595, +0x3599,0x359d,0x35a1,0x35a5,0x35a9,0x35ad,0x35b1,0x2f81,0x35b5,0x35bb,0x35bf,0x35c3,0x308f,0x35c3,0x35c7,0x2f89, +0x35cb,0x35cf,0x35d3,0x35d7,0x2f8d,0x2b05,0x35db,0x35df,0x35e3,0x35e7,0x35eb,0x35ef,0x35f3,0x35f9,0x35fd,0x3601, +0x3605,0x3609,0x360d,0x3613,0x3617,0x361b,0x361f,0x3623,0x3627,0x362b,0x362f,0x3633,0x2f91,0x3637,0x363b,0x3641, +0x3645,0x3649,0x364d,0x2f99,0x3651,0x3655,0x3659,0x365d,0x3661,0x3665,0x3669,0x366d,0x2b75,0x30af,0x3671,0x3675, +0x3679,0x367d,0x3683,0x3687,0x368b,0x368f,0x2f9d,0x3693,0x3699,0x369d,0x36a1,0x3161,0x36a5,0x36a9,0x36ad,0x36b1, +0x36b5,0x36bb,0x36bf,0x36c3,0x36c7,0x36cd,0x36d1,0x36d5,0x36d9,0x2c8d,0x36dd,0x36e1,0x36e7,0x36ed,0x36f3,0x36f7, +0x36fd,0x3701,0x3705,0x3709,0x370d,0x2fa1,0x2de9,0x3711,0x3715,0x3719,0x371d,0x3723,0x3727,0x372b,0x372f,0x30bf, +0x3733,0x3737,0x373d,0x3741,0x3745,0x374b,0x3751,0x3755,0x30c3,0x3759,0x375d,0x3761,0x3765,0x3769,0x376d,0x3771, +0x3777,0x377b,0x3781,0x3785,0x378b,0x30cb,0x378f,0x3793,0x3799,0x379d,0x37a1,0x37a7,0x37ad,0x37b1,0x37b5,0x37b9, +0x37bd,0x37bd,0x37c1,0x37c5,0x30d3,0x37c9,0x37cd,0x37d1,0x37d5,0x37d9,0x37df,0x37e3,0x2c55,0x37e9,0x37ef,0x37f3, +0x37f9,0x37ff,0x3805,0x3809,0x30eb,0x380d,0x3813,0x3819,0x381f,0x3825,0x3829,0x3829,0x30ef,0x3169,0x382d,0x3831, +0x3835,0x3839,0x383f,0x2bbd,0x30f7,0x3843,0x3847,0x2fcd,0x384d,0x3853,0x2f15,0x3859,0x385d,0x2fdd,0x3861,0x3865, +0x3869,0x386f,0x386f,0x3875,0x3879,0x387d,0x3883,0x3887,0x388b,0x388f,0x3895,0x3899,0x389d,0x38a1,0x38a5,0x38a9, +0x38af,0x38b3,0x38b7,0x38bb,0x38bf,0x38c3,0x38c7,0x38cd,0x38d3,0x38d7,0x38dd,0x38e1,0x38e7,0x38eb,0x2ff5,0x38ef, +0x38f5,0x38fb,0x38ff,0x3905,0x3909,0x390f,0x3913,0x3917,0x391b,0x391f,0x3923,0x3927,0x392d,0x3933,0x3939,0x3575, +0x393f,0x3943,0x3947,0x394b,0x394f,0x3953,0x3957,0x395b,0x395f,0x3963,0x3967,0x396b,0x2c9d,0x3971,0x3975,0x3979, +0x397d,0x3981,0x3985,0x3001,0x3989,0x398d,0x3991,0x3995,0x3999,0x399f,0x39a5,0x39ab,0x39af,0x39b3,0x39b7,0x39bb, +0x39c1,0x39c5,0x39cb,0x39cf,0x39d3,0x39d9,0x39df,0x39e3,0x2ba9,0x39e7,0x39eb,0x39ef,0x39f3,0x39f7,0x39fb,0x3113, +0x39ff,0x3a03,0x3a07,0x3a0b,0x3a0f,0x3a13,0x3a17,0x3a1b,0x3a1f,0x3a23,0x3a29,0x3a2d,0x3a31,0x3a35,0x3a39,0x3a3d, +0x3a43,0x3a49,0x3a4d,0x3a51,0x3127,0x312b,0x3a55,0x3a59,0x3a5f,0x3a63,0x3a67,0x3a6b,0x3a6f,0x3a75,0x3a7b,0x3a7f, +0x3a83,0x3a87,0x3a8d,0x312f,0x3a91,0x3a97,0x3a9d,0x3aa1,0x3aa5,0x3aa9,0x3aaf,0x3ab3,0x3ab7,0x3abb,0x3abf,0x3ac3, +0x3ac7,0x3acb,0x3ad1,0x3ad5,0x3ad9,0x3add,0x3ae3,0x3ae7,0x3aeb,0x3aef,0x3af3,0x3af9,0x3aff,0x3b03,0x3b07,0x3b0b, +0x3b11,0x3b15,0x3147,0x3147,0x3b1b,0x3b1f,0x3b25,0x3b29,0x3b2d,0x3b31,0x3b35,0x3b39,0x3b3d,0x3b41,0x314b,0x3b47, +0x3b4b,0x3b4f,0x3b53,0x3b57,0x3b5b,0x3b61,0x3b65,0x3b6b,0x3b71,0x3b77,0x3b7b,0x3b7f,0x3b83,0x3b87,0x3b8b,0x3b8f, +0x3b93,0x3b97,1,1 }; static const UCPTrie norm2_nfc_data_trie={ norm2_nfc_data_trieIndex, { norm2_nfc_data_trieData }, - 1712, 7824, + 1746, 7892, 0x2fc00, 0x30, 0, 0, 0, 0, @@ -632,7 +640,7 @@ static const UCPTrie norm2_nfc_data_trie={ 0x1, }; -static const uint16_t norm2_nfc_data_extraData[7724]={ +static const uint16_t norm2_nfc_data_extraData[7732]={ 0xffff,0xffff,0x8670,0x44dc,0x8670,0x44c0,0x8670,0x44de,0x600,0x180,0x602,0x182,0x604,0x185,0x606,0x186, 0x608,0x200,0x60c,0x205,0x60e,0x44d,0x610,0x189,0x612,0x3d44,0x614,0x18b,0x618,0x39a,0x61e,0x400, 0x622,0x404,0x646,0x3d41,0x64a,0x3c00,0x8650,0x208,0x60e,0x3c04,0x646,0x3c08,0x8662,0x3c0c,0x602,0x20c, @@ -719,408 +727,409 @@ static const uint16_t norm2_nfc_data_extraData[7724]={ 0x6132,0x61a6,0xe134,0x61a8,0x6132,0x61ac,0xe134,0x61ae,0x6132,0x61b2,0xe134,0x61b4,0x6132,0x61b8,0xe134,0x61ba, 0xe132,0x61ee,0xe132,0x61f0,0xe132,0x61f2,0xe132,0x61f4,0xe132,0x61fc,0xb489,0x2e82,0x2134,0xb489,0x2e82,0x2138, 0xb489,0x2e82,0x2156,0xb489,0x49c2,0x225c,0xb489,0x49c2,0x225e,0x3489,0xcf82,0x2696,0xb489,0xd5c2,0x2698,0x348b, -0x2c02,0x2978,0x348b,0x2e82,0x2976,0xb48b,0x2f42,0x297c,0xb48b,0x6bc2,0x2b74,0xb48b,0x6bc2,0x2b76,2,0xe602, -0x41,0x302,0x600,0x3d4c,0x602,0x3d48,0x606,0x3d54,0x8612,0x3d50,0xe602,0x41,0x308,0x8608,0x3bc,0xe602, -0x41,0x30a,0x8602,0x3f4,0xca02,0x43,0x327,0x8602,0x3c10,0xe602,0x45,0x302,0x600,0x3d80,0x602,0x3d7c, -0x606,0x3d88,0x8612,0x3d84,0xe602,0x49,0x308,0x8602,0x3c5c,0xe602,0x4f,0x302,0x600,0x3da4,0x602,0x3da0, -0x606,0x3dac,0x8612,0x3da8,0xe602,0x4f,0x303,0x602,0x3c98,0x608,0x458,0x8610,0x3c9c,0xe602,0x4f,0x308, -0x8608,0x454,0xe602,0x55,0x308,0x600,0x3b6,0x602,0x3ae,0x608,0x3aa,0x8618,0x3b2,0xe602,0x61,0x302, -0x600,0x3d4e,0x602,0x3d4a,0x606,0x3d56,0x8612,0x3d52,0xe602,0x61,0x308,0x8608,0x3be,0xe602,0x61,0x30a, -0x8602,0x3f6,0xca02,0x63,0x327,0x8602,0x3c12,0xe602,0x65,0x302,0x600,0x3d82,0x602,0x3d7e,0x606,0x3d8a, -0x8612,0x3d86,0xe602,0x69,0x308,0x8602,0x3c5e,0xe602,0x6f,0x302,0x600,0x3da6,0x602,0x3da2,0x606,0x3dae, -0x8612,0x3daa,0xe602,0x6f,0x303,0x602,0x3c9a,0x608,0x45a,0x8610,0x3c9e,0xe602,0x6f,0x308,0x8608,0x456, -0xe602,0x75,0x308,0x600,0x3b8,0x602,0x3b0,0x608,0x3ac,0x8618,0x3b4,0xe602,0x41,0x306,0x600,0x3d60, -0x602,0x3d5c,0x606,0x3d68,0x8612,0x3d64,0xe602,0x61,0x306,0x600,0x3d62,0x602,0x3d5e,0x606,0x3d6a,0x8612, -0x3d66,0xe602,0x45,0x304,0x600,0x3c28,0x8602,0x3c2c,0xe602,0x65,0x304,0x600,0x3c2a,0x8602,0x3c2e,0xe602, -0x4f,0x304,0x600,0x3ca0,0x8602,0x3ca4,0xe602,0x6f,0x304,0x600,0x3ca2,0x8602,0x3ca6,0xe602,0x53,0x301, -0x860e,0x3cc8,0xe602,0x73,0x301,0x860e,0x3cca,0xe602,0x53,0x30c,0x860e,0x3ccc,0xe602,0x73,0x30c,0x860e, -0x3cce,0xe602,0x55,0x303,0x8602,0x3cf0,0xe602,0x75,0x303,0x8602,0x3cf2,0xe602,0x55,0x304,0x8610,0x3cf4, -0xe602,0x75,0x304,0x8610,0x3cf6,0xd802,0x4f,0x31b,0x600,0x3db8,0x602,0x3db4,0x606,0x3dc0,0x612,0x3dbc, -0x8646,0x3dc4,0xd802,0x6f,0x31b,0x600,0x3dba,0x602,0x3db6,0x606,0x3dc2,0x612,0x3dbe,0x8646,0x3dc6,0xd802, -0x55,0x31b,0x600,0x3dd4,0x602,0x3dd0,0x606,0x3ddc,0x612,0x3dd8,0x8646,0x3de0,0xd802,0x75,0x31b,0x600, -0x3dd6,0x602,0x3dd2,0x606,0x3dde,0x612,0x3dda,0x8646,0x3de2,0xca02,0x4f,0x328,0x8608,0x3d8,0xca02,0x6f, -0x328,0x8608,0x3da,0xe602,0x41,0x307,0x8608,0x3c0,0xe602,0x61,0x307,0x8608,0x3c2,0xca02,0x45,0x327, -0x860c,0x3c38,0xca02,0x65,0x327,0x860c,0x3c3a,0xe602,0x4f,0x307,0x8608,0x460,0xe602,0x6f,0x307,0x8608, -0x462,0xe602,0x3b1,0x301,0x868a,0x3f68,0xe602,0x3b7,0x301,0x868a,0x3f88,0xe602,0x3b9,0x308,0x600,0x3fa4, -0x602,0x720,0x8684,0x3fae,0xe602,0x3c5,0x308,0x600,0x3fc4,0x602,0x760,0x8684,0x3fce,0xe602,0x3c9,0x301, -0x868a,0x3fe8,2,0xcc6,0xcc2,0x99aa,0x1996,2,0xdd9,0xdcf,0x9b94,0x1bba,0xdc02,0x4c,0x323,0x8608, -0x3c70,0xdc02,0x6c,0x323,0x8608,0x3c72,0xdc02,0x52,0x323,0x8608,0x3cb8,0xdc02,0x72,0x323,0x8608,0x3cba, -0xdc02,0x53,0x323,0x860e,0x3cd0,0xdc02,0x73,0x323,0x860e,0x3cd2,0xdc02,0x41,0x323,0x604,0x3d58,0x860c, -0x3d6c,0xdc02,0x61,0x323,0x604,0x3d5a,0x860c,0x3d6e,0xdc02,0x45,0x323,0x8604,0x3d8c,0xdc02,0x65,0x323, -0x8604,0x3d8e,0xdc02,0x4f,0x323,0x8604,0x3db0,0xdc02,0x6f,0x323,0x8604,0x3db2,0xe602,0x3b1,0x313,0x600, -0x3e05,0x602,0x3e09,0x684,0x3e0d,0x868a,0x3f00,0xe602,0x3b1,0x314,0x600,0x3e07,0x602,0x3e0b,0x684,0x3e0f, -0x868a,0x3f02,0x1f00,0xe643,0x3b1,0x313,0x300,0x868a,0x3f04,0x1f01,0xe643,0x3b1,0x314,0x300,0x868a,0x3f06, -0x1f00,0xe643,0x3b1,0x313,0x301,0x868a,0x3f08,0x1f01,0xe643,0x3b1,0x314,0x301,0x868a,0x3f0a,0x1f00,0xe643, -0x3b1,0x313,0x342,0x868a,0x3f0c,0x1f01,0xe643,0x3b1,0x314,0x342,0x868a,0x3f0e,0xe602,0x391,0x313,0x600, -0x3e15,0x602,0x3e19,0x684,0x3e1d,0x868a,0x3f10,0xe602,0x391,0x314,0x600,0x3e17,0x602,0x3e1b,0x684,0x3e1f, -0x868a,0x3f12,0x1f08,0xe643,0x391,0x313,0x300,0x868a,0x3f14,0x1f09,0xe643,0x391,0x314,0x300,0x868a,0x3f16, -0x1f08,0xe643,0x391,0x313,0x301,0x868a,0x3f18,0x1f09,0xe643,0x391,0x314,0x301,0x868a,0x3f1a,0x1f08,0xe643, -0x391,0x313,0x342,0x868a,0x3f1c,0x1f09,0xe643,0x391,0x314,0x342,0x868a,0x3f1e,0xe602,0x3b5,0x313,0x600, -0x3e24,0x8602,0x3e28,0xe602,0x3b5,0x314,0x600,0x3e26,0x8602,0x3e2a,0xe602,0x395,0x313,0x600,0x3e34,0x8602, -0x3e38,0xe602,0x395,0x314,0x600,0x3e36,0x8602,0x3e3a,0xe602,0x3b7,0x313,0x600,0x3e45,0x602,0x3e49,0x684, -0x3e4d,0x868a,0x3f20,0xe602,0x3b7,0x314,0x600,0x3e47,0x602,0x3e4b,0x684,0x3e4f,0x868a,0x3f22,0x1f20,0xe643, -0x3b7,0x313,0x300,0x868a,0x3f24,0x1f21,0xe643,0x3b7,0x314,0x300,0x868a,0x3f26,0x1f20,0xe643,0x3b7,0x313, -0x301,0x868a,0x3f28,0x1f21,0xe643,0x3b7,0x314,0x301,0x868a,0x3f2a,0x1f20,0xe643,0x3b7,0x313,0x342,0x868a, -0x3f2c,0x1f21,0xe643,0x3b7,0x314,0x342,0x868a,0x3f2e,0xe602,0x397,0x313,0x600,0x3e55,0x602,0x3e59,0x684, -0x3e5d,0x868a,0x3f30,0xe602,0x397,0x314,0x600,0x3e57,0x602,0x3e5b,0x684,0x3e5f,0x868a,0x3f32,0x1f28,0xe643, -0x397,0x313,0x300,0x868a,0x3f34,0x1f29,0xe643,0x397,0x314,0x300,0x868a,0x3f36,0x1f28,0xe643,0x397,0x313, -0x301,0x868a,0x3f38,0x1f29,0xe643,0x397,0x314,0x301,0x868a,0x3f3a,0x1f28,0xe643,0x397,0x313,0x342,0x868a, -0x3f3c,0x1f29,0xe643,0x397,0x314,0x342,0x868a,0x3f3e,0xe602,0x3b9,0x313,0x600,0x3e64,0x602,0x3e68,0x8684, -0x3e6c,0xe602,0x3b9,0x314,0x600,0x3e66,0x602,0x3e6a,0x8684,0x3e6e,0xe602,0x399,0x313,0x600,0x3e74,0x602, -0x3e78,0x8684,0x3e7c,0xe602,0x399,0x314,0x600,0x3e76,0x602,0x3e7a,0x8684,0x3e7e,0xe602,0x3bf,0x313,0x600, -0x3e84,0x8602,0x3e88,0xe602,0x3bf,0x314,0x600,0x3e86,0x8602,0x3e8a,0xe602,0x39f,0x313,0x600,0x3e94,0x8602, -0x3e98,0xe602,0x39f,0x314,0x600,0x3e96,0x8602,0x3e9a,0xe602,0x3c5,0x313,0x600,0x3ea4,0x602,0x3ea8,0x8684, -0x3eac,0xe602,0x3c5,0x314,0x600,0x3ea6,0x602,0x3eaa,0x8684,0x3eae,0xe602,0x3a5,0x314,0x600,0x3eb6,0x602, -0x3eba,0x8684,0x3ebe,0xe602,0x3c9,0x313,0x600,0x3ec5,0x602,0x3ec9,0x684,0x3ecd,0x868a,0x3f40,0xe602,0x3c9, -0x314,0x600,0x3ec7,0x602,0x3ecb,0x684,0x3ecf,0x868a,0x3f42,0x1f60,0xe643,0x3c9,0x313,0x300,0x868a,0x3f44, -0x1f61,0xe643,0x3c9,0x314,0x300,0x868a,0x3f46,0x1f60,0xe643,0x3c9,0x313,0x301,0x868a,0x3f48,0x1f61,0xe643, -0x3c9,0x314,0x301,0x868a,0x3f4a,0x1f60,0xe643,0x3c9,0x313,0x342,0x868a,0x3f4c,0x1f61,0xe643,0x3c9,0x314, -0x342,0x868a,0x3f4e,0xe602,0x3a9,0x313,0x600,0x3ed5,0x602,0x3ed9,0x684,0x3edd,0x868a,0x3f50,0xe602,0x3a9, -0x314,0x600,0x3ed7,0x602,0x3edb,0x684,0x3edf,0x868a,0x3f52,0x1f68,0xe643,0x3a9,0x313,0x300,0x868a,0x3f54, -0x1f69,0xe643,0x3a9,0x314,0x300,0x868a,0x3f56,0x1f68,0xe643,0x3a9,0x313,0x301,0x868a,0x3f58,0x1f69,0xe643, -0x3a9,0x314,0x301,0x868a,0x3f5a,0x1f68,0xe643,0x3a9,0x313,0x342,0x868a,0x3f5c,0x1f69,0xe643,0x3a9,0x314, -0x342,0x868a,0x3f5e,0xe602,0x3b1,0x300,0x868a,0x3f64,0xe602,0x3b7,0x300,0x868a,0x3f84,0xe602,0x3c9,0x300, -0x868a,0x3fe4,0xe602,0x3b1,0x342,0x868a,0x3f6e,0xe602,0x3b7,0x342,0x868a,0x3f8e,0xe602,0x3c9,0x342,0x868a, -0x3fee,3,0xe602,0x41,0x300,0xe602,0x41,0x301,0xe602,0x41,0x303,0xe602,0x45,0x300,0xe602,0x45, -0x301,0xe602,0x45,0x308,0xe602,0x49,0x300,0xe602,0x49,0x301,0xe602,0x49,0x302,0xe602,0x4e,0x303, -0xe602,0x4f,0x300,0xe602,0x4f,0x301,0xe602,0x55,0x300,0xe602,0x55,0x301,0xe602,0x55,0x302,0xe602, -0x59,0x301,0xe602,0x61,0x300,0xe602,0x61,0x301,0xe602,0x61,0x303,0xe602,0x65,0x300,0xe602,0x65, -0x301,0xe602,0x65,0x308,0xe602,0x69,0x300,0xe602,0x69,0x301,0xe602,0x69,0x302,0xe602,0x6e,0x303, -0xe602,0x6f,0x300,0xe602,0x6f,0x301,0xe602,0x75,0x300,0xe602,0x75,0x301,0xe602,0x75,0x302,0xe602, -0x79,0x301,0xe602,0x79,0x308,0xe602,0x41,0x304,0xe602,0x61,0x304,0xca02,0x41,0x328,0xca02,0x61, -0x328,0xe602,0x43,0x301,0xe602,0x63,0x301,0xe602,0x43,0x302,0xe602,0x63,0x302,0xe602,0x43,0x307, -0xe602,0x63,0x307,0xe602,0x43,0x30c,0xe602,0x63,0x30c,0xe602,0x44,0x30c,0xe602,0x64,0x30c,0xe602, -0x45,0x306,0xe602,0x65,0x306,0xe602,0x45,0x307,0xe602,0x65,0x307,0xca02,0x45,0x328,0xca02,0x65, -0x328,0xe602,0x45,0x30c,0xe602,0x65,0x30c,0xe602,0x47,0x302,0xe602,0x67,0x302,0xe602,0x47,0x306, -0xe602,0x67,0x306,0xe602,0x47,0x307,0xe602,0x67,0x307,0xca02,0x47,0x327,0xca02,0x67,0x327,0xe602, -0x48,0x302,0xe602,0x68,0x302,0xe602,0x49,0x303,0xe602,0x69,0x303,0xe602,0x49,0x304,0xe602,0x69, -0x304,0xe602,0x49,0x306,0xe602,0x69,0x306,0xca02,0x49,0x328,0xca02,0x69,0x328,0xe602,0x49,0x307, -0xe602,0x4a,0x302,0xe602,0x6a,0x302,0xca02,0x4b,0x327,0xca02,0x6b,0x327,0xe602,0x4c,0x301,0xe602, -0x6c,0x301,0xca02,0x4c,0x327,0xca02,0x6c,0x327,0xe602,0x4c,0x30c,0xe602,0x6c,0x30c,0xe602,0x4e, -0x301,0xe602,0x6e,0x301,0xca02,0x4e,0x327,0xca02,0x6e,0x327,0xe602,0x4e,0x30c,0xe602,0x6e,0x30c, -0xe602,0x4f,0x306,0xe602,0x6f,0x306,0xe602,0x4f,0x30b,0xe602,0x6f,0x30b,0xe602,0x52,0x301,0xe602, -0x72,0x301,0xca02,0x52,0x327,0xca02,0x72,0x327,0xe602,0x52,0x30c,0xe602,0x72,0x30c,0xe602,0x53, -0x302,0xe602,0x73,0x302,0xca02,0x53,0x327,0xca02,0x73,0x327,0xca02,0x54,0x327,0xca02,0x74,0x327, -0xe602,0x54,0x30c,0xe602,0x74,0x30c,0xe602,0x55,0x306,0xe602,0x75,0x306,0xe602,0x55,0x30a,0xe602, -0x75,0x30a,0xe602,0x55,0x30b,0xe602,0x75,0x30b,0xca02,0x55,0x328,0xca02,0x75,0x328,0xe602,0x57, -0x302,0xe602,0x77,0x302,0xe602,0x59,0x302,0xe602,0x79,0x302,0xe602,0x59,0x308,0xe602,0x5a,0x301, -0xe602,0x7a,0x301,0xe602,0x5a,0x307,0xe602,0x7a,0x307,0xe602,0x5a,0x30c,0xe602,0x7a,0x30c,0xe602, -0x41,0x30c,0xe602,0x61,0x30c,0xe602,0x49,0x30c,0xe602,0x69,0x30c,0xe602,0x4f,0x30c,0xe602,0x6f, -0x30c,0xe602,0x55,0x30c,0xe602,0x75,0x30c,0xdc,0xe643,0x55,0x308,0x304,0xfc,0xe643,0x75,0x308, -0x304,0xdc,0xe643,0x55,0x308,0x301,0xfc,0xe643,0x75,0x308,0x301,0xdc,0xe643,0x55,0x308,0x30c, -0xfc,0xe643,0x75,0x308,0x30c,0xdc,0xe643,0x55,0x308,0x300,0xfc,0xe643,0x75,0x308,0x300,0xc4, -0xe643,0x41,0x308,0x304,0xe4,0xe643,0x61,0x308,0x304,0x226,0xe643,0x41,0x307,0x304,0x227,0xe643, -0x61,0x307,0x304,0xe602,0xc6,0x304,0xe602,0xe6,0x304,0xe602,0x47,0x30c,0xe602,0x67,0x30c,0xe602, -0x4b,0x30c,0xe602,0x6b,0x30c,0x1ea,0xe643,0x4f,0x328,0x304,0x1eb,0xe643,0x6f,0x328,0x304,0xe602, -0x1b7,0x30c,0xe602,0x292,0x30c,0xe602,0x6a,0x30c,0xe602,0x47,0x301,0xe602,0x67,0x301,0xe602,0x4e, -0x300,0xe602,0x6e,0x300,0xc5,0xe643,0x41,0x30a,0x301,0xe5,0xe643,0x61,0x30a,0x301,0xe602,0xc6, -0x301,0xe602,0xe6,0x301,0xe602,0xd8,0x301,0xe602,0xf8,0x301,0xe602,0x41,0x30f,0xe602,0x61,0x30f, -0xe602,0x41,0x311,0xe602,0x61,0x311,0xe602,0x45,0x30f,0xe602,0x65,0x30f,0xe602,0x45,0x311,0xe602, -0x65,0x311,0xe602,0x49,0x30f,0xe602,0x69,0x30f,0xe602,0x49,0x311,0xe602,0x69,0x311,0xe602,0x4f, -0x30f,0xe602,0x6f,0x30f,0xe602,0x4f,0x311,0xe602,0x6f,0x311,0xe602,0x52,0x30f,0xe602,0x72,0x30f, -0xe602,0x52,0x311,0xe602,0x72,0x311,0xe602,0x55,0x30f,0xe602,0x75,0x30f,0xe602,0x55,0x311,0xe602, -0x75,0x311,0xdc02,0x53,0x326,0xdc02,0x73,0x326,0xdc02,0x54,0x326,0xdc02,0x74,0x326,0xe602,0x48, -0x30c,0xe602,0x68,0x30c,0xd6,0xe643,0x4f,0x308,0x304,0xf6,0xe643,0x6f,0x308,0x304,0xd5,0xe643, -0x4f,0x303,0x304,0xf5,0xe643,0x6f,0x303,0x304,0x22e,0xe643,0x4f,0x307,0x304,0x22f,0xe643,0x6f, -0x307,0x304,0xe602,0x59,0x304,0xe602,0x79,0x304,0xe602,0xa8,0x301,0xe602,0x391,0x301,0xe602,0x395, -0x301,0xe602,0x397,0x301,0xe602,0x399,0x301,0xe602,0x39f,0x301,0xe602,0x3a5,0x301,0xe602,0x3a9,0x301, -0x3ca,0xe643,0x3b9,0x308,0x301,0xe602,0x399,0x308,0xe602,0x3a5,0x308,0xe602,0x3b5,0x301,0xe602,0x3b9, -0x301,0x3cb,0xe643,0x3c5,0x308,0x301,0xe602,0x3bf,0x301,0xe602,0x3c5,0x301,0xe602,0x3d2,0x301,0xe602, -0x3d2,0x308,0xe602,0x415,0x300,0xe602,0x415,0x308,0xe602,0x413,0x301,0xe602,0x406,0x308,0xe602,0x41a, -0x301,0xe602,0x418,0x300,0xe602,0x423,0x306,0xe602,0x418,0x306,0xe602,0x438,0x306,0xe602,0x435,0x300, -0xe602,0x435,0x308,0xe602,0x433,0x301,0xe602,0x456,0x308,0xe602,0x43a,0x301,0xe602,0x438,0x300,0xe602, -0x443,0x306,0xe602,0x474,0x30f,0xe602,0x475,0x30f,0xe602,0x416,0x306,0xe602,0x436,0x306,0xe602,0x410, -0x306,0xe602,0x430,0x306,0xe602,0x410,0x308,0xe602,0x430,0x308,0xe602,0x415,0x306,0xe602,0x435,0x306, -0xe602,0x4d8,0x308,0xe602,0x4d9,0x308,0xe602,0x416,0x308,0xe602,0x436,0x308,0xe602,0x417,0x308,0xe602, -0x437,0x308,0xe602,0x418,0x304,0xe602,0x438,0x304,0xe602,0x418,0x308,0xe602,0x438,0x308,0xe602,0x41e, -0x308,0xe602,0x43e,0x308,0xe602,0x4e8,0x308,0xe602,0x4e9,0x308,0xe602,0x42d,0x308,0xe602,0x44d,0x308, -0xe602,0x423,0x304,0xe602,0x443,0x304,0xe602,0x423,0x308,0xe602,0x443,0x308,0xe602,0x423,0x30b,0xe602, -0x443,0x30b,0xe602,0x427,0x308,0xe602,0x447,0x308,0xe602,0x42b,0x308,0xe602,0x44b,0x308,0xe602,0x627, -0x653,0xe602,0x627,0x654,0xe602,0x648,0x654,0xdc02,0x627,0x655,0xe602,0x64a,0x654,0xe602,0x6d5,0x654, -0xe602,0x6c1,0x654,0xe602,0x6d2,0x654,0x702,0x928,0x93c,0x702,0x930,0x93c,0x702,0x933,0x93c,2, -0x9c7,0x9be,2,0x9c7,0x9d7,2,0xb47,0xb56,2,0xb47,0xb3e,2,0xb47,0xb57,2,0xb92, -0xbd7,2,0xbc6,0xbbe,2,0xbc7,0xbbe,2,0xbc6,0xbd7,0x5b02,0xc46,0xc56,2,0xcbf,0xcd5, -2,0xcc6,0xcd5,2,0xcc6,0xcd6,0xcca,0x43,0xcc6,0xcc2,0xcd5,2,0xd46,0xd3e,2,0xd47, -0xd3e,2,0xd46,0xd57,0x902,0xdd9,0xdca,0xddc,0x943,0xdd9,0xdcf,0xdca,2,0xdd9,0xddf,2, -0x1025,0x102e,2,0x1b05,0x1b35,2,0x1b07,0x1b35,2,0x1b09,0x1b35,2,0x1b0b,0x1b35,2,0x1b0d, -0x1b35,2,0x1b11,0x1b35,2,0x1b3a,0x1b35,2,0x1b3c,0x1b35,2,0x1b3e,0x1b35,2,0x1b3f,0x1b35, -2,0x1b42,0x1b35,0xdc02,0x41,0x325,0xdc02,0x61,0x325,0xe602,0x42,0x307,0xe602,0x62,0x307,0xdc02, -0x42,0x323,0xdc02,0x62,0x323,0xdc02,0x42,0x331,0xdc02,0x62,0x331,0xc7,0xe643,0x43,0x327,0x301, -0xe7,0xe643,0x63,0x327,0x301,0xe602,0x44,0x307,0xe602,0x64,0x307,0xdc02,0x44,0x323,0xdc02,0x64, -0x323,0xdc02,0x44,0x331,0xdc02,0x64,0x331,0xca02,0x44,0x327,0xca02,0x64,0x327,0xdc02,0x44,0x32d, -0xdc02,0x64,0x32d,0x112,0xe643,0x45,0x304,0x300,0x113,0xe643,0x65,0x304,0x300,0x112,0xe643,0x45, -0x304,0x301,0x113,0xe643,0x65,0x304,0x301,0xdc02,0x45,0x32d,0xdc02,0x65,0x32d,0xdc02,0x45,0x330, -0xdc02,0x65,0x330,0x228,0xe643,0x45,0x327,0x306,0x229,0xe643,0x65,0x327,0x306,0xe602,0x46,0x307, -0xe602,0x66,0x307,0xe602,0x47,0x304,0xe602,0x67,0x304,0xe602,0x48,0x307,0xe602,0x68,0x307,0xdc02, -0x48,0x323,0xdc02,0x68,0x323,0xe602,0x48,0x308,0xe602,0x68,0x308,0xca02,0x48,0x327,0xca02,0x68, -0x327,0xdc02,0x48,0x32e,0xdc02,0x68,0x32e,0xdc02,0x49,0x330,0xdc02,0x69,0x330,0xcf,0xe643,0x49, -0x308,0x301,0xef,0xe643,0x69,0x308,0x301,0xe602,0x4b,0x301,0xe602,0x6b,0x301,0xdc02,0x4b,0x323, -0xdc02,0x6b,0x323,0xdc02,0x4b,0x331,0xdc02,0x6b,0x331,0x1e36,0xe643,0x4c,0x323,0x304,0x1e37,0xe643, -0x6c,0x323,0x304,0xdc02,0x4c,0x331,0xdc02,0x6c,0x331,0xdc02,0x4c,0x32d,0xdc02,0x6c,0x32d,0xe602, -0x4d,0x301,0xe602,0x6d,0x301,0xe602,0x4d,0x307,0xe602,0x6d,0x307,0xdc02,0x4d,0x323,0xdc02,0x6d, -0x323,0xe602,0x4e,0x307,0xe602,0x6e,0x307,0xdc02,0x4e,0x323,0xdc02,0x6e,0x323,0xdc02,0x4e,0x331, -0xdc02,0x6e,0x331,0xdc02,0x4e,0x32d,0xdc02,0x6e,0x32d,0xd5,0xe643,0x4f,0x303,0x301,0xf5,0xe643, -0x6f,0x303,0x301,0xd5,0xe643,0x4f,0x303,0x308,0xf5,0xe643,0x6f,0x303,0x308,0x14c,0xe643,0x4f, -0x304,0x300,0x14d,0xe643,0x6f,0x304,0x300,0x14c,0xe643,0x4f,0x304,0x301,0x14d,0xe643,0x6f,0x304, -0x301,0xe602,0x50,0x301,0xe602,0x70,0x301,0xe602,0x50,0x307,0xe602,0x70,0x307,0xe602,0x52,0x307, -0xe602,0x72,0x307,0x1e5a,0xe643,0x52,0x323,0x304,0x1e5b,0xe643,0x72,0x323,0x304,0xdc02,0x52,0x331, -0xdc02,0x72,0x331,0xe602,0x53,0x307,0xe602,0x73,0x307,0x15a,0xe643,0x53,0x301,0x307,0x15b,0xe643, -0x73,0x301,0x307,0x160,0xe643,0x53,0x30c,0x307,0x161,0xe643,0x73,0x30c,0x307,0x1e62,0xe643,0x53, -0x323,0x307,0x1e63,0xe643,0x73,0x323,0x307,0xe602,0x54,0x307,0xe602,0x74,0x307,0xdc02,0x54,0x323, -0xdc02,0x74,0x323,0xdc02,0x54,0x331,0xdc02,0x74,0x331,0xdc02,0x54,0x32d,0xdc02,0x74,0x32d,0xdc02, -0x55,0x324,0xdc02,0x75,0x324,0xdc02,0x55,0x330,0xdc02,0x75,0x330,0xdc02,0x55,0x32d,0xdc02,0x75, -0x32d,0x168,0xe643,0x55,0x303,0x301,0x169,0xe643,0x75,0x303,0x301,0x16a,0xe643,0x55,0x304,0x308, -0x16b,0xe643,0x75,0x304,0x308,0xe602,0x56,0x303,0xe602,0x76,0x303,0xdc02,0x56,0x323,0xdc02,0x76, -0x323,0xe602,0x57,0x300,0xe602,0x77,0x300,0xe602,0x57,0x301,0xe602,0x77,0x301,0xe602,0x57,0x308, -0xe602,0x77,0x308,0xe602,0x57,0x307,0xe602,0x77,0x307,0xdc02,0x57,0x323,0xdc02,0x77,0x323,0xe602, -0x58,0x307,0xe602,0x78,0x307,0xe602,0x58,0x308,0xe602,0x78,0x308,0xe602,0x59,0x307,0xe602,0x79, -0x307,0xe602,0x5a,0x302,0xe602,0x7a,0x302,0xdc02,0x5a,0x323,0xdc02,0x7a,0x323,0xdc02,0x5a,0x331, -0xdc02,0x7a,0x331,0xdc02,0x68,0x331,0xe602,0x74,0x308,0xe602,0x77,0x30a,0xe602,0x79,0x30a,0xe602, -0x17f,0x307,0xe602,0x41,0x309,0xe602,0x61,0x309,0xc2,0xe643,0x41,0x302,0x301,0xe2,0xe643,0x61, -0x302,0x301,0xc2,0xe643,0x41,0x302,0x300,0xe2,0xe643,0x61,0x302,0x300,0xc2,0xe643,0x41,0x302, -0x309,0xe2,0xe643,0x61,0x302,0x309,0xc2,0xe643,0x41,0x302,0x303,0xe2,0xe643,0x61,0x302,0x303, -0x1ea0,0xe643,0x41,0x323,0x302,0x1ea1,0xe643,0x61,0x323,0x302,0x102,0xe643,0x41,0x306,0x301,0x103, -0xe643,0x61,0x306,0x301,0x102,0xe643,0x41,0x306,0x300,0x103,0xe643,0x61,0x306,0x300,0x102,0xe643, -0x41,0x306,0x309,0x103,0xe643,0x61,0x306,0x309,0x102,0xe643,0x41,0x306,0x303,0x103,0xe643,0x61, -0x306,0x303,0x1ea0,0xe643,0x41,0x323,0x306,0x1ea1,0xe643,0x61,0x323,0x306,0xe602,0x45,0x309,0xe602, -0x65,0x309,0xe602,0x45,0x303,0xe602,0x65,0x303,0xca,0xe643,0x45,0x302,0x301,0xea,0xe643,0x65, -0x302,0x301,0xca,0xe643,0x45,0x302,0x300,0xea,0xe643,0x65,0x302,0x300,0xca,0xe643,0x45,0x302, -0x309,0xea,0xe643,0x65,0x302,0x309,0xca,0xe643,0x45,0x302,0x303,0xea,0xe643,0x65,0x302,0x303, -0x1eb8,0xe643,0x45,0x323,0x302,0x1eb9,0xe643,0x65,0x323,0x302,0xe602,0x49,0x309,0xe602,0x69,0x309, -0xdc02,0x49,0x323,0xdc02,0x69,0x323,0xe602,0x4f,0x309,0xe602,0x6f,0x309,0xd4,0xe643,0x4f,0x302, -0x301,0xf4,0xe643,0x6f,0x302,0x301,0xd4,0xe643,0x4f,0x302,0x300,0xf4,0xe643,0x6f,0x302,0x300, -0xd4,0xe643,0x4f,0x302,0x309,0xf4,0xe643,0x6f,0x302,0x309,0xd4,0xe643,0x4f,0x302,0x303,0xf4, -0xe643,0x6f,0x302,0x303,0x1ecc,0xe643,0x4f,0x323,0x302,0x1ecd,0xe643,0x6f,0x323,0x302,0x1a0,0xe643, -0x4f,0x31b,0x301,0x1a1,0xe643,0x6f,0x31b,0x301,0x1a0,0xe643,0x4f,0x31b,0x300,0x1a1,0xe643,0x6f, -0x31b,0x300,0x1a0,0xe643,0x4f,0x31b,0x309,0x1a1,0xe643,0x6f,0x31b,0x309,0x1a0,0xe643,0x4f,0x31b, -0x303,0x1a1,0xe643,0x6f,0x31b,0x303,0x1a0,0xdc43,0x4f,0x31b,0x323,0x1a1,0xdc43,0x6f,0x31b,0x323, -0xdc02,0x55,0x323,0xdc02,0x75,0x323,0xe602,0x55,0x309,0xe602,0x75,0x309,0x1af,0xe643,0x55,0x31b, -0x301,0x1b0,0xe643,0x75,0x31b,0x301,0x1af,0xe643,0x55,0x31b,0x300,0x1b0,0xe643,0x75,0x31b,0x300, -0x1af,0xe643,0x55,0x31b,0x309,0x1b0,0xe643,0x75,0x31b,0x309,0x1af,0xe643,0x55,0x31b,0x303,0x1b0, -0xe643,0x75,0x31b,0x303,0x1af,0xdc43,0x55,0x31b,0x323,0x1b0,0xdc43,0x75,0x31b,0x323,0xe602,0x59, -0x300,0xe602,0x79,0x300,0xdc02,0x59,0x323,0xdc02,0x79,0x323,0xe602,0x59,0x309,0xe602,0x79,0x309, -0xe602,0x59,0x303,0xe602,0x79,0x303,0x1f10,0xe643,0x3b5,0x313,0x300,0x1f11,0xe643,0x3b5,0x314,0x300, -0x1f10,0xe643,0x3b5,0x313,0x301,0x1f11,0xe643,0x3b5,0x314,0x301,0x1f18,0xe643,0x395,0x313,0x300,0x1f19, -0xe643,0x395,0x314,0x300,0x1f18,0xe643,0x395,0x313,0x301,0x1f19,0xe643,0x395,0x314,0x301,0x1f30,0xe643, -0x3b9,0x313,0x300,0x1f31,0xe643,0x3b9,0x314,0x300,0x1f30,0xe643,0x3b9,0x313,0x301,0x1f31,0xe643,0x3b9, -0x314,0x301,0x1f30,0xe643,0x3b9,0x313,0x342,0x1f31,0xe643,0x3b9,0x314,0x342,0x1f38,0xe643,0x399,0x313, -0x300,0x1f39,0xe643,0x399,0x314,0x300,0x1f38,0xe643,0x399,0x313,0x301,0x1f39,0xe643,0x399,0x314,0x301, -0x1f38,0xe643,0x399,0x313,0x342,0x1f39,0xe643,0x399,0x314,0x342,0x1f40,0xe643,0x3bf,0x313,0x300,0x1f41, -0xe643,0x3bf,0x314,0x300,0x1f40,0xe643,0x3bf,0x313,0x301,0x1f41,0xe643,0x3bf,0x314,0x301,0x1f48,0xe643, -0x39f,0x313,0x300,0x1f49,0xe643,0x39f,0x314,0x300,0x1f48,0xe643,0x39f,0x313,0x301,0x1f49,0xe643,0x39f, -0x314,0x301,0x1f50,0xe643,0x3c5,0x313,0x300,0x1f51,0xe643,0x3c5,0x314,0x300,0x1f50,0xe643,0x3c5,0x313, -0x301,0x1f51,0xe643,0x3c5,0x314,0x301,0x1f50,0xe643,0x3c5,0x313,0x342,0x1f51,0xe643,0x3c5,0x314,0x342, -0x1f59,0xe643,0x3a5,0x314,0x300,0x1f59,0xe643,0x3a5,0x314,0x301,0x1f59,0xe643,0x3a5,0x314,0x342,0xe602, -0x3b5,0x300,0xe602,0x3b9,0x300,0xe602,0x3bf,0x300,0xe602,0x3c5,0x300,0x1f00,0xf043,0x3b1,0x313,0x345, -0x1f01,0xf043,0x3b1,0x314,0x345,0x1f02,0x345,2,0xf044,0x3b1,0x313,0x300,0x345,0x1f03,0x345,2, -0xf044,0x3b1,0x314,0x300,0x345,0x1f04,0x345,2,0xf044,0x3b1,0x313,0x301,0x345,0x1f05,0x345,2, -0xf044,0x3b1,0x314,0x301,0x345,0x1f06,0x345,2,0xf044,0x3b1,0x313,0x342,0x345,0x1f07,0x345,2, -0xf044,0x3b1,0x314,0x342,0x345,0x1f08,0xf043,0x391,0x313,0x345,0x1f09,0xf043,0x391,0x314,0x345,0x1f0a, -0x345,2,0xf044,0x391,0x313,0x300,0x345,0x1f0b,0x345,2,0xf044,0x391,0x314,0x300,0x345,0x1f0c, -0x345,2,0xf044,0x391,0x313,0x301,0x345,0x1f0d,0x345,2,0xf044,0x391,0x314,0x301,0x345,0x1f0e, -0x345,2,0xf044,0x391,0x313,0x342,0x345,0x1f0f,0x345,2,0xf044,0x391,0x314,0x342,0x345,0x1f20, -0xf043,0x3b7,0x313,0x345,0x1f21,0xf043,0x3b7,0x314,0x345,0x1f22,0x345,2,0xf044,0x3b7,0x313,0x300, -0x345,0x1f23,0x345,2,0xf044,0x3b7,0x314,0x300,0x345,0x1f24,0x345,2,0xf044,0x3b7,0x313,0x301, -0x345,0x1f25,0x345,2,0xf044,0x3b7,0x314,0x301,0x345,0x1f26,0x345,2,0xf044,0x3b7,0x313,0x342, -0x345,0x1f27,0x345,2,0xf044,0x3b7,0x314,0x342,0x345,0x1f28,0xf043,0x397,0x313,0x345,0x1f29,0xf043, -0x397,0x314,0x345,0x1f2a,0x345,2,0xf044,0x397,0x313,0x300,0x345,0x1f2b,0x345,2,0xf044,0x397, -0x314,0x300,0x345,0x1f2c,0x345,2,0xf044,0x397,0x313,0x301,0x345,0x1f2d,0x345,2,0xf044,0x397, -0x314,0x301,0x345,0x1f2e,0x345,2,0xf044,0x397,0x313,0x342,0x345,0x1f2f,0x345,2,0xf044,0x397, -0x314,0x342,0x345,0x1f60,0xf043,0x3c9,0x313,0x345,0x1f61,0xf043,0x3c9,0x314,0x345,0x1f62,0x345,2, -0xf044,0x3c9,0x313,0x300,0x345,0x1f63,0x345,2,0xf044,0x3c9,0x314,0x300,0x345,0x1f64,0x345,2, -0xf044,0x3c9,0x313,0x301,0x345,0x1f65,0x345,2,0xf044,0x3c9,0x314,0x301,0x345,0x1f66,0x345,2, -0xf044,0x3c9,0x313,0x342,0x345,0x1f67,0x345,2,0xf044,0x3c9,0x314,0x342,0x345,0x1f68,0xf043,0x3a9, -0x313,0x345,0x1f69,0xf043,0x3a9,0x314,0x345,0x1f6a,0x345,2,0xf044,0x3a9,0x313,0x300,0x345,0x1f6b, -0x345,2,0xf044,0x3a9,0x314,0x300,0x345,0x1f6c,0x345,2,0xf044,0x3a9,0x313,0x301,0x345,0x1f6d, -0x345,2,0xf044,0x3a9,0x314,0x301,0x345,0x1f6e,0x345,2,0xf044,0x3a9,0x313,0x342,0x345,0x1f6f, -0x345,2,0xf044,0x3a9,0x314,0x342,0x345,0xe602,0x3b1,0x306,0xe602,0x3b1,0x304,0x1f70,0xf043,0x3b1, -0x300,0x345,0xf002,0x3b1,0x345,0x3ac,0xf043,0x3b1,0x301,0x345,0x1fb6,0xf043,0x3b1,0x342,0x345,0xe602, -0x391,0x306,0xe602,0x391,0x304,0xe602,0x391,0x300,0xf002,0x391,0x345,0xe602,0xa8,0x342,0x1f74,0xf043, -0x3b7,0x300,0x345,0xf002,0x3b7,0x345,0x3ae,0xf043,0x3b7,0x301,0x345,0x1fc6,0xf043,0x3b7,0x342,0x345, -0xe602,0x395,0x300,0xe602,0x397,0x300,0xf002,0x397,0x345,0xe602,0x1fbf,0x300,0xe602,0x1fbf,0x301,0xe602, -0x1fbf,0x342,0xe602,0x3b9,0x306,0xe602,0x3b9,0x304,0x3ca,0xe643,0x3b9,0x308,0x300,0xe602,0x3b9,0x342, -0x3ca,0xe643,0x3b9,0x308,0x342,0xe602,0x399,0x306,0xe602,0x399,0x304,0xe602,0x399,0x300,0xe602,0x1ffe, -0x300,0xe602,0x1ffe,0x301,0xe602,0x1ffe,0x342,0xe602,0x3c5,0x306,0xe602,0x3c5,0x304,0x3cb,0xe643,0x3c5, -0x308,0x300,0xe602,0x3c1,0x313,0xe602,0x3c1,0x314,0xe602,0x3c5,0x342,0x3cb,0xe643,0x3c5,0x308,0x342, -0xe602,0x3a5,0x306,0xe602,0x3a5,0x304,0xe602,0x3a5,0x300,0xe602,0x3a1,0x314,0xe602,0xa8,0x300,0x1f7c, -0xf043,0x3c9,0x300,0x345,0xf002,0x3c9,0x345,0x3ce,0xf043,0x3c9,0x301,0x345,0x1ff6,0xf043,0x3c9,0x342, -0x345,0xe602,0x39f,0x300,0xe602,0x3a9,0x300,0xf002,0x3a9,0x345,0x102,0x2190,0x338,0x102,0x2192,0x338, -0x102,0x2194,0x338,0x102,0x21d0,0x338,0x102,0x21d4,0x338,0x102,0x21d2,0x338,0x102,0x2203,0x338,0x102, -0x2208,0x338,0x102,0x220b,0x338,0x102,0x2223,0x338,0x102,0x2225,0x338,0x102,0x223c,0x338,0x102,0x2243, -0x338,0x102,0x2245,0x338,0x102,0x2248,0x338,0x102,0x3d,0x338,0x102,0x2261,0x338,0x102,0x224d,0x338, -0x102,0x3c,0x338,0x102,0x3e,0x338,0x102,0x2264,0x338,0x102,0x2265,0x338,0x102,0x2272,0x338,0x102, -0x2273,0x338,0x102,0x2276,0x338,0x102,0x2277,0x338,0x102,0x227a,0x338,0x102,0x227b,0x338,0x102,0x2282, -0x338,0x102,0x2283,0x338,0x102,0x2286,0x338,0x102,0x2287,0x338,0x102,0x22a2,0x338,0x102,0x22a8,0x338, -0x102,0x22a9,0x338,0x102,0x22ab,0x338,0x102,0x227c,0x338,0x102,0x227d,0x338,0x102,0x2291,0x338,0x102, -0x2292,0x338,0x102,0x22b2,0x338,0x102,0x22b3,0x338,0x102,0x22b4,0x338,0x102,0x22b5,0x338,0x802,0x304b, -0x3099,0x802,0x304d,0x3099,0x802,0x304f,0x3099,0x802,0x3051,0x3099,0x802,0x3053,0x3099,0x802,0x3055,0x3099, -0x802,0x3057,0x3099,0x802,0x3059,0x3099,0x802,0x305b,0x3099,0x802,0x305d,0x3099,0x802,0x305f,0x3099,0x802, -0x3061,0x3099,0x802,0x3064,0x3099,0x802,0x3066,0x3099,0x802,0x3068,0x3099,0x802,0x306f,0x3099,0x802,0x306f, -0x309a,0x802,0x3072,0x3099,0x802,0x3072,0x309a,0x802,0x3075,0x3099,0x802,0x3075,0x309a,0x802,0x3078,0x3099, -0x802,0x3078,0x309a,0x802,0x307b,0x3099,0x802,0x307b,0x309a,0x802,0x3046,0x3099,0x802,0x309d,0x3099,0x802, -0x30ab,0x3099,0x802,0x30ad,0x3099,0x802,0x30af,0x3099,0x802,0x30b1,0x3099,0x802,0x30b3,0x3099,0x802,0x30b5, -0x3099,0x802,0x30b7,0x3099,0x802,0x30b9,0x3099,0x802,0x30bb,0x3099,0x802,0x30bd,0x3099,0x802,0x30bf,0x3099, -0x802,0x30c1,0x3099,0x802,0x30c4,0x3099,0x802,0x30c6,0x3099,0x802,0x30c8,0x3099,0x802,0x30cf,0x3099,0x802, -0x30cf,0x309a,0x802,0x30d2,0x3099,0x802,0x30d2,0x309a,0x802,0x30d5,0x3099,0x802,0x30d5,0x309a,0x802,0x30d8, -0x3099,0x802,0x30d8,0x309a,0x802,0x30db,0x3099,0x802,0x30db,0x309a,0x802,0x30a6,0x3099,0x802,0x30ef,0x3099, -0x802,0x30f0,0x3099,0x802,0x30f1,0x3099,0x802,0x30f2,0x3099,0x802,0x30fd,0x3099,0x704,0xd804,0xdc99,0xd804, -0xdcba,0x704,0xd804,0xdc9b,0xd804,0xdcba,0x704,0xd804,0xdca5,0xd804,0xdcba,4,0xd804,0xdd31,0xd804,0xdd27, -4,0xd804,0xdd32,0xd804,0xdd27,4,0xd804,0xdf47,0xd804,0xdf3e,4,0xd804,0xdf47,0xd804,0xdf57,4, -0xd805,0xdcb9,0xd805,0xdcba,4,0xd805,0xdcb9,0xd805,0xdcb0,4,0xd805,0xdcb9,0xd805,0xdcbd,4,0xd805, -0xddb8,0xd805,0xddaf,4,0xd805,0xddb9,0xd805,0xddaf,1,0x2b9,1,0x3b,1,0xb7,0x702,0x915, -0x93c,0x702,0x916,0x93c,0x702,0x917,0x93c,0x702,0x91c,0x93c,0x702,0x921,0x93c,0x702,0x922,0x93c, -0x702,0x92b,0x93c,0x702,0x92f,0x93c,0x702,0x9a1,0x9bc,0x702,0x9a2,0x9bc,0x702,0x9af,0x9bc,0x702, -0xa32,0xa3c,0x702,0xa38,0xa3c,0x702,0xa16,0xa3c,0x702,0xa17,0xa3c,0x702,0xa1c,0xa3c,0x702,0xa2b, -0xa3c,0x702,0xb21,0xb3c,0x702,0xb22,0xb3c,2,0xf42,0xfb7,2,0xf4c,0xfb7,2,0xf51,0xfb7, -2,0xf56,0xfb7,2,0xf5b,0xfb7,2,0xf40,0xfb5,0x8202,0xfb2,0xf80,0x8202,0xfb3,0xf80,2, -0xf92,0xfb7,2,0xf9c,0xfb7,2,0xfa1,0xfb7,2,0xfa6,0xfb7,2,0xfab,0xfb7,2,0xf90, -0xfb5,1,0x3b9,1,0x60,1,0xb4,1,0x3a9,1,0x4b,1,0x3008,1,0x3009,0x102, -0x2add,0x338,1,0x8c48,1,0x66f4,1,0x8eca,1,0x8cc8,1,0x6ed1,1,0x4e32,1,0x53e5, -1,0x9f9c,1,0x5951,1,0x91d1,1,0x5587,1,0x5948,1,0x61f6,1,0x7669,1,0x7f85, -1,0x863f,1,0x87ba,1,0x88f8,1,0x908f,1,0x6a02,1,0x6d1b,1,0x70d9,1,0x73de, -1,0x843d,1,0x916a,1,0x99f1,1,0x4e82,1,0x5375,1,0x6b04,1,0x721b,1,0x862d, -1,0x9e1e,1,0x5d50,1,0x6feb,1,0x85cd,1,0x8964,1,0x62c9,1,0x81d8,1,0x881f, -1,0x5eca,1,0x6717,1,0x6d6a,1,0x72fc,1,0x90ce,1,0x4f86,1,0x51b7,1,0x52de, -1,0x64c4,1,0x6ad3,1,0x7210,1,0x76e7,1,0x8001,1,0x8606,1,0x865c,1,0x8def, -1,0x9732,1,0x9b6f,1,0x9dfa,1,0x788c,1,0x797f,1,0x7da0,1,0x83c9,1,0x9304, -1,0x9e7f,1,0x8ad6,1,0x58df,1,0x5f04,1,0x7c60,1,0x807e,1,0x7262,1,0x78ca, -1,0x8cc2,1,0x96f7,1,0x58d8,1,0x5c62,1,0x6a13,1,0x6dda,1,0x6f0f,1,0x7d2f, -1,0x7e37,1,0x964b,1,0x52d2,1,0x808b,1,0x51dc,1,0x51cc,1,0x7a1c,1,0x7dbe, -1,0x83f1,1,0x9675,1,0x8b80,1,0x62cf,1,0x8afe,1,0x4e39,1,0x5be7,1,0x6012, -1,0x7387,1,0x7570,1,0x5317,1,0x78fb,1,0x4fbf,1,0x5fa9,1,0x4e0d,1,0x6ccc, -1,0x6578,1,0x7d22,1,0x53c3,1,0x585e,1,0x7701,1,0x8449,1,0x8aaa,1,0x6bba, -1,0x8fb0,1,0x6c88,1,0x62fe,1,0x82e5,1,0x63a0,1,0x7565,1,0x4eae,1,0x5169, -1,0x51c9,1,0x6881,1,0x7ce7,1,0x826f,1,0x8ad2,1,0x91cf,1,0x52f5,1,0x5442, -1,0x5973,1,0x5eec,1,0x65c5,1,0x6ffe,1,0x792a,1,0x95ad,1,0x9a6a,1,0x9e97, -1,0x9ece,1,0x529b,1,0x66c6,1,0x6b77,1,0x8f62,1,0x5e74,1,0x6190,1,0x6200, -1,0x649a,1,0x6f23,1,0x7149,1,0x7489,1,0x79ca,1,0x7df4,1,0x806f,1,0x8f26, -1,0x84ee,1,0x9023,1,0x934a,1,0x5217,1,0x52a3,1,0x54bd,1,0x70c8,1,0x88c2, -1,0x5ec9,1,0x5ff5,1,0x637b,1,0x6bae,1,0x7c3e,1,0x7375,1,0x4ee4,1,0x56f9, -1,0x5dba,1,0x601c,1,0x73b2,1,0x7469,1,0x7f9a,1,0x8046,1,0x9234,1,0x96f6, -1,0x9748,1,0x9818,1,0x4f8b,1,0x79ae,1,0x91b4,1,0x96b8,1,0x60e1,1,0x4e86, -1,0x50da,1,0x5bee,1,0x5c3f,1,0x6599,1,0x71ce,1,0x7642,1,0x84fc,1,0x907c, -1,0x9f8d,1,0x6688,1,0x962e,1,0x5289,1,0x677b,1,0x67f3,1,0x6d41,1,0x6e9c, -1,0x7409,1,0x7559,1,0x786b,1,0x7d10,1,0x985e,1,0x516d,1,0x622e,1,0x9678, -1,0x502b,1,0x5d19,1,0x6dea,1,0x8f2a,1,0x5f8b,1,0x6144,1,0x6817,1,0x9686, -1,0x5229,1,0x540f,1,0x5c65,1,0x6613,1,0x674e,1,0x68a8,1,0x6ce5,1,0x7406, -1,0x75e2,1,0x7f79,1,0x88cf,1,0x88e1,1,0x91cc,1,0x96e2,1,0x533f,1,0x6eba, -1,0x541d,1,0x71d0,1,0x7498,1,0x85fa,1,0x96a3,1,0x9c57,1,0x9e9f,1,0x6797, -1,0x6dcb,1,0x81e8,1,0x7acb,1,0x7b20,1,0x7c92,1,0x72c0,1,0x7099,1,0x8b58, -1,0x4ec0,1,0x8336,1,0x523a,1,0x5207,1,0x5ea6,1,0x62d3,1,0x7cd6,1,0x5b85, -1,0x6d1e,1,0x66b4,1,0x8f3b,1,0x884c,1,0x964d,1,0x898b,1,0x5ed3,1,0x5140, -1,0x55c0,1,0x585a,1,0x6674,1,0x51de,1,0x732a,1,0x76ca,1,0x793c,1,0x795e, -1,0x7965,1,0x798f,1,0x9756,1,0x7cbe,1,0x7fbd,1,0x8612,1,0x8af8,1,0x9038, -1,0x90fd,1,0x98ef,1,0x98fc,1,0x9928,1,0x9db4,1,0x90de,1,0x96b7,1,0x4fae, -1,0x50e7,1,0x514d,1,0x52c9,1,0x52e4,1,0x5351,1,0x559d,1,0x5606,1,0x5668, -1,0x5840,1,0x58a8,1,0x5c64,1,0x5c6e,1,0x6094,1,0x6168,1,0x618e,1,0x61f2, -1,0x654f,1,0x65e2,1,0x6691,1,0x6885,1,0x6d77,1,0x6e1a,1,0x6f22,1,0x716e, -1,0x722b,1,0x7422,1,0x7891,1,0x793e,1,0x7949,1,0x7948,1,0x7950,1,0x7956, -1,0x795d,1,0x798d,1,0x798e,1,0x7a40,1,0x7a81,1,0x7bc0,1,0x7e09,1,0x7e41, -1,0x7f72,1,0x8005,1,0x81ed,1,0x8279,1,0x8457,1,0x8910,1,0x8996,1,0x8b01, -1,0x8b39,1,0x8cd3,1,0x8d08,1,0x8fb6,1,0x96e3,1,0x97ff,1,0x983b,1,0x6075, -2,0xd850,0xdeee,1,0x8218,1,0x4e26,1,0x51b5,1,0x5168,1,0x4f80,1,0x5145,1, -0x5180,1,0x52c7,1,0x52fa,1,0x5555,1,0x5599,1,0x55e2,1,0x58b3,1,0x5944,1, -0x5954,1,0x5a62,1,0x5b28,1,0x5ed2,1,0x5ed9,1,0x5f69,1,0x5fad,1,0x60d8,1, -0x614e,1,0x6108,1,0x6160,1,0x6234,1,0x63c4,1,0x641c,1,0x6452,1,0x6556,1, -0x671b,1,0x6756,1,0x6b79,1,0x6edb,1,0x6ecb,1,0x701e,1,0x77a7,1,0x7235,1, -0x72af,1,0x7471,1,0x7506,1,0x753b,1,0x761d,1,0x761f,1,0x76db,1,0x76f4,1, -0x774a,1,0x7740,1,0x78cc,1,0x7ab1,1,0x7c7b,1,0x7d5b,1,0x7f3e,1,0x8352,1, -0x83ef,1,0x8779,1,0x8941,1,0x8986,1,0x8abf,1,0x8acb,1,0x8aed,1,0x8b8a,1, -0x8f38,1,0x9072,1,0x9199,1,0x9276,1,0x967c,1,0x97db,1,0x980b,1,0x9b12,2, -0xd84a,0xdc4a,2,0xd84a,0xdc44,2,0xd84c,0xdfd5,1,0x3b9d,1,0x4018,1,0x4039,2,0xd854, -0xde49,2,0xd857,0xdcd0,2,0xd85f,0xded3,1,0x9f43,1,0x9f8e,0xe02,0x5d9,0x5b4,0x1102,0x5f2, -0x5b7,0x1802,0x5e9,0x5c1,0x1902,0x5e9,0x5c2,0xfb49,0x1843,0x5e9,0x5bc,0x5c1,0xfb49,0x1943,0x5e9,0x5bc, -0x5c2,0x1102,0x5d0,0x5b7,0x1202,0x5d0,0x5b8,0x1502,0x5d0,0x5bc,0x1502,0x5d1,0x5bc,0x1502,0x5d2,0x5bc, -0x1502,0x5d3,0x5bc,0x1502,0x5d4,0x5bc,0x1502,0x5d5,0x5bc,0x1502,0x5d6,0x5bc,0x1502,0x5d8,0x5bc,0x1502, -0x5d9,0x5bc,0x1502,0x5da,0x5bc,0x1502,0x5db,0x5bc,0x1502,0x5dc,0x5bc,0x1502,0x5de,0x5bc,0x1502,0x5e0, -0x5bc,0x1502,0x5e1,0x5bc,0x1502,0x5e3,0x5bc,0x1502,0x5e4,0x5bc,0x1502,0x5e6,0x5bc,0x1502,0x5e7,0x5bc, -0x1502,0x5e8,0x5bc,0x1502,0x5e9,0x5bc,0x1502,0x5ea,0x5bc,0x1302,0x5d5,0x5b9,0x1702,0x5d1,0x5bf,0x1702, -0x5db,0x5bf,0x1702,0x5e4,0x5bf,0xd804,0xd834,0xdd57,0xd834,0xdd65,0xd804,0xd834,0xdd58,0xd834,0xdd65,0xd834, -0xdd5f,0xd834,0xdd6e,4,0xd846,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd6e,0xd834,0xdd5f,0xd834,0xdd6f,4, -0xd846,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd6f,0xd834,0xdd5f,0xd834,0xdd70,4,0xd846,0xd834,0xdd58,0xd834, -0xdd65,0xd834,0xdd70,0xd834,0xdd5f,0xd834,0xdd71,4,0xd846,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd71,0xd834, -0xdd5f,0xd834,0xdd72,4,0xd846,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd72,0xd804,0xd834,0xddb9,0xd834,0xdd65, -0xd804,0xd834,0xddba,0xd834,0xdd65,0xd834,0xddbb,0xd834,0xdd6e,4,0xd846,0xd834,0xddb9,0xd834,0xdd65,0xd834, -0xdd6e,0xd834,0xddbc,0xd834,0xdd6e,4,0xd846,0xd834,0xddba,0xd834,0xdd65,0xd834,0xdd6e,0xd834,0xddbb,0xd834, -0xdd6f,4,0xd846,0xd834,0xddb9,0xd834,0xdd65,0xd834,0xdd6f,0xd834,0xddbc,0xd834,0xdd6f,4,0xd846,0xd834, -0xddba,0xd834,0xdd65,0xd834,0xdd6f,1,0x4e3d,1,0x4e38,1,0x4e41,2,0xd840,0xdd22,1,0x4f60, -1,0x4fbb,1,0x5002,1,0x507a,1,0x5099,1,0x50cf,1,0x349e,2,0xd841,0xde3a,1, -0x5154,1,0x5164,1,0x5177,2,0xd841,0xdd1c,1,0x34b9,1,0x5167,1,0x518d,2,0xd841, -0xdd4b,1,0x5197,1,0x51a4,1,0x4ecc,1,0x51ac,2,0xd864,0xdddf,1,0x51f5,1,0x5203, -1,0x34df,1,0x523b,1,0x5246,1,0x5272,1,0x5277,1,0x3515,1,0x5305,1,0x5306, -1,0x5349,1,0x535a,1,0x5373,1,0x537d,1,0x537f,2,0xd842,0xde2c,1,0x7070,1, -0x53ca,1,0x53df,2,0xd842,0xdf63,1,0x53eb,1,0x53f1,1,0x5406,1,0x549e,1,0x5438, -1,0x5448,1,0x5468,1,0x54a2,1,0x54f6,1,0x5510,1,0x5553,1,0x5563,1,0x5584, -1,0x55ab,1,0x55b3,1,0x55c2,1,0x5716,1,0x5717,1,0x5651,1,0x5674,1,0x58ee, -1,0x57ce,1,0x57f4,1,0x580d,1,0x578b,1,0x5832,1,0x5831,1,0x58ac,2,0xd845, -0xdce4,1,0x58f2,1,0x58f7,1,0x5906,1,0x591a,1,0x5922,1,0x5962,2,0xd845,0xdea8, -2,0xd845,0xdeea,1,0x59ec,1,0x5a1b,1,0x5a27,1,0x59d8,1,0x5a66,1,0x36ee,1, -0x36fc,1,0x5b08,1,0x5b3e,2,0xd846,0xddc8,1,0x5bc3,1,0x5bd8,1,0x5bf3,2,0xd846, -0xdf18,1,0x5bff,1,0x5c06,1,0x5f53,1,0x5c22,1,0x3781,1,0x5c60,1,0x5cc0,1, -0x5c8d,2,0xd847,0xdde4,1,0x5d43,2,0xd847,0xdde6,1,0x5d6e,1,0x5d6b,1,0x5d7c,1, -0x5de1,1,0x5de2,1,0x382f,1,0x5dfd,1,0x5e28,1,0x5e3d,1,0x5e69,1,0x3862,2, -0xd848,0xdd83,1,0x387c,1,0x5eb0,1,0x5eb3,1,0x5eb6,2,0xd868,0xdf92,1,0x5efe,2, -0xd848,0xdf31,1,0x8201,1,0x5f22,1,0x38c7,2,0xd84c,0xdeb8,2,0xd858,0xddda,1,0x5f62, -1,0x5f6b,1,0x38e3,1,0x5f9a,1,0x5fcd,1,0x5fd7,1,0x5ff9,1,0x6081,1,0x393a, -1,0x391c,2,0xd849,0xded4,1,0x60c7,1,0x6148,1,0x614c,1,0x617a,1,0x61b2,1, -0x61a4,1,0x61af,1,0x61de,1,0x6210,1,0x621b,1,0x625d,1,0x62b1,1,0x62d4,1, -0x6350,2,0xd84a,0xdf0c,1,0x633d,1,0x62fc,1,0x6368,1,0x6383,1,0x63e4,2,0xd84a, -0xdff1,1,0x6422,1,0x63c5,1,0x63a9,1,0x3a2e,1,0x6469,1,0x647e,1,0x649d,1, -0x6477,1,0x3a6c,1,0x656c,2,0xd84c,0xdc0a,1,0x65e3,1,0x66f8,1,0x6649,1,0x3b19, -1,0x3b08,1,0x3ae4,1,0x5192,1,0x5195,1,0x6700,1,0x669c,1,0x80ad,1,0x43d9, -1,0x6721,1,0x675e,1,0x6753,2,0xd84c,0xdfc3,1,0x3b49,1,0x67fa,1,0x6785,1, -0x6852,2,0xd84d,0xdc6d,1,0x688e,1,0x681f,1,0x6914,1,0x6942,1,0x69a3,1,0x69ea, -1,0x6aa8,2,0xd84d,0xdea3,1,0x6adb,1,0x3c18,1,0x6b21,2,0xd84e,0xdca7,1,0x6b54, -1,0x3c4e,1,0x6b72,1,0x6b9f,1,0x6bbb,2,0xd84e,0xde8d,2,0xd847,0xdd0b,2,0xd84e, -0xdefa,1,0x6c4e,2,0xd84f,0xdcbc,1,0x6cbf,1,0x6ccd,1,0x6c67,1,0x6d16,1,0x6d3e, -1,0x6d69,1,0x6d78,1,0x6d85,2,0xd84f,0xdd1e,1,0x6d34,1,0x6e2f,1,0x6e6e,1, -0x3d33,1,0x6ec7,2,0xd84f,0xded1,1,0x6df9,1,0x6f6e,2,0xd84f,0xdf5e,2,0xd84f,0xdf8e, -1,0x6fc6,1,0x7039,1,0x701b,1,0x3d96,1,0x704a,1,0x707d,1,0x7077,1,0x70ad, -2,0xd841,0xdd25,1,0x7145,2,0xd850,0xde63,1,0x719c,2,0xd850,0xdfab,1,0x7228,1, -0x7250,2,0xd851,0xde08,1,0x7280,1,0x7295,2,0xd851,0xdf35,2,0xd852,0xdc14,1,0x737a, -1,0x738b,1,0x3eac,1,0x73a5,1,0x3eb8,1,0x7447,1,0x745c,1,0x7485,1,0x74ca, -1,0x3f1b,1,0x7524,2,0xd853,0xdc36,1,0x753e,2,0xd853,0xdc92,2,0xd848,0xdd9f,1, -0x7610,2,0xd853,0xdfa1,2,0xd853,0xdfb8,2,0xd854,0xdc44,1,0x3ffc,1,0x4008,2,0xd854, -0xdcf3,2,0xd854,0xdcf2,2,0xd854,0xdd19,2,0xd854,0xdd33,1,0x771e,1,0x771f,1,0x778b, -1,0x4046,1,0x4096,2,0xd855,0xdc1d,1,0x784e,1,0x40e3,2,0xd855,0xde26,2,0xd855, -0xde9a,2,0xd855,0xdec5,1,0x79eb,1,0x412f,1,0x7a4a,1,0x7a4f,2,0xd856,0xdd7c,2, -0xd856,0xdea7,1,0x7aee,1,0x4202,2,0xd856,0xdfab,1,0x7bc6,1,0x7bc9,1,0x4227,2, -0xd857,0xdc80,1,0x7cd2,1,0x42a0,1,0x7ce8,1,0x7ce3,1,0x7d00,2,0xd857,0xdf86,1, -0x7d63,1,0x4301,1,0x7dc7,1,0x7e02,1,0x7e45,1,0x4334,2,0xd858,0xde28,2,0xd858, -0xde47,1,0x4359,2,0xd858,0xded9,1,0x7f7a,2,0xd858,0xdf3e,1,0x7f95,1,0x7ffa,2, -0xd859,0xdcda,2,0xd859,0xdd23,1,0x8060,2,0xd859,0xdda8,1,0x8070,2,0xd84c,0xdf5f,1, -0x43d5,1,0x80b2,1,0x8103,1,0x440b,1,0x813e,1,0x5ab5,2,0xd859,0xdfa7,2,0xd859, -0xdfb5,2,0xd84c,0xdf93,2,0xd84c,0xdf9c,1,0x8204,1,0x8f9e,1,0x446b,1,0x8291,1, -0x828b,1,0x829d,1,0x52b3,1,0x82b1,1,0x82b3,1,0x82bd,1,0x82e6,2,0xd85a,0xdf3c, -1,0x831d,1,0x8363,1,0x83ad,1,0x8323,1,0x83bd,1,0x83e7,1,0x8353,1,0x83ca, -1,0x83cc,1,0x83dc,2,0xd85b,0xdc36,2,0xd85b,0xdd6b,2,0xd85b,0xdcd5,1,0x452b,1, -0x84f1,1,0x84f3,1,0x8516,2,0xd85c,0xdfca,1,0x8564,2,0xd85b,0xdf2c,1,0x455d,1, -0x4561,2,0xd85b,0xdfb1,2,0xd85c,0xdcd2,1,0x456b,1,0x8650,1,0x8667,1,0x8669,1, -0x86a9,1,0x8688,1,0x870e,1,0x86e2,1,0x8728,1,0x876b,1,0x8786,1,0x45d7,1, -0x87e1,1,0x8801,1,0x45f9,1,0x8860,1,0x8863,2,0xd85d,0xde67,1,0x88d7,1,0x88de, -1,0x4635,1,0x88fa,1,0x34bb,2,0xd85e,0xdcae,2,0xd85e,0xdd66,1,0x46be,1,0x46c7, -1,0x8aa0,1,0x8c55,2,0xd85f,0xdca8,1,0x8cab,1,0x8cc1,1,0x8d1b,1,0x8d77,2, -0xd85f,0xdf2f,2,0xd842,0xdc04,1,0x8dcb,1,0x8dbc,1,0x8df0,2,0xd842,0xdcde,1,0x8ed4, -2,0xd861,0xddd2,2,0xd861,0xdded,1,0x9094,1,0x90f1,1,0x9111,2,0xd861,0xdf2e,1, -0x911b,1,0x9238,1,0x92d7,1,0x92d8,1,0x927c,1,0x93f9,1,0x9415,2,0xd862,0xdffa, -1,0x958b,1,0x4995,1,0x95b7,2,0xd863,0xdd77,1,0x49e6,1,0x96c3,1,0x5db2,1, -0x9723,2,0xd864,0xdd45,2,0xd864,0xde1a,1,0x4a6e,1,0x4a76,1,0x97e0,2,0xd865,0xdc0a, -1,0x4ab2,2,0xd865,0xdc96,1,0x9829,2,0xd865,0xddb6,1,0x98e2,1,0x4b33,1,0x9929, -1,0x99a7,1,0x99c2,1,0x99fe,1,0x4bce,2,0xd866,0xdf30,1,0x9c40,1,0x9cfd,1, -0x4cce,1,0x4ced,1,0x9d67,2,0xd868,0xdcce,1,0x4cf8,2,0xd868,0xdd05,2,0xd868,0xde0e, -2,0xd868,0xde91,1,0x9ebb,1,0x4d56,1,0x9ef9,1,0x9efe,1,0x9f05,1,0x9f0f,1, -0x9f16,1,0x9f3b,2,0xd869,0xde00,0x3ac,0xe642,0x3b1,0x301,0x3ad,0xe642,0x3b5,0x301,0x3ae,0xe642, -0x3b7,0x301,0x3af,0xe642,0x3b9,0x301,0x3cc,0xe642,0x3bf,0x301,0x3cd,0xe642,0x3c5,0x301,0x3ce,0xe642, -0x3c9,0x301,0x386,0xe642,0x391,0x301,0x388,0xe642,0x395,0x301,0x389,0xe642,0x397,0x301,0x390,1, -0xe643,0x3b9,0x308,0x301,0x38a,0xe642,0x399,0x301,0x3b0,1,0xe643,0x3c5,0x308,0x301,0x38e,0xe642, -0x3a5,0x301,0x385,0xe642,0xa8,0x301,0x38c,0xe642,0x39f,0x301,0x38f,0xe642,0x3a9,0x301,0xc5,0xe642, -0x41,0x30a,0xe6e6,0xe681,0x300,0xe6e6,0xe681,0x301,0xe6e6,0xe681,0x313,0xe6e6,0xe682,0x308,0x301,0x8100, -0x8282,0xf71,0xf72,0x8100,0x8482,0xf71,0xf74,0x8100,0x8282,0xf71,0xf80,0 +0x2c02,0x2978,0x348b,0x2e82,0x2976,0xb48b,0x2f42,0x297c,0xb48b,0x6bc2,0x2b74,0xb48b,0x6bc2,0x2b76,0xb48d,0x4c02, +0x3270,2,0xe602,0x41,0x302,0x600,0x3d4c,0x602,0x3d48,0x606,0x3d54,0x8612,0x3d50,0xe602,0x41,0x308, +0x8608,0x3bc,0xe602,0x41,0x30a,0x8602,0x3f4,0xca02,0x43,0x327,0x8602,0x3c10,0xe602,0x45,0x302,0x600, +0x3d80,0x602,0x3d7c,0x606,0x3d88,0x8612,0x3d84,0xe602,0x49,0x308,0x8602,0x3c5c,0xe602,0x4f,0x302,0x600, +0x3da4,0x602,0x3da0,0x606,0x3dac,0x8612,0x3da8,0xe602,0x4f,0x303,0x602,0x3c98,0x608,0x458,0x8610,0x3c9c, +0xe602,0x4f,0x308,0x8608,0x454,0xe602,0x55,0x308,0x600,0x3b6,0x602,0x3ae,0x608,0x3aa,0x8618,0x3b2, +0xe602,0x61,0x302,0x600,0x3d4e,0x602,0x3d4a,0x606,0x3d56,0x8612,0x3d52,0xe602,0x61,0x308,0x8608,0x3be, +0xe602,0x61,0x30a,0x8602,0x3f6,0xca02,0x63,0x327,0x8602,0x3c12,0xe602,0x65,0x302,0x600,0x3d82,0x602, +0x3d7e,0x606,0x3d8a,0x8612,0x3d86,0xe602,0x69,0x308,0x8602,0x3c5e,0xe602,0x6f,0x302,0x600,0x3da6,0x602, +0x3da2,0x606,0x3dae,0x8612,0x3daa,0xe602,0x6f,0x303,0x602,0x3c9a,0x608,0x45a,0x8610,0x3c9e,0xe602,0x6f, +0x308,0x8608,0x456,0xe602,0x75,0x308,0x600,0x3b8,0x602,0x3b0,0x608,0x3ac,0x8618,0x3b4,0xe602,0x41, +0x306,0x600,0x3d60,0x602,0x3d5c,0x606,0x3d68,0x8612,0x3d64,0xe602,0x61,0x306,0x600,0x3d62,0x602,0x3d5e, +0x606,0x3d6a,0x8612,0x3d66,0xe602,0x45,0x304,0x600,0x3c28,0x8602,0x3c2c,0xe602,0x65,0x304,0x600,0x3c2a, +0x8602,0x3c2e,0xe602,0x4f,0x304,0x600,0x3ca0,0x8602,0x3ca4,0xe602,0x6f,0x304,0x600,0x3ca2,0x8602,0x3ca6, +0xe602,0x53,0x301,0x860e,0x3cc8,0xe602,0x73,0x301,0x860e,0x3cca,0xe602,0x53,0x30c,0x860e,0x3ccc,0xe602, +0x73,0x30c,0x860e,0x3cce,0xe602,0x55,0x303,0x8602,0x3cf0,0xe602,0x75,0x303,0x8602,0x3cf2,0xe602,0x55, +0x304,0x8610,0x3cf4,0xe602,0x75,0x304,0x8610,0x3cf6,0xd802,0x4f,0x31b,0x600,0x3db8,0x602,0x3db4,0x606, +0x3dc0,0x612,0x3dbc,0x8646,0x3dc4,0xd802,0x6f,0x31b,0x600,0x3dba,0x602,0x3db6,0x606,0x3dc2,0x612,0x3dbe, +0x8646,0x3dc6,0xd802,0x55,0x31b,0x600,0x3dd4,0x602,0x3dd0,0x606,0x3ddc,0x612,0x3dd8,0x8646,0x3de0,0xd802, +0x75,0x31b,0x600,0x3dd6,0x602,0x3dd2,0x606,0x3dde,0x612,0x3dda,0x8646,0x3de2,0xca02,0x4f,0x328,0x8608, +0x3d8,0xca02,0x6f,0x328,0x8608,0x3da,0xe602,0x41,0x307,0x8608,0x3c0,0xe602,0x61,0x307,0x8608,0x3c2, +0xca02,0x45,0x327,0x860c,0x3c38,0xca02,0x65,0x327,0x860c,0x3c3a,0xe602,0x4f,0x307,0x8608,0x460,0xe602, +0x6f,0x307,0x8608,0x462,0xe602,0x3b1,0x301,0x868a,0x3f68,0xe602,0x3b7,0x301,0x868a,0x3f88,0xe602,0x3b9, +0x308,0x600,0x3fa4,0x602,0x720,0x8684,0x3fae,0xe602,0x3c5,0x308,0x600,0x3fc4,0x602,0x760,0x8684,0x3fce, +0xe602,0x3c9,0x301,0x868a,0x3fe8,2,0xcc6,0xcc2,0x99aa,0x1996,2,0xdd9,0xdcf,0x9b94,0x1bba,0xdc02, +0x4c,0x323,0x8608,0x3c70,0xdc02,0x6c,0x323,0x8608,0x3c72,0xdc02,0x52,0x323,0x8608,0x3cb8,0xdc02,0x72, +0x323,0x8608,0x3cba,0xdc02,0x53,0x323,0x860e,0x3cd0,0xdc02,0x73,0x323,0x860e,0x3cd2,0xdc02,0x41,0x323, +0x604,0x3d58,0x860c,0x3d6c,0xdc02,0x61,0x323,0x604,0x3d5a,0x860c,0x3d6e,0xdc02,0x45,0x323,0x8604,0x3d8c, +0xdc02,0x65,0x323,0x8604,0x3d8e,0xdc02,0x4f,0x323,0x8604,0x3db0,0xdc02,0x6f,0x323,0x8604,0x3db2,0xe602, +0x3b1,0x313,0x600,0x3e05,0x602,0x3e09,0x684,0x3e0d,0x868a,0x3f00,0xe602,0x3b1,0x314,0x600,0x3e07,0x602, +0x3e0b,0x684,0x3e0f,0x868a,0x3f02,0x1f00,0xe643,0x3b1,0x313,0x300,0x868a,0x3f04,0x1f01,0xe643,0x3b1,0x314, +0x300,0x868a,0x3f06,0x1f00,0xe643,0x3b1,0x313,0x301,0x868a,0x3f08,0x1f01,0xe643,0x3b1,0x314,0x301,0x868a, +0x3f0a,0x1f00,0xe643,0x3b1,0x313,0x342,0x868a,0x3f0c,0x1f01,0xe643,0x3b1,0x314,0x342,0x868a,0x3f0e,0xe602, +0x391,0x313,0x600,0x3e15,0x602,0x3e19,0x684,0x3e1d,0x868a,0x3f10,0xe602,0x391,0x314,0x600,0x3e17,0x602, +0x3e1b,0x684,0x3e1f,0x868a,0x3f12,0x1f08,0xe643,0x391,0x313,0x300,0x868a,0x3f14,0x1f09,0xe643,0x391,0x314, +0x300,0x868a,0x3f16,0x1f08,0xe643,0x391,0x313,0x301,0x868a,0x3f18,0x1f09,0xe643,0x391,0x314,0x301,0x868a, +0x3f1a,0x1f08,0xe643,0x391,0x313,0x342,0x868a,0x3f1c,0x1f09,0xe643,0x391,0x314,0x342,0x868a,0x3f1e,0xe602, +0x3b5,0x313,0x600,0x3e24,0x8602,0x3e28,0xe602,0x3b5,0x314,0x600,0x3e26,0x8602,0x3e2a,0xe602,0x395,0x313, +0x600,0x3e34,0x8602,0x3e38,0xe602,0x395,0x314,0x600,0x3e36,0x8602,0x3e3a,0xe602,0x3b7,0x313,0x600,0x3e45, +0x602,0x3e49,0x684,0x3e4d,0x868a,0x3f20,0xe602,0x3b7,0x314,0x600,0x3e47,0x602,0x3e4b,0x684,0x3e4f,0x868a, +0x3f22,0x1f20,0xe643,0x3b7,0x313,0x300,0x868a,0x3f24,0x1f21,0xe643,0x3b7,0x314,0x300,0x868a,0x3f26,0x1f20, +0xe643,0x3b7,0x313,0x301,0x868a,0x3f28,0x1f21,0xe643,0x3b7,0x314,0x301,0x868a,0x3f2a,0x1f20,0xe643,0x3b7, +0x313,0x342,0x868a,0x3f2c,0x1f21,0xe643,0x3b7,0x314,0x342,0x868a,0x3f2e,0xe602,0x397,0x313,0x600,0x3e55, +0x602,0x3e59,0x684,0x3e5d,0x868a,0x3f30,0xe602,0x397,0x314,0x600,0x3e57,0x602,0x3e5b,0x684,0x3e5f,0x868a, +0x3f32,0x1f28,0xe643,0x397,0x313,0x300,0x868a,0x3f34,0x1f29,0xe643,0x397,0x314,0x300,0x868a,0x3f36,0x1f28, +0xe643,0x397,0x313,0x301,0x868a,0x3f38,0x1f29,0xe643,0x397,0x314,0x301,0x868a,0x3f3a,0x1f28,0xe643,0x397, +0x313,0x342,0x868a,0x3f3c,0x1f29,0xe643,0x397,0x314,0x342,0x868a,0x3f3e,0xe602,0x3b9,0x313,0x600,0x3e64, +0x602,0x3e68,0x8684,0x3e6c,0xe602,0x3b9,0x314,0x600,0x3e66,0x602,0x3e6a,0x8684,0x3e6e,0xe602,0x399,0x313, +0x600,0x3e74,0x602,0x3e78,0x8684,0x3e7c,0xe602,0x399,0x314,0x600,0x3e76,0x602,0x3e7a,0x8684,0x3e7e,0xe602, +0x3bf,0x313,0x600,0x3e84,0x8602,0x3e88,0xe602,0x3bf,0x314,0x600,0x3e86,0x8602,0x3e8a,0xe602,0x39f,0x313, +0x600,0x3e94,0x8602,0x3e98,0xe602,0x39f,0x314,0x600,0x3e96,0x8602,0x3e9a,0xe602,0x3c5,0x313,0x600,0x3ea4, +0x602,0x3ea8,0x8684,0x3eac,0xe602,0x3c5,0x314,0x600,0x3ea6,0x602,0x3eaa,0x8684,0x3eae,0xe602,0x3a5,0x314, +0x600,0x3eb6,0x602,0x3eba,0x8684,0x3ebe,0xe602,0x3c9,0x313,0x600,0x3ec5,0x602,0x3ec9,0x684,0x3ecd,0x868a, +0x3f40,0xe602,0x3c9,0x314,0x600,0x3ec7,0x602,0x3ecb,0x684,0x3ecf,0x868a,0x3f42,0x1f60,0xe643,0x3c9,0x313, +0x300,0x868a,0x3f44,0x1f61,0xe643,0x3c9,0x314,0x300,0x868a,0x3f46,0x1f60,0xe643,0x3c9,0x313,0x301,0x868a, +0x3f48,0x1f61,0xe643,0x3c9,0x314,0x301,0x868a,0x3f4a,0x1f60,0xe643,0x3c9,0x313,0x342,0x868a,0x3f4c,0x1f61, +0xe643,0x3c9,0x314,0x342,0x868a,0x3f4e,0xe602,0x3a9,0x313,0x600,0x3ed5,0x602,0x3ed9,0x684,0x3edd,0x868a, +0x3f50,0xe602,0x3a9,0x314,0x600,0x3ed7,0x602,0x3edb,0x684,0x3edf,0x868a,0x3f52,0x1f68,0xe643,0x3a9,0x313, +0x300,0x868a,0x3f54,0x1f69,0xe643,0x3a9,0x314,0x300,0x868a,0x3f56,0x1f68,0xe643,0x3a9,0x313,0x301,0x868a, +0x3f58,0x1f69,0xe643,0x3a9,0x314,0x301,0x868a,0x3f5a,0x1f68,0xe643,0x3a9,0x313,0x342,0x868a,0x3f5c,0x1f69, +0xe643,0x3a9,0x314,0x342,0x868a,0x3f5e,0xe602,0x3b1,0x300,0x868a,0x3f64,0xe602,0x3b7,0x300,0x868a,0x3f84, +0xe602,0x3c9,0x300,0x868a,0x3fe4,0xe602,0x3b1,0x342,0x868a,0x3f6e,0xe602,0x3b7,0x342,0x868a,0x3f8e,0xe602, +0x3c9,0x342,0x868a,0x3fee,3,0xe602,0x41,0x300,0xe602,0x41,0x301,0xe602,0x41,0x303,0xe602,0x45, +0x300,0xe602,0x45,0x301,0xe602,0x45,0x308,0xe602,0x49,0x300,0xe602,0x49,0x301,0xe602,0x49,0x302, +0xe602,0x4e,0x303,0xe602,0x4f,0x300,0xe602,0x4f,0x301,0xe602,0x55,0x300,0xe602,0x55,0x301,0xe602, +0x55,0x302,0xe602,0x59,0x301,0xe602,0x61,0x300,0xe602,0x61,0x301,0xe602,0x61,0x303,0xe602,0x65, +0x300,0xe602,0x65,0x301,0xe602,0x65,0x308,0xe602,0x69,0x300,0xe602,0x69,0x301,0xe602,0x69,0x302, +0xe602,0x6e,0x303,0xe602,0x6f,0x300,0xe602,0x6f,0x301,0xe602,0x75,0x300,0xe602,0x75,0x301,0xe602, +0x75,0x302,0xe602,0x79,0x301,0xe602,0x79,0x308,0xe602,0x41,0x304,0xe602,0x61,0x304,0xca02,0x41, +0x328,0xca02,0x61,0x328,0xe602,0x43,0x301,0xe602,0x63,0x301,0xe602,0x43,0x302,0xe602,0x63,0x302, +0xe602,0x43,0x307,0xe602,0x63,0x307,0xe602,0x43,0x30c,0xe602,0x63,0x30c,0xe602,0x44,0x30c,0xe602, +0x64,0x30c,0xe602,0x45,0x306,0xe602,0x65,0x306,0xe602,0x45,0x307,0xe602,0x65,0x307,0xca02,0x45, +0x328,0xca02,0x65,0x328,0xe602,0x45,0x30c,0xe602,0x65,0x30c,0xe602,0x47,0x302,0xe602,0x67,0x302, +0xe602,0x47,0x306,0xe602,0x67,0x306,0xe602,0x47,0x307,0xe602,0x67,0x307,0xca02,0x47,0x327,0xca02, +0x67,0x327,0xe602,0x48,0x302,0xe602,0x68,0x302,0xe602,0x49,0x303,0xe602,0x69,0x303,0xe602,0x49, +0x304,0xe602,0x69,0x304,0xe602,0x49,0x306,0xe602,0x69,0x306,0xca02,0x49,0x328,0xca02,0x69,0x328, +0xe602,0x49,0x307,0xe602,0x4a,0x302,0xe602,0x6a,0x302,0xca02,0x4b,0x327,0xca02,0x6b,0x327,0xe602, +0x4c,0x301,0xe602,0x6c,0x301,0xca02,0x4c,0x327,0xca02,0x6c,0x327,0xe602,0x4c,0x30c,0xe602,0x6c, +0x30c,0xe602,0x4e,0x301,0xe602,0x6e,0x301,0xca02,0x4e,0x327,0xca02,0x6e,0x327,0xe602,0x4e,0x30c, +0xe602,0x6e,0x30c,0xe602,0x4f,0x306,0xe602,0x6f,0x306,0xe602,0x4f,0x30b,0xe602,0x6f,0x30b,0xe602, +0x52,0x301,0xe602,0x72,0x301,0xca02,0x52,0x327,0xca02,0x72,0x327,0xe602,0x52,0x30c,0xe602,0x72, +0x30c,0xe602,0x53,0x302,0xe602,0x73,0x302,0xca02,0x53,0x327,0xca02,0x73,0x327,0xca02,0x54,0x327, +0xca02,0x74,0x327,0xe602,0x54,0x30c,0xe602,0x74,0x30c,0xe602,0x55,0x306,0xe602,0x75,0x306,0xe602, +0x55,0x30a,0xe602,0x75,0x30a,0xe602,0x55,0x30b,0xe602,0x75,0x30b,0xca02,0x55,0x328,0xca02,0x75, +0x328,0xe602,0x57,0x302,0xe602,0x77,0x302,0xe602,0x59,0x302,0xe602,0x79,0x302,0xe602,0x59,0x308, +0xe602,0x5a,0x301,0xe602,0x7a,0x301,0xe602,0x5a,0x307,0xe602,0x7a,0x307,0xe602,0x5a,0x30c,0xe602, +0x7a,0x30c,0xe602,0x41,0x30c,0xe602,0x61,0x30c,0xe602,0x49,0x30c,0xe602,0x69,0x30c,0xe602,0x4f, +0x30c,0xe602,0x6f,0x30c,0xe602,0x55,0x30c,0xe602,0x75,0x30c,0xdc,0xe643,0x55,0x308,0x304,0xfc, +0xe643,0x75,0x308,0x304,0xdc,0xe643,0x55,0x308,0x301,0xfc,0xe643,0x75,0x308,0x301,0xdc,0xe643, +0x55,0x308,0x30c,0xfc,0xe643,0x75,0x308,0x30c,0xdc,0xe643,0x55,0x308,0x300,0xfc,0xe643,0x75, +0x308,0x300,0xc4,0xe643,0x41,0x308,0x304,0xe4,0xe643,0x61,0x308,0x304,0x226,0xe643,0x41,0x307, +0x304,0x227,0xe643,0x61,0x307,0x304,0xe602,0xc6,0x304,0xe602,0xe6,0x304,0xe602,0x47,0x30c,0xe602, +0x67,0x30c,0xe602,0x4b,0x30c,0xe602,0x6b,0x30c,0x1ea,0xe643,0x4f,0x328,0x304,0x1eb,0xe643,0x6f, +0x328,0x304,0xe602,0x1b7,0x30c,0xe602,0x292,0x30c,0xe602,0x6a,0x30c,0xe602,0x47,0x301,0xe602,0x67, +0x301,0xe602,0x4e,0x300,0xe602,0x6e,0x300,0xc5,0xe643,0x41,0x30a,0x301,0xe5,0xe643,0x61,0x30a, +0x301,0xe602,0xc6,0x301,0xe602,0xe6,0x301,0xe602,0xd8,0x301,0xe602,0xf8,0x301,0xe602,0x41,0x30f, +0xe602,0x61,0x30f,0xe602,0x41,0x311,0xe602,0x61,0x311,0xe602,0x45,0x30f,0xe602,0x65,0x30f,0xe602, +0x45,0x311,0xe602,0x65,0x311,0xe602,0x49,0x30f,0xe602,0x69,0x30f,0xe602,0x49,0x311,0xe602,0x69, +0x311,0xe602,0x4f,0x30f,0xe602,0x6f,0x30f,0xe602,0x4f,0x311,0xe602,0x6f,0x311,0xe602,0x52,0x30f, +0xe602,0x72,0x30f,0xe602,0x52,0x311,0xe602,0x72,0x311,0xe602,0x55,0x30f,0xe602,0x75,0x30f,0xe602, +0x55,0x311,0xe602,0x75,0x311,0xdc02,0x53,0x326,0xdc02,0x73,0x326,0xdc02,0x54,0x326,0xdc02,0x74, +0x326,0xe602,0x48,0x30c,0xe602,0x68,0x30c,0xd6,0xe643,0x4f,0x308,0x304,0xf6,0xe643,0x6f,0x308, +0x304,0xd5,0xe643,0x4f,0x303,0x304,0xf5,0xe643,0x6f,0x303,0x304,0x22e,0xe643,0x4f,0x307,0x304, +0x22f,0xe643,0x6f,0x307,0x304,0xe602,0x59,0x304,0xe602,0x79,0x304,0xe602,0xa8,0x301,0xe602,0x391, +0x301,0xe602,0x395,0x301,0xe602,0x397,0x301,0xe602,0x399,0x301,0xe602,0x39f,0x301,0xe602,0x3a5,0x301, +0xe602,0x3a9,0x301,0x3ca,0xe643,0x3b9,0x308,0x301,0xe602,0x399,0x308,0xe602,0x3a5,0x308,0xe602,0x3b5, +0x301,0xe602,0x3b9,0x301,0x3cb,0xe643,0x3c5,0x308,0x301,0xe602,0x3bf,0x301,0xe602,0x3c5,0x301,0xe602, +0x3d2,0x301,0xe602,0x3d2,0x308,0xe602,0x415,0x300,0xe602,0x415,0x308,0xe602,0x413,0x301,0xe602,0x406, +0x308,0xe602,0x41a,0x301,0xe602,0x418,0x300,0xe602,0x423,0x306,0xe602,0x418,0x306,0xe602,0x438,0x306, +0xe602,0x435,0x300,0xe602,0x435,0x308,0xe602,0x433,0x301,0xe602,0x456,0x308,0xe602,0x43a,0x301,0xe602, +0x438,0x300,0xe602,0x443,0x306,0xe602,0x474,0x30f,0xe602,0x475,0x30f,0xe602,0x416,0x306,0xe602,0x436, +0x306,0xe602,0x410,0x306,0xe602,0x430,0x306,0xe602,0x410,0x308,0xe602,0x430,0x308,0xe602,0x415,0x306, +0xe602,0x435,0x306,0xe602,0x4d8,0x308,0xe602,0x4d9,0x308,0xe602,0x416,0x308,0xe602,0x436,0x308,0xe602, +0x417,0x308,0xe602,0x437,0x308,0xe602,0x418,0x304,0xe602,0x438,0x304,0xe602,0x418,0x308,0xe602,0x438, +0x308,0xe602,0x41e,0x308,0xe602,0x43e,0x308,0xe602,0x4e8,0x308,0xe602,0x4e9,0x308,0xe602,0x42d,0x308, +0xe602,0x44d,0x308,0xe602,0x423,0x304,0xe602,0x443,0x304,0xe602,0x423,0x308,0xe602,0x443,0x308,0xe602, +0x423,0x30b,0xe602,0x443,0x30b,0xe602,0x427,0x308,0xe602,0x447,0x308,0xe602,0x42b,0x308,0xe602,0x44b, +0x308,0xe602,0x627,0x653,0xe602,0x627,0x654,0xe602,0x648,0x654,0xdc02,0x627,0x655,0xe602,0x64a,0x654, +0xe602,0x6d5,0x654,0xe602,0x6c1,0x654,0xe602,0x6d2,0x654,0x702,0x928,0x93c,0x702,0x930,0x93c,0x702, +0x933,0x93c,2,0x9c7,0x9be,2,0x9c7,0x9d7,2,0xb47,0xb56,2,0xb47,0xb3e,2,0xb47, +0xb57,2,0xb92,0xbd7,2,0xbc6,0xbbe,2,0xbc7,0xbbe,2,0xbc6,0xbd7,0x5b02,0xc46,0xc56, +2,0xcbf,0xcd5,2,0xcc6,0xcd5,2,0xcc6,0xcd6,0xcca,0x43,0xcc6,0xcc2,0xcd5,2,0xd46, +0xd3e,2,0xd47,0xd3e,2,0xd46,0xd57,0x902,0xdd9,0xdca,0xddc,0x943,0xdd9,0xdcf,0xdca,2, +0xdd9,0xddf,2,0x1025,0x102e,2,0x1b05,0x1b35,2,0x1b07,0x1b35,2,0x1b09,0x1b35,2,0x1b0b, +0x1b35,2,0x1b0d,0x1b35,2,0x1b11,0x1b35,2,0x1b3a,0x1b35,2,0x1b3c,0x1b35,2,0x1b3e,0x1b35, +2,0x1b3f,0x1b35,2,0x1b42,0x1b35,0xdc02,0x41,0x325,0xdc02,0x61,0x325,0xe602,0x42,0x307,0xe602, +0x62,0x307,0xdc02,0x42,0x323,0xdc02,0x62,0x323,0xdc02,0x42,0x331,0xdc02,0x62,0x331,0xc7,0xe643, +0x43,0x327,0x301,0xe7,0xe643,0x63,0x327,0x301,0xe602,0x44,0x307,0xe602,0x64,0x307,0xdc02,0x44, +0x323,0xdc02,0x64,0x323,0xdc02,0x44,0x331,0xdc02,0x64,0x331,0xca02,0x44,0x327,0xca02,0x64,0x327, +0xdc02,0x44,0x32d,0xdc02,0x64,0x32d,0x112,0xe643,0x45,0x304,0x300,0x113,0xe643,0x65,0x304,0x300, +0x112,0xe643,0x45,0x304,0x301,0x113,0xe643,0x65,0x304,0x301,0xdc02,0x45,0x32d,0xdc02,0x65,0x32d, +0xdc02,0x45,0x330,0xdc02,0x65,0x330,0x228,0xe643,0x45,0x327,0x306,0x229,0xe643,0x65,0x327,0x306, +0xe602,0x46,0x307,0xe602,0x66,0x307,0xe602,0x47,0x304,0xe602,0x67,0x304,0xe602,0x48,0x307,0xe602, +0x68,0x307,0xdc02,0x48,0x323,0xdc02,0x68,0x323,0xe602,0x48,0x308,0xe602,0x68,0x308,0xca02,0x48, +0x327,0xca02,0x68,0x327,0xdc02,0x48,0x32e,0xdc02,0x68,0x32e,0xdc02,0x49,0x330,0xdc02,0x69,0x330, +0xcf,0xe643,0x49,0x308,0x301,0xef,0xe643,0x69,0x308,0x301,0xe602,0x4b,0x301,0xe602,0x6b,0x301, +0xdc02,0x4b,0x323,0xdc02,0x6b,0x323,0xdc02,0x4b,0x331,0xdc02,0x6b,0x331,0x1e36,0xe643,0x4c,0x323, +0x304,0x1e37,0xe643,0x6c,0x323,0x304,0xdc02,0x4c,0x331,0xdc02,0x6c,0x331,0xdc02,0x4c,0x32d,0xdc02, +0x6c,0x32d,0xe602,0x4d,0x301,0xe602,0x6d,0x301,0xe602,0x4d,0x307,0xe602,0x6d,0x307,0xdc02,0x4d, +0x323,0xdc02,0x6d,0x323,0xe602,0x4e,0x307,0xe602,0x6e,0x307,0xdc02,0x4e,0x323,0xdc02,0x6e,0x323, +0xdc02,0x4e,0x331,0xdc02,0x6e,0x331,0xdc02,0x4e,0x32d,0xdc02,0x6e,0x32d,0xd5,0xe643,0x4f,0x303, +0x301,0xf5,0xe643,0x6f,0x303,0x301,0xd5,0xe643,0x4f,0x303,0x308,0xf5,0xe643,0x6f,0x303,0x308, +0x14c,0xe643,0x4f,0x304,0x300,0x14d,0xe643,0x6f,0x304,0x300,0x14c,0xe643,0x4f,0x304,0x301,0x14d, +0xe643,0x6f,0x304,0x301,0xe602,0x50,0x301,0xe602,0x70,0x301,0xe602,0x50,0x307,0xe602,0x70,0x307, +0xe602,0x52,0x307,0xe602,0x72,0x307,0x1e5a,0xe643,0x52,0x323,0x304,0x1e5b,0xe643,0x72,0x323,0x304, +0xdc02,0x52,0x331,0xdc02,0x72,0x331,0xe602,0x53,0x307,0xe602,0x73,0x307,0x15a,0xe643,0x53,0x301, +0x307,0x15b,0xe643,0x73,0x301,0x307,0x160,0xe643,0x53,0x30c,0x307,0x161,0xe643,0x73,0x30c,0x307, +0x1e62,0xe643,0x53,0x323,0x307,0x1e63,0xe643,0x73,0x323,0x307,0xe602,0x54,0x307,0xe602,0x74,0x307, +0xdc02,0x54,0x323,0xdc02,0x74,0x323,0xdc02,0x54,0x331,0xdc02,0x74,0x331,0xdc02,0x54,0x32d,0xdc02, +0x74,0x32d,0xdc02,0x55,0x324,0xdc02,0x75,0x324,0xdc02,0x55,0x330,0xdc02,0x75,0x330,0xdc02,0x55, +0x32d,0xdc02,0x75,0x32d,0x168,0xe643,0x55,0x303,0x301,0x169,0xe643,0x75,0x303,0x301,0x16a,0xe643, +0x55,0x304,0x308,0x16b,0xe643,0x75,0x304,0x308,0xe602,0x56,0x303,0xe602,0x76,0x303,0xdc02,0x56, +0x323,0xdc02,0x76,0x323,0xe602,0x57,0x300,0xe602,0x77,0x300,0xe602,0x57,0x301,0xe602,0x77,0x301, +0xe602,0x57,0x308,0xe602,0x77,0x308,0xe602,0x57,0x307,0xe602,0x77,0x307,0xdc02,0x57,0x323,0xdc02, +0x77,0x323,0xe602,0x58,0x307,0xe602,0x78,0x307,0xe602,0x58,0x308,0xe602,0x78,0x308,0xe602,0x59, +0x307,0xe602,0x79,0x307,0xe602,0x5a,0x302,0xe602,0x7a,0x302,0xdc02,0x5a,0x323,0xdc02,0x7a,0x323, +0xdc02,0x5a,0x331,0xdc02,0x7a,0x331,0xdc02,0x68,0x331,0xe602,0x74,0x308,0xe602,0x77,0x30a,0xe602, +0x79,0x30a,0xe602,0x17f,0x307,0xe602,0x41,0x309,0xe602,0x61,0x309,0xc2,0xe643,0x41,0x302,0x301, +0xe2,0xe643,0x61,0x302,0x301,0xc2,0xe643,0x41,0x302,0x300,0xe2,0xe643,0x61,0x302,0x300,0xc2, +0xe643,0x41,0x302,0x309,0xe2,0xe643,0x61,0x302,0x309,0xc2,0xe643,0x41,0x302,0x303,0xe2,0xe643, +0x61,0x302,0x303,0x1ea0,0xe643,0x41,0x323,0x302,0x1ea1,0xe643,0x61,0x323,0x302,0x102,0xe643,0x41, +0x306,0x301,0x103,0xe643,0x61,0x306,0x301,0x102,0xe643,0x41,0x306,0x300,0x103,0xe643,0x61,0x306, +0x300,0x102,0xe643,0x41,0x306,0x309,0x103,0xe643,0x61,0x306,0x309,0x102,0xe643,0x41,0x306,0x303, +0x103,0xe643,0x61,0x306,0x303,0x1ea0,0xe643,0x41,0x323,0x306,0x1ea1,0xe643,0x61,0x323,0x306,0xe602, +0x45,0x309,0xe602,0x65,0x309,0xe602,0x45,0x303,0xe602,0x65,0x303,0xca,0xe643,0x45,0x302,0x301, +0xea,0xe643,0x65,0x302,0x301,0xca,0xe643,0x45,0x302,0x300,0xea,0xe643,0x65,0x302,0x300,0xca, +0xe643,0x45,0x302,0x309,0xea,0xe643,0x65,0x302,0x309,0xca,0xe643,0x45,0x302,0x303,0xea,0xe643, +0x65,0x302,0x303,0x1eb8,0xe643,0x45,0x323,0x302,0x1eb9,0xe643,0x65,0x323,0x302,0xe602,0x49,0x309, +0xe602,0x69,0x309,0xdc02,0x49,0x323,0xdc02,0x69,0x323,0xe602,0x4f,0x309,0xe602,0x6f,0x309,0xd4, +0xe643,0x4f,0x302,0x301,0xf4,0xe643,0x6f,0x302,0x301,0xd4,0xe643,0x4f,0x302,0x300,0xf4,0xe643, +0x6f,0x302,0x300,0xd4,0xe643,0x4f,0x302,0x309,0xf4,0xe643,0x6f,0x302,0x309,0xd4,0xe643,0x4f, +0x302,0x303,0xf4,0xe643,0x6f,0x302,0x303,0x1ecc,0xe643,0x4f,0x323,0x302,0x1ecd,0xe643,0x6f,0x323, +0x302,0x1a0,0xe643,0x4f,0x31b,0x301,0x1a1,0xe643,0x6f,0x31b,0x301,0x1a0,0xe643,0x4f,0x31b,0x300, +0x1a1,0xe643,0x6f,0x31b,0x300,0x1a0,0xe643,0x4f,0x31b,0x309,0x1a1,0xe643,0x6f,0x31b,0x309,0x1a0, +0xe643,0x4f,0x31b,0x303,0x1a1,0xe643,0x6f,0x31b,0x303,0x1a0,0xdc43,0x4f,0x31b,0x323,0x1a1,0xdc43, +0x6f,0x31b,0x323,0xdc02,0x55,0x323,0xdc02,0x75,0x323,0xe602,0x55,0x309,0xe602,0x75,0x309,0x1af, +0xe643,0x55,0x31b,0x301,0x1b0,0xe643,0x75,0x31b,0x301,0x1af,0xe643,0x55,0x31b,0x300,0x1b0,0xe643, +0x75,0x31b,0x300,0x1af,0xe643,0x55,0x31b,0x309,0x1b0,0xe643,0x75,0x31b,0x309,0x1af,0xe643,0x55, +0x31b,0x303,0x1b0,0xe643,0x75,0x31b,0x303,0x1af,0xdc43,0x55,0x31b,0x323,0x1b0,0xdc43,0x75,0x31b, +0x323,0xe602,0x59,0x300,0xe602,0x79,0x300,0xdc02,0x59,0x323,0xdc02,0x79,0x323,0xe602,0x59,0x309, +0xe602,0x79,0x309,0xe602,0x59,0x303,0xe602,0x79,0x303,0x1f10,0xe643,0x3b5,0x313,0x300,0x1f11,0xe643, +0x3b5,0x314,0x300,0x1f10,0xe643,0x3b5,0x313,0x301,0x1f11,0xe643,0x3b5,0x314,0x301,0x1f18,0xe643,0x395, +0x313,0x300,0x1f19,0xe643,0x395,0x314,0x300,0x1f18,0xe643,0x395,0x313,0x301,0x1f19,0xe643,0x395,0x314, +0x301,0x1f30,0xe643,0x3b9,0x313,0x300,0x1f31,0xe643,0x3b9,0x314,0x300,0x1f30,0xe643,0x3b9,0x313,0x301, +0x1f31,0xe643,0x3b9,0x314,0x301,0x1f30,0xe643,0x3b9,0x313,0x342,0x1f31,0xe643,0x3b9,0x314,0x342,0x1f38, +0xe643,0x399,0x313,0x300,0x1f39,0xe643,0x399,0x314,0x300,0x1f38,0xe643,0x399,0x313,0x301,0x1f39,0xe643, +0x399,0x314,0x301,0x1f38,0xe643,0x399,0x313,0x342,0x1f39,0xe643,0x399,0x314,0x342,0x1f40,0xe643,0x3bf, +0x313,0x300,0x1f41,0xe643,0x3bf,0x314,0x300,0x1f40,0xe643,0x3bf,0x313,0x301,0x1f41,0xe643,0x3bf,0x314, +0x301,0x1f48,0xe643,0x39f,0x313,0x300,0x1f49,0xe643,0x39f,0x314,0x300,0x1f48,0xe643,0x39f,0x313,0x301, +0x1f49,0xe643,0x39f,0x314,0x301,0x1f50,0xe643,0x3c5,0x313,0x300,0x1f51,0xe643,0x3c5,0x314,0x300,0x1f50, +0xe643,0x3c5,0x313,0x301,0x1f51,0xe643,0x3c5,0x314,0x301,0x1f50,0xe643,0x3c5,0x313,0x342,0x1f51,0xe643, +0x3c5,0x314,0x342,0x1f59,0xe643,0x3a5,0x314,0x300,0x1f59,0xe643,0x3a5,0x314,0x301,0x1f59,0xe643,0x3a5, +0x314,0x342,0xe602,0x3b5,0x300,0xe602,0x3b9,0x300,0xe602,0x3bf,0x300,0xe602,0x3c5,0x300,0x1f00,0xf043, +0x3b1,0x313,0x345,0x1f01,0xf043,0x3b1,0x314,0x345,0x1f02,0x345,2,0xf044,0x3b1,0x313,0x300,0x345, +0x1f03,0x345,2,0xf044,0x3b1,0x314,0x300,0x345,0x1f04,0x345,2,0xf044,0x3b1,0x313,0x301,0x345, +0x1f05,0x345,2,0xf044,0x3b1,0x314,0x301,0x345,0x1f06,0x345,2,0xf044,0x3b1,0x313,0x342,0x345, +0x1f07,0x345,2,0xf044,0x3b1,0x314,0x342,0x345,0x1f08,0xf043,0x391,0x313,0x345,0x1f09,0xf043,0x391, +0x314,0x345,0x1f0a,0x345,2,0xf044,0x391,0x313,0x300,0x345,0x1f0b,0x345,2,0xf044,0x391,0x314, +0x300,0x345,0x1f0c,0x345,2,0xf044,0x391,0x313,0x301,0x345,0x1f0d,0x345,2,0xf044,0x391,0x314, +0x301,0x345,0x1f0e,0x345,2,0xf044,0x391,0x313,0x342,0x345,0x1f0f,0x345,2,0xf044,0x391,0x314, +0x342,0x345,0x1f20,0xf043,0x3b7,0x313,0x345,0x1f21,0xf043,0x3b7,0x314,0x345,0x1f22,0x345,2,0xf044, +0x3b7,0x313,0x300,0x345,0x1f23,0x345,2,0xf044,0x3b7,0x314,0x300,0x345,0x1f24,0x345,2,0xf044, +0x3b7,0x313,0x301,0x345,0x1f25,0x345,2,0xf044,0x3b7,0x314,0x301,0x345,0x1f26,0x345,2,0xf044, +0x3b7,0x313,0x342,0x345,0x1f27,0x345,2,0xf044,0x3b7,0x314,0x342,0x345,0x1f28,0xf043,0x397,0x313, +0x345,0x1f29,0xf043,0x397,0x314,0x345,0x1f2a,0x345,2,0xf044,0x397,0x313,0x300,0x345,0x1f2b,0x345, +2,0xf044,0x397,0x314,0x300,0x345,0x1f2c,0x345,2,0xf044,0x397,0x313,0x301,0x345,0x1f2d,0x345, +2,0xf044,0x397,0x314,0x301,0x345,0x1f2e,0x345,2,0xf044,0x397,0x313,0x342,0x345,0x1f2f,0x345, +2,0xf044,0x397,0x314,0x342,0x345,0x1f60,0xf043,0x3c9,0x313,0x345,0x1f61,0xf043,0x3c9,0x314,0x345, +0x1f62,0x345,2,0xf044,0x3c9,0x313,0x300,0x345,0x1f63,0x345,2,0xf044,0x3c9,0x314,0x300,0x345, +0x1f64,0x345,2,0xf044,0x3c9,0x313,0x301,0x345,0x1f65,0x345,2,0xf044,0x3c9,0x314,0x301,0x345, +0x1f66,0x345,2,0xf044,0x3c9,0x313,0x342,0x345,0x1f67,0x345,2,0xf044,0x3c9,0x314,0x342,0x345, +0x1f68,0xf043,0x3a9,0x313,0x345,0x1f69,0xf043,0x3a9,0x314,0x345,0x1f6a,0x345,2,0xf044,0x3a9,0x313, +0x300,0x345,0x1f6b,0x345,2,0xf044,0x3a9,0x314,0x300,0x345,0x1f6c,0x345,2,0xf044,0x3a9,0x313, +0x301,0x345,0x1f6d,0x345,2,0xf044,0x3a9,0x314,0x301,0x345,0x1f6e,0x345,2,0xf044,0x3a9,0x313, +0x342,0x345,0x1f6f,0x345,2,0xf044,0x3a9,0x314,0x342,0x345,0xe602,0x3b1,0x306,0xe602,0x3b1,0x304, +0x1f70,0xf043,0x3b1,0x300,0x345,0xf002,0x3b1,0x345,0x3ac,0xf043,0x3b1,0x301,0x345,0x1fb6,0xf043,0x3b1, +0x342,0x345,0xe602,0x391,0x306,0xe602,0x391,0x304,0xe602,0x391,0x300,0xf002,0x391,0x345,0xe602,0xa8, +0x342,0x1f74,0xf043,0x3b7,0x300,0x345,0xf002,0x3b7,0x345,0x3ae,0xf043,0x3b7,0x301,0x345,0x1fc6,0xf043, +0x3b7,0x342,0x345,0xe602,0x395,0x300,0xe602,0x397,0x300,0xf002,0x397,0x345,0xe602,0x1fbf,0x300,0xe602, +0x1fbf,0x301,0xe602,0x1fbf,0x342,0xe602,0x3b9,0x306,0xe602,0x3b9,0x304,0x3ca,0xe643,0x3b9,0x308,0x300, +0xe602,0x3b9,0x342,0x3ca,0xe643,0x3b9,0x308,0x342,0xe602,0x399,0x306,0xe602,0x399,0x304,0xe602,0x399, +0x300,0xe602,0x1ffe,0x300,0xe602,0x1ffe,0x301,0xe602,0x1ffe,0x342,0xe602,0x3c5,0x306,0xe602,0x3c5,0x304, +0x3cb,0xe643,0x3c5,0x308,0x300,0xe602,0x3c1,0x313,0xe602,0x3c1,0x314,0xe602,0x3c5,0x342,0x3cb,0xe643, +0x3c5,0x308,0x342,0xe602,0x3a5,0x306,0xe602,0x3a5,0x304,0xe602,0x3a5,0x300,0xe602,0x3a1,0x314,0xe602, +0xa8,0x300,0x1f7c,0xf043,0x3c9,0x300,0x345,0xf002,0x3c9,0x345,0x3ce,0xf043,0x3c9,0x301,0x345,0x1ff6, +0xf043,0x3c9,0x342,0x345,0xe602,0x39f,0x300,0xe602,0x3a9,0x300,0xf002,0x3a9,0x345,0x102,0x2190,0x338, +0x102,0x2192,0x338,0x102,0x2194,0x338,0x102,0x21d0,0x338,0x102,0x21d4,0x338,0x102,0x21d2,0x338,0x102, +0x2203,0x338,0x102,0x2208,0x338,0x102,0x220b,0x338,0x102,0x2223,0x338,0x102,0x2225,0x338,0x102,0x223c, +0x338,0x102,0x2243,0x338,0x102,0x2245,0x338,0x102,0x2248,0x338,0x102,0x3d,0x338,0x102,0x2261,0x338, +0x102,0x224d,0x338,0x102,0x3c,0x338,0x102,0x3e,0x338,0x102,0x2264,0x338,0x102,0x2265,0x338,0x102, +0x2272,0x338,0x102,0x2273,0x338,0x102,0x2276,0x338,0x102,0x2277,0x338,0x102,0x227a,0x338,0x102,0x227b, +0x338,0x102,0x2282,0x338,0x102,0x2283,0x338,0x102,0x2286,0x338,0x102,0x2287,0x338,0x102,0x22a2,0x338, +0x102,0x22a8,0x338,0x102,0x22a9,0x338,0x102,0x22ab,0x338,0x102,0x227c,0x338,0x102,0x227d,0x338,0x102, +0x2291,0x338,0x102,0x2292,0x338,0x102,0x22b2,0x338,0x102,0x22b3,0x338,0x102,0x22b4,0x338,0x102,0x22b5, +0x338,0x802,0x304b,0x3099,0x802,0x304d,0x3099,0x802,0x304f,0x3099,0x802,0x3051,0x3099,0x802,0x3053,0x3099, +0x802,0x3055,0x3099,0x802,0x3057,0x3099,0x802,0x3059,0x3099,0x802,0x305b,0x3099,0x802,0x305d,0x3099,0x802, +0x305f,0x3099,0x802,0x3061,0x3099,0x802,0x3064,0x3099,0x802,0x3066,0x3099,0x802,0x3068,0x3099,0x802,0x306f, +0x3099,0x802,0x306f,0x309a,0x802,0x3072,0x3099,0x802,0x3072,0x309a,0x802,0x3075,0x3099,0x802,0x3075,0x309a, +0x802,0x3078,0x3099,0x802,0x3078,0x309a,0x802,0x307b,0x3099,0x802,0x307b,0x309a,0x802,0x3046,0x3099,0x802, +0x309d,0x3099,0x802,0x30ab,0x3099,0x802,0x30ad,0x3099,0x802,0x30af,0x3099,0x802,0x30b1,0x3099,0x802,0x30b3, +0x3099,0x802,0x30b5,0x3099,0x802,0x30b7,0x3099,0x802,0x30b9,0x3099,0x802,0x30bb,0x3099,0x802,0x30bd,0x3099, +0x802,0x30bf,0x3099,0x802,0x30c1,0x3099,0x802,0x30c4,0x3099,0x802,0x30c6,0x3099,0x802,0x30c8,0x3099,0x802, +0x30cf,0x3099,0x802,0x30cf,0x309a,0x802,0x30d2,0x3099,0x802,0x30d2,0x309a,0x802,0x30d5,0x3099,0x802,0x30d5, +0x309a,0x802,0x30d8,0x3099,0x802,0x30d8,0x309a,0x802,0x30db,0x3099,0x802,0x30db,0x309a,0x802,0x30a6,0x3099, +0x802,0x30ef,0x3099,0x802,0x30f0,0x3099,0x802,0x30f1,0x3099,0x802,0x30f2,0x3099,0x802,0x30fd,0x3099,0x704, +0xd804,0xdc99,0xd804,0xdcba,0x704,0xd804,0xdc9b,0xd804,0xdcba,0x704,0xd804,0xdca5,0xd804,0xdcba,4,0xd804, +0xdd31,0xd804,0xdd27,4,0xd804,0xdd32,0xd804,0xdd27,4,0xd804,0xdf47,0xd804,0xdf3e,4,0xd804,0xdf47, +0xd804,0xdf57,4,0xd805,0xdcb9,0xd805,0xdcba,4,0xd805,0xdcb9,0xd805,0xdcb0,4,0xd805,0xdcb9,0xd805, +0xdcbd,4,0xd805,0xddb8,0xd805,0xddaf,4,0xd805,0xddb9,0xd805,0xddaf,4,0xd806,0xdd35,0xd806,0xdd30, +1,0x2b9,1,0x3b,1,0xb7,0x702,0x915,0x93c,0x702,0x916,0x93c,0x702,0x917,0x93c,0x702, +0x91c,0x93c,0x702,0x921,0x93c,0x702,0x922,0x93c,0x702,0x92b,0x93c,0x702,0x92f,0x93c,0x702,0x9a1, +0x9bc,0x702,0x9a2,0x9bc,0x702,0x9af,0x9bc,0x702,0xa32,0xa3c,0x702,0xa38,0xa3c,0x702,0xa16,0xa3c, +0x702,0xa17,0xa3c,0x702,0xa1c,0xa3c,0x702,0xa2b,0xa3c,0x702,0xb21,0xb3c,0x702,0xb22,0xb3c,2, +0xf42,0xfb7,2,0xf4c,0xfb7,2,0xf51,0xfb7,2,0xf56,0xfb7,2,0xf5b,0xfb7,2,0xf40, +0xfb5,0x8202,0xfb2,0xf80,0x8202,0xfb3,0xf80,2,0xf92,0xfb7,2,0xf9c,0xfb7,2,0xfa1,0xfb7, +2,0xfa6,0xfb7,2,0xfab,0xfb7,2,0xf90,0xfb5,1,0x3b9,1,0x60,1,0xb4,1, +0x3a9,1,0x4b,1,0x3008,1,0x3009,0x102,0x2add,0x338,1,0x8c48,1,0x66f4,1,0x8eca, +1,0x8cc8,1,0x6ed1,1,0x4e32,1,0x53e5,1,0x9f9c,1,0x5951,1,0x91d1,1,0x5587, +1,0x5948,1,0x61f6,1,0x7669,1,0x7f85,1,0x863f,1,0x87ba,1,0x88f8,1,0x908f, +1,0x6a02,1,0x6d1b,1,0x70d9,1,0x73de,1,0x843d,1,0x916a,1,0x99f1,1,0x4e82, +1,0x5375,1,0x6b04,1,0x721b,1,0x862d,1,0x9e1e,1,0x5d50,1,0x6feb,1,0x85cd, +1,0x8964,1,0x62c9,1,0x81d8,1,0x881f,1,0x5eca,1,0x6717,1,0x6d6a,1,0x72fc, +1,0x90ce,1,0x4f86,1,0x51b7,1,0x52de,1,0x64c4,1,0x6ad3,1,0x7210,1,0x76e7, +1,0x8001,1,0x8606,1,0x865c,1,0x8def,1,0x9732,1,0x9b6f,1,0x9dfa,1,0x788c, +1,0x797f,1,0x7da0,1,0x83c9,1,0x9304,1,0x9e7f,1,0x8ad6,1,0x58df,1,0x5f04, +1,0x7c60,1,0x807e,1,0x7262,1,0x78ca,1,0x8cc2,1,0x96f7,1,0x58d8,1,0x5c62, +1,0x6a13,1,0x6dda,1,0x6f0f,1,0x7d2f,1,0x7e37,1,0x964b,1,0x52d2,1,0x808b, +1,0x51dc,1,0x51cc,1,0x7a1c,1,0x7dbe,1,0x83f1,1,0x9675,1,0x8b80,1,0x62cf, +1,0x8afe,1,0x4e39,1,0x5be7,1,0x6012,1,0x7387,1,0x7570,1,0x5317,1,0x78fb, +1,0x4fbf,1,0x5fa9,1,0x4e0d,1,0x6ccc,1,0x6578,1,0x7d22,1,0x53c3,1,0x585e, +1,0x7701,1,0x8449,1,0x8aaa,1,0x6bba,1,0x8fb0,1,0x6c88,1,0x62fe,1,0x82e5, +1,0x63a0,1,0x7565,1,0x4eae,1,0x5169,1,0x51c9,1,0x6881,1,0x7ce7,1,0x826f, +1,0x8ad2,1,0x91cf,1,0x52f5,1,0x5442,1,0x5973,1,0x5eec,1,0x65c5,1,0x6ffe, +1,0x792a,1,0x95ad,1,0x9a6a,1,0x9e97,1,0x9ece,1,0x529b,1,0x66c6,1,0x6b77, +1,0x8f62,1,0x5e74,1,0x6190,1,0x6200,1,0x649a,1,0x6f23,1,0x7149,1,0x7489, +1,0x79ca,1,0x7df4,1,0x806f,1,0x8f26,1,0x84ee,1,0x9023,1,0x934a,1,0x5217, +1,0x52a3,1,0x54bd,1,0x70c8,1,0x88c2,1,0x5ec9,1,0x5ff5,1,0x637b,1,0x6bae, +1,0x7c3e,1,0x7375,1,0x4ee4,1,0x56f9,1,0x5dba,1,0x601c,1,0x73b2,1,0x7469, +1,0x7f9a,1,0x8046,1,0x9234,1,0x96f6,1,0x9748,1,0x9818,1,0x4f8b,1,0x79ae, +1,0x91b4,1,0x96b8,1,0x60e1,1,0x4e86,1,0x50da,1,0x5bee,1,0x5c3f,1,0x6599, +1,0x71ce,1,0x7642,1,0x84fc,1,0x907c,1,0x9f8d,1,0x6688,1,0x962e,1,0x5289, +1,0x677b,1,0x67f3,1,0x6d41,1,0x6e9c,1,0x7409,1,0x7559,1,0x786b,1,0x7d10, +1,0x985e,1,0x516d,1,0x622e,1,0x9678,1,0x502b,1,0x5d19,1,0x6dea,1,0x8f2a, +1,0x5f8b,1,0x6144,1,0x6817,1,0x9686,1,0x5229,1,0x540f,1,0x5c65,1,0x6613, +1,0x674e,1,0x68a8,1,0x6ce5,1,0x7406,1,0x75e2,1,0x7f79,1,0x88cf,1,0x88e1, +1,0x91cc,1,0x96e2,1,0x533f,1,0x6eba,1,0x541d,1,0x71d0,1,0x7498,1,0x85fa, +1,0x96a3,1,0x9c57,1,0x9e9f,1,0x6797,1,0x6dcb,1,0x81e8,1,0x7acb,1,0x7b20, +1,0x7c92,1,0x72c0,1,0x7099,1,0x8b58,1,0x4ec0,1,0x8336,1,0x523a,1,0x5207, +1,0x5ea6,1,0x62d3,1,0x7cd6,1,0x5b85,1,0x6d1e,1,0x66b4,1,0x8f3b,1,0x884c, +1,0x964d,1,0x898b,1,0x5ed3,1,0x5140,1,0x55c0,1,0x585a,1,0x6674,1,0x51de, +1,0x732a,1,0x76ca,1,0x793c,1,0x795e,1,0x7965,1,0x798f,1,0x9756,1,0x7cbe, +1,0x7fbd,1,0x8612,1,0x8af8,1,0x9038,1,0x90fd,1,0x98ef,1,0x98fc,1,0x9928, +1,0x9db4,1,0x90de,1,0x96b7,1,0x4fae,1,0x50e7,1,0x514d,1,0x52c9,1,0x52e4, +1,0x5351,1,0x559d,1,0x5606,1,0x5668,1,0x5840,1,0x58a8,1,0x5c64,1,0x5c6e, +1,0x6094,1,0x6168,1,0x618e,1,0x61f2,1,0x654f,1,0x65e2,1,0x6691,1,0x6885, +1,0x6d77,1,0x6e1a,1,0x6f22,1,0x716e,1,0x722b,1,0x7422,1,0x7891,1,0x793e, +1,0x7949,1,0x7948,1,0x7950,1,0x7956,1,0x795d,1,0x798d,1,0x798e,1,0x7a40, +1,0x7a81,1,0x7bc0,1,0x7e09,1,0x7e41,1,0x7f72,1,0x8005,1,0x81ed,1,0x8279, +1,0x8457,1,0x8910,1,0x8996,1,0x8b01,1,0x8b39,1,0x8cd3,1,0x8d08,1,0x8fb6, +1,0x96e3,1,0x97ff,1,0x983b,1,0x6075,2,0xd850,0xdeee,1,0x8218,1,0x4e26,1, +0x51b5,1,0x5168,1,0x4f80,1,0x5145,1,0x5180,1,0x52c7,1,0x52fa,1,0x5555,1, +0x5599,1,0x55e2,1,0x58b3,1,0x5944,1,0x5954,1,0x5a62,1,0x5b28,1,0x5ed2,1, +0x5ed9,1,0x5f69,1,0x5fad,1,0x60d8,1,0x614e,1,0x6108,1,0x6160,1,0x6234,1, +0x63c4,1,0x641c,1,0x6452,1,0x6556,1,0x671b,1,0x6756,1,0x6b79,1,0x6edb,1, +0x6ecb,1,0x701e,1,0x77a7,1,0x7235,1,0x72af,1,0x7471,1,0x7506,1,0x753b,1, +0x761d,1,0x761f,1,0x76db,1,0x76f4,1,0x774a,1,0x7740,1,0x78cc,1,0x7ab1,1, +0x7c7b,1,0x7d5b,1,0x7f3e,1,0x8352,1,0x83ef,1,0x8779,1,0x8941,1,0x8986,1, +0x8abf,1,0x8acb,1,0x8aed,1,0x8b8a,1,0x8f38,1,0x9072,1,0x9199,1,0x9276,1, +0x967c,1,0x97db,1,0x980b,1,0x9b12,2,0xd84a,0xdc4a,2,0xd84a,0xdc44,2,0xd84c,0xdfd5, +1,0x3b9d,1,0x4018,1,0x4039,2,0xd854,0xde49,2,0xd857,0xdcd0,2,0xd85f,0xded3,1, +0x9f43,1,0x9f8e,0xe02,0x5d9,0x5b4,0x1102,0x5f2,0x5b7,0x1802,0x5e9,0x5c1,0x1902,0x5e9,0x5c2,0xfb49, +0x1843,0x5e9,0x5bc,0x5c1,0xfb49,0x1943,0x5e9,0x5bc,0x5c2,0x1102,0x5d0,0x5b7,0x1202,0x5d0,0x5b8,0x1502, +0x5d0,0x5bc,0x1502,0x5d1,0x5bc,0x1502,0x5d2,0x5bc,0x1502,0x5d3,0x5bc,0x1502,0x5d4,0x5bc,0x1502,0x5d5, +0x5bc,0x1502,0x5d6,0x5bc,0x1502,0x5d8,0x5bc,0x1502,0x5d9,0x5bc,0x1502,0x5da,0x5bc,0x1502,0x5db,0x5bc, +0x1502,0x5dc,0x5bc,0x1502,0x5de,0x5bc,0x1502,0x5e0,0x5bc,0x1502,0x5e1,0x5bc,0x1502,0x5e3,0x5bc,0x1502, +0x5e4,0x5bc,0x1502,0x5e6,0x5bc,0x1502,0x5e7,0x5bc,0x1502,0x5e8,0x5bc,0x1502,0x5e9,0x5bc,0x1502,0x5ea, +0x5bc,0x1302,0x5d5,0x5b9,0x1702,0x5d1,0x5bf,0x1702,0x5db,0x5bf,0x1702,0x5e4,0x5bf,0xd804,0xd834,0xdd57, +0xd834,0xdd65,0xd804,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd5f,0xd834,0xdd6e,4,0xd846,0xd834,0xdd58,0xd834, +0xdd65,0xd834,0xdd6e,0xd834,0xdd5f,0xd834,0xdd6f,4,0xd846,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd6f,0xd834, +0xdd5f,0xd834,0xdd70,4,0xd846,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd70,0xd834,0xdd5f,0xd834,0xdd71,4, +0xd846,0xd834,0xdd58,0xd834,0xdd65,0xd834,0xdd71,0xd834,0xdd5f,0xd834,0xdd72,4,0xd846,0xd834,0xdd58,0xd834, +0xdd65,0xd834,0xdd72,0xd804,0xd834,0xddb9,0xd834,0xdd65,0xd804,0xd834,0xddba,0xd834,0xdd65,0xd834,0xddbb,0xd834, +0xdd6e,4,0xd846,0xd834,0xddb9,0xd834,0xdd65,0xd834,0xdd6e,0xd834,0xddbc,0xd834,0xdd6e,4,0xd846,0xd834, +0xddba,0xd834,0xdd65,0xd834,0xdd6e,0xd834,0xddbb,0xd834,0xdd6f,4,0xd846,0xd834,0xddb9,0xd834,0xdd65,0xd834, +0xdd6f,0xd834,0xddbc,0xd834,0xdd6f,4,0xd846,0xd834,0xddba,0xd834,0xdd65,0xd834,0xdd6f,1,0x4e3d,1, +0x4e38,1,0x4e41,2,0xd840,0xdd22,1,0x4f60,1,0x4fbb,1,0x5002,1,0x507a,1,0x5099, +1,0x50cf,1,0x349e,2,0xd841,0xde3a,1,0x5154,1,0x5164,1,0x5177,2,0xd841,0xdd1c, +1,0x34b9,1,0x5167,1,0x518d,2,0xd841,0xdd4b,1,0x5197,1,0x51a4,1,0x4ecc,1, +0x51ac,2,0xd864,0xdddf,1,0x51f5,1,0x5203,1,0x34df,1,0x523b,1,0x5246,1,0x5272, +1,0x5277,1,0x3515,1,0x5305,1,0x5306,1,0x5349,1,0x535a,1,0x5373,1,0x537d, +1,0x537f,2,0xd842,0xde2c,1,0x7070,1,0x53ca,1,0x53df,2,0xd842,0xdf63,1,0x53eb, +1,0x53f1,1,0x5406,1,0x549e,1,0x5438,1,0x5448,1,0x5468,1,0x54a2,1,0x54f6, +1,0x5510,1,0x5553,1,0x5563,1,0x5584,1,0x55ab,1,0x55b3,1,0x55c2,1,0x5716, +1,0x5717,1,0x5651,1,0x5674,1,0x58ee,1,0x57ce,1,0x57f4,1,0x580d,1,0x578b, +1,0x5832,1,0x5831,1,0x58ac,2,0xd845,0xdce4,1,0x58f2,1,0x58f7,1,0x5906,1, +0x591a,1,0x5922,1,0x5962,2,0xd845,0xdea8,2,0xd845,0xdeea,1,0x59ec,1,0x5a1b,1, +0x5a27,1,0x59d8,1,0x5a66,1,0x36ee,1,0x36fc,1,0x5b08,1,0x5b3e,2,0xd846,0xddc8, +1,0x5bc3,1,0x5bd8,1,0x5bf3,2,0xd846,0xdf18,1,0x5bff,1,0x5c06,1,0x5f53,1, +0x5c22,1,0x3781,1,0x5c60,1,0x5cc0,1,0x5c8d,2,0xd847,0xdde4,1,0x5d43,2,0xd847, +0xdde6,1,0x5d6e,1,0x5d6b,1,0x5d7c,1,0x5de1,1,0x5de2,1,0x382f,1,0x5dfd,1, +0x5e28,1,0x5e3d,1,0x5e69,1,0x3862,2,0xd848,0xdd83,1,0x387c,1,0x5eb0,1,0x5eb3, +1,0x5eb6,2,0xd868,0xdf92,1,0x5efe,2,0xd848,0xdf31,1,0x8201,1,0x5f22,1,0x38c7, +2,0xd84c,0xdeb8,2,0xd858,0xddda,1,0x5f62,1,0x5f6b,1,0x38e3,1,0x5f9a,1,0x5fcd, +1,0x5fd7,1,0x5ff9,1,0x6081,1,0x393a,1,0x391c,2,0xd849,0xded4,1,0x60c7,1, +0x6148,1,0x614c,1,0x617a,1,0x61b2,1,0x61a4,1,0x61af,1,0x61de,1,0x6210,1, +0x621b,1,0x625d,1,0x62b1,1,0x62d4,1,0x6350,2,0xd84a,0xdf0c,1,0x633d,1,0x62fc, +1,0x6368,1,0x6383,1,0x63e4,2,0xd84a,0xdff1,1,0x6422,1,0x63c5,1,0x63a9,1, +0x3a2e,1,0x6469,1,0x647e,1,0x649d,1,0x6477,1,0x3a6c,1,0x656c,2,0xd84c,0xdc0a, +1,0x65e3,1,0x66f8,1,0x6649,1,0x3b19,1,0x3b08,1,0x3ae4,1,0x5192,1,0x5195, +1,0x6700,1,0x669c,1,0x80ad,1,0x43d9,1,0x6721,1,0x675e,1,0x6753,2,0xd84c, +0xdfc3,1,0x3b49,1,0x67fa,1,0x6785,1,0x6852,2,0xd84d,0xdc6d,1,0x688e,1,0x681f, +1,0x6914,1,0x6942,1,0x69a3,1,0x69ea,1,0x6aa8,2,0xd84d,0xdea3,1,0x6adb,1, +0x3c18,1,0x6b21,2,0xd84e,0xdca7,1,0x6b54,1,0x3c4e,1,0x6b72,1,0x6b9f,1,0x6bbb, +2,0xd84e,0xde8d,2,0xd847,0xdd0b,2,0xd84e,0xdefa,1,0x6c4e,2,0xd84f,0xdcbc,1,0x6cbf, +1,0x6ccd,1,0x6c67,1,0x6d16,1,0x6d3e,1,0x6d69,1,0x6d78,1,0x6d85,2,0xd84f, +0xdd1e,1,0x6d34,1,0x6e2f,1,0x6e6e,1,0x3d33,1,0x6ec7,2,0xd84f,0xded1,1,0x6df9, +1,0x6f6e,2,0xd84f,0xdf5e,2,0xd84f,0xdf8e,1,0x6fc6,1,0x7039,1,0x701b,1,0x3d96, +1,0x704a,1,0x707d,1,0x7077,1,0x70ad,2,0xd841,0xdd25,1,0x7145,2,0xd850,0xde63, +1,0x719c,2,0xd850,0xdfab,1,0x7228,1,0x7250,2,0xd851,0xde08,1,0x7280,1,0x7295, +2,0xd851,0xdf35,2,0xd852,0xdc14,1,0x737a,1,0x738b,1,0x3eac,1,0x73a5,1,0x3eb8, +1,0x7447,1,0x745c,1,0x7485,1,0x74ca,1,0x3f1b,1,0x7524,2,0xd853,0xdc36,1, +0x753e,2,0xd853,0xdc92,2,0xd848,0xdd9f,1,0x7610,2,0xd853,0xdfa1,2,0xd853,0xdfb8,2, +0xd854,0xdc44,1,0x3ffc,1,0x4008,2,0xd854,0xdcf3,2,0xd854,0xdcf2,2,0xd854,0xdd19,2, +0xd854,0xdd33,1,0x771e,1,0x771f,1,0x778b,1,0x4046,1,0x4096,2,0xd855,0xdc1d,1, +0x784e,1,0x40e3,2,0xd855,0xde26,2,0xd855,0xde9a,2,0xd855,0xdec5,1,0x79eb,1,0x412f, +1,0x7a4a,1,0x7a4f,2,0xd856,0xdd7c,2,0xd856,0xdea7,1,0x7aee,1,0x4202,2,0xd856, +0xdfab,1,0x7bc6,1,0x7bc9,1,0x4227,2,0xd857,0xdc80,1,0x7cd2,1,0x42a0,1,0x7ce8, +1,0x7ce3,1,0x7d00,2,0xd857,0xdf86,1,0x7d63,1,0x4301,1,0x7dc7,1,0x7e02,1, +0x7e45,1,0x4334,2,0xd858,0xde28,2,0xd858,0xde47,1,0x4359,2,0xd858,0xded9,1,0x7f7a, +2,0xd858,0xdf3e,1,0x7f95,1,0x7ffa,2,0xd859,0xdcda,2,0xd859,0xdd23,1,0x8060,2, +0xd859,0xdda8,1,0x8070,2,0xd84c,0xdf5f,1,0x43d5,1,0x80b2,1,0x8103,1,0x440b,1, +0x813e,1,0x5ab5,2,0xd859,0xdfa7,2,0xd859,0xdfb5,2,0xd84c,0xdf93,2,0xd84c,0xdf9c,1, +0x8204,1,0x8f9e,1,0x446b,1,0x8291,1,0x828b,1,0x829d,1,0x52b3,1,0x82b1,1, +0x82b3,1,0x82bd,1,0x82e6,2,0xd85a,0xdf3c,1,0x831d,1,0x8363,1,0x83ad,1,0x8323, +1,0x83bd,1,0x83e7,1,0x8353,1,0x83ca,1,0x83cc,1,0x83dc,2,0xd85b,0xdc36,2, +0xd85b,0xdd6b,2,0xd85b,0xdcd5,1,0x452b,1,0x84f1,1,0x84f3,1,0x8516,2,0xd85c,0xdfca, +1,0x8564,2,0xd85b,0xdf2c,1,0x455d,1,0x4561,2,0xd85b,0xdfb1,2,0xd85c,0xdcd2,1, +0x456b,1,0x8650,1,0x8667,1,0x8669,1,0x86a9,1,0x8688,1,0x870e,1,0x86e2,1, +0x8728,1,0x876b,1,0x8786,1,0x45d7,1,0x87e1,1,0x8801,1,0x45f9,1,0x8860,1, +0x8863,2,0xd85d,0xde67,1,0x88d7,1,0x88de,1,0x4635,1,0x88fa,1,0x34bb,2,0xd85e, +0xdcae,2,0xd85e,0xdd66,1,0x46be,1,0x46c7,1,0x8aa0,1,0x8c55,2,0xd85f,0xdca8,1, +0x8cab,1,0x8cc1,1,0x8d1b,1,0x8d77,2,0xd85f,0xdf2f,2,0xd842,0xdc04,1,0x8dcb,1, +0x8dbc,1,0x8df0,2,0xd842,0xdcde,1,0x8ed4,2,0xd861,0xddd2,2,0xd861,0xdded,1,0x9094, +1,0x90f1,1,0x9111,2,0xd861,0xdf2e,1,0x911b,1,0x9238,1,0x92d7,1,0x92d8,1, +0x927c,1,0x93f9,1,0x9415,2,0xd862,0xdffa,1,0x958b,1,0x4995,1,0x95b7,2,0xd863, +0xdd77,1,0x49e6,1,0x96c3,1,0x5db2,1,0x9723,2,0xd864,0xdd45,2,0xd864,0xde1a,1, +0x4a6e,1,0x4a76,1,0x97e0,2,0xd865,0xdc0a,1,0x4ab2,2,0xd865,0xdc96,1,0x9829,2, +0xd865,0xddb6,1,0x98e2,1,0x4b33,1,0x9929,1,0x99a7,1,0x99c2,1,0x99fe,1,0x4bce, +2,0xd866,0xdf30,1,0x9c40,1,0x9cfd,1,0x4cce,1,0x4ced,1,0x9d67,2,0xd868,0xdcce, +1,0x4cf8,2,0xd868,0xdd05,2,0xd868,0xde0e,2,0xd868,0xde91,1,0x9ebb,1,0x4d56,1, +0x9ef9,1,0x9efe,1,0x9f05,1,0x9f0f,1,0x9f16,1,0x9f3b,2,0xd869,0xde00,0x3ac,0xe642, +0x3b1,0x301,0x3ad,0xe642,0x3b5,0x301,0x3ae,0xe642,0x3b7,0x301,0x3af,0xe642,0x3b9,0x301,0x3cc,0xe642, +0x3bf,0x301,0x3cd,0xe642,0x3c5,0x301,0x3ce,0xe642,0x3c9,0x301,0x386,0xe642,0x391,0x301,0x388,0xe642, +0x395,0x301,0x389,0xe642,0x397,0x301,0x390,1,0xe643,0x3b9,0x308,0x301,0x38a,0xe642,0x399,0x301, +0x3b0,1,0xe643,0x3c5,0x308,0x301,0x38e,0xe642,0x3a5,0x301,0x385,0xe642,0xa8,0x301,0x38c,0xe642, +0x39f,0x301,0x38f,0xe642,0x3a9,0x301,0xc5,0xe642,0x41,0x30a,0xe6e6,0xe681,0x300,0xe6e6,0xe681,0x301, +0xe6e6,0xe681,0x313,0xe6e6,0xe682,0x308,0x301,0x8100,0x8282,0xf71,0xf72,0x8100,0x8482,0xf71,0xf74,0x8100, +0x8282,0xf71,0xf80,0 }; static const uint8_t norm2_nfc_data_smallFCD[256]={ 0xc0,0xef,3,0x7f,0xdf,0x70,0xcf,0x87,0xc7,0xe6,0x66,0x46,0x64,0x46,0x66,0x5b, -0x12,0,0,4,0,0,0,0x43,0x20,2,0x29,0xae,0xc2,0xc0,0xff,0xff, +0x12,0,0,4,0,0,0,0x43,0x20,2,0x69,0xae,0xc2,0xc0,0xff,0xff, 0xc0,0x72,0xbf,0,0,0,0,0,0,0,0x40,0,0x80,0x88,0,0, 0xfe,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -1129,7 +1138,7 @@ static const uint8_t norm2_nfc_data_smallFCD[256]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0x98,0,0xc1,0x66,0xe0,0x80,0,0,0,0, +0,0,0,0,0,0,0x98,0,0xc3,0x66,0xe0,0x80,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0, diff --git a/deps/icu-small/source/common/normalizer2impl.cpp b/deps/icu-small/source/common/normalizer2impl.cpp index b2dd7ad4b868d1..cbf6b4d980450a 100644 --- a/deps/icu-small/source/common/normalizer2impl.cpp +++ b/deps/icu-small/source/common/normalizer2impl.cpp @@ -2088,6 +2088,13 @@ uint8_t Normalizer2Impl::getPreviousTrailCC(const uint8_t *start, const uint8_t // minDecompNoCP etc. and smallFCD[] are intended to help with any loss of performance, // at least for ASCII & CJK. +// Ticket 20907 - The optimizer in MSVC/Visual Studio versions below 16.4 has trouble with this +// function on Windows ARM64. As a work-around, we disable optimizations for this function. +// This work-around could/should be removed once the following versions of Visual Studio are no +// longer supported: All versions of VS2017, and versions of VS2019 below 16.4. +#if (defined(_MSC_VER) && (defined(_M_ARM64)) && (_MSC_VER < 1924)) +#pragma optimize( "", off ) +#endif // Gets the FCD value from the regular normalization data. uint16_t Normalizer2Impl::getFCD16FromNormData(UChar32 c) const { uint16_t norm16=getNorm16(c); @@ -2121,6 +2128,9 @@ uint16_t Normalizer2Impl::getFCD16FromNormData(UChar32 c) const { } return norm16; } +#if (defined(_MSC_VER) && (defined(_M_ARM64)) && (_MSC_VER < 1924)) +#pragma optimize( "", on ) +#endif // Dual functionality: // buffer!=NULL: normalize diff --git a/deps/icu-small/source/common/propname_data.h b/deps/icu-small/source/common/propname_data.h index e56ccd897b9eab..6f63e9cdd476ce 100644 --- a/deps/icu-small/source/common/propname_data.h +++ b/deps/icu-small/source/common/propname_data.h @@ -13,98 +13,99 @@ U_NAMESPACE_BEGIN -const int32_t PropNameData::indexes[8]={0x20,0x157c,0x4f32,0xa3ee,0xa3ee,0xa3ee,0x2f,0}; +const int32_t PropNameData::indexes[8]={0x20,0x15b8,0x5048,0xa69a,0xa69a,0xa69a,0x2f,0}; -const int32_t PropNameData::valueMaps[1367]={ -6,0,0x41,0,0xe3,0x356,0xe3,0x36c,0xe3,0x381,0xe3,0x397,0xe3,0x3a2,0xe3,0x3c3, -0xe3,0x3d3,0xe3,0x3e2,0xe3,0x3f0,0xe3,0x414,0xe3,0x42b,0xe3,0x443,0xe3,0x45a,0xe3,0x469, -0xe3,0x478,0xe3,0x489,0xe3,0x497,0xe3,0x4a9,0xe3,0x4c3,0xe3,0x4de,0xe3,0x4f3,0xe3,0x510, -0xe3,0x521,0xe3,0x52c,0xe3,0x54b,0xe3,0x561,0xe3,0x572,0xe3,0x582,0xe3,0x59d,0xe3,0x5b6, -0xe3,0x5c7,0xe3,0x5e1,0xe3,0x5f4,0xe3,0x604,0xe3,0x61e,0xe3,0x637,0xe3,0x64e,0xe3,0x662, -0xe3,0x678,0xe3,0x68c,0xe3,0x6a2,0xe3,0x6bc,0xe3,0x6d4,0xe3,0x6f0,0xe3,0x6f8,0xe3,0x700, -0xe3,0x708,0xe3,0x710,0xe3,0x719,0xe3,0x726,0xe3,0x739,0xe3,0x756,0xe3,0x773,0xe3,0x790, -0xe3,0x7ae,0xe3,0x7cc,0xe3,0x7f0,0xe3,0x7fd,0xe3,0x817,0xe3,0x82c,0xe3,0x847,0xe3,0x85e, -0xe3,0x875,0xe3,0x897,0xe3,0x1000,0x1019,0x8b6,0x15d,0xad6,0x178,0x2df6,0xe9,0x2e15,0x2a9,0x2f53, -0x2bf,0x2fad,0x2c9,0x320a,0x2eb,0x3b05,0x355,0x3b75,0x35f,0x3e0f,0x38e,0x3e4d,0x396,0x48f6,0x457,0x4974, -0x461,0x4999,0x467,0x49b3,0x46d,0x49d4,0x474,0x49ee,0xe9,0x4a13,0xe9,0x4a39,0x47b,0x4ae3,0x491,0x4b5c, -0x4a4,0x4c0e,0x4bf,0x4c45,0x4c6,0x4df4,0x4d9,0x5274,0x501,0x2000,0x2001,0x52d3,0x509,0x3000,0x3001,0x535f, -0,0x4000,0x400e,0x5371,0,0x537a,0,0x5394,0,0x53a5,0,0x53b6,0,0x53cc,0,0x53d5, -0,0x53f2,0,0x5410,0,0x542e,0,0x544c,0,0x5462,0,0x5476,0,0x548c,0,0x7000, -0x7001,0x54a5,0,0x7d6,0x12,0,1,0x12,0x20,0x7f4,0x49,0,1,7,8,9, -0xa,0xb,0xc,0xd,0xe,0xf,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, -0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x54,0x5b,0x67,0x6b,0x76, -0x7a,0x81,0x82,0x84,0x85,0xc8,0xca,0xd6,0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6, -0xe8,0xe9,0xea,0xf0,0x2e,0x40,0x4c,0x56,0x67,0x72,0x7f,0x8c,0x99,0xa6,0xb3,0xc0, -0xcd,0xda,0xe7,0xf4,0x101,0x10e,0x11b,0x128,0x135,0x142,0x14f,0x15c,0x169,0x176,0x183,0x190, -0x19d,0x1aa,0x1b7,0x1c4,0x1d1,0x1de,0x1eb,0x1fa,0x209,0x218,0x227,0x236,0x245,0x254,0x263,0x27d, -0x291,0x2a5,0x2c0,0x2cf,0x2d8,0x2e8,0x2f0,0x2f9,0x308,0x311,0x321,0x332,0x343,0x986,1,0, -0x17,0x8c5,0x8d6,0x8e7,0x8fb,0x912,0x92a,0x93c,0x951,0x968,0x97d,0x98d,0x99f,0x9bc,0x9d8,0x9ea, -0xa07,0xa23,0xa3f,0xa54,0xa69,0xa83,0xa9e,0xab9,0xb28,1,0,0x12d,0xae1,0xaee,0xb01,0xb29, -0xb47,0xb65,0xb7d,0xba8,0xbd2,0xbea,0xbfd,0xc10,0xc1f,0xc2e,0xc3d,0xc4c,0xc63,0xc74,0xc87,0xc9a, -0xca7,0xcb4,0xcc3,0xcd4,0xce9,0xcfa,0xd05,0xd0e,0xd1f,0xd30,0xd43,0xd55,0xd68,0xd7b,0xdba,0xdc7, -0xdd4,0xde1,0xdf6,0xe26,0xe40,0xe61,0xe8c,0xeaf,0xf0d,0xf34,0xf4f,0xf5e,0xf85,0xfad,0xfd0,0xff3, -0x101d,0x1036,0x1055,0x1078,0x109c,0x10af,0x10c9,0x10f3,0x110b,0x1133,0x115c,0x116f,0x1182,0x1195,0x11bc,0x11cb, -0x11eb,0x1219,0x1237,0x1265,0x1281,0x129c,0x12b5,0x12ce,0x12ef,0x131f,0x133e,0x1360,0x1394,0x13c1,0x1406,0x1427, -0x1451,0x1472,0x149b,0x14ae,0x14e1,0x14f8,0x1507,0x1518,0x1543,0x155a,0x158b,0x15b9,0x15fc,0x1607,0x1640,0x1651, -0x1662,0x166f,0x1682,0x16bc,0x16e0,0x1704,0x173e,0x1776,0x17a1,0x17b9,0x17e5,0x1811,0x181e,0x182d,0x184a,0x186c, -0x189a,0x18ba,0x18e1,0x1908,0x1927,0x193a,0x194b,0x195c,0x1981,0x19a6,0x19cd,0x1a01,0x1a2e,0x1a4c,0x1a5f,0x1a78, -0x1ab1,0x1ac0,0x1ae0,0x1b02,0x1b24,0x1b3b,0x1b52,0x1b7f,0x1b98,0x1bb1,0x1be2,0x1c0c,0x1c27,0x1c3a,0x1c59,0x1c62, -0x1c75,0x1c93,0x1cb1,0x1cc4,0x1cdb,0x1cf0,0x1d25,0x1d49,0x1d5e,0x1d6d,0x1d80,0x1da4,0x1dad,0x1dd1,0x1de8,0x1dfb, -0x1e0a,0x1e15,0x1e36,0x1e4e,0x1e5d,0x1e6c,0x1e7b,0x1e92,0x1ea7,0x1ebc,0x1ef5,0x1f08,0x1f24,0x1f2f,0x1f3c,0x1f6a, -0x1f8e,0x1fb1,0x1fc4,0x1fe6,0x1ff9,0x2014,0x2037,0x205a,0x207f,0x2090,0x20bf,0x20ec,0x2103,0x211e,0x212d,0x2158, -0x2190,0x21ca,0x21f8,0x2209,0x2216,0x223a,0x2249,0x2265,0x227f,0x229c,0x22d4,0x22e9,0x2316,0x2335,0x2363,0x2383, -0x23b7,0x23c6,0x23f0,0x2413,0x243e,0x2449,0x245a,0x2475,0x2499,0x24a6,0x24bb,0x24e2,0x250d,0x2544,0x2557,0x2568, -0x2598,0x25a9,0x25b8,0x25cd,0x25eb,0x25fe,0x2611,0x2628,0x2645,0x2650,0x2659,0x267b,0x2690,0x26b5,0x26cc,0x26f5, -0x2710,0x2725,0x273e,0x275f,0x2794,0x27a5,0x27d6,0x27fa,0x280b,0x2824,0x282f,0x285c,0x287e,0x28ac,0x28df,0x28ee, -0x28ff,0x291c,0x295e,0x2985,0x2992,0x29a7,0x29cb,0x29f1,0x2a2a,0x2a3b,0x2a5f,0x2a6a,0x2a77,0x2a86,0x2aab,0x2ad9, -0x2af5,0x2b12,0x2b1f,0x2b30,0x2b4e,0x2b71,0x2b8e,0x2b9b,0x2bbb,0x2bd8,0x2bf9,0x2c22,0x2c33,0x2c52,0x2c6b,0x2c84, -0x2c95,0x2cde,0x2cef,0x2d08,0x2d37,0x2d64,0x2d89,0x2dcb,0x2de7,0x1e00,1,0,0x12,0x2e2c,0x2e3c,0x2e4f, -0x2e5f,0x2e6f,0x2e7e,0x2e8e,0x2ea0,0x2eb3,0x2ec5,0x2ed5,0x2ee5,0x2ef4,0x2f03,0x2f13,0x2f20,0x2f2f,0x2f43,0x1ebe, -1,0,6,0x2f68,0x2f73,0x2f80,0x2f8d,0x2f9a,0x2fa5,0x1f02,1,0,0x1e,0x2fc2,0x2fd1,0x2fe6, -0x2ffb,0x3010,0x3024,0x3035,0x3049,0x305c,0x306d,0x3086,0x3098,0x30a9,0x30bd,0x30d0,0x30e8,0x30fa,0x3105,0x3115, -0x3123,0x3138,0x314d,0x3163,0x317d,0x3193,0x31a3,0x31b7,0x31cb,0x31dc,0x31f4,0x212d,1,0,0x66,0x321c, -0x323f,0x3248,0x3255,0x3260,0x3269,0x3274,0x327d,0x3296,0x329b,0x32a4,0x32c1,0x32ca,0x32d7,0x32e0,0x3304,0x330b, -0x3314,0x3327,0x3332,0x333b,0x3346,0x335f,0x3368,0x3377,0x3382,0x338b,0x3396,0x339f,0x33a6,0x33af,0x33ba,0x33c3, -0x33dc,0x33e5,0x33f2,0x33fd,0x340e,0x3419,0x342e,0x3445,0x344e,0x3457,0x3470,0x347b,0x3484,0x348d,0x34a4,0x34c1, -0x34cc,0x34dd,0x34e8,0x34ef,0x34fc,0x3509,0x3536,0x354b,0x3554,0x356f,0x3592,0x35b3,0x35d4,0x35f9,0x3620,0x3641, -0x3664,0x3685,0x36ac,0x36cd,0x36f2,0x3711,0x3730,0x374f,0x376c,0x378d,0x37ae,0x37d1,0x37f6,0x3815,0x3834,0x3855, -0x387c,0x38a1,0x38c0,0x38e1,0x3904,0x391f,0x3938,0x3953,0x396c,0x3989,0x39a4,0x39c1,0x39e0,0x39fd,0x3a1a,0x3a39, -0x3a56,0x3a71,0x3a8e,0x3aab,0x3ade,0x2472,1,0,6,0x3b16,0x3b25,0x3b35,0x3b45,0x3b55,0x3b66,0x24d0, -1,0,0x2b,0x3b84,0x3b90,0x3b9e,0x3bad,0x3bbc,0x3bcc,0x3bdd,0x3bf1,0x3c06,0x3c1c,0x3c2f,0x3c43,0x3c53, -0x3c5c,0x3c67,0x3c77,0x3c93,0x3ca5,0x3cb3,0x3cc2,0x3cce,0x3ce3,0x3cf7,0x3d0a,0x3d18,0x3d2c,0x3d3a,0x3d44,0x3d56, -0x3d62,0x3d70,0x3d80,0x3d87,0x3d8e,0x3d95,0x3d9c,0x3da3,0x3db9,0x3dda,0x85e,0x3dec,0x3df7,0x3e06,0x2729,1, -0,4,0x3e20,0x3e2b,0x3e37,0x3e41,0x274f,1,0,0xbd,0x3e58,0x3e65,0x3e7a,0x3e87,0x3e96,0x3ea4, -0x3eb3,0x3ec2,0x3ed4,0x3ee3,0x3ef1,0x3f02,0x3f11,0x3f20,0x3f2d,0x3f39,0x3f48,0x3f57,0x3f61,0x3f6e,0x3f7b,0x3f8a, -0x3f98,0x3fa7,0x3fb3,0x3fbd,0x3fc9,0x3fd9,0x3fe9,0x3ff7,0x4003,0x4014,0x4020,0x402c,0x403a,0x4047,0x4053,0x4060, -0xcfa,0x406d,0x407b,0x4095,0x409e,0x40ac,0x40ba,0x40c6,0x40d5,0x40e3,0x40f1,0x40fd,0x410c,0x411a,0x4128,0x4135, -0x4144,0x415f,0x416e,0x417f,0x4190,0x41a3,0x41b5,0x41c4,0x41d6,0x41e5,0x41f1,0x41fc,0x1e0a,0x4209,0x4214,0x421f, -0x422a,0x4235,0x4250,0x425b,0x4266,0x4271,0x4284,0x4298,0x42a3,0x42b2,0x42c1,0x42cc,0x42d7,0x42e4,0x42f3,0x4301, -0x430c,0x4327,0x4331,0x4342,0x4353,0x4362,0x4373,0x437e,0x4389,0x4394,0x439f,0x43aa,0x43b5,0x43c0,0x43ca,0x43d5, -0x43e5,0x43f0,0x43fe,0x440b,0x4416,0x4425,0x4432,0x443f,0x444e,0x445b,0x446c,0x447e,0x448e,0x4499,0x44ac,0x44c3, -0x44d1,0x44de,0x44e9,0x44f6,0x4507,0x4523,0x4539,0x4544,0x4561,0x4571,0x4580,0x458b,0x4596,0x1f24,0x45a2,0x45ad, -0x45c5,0x45d5,0x45e4,0x45f2,0x4600,0x460b,0x4616,0x462a,0x4641,0x4659,0x4669,0x4679,0x4689,0x469b,0x46a6,0x46b1, -0x46bb,0x46c7,0x46d5,0x46e8,0x46f4,0x4701,0x470c,0x4728,0x4735,0x4743,0x475c,0x2824,0x476b,0x2645,0x4778,0x4786, -0x4798,0x47a6,0x47b2,0x47c2,0x2a5f,0x47d0,0x47dc,0x47e7,0x47f2,0x47fd,0x4811,0x481f,0x4836,0x4842,0x4856,0x4864, -0x4876,0x488c,0x489a,0x48ac,0x48ba,0x48d7,0x48e9,0x30fb,1,0,6,0x4910,0x4923,0x4933,0x4941,0x4952, -0x4962,0x3157,0x12,0,1,0x498c,0x4992,0x3164,0x12,0,1,0x498c,0x4992,0x3171,1,0, -3,0x498c,0x4992,0x49cb,0x3187,1,0,3,0x498c,0x4992,0x49cb,0x319d,1,0,0x12,0x4a55, -0x4a5f,0x4a6b,0x4a72,0x4a7d,0x4a82,0x4a89,0x4a90,0x4a99,0x4a9e,0x4aa3,0x4ab3,0x85e,0x3dec,0x4abf,0x3df7,0x4acf, -0x3e06,0x3246,1,0,0xf,0x4a55,0x4af6,0x4b00,0x4b0a,0x4b15,0x3cc2,0x4b1f,0x4b2b,0x4b33,0x4b3a,0x4b44, -0x4a6b,0x4a72,0x4a82,0x4b4e,0x32cd,1,0,0x17,0x4a55,0x4b6b,0x4b0a,0x4b77,0x4b84,0x4b92,0x3cc2,0x4b9d, -0x4a6b,0x4bae,0x4a82,0x4bbd,0x4bcb,0x85e,0x3dda,0x4bd7,0x4be8,0x3dec,0x4abf,0x3df7,0x4acf,0x3e06,0x4bf9,0x33ea, -1,0,3,0x4c2c,0x4c34,0x4c3c,0x3403,1,0,0xf,0x4c65,0x4c6c,0x4c7b,0x4c9c,0x4cbf,0x4cca, -0x4ce9,0x4d00,0x4d0d,0x4d16,0x4d35,0x4d68,0x4d83,0x4db2,0x4dcf,0x3493,1,0,0x24,0x4e12,0x4e1f,0x4e32, -0x4e3f,0x4e6c,0x4e91,0x4ea6,0x4ec5,0x4ee6,0x4f13,0x4f4c,0x4f6f,0x4f92,0x4fbf,0x4ff4,0x501b,0x5044,0x507b,0x50aa, -0x50cb,0x50f0,0x50ff,0x5122,0x5139,0x5146,0x5155,0x5172,0x518b,0x51ae,0x51d3,0x51ec,0x5201,0x5210,0x5221,0x522e, -0x524f,0x3663,1,0,4,0x528d,0x5298,0x52b0,0x52c8,0x369f,0x36,1,2,4,8,0xe, -0x10,0x20,0x3e,0x40,0x80,0x100,0x1c0,0x200,0x400,0x800,0xe00,0x1000,0x2000,0x4000,0x7000,0x8000, -0x10000,0x20000,0x40000,0x78001,0x80000,0x100000,0x200000,0x400000,0x800000,0x1000000,0x2000000,0x4000000,0x8000000,0xf000000,0x10000000,0x20000000, -0x30f80000,0x2fc2,0x2fd1,0x2fe6,0x2ffb,0x5301,0x3010,0x3024,0x52f7,0x3035,0x3049,0x305c,0x5312,0x306d,0x3086,0x3098, -0x5329,0x30a9,0x30bd,0x30d0,0x5352,0x30e8,0x30fa,0x3105,0x3115,0x52ee,0x3123,0x3138,0x314d,0x3163,0x317d,0x3193, -0x31a3,0x31b7,0x31cb,0x5348,0x31dc,0x31f4,0x5333 +const int32_t PropNameData::valueMaps[1382]={ +6,0,0x41,0,0xe3,0x368,0xe3,0x37e,0xe3,0x393,0xe3,0x3a9,0xe3,0x3b4,0xe3,0x3d5, +0xe3,0x3e5,0xe3,0x3f4,0xe3,0x402,0xe3,0x426,0xe3,0x43d,0xe3,0x455,0xe3,0x46c,0xe3,0x47b, +0xe3,0x48a,0xe3,0x49b,0xe3,0x4a9,0xe3,0x4bb,0xe3,0x4d5,0xe3,0x4f0,0xe3,0x505,0xe3,0x522, +0xe3,0x533,0xe3,0x53e,0xe3,0x55d,0xe3,0x573,0xe3,0x584,0xe3,0x594,0xe3,0x5af,0xe3,0x5c8, +0xe3,0x5d9,0xe3,0x5f3,0xe3,0x606,0xe3,0x616,0xe3,0x630,0xe3,0x649,0xe3,0x660,0xe3,0x674, +0xe3,0x68a,0xe3,0x69e,0xe3,0x6b4,0xe3,0x6ce,0xe3,0x6e6,0xe3,0x702,0xe3,0x70a,0xe3,0x712, +0xe3,0x71a,0xe3,0x722,0xe3,0x72b,0xe3,0x738,0xe3,0x74b,0xe3,0x768,0xe3,0x785,0xe3,0x7a2, +0xe3,0x7c0,0xe3,0x7de,0xe3,0x802,0xe3,0x80f,0xe3,0x829,0xe3,0x83e,0xe3,0x859,0xe3,0x870, +0xe3,0x887,0xe3,0x8a9,0xe3,0x1000,0x1019,0x8c8,0x15f,0xae8,0x17a,0x2f11,0xe9,0x2f30,0x2b3,0x306e, +0x2c9,0x30c8,0x2d3,0x3325,0x2f5,0x3c20,0x35f,0x3c90,0x369,0x3f2a,0x398,0x3f68,0x3a0,0x4a5b,0x465,0x4ad9, +0x46f,0x4afe,0x475,0x4b18,0x47b,0x4b39,0x482,0x4b53,0xe9,0x4b78,0xe9,0x4b9e,0x489,0x4c48,0x49f,0x4cc1, +0x4b2,0x4d73,0x4cd,0x4daa,0x4d4,0x4f8a,0x4e8,0x540a,0x510,0x2000,0x2001,0x5469,0x518,0x3000,0x3001,0x54f5, +0,0x4000,0x400e,0x5507,0,0x5510,0,0x552a,0,0x553b,0,0x554c,0,0x5562,0,0x556b, +0,0x5588,0,0x55a6,0,0x55c4,0,0x55e2,0,0x55f8,0,0x560c,0,0x5622,0,0x7000, +0x7001,0x563b,0,0x7d6,0x12,0,1,0x12,0x20,0x7f4,0x4a,0,1,6,7,8, +9,0xa,0xb,0xc,0xd,0xe,0xf,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, +0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x54,0x5b,0x67,0x6b, +0x76,0x7a,0x81,0x82,0x84,0x85,0xc8,0xca,0xd6,0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4, +0xe6,0xe8,0xe9,0xea,0xf0,0x2e,0x40,0x4c,0x5e,0x68,0x79,0x84,0x91,0x9e,0xab,0xb8, +0xc5,0xd2,0xdf,0xec,0xf9,0x106,0x113,0x120,0x12d,0x13a,0x147,0x154,0x161,0x16e,0x17b,0x188, +0x195,0x1a2,0x1af,0x1bc,0x1c9,0x1d6,0x1e3,0x1f0,0x1fd,0x20c,0x21b,0x22a,0x239,0x248,0x257,0x266, +0x275,0x28f,0x2a3,0x2b7,0x2d2,0x2e1,0x2ea,0x2fa,0x302,0x30b,0x31a,0x323,0x333,0x344,0x355,0x995, +1,0,0x17,0x8d7,0x8e8,0x8f9,0x90d,0x924,0x93c,0x94e,0x963,0x97a,0x98f,0x99f,0x9b1,0x9ce, +0x9ea,0x9fc,0xa19,0xa35,0xa51,0xa66,0xa7b,0xa95,0xab0,0xacb,0xb37,1,0,0x135,0xaf3,0xb00, +0xb13,0xb3b,0xb59,0xb77,0xb8f,0xbba,0xbe4,0xbfc,0xc0f,0xc22,0xc31,0xc40,0xc4f,0xc5e,0xc75,0xc86, +0xc99,0xcac,0xcb9,0xcc6,0xcd5,0xce6,0xcfb,0xd0c,0xd17,0xd20,0xd31,0xd42,0xd55,0xd67,0xd7a,0xd8d, +0xdcc,0xdd9,0xde6,0xdf3,0xe08,0xe38,0xe52,0xe73,0xe9e,0xec1,0xf1f,0xf46,0xf61,0xf70,0xf97,0xfbf, +0xfe2,0x1005,0x102f,0x1048,0x1067,0x108a,0x10ae,0x10c1,0x10db,0x1105,0x111d,0x1145,0x116e,0x1181,0x1194,0x11a7, +0x11ce,0x11dd,0x11fd,0x122b,0x1249,0x1277,0x1293,0x12ae,0x12c7,0x12e0,0x1301,0x1331,0x1350,0x1372,0x13a6,0x13d3, +0x1418,0x1439,0x1463,0x1484,0x14ad,0x14c0,0x14f3,0x150a,0x1519,0x152a,0x1555,0x156c,0x159d,0x15cb,0x160e,0x1619, +0x1652,0x1663,0x1674,0x1681,0x1694,0x16ce,0x16f2,0x1716,0x1750,0x1788,0x17b3,0x17cb,0x17f7,0x1823,0x1830,0x183f, +0x185c,0x187e,0x18ac,0x18cc,0x18f3,0x191a,0x1939,0x194c,0x195d,0x196e,0x1993,0x19b8,0x19df,0x1a13,0x1a40,0x1a5e, +0x1a71,0x1a8a,0x1ac3,0x1ad2,0x1af2,0x1b14,0x1b36,0x1b4d,0x1b64,0x1b91,0x1baa,0x1bc3,0x1bf4,0x1c1e,0x1c39,0x1c4c, +0x1c6b,0x1c74,0x1c87,0x1ca5,0x1cc3,0x1cd6,0x1ced,0x1d02,0x1d37,0x1d5b,0x1d70,0x1d7f,0x1d92,0x1db6,0x1dbf,0x1de3, +0x1dfa,0x1e0d,0x1e1c,0x1e27,0x1e48,0x1e60,0x1e6f,0x1e7e,0x1e8d,0x1ea4,0x1eb9,0x1ece,0x1f07,0x1f1a,0x1f36,0x1f41, +0x1f4e,0x1f7c,0x1fa0,0x1fc3,0x1fd6,0x1ff8,0x200b,0x2026,0x2049,0x206c,0x2091,0x20a2,0x20d1,0x20fe,0x2115,0x2130, +0x213f,0x216a,0x21a2,0x21dc,0x220a,0x221b,0x2228,0x224c,0x225b,0x2277,0x2291,0x22ae,0x22e6,0x22fb,0x2328,0x2347, +0x2375,0x2395,0x23c9,0x23d8,0x2402,0x2425,0x2450,0x245b,0x246c,0x2487,0x24ab,0x24b8,0x24cd,0x24f4,0x251f,0x2556, +0x2569,0x257a,0x25aa,0x25bb,0x25ca,0x25df,0x25fd,0x2610,0x2623,0x263a,0x2657,0x2662,0x266b,0x268d,0x26a2,0x26c7, +0x26de,0x2707,0x2722,0x2737,0x2750,0x2771,0x27a6,0x27b7,0x27e8,0x280c,0x281d,0x2836,0x2841,0x286e,0x2890,0x28be, +0x28f1,0x2900,0x2911,0x292e,0x2970,0x2997,0x29a4,0x29b9,0x29dd,0x2a03,0x2a3c,0x2a4d,0x2a71,0x2a7c,0x2a89,0x2a98, +0x2abd,0x2aeb,0x2b07,0x2b24,0x2b31,0x2b42,0x2b60,0x2b83,0x2ba0,0x2bad,0x2bcd,0x2bea,0x2c0b,0x2c34,0x2c45,0x2c64, +0x2c7d,0x2c96,0x2ca7,0x2cf0,0x2d01,0x2d1a,0x2d49,0x2d76,0x2d9b,0x2ddd,0x2df9,0x2e08,0x2e1f,0x2e4d,0x2e66,0x2e8f, +0x2ea9,0x2ee4,0x2f02,0x1e85,1,0,0x12,0x2f47,0x2f57,0x2f6a,0x2f7a,0x2f8a,0x2f99,0x2fa9,0x2fbb,0x2fce, +0x2fe0,0x2ff0,0x3000,0x300f,0x301e,0x302e,0x303b,0x304a,0x305e,0x1f43,1,0,6,0x3083,0x308e,0x309b, +0x30a8,0x30b5,0x30c0,0x1f87,1,0,0x1e,0x30dd,0x30ec,0x3101,0x3116,0x312b,0x313f,0x3150,0x3164,0x3177, +0x3188,0x31a1,0x31b3,0x31c4,0x31d8,0x31eb,0x3203,0x3215,0x3220,0x3230,0x323e,0x3253,0x3268,0x327e,0x3298,0x32ae, +0x32be,0x32d2,0x32e6,0x32f7,0x330f,0x21b2,1,0,0x66,0x3337,0x335a,0x3363,0x3370,0x337b,0x3384,0x338f, +0x3398,0x33b1,0x33b6,0x33bf,0x33dc,0x33e5,0x33f2,0x33fb,0x341f,0x3426,0x342f,0x3442,0x344d,0x3456,0x3461,0x347a, +0x3483,0x3492,0x349d,0x34a6,0x34b1,0x34ba,0x34c1,0x34ca,0x34d5,0x34de,0x34f7,0x3500,0x350d,0x3518,0x3529,0x3534, +0x3549,0x3560,0x3569,0x3572,0x358b,0x3596,0x359f,0x35a8,0x35bf,0x35dc,0x35e7,0x35f8,0x3603,0x360a,0x3617,0x3624, +0x3651,0x3666,0x366f,0x368a,0x36ad,0x36ce,0x36ef,0x3714,0x373b,0x375c,0x377f,0x37a0,0x37c7,0x37e8,0x380d,0x382c, +0x384b,0x386a,0x3887,0x38a8,0x38c9,0x38ec,0x3911,0x3930,0x394f,0x3970,0x3997,0x39bc,0x39db,0x39fc,0x3a1f,0x3a3a, +0x3a53,0x3a6e,0x3a87,0x3aa4,0x3abf,0x3adc,0x3afb,0x3b18,0x3b35,0x3b54,0x3b71,0x3b8c,0x3ba9,0x3bc6,0x3bf9,0x24f7, +1,0,6,0x3c31,0x3c40,0x3c50,0x3c60,0x3c70,0x3c81,0x2555,1,0,0x2b,0x3c9f,0x3cab,0x3cb9, +0x3cc8,0x3cd7,0x3ce7,0x3cf8,0x3d0c,0x3d21,0x3d37,0x3d4a,0x3d5e,0x3d6e,0x3d77,0x3d82,0x3d92,0x3dae,0x3dc0,0x3dce, +0x3ddd,0x3de9,0x3dfe,0x3e12,0x3e25,0x3e33,0x3e47,0x3e55,0x3e5f,0x3e71,0x3e7d,0x3e8b,0x3e9b,0x3ea2,0x3ea9,0x3eb0, +0x3eb7,0x3ebe,0x3ed4,0x3ef5,0x870,0x3f07,0x3f12,0x3f21,0x27ae,1,0,4,0x3f3b,0x3f46,0x3f52,0x3f5c, +0x27d4,1,0,0xc1,0x3f73,0x3f80,0x3f95,0x3fa2,0x3fb1,0x3fbf,0x3fce,0x3fdd,0x3fef,0x3ffe,0x400c,0x401d, +0x402c,0x403b,0x4048,0x4054,0x4063,0x4072,0x407c,0x4089,0x4096,0x40a5,0x40b3,0x40c2,0x40ce,0x40d8,0x40e4,0x40f4, +0x4104,0x4112,0x411e,0x412f,0x413b,0x4147,0x4155,0x4162,0x416e,0x417b,0xd0c,0x4188,0x4196,0x41b0,0x41b9,0x41c7, +0x41d5,0x41e1,0x41f0,0x41fe,0x420c,0x4218,0x4227,0x4235,0x4243,0x4250,0x425f,0x427a,0x4289,0x429a,0x42ab,0x42be, +0x42d0,0x42df,0x42f1,0x4300,0x430c,0x4317,0x1e1c,0x4324,0x432f,0x433a,0x4345,0x4350,0x436b,0x4376,0x4381,0x438c, +0x439f,0x43b3,0x43be,0x43cd,0x43dc,0x43e7,0x43f2,0x43ff,0x440e,0x441c,0x4427,0x4442,0x444c,0x445d,0x446e,0x447d, +0x448e,0x4499,0x44a4,0x44af,0x44ba,0x44c5,0x44d0,0x44db,0x44e5,0x44f0,0x4500,0x450b,0x4519,0x4526,0x4531,0x4540, +0x454d,0x455a,0x4569,0x4576,0x4587,0x4599,0x45a9,0x45b4,0x45c7,0x45de,0x45ec,0x45f9,0x4604,0x4611,0x4622,0x463e, +0x4654,0x465f,0x467c,0x468c,0x469b,0x46a6,0x46b1,0x1f36,0x46bd,0x46c8,0x46e0,0x46f0,0x46ff,0x470d,0x471b,0x4726, +0x4731,0x4745,0x475c,0x4774,0x4784,0x4794,0x47a4,0x47b6,0x47c1,0x47cc,0x47d6,0x47e2,0x47f0,0x4803,0x480f,0x481c, +0x4827,0x4843,0x4850,0x485e,0x4877,0x2836,0x4886,0x2657,0x4893,0x48a1,0x48b3,0x48c1,0x48cd,0x48dd,0x2a71,0x48eb, +0x48f7,0x4902,0x490d,0x4918,0x492c,0x493a,0x4951,0x495d,0x4971,0x497f,0x4991,0x49a7,0x49b5,0x49c7,0x49d5,0x49f2, +0x4a04,0x4a11,0x4a22,0x4a34,0x4a4e,0x31cc,1,0,6,0x4a75,0x4a88,0x4a98,0x4aa6,0x4ab7,0x4ac7,0x3228, +0x12,0,1,0x4af1,0x4af7,0x3235,0x12,0,1,0x4af1,0x4af7,0x3242,1,0,3,0x4af1, +0x4af7,0x4b30,0x3258,1,0,3,0x4af1,0x4af7,0x4b30,0x326e,1,0,0x12,0x4bba,0x4bc4,0x4bd0, +0x4bd7,0x4be2,0x4be7,0x4bee,0x4bf5,0x4bfe,0x4c03,0x4c08,0x4c18,0x870,0x3f07,0x4c24,0x3f12,0x4c34,0x3f21,0x3317, +1,0,0xf,0x4bba,0x4c5b,0x4c65,0x4c6f,0x4c7a,0x3ddd,0x4c84,0x4c90,0x4c98,0x4c9f,0x4ca9,0x4bd0,0x4bd7, +0x4be7,0x4cb3,0x339e,1,0,0x17,0x4bba,0x4cd0,0x4c6f,0x4cdc,0x4ce9,0x4cf7,0x3ddd,0x4d02,0x4bd0,0x4d13, +0x4be7,0x4d22,0x4d30,0x870,0x3ef5,0x4d3c,0x4d4d,0x3f07,0x4c24,0x3f12,0x4c34,0x3f21,0x4d5e,0x34bb,1,0, +3,0x4d91,0x4d99,0x4da1,0x34d4,1,0,0x10,0x4dca,0x4dd1,0x4de0,0x4e01,0x4e24,0x4e2f,0x4e4e,0x4e65, +0x4e72,0x4e7b,0x4e9a,0x4ecd,0x4ee8,0x4f17,0x4f34,0x4f59,0x356d,1,0,0x24,0x4fa8,0x4fb5,0x4fc8,0x4fd5, +0x5002,0x5027,0x503c,0x505b,0x507c,0x50a9,0x50e2,0x5105,0x5128,0x5155,0x518a,0x51b1,0x51da,0x5211,0x5240,0x5261, +0x5286,0x5295,0x52b8,0x52cf,0x52dc,0x52eb,0x5308,0x5321,0x5344,0x5369,0x5382,0x5397,0x53a6,0x53b7,0x53c4,0x53e5, +0x373d,1,0,4,0x5423,0x542e,0x5446,0x545e,0x3779,0x36,1,2,4,8,0xe,0x10, +0x20,0x3e,0x40,0x80,0x100,0x1c0,0x200,0x400,0x800,0xe00,0x1000,0x2000,0x4000,0x7000,0x8000,0x10000, +0x20000,0x40000,0x78001,0x80000,0x100000,0x200000,0x400000,0x800000,0x1000000,0x2000000,0x4000000,0x8000000,0xf000000,0x10000000,0x20000000,0x30f80000, +0x30dd,0x30ec,0x3101,0x3116,0x5497,0x312b,0x313f,0x548d,0x3150,0x3164,0x3177,0x54a8,0x3188,0x31a1,0x31b3,0x54bf, +0x31c4,0x31d8,0x31eb,0x54e8,0x3203,0x3215,0x3220,0x3230,0x5484,0x323e,0x3253,0x3268,0x327e,0x3298,0x32ae,0x32be, +0x32d2,0x32e6,0x54de,0x32f7,0x330f,0x54c9 }; -const uint8_t PropNameData::bytesTries[14774]={ +const uint8_t PropNameData::bytesTries[14992]={ 0,0x15,0x6d,0xc3,0x78,0x73,0xc2,0x12,0x76,0x7a,0x76,0x6a,0x77,0xa2,0x52,0x78, 1,0x64,0x50,0x69,0x10,0x64,1,0x63,0x30,0x73,0x62,0x13,0x74,0x61,0x72,0x74, 0x63,0x60,0x16,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x61,0x13,0x69,0x67,0x69,0x74, @@ -232,22 +233,17 @@ const uint8_t PropNameData::bytesTries[14774]={ 0x63,0x6f,0x64,0x65,0x70,0x6f,0x69,0x6e,0x74,0x2b,0x2a,0x10,0x61,0x2e,0x15,0x63, 0x72,0x69,0x74,0x69,0x63,0x2f,3,0x66,0x34,0x6e,0x3e,0x74,0x42,0x79,0x22,0x11, 0x65,0x73,0x23,0x20,0x13,0x61,0x6c,0x73,0x65,0x21,0x20,0x10,0x6f,0x21,0x22,0x12, -0x72,0x75,0x65,0x23,0xa,0x6b,0x5b,0x6f,0x23,0x6f,0x3c,0x72,0x4c,0x76,1,0x69, +0x72,0x75,0x65,0x23,0xb,0x6b,0x5b,0x6f,0x23,0x6f,0x3c,0x72,0x4c,0x76,1,0x69, 0x24,0x72,0x33,0x13,0x72,0x61,0x6d,0x61,0x33,0x10,0x76,0x22,0x14,0x65,0x72,0x6c, 0x61,0x79,0x23,0xa2,0xe2,0x13,0x69,0x67,0x68,0x74,0xa3,0xe2,0x6b,0x58,0x6c,0x74, 0x6e,3,0x6b,0x2f,0x6f,0x30,0x72,0x21,0x75,0x12,0x6b,0x74,0x61,0x2f,0x19,0x74, 0x72,0x65,0x6f,0x72,0x64,0x65,0x72,0x65,0x64,0x21,1,0x61,0x24,0x76,0x31,0x18, 0x6e,0x61,0x76,0x6f,0x69,0x63,0x69,0x6e,0x67,0x31,0xa2,0xe0,0x12,0x65,0x66,0x74, -0xa3,0xe0,0x61,0x5c,0x62,0xa2,0x77,0x63,0xa2,0x96,0x64,0xa4,0xa,0x69,1,0x6f, -0x26,0x73,0xa3,0xf0,0x1a,0x74,0x61,0x73,0x75,0x62,0x73,0x63,0x72,0x69,0x70,0x74, -0xa3,0xf0,0xa2,0xe6,3,0x62,0xa0,0x6c,0xa3,0xe4,0x72,0xa3,0xe8,0x74,2,0x61, -0x74,0x62,0x7c,0x74,0x14,0x61,0x63,0x68,0x65,0x64,1,0x61,0x3e,0x62,0x13,0x65, -0x6c,0x6f,0x77,0xa2,0xca,0x13,0x6c,0x65,0x66,0x74,0xa3,0xc8,0x13,0x62,0x6f,0x76, -0x65,0xa2,0xd6,0x14,0x72,0x69,0x67,0x68,0x74,0xa3,0xd8,0xa2,0xd6,0x10,0x72,0xa3, -0xd8,0xa2,0xca,0x10,0x6c,0xa3,0xc8,0x12,0x6f,0x76,0x65,0xa2,0xe6,1,0x6c,0x30, -0x72,0x13,0x69,0x67,0x68,0x74,0xa3,0xe8,0x12,0x65,0x66,0x74,0xa3,0xe4,0xa2,0xdc, -2,0x65,0x2c,0x6c,0xa3,0xda,0x72,0xa3,0xde,0x12,0x6c,0x6f,0x77,0xa2,0xdc,1, -0x6c,0x30,0x72,0x13,0x69,0x67,0x68,0x74,0xa3,0xde,0x12,0x65,0x66,0x74,0xa3,0xda, +0xa3,0xe0,0x64,0x45,0x64,0x4e,0x68,0x88,0x69,1,0x6f,0x26,0x73,0xa3,0xf0,0x1a, +0x74,0x61,0x73,0x75,0x62,0x73,0x63,0x72,0x69,0x70,0x74,0xa3,0xf0,2,0x61,0xa3, +0xea,0x62,0xa3,0xe9,0x6f,0x13,0x75,0x62,0x6c,0x65,1,0x61,0x30,0x62,0x13,0x65, +0x6c,0x6f,0x77,0xa3,0xe9,0x13,0x62,0x6f,0x76,0x65,0xa3,0xea,0x12,0x61,0x6e,0x72, +0x2c,0x15,0x65,0x61,0x64,0x69,0x6e,0x67,0x2d,0x61,0xa2,0x7b,0x62,0xa2,0xd4,0x63, 0x11,0x63,0x63,4,0x31,0x3c,0x32,0xa2,0x42,0x33,0xa2,0x56,0x38,0xa2,0x64,0x39, 0x10,0x31,0xa3,0x5b,9,0x35,0xa,0x35,0x3f,0x36,0x41,0x37,0x43,0x38,0x45,0x39, 0x47,0x30,0x30,0x31,0x3c,0x32,0x42,0x33,0x4e,0x34,0x3d,0x34,1,0x33,0xa3,0x67, @@ -255,788 +251,806 @@ const uint8_t PropNameData::bytesTries[14774]={ 0x3a,2,0x30,0xa3,0x82,0x32,0xa3,0x84,0x33,0xa3,0x85,9,0x35,0xa,0x35,0x53, 0x36,0x55,0x37,0x57,0x38,0x59,0x39,0x5b,0x30,0x49,0x31,0x4b,0x32,0x4d,0x33,0x4f, 0x34,0x51,6,0x33,8,0x33,0x63,0x34,0x65,0x35,0x67,0x36,0x69,0x30,0x5d,0x31, -0x5f,0x32,0x61,0x10,0x34,0xa3,0x54,2,0x61,0xa3,0xea,0x62,0xa3,0xe9,0x6f,0x13, -0x75,0x62,0x6c,0x65,1,0x61,0x30,0x62,0x13,0x65,0x6c,0x6f,0x77,0xa3,0xe9,0x13, -0x62,0x6f,0x76,0x65,0xa3,0xea,0xb,0x6e,0xc0,0xca,0x72,0x5f,0x72,0x46,0x73,0xa2, -0x48,0x77,1,0x68,0x24,0x73,0x33,0x17,0x69,0x74,0x65,0x73,0x70,0x61,0x63,0x65, -0x33,0x22,1,0x69,0x30,0x6c,2,0x65,0x3d,0x69,0x4b,0x6f,0x3f,0x18,0x67,0x68, -0x74,0x74,0x6f,0x6c,0x65,0x66,0x74,0x22,2,0x65,0x38,0x69,0x48,0x6f,0x16,0x76, -0x65,0x72,0x72,0x69,0x64,0x65,0x3f,0x17,0x6d,0x62,0x65,0x64,0x64,0x69,0x6e,0x67, -0x3d,0x15,0x73,0x6f,0x6c,0x61,0x74,0x65,0x4b,0x30,0x1e,0x65,0x67,0x6d,0x65,0x6e, -0x74,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x31,0x6e,0xa2,0x41,0x6f,0xa2, -0x53,0x70,2,0x61,0x66,0x64,0x86,0x6f,0x1b,0x70,0x64,0x69,0x72,0x65,0x63,0x74, -0x69,0x6f,0x6e,0x61,0x6c,1,0x66,0x32,0x69,0x15,0x73,0x6f,0x6c,0x61,0x74,0x65, -0x4d,0x14,0x6f,0x72,0x6d,0x61,0x74,0x41,0x1f,0x72,0x61,0x67,0x72,0x61,0x70,0x68, -0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x2f,1,0x66,0x41,0x69,0x4d,1, -0x6f,0x28,0x73,0x10,0x6d,0x43,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69,0x6e,0x67,0x6d, -0x61,0x72,0x6b,0x43,1,0x6e,0x35,0x74,0x19,0x68,0x65,0x72,0x6e,0x65,0x75,0x74, -0x72,0x61,0x6c,0x35,0x65,0x88,0x65,0x98,0x66,0xa2,0x6a,0x6c,0x20,1,0x65,0x30, -0x72,2,0x65,0x37,0x69,0x49,0x6f,0x39,0x18,0x66,0x74,0x74,0x6f,0x72,0x69,0x67, -0x68,0x74,0x20,2,0x65,0x38,0x69,0x48,0x6f,0x16,0x76,0x65,0x72,0x72,0x69,0x64, -0x65,0x39,0x17,0x6d,0x62,0x65,0x64,0x64,0x69,0x6e,0x67,0x37,0x15,0x73,0x6f,0x6c, -0x61,0x74,0x65,0x49,3,0x6e,0x25,0x73,0x27,0x74,0x29,0x75,0x15,0x72,0x6f,0x70, -0x65,0x61,0x6e,2,0x6e,0x3c,0x73,0x46,0x74,0x18,0x65,0x72,0x6d,0x69,0x6e,0x61, -0x74,0x6f,0x72,0x29,0x14,0x75,0x6d,0x62,0x65,0x72,0x25,0x17,0x65,0x70,0x61,0x72, -0x61,0x74,0x6f,0x72,0x27,1,0x69,0x28,0x73,0x10,0x69,0x47,0x1f,0x72,0x73,0x74, -0x73,0x74,0x72,0x6f,0x6e,0x67,0x69,0x73,0x6f,0x6c,0x61,0x74,0x65,0x47,0x61,0x4e, -0x62,0x84,0x63,1,0x6f,0x24,0x73,0x2d,0x1c,0x6d,0x6d,0x6f,0x6e,0x73,0x65,0x70, -0x61,0x72,0x61,0x74,0x6f,0x72,0x2d,2,0x6c,0x3b,0x6e,0x2b,0x72,0x13,0x61,0x62, -0x69,0x63,1,0x6c,0x30,0x6e,0x14,0x75,0x6d,0x62,0x65,0x72,0x2b,0x14,0x65,0x74, -0x74,0x65,0x72,0x3b,0x2e,1,0x6e,0x45,0x6f,0x1c,0x75,0x6e,0x64,0x61,0x72,0x79, -0x6e,0x65,0x75,0x74,0x72,0x61,0x6c,0x45,0,0x16,0x6d,0xc8,0x94,0x74,0xc1,0xd2, -0x77,0x61,0x77,0x48,0x79,0x70,0x7a,0x1d,0x61,0x6e,0x61,0x62,0x61,0x7a,0x61,0x72, -0x73,0x71,0x75,0x61,0x72,0x65,0xa5,0x18,0x10,0x61,1,0x6e,0x36,0x72,0x16,0x61, -0x6e,0x67,0x63,0x69,0x74,0x69,0xa3,0xfc,0x12,0x63,0x68,0x6f,0xa5,0x2c,0x10,0x69, -2,0x6a,0x3c,0x72,0x68,0x73,0x17,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x73,0xa3, -0x48,0x12,0x69,0x6e,0x67,0xa2,0x74,0x1e,0x68,0x65,0x78,0x61,0x67,0x72,0x61,0x6d, -0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x74,0x16,0x61,0x64,0x69,0x63,0x61,0x6c, -0x73,0xa3,0x49,0x74,0xa2,0x59,0x75,0xa4,0x22,0x76,2,0x61,0x36,0x65,0x7a,0x73, -0xa2,0x6c,0x12,0x73,0x75,0x70,0xa3,0x7d,1,0x69,0xa3,0x9f,0x72,0x1e,0x69,0x61, -0x74,0x69,0x6f,0x6e,0x73,0x65,0x6c,0x65,0x63,0x74,0x6f,0x72,0x73,0xa2,0x6c,0x19, -0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x7d,1,0x64,0x3c,0x72, -0x19,0x74,0x69,0x63,0x61,0x6c,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x91,0x14,0x69,0x63, -0x65,0x78,0x74,0xa2,0xaf,0x16,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa3,0xaf,4, -0x61,0x68,0x65,0xa2,0x9a,0x68,0xa2,0x9d,0x69,0xa2,0xa5,0x72,0x1c,0x61,0x6e,0x73, -0x70,0x6f,0x72,0x74,0x61,0x6e,0x64,0x6d,0x61,0x70,0xa2,0xcf,0x16,0x73,0x79,0x6d, -0x62,0x6f,0x6c,0x73,0xa3,0xcf,4,0x67,0x58,0x69,0x7e,0x6b,0xa2,0x58,0x6d,0xa2, -0x5a,0x6e,0x12,0x67,0x75,0x74,0xa4,0x10,0x19,0x63,0x6f,0x6d,0x70,0x6f,0x6e,0x65, -0x6e,0x74,0x73,0xa5,0x11,2,0x61,0x2a,0x62,0x32,0x73,0xa3,0x60,0x12,0x6c,0x6f, -0x67,0xa3,0x62,0x13,0x61,0x6e,0x77,0x61,0xa3,0x65,3,0x6c,0x52,0x74,0x56,0x76, -0x5e,0x78,0x16,0x75,0x61,0x6e,0x6a,0x69,0x6e,0x67,0xa2,0x7c,0x16,0x73,0x79,0x6d, -0x62,0x6f,0x6c,0x73,0xa3,0x7c,0x10,0x65,0xa3,0x70,0x12,0x68,0x61,0x6d,0xa3,0xae, -0x12,0x69,0x65,0x74,0xa3,0xb7,0x11,0x72,0x69,0xa3,0xdc,0x11,0x69,0x6c,0x48,0x12, -0x73,0x75,0x70,0xa4,0x2b,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0x2b,0x13, -0x6c,0x75,0x67,0x75,0x4b,0x10,0x61,1,0x61,0x24,0x69,0x53,0x11,0x6e,0x61,0x3d, -2,0x62,0x34,0x66,0x3c,0x72,0x13,0x68,0x75,0x74,0x61,0xa3,0xfb,0x13,0x65,0x74, -0x61,0x6e,0x57,0x14,0x69,0x6e,0x61,0x67,0x68,0xa3,0x90,2,0x63,0x82,0x67,0x92, -0x6e,0x1f,0x69,0x66,0x69,0x65,0x64,0x63,0x61,0x6e,0x61,0x64,0x69,0x61,0x6e,0x61, -0x62,0x6f,0x1f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x73,0x79,0x6c,0x6c,0x61,0x62, -0x69,0x63,0x73,0x62,0x17,0x65,0x78,0x74,0x65,0x6e,0x64,0x65,0x64,0xa3,0xad,0x11, -0x61,0x73,0x62,0x12,0x65,0x78,0x74,0xa3,0xad,0x15,0x61,0x72,0x69,0x74,0x69,0x63, -0xa3,0x78,0x70,0xc3,0x33,0x70,0xa6,0x49,0x72,0xa8,5,0x73,7,0x6f,0xc1,0xa6, -0x6f,0xa2,0x51,0x70,0xa2,0x6d,0x75,0xa2,0x8c,0x79,2,0x6c,0x50,0x6d,0x62,0x72, -0x12,0x69,0x61,0x63,0x3a,0x12,0x73,0x75,0x70,0xa4,0x17,0x16,0x70,0x6c,0x65,0x6d, -0x65,0x6e,0x74,0xa5,0x17,0x17,0x6f,0x74,0x69,0x6e,0x61,0x67,0x72,0x69,0xa3,0x8f, -0x14,0x62,0x6f,0x6c,0x73,0x61,0x1f,0x6e,0x64,0x70,0x69,0x63,0x74,0x6f,0x67,0x72, -0x61,0x70,0x68,0x73,0x65,0x78,0x74,1,0x61,0xa5,0x2a,0x65,0x14,0x6e,0x64,0x65, -0x64,0x61,0xa5,0x2a,2,0x67,0x34,0x72,0x3e,0x79,0x13,0x6f,0x6d,0x62,0x6f,0xa5, -0x16,0x13,0x64,0x69,0x61,0x6e,0xa5,0x23,0x17,0x61,0x73,0x6f,0x6d,0x70,0x65,0x6e, -0x67,0xa3,0xda,1,0x61,0x32,0x65,0x14,0x63,0x69,0x61,0x6c,0x73,0xa3,0x56,0x12, -0x63,0x69,0x6e,0x1f,0x67,0x6d,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x6c,0x65,0x74, -0x74,0x65,0x72,0x73,0x2d,2,0x6e,0x48,0x70,0x76,0x74,0x1d,0x74,0x6f,0x6e,0x73, -0x69,0x67,0x6e,0x77,0x72,0x69,0x74,0x69,0x6e,0x67,0xa5,6,0x15,0x64,0x61,0x6e, -0x65,0x73,0x65,0xa2,0x9b,0x12,0x73,0x75,0x70,0xa2,0xdb,0x16,0x70,0x6c,0x65,0x6d, -0x65,0x6e,0x74,0xa3,0xdb,4,0x61,0xa2,0xa8,0x65,0x5c,0x6d,0x9e,0x70,0xa2,0x4b, -0x73,0x13,0x79,0x6d,0x62,0x6f,0x1f,0x6c,0x73,0x61,0x6e,0x64,0x70,0x69,0x63,0x74, -0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa5,5,0x10,0x72,1,0x61,0x4e,0x73,0x12, -0x63,0x72,0x69,0x1f,0x70,0x74,0x73,0x61,0x6e,0x64,0x73,0x75,0x62,0x73,0x63,0x72, -0x69,0x70,0x74,0x73,0x73,0x14,0x6e,0x64,0x73,0x75,0x62,0x73,0x1b,0x61,0x74,0x68, -0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0xa3,0x6a,1,0x6c,0x40,0x75,1, -0x61,0x6e,0x6e,0x17,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x8e,0x15,0x65, -0x6d,0x65,0x6e,0x74,0x61,1,0x6c,0x50,0x72,0x1e,0x79,0x70,0x72,0x69,0x76,0x61, -0x74,0x65,0x75,0x73,0x65,0x61,0x72,0x65,0x61,1,0x61,0xa3,0x6d,0x62,0xa3,0x6e, -3,0x61,0x5c,0x6d,0x78,0x70,0xa2,0x41,0x73,0x13,0x79,0x6d,0x62,0x6f,0x1f,0x6c, -0x73,0x61,0x6e,0x64,0x70,0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa5, -5,0x14,0x72,0x72,0x6f,0x77,0x73,2,0x61,0xa3,0x67,0x62,0xa3,0x68,0x63,0xa3, -0xfa,0x13,0x61,0x74,0x68,0x65,0x1f,0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,0x6f,0x70, -0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0xa3,0x6a,0x19,0x75,0x6e,0x63,0x74,0x75,0x61, -0x74,0x69,0x6f,0x6e,0xa3,0x8e,0x61,0x88,0x68,0xa2,0x48,0x69,0xa2,0x71,0x6d,0x12, -0x61,0x6c,0x6c,1,0x66,0x46,0x6b,0x15,0x61,0x6e,0x61,0x65,0x78,0x74,0xa4,0x29, -0x15,0x65,0x6e,0x73,0x69,0x6f,0x6e,0xa5,0x29,0x12,0x6f,0x72,0x6d,1,0x73,0xa3, -0x54,0x76,0x16,0x61,0x72,0x69,0x61,0x6e,0x74,0x73,0xa3,0x54,1,0x6d,0x36,0x75, -0x16,0x72,0x61,0x73,0x68,0x74,0x72,0x61,0xa3,0xa1,0x15,0x61,0x72,0x69,0x74,0x61, -0x6e,0xa3,0xac,1,0x61,0x52,0x6f,0x13,0x72,0x74,0x68,0x61,0x1f,0x6e,0x64,0x66, -0x6f,0x72,0x6d,0x61,0x74,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x73,0xa3,0xf7,1, -0x72,0x2e,0x76,0x12,0x69,0x61,0x6e,0xa3,0x79,0x12,0x61,0x64,0x61,0xa3,0xd9,1, -0x64,0x50,0x6e,0x13,0x68,0x61,0x6c,0x61,0x50,0x1d,0x61,0x72,0x63,0x68,0x61,0x69, -0x63,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0xf9,0x13,0x64,0x68,0x61,0x6d,0xa3, -0xf8,5,0x72,0x35,0x72,0x44,0x73,0x64,0x75,1,0x61,0xa3,0x4e,0x6e,0x17,0x63, -0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x71,0x17,0x69,0x76,0x61,0x74,0x65,0x75,0x73, -0x65,0xa2,0x4e,0x13,0x61,0x72,0x65,0x61,0xa3,0x4e,0x1b,0x61,0x6c,0x74,0x65,0x72, -0x70,0x61,0x68,0x6c,0x61,0x76,0x69,0xa3,0xf6,0x61,0x40,0x68,0x82,0x6c,0x19,0x61, -0x79,0x69,0x6e,0x67,0x63,0x61,0x72,0x64,0x73,0xa3,0xcc,2,0x68,0x38,0x6c,0x4a, -0x75,0x15,0x63,0x69,0x6e,0x68,0x61,0x75,0xa3,0xf5,0x17,0x61,0x77,0x68,0x68,0x6d, -0x6f,0x6e,0x67,0xa3,0xf3,0x15,0x6d,0x79,0x72,0x65,0x6e,0x65,0xa3,0xf4,1,0x61, -0x8e,0x6f,1,0x65,0x74,0x6e,0x16,0x65,0x74,0x69,0x63,0x65,0x78,0x74,0xa2,0x72, -1,0x65,0x2c,0x73,0x11,0x75,0x70,0xa3,0x8d,0x15,0x6e,0x73,0x69,0x6f,0x6e,0x73, -0xa2,0x72,0x19,0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x8d,0x15, -0x6e,0x69,0x63,0x69,0x61,0x6e,0xa3,0x97,1,0x67,0x3e,0x69,0x13,0x73,0x74,0x6f, -0x73,0xa2,0xa6,0x13,0x64,0x69,0x73,0x63,0xa3,0xa6,0x12,0x73,0x70,0x61,0xa3,0x96, -1,0x65,0x5c,0x75,1,0x6d,0x2a,0x6e,0x11,0x69,0x63,0x67,0x10,0x69,0xa2,0xc0, -0x1d,0x6e,0x75,0x6d,0x65,0x72,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3, -0xc0,0x13,0x6a,0x61,0x6e,0x67,0xa3,0xa3,0x6d,0xa2,0xe6,0x6e,0xa8,0x19,0x6f,6, -0x70,0x63,0x70,0x56,0x72,0x8a,0x73,0xa2,0x4c,0x74,0x10,0x74,0x1f,0x6f,0x6d,0x61, -0x6e,0x73,0x69,0x79,0x61,0x71,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa5,0x28,0x18, -0x74,0x69,0x63,0x61,0x6c,0x63,0x68,0x61,0x72,0x1f,0x61,0x63,0x74,0x65,0x72,0x72, -0x65,0x63,0x6f,0x67,0x6e,0x69,0x74,0x69,0x6f,0x6e,0x85,1,0x69,0x46,0x6e,0x1e, -0x61,0x6d,0x65,0x6e,0x74,0x61,0x6c,0x64,0x69,0x6e,0x67,0x62,0x61,0x74,0x73,0xa3, -0xf2,0x11,0x79,0x61,0x47,1,0x61,0x30,0x6d,0x13,0x61,0x6e,0x79,0x61,0xa3,0x7a, -0x11,0x67,0x65,0xa5,0xf,0x63,0xa2,0x71,0x67,0xa2,0x71,0x6c,1,0x63,0xa2,0x62, -0x64,5,0x70,0x38,0x70,0x36,0x73,0x56,0x74,0x14,0x75,0x72,0x6b,0x69,0x63,0xa3, -0xbf,0x11,0x65,0x72,1,0x6d,0x2e,0x73,0x12,0x69,0x61,0x6e,0xa3,0x8c,0x11,0x69, -0x63,0xa3,0xf1,0x10,0x6f,1,0x67,0x3a,0x75,0x18,0x74,0x68,0x61,0x72,0x61,0x62, -0x69,0x61,0x6e,0xa3,0xbb,0x13,0x64,0x69,0x61,0x6e,0xa5,0x22,0x68,0x42,0x69,0x54, -0x6e,0x1a,0x6f,0x72,0x74,0x68,0x61,0x72,0x61,0x62,0x69,0x61,0x6e,0xa3,0xf0,0x17, -0x75,0x6e,0x67,0x61,0x72,0x69,0x61,0x6e,0xa5,4,0x14,0x74,0x61,0x6c,0x69,0x63, -0xa3,0x58,0x13,0x68,0x69,0x6b,0x69,0xa3,0x9d,0x10,0x72,0x85,0x12,0x68,0x61,0x6d, -0x65,6,0x6f,0x86,0x6f,0x6c,0x72,0xa2,0x61,0x75,0xa2,0x62,0x79,0x14,0x61,0x6e, -0x6d,0x61,0x72,0x58,0x12,0x65,0x78,0x74,2,0x61,0xa3,0xb6,0x62,0xa3,0xee,0x65, -0x13,0x6e,0x64,0x65,0x64,1,0x61,0xa3,0xb6,0x62,0xa3,0xee,1,0x64,0x52,0x6e, -0x15,0x67,0x6f,0x6c,0x69,0x61,0x6e,0x6a,0x12,0x73,0x75,0x70,0xa4,0xd,0x16,0x70, -0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0xd,0x10,0x69,0xa2,0xec,0x13,0x66,0x69,0x65, -0x72,1,0x6c,0x3c,0x74,0x19,0x6f,0x6e,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x73, -0xa3,0x8a,0x15,0x65,0x74,0x74,0x65,0x72,0x73,0x2d,0x10,0x6f,0xa3,0xed,1,0x6c, -0x44,0x73,0x11,0x69,0x63,0xa2,0x5c,0x18,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c, -0x73,0xa3,0x5c,0x13,0x74,0x61,0x6e,0x69,0xa5,3,0x61,0xa2,0x9b,0x65,0xa4,0x4c, -0x69,1,0x61,0xa2,0x8f,0x73,0x10,0x63,5,0x70,0x18,0x70,0xa2,0x71,0x73,0x36, -0x74,0x17,0x65,0x63,0x68,0x6e,0x69,0x63,0x61,0x6c,0x81,0x15,0x79,0x6d,0x62,0x6f, -0x6c,0x73,0x8f,0x61,0xa2,0x66,0x65,0x46,0x6d,0x19,0x61,0x74,0x68,0x73,0x79,0x6d, -0x62,0x6f,0x6c,0x73,1,0x61,0xa3,0x66,0x62,0xa3,0x69,0x17,0x6c,0x6c,0x61,0x6e, -0x65,0x6f,0x75,0x73,2,0x6d,0x3a,0x73,0x6c,0x74,0x17,0x65,0x63,0x68,0x6e,0x69, -0x63,0x61,0x6c,0x81,0x11,0x61,0x74,0x1f,0x68,0x65,0x6d,0x61,0x74,0x69,0x63,0x61, -0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,1,0x61,0xa3,0x66,0x62,0xa3,0x69,0x15, -0x79,0x6d,0x62,0x6f,0x6c,0x73,0x8e,0x12,0x61,0x6e,0x64,1,0x61,0x3c,0x70,0x19, -0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa3,0xcd,0x14,0x72,0x72,0x6f, -0x77,0x73,0xa3,0x73,0x10,0x6f,0xa3,0xd8,7,0x72,0x6f,0x72,0x44,0x73,0x4e,0x74, -0x62,0x79,0x19,0x61,0x6e,0x6e,0x75,0x6d,0x65,0x72,0x61,0x6c,0x73,0xa5,0x20,0x13, -0x63,0x68,0x65,0x6e,0xa5,0xc,0x18,0x61,0x72,0x61,0x6d,0x67,0x6f,0x6e,0x64,0x69, -0xa5,0x14,0x10,0x68,2,0x61,0x3a,0x65,0x4a,0x6f,0x17,0x70,0x65,0x72,0x61,0x74, -0x6f,0x72,0x73,0x7f,0x16,0x6c,0x70,0x68,0x61,0x6e,0x75,0x6d,0xa3,0x5d,0x16,0x6d, -0x61,0x74,0x69,0x63,0x61,0x6c,1,0x61,0x36,0x6f,0x17,0x70,0x65,0x72,0x61,0x74, -0x6f,0x72,0x73,0x7f,0x11,0x6c,0x70,0x1f,0x68,0x61,0x6e,0x75,0x6d,0x65,0x72,0x69, -0x63,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5d,0x68,0x50,0x6b,0x7e,0x6c,0x88, -0x6e,1,0x64,0x34,0x69,0x15,0x63,0x68,0x61,0x65,0x61,0x6e,0xa3,0xea,0x12,0x61, -0x69,0x63,0xa3,0xc6,1,0x61,0x3e,0x6a,0x12,0x6f,0x6e,0x67,0xa2,0xaa,0x14,0x74, -0x69,0x6c,0x65,0x73,0xa3,0xaa,0x13,0x6a,0x61,0x6e,0x69,0xa3,0xe9,0x13,0x61,0x73, -0x61,0x72,0xa5,0x1f,0x15,0x61,0x79,0x61,0x6c,0x61,0x6d,0x4f,3,0x64,0x6c,0x65, -0x7e,0x6e,0xa2,0x47,0x72,0x14,0x6f,0x69,0x74,0x69,0x63,1,0x63,0x3c,0x68,0x19, -0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0xd7,0x15,0x75,0x72,0x73, -0x69,0x76,0x65,0xa3,0xd6,0x17,0x65,0x66,0x61,0x69,0x64,0x72,0x69,0x6e,0xa5,0x21, -0x17,0x74,0x65,0x69,0x6d,0x61,0x79,0x65,0x6b,0xa2,0xb8,0x12,0x65,0x78,0x74,0xa2, -0xd5,0x16,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa3,0xd5,0x18,0x64,0x65,0x6b,0x69, -0x6b,0x61,0x6b,0x75,0x69,0xa3,0xeb,6,0x6b,0x3b,0x6b,0x56,0x6f,0x5a,0x75,0x64, -0x79,0x11,0x69,0x61,0x1f,0x6b,0x65,0x6e,0x67,0x70,0x75,0x61,0x63,0x68,0x75,0x65, -0x68,0x6d,0x6f,0x6e,0x67,0xa5,0x27,0x10,0x6f,0xa3,0x92,0x14,0x62,0x6c,0x6f,0x63, -0x6b,0x21,1,0x6d,0x2c,0x73,0x11,0x68,0x75,0xa5,0x15,0x17,0x62,0x65,0x72,0x66, -0x6f,0x72,0x6d,0x73,0x7b,0x61,0x44,0x62,0x21,0x65,0x10,0x77,1,0x61,0xa5,0xe, -0x74,0x14,0x61,0x69,0x6c,0x75,0x65,0xa3,0x8b,1,0x62,0x38,0x6e,0x17,0x64,0x69, -0x6e,0x61,0x67,0x61,0x72,0x69,0xa5,0x26,0x15,0x61,0x74,0x61,0x65,0x61,0x6e,0xa3, -0xef,0x67,0xc4,0xe,0x6a,0xc1,0x95,0x6a,0xa2,0xc5,0x6b,0xa2,0xde,0x6c,4,0x61, -0x54,0x65,0xa2,0x61,0x69,0xa2,0x78,0x6f,0xa2,0xa7,0x79,1,0x63,0x2e,0x64,0x12, -0x69,0x61,0x6e,0xa3,0xa9,0x12,0x69,0x61,0x6e,0xa3,0xa7,1,0x6f,0x55,0x74,0x11, -0x69,0x6e,1,0x31,0x82,0x65,0x11,0x78,0x74,4,0x61,0x5c,0x62,0x29,0x63,0xa3, -0x94,0x64,0xa3,0x95,0x65,0xa2,0xe7,0x13,0x6e,0x64,0x65,0x64,4,0x61,0x36,0x62, -0x29,0x63,0xa3,0x94,0x64,0xa3,0x95,0x65,0xa3,0xe7,0x26,0x18,0x64,0x64,0x69,0x74, -0x69,0x6f,0x6e,0x61,0x6c,0x6d,0x24,0x12,0x73,0x75,0x70,0x24,0x16,0x70,0x6c,0x65, -0x6d,0x65,0x6e,0x74,0x25,1,0x70,0x42,0x74,0x1d,0x74,0x65,0x72,0x6c,0x69,0x6b, -0x65,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x79,0x12,0x63,0x68,0x61,0xa3,0x9c,2, -0x6d,0x2e,0x6e,0x34,0x73,0x10,0x75,0xa3,0xb0,0x11,0x62,0x75,0xa3,0x6f,0x12,0x65, -0x61,0x72,1,0x61,0xa3,0xe8,0x62,1,0x69,0x38,0x73,0x17,0x79,0x6c,0x6c,0x61, -0x62,0x61,0x72,0x79,0xa3,0x75,0x17,0x64,0x65,0x6f,0x67,0x72,0x61,0x6d,0x73,0xa3, -0x76,0x1a,0x77,0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4d,0x10, -0x61,1,0x6d,0x32,0x76,0x14,0x61,0x6e,0x65,0x73,0x65,0xa3,0xb5,0x10,0x6f,0x5c, -0x12,0x65,0x78,0x74,1,0x61,0xa3,0xb4,0x62,0xa3,0xb9,1,0x61,0x80,0x68,3, -0x61,0x3c,0x6d,0x4c,0x6f,0x64,0x75,0x15,0x64,0x61,0x77,0x61,0x64,0x69,0xa3,0xe6, -0x16,0x72,0x6f,0x73,0x68,0x74,0x68,0x69,0xa3,0x89,0x11,0x65,0x72,0x68,0x16,0x73, -0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x71,0x12,0x6a,0x6b,0x69,0xa3,0xe5,3,0x69, -0x3a,0x6e,0x42,0x74,0xa2,0x51,0x79,0x13,0x61,0x68,0x6c,0x69,0xa3,0xa2,0x12,0x74, -0x68,0x69,0xa3,0xc1,3,0x61,0x34,0x62,0x76,0x67,0x7c,0x6e,0x12,0x61,0x64,0x61, -0x4d,1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2,0xcb,0x16,0x70,0x6c,0x65,0x6d,0x65, -0x6e,0x74,0xa3,0xcb,0x11,0x78,0x74,1,0x61,0xa5,0x13,0x65,0x14,0x6e,0x64,0x65, -0x64,0x61,0xa5,0x13,0x11,0x75,0x6e,0xa3,0x42,0x11,0x78,0x69,0x96,0x17,0x72,0x61, -0x64,0x69,0x63,0x61,0x6c,0x73,0x97,0x14,0x61,0x6b,0x61,0x6e,0x61,0x9e,1,0x65, -0x4c,0x70,0x10,0x68,0x1f,0x6f,0x6e,0x65,0x74,0x69,0x63,0x65,0x78,0x74,0x65,0x6e, -0x73,0x69,0x6f,0x6e,0x73,0xa3,0x6b,0x11,0x78,0x74,0xa3,0x6b,0x67,0xa2,0xb5,0x68, -0xa4,0x84,0x69,3,0x64,0x4c,0x6d,0xa2,0x55,0x6e,0xa2,0x62,0x70,0x13,0x61,0x65, -0x78,0x74,0x2a,0x16,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0x2b,1,0x63,0x99,0x65, -0x17,0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63,1,0x64,0x56,0x73,0x15,0x79,0x6d, -0x62,0x6f,0x6c,0x73,0xa4,0xb,0x1d,0x61,0x6e,0x64,0x70,0x75,0x6e,0x63,0x74,0x75, -0x61,0x74,0x69,0x6f,0x6e,0xa5,0xb,0x13,0x65,0x73,0x63,0x72,0x1f,0x69,0x70,0x74, -0x69,0x6f,0x6e,0x63,0x68,0x61,0x72,0x61,0x63,0x74,0x65,0x72,0x73,0x99,0x1c,0x70, -0x65,0x72,0x69,0x61,0x6c,0x61,0x72,0x61,0x6d,0x61,0x69,0x63,0xa3,0xba,1,0x64, -0x62,0x73,0x1b,0x63,0x72,0x69,0x70,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x70,0x61,1, -0x68,0x32,0x72,0x14,0x74,0x68,0x69,0x61,0x6e,0xa3,0xbd,0x13,0x6c,0x61,0x76,0x69, -0xa3,0xbe,0x11,0x69,0x63,1,0x6e,0x3e,0x73,0x1a,0x69,0x79,0x61,0x71,0x6e,0x75, -0x6d,0x62,0x65,0x72,0x73,0xa5,0x1e,0x19,0x75,0x6d,0x62,0x65,0x72,0x66,0x6f,0x72, -0x6d,0x73,0xa3,0xb2,4,0x65,0x74,0x6c,0xa2,0x82,0x6f,0xa2,0x9a,0x72,0xa2,0x9e, -0x75,2,0x6a,0x34,0x6e,0x3e,0x72,0x14,0x6d,0x75,0x6b,0x68,0x69,0x43,0x14,0x61, -0x72,0x61,0x74,0x69,0x45,0x18,0x6a,0x61,0x6c,0x61,0x67,0x6f,0x6e,0x64,0x69,0xa5, -0x1c,1,0x6e,0xa2,0x46,0x6f,1,0x6d,0x6e,0x72,0x13,0x67,0x69,0x61,0x6e,0x5a, -1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2,0x87,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e, -0x74,0xa3,0x87,0x11,0x78,0x74,0xa4,0x1b,0x14,0x65,0x6e,0x64,0x65,0x64,0xa5,0x1b, -0x1a,0x65,0x74,0x72,0x69,0x63,0x73,0x68,0x61,0x70,0x65,0x73,0x8c,0x12,0x65,0x78, -0x74,0xa2,0xe3,0x14,0x65,0x6e,0x64,0x65,0x64,0xa3,0xe3,0x1e,0x65,0x72,0x61,0x6c, -0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x71,0x17,0x61,0x67,0x6f, -0x6c,0x69,0x74,0x69,0x63,0xa2,0x88,0x12,0x73,0x75,0x70,0xa4,0xa,0x16,0x70,0x6c, -0x65,0x6d,0x65,0x6e,0x74,0xa5,0xa,0x13,0x74,0x68,0x69,0x63,0xa3,0x59,1,0x61, -0x5c,0x65,0x11,0x65,0x6b,0x30,1,0x61,0x38,0x65,0x11,0x78,0x74,0x6e,0x14,0x65, -0x6e,0x64,0x65,0x64,0x6f,0x17,0x6e,0x64,0x63,0x6f,0x70,0x74,0x69,0x63,0x31,0x13, -0x6e,0x74,0x68,0x61,0xa3,0xe4,2,0x61,0xa2,0x48,0x65,0xa2,0xdf,0x69,1,0x67, -0x30,0x72,0x14,0x61,0x67,0x61,0x6e,0x61,0x9d,0x10,0x68,1,0x70,0x3a,0x73,0x18, -0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4b,1,0x72,0x3c,0x75,0x19, -0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4c,0x11,0x69,0x76,0x1f, -0x61,0x74,0x65,0x75,0x73,0x65,0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73, -0xa3,0x4c,2,0x6c,0x32,0x6e,0x9a,0x74,0x12,0x72,0x61,0x6e,0xa5,2,0x10,0x66, -2,0x61,0x58,0x6d,0x70,0x77,0x14,0x69,0x64,0x74,0x68,0x61,0x1f,0x6e,0x64,0x66, -0x75,0x6c,0x6c,0x77,0x69,0x64,0x74,0x68,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x57,0x1a, -0x6e,0x64,0x66,0x75,0x6c,0x6c,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x57,0x13,0x61,0x72, -0x6b,0x73,0xa3,0x52,2,0x67,0x34,0x69,0xa2,0x45,0x75,0x12,0x6e,0x6f,0x6f,0xa3, -0x63,0x11,0x75,0x6c,0xa2,0x4a,2,0x63,0x3c,0x6a,0x5e,0x73,0x17,0x79,0x6c,0x6c, -0x61,0x62,0x6c,0x65,0x73,0xa3,0x4a,0x1f,0x6f,0x6d,0x70,0x61,0x74,0x69,0x62,0x69, -0x6c,0x69,0x74,0x79,0x6a,0x61,0x6d,0x6f,0xa3,0x41,0x12,0x61,0x6d,0x6f,0x5c,0x17, -0x65,0x78,0x74,0x65,0x6e,0x64,0x65,0x64,1,0x61,0xa3,0xb4,0x62,0xa3,0xb9,0x19, -0x66,0x69,0x72,0x6f,0x68,0x69,0x6e,0x67,0x79,0x61,0xa5,0x1d,0x13,0x62,0x72,0x65, -0x77,0x37,0x61,0xa4,5,0x62,0xa6,0x45,0x63,0xa8,0x1a,0x64,0xac,0xa6,0x65,5, -0x6d,0xa2,0x6d,0x86,0x6e,0x96,0x74,0x15,0x68,0x69,0x6f,0x70,0x69,0x63,0x5e,1, -0x65,0x40,0x73,0x11,0x75,0x70,0xa2,0x86,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, -0xa3,0x86,0x11,0x78,0x74,0xa2,0x85,1,0x61,0xa3,0xc8,0x65,0x13,0x6e,0x64,0x65, -0x64,0xa2,0x85,0x10,0x61,0xa3,0xc8,0x16,0x6f,0x74,0x69,0x63,0x6f,0x6e,0x73,0xa3, -0xce,0x15,0x63,0x6c,0x6f,0x73,0x65,0x64,2,0x61,0x5a,0x63,0x9e,0x69,0x1c,0x64, -0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x75,0x70,0xa2,0xc4,0x16,0x70, -0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xc4,0x16,0x6c,0x70,0x68,0x61,0x6e,0x75,0x6d, -0x86,1,0x65,0x2c,0x73,0x11,0x75,0x70,0xa3,0xc3,0x13,0x72,0x69,0x63,0x73,0x86, -0x18,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xc3,0x11,0x6a,0x6b,0xa2, -0x44,0x1f,0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0x61,0x6e,0x64,0x6d,0x6f,0x6e,0x74, -0x68,0x73,0xa3,0x44,0x61,0x4a,0x67,0x76,0x6c,1,0x62,0x30,0x79,0x13,0x6d,0x61, -0x69,0x63,0xa5,0x25,0x13,0x61,0x73,0x61,0x6e,0xa3,0xe2,0x13,0x72,0x6c,0x79,0x64, -0x1f,0x79,0x6e,0x61,0x73,0x74,0x69,0x63,0x63,0x75,0x6e,0x65,0x69,0x66,0x6f,0x72, -0x6d,0xa5,1,0x1f,0x79,0x70,0x74,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67, -0x6c,0x79,0x70,0x68,1,0x66,0x26,0x73,0xa3,0xc2,0x1c,0x6f,0x72,0x6d,0x61,0x74, -0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x73,0xa5,0x24,7,0x6e,0xc0,0xe5,0x6e,0x3e, -0x72,0xa2,0x5d,0x73,0xa2,0xd8,0x76,0x14,0x65,0x73,0x74,0x61,0x6e,0xa3,0xbc,1, -0x61,0x92,0x63,0x13,0x69,0x65,0x6e,0x74,1,0x67,0x34,0x73,0x15,0x79,0x6d,0x62, -0x6f,0x6c,0x73,0xa3,0xa5,0x13,0x72,0x65,0x65,0x6b,1,0x6d,0x34,0x6e,0x15,0x75, -0x6d,0x62,0x65,0x72,0x73,0xa3,0x7f,0x13,0x75,0x73,0x69,0x63,0xa2,0x7e,0x19,0x61, -0x6c,0x6e,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x7e,0x10,0x74,0x1f,0x6f,0x6c, -0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0xfe, -2,0x61,0x32,0x6d,0xa2,0x71,0x72,0x12,0x6f,0x77,0x73,0x7d,0x12,0x62,0x69,0x63, -0x38,3,0x65,0x4a,0x6d,0x66,0x70,0xa2,0x43,0x73,0x11,0x75,0x70,0xa2,0x80,0x16, -0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x80,0x11,0x78,0x74,1,0x61,0xa3,0xd2, -0x65,0x14,0x6e,0x64,0x65,0x64,0x61,0xa3,0xd2,0x12,0x61,0x74,0x68,0xa2,0xd3,0x18, -0x65,0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,0x61,0x1f,0x6c,0x70,0x68,0x61,0x62,0x65, -0x74,0x69,0x63,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xd3,1,0x66,0x42,0x72, -0x1e,0x65,0x73,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x66,0x6f,0x72,0x6d,0x73, -1,0x61,0xa3,0x51,0x62,0xa3,0x55,0x14,0x65,0x6e,0x69,0x61,0x6e,0x35,0x12,0x63, -0x69,0x69,0x23,0x64,0x9e,0x65,0xa2,0x42,0x68,0xa2,0x4d,0x6c,1,0x63,0x62,0x70, -0x17,0x68,0x61,0x62,0x65,0x74,0x69,0x63,0x70,1,0x66,0xa3,0x50,0x72,0x1e,0x65, -0x73,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x50, -0x16,0x68,0x65,0x6d,0x69,0x63,0x61,0x6c,0xa2,0xd0,0x16,0x73,0x79,0x6d,0x62,0x6f, -0x6c,0x73,0xa3,0xd0,0x12,0x6c,0x61,0x6d,0xa5,7,0x1a,0x67,0x65,0x61,0x6e,0x6e, -0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0x77,0x11,0x6f,0x6d,0xa3,0xfd,7,0x6f,0x71, -0x6f,0x64,0x72,0xa2,0x41,0x75,0xa2,0x58,0x79,0x1b,0x7a,0x61,0x6e,0x74,0x69,0x6e, -0x65,0x6d,0x75,0x73,0x69,0x63,0xa2,0x5b,0x18,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f, -0x6c,0x73,0xa3,0x5b,1,0x70,0x34,0x78,0x16,0x64,0x72,0x61,0x77,0x69,0x6e,0x67, -0x89,0x14,0x6f,0x6d,0x6f,0x66,0x6f,0xa0,0x12,0x65,0x78,0x74,0xa2,0x43,0x14,0x65, -0x6e,0x64,0x65,0x64,0xa3,0x43,0x10,0x61,1,0x68,0x40,0x69,0x12,0x6c,0x6c,0x65, -0x92,0x17,0x70,0x61,0x74,0x74,0x65,0x72,0x6e,0x73,0x93,0x11,0x6d,0x69,0xa3,0xc9, -1,0x67,0x2c,0x68,0x11,0x69,0x64,0xa3,0x64,0x14,0x69,0x6e,0x65,0x73,0x65,0xa3, -0x81,0x61,0x48,0x65,0xa2,0x4e,0x68,0xa2,0x52,0x6c,0x1a,0x6f,0x63,0x6b,0x65,0x6c, -0x65,0x6d,0x65,0x6e,0x74,0x73,0x8b,3,0x6c,0x34,0x6d,0x40,0x73,0x66,0x74,0x11, -0x61,0x6b,0xa3,0xc7,0x14,0x69,0x6e,0x65,0x73,0x65,0xa3,0x93,0x11,0x75,0x6d,0xa2, -0xb1,0x12,0x73,0x75,0x70,0xa2,0xca,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3, -0xca,1,0x69,0x30,0x73,0x13,0x61,0x76,0x61,0x68,0xa3,0xdd,0x15,0x63,0x6c,0x61, -0x74,0x69,0x6e,0x23,0x14,0x6e,0x67,0x61,0x6c,0x69,0x41,0x16,0x61,0x69,0x6b,0x73, -0x75,0x6b,0x69,0xa5,8,5,0x6f,0xc1,0x4c,0x6f,0xa2,0x55,0x75,0xa4,0x10,0x79, -1,0x70,0x9c,0x72,0x14,0x69,0x6c,0x6c,0x69,0x63,0x32,1,0x65,0x4c,0x73,0x11, -0x75,0x70,0xa2,0x61,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa2,0x61,0x12,0x61, -0x72,0x79,0xa3,0x61,0x11,0x78,0x74,3,0x61,0xa3,0x9e,0x62,0xa3,0xa0,0x63,0xa5, -9,0x65,0x13,0x6e,0x64,0x65,0x64,2,0x61,0xa3,0x9e,0x62,0xa3,0xa0,0x63,0xa5, -9,0x1c,0x72,0x69,0x6f,0x74,0x73,0x79,0x6c,0x6c,0x61,0x62,0x61,0x72,0x79,0xa3, -0x7b,3,0x6d,0x5a,0x6e,0xa2,0x95,0x70,0xa2,0xa0,0x75,0x17,0x6e,0x74,0x69,0x6e, -0x67,0x72,0x6f,0x64,0xa2,0x9a,0x17,0x6e,0x75,0x6d,0x65,0x72,0x61,0x6c,0x73,0xa3, -0x9a,2,0x62,0x3a,0x6d,0xa2,0x5f,0x70,0x15,0x61,0x74,0x6a,0x61,0x6d,0x6f,0xa3, -0x41,0x14,0x69,0x6e,0x69,0x6e,0x67,2,0x64,0x46,0x68,0x9e,0x6d,0x1d,0x61,0x72, -0x6b,0x73,0x66,0x6f,0x72,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x77,0x1e,0x69,0x61, -0x63,0x72,0x69,0x74,0x69,0x63,0x61,0x6c,0x6d,0x61,0x72,0x6b,0x73,0x2e,2,0x65, -0x40,0x66,0xa6,0x2a,0x73,0x18,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3, -0x83,0x16,0x78,0x74,0x65,0x6e,0x64,0x65,0x64,0xa3,0xe0,0x17,0x61,0x6c,0x66,0x6d, -0x61,0x72,0x6b,0x73,0xa3,0x52,0x11,0x6f,0x6e,0x1f,0x69,0x6e,0x64,0x69,0x63,0x6e, -0x75,0x6d,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d,0x73,0xa3,0xb2,0x1b,0x74,0x72,0x6f, -0x6c,0x70,0x69,0x63,0x74,0x75,0x72,0x65,0x73,0x83,0x12,0x74,0x69,0x63,0xa2,0x84, -0x1b,0x65,0x70,0x61,0x63,0x74,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0xdf,1, -0x6e,0x3e,0x72,0x1b,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73, -0x75,0x15,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa2,0x98,0x16,0x6e,0x75,0x6d,0x62,0x65, -0x72,0x73,0xa2,0x99,0x1d,0x61,0x6e,0x64,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74, -0x69,0x6f,0x6e,0xa3,0x99,0x61,0xa2,0xdb,0x68,0xa4,5,0x6a,0x10,0x6b,0xa2,0x47, -4,0x63,0x86,0x65,0xa2,0x7d,0x72,0xa2,0x92,0x73,0xa2,0xa4,0x75,0x1f,0x6e,0x69, -0x66,0x69,0x65,0x64,0x69,0x64,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa2,0x47, -0x18,0x65,0x78,0x74,0x65,0x6e,0x73,0x69,0x6f,0x6e,5,0x64,0x65,0x64,0xa3,0xd1, -0x65,0xa5,0,0x66,0xa5,0x12,0x14,0x6f,0x6d,0x70,0x61,0x74,0xa2,0x45,1,0x66, -0x96,0x69,1,0x62,0x44,0x64,0x17,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa2, -0x4f,0x12,0x73,0x75,0x70,0xa3,0x5f,0x14,0x69,0x6c,0x69,0x74,0x79,0xa2,0x45,1, -0x66,0x54,0x69,0x18,0x64,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa2,0x4f,0x19, -0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x5f,0x13,0x6f,0x72,0x6d, -0x73,0xa3,0x53,0x11,0x78,0x74,5,0x64,9,0x64,0xa3,0xd1,0x65,0xa5,0,0x66, -0xa5,0x12,0x61,0xa3,0x46,0x62,0xa3,0x5e,0x63,0xa3,0xc5,0x19,0x61,0x64,0x69,0x63, -0x61,0x6c,0x73,0x73,0x75,0x70,0x94,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x95, -1,0x74,0x50,0x79,0x14,0x6d,0x62,0x6f,0x6c,0x73,0x9a,0x1d,0x61,0x6e,0x64,0x70, -0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x9b,0x14,0x72,0x6f,0x6b,0x65, -0x73,0xa3,0x82,2,0x6e,0x48,0x72,0x64,0x75,0x1d,0x63,0x61,0x73,0x69,0x61,0x6e, -0x61,0x6c,0x62,0x61,0x6e,0x69,0x61,0x6e,0xa3,0xde,0x1d,0x61,0x64,0x69,0x61,0x6e, -0x73,0x79,0x6c,0x6c,0x61,0x62,0x69,0x63,0x73,0x63,0x12,0x69,0x61,0x6e,0xa3,0xa8, -1,0x61,0x6c,0x65,1,0x72,0x38,0x73,0x17,0x73,0x73,0x79,0x6d,0x62,0x6f,0x6c, -0x73,0xa5,0x19,0x13,0x6f,0x6b,0x65,0x65,0x60,0x12,0x73,0x75,0x70,0xa2,0xff,0x16, -0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xff,1,0x6b,0x26,0x6d,0xa3,0xa4,0x11, -0x6d,0x61,0xa3,0xd4,3,0x65,0x3e,0x69,0x7e,0x6f,0xa2,0x5d,0x75,0x15,0x70,0x6c, -0x6f,0x79,0x61,0x6e,0xa3,0xe1,1,0x73,0x50,0x76,0x16,0x61,0x6e,0x61,0x67,0x61, -0x72,0x69,0x3e,0x12,0x65,0x78,0x74,0xa2,0xb3,0x14,0x65,0x6e,0x64,0x65,0x64,0xa3, -0xb3,0x13,0x65,0x72,0x65,0x74,0xa3,0x5a,1,0x61,0x30,0x6e,0x14,0x67,0x62,0x61, -0x74,0x73,0x91,0x18,0x63,0x72,0x69,0x74,0x69,0x63,0x61,0x6c,0x73,0x2e,2,0x65, -0x30,0x66,0x36,0x73,0x11,0x75,0x70,0xa3,0x83,0x11,0x78,0x74,0xa3,0xe0,0x18,0x6f, -0x72,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x77,1,0x67,0x3e,0x6d,0x12,0x69,0x6e, -0x6f,0xa2,0xab,0x14,0x74,0x69,0x6c,0x65,0x73,0xa3,0xab,0x11,0x72,0x61,0xa5,0x1a, -8,0x6d,0x5f,0x6d,0x3a,0x6e,0x48,0x73,0x7a,0x76,0xa2,0x4b,0x77,0x12,0x69,0x64, -0x65,0x43,0x11,0x65,0x64,0x32,0x12,0x69,0x61,0x6c,0x33,2,0x61,0x40,0x62,0x37, -0x6f,1,0x62,0x28,0x6e,0x10,0x65,0x21,0x13,0x72,0x65,0x61,0x6b,0x37,0x10,0x72, -0x34,0x12,0x72,0x6f,0x77,0x35,2,0x6d,0x38,0x71,0x46,0x75,1,0x62,0x3d,0x70, -0x3e,0x11,0x65,0x72,0x3f,1,0x61,0x24,0x6c,0x39,0x11,0x6c,0x6c,0x39,1,0x72, -0x3b,0x75,0x12,0x61,0x72,0x65,0x3b,0x12,0x65,0x72,0x74,0x40,0x13,0x69,0x63,0x61, -0x6c,0x41,0x63,0x58,0x65,0x92,0x66,0x96,0x69,1,0x6e,0x36,0x73,0x10,0x6f,0x30, -0x14,0x6c,0x61,0x74,0x65,0x64,0x31,0x11,0x69,0x74,0x2e,0x12,0x69,0x61,0x6c,0x2f, -2,0x61,0x36,0x69,0x48,0x6f,0x10,0x6d,0x24,0x12,0x70,0x61,0x74,0x25,0x10,0x6e, -0x22,0x15,0x6f,0x6e,0x69,0x63,0x61,0x6c,0x23,0x13,0x72,0x63,0x6c,0x65,0x27,0x11, -0x6e,0x63,0x27,2,0x69,0x3a,0x6f,0x44,0x72,0x10,0x61,0x2c,0x14,0x63,0x74,0x69, -0x6f,0x6e,0x2d,0x10,0x6e,0x28,0x11,0x61,0x6c,0x29,0x11,0x6e,0x74,0x2b,4,0x61, -0x3a,0x66,0x4c,0x68,0x5e,0x6e,0x70,0x77,0x2a,0x12,0x69,0x64,0x65,0x2b,0x22,0x17, -0x6d,0x62,0x69,0x67,0x75,0x6f,0x75,0x73,0x23,0x26,0x17,0x75,0x6c,0x6c,0x77,0x69, -0x64,0x74,0x68,0x27,0x24,0x17,0x61,0x6c,0x66,0x77,0x69,0x64,0x74,0x68,0x25,0x20, -1,0x61,0x30,0x65,0x14,0x75,0x74,0x72,0x61,0x6c,0x21,0x28,0x13,0x72,0x72,0x6f, -0x77,0x29,0xd,0x6e,0xc0,0xfb,0x73,0x6d,0x73,0x3a,0x74,0x98,0x75,0xa2,0x49,0x7a, -2,0x6c,0x3b,0x70,0x3d,0x73,0x39,5,0x6f,0x28,0x6f,0x57,0x70,0x34,0x75,0x16, -0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x45,0x11,0x61,0x63,1,0x65,0x32,0x69,0x15, -0x6e,0x67,0x6d,0x61,0x72,0x6b,0x31,0x18,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f, -0x72,0x39,0x63,0x53,0x6b,0x55,0x6d,0x51,0x1d,0x69,0x74,0x6c,0x65,0x63,0x61,0x73, -0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x27,1,0x6e,0x40,0x70,0x1c,0x70,0x65,0x72, -0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x23,0x17,0x61,0x73,0x73,0x69, -0x67,0x6e,0x65,0x64,0x21,0x6e,0x8a,0x6f,0xa2,0x47,0x70,8,0x66,0x14,0x66,0x5b, -0x69,0x59,0x6f,0x4f,0x72,0x24,0x73,0x49,0x17,0x69,0x76,0x61,0x74,0x65,0x75,0x73, -0x65,0x43,0x61,0x2c,0x63,0x4d,0x64,0x47,0x65,0x4b,0x1f,0x72,0x61,0x67,0x72,0x61, -0x70,0x68,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x3d,2,0x64,0x33,0x6c, -0x35,0x6f,0x36,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b, -0x2d,1,0x70,0x7c,0x74,0x12,0x68,0x65,0x72,3,0x6c,0x38,0x6e,0x42,0x70,0x4c, -0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0x57,0x14,0x65,0x74,0x74,0x65,0x72,0x2b,0x14, -0x75,0x6d,0x62,0x65,0x72,0x37,0x19,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f, -0x6e,0x4f,0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e, -0x49,0x66,0x9e,0x66,0x88,0x69,0xa2,0x4b,0x6c,0xa2,0x5c,0x6d,4,0x61,0x60,0x63, -0x31,0x65,0x2f,0x6e,0x2d,0x6f,0x15,0x64,0x69,0x66,0x69,0x65,0x72,1,0x6c,0x30, -0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0x55,0x14,0x65,0x74,0x74,0x65,0x72,0x29,0x17, -0x74,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x51,1,0x69,0x2e,0x6f,0x13,0x72,0x6d, -0x61,0x74,0x41,0x1d,0x6e,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69, -0x6f,0x6e,0x5b,0x10,0x6e,0x1f,0x69,0x74,0x69,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74, -0x75,0x61,0x74,0x69,0x6f,0x6e,0x59,6,0x6d,0x18,0x6d,0x29,0x6f,0x28,0x74,0x27, -0x75,0x23,0x2a,0x1c,0x77,0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65, -0x72,0x25,0x65,0x28,0x69,0x3c,0x6c,0x25,0x19,0x74,0x74,0x65,0x72,0x6e,0x75,0x6d, -0x62,0x65,0x72,0x35,0x1a,0x6e,0x65,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72, -0x3b,0x63,0x44,0x64,0xa2,0x60,0x65,0x1b,0x6e,0x63,0x6c,0x6f,0x73,0x69,0x6e,0x67, -0x6d,0x61,0x72,0x6b,0x2f,6,0x6e,0x39,0x6e,0x46,0x6f,0x4e,0x73,0x45,0x75,0x1b, -0x72,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x53,0x20,0x12,0x74, -0x72,0x6c,0x3f,0x42,0x10,0x6e,1,0x6e,0x2c,0x74,0x12,0x72,0x6f,0x6c,0x3f,0x1f, -0x65,0x63,0x74,0x6f,0x72,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e, -0x4d,0x63,0x3f,0x66,0x41,0x6c,0x1d,0x6f,0x73,0x65,0x70,0x75,0x6e,0x63,0x74,0x75, -0x61,0x74,0x69,0x6f,0x6e,0x4b,2,0x61,0x30,0x65,0x4a,0x69,0x12,0x67,0x69,0x74, -0x33,0x1c,0x73,0x68,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x47, -0x1a,0x63,0x69,0x6d,0x61,0x6c,0x6e,0x75,0x6d,0x62,0x65,0x72,0x33,0,0x12,0x6d, -0xc2,0x3f,0x73,0xa1,0x73,0x4e,0x74,0xa2,0x56,0x77,0xa2,0x72,0x79,0xa2,0x73,0x7a, -1,0x61,0x2c,0x68,0x12,0x61,0x69,0x6e,0x8b,0x11,0x69,0x6e,0x85,5,0x74,0x22, -0x74,0x38,0x77,0x4c,0x79,0x16,0x72,0x69,0x61,0x63,0x77,0x61,0x77,0x6f,0x18,0x72, -0x61,0x69,0x67,0x68,0x74,0x77,0x61,0x77,0xa3,0x55,0x15,0x61,0x73,0x68,0x6b,0x61, -0x66,0x6d,0x61,0x2e,0x65,0x38,0x68,0x11,0x69,0x6e,0x6b,0x10,0x64,0x62,0x11,0x68, -0x65,0x65,1,0x65,0x2e,0x6d,0x13,0x6b,0x61,0x74,0x68,0x69,0x10,0x6e,0x67,1, -0x61,0x4e,0x65,1,0x68,0x28,0x74,0x10,0x68,0x77,0x16,0x6d,0x61,0x72,0x62,0x75, -0x74,0x61,0x74,0x13,0x67,0x6f,0x61,0x6c,0x3d,1,0x68,0x71,0x77,0x73,0x11,0x61, -0x77,0x79,1,0x65,0x32,0x75,0x11,0x64,0x68,0x80,0x11,0x68,0x65,0x83,0x10,0x68, -0x7a,1,0x62,0x34,0x77,0x16,0x69,0x74,0x68,0x74,0x61,0x69,0x6c,0x7f,0x14,0x61, -0x72,0x72,0x65,0x65,0x7d,0x6d,0x6c,0x6e,0xa4,0x6b,0x70,0xa4,0x88,0x71,0xa4,0x88, -0x72,1,0x65,0x38,0x6f,0x18,0x68,0x69,0x6e,0x67,0x79,0x61,0x79,0x65,0x68,0x93, -1,0x68,0x5f,0x76,0x16,0x65,0x72,0x73,0x65,0x64,0x70,0x65,0x61,2,0x61,0x2e, -0x65,0xa4,0x3e,0x69,0x10,0x6d,0x53,1,0x6c,0xa2,0xe7,0x6e,0x16,0x69,0x63,0x68, -0x61,0x65,0x61,0x6e,0,0x12,0x6e,0x76,0x73,0x51,0x73,0x3e,0x74,0x5c,0x77,0xa0, -0x79,0xa2,0x42,0x7a,0x13,0x61,0x79,0x69,0x6e,0xa3,0x54,0x10,0x61,1,0x64,0x2e, -0x6d,0x12,0x65,0x6b,0x68,0xa3,0x4c,0x11,0x68,0x65,0xa3,0x4b,3,0x61,0x38,0x65, -0x3c,0x68,0x4a,0x77,0x13,0x65,0x6e,0x74,0x79,0xa3,0x51,0x10,0x77,0xa3,0x4d,1, -0x6e,0xa3,0x4e,0x74,0x10,0x68,0xa3,0x4f,0x14,0x61,0x6d,0x65,0x64,0x68,0xa3,0x50, -0x11,0x61,0x77,0xa3,0x52,0x12,0x6f,0x64,0x68,0xa3,0x53,0x6e,0x3a,0x6f,0x40,0x70, -0x46,0x71,0x4a,0x72,0x12,0x65,0x73,0x68,0xa3,0x4a,0x11,0x75,0x6e,0xa3,0x46,0x11, -0x6e,0x65,0xa3,0x47,0x10,0x65,0xa3,0x48,0x12,0x6f,0x70,0x68,0xa3,0x49,0x67,0x33, -0x67,0x38,0x68,0x40,0x6b,0x5e,0x6c,0x66,0x6d,0x11,0x65,0x6d,0xa3,0x45,0x13,0x69, -0x6d,0x65,0x6c,0xa1,1,0x65,0x32,0x75,0x14,0x6e,0x64,0x72,0x65,0x64,0xa3,0x42, -0x11,0x74,0x68,0xa3,0x41,0x12,0x61,0x70,0x68,0xa3,0x43,0x14,0x61,0x6d,0x65,0x64, -0x68,0xa3,0x44,0x61,0x34,0x62,0x4a,0x64,0x50,0x66,0x12,0x69,0x76,0x65,0x9f,1, -0x6c,0x2a,0x79,0x11,0x69,0x6e,0x97,0x12,0x65,0x70,0x68,0x95,0x12,0x65,0x74,0x68, -0x99,1,0x61,0x30,0x68,0x14,0x61,0x6d,0x65,0x64,0x68,0x9d,0x13,0x6c,0x65,0x74, -0x68,0x9b,0x15,0x61,0x79,0x61,0x6c,0x61,0x6d,6,0x6e,0x2c,0x6e,0x34,0x72,0x5e, -0x73,0x62,0x74,0x11,0x74,0x61,0xa3,0x63,2,0x67,0x2e,0x6e,0x32,0x79,0x10,0x61, -0xa3,0x60,0x10,0x61,0xa3,0x5d,1,0x61,0xa3,0x5e,0x6e,0x10,0x61,0xa3,0x5f,0x10, -0x61,0xa3,0x61,0x11,0x73,0x61,0xa3,0x62,0x62,0x3c,0x6a,0x42,0x6c,0x10,0x6c,1, -0x61,0xa3,0x5b,0x6c,0x10,0x61,0xa3,0x5c,0x11,0x68,0x61,0xa3,0x59,0x10,0x61,0xa3, -0x5a,0x11,0x65,0x6d,0x51,2,0x6f,0x2c,0x75,0x50,0x79,0x10,0x61,0x91,1,0x6a, -0x28,0x6f,0x10,0x6e,0x55,0x1a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x67,0x72,0x6f,0x75, -0x70,0x21,0x10,0x6e,0x57,0x10,0x65,0x59,0x10,0x61,1,0x66,0x5b,0x70,0x10,0x68, -0x5d,0x66,0x9a,0x66,0x42,0x67,0x7a,0x68,0x8a,0x6b,0xa2,0x75,0x6c,0x11,0x61,0x6d, -0x4c,0x12,0x61,0x64,0x68,0x4f,2,0x61,0x3e,0x65,0x4a,0x69,0x19,0x6e,0x61,0x6c, -0x73,0x65,0x6d,0x6b,0x61,0x74,0x68,0x35,0x15,0x72,0x73,0x69,0x79,0x65,0x68,0x8f, -0x86,0x10,0x68,0x33,0x10,0x61,1,0x66,0x37,0x6d,0x11,0x61,0x6c,0x39,1,0x61, -0x40,0x65,0x3e,1,0x68,0x28,0x74,0x10,0x68,0x45,0x40,0x13,0x67,0x6f,0x61,0x6c, -0x43,2,0x68,0x3b,0x6d,0x5c,0x6e,0x1a,0x69,0x66,0x69,0x72,0x6f,0x68,0x69,0x6e, -0x67,0x79,0x61,1,0x6b,0x2a,0x70,0x10,0x61,0xa3,0x65,0x15,0x69,0x6e,0x6e,0x61, -0x79,0x61,0xa3,0x64,0x1a,0x7a,0x61,0x6f,0x6e,0x68,0x65,0x68,0x67,0x6f,0x61,0x6c, -0x3d,2,0x61,0x3a,0x68,0x44,0x6e,0x17,0x6f,0x74,0x74,0x65,0x64,0x68,0x65,0x68, -0x4b,1,0x66,0x47,0x70,0x10,0x68,0x49,0x12,0x61,0x70,0x68,0x89,0x61,0x2e,0x62, -0x8a,0x64,0xa2,0x51,0x65,0x31,2,0x66,0x3c,0x69,0x70,0x6c,1,0x61,0x28,0x65, -0x10,0x66,0x27,0x11,0x70,0x68,0x25,0x14,0x72,0x69,0x63,0x61,0x6e,2,0x66,0x30, -0x6e,0x36,0x71,0x11,0x61,0x66,0xa3,0x58,0x11,0x65,0x68,0xa3,0x56,0x12,0x6f,0x6f, -0x6e,0xa3,0x57,0x10,0x6e,0x23,1,0x65,0x4a,0x75,0x10,0x72,0x1f,0x75,0x73,0x68, -0x61,0x73,0x6b,0x69,0x79,0x65,0x68,0x62,0x61,0x72,0x72,0x65,0x65,0x8d,1,0x68, -0x29,0x74,0x10,0x68,0x2b,0x11,0x61,0x6c,0x2c,0x16,0x61,0x74,0x68,0x72,0x69,0x73, -0x68,0x2f,7,0x6e,0x2e,0x6e,0x2c,0x72,0x3e,0x74,0x56,0x75,0x21,0x18,0x6f,0x6e, -0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x21,0x28,0x1a,0x69,0x67,0x68,0x74,0x6a,0x6f, -0x69,0x6e,0x69,0x6e,0x67,0x29,0x2a,0x19,0x72,0x61,0x6e,0x73,0x70,0x61,0x72,0x65, -0x6e,0x74,0x2b,0x63,0x23,0x64,0x40,0x6a,0x56,0x6c,0x26,0x19,0x65,0x66,0x74,0x6a, -0x6f,0x69,0x6e,0x69,0x6e,0x67,0x27,0x24,0x19,0x75,0x61,0x6c,0x6a,0x6f,0x69,0x6e, -0x69,0x6e,0x67,0x25,0x19,0x6f,0x69,0x6e,0x63,0x61,0x75,0x73,0x69,0x6e,0x67,0x23, -0,0x13,0x6e,0xc0,0xd0,0x73,0x49,0x73,0x48,0x75,0x78,0x77,0x84,0x78,0x9c,0x7a, -0x10,0x77,0x58,1,0x6a,0x75,0x73,0x13,0x70,0x61,0x63,0x65,0x59,4,0x61,0x51, -0x67,0x53,0x70,0x28,0x75,0x30,0x79,0x57,0x54,0x12,0x61,0x63,0x65,0x55,0x16,0x72, -0x72,0x6f,0x67,0x61,0x74,0x65,0x53,0x15,0x6e,0x6b,0x6e,0x6f,0x77,0x6e,0x21,1, -0x6a,0x5d,0x6f,0x17,0x72,0x64,0x6a,0x6f,0x69,0x6e,0x65,0x72,0x5d,0x10,0x78,0x21, -0x6e,0x60,0x6f,0xa2,0x41,0x70,0xa2,0x50,0x71,0xa2,0x6e,0x72,1,0x65,0x24,0x69, -0x6f,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64,0x69,0x63,0x61,0x74,0x6f, -0x72,0x6f,4,0x65,0x3e,0x6c,0x5b,0x6f,0x46,0x73,0x45,0x75,0x46,0x14,0x6d,0x65, -0x72,0x69,0x63,0x47,0x15,0x78,0x74,0x6c,0x69,0x6e,0x65,0x5b,0x17,0x6e,0x73,0x74, -0x61,0x72,0x74,0x65,0x72,0x45,0x10,0x70,0x48,0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63, -0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x49,1,0x6f,0x3e,0x72,0x4c,0x1a,0x65,0x66, -0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x4d,0x4a,0x1b,0x73,0x74,0x66,0x69, -0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x4b,0x10,0x75,0x4e,0x16,0x6f,0x74,0x61, -0x74,0x69,0x6f,0x6e,0x4f,0x68,0x7b,0x68,0x50,0x69,0x86,0x6a,0xa2,0x61,0x6c,0xa2, -0x65,0x6d,0x1c,0x61,0x6e,0x64,0x61,0x74,0x6f,0x72,0x79,0x62,0x72,0x65,0x61,0x6b, -0x2d,4,0x32,0x5f,0x33,0x61,0x65,0x34,0x6c,0x6d,0x79,0x3a,0x13,0x70,0x68,0x65, -0x6e,0x3b,0x19,0x62,0x72,0x65,0x77,0x6c,0x65,0x74,0x74,0x65,0x72,0x6d,2,0x64, -0x28,0x6e,0x3c,0x73,0x41,0x3c,0x18,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63, -0x3d,0x3e,1,0x66,0x3e,0x73,0x11,0x65,0x70,1,0x61,0x22,0x65,0x14,0x72,0x61, -0x62,0x6c,0x65,0x3f,0x18,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x41,2, -0x6c,0x63,0x74,0x65,0x76,0x67,1,0x66,0x43,0x69,0x15,0x6e,0x65,0x66,0x65,0x65, -0x64,0x43,0x61,0x40,0x62,0x70,0x63,0xa2,0x55,0x65,0xa2,0xdb,0x67,0x10,0x6c,0x38, -0x11,0x75,0x65,0x39,2,0x69,0x23,0x6c,0x34,0x6d,0x16,0x62,0x69,0x67,0x75,0x6f, -0x75,0x73,0x23,0x24,0x17,0x70,0x68,0x61,0x62,0x65,0x74,0x69,0x63,0x25,4,0x32, -0x27,0x61,0x29,0x62,0x2b,0x6b,0x2d,0x72,0x12,0x65,0x61,0x6b,2,0x61,0x36,0x62, -0x3e,0x73,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x57,0x13,0x66,0x74,0x65,0x72,0x29, -1,0x65,0x2a,0x6f,0x11,0x74,0x68,0x27,0x13,0x66,0x6f,0x72,0x65,0x2b,7,0x6d, -0x51,0x6d,0x33,0x6f,0x28,0x70,0x69,0x72,0x35,1,0x6d,0x76,0x6e,1,0x64,0x3c, -0x74,0x1a,0x69,0x6e,0x67,0x65,0x6e,0x74,0x62,0x72,0x65,0x61,0x6b,0x2f,0x15,0x69, -0x74,0x69,0x6f,0x6e,0x61,0x1f,0x6c,0x6a,0x61,0x70,0x61,0x6e,0x65,0x73,0x65,0x73, -0x74,0x61,0x72,0x74,0x65,0x72,0x6b,1,0x62,0x3a,0x70,0x19,0x6c,0x65,0x78,0x63, -0x6f,0x6e,0x74,0x65,0x78,0x74,0x51,0x18,0x69,0x6e,0x69,0x6e,0x67,0x6d,0x61,0x72, -0x6b,0x33,0x61,0x6a,0x62,0x2f,0x6a,0x6b,0x6c,0x30,0x13,0x6f,0x73,0x65,0x70,1, -0x61,0x38,0x75,0x18,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x31,0x18,0x72, -0x65,0x6e,0x74,0x68,0x65,0x73,0x69,0x73,0x69,0x1b,0x72,0x72,0x69,0x61,0x67,0x65, -0x72,0x65,0x74,0x75,0x72,0x6e,0x35,2,0x62,0x3e,0x6d,0x46,0x78,0x36,0x18,0x63, -0x6c,0x61,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x37,0x70,0x12,0x61,0x73,0x65,0x71,0x72, -0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x73,1,0x64,0x42,0x6e,1,0x6f,0x32, -0x75,0x26,0x14,0x6d,0x65,0x72,0x69,0x63,0x27,0x11,0x6e,0x65,0x21,1,0x65,0x2e, -0x69,0x24,0x12,0x67,0x69,0x74,0x25,0x22,0x14,0x63,0x69,0x6d,0x61,0x6c,0x23,0, -0x18,0x6e,0xc4,0x1e,0x74,0xc1,0x61,0x77,0x8a,0x77,0xa2,0x4c,0x78,0xa2,0x70,0x79, -0xa2,0x7a,0x7a,6,0x73,0x1e,0x73,0x34,0x78,0x42,0x79,0x48,0x7a,0x11,0x7a,0x7a, -0xa3,0x67,0x10,0x79,1,0x65,0xa3,0xae,0x6d,0xa3,0x81,0x11,0x78,0x78,0xa3,0x66, -0x11,0x79,0x79,0x21,0x61,0x30,0x69,0x58,0x6d,0x11,0x74,0x68,0xa3,0x80,0x10,0x6e, -1,0x61,0x26,0x62,0xa3,0xb1,0x1a,0x62,0x61,0x7a,0x61,0x72,0x73,0x71,0x75,0x61, -0x72,0x65,0xa3,0xb1,0x11,0x6e,0x68,0x23,2,0x61,0x30,0x63,0x5a,0x6f,0x11,0x6c, -0x65,0xa3,0x9b,1,0x6e,0x3c,0x72,0x10,0x61,0xa2,0x92,0x15,0x6e,0x67,0x63,0x69, -0x74,0x69,0xa3,0x92,0x12,0x63,0x68,0x6f,0xa3,0xbc,0x11,0x68,0x6f,0xa3,0xbc,1, -0x70,0x2c,0x73,0x11,0x75,0x78,0xa3,0x65,0x11,0x65,0x6f,0x9b,0x10,0x69,0x72,0x11, -0x69,0x69,0x73,0x74,0x4a,0x75,0xa2,0xba,0x76,1,0x61,0x2c,0x69,0x11,0x73,0x70, -0xa3,0x64,0x10,0x69,0xa2,0x63,0x10,0x69,0xa3,0x63,5,0x67,0x36,0x67,0x68,0x68, -0x6c,0x69,2,0x62,0x3a,0x66,0x4a,0x72,0x10,0x68,0xa2,0x9e,0x12,0x75,0x74,0x61, -0xa3,0x9e,1,0x65,0x24,0x74,0x6f,0x12,0x74,0x61,0x6e,0x6f,0x14,0x69,0x6e,0x61, -0x67,0x68,0x99,0x11,0x6c,0x67,0x75,0x10,0x61,1,0x61,0x24,0x69,0x6d,0x6a,0x11, -0x6e,0x61,0x6b,0x61,0x30,0x65,0xa2,0x5b,0x66,0x11,0x6e,0x67,0x99,6,0x6c,0x21, -0x6c,0x32,0x6d,0x38,0x6e,0x44,0x76,0x10,0x74,0xa3,0x7f,1,0x65,0x89,0x75,0x97, -1,0x69,0x24,0x6c,0x67,0x10,0x6c,0x67,0x10,0x67,0xa2,0x9a,0x11,0x75,0x74,0xa3, -0x9a,0x67,0x36,0x69,0x52,0x6b,0x10,0x72,0xa2,0x99,0x10,0x69,0xa3,0x99,1,0x61, -0x30,0x62,0x7a,0x13,0x61,0x6e,0x77,0x61,0x7b,0x12,0x6c,0x6f,0x67,0x75,2,0x6c, -0x32,0x74,0x34,0x76,0x12,0x69,0x65,0x74,0xa3,0x7f,0x10,0x65,0x89,0x12,0x68,0x61, -0x6d,0xa3,0x6a,1,0x6c,0x2a,0x6e,0x10,0x67,0xa3,0x62,0x10,0x75,0x68,0x11,0x67, -0x75,0x69,1,0x67,0x32,0x6e,0x14,0x6b,0x6e,0x6f,0x77,0x6e,0xa3,0x67,0x11,0x61, -0x72,0x8a,0x13,0x69,0x74,0x69,0x63,0x8b,0x71,0xc1,0x13,0x71,0xa2,0xde,0x72,0xa2, -0xe3,0x73,6,0x69,0x8a,0x69,0x72,0x6f,0xa2,0x4c,0x75,0xa2,0x75,0x79,1,0x6c, -0x46,0x72,4,0x63,0x65,0x65,0xa3,0x5f,0x69,0x2c,0x6a,0xa3,0x60,0x6e,0xa3,0x61, -0x11,0x61,0x63,0x65,0x10,0x6f,0x94,0x16,0x74,0x69,0x6e,0x61,0x67,0x72,0x69,0x95, -2,0x64,0x3c,0x67,0x4c,0x6e,1,0x64,0xa3,0x91,0x68,0x62,0x12,0x61,0x6c,0x61, -0x63,0x10,0x64,0xa2,0xa6,0x12,0x68,0x61,0x6d,0xa3,0xa6,0x17,0x6e,0x77,0x72,0x69, -0x74,0x69,0x6e,0x67,0xa3,0x70,2,0x67,0x3a,0x72,0x52,0x79,0x10,0x6f,0xa2,0xb0, -0x12,0x6d,0x62,0x6f,0xa3,0xb0,1,0x64,0x26,0x6f,0xa3,0xb8,0xa2,0xb7,0x12,0x69, -0x61,0x6e,0xa3,0xb7,0x10,0x61,0xa2,0x98,0x16,0x73,0x6f,0x6d,0x70,0x65,0x6e,0x67, -0xa3,0x98,0x11,0x6e,0x64,0xa2,0x71,0x14,0x61,0x6e,0x65,0x73,0x65,0xa3,0x71,0x61, -0x5c,0x67,0xa2,0x43,0x68,1,0x61,0x2a,0x72,0x10,0x64,0xa3,0x97,2,0x72,0x28, -0x76,0x30,0x77,0x87,0x12,0x61,0x64,0x61,0xa3,0x97,0x12,0x69,0x61,0x6e,0x87,2, -0x6d,0x40,0x72,0x58,0x75,0x10,0x72,0xa2,0x6f,0x15,0x61,0x73,0x68,0x74,0x72,0x61, -0xa3,0x6f,1,0x61,0x26,0x72,0xa3,0x7e,0x14,0x72,0x69,0x74,0x61,0x6e,0xa3,0x7e, -1,0x61,0xa3,0x5e,0x62,0xa3,0x85,0x11,0x6e,0x77,0xa3,0x70,0x11,0x61,0x61,1, -0x63,0x2f,0x69,0x23,3,0x65,0x3e,0x6a,0x48,0x6f,0x4e,0x75,0x10,0x6e,1,0x69, -0x24,0x72,0x61,0x10,0x63,0x61,0x13,0x6a,0x61,0x6e,0x67,0xa3,0x6e,0x11,0x6e,0x67, -0xa3,0x6e,1,0x68,0x2a,0x72,0x10,0x6f,0xa3,0x5d,0x10,0x67,0xa3,0xb6,0x6e,0xa2, -0x83,0x6f,0xa2,0xf2,0x70,5,0x6c,0x1e,0x6c,0x44,0x72,0x4a,0x73,0x1b,0x61,0x6c, -0x74,0x65,0x72,0x70,0x61,0x68,0x6c,0x61,0x76,0x69,0xa3,0x7b,0x11,0x72,0x64,0xa3, -0x5c,0x11,0x74,0x69,0xa3,0x7d,0x61,0x7c,0x65,0xa2,0x54,0x68,3,0x61,0x3e,0x6c, -0x4e,0x6e,0x5e,0x6f,0x16,0x65,0x6e,0x69,0x63,0x69,0x61,0x6e,0xa3,0x5b,0x10,0x67, -0xa2,0x5a,0x12,0x73,0x70,0x61,0xa3,0x5a,2,0x69,0xa3,0x7a,0x70,0xa3,0x7b,0x76, -0xa3,0x7c,0x10,0x78,0xa3,0x5b,2,0x68,0x3e,0x6c,0x50,0x75,0x10,0x63,0xa2,0xa5, -0x14,0x69,0x6e,0x68,0x61,0x75,0xa3,0xa5,0x17,0x61,0x77,0x68,0x68,0x6d,0x6f,0x6e, -0x67,0xa3,0x4b,0x10,0x6d,0xa2,0x90,0x14,0x79,0x72,0x65,0x6e,0x65,0xa3,0x90,0x11, -0x72,0x6d,0xa3,0x59,6,0x6b,0x36,0x6b,0x56,0x73,0x6e,0x75,0x74,0x79,0x11,0x69, -0x61,0x1f,0x6b,0x65,0x6e,0x67,0x70,0x75,0x61,0x63,0x68,0x75,0x65,0x68,0x6d,0x6f, -0x6e,0x67,0xa3,0xba,1,0x67,0x2e,0x6f,0xa2,0x57,0x10,0x6f,0xa3,0x57,0x10,0x62, -0xa3,0x84,0x11,0x68,0x75,0xa3,0x96,0x12,0x73,0x68,0x75,0xa3,0x96,0x61,0x42,0x62, -0x80,0x65,0x10,0x77,1,0x61,0xa3,0xaa,0x74,0x14,0x61,0x69,0x6c,0x75,0x65,0x97, -2,0x62,0x2e,0x6e,0x3c,0x72,0x10,0x62,0xa3,0x8e,0x15,0x61,0x74,0x61,0x65,0x61, -0x6e,0xa3,0x8f,0x10,0x64,0xa2,0xbb,0x16,0x69,0x6e,0x61,0x67,0x61,0x72,0x69,0xa3, -0xbb,0x11,0x61,0x74,0xa3,0x8f,3,0x67,0x5a,0x6c,0x6c,0x72,0xa2,0x93,0x73,2, -0x61,0x36,0x67,0x3c,0x6d,0x10,0x61,0x84,0x12,0x6e,0x79,0x61,0x85,0x11,0x67,0x65, -0xa3,0xab,0x10,0x65,0xa3,0xab,1,0x61,0x2a,0x68,0x11,0x61,0x6d,0x5b,0x10,0x6d, -0x5b,1,0x63,0xa2,0x60,0x64,5,0x70,0x37,0x70,0x36,0x73,0x54,0x74,0x14,0x75, -0x72,0x6b,0x69,0x63,0xa3,0x58,0x11,0x65,0x72,1,0x6d,0x2c,0x73,0x12,0x69,0x61, -0x6e,0x9b,0x11,0x69,0x63,0xa3,0x59,0x10,0x6f,1,0x67,0x3a,0x75,0x18,0x74,0x68, -0x61,0x72,0x61,0x62,0x69,0x61,0x6e,0xa3,0x85,0x13,0x64,0x69,0x61,0x6e,0xa3,0xb8, -0x68,0x42,0x69,0x54,0x6e,0x1a,0x6f,0x72,0x74,0x68,0x61,0x72,0x61,0x62,0x69,0x61, -0x6e,0xa3,0x8e,0x17,0x75,0x6e,0x67,0x61,0x72,0x69,0x61,0x6e,0xa3,0x4c,0x14,0x74, -0x61,0x6c,0x69,0x63,0x5d,1,0x68,0x26,0x6b,0xa3,0x6d,0x12,0x69,0x6b,0x69,0xa3, -0x6d,2,0x69,0x2c,0x6b,0x30,0x79,0x10,0x61,0x5f,0x11,0x79,0x61,0x5f,0x10,0x68, -0xa3,0x58,0x68,0xc2,0xf3,0x6b,0xc2,0xa,0x6b,0xa4,0x17,0x6c,0xa4,0x98,0x6d,8, -0x6f,0x46,0x6f,0x48,0x72,0x74,0x74,0x80,0x75,0x86,0x79,1,0x61,0x28,0x6d,0x10, -0x72,0x59,0x13,0x6e,0x6d,0x61,0x72,0x59,2,0x64,0x2e,0x6e,0x32,0x6f,0x10,0x6e, -0xa3,0x72,0x10,0x69,0xa3,0xa3,0x10,0x67,0x56,0x14,0x6f,0x6c,0x69,0x61,0x6e,0x57, -0x10,0x6f,0xa2,0x95,0x10,0x6f,0xa3,0x95,0x11,0x65,0x69,0xa3,0x73,0x11,0x6c,0x74, -0xa2,0xa4,0x12,0x61,0x6e,0x69,0xa3,0xa4,0x61,0x36,0x65,0xa2,0x67,0x69,0xa2,0xbd, -0x6c,0x11,0x79,0x6d,0x55,6,0x6e,0x38,0x6e,0x32,0x72,0x5c,0x73,0x6c,0x79,0x10, -0x61,0xa3,0x55,1,0x64,0x38,0x69,0xa2,0x79,0x15,0x63,0x68,0x61,0x65,0x61,0x6e, -0xa3,0x79,0xa2,0x54,0x12,0x61,0x69,0x63,0xa3,0x54,0x10,0x63,0xa2,0xa9,0x12,0x68, -0x65,0x6e,0xa3,0xa9,0x18,0x61,0x72,0x61,0x6d,0x67,0x6f,0x6e,0x64,0x69,0xa3,0xaf, -0x68,0x36,0x6b,0x4c,0x6c,0x15,0x61,0x79,0x61,0x6c,0x61,0x6d,0x55,1,0x61,0x26, -0x6a,0xa3,0xa0,0x13,0x6a,0x61,0x6e,0x69,0xa3,0xa0,0x10,0x61,0xa2,0xb4,0x12,0x73, -0x61,0x72,0xa3,0xb4,3,0x64,0x78,0x65,0x94,0x6e,0xa2,0x42,0x72,1,0x63,0xa3, -0x8d,0x6f,0xa2,0x56,0x13,0x69,0x74,0x69,0x63,1,0x63,0x3c,0x68,0x19,0x69,0x65, -0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0x56,0x15,0x75,0x72,0x73,0x69,0x76, -0x65,0xa3,0x8d,1,0x65,0x26,0x66,0xa3,0xb5,0x16,0x66,0x61,0x69,0x64,0x72,0x69, -0x6e,0xa3,0xb5,0x17,0x74,0x65,0x69,0x6d,0x61,0x79,0x65,0x6b,0xa3,0x73,0x10,0x64, -0xa2,0x8c,0x17,0x65,0x6b,0x69,0x6b,0x61,0x6b,0x75,0x69,0xa3,0x8c,0x11,0x61,0x6f, -0xa3,0x5c,5,0x6f,0x14,0x6f,0x30,0x70,0x36,0x74,0x11,0x68,0x69,0xa3,0x78,0x11, -0x72,0x65,0xa3,0x77,0x11,0x65,0x6c,0xa3,0x8a,0x61,0x2e,0x68,0x98,0x6e,0x11,0x64, -0x61,0x4b,4,0x69,0x3c,0x6c,0x44,0x6e,0x48,0x74,0x56,0x79,0x13,0x61,0x68,0x6c, -0x69,0xa3,0x4f,0x12,0x74,0x68,0x69,0xa3,0x78,0x10,0x69,0xa3,0x4f,1,0x61,0x4d, -0x6e,0x12,0x61,0x64,0x61,0x4b,0x14,0x61,0x6b,0x61,0x6e,0x61,0x4c,0x19,0x6f,0x72, -0x68,0x69,0x72,0x61,0x67,0x61,0x6e,0x61,0x8d,3,0x61,0x3c,0x6d,0x4e,0x6f,0x5a, -0x75,0x15,0x64,0x61,0x77,0x61,0x64,0x69,0xa3,0x91,0x10,0x72,0x92,0x15,0x6f,0x73, -0x68,0x74,0x68,0x69,0x93,1,0x65,0x24,0x72,0x4f,0x10,0x72,0x4f,0x10,0x6a,0xa2, -0x9d,0x11,0x6b,0x69,0xa3,0x9d,4,0x61,0x5c,0x65,0x90,0x69,0xa0,0x6f,0xa2,0x5d, -0x79,1,0x63,0x34,0x64,0x10,0x69,0xa2,0x6c,0x11,0x61,0x6e,0xa3,0x6c,0x10,0x69, -0xa2,0x6b,0x11,0x61,0x6e,0xa3,0x6b,2,0x6e,0x42,0x6f,0x46,0x74,3,0x66,0xa3, -0x50,0x67,0xa3,0x51,0x69,0x24,0x6e,0x53,0x10,0x6e,0x53,0x10,0x61,0xa3,0x6a,0x50, -0x10,0x6f,0x51,0x11,0x70,0x63,0xa2,0x52,0x11,0x68,0x61,0xa3,0x52,2,0x6d,0x2e, -0x6e,0x36,0x73,0x10,0x75,0xa3,0x83,0x10,0x62,0x80,0x10,0x75,0x81,2,0x61,0xa3, -0x53,0x62,0x83,0x65,0x11,0x61,0x72,1,0x61,0xa3,0x53,0x62,0x83,0x11,0x6d,0x61, -0xa3,0x8b,0x68,0x6e,0x69,0xa2,0x95,0x6a,2,0x61,0x30,0x70,0x52,0x75,0x11,0x72, -0x63,0xa3,0x94,1,0x6d,0x38,0x76,0x10,0x61,0xa2,0x4e,0x13,0x6e,0x65,0x73,0x65, -0xa3,0x4e,0x10,0x6f,0xa3,0xad,0x11,0x61,0x6e,0xa3,0x69,6,0x6c,0x1e,0x6c,0x34, -0x6d,0x3a,0x72,0x48,0x75,0x11,0x6e,0x67,0xa3,0x4c,0x11,0x75,0x77,0xa3,0x9c,0x10, -0x6e,1,0x67,0xa3,0x4b,0x70,0xa3,0xba,0x11,0x6b,0x74,0x8d,0x61,0x3c,0x65,0xa2, -0x43,0x69,0x11,0x72,0x61,0x48,0x13,0x67,0x61,0x6e,0x61,0x49,1,0x6e,0x34,0x74, -0x10,0x72,0xa2,0xa2,0x11,0x61,0x6e,0xa3,0xa2,0x42,6,0x6f,0xe,0x6f,0x77,0x73, -0xa3,0x49,0x74,0xa3,0x4a,0x75,0x12,0x6e,0x6f,0x6f,0x77,0x62,0xa3,0xac,0x67,0x3e, -0x69,0x42,0x19,0x66,0x69,0x72,0x6f,0x68,0x69,0x6e,0x67,0x79,0x61,0xa3,0xb6,0x44, -0x11,0x75,0x6c,0x45,0x11,0x62,0x72,0x46,0x11,0x65,0x77,0x47,2,0x6d,0x2e,0x6e, -0x4a,0x74,0x11,0x61,0x6c,0x5d,0x1c,0x70,0x65,0x72,0x69,0x61,0x6c,0x61,0x72,0x61, -0x6d,0x61,0x69,0x63,0xa3,0x74,2,0x64,0x66,0x68,0x6a,0x73,0x1b,0x63,0x72,0x69, -0x70,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x70,0x61,1,0x68,0x32,0x72,0x14,0x74,0x68, -0x69,0x61,0x6e,0xa3,0x7d,0x13,0x6c,0x61,0x76,0x69,0xa3,0x7a,0x10,0x73,0xa3,0x4d, -0x15,0x65,0x72,0x69,0x74,0x65,0x64,0x23,0x64,0xc0,0xf9,0x64,0xa2,0x7a,0x65,0xa2, -0xad,0x67,4,0x65,0x82,0x6c,0x9a,0x6f,0xa2,0x46,0x72,0xa2,0x55,0x75,2,0x6a, -0x3c,0x6e,0x4e,0x72,1,0x6d,0x24,0x75,0x41,0x13,0x75,0x6b,0x68,0x69,0x41,1, -0x61,0x24,0x72,0x3f,0x13,0x72,0x61,0x74,0x69,0x3f,0x18,0x6a,0x61,0x6c,0x61,0x67, -0x6f,0x6e,0x64,0x69,0xa3,0xb3,0x10,0x6f,1,0x6b,0xa3,0x48,0x72,0x38,0x13,0x67, -0x69,0x61,0x6e,0x39,0x11,0x61,0x67,0x90,0x15,0x6f,0x6c,0x69,0x74,0x69,0x63,0x91, -1,0x6e,0x30,0x74,0x10,0x68,0x3a,0x11,0x69,0x63,0x3b,1,0x67,0xa3,0xb3,0x6d, -0xa3,0xaf,1,0x61,0x32,0x65,1,0x65,0x24,0x6b,0x3d,0x10,0x6b,0x3d,0x10,0x6e, -0xa2,0x89,0x12,0x74,0x68,0x61,0xa3,0x89,3,0x65,0x42,0x6f,0x68,0x73,0x76,0x75, -0x11,0x70,0x6c,0xa2,0x87,0x13,0x6f,0x79,0x61,0x6e,0xa3,0x87,1,0x73,0x38,0x76, -0x10,0x61,0x34,0x15,0x6e,0x61,0x67,0x61,0x72,0x69,0x35,0x13,0x65,0x72,0x65,0x74, -0x33,0x11,0x67,0x72,0xa2,0xb2,0x10,0x61,0xa3,0xb2,0x11,0x72,0x74,0x33,2,0x67, -0x3a,0x6c,0x72,0x74,0x11,0x68,0x69,0x36,0x13,0x6f,0x70,0x69,0x63,0x37,0x10,0x79, -2,0x64,0xa3,0x45,0x68,0xa3,0x46,0x70,0xa2,0x47,0x1e,0x74,0x69,0x61,0x6e,0x68, -0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0x47,1,0x62,0x36,0x79, -0x10,0x6d,0xa2,0xb9,0x12,0x61,0x69,0x63,0xa3,0xb9,0x10,0x61,0xa2,0x88,0x12,0x73, -0x61,0x6e,0xa3,0x88,0x61,0xa2,0xa2,0x62,0xa4,7,0x63,6,0x6f,0x3d,0x6f,0x5a, -0x70,0x76,0x75,0x7a,0x79,1,0x70,0x3e,0x72,2,0x69,0x2a,0x6c,0x31,0x73,0xa3, -0x44,0x13,0x6c,0x6c,0x69,0x63,0x31,0x13,0x72,0x69,0x6f,0x74,0x7f,1,0x6d,0x30, -0x70,0x10,0x74,0x2e,0x11,0x69,0x63,0x2f,0x12,0x6d,0x6f,0x6e,0x21,0x11,0x72,0x74, -0x7f,0x16,0x6e,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa3,0x65,0x61,0x32,0x68,0xa2,0x41, -0x69,0x11,0x72,0x74,0xa3,0x43,3,0x6b,0x4c,0x6e,0x50,0x72,0x76,0x75,0x1d,0x63, -0x61,0x73,0x69,0x61,0x6e,0x61,0x6c,0x62,0x61,0x6e,0x69,0x61,0x6e,0xa3,0x9f,0x10, -0x6d,0xa3,0x76,1,0x61,0x24,0x73,0x71,0x1d,0x64,0x69,0x61,0x6e,0x61,0x62,0x6f, -0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x71,0x10,0x69,0xa2,0x68,0x11,0x61,0x6e,0xa3, -0x68,1,0x61,0x34,0x65,0x10,0x72,0x2c,0x13,0x6f,0x6b,0x65,0x65,0x2d,1,0x6b, -0x26,0x6d,0xa3,0x42,0x11,0x6d,0x61,0xa3,0x76,6,0x68,0x4a,0x68,0x48,0x6e,0x4e, -0x72,0x76,0x76,1,0x65,0x2a,0x73,0x10,0x74,0xa3,0x75,0x13,0x73,0x74,0x61,0x6e, -0xa3,0x75,0x11,0x6f,0x6d,0xa3,0xa1,0x11,0x61,0x74,0x1f,0x6f,0x6c,0x69,0x61,0x6e, -0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0x9c,1,0x61,0x3e, -0x6d,2,0x65,0x2a,0x69,0xa3,0x74,0x6e,0x27,0x13,0x6e,0x69,0x61,0x6e,0x27,0x10, -0x62,0x24,0x11,0x69,0x63,0x25,0x64,0x30,0x66,0x44,0x67,0x11,0x68,0x62,0xa3,0x9f, -0x10,0x6c,1,0x61,0x26,0x6d,0xa3,0xa7,0x10,0x6d,0xa3,0xa7,0x11,0x61,0x6b,0xa3, -0x93,6,0x6c,0x3c,0x6c,0x52,0x6f,0x56,0x72,0x66,0x75,1,0x67,0x30,0x68,1, -0x64,0x79,0x69,0x10,0x64,0x79,0x10,0x69,0x8e,0x13,0x6e,0x65,0x73,0x65,0x8f,0x11, -0x69,0x73,0xa1,0x11,0x70,0x6f,0x2a,0x13,0x6d,0x6f,0x66,0x6f,0x2b,0x10,0x61,1, -0x68,0x2e,0x69,0x7c,0x12,0x6c,0x6c,0x65,0x7d,0xa2,0x41,0x11,0x6d,0x69,0xa3,0x41, -0x61,0x48,0x65,0x9c,0x68,1,0x61,0x2a,0x6b,0x10,0x73,0xa3,0xa8,0x15,0x69,0x6b, -0x73,0x75,0x6b,0x69,0xa3,0xa8,3,0x6c,0x3a,0x6d,0x48,0x73,0x54,0x74,1,0x61, -0x24,0x6b,0x9f,0x10,0x6b,0x9f,0x10,0x69,0x9c,0x13,0x6e,0x65,0x73,0x65,0x9d,0x10, -0x75,0xa2,0x82,0x10,0x6d,0xa3,0x82,0x10,0x73,0xa2,0x86,0x13,0x61,0x76,0x61,0x68, -0xa3,0x86,0x11,0x6e,0x67,0x28,0x12,0x61,0x6c,0x69,0x29,3,0x6c,0x42,0x6e,0x90, -0x74,0xa2,0x46,0x76,0x24,0x17,0x6f,0x77,0x65,0x6c,0x6a,0x61,0x6d,0x6f,0x25,0x22, -1,0x65,0x54,0x76,0x28,1,0x73,0x38,0x74,0x2a,0x17,0x73,0x79,0x6c,0x6c,0x61, -0x62,0x6c,0x65,0x2b,0x16,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x29,0x18,0x61,0x64, -0x69,0x6e,0x67,0x6a,0x61,0x6d,0x6f,0x23,1,0x61,0x21,0x6f,0x1a,0x74,0x61,0x70, -0x70,0x6c,0x69,0x63,0x61,0x62,0x6c,0x65,0x21,0x26,0x1a,0x72,0x61,0x69,0x6c,0x69, -0x6e,0x67,0x6a,0x61,0x6d,0x6f,0x27,1,0x6e,0x2c,0x79,0x22,0x11,0x65,0x73,0x23, -0x20,0x10,0x6f,0x21,1,0x6e,0x2c,0x79,0x22,0x11,0x65,0x73,0x23,0x20,0x10,0x6f, -0x21,2,0x6d,0x30,0x6e,0x3a,0x79,0x22,0x11,0x65,0x73,0x23,0x24,0x13,0x61,0x79, -0x62,0x65,0x25,0x20,0x10,0x6f,0x21,2,0x6d,0x30,0x6e,0x3a,0x79,0x22,0x11,0x65, -0x73,0x23,0x24,0x13,0x61,0x79,0x62,0x65,0x25,0x20,0x10,0x6f,0x21,0xb,0x72,0x39, -0x76,0xc,0x76,0x33,0x78,0x2a,0x7a,0x11,0x77,0x6a,0x43,0x10,0x78,0x21,0x72,0x28, -0x73,0x50,0x74,0x31,1,0x65,0x24,0x69,0x39,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c, -0x69,0x6e,0x64,0x69,0x63,0x61,0x74,0x6f,0x72,0x39,1,0x6d,0x35,0x70,0x18,0x61, -0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x35,0x6c,0x1f,0x6c,0x3c,0x6f,0x4a,0x70, -1,0x70,0x37,0x72,0x14,0x65,0x70,0x65,0x6e,0x64,0x37,0x28,1,0x66,0x2b,0x76, -0x2c,0x10,0x74,0x2f,0x13,0x74,0x68,0x65,0x72,0x21,0x63,0x4c,0x65,0x64,0x67,1, -0x61,0x3a,0x6c,0x19,0x75,0x65,0x61,0x66,0x74,0x65,0x72,0x7a,0x77,0x6a,0x41,0x10, -0x7a,0x41,2,0x6e,0x23,0x6f,0x24,0x72,0x25,0x14,0x6e,0x74,0x72,0x6f,0x6c,0x23, -2,0x62,0x34,0x6d,0x4e,0x78,0x26,0x13,0x74,0x65,0x6e,0x64,0x27,0x3a,1,0x61, -0x24,0x67,0x3d,0x11,0x73,0x65,0x3a,0x12,0x67,0x61,0x7a,0x3d,0x3e,0x16,0x6f,0x64, -0x69,0x66,0x69,0x65,0x72,0x3f,9,0x6e,0x4a,0x6e,0x34,0x6f,0x44,0x73,0x60,0x75, -0x94,0x78,0x10,0x78,0x21,0x10,0x75,0x2a,0x14,0x6d,0x65,0x72,0x69,0x63,0x2b,1, -0x6c,0x2c,0x74,0x12,0x68,0x65,0x72,0x21,0x14,0x65,0x74,0x74,0x65,0x72,0x2d,3, -0x63,0x36,0x65,0x46,0x70,0x31,0x74,0x32,0x12,0x65,0x72,0x6d,0x33,0x3c,0x16,0x6f, -0x6e,0x74,0x69,0x6e,0x75,0x65,0x3d,0x2e,0x10,0x70,0x2f,0x10,0x70,0x34,0x12,0x70, -0x65,0x72,0x35,0x61,0x46,0x63,0x52,0x65,0x64,0x66,0x72,0x6c,2,0x65,0x2d,0x66, -0x3b,0x6f,0x28,0x12,0x77,0x65,0x72,0x29,0x10,0x74,0x22,0x12,0x65,0x72,0x6d,0x23, -1,0x6c,0x24,0x72,0x37,0x24,0x12,0x6f,0x73,0x65,0x25,0x10,0x78,0x38,0x13,0x74, -0x65,0x6e,0x64,0x39,0x10,0x6f,0x26,0x13,0x72,0x6d,0x61,0x74,0x27,0,0x10,0x6c, -0x88,0x72,0x40,0x72,0x36,0x73,0x5e,0x77,0x7a,0x78,0x8a,0x7a,0x11,0x77,0x6a,0x4b, -1,0x65,0x24,0x69,0x3b,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64,0x69, -0x63,0x61,0x74,0x6f,0x72,0x3b,1,0x69,0x24,0x71,0x3f,0x18,0x6e,0x67,0x6c,0x65, -0x71,0x75,0x6f,0x74,0x65,0x3f,0x17,0x73,0x65,0x67,0x73,0x70,0x61,0x63,0x65,0x4d, -0x10,0x78,0x21,0x6c,0x36,0x6d,0x3c,0x6e,0x76,0x6f,0x13,0x74,0x68,0x65,0x72,0x21, -1,0x65,0x23,0x66,0x35,3,0x62,0x37,0x69,0x28,0x6c,0x29,0x6e,0x2b,0x10,0x64, -1,0x6c,0x34,0x6e,0x11,0x75,0x6d,0x2a,0x12,0x6c,0x65,0x74,0x37,0x14,0x65,0x74, -0x74,0x65,0x72,0x29,2,0x65,0x36,0x6c,0x39,0x75,0x2c,0x14,0x6d,0x65,0x72,0x69, -0x63,0x2d,0x14,0x77,0x6c,0x69,0x6e,0x65,0x39,0x66,0x3f,0x66,0x40,0x67,0x4e,0x68, -0x70,0x6b,0x10,0x61,0x26,0x15,0x74,0x61,0x6b,0x61,0x6e,0x61,0x27,0x10,0x6f,0x24, -0x13,0x72,0x6d,0x61,0x74,0x25,1,0x61,0x3a,0x6c,0x19,0x75,0x65,0x61,0x66,0x74, -0x65,0x72,0x7a,0x77,0x6a,0x49,0x10,0x7a,0x49,1,0x65,0x24,0x6c,0x3d,0x19,0x62, -0x72,0x65,0x77,0x6c,0x65,0x74,0x74,0x65,0x72,0x3d,0x61,0x86,0x63,0x92,0x64,0x94, -0x65,2,0x62,0x44,0x6d,0x5e,0x78,0x2e,0x13,0x74,0x65,0x6e,0x64,0x32,0x15,0x6e, -0x75,0x6d,0x6c,0x65,0x74,0x2f,0x42,1,0x61,0x24,0x67,0x45,0x11,0x73,0x65,0x42, -0x12,0x67,0x61,0x7a,0x45,0x46,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x47,0x15, -0x6c,0x65,0x74,0x74,0x65,0x72,0x23,0x10,0x72,0x31,1,0x6f,0x24,0x71,0x41,0x18, -0x75,0x62,0x6c,0x65,0x71,0x75,0x6f,0x74,0x65,0x41,2,0x63,0x32,0x6e,0x3c,0x6f, -0x22,0x12,0x70,0x65,0x6e,0x23,0x24,0x13,0x6c,0x6f,0x73,0x65,0x25,0x20,0x12,0x6f, -0x6e,0x65,0x21,6,0x6f,0x5c,0x6f,0x4a,0x72,0x5c,0x74,0x64,0x76,0x1d,0x69,0x73, -0x75,0x61,0x6c,0x6f,0x72,0x64,0x65,0x72,0x6c,0x65,0x66,0x74,0x3d,0x18,0x76,0x65, -0x72,0x73,0x74,0x72,0x75,0x63,0x6b,0x2d,0x13,0x69,0x67,0x68,0x74,0x2f,0x11,0x6f, -0x70,0x30,0x12,0x61,0x6e,0x64,2,0x62,0x32,0x6c,0x50,0x72,0x13,0x69,0x67,0x68, -0x74,0x3b,0x14,0x6f,0x74,0x74,0x6f,0x6d,0x32,0x17,0x61,0x6e,0x64,0x72,0x69,0x67, -0x68,0x74,0x35,0x12,0x65,0x66,0x74,0x36,0x17,0x61,0x6e,0x64,0x72,0x69,0x67,0x68, -0x74,0x39,0x62,0x2c,0x6c,0x5c,0x6e,0x10,0x61,0x21,0x14,0x6f,0x74,0x74,0x6f,0x6d, -0x22,0x12,0x61,0x6e,0x64,1,0x6c,0x2e,0x72,0x13,0x69,0x67,0x68,0x74,0x27,0x12, -0x65,0x66,0x74,0x25,0x12,0x65,0x66,0x74,0x28,0x17,0x61,0x6e,0x64,0x72,0x69,0x67, -0x68,0x74,0x2b,0xd,0x6e,0xaa,0x72,0x70,0x72,0x92,0x73,0xa2,0x46,0x74,0xa2,0x54, -0x76,1,0x69,0x60,0x6f,0x12,0x77,0x65,0x6c,0x62,1,0x64,0x3a,0x69,0x19,0x6e, -0x64,0x65,0x70,0x65,0x6e,0x64,0x65,0x6e,0x74,0x67,0x17,0x65,0x70,0x65,0x6e,0x64, -0x65,0x6e,0x74,0x65,1,0x72,0x2e,0x73,0x13,0x61,0x72,0x67,0x61,0x61,0x12,0x61, -0x6d,0x61,0x5f,0x1d,0x65,0x67,0x69,0x73,0x74,0x65,0x72,0x73,0x68,0x69,0x66,0x74, -0x65,0x72,0x57,0x1e,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x6d,0x6f,0x64,0x69,0x66, -0x69,0x65,0x72,0x59,0x12,0x6f,0x6e,0x65,1,0x6c,0x2c,0x6d,0x12,0x61,0x72,0x6b, -0x5d,0x14,0x65,0x74,0x74,0x65,0x72,0x5b,0x6e,0x3c,0x6f,0x7c,0x70,0x18,0x75,0x72, -0x65,0x6b,0x69,0x6c,0x6c,0x65,0x72,0x55,1,0x6f,0x4c,0x75,1,0x6b,0x3c,0x6d, -0x12,0x62,0x65,0x72,0x50,0x15,0x6a,0x6f,0x69,0x6e,0x65,0x72,0x53,0x11,0x74,0x61, -0x4f,0x16,0x6e,0x6a,0x6f,0x69,0x6e,0x65,0x72,0x4d,0x13,0x74,0x68,0x65,0x72,0x21, -0x67,0x3e,0x67,0x4a,0x69,0x64,0x6a,0x82,0x6d,0x1d,0x6f,0x64,0x69,0x66,0x79,0x69, -0x6e,0x67,0x6c,0x65,0x74,0x74,0x65,0x72,0x4b,0x1c,0x65,0x6d,0x69,0x6e,0x61,0x74, -0x69,0x6f,0x6e,0x6d,0x61,0x72,0x6b,0x45,0x1e,0x6e,0x76,0x69,0x73,0x69,0x62,0x6c, -0x65,0x73,0x74,0x61,0x63,0x6b,0x65,0x72,0x47,0x14,0x6f,0x69,0x6e,0x65,0x72,0x49, -0x61,0xa2,0xba,0x62,0xa2,0xc0,0x63,1,0x61,0xa2,0xa2,0x6f,0x16,0x6e,0x73,0x6f, -0x6e,0x61,0x6e,0x74,0x2a,8,0x6b,0x67,0x6b,0x48,0x6d,0x52,0x70,0x5c,0x73,0xa2, -0x42,0x77,0x19,0x69,0x74,0x68,0x73,0x74,0x61,0x63,0x6b,0x65,0x72,0x43,0x14,0x69, -0x6c,0x6c,0x65,0x72,0x35,0x14,0x65,0x64,0x69,0x61,0x6c,0x37,1,0x6c,0x52,0x72, -0x10,0x65,1,0x63,0x2e,0x66,0x13,0x69,0x78,0x65,0x64,0x3d,0x19,0x65,0x64,0x69, -0x6e,0x67,0x72,0x65,0x70,0x68,0x61,0x3b,0x18,0x61,0x63,0x65,0x68,0x6f,0x6c,0x64, -0x65,0x72,0x39,0x10,0x75,1,0x62,0x3e,0x63,0x1b,0x63,0x65,0x65,0x64,0x69,0x6e, -0x67,0x72,0x65,0x70,0x68,0x61,0x41,0x15,0x6a,0x6f,0x69,0x6e,0x65,0x64,0x3f,0x64, -0x4c,0x66,0x52,0x68,0x5a,0x69,0x1e,0x6e,0x69,0x74,0x69,0x61,0x6c,0x70,0x6f,0x73, -0x74,0x66,0x69,0x78,0x65,0x64,0x33,0x12,0x65,0x61,0x64,0x2d,0x13,0x69,0x6e,0x61, -0x6c,0x2f,0x18,0x65,0x61,0x64,0x6c,0x65,0x74,0x74,0x65,0x72,0x31,0x1d,0x6e,0x74, -0x69,0x6c,0x6c,0x61,0x74,0x69,0x6f,0x6e,0x6d,0x61,0x72,0x6b,0x29,0x16,0x76,0x61, -0x67,0x72,0x61,0x68,0x61,0x23,1,0x69,0x4a,0x72,0x10,0x61,0x1f,0x68,0x6d,0x69, -0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x6e,0x75,0x6d,0x62,0x65,0x72,0x27,0x12,0x6e, -0x64,0x75,0x25,2,0x72,0x38,0x74,0x46,0x75,0x26,0x15,0x70,0x72,0x69,0x67,0x68, -0x74,0x27,0x20,0x15,0x6f,0x74,0x61,0x74,0x65,0x64,0x21,1,0x72,0x24,0x75,0x25, -0x22,0x18,0x61,0x6e,0x73,0x66,0x6f,0x72,0x6d,0x65,0x64,1,0x72,0x32,0x75,0x15, -0x70,0x72,0x69,0x67,0x68,0x74,0x25,0x15,0x6f,0x74,0x61,0x74,0x65,0x64,0x23,0xd, -0x6e,0xc1,0x86,0x73,0xa8,0x73,0x4c,0x74,0xa2,0x76,0x75,0xa2,0x83,0x7a,0xd8,0x70, -0,2,0x6c,0xd9,0x20,0,0x70,0xd9,0x40,0,0x73,0xc3,0,0xfe,0xf,0, -0,0,7,0x6f,0x3c,0x6f,0xff,8,0,0,0,0x70,0x3a,0x75,0x6e,0x79, -0x13,0x6d,0x62,0x6f,0x6c,0xff,0xf,0,0,0,0x11,0x61,0x63,1,0x65,0x34, -0x69,0x15,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa5,0,0x18,0x73,0x65,0x70,0x61,0x72, -0x61,0x74,0x6f,0x72,0xc3,0,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0xe1,0, -0,0x63,0xff,2,0,0,0,0x65,0x38,0x6b,0xff,4,0,0,0,0x6d, -0xff,1,0,0,0,0x16,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x70,0, -0x1d,0x69,0x74,0x6c,0x65,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x31, -1,0x6e,0x40,0x70,0x1c,0x70,0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74, -0x65,0x72,0x25,0x17,0x61,0x73,0x73,0x69,0x67,0x6e,0x65,0x64,0x23,0x6e,0xa2,0x69, -0x6f,0xa2,0x89,0x70,0xfe,0x30,0xf8,0,0,9,0x69,0x33,0x69,0xff,0x10,0, -0,0,0x6f,0xfd,0x80,0,0,0x72,0x54,0x73,0xf9,0,0,0x75,0x12,0x6e, -0x63,0x74,0xfe,0x30,0xf8,0,0,0x15,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff,0x30, -0xf8,0,0,0x17,0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0xdd,0,0,0x61, -0x48,0x63,0xfd,0x40,0,0,0x64,0xe9,0,0,0x65,0xfd,0x20,0,0,0x66, -0xff,0x20,0,0,0,0x1f,0x72,0x61,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x70, -0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x40,0,0xbe,0,3,0x64,0xa7,0,0x6c, -0xab,0,0x6f,0x30,0x75,0x13,0x6d,0x62,0x65,0x72,0xbf,0,0xb2,0,0x1b,0x6e, -0x73,0x70,0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa1,1,0x70,0x92,0x74, -0x12,0x68,0x65,0x72,0xe6,0x80,1,3,0x6c,0x40,0x6e,0x4a,0x70,0x56,0x73,0x14, -0x79,0x6d,0x62,0x6f,0x6c,0xff,8,0,0,0,0x14,0x65,0x74,0x74,0x65,0x72, -0x61,0x14,0x75,0x6d,0x62,0x65,0x72,0xb3,0,0x19,0x75,0x6e,0x63,0x74,0x75,0x61, -0x74,0x69,0x6f,0x6e,0xfd,0x80,0,0,0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63,0x74, -0x75,0x61,0x74,0x69,0x6f,0x6e,0xf9,0,0,0x66,0xc0,0xc4,0x66,0xa2,0x47,0x69, -0xa2,0x64,0x6c,0xa2,0x79,0x6d,0xa4,0xc0,4,0x61,0x6c,0x63,0xa5,0,0x65,0xa3, -0x80,0x6e,0xa1,0x6f,0x15,0x64,0x69,0x66,0x69,0x65,0x72,1,0x6c,0x38,0x73,0x14, -0x79,0x6d,0x62,0x6f,0x6c,0xff,4,0,0,0,0x14,0x65,0x74,0x74,0x65,0x72, -0x41,1,0x72,0x3c,0x74,0x16,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c,0xff,1,0, -0,0,0x10,0x6b,0xa5,0xc0,1,0x69,0x32,0x6f,0x13,0x72,0x6d,0x61,0x74,0xdb, -0,0,0x1d,0x6e,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f, -0x6e,0xff,0x20,0,0,0,0x10,0x6e,0x1f,0x69,0x74,0x69,0x61,0x6c,0x70,0x75, -0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff,0x10,0,0,0,0x9c,7, -0x6d,0x18,0x6d,0x41,0x6f,0x28,0x74,0x31,0x75,0x25,0x60,0x1c,0x77,0x65,0x72,0x63, -0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x29,0x63,0x3d,0x65,0x28,0x69,0x42, -0x6c,0x29,0x13,0x74,0x74,0x65,0x72,0x9c,0x15,0x6e,0x75,0x6d,0x62,0x65,0x72,0xab, -0,0x1a,0x6e,0x65,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x20,0, -0x63,0x46,0x64,0xa2,0x96,0x65,0x1b,0x6e,0x63,0x6c,0x6f,0x73,0x69,0x6e,0x67,0x6d, -0x61,0x72,0x6b,0xa3,0x80,0xe6,0x80,1,7,0x6e,0x57,0x6e,0x52,0x6f,0x5e,0x73, -0xe1,0,0,0x75,0x1b,0x72,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62,0x6f, -0x6c,0xff,2,0,0,0,0x22,0x12,0x74,0x72,0x6c,0xd9,0x80,0,0xdc,0, -0,1,0x6d,0x62,0x6e,1,0x6e,0x30,0x74,0x12,0x72,0x6f,0x6c,0xd9,0x80,0, -0x1f,0x65,0x63,0x74,0x6f,0x72,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f, -0x6e,0xfd,0x40,0,0,0x19,0x62,0x69,0x6e,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b, -0xa5,0xc0,0x61,0x58,0x63,0xd9,0x80,0,0x66,0xdb,0,0,0x6c,0x1d,0x6f,0x73, -0x65,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xfd,0x20,0,0, -0x18,0x73,0x65,0x64,0x6c,0x65,0x74,0x74,0x65,0x72,0x3d,2,0x61,0x32,0x65,0x50, -0x69,0x12,0x67,0x69,0x74,0xa7,0,0x1c,0x73,0x68,0x70,0x75,0x6e,0x63,0x74,0x75, -0x61,0x74,0x69,0x6f,0x6e,0xe9,0,0,0x1a,0x63,0x69,0x6d,0x61,0x6c,0x6e,0x75, -0x6d,0x62,0x65,0x72,0xa7,0 +0x5f,0x32,0x61,0x10,0x34,0xa3,0x54,0xa2,0xe6,3,0x62,0xa0,0x6c,0xa3,0xe4,0x72, +0xa3,0xe8,0x74,2,0x61,0x74,0x62,0x7c,0x74,0x14,0x61,0x63,0x68,0x65,0x64,1, +0x61,0x3e,0x62,0x13,0x65,0x6c,0x6f,0x77,0xa2,0xca,0x13,0x6c,0x65,0x66,0x74,0xa3, +0xc8,0x13,0x62,0x6f,0x76,0x65,0xa2,0xd6,0x14,0x72,0x69,0x67,0x68,0x74,0xa3,0xd8, +0xa2,0xd6,0x10,0x72,0xa3,0xd8,0xa2,0xca,0x10,0x6c,0xa3,0xc8,0x12,0x6f,0x76,0x65, +0xa2,0xe6,1,0x6c,0x30,0x72,0x13,0x69,0x67,0x68,0x74,0xa3,0xe8,0x12,0x65,0x66, +0x74,0xa3,0xe4,0xa2,0xdc,2,0x65,0x2c,0x6c,0xa3,0xda,0x72,0xa3,0xde,0x12,0x6c, +0x6f,0x77,0xa2,0xdc,1,0x6c,0x30,0x72,0x13,0x69,0x67,0x68,0x74,0xa3,0xde,0x12, +0x65,0x66,0x74,0xa3,0xda,0xb,0x6e,0xc0,0xca,0x72,0x5f,0x72,0x46,0x73,0xa2,0x48, +0x77,1,0x68,0x24,0x73,0x33,0x17,0x69,0x74,0x65,0x73,0x70,0x61,0x63,0x65,0x33, +0x22,1,0x69,0x30,0x6c,2,0x65,0x3d,0x69,0x4b,0x6f,0x3f,0x18,0x67,0x68,0x74, +0x74,0x6f,0x6c,0x65,0x66,0x74,0x22,2,0x65,0x38,0x69,0x48,0x6f,0x16,0x76,0x65, +0x72,0x72,0x69,0x64,0x65,0x3f,0x17,0x6d,0x62,0x65,0x64,0x64,0x69,0x6e,0x67,0x3d, +0x15,0x73,0x6f,0x6c,0x61,0x74,0x65,0x4b,0x30,0x1e,0x65,0x67,0x6d,0x65,0x6e,0x74, +0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x31,0x6e,0xa2,0x41,0x6f,0xa2,0x53, +0x70,2,0x61,0x66,0x64,0x86,0x6f,0x1b,0x70,0x64,0x69,0x72,0x65,0x63,0x74,0x69, +0x6f,0x6e,0x61,0x6c,1,0x66,0x32,0x69,0x15,0x73,0x6f,0x6c,0x61,0x74,0x65,0x4d, +0x14,0x6f,0x72,0x6d,0x61,0x74,0x41,0x1f,0x72,0x61,0x67,0x72,0x61,0x70,0x68,0x73, +0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x2f,1,0x66,0x41,0x69,0x4d,1,0x6f, +0x28,0x73,0x10,0x6d,0x43,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69,0x6e,0x67,0x6d,0x61, +0x72,0x6b,0x43,1,0x6e,0x35,0x74,0x19,0x68,0x65,0x72,0x6e,0x65,0x75,0x74,0x72, +0x61,0x6c,0x35,0x65,0x88,0x65,0x98,0x66,0xa2,0x6a,0x6c,0x20,1,0x65,0x30,0x72, +2,0x65,0x37,0x69,0x49,0x6f,0x39,0x18,0x66,0x74,0x74,0x6f,0x72,0x69,0x67,0x68, +0x74,0x20,2,0x65,0x38,0x69,0x48,0x6f,0x16,0x76,0x65,0x72,0x72,0x69,0x64,0x65, +0x39,0x17,0x6d,0x62,0x65,0x64,0x64,0x69,0x6e,0x67,0x37,0x15,0x73,0x6f,0x6c,0x61, +0x74,0x65,0x49,3,0x6e,0x25,0x73,0x27,0x74,0x29,0x75,0x15,0x72,0x6f,0x70,0x65, +0x61,0x6e,2,0x6e,0x3c,0x73,0x46,0x74,0x18,0x65,0x72,0x6d,0x69,0x6e,0x61,0x74, +0x6f,0x72,0x29,0x14,0x75,0x6d,0x62,0x65,0x72,0x25,0x17,0x65,0x70,0x61,0x72,0x61, +0x74,0x6f,0x72,0x27,1,0x69,0x28,0x73,0x10,0x69,0x47,0x1f,0x72,0x73,0x74,0x73, +0x74,0x72,0x6f,0x6e,0x67,0x69,0x73,0x6f,0x6c,0x61,0x74,0x65,0x47,0x61,0x4e,0x62, +0x84,0x63,1,0x6f,0x24,0x73,0x2d,0x1c,0x6d,0x6d,0x6f,0x6e,0x73,0x65,0x70,0x61, +0x72,0x61,0x74,0x6f,0x72,0x2d,2,0x6c,0x3b,0x6e,0x2b,0x72,0x13,0x61,0x62,0x69, +0x63,1,0x6c,0x30,0x6e,0x14,0x75,0x6d,0x62,0x65,0x72,0x2b,0x14,0x65,0x74,0x74, +0x65,0x72,0x3b,0x2e,1,0x6e,0x45,0x6f,0x1c,0x75,0x6e,0x64,0x61,0x72,0x79,0x6e, +0x65,0x75,0x74,0x72,0x61,0x6c,0x45,0,0x16,0x6d,0xc8,0xc8,0x74,0xc1,0xee,0x77, +0x6a,0x77,0x48,0x79,0x70,0x7a,0x1d,0x61,0x6e,0x61,0x62,0x61,0x7a,0x61,0x72,0x73, +0x71,0x75,0x61,0x72,0x65,0xa5,0x18,0x10,0x61,1,0x6e,0x36,0x72,0x16,0x61,0x6e, +0x67,0x63,0x69,0x74,0x69,0xa3,0xfc,0x12,0x63,0x68,0x6f,0xa5,0x2c,1,0x65,0x88, +0x69,2,0x6a,0x3c,0x72,0x68,0x73,0x17,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x73, +0xa3,0x48,0x12,0x69,0x6e,0x67,0xa2,0x74,0x1e,0x68,0x65,0x78,0x61,0x67,0x72,0x61, +0x6d,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x74,0x16,0x61,0x64,0x69,0x63,0x61, +0x6c,0x73,0xa3,0x49,0x13,0x7a,0x69,0x64,0x69,0xa5,0x34,0x74,0xa2,0x59,0x75,0xa4, +0x35,0x76,2,0x61,0x36,0x65,0x7a,0x73,0xa2,0x6c,0x12,0x73,0x75,0x70,0xa3,0x7d, +1,0x69,0xa3,0x9f,0x72,0x1e,0x69,0x61,0x74,0x69,0x6f,0x6e,0x73,0x65,0x6c,0x65, +0x63,0x74,0x6f,0x72,0x73,0xa2,0x6c,0x19,0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65, +0x6e,0x74,0xa3,0x7d,1,0x64,0x3c,0x72,0x19,0x74,0x69,0x63,0x61,0x6c,0x66,0x6f, +0x72,0x6d,0x73,0xa3,0x91,0x14,0x69,0x63,0x65,0x78,0x74,0xa2,0xaf,0x16,0x65,0x6e, +0x73,0x69,0x6f,0x6e,0x73,0xa3,0xaf,4,0x61,0x68,0x65,0xa2,0xad,0x68,0xa2,0xb0, +0x69,0xa2,0xb8,0x72,0x1c,0x61,0x6e,0x73,0x70,0x6f,0x72,0x74,0x61,0x6e,0x64,0x6d, +0x61,0x70,0xa2,0xcf,0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xcf,4,0x67, +0x7e,0x69,0xa2,0x41,0x6b,0xa2,0x6a,0x6d,0xa2,0x6c,0x6e,0x12,0x67,0x75,0x74,0xa4, +0x10,1,0x63,0x40,0x73,0x11,0x75,0x70,0xa4,0x33,0x16,0x70,0x6c,0x65,0x6d,0x65, +0x6e,0x74,0xa5,0x33,0x18,0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x73,0xa5,0x11, +2,0x61,0x2a,0x62,0x32,0x73,0xa3,0x60,0x12,0x6c,0x6f,0x67,0xa3,0x62,0x13,0x61, +0x6e,0x77,0x61,0xa3,0x65,3,0x6c,0x52,0x74,0x56,0x76,0x5e,0x78,0x16,0x75,0x61, +0x6e,0x6a,0x69,0x6e,0x67,0xa2,0x7c,0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3, +0x7c,0x10,0x65,0xa3,0x70,0x12,0x68,0x61,0x6d,0xa3,0xae,0x12,0x69,0x65,0x74,0xa3, +0xb7,0x11,0x72,0x69,0xa3,0xdc,0x11,0x69,0x6c,0x48,0x12,0x73,0x75,0x70,0xa4,0x2b, +0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0x2b,0x13,0x6c,0x75,0x67,0x75,0x4b, +0x10,0x61,1,0x61,0x24,0x69,0x53,0x11,0x6e,0x61,0x3d,2,0x62,0x34,0x66,0x3c, +0x72,0x13,0x68,0x75,0x74,0x61,0xa3,0xfb,0x13,0x65,0x74,0x61,0x6e,0x57,0x14,0x69, +0x6e,0x61,0x67,0x68,0xa3,0x90,2,0x63,0x82,0x67,0x92,0x6e,0x1f,0x69,0x66,0x69, +0x65,0x64,0x63,0x61,0x6e,0x61,0x64,0x69,0x61,0x6e,0x61,0x62,0x6f,0x1f,0x72,0x69, +0x67,0x69,0x6e,0x61,0x6c,0x73,0x79,0x6c,0x6c,0x61,0x62,0x69,0x63,0x73,0x62,0x17, +0x65,0x78,0x74,0x65,0x6e,0x64,0x65,0x64,0xa3,0xad,0x11,0x61,0x73,0x62,0x12,0x65, +0x78,0x74,0xa3,0xad,0x15,0x61,0x72,0x69,0x74,0x69,0x63,0xa3,0x78,0x70,0xc3,0x4b, +0x70,0xa6,0x61,0x72,0xa8,0x1d,0x73,7,0x6f,0xc1,0xbe,0x6f,0xa2,0x69,0x70,0xa2, +0x85,0x75,0xa2,0xa4,0x79,2,0x6c,0x50,0x6d,0x62,0x72,0x12,0x69,0x61,0x63,0x3a, +0x12,0x73,0x75,0x70,0xa4,0x17,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0x17, +0x17,0x6f,0x74,0x69,0x6e,0x61,0x67,0x72,0x69,0xa3,0x8f,0x13,0x62,0x6f,0x6c,0x73, +1,0x61,0x4c,0x66,0x10,0x6f,0x1f,0x72,0x6c,0x65,0x67,0x61,0x63,0x79,0x63,0x6f, +0x6d,0x70,0x75,0x74,0x69,0x6e,0x67,0xa5,0x32,0x1f,0x6e,0x64,0x70,0x69,0x63,0x74, +0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x78,0x74,1,0x61,0xa5,0x2a,0x65,0x14, +0x6e,0x64,0x65,0x64,0x61,0xa5,0x2a,2,0x67,0x34,0x72,0x3e,0x79,0x13,0x6f,0x6d, +0x62,0x6f,0xa5,0x16,0x13,0x64,0x69,0x61,0x6e,0xa5,0x23,0x17,0x61,0x73,0x6f,0x6d, +0x70,0x65,0x6e,0x67,0xa3,0xda,1,0x61,0x32,0x65,0x14,0x63,0x69,0x61,0x6c,0x73, +0xa3,0x56,0x12,0x63,0x69,0x6e,0x1f,0x67,0x6d,0x6f,0x64,0x69,0x66,0x69,0x65,0x72, +0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0x2d,2,0x6e,0x48,0x70,0x76,0x74,0x1d,0x74, +0x6f,0x6e,0x73,0x69,0x67,0x6e,0x77,0x72,0x69,0x74,0x69,0x6e,0x67,0xa5,6,0x15, +0x64,0x61,0x6e,0x65,0x73,0x65,0xa2,0x9b,0x12,0x73,0x75,0x70,0xa2,0xdb,0x16,0x70, +0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xdb,4,0x61,0xa2,0xa8,0x65,0x5c,0x6d,0x9e, +0x70,0xa2,0x4b,0x73,0x13,0x79,0x6d,0x62,0x6f,0x1f,0x6c,0x73,0x61,0x6e,0x64,0x70, +0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa5,5,0x10,0x72,1,0x61, +0x4e,0x73,0x12,0x63,0x72,0x69,0x1f,0x70,0x74,0x73,0x61,0x6e,0x64,0x73,0x75,0x62, +0x73,0x63,0x72,0x69,0x70,0x74,0x73,0x73,0x14,0x6e,0x64,0x73,0x75,0x62,0x73,0x1b, +0x61,0x74,0x68,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0xa3,0x6a,1,0x6c, +0x40,0x75,1,0x61,0x6e,0x6e,0x17,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa3, +0x8e,0x15,0x65,0x6d,0x65,0x6e,0x74,0x61,1,0x6c,0x50,0x72,0x1e,0x79,0x70,0x72, +0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0x61,0x72,0x65,0x61,1,0x61,0xa3,0x6d, +0x62,0xa3,0x6e,3,0x61,0x5c,0x6d,0x78,0x70,0xa2,0x41,0x73,0x13,0x79,0x6d,0x62, +0x6f,0x1f,0x6c,0x73,0x61,0x6e,0x64,0x70,0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70, +0x68,0x73,0xa5,5,0x14,0x72,0x72,0x6f,0x77,0x73,2,0x61,0xa3,0x67,0x62,0xa3, +0x68,0x63,0xa3,0xfa,0x13,0x61,0x74,0x68,0x65,0x1f,0x6d,0x61,0x74,0x69,0x63,0x61, +0x6c,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0xa3,0x6a,0x19,0x75,0x6e,0x63, +0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x8e,0x61,0x88,0x68,0xa2,0x48,0x69,0xa2, +0x71,0x6d,0x12,0x61,0x6c,0x6c,1,0x66,0x46,0x6b,0x15,0x61,0x6e,0x61,0x65,0x78, +0x74,0xa4,0x29,0x15,0x65,0x6e,0x73,0x69,0x6f,0x6e,0xa5,0x29,0x12,0x6f,0x72,0x6d, +1,0x73,0xa3,0x54,0x76,0x16,0x61,0x72,0x69,0x61,0x6e,0x74,0x73,0xa3,0x54,1, +0x6d,0x36,0x75,0x16,0x72,0x61,0x73,0x68,0x74,0x72,0x61,0xa3,0xa1,0x15,0x61,0x72, +0x69,0x74,0x61,0x6e,0xa3,0xac,1,0x61,0x52,0x6f,0x13,0x72,0x74,0x68,0x61,0x1f, +0x6e,0x64,0x66,0x6f,0x72,0x6d,0x61,0x74,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x73, +0xa3,0xf7,1,0x72,0x2e,0x76,0x12,0x69,0x61,0x6e,0xa3,0x79,0x12,0x61,0x64,0x61, +0xa3,0xd9,1,0x64,0x50,0x6e,0x13,0x68,0x61,0x6c,0x61,0x50,0x1d,0x61,0x72,0x63, +0x68,0x61,0x69,0x63,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0xf9,0x13,0x64,0x68, +0x61,0x6d,0xa3,0xf8,5,0x72,0x35,0x72,0x44,0x73,0x64,0x75,1,0x61,0xa3,0x4e, +0x6e,0x17,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x71,0x17,0x69,0x76,0x61,0x74, +0x65,0x75,0x73,0x65,0xa2,0x4e,0x13,0x61,0x72,0x65,0x61,0xa3,0x4e,0x1b,0x61,0x6c, +0x74,0x65,0x72,0x70,0x61,0x68,0x6c,0x61,0x76,0x69,0xa3,0xf6,0x61,0x40,0x68,0x82, +0x6c,0x19,0x61,0x79,0x69,0x6e,0x67,0x63,0x61,0x72,0x64,0x73,0xa3,0xcc,2,0x68, +0x38,0x6c,0x4a,0x75,0x15,0x63,0x69,0x6e,0x68,0x61,0x75,0xa3,0xf5,0x17,0x61,0x77, +0x68,0x68,0x6d,0x6f,0x6e,0x67,0xa3,0xf3,0x15,0x6d,0x79,0x72,0x65,0x6e,0x65,0xa3, +0xf4,1,0x61,0x8e,0x6f,1,0x65,0x74,0x6e,0x16,0x65,0x74,0x69,0x63,0x65,0x78, +0x74,0xa2,0x72,1,0x65,0x2c,0x73,0x11,0x75,0x70,0xa3,0x8d,0x15,0x6e,0x73,0x69, +0x6f,0x6e,0x73,0xa2,0x72,0x19,0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, +0xa3,0x8d,0x15,0x6e,0x69,0x63,0x69,0x61,0x6e,0xa3,0x97,1,0x67,0x3e,0x69,0x13, +0x73,0x74,0x6f,0x73,0xa2,0xa6,0x13,0x64,0x69,0x73,0x63,0xa3,0xa6,0x12,0x73,0x70, +0x61,0xa3,0x96,1,0x65,0x5c,0x75,1,0x6d,0x2a,0x6e,0x11,0x69,0x63,0x67,0x10, +0x69,0xa2,0xc0,0x1d,0x6e,0x75,0x6d,0x65,0x72,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f, +0x6c,0x73,0xa3,0xc0,0x13,0x6a,0x61,0x6e,0x67,0xa3,0xa3,0x6d,0xa2,0xe6,0x6e,0xa8, +0x19,0x6f,6,0x70,0x63,0x70,0x56,0x72,0x8a,0x73,0xa2,0x4c,0x74,0x10,0x74,0x1f, +0x6f,0x6d,0x61,0x6e,0x73,0x69,0x79,0x61,0x71,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73, +0xa5,0x28,0x18,0x74,0x69,0x63,0x61,0x6c,0x63,0x68,0x61,0x72,0x1f,0x61,0x63,0x74, +0x65,0x72,0x72,0x65,0x63,0x6f,0x67,0x6e,0x69,0x74,0x69,0x6f,0x6e,0x85,1,0x69, +0x46,0x6e,0x1e,0x61,0x6d,0x65,0x6e,0x74,0x61,0x6c,0x64,0x69,0x6e,0x67,0x62,0x61, +0x74,0x73,0xa3,0xf2,0x11,0x79,0x61,0x47,1,0x61,0x30,0x6d,0x13,0x61,0x6e,0x79, +0x61,0xa3,0x7a,0x11,0x67,0x65,0xa5,0xf,0x63,0xa2,0x71,0x67,0xa2,0x71,0x6c,1, +0x63,0xa2,0x62,0x64,5,0x70,0x38,0x70,0x36,0x73,0x56,0x74,0x14,0x75,0x72,0x6b, +0x69,0x63,0xa3,0xbf,0x11,0x65,0x72,1,0x6d,0x2e,0x73,0x12,0x69,0x61,0x6e,0xa3, +0x8c,0x11,0x69,0x63,0xa3,0xf1,0x10,0x6f,1,0x67,0x3a,0x75,0x18,0x74,0x68,0x61, +0x72,0x61,0x62,0x69,0x61,0x6e,0xa3,0xbb,0x13,0x64,0x69,0x61,0x6e,0xa5,0x22,0x68, +0x42,0x69,0x54,0x6e,0x1a,0x6f,0x72,0x74,0x68,0x61,0x72,0x61,0x62,0x69,0x61,0x6e, +0xa3,0xf0,0x17,0x75,0x6e,0x67,0x61,0x72,0x69,0x61,0x6e,0xa5,4,0x14,0x74,0x61, +0x6c,0x69,0x63,0xa3,0x58,0x13,0x68,0x69,0x6b,0x69,0xa3,0x9d,0x10,0x72,0x85,0x12, +0x68,0x61,0x6d,0x65,6,0x6f,0x86,0x6f,0x6c,0x72,0xa2,0x61,0x75,0xa2,0x62,0x79, +0x14,0x61,0x6e,0x6d,0x61,0x72,0x58,0x12,0x65,0x78,0x74,2,0x61,0xa3,0xb6,0x62, +0xa3,0xee,0x65,0x13,0x6e,0x64,0x65,0x64,1,0x61,0xa3,0xb6,0x62,0xa3,0xee,1, +0x64,0x52,0x6e,0x15,0x67,0x6f,0x6c,0x69,0x61,0x6e,0x6a,0x12,0x73,0x75,0x70,0xa4, +0xd,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0xd,0x10,0x69,0xa2,0xec,0x13, +0x66,0x69,0x65,0x72,1,0x6c,0x3c,0x74,0x19,0x6f,0x6e,0x65,0x6c,0x65,0x74,0x74, +0x65,0x72,0x73,0xa3,0x8a,0x15,0x65,0x74,0x74,0x65,0x72,0x73,0x2d,0x10,0x6f,0xa3, +0xed,1,0x6c,0x44,0x73,0x11,0x69,0x63,0xa2,0x5c,0x18,0x61,0x6c,0x73,0x79,0x6d, +0x62,0x6f,0x6c,0x73,0xa3,0x5c,0x13,0x74,0x61,0x6e,0x69,0xa5,3,0x61,0xa2,0x9b, +0x65,0xa4,0x4c,0x69,1,0x61,0xa2,0x8f,0x73,0x10,0x63,5,0x70,0x18,0x70,0xa2, +0x71,0x73,0x36,0x74,0x17,0x65,0x63,0x68,0x6e,0x69,0x63,0x61,0x6c,0x81,0x15,0x79, +0x6d,0x62,0x6f,0x6c,0x73,0x8f,0x61,0xa2,0x66,0x65,0x46,0x6d,0x19,0x61,0x74,0x68, +0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,1,0x61,0xa3,0x66,0x62,0xa3,0x69,0x17,0x6c, +0x6c,0x61,0x6e,0x65,0x6f,0x75,0x73,2,0x6d,0x3a,0x73,0x6c,0x74,0x17,0x65,0x63, +0x68,0x6e,0x69,0x63,0x61,0x6c,0x81,0x11,0x61,0x74,0x1f,0x68,0x65,0x6d,0x61,0x74, +0x69,0x63,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,1,0x61,0xa3,0x66,0x62, +0xa3,0x69,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x8e,0x12,0x61,0x6e,0x64,1,0x61, +0x3c,0x70,0x19,0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa3,0xcd,0x14, +0x72,0x72,0x6f,0x77,0x73,0xa3,0x73,0x10,0x6f,0xa3,0xd8,7,0x72,0x6f,0x72,0x44, +0x73,0x4e,0x74,0x62,0x79,0x19,0x61,0x6e,0x6e,0x75,0x6d,0x65,0x72,0x61,0x6c,0x73, +0xa5,0x20,0x13,0x63,0x68,0x65,0x6e,0xa5,0xc,0x18,0x61,0x72,0x61,0x6d,0x67,0x6f, +0x6e,0x64,0x69,0xa5,0x14,0x10,0x68,2,0x61,0x3a,0x65,0x4a,0x6f,0x17,0x70,0x65, +0x72,0x61,0x74,0x6f,0x72,0x73,0x7f,0x16,0x6c,0x70,0x68,0x61,0x6e,0x75,0x6d,0xa3, +0x5d,0x16,0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,1,0x61,0x36,0x6f,0x17,0x70,0x65, +0x72,0x61,0x74,0x6f,0x72,0x73,0x7f,0x11,0x6c,0x70,0x1f,0x68,0x61,0x6e,0x75,0x6d, +0x65,0x72,0x69,0x63,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5d,0x68,0x50,0x6b, +0x7e,0x6c,0x88,0x6e,1,0x64,0x34,0x69,0x15,0x63,0x68,0x61,0x65,0x61,0x6e,0xa3, +0xea,0x12,0x61,0x69,0x63,0xa3,0xc6,1,0x61,0x3e,0x6a,0x12,0x6f,0x6e,0x67,0xa2, +0xaa,0x14,0x74,0x69,0x6c,0x65,0x73,0xa3,0xaa,0x13,0x6a,0x61,0x6e,0x69,0xa3,0xe9, +0x13,0x61,0x73,0x61,0x72,0xa5,0x1f,0x15,0x61,0x79,0x61,0x6c,0x61,0x6d,0x4f,3, +0x64,0x6c,0x65,0x7e,0x6e,0xa2,0x47,0x72,0x14,0x6f,0x69,0x74,0x69,0x63,1,0x63, +0x3c,0x68,0x19,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0xd7,0x15, +0x75,0x72,0x73,0x69,0x76,0x65,0xa3,0xd6,0x17,0x65,0x66,0x61,0x69,0x64,0x72,0x69, +0x6e,0xa5,0x21,0x17,0x74,0x65,0x69,0x6d,0x61,0x79,0x65,0x6b,0xa2,0xb8,0x12,0x65, +0x78,0x74,0xa2,0xd5,0x16,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa3,0xd5,0x18,0x64, +0x65,0x6b,0x69,0x6b,0x61,0x6b,0x75,0x69,0xa3,0xeb,6,0x6b,0x3b,0x6b,0x56,0x6f, +0x5a,0x75,0x64,0x79,0x11,0x69,0x61,0x1f,0x6b,0x65,0x6e,0x67,0x70,0x75,0x61,0x63, +0x68,0x75,0x65,0x68,0x6d,0x6f,0x6e,0x67,0xa5,0x27,0x10,0x6f,0xa3,0x92,0x14,0x62, +0x6c,0x6f,0x63,0x6b,0x21,1,0x6d,0x2c,0x73,0x11,0x68,0x75,0xa5,0x15,0x17,0x62, +0x65,0x72,0x66,0x6f,0x72,0x6d,0x73,0x7b,0x61,0x44,0x62,0x21,0x65,0x10,0x77,1, +0x61,0xa5,0xe,0x74,0x14,0x61,0x69,0x6c,0x75,0x65,0xa3,0x8b,1,0x62,0x38,0x6e, +0x17,0x64,0x69,0x6e,0x61,0x67,0x61,0x72,0x69,0xa5,0x26,0x15,0x61,0x74,0x61,0x65, +0x61,0x6e,0xa3,0xef,0x67,0xc4,0x32,0x6a,0xc1,0xb9,0x6a,0xa2,0xd5,0x6b,0xa2,0xee, +0x6c,4,0x61,0x54,0x65,0xa2,0x61,0x69,0xa2,0x78,0x6f,0xa2,0xb7,0x79,1,0x63, +0x2e,0x64,0x12,0x69,0x61,0x6e,0xa3,0xa9,0x12,0x69,0x61,0x6e,0xa3,0xa7,1,0x6f, +0x55,0x74,0x11,0x69,0x6e,1,0x31,0x82,0x65,0x11,0x78,0x74,4,0x61,0x5c,0x62, +0x29,0x63,0xa3,0x94,0x64,0xa3,0x95,0x65,0xa2,0xe7,0x13,0x6e,0x64,0x65,0x64,4, +0x61,0x36,0x62,0x29,0x63,0xa3,0x94,0x64,0xa3,0x95,0x65,0xa3,0xe7,0x26,0x18,0x64, +0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x6d,0x24,0x12,0x73,0x75,0x70,0x24,0x16, +0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x25,1,0x70,0x42,0x74,0x1d,0x74,0x65,0x72, +0x6c,0x69,0x6b,0x65,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x79,0x12,0x63,0x68,0x61, +0xa3,0x9c,2,0x6d,0x4e,0x6e,0x54,0x73,0x10,0x75,0xa2,0xb0,0x12,0x73,0x75,0x70, +0xa4,0x31,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0x31,0x11,0x62,0x75,0xa3, +0x6f,0x12,0x65,0x61,0x72,1,0x61,0xa3,0xe8,0x62,1,0x69,0x38,0x73,0x17,0x79, +0x6c,0x6c,0x61,0x62,0x61,0x72,0x79,0xa3,0x75,0x17,0x64,0x65,0x6f,0x67,0x72,0x61, +0x6d,0x73,0xa3,0x76,0x1a,0x77,0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73, +0xa3,0x4d,0x10,0x61,1,0x6d,0x32,0x76,0x14,0x61,0x6e,0x65,0x73,0x65,0xa3,0xb5, +0x10,0x6f,0x5c,0x12,0x65,0x78,0x74,1,0x61,0xa3,0xb4,0x62,0xa3,0xb9,1,0x61, +0xa2,0x43,0x68,4,0x61,0x40,0x69,0x50,0x6d,0x6e,0x6f,0x86,0x75,0x15,0x64,0x61, +0x77,0x61,0x64,0x69,0xa3,0xe6,0x16,0x72,0x6f,0x73,0x68,0x74,0x68,0x69,0xa3,0x89, +0x1d,0x74,0x61,0x6e,0x73,0x6d,0x61,0x6c,0x6c,0x73,0x63,0x72,0x69,0x70,0x74,0xa5, +0x30,0x11,0x65,0x72,0x68,0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x71,0x12, +0x6a,0x6b,0x69,0xa3,0xe5,3,0x69,0x3a,0x6e,0x42,0x74,0xa2,0x51,0x79,0x13,0x61, +0x68,0x6c,0x69,0xa3,0xa2,0x12,0x74,0x68,0x69,0xa3,0xc1,3,0x61,0x34,0x62,0x76, +0x67,0x7c,0x6e,0x12,0x61,0x64,0x61,0x4d,1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2, +0xcb,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xcb,0x11,0x78,0x74,1,0x61, +0xa5,0x13,0x65,0x14,0x6e,0x64,0x65,0x64,0x61,0xa5,0x13,0x11,0x75,0x6e,0xa3,0x42, +0x11,0x78,0x69,0x96,0x17,0x72,0x61,0x64,0x69,0x63,0x61,0x6c,0x73,0x97,0x14,0x61, +0x6b,0x61,0x6e,0x61,0x9e,1,0x65,0x4c,0x70,0x10,0x68,0x1f,0x6f,0x6e,0x65,0x74, +0x69,0x63,0x65,0x78,0x74,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa3,0x6b,0x11,0x78, +0x74,0xa3,0x6b,0x67,0xa2,0xb5,0x68,0xa4,0x84,0x69,3,0x64,0x4c,0x6d,0xa2,0x55, +0x6e,0xa2,0x62,0x70,0x13,0x61,0x65,0x78,0x74,0x2a,0x16,0x65,0x6e,0x73,0x69,0x6f, +0x6e,0x73,0x2b,1,0x63,0x99,0x65,0x17,0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63, +1,0x64,0x56,0x73,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa4,0xb,0x1d,0x61,0x6e, +0x64,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa5,0xb,0x13,0x65, +0x73,0x63,0x72,0x1f,0x69,0x70,0x74,0x69,0x6f,0x6e,0x63,0x68,0x61,0x72,0x61,0x63, +0x74,0x65,0x72,0x73,0x99,0x1c,0x70,0x65,0x72,0x69,0x61,0x6c,0x61,0x72,0x61,0x6d, +0x61,0x69,0x63,0xa3,0xba,1,0x64,0x62,0x73,0x1b,0x63,0x72,0x69,0x70,0x74,0x69, +0x6f,0x6e,0x61,0x6c,0x70,0x61,1,0x68,0x32,0x72,0x14,0x74,0x68,0x69,0x61,0x6e, +0xa3,0xbd,0x13,0x6c,0x61,0x76,0x69,0xa3,0xbe,0x11,0x69,0x63,1,0x6e,0x3e,0x73, +0x1a,0x69,0x79,0x61,0x71,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa5,0x1e,0x19,0x75, +0x6d,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d,0x73,0xa3,0xb2,4,0x65,0x74,0x6c,0xa2, +0x82,0x6f,0xa2,0x9a,0x72,0xa2,0x9e,0x75,2,0x6a,0x34,0x6e,0x3e,0x72,0x14,0x6d, +0x75,0x6b,0x68,0x69,0x43,0x14,0x61,0x72,0x61,0x74,0x69,0x45,0x18,0x6a,0x61,0x6c, +0x61,0x67,0x6f,0x6e,0x64,0x69,0xa5,0x1c,1,0x6e,0xa2,0x46,0x6f,1,0x6d,0x6e, +0x72,0x13,0x67,0x69,0x61,0x6e,0x5a,1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2,0x87, +0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x87,0x11,0x78,0x74,0xa4,0x1b,0x14, +0x65,0x6e,0x64,0x65,0x64,0xa5,0x1b,0x1a,0x65,0x74,0x72,0x69,0x63,0x73,0x68,0x61, +0x70,0x65,0x73,0x8c,0x12,0x65,0x78,0x74,0xa2,0xe3,0x14,0x65,0x6e,0x64,0x65,0x64, +0xa3,0xe3,0x1e,0x65,0x72,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69, +0x6f,0x6e,0x71,0x17,0x61,0x67,0x6f,0x6c,0x69,0x74,0x69,0x63,0xa2,0x88,0x12,0x73, +0x75,0x70,0xa4,0xa,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0xa,0x13,0x74, +0x68,0x69,0x63,0xa3,0x59,1,0x61,0x5c,0x65,0x11,0x65,0x6b,0x30,1,0x61,0x38, +0x65,0x11,0x78,0x74,0x6e,0x14,0x65,0x6e,0x64,0x65,0x64,0x6f,0x17,0x6e,0x64,0x63, +0x6f,0x70,0x74,0x69,0x63,0x31,0x13,0x6e,0x74,0x68,0x61,0xa3,0xe4,2,0x61,0xa2, +0x48,0x65,0xa2,0xdf,0x69,1,0x67,0x30,0x72,0x14,0x61,0x67,0x61,0x6e,0x61,0x9d, +0x10,0x68,1,0x70,0x3a,0x73,0x18,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73, +0xa3,0x4b,1,0x72,0x3c,0x75,0x19,0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65, +0x73,0xa3,0x4c,0x11,0x69,0x76,0x1f,0x61,0x74,0x65,0x75,0x73,0x65,0x73,0x75,0x72, +0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4c,2,0x6c,0x32,0x6e,0x9a,0x74,0x12, +0x72,0x61,0x6e,0xa5,2,0x10,0x66,2,0x61,0x58,0x6d,0x70,0x77,0x14,0x69,0x64, +0x74,0x68,0x61,0x1f,0x6e,0x64,0x66,0x75,0x6c,0x6c,0x77,0x69,0x64,0x74,0x68,0x66, +0x6f,0x72,0x6d,0x73,0xa3,0x57,0x1a,0x6e,0x64,0x66,0x75,0x6c,0x6c,0x66,0x6f,0x72, +0x6d,0x73,0xa3,0x57,0x13,0x61,0x72,0x6b,0x73,0xa3,0x52,2,0x67,0x34,0x69,0xa2, +0x45,0x75,0x12,0x6e,0x6f,0x6f,0xa3,0x63,0x11,0x75,0x6c,0xa2,0x4a,2,0x63,0x3c, +0x6a,0x5e,0x73,0x17,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x73,0xa3,0x4a,0x1f,0x6f, +0x6d,0x70,0x61,0x74,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,0x6a,0x61,0x6d,0x6f,0xa3, +0x41,0x12,0x61,0x6d,0x6f,0x5c,0x17,0x65,0x78,0x74,0x65,0x6e,0x64,0x65,0x64,1, +0x61,0xa3,0xb4,0x62,0xa3,0xb9,0x19,0x66,0x69,0x72,0x6f,0x68,0x69,0x6e,0x67,0x79, +0x61,0xa5,0x1d,0x13,0x62,0x72,0x65,0x77,0x37,0x61,0xa4,5,0x62,0xa6,0x45,0x63, +0xa8,0x1a,0x64,0xac,0xb8,0x65,5,0x6d,0xa2,0x6d,0x86,0x6e,0x96,0x74,0x15,0x68, +0x69,0x6f,0x70,0x69,0x63,0x5e,1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2,0x86,0x16, +0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x86,0x11,0x78,0x74,0xa2,0x85,1,0x61, +0xa3,0xc8,0x65,0x13,0x6e,0x64,0x65,0x64,0xa2,0x85,0x10,0x61,0xa3,0xc8,0x16,0x6f, +0x74,0x69,0x63,0x6f,0x6e,0x73,0xa3,0xce,0x15,0x63,0x6c,0x6f,0x73,0x65,0x64,2, +0x61,0x5a,0x63,0x9e,0x69,0x1c,0x64,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63, +0x73,0x75,0x70,0xa2,0xc4,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xc4,0x16, +0x6c,0x70,0x68,0x61,0x6e,0x75,0x6d,0x86,1,0x65,0x2c,0x73,0x11,0x75,0x70,0xa3, +0xc3,0x13,0x72,0x69,0x63,0x73,0x86,0x18,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e, +0x74,0xa3,0xc3,0x11,0x6a,0x6b,0xa2,0x44,0x1f,0x6c,0x65,0x74,0x74,0x65,0x72,0x73, +0x61,0x6e,0x64,0x6d,0x6f,0x6e,0x74,0x68,0x73,0xa3,0x44,0x61,0x4a,0x67,0x76,0x6c, +1,0x62,0x30,0x79,0x13,0x6d,0x61,0x69,0x63,0xa5,0x25,0x13,0x61,0x73,0x61,0x6e, +0xa3,0xe2,0x13,0x72,0x6c,0x79,0x64,0x1f,0x79,0x6e,0x61,0x73,0x74,0x69,0x63,0x63, +0x75,0x6e,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa5,1,0x1f,0x79,0x70,0x74,0x69,0x61, +0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,1,0x66,0x26,0x73,0xa3, +0xc2,0x1c,0x6f,0x72,0x6d,0x61,0x74,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x73,0xa5, +0x24,7,0x6e,0xc0,0xe5,0x6e,0x3e,0x72,0xa2,0x5d,0x73,0xa2,0xd8,0x76,0x14,0x65, +0x73,0x74,0x61,0x6e,0xa3,0xbc,1,0x61,0x92,0x63,0x13,0x69,0x65,0x6e,0x74,1, +0x67,0x34,0x73,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xa5,0x13,0x72,0x65,0x65, +0x6b,1,0x6d,0x34,0x6e,0x15,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0x7f,0x13,0x75, +0x73,0x69,0x63,0xa2,0x7e,0x19,0x61,0x6c,0x6e,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e, +0xa3,0x7e,0x10,0x74,0x1f,0x6f,0x6c,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67, +0x6c,0x79,0x70,0x68,0x73,0xa3,0xfe,2,0x61,0x32,0x6d,0xa2,0x71,0x72,0x12,0x6f, +0x77,0x73,0x7d,0x12,0x62,0x69,0x63,0x38,3,0x65,0x4a,0x6d,0x66,0x70,0xa2,0x43, +0x73,0x11,0x75,0x70,0xa2,0x80,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x80, +0x11,0x78,0x74,1,0x61,0xa3,0xd2,0x65,0x14,0x6e,0x64,0x65,0x64,0x61,0xa3,0xd2, +0x12,0x61,0x74,0x68,0xa2,0xd3,0x18,0x65,0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,0x61, +0x1f,0x6c,0x70,0x68,0x61,0x62,0x65,0x74,0x69,0x63,0x73,0x79,0x6d,0x62,0x6f,0x6c, +0x73,0xa3,0xd3,1,0x66,0x42,0x72,0x1e,0x65,0x73,0x65,0x6e,0x74,0x61,0x74,0x69, +0x6f,0x6e,0x66,0x6f,0x72,0x6d,0x73,1,0x61,0xa3,0x51,0x62,0xa3,0x55,0x14,0x65, +0x6e,0x69,0x61,0x6e,0x35,0x12,0x63,0x69,0x69,0x23,0x64,0x9e,0x65,0xa2,0x42,0x68, +0xa2,0x4d,0x6c,1,0x63,0x62,0x70,0x17,0x68,0x61,0x62,0x65,0x74,0x69,0x63,0x70, +1,0x66,0xa3,0x50,0x72,0x1e,0x65,0x73,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e, +0x66,0x6f,0x72,0x6d,0x73,0xa3,0x50,0x16,0x68,0x65,0x6d,0x69,0x63,0x61,0x6c,0xa2, +0xd0,0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xd0,0x12,0x6c,0x61,0x6d,0xa5, +7,0x1a,0x67,0x65,0x61,0x6e,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0x77,0x11, +0x6f,0x6d,0xa3,0xfd,7,0x6f,0x71,0x6f,0x64,0x72,0xa2,0x41,0x75,0xa2,0x58,0x79, +0x1b,0x7a,0x61,0x6e,0x74,0x69,0x6e,0x65,0x6d,0x75,0x73,0x69,0x63,0xa2,0x5b,0x18, +0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5b,1,0x70,0x34,0x78,0x16, +0x64,0x72,0x61,0x77,0x69,0x6e,0x67,0x89,0x14,0x6f,0x6d,0x6f,0x66,0x6f,0xa0,0x12, +0x65,0x78,0x74,0xa2,0x43,0x14,0x65,0x6e,0x64,0x65,0x64,0xa3,0x43,0x10,0x61,1, +0x68,0x40,0x69,0x12,0x6c,0x6c,0x65,0x92,0x17,0x70,0x61,0x74,0x74,0x65,0x72,0x6e, +0x73,0x93,0x11,0x6d,0x69,0xa3,0xc9,1,0x67,0x2c,0x68,0x11,0x69,0x64,0xa3,0x64, +0x14,0x69,0x6e,0x65,0x73,0x65,0xa3,0x81,0x61,0x48,0x65,0xa2,0x4e,0x68,0xa2,0x52, +0x6c,0x1a,0x6f,0x63,0x6b,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x73,0x8b,3,0x6c, +0x34,0x6d,0x40,0x73,0x66,0x74,0x11,0x61,0x6b,0xa3,0xc7,0x14,0x69,0x6e,0x65,0x73, +0x65,0xa3,0x93,0x11,0x75,0x6d,0xa2,0xb1,0x12,0x73,0x75,0x70,0xa2,0xca,0x16,0x70, +0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xca,1,0x69,0x30,0x73,0x13,0x61,0x76,0x61, +0x68,0xa3,0xdd,0x15,0x63,0x6c,0x61,0x74,0x69,0x6e,0x23,0x14,0x6e,0x67,0x61,0x6c, +0x69,0x41,0x16,0x61,0x69,0x6b,0x73,0x75,0x6b,0x69,0xa5,8,5,0x6f,0xc1,0x4c, +0x6f,0xa2,0x55,0x75,0xa4,0x10,0x79,1,0x70,0x9c,0x72,0x14,0x69,0x6c,0x6c,0x69, +0x63,0x32,1,0x65,0x4c,0x73,0x11,0x75,0x70,0xa2,0x61,0x16,0x70,0x6c,0x65,0x6d, +0x65,0x6e,0x74,0xa2,0x61,0x12,0x61,0x72,0x79,0xa3,0x61,0x11,0x78,0x74,3,0x61, +0xa3,0x9e,0x62,0xa3,0xa0,0x63,0xa5,9,0x65,0x13,0x6e,0x64,0x65,0x64,2,0x61, +0xa3,0x9e,0x62,0xa3,0xa0,0x63,0xa5,9,0x1c,0x72,0x69,0x6f,0x74,0x73,0x79,0x6c, +0x6c,0x61,0x62,0x61,0x72,0x79,0xa3,0x7b,3,0x6d,0x5a,0x6e,0xa2,0x95,0x70,0xa2, +0xa0,0x75,0x17,0x6e,0x74,0x69,0x6e,0x67,0x72,0x6f,0x64,0xa2,0x9a,0x17,0x6e,0x75, +0x6d,0x65,0x72,0x61,0x6c,0x73,0xa3,0x9a,2,0x62,0x3a,0x6d,0xa2,0x5f,0x70,0x15, +0x61,0x74,0x6a,0x61,0x6d,0x6f,0xa3,0x41,0x14,0x69,0x6e,0x69,0x6e,0x67,2,0x64, +0x46,0x68,0x9e,0x6d,0x1d,0x61,0x72,0x6b,0x73,0x66,0x6f,0x72,0x73,0x79,0x6d,0x62, +0x6f,0x6c,0x73,0x77,0x1e,0x69,0x61,0x63,0x72,0x69,0x74,0x69,0x63,0x61,0x6c,0x6d, +0x61,0x72,0x6b,0x73,0x2e,2,0x65,0x40,0x66,0xa6,0x41,0x73,0x18,0x75,0x70,0x70, +0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x83,0x16,0x78,0x74,0x65,0x6e,0x64,0x65,0x64, +0xa3,0xe0,0x17,0x61,0x6c,0x66,0x6d,0x61,0x72,0x6b,0x73,0xa3,0x52,0x11,0x6f,0x6e, +0x1f,0x69,0x6e,0x64,0x69,0x63,0x6e,0x75,0x6d,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d, +0x73,0xa3,0xb2,0x1b,0x74,0x72,0x6f,0x6c,0x70,0x69,0x63,0x74,0x75,0x72,0x65,0x73, +0x83,0x12,0x74,0x69,0x63,0xa2,0x84,0x1b,0x65,0x70,0x61,0x63,0x74,0x6e,0x75,0x6d, +0x62,0x65,0x72,0x73,0xa3,0xdf,1,0x6e,0x3e,0x72,0x1b,0x72,0x65,0x6e,0x63,0x79, +0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x75,0x15,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa2, +0x98,0x16,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa2,0x99,0x1d,0x61,0x6e,0x64,0x70, +0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x99,0x61,0xa2,0xe1,0x68, +0xa4,0xb,0x6a,0x10,0x6b,0xa2,0x47,4,0x63,0x8c,0x65,0xa2,0x80,0x72,0xa2,0x98, +0x73,0xa2,0xaa,0x75,0x1f,0x6e,0x69,0x66,0x69,0x65,0x64,0x69,0x64,0x65,0x6f,0x67, +0x72,0x61,0x70,0x68,0x73,0xa2,0x47,0x18,0x65,0x78,0x74,0x65,0x6e,0x73,0x69,0x6f, +0x6e,6,0x64,0x6b,0x64,0xa3,0xd1,0x65,0xa5,0,0x66,0xa5,0x12,0x67,0xa5,0x2e, +0x14,0x6f,0x6d,0x70,0x61,0x74,0xa2,0x45,1,0x66,0x96,0x69,1,0x62,0x44,0x64, +0x17,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa2,0x4f,0x12,0x73,0x75,0x70,0xa3, +0x5f,0x14,0x69,0x6c,0x69,0x74,0x79,0xa2,0x45,1,0x66,0x54,0x69,0x18,0x64,0x65, +0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa2,0x4f,0x19,0x73,0x75,0x70,0x70,0x6c,0x65, +0x6d,0x65,0x6e,0x74,0xa3,0x5f,0x13,0x6f,0x72,0x6d,0x73,0xa3,0x53,0x11,0x78,0x74, +6,0x64,0xc,0x64,0xa3,0xd1,0x65,0xa5,0,0x66,0xa5,0x12,0x67,0xa5,0x2e,0x61, +0xa3,0x46,0x62,0xa3,0x5e,0x63,0xa3,0xc5,0x19,0x61,0x64,0x69,0x63,0x61,0x6c,0x73, +0x73,0x75,0x70,0x94,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x95,1,0x74,0x50, +0x79,0x14,0x6d,0x62,0x6f,0x6c,0x73,0x9a,0x1d,0x61,0x6e,0x64,0x70,0x75,0x6e,0x63, +0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x9b,0x14,0x72,0x6f,0x6b,0x65,0x73,0xa3,0x82, +2,0x6e,0x48,0x72,0x64,0x75,0x1d,0x63,0x61,0x73,0x69,0x61,0x6e,0x61,0x6c,0x62, +0x61,0x6e,0x69,0x61,0x6e,0xa3,0xde,0x1d,0x61,0x64,0x69,0x61,0x6e,0x73,0x79,0x6c, +0x6c,0x61,0x62,0x69,0x63,0x73,0x63,0x12,0x69,0x61,0x6e,0xa3,0xa8,2,0x61,0x3a, +0x65,0x4c,0x6f,0x16,0x72,0x61,0x73,0x6d,0x69,0x61,0x6e,0xa5,0x2d,1,0x6b,0x26, +0x6d,0xa3,0xa4,0x11,0x6d,0x61,0xa3,0xd4,1,0x72,0x38,0x73,0x17,0x73,0x73,0x79, +0x6d,0x62,0x6f,0x6c,0x73,0xa5,0x19,0x13,0x6f,0x6b,0x65,0x65,0x60,0x12,0x73,0x75, +0x70,0xa2,0xff,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xff,3,0x65,0x3e, +0x69,0x7e,0x6f,0xa2,0x69,0x75,0x15,0x70,0x6c,0x6f,0x79,0x61,0x6e,0xa3,0xe1,1, +0x73,0x50,0x76,0x16,0x61,0x6e,0x61,0x67,0x61,0x72,0x69,0x3e,0x12,0x65,0x78,0x74, +0xa2,0xb3,0x14,0x65,0x6e,0x64,0x65,0x64,0xa3,0xb3,0x13,0x65,0x72,0x65,0x74,0xa3, +0x5a,2,0x61,0x3a,0x6e,0x82,0x76,0x16,0x65,0x73,0x61,0x6b,0x75,0x72,0x75,0xa5, +0x2f,0x18,0x63,0x72,0x69,0x74,0x69,0x63,0x61,0x6c,0x73,0x2e,2,0x65,0x30,0x66, +0x36,0x73,0x11,0x75,0x70,0xa3,0x83,0x11,0x78,0x74,0xa3,0xe0,0x18,0x6f,0x72,0x73, +0x79,0x6d,0x62,0x6f,0x6c,0x73,0x77,0x14,0x67,0x62,0x61,0x74,0x73,0x91,1,0x67, +0x3e,0x6d,0x12,0x69,0x6e,0x6f,0xa2,0xab,0x14,0x74,0x69,0x6c,0x65,0x73,0xa3,0xab, +0x11,0x72,0x61,0xa5,0x1a,8,0x6d,0x5f,0x6d,0x3a,0x6e,0x48,0x73,0x7a,0x76,0xa2, +0x4b,0x77,0x12,0x69,0x64,0x65,0x43,0x11,0x65,0x64,0x32,0x12,0x69,0x61,0x6c,0x33, +2,0x61,0x40,0x62,0x37,0x6f,1,0x62,0x28,0x6e,0x10,0x65,0x21,0x13,0x72,0x65, +0x61,0x6b,0x37,0x10,0x72,0x34,0x12,0x72,0x6f,0x77,0x35,2,0x6d,0x38,0x71,0x46, +0x75,1,0x62,0x3d,0x70,0x3e,0x11,0x65,0x72,0x3f,1,0x61,0x24,0x6c,0x39,0x11, +0x6c,0x6c,0x39,1,0x72,0x3b,0x75,0x12,0x61,0x72,0x65,0x3b,0x12,0x65,0x72,0x74, +0x40,0x13,0x69,0x63,0x61,0x6c,0x41,0x63,0x58,0x65,0x92,0x66,0x96,0x69,1,0x6e, +0x36,0x73,0x10,0x6f,0x30,0x14,0x6c,0x61,0x74,0x65,0x64,0x31,0x11,0x69,0x74,0x2e, +0x12,0x69,0x61,0x6c,0x2f,2,0x61,0x36,0x69,0x48,0x6f,0x10,0x6d,0x24,0x12,0x70, +0x61,0x74,0x25,0x10,0x6e,0x22,0x15,0x6f,0x6e,0x69,0x63,0x61,0x6c,0x23,0x13,0x72, +0x63,0x6c,0x65,0x27,0x11,0x6e,0x63,0x27,2,0x69,0x3a,0x6f,0x44,0x72,0x10,0x61, +0x2c,0x14,0x63,0x74,0x69,0x6f,0x6e,0x2d,0x10,0x6e,0x28,0x11,0x61,0x6c,0x29,0x11, +0x6e,0x74,0x2b,4,0x61,0x3a,0x66,0x4c,0x68,0x5e,0x6e,0x70,0x77,0x2a,0x12,0x69, +0x64,0x65,0x2b,0x22,0x17,0x6d,0x62,0x69,0x67,0x75,0x6f,0x75,0x73,0x23,0x26,0x17, +0x75,0x6c,0x6c,0x77,0x69,0x64,0x74,0x68,0x27,0x24,0x17,0x61,0x6c,0x66,0x77,0x69, +0x64,0x74,0x68,0x25,0x20,1,0x61,0x30,0x65,0x14,0x75,0x74,0x72,0x61,0x6c,0x21, +0x28,0x13,0x72,0x72,0x6f,0x77,0x29,0xd,0x6e,0xc0,0xfb,0x73,0x6d,0x73,0x3a,0x74, +0x98,0x75,0xa2,0x49,0x7a,2,0x6c,0x3b,0x70,0x3d,0x73,0x39,5,0x6f,0x28,0x6f, +0x57,0x70,0x34,0x75,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x45,0x11,0x61,0x63, +1,0x65,0x32,0x69,0x15,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x31,0x18,0x73,0x65,0x70, +0x61,0x72,0x61,0x74,0x6f,0x72,0x39,0x63,0x53,0x6b,0x55,0x6d,0x51,0x1d,0x69,0x74, +0x6c,0x65,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x27,1,0x6e,0x40, +0x70,0x1c,0x70,0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x23, +0x17,0x61,0x73,0x73,0x69,0x67,0x6e,0x65,0x64,0x21,0x6e,0x8a,0x6f,0xa2,0x47,0x70, +8,0x66,0x14,0x66,0x5b,0x69,0x59,0x6f,0x4f,0x72,0x24,0x73,0x49,0x17,0x69,0x76, +0x61,0x74,0x65,0x75,0x73,0x65,0x43,0x61,0x2c,0x63,0x4d,0x64,0x47,0x65,0x4b,0x1f, +0x72,0x61,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72, +0x3d,2,0x64,0x33,0x6c,0x35,0x6f,0x36,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69,0x6e, +0x67,0x6d,0x61,0x72,0x6b,0x2d,1,0x70,0x7c,0x74,0x12,0x68,0x65,0x72,3,0x6c, +0x38,0x6e,0x42,0x70,0x4c,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0x57,0x14,0x65,0x74, +0x74,0x65,0x72,0x2b,0x14,0x75,0x6d,0x62,0x65,0x72,0x37,0x19,0x75,0x6e,0x63,0x74, +0x75,0x61,0x74,0x69,0x6f,0x6e,0x4f,0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63,0x74,0x75, +0x61,0x74,0x69,0x6f,0x6e,0x49,0x66,0x9e,0x66,0x88,0x69,0xa2,0x4b,0x6c,0xa2,0x5c, +0x6d,4,0x61,0x60,0x63,0x31,0x65,0x2f,0x6e,0x2d,0x6f,0x15,0x64,0x69,0x66,0x69, +0x65,0x72,1,0x6c,0x30,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0x55,0x14,0x65,0x74, +0x74,0x65,0x72,0x29,0x17,0x74,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x51,1,0x69, +0x2e,0x6f,0x13,0x72,0x6d,0x61,0x74,0x41,0x1d,0x6e,0x61,0x6c,0x70,0x75,0x6e,0x63, +0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x5b,0x10,0x6e,0x1f,0x69,0x74,0x69,0x61,0x6c, +0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x59,6,0x6d,0x18,0x6d, +0x29,0x6f,0x28,0x74,0x27,0x75,0x23,0x2a,0x1c,0x77,0x65,0x72,0x63,0x61,0x73,0x65, +0x6c,0x65,0x74,0x74,0x65,0x72,0x25,0x65,0x28,0x69,0x3c,0x6c,0x25,0x19,0x74,0x74, +0x65,0x72,0x6e,0x75,0x6d,0x62,0x65,0x72,0x35,0x1a,0x6e,0x65,0x73,0x65,0x70,0x61, +0x72,0x61,0x74,0x6f,0x72,0x3b,0x63,0x44,0x64,0xa2,0x60,0x65,0x1b,0x6e,0x63,0x6c, +0x6f,0x73,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x2f,6,0x6e,0x39,0x6e,0x46,0x6f, +0x4e,0x73,0x45,0x75,0x1b,0x72,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62,0x6f, +0x6c,0x53,0x20,0x12,0x74,0x72,0x6c,0x3f,0x42,0x10,0x6e,1,0x6e,0x2c,0x74,0x12, +0x72,0x6f,0x6c,0x3f,0x1f,0x65,0x63,0x74,0x6f,0x72,0x70,0x75,0x6e,0x63,0x74,0x75, +0x61,0x74,0x69,0x6f,0x6e,0x4d,0x63,0x3f,0x66,0x41,0x6c,0x1d,0x6f,0x73,0x65,0x70, +0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x4b,2,0x61,0x30,0x65,0x4a, +0x69,0x12,0x67,0x69,0x74,0x33,0x1c,0x73,0x68,0x70,0x75,0x6e,0x63,0x74,0x75,0x61, +0x74,0x69,0x6f,0x6e,0x47,0x1a,0x63,0x69,0x6d,0x61,0x6c,0x6e,0x75,0x6d,0x62,0x65, +0x72,0x33,0,0x12,0x6d,0xc2,0x3f,0x73,0xa1,0x73,0x4e,0x74,0xa2,0x56,0x77,0xa2, +0x72,0x79,0xa2,0x73,0x7a,1,0x61,0x2c,0x68,0x12,0x61,0x69,0x6e,0x8b,0x11,0x69, +0x6e,0x85,5,0x74,0x22,0x74,0x38,0x77,0x4c,0x79,0x16,0x72,0x69,0x61,0x63,0x77, +0x61,0x77,0x6f,0x18,0x72,0x61,0x69,0x67,0x68,0x74,0x77,0x61,0x77,0xa3,0x55,0x15, +0x61,0x73,0x68,0x6b,0x61,0x66,0x6d,0x61,0x2e,0x65,0x38,0x68,0x11,0x69,0x6e,0x6b, +0x10,0x64,0x62,0x11,0x68,0x65,0x65,1,0x65,0x2e,0x6d,0x13,0x6b,0x61,0x74,0x68, +0x69,0x10,0x6e,0x67,1,0x61,0x4e,0x65,1,0x68,0x28,0x74,0x10,0x68,0x77,0x16, +0x6d,0x61,0x72,0x62,0x75,0x74,0x61,0x74,0x13,0x67,0x6f,0x61,0x6c,0x3d,1,0x68, +0x71,0x77,0x73,0x11,0x61,0x77,0x79,1,0x65,0x32,0x75,0x11,0x64,0x68,0x80,0x11, +0x68,0x65,0x83,0x10,0x68,0x7a,1,0x62,0x34,0x77,0x16,0x69,0x74,0x68,0x74,0x61, +0x69,0x6c,0x7f,0x14,0x61,0x72,0x72,0x65,0x65,0x7d,0x6d,0x6c,0x6e,0xa4,0x6b,0x70, +0xa4,0x88,0x71,0xa4,0x88,0x72,1,0x65,0x38,0x6f,0x18,0x68,0x69,0x6e,0x67,0x79, +0x61,0x79,0x65,0x68,0x93,1,0x68,0x5f,0x76,0x16,0x65,0x72,0x73,0x65,0x64,0x70, +0x65,0x61,2,0x61,0x2e,0x65,0xa4,0x3e,0x69,0x10,0x6d,0x53,1,0x6c,0xa2,0xe7, +0x6e,0x16,0x69,0x63,0x68,0x61,0x65,0x61,0x6e,0,0x12,0x6e,0x76,0x73,0x51,0x73, +0x3e,0x74,0x5c,0x77,0xa0,0x79,0xa2,0x42,0x7a,0x13,0x61,0x79,0x69,0x6e,0xa3,0x54, +0x10,0x61,1,0x64,0x2e,0x6d,0x12,0x65,0x6b,0x68,0xa3,0x4c,0x11,0x68,0x65,0xa3, +0x4b,3,0x61,0x38,0x65,0x3c,0x68,0x4a,0x77,0x13,0x65,0x6e,0x74,0x79,0xa3,0x51, +0x10,0x77,0xa3,0x4d,1,0x6e,0xa3,0x4e,0x74,0x10,0x68,0xa3,0x4f,0x14,0x61,0x6d, +0x65,0x64,0x68,0xa3,0x50,0x11,0x61,0x77,0xa3,0x52,0x12,0x6f,0x64,0x68,0xa3,0x53, +0x6e,0x3a,0x6f,0x40,0x70,0x46,0x71,0x4a,0x72,0x12,0x65,0x73,0x68,0xa3,0x4a,0x11, +0x75,0x6e,0xa3,0x46,0x11,0x6e,0x65,0xa3,0x47,0x10,0x65,0xa3,0x48,0x12,0x6f,0x70, +0x68,0xa3,0x49,0x67,0x33,0x67,0x38,0x68,0x40,0x6b,0x5e,0x6c,0x66,0x6d,0x11,0x65, +0x6d,0xa3,0x45,0x13,0x69,0x6d,0x65,0x6c,0xa1,1,0x65,0x32,0x75,0x14,0x6e,0x64, +0x72,0x65,0x64,0xa3,0x42,0x11,0x74,0x68,0xa3,0x41,0x12,0x61,0x70,0x68,0xa3,0x43, +0x14,0x61,0x6d,0x65,0x64,0x68,0xa3,0x44,0x61,0x34,0x62,0x4a,0x64,0x50,0x66,0x12, +0x69,0x76,0x65,0x9f,1,0x6c,0x2a,0x79,0x11,0x69,0x6e,0x97,0x12,0x65,0x70,0x68, +0x95,0x12,0x65,0x74,0x68,0x99,1,0x61,0x30,0x68,0x14,0x61,0x6d,0x65,0x64,0x68, +0x9d,0x13,0x6c,0x65,0x74,0x68,0x9b,0x15,0x61,0x79,0x61,0x6c,0x61,0x6d,6,0x6e, +0x2c,0x6e,0x34,0x72,0x5e,0x73,0x62,0x74,0x11,0x74,0x61,0xa3,0x63,2,0x67,0x2e, +0x6e,0x32,0x79,0x10,0x61,0xa3,0x60,0x10,0x61,0xa3,0x5d,1,0x61,0xa3,0x5e,0x6e, +0x10,0x61,0xa3,0x5f,0x10,0x61,0xa3,0x61,0x11,0x73,0x61,0xa3,0x62,0x62,0x3c,0x6a, +0x42,0x6c,0x10,0x6c,1,0x61,0xa3,0x5b,0x6c,0x10,0x61,0xa3,0x5c,0x11,0x68,0x61, +0xa3,0x59,0x10,0x61,0xa3,0x5a,0x11,0x65,0x6d,0x51,2,0x6f,0x2c,0x75,0x50,0x79, +0x10,0x61,0x91,1,0x6a,0x28,0x6f,0x10,0x6e,0x55,0x1a,0x6f,0x69,0x6e,0x69,0x6e, +0x67,0x67,0x72,0x6f,0x75,0x70,0x21,0x10,0x6e,0x57,0x10,0x65,0x59,0x10,0x61,1, +0x66,0x5b,0x70,0x10,0x68,0x5d,0x66,0x9a,0x66,0x42,0x67,0x7a,0x68,0x8a,0x6b,0xa2, +0x75,0x6c,0x11,0x61,0x6d,0x4c,0x12,0x61,0x64,0x68,0x4f,2,0x61,0x3e,0x65,0x4a, +0x69,0x19,0x6e,0x61,0x6c,0x73,0x65,0x6d,0x6b,0x61,0x74,0x68,0x35,0x15,0x72,0x73, +0x69,0x79,0x65,0x68,0x8f,0x86,0x10,0x68,0x33,0x10,0x61,1,0x66,0x37,0x6d,0x11, +0x61,0x6c,0x39,1,0x61,0x40,0x65,0x3e,1,0x68,0x28,0x74,0x10,0x68,0x45,0x40, +0x13,0x67,0x6f,0x61,0x6c,0x43,2,0x68,0x3b,0x6d,0x5c,0x6e,0x1a,0x69,0x66,0x69, +0x72,0x6f,0x68,0x69,0x6e,0x67,0x79,0x61,1,0x6b,0x2a,0x70,0x10,0x61,0xa3,0x65, +0x15,0x69,0x6e,0x6e,0x61,0x79,0x61,0xa3,0x64,0x1a,0x7a,0x61,0x6f,0x6e,0x68,0x65, +0x68,0x67,0x6f,0x61,0x6c,0x3d,2,0x61,0x3a,0x68,0x44,0x6e,0x17,0x6f,0x74,0x74, +0x65,0x64,0x68,0x65,0x68,0x4b,1,0x66,0x47,0x70,0x10,0x68,0x49,0x12,0x61,0x70, +0x68,0x89,0x61,0x2e,0x62,0x8a,0x64,0xa2,0x51,0x65,0x31,2,0x66,0x3c,0x69,0x70, +0x6c,1,0x61,0x28,0x65,0x10,0x66,0x27,0x11,0x70,0x68,0x25,0x14,0x72,0x69,0x63, +0x61,0x6e,2,0x66,0x30,0x6e,0x36,0x71,0x11,0x61,0x66,0xa3,0x58,0x11,0x65,0x68, +0xa3,0x56,0x12,0x6f,0x6f,0x6e,0xa3,0x57,0x10,0x6e,0x23,1,0x65,0x4a,0x75,0x10, +0x72,0x1f,0x75,0x73,0x68,0x61,0x73,0x6b,0x69,0x79,0x65,0x68,0x62,0x61,0x72,0x72, +0x65,0x65,0x8d,1,0x68,0x29,0x74,0x10,0x68,0x2b,0x11,0x61,0x6c,0x2c,0x16,0x61, +0x74,0x68,0x72,0x69,0x73,0x68,0x2f,7,0x6e,0x2e,0x6e,0x2c,0x72,0x3e,0x74,0x56, +0x75,0x21,0x18,0x6f,0x6e,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x21,0x28,0x1a,0x69, +0x67,0x68,0x74,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x29,0x2a,0x19,0x72,0x61,0x6e, +0x73,0x70,0x61,0x72,0x65,0x6e,0x74,0x2b,0x63,0x23,0x64,0x40,0x6a,0x56,0x6c,0x26, +0x19,0x65,0x66,0x74,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x27,0x24,0x19,0x75,0x61, +0x6c,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x25,0x19,0x6f,0x69,0x6e,0x63,0x61,0x75, +0x73,0x69,0x6e,0x67,0x23,0,0x13,0x6e,0xc0,0xd0,0x73,0x49,0x73,0x48,0x75,0x78, +0x77,0x84,0x78,0x9c,0x7a,0x10,0x77,0x58,1,0x6a,0x75,0x73,0x13,0x70,0x61,0x63, +0x65,0x59,4,0x61,0x51,0x67,0x53,0x70,0x28,0x75,0x30,0x79,0x57,0x54,0x12,0x61, +0x63,0x65,0x55,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x53,0x15,0x6e,0x6b,0x6e, +0x6f,0x77,0x6e,0x21,1,0x6a,0x5d,0x6f,0x17,0x72,0x64,0x6a,0x6f,0x69,0x6e,0x65, +0x72,0x5d,0x10,0x78,0x21,0x6e,0x60,0x6f,0xa2,0x41,0x70,0xa2,0x50,0x71,0xa2,0x6e, +0x72,1,0x65,0x24,0x69,0x6f,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64, +0x69,0x63,0x61,0x74,0x6f,0x72,0x6f,4,0x65,0x3e,0x6c,0x5b,0x6f,0x46,0x73,0x45, +0x75,0x46,0x14,0x6d,0x65,0x72,0x69,0x63,0x47,0x15,0x78,0x74,0x6c,0x69,0x6e,0x65, +0x5b,0x17,0x6e,0x73,0x74,0x61,0x72,0x74,0x65,0x72,0x45,0x10,0x70,0x48,0x1c,0x65, +0x6e,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x49,1,0x6f,0x3e, +0x72,0x4c,0x1a,0x65,0x66,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x4d,0x4a, +0x1b,0x73,0x74,0x66,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x4b,0x10,0x75, +0x4e,0x16,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0x4f,0x68,0x7b,0x68,0x50,0x69,0x86, +0x6a,0xa2,0x61,0x6c,0xa2,0x65,0x6d,0x1c,0x61,0x6e,0x64,0x61,0x74,0x6f,0x72,0x79, +0x62,0x72,0x65,0x61,0x6b,0x2d,4,0x32,0x5f,0x33,0x61,0x65,0x34,0x6c,0x6d,0x79, +0x3a,0x13,0x70,0x68,0x65,0x6e,0x3b,0x19,0x62,0x72,0x65,0x77,0x6c,0x65,0x74,0x74, +0x65,0x72,0x6d,2,0x64,0x28,0x6e,0x3c,0x73,0x41,0x3c,0x18,0x65,0x6f,0x67,0x72, +0x61,0x70,0x68,0x69,0x63,0x3d,0x3e,1,0x66,0x3e,0x73,0x11,0x65,0x70,1,0x61, +0x22,0x65,0x14,0x72,0x61,0x62,0x6c,0x65,0x3f,0x18,0x69,0x78,0x6e,0x75,0x6d,0x65, +0x72,0x69,0x63,0x41,2,0x6c,0x63,0x74,0x65,0x76,0x67,1,0x66,0x43,0x69,0x15, +0x6e,0x65,0x66,0x65,0x65,0x64,0x43,0x61,0x40,0x62,0x70,0x63,0xa2,0x55,0x65,0xa2, +0xdb,0x67,0x10,0x6c,0x38,0x11,0x75,0x65,0x39,2,0x69,0x23,0x6c,0x34,0x6d,0x16, +0x62,0x69,0x67,0x75,0x6f,0x75,0x73,0x23,0x24,0x17,0x70,0x68,0x61,0x62,0x65,0x74, +0x69,0x63,0x25,4,0x32,0x27,0x61,0x29,0x62,0x2b,0x6b,0x2d,0x72,0x12,0x65,0x61, +0x6b,2,0x61,0x36,0x62,0x3e,0x73,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x57,0x13, +0x66,0x74,0x65,0x72,0x29,1,0x65,0x2a,0x6f,0x11,0x74,0x68,0x27,0x13,0x66,0x6f, +0x72,0x65,0x2b,7,0x6d,0x51,0x6d,0x33,0x6f,0x28,0x70,0x69,0x72,0x35,1,0x6d, +0x76,0x6e,1,0x64,0x3c,0x74,0x1a,0x69,0x6e,0x67,0x65,0x6e,0x74,0x62,0x72,0x65, +0x61,0x6b,0x2f,0x15,0x69,0x74,0x69,0x6f,0x6e,0x61,0x1f,0x6c,0x6a,0x61,0x70,0x61, +0x6e,0x65,0x73,0x65,0x73,0x74,0x61,0x72,0x74,0x65,0x72,0x6b,1,0x62,0x3a,0x70, +0x19,0x6c,0x65,0x78,0x63,0x6f,0x6e,0x74,0x65,0x78,0x74,0x51,0x18,0x69,0x6e,0x69, +0x6e,0x67,0x6d,0x61,0x72,0x6b,0x33,0x61,0x6a,0x62,0x2f,0x6a,0x6b,0x6c,0x30,0x13, +0x6f,0x73,0x65,0x70,1,0x61,0x38,0x75,0x18,0x6e,0x63,0x74,0x75,0x61,0x74,0x69, +0x6f,0x6e,0x31,0x18,0x72,0x65,0x6e,0x74,0x68,0x65,0x73,0x69,0x73,0x69,0x1b,0x72, +0x72,0x69,0x61,0x67,0x65,0x72,0x65,0x74,0x75,0x72,0x6e,0x35,2,0x62,0x3e,0x6d, +0x46,0x78,0x36,0x18,0x63,0x6c,0x61,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x37,0x70,0x12, +0x61,0x73,0x65,0x71,0x72,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x73,1,0x64, +0x42,0x6e,1,0x6f,0x32,0x75,0x26,0x14,0x6d,0x65,0x72,0x69,0x63,0x27,0x11,0x6e, +0x65,0x21,1,0x65,0x2e,0x69,0x24,0x12,0x67,0x69,0x74,0x25,0x22,0x14,0x63,0x69, +0x6d,0x61,0x6c,0x23,0,0x18,0x6e,0xc4,0x2a,0x74,0xc1,0x6d,0x77,0x96,0x77,0xa2, +0x4c,0x78,0xa2,0x70,0x79,0xa2,0x7a,0x7a,6,0x73,0x1e,0x73,0x34,0x78,0x42,0x79, +0x48,0x7a,0x11,0x7a,0x7a,0xa3,0x67,0x10,0x79,1,0x65,0xa3,0xae,0x6d,0xa3,0x81, +0x11,0x78,0x78,0xa3,0x66,0x11,0x79,0x79,0x21,0x61,0x30,0x69,0x58,0x6d,0x11,0x74, +0x68,0xa3,0x80,0x10,0x6e,1,0x61,0x26,0x62,0xa3,0xb1,0x1a,0x62,0x61,0x7a,0x61, +0x72,0x73,0x71,0x75,0x61,0x72,0x65,0xa3,0xb1,0x11,0x6e,0x68,0x23,2,0x61,0x30, +0x63,0x5a,0x6f,0x11,0x6c,0x65,0xa3,0x9b,1,0x6e,0x3c,0x72,0x10,0x61,0xa2,0x92, +0x15,0x6e,0x67,0x63,0x69,0x74,0x69,0xa3,0x92,0x12,0x63,0x68,0x6f,0xa3,0xbc,0x11, +0x68,0x6f,0xa3,0xbc,1,0x70,0x2c,0x73,0x11,0x75,0x78,0xa3,0x65,0x11,0x65,0x6f, +0x9b,1,0x65,0x2c,0x69,0x72,0x11,0x69,0x69,0x73,0x11,0x7a,0x69,0xa2,0xc0,0x11, +0x64,0x69,0xa3,0xc0,0x74,0x4a,0x75,0xa2,0xba,0x76,1,0x61,0x2c,0x69,0x11,0x73, +0x70,0xa3,0x64,0x10,0x69,0xa2,0x63,0x10,0x69,0xa3,0x63,5,0x67,0x36,0x67,0x68, +0x68,0x6c,0x69,2,0x62,0x3a,0x66,0x4a,0x72,0x10,0x68,0xa2,0x9e,0x12,0x75,0x74, +0x61,0xa3,0x9e,1,0x65,0x24,0x74,0x6f,0x12,0x74,0x61,0x6e,0x6f,0x14,0x69,0x6e, +0x61,0x67,0x68,0x99,0x11,0x6c,0x67,0x75,0x10,0x61,1,0x61,0x24,0x69,0x6d,0x6a, +0x11,0x6e,0x61,0x6b,0x61,0x30,0x65,0xa2,0x5b,0x66,0x11,0x6e,0x67,0x99,6,0x6c, +0x21,0x6c,0x32,0x6d,0x38,0x6e,0x44,0x76,0x10,0x74,0xa3,0x7f,1,0x65,0x89,0x75, +0x97,1,0x69,0x24,0x6c,0x67,0x10,0x6c,0x67,0x10,0x67,0xa2,0x9a,0x11,0x75,0x74, +0xa3,0x9a,0x67,0x36,0x69,0x52,0x6b,0x10,0x72,0xa2,0x99,0x10,0x69,0xa3,0x99,1, +0x61,0x30,0x62,0x7a,0x13,0x61,0x6e,0x77,0x61,0x7b,0x12,0x6c,0x6f,0x67,0x75,2, +0x6c,0x32,0x74,0x34,0x76,0x12,0x69,0x65,0x74,0xa3,0x7f,0x10,0x65,0x89,0x12,0x68, +0x61,0x6d,0xa3,0x6a,1,0x6c,0x2a,0x6e,0x10,0x67,0xa3,0x62,0x10,0x75,0x68,0x11, +0x67,0x75,0x69,1,0x67,0x32,0x6e,0x14,0x6b,0x6e,0x6f,0x77,0x6e,0xa3,0x67,0x11, +0x61,0x72,0x8a,0x13,0x69,0x74,0x69,0x63,0x8b,0x71,0xc1,0x13,0x71,0xa2,0xde,0x72, +0xa2,0xe3,0x73,6,0x69,0x8a,0x69,0x72,0x6f,0xa2,0x4c,0x75,0xa2,0x75,0x79,1, +0x6c,0x46,0x72,4,0x63,0x65,0x65,0xa3,0x5f,0x69,0x2c,0x6a,0xa3,0x60,0x6e,0xa3, +0x61,0x11,0x61,0x63,0x65,0x10,0x6f,0x94,0x16,0x74,0x69,0x6e,0x61,0x67,0x72,0x69, +0x95,2,0x64,0x3c,0x67,0x4c,0x6e,1,0x64,0xa3,0x91,0x68,0x62,0x12,0x61,0x6c, +0x61,0x63,0x10,0x64,0xa2,0xa6,0x12,0x68,0x61,0x6d,0xa3,0xa6,0x17,0x6e,0x77,0x72, +0x69,0x74,0x69,0x6e,0x67,0xa3,0x70,2,0x67,0x3a,0x72,0x52,0x79,0x10,0x6f,0xa2, +0xb0,0x12,0x6d,0x62,0x6f,0xa3,0xb0,1,0x64,0x26,0x6f,0xa3,0xb8,0xa2,0xb7,0x12, +0x69,0x61,0x6e,0xa3,0xb7,0x10,0x61,0xa2,0x98,0x16,0x73,0x6f,0x6d,0x70,0x65,0x6e, +0x67,0xa3,0x98,0x11,0x6e,0x64,0xa2,0x71,0x14,0x61,0x6e,0x65,0x73,0x65,0xa3,0x71, +0x61,0x5c,0x67,0xa2,0x43,0x68,1,0x61,0x2a,0x72,0x10,0x64,0xa3,0x97,2,0x72, +0x28,0x76,0x30,0x77,0x87,0x12,0x61,0x64,0x61,0xa3,0x97,0x12,0x69,0x61,0x6e,0x87, +2,0x6d,0x40,0x72,0x58,0x75,0x10,0x72,0xa2,0x6f,0x15,0x61,0x73,0x68,0x74,0x72, +0x61,0xa3,0x6f,1,0x61,0x26,0x72,0xa3,0x7e,0x14,0x72,0x69,0x74,0x61,0x6e,0xa3, +0x7e,1,0x61,0xa3,0x5e,0x62,0xa3,0x85,0x11,0x6e,0x77,0xa3,0x70,0x11,0x61,0x61, +1,0x63,0x2f,0x69,0x23,3,0x65,0x3e,0x6a,0x48,0x6f,0x4e,0x75,0x10,0x6e,1, +0x69,0x24,0x72,0x61,0x10,0x63,0x61,0x13,0x6a,0x61,0x6e,0x67,0xa3,0x6e,0x11,0x6e, +0x67,0xa3,0x6e,1,0x68,0x2a,0x72,0x10,0x6f,0xa3,0x5d,0x10,0x67,0xa3,0xb6,0x6e, +0xa2,0x83,0x6f,0xa2,0xf2,0x70,5,0x6c,0x1e,0x6c,0x44,0x72,0x4a,0x73,0x1b,0x61, +0x6c,0x74,0x65,0x72,0x70,0x61,0x68,0x6c,0x61,0x76,0x69,0xa3,0x7b,0x11,0x72,0x64, +0xa3,0x5c,0x11,0x74,0x69,0xa3,0x7d,0x61,0x7c,0x65,0xa2,0x54,0x68,3,0x61,0x3e, +0x6c,0x4e,0x6e,0x5e,0x6f,0x16,0x65,0x6e,0x69,0x63,0x69,0x61,0x6e,0xa3,0x5b,0x10, +0x67,0xa2,0x5a,0x12,0x73,0x70,0x61,0xa3,0x5a,2,0x69,0xa3,0x7a,0x70,0xa3,0x7b, +0x76,0xa3,0x7c,0x10,0x78,0xa3,0x5b,2,0x68,0x3e,0x6c,0x50,0x75,0x10,0x63,0xa2, +0xa5,0x14,0x69,0x6e,0x68,0x61,0x75,0xa3,0xa5,0x17,0x61,0x77,0x68,0x68,0x6d,0x6f, +0x6e,0x67,0xa3,0x4b,0x10,0x6d,0xa2,0x90,0x14,0x79,0x72,0x65,0x6e,0x65,0xa3,0x90, +0x11,0x72,0x6d,0xa3,0x59,6,0x6b,0x36,0x6b,0x56,0x73,0x6e,0x75,0x74,0x79,0x11, +0x69,0x61,0x1f,0x6b,0x65,0x6e,0x67,0x70,0x75,0x61,0x63,0x68,0x75,0x65,0x68,0x6d, +0x6f,0x6e,0x67,0xa3,0xba,1,0x67,0x2e,0x6f,0xa2,0x57,0x10,0x6f,0xa3,0x57,0x10, +0x62,0xa3,0x84,0x11,0x68,0x75,0xa3,0x96,0x12,0x73,0x68,0x75,0xa3,0x96,0x61,0x42, +0x62,0x80,0x65,0x10,0x77,1,0x61,0xa3,0xaa,0x74,0x14,0x61,0x69,0x6c,0x75,0x65, +0x97,2,0x62,0x2e,0x6e,0x3c,0x72,0x10,0x62,0xa3,0x8e,0x15,0x61,0x74,0x61,0x65, +0x61,0x6e,0xa3,0x8f,0x10,0x64,0xa2,0xbb,0x16,0x69,0x6e,0x61,0x67,0x61,0x72,0x69, +0xa3,0xbb,0x11,0x61,0x74,0xa3,0x8f,3,0x67,0x5a,0x6c,0x6c,0x72,0xa2,0x93,0x73, +2,0x61,0x36,0x67,0x3c,0x6d,0x10,0x61,0x84,0x12,0x6e,0x79,0x61,0x85,0x11,0x67, +0x65,0xa3,0xab,0x10,0x65,0xa3,0xab,1,0x61,0x2a,0x68,0x11,0x61,0x6d,0x5b,0x10, +0x6d,0x5b,1,0x63,0xa2,0x60,0x64,5,0x70,0x37,0x70,0x36,0x73,0x54,0x74,0x14, +0x75,0x72,0x6b,0x69,0x63,0xa3,0x58,0x11,0x65,0x72,1,0x6d,0x2c,0x73,0x12,0x69, +0x61,0x6e,0x9b,0x11,0x69,0x63,0xa3,0x59,0x10,0x6f,1,0x67,0x3a,0x75,0x18,0x74, +0x68,0x61,0x72,0x61,0x62,0x69,0x61,0x6e,0xa3,0x85,0x13,0x64,0x69,0x61,0x6e,0xa3, +0xb8,0x68,0x42,0x69,0x54,0x6e,0x1a,0x6f,0x72,0x74,0x68,0x61,0x72,0x61,0x62,0x69, +0x61,0x6e,0xa3,0x8e,0x17,0x75,0x6e,0x67,0x61,0x72,0x69,0x61,0x6e,0xa3,0x4c,0x14, +0x74,0x61,0x6c,0x69,0x63,0x5d,1,0x68,0x26,0x6b,0xa3,0x6d,0x12,0x69,0x6b,0x69, +0xa3,0x6d,2,0x69,0x2c,0x6b,0x30,0x79,0x10,0x61,0x5f,0x11,0x79,0x61,0x5f,0x10, +0x68,0xa3,0x58,0x68,0xc3,0xd,0x6b,0xc2,0x24,0x6b,0xa4,0x17,0x6c,0xa4,0xb2,0x6d, +8,0x6f,0x46,0x6f,0x48,0x72,0x74,0x74,0x80,0x75,0x86,0x79,1,0x61,0x28,0x6d, +0x10,0x72,0x59,0x13,0x6e,0x6d,0x61,0x72,0x59,2,0x64,0x2e,0x6e,0x32,0x6f,0x10, +0x6e,0xa3,0x72,0x10,0x69,0xa3,0xa3,0x10,0x67,0x56,0x14,0x6f,0x6c,0x69,0x61,0x6e, +0x57,0x10,0x6f,0xa2,0x95,0x10,0x6f,0xa3,0x95,0x11,0x65,0x69,0xa3,0x73,0x11,0x6c, +0x74,0xa2,0xa4,0x12,0x61,0x6e,0x69,0xa3,0xa4,0x61,0x36,0x65,0xa2,0x67,0x69,0xa2, +0xbd,0x6c,0x11,0x79,0x6d,0x55,6,0x6e,0x38,0x6e,0x32,0x72,0x5c,0x73,0x6c,0x79, +0x10,0x61,0xa3,0x55,1,0x64,0x38,0x69,0xa2,0x79,0x15,0x63,0x68,0x61,0x65,0x61, +0x6e,0xa3,0x79,0xa2,0x54,0x12,0x61,0x69,0x63,0xa3,0x54,0x10,0x63,0xa2,0xa9,0x12, +0x68,0x65,0x6e,0xa3,0xa9,0x18,0x61,0x72,0x61,0x6d,0x67,0x6f,0x6e,0x64,0x69,0xa3, +0xaf,0x68,0x36,0x6b,0x4c,0x6c,0x15,0x61,0x79,0x61,0x6c,0x61,0x6d,0x55,1,0x61, +0x26,0x6a,0xa3,0xa0,0x13,0x6a,0x61,0x6e,0x69,0xa3,0xa0,0x10,0x61,0xa2,0xb4,0x12, +0x73,0x61,0x72,0xa3,0xb4,3,0x64,0x78,0x65,0x94,0x6e,0xa2,0x42,0x72,1,0x63, +0xa3,0x8d,0x6f,0xa2,0x56,0x13,0x69,0x74,0x69,0x63,1,0x63,0x3c,0x68,0x19,0x69, +0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0x56,0x15,0x75,0x72,0x73,0x69, +0x76,0x65,0xa3,0x8d,1,0x65,0x26,0x66,0xa3,0xb5,0x16,0x66,0x61,0x69,0x64,0x72, +0x69,0x6e,0xa3,0xb5,0x17,0x74,0x65,0x69,0x6d,0x61,0x79,0x65,0x6b,0xa3,0x73,0x10, +0x64,0xa2,0x8c,0x17,0x65,0x6b,0x69,0x6b,0x61,0x6b,0x75,0x69,0xa3,0x8c,0x11,0x61, +0x6f,0xa3,0x5c,6,0x6e,0x1a,0x6e,0x34,0x6f,0x38,0x70,0x3e,0x74,0x11,0x68,0x69, +0xa3,0x78,0x11,0x64,0x61,0x4b,0x11,0x72,0x65,0xa3,0x77,0x11,0x65,0x6c,0xa3,0x8a, +0x61,0x30,0x68,0x9a,0x69,0x11,0x74,0x73,0xa3,0xbf,4,0x69,0x3c,0x6c,0x44,0x6e, +0x48,0x74,0x56,0x79,0x13,0x61,0x68,0x6c,0x69,0xa3,0x4f,0x12,0x74,0x68,0x69,0xa3, +0x78,0x10,0x69,0xa3,0x4f,1,0x61,0x4d,0x6e,0x12,0x61,0x64,0x61,0x4b,0x14,0x61, +0x6b,0x61,0x6e,0x61,0x4c,0x19,0x6f,0x72,0x68,0x69,0x72,0x61,0x67,0x61,0x6e,0x61, +0x8d,4,0x61,0x40,0x69,0x52,0x6d,0x70,0x6f,0x7c,0x75,0x15,0x64,0x61,0x77,0x61, +0x64,0x69,0xa3,0x91,0x10,0x72,0x92,0x15,0x6f,0x73,0x68,0x74,0x68,0x69,0x93,0x1d, +0x74,0x61,0x6e,0x73,0x6d,0x61,0x6c,0x6c,0x73,0x63,0x72,0x69,0x70,0x74,0xa3,0xbf, +1,0x65,0x24,0x72,0x4f,0x10,0x72,0x4f,0x10,0x6a,0xa2,0x9d,0x11,0x6b,0x69,0xa3, +0x9d,4,0x61,0x5c,0x65,0x90,0x69,0xa0,0x6f,0xa2,0x5d,0x79,1,0x63,0x34,0x64, +0x10,0x69,0xa2,0x6c,0x11,0x61,0x6e,0xa3,0x6c,0x10,0x69,0xa2,0x6b,0x11,0x61,0x6e, +0xa3,0x6b,2,0x6e,0x42,0x6f,0x46,0x74,3,0x66,0xa3,0x50,0x67,0xa3,0x51,0x69, +0x24,0x6e,0x53,0x10,0x6e,0x53,0x10,0x61,0xa3,0x6a,0x50,0x10,0x6f,0x51,0x11,0x70, +0x63,0xa2,0x52,0x11,0x68,0x61,0xa3,0x52,2,0x6d,0x2e,0x6e,0x36,0x73,0x10,0x75, +0xa3,0x83,0x10,0x62,0x80,0x10,0x75,0x81,2,0x61,0xa3,0x53,0x62,0x83,0x65,0x11, +0x61,0x72,1,0x61,0xa3,0x53,0x62,0x83,0x11,0x6d,0x61,0xa3,0x8b,0x68,0x6e,0x69, +0xa2,0x95,0x6a,2,0x61,0x30,0x70,0x52,0x75,0x11,0x72,0x63,0xa3,0x94,1,0x6d, +0x38,0x76,0x10,0x61,0xa2,0x4e,0x13,0x6e,0x65,0x73,0x65,0xa3,0x4e,0x10,0x6f,0xa3, +0xad,0x11,0x61,0x6e,0xa3,0x69,6,0x6c,0x1e,0x6c,0x34,0x6d,0x3a,0x72,0x48,0x75, +0x11,0x6e,0x67,0xa3,0x4c,0x11,0x75,0x77,0xa3,0x9c,0x10,0x6e,1,0x67,0xa3,0x4b, +0x70,0xa3,0xba,0x11,0x6b,0x74,0x8d,0x61,0x3c,0x65,0xa2,0x43,0x69,0x11,0x72,0x61, +0x48,0x13,0x67,0x61,0x6e,0x61,0x49,1,0x6e,0x34,0x74,0x10,0x72,0xa2,0xa2,0x11, +0x61,0x6e,0xa3,0xa2,0x42,6,0x6f,0xe,0x6f,0x77,0x73,0xa3,0x49,0x74,0xa3,0x4a, +0x75,0x12,0x6e,0x6f,0x6f,0x77,0x62,0xa3,0xac,0x67,0x3e,0x69,0x42,0x19,0x66,0x69, +0x72,0x6f,0x68,0x69,0x6e,0x67,0x79,0x61,0xa3,0xb6,0x44,0x11,0x75,0x6c,0x45,0x11, +0x62,0x72,0x46,0x11,0x65,0x77,0x47,2,0x6d,0x2e,0x6e,0x4a,0x74,0x11,0x61,0x6c, +0x5d,0x1c,0x70,0x65,0x72,0x69,0x61,0x6c,0x61,0x72,0x61,0x6d,0x61,0x69,0x63,0xa3, +0x74,2,0x64,0x66,0x68,0x6a,0x73,0x1b,0x63,0x72,0x69,0x70,0x74,0x69,0x6f,0x6e, +0x61,0x6c,0x70,0x61,1,0x68,0x32,0x72,0x14,0x74,0x68,0x69,0x61,0x6e,0xa3,0x7d, +0x13,0x6c,0x61,0x76,0x69,0xa3,0x7a,0x10,0x73,0xa3,0x4d,0x15,0x65,0x72,0x69,0x74, +0x65,0x64,0x23,0x64,0xc1,0xd,0x64,0xa2,0x7a,0x65,0xa2,0xc1,0x67,4,0x65,0x82, +0x6c,0x9a,0x6f,0xa2,0x46,0x72,0xa2,0x55,0x75,2,0x6a,0x3c,0x6e,0x4e,0x72,1, +0x6d,0x24,0x75,0x41,0x13,0x75,0x6b,0x68,0x69,0x41,1,0x61,0x24,0x72,0x3f,0x13, +0x72,0x61,0x74,0x69,0x3f,0x18,0x6a,0x61,0x6c,0x61,0x67,0x6f,0x6e,0x64,0x69,0xa3, +0xb3,0x10,0x6f,1,0x6b,0xa3,0x48,0x72,0x38,0x13,0x67,0x69,0x61,0x6e,0x39,0x11, +0x61,0x67,0x90,0x15,0x6f,0x6c,0x69,0x74,0x69,0x63,0x91,1,0x6e,0x30,0x74,0x10, +0x68,0x3a,0x11,0x69,0x63,0x3b,1,0x67,0xa3,0xb3,0x6d,0xa3,0xaf,1,0x61,0x32, +0x65,1,0x65,0x24,0x6b,0x3d,0x10,0x6b,0x3d,0x10,0x6e,0xa2,0x89,0x12,0x74,0x68, +0x61,0xa3,0x89,4,0x65,0x46,0x69,0x6c,0x6f,0x8c,0x73,0x9a,0x75,0x11,0x70,0x6c, +0xa2,0x87,0x13,0x6f,0x79,0x61,0x6e,0xa3,0x87,1,0x73,0x38,0x76,0x10,0x61,0x34, +0x15,0x6e,0x61,0x67,0x61,0x72,0x69,0x35,0x13,0x65,0x72,0x65,0x74,0x33,1,0x61, +0x36,0x76,0x16,0x65,0x73,0x61,0x6b,0x75,0x72,0x75,0xa3,0xbe,0x10,0x6b,0xa3,0xbe, +0x11,0x67,0x72,0xa2,0xb2,0x10,0x61,0xa3,0xb2,0x11,0x72,0x74,0x33,2,0x67,0x3a, +0x6c,0x72,0x74,0x11,0x68,0x69,0x36,0x13,0x6f,0x70,0x69,0x63,0x37,0x10,0x79,2, +0x64,0xa3,0x45,0x68,0xa3,0x46,0x70,0xa2,0x47,0x1e,0x74,0x69,0x61,0x6e,0x68,0x69, +0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0x47,1,0x62,0x36,0x79,0x10, +0x6d,0xa2,0xb9,0x12,0x61,0x69,0x63,0xa3,0xb9,0x10,0x61,0xa2,0x88,0x12,0x73,0x61, +0x6e,0xa3,0x88,0x61,0xa2,0xb4,0x62,0xa4,0x19,0x63,6,0x6f,0x3d,0x6f,0x5a,0x70, +0x76,0x75,0x7a,0x79,1,0x70,0x3e,0x72,2,0x69,0x2a,0x6c,0x31,0x73,0xa3,0x44, +0x13,0x6c,0x6c,0x69,0x63,0x31,0x13,0x72,0x69,0x6f,0x74,0x7f,1,0x6d,0x30,0x70, +0x10,0x74,0x2e,0x11,0x69,0x63,0x2f,0x12,0x6d,0x6f,0x6e,0x21,0x11,0x72,0x74,0x7f, +0x16,0x6e,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa3,0x65,0x61,0x32,0x68,0xa2,0x41,0x69, +0x11,0x72,0x74,0xa3,0x43,3,0x6b,0x4c,0x6e,0x50,0x72,0x76,0x75,0x1d,0x63,0x61, +0x73,0x69,0x61,0x6e,0x61,0x6c,0x62,0x61,0x6e,0x69,0x61,0x6e,0xa3,0x9f,0x10,0x6d, +0xa3,0x76,1,0x61,0x24,0x73,0x71,0x1d,0x64,0x69,0x61,0x6e,0x61,0x62,0x6f,0x72, +0x69,0x67,0x69,0x6e,0x61,0x6c,0x71,0x10,0x69,0xa2,0x68,0x11,0x61,0x6e,0xa3,0x68, +3,0x61,0x32,0x65,0x44,0x6f,0x52,0x72,0x10,0x73,0xa3,0xbd,1,0x6b,0x26,0x6d, +0xa3,0x42,0x11,0x6d,0x61,0xa3,0x76,0x10,0x72,0x2c,0x13,0x6f,0x6b,0x65,0x65,0x2d, +0x16,0x72,0x61,0x73,0x6d,0x69,0x61,0x6e,0xa3,0xbd,6,0x68,0x4a,0x68,0x48,0x6e, +0x4e,0x72,0x76,0x76,1,0x65,0x2a,0x73,0x10,0x74,0xa3,0x75,0x13,0x73,0x74,0x61, +0x6e,0xa3,0x75,0x11,0x6f,0x6d,0xa3,0xa1,0x11,0x61,0x74,0x1f,0x6f,0x6c,0x69,0x61, +0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0x9c,1,0x61, +0x3e,0x6d,2,0x65,0x2a,0x69,0xa3,0x74,0x6e,0x27,0x13,0x6e,0x69,0x61,0x6e,0x27, +0x10,0x62,0x24,0x11,0x69,0x63,0x25,0x64,0x30,0x66,0x44,0x67,0x11,0x68,0x62,0xa3, +0x9f,0x10,0x6c,1,0x61,0x26,0x6d,0xa3,0xa7,0x10,0x6d,0xa3,0xa7,0x11,0x61,0x6b, +0xa3,0x93,6,0x6c,0x3c,0x6c,0x52,0x6f,0x56,0x72,0x66,0x75,1,0x67,0x30,0x68, +1,0x64,0x79,0x69,0x10,0x64,0x79,0x10,0x69,0x8e,0x13,0x6e,0x65,0x73,0x65,0x8f, +0x11,0x69,0x73,0xa1,0x11,0x70,0x6f,0x2a,0x13,0x6d,0x6f,0x66,0x6f,0x2b,0x10,0x61, +1,0x68,0x2e,0x69,0x7c,0x12,0x6c,0x6c,0x65,0x7d,0xa2,0x41,0x11,0x6d,0x69,0xa3, +0x41,0x61,0x48,0x65,0x9c,0x68,1,0x61,0x2a,0x6b,0x10,0x73,0xa3,0xa8,0x15,0x69, +0x6b,0x73,0x75,0x6b,0x69,0xa3,0xa8,3,0x6c,0x3a,0x6d,0x48,0x73,0x54,0x74,1, +0x61,0x24,0x6b,0x9f,0x10,0x6b,0x9f,0x10,0x69,0x9c,0x13,0x6e,0x65,0x73,0x65,0x9d, +0x10,0x75,0xa2,0x82,0x10,0x6d,0xa3,0x82,0x10,0x73,0xa2,0x86,0x13,0x61,0x76,0x61, +0x68,0xa3,0x86,0x11,0x6e,0x67,0x28,0x12,0x61,0x6c,0x69,0x29,3,0x6c,0x42,0x6e, +0x90,0x74,0xa2,0x46,0x76,0x24,0x17,0x6f,0x77,0x65,0x6c,0x6a,0x61,0x6d,0x6f,0x25, +0x22,1,0x65,0x54,0x76,0x28,1,0x73,0x38,0x74,0x2a,0x17,0x73,0x79,0x6c,0x6c, +0x61,0x62,0x6c,0x65,0x2b,0x16,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x29,0x18,0x61, +0x64,0x69,0x6e,0x67,0x6a,0x61,0x6d,0x6f,0x23,1,0x61,0x21,0x6f,0x1a,0x74,0x61, +0x70,0x70,0x6c,0x69,0x63,0x61,0x62,0x6c,0x65,0x21,0x26,0x1a,0x72,0x61,0x69,0x6c, +0x69,0x6e,0x67,0x6a,0x61,0x6d,0x6f,0x27,1,0x6e,0x2c,0x79,0x22,0x11,0x65,0x73, +0x23,0x20,0x10,0x6f,0x21,1,0x6e,0x2c,0x79,0x22,0x11,0x65,0x73,0x23,0x20,0x10, +0x6f,0x21,2,0x6d,0x30,0x6e,0x3a,0x79,0x22,0x11,0x65,0x73,0x23,0x24,0x13,0x61, +0x79,0x62,0x65,0x25,0x20,0x10,0x6f,0x21,2,0x6d,0x30,0x6e,0x3a,0x79,0x22,0x11, +0x65,0x73,0x23,0x24,0x13,0x61,0x79,0x62,0x65,0x25,0x20,0x10,0x6f,0x21,0xb,0x72, +0x39,0x76,0xc,0x76,0x33,0x78,0x2a,0x7a,0x11,0x77,0x6a,0x43,0x10,0x78,0x21,0x72, +0x28,0x73,0x50,0x74,0x31,1,0x65,0x24,0x69,0x39,0x1e,0x67,0x69,0x6f,0x6e,0x61, +0x6c,0x69,0x6e,0x64,0x69,0x63,0x61,0x74,0x6f,0x72,0x39,1,0x6d,0x35,0x70,0x18, +0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x35,0x6c,0x1f,0x6c,0x3c,0x6f,0x4a, +0x70,1,0x70,0x37,0x72,0x14,0x65,0x70,0x65,0x6e,0x64,0x37,0x28,1,0x66,0x2b, +0x76,0x2c,0x10,0x74,0x2f,0x13,0x74,0x68,0x65,0x72,0x21,0x63,0x4c,0x65,0x64,0x67, +1,0x61,0x3a,0x6c,0x19,0x75,0x65,0x61,0x66,0x74,0x65,0x72,0x7a,0x77,0x6a,0x41, +0x10,0x7a,0x41,2,0x6e,0x23,0x6f,0x24,0x72,0x25,0x14,0x6e,0x74,0x72,0x6f,0x6c, +0x23,2,0x62,0x34,0x6d,0x4e,0x78,0x26,0x13,0x74,0x65,0x6e,0x64,0x27,0x3a,1, +0x61,0x24,0x67,0x3d,0x11,0x73,0x65,0x3a,0x12,0x67,0x61,0x7a,0x3d,0x3e,0x16,0x6f, +0x64,0x69,0x66,0x69,0x65,0x72,0x3f,9,0x6e,0x4a,0x6e,0x34,0x6f,0x44,0x73,0x60, +0x75,0x94,0x78,0x10,0x78,0x21,0x10,0x75,0x2a,0x14,0x6d,0x65,0x72,0x69,0x63,0x2b, +1,0x6c,0x2c,0x74,0x12,0x68,0x65,0x72,0x21,0x14,0x65,0x74,0x74,0x65,0x72,0x2d, +3,0x63,0x36,0x65,0x46,0x70,0x31,0x74,0x32,0x12,0x65,0x72,0x6d,0x33,0x3c,0x16, +0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x3d,0x2e,0x10,0x70,0x2f,0x10,0x70,0x34,0x12, +0x70,0x65,0x72,0x35,0x61,0x46,0x63,0x52,0x65,0x64,0x66,0x72,0x6c,2,0x65,0x2d, +0x66,0x3b,0x6f,0x28,0x12,0x77,0x65,0x72,0x29,0x10,0x74,0x22,0x12,0x65,0x72,0x6d, +0x23,1,0x6c,0x24,0x72,0x37,0x24,0x12,0x6f,0x73,0x65,0x25,0x10,0x78,0x38,0x13, +0x74,0x65,0x6e,0x64,0x39,0x10,0x6f,0x26,0x13,0x72,0x6d,0x61,0x74,0x27,0,0x10, +0x6c,0x88,0x72,0x40,0x72,0x36,0x73,0x5e,0x77,0x7a,0x78,0x8a,0x7a,0x11,0x77,0x6a, +0x4b,1,0x65,0x24,0x69,0x3b,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64, +0x69,0x63,0x61,0x74,0x6f,0x72,0x3b,1,0x69,0x24,0x71,0x3f,0x18,0x6e,0x67,0x6c, +0x65,0x71,0x75,0x6f,0x74,0x65,0x3f,0x17,0x73,0x65,0x67,0x73,0x70,0x61,0x63,0x65, +0x4d,0x10,0x78,0x21,0x6c,0x36,0x6d,0x3c,0x6e,0x76,0x6f,0x13,0x74,0x68,0x65,0x72, +0x21,1,0x65,0x23,0x66,0x35,3,0x62,0x37,0x69,0x28,0x6c,0x29,0x6e,0x2b,0x10, +0x64,1,0x6c,0x34,0x6e,0x11,0x75,0x6d,0x2a,0x12,0x6c,0x65,0x74,0x37,0x14,0x65, +0x74,0x74,0x65,0x72,0x29,2,0x65,0x36,0x6c,0x39,0x75,0x2c,0x14,0x6d,0x65,0x72, +0x69,0x63,0x2d,0x14,0x77,0x6c,0x69,0x6e,0x65,0x39,0x66,0x3f,0x66,0x40,0x67,0x4e, +0x68,0x70,0x6b,0x10,0x61,0x26,0x15,0x74,0x61,0x6b,0x61,0x6e,0x61,0x27,0x10,0x6f, +0x24,0x13,0x72,0x6d,0x61,0x74,0x25,1,0x61,0x3a,0x6c,0x19,0x75,0x65,0x61,0x66, +0x74,0x65,0x72,0x7a,0x77,0x6a,0x49,0x10,0x7a,0x49,1,0x65,0x24,0x6c,0x3d,0x19, +0x62,0x72,0x65,0x77,0x6c,0x65,0x74,0x74,0x65,0x72,0x3d,0x61,0x86,0x63,0x92,0x64, +0x94,0x65,2,0x62,0x44,0x6d,0x5e,0x78,0x2e,0x13,0x74,0x65,0x6e,0x64,0x32,0x15, +0x6e,0x75,0x6d,0x6c,0x65,0x74,0x2f,0x42,1,0x61,0x24,0x67,0x45,0x11,0x73,0x65, +0x42,0x12,0x67,0x61,0x7a,0x45,0x46,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x47, +0x15,0x6c,0x65,0x74,0x74,0x65,0x72,0x23,0x10,0x72,0x31,1,0x6f,0x24,0x71,0x41, +0x18,0x75,0x62,0x6c,0x65,0x71,0x75,0x6f,0x74,0x65,0x41,2,0x63,0x32,0x6e,0x3c, +0x6f,0x22,0x12,0x70,0x65,0x6e,0x23,0x24,0x13,0x6c,0x6f,0x73,0x65,0x25,0x20,0x12, +0x6f,0x6e,0x65,0x21,6,0x6f,0x65,0x6f,0x4a,0x72,0x5c,0x74,0x64,0x76,0x1d,0x69, +0x73,0x75,0x61,0x6c,0x6f,0x72,0x64,0x65,0x72,0x6c,0x65,0x66,0x74,0x3d,0x18,0x76, +0x65,0x72,0x73,0x74,0x72,0x75,0x63,0x6b,0x2d,0x13,0x69,0x67,0x68,0x74,0x2f,0x11, +0x6f,0x70,0x30,0x12,0x61,0x6e,0x64,2,0x62,0x32,0x6c,0x62,0x72,0x13,0x69,0x67, +0x68,0x74,0x3b,0x14,0x6f,0x74,0x74,0x6f,0x6d,0x32,0x12,0x61,0x6e,0x64,1,0x6c, +0x2e,0x72,0x13,0x69,0x67,0x68,0x74,0x35,0x12,0x65,0x66,0x74,0x3f,0x12,0x65,0x66, +0x74,0x36,0x17,0x61,0x6e,0x64,0x72,0x69,0x67,0x68,0x74,0x39,0x62,0x2c,0x6c,0x5c, +0x6e,0x10,0x61,0x21,0x14,0x6f,0x74,0x74,0x6f,0x6d,0x22,0x12,0x61,0x6e,0x64,1, +0x6c,0x2e,0x72,0x13,0x69,0x67,0x68,0x74,0x27,0x12,0x65,0x66,0x74,0x25,0x12,0x65, +0x66,0x74,0x28,0x17,0x61,0x6e,0x64,0x72,0x69,0x67,0x68,0x74,0x2b,0xd,0x6e,0xaa, +0x72,0x70,0x72,0x92,0x73,0xa2,0x46,0x74,0xa2,0x54,0x76,1,0x69,0x60,0x6f,0x12, +0x77,0x65,0x6c,0x62,1,0x64,0x3a,0x69,0x19,0x6e,0x64,0x65,0x70,0x65,0x6e,0x64, +0x65,0x6e,0x74,0x67,0x17,0x65,0x70,0x65,0x6e,0x64,0x65,0x6e,0x74,0x65,1,0x72, +0x2e,0x73,0x13,0x61,0x72,0x67,0x61,0x61,0x12,0x61,0x6d,0x61,0x5f,0x1d,0x65,0x67, +0x69,0x73,0x74,0x65,0x72,0x73,0x68,0x69,0x66,0x74,0x65,0x72,0x57,0x1e,0x79,0x6c, +0x6c,0x61,0x62,0x6c,0x65,0x6d,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x59,0x12,0x6f, +0x6e,0x65,1,0x6c,0x2c,0x6d,0x12,0x61,0x72,0x6b,0x5d,0x14,0x65,0x74,0x74,0x65, +0x72,0x5b,0x6e,0x3c,0x6f,0x7c,0x70,0x18,0x75,0x72,0x65,0x6b,0x69,0x6c,0x6c,0x65, +0x72,0x55,1,0x6f,0x4c,0x75,1,0x6b,0x3c,0x6d,0x12,0x62,0x65,0x72,0x50,0x15, +0x6a,0x6f,0x69,0x6e,0x65,0x72,0x53,0x11,0x74,0x61,0x4f,0x16,0x6e,0x6a,0x6f,0x69, +0x6e,0x65,0x72,0x4d,0x13,0x74,0x68,0x65,0x72,0x21,0x67,0x3e,0x67,0x4a,0x69,0x64, +0x6a,0x82,0x6d,0x1d,0x6f,0x64,0x69,0x66,0x79,0x69,0x6e,0x67,0x6c,0x65,0x74,0x74, +0x65,0x72,0x4b,0x1c,0x65,0x6d,0x69,0x6e,0x61,0x74,0x69,0x6f,0x6e,0x6d,0x61,0x72, +0x6b,0x45,0x1e,0x6e,0x76,0x69,0x73,0x69,0x62,0x6c,0x65,0x73,0x74,0x61,0x63,0x6b, +0x65,0x72,0x47,0x14,0x6f,0x69,0x6e,0x65,0x72,0x49,0x61,0xa2,0xba,0x62,0xa2,0xc0, +0x63,1,0x61,0xa2,0xa2,0x6f,0x16,0x6e,0x73,0x6f,0x6e,0x61,0x6e,0x74,0x2a,8, +0x6b,0x67,0x6b,0x48,0x6d,0x52,0x70,0x5c,0x73,0xa2,0x42,0x77,0x19,0x69,0x74,0x68, +0x73,0x74,0x61,0x63,0x6b,0x65,0x72,0x43,0x14,0x69,0x6c,0x6c,0x65,0x72,0x35,0x14, +0x65,0x64,0x69,0x61,0x6c,0x37,1,0x6c,0x52,0x72,0x10,0x65,1,0x63,0x2e,0x66, +0x13,0x69,0x78,0x65,0x64,0x3d,0x19,0x65,0x64,0x69,0x6e,0x67,0x72,0x65,0x70,0x68, +0x61,0x3b,0x18,0x61,0x63,0x65,0x68,0x6f,0x6c,0x64,0x65,0x72,0x39,0x10,0x75,1, +0x62,0x3e,0x63,0x1b,0x63,0x65,0x65,0x64,0x69,0x6e,0x67,0x72,0x65,0x70,0x68,0x61, +0x41,0x15,0x6a,0x6f,0x69,0x6e,0x65,0x64,0x3f,0x64,0x4c,0x66,0x52,0x68,0x5a,0x69, +0x1e,0x6e,0x69,0x74,0x69,0x61,0x6c,0x70,0x6f,0x73,0x74,0x66,0x69,0x78,0x65,0x64, +0x33,0x12,0x65,0x61,0x64,0x2d,0x13,0x69,0x6e,0x61,0x6c,0x2f,0x18,0x65,0x61,0x64, +0x6c,0x65,0x74,0x74,0x65,0x72,0x31,0x1d,0x6e,0x74,0x69,0x6c,0x6c,0x61,0x74,0x69, +0x6f,0x6e,0x6d,0x61,0x72,0x6b,0x29,0x16,0x76,0x61,0x67,0x72,0x61,0x68,0x61,0x23, +1,0x69,0x4a,0x72,0x10,0x61,0x1f,0x68,0x6d,0x69,0x6a,0x6f,0x69,0x6e,0x69,0x6e, +0x67,0x6e,0x75,0x6d,0x62,0x65,0x72,0x27,0x12,0x6e,0x64,0x75,0x25,2,0x72,0x38, +0x74,0x46,0x75,0x26,0x15,0x70,0x72,0x69,0x67,0x68,0x74,0x27,0x20,0x15,0x6f,0x74, +0x61,0x74,0x65,0x64,0x21,1,0x72,0x24,0x75,0x25,0x22,0x18,0x61,0x6e,0x73,0x66, +0x6f,0x72,0x6d,0x65,0x64,1,0x72,0x32,0x75,0x15,0x70,0x72,0x69,0x67,0x68,0x74, +0x25,0x15,0x6f,0x74,0x61,0x74,0x65,0x64,0x23,0xd,0x6e,0xc1,0x86,0x73,0xa8,0x73, +0x4c,0x74,0xa2,0x76,0x75,0xa2,0x83,0x7a,0xd8,0x70,0,2,0x6c,0xd9,0x20,0, +0x70,0xd9,0x40,0,0x73,0xc3,0,0xfe,0xf,0,0,0,7,0x6f,0x3c,0x6f, +0xff,8,0,0,0,0x70,0x3a,0x75,0x6e,0x79,0x13,0x6d,0x62,0x6f,0x6c,0xff, +0xf,0,0,0,0x11,0x61,0x63,1,0x65,0x34,0x69,0x15,0x6e,0x67,0x6d,0x61, +0x72,0x6b,0xa5,0,0x18,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xc3,0, +0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0xe1,0,0,0x63,0xff,2,0,0, +0,0x65,0x38,0x6b,0xff,4,0,0,0,0x6d,0xff,1,0,0,0,0x16, +0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x70,0,0x1d,0x69,0x74,0x6c,0x65,0x63, +0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x31,1,0x6e,0x40,0x70,0x1c,0x70, +0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x25,0x17,0x61,0x73, +0x73,0x69,0x67,0x6e,0x65,0x64,0x23,0x6e,0xa2,0x69,0x6f,0xa2,0x89,0x70,0xfe,0x30, +0xf8,0,0,9,0x69,0x33,0x69,0xff,0x10,0,0,0,0x6f,0xfd,0x80,0, +0,0x72,0x54,0x73,0xf9,0,0,0x75,0x12,0x6e,0x63,0x74,0xfe,0x30,0xf8,0, +0,0x15,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff,0x30,0xf8,0,0,0x17,0x69,0x76, +0x61,0x74,0x65,0x75,0x73,0x65,0xdd,0,0,0x61,0x48,0x63,0xfd,0x40,0,0, +0x64,0xe9,0,0,0x65,0xfd,0x20,0,0,0x66,0xff,0x20,0,0,0,0x1f, +0x72,0x61,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72, +0xd9,0x40,0,0xbe,0,3,0x64,0xa7,0,0x6c,0xab,0,0x6f,0x30,0x75,0x13, +0x6d,0x62,0x65,0x72,0xbf,0,0xb2,0,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69,0x6e, +0x67,0x6d,0x61,0x72,0x6b,0xa1,1,0x70,0x92,0x74,0x12,0x68,0x65,0x72,0xe6,0x80, +1,3,0x6c,0x40,0x6e,0x4a,0x70,0x56,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0xff, +8,0,0,0,0x14,0x65,0x74,0x74,0x65,0x72,0x61,0x14,0x75,0x6d,0x62,0x65, +0x72,0xb3,0,0x19,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xfd,0x80, +0,0,0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e, +0xf9,0,0,0x66,0xc0,0xc4,0x66,0xa2,0x47,0x69,0xa2,0x64,0x6c,0xa2,0x79,0x6d, +0xa4,0xc0,4,0x61,0x6c,0x63,0xa5,0,0x65,0xa3,0x80,0x6e,0xa1,0x6f,0x15,0x64, +0x69,0x66,0x69,0x65,0x72,1,0x6c,0x38,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0xff, +4,0,0,0,0x14,0x65,0x74,0x74,0x65,0x72,0x41,1,0x72,0x3c,0x74,0x16, +0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c,0xff,1,0,0,0,0x10,0x6b,0xa5,0xc0, +1,0x69,0x32,0x6f,0x13,0x72,0x6d,0x61,0x74,0xdb,0,0,0x1d,0x6e,0x61,0x6c, +0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff,0x20,0,0,0, +0x10,0x6e,0x1f,0x69,0x74,0x69,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74, +0x69,0x6f,0x6e,0xff,0x10,0,0,0,0x9c,7,0x6d,0x18,0x6d,0x41,0x6f,0x28, +0x74,0x31,0x75,0x25,0x60,0x1c,0x77,0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74, +0x74,0x65,0x72,0x29,0x63,0x3d,0x65,0x28,0x69,0x42,0x6c,0x29,0x13,0x74,0x74,0x65, +0x72,0x9c,0x15,0x6e,0x75,0x6d,0x62,0x65,0x72,0xab,0,0x1a,0x6e,0x65,0x73,0x65, +0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x20,0,0x63,0x46,0x64,0xa2,0x96,0x65, +0x1b,0x6e,0x63,0x6c,0x6f,0x73,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa3,0x80,0xe6, +0x80,1,7,0x6e,0x57,0x6e,0x52,0x6f,0x5e,0x73,0xe1,0,0,0x75,0x1b,0x72, +0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62,0x6f,0x6c,0xff,2,0,0,0, +0x22,0x12,0x74,0x72,0x6c,0xd9,0x80,0,0xdc,0,0,1,0x6d,0x62,0x6e,1, +0x6e,0x30,0x74,0x12,0x72,0x6f,0x6c,0xd9,0x80,0,0x1f,0x65,0x63,0x74,0x6f,0x72, +0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xfd,0x40,0,0,0x19, +0x62,0x69,0x6e,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa5,0xc0,0x61,0x58,0x63,0xd9, +0x80,0,0x66,0xdb,0,0,0x6c,0x1d,0x6f,0x73,0x65,0x70,0x75,0x6e,0x63,0x74, +0x75,0x61,0x74,0x69,0x6f,0x6e,0xfd,0x20,0,0,0x18,0x73,0x65,0x64,0x6c,0x65, +0x74,0x74,0x65,0x72,0x3d,2,0x61,0x32,0x65,0x50,0x69,0x12,0x67,0x69,0x74,0xa7, +0,0x1c,0x73,0x68,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xe9, +0,0,0x1a,0x63,0x69,0x6d,0x61,0x6c,0x6e,0x75,0x6d,0x62,0x65,0x72,0xa7,0 }; -const char PropNameData::nameGroups[21692]={ +const char PropNameData::nameGroups[22098]={ 2,'A','l','p','h','a',0,'A','l','p','h','a','b','e','t','i','c',0, 4,'N',0,'N','o',0,'F',0,'F','a','l','s','e',0,4,'Y',0,'Y','e','s',0,'T',0,'T','r','u','e',0, 2,'N','R',0,'N','o','t','_','R','e','o','r','d','e','r','e','d',0, -2,'O','V',0,'O','v','e','r','l','a','y',0,2,'N','K',0,'N','u','k','t','a',0, -2,'K','V',0,'K','a','n','a','_','V','o','i','c','i','n','g',0, +2,'O','V',0,'O','v','e','r','l','a','y',0,2,'H','A','N','R',0,'H','a','n','_','R','e','a','d','i','n','g',0, +2,'N','K',0,'N','u','k','t','a',0,2,'K','V',0,'K','a','n','a','_','V','o','i','c','i','n','g',0, 2,'V','R',0,'V','i','r','a','m','a',0,2,'C','C','C','1','0',0,'C','C','C','1','0',0, 2,'C','C','C','1','1',0,'C','C','C','1','1',0,2,'C','C','C','1','2',0,'C','C','C','1','2',0, 2,'C','C','C','1','3',0,'C','C','C','1','3',0,2,'C','C','C','1','4',0,'C','C','C','1','4',0, @@ -1486,7 +1500,16 @@ const char PropNameData::nameGroups[21692]={ 2,'S','y','m','b','o','l','s','_','A','n','d','_','P','i','c','t','o','g','r','a','p','h','s','_','E','x','t','_','A',0, 'S','y','m','b','o','l','s','_','A','n','d','_','P','i','c','t','o','g','r','a','p','h','s','_','E','x','t','e','n','d','e','d', '_','A',0,2,'T','a','m','i','l','_','S','u','p',0,'T','a','m','i','l','_','S','u','p','p','l','e','m','e','n','t',0, -2,'W','a','n','c','h','o',0,'W','a','n','c','h','o',0,2,'c','c','c',0,'C','a','n','o','n','i','c','a','l','_','C','o', +2,'W','a','n','c','h','o',0,'W','a','n','c','h','o',0,2,'C','h','o','r','a','s','m','i','a','n',0, +'C','h','o','r','a','s','m','i','a','n',0,2,'C','J','K','_','E','x','t','_','G',0,'C','J','K','_','U','n','i','f','i','e', +'d','_','I','d','e','o','g','r','a','p','h','s','_','E','x','t','e','n','s','i','o','n','_','G',0, +2,'D','i','v','e','s','_','A','k','u','r','u',0,'D','i','v','e','s','_','A','k','u','r','u',0, +2,'K','h','i','t','a','n','_','S','m','a','l','l','_','S','c','r','i','p','t',0,'K','h','i','t','a','n','_','S','m','a','l', +'l','_','S','c','r','i','p','t',0,2,'L','i','s','u','_','S','u','p',0,'L','i','s','u','_','S','u','p','p','l','e','m','e', +'n','t',0,2,'S','y','m','b','o','l','s','_','F','o','r','_','L','e','g','a','c','y','_','C','o','m','p','u','t','i','n','g', +0,'S','y','m','b','o','l','s','_','F','o','r','_','L','e','g','a','c','y','_','C','o','m','p','u','t','i','n','g',0, +2,'T','a','n','g','u','t','_','S','u','p',0,'T','a','n','g','u','t','_','S','u','p','p','l','e','m','e','n','t',0, +2,'Y','e','z','i','d','i',0,'Y','e','z','i','d','i',0,2,'c','c','c',0,'C','a','n','o','n','i','c','a','l','_','C','o', 'm','b','i','n','i','n','g','_','C','l','a','s','s',0,2,'d','t',0,'D','e','c','o','m','p','o','s','i','t','i','o','n','_', 'T','y','p','e',0,3,'N','o','n','e',0,'N','o','n','e',0,'n','o','n','e',0, 3,'C','a','n',0,'C','a','n','o','n','i','c','a','l',0,'c','a','n',0, @@ -1769,7 +1792,10 @@ const char PropNameData::nameGroups[21692]={ 2,'S','o','g','d',0,'S','o','g','d','i','a','n',0,2,'S','o','g','o',0,'O','l','d','_','S','o','g','d','i','a','n',0, 2,'E','l','y','m',0,'E','l','y','m','a','i','c',0,2,'H','m','n','p',0,'N','y','i','a','k','e','n','g','_','P','u','a', 'c','h','u','e','_','H','m','o','n','g',0,2,'N','a','n','d',0,'N','a','n','d','i','n','a','g','a','r','i',0, -2,'W','c','h','o',0,'W','a','n','c','h','o',0,2,'h','s','t',0,'H','a','n','g','u','l','_','S','y','l','l','a','b','l', +2,'W','c','h','o',0,'W','a','n','c','h','o',0,2,'C','h','r','s',0,'C','h','o','r','a','s','m','i','a','n',0, +2,'D','i','a','k',0,'D','i','v','e','s','_','A','k','u','r','u',0, +2,'K','i','t','s',0,'K','h','i','t','a','n','_','S','m','a','l','l','_','S','c','r','i','p','t',0, +2,'Y','e','z','i',0,'Y','e','z','i','d','i',0,2,'h','s','t',0,'H','a','n','g','u','l','_','S','y','l','l','a','b','l', 'e','_','T','y','p','e',0,2,'N','A',0,'N','o','t','_','A','p','p','l','i','c','a','b','l','e',0, 2,'L',0,'L','e','a','d','i','n','g','_','J','a','m','o',0, 2,'V',0,'V','o','w','e','l','_','J','a','m','o',0,2,'T',0,'T','r','a','i','l','i','n','g','_','J','a','m','o',0, @@ -1820,9 +1846,10 @@ const char PropNameData::nameGroups[21692]={ 'T','o','p','_','A','n','d','_','L','e','f','t','_','A','n','d','_','R','i','g','h','t',0, 2,'T','o','p','_','A','n','d','_','R','i','g','h','t',0,'T','o','p','_','A','n','d','_','R','i','g','h','t',0, 2,'V','i','s','u','a','l','_','O','r','d','e','r','_','L','e','f','t',0,'V','i','s','u','a','l','_','O','r','d','e','r','_', -'L','e','f','t',0,2,'I','n','S','C',0,'I','n','d','i','c','_','S','y','l','l','a','b','i','c','_','C','a','t','e','g','o', -'r','y',0,2,'O','t','h','e','r',0,'O','t','h','e','r',0, -2,'A','v','a','g','r','a','h','a',0,'A','v','a','g','r','a','h','a',0, +'L','e','f','t',0,2,'T','o','p','_','A','n','d','_','B','o','t','t','o','m','_','A','n','d','_','L','e','f','t',0, +'T','o','p','_','A','n','d','_','B','o','t','t','o','m','_','A','n','d','_','L','e','f','t',0, +2,'I','n','S','C',0,'I','n','d','i','c','_','S','y','l','l','a','b','i','c','_','C','a','t','e','g','o','r','y',0, +2,'O','t','h','e','r',0,'O','t','h','e','r',0,2,'A','v','a','g','r','a','h','a',0,'A','v','a','g','r','a','h','a',0, 2,'B','i','n','d','u',0,'B','i','n','d','u',0,2,'B','r','a','h','m','i','_','J','o','i','n','i','n','g','_','N','u','m', 'b','e','r',0,'B','r','a','h','m','i','_','J','o','i','n','i','n','g','_','N','u','m','b','e','r',0, 2,'C','a','n','t','i','l','l','a','t','i','o','n','_','M','a','r','k',0,'C','a','n','t','i','l','l','a','t','i','o','n','_', diff --git a/deps/icu-small/source/common/putil.cpp b/deps/icu-small/source/common/putil.cpp index 207350f8f26120..51c2473c982d5d 100644 --- a/deps/icu-small/source/common/putil.cpp +++ b/deps/icu-small/source/common/putil.cpp @@ -1459,6 +1459,11 @@ static void U_CALLCONV TimeZoneDataDirInitFn(UErrorCode &status) { const char *dir = ""; +#if defined(ICU_TIMEZONE_FILES_DIR_PREFIX_ENV_VAR) + char timezonefilesdir_path_buffer[PATH_MAX]; + const char *prefix = getenv(ICU_TIMEZONE_FILES_DIR_PREFIX_ENV_VAR); +#endif + #if U_PLATFORM_HAS_WINUWP_API == 1 // The UWP version does not support the environment variable setting. @@ -1485,6 +1490,13 @@ static void U_CALLCONV TimeZoneDataDirInitFn(UErrorCode &status) { dir = ""; } +#if defined(ICU_TIMEZONE_FILES_DIR_PREFIX_ENV_VAR) + if (prefix != NULL) { + snprintf(timezonefilesdir_path_buffer, PATH_MAX, "%s%s", prefix, dir); + dir = timezonefilesdir_path_buffer; + } +#endif + setTimeZoneFilesDir(dir, status); } diff --git a/deps/icu-small/source/common/rbbi.cpp b/deps/icu-small/source/common/rbbi.cpp index 01dae48de44c1d..43ba58ba9e6577 100644 --- a/deps/icu-small/source/common/rbbi.cpp +++ b/deps/icu-small/source/common/rbbi.cpp @@ -883,9 +883,15 @@ int32_t RuleBasedBreakIterator::handleNext() { return lookaheadResult; } } + + // If we are at the position of the '/' in a look-ahead (hard break) rule; + // record the current position, to be returned later, if the full rule matches. + // TODO: Move this check before the previous check of fAccepting. + // This would enable hard-break rules with no following context. + // But there are line break test failures when trying this. Investigate. + // Issue ICU-20837 int16_t rule = row->fLookAhead; if (rule != 0) { - // At the position of a '/' in a look-ahead match. Record it. int32_t pos = (int32_t)UTEXT_GETNATIVEINDEX(&fText); lookAheadMatches.setPosition(rule, pos); } @@ -1111,7 +1117,7 @@ static icu::UInitOnce gRBBIInitOnce = U_INITONCE_INITIALIZER; * Release all static memory held by breakiterator. */ U_CDECL_BEGIN -static UBool U_CALLCONV rbbi_cleanup(void) { +UBool U_CALLCONV rbbi_cleanup(void) { delete gLanguageBreakFactories; gLanguageBreakFactories = nullptr; delete gEmptyString; diff --git a/deps/icu-small/source/common/rbbidata.h b/deps/icu-small/source/common/rbbidata.h index 3e573039d0f491..96e4649533f068 100644 --- a/deps/icu-small/source/common/rbbidata.h +++ b/deps/icu-small/source/common/rbbidata.h @@ -192,6 +192,8 @@ class RBBIDataWrapper : public UMemory { U_NAMESPACE_END +U_CFUNC UBool rbbi_cleanup(void); + #endif /* C++ */ #endif diff --git a/deps/icu-small/source/common/rbbirb.cpp b/deps/icu-small/source/common/rbbirb.cpp index 5f5661af94776d..4df96532643d06 100644 --- a/deps/icu-small/source/common/rbbirb.cpp +++ b/deps/icu-small/source/common/rbbirb.cpp @@ -161,6 +161,19 @@ RBBIDataHeader *RBBIRuleBuilder::flattenData() { + reverseTableSize + statusTableSize + trieSize + rulesSize; +#ifdef RBBI_DEBUG + if (fDebugEnv && uprv_strstr(fDebugEnv, "size")) { + RBBIDebugPrintf("Header Size: %8d\n", headerSize); + RBBIDebugPrintf("Forward Table Size: %8d\n", forwardTableSize); + RBBIDebugPrintf("Reverse Table Size: %8d\n", reverseTableSize); + RBBIDebugPrintf("Trie Size: %8d\n", trieSize); + RBBIDebugPrintf("Status Table Size: %8d\n", statusTableSize); + RBBIDebugPrintf("Rules Size: %8d\n", rulesSize); + RBBIDebugPrintf("-----------------------------\n"); + RBBIDebugPrintf("Total Size: %8d\n", totalSize); + } +#endif + RBBIDataHeader *data = (RBBIDataHeader *)uprv_malloc(totalSize); if (data == NULL) { *fStatus = U_MEMORY_ALLOCATION_ERROR; diff --git a/deps/icu-small/source/common/rbbiscan.cpp b/deps/icu-small/source/common/rbbiscan.cpp index 170c212e13fd1f..da8246ba6f1e47 100644 --- a/deps/icu-small/source/common/rbbiscan.cpp +++ b/deps/icu-small/source/common/rbbiscan.cpp @@ -1274,6 +1274,10 @@ void RBBIRuleScanner::scanSet() { } +int32_t RBBIRuleScanner::numRules() { + return fRuleNum; +} + U_NAMESPACE_END #endif /* #if !UCONFIG_NO_BREAK_ITERATION */ diff --git a/deps/icu-small/source/common/rbbiscan.h b/deps/icu-small/source/common/rbbiscan.h index cac60fb18a11b8..559617e78b439f 100644 --- a/deps/icu-small/source/common/rbbiscan.h +++ b/deps/icu-small/source/common/rbbiscan.h @@ -73,6 +73,8 @@ class RBBIRuleScanner : public UMemory { // reverse rules, // and a list of UnicodeSets encountered. + int32_t numRules(); // Return the number of rules that have been seen. + /** * Return a rules string without unnecessary * characters. diff --git a/deps/icu-small/source/common/rbbitblb.cpp b/deps/icu-small/source/common/rbbitblb.cpp index e6ae2dc654a88c..3b1edc6a15c700 100644 --- a/deps/icu-small/source/common/rbbitblb.cpp +++ b/deps/icu-small/source/common/rbbitblb.cpp @@ -18,6 +18,7 @@ #include "unicode/unistr.h" #include "rbbitblb.h" #include "rbbirb.h" +#include "rbbiscan.h" #include "rbbisetb.h" #include "rbbidata.h" #include "cstring.h" @@ -52,6 +53,7 @@ RBBITableBuilder::~RBBITableBuilder() { } delete fDStates; delete fSafeTable; + delete fLookAheadRuleMap; } @@ -121,7 +123,7 @@ void RBBITableBuilder::buildForwardTable() { } cn->fLeftChild = fTree; fTree->fParent = cn; - cn->fRightChild = new RBBINode(RBBINode::endMark); + RBBINode *endMarkerNode = cn->fRightChild = new RBBINode(RBBINode::endMark); // Delete and exit if memory allocation failed. if (cn->fRightChild == NULL) { *fStatus = U_MEMORY_ALLOCATION_ERROR; @@ -164,7 +166,7 @@ void RBBITableBuilder::buildForwardTable() { // For "chained" rules, modify the followPos sets // if (fRB->fChainRules) { - calcChainedFollowPos(fTree); + calcChainedFollowPos(fTree, endMarkerNode); } // @@ -178,6 +180,7 @@ void RBBITableBuilder::buildForwardTable() { // Build the DFA state transition tables. // buildStateTable(); + mapLookAheadRules(); flagAcceptingStates(); flagLookAheadStates(); flagTaggedStates(); @@ -401,19 +404,13 @@ void RBBITableBuilder::addRuleRootNodes(UVector *dest, RBBINode *node) { // to implement rule chaining. NOT described by Aho // //----------------------------------------------------------------------------- -void RBBITableBuilder::calcChainedFollowPos(RBBINode *tree) { +void RBBITableBuilder::calcChainedFollowPos(RBBINode *tree, RBBINode *endMarkNode) { - UVector endMarkerNodes(*fStatus); UVector leafNodes(*fStatus); - int32_t i; - if (U_FAILURE(*fStatus)) { return; } - // get a list of all endmarker nodes. - tree->findNodes(&endMarkerNodes, RBBINode::endMark, *fStatus); - // get a list all leaf nodes tree->findNodes(&leafNodes, RBBINode::leafChar, *fStatus); if (U_FAILURE(*fStatus)) { @@ -442,28 +439,26 @@ void RBBITableBuilder::calcChainedFollowPos(RBBINode *tree) { int32_t startNodeIx; for (endNodeIx=0; endNodeIxfFollowPos->contains(endMarkerNodes.elementAt(i))) { - endNode = tNode; - break; - } - } - if (endNode == NULL) { - // node wasn't an end node. Try again with the next. + // These include the endMarkNode in their followPos sets. + // + // Note: do not consider other end marker nodes, those that are added to + // look-ahead rules. These can't chain; a match immediately stops + // further matching. This leaves exactly one end marker node, the one + // at the end of the complete tree. + + if (!endNode->fFollowPos->contains(endMarkNode)) { continue; } // We've got a node that can end a match. - // Line Break Specific hack: If this node's val correspond to the $CM char class, - // don't chain from it. - // TODO: Add rule syntax for this behavior, get specifics out of here and - // into the rule file. + // !!LBCMNoChain implementation: If this node's val correspond to + // the Line Break $CM char class, don't chain from it. + // TODO: Remove this. !!LBCMNoChain is deprecated, and is not used + // by any of the standard ICU rules. if (fRB->fLBCMNoChain) { UChar32 c = this->fRB->fSetBuilder->getFirstChar(endNode->fVal); if (c != -1) { @@ -475,7 +470,6 @@ void RBBITableBuilder::calcChainedFollowPos(RBBINode *tree) { } } - // Now iterate over the nodes that can start a match, looking for ones // with the same char class as our ending node. RBBINode *startNode; @@ -705,6 +699,77 @@ void RBBITableBuilder::buildStateTable() { } +/** + * mapLookAheadRules + * + */ +void RBBITableBuilder::mapLookAheadRules() { + fLookAheadRuleMap = new UVector32(fRB->fScanner->numRules() + 1, *fStatus); + if (fLookAheadRuleMap == nullptr) { + *fStatus = U_MEMORY_ALLOCATION_ERROR; + } + if (U_FAILURE(*fStatus)) { + return; + } + fLookAheadRuleMap->setSize(fRB->fScanner->numRules() + 1); + int32_t laSlotsInUse = 0; + + for (int32_t n=0; nsize(); n++) { + RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(n); + int32_t laSlotForState = 0; + + // Establish the look-ahead slot for this state, if the state covers + // any look-ahead nodes - corresponding to the '/' in look-ahead rules. + + // If any of the look-ahead nodes already have a slot assigned, use it, + // otherwise assign a new one. + + bool sawLookAheadNode = false; + for (int32_t ipos=0; iposfPositions->size(); ++ipos) { + RBBINode *node = static_cast(sd->fPositions->elementAt(ipos)); + if (node->fType != RBBINode::NodeType::lookAhead) { + continue; + } + sawLookAheadNode = true; + int32_t ruleNum = node->fVal; // Set when rule was originally parsed. + U_ASSERT(ruleNum < fLookAheadRuleMap->size()); + U_ASSERT(ruleNum > 0); + int32_t laSlot = fLookAheadRuleMap->elementAti(ruleNum); + if (laSlot != 0) { + if (laSlotForState == 0) { + laSlotForState = laSlot; + } else { + // TODO: figure out if this can fail, change to setting an error code if so. + U_ASSERT(laSlot == laSlotForState); + } + } + } + if (!sawLookAheadNode) { + continue; + } + + if (laSlotForState == 0) { + laSlotForState = ++laSlotsInUse; + } + + // For each look ahead node covered by this state, + // set the mapping from the node's rule number to the look ahead slot. + // There can be multiple nodes/rule numbers going to the same la slot. + + for (int32_t ipos=0; iposfPositions->size(); ++ipos) { + RBBINode *node = static_cast(sd->fPositions->elementAt(ipos)); + if (node->fType != RBBINode::NodeType::lookAhead) { + continue; + } + int32_t ruleNum = node->fVal; // Set when rule was originally parsed. + int32_t existingVal = fLookAheadRuleMap->elementAti(ruleNum); + (void)existingVal; + U_ASSERT(existingVal == 0 || existingVal == laSlotForState); + fLookAheadRuleMap->setElementAt(laSlotForState, ruleNum); + } + } + +} //----------------------------------------------------------------------------- // @@ -744,28 +809,19 @@ void RBBITableBuilder::flagAcceptingStates() { if (sd->fAccepting==0) { // State hasn't been marked as accepting yet. Do it now. - sd->fAccepting = endMarker->fVal; + sd->fAccepting = fLookAheadRuleMap->elementAti(endMarker->fVal); if (sd->fAccepting == 0) { sd->fAccepting = -1; } } if (sd->fAccepting==-1 && endMarker->fVal != 0) { // Both lookahead and non-lookahead accepting for this state. - // Favor the look-ahead. Expedient for line break. - // TODO: need a more elegant resolution for conflicting rules. - sd->fAccepting = endMarker->fVal; + // Favor the look-ahead, because a look-ahead match needs to + // immediately stop the run-time engine. First match, not longest. + sd->fAccepting = fLookAheadRuleMap->elementAti(endMarker->fVal); } // implicit else: // if sd->fAccepting already had a value other than 0 or -1, leave it be. - - // If the end marker node is from a look-ahead rule, set - // the fLookAhead field for this state also. - if (endMarker->fLookAheadEnd) { - // TODO: don't change value if already set? - // TODO: allow for more than one active look-ahead rule in engine. - // Make value here an index to a side array in engine? - sd->fLookAhead = sd->fAccepting; - } } } } @@ -792,11 +848,20 @@ void RBBITableBuilder::flagLookAheadStates() { } for (i=0; ifType == RBBINode::NodeType::lookAhead); for (n=0; nsize(); n++) { RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(n); - if (sd->fPositions->indexOf(lookAheadNode) >= 0) { - sd->fLookAhead = lookAheadNode->fVal; + int32_t positionsIdx = sd->fPositions->indexOf(lookAheadNode); + if (positionsIdx >= 0) { + U_ASSERT(lookAheadNode == sd->fPositions->elementAt(positionsIdx)); + int32_t lookaheadSlot = fLookAheadRuleMap->elementAti(lookAheadNode->fVal); + U_ASSERT(sd->fLookAhead == 0 || sd->fLookAhead == lookaheadSlot); + // if (sd->fLookAhead != 0 && sd->fLookAhead != lookaheadSlot) { + // printf("%s:%d Bingo. sd->fLookAhead:%d lookaheadSlot:%d\n", + // __FILE__, __LINE__, sd->fLookAhead, lookaheadSlot); + // } + sd->fLookAhead = lookaheadSlot; } } } @@ -1204,16 +1269,6 @@ void RBBITableBuilder::removeState(IntPair duplStates) { } sd->fDtran->setElementAt(newVal, col); } - if (sd->fAccepting == duplState) { - sd->fAccepting = keepState; - } else if (sd->fAccepting > duplState) { - sd->fAccepting--; - } - if (sd->fLookAhead == duplState) { - sd->fLookAhead = keepState; - } else if (sd->fLookAhead > duplState) { - sd->fLookAhead--; - } } } diff --git a/deps/icu-small/source/common/rbbitblb.h b/deps/icu-small/source/common/rbbitblb.h index bc6077bb4da3dc..c2b574fe1b8f93 100644 --- a/deps/icu-small/source/common/rbbitblb.h +++ b/deps/icu-small/source/common/rbbitblb.h @@ -91,9 +91,10 @@ class RBBITableBuilder : public UMemory { void calcFirstPos(RBBINode *n); void calcLastPos(RBBINode *n); void calcFollowPos(RBBINode *n); - void calcChainedFollowPos(RBBINode *n); + void calcChainedFollowPos(RBBINode *n, RBBINode *endMarkNode); void bofFixup(); void buildStateTable(); + void mapLookAheadRules(); void flagAcceptingStates(); void flagLookAheadStates(); void flagTaggedStates(); @@ -175,6 +176,9 @@ class RBBITableBuilder : public UMemory { /** Synthesized safe table, UVector of UnicodeString, one string per table row. */ UVector *fSafeTable; + /** Map from rule number (fVal in look ahead nodes) to sequential lookahead index. */ + UVector32 *fLookAheadRuleMap = nullptr; + RBBITableBuilder(const RBBITableBuilder &other); // forbid copying of this class RBBITableBuilder &operator=(const RBBITableBuilder &other); // forbid copying of this class diff --git a/deps/icu-small/source/common/stringpiece.cpp b/deps/icu-small/source/common/stringpiece.cpp index d4f7f310bafc7d..99089e08ef90f1 100644 --- a/deps/icu-small/source/common/stringpiece.cpp +++ b/deps/icu-small/source/common/stringpiece.cpp @@ -51,6 +51,47 @@ void StringPiece::set(const char* str) { length_ = 0; } +int32_t StringPiece::find(StringPiece needle, int32_t offset) { + if (length() == 0 && needle.length() == 0) { + return 0; + } + // TODO: Improve to be better than O(N^2)? + for (int32_t i = offset; i < length(); i++) { + int32_t j = 0; + for (; j < needle.length(); i++, j++) { + if (data()[i] != needle.data()[j]) { + i -= j; + goto outer_end; + } + } + return i - j; + outer_end: void(); + } + return -1; +} + +int32_t StringPiece::compare(StringPiece other) { + int32_t i = 0; + for (; i < length(); i++) { + if (i == other.length()) { + // this is longer + return 1; + } + char a = data()[i]; + char b = other.data()[i]; + if (a < b) { + return -1; + } else if (a > b) { + return 1; + } + } + if (i < other.length()) { + // other is longer + return -1; + } + return 0; +} + U_EXPORT UBool U_EXPORT2 operator==(const StringPiece& x, const StringPiece& y) { int32_t len = x.size(); diff --git a/deps/icu-small/source/common/uarrsort.cpp b/deps/icu-small/source/common/uarrsort.cpp index 60905821649db9..c17dbb2e2b16a5 100644 --- a/deps/icu-small/source/common/uarrsort.cpp +++ b/deps/icu-small/source/common/uarrsort.cpp @@ -18,6 +18,8 @@ * Internal function for sorting arrays. */ +#include + #include "unicode/utypes.h" #include "cmemory.h" #include "uarrsort.h" @@ -35,7 +37,7 @@ enum { }; static constexpr int32_t sizeInMaxAlignTs(int32_t sizeInBytes) { - return (sizeInBytes + sizeof(max_align_t) - 1) / sizeof(max_align_t); + return (sizeInBytes + sizeof(std::max_align_t) - 1) / sizeof(std::max_align_t); } /* UComparator convenience implementations ---------------------------------- */ @@ -139,7 +141,7 @@ static void insertionSort(char *array, int32_t length, int32_t itemSize, UComparator *cmp, const void *context, UErrorCode *pErrorCode) { - icu::MaybeStackArray v; + icu::MaybeStackArray v; if (sizeInMaxAlignTs(itemSize) > v.getCapacity() && v.resize(sizeInMaxAlignTs(itemSize)) == nullptr) { *pErrorCode = U_MEMORY_ALLOCATION_ERROR; @@ -233,7 +235,7 @@ static void quickSort(char *array, int32_t length, int32_t itemSize, UComparator *cmp, const void *context, UErrorCode *pErrorCode) { /* allocate two intermediate item variables (x and w) */ - icu::MaybeStackArray xw; + icu::MaybeStackArray xw; if(sizeInMaxAlignTs(itemSize)*2 > xw.getCapacity() && xw.resize(sizeInMaxAlignTs(itemSize) * 2) == nullptr) { *pErrorCode=U_MEMORY_ALLOCATION_ERROR; diff --git a/deps/icu-small/source/common/uassert.h b/deps/icu-small/source/common/uassert.h index f0f7a92574b4d4..afd31eeffd91a4 100644 --- a/deps/icu-small/source/common/uassert.h +++ b/deps/icu-small/source/common/uassert.h @@ -31,6 +31,8 @@ #if U_DEBUG # include # define U_ASSERT(exp) assert(exp) +#elif U_CPLUSPLUS_VERSION +# define U_ASSERT(exp) (void)0 #else # define U_ASSERT(exp) #endif diff --git a/deps/icu-small/source/common/ubidi_props_data.h b/deps/icu-small/source/common/ubidi_props_data.h index 70083892048f80..7a34870bd8003f 100644 --- a/deps/icu-small/source/common/ubidi_props_data.h +++ b/deps/icu-small/source/common/ubidi_props_data.h @@ -11,37 +11,37 @@ #ifdef INCLUDED_FROM_UBIDI_PROPS_C -static const UVersionInfo ubidi_props_dataVersion={0xc,1,0,0}; +static const UVersionInfo ubidi_props_dataVersion={0xd,0,0,0}; -static const int32_t ubidi_props_indexes[UBIDI_IX_TOP]={0x10,0x663c,0x6058,0x28,0x620,0x8c0,0x10ac0,0x10d24,0,0,0,0,0,0,0,0x6502b6}; +static const int32_t ubidi_props_indexes[UBIDI_IX_TOP]={0x10,0x67ec,0x6200,0x28,0x620,0x8c8,0x10ac0,0x10d24,0,0,0,0,0,0,0,0x6502b6}; -static const uint16_t ubidi_props_trieIndex[12324]={ +static const uint16_t ubidi_props_trieIndex[12536]={ 0x37c,0x384,0x38c,0x394,0x3ac,0x3b4,0x3bc,0x3c4,0x39c,0x3a4,0x39c,0x3a4,0x39c,0x3a4,0x39c,0x3a4, 0x39c,0x3a4,0x39c,0x3a4,0x3ca,0x3d2,0x3da,0x3e2,0x3ea,0x3f2,0x3ee,0x3f6,0x3fe,0x406,0x401,0x409, 0x39c,0x3a4,0x39c,0x3a4,0x411,0x419,0x39c,0x3a4,0x39c,0x3a4,0x39c,0x3a4,0x41f,0x427,0x42f,0x437, 0x43f,0x447,0x44f,0x457,0x45d,0x465,0x46d,0x475,0x47d,0x485,0x48b,0x493,0x49b,0x4a3,0x4ab,0x4b3, -0x4bf,0x4bb,0x4c7,0x4cf,0x431,0x4df,0x4e7,0x4d7,0x4ef,0x4f1,0x4f9,0x501,0x509,0x50a,0x512,0x51a, -0x522,0x50a,0x52a,0x52f,0x522,0x50a,0x537,0x53f,0x509,0x547,0x54f,0x501,0x554,0x39c,0x55c,0x560, -0x568,0x56a,0x572,0x57a,0x509,0x582,0x58a,0x501,0x413,0x58e,0x512,0x501,0x39c,0x39c,0x596,0x39c, -0x39c,0x59c,0x5a4,0x39c,0x39c,0x5a8,0x5b0,0x39c,0x5b4,0x5bb,0x39c,0x5c3,0x5cb,0x5d2,0x553,0x39c, -0x39c,0x5da,0x5e2,0x5ea,0x5f2,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x5fa,0x39c,0x602,0x39c,0x39c,0x39c, -0x60a,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0x39c,0x39c,0x612,0x39c,0x39c,0x39c,0x61a,0x61a,0x516,0x516,0x39c,0x620,0x628,0x602, -0x63e,0x630,0x630,0x646,0x64d,0x636,0x39c,0x39c,0x39c,0x655,0x65d,0x39c,0x39c,0x39c,0x65f,0x667, -0x66f,0x39c,0x676,0x67e,0x39c,0x686,0x39c,0x39c,0x546,0x68e,0x554,0x696,0x413,0x69e,0x39c,0x6a5, -0x39c,0x6aa,0x39c,0x39c,0x39c,0x39c,0x6b0,0x6b8,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x3ea,0x6c0, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x6c8,0x6d0,0x6d4, -0x6ec,0x6f2,0x6dc,0x6e4,0x6fa,0x702,0x706,0x5d5,0x70e,0x716,0x71e,0x39c,0x726,0x667,0x667,0x667, -0x736,0x73e,0x746,0x74e,0x753,0x75b,0x763,0x72e,0x76b,0x773,0x39c,0x779,0x780,0x667,0x667,0x667, -0x667,0x580,0x786,0x667,0x78e,0x39c,0x39c,0x664,0x667,0x667,0x667,0x667,0x667,0x667,0x667,0x667, -0x667,0x667,0x667,0x667,0x667,0x796,0x667,0x667,0x667,0x667,0x667,0x79c,0x667,0x667,0x7a4,0x7ac, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x667,0x667,0x667,0x667,0x7bc,0x7c4,0x7cc,0x7b4, -0x7dc,0x7e4,0x7ec,0x7f3,0x7fa,0x802,0x806,0x7d4,0x667,0x667,0x667,0x80e,0x814,0x667,0x667,0x81a, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x822,0x39c,0x39c,0x39c,0x82a,0x39c,0x39c,0x39c,0x3ea, -0x832,0x83a,0x66b,0x39c,0x83d,0x667,0x667,0x66a,0x667,0x667,0x667,0x667,0x667,0x667,0x844,0x84a, -0x85a,0x852,0x39c,0x39c,0x862,0x60a,0x39c,0x3c3,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x667,0x829, -0x3d1,0x39c,0x86a,0x872,0x39c,0x87a,0x882,0x39c,0x39c,0x39c,0x39c,0x886,0x39c,0x39c,0x65f,0x3c2, +0x4bf,0x4bb,0x4c7,0x4cf,0x431,0x4df,0x4e6,0x4d7,0x4ee,0x4f0,0x4f8,0x500,0x508,0x509,0x511,0x519, +0x521,0x509,0x529,0x52e,0x521,0x509,0x536,0x53e,0x508,0x546,0x54e,0x500,0x556,0x39c,0x55e,0x562, +0x56a,0x56c,0x574,0x57c,0x508,0x584,0x58c,0x500,0x413,0x590,0x511,0x500,0x508,0x39c,0x598,0x39c, +0x39c,0x59e,0x5a6,0x39c,0x39c,0x5aa,0x5b2,0x39c,0x5b6,0x5bd,0x39c,0x5c5,0x5cd,0x5d4,0x555,0x39c, +0x39c,0x5dc,0x5e4,0x5ec,0x5f4,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x5fc,0x39c,0x604,0x39c,0x39c,0x39c, +0x60c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, +0x39c,0x39c,0x39c,0x39c,0x614,0x39c,0x39c,0x39c,0x61c,0x61c,0x515,0x515,0x39c,0x622,0x62a,0x604, +0x640,0x632,0x632,0x648,0x64f,0x638,0x39c,0x39c,0x39c,0x657,0x65f,0x39c,0x39c,0x39c,0x661,0x669, +0x671,0x39c,0x678,0x680,0x39c,0x688,0x56b,0x39c,0x545,0x690,0x556,0x698,0x413,0x6a0,0x39c,0x6a7, +0x39c,0x6ac,0x39c,0x39c,0x39c,0x39c,0x6b2,0x6ba,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x3ea,0x6c2, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x6ca,0x6d2,0x6d6, +0x6ee,0x6f4,0x6de,0x6e6,0x6fc,0x704,0x708,0x5d7,0x710,0x718,0x720,0x39c,0x728,0x669,0x669,0x669, +0x738,0x740,0x748,0x750,0x755,0x75d,0x765,0x730,0x76d,0x775,0x39c,0x77b,0x782,0x669,0x669,0x669, +0x669,0x582,0x788,0x669,0x790,0x39c,0x39c,0x666,0x669,0x669,0x669,0x669,0x669,0x669,0x669,0x669, +0x669,0x669,0x669,0x669,0x669,0x798,0x669,0x669,0x669,0x669,0x669,0x79e,0x669,0x669,0x7a6,0x7ae, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x669,0x669,0x669,0x669,0x7be,0x7c6,0x7ce,0x7b6, +0x7de,0x7e6,0x7ee,0x7f5,0x7fc,0x804,0x808,0x7d6,0x669,0x669,0x669,0x810,0x816,0x669,0x669,0x81c, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x824,0x39c,0x39c,0x39c,0x82c,0x39c,0x39c,0x39c,0x3ea, +0x834,0x83c,0x840,0x39c,0x848,0x669,0x669,0x66c,0x669,0x669,0x669,0x669,0x669,0x669,0x84f,0x855, +0x865,0x85d,0x39c,0x39c,0x86d,0x60c,0x39c,0x3c3,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x669,0x82b, +0x3d1,0x39c,0x875,0x87d,0x39c,0x885,0x88d,0x39c,0x39c,0x39c,0x39c,0x891,0x39c,0x39c,0x661,0x3c2, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, @@ -54,7 +54,7 @@ static const uint16_t ubidi_props_trieIndex[12324]={ 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x667,0x667, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x669,0x669, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, @@ -98,10 +98,10 @@ static const uint16_t ubidi_props_trieIndex[12324]={ 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0x39c,0x39c,0x86a,0x667,0x580,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x88d,0x39c,0x39c,0x892,0x56a,0x39c,0x39c,0x5b6,0x667,0x65e,0x39c,0x39c,0x89a,0x39c,0x39c,0x39c, -0x8a2,0x8a9,0x630,0x8b1,0x39c,0x39c,0x58c,0x8b9,0x39c,0x8c1,0x8c8,0x39c,0x4ef,0x8cd,0x39c,0x508, -0x39c,0x8d5,0x8dd,0x50a,0x39c,0x8e1,0x509,0x8e9,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x8f0, +0x39c,0x39c,0x39c,0x39c,0x875,0x669,0x582,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, +0x898,0x39c,0x39c,0x89d,0x56c,0x39c,0x39c,0x5b8,0x669,0x660,0x39c,0x39c,0x8a5,0x39c,0x39c,0x39c, +0x8ad,0x8b4,0x632,0x8bc,0x39c,0x39c,0x58e,0x8c4,0x39c,0x8cc,0x8d3,0x39c,0x4ee,0x8d8,0x39c,0x507, +0x39c,0x8e0,0x8e8,0x509,0x39c,0x8ec,0x508,0x8f4,0x39c,0x39c,0x39c,0x8fa,0x39c,0x39c,0x39c,0x901, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, @@ -141,9 +141,9 @@ static const uint16_t ubidi_props_trieIndex[12324]={ 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x904,0x8f8,0x8fc,0x49b,0x49b,0x49b,0x49b,0x49b, -0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x90c,0x49b,0x49b,0x49b,0x49b,0x914,0x918, -0x920,0x928,0x92c,0x934,0x49b,0x49b,0x49b,0x938,0x940,0x38c,0x948,0x950,0x39c,0x39c,0x39c,0x958, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x915,0x909,0x90d,0x49b,0x49b,0x49b,0x49b,0x49b, +0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x49b,0x91d,0x49b,0x49b,0x49b,0x49b,0x925,0x929, +0x931,0x939,0x93d,0x945,0x49b,0x49b,0x49b,0x949,0x951,0x38c,0x959,0x961,0x39c,0x39c,0x39c,0x969, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0xe70,0xe70,0xeb0,0xef0,0xe70,0xe70,0xe70,0xe70,0xe70,0xe70,0xf28,0xf68,0xfa8,0xfb8,0xff8,0x1004, @@ -180,65 +180,65 @@ static const uint16_t ubidi_props_trieIndex[12324]={ 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd5d, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd5d, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x960,0x39c,0x667,0x667,0x968,0x60a,0x39c,0x502, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x970,0x39c,0x39c,0x39c,0x977,0x39c,0x39c,0x39c,0x39c, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x971,0x39c,0x669,0x669,0x979,0x60c,0x39c,0x501, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x981,0x39c,0x39c,0x39c,0x988,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x97f,0x431,0x431,0x431,0x431,0x431,0x431,0x431, -0x987,0x98b,0x431,0x431,0x431,0x431,0x99b,0x993,0x431,0x9a3,0x431,0x431,0x9ab,0x9b1,0x431,0x431, -0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x9c1,0x9b9,0x431,0x431,0x431,0x431,0x431,0x431, -0x431,0x431,0x431,0x9c9,0x431,0x431,0x431,0x431,0x431,0x9d1,0x9d8,0x9de,0x431,0x431,0x431,0x431, -0x509,0x9e6,0x9ed,0x9f4,0x413,0x9f7,0x39c,0x39c,0x4ef,0x9fe,0x39c,0xa04,0x413,0xa09,0xa11,0x39c, -0x39c,0xa16,0x39c,0x39c,0x39c,0x39c,0x82a,0xa1e,0x413,0x58e,0x569,0xa25,0x39c,0x39c,0x39c,0x39c, -0x39c,0x9e6,0xa2d,0x39c,0x39c,0xa35,0xa3d,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xa41,0xa49,0x39c, -0x39c,0xa51,0x569,0xa59,0x39c,0xa5f,0x39c,0x39c,0x5fa,0xa67,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0xa6c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xa73,0x569,0xa7b, -0xa7f,0xa87,0x39c,0xa8e,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0xa95,0x39c,0x39c,0xaa3,0xa9d,0x39c,0x39c,0x39c,0xaab,0xab3,0x39c,0xab7,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x590,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xac4,0xabf,0x39c, +0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x990,0x431,0x431,0x431,0x431,0x431,0x431,0x431, +0x998,0x99c,0x431,0x431,0x431,0x431,0x9ac,0x9a4,0x431,0x9b4,0x431,0x431,0x9bc,0x9c2,0x431,0x431, +0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x9d2,0x9ca,0x431,0x431,0x431,0x431,0x431,0x431, +0x431,0x431,0x431,0x9da,0x431,0x9e2,0x431,0x431,0x431,0x9e6,0x9ed,0x9f3,0x431,0x9f7,0x9ff,0x431, +0x508,0xa07,0xa0e,0xa15,0x413,0xa18,0x39c,0x39c,0x4ee,0xa1f,0x39c,0xa25,0x413,0xa2a,0xa32,0x39c, +0x39c,0xa37,0x39c,0x39c,0x39c,0x39c,0x82c,0xa3f,0x413,0x590,0x56b,0xa46,0x39c,0x39c,0x39c,0x39c, +0x39c,0xa07,0xa4e,0x39c,0x39c,0xa56,0xa5e,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xa62,0xa6a,0x39c, +0x39c,0xa72,0x56b,0xa7a,0x39c,0xa80,0x39c,0x39c,0x5fc,0xa88,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, +0xa8d,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xa94,0xa9c,0x39c,0x39c,0x39c,0xa9f,0x56b,0xaa7, +0xaab,0xab3,0x39c,0xaba,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, +0xac1,0x39c,0x39c,0xacf,0xac9,0x39c,0x39c,0x39c,0xad7,0xadf,0x39c,0xae3,0x39c,0x39c,0x39c,0x39c, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x592,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xaf0,0xaeb,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0xacc,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xad3, -0x39c,0xad9,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, +0xaf8,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xaff, +0x39c,0xb05,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0xa05,0x39c,0xadf,0x39c,0x39c,0xae7,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, +0x39c,0x39c,0xa26,0x39c,0xb0b,0x39c,0x39c,0xb13,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x523,0xaef,0x39c,0x39c, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x522,0xb1b,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xaf6,0xafe,0xb04,0x39c,0x39c,0x667,0x667,0xb0c, -0x39c,0x39c,0x39c,0x39c,0x39c,0x667,0x667,0xb14,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xb22,0xb2a,0xb30,0x39c,0x39c,0x669,0x669,0xb38, +0x39c,0x39c,0x39c,0x39c,0x39c,0x669,0x669,0x83f,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0x39c,0xb1a,0x39c,0xb21,0x39c,0xb1d,0x39c,0xb24,0x39c,0xb2c,0xb30,0x39c,0x39c,0x39c, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x3ea,0xb38,0x3ea, -0xb3f,0xb46,0xb4e,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, +0x39c,0x39c,0x39c,0xb3a,0x39c,0xb41,0x39c,0xb3d,0x39c,0xb44,0x39c,0xb4c,0xb50,0x39c,0x39c,0x39c, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x3ea,0xb58,0x3ea, +0xb5f,0xb66,0xb6e,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xb56,0xb5e,0x39c, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xad9,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0x39c,0x39c,0xb63,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xb76,0xb7e,0x39c, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xb05,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, +0x39c,0x39c,0x39c,0x39c,0xb83,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x431,0x431,0x431, -0x431,0x431,0x431,0xb6b,0x431,0xb73,0xb73,0xb7a,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431, +0x431,0x431,0x431,0xb8b,0x431,0xb93,0xb93,0xb9a,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431, 0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431, -0x8fc,0x49b,0x49b,0x431,0x431,0x49b,0x49b,0x9de,0x431,0x431,0x431,0x431,0x431,0x49b,0x49b,0x49b, -0x49b,0x49b,0x49b,0x49b,0xb82,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x667,0xb8a,0x667, -0x667,0x66a,0xb8f,0xb93,0x844,0xb9b,0x3be,0x39c,0xba1,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x777,0x39c,0x39c,0x39c,0x39c,0x667,0x667,0x667,0x667,0x667,0x667,0x667,0x667,0x667,0x667,0x667, -0x667,0x667,0x667,0x667,0x667,0x667,0x667,0x667,0x667,0x667,0x667,0x667,0x667,0x667,0x667,0x667, -0x667,0x667,0x667,0x844,0xba9,0x667,0x667,0x667,0x66a,0x667,0x667,0xbb1,0x66c,0xb8a,0x667,0xbb9, -0x667,0xbc1,0x846,0x39c,0x39c,0x796,0x667,0x667,0xbc5,0x667,0xbcd,0xbd3,0x667,0x667,0x667,0x66a, -0xbd8,0xbe7,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, +0x90d,0x49b,0x49b,0x431,0x431,0x49b,0x49b,0x9f3,0x431,0x431,0x431,0x431,0x431,0x49b,0x49b,0x49b, +0x49b,0x49b,0x49b,0x49b,0xba2,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x431,0x669,0xbaa,0x669, +0x669,0x66c,0xbaf,0xbb3,0x84f,0xbbb,0x3be,0x39c,0xbc1,0x39c,0xbc6,0x39c,0x39c,0x39c,0x39c,0x39c, +0x779,0x39c,0x39c,0x39c,0x39c,0x669,0x669,0x669,0x669,0x669,0x669,0x669,0x669,0x669,0x669,0x669, +0x669,0x669,0x669,0x669,0x669,0x669,0x669,0x669,0x669,0x669,0x669,0x669,0x669,0x669,0x669,0x669, +0x669,0x669,0x669,0x66b,0x979,0x669,0x669,0x669,0x66c,0x669,0x669,0xbce,0x66e,0xbaa,0x669,0xbd6, +0x669,0xbde,0xbe3,0x39c,0x39c,0x669,0x669,0x669,0xbeb,0x669,0x669,0x798,0x669,0x669,0x669,0x66c, +0xbf2,0xbfa,0xc00,0xc05,0x39c,0x669,0x669,0x669,0x669,0xc0d,0x669,0x788,0xc15,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xbdf,0x39c,0x39c,0x39c, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xc1c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, 0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xbdf,0xbf7,0xbef,0xbef, -0xbef,0xbf8,0xbf8,0xbf8,0xbf8,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0xc00,0xbf8,0xbf8,0xbf8, -0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8, -0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8, -0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8, -0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0xbf8,0x37b,0x37b,0x37b, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xc1c,0xc2c,0xc24,0xc24, +0xc24,0xc2d,0xc2d,0xc2d,0xc2d,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0xc35,0xc2d,0xc2d,0xc2d, +0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d, +0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d, +0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d, +0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0x37b,0x37b,0x37b, 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,8,7,8,9,7,0x12,0x12, 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,7,7,7,8, 9,0xa,0xa,4,4,4,0xa,0xa,0x310a,0xf20a,0xa,3,6,3,6,6, @@ -323,368 +323,379 @@ static const uint16_t ubidi_props_trieIndex[12324]={ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,0xb1,0xb1,0xb1,0xb1,1,0xb1,0xb1,0xb1,0xb1,0xb1,0x81,0x41,0x41,0x41, 0x41,0x41,0x81,0x81,0x41,0x81,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, -0x81,0x41,1,1,1,0xb1,0xb1,0xb1,1,1,1,1,0x4d,0xd,0x4d,0x4d, +0x81,0x41,0x81,0x81,0x81,0xb1,0xb1,0xb1,1,1,1,1,0x4d,0xd,0x4d,0x4d, 0x4d,0x4d,0xd,0x8d,0x4d,0x8d,0x8d,0xd,0xd,0xd,0xd,0xd,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,0xb1,0xb1,5,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0x4d,0x4d,0x4d,0x4d, 0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x8d,0x8d,0xd,0x8d,0x4d,0x4d,0x8d,0x8d,0x4d, -0x4d,0xd,0x4d,0x4d,0x4d,0x8d,0x4d,0x4d,0x4d,0x4d,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, +0x4d,0xd,0x4d,0x4d,0x4d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0, -0xb1,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0, -0,0xb1,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0, -0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xb1,0,0xb1,0,0,0, +0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0xb1,0,0, +0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0, +0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0, +0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb1,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0, -0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0, +0xb1,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, +0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,4, +0,0,0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xb1,0xb1,0,0,0,0,0xb1,0xb1,0,0,0xb1, +0xb1,0xb1,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0xb1,0,0, +0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1, +0xb1,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0, -0,0,0,4,0,0,0xb1,0,0,0xb1,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0, +0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0xb1, -0xb1,0,0,0xb1,0xb1,0xb1,0,0,0,0xb1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0, -0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1, -0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0xb1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, -0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, -0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0, +0,0,0,0,0xb1,0,0,0xb1,0,0xb1,0xb1,0xb1,0xb1,0,0,0, +0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0xb1,0xb1,0, +0,0,0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xb1,0,0,0xb1,0,0xb1,0xb1,0xb1, -0xb1,0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0, -0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0, +0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa, +0xa,4,0xa,0,0,0,0,0,0xb1,0,0,0,0xb1,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, +0xb1,0,0,0,0,0,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0,0, +0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0, +0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,4,0xa,0,0,0,0,0, -0xb1,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0,0xa0, +0,0,0,0,0,0,0xa0,0,0,0,0,0,0xb1,0xb1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0,0,0,0,0xb1,0xb1, -0xb1,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0xb1,0xb1,0, -0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0, +0,0,0xb1,0xb1,0xb1,0,0xb1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0,0,0,0,4,0,0,0,0,0,0,0,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0, +0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xb1,0,0xb1,0,0xb1,0x310a,0xf20a, +0x310a,0xf20a,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0,0,0, +0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1, +0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0,0xb1,0xb1,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb1,0,0,0xa0,0,0,0,0,0,0,0xa0,0, -0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0xb1,0xb1, +0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0,0xb1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0, -0,0,0xb1,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0xb1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,4, -0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0, +0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0, -0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0, +9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x310a,0xf20a,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0, +0,0,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0xb1,0, +0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0, +0,0,0,4,0,0xb1,0,0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xb1,0x40,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xb1,0,0xb1,0,0xb1,0x310a,0xf20a,0x310a,0xf20a,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1, -0xb1,0,0xb1,0xb1,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x4a,0xa,0xa,0x2a,0xb1,0xb1,0xb1,0x12,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0xb1,0xb1,0,0,0,0,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0, -0,0,0,0,0,0,0,0,0,0,0xb1,0,0,0xb1,0xb1,0, -0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0,0,0,0,0,0,0, +0,0xb1,0xb1,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xb1,0xb1,0xb1,0, +0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0xb1,0, +0,0,0,0,0,0xb1,0xb1,0xb1,0,0,0,0,0xa,0,0,0, +0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0,0,0,0,0,0,0xa,0,0,0,0,0,0,0, +0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0xb1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, +0xb1,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0, +0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0x310a,0xf20a,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0, -0,0,0,0,0,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,4,0,0xb1,0,0, -0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, -0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, -0x40,0xb1,0x40,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x4a, -0xa,0xa,0x2a,0xb1,0xb1,0xb1,0x12,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, -0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, -0x40,0,0,0,0,0,0,0,0,0xb1,0xb1,0x40,0x40,0x40,0x40,0x40, -0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, -0x40,0x40,0x40,0x40,0xb1,0xb1,0xb1,0,0,0,0,0xb1,0xb1,0,0,0, -0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0xb1,0xb1,0xb1, -0,0,0,0,0xa,0,0,0,0xa,0xa,0,0,0,0,0,0, +0,0,0,0,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0xb1,0xb1,0xb1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0xb1,0xb1,0,0,0xb1,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0,0xb1,0,0,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0xb1,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0, -0xb1,0xb1,0,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0xb1,0,0xb1,0xb1,0,0, -0,0xb1,0,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0xb1,0,0, -0,0,0,0,0xb1,0,0,0,0xb1,0xb1,0,0,0,0,0,0, +0,0,0xb1,0,0xb1,0xb1,0,0,0,0xb1,0,0xb1,0xb1,0xb1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0,0,0,0,0xb1,0,0,0,0,0,0,0xb1,0,0,0, +0xb1,0xb1,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0,0xa, -0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa, -0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa, -0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0, -0xa,0xa,0xa,0xa,6,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,9, -0xb2,0xb2,0xb2,0xb2,0xb2,0x12,0x814,0x815,0x813,0x816,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2, -2,0,0,0,2,2,2,2,2,2,3,3,0xa,0x310a,0xf20a,0, -9,9,9,9,9,9,9,9,9,9,9,0xb2,0x412,0x432,0x8a0,0x8a1, +0,0,0,0,0,0xa,0,0xa,0xa,0xa,0,0,0,0,0,0, +0,0,0,0,0,0xa,0xa,0xa,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xa,0xa,0xa,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xa,0xa,0,0xa,0xa,0xa,0xa,6,0x310a,0xf20a,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -9,7,0x8ab,0x8ae,0x8b0,0x8ac,0x8af,6,4,4,4,4,4,0xa,0xa,0xa, -0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,2,2,2,2,2,2,2,2, -2,2,3,3,0xa,0x310a,0xf20a,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,9,0xb2,0xb2,0xb2,0xb2,0xb2,0x12,0x814,0x815, +0x813,0x816,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,2,0,0,0,2,2,2,2, +2,2,3,3,0xa,0x310a,0xf20a,0,9,9,9,9,9,9,9,9, +9,9,9,0xb2,0x412,0x432,0x8a0,0x8a1,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,9,7,0x8ab,0x8ae,0x8b0,0x8ac,0x8af,6, +4,4,4,4,4,0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa, +2,2,2,2,2,2,2,2,2,2,3,3,0xa,0x310a,0xf20a,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, -4,4,4,4,4,4,4,4,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa,0xa,0,0xa,0xa,0xa,0xa,0, -0xa,0xa,0,0,0,0,0,0,0,0,0,0,0xa,0,0xa,0xa, -0xa,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0,0xa, -0,0xa,0,0,0,0,4,0,0,0,0,0,0,0,0,0, -0,0,0xa,0xa,0,0,0,0,0x100a,0xa,0xa,0xa,0xa,0,0,0, -0,0,0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, -0,0xa,0xa,0xa,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, -0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0x300a,0xf00a,0x900a,0x900a,0x900a,0x100a,0x900a,0x900a, -0x100a,0x100a,0x900a,0x900a,0x900a,0x900a,0x900a,0x100a,0xa,0x100a,0x100a,0x100a,0x100a,0xa,0xa,0xa, -0x700a,0x700a,0x700a,0xb00a,0xb00a,0xb00a,0xa,0xa,0xa,0x100a,3,4,0xa,0x900a,0x100a,0xa, -0xa,0xa,0x100a,0x100a,0x100a,0x100a,0xa,0x900a,0x900a,0x900a,0x900a,0xa,0x900a,0xa,0x100a,0xa, -0xa,0xa,0xa,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0xa,0xa,0xa,0xa, -0xa,0x100a,0xa,0x100a,0x300a,0xf00a,0x100a,0x100a,0x100a,0x100a,0x100a,0x900a,0x100a,0x900a,0x100a,0x100a, -0x100a,0x100a,0x100a,0x100a,0x900a,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0xa,0x100a,0xa,0x300a,0xf00a,0x300a,0xf00a, -0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, -0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x100a,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa, -0xa,0xa,0xa,0xa,0x900a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a, -0xa,0xa,0x900a,0x100a,0x900a,0x900a,0x100a,0x900a,0x100a,0x100a,0x100a,0x100a,0x300a,0xf00a,0x300a,0xf00a, -0x300a,0xf00a,0x300a,0xf00a,0x900a,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x900a,0xa,0xa,0x300a,0xf00a,0xa,0xa, -0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xa,0xa,0,0xa,0xa,0xa,0xa,0,0xa,0xa,0,0,0,0,0,0, +0,0,0,0,0xa,0,0xa,0xa,0xa,0,0,0,0,0,0xa,0xa, +0xa,0xa,0xa,0xa,0,0xa,0,0xa,0,0xa,0,0,0,0,4,0, +0,0,0,0,0,0,0,0,0,0,0xa,0xa,0,0,0,0, +0x100a,0xa,0xa,0xa,0xa,0,0,0,0,0,0xa,0xa,0xa,0xa,0,0, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a, -0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0x100a,0xa,0xa,0x300a,0xf00a,0x310a,0xf20a,0xa,0x300a,0xf00a,0xa,0x500a,0x100a,0xd00a,0xa,0xa, -0xa,0xa,0xa,0x100a,0x100a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0x900a,0x300a,0xf00a,0xa, -0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a, +0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0,0,0,0, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0x100a,0xa,0x100a,0x100a,0x100a,0xa,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0x100a,0x900a,0x100a,0x100a,0x300a,0xf00a,0xa,0xa,0x310a,0xf20a,0xa,0xa, -0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x710a,0x320a,0xf10a, -0xb20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0x900a,0x100a,0x100a,0x100a,0x100a, -0x900a,0xa,0x100a,0x900a,0x300a,0xf00a,0x100a,0x100a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x900a,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0x300a,0xf00a,0x100a,0x100a,0x300a,0xf00a,0xa,0xa,0xa,0x100a,0xa,0xa,0xa,0xa,0x100a,0x300a, -0xf00a,0x300a,0xf00a,0xa,0x300a,0xf00a,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x100a,0xa,0xa,0xa, -0xa,0xa,0x100a,0x900a,0x900a,0x900a,0x100a,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x900a,0xa, -0xa,0xa,0xa,0x100a,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x100a,0xa,0x100a,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a, -0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0xa,0x100a,0x100a, -0x100a,0x100a,0xa,0xa,0x100a,0xa,0x100a,0xa,0xa,0x100a,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa, -0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x100a,0xa, +0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa, +0x300a,0xf00a,0x900a,0x900a,0x900a,0x100a,0x900a,0x900a,0x100a,0x100a,0x900a,0x900a,0x900a,0x900a,0x900a,0x100a, +0xa,0x100a,0x100a,0x100a,0x100a,0xa,0xa,0xa,0x700a,0x700a,0x700a,0xb00a,0xb00a,0xb00a,0xa,0xa, +0xa,0x100a,3,4,0xa,0x900a,0x100a,0xa,0xa,0xa,0x100a,0x100a,0x100a,0x100a,0xa,0x900a, +0x900a,0x900a,0x900a,0xa,0x900a,0xa,0x100a,0xa,0xa,0xa,0xa,0x100a,0x100a,0x100a,0x100a,0x100a, +0x100a,0x100a,0x100a,0x100a,0xa,0xa,0xa,0xa,0xa,0x100a,0xa,0x100a,0x300a,0xf00a,0x100a,0x100a, +0x100a,0x100a,0x100a,0x900a,0x100a,0x900a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x900a,0xa,0xa,0xa, +0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a, +0x100a,0xa,0x100a,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0x300a,0xf00a, +0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, +0x100a,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0x900a,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa,0x900a,0x100a,0x900a,0x900a,0x100a,0x900a, +0x100a,0x100a,0x100a,0x100a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x900a,0xa,0xa,0xa, +0xa,0xa,0x100a,0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a, +0xf00a,0x900a,0xa,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, +0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0x300a,0xf00a,0xa,0xa,0xa,0xa,0x100a,0x100a,0x100a,0x100a,0xa,0x100a,0x100a,0xa,0xa,0x100a, -0x100a,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, -0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, -0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x100a,0xa,0xa,0x300a,0xf00a, -0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, -0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa, -0xa,0xa,0xa,0xa,0x100a,0xa,0x900a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa, +0xa,0xa,0xa,0xa,0x100a,0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x310a,0xf20a,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0xa,0xa,0x300a,0xf00a,0x310a,0xf20a,0xa, +0x300a,0xf00a,0xa,0x500a,0x100a,0xd00a,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0x300a,0xf00a,0xa, +0xa,0xa,0xa,0xa,0x900a,0x300a,0xf00a,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x310a,0xf20a, +0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0xa,0x100a,0x100a,0x100a,0xa,0xa, +0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x900a,0x100a,0x100a, +0x300a,0xf00a,0xa,0xa,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a, +0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x710a,0x320a,0xf10a,0xb20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a, +0xf20a,0xa,0xa,0x900a,0x100a,0x100a,0x100a,0x100a,0x900a,0xa,0x100a,0x900a,0x300a,0xf00a,0x100a,0x100a, +0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0x900a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x100a,0x100a,0x300a,0xf00a,0xa,0xa, +0xa,0x100a,0xa,0xa,0xa,0xa,0x100a,0x300a,0xf00a,0x300a,0xf00a,0xa,0x300a,0xf00a,0xa,0xa, +0x310a,0xf20a,0x310a,0xf20a,0x100a,0xa,0xa,0xa,0xa,0xa,0x100a,0x900a,0x900a,0x900a,0x100a,0xa, +0xa,0xa,0xa,0xa,0x300a,0xf00a,0x900a,0xa,0xa,0xa,0xa,0x100a,0xa,0xa,0xa,0x300a, +0xf00a,0x300a,0xf00a,0x100a,0xa,0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a, +0x100a,0x100a,0x100a,0x100a,0x100a,0xa,0x100a,0x100a,0x100a,0x100a,0xa,0xa,0x100a,0xa,0x100a,0xa, +0xa,0x100a,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa, +0xa,0xa,0xa,0xa,0x300a,0xf00a,0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a, +0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0x100a,0x100a, +0x100a,0x100a,0xa,0x100a,0x100a,0xa,0xa,0x100a,0x100a,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a, +0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, +0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, +0xf00a,0x300a,0xf00a,0x100a,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0x300a, +0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, +0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0x100a,0xa,0x900a,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0x900a,0xa,0,0,0,0,0,0xa,0xa,0xa, -0xa,0xa,0xa,0,0,0,0,0xb1,0xb1,0xb1,0,0,0,0,0,0, -0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa, -0xa,0x300a,0xf00a,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa,0x300a,0xf00a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a, -0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0,0,0,0,0xa,0,0,0,0,0,0,0, -0,0,0xb1,0xb1,0xb1,0xb1,0,0,0xa,0,0,0,0,0,0xa,0xa, -0,0,0,0,0,0xa,0xa,0xa,9,0xa,0xa,0xa,0xa,0,0,0, -0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a, -0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xb1,0xb1,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x900a,0xa, +0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0xb1, +0xb1,0xb1,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, -0,0,0,0,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0x300a,0xf00a,0xa,0x300a,0xf00a,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa, +0x300a,0xf00a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, 0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xa,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa,0xa,0,0,0,0,0,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0,0,0,0,0xa,0,0,0,0,0,0,0,0,0,0xb1,0xb1, +0xb1,0xb1,0,0,0xa,0,0,0,0,0,0xa,0xa,0,0,0,0, +0,0xa,0xa,0xa,9,0xa,0xa,0xa,0xa,0,0,0,0x310a,0xf20a,0x310a,0xf20a, +0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a, +0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xa, 0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0xb1,0,0,0,0xb1,0, -0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0xa,0xa,0xa,0xa, -0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0, -0,0,0,0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, -0x40,0x40,0x40,0x40,0x40,0x40,0x60,0,0xa,0xa,0xa,0xa,0,0,0,0, -0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0xb1,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0,0, -0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0, -0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb1,0,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0, -0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, -0xb1,0xb1,0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0, -0,0,0,0,0,0xb1,0,0,0xb1,0,0,0,0,0xb1,0,0, +0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0, +0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xb1,0xb1,0xb1,0xb1,0xa,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xa,0xa,0,0,0,0,0,0,0,0,0xa,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1, +0,0,0,0,0,0,0xb1,0,0,0,0xb1,0,0,0,0,0xb1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xb1,0xb1,0,0xa,0xa,0xa,0xa,0xb1,0,0,0, +0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x60,0,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0, +0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, +0,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0, +0,0,0,0xb1,0,0,0,0,0,0,0,0,0xb1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xb1,0,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0xb1,0xb1, +0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0, +0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0, +0,0,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xb1,0,0,0xb1,0,0,0, +0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,1,1,1,1,1,1,1,1,3,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +1,1,1,1,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,1,0xb1,1, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xa,0xa, +0,1,0xb1,1,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, 0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xa,0xd,0xd, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -6,0xa,6,0,0xa,6,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,4, -0xa,0xa,3,3,0x300a,0xf00a,0xa,0,0xa,4,4,0xa,0,0,0,0, +0xd,0xd,0xa,0xa,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, +0x12,0x12,0x12,0x12,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xa,0xd,0xd,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0, +0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,6,0xa,6,0,0xa,6,0xa,0xa,0xa,0x310a,0xf20a,0x310a, +0xf20a,0x310a,0xf20a,4,0xa,0xa,3,3,0x300a,0xf00a,0xa,0,0xa,4,4,0xa, +0,0,0,0,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, 0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xb2, -0,0xa,0xa,4,4,4,0xa,0xa,0x310a,0xf20a,0xa,3,6,3,6,6, -2,2,2,2,2,2,2,2,2,2,6,0xa,0x500a,0xa,0xd00a,0xa, -0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0x510a,0xa,0xd20a,0xa,0x310a, -0xf20a,0xa,0x310a,0xf20a,0xa,0xa,0,0,0,0,0,0,0,0,0,0, +0xd,0xd,0xd,0xb2,0,0xa,0xa,4,4,4,0xa,0xa,0x310a,0xf20a,0xa,3, +6,3,6,6,2,2,2,2,2,2,2,2,2,2,6,0xa, +0x500a,0xa,0xd00a,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x510a, +0xa,0xd20a,0xa,0x310a,0xf20a,0xa,0x310a,0xf20a,0xa,0xa,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,4,0xa,0xa,0xa,4,4,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0, -0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0xaa,0xaa,0xaa,0xa,0xa,0x12,0x12, -0,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,4,4,0xa,0xa,0xa,4,4,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0xaa,0xaa,0xaa, +0xa,0xa,0x12,0x12,0,0xa,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0, -0xb1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0, +0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0,0,0,0xb1,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,1,1,1,1, +0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,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,0xa, +1,0xb1,0xb1,0xb1,1,0xb1,0xb1,1,1,1,1,1,0xb1,0xb1,0xb1,0xb1, 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,0xa,1,0xb1,0xb1,0xb1, -1,0xb1,0xb1,1,1,1,1,1,0xb1,0xb1,0xb1,0xb1,1,1,1,1, +1,1,1,1,1,1,1,1,0xb1,0xb1,0xb1,1,1,1,1,0xb1, +0x41,0x81,1,1,0x81,0xb1,0xb1,1,1,1,1,0x41,0x41,0x41,0x41,0x81, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0xb1,0xb1,0xb1,1,1,1,1,0xb1,0x41,0x81,1,1, -0x81,0xb1,0xb1,1,1,1,1,0x41,0x41,0x41,0x41,0x81,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0x41,0x41,0x41,0x41, -0x41,0x81,1,0x81,1,0x81,0x81,1,1,0x61,0x81,0x81,0x81,0x81,0x81,0x41, -0x41,0x41,0x41,0x61,0x41,0x41,0x41,0x41,0x41,0x81,0x41,0x41,1,1,1,1, +0x41,0x41,0x41,0x41,0x41,0x81,1,0x81,1,0x81,0x81,1,1,0x61,0x81,0x81, +0x81,0x81,0x81,0x41,0x41,0x41,0x41,0x61,0x41,0x41,0x41,0x41,0x41,0x81,0x41,0x41, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x41,0x81,0x41,0x81, -0x81,0x81,0x41,0x41,0x41,0x81,0x41,0x41,0x81,0x41,0x81,0x81,0x41,0x81,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,0x81,0x81,0x81, -0x81,0x41,0x41,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0x4d,0x4d,0x8d,0x4d,0xb1,0xb1,0xb1,0xb1,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,5,5,5,5,5,5,5,5,5,5,0xd,0xd, -0xd,0xd,0xd,0xd,0x6d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +1,1,1,1,1,1,1,1,1,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0x41,0x81,0x41,0x81,0x81,0x81,0x41,0x41,0x41,0x81,0x41,0x41,0x81,0x41,0x81,0x81, +0x41,0x81,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,0x81,0x81,0x81,0x81,0x41,0x41,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0x4d,0x4d,0x8d,0x4d,0xb1,0xb1,0xb1,0xb1, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,5,5,5,5,5,5,5,5, +5,5,0xd,0xd,0xd,0xd,0xd,0xd,0x6d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, 0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, -0x4d,0x4d,0x4d,0x4d,5,5,5,5,5,5,5,5,5,5,5,5, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0x4d,0x4d,0x4d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, -0x4d,0x4d,0x4d,0x4d,0x4d,0xd,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0x4d,0x4d,0x4d,0x8d,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, +5,5,5,5,5,5,5,1,1,1,1,1,1,1,1,1, +1,1,1,0xb1,0xb1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0x4d,0x4d,0x4d,0x8d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0xd,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0x4d,0x4d,0x4d,0x8d,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,0x41,1,0x41,0x41, +0x81,0x81,0x81,1,0x41,0x81,0x81,0x41,0x41,0x81,0x41,0x41,1,0x41,0x81,0x81, +0x41,1,1,1,1,0x81,0x41,0x61,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,0,0,0,0,0, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0, -0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, -0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0xb1, -0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0, +0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, +0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1, +0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0, +0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0,0xb1,0,0xb1,0xb1, -0,0,0,0,0,0,0xb1,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0, +0,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0, +0xb1,0,0xb1,0xb1,0,0,0,0,0,0,0xb1,0,0,0,0,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0xb1,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0, -0,0,0,0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0,0xb1,0,0,0,0,0xb1,0xb1,0,0xb1,0xb1,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0, -0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0, +0,0,0,0,0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, -0,0xb1,0,0xb1,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0,0xb1,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, -0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0, +0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0,0,0xb1,0,0xb1,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0xb1,0,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0,0,0,0,0,0,0,0, +0,0,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0xb1,0, +0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xa0,0xa0,0xb1,0xb1,0,0,0,0,0,0,0,0,0, @@ -714,7 +725,7 @@ static const uint16_t ubidi_props_trieIndex[12324]={ 0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0xb2,0xb2,0xb2,0xb2, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, @@ -725,9 +736,6 @@ static const uint16_t ubidi_props_trieIndex[12324]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0xa,0xa,0xb1,0xb1,0xb1,0xa,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0x100a,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0x100a,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -759,34 +767,39 @@ static const uint16_t ubidi_props_trieIndex[12324]={ 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,2,2,2,2, -2,2,2,2,2,2,2,0xa,0xa,0,0,0,0,0,0,0, +2,2,2,2,2,2,2,0xa,0xa,0xa,0xa,0xa,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa, -0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0, -0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0, -0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0, -0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0, -0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0, +0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xa,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0,0,0, +0xa,0xa,0xa,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0, +0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0, 0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0,0,0,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0, -0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0, -0xa,0xa,0xa,0xa,0,0,0,0,0xa,0xa,0xa,0,0,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0x12,0x12,0xa,0xa,0xa,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0,0,0,0,0,0,0,0,0,0,0xb2,0xb2,0xb2,0xb2, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x12,0x12, 0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2, -0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0x12,0xb2,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2, +0x12,0xb2,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, -0,0,0,0 +0x12,0x12,0x12,0x12,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, +0x12,0x12,0x12,0x12,0,0,0,0 }; static const uint32_t ubidi_props_mirrors[40]={ @@ -795,7 +808,7 @@ static const uint32_t ubidi_props_mirrors[40]={ 0x16029b8,0x4029f5,0x1802ade,0x1c02ae3,0x1a02ae4,0x1e02ae5,0xe02aee,0x602bfe }; -static const uint8_t ubidi_props_jgArray[672]={ +static const uint8_t ubidi_props_jgArray[680]={ 0x2d,0,3,3,0x2c,3,0x2d,3,4,0x2a,4,4,0xd,0xd,0xd,6, 6,0x1f,0x1f,0x23,0x23,0x21,0x21,0x28,0x28,1,1,0xb,0xb,0x37,0x37,0x37, 0,9,0x1d,0x13,0x16,0x18,0x1a,0x10,0x2c,0x2d,0x2d,0,0,0,0,0, @@ -837,7 +850,8 @@ static const uint8_t ubidi_props_jgArray[672]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4,4,0xd,0x28,9,0x1d,0x16,0x18,0x2d,0x2d,0x1f,0x2c,0x39,0,6,0x21, -0xb,0x55,0x1f,1,0x13,0,4,4,4,0x1f,0x2d,0x56,0x58,0x57,0,0 +0xb,0x55,0x1f,1,0x13,0,4,4,4,0x1f,0x2d,0x56,0x58,0x57,4,4, +4,0xd,0xb,1,0x58,0xd,0xd,0x16 }; static const uint8_t ubidi_props_jgArray2[612]={ @@ -893,13 +907,13 @@ static const UBiDiProps ubidi_props_singleton={ ubidi_props_trieIndex+3568, NULL, 3568, - 8756, + 8968, 0x1a0, 0xe70, 0x0, 0x0, 0x110000, - 0x3020, + 0x30f4, NULL, 0, FALSE, FALSE, 0, NULL }, { 2,2,0,0 } diff --git a/deps/icu-small/source/common/ubidiwrt.cpp b/deps/icu-small/source/common/ubidiwrt.cpp index aa4d6b544c1787..a69c0a4b8b16f8 100644 --- a/deps/icu-small/source/common/ubidiwrt.cpp +++ b/deps/icu-small/source/common/ubidiwrt.cpp @@ -346,6 +346,13 @@ ubidi_writeReverse(const UChar *src, int32_t srcLength, return u_terminateUChars(dest, destSize, destLength, pErrorCode); } +// Ticket 20907 - The optimizer in MSVC/Visual Studio versions below 16.4 has trouble with this +// function on Windows ARM64. As a work-around, we disable optimizations for this function. +// This work-around could/should be removed once the following versions of Visual Studio are no +// longer supported: All versions of VS2017, and versions of VS2019 below 16.4. +#if (defined(_MSC_VER) && (defined(_M_ARM64)) && (_MSC_VER < 1924)) +#pragma optimize( "", off ) +#endif U_CAPI int32_t U_EXPORT2 ubidi_writeReordered(UBiDi *pBiDi, UChar *dest, int32_t destSize, @@ -638,3 +645,6 @@ ubidi_writeReordered(UBiDi *pBiDi, return u_terminateUChars(saveDest, destCapacity, destCapacity-destSize, pErrorCode); } +#if (defined(_MSC_VER) && (defined(_M_ARM64)) && (_MSC_VER < 1924)) +#pragma optimize( "", on ) +#endif diff --git a/deps/icu-small/source/common/ucase_props_data.h b/deps/icu-small/source/common/ucase_props_data.h index 68554b3130c83f..7c97230957024a 100644 --- a/deps/icu-small/source/common/ucase_props_data.h +++ b/deps/icu-small/source/common/ucase_props_data.h @@ -11,36 +11,36 @@ #ifdef INCLUDED_FROM_UCASE_CPP -static const UVersionInfo ucase_props_dataVersion={0xc,1,0,0}; +static const UVersionInfo ucase_props_dataVersion={0xd,0,0,0}; -static const int32_t ucase_props_indexes[UCASE_IX_TOP]={0x10,0x6fea,0x5fb8,0x687,0x172,0,0,0,0,0,0,0,0,0,0,3}; +static const int32_t ucase_props_indexes[UCASE_IX_TOP]={0x10,0x70ca,0x6098,0x687,0x172,0,0,0,0,0,0,0,0,0,0,3}; -static const uint16_t ucase_props_trieIndex[12244]={ +static const uint16_t ucase_props_trieIndex[12356]={ 0x336,0x33e,0x346,0x34e,0x35c,0x364,0x36c,0x374,0x37c,0x384,0x38b,0x393,0x39b,0x3a3,0x3ab,0x3b3, 0x3b9,0x3c1,0x3c9,0x3d1,0x3d9,0x3e1,0x3e9,0x3f1,0x3f9,0x401,0x409,0x411,0x419,0x421,0x429,0x431, 0x439,0x441,0x449,0x451,0x459,0x461,0x469,0x471,0x46d,0x475,0x47a,0x482,0x489,0x491,0x499,0x4a1, 0x4a9,0x4b1,0x4b9,0x4c1,0x355,0x35d,0x4c6,0x4ce,0x4d3,0x4db,0x4e3,0x4eb,0x4ea,0x4f2,0x4f7,0x4ff, -0x507,0x50e,0x512,0x355,0x355,0x336,0x522,0x51a,0x52a,0x52c,0x534,0x53c,0x540,0x541,0x549,0x551, -0x559,0x541,0x561,0x566,0x559,0x541,0x56e,0x576,0x540,0x57e,0x586,0x58e,0x596,0x355,0x59e,0x355, -0x5a6,0x4ec,0x5ae,0x58e,0x540,0x57e,0x5b5,0x58e,0x5bd,0x5bf,0x549,0x58e,0x355,0x355,0x5c7,0x355, -0x355,0x5cd,0x5d4,0x355,0x355,0x5d8,0x5e0,0x355,0x5e4,0x5eb,0x355,0x5f2,0x5fa,0x601,0x609,0x355, -0x355,0x60e,0x616,0x61e,0x626,0x62e,0x635,0x63d,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x645,0x355,0x355,0x655,0x655,0x64d, +0x507,0x50e,0x512,0x355,0x355,0x355,0x519,0x521,0x529,0x52b,0x533,0x53b,0x53f,0x540,0x548,0x550, +0x558,0x540,0x560,0x565,0x558,0x540,0x56d,0x575,0x53f,0x57d,0x585,0x58d,0x595,0x355,0x59d,0x355, +0x5a5,0x4ec,0x5ad,0x58d,0x53f,0x57d,0x5b4,0x58d,0x5bc,0x5be,0x548,0x58d,0x53f,0x355,0x5c6,0x355, +0x355,0x5cc,0x5d3,0x355,0x355,0x5d7,0x5df,0x355,0x5e3,0x5ea,0x355,0x5f1,0x5f9,0x600,0x608,0x355, +0x355,0x60d,0x615,0x61d,0x625,0x62d,0x634,0x63c,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x644,0x355,0x355,0x654,0x654,0x64c, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x65d,0x65d,0x54d,0x54d,0x355,0x663,0x66b,0x355, -0x673,0x355,0x67b,0x355,0x682,0x688,0x355,0x355,0x355,0x690,0x355,0x355,0x355,0x355,0x355,0x355, -0x697,0x355,0x69e,0x6a6,0x355,0x6ae,0x355,0x355,0x57d,0x6b6,0x6be,0x6c4,0x5bd,0x6cc,0x355,0x6d3, -0x355,0x6d8,0x355,0x6de,0x6e6,0x6ea,0x6f2,0x6fa,0x702,0x707,0x70a,0x712,0x722,0x71a,0x732,0x72a, -0x37c,0x73a,0x37c,0x742,0x745,0x37c,0x74d,0x37c,0x755,0x75d,0x765,0x76d,0x775,0x77d,0x785,0x78d, -0x795,0x79c,0x355,0x7a4,0x7ac,0x355,0x7b4,0x7bc,0x7c4,0x7cc,0x7d4,0x7dc,0x7e4,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x65c,0x65c,0x54c,0x54c,0x355,0x662,0x66a,0x355, +0x672,0x355,0x67a,0x355,0x681,0x687,0x355,0x355,0x355,0x68f,0x355,0x355,0x355,0x355,0x355,0x355, +0x696,0x355,0x69d,0x6a5,0x355,0x6ad,0x6b5,0x355,0x57c,0x6b8,0x6c0,0x6c6,0x5bc,0x6ce,0x355,0x6d5, +0x355,0x6da,0x355,0x6e0,0x6e8,0x6ec,0x6f4,0x6fc,0x704,0x709,0x70c,0x714,0x724,0x71c,0x734,0x72c, +0x37c,0x73c,0x37c,0x744,0x747,0x37c,0x74f,0x37c,0x757,0x75f,0x767,0x76f,0x777,0x77f,0x787,0x78f, +0x797,0x79e,0x355,0x7a6,0x7ae,0x355,0x7b6,0x7be,0x7c6,0x7ce,0x7d6,0x7de,0x7e6,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0x7e7,0x7ed,0x7f3,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0x7e9,0x7ef,0x7f5,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x7fb,0x800,0x804,0x80c,0x37c,0x37c,0x37c,0x814,0x81c,0x823,0x355,0x828,0x355,0x355,0x355,0x830, -0x355,0x678,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x53f,0x838,0x355,0x355,0x83f,0x355,0x355,0x847,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x7fd,0x802,0x806,0x80e,0x37c,0x37c,0x37c,0x816,0x81e,0x825,0x355,0x82a,0x355,0x355,0x355,0x832, +0x355,0x677,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x53e,0x83a,0x355,0x355,0x841,0x355,0x355,0x849,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, @@ -96,12 +96,12 @@ static const uint16_t ucase_props_trieIndex[12244]={ 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x84f,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x851,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x6de,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x855,0x355,0x85d,0x862,0x86a,0x355,0x355,0x872,0x87a,0x882,0x37c,0x887,0x88f,0x895,0x89d,0x89f, -0x8a7,0x682,0x355,0x355,0x355,0x355,0x8ae,0x8b6,0x355,0x8be,0x8c5,0x355,0x52a,0x8ca,0x8d2,0x682, -0x355,0x8d8,0x8e0,0x8e4,0x355,0x8ec,0x8f4,0x8fc,0x355,0x902,0x906,0x90e,0x91e,0x916,0x355,0x926, +0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x6e0,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x857,0x355,0x85f,0x864,0x86c,0x355,0x355,0x874,0x87c,0x884,0x37c,0x889,0x891,0x897,0x89f,0x8a2, +0x8aa,0x8b1,0x355,0x355,0x355,0x355,0x8b8,0x8c0,0x355,0x8c8,0x8cf,0x355,0x529,0x8d4,0x8dc,0x681, +0x355,0x8e2,0x8ea,0x8ee,0x355,0x8f6,0x8fe,0x906,0x355,0x90c,0x910,0x918,0x928,0x920,0x355,0x930, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, @@ -141,9 +141,9 @@ static const uint16_t ucase_props_trieIndex[12244]={ 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x92e,0x355,0x355,0x355,0x355,0x936,0x5bd,0x355, +0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x938,0x355,0x355,0x355,0x355,0x940,0x5bc,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x93b,0x943,0x947,0x355,0x355,0x355,0x355,0x338,0x33e,0x94f,0x957,0x95e,0x4ec,0x355,0x355,0x966, +0x945,0x94d,0x951,0x355,0x355,0x355,0x355,0x338,0x33e,0x959,0x961,0x968,0x4ec,0x355,0x355,0x970, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0xd58,0xd58,0xd70,0xdb0,0xdf0,0xe2c,0xe6c,0xeac,0xee4,0xf24,0xf64,0xfa4,0xfe4,0x1024,0x1064,0x10a4, @@ -175,50 +175,50 @@ static const uint16_t ucase_props_trieIndex[12244]={ 0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188, 0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188, 0xc96,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x96d,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x975,0x355,0x355,0x355,0x978,0x355,0x355,0x355, -0x355,0x980,0x986,0x98a,0x355,0x355,0x98e,0x992,0x998,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x977,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x6b5,0x355,0x355,0x355,0x97f,0x355,0x355,0x355, +0x355,0x987,0x98d,0x991,0x355,0x355,0x995,0x999,0x99f,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x9a0,0x9a4,0x355,0x355,0x355,0x355,0x355,0x9ac,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0x9b4,0x9b8,0x9c0,0x9c4,0x355,0x9cb,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x9d2,0x355,0x355,0x355,0x355, -0x355,0x540,0x9d7,0x9de,0x5be,0x5bd,0x9e2,0x53d,0x355,0x9ea,0x9f1,0x355,0x9f7,0x5bd,0x9fc,0xa04, -0x355,0x355,0xa09,0x355,0x355,0x355,0x355,0x338,0xa11,0x5bd,0x5bf,0xa19,0xa20,0x355,0x355,0x355, -0x355,0x355,0x9d7,0xa28,0x355,0x355,0xa30,0xa38,0x355,0x355,0x355,0x355,0x355,0x355,0xa3c,0xa44, -0x355,0x355,0xa4c,0x4b0,0x355,0x355,0xa54,0x355,0x355,0xa5a,0xa62,0x355,0x355,0x355,0x355,0x355, -0x355,0xa67,0x355,0x355,0x355,0xa6f,0xa77,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0xa7f,0x975, -0xa87,0xa8b,0xa93,0x355,0xa9a,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0xaa1,0x355,0x355,0x936,0xaa9,0x355,0x355,0x355,0xaaf,0xab7,0x355,0xabb,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0x355,0x355,0xac1,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x355,0x9a7,0x9ab,0x355,0x355,0x355,0x355,0x355,0x9b3,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0x9bb,0x9bf,0x9c7,0x9cb,0x355,0x9d2,0x355,0x355,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0x355,0x9d8,0x355,0x355,0x355,0x355,0x9df,0x355,0x355,0x355,0x355, +0x355,0x53f,0x9e4,0x9eb,0x5bd,0x5bc,0x9ef,0x53c,0x355,0x9f7,0x9fe,0x355,0xa04,0x5bc,0xa09,0xa11, +0x355,0x355,0xa16,0x355,0x355,0x355,0x355,0x338,0xa1e,0x5bc,0x5be,0xa26,0xa2d,0x355,0x355,0x355, +0x355,0x355,0x9e4,0xa35,0x355,0x355,0xa3d,0xa45,0x355,0x355,0x355,0x355,0x355,0x355,0xa49,0xa51, +0x355,0x355,0xa59,0x4b0,0x355,0x355,0xa61,0x355,0x355,0xa67,0xa6f,0x355,0x355,0x355,0x355,0x355, +0x355,0xa74,0x355,0x355,0x355,0xa7c,0xa84,0x355,0x355,0xa8c,0xa94,0x355,0x355,0x355,0xa97,0x6b5, +0xa9f,0xaa3,0xaab,0x355,0xab2,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x355,0xab9,0x355,0x355,0x940,0xac1,0x355,0x355,0x355,0xac7,0xacf,0x355,0xad3,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0x355,0x355,0xad9,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0xac7,0x355,0x355,0x355,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0xadf,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0xace,0x355,0xad4,0x57d,0x355,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0xae6,0x355,0xaec,0x57c,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0xa6f,0xa77,0x355,0x355,0x355,0x355,0x355,0x355,0x678,0x355,0xada,0x355,0x355, -0xae2,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x355,0x355,0x355,0xa7c,0xa84,0x355,0x355,0x355,0x355,0x355,0x355,0x677,0x355,0xaf2,0x355,0x355, +0xafa,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0xae3,0x57d,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0xaff,0x57c,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0xaeb,0xaf3,0xaf9,0x355,0x355,0x355,0x355,0xb01,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0x355,0xb09,0xb11,0xb16,0xb1c,0xb24,0xb2c,0xb34,0xb0d,0xb3c,0xb44, -0xb4c,0xb53,0xb0e,0xb09,0xb11,0xb0c,0xb1c,0xb0f,0xb0a,0xb5b,0xb0d,0xb63,0xb6b,0xb73,0xb7a,0xb66, -0xb6e,0xb76,0xb7d,0xb69,0xb85,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0x87a,0xb8d,0x87a,0xb94,0xb9b,0xba3,0x355,0x355,0x355,0x355,0x355, +0x355,0xb07,0xb0f,0xb15,0x355,0x355,0x355,0x355,0xb1d,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0x355,0xb25,0xb2d,0xb32,0xb38,0xb40,0xb48,0xb50,0xb29,0xb58,0xb60, +0xb68,0xb6f,0xb2a,0xb25,0xb2d,0xb28,0xb38,0xb2b,0xb26,0xb77,0xb29,0xb7f,0xb87,0xb8f,0xb96,0xb82, +0xb8a,0xb92,0xb99,0xb85,0xba1,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0x87c,0xba9,0x87c,0xbb0,0xbb7,0xbbf,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0xbab,0xbb3,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0xbb7,0x355, -0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x9c9,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0xbc7,0xbcf,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0xbd3,0x355, +0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x9d0,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0xbbf,0x355,0xbc7,0xbcf,0xbd6,0x355,0x355,0x355,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0xbdb,0x355,0xbe3,0xbeb,0xbf2,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0xb05, -0xbde,0xbde,0xbe4,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0x9ec,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0xb21, +0xbfa,0xbfa,0xc00,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0x9f9,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, -0x355,0x355,0x355,0x355,0x355,0x355,0x540,0x87a,0x87a,0x87a,0x355,0x355,0x355,0x355,0x87a,0x87a, -0x87a,0x87a,0x87a,0x87a,0x87a,0xbec,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, +0x355,0x355,0x355,0x355,0x355,0x355,0x53f,0x87c,0x87c,0x87c,0x355,0x355,0x355,0x355,0x87c,0x87c, +0x87c,0x87c,0x87c,0x87c,0x87c,0xc08,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355,0x355, 0x355,0x355,0x355,0x355,0x355,0x355,0x335,0x335,0,0,0,0,0,0,0,0, @@ -304,7 +304,7 @@ static const uint16_t ucase_props_trieIndex[12244]={ 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812, 0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0, -0,4,0,0,0,0,0,0,1,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811, +0,4,0,0,0,0,0,4,1,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811, 0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811, 0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0x1719,1,0,0,0, 0,0,0,0,0,0x64,0x44,0x44,0x44,0x44,0x64,0x44,0x44,0x44,0x64,0x64, @@ -342,352 +342,358 @@ static const uint16_t ucase_props_trieIndex[12244]={ 0,0,0x44,0x44,0x44,0x44,4,0x44,0x44,0x44,0x44,0x44,4,0x44,0x44,0x44, 4,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0x64,0x64,0x64,0,0,0,0,0x44,0x44,4,0x64,0x44,0x44,0x64,0x44, -0x44,0x64,0x44,0x44,0x44,0x64,0x64,0x64,0x64,0x64,0x64,0x44,0x44,0x44,0x64,0x44, -0x44,0x64,0x64,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0x64,0x44,0x44,0x44,0x44, -0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,4,4,4,0,0,0,0,0, +0,0x64,0x64,0x64,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x64,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, +0x44,0x44,0x44,0x44,0x44,0x44,4,0x64,0x44,0x44,0x64,0x44,0x44,0x64,0x44,0x44, +0x44,0x64,0x64,0x64,0x64,0x64,0x64,0x44,0x44,0x44,0x64,0x44,0x44,0x64,0x64,0x44, +0x44,0x44,0x44,0x44,4,4,4,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,4,0,0x64,0,0,0,0,4,4,4, +4,4,4,4,4,0,0,0,0,0x64,0,0,0,0x44,0x64,0x44, +0x44,4,4,4,0,0,0,0,0,0,0,0,0,0,4,4, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x64,0,0,0, +0,4,4,4,4,0,0,0,0,0,0,0,0,0x64,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,4,0,0x64,0,0,0, -0,4,4,4,4,4,4,4,4,0,0,0,0,0x64,0,0, -0,0x44,0x64,0x44,0x44,4,4,4,0,0,0,0,0,0,0,0, 0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0, -0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x44,0, +0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x64,0,0,0,0,4,4,4,4,0,0,0,0,0,0,0, +0,4,4,0,0,0,0,4,4,0,0,4,4,0x64,0,0, +0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,4,4,0,0,0,4,0,0,0,0,0,0, +0,0,0,0,0,4,4,4,4,4,0,4,4,0,0,0, 0,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4, +4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0x44,0,0,4,4,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,4,4,0,0,0,0,4,4,0,0,4, -4,0x64,0,0,0,4,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,4,0,0,0,4,0,0, -0,0,0,0,0,0,0,0,0,4,4,4,4,4,0,4, -4,0,0,0,0,0x64,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x64,0,0,4,0,4,4,4,4,0,0,0, -0,0,0,0,0,0x64,0,0,0,0,0,0,0,0,4,0, -0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0, +0x64,0,0,4,0,4,4,4,4,0,0,0,0,0,0,0, +0,0x64,0,0,0,0,0,0,0,4,4,0,0,0,0,0, +0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0, +0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, -0,0,0,0,0,0x64,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0, +0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0, +0,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,0,0,0,0,0,4,4, -4,0,4,4,4,0x64,0,0,0,0,0,0,0,0x64,0x64,0, -0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0, -4,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,4,0,0,0,0,0,4,4,4,0,4,4, +4,0x64,0,0,0,0,0,0,0,0x64,0x64,0,0,0,0,0, +0,0,0,0,0,0,4,0,0,0,0,0,4,0x64,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0x64,0x64,0,0,0,0,0,0,0, -0,0,0,0,0,0,0x64,0,0,0,0,0,0,0,4,4, -4,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,4,0,0,4,4,4,4,0x64,0x64,0x64,0, -0,0,0,0,0,0,4,4,0x64,0x64,0x64,0x64,4,4,4,0, +4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,4,0,0,4,4,4,4,0x64,0x64,0x64,4,4,0,0,0, -0,0,0,0,0,0,4,0,0x64,0x64,0x64,0x64,4,4,0,0, +0,0,0,0x64,0x64,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x64,0,0,0,0,0,0,0,4,4,4,0,4,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x64,0x64,0,0,0,0,0,0, +0,4,0,0,4,4,4,4,0x64,0x64,0x64,0,0,0,0,0, +0,0,4,4,0x64,0x64,0x64,0x64,4,4,4,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, +4,4,4,4,0x64,0x64,0x64,4,4,0,0,0,0,0,0,0, +0,0,4,0,0x64,0x64,0x64,0x64,4,4,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0x64,0,0x64,0,0x64,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0x64,0x64,4,0x64,4,4,4, -4,4,0x64,0x64,0x64,0x64,4,0,0x64,4,0x44,0x44,0x64,0,0x44,0x44, -0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4, -0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +0,0,0,0,0x64,0x64,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x64,0,0x64, +0,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0x64,0x64,4,0x64,4,4,4,4,4,0x64,0x64, +0x64,0x64,4,0,0x64,4,0x44,0x44,0x64,0,0x44,0x44,0,0,0,0, +0,4,4,4,4,4,4,4,4,4,4,4,0,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, -4,0,0,0,0,0,0,0,0,0,0x64,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,4,4,4,4,0,4,4,4,4,4,0x64, -0,0x64,0x64,0,0,4,4,0,0,0,0,0,0,0,0,0, +4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0, +0,0,0,0,0,0,0x64,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,4,0,0,0,0,4,4,4,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,4,4,4,4,0,0,0, -0,0,0,0,0,0,0,0,0,0,4,0,0,4,4,0, -0,0,0,0,0,0x64,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,4,0,0,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a, +0,4,4,4,4,0,4,4,4,4,4,0x64,0,0x64,0x64,0, +0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0, +0,0,4,4,4,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,4,4,4,4,0,0,0,0,0,0,0, +0,0,0,0,0,0,4,0,0,4,4,0,0,0,0,0, +0,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,4,0,0,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a, 0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a, -0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0,0x179a,0,0,0,0, -0,0x179a,0,0,0x17b9,0x17e9,0x1819,0x1849,0x1879,0x18a9,0x18d9,0x1909,0x1939,0x1969,0x1999,0x19c9, -0x19f9,0x1a29,0x1a59,0x1a89,0x1ab9,0x1ae9,0x1b19,0x1b49,0x1b79,0x1ba9,0x1bd9,0x1c09,0x1c39,0x1c69,0x1c99,0x1cc9, -0x1cf9,0x1d29,0x1d59,0x1d89,0x1db9,0x1de9,0x1e19,0x1e49,0x1e79,0x1ea9,0x1ed9,0x1f09,0x1f39,0x1f69,0x1f99,0, -4,0x1fc9,0x1ff9,0x2029,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0x44,0x44,0x44,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a, -0x205a,0x205a,0x205a,0x205a,0x207a,0x207a,0x207a,0x207a,0x207a,0x207a,0,0,0x2099,0x20c9,0x20f9,0x2129, -0x2159,0x2189,0,0,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a, -0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a, -0x205a,0x205a,0x205a,0x205a,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,4,4,0x64,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,4,0,4,4,4,4,4,4,4,0,0,0,0,0,0, -0,0,4,0,0,4,4,4,4,4,4,4,4,4,0x64,4, -0,0,0,4,0,0,0,0,0,0x44,0,0,0,0,0,0, -0,0,0,0,0,0,0,4,4,4,4,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0x64,0,0,0,0,0,0, +0x179a,0x179a,0x179a,0x179a,0x179a,0x179a,0,0x179a,0,0,0,0,0,0x179a,0,0, +0x17b9,0x17e9,0x1819,0x1849,0x1879,0x18a9,0x18d9,0x1909,0x1939,0x1969,0x1999,0x19c9,0x19f9,0x1a29,0x1a59,0x1a89, +0x1ab9,0x1ae9,0x1b19,0x1b49,0x1b79,0x1ba9,0x1bd9,0x1c09,0x1c39,0x1c69,0x1c99,0x1cc9,0x1cf9,0x1d29,0x1d59,0x1d89, +0x1db9,0x1de9,0x1e19,0x1e49,0x1e79,0x1ea9,0x1ed9,0x1f09,0x1f39,0x1f69,0x1f99,0,4,0x1fc9,0x1ff9,0x2029, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,4,4,0,0,0,0,4,4,0,0,0,0,0,0,0, -0,0,4,0,0,0,0,0,0,0x64,0x44,0x64,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0x44,0x64,0,0,4,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0, -4,4,4,4,4,4,4,0,0x64,0,4,0,0,4,4,4, -4,4,4,4,4,0,0,0,0,0,0,4,4,0x44,0x44,0x44, -0x44,0x44,0x44,0x44,0x44,0,0,0x64,0,0,0,0,0,0,0,4, -0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x64,0x64,0x64, -0x64,0x64,0x64,0x44,0x44,0x64,4,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x64,0,4,4, -4,4,4,0,4,0,0,0,0,0,4,0,0x60,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x44,0x44,0x44, +0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a, +0x207a,0x207a,0x207a,0x207a,0x207a,0x207a,0,0,0x2099,0x20c9,0x20f9,0x2129,0x2159,0x2189,0,0, +0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a, +0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a,0x205a, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0x44,0x64,0x44,0x44,0x44, -0x44,0x44,0x44,0x44,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,4,4,4,4,0,0,4,4,0x60,0x64,4,4,0,0, +0,0,4,4,0x64,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,4, +4,4,4,4,4,4,0,0,0,0,0,0,0,0,4,0, +0,4,4,4,4,4,4,4,4,4,0x64,4,0,0,0,4, +0,0,0,0,0,0x44,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0x64,0,4,4,0,0,0,4,0,4,4,4,0x60,0x60, -0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4, -4,4,4,4,0,0,4,0x64,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,4,4,4,4,4,0,0,0x21b9,0x21e9,0x2219,0x2249,0x2279,0x22c9,0x2319,0x2349, -0x2379,0,0,0,0,0,0,0,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa, +0,0,0,0,0,0x64,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,0, +0,0,0,4,4,0,0,0,0,0,0,0,0,0,4,0, +0,0,0,0,0,0x64,0x44,0x64,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x44, +0x64,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,4,0,4,4,4,4, +4,4,4,0,0x64,0,4,0,0,4,4,4,4,4,4,4, +4,0,0,0,0,0,0,4,4,0x44,0x44,0x44,0x44,0x44,0x44,0x44, +0x44,0,0,0x64,0,0,0,0,0,0,0,4,0,0,0,0, +0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x64,0x64,0x64,0x64,0x64,0x64,0x44, +0x44,0x64,4,0x64,0x64,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x64,0,4,4,4,4,4,0,4,0,0,0, +0,0,4,0,0x60,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0x44,0x64,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,4,4,4,4,0,0, +4,4,0x60,0x64,4,4,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x64,0,4,4,0,0, +0,4,0,4,4,4,0x60,0x60,0,0,0,0,0,0,0,0, +0,0,0,0,4,4,4,4,4,4,4,4,0,0,4,0x64, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,4,4,4,4,4,0,0, +0x21b9,0x21e9,0x2219,0x2249,0x2279,0x22c9,0x2319,0x2349,0x2379,0,0,0,0,0,0,0, 0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa, -0x23aa,0x23aa,0x23aa,0,0,0x23aa,0x23aa,0x23aa,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x44,0x44,0x44,0,0x64,0x64,0x64,0x64, -0x64,0x64,0x44,0x44,0x64,0x64,0x64,0x64,0x44,0,0x64,0x64,0x64,0x64,0x64,0x64, -0x64,0,0,0,0,0x64,0,0,0,0,0,0,0x44,0,0,0, -0x44,0x44,0,0,0,0,0,0,1,1,1,1,1,1,1,1, +0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0x23aa,0,0,0x23aa,0x23aa,0x23aa, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x44,0x44,0x44,0,0x64,0x64,0x64,0x64,0x64,0x64,0x44,0x44,0x64,0x64,0x64,0x64, +0x44,0,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0,0,0,0,0x64,0,0, +0,0,0,0,0x44,0,0,0,0x44,0x44,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,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,0x25,5,5,5,5,5, -5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1, -5,0x23c9,1,1,1,0x23e9,1,1,5,5,5,5,0x25,5,5,5, -0x25,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0x2409,1,1,1,1,1,1,1,0x21,1, -1,1,1,5,5,5,5,5,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, -0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x64,0x64, -0x64,0x64,0,0x44,0x64,0x64,0x44,0x64,0x44,0x44,0x64,0x44,0x44,0x44,0x44,0x44, -0x44,0x44,0x64,0x44,0x44,0x64,0x64,0x64,0x64,0x44,0x44,0x44,0x44,0x44,0x44,0x44, -0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xffb1,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x242a,0x2469,0x92,0xff91,0x92,0xff91,0x92,0xff91, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,0x25,5,5,5,5,5,5,5,5,1,1,1,1,1, +1,1,1,1,1,1,1,1,5,0x23c9,1,1,1,0x23e9,1,1, +5,5,5,5,0x25,5,5,5,0x25,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x2409,1, +1,1,1,1,1,1,0x21,1,1,1,1,5,5,5,5,5, +0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, +0x44,0x44,0x44,0x44,0x44,0x44,0x64,0x64,0x64,0x64,0,0x44,0x64,0x64,0x44,0x64, +0x44,0x44,0x64,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x64,0x44,0x44,0x64,0x64,0x64, +0x64,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xffb1,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x24a9,0x2529,0x25a9,0x2629,0x26a9,0x2729, -1,1,0x275a,1,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xffb1, +0x242a,0x2469,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12, -0xfc12,0xfc12,0xfc12,0xfc12,0x411,0x411,0x411,0x411,0x411,0x411,0,0,0xfc12,0xfc12,0xfc12,0xfc12, -0xfc12,0xfc12,0,0,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12, -0xfc12,0xfc12,0xfc12,0xfc12,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12, -0xfc12,0xfc12,0xfc12,0xfc12,0x411,0x411,0x411,0x411,0x411,0x411,0,0,0xfc12,0xfc12,0xfc12,0xfc12, -0xfc12,0xfc12,0,0,0x27a9,0x411,0x2829,0x411,0x28d9,0x411,0x2989,0x411,0,0xfc12,0,0xfc12, -0,0xfc12,0,0xfc12,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12, -0xfc12,0xfc12,0xfc12,0xfc12,0x2511,0x2511,0x2b11,0x2b11,0x2b11,0x2b11,0x3211,0x3211,0x4011,0x4011,0x3811,0x3811, -0x3f11,0x3f11,0,0,0x2a39,0x2aa9,0x2b19,0x2b89,0x2bf9,0x2c69,0x2cd9,0x2d49,0x2dbb,0x2e2b,0x2e9b,0x2f0b, -0x2f7b,0x2feb,0x305b,0x30cb,0x3139,0x31a9,0x3219,0x3289,0x32f9,0x3369,0x33d9,0x3449,0x34bb,0x352b,0x359b,0x360b, -0x367b,0x36eb,0x375b,0x37cb,0x3839,0x38a9,0x3919,0x3989,0x39f9,0x3a69,0x3ad9,0x3b49,0x3bbb,0x3c2b,0x3c9b,0x3d0b, -0x3d7b,0x3deb,0x3e5b,0x3ecb,0x411,0x411,0x3f39,0x3fb9,0x4029,0,0x40a9,0x4129,0xfc12,0xfc12,0xdb12,0xdb12, -0x41db,4,0x4249,4,4,4,0x4299,0x4319,0x4389,0,0x4409,0x4489,0xd512,0xd512,0xd512,0xd512, -0x453b,4,4,4,0x411,0x411,0x45a9,0x4659,0,0,0x4729,0x47a9,0xfc12,0xfc12,0xce12,0xce12, -0,4,4,4,0x411,0x411,0x4859,0x4909,0x49d9,0x391,0x4a59,0x4ad9,0xfc12,0xfc12,0xc812,0xc812, -0xfc92,4,4,4,0,0,0x4b89,0x4c09,0x4c79,0,0x4cf9,0x4d79,0xc012,0xc012,0xc112,0xc112, -0x4e2b,4,4,0,0,0,0,0,0,0,0,0,0,0,0,4, -4,4,4,4,0,0,0,0,0,0,0,0,4,4,0,0, -0,0,0,0,4,0,0,4,0,0,4,4,4,4,4,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,4,4,4,4,0,4,4,4,4,4,4,4,4,4,4, -0,0x25,0,0,0,0,0,0,0,0,0,0,0,0,0,5, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x44,0x44,0x64,0x64,0x44,0x44,0x44,0x44,0x64,0x64,0x64,0x44,0x44,4,4,4, -4,0x44,4,4,4,0x64,0x64,0x44,0x64,0x44,0x64,0x64,0x64,0x64,0x64,0x64, -0x44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,2,0,0,0,0,2,0,0,1,2,2,2,1,1, -2,2,2,1,0,2,0,0,0,2,2,2,2,2,0,0, -0,0,0,0,2,0,0x4e9a,0,2,0,0x4eda,0x4f1a,2,2,0,1, -2,2,0xe12,2,1,0,0,0,0,1,0,0,1,1,2,2, -0,0,0,0,0,2,1,1,0x21,0x21,0,0,0,0,0xf211,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812, -0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811, -0,0,0,0x92,0xff91,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12, -0xd12,0xd12,0xd12,0xd12,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311, -0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x1812,0x1812,0x1812,0x1812, +0x92,0xff91,0x24a9,0x2529,0x25a9,0x2629,0x26a9,0x2729,1,1,0x275a,1,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xffb1,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x411,0x411,0x411,0x411, +0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0x411,0x411,0x411,0x411, +0x411,0x411,0,0,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0,0,0x411,0x411,0x411,0x411, +0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0x411,0x411,0x411,0x411, +0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0x411,0x411,0x411,0x411, +0x411,0x411,0,0,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0,0,0x27a9,0x411,0x2829,0x411, +0x28d9,0x411,0x2989,0x411,0,0xfc12,0,0xfc12,0,0xfc12,0,0xfc12,0x411,0x411,0x411,0x411, +0x411,0x411,0x411,0x411,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0xfc12,0x2511,0x2511,0x2b11,0x2b11, +0x2b11,0x2b11,0x3211,0x3211,0x4011,0x4011,0x3811,0x3811,0x3f11,0x3f11,0,0,0x2a39,0x2aa9,0x2b19,0x2b89, +0x2bf9,0x2c69,0x2cd9,0x2d49,0x2dbb,0x2e2b,0x2e9b,0x2f0b,0x2f7b,0x2feb,0x305b,0x30cb,0x3139,0x31a9,0x3219,0x3289, +0x32f9,0x3369,0x33d9,0x3449,0x34bb,0x352b,0x359b,0x360b,0x367b,0x36eb,0x375b,0x37cb,0x3839,0x38a9,0x3919,0x3989, +0x39f9,0x3a69,0x3ad9,0x3b49,0x3bbb,0x3c2b,0x3c9b,0x3d0b,0x3d7b,0x3deb,0x3e5b,0x3ecb,0x411,0x411,0x3f39,0x3fb9, +0x4029,0,0x40a9,0x4129,0xfc12,0xfc12,0xdb12,0xdb12,0x41db,4,0x4249,4,4,4,0x4299,0x4319, +0x4389,0,0x4409,0x4489,0xd512,0xd512,0xd512,0xd512,0x453b,4,4,4,0x411,0x411,0x45a9,0x4659, +0,0,0x4729,0x47a9,0xfc12,0xfc12,0xce12,0xce12,0,4,4,4,0x411,0x411,0x4859,0x4909, +0x49d9,0x391,0x4a59,0x4ad9,0xfc12,0xfc12,0xc812,0xc812,0xfc92,4,4,4,0,0,0x4b89,0x4c09, +0x4c79,0,0x4cf9,0x4d79,0xc012,0xc012,0xc112,0xc112,0x4e2b,4,4,0,0,0,0,0, +0,0,0,0,0,0,0,4,4,4,4,4,0,0,0,0, +0,0,0,0,4,4,0,0,0,0,0,0,4,0,0,4, +0,0,4,4,4,4,4,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,4,4,4,4,0,4,4, +4,4,4,4,4,4,4,4,0,0x25,0,0,0,0,0,0, +0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, +5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x44,0x44,0x64,0x64,0x44,0x44,0x44,0x44, +0x64,0x64,0x64,0x44,0x44,4,4,4,4,0x44,4,4,4,0x64,0x64,0x44, +0x64,0x44,0x64,0x64,0x64,0x64,0x64,0x64,0x44,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,2, +0,0,1,2,2,2,1,1,2,2,2,1,0,2,0,0, +0,2,2,2,2,2,0,0,0,0,0,0,2,0,0x4e9a,0, +2,0,0x4eda,0x4f1a,2,2,0,1,2,2,0xe12,2,1,0,0,0, +0,1,0,0,1,1,2,2,0,0,0,0,0,2,1,1, +0x21,0x21,0,0,0,0,0xf211,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812, +0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811, +0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0xf811,0,0,0,0x92,0xff91,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12, +0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xd12,0xf311,0xf311,0xf311,0xf311, +0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0xf311,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812, 0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812, -0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0, +0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811, 0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811, -0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0, -0x92,0xff91,0x4f5a,0x4f7a,0x4f9a,0x4fb9,0x4fd9,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x4ffa,0x501a,0x503a, -0x505a,1,0x92,0xff91,1,0x92,0xff91,1,1,1,1,1,0x25,5,0x507a,0x507a, -0x92,0xff91,0x92,0xff91,1,0,0,0,0,0,0,0x92,0xff91,0x92,0xff91,0x44, -0x44,0x44,0x92,0xff91,0,0,0,0,0,0,0,0,0,0,0,0, -0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099, +0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0,0x92,0xff91,0x4f5a,0x4f7a,0x4f9a,0x4fb9,0x4fd9,0x92, +0xff91,0x92,0xff91,0x92,0xff91,0x4ffa,0x501a,0x503a,0x505a,1,0x92,0xff91,1,0x92,0xff91,1, +1,1,1,1,0x25,5,0x507a,0x507a,0x92,0xff91,0x92,0xff91,1,0,0,0, +0,0,0,0x92,0xff91,0x92,0xff91,0x44,0x44,0x44,0x92,0xff91,0,0,0,0, +0,0,0,0,0,0,0,0,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099, 0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099, -0x5099,0x5099,0,0x5099,0,0,0,0,0,0x5099,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x64, -0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, +0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0x5099,0,0x5099,0,0,0,0, +0,0x5099,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x64,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, -0,0,0,0,0,0,0,0,0,0,0x64,0x64,0x64,0x64,0x60,0x60, -0,4,4,4,4,4,0,0,0,0,0,4,0,0,0,0, +0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0,0,0,0, +0,0,0x64,0x64,0x64,0x64,0x60,0x60,0,4,4,4,4,4,0,0, +0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x64,0x64,4, +4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x50ba,0x50f9,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0,0x44, +4,4,4,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,4, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,5,5,0x44,0x44, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0x64,0x64,4,4,4,4,0,0,0,0,0, +0x44,0x44,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +1,1,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,5,1,1,1,1,1,1,1,1,0x92,0xff91,0x92, +0xff91,0x513a,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,4,4,4,0x92, +0xff91,0x515a,1,0,0x92,0xff91,0x92,0xff91,0x1811,1,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x517a,0x519a,0x51ba,0x51da,0x517a,1,0x51fa,0x521a,0x523a,0x525a, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0,0,0x92,0xff91, +0xe812,0x527a,0x529a,0x92,0xff91,0x92,0xff91,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x92,0xff91,0, +5,5,1,0,0,0,0,0,0,0,4,0,0,0,0x64,0, +0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0, +0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x64,4,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,4,4,0,0,0,0,0, +0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, +0x44,0x44,0,0,0,0,0,0,0,0,0,0,0,0,0,4, +0,0,0,0,0,0,4,4,4,4,4,0x64,0x64,0x64,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x50ba,0x50f9, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0,0x44,4,4,4,0,0x44,0x44,0x44,0x44, -0x44,0x44,0x44,0x44,0x44,0x44,0,4,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,5,5,0x44,0x44,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x44,0x44,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,1,1,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,5,1,1,1, -1,1,1,1,1,0x92,0xff91,0x92,0xff91,0x513a,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,4,4,4,0x92,0xff91,0x515a,1,0,0x92,0xff91,0x92,0xff91, -0x1811,1,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x517a,0x519a, -0x51ba,0x51da,0x517a,1,0x51fa,0x521a,0x523a,0x525a,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0,0,0x92,0xff91,0xe812,0x527a,0x529a,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,5,5,1,0,0,0,0,0,0,0,4,0, -0,0,0x64,0,0,0,0,4,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x64,4,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, -0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0,0, -0,0,0,0,0,0,0,4,0,0,0,0,0,0,4,4, -4,4,4,0x64,0x64,0x64,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4, -4,4,4,4,4,4,0,0x60,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0x64,0,0,4,4, -4,4,0,0,4,4,0,0,0x60,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,0, -0,4,4,0,0,4,4,0,0,0,0,0,0,0,0,0, -0,0,0,4,0,0,0,0,0,0,0,0,4,0,0,0, +0,0,0,4,4,4,4,4,4,4,4,4,4,4,0,0x60, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0, +0,0,0,0x64,0,0,4,4,4,4,0,0,4,4,0,0, +0x60,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x44,0,0x44,0x44,0x64,0,0,0x44,0x44,0,0,0,0,0,0x44,0x44, -0,0x44,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0, -0,0,0,4,4,0,0x64,0,0,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,0x52b9,1,1,1,1, -1,1,1,4,5,5,5,5,1,1,1,1,1,1,1,1, -0,0,0,0,0,0,0,0,0x52d9,0x5309,0x5339,0x5369,0x5399,0x53c9,0x53f9,0x5429, -0x5459,0x5489,0x54b9,0x54e9,0x5519,0x5549,0x5579,0x55a9,0x5bd9,0x5c09,0x5c39,0x5c69,0x5c99,0x5cc9,0x5cf9,0x5d29, -0x5d59,0x5d89,0x5db9,0x5de9,0x5e19,0x5e49,0x5e79,0x5ea9,0x5ed9,0x5f09,0x5f39,0x5f69,0x5f99,0x5fc9,0x5ff9,0x6029, -0x6059,0x6089,0x60b9,0x60e9,0x6119,0x6149,0x6179,0x61a9,0x55d9,0x5609,0x5639,0x5669,0x5699,0x56c9,0x56f9,0x5729, -0x5759,0x5789,0x57b9,0x57e9,0x5819,0x5849,0x5879,0x58a9,0x58d9,0x5909,0x5939,0x5969,0x5999,0x59c9,0x59f9,0x5a29, -0x5a59,0x5a89,0x5ab9,0x5ae9,0x5b19,0x5b49,0x5b79,0x5ba9,0,0,0,0,0,4,0,0, -4,0,0,0,0,0x64,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x61d9,0x6259,0x62d9,0x6359,0x6409,0x64b9,0x6559,0, -0,0,0,0,0,0,0,0,0,0,0,0x65f9,0x6679,0x66f9,0x6779,0x67f9, -0,0,0,0,0,0,0x64,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,4, -0,0,0,0,0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44, -0x44,0x44,0x44,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x44,0x44,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0, -0,4,0,0,0,0,0,0,0,0,0,0,0,0x1012,0x1012,0x1012, -0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012, -0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0,0,0,4,0,4,0xf011,0xf011,0xf011, -0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011, -0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, +0,4,4,4,4,4,4,0,0,4,4,0,0,4,4,0, 0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0, +0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, +0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x44,0,0x44,0x44,0x64,0,0,0x44, +0x44,0,0,0,0,0,0x44,0x44,0,0x44,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,4,4,0,0,0,0,0,4,4,0,0x64,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0x64,0,0,0x64,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,0x52b9,1,1,1,1,1,1,1,4,5,5,5,5, +1,1,1,1,1,1,1,1,1,4,4,4,0,0,0,0, +0x52d9,0x5309,0x5339,0x5369,0x5399,0x53c9,0x53f9,0x5429,0x5459,0x5489,0x54b9,0x54e9,0x5519,0x5549,0x5579,0x55a9, +0x5bd9,0x5c09,0x5c39,0x5c69,0x5c99,0x5cc9,0x5cf9,0x5d29,0x5d59,0x5d89,0x5db9,0x5de9,0x5e19,0x5e49,0x5e79,0x5ea9, +0x5ed9,0x5f09,0x5f39,0x5f69,0x5f99,0x5fc9,0x5ff9,0x6029,0x6059,0x6089,0x60b9,0x60e9,0x6119,0x6149,0x6179,0x61a9, +0x55d9,0x5609,0x5639,0x5669,0x5699,0x56c9,0x56f9,0x5729,0x5759,0x5789,0x57b9,0x57e9,0x5819,0x5849,0x5879,0x58a9, +0x58d9,0x5909,0x5939,0x5969,0x5999,0x59c9,0x59f9,0x5a29,0x5a59,0x5a89,0x5ab9,0x5ae9,0x5b19,0x5b49,0x5b79,0x5ba9, +0,0,0,0,0,4,0,0,4,0,0,0,0,0x64,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x61d9,0x6259,0x62d9,0x6359,0x6409,0x64b9,0x6559,0,0,0,0,0,0,0,0,0, +0,0,0,0x65f9,0x6679,0x66f9,0x6779,0x67f9,0,0,0,0,0,0,0x64,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,0,0,0,4,0,0,0,0,0,0,0,0, +0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x44,0x44,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,4,0,0,4,0,0,0,0,0,0, +0,0,0,0,0,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012, +0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0, +0,0,4,0,4,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011, +0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0, -0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412, +4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,4,4,4,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x64,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0,0x1412,0x1412,0x1412,0x1412, 0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412, +0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0xec11,0xec11,0xec11,0xec11, 0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11, -0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412, -0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0,0,0,0, +0xec11,0xec11,0xec11,0xec11,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412, +0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0x1412,0,0,0,0,0xec11,0xec11,0xec11,0xec11, 0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11, -0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0,0,0,0, -0,4,4,4,0,4,4,0,0,0,0,0,4,0x64,4,0x44, +0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0xec11,0,0,0,0,0,4,4,4, +0,4,4,0,0,0,0,0,4,0x64,4,0x44,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x44,0x64,0x64,0,0,0,0,0x64, -0,0,0,0,0,0x44,0x64,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012, +0,0,0,0,0x44,0x64,0x64,0,0,0,0,0x64,0,0,0,0, +0,0x44,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x2012,0x2012,0x2012,0x2012, 0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012, -0x2012,0x2012,0x2012,0,0,0,0,0,0,0,0,0,0,0,0,0, -0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011, +0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0x2012,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xe011,0xe011,0xe011,0xe011, 0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011, -0xe011,0xe011,0xe011,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x44,0x44,0x44,0x44,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x64,0x64, -0x44,0x44,0x44,0x64,0x44,0x64,0x64,0x64,0x64,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,4,4,4,4,4,4,4,4,4,4,0x64,0, +0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0xe011,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,0, -0,0x64,0x64,0,0,4,0,0,0x44,0x44,0x44,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x44,0x44,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4, -0,4,4,4,4,4,4,0x64,0x64,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x64, +0,0,0x64,0x64,0x44,0x44,0x44,0x64,0x44,0x64,0x64,0x64,0x64,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,0, -0x60,0,0,0,0,0,0,0,0,4,0x64,4,4,0,0,0, +0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4, +4,4,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, +4,4,4,0,0,0x64,0x64,0,0,4,0,0,0x44,0x44,0x44,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,4,4,4,0,0,4,0x60,0x64,4,0,0,0,0, -0,0,4,0,0,0,0,4,4,4,4,4,4,0x64,0x64,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, +4,4,4,4,0,4,4,4,4,4,4,0x64,0x64,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0, -0,0x60,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,0,0, -0x44,0x44,0x44,0x44,0x44,0,0,0,0,0,0,0,0,0,0,0, -0,0,0x64,4,4,0,0x64,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x44,0, +0,0,0,0x64,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4, +4,4,4,0,0x60,0,0,0,0,0,0,0,0,4,0x64,4, +4,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,4,4,0,0,4,0x60,0x64,4, +0,0,0,0,0,0,4,0,0,0,0,4,4,4,4,4, +4,0x64,0x64,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, +0,0,0,0,0,0x60,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x44,0x44,0x44,0x44,0x44,0x44, +0x44,0,0,0,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0,0,0, +0,0,0,0,0,0,0x64,4,4,0,0x64,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,4,4,4,4,4,4,0,4,0,0,0,0,4, -4,0,0x64,0x64,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x44,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,4,4,4,4,4,0,4,0, +0,0,0,4,4,0,0x64,0x64,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,4,4,4,4,0,0,0,0,0,0,4,4,0,0x64, -0x64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0, +0,0,0,0,0,0,4,4,4,4,0,0,0,0,0,0, +4,4,0,0x64,0x64,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,4,4,4,4,4,4,4,4,0,0,4,0,0x64, -0,0,0,0,0,0,0,0,0,0,0,4,0,4,0,0, -4,4,4,4,4,4,0x60,0x64,0,0,0,0,0,0,0,0, +4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,0, +0,4,0,0x64,0,0,0,0,0,0,0,0,0,0,0,4, +0,4,0,0,4,4,4,4,4,4,0x60,0x64,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,4,4,4,0,0,4,4,4,4,0,4, -4,4,4,0x64,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4, -4,4,4,4,0,0x64,0x64,0,0,0,0,0,0x1012,0x1012,0x1012,0x1012, +0,0,0,0,0,0,0,0,0,4,4,4,0,0,4,4, +4,4,0,4,4,4,4,0x64,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, +4,4,4,4,4,4,4,4,0,0x64,0x64,0,0,0,0,0, 0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012, -0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0xf011,0xf011,0xf011,0xf011, +0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012,0x1012, +0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011, 0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011, -0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0xf011,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,4,4,0x60,0x64,0, +0,0,0,0x64,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4,4,4,4,0,0,4,4,0,0,0,0,0,4,4,4, 4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0, @@ -712,7 +718,8 @@ static const uint16_t ucase_props_trieIndex[12244]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,0,4,0,0,0,0, +4,4,4,4,4,4,4,4,4,4,0,4,4,0,0,0, +0,0,0,0,0,0,0,0,0x60,0x60,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,4,0x64,0,0,0,0,0, 0,0x60,0x60,0x64,0x64,0x64,0,0,0,0x60,0x60,0x60,0x60,0x60,0x60,4, @@ -929,13 +936,13 @@ static const UCaseProps ucase_props_singleton={ ucase_props_trieIndex+3288, NULL, 3288, - 8956, + 9068, 0x188, 0xd54, 0x0, 0x0, 0xe0800, - 0x2fd0, + 0x3040, NULL, 0, FALSE, FALSE, 0, NULL }, { 4,0,0,0 } diff --git a/deps/icu-small/source/common/ucasemap.cpp b/deps/icu-small/source/common/ucasemap.cpp index 99e30c9fc6987e..ed72bda828fc1c 100644 --- a/deps/icu-small/source/common/ucasemap.cpp +++ b/deps/icu-small/source/common/ucasemap.cpp @@ -687,13 +687,13 @@ void toUpper(uint32_t options, if (change) { ByteSinkUtil::appendTwoBytes(upper, sink); if ((data & HAS_EITHER_DIALYTIKA) != 0) { - sink.Append(u8"\u0308", 2); // restore or add a dialytika + sink.AppendU8(u8"\u0308", 2); // restore or add a dialytika } if (addTonos) { - sink.Append(u8"\u0301", 2); + sink.AppendU8(u8"\u0301", 2); } while (numYpogegrammeni > 0) { - sink.Append(u8"\u0399", 2); + sink.AppendU8(u8"\u0399", 2); --numYpogegrammeni; } } diff --git a/deps/icu-small/source/common/uchar.cpp b/deps/icu-small/source/common/uchar.cpp index 12365fd6976e5b..f02ae530ccf6d8 100644 --- a/deps/icu-small/source/common/uchar.cpp +++ b/deps/icu-small/source/common/uchar.cpp @@ -556,7 +556,6 @@ u_charAge(UChar32 c, UVersionInfo versionArray) { U_CAPI UScriptCode U_EXPORT2 uscript_getScript(UChar32 c, UErrorCode *pErrorCode) { - uint32_t scriptX; if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { return USCRIPT_INVALID_CODE; } @@ -564,48 +563,46 @@ uscript_getScript(UChar32 c, UErrorCode *pErrorCode) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return USCRIPT_INVALID_CODE; } - scriptX=u_getUnicodeProperties(c, 0)&UPROPS_SCRIPT_X_MASK; + uint32_t scriptX=u_getUnicodeProperties(c, 0)&UPROPS_SCRIPT_X_MASK; + uint32_t codeOrIndex=uprops_mergeScriptCodeOrIndex(scriptX); if(scriptX=UPROPS_SCRIPT_X_WITH_OTHER) { scx=scriptExtensions+scx[1]; } - if(sc>=USCRIPT_CODE_LIMIT) { + uint32_t sc32=sc; + if(sc32>0x7fff) { /* Guard against bogus input that would make us go past the Script_Extensions terminator. */ return FALSE; } - while(sc>*scx) { + while(sc32>*scx) { ++scx; } - return sc==(*scx&0x7fff); + return sc32==(*scx&0x7fff); } U_CAPI int32_t U_EXPORT2 uscript_getScriptExtensions(UChar32 c, UScriptCode *scripts, int32_t capacity, UErrorCode *pErrorCode) { - uint32_t scriptX; - int32_t length; - const uint16_t *scx; - uint16_t sx; if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { return 0; } @@ -613,21 +610,23 @@ uscript_getScriptExtensions(UChar32 c, *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } - scriptX=u_getUnicodeProperties(c, 0)&UPROPS_SCRIPT_X_MASK; + uint32_t scriptX=u_getUnicodeProperties(c, 0)&UPROPS_SCRIPT_X_MASK; + uint32_t codeOrIndex=uprops_mergeScriptCodeOrIndex(scriptX); if(scriptX=UPROPS_SCRIPT_X_WITH_OTHER) { scx=scriptExtensions+scx[1]; } - length=0; + int32_t length=0; + uint16_t sx; do { sx=*scx++; if(length(aligned_p); - stackBufferSize -= pointerAdjustment; + stackBufferSize -= static_cast(pointerAdjustment); } else { /* prevent using the stack buffer but keep the size > 0 so that we do not just preflight */ stackBufferSize = 1; diff --git a/deps/icu-small/source/common/ucnv2022.cpp b/deps/icu-small/source/common/ucnv2022.cpp index 6cd9a3d12e40fc..89db9e81ddea06 100644 --- a/deps/icu-small/source/common/ucnv2022.cpp +++ b/deps/icu-small/source/common/ucnv2022.cpp @@ -478,7 +478,7 @@ setInitialStateFromUnicodeKR(UConverter* converter,UConverterDataISO2022 *myConv static void U_CALLCONV _ISO2022Open(UConverter *cnv, UConverterLoadArgs *pArgs, UErrorCode *errorCode){ - char myLocale[6]={' ',' ',' ',' ',' ',' '}; + char myLocale[7]={' ',' ',' ',' ',' ',' ', '\0'}; cnv->extraInfo = uprv_malloc (sizeof (UConverterDataISO2022)); if(cnv->extraInfo != NULL) { @@ -493,7 +493,7 @@ _ISO2022Open(UConverter *cnv, UConverterLoadArgs *pArgs, UErrorCode *errorCode){ myConverterData->currentType = ASCII1; cnv->fromUnicodeStatus =FALSE; if(pArgs->locale){ - uprv_strncpy(myLocale, pArgs->locale, sizeof(myLocale)); + uprv_strncpy(myLocale, pArgs->locale, sizeof(myLocale)-1); } version = pArgs->options & UCNV_OPTIONS_VERSION_MASK; myConverterData->version = version; diff --git a/deps/icu-small/source/common/ucurr.cpp b/deps/icu-small/source/common/ucurr.cpp index d42c2f10b1d4c6..391b08083b899a 100644 --- a/deps/icu-small/source/common/ucurr.cpp +++ b/deps/icu-small/source/common/ucurr.cpp @@ -866,7 +866,7 @@ getCurrencyNameCount(const char* loc, int32_t* total_currency_name_count, int32_ *total_currency_name_count = 0; *total_currency_symbol_count = 0; const UChar* s = NULL; - char locale[ULOC_FULLNAME_CAPACITY]; + char locale[ULOC_FULLNAME_CAPACITY] = ""; uprv_strcpy(locale, loc); const icu::Hashtable *currencySymbolsEquiv = getCurrSymbolsEquiv(); for (;;) { @@ -941,7 +941,7 @@ collectCurrencyNames(const char* locale, // Look up the Currencies resource for the given locale. UErrorCode ec2 = U_ZERO_ERROR; - char loc[ULOC_FULLNAME_CAPACITY]; + char loc[ULOC_FULLNAME_CAPACITY] = ""; uloc_getName(locale, loc, sizeof(loc), &ec2); if (U_FAILURE(ec2) || ec2 == U_STRING_NOT_TERMINATED_WARNING) { ec = U_ILLEGAL_ARGUMENT_ERROR; diff --git a/deps/icu-small/source/common/uloc.cpp b/deps/icu-small/source/common/uloc.cpp index 6a9bfcfbff5999..0e235d7958ceb1 100644 --- a/deps/icu-small/source/common/uloc.cpp +++ b/deps/icu-small/source/common/uloc.cpp @@ -30,10 +30,14 @@ l = lang, C = ctry, M = charmap, V = variant */ +#include "unicode/bytestream.h" +#include "unicode/errorcode.h" +#include "unicode/stringpiece.h" #include "unicode/utypes.h" #include "unicode/ustring.h" #include "unicode/uloc.h" +#include "bytesinkutil.h" #include "putilimp.h" #include "ustr_imp.h" #include "ulocimp.h" @@ -46,6 +50,7 @@ #include "uassert.h" #include "charstr.h" +#include #include /* for sprintf */ U_NAMESPACE_USE @@ -59,7 +64,6 @@ U_CFUNC int32_t locale_getKeywords(const char *localeID, char prev, char *keywords, int32_t keywordCapacity, - char *values, int32_t valuesCapacity, int32_t *valLen, UBool valuesToo, UErrorCode *status); @@ -157,7 +161,7 @@ static const char * const LANGUAGES[] = { "nnh", "no", "nog", "non", "nov", "nqo", "nr", "nso", "nus", "nv", "nwc", "ny", "nym", "nyn", "nyo", "nzi", "oc", "oj", "om", "or", "os", "osa", "ota", - "pa", "pag", "pal", "pam", "pap", "pau", "pcd", "pdc", + "pa", "pag", "pal", "pam", "pap", "pau", "pcd", "pcm", "pdc", "pdt", "peo", "pfl", "phn", "pi", "pl", "pms", "pnt", "pon", "prg", "pro", "ps", "pt", "qu", "quc", "qug", @@ -274,7 +278,7 @@ static const char * const LANGUAGES_3[] = { "nnh", "nor", "nog", "non", "nov", "nqo", "nbl", "nso", "nus", "nav", "nwc", "nya", "nym", "nyn", "nyo", "nzi", "oci", "oji", "orm", "ori", "oss", "osa", "ota", - "pan", "pag", "pal", "pam", "pap", "pau", "pcd", "pdc", + "pan", "pag", "pal", "pam", "pap", "pau", "pcd", "pcm", "pdc", "pdt", "peo", "pfl", "phn", "pli", "pol", "pms", "pnt", "pon", "prg", "pro", "pus", "por", "que", "quc", "qug", @@ -466,15 +470,16 @@ typedef struct CanonicalizationMap { * different semantic kinds of transformations. */ static const CanonicalizationMap CANONICALIZE_MAP[] = { - { "art_LOJBAN", "jbo" }, /* registered name */ + { "art__LOJBAN", "jbo" }, /* registered name */ { "hy__AREVELA", "hy" }, /* Registered IANA variant */ { "hy__AREVMDA", "hyw" }, /* Registered IANA variant */ + { "zh__GUOYU", "zh" }, /* registered name */ + { "zh__HAKKA", "hak" }, /* registered name */ + { "zh__XIANG", "hsn" }, /* registered name */ + // subtags with 3 chars won't be treated as variants. { "zh_GAN", "gan" }, /* registered name */ - { "zh_GUOYU", "zh" }, /* registered name */ - { "zh_HAKKA", "hak" }, /* registered name */ { "zh_MIN_NAN", "nan" }, /* registered name */ { "zh_WUU", "wuu" }, /* registered name */ - { "zh_XIANG", "hsn" }, /* registered name */ { "zh_YUE", "yue" }, /* registered name */ }; @@ -596,11 +601,10 @@ compareKeywordStructs(const void * /*context*/, const void *left, const void *ri return uprv_strcmp(leftString, rightString); } -static int32_t +static void _getKeywords(const char *localeID, char prev, - char *keywords, int32_t keywordCapacity, - char *values, int32_t valuesCapacity, int32_t *valLen, + ByteSink& sink, UBool valuesToo, UErrorCode *status) { @@ -612,8 +616,6 @@ _getKeywords(const char *localeID, const char* equalSign = NULL; const char* semicolon = NULL; int32_t i = 0, j, n; - int32_t keywordsLen = 0; - int32_t valuesLen = 0; if(prev == '@') { /* start of keyword definition */ /* we will grab pairs, trim spaces, lowercase keywords, sort and return */ @@ -628,7 +630,7 @@ _getKeywords(const char *localeID, } if(numKeywords == maxKeywords) { *status = U_INTERNAL_PROGRAM_ERROR; - return 0; + return; } equalSign = uprv_strchr(pos, '='); semicolon = uprv_strchr(pos, ';'); @@ -636,13 +638,13 @@ _getKeywords(const char *localeID, /* ';' before '=' [foo@currency;collation=pinyin] is illegal */ if(!equalSign || (semicolon && semicolon= ULOC_KEYWORD_BUFFER_LEN) { /* keyword name too long for internal buffer */ *status = U_INTERNAL_PROGRAM_ERROR; - return 0; + return; } for(i = 0, n = 0; i < equalSign - pos; ++i) { if (pos[i] != ' ') { @@ -653,7 +655,7 @@ _getKeywords(const char *localeID, /* zero-length keyword is an error. */ if (n == 0) { *status = U_INVALID_FORMAT_ERROR; - return 0; + return; } keywordList[numKeywords].keyword[n] = 0; @@ -668,7 +670,7 @@ _getKeywords(const char *localeID, /* Premature end or zero-length value */ if (!*equalSign || equalSign == semicolon) { *status = U_INVALID_FORMAT_ERROR; - return 0; + return; } keywordList[numKeywords].valueStart = equalSign; @@ -706,45 +708,17 @@ _getKeywords(const char *localeID, /* Now construct the keyword part */ for(i = 0; i < numKeywords; i++) { - if(keywordsLen + keywordList[i].keywordLen + 1< keywordCapacity) { - uprv_strcpy(keywords+keywordsLen, keywordList[i].keyword); - if(valuesToo) { - keywords[keywordsLen + keywordList[i].keywordLen] = '='; - } else { - keywords[keywordsLen + keywordList[i].keywordLen] = 0; - } - } - keywordsLen += keywordList[i].keywordLen + 1; + sink.Append(keywordList[i].keyword, keywordList[i].keywordLen); if(valuesToo) { - if(keywordsLen + keywordList[i].valueLen <= keywordCapacity) { - uprv_strncpy(keywords+keywordsLen, keywordList[i].valueStart, keywordList[i].valueLen); - } - keywordsLen += keywordList[i].valueLen; - + sink.Append("=", 1); + sink.Append(keywordList[i].valueStart, keywordList[i].valueLen); if(i < numKeywords - 1) { - if(keywordsLen < keywordCapacity) { - keywords[keywordsLen] = ';'; - } - keywordsLen++; - } - } - if(values) { - if(valuesLen + keywordList[i].valueLen + 1< valuesCapacity) { - uprv_strcpy(values+valuesLen, keywordList[i].valueStart); - values[valuesLen + keywordList[i].valueLen] = 0; + sink.Append(";", 1); } - valuesLen += keywordList[i].valueLen + 1; - } - } - if(values) { - values[valuesLen] = 0; - if(valLen) { - *valLen = valuesLen; + } else { + sink.Append("\0", 1); } } - return u_terminateChars(keywords, keywordCapacity, keywordsLen, status); - } else { - return 0; } } @@ -752,12 +726,28 @@ U_CFUNC int32_t locale_getKeywords(const char *localeID, char prev, char *keywords, int32_t keywordCapacity, - char *values, int32_t valuesCapacity, int32_t *valLen, UBool valuesToo, UErrorCode *status) { - return _getKeywords(localeID, prev, keywords, keywordCapacity, - values, valuesCapacity, valLen, valuesToo, - status); + if (U_FAILURE(*status)) { + return 0; + } + + CheckedArrayByteSink sink(keywords, keywordCapacity); + _getKeywords(localeID, prev, sink, valuesToo, status); + + int32_t reslen = sink.NumberOfBytesAppended(); + + if (U_FAILURE(*status)) { + return reslen; + } + + if (sink.Overflowed()) { + *status = U_BUFFER_OVERFLOW_ERROR; + } else { + u_terminateChars(keywords, keywordCapacity, reslen, status); + } + + return reslen; } U_CAPI int32_t U_EXPORT2 @@ -766,6 +756,9 @@ uloc_getKeywordValue(const char* localeID, char* buffer, int32_t bufferCapacity, UErrorCode* status) { + if (buffer != nullptr) { + buffer[0] = '\0'; + } const char* startSearchHere = NULL; const char* nextSeparator = NULL; char keywordNameBuffer[ULOC_KEYWORD_BUFFER_LEN]; @@ -1131,26 +1124,6 @@ static int16_t _findIndex(const char* const* list, const char* key) return -1; } -/* count the length of src while copying it to dest; return strlen(src) */ -static inline int32_t -_copyCount(char *dest, int32_t destCapacity, const char *src) { - const char *anchor; - char c; - - anchor=src; - for(;;) { - if((c=*src)==0) { - return (int32_t)(src-anchor); - } - if(destCapacity<=0) { - return (int32_t)((src-anchor)+uprv_strlen(src)); - } - ++src; - *dest++=c; - --destCapacity; - } -} - U_CFUNC const char* uloc_getCurrentCountryID(const char* oldID){ int32_t offset = _findIndex(DEPRECATED_COUNTRIES, oldID); @@ -1175,13 +1148,11 @@ uloc_getCurrentLanguageID(const char* oldID){ * * TODO try to use this in Locale */ -U_CFUNC int32_t +static CharString ulocimp_getLanguage(const char *localeID, - char *language, int32_t languageCapacity, - const char **pEnd) { - int32_t i=0; - int32_t offset; - char lang[4]={ 0, 0, 0, 0 }; /* temporary buffer to hold language code for searching */ + const char **pEnd, + UErrorCode &status) { + CharString result; if (uprv_stricmp(localeID, "root") == 0) { localeID += 4; @@ -1195,48 +1166,52 @@ ulocimp_getLanguage(const char *localeID, /* if it starts with i- or x- then copy that prefix */ if(_isIDPrefix(localeID)) { - if(i=0); - lang[i]=(char)uprv_tolower(*localeID); - } - i++; + result.append((char)uprv_tolower(*localeID), status); localeID++; } - if(i==3) { + if(result.length()==3) { /* convert 3 character code to 2 character code if possible *CWB*/ - offset=_findIndex(LANGUAGES_3, lang); + int32_t offset = _findIndex(LANGUAGES_3, result.data()); if(offset>=0) { - i=_copyCount(language, languageCapacity, LANGUAGES[offset]); + result.clear(); + result.append(LANGUAGES[offset], status); } } if(pEnd!=NULL) { *pEnd=localeID; } - return i; + + return result; } U_CFUNC int32_t +ulocimp_getLanguage(const char *localeID, + char *language, int32_t languageCapacity, + const char **pEnd) { + ErrorCode status; + CharString result = ulocimp_getLanguage(localeID, pEnd, status); + if (status.isFailure()) { + return 0; + } + int32_t reslen = result.length(); + uprv_memcpy(language, result.data(), std::min(reslen, languageCapacity)); + return reslen; +} + +static CharString ulocimp_getScript(const char *localeID, - char *script, int32_t scriptCapacity, - const char **pEnd) -{ + const char **pEnd, + UErrorCode &status) { + CharString result; int32_t idLen = 0; if (pEnd != NULL) { @@ -1255,132 +1230,137 @@ ulocimp_getScript(const char *localeID, if (pEnd != NULL) { *pEnd = localeID+idLen; } - if(idLen > scriptCapacity) { - idLen = scriptCapacity; - } if (idLen >= 1) { - script[0]=(char)uprv_toupper(*(localeID++)); + result.append((char)uprv_toupper(*(localeID++)), status); } for (i = 1; i < idLen; i++) { - script[i]=(char)uprv_tolower(*(localeID++)); + result.append((char)uprv_tolower(*(localeID++)), status); } } - else { - idLen = 0; - } - return idLen; + + return result; } U_CFUNC int32_t +ulocimp_getScript(const char *localeID, + char *script, int32_t scriptCapacity, + const char **pEnd) { + ErrorCode status; + CharString result = ulocimp_getScript(localeID, pEnd, status); + if (status.isFailure()) { + return 0; + } + int32_t reslen = result.length(); + uprv_memcpy(script, result.data(), std::min(reslen, scriptCapacity)); + return reslen; +} + +static CharString ulocimp_getCountry(const char *localeID, - char *country, int32_t countryCapacity, - const char **pEnd) -{ + const char **pEnd, + UErrorCode &status) { + CharString result; int32_t idLen=0; - char cnty[ULOC_COUNTRY_CAPACITY]={ 0, 0, 0, 0 }; - int32_t offset; /* copy the country as far as possible and count its length */ while(!_isTerminator(localeID[idLen]) && !_isIDSeparator(localeID[idLen])) { - if(idLen<(ULOC_COUNTRY_CAPACITY-1)) { /*CWB*/ - cnty[idLen]=(char)uprv_toupper(localeID[idLen]); - } + result.append((char)uprv_toupper(localeID[idLen]), status); idLen++; } /* the country should be either length 2 or 3 */ if (idLen == 2 || idLen == 3) { - UBool gotCountry = FALSE; /* convert 3 character code to 2 character code if possible *CWB*/ if(idLen==3) { - offset=_findIndex(COUNTRIES_3, cnty); + int32_t offset = _findIndex(COUNTRIES_3, result.data()); if(offset>=0) { - idLen=_copyCount(country, countryCapacity, COUNTRIES[offset]); - gotCountry = TRUE; - } - } - if (!gotCountry) { - int32_t i = 0; - for (i = 0; i < idLen; i++) { - if (i < countryCapacity) { - country[i]=(char)uprv_toupper(localeID[i]); - } + result.clear(); + result.append(COUNTRIES[offset], status); } } localeID+=idLen; } else { - idLen = 0; + result.clear(); } if(pEnd!=NULL) { *pEnd=localeID; } - return idLen; + return result; +} + +U_CFUNC int32_t +ulocimp_getCountry(const char *localeID, + char *country, int32_t countryCapacity, + const char **pEnd) { + ErrorCode status; + CharString result = ulocimp_getCountry(localeID, pEnd, status); + if (status.isFailure()) { + return 0; + } + int32_t reslen = result.length(); + uprv_memcpy(country, result.data(), std::min(reslen, countryCapacity)); + return reslen; } /** * @param needSeparator if true, then add leading '_' if any variants * are added to 'variant' */ -static int32_t +static void _getVariantEx(const char *localeID, char prev, - char *variant, int32_t variantCapacity, + ByteSink& sink, UBool needSeparator) { - int32_t i=0; + UBool hasVariant = FALSE; /* get one or more variant tags and separate them with '_' */ if(_isIDSeparator(prev)) { /* get a variant string after a '-' or '_' */ while(!_isTerminator(*localeID)) { if (needSeparator) { - if (i 0) { /* Found optional script */ tmpLocaleID = scriptID; ++fieldCount; - len+=scriptSize; if (_isIDSeparator(*tmpLocaleID)) { /* If there is something else, then we add the _ */ - if(len 0) { + + CharString country = ulocimp_getCountry(tmpLocaleID+1, &cntryID, *err); + tag.append(country, *err); + if (!country.isEmpty()) { /* Found optional country */ tmpLocaleID = cntryID; - len+=cntrySize; } if(_isIDSeparator(*tmpLocaleID)) { /* If there is something else, then we add the _ if we found country before. */ - if (cntrySize >= 0 && ! _isIDSeparator(*(tmpLocaleID+1)) ) { + if (!_isIDSeparator(*(tmpLocaleID+1))) { ++fieldCount; - if(len 0) { - variant = len 0)) { do { - if(len 0)); + + int32_t posixVariantSize = -tag.length(); + { + CharStringByteSink s(&tag); + _getVariantEx(tmpLocaleID+1, '@', s, (UBool)(variantSize > 0)); + } + posixVariantSize += tag.length(); if (posixVariantSize > 0) { - if (variant == NULL) { - variant = name+len; - } - len += posixVariantSize; variantSize += posixVariantSize; } } /* Look up the ID in the canonicalization map */ for (j=0; j keywordAssign)) { - if(len resultCapacity) ? resultCapacity : len); - } - - return u_terminateChars(result, resultCapacity, len, err); } /* ### ID parsing API **************************************************/ @@ -1946,7 +1883,34 @@ uloc_getName(const char* localeID, int32_t nameCapacity, UErrorCode* err) { - return _canonicalize(localeID, name, nameCapacity, 0, err); + if (U_FAILURE(*err)) { + return 0; + } + + CheckedArrayByteSink sink(name, nameCapacity); + ulocimp_getName(localeID, sink, err); + + int32_t reslen = sink.NumberOfBytesAppended(); + + if (U_FAILURE(*err)) { + return reslen; + } + + if (sink.Overflowed()) { + *err = U_BUFFER_OVERFLOW_ERROR; + } else { + u_terminateChars(name, nameCapacity, reslen, err); + } + + return reslen; +} + +U_STABLE void U_EXPORT2 +ulocimp_getName(const char* localeID, + ByteSink& sink, + UErrorCode* err) +{ + _canonicalize(localeID, sink, 0, err); } U_CAPI int32_t U_EXPORT2 @@ -1955,7 +1919,34 @@ uloc_getBaseName(const char* localeID, int32_t nameCapacity, UErrorCode* err) { - return _canonicalize(localeID, name, nameCapacity, _ULOC_STRIP_KEYWORDS, err); + if (U_FAILURE(*err)) { + return 0; + } + + CheckedArrayByteSink sink(name, nameCapacity); + ulocimp_getBaseName(localeID, sink, err); + + int32_t reslen = sink.NumberOfBytesAppended(); + + if (U_FAILURE(*err)) { + return reslen; + } + + if (sink.Overflowed()) { + *err = U_BUFFER_OVERFLOW_ERROR; + } else { + u_terminateChars(name, nameCapacity, reslen, err); + } + + return reslen; +} + +U_STABLE void U_EXPORT2 +ulocimp_getBaseName(const char* localeID, + ByteSink& sink, + UErrorCode* err) +{ + _canonicalize(localeID, sink, _ULOC_STRIP_KEYWORDS, err); } U_CAPI int32_t U_EXPORT2 @@ -1964,7 +1955,34 @@ uloc_canonicalize(const char* localeID, int32_t nameCapacity, UErrorCode* err) { - return _canonicalize(localeID, name, nameCapacity, _ULOC_CANONICALIZE, err); + if (U_FAILURE(*err)) { + return 0; + } + + CheckedArrayByteSink sink(name, nameCapacity); + ulocimp_canonicalize(localeID, sink, err); + + int32_t reslen = sink.NumberOfBytesAppended(); + + if (U_FAILURE(*err)) { + return reslen; + } + + if (sink.Overflowed()) { + *err = U_BUFFER_OVERFLOW_ERROR; + } else { + u_terminateChars(name, nameCapacity, reslen, err); + } + + return reslen; +} + +U_STABLE void U_EXPORT2 +ulocimp_canonicalize(const char* localeID, + ByteSink& sink, + UErrorCode* err) +{ + _canonicalize(localeID, sink, _ULOC_CANONICALIZE, err); } U_CAPI const char* U_EXPORT2 @@ -2123,301 +2141,6 @@ uloc_getISOCountries() return COUNTRIES; } - -/* this function to be moved into cstring.c later */ -static char gDecimal = 0; - -static /* U_CAPI */ -double -/* U_EXPORT2 */ -_uloc_strtod(const char *start, char **end) { - char *decimal; - char *myEnd; - char buf[30]; - double rv; - if (!gDecimal) { - char rep[5]; - /* For machines that decide to change the decimal on you, - and try to be too smart with localization. - This normally should be just a '.'. */ - sprintf(rep, "%+1.1f", 1.0); - gDecimal = rep[2]; - } - - if(gDecimal == '.') { - return uprv_strtod(start, end); /* fall through to OS */ - } else { - uprv_strncpy(buf, start, 29); - buf[29]=0; - decimal = uprv_strchr(buf, '.'); - if(decimal) { - *decimal = gDecimal; - } else { - return uprv_strtod(start, end); /* no decimal point */ - } - rv = uprv_strtod(buf, &myEnd); - if(end) { - *end = (char*)(start+(myEnd-buf)); /* cast away const (to follow uprv_strtod API.) */ - } - return rv; - } -} - -typedef struct { - float q; - int32_t dummy; /* to avoid uninitialized memory copy from qsort */ - char locale[ULOC_FULLNAME_CAPACITY+1]; -} _acceptLangItem; - -static int32_t U_CALLCONV -uloc_acceptLanguageCompare(const void * /*context*/, const void *a, const void *b) -{ - const _acceptLangItem *aa = (const _acceptLangItem*)a; - const _acceptLangItem *bb = (const _acceptLangItem*)b; - - int32_t rc = 0; - if(bb->q < aa->q) { - rc = -1; /* A > B */ - } else if(bb->q > aa->q) { - rc = 1; /* A < B */ - } else { - rc = 0; /* A = B */ - } - - if(rc==0) { - rc = uprv_stricmp(aa->locale, bb->locale); - } - -#if defined(ULOC_DEBUG) - /* fprintf(stderr, "a:[%s:%g], b:[%s:%g] -> %d\n", - aa->locale, aa->q, - bb->locale, bb->q, - rc);*/ -#endif - - return rc; -} - -/* -mt-mt, ja;q=0.76, en-us;q=0.95, en;q=0.92, en-gb;q=0.89, fr;q=0.87, iu-ca;q=0.84, iu;q=0.82, ja-jp;q=0.79, mt;q=0.97, de-de;q=0.74, de;q=0.71, es;q=0.68, it-it;q=0.66, it;q=0.63, vi-vn;q=0.61, vi;q=0.58, nl-nl;q=0.55, nl;q=0.53 -*/ - -U_CAPI int32_t U_EXPORT2 -uloc_acceptLanguageFromHTTP(char *result, int32_t resultAvailable, UAcceptResult *outResult, - const char *httpAcceptLanguage, - UEnumeration* availableLocales, - UErrorCode *status) -{ - MaybeStackArray<_acceptLangItem, 4> items; // Struct for collecting items. - char tmp[ULOC_FULLNAME_CAPACITY +1]; - int32_t n = 0; - const char *itemEnd; - const char *paramEnd; - const char *s; - const char *t; - int32_t res; - int32_t i; - int32_t l = (int32_t)uprv_strlen(httpAcceptLanguage); - - if(U_FAILURE(*status)) { - return -1; - } - - for(s=httpAcceptLanguage;s&&*s;) { - while(isspace(*s)) /* eat space at the beginning */ - s++; - itemEnd=uprv_strchr(s,','); - paramEnd=uprv_strchr(s,';'); - if(!itemEnd) { - itemEnd = httpAcceptLanguage+l; /* end of string */ - } - if(paramEnd && paramEnds)&&isspace(*t);t--) - ; - int32_t slen = static_cast(((t+1)-s)); - if(slen > ULOC_FULLNAME_CAPACITY) { - *status = U_BUFFER_OVERFLOW_ERROR; - return -1; // too big - } - uprv_strncpy(items[n].locale, s, slen); - items[n].locale[slen]=0; // terminate - int32_t clen = uloc_canonicalize(items[n].locale, tmp, UPRV_LENGTHOF(tmp)-1, status); - if(U_FAILURE(*status)) return -1; - if((clen!=slen) || (uprv_strncmp(items[n].locale, tmp, slen))) { - // canonicalization had an effect- copy back - uprv_strncpy(items[n].locale, tmp, clen); - items[n].locale[clen] = 0; // terminate - } -#if defined(ULOC_DEBUG) - /*fprintf(stderr,"%d: s <%s> q <%g>\n", n, j[n].locale, j[n].q);*/ -#endif - n++; - s = itemEnd; - while(*s==',') { /* eat duplicate commas */ - s++; - } - if(n>=items.getCapacity()) { // If we need more items - if(NULL == items.resize(items.getCapacity()*2, items.getCapacity())) { - *status = U_MEMORY_ALLOCATION_ERROR; - return -1; - } -#if defined(ULOC_DEBUG) - fprintf(stderr,"malloced at size %d\n", items.getCapacity()); -#endif - } - } - uprv_sortArray(items.getAlias(), n, sizeof(items[0]), uloc_acceptLanguageCompare, NULL, TRUE, status); - if (U_FAILURE(*status)) { - return -1; - } - LocalMemory strs(NULL); - if (strs.allocateInsteadAndReset(n) == NULL) { - *status = U_MEMORY_ALLOCATION_ERROR; - return -1; - } - for(i=0;i q <%g>\n", i, j[i].locale, j[i].q);*/ -#endif - strs[i]=items[i].locale; - } - res = uloc_acceptLanguage(result, resultAvailable, outResult, - strs.getAlias(), n, availableLocales, status); - return res; -} - - -U_CAPI int32_t U_EXPORT2 -uloc_acceptLanguage(char *result, int32_t resultAvailable, - UAcceptResult *outResult, const char **acceptList, - int32_t acceptListCount, - UEnumeration* availableLocales, - UErrorCode *status) -{ - int32_t i,j; - int32_t len; - int32_t maxLen=0; - char tmp[ULOC_FULLNAME_CAPACITY+1]; - const char *l; - char **fallbackList; - if(U_FAILURE(*status)) { - return -1; - } - fallbackList = static_cast(uprv_malloc((size_t)(sizeof(fallbackList[0])*acceptListCount))); - if(fallbackList==NULL) { - *status = U_MEMORY_ALLOCATION_ERROR; - return -1; - } - for(i=0;i0) { - uprv_strncpy(result, l, uprv_min(len, resultAvailable)); - } - for(j=0;jmaxLen) { - maxLen = len; - } - } - uenum_reset(availableLocales, status); - /* save off parent info */ - if(uloc_getParent(acceptList[i], tmp, UPRV_LENGTHOF(tmp), status)!=0) { - fallbackList[i] = uprv_strdup(tmp); - } else { - fallbackList[i]=0; - } - } - - for(maxLen--;maxLen>0;maxLen--) { - for(i=0;i0) { - uprv_strncpy(result, l, uprv_min(len, resultAvailable)); - } - for(j=0;jnext) { + for (VariantListEntry* var2 = var1->next; var2 != NULL; var2 = var2->next) { + // Swap var1->variant and var2->variant. + if (uprv_compareInvCharsAsAscii(var1->variant, var2->variant) > 0) { + const char* temp = var1->variant; + var1->variant = var2->variant; + var2->variant = temp; + } + } + } +} + static void _appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool strict, UBool *hadPosix, UErrorCode* status) { char buf[ULOC_FULLNAME_CAPACITY]; @@ -1199,6 +1212,9 @@ _appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool st if (varFirst != NULL) { int32_t varLen; + /* per UTS35, we should sort the variants */ + _sortVariants(varFirst); + /* write out validated/normalized variants to the target */ var = varFirst; while (var != NULL) { @@ -1492,8 +1508,11 @@ _appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool st } else { sink.Append("-", 1); sink.Append(ext->key, static_cast(uprv_strlen(ext->key))); - sink.Append("-", 1); - sink.Append(ext->value, static_cast(uprv_strlen(ext->value))); + if (uprv_strcmp(ext->value, "true") != 0 && + uprv_strcmp(ext->value, "yes") != 0) { + sink.Append("-", 1); + sink.Append(ext->value, static_cast(uprv_strlen(ext->value))); + } } } } @@ -1662,7 +1681,7 @@ _appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendT const char *pKey = NULL; /* LDML key */ const char *pType = NULL; /* LDML type */ - char bcpKeyBuf[9]; /* BCP key length is always 2 for now */ + char bcpKeyBuf[3]; /* BCP key length is always 2 for now */ U_ASSERT(pBcpKey != NULL); @@ -1671,6 +1690,7 @@ _appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendT *status = U_ILLEGAL_ARGUMENT_ERROR; return; } + U_ASSERT(bcpKeyLen <= 2); uprv_strncpy(bcpKeyBuf, pBcpKey, bcpKeyLen); bcpKeyBuf[bcpKeyLen] = 0; @@ -2822,6 +2842,7 @@ ulocimp_forLanguageTag(const char* langtag, } /* variants */ + _sortVariants(lt.getAlias()->variants); n = ultag_getVariantsSize(lt.getAlias()); if (n > 0) { if (noRegion) { diff --git a/deps/icu-small/source/common/ulocimp.h b/deps/icu-small/source/common/ulocimp.h index dac82872e6ed40..98b95dddfe75bc 100644 --- a/deps/icu-small/source/common/ulocimp.h +++ b/deps/icu-small/source/common/ulocimp.h @@ -62,6 +62,21 @@ ulocimp_getCountry(const char *localeID, char *country, int32_t countryCapacity, const char **pEnd); +U_STABLE void U_EXPORT2 +ulocimp_getName(const char* localeID, + icu::ByteSink& sink, + UErrorCode* err); + +U_STABLE void U_EXPORT2 +ulocimp_getBaseName(const char* localeID, + icu::ByteSink& sink, + UErrorCode* err); + +U_STABLE void U_EXPORT2 +ulocimp_canonicalize(const char* localeID, + icu::ByteSink& sink, + UErrorCode* err); + /** * Writes a well-formed language tag for this locale ID. * diff --git a/deps/icu-small/source/common/umutex.h b/deps/icu-small/source/common/umutex.h old mode 100755 new mode 100644 diff --git a/deps/icu-small/source/common/unames.cpp b/deps/icu-small/source/common/unames.cpp index a28b6ee6036b96..c55e2d662acff5 100644 --- a/deps/icu-small/source/common/unames.cpp +++ b/deps/icu-small/source/common/unames.cpp @@ -1519,7 +1519,8 @@ U_CAPI UChar32 U_EXPORT2 u_charFromName(UCharNameChoice nameChoice, const char *name, UErrorCode *pErrorCode) { - char upper[120], lower[120]; + char upper[120] = {0}; + char lower[120] = {0}; FindName findName; AlgorithmicRange *algRange; uint32_t *p; diff --git a/deps/icu-small/source/common/unicode/bytestream.h b/deps/icu-small/source/common/unicode/bytestream.h index 2c71c248e3dfa0..33505a34299818 100644 --- a/deps/icu-small/source/common/unicode/bytestream.h +++ b/deps/icu-small/source/common/unicode/bytestream.h @@ -71,6 +71,40 @@ class U_COMMON_API ByteSink : public UMemory { */ virtual void Append(const char* bytes, int32_t n) = 0; +#ifndef U_HIDE_DRAFT_API + /** + * Appends n bytes to this. Same as Append(). + * Call AppendU8() with u8"string literals" which are const char * in C++11 + * but const char8_t * in C++20. + * If the compiler does support char8_t as a distinct type, + * then an AppendU8() overload for that is defined and will be chosen. + * + * @param bytes the pointer to the bytes + * @param n the number of bytes; must be non-negative + * @draft ICU 67 + */ + inline void AppendU8(const char* bytes, int32_t n) { + Append(bytes, n); + } + +#if defined(__cpp_char8_t) || defined(U_IN_DOXYGEN) + /** + * Appends n bytes to this. Same as Append() but for a const char8_t * pointer. + * Call AppendU8() with u8"string literals" which are const char * in C++11 + * but const char8_t * in C++20. + * If the compiler does support char8_t as a distinct type, + * then this AppendU8() overload for that is defined and will be chosen. + * + * @param bytes the pointer to the bytes + * @param n the number of bytes; must be non-negative + * @draft ICU 67 + */ + inline void AppendU8(const char8_t* bytes, int32_t n) { + Append(reinterpret_cast(bytes), n); + } +#endif +#endif // U_HIDE_DRAFT_API + /** * Returns a writable buffer for appending and writes the buffer's capacity to * *result_capacity. Guarantees *result_capacity>=min_capacity. diff --git a/deps/icu-small/source/common/unicode/localebuilder.h b/deps/icu-small/source/common/unicode/localebuilder.h index 19e10f1c070924..c5836fe27021b3 100644 --- a/deps/icu-small/source/common/unicode/localebuilder.h +++ b/deps/icu-small/source/common/unicode/localebuilder.h @@ -12,7 +12,6 @@ #include "unicode/stringpiece.h" #include "unicode/uobject.h" -#ifndef U_HIDE_DRAFT_API /** * \file * \brief C++ API: Builder API for Locale @@ -57,7 +56,7 @@ class CharString; * UErrorCode, then track the error of the validation of the input parameter * into the internal UErrorCode. * - * @draft ICU 64 + * @stable ICU 64 */ class U_COMMON_API LocaleBuilder : public UObject { public: @@ -66,13 +65,13 @@ class U_COMMON_API LocaleBuilder : public UObject { * fields, extensions, and private use information is the * empty string. * - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder(); /** * Destructor - * @draft ICU 64 + * @stable ICU 64 */ virtual ~LocaleBuilder(); @@ -86,7 +85,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * @param locale the locale * @return This builder. * - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setLocale(const Locale& locale); @@ -104,7 +103,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * @param tag the language tag, defined as * [unicode_locale_id](http://www.unicode.org/reports/tr35/tr35.html#unicode_locale_id). * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setLanguageTag(StringPiece tag); @@ -119,7 +118,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * * @param language the language * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setLanguage(StringPiece language); @@ -135,7 +134,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * * @param script the script * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setScript(StringPiece script); @@ -154,7 +153,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * * @param region the region * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setRegion(StringPiece region); @@ -175,7 +174,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * * @param variant the variant * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setVariant(StringPiece variant); @@ -196,7 +195,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * @param key the extension key * @param value the extension value * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setExtension(char key, StringPiece value); @@ -216,7 +215,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * @param key the Unicode locale key * @param type the Unicode locale type * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& setUnicodeLocaleKeyword( StringPiece key, StringPiece type); @@ -229,7 +228,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * * @param attribute the attribute * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& addUnicodeLocaleAttribute(StringPiece attribute); @@ -242,7 +241,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * * @param attribute the attribute * @return This builder. - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& removeUnicodeLocaleAttribute(StringPiece attribute); @@ -251,7 +250,7 @@ class U_COMMON_API LocaleBuilder : public UObject { *

This method clears the internal UErrorCode. * * @return this builder - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& clear(); @@ -260,7 +259,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * Language, script, region and variant are unchanged. * * @return this builder - * @draft ICU 64 + * @stable ICU 64 */ LocaleBuilder& clearExtensions(); @@ -275,7 +274,7 @@ class U_COMMON_API LocaleBuilder : public UObject { * the same builder to build more locales. * * @return a new Locale - * @draft ICU 64 + * @stable ICU 64 */ Locale build(UErrorCode& status); @@ -308,8 +307,6 @@ class U_COMMON_API LocaleBuilder : public UObject { U_NAMESPACE_END -#endif // U_HIDE_DRAFT_API - #endif /* U_SHOW_CPLUSPLUS_API */ #endif // __LOCALEBUILDER_H__ diff --git a/deps/icu-small/source/common/unicode/localematcher.h b/deps/icu-small/source/common/unicode/localematcher.h index 701123f750b222..2e1a7a349f3983 100644 --- a/deps/icu-small/source/common/unicode/localematcher.h +++ b/deps/icu-small/source/common/unicode/localematcher.h @@ -20,12 +20,12 @@ * \brief C++ API: Locale matcher: User's desired locales vs. application's supported locales. */ -#ifndef U_HIDE_DRAFT_API +#ifndef U_FORCE_HIDE_DRAFT_API /** * Builder option for whether the language subtag or the script subtag is most important. * - * @see Builder#setFavorSubtag(FavorSubtag) + * @see Builder#setFavorSubtag(ULocMatchFavorSubtag) * @draft ICU 65 */ enum ULocMatchFavorSubtag { @@ -51,7 +51,7 @@ typedef enum ULocMatchFavorSubtag ULocMatchFavorSubtag; * Builder option for whether all desired locales are treated equally or * earlier ones are preferred. * - * @see Builder#setDemotionPerDesiredLocale(Demotion) + * @see Builder#setDemotionPerDesiredLocale(ULocMatchDemotion) * @draft ICU 65 */ enum ULocMatchDemotion { @@ -93,6 +93,42 @@ enum ULocMatchDemotion { typedef enum ULocMatchDemotion ULocMatchDemotion; #endif +/** + * Builder option for whether to include or ignore one-way (fallback) match data. + * The LocaleMatcher uses CLDR languageMatch data which includes fallback (oneway=true) entries. + * Sometimes it is desirable to ignore those. + * + *

For example, consider a web application with the UI in a given language, + * with a link to another, related web app. + * The link should include the UI language, and the target server may also use + * the client’s Accept-Language header data. + * The target server has its own list of supported languages. + * One may want to favor UI language consistency, that is, + * if there is a decent match for the original UI language, we want to use it, + * but not if it is merely a fallback. + * + * @see Builder#setDirection(ULocMatchDirection) + * @draft ICU 67 + */ +enum ULocMatchDirection { + /** + * Locale matching includes one-way matches such as Breton→French. (default) + * + * @draft ICU 67 + */ + ULOCMATCH_DIRECTION_WITH_ONE_WAY, + /** + * Locale matching limited to two-way matches including e.g. Danish↔Norwegian + * but ignoring one-way matches. + * + * @draft ICU 67 + */ + ULOCMATCH_DIRECTION_ONLY_TWO_WAY +}; +#ifndef U_IN_DOXYGEN +typedef enum ULocMatchDirection ULocMatchDirection; +#endif + struct UHashtable; U_NAMESPACE_BEGIN @@ -182,6 +218,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { */ Result &operator=(Result &&src) U_NOEXCEPT; +#ifndef U_HIDE_DRAFT_API /** * Returns the best-matching desired locale. * nullptr if the list of desired locales is empty or if none matched well enough. @@ -236,6 +273,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { * @draft ICU 65 */ Locale makeResolvedLocale(UErrorCode &errorCode) const; +#endif // U_HIDE_DRAFT_API private: Result(const Locale *desired, const Locale *supported, @@ -298,6 +336,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { */ Builder &operator=(Builder &&src) U_NOEXCEPT; +#ifndef U_HIDE_DRAFT_API /** * Parses an Accept-Language string * (RFC 2616 Section 14.4), @@ -412,6 +451,21 @@ class U_COMMON_API LocaleMatcher : public UMemory { */ Builder &setDemotionPerDesiredLocale(ULocMatchDemotion demotion); + /** + * Option for whether to include or ignore one-way (fallback) match data. + * By default, they are included. + * + * @param direction the match direction to set. + * @return this Builder object + * @draft ICU 67 + */ + Builder &setDirection(ULocMatchDirection direction) { + if (U_SUCCESS(errorCode_)) { + direction_ = direction; + } + return *this; + } + /** * Sets the UErrorCode if an error occurred while setting parameters. * Preserves older error codes in the outErrorCode. @@ -435,6 +489,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { * @draft ICU 65 */ LocaleMatcher build(UErrorCode &errorCode) const; +#endif // U_HIDE_DRAFT_API private: friend class LocaleMatcher; @@ -451,6 +506,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { ULocMatchDemotion demotion_ = ULOCMATCH_DEMOTION_REGION; Locale *defaultLocale_ = nullptr; ULocMatchFavorSubtag favor_ = ULOCMATCH_FAVOR_LANGUAGE; + ULocMatchDirection direction_ = ULOCMATCH_DIRECTION_WITH_ONE_WAY; }; // FYI No public LocaleMatcher constructors in C++; use the Builder. @@ -479,6 +535,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { */ LocaleMatcher &operator=(LocaleMatcher &&src) U_NOEXCEPT; +#ifndef U_HIDE_DRAFT_API /** * Returns the supported locale which best matches the desired locale. * @@ -546,6 +603,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { * @draft ICU 65 */ Result getBestMatchResult(Locale::Iterator &desiredLocales, UErrorCode &errorCode) const; +#endif // U_HIDE_DRAFT_API #ifndef U_HIDE_INTERNAL_API /** @@ -574,6 +632,8 @@ class U_COMMON_API LocaleMatcher : public UMemory { LocaleMatcher(const LocaleMatcher &other) = delete; LocaleMatcher &operator=(const LocaleMatcher &other) = delete; + int32_t putIfAbsent(const LSR &lsr, int32_t i, int32_t suppLength, UErrorCode &errorCode); + int32_t getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, UErrorCode &errorCode) const; const XLikelySubtags &likelySubtags; @@ -581,6 +641,7 @@ class U_COMMON_API LocaleMatcher : public UMemory { int32_t thresholdDistance; int32_t demotionPerDesiredLocale; ULocMatchFavorSubtag favorSubtag; + ULocMatchDirection direction; // These are in input order. const Locale ** supportedLocales; @@ -595,11 +656,10 @@ class U_COMMON_API LocaleMatcher : public UMemory { int32_t supportedLSRsLength; Locale *ownedDefaultLocale; const Locale *defaultLocale; - int32_t defaultLocaleIndex; }; U_NAMESPACE_END -#endif // U_HIDE_DRAFT_API +#endif // U_FORCE_HIDE_DRAFT_API #endif // U_SHOW_CPLUSPLUS_API #endif // __LOCALEMATCHER_H__ diff --git a/deps/icu-small/source/common/unicode/localpointer.h b/deps/icu-small/source/common/unicode/localpointer.h index e011688b1a54df..61c3020918e578 100644 --- a/deps/icu-small/source/common/unicode/localpointer.h +++ b/deps/icu-small/source/common/unicode/localpointer.h @@ -225,7 +225,6 @@ class LocalPointer : public LocalPointerBase { src.ptr=NULL; } -#ifndef U_HIDE_DRAFT_API /** * Constructs a LocalPointer from a C++11 std::unique_ptr. * The LocalPointer steals the object owned by the std::unique_ptr. @@ -234,11 +233,10 @@ class LocalPointer : public LocalPointerBase { * in a local variable, you must use std::move. * * @param p The std::unique_ptr from which the pointer will be stolen. - * @draft ICU 64 + * @stable ICU 64 */ explicit LocalPointer(std::unique_ptr &&p) : LocalPointerBase(p.release()) {} -#endif /* U_HIDE_DRAFT_API */ /** * Destructor deletes the object it owns. @@ -261,20 +259,18 @@ class LocalPointer : public LocalPointerBase { return *this; } -#ifndef U_HIDE_DRAFT_API /** * Move-assign from an std::unique_ptr to this LocalPointer. * Steals the pointer from the std::unique_ptr. * * @param p The std::unique_ptr from which the pointer will be stolen. * @return *this - * @draft ICU 64 + * @stable ICU 64 */ LocalPointer &operator=(std::unique_ptr &&p) U_NOEXCEPT { adoptInstead(p.release()); return *this; } -#endif /* U_HIDE_DRAFT_API */ /** * Swap pointers. @@ -332,7 +328,6 @@ class LocalPointer : public LocalPointerBase { } } -#ifndef U_HIDE_DRAFT_API /** * Conversion operator to a C++11 std::unique_ptr. * Disowns the object and gives it to the returned std::unique_ptr. @@ -342,12 +337,11 @@ class LocalPointer : public LocalPointerBase { * * @return An std::unique_ptr owning the pointer previously owned by this * icu::LocalPointer. - * @draft ICU 64 + * @stable ICU 64 */ operator std::unique_ptr () && { return std::unique_ptr(LocalPointerBase::orphan()); } -#endif /* U_HIDE_DRAFT_API */ }; /** @@ -406,7 +400,6 @@ class LocalArray : public LocalPointerBase { src.ptr=NULL; } -#ifndef U_HIDE_DRAFT_API /** * Constructs a LocalArray from a C++11 std::unique_ptr of an array type. * The LocalPointer steals the array owned by the std::unique_ptr. @@ -415,11 +408,10 @@ class LocalArray : public LocalPointerBase { * in a local variable, you must use std::move. * * @param p The std::unique_ptr from which the array will be stolen. - * @draft ICU 64 + * @stable ICU 64 */ explicit LocalArray(std::unique_ptr &&p) : LocalPointerBase(p.release()) {} -#endif /* U_HIDE_DRAFT_API */ /** * Destructor deletes the array it owns. @@ -442,20 +434,18 @@ class LocalArray : public LocalPointerBase { return *this; } -#ifndef U_HIDE_DRAFT_API /** * Move-assign from an std::unique_ptr to this LocalPointer. * Steals the array from the std::unique_ptr. * * @param p The std::unique_ptr from which the array will be stolen. * @return *this - * @draft ICU 64 + * @stable ICU 64 */ LocalArray &operator=(std::unique_ptr &&p) U_NOEXCEPT { adoptInstead(p.release()); return *this; } -#endif /* U_HIDE_DRAFT_API */ /** * Swap pointers. @@ -521,7 +511,6 @@ class LocalArray : public LocalPointerBase { */ T &operator[](ptrdiff_t i) const { return LocalPointerBase::ptr[i]; } -#ifndef U_HIDE_DRAFT_API /** * Conversion operator to a C++11 std::unique_ptr. * Disowns the object and gives it to the returned std::unique_ptr. @@ -531,12 +520,11 @@ class LocalArray : public LocalPointerBase { * * @return An std::unique_ptr owning the pointer previously owned by this * icu::LocalPointer. - * @draft ICU 64 + * @stable ICU 64 */ operator std::unique_ptr () && { return std::unique_ptr(LocalPointerBase::orphan()); } -#endif /* U_HIDE_DRAFT_API */ }; /** diff --git a/deps/icu-small/source/common/unicode/locid.h b/deps/icu-small/source/common/unicode/locid.h index 6fb0897fc05d95..ee8697b0a57f3e 100644 --- a/deps/icu-small/source/common/unicode/locid.h +++ b/deps/icu-small/source/common/unicode/locid.h @@ -448,7 +448,7 @@ class U_COMMON_API Locale : public UObject { /** * Creates a locale from the given string after canonicalizing - * the string by calling uloc_canonicalize(). + * the string according to CLDR by calling uloc_canonicalize(). * @param name the locale ID to create from. Must not be NULL. * @return a new locale object corresponding to the given name * @stable ICU 3.0 @@ -567,6 +567,16 @@ class U_COMMON_API Locale : public UObject { */ void minimizeSubtags(UErrorCode& status); +#ifndef U_HIDE_DRAFT_API + /** + * Canonicalize the locale ID of this object according to CLDR. + * @param status the status code + * @draft ICU 67 + * @see createCanonical + */ + void canonicalize(UErrorCode& status); +#endif // U_HIDE_DRAFT_API + /** * Gets the list of keywords for the specified locale. * diff --git a/deps/icu-small/source/common/unicode/platform.h b/deps/icu-small/source/common/unicode/platform.h index 74689d790cf79a..d6f792ba345b7e 100644 --- a/deps/icu-small/source/common/unicode/platform.h +++ b/deps/icu-small/source/common/unicode/platform.h @@ -828,7 +828,7 @@ namespace std { # define U_EXPORT #endif -/* U_CALLCONV is releated to U_EXPORT2 */ +/* U_CALLCONV is related to U_EXPORT2 */ #ifdef U_EXPORT2 /* Use the predefined value. */ #elif defined(_MSC_VER) diff --git a/deps/icu-small/source/common/unicode/stringpiece.h b/deps/icu-small/source/common/unicode/stringpiece.h index 15cebb0f202fe7..19fbe2e22eb032 100644 --- a/deps/icu-small/source/common/unicode/stringpiece.h +++ b/deps/icu-small/source/common/unicode/stringpiece.h @@ -67,19 +67,50 @@ class U_COMMON_API StringPiece : public UMemory { * Default constructor, creates an empty StringPiece. * @stable ICU 4.2 */ - StringPiece() : ptr_(NULL), length_(0) { } + StringPiece() : ptr_(nullptr), length_(0) { } + /** * Constructs from a NUL-terminated const char * pointer. * @param str a NUL-terminated const char * pointer * @stable ICU 4.2 */ StringPiece(const char* str); +#ifndef U_HIDE_DRAFT_API +#if defined(__cpp_char8_t) || defined(U_IN_DOXYGEN) + /** + * Constructs from a NUL-terminated const char8_t * pointer. + * @param str a NUL-terminated const char8_t * pointer + * @draft ICU 67 + */ + StringPiece(const char8_t* str) : StringPiece(reinterpret_cast(str)) {} +#endif + /** + * Constructs an empty StringPiece. + * Needed for type disambiguation from multiple other overloads. + * @param p nullptr + * @draft ICU 67 + */ + StringPiece(std::nullptr_t p) : ptr_(p), length_(0) {} +#endif // U_HIDE_DRAFT_API + /** * Constructs from a std::string. * @stable ICU 4.2 */ StringPiece(const std::string& str) : ptr_(str.data()), length_(static_cast(str.size())) { } +#ifndef U_HIDE_DRAFT_API +#if defined(__cpp_lib_char8_t) || defined(U_IN_DOXYGEN) + /** + * Constructs from a std::u8string. + * @draft ICU 67 + */ + StringPiece(const std::u8string& str) + : ptr_(reinterpret_cast(str.data())), + length_(static_cast(str.size())) { } +#endif +#endif // U_HIDE_DRAFT_API + #ifndef U_HIDE_DRAFT_API /** * Constructs from some other implementation of a string piece class, from any @@ -88,7 +119,7 @@ class U_COMMON_API StringPiece : public UMemory { * \code{.cpp} * * struct OtherStringPieceClass { - * const char* data(); + * const char* data(); // or const char8_t* * size_t size(); * }; * @@ -97,16 +128,25 @@ class U_COMMON_API StringPiece : public UMemory { * The other string piece class will typically be std::string_view from C++17 * or absl::string_view from Abseil. * + * Starting with C++20, data() may also return a const char8_t* pointer, + * as from std::u8string_view. + * * @param str the other string piece * @draft ICU 65 */ template ::value && + (std::is_same::value +#if defined(__cpp_char8_t) + || std::is_same::value +#endif + ) && std::is_same::value>::type> StringPiece(T str) - : ptr_(str.data()), length_(static_cast(str.size())) {} + : ptr_(reinterpret_cast(str.data())), + length_(static_cast(str.size())) {} #endif // U_HIDE_DRAFT_API + /** * Constructs from a const char * pointer and a specified length. * @param offset a const char * pointer (need not be terminated) @@ -114,6 +154,19 @@ class U_COMMON_API StringPiece : public UMemory { * @stable ICU 4.2 */ StringPiece(const char* offset, int32_t len) : ptr_(offset), length_(len) { } +#ifndef U_HIDE_DRAFT_API +#if defined(__cpp_char8_t) || defined(U_IN_DOXYGEN) + /** + * Constructs from a const char8_t * pointer and a specified length. + * @param str a const char8_t * pointer (need not be terminated) + * @param len the length of the string; must be non-negative + * @draft ICU 67 + */ + StringPiece(const char8_t* str, int32_t len) : + StringPiece(reinterpret_cast(str), len) {} +#endif +#endif // U_HIDE_DRAFT_API + /** * Substring of another StringPiece. * @param x the other StringPiece @@ -132,7 +185,7 @@ class U_COMMON_API StringPiece : public UMemory { StringPiece(const StringPiece& x, int32_t pos, int32_t len); /** - * Returns the string pointer. May be NULL if it is empty. + * Returns the string pointer. May be nullptr if it is empty. * * data() may return a pointer to a buffer with embedded NULs, and the * returned buffer may or may not be null terminated. Therefore it is @@ -165,7 +218,7 @@ class U_COMMON_API StringPiece : public UMemory { * Sets to an empty string. * @stable ICU 4.2 */ - void clear() { ptr_ = NULL; length_ = 0; } + void clear() { ptr_ = nullptr; length_ = 0; } /** * Reset the stringpiece to refer to new data. @@ -182,6 +235,29 @@ class U_COMMON_API StringPiece : public UMemory { */ void set(const char* str); +#ifndef U_HIDE_DRAFT_API +#if defined(__cpp_char8_t) || defined(U_IN_DOXYGEN) + /** + * Resets the stringpiece to refer to new data. + * @param xdata pointer the new string data. Need not be NUL-terminated. + * @param len the length of the new data + * @draft ICU 67 + */ + inline void set(const char8_t* xdata, int32_t len) { + set(reinterpret_cast(xdata), len); + } + + /** + * Resets the stringpiece to refer to new data. + * @param str a pointer to a NUL-terminated string. + * @draft ICU 67 + */ + inline void set(const char8_t* str) { + set(reinterpret_cast(str)); + } +#endif +#endif // U_HIDE_DRAFT_API + /** * Removes the first n string units. * @param n prefix length, must be non-negative and <=length() @@ -212,6 +288,26 @@ class U_COMMON_API StringPiece : public UMemory { } } +#ifndef U_HIDE_DRAFT_API + /** + * Searches the StringPiece for the given search string (needle); + * @param needle The string for which to search. + * @param offset Where to start searching within this string (haystack). + * @return The offset of needle in haystack, or -1 if not found. + * @draft ICU 67 + */ + int32_t find(StringPiece needle, int32_t offset); + + /** + * Compares this StringPiece with the other StringPiece, with semantics + * similar to std::string::compare(). + * @param other The string to compare to. + * @return below zero if this < other; above zero if this > other; 0 if this == other. + * @draft ICU 67 + */ + int32_t compare(StringPiece other); +#endif // U_HIDE_DRAFT_API + /** * Maximum integer, used as a default value for substring methods. * @stable ICU 4.2 diff --git a/deps/icu-small/source/common/unicode/uchar.h b/deps/icu-small/source/common/unicode/uchar.h index 1b7ee099be7ca2..3b55b2326dfc1f 100644 --- a/deps/icu-small/source/common/unicode/uchar.h +++ b/deps/icu-small/source/common/unicode/uchar.h @@ -60,7 +60,7 @@ U_CDECL_BEGIN * @see u_getUnicodeVersion * @stable ICU 2.0 */ -#define U_UNICODE_VERSION "12.1" +#define U_UNICODE_VERSION "13.0" /** * \file @@ -1788,6 +1788,25 @@ enum UBlockCode { /** @stable ICU 64 */ UBLOCK_WANCHO = 300, /*[1E2C0]*/ + // New blocks in Unicode 13.0 + + /** @stable ICU 66 */ + UBLOCK_CHORASMIAN = 301, /*[10FB0]*/ + /** @stable ICU 66 */ + UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_G = 302, /*[30000]*/ + /** @stable ICU 66 */ + UBLOCK_DIVES_AKURU = 303, /*[11900]*/ + /** @stable ICU 66 */ + UBLOCK_KHITAN_SMALL_SCRIPT = 304, /*[18B00]*/ + /** @stable ICU 66 */ + UBLOCK_LISU_SUPPLEMENT = 305, /*[11FB0]*/ + /** @stable ICU 66 */ + UBLOCK_SYMBOLS_FOR_LEGACY_COMPUTING = 306, /*[1FB00]*/ + /** @stable ICU 66 */ + UBLOCK_TANGUT_SUPPLEMENT = 307, /*[18D00]*/ + /** @stable ICU 66 */ + UBLOCK_YEZIDI = 308, /*[10E80]*/ + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal UBlockCode value. @@ -1795,7 +1814,7 @@ enum UBlockCode { * * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - UBLOCK_COUNT = 301, + UBLOCK_COUNT = 309, #endif // U_HIDE_DEPRECATED_API /** @stable ICU 2.0 */ @@ -2436,6 +2455,8 @@ typedef enum UIndicPositionalCategory { U_INPC_TOP_AND_RIGHT, /** @stable ICU 63 */ U_INPC_VISUAL_ORDER_LEFT, + /** @stable ICU 66 */ + U_INPC_TOP_AND_BOTTOM_AND_LEFT, } UIndicPositionalCategory; /** diff --git a/deps/icu-small/source/common/unicode/uloc.h b/deps/icu-small/source/common/unicode/uloc.h index 882f79bedca62c..a10ab526cec141 100644 --- a/deps/icu-small/source/common/unicode/uloc.h +++ b/deps/icu-small/source/common/unicode/uloc.h @@ -1034,29 +1034,45 @@ uloc_getLineOrientation(const char* localeId, UErrorCode *status); /** - * enums for the 'outResult' parameter return value + * Output values which uloc_acceptLanguage() writes to the 'outResult' parameter. + * * @see uloc_acceptLanguageFromHTTP * @see uloc_acceptLanguage * @stable ICU 3.2 */ typedef enum { - ULOC_ACCEPT_FAILED = 0, /* No exact match was found. */ - ULOC_ACCEPT_VALID = 1, /* An exact match was found. */ - ULOC_ACCEPT_FALLBACK = 2 /* A fallback was found, for example, - Accept list contained 'ja_JP' - which matched available locale 'ja'. */ + /** + * No exact match was found. + * @stable ICU 3.2 + */ + ULOC_ACCEPT_FAILED = 0, + /** + * An exact match was found. + * @stable ICU 3.2 + */ + ULOC_ACCEPT_VALID = 1, + /** + * A fallback was found. For example, the Accept-Language list includes 'ja_JP' + * and is matched with available locale 'ja'. + * @stable ICU 3.2 + */ + ULOC_ACCEPT_FALLBACK = 2 /* */ } UAcceptResult; - /** * Based on a HTTP header from a web browser and a list of available locales, * determine an acceptable locale for the user. + * + * This is a thin wrapper over C++ class LocaleMatcher. + * * @param result - buffer to accept the result locale * @param resultAvailable the size of the result buffer. * @param outResult - An out parameter that contains the fallback status * @param httpAcceptLanguage - "Accept-Language:" header as per HTTP. * @param availableLocales - list of available locales to match - * @param status Error status, may be BUFFER_OVERFLOW_ERROR + * @param status ICU error code. Its input value must pass the U_SUCCESS() test, + * or else the function returns immediately. Check for U_FAILURE() + * on output or use with function chaining. (See User Guide for details.) * @return length needed for the locale. * @stable ICU 3.2 */ @@ -1070,13 +1086,18 @@ uloc_acceptLanguageFromHTTP(char *result, int32_t resultAvailable, /** * Based on a list of available locales, * determine an acceptable locale for the user. + * + * This is a thin wrapper over C++ class LocaleMatcher. + * * @param result - buffer to accept the result locale * @param resultAvailable the size of the result buffer. * @param outResult - An out parameter that contains the fallback status * @param acceptList - list of acceptable languages * @param acceptListCount - count of acceptList items * @param availableLocales - list of available locales to match - * @param status Error status, may be BUFFER_OVERFLOW_ERROR + * @param status ICU error code. Its input value must pass the U_SUCCESS() test, + * or else the function returns immediately. Check for U_FAILURE() + * on output or use with function chaining. (See User Guide for details.) * @return length needed for the locale. * @stable ICU 3.2 */ diff --git a/deps/icu-small/source/common/unicode/umachine.h b/deps/icu-small/source/common/unicode/umachine.h index 5cb95e58f37295..ff5deb8d01786a 100644 --- a/deps/icu-small/source/common/unicode/umachine.h +++ b/deps/icu-small/source/common/unicode/umachine.h @@ -372,7 +372,7 @@ typedef int8_t UBool; typedef char16_t UChar; #elif defined(UCHAR_TYPE) typedef UCHAR_TYPE UChar; -#elif defined(__cplusplus) +#elif (U_CPLUSPLUS_VERSION >= 11) typedef char16_t UChar; #else typedef uint16_t UChar; diff --git a/deps/icu-small/source/common/unicode/umutablecptrie.h b/deps/icu-small/source/common/unicode/umutablecptrie.h index 13e71ef25e8c87..f2af36477d5300 100644 --- a/deps/icu-small/source/common/unicode/umutablecptrie.h +++ b/deps/icu-small/source/common/unicode/umutablecptrie.h @@ -83,25 +83,6 @@ umutablecptrie_clone(const UMutableCPTrie *other, UErrorCode *pErrorCode); U_CAPI void U_EXPORT2 umutablecptrie_close(UMutableCPTrie *trie); -#if U_SHOW_CPLUSPLUS_API - -U_NAMESPACE_BEGIN - -/** - * \class LocalUMutableCPTriePointer - * "Smart pointer" class, closes a UMutableCPTrie via umutablecptrie_close(). - * For most methods see the LocalPointerBase base class. - * - * @see LocalPointerBase - * @see LocalPointer - * @stable ICU 63 - */ -U_DEFINE_LOCAL_OPEN_POINTER(LocalUMutableCPTriePointer, UMutableCPTrie, umutablecptrie_close); - -U_NAMESPACE_END - -#endif - /** * Creates a mutable trie with the same contents as the UCPMap. * You must umutablecptrie_close() the mutable trie once you are done using it. @@ -235,4 +216,23 @@ umutablecptrie_buildImmutable(UMutableCPTrie *trie, UCPTrieType type, UCPTrieVal U_CDECL_END +#if U_SHOW_CPLUSPLUS_API + +U_NAMESPACE_BEGIN + +/** + * \class LocalUMutableCPTriePointer + * "Smart pointer" class, closes a UMutableCPTrie via umutablecptrie_close(). + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @stable ICU 63 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUMutableCPTriePointer, UMutableCPTrie, umutablecptrie_close); + +U_NAMESPACE_END + +#endif + #endif diff --git a/deps/icu-small/source/common/unicode/urename.h b/deps/icu-small/source/common/unicode/urename.h index e302bf0976e01d..30f4b7af39adc5 100644 --- a/deps/icu-small/source/common/unicode/urename.h +++ b/deps/icu-small/source/common/unicode/urename.h @@ -135,6 +135,7 @@ #define locale_get_default U_ICU_ENTRY_POINT_RENAME(locale_get_default) #define locale_set_default U_ICU_ENTRY_POINT_RENAME(locale_set_default) #define numSysCleanup U_ICU_ENTRY_POINT_RENAME(numSysCleanup) +#define rbbi_cleanup U_ICU_ENTRY_POINT_RENAME(rbbi_cleanup) #define pl_addFontRun U_ICU_ENTRY_POINT_RENAME(pl_addFontRun) #define pl_addLocaleRun U_ICU_ENTRY_POINT_RENAME(pl_addLocaleRun) #define pl_addValueRun U_ICU_ENTRY_POINT_RENAME(pl_addValueRun) @@ -192,13 +193,10 @@ #define res_findResource U_ICU_ENTRY_POINT_RENAME(res_findResource) #define res_getAlias U_ICU_ENTRY_POINT_RENAME(res_getAlias) #define res_getArrayItem U_ICU_ENTRY_POINT_RENAME(res_getArrayItem) -#define res_getBinary U_ICU_ENTRY_POINT_RENAME(res_getBinary) #define res_getBinaryNoTrace U_ICU_ENTRY_POINT_RENAME(res_getBinaryNoTrace) -#define res_getIntVector U_ICU_ENTRY_POINT_RENAME(res_getIntVector) #define res_getIntVectorNoTrace U_ICU_ENTRY_POINT_RENAME(res_getIntVectorNoTrace) #define res_getPublicType U_ICU_ENTRY_POINT_RENAME(res_getPublicType) #define res_getResource U_ICU_ENTRY_POINT_RENAME(res_getResource) -#define res_getString U_ICU_ENTRY_POINT_RENAME(res_getString) #define res_getStringNoTrace U_ICU_ENTRY_POINT_RENAME(res_getStringNoTrace) #define res_getTableItemByIndex U_ICU_ENTRY_POINT_RENAME(res_getTableItemByIndex) #define res_getTableItemByKey U_ICU_ENTRY_POINT_RENAME(res_getTableItemByKey) @@ -206,6 +204,7 @@ #define res_read U_ICU_ENTRY_POINT_RENAME(res_read) #define res_unload U_ICU_ENTRY_POINT_RENAME(res_unload) #define u_UCharsToChars U_ICU_ENTRY_POINT_RENAME(u_UCharsToChars) +#define u_asciiToUpper U_ICU_ENTRY_POINT_RENAME(u_asciiToUpper) #define u_austrcpy U_ICU_ENTRY_POINT_RENAME(u_austrcpy) #define u_austrncpy U_ICU_ENTRY_POINT_RENAME(u_austrncpy) #define u_caseInsensitivePrefixMatch U_ICU_ENTRY_POINT_RENAME(u_caseInsensitivePrefixMatch) @@ -899,6 +898,7 @@ #define udatpg_getBestPatternWithOptions U_ICU_ENTRY_POINT_RENAME(udatpg_getBestPatternWithOptions) #define udatpg_getDateTimeFormat U_ICU_ENTRY_POINT_RENAME(udatpg_getDateTimeFormat) #define udatpg_getDecimal U_ICU_ENTRY_POINT_RENAME(udatpg_getDecimal) +#define udatpg_getDefaultHourCycle U_ICU_ENTRY_POINT_RENAME(udatpg_getDefaultHourCycle) #define udatpg_getFieldDisplayName U_ICU_ENTRY_POINT_RENAME(udatpg_getFieldDisplayName) #define udatpg_getPatternForSkeleton U_ICU_ENTRY_POINT_RENAME(udatpg_getPatternForSkeleton) #define udatpg_getSkeleton U_ICU_ENTRY_POINT_RENAME(udatpg_getSkeleton) @@ -916,6 +916,7 @@ #define udtitvfmt_close U_ICU_ENTRY_POINT_RENAME(udtitvfmt_close) #define udtitvfmt_closeResult U_ICU_ENTRY_POINT_RENAME(udtitvfmt_closeResult) #define udtitvfmt_format U_ICU_ENTRY_POINT_RENAME(udtitvfmt_format) +#define udtitvfmt_formatCalendarToResult U_ICU_ENTRY_POINT_RENAME(udtitvfmt_formatCalendarToResult) #define udtitvfmt_formatToResult U_ICU_ENTRY_POINT_RENAME(udtitvfmt_formatToResult) #define udtitvfmt_open U_ICU_ENTRY_POINT_RENAME(udtitvfmt_open) #define udtitvfmt_openResult U_ICU_ENTRY_POINT_RENAME(udtitvfmt_openResult) @@ -1056,6 +1057,7 @@ #define ulistfmt_format U_ICU_ENTRY_POINT_RENAME(ulistfmt_format) #define ulistfmt_formatStringsToResult U_ICU_ENTRY_POINT_RENAME(ulistfmt_formatStringsToResult) #define ulistfmt_open U_ICU_ENTRY_POINT_RENAME(ulistfmt_open) +#define ulistfmt_openForType U_ICU_ENTRY_POINT_RENAME(ulistfmt_openForType) #define ulistfmt_openResult U_ICU_ENTRY_POINT_RENAME(ulistfmt_openResult) #define ulistfmt_resultAsValue U_ICU_ENTRY_POINT_RENAME(ulistfmt_resultAsValue) #define uloc_acceptLanguage U_ICU_ENTRY_POINT_RENAME(uloc_acceptLanguage) @@ -1117,9 +1119,12 @@ #define ulocdata_open U_ICU_ENTRY_POINT_RENAME(ulocdata_open) #define ulocdata_setNoSubstitute U_ICU_ENTRY_POINT_RENAME(ulocdata_setNoSubstitute) #define ulocimp_addLikelySubtags U_ICU_ENTRY_POINT_RENAME(ulocimp_addLikelySubtags) +#define ulocimp_canonicalize U_ICU_ENTRY_POINT_RENAME(ulocimp_canonicalize) #define ulocimp_forLanguageTag U_ICU_ENTRY_POINT_RENAME(ulocimp_forLanguageTag) +#define ulocimp_getBaseName U_ICU_ENTRY_POINT_RENAME(ulocimp_getBaseName) #define ulocimp_getCountry U_ICU_ENTRY_POINT_RENAME(ulocimp_getCountry) #define ulocimp_getLanguage U_ICU_ENTRY_POINT_RENAME(ulocimp_getLanguage) +#define ulocimp_getName U_ICU_ENTRY_POINT_RENAME(ulocimp_getName) #define ulocimp_getRegionForSupplementalData U_ICU_ENTRY_POINT_RENAME(ulocimp_getRegionForSupplementalData) #define ulocimp_getScript U_ICU_ENTRY_POINT_RENAME(ulocimp_getScript) #define ulocimp_minimizeSubtags U_ICU_ENTRY_POINT_RENAME(ulocimp_minimizeSubtags) @@ -1298,7 +1303,6 @@ #define uprv_convertToPosix U_ICU_ENTRY_POINT_RENAME(uprv_convertToPosix) #define uprv_copyAscii U_ICU_ENTRY_POINT_RENAME(uprv_copyAscii) #define uprv_copyEbcdic U_ICU_ENTRY_POINT_RENAME(uprv_copyEbcdic) -#define uprv_currencyLeads U_ICU_ENTRY_POINT_RENAME(uprv_currencyLeads) #define uprv_decContextClearStatus U_ICU_ENTRY_POINT_RENAME(uprv_decContextClearStatus) #define uprv_decContextDefault U_ICU_ENTRY_POINT_RENAME(uprv_decContextDefault) #define uprv_decContextGetRounding U_ICU_ENTRY_POINT_RENAME(uprv_decContextGetRounding) diff --git a/deps/icu-small/source/common/unicode/uscript.h b/deps/icu-small/source/common/unicode/uscript.h index c8babdf03068a3..53d57abed14cd0 100644 --- a/deps/icu-small/source/common/unicode/uscript.h +++ b/deps/icu-small/source/common/unicode/uscript.h @@ -475,6 +475,15 @@ typedef enum UScriptCode { /** @stable ICU 64 */ USCRIPT_WANCHO = 188,/* Wcho */ + /** @stable ICU 66 */ + USCRIPT_CHORASMIAN = 189,/* Chrs */ + /** @stable ICU 66 */ + USCRIPT_DIVES_AKURU = 190,/* Diak */ + /** @stable ICU 66 */ + USCRIPT_KHITAN_SMALL_SCRIPT = 191,/* Kits */ + /** @stable ICU 66 */ + USCRIPT_YEZIDI = 192,/* Yezi */ + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal UScriptCode value. @@ -482,7 +491,7 @@ typedef enum UScriptCode { * * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - USCRIPT_CODE_LIMIT = 189 + USCRIPT_CODE_LIMIT = 193 #endif // U_HIDE_DEPRECATED_API } UScriptCode; diff --git a/deps/icu-small/source/common/unicode/utext.h b/deps/icu-small/source/common/unicode/utext.h index 6f1e3409d8fdeb..d36c1c035e70f1 100644 --- a/deps/icu-small/source/common/unicode/utext.h +++ b/deps/icu-small/source/common/unicode/utext.h @@ -183,25 +183,6 @@ typedef struct UText UText; /**< C typedef for struct UText. @stable ICU 3.6 */ U_STABLE UText * U_EXPORT2 utext_close(UText *ut); -#if U_SHOW_CPLUSPLUS_API - -U_NAMESPACE_BEGIN - -/** - * \class LocalUTextPointer - * "Smart pointer" class, closes a UText via utext_close(). - * For most methods see the LocalPointerBase base class. - * - * @see LocalPointerBase - * @see LocalPointer - * @stable ICU 4.4 - */ -U_DEFINE_LOCAL_OPEN_POINTER(LocalUTextPointer, UText, utext_close); - -U_NAMESPACE_END - -#endif - /** * Open a read-only UText implementation for UTF-8 strings. * @@ -1599,5 +1580,24 @@ enum { U_CDECL_END +#if U_SHOW_CPLUSPLUS_API + +U_NAMESPACE_BEGIN + +/** + * \class LocalUTextPointer + * "Smart pointer" class, closes a UText via utext_close(). + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @stable ICU 4.4 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUTextPointer, UText, utext_close); + +U_NAMESPACE_END + +#endif + #endif diff --git a/deps/icu-small/source/common/unicode/utrace.h b/deps/icu-small/source/common/unicode/utrace.h index 0af050756fc38a..c7d51ff44f5bf7 100644 --- a/deps/icu-small/source/common/unicode/utrace.h +++ b/deps/icu-small/source/common/unicode/utrace.h @@ -177,6 +177,71 @@ typedef enum UTraceFunctionNumber { UTRACE_RES_DATA_LIMIT, #endif // U_HIDE_INTERNAL_API +#ifndef U_HIDE_DRAFT_API + /** + * The lowest break iterator location. + * @draft ICU 67 + */ + UTRACE_UBRK_START=0x4000, + + /** + * Indicates that a character instance of break iterator was created. + * + * @draft ICU 67 + */ + UTRACE_UBRK_CREATE_CHARACTER = UTRACE_UBRK_START, + + /** + * Indicates that a word instance of break iterator was created. + * + * @draft ICU 67 + */ + UTRACE_UBRK_CREATE_WORD, + + /** + * Indicates that a line instance of break iterator was created. + * + * Provides one C-style string to UTraceData: the lb value ("", + * "loose", "strict", or "normal"). + * + * @draft ICU 67 + */ + UTRACE_UBRK_CREATE_LINE, + + /** + * Indicates that a sentence instance of break iterator was created. + * + * @draft ICU 67 + */ + UTRACE_UBRK_CREATE_SENTENCE, + + /** + * Indicates that a title instance of break iterator was created. + * + * @draft ICU 67 + */ + UTRACE_UBRK_CREATE_TITLE, + + /** + * Indicates that an internal dictionary break engine was created. + * + * Provides one C-style string to UTraceData: the script code of what + * the break engine cover ("Hani", "Khmr", "Laoo", "Mymr", or "Thai"). + * + * @draft ICU 67 + */ + UTRACE_UBRK_CREATE_BREAK_ENGINE, + +#endif // U_HIDE_DRAFT_API + +#ifndef U_HIDE_INTERNAL_API + /** + * One more than the highest normal break iterator trace location. + * @internal The numeric value may change over time, see ICU ticket #12420. + */ + UTRACE_UBRK_LIMIT, +#endif // U_HIDE_INTERNAL_API + } UTraceFunctionNumber; /** diff --git a/deps/icu-small/source/common/unicode/uvernum.h b/deps/icu-small/source/common/unicode/uvernum.h index 0923c1d9189d0f..c66776d10b5826 100644 --- a/deps/icu-small/source/common/unicode/uvernum.h +++ b/deps/icu-small/source/common/unicode/uvernum.h @@ -60,7 +60,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION_MAJOR_NUM 65 +#define U_ICU_VERSION_MAJOR_NUM 67 /** The current ICU minor version as an integer. * This value will change in the subsequent releases of ICU @@ -86,7 +86,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.6 */ -#define U_ICU_VERSION_SUFFIX _65 +#define U_ICU_VERSION_SUFFIX _67 /** * \def U_DEF2_ICU_ENTRY_POINT_RENAME @@ -139,7 +139,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION "65.1" +#define U_ICU_VERSION "67.1" /** * The current ICU library major version number as a string, for library name suffixes. @@ -152,13 +152,13 @@ * * @stable ICU 2.6 */ -#define U_ICU_VERSION_SHORT "65" +#define U_ICU_VERSION_SHORT "67" #ifndef U_HIDE_INTERNAL_API /** Data version in ICU4C. * @internal ICU 4.4 Internal Use Only **/ -#define U_ICU_DATA_VERSION "65.1" +#define U_ICU_DATA_VERSION "67.1" #endif /* U_HIDE_INTERNAL_API */ /*=========================================================================== diff --git a/deps/icu-small/source/common/unistr.cpp b/deps/icu-small/source/common/unistr.cpp index eeb0c3a679a5e9..1c59de972d95ed 100644 --- a/deps/icu-small/source/common/unistr.cpp +++ b/deps/icu-small/source/common/unistr.cpp @@ -1563,7 +1563,11 @@ UnicodeString::doAppend(const UChar *srcChars, int32_t srcStart, int32_t srcLeng } int32_t oldLength = length(); - int32_t newLength = oldLength + srcLength; + int32_t newLength; + if (uprv_add32_overflow(oldLength, srcLength, &newLength)) { + setToBogus(); + return *this; + } // Check for append onto ourself const UChar* oldArray = getArrayStart(); diff --git a/deps/icu-small/source/common/uposixdefs.h b/deps/icu-small/source/common/uposixdefs.h index 45ca1233ac731a..23c3f6d466700c 100644 --- a/deps/icu-small/source/common/uposixdefs.h +++ b/deps/icu-small/source/common/uposixdefs.h @@ -68,4 +68,10 @@ # define _STDC_C99 #endif +#if !defined _POSIX_C_SOURCE && \ + defined(__APPLE__) && defined(__MACH__) && !defined(__clang__) +// Needed to prevent EOWNERDEAD issues with GCC on Mac +#define _POSIX_C_SOURCE 200809L +#endif + #endif /* __UPOSIXDEFS_H__ */ diff --git a/deps/icu-small/source/common/uprops.cpp b/deps/icu-small/source/common/uprops.cpp index 7d99675220eb5f..1604ad9a179bec 100644 --- a/deps/icu-small/source/common/uprops.cpp +++ b/deps/icu-small/source/common/uprops.cpp @@ -480,6 +480,11 @@ static int32_t getScript(const IntProperty &/*prop*/, UChar32 c, UProperty /*whi return (int32_t)uscript_getScript(c, &errorCode); } +static int32_t scriptGetMaxValue(const IntProperty &/*prop*/, UProperty /*which*/) { + uint32_t scriptX=uprv_getMaxValues(0)&UPROPS_SCRIPT_X_MASK; + return uprops_mergeScriptCodeOrIndex(scriptX); +} + /* * Map some of the Grapheme Cluster Break values to Hangul Syllable Types. * Hangul_Syllable_Type is fully redundant with a subset of Grapheme_Cluster_Break. @@ -586,7 +591,7 @@ static const IntProperty intProps[UCHAR_INT_LIMIT-UCHAR_INT_START]={ { UPROPS_SRC_BIDI, 0, 0, getJoiningType, biDiGetMaxValue }, { 2, UPROPS_LB_MASK, UPROPS_LB_SHIFT, defaultGetValue, defaultGetMaxValue }, { UPROPS_SRC_CHAR, 0, (int32_t)U_NT_COUNT-1, getNumericType, getMaxValueFromShift }, - { 0, UPROPS_SCRIPT_MASK, 0, getScript, defaultGetMaxValue }, + { UPROPS_SRC_PROPSVEC, 0, 0, getScript, scriptGetMaxValue }, { UPROPS_SRC_PROPSVEC, 0, (int32_t)U_HST_COUNT-1, getHangulSyllableType, getMaxValueFromShift }, // UCHAR_NFD_QUICK_CHECK: max=1=YES -- never "maybe", only "no" or "yes" { UPROPS_SRC_NFC, 0, (int32_t)UNORM_YES, getNormQuickCheck, getMaxValueFromShift }, diff --git a/deps/icu-small/source/common/uprops.h b/deps/icu-small/source/common/uprops.h index c7d648694ee5c3..8bf929919f200c 100644 --- a/deps/icu-small/source/common/uprops.h +++ b/deps/icu-small/source/common/uprops.h @@ -121,12 +121,12 @@ enum { * Properties in vector word 0 * Bits * 31..24 DerivedAge version major/minor one nibble each - * 23..22 3..1: Bits 7..0 = Script_Extensions index + * 23..22 3..1: Bits 21..20 & 7..0 = Script_Extensions index * 3: Script value from Script_Extensions * 2: Script=Inherited * 1: Script=Common - * 0: Script=bits 7..0 - * 21..20 reserved + * 0: Script=bits 21..20 & 7..0 + * 21..20 Bits 9..8 of the UScriptCode, or index to Script_Extensions * 19..17 East Asian Width * 16.. 8 UBlockCode * 7.. 0 UScriptCode, or index to Script_Extensions @@ -137,22 +137,43 @@ enum { #define UPROPS_AGE_SHIFT 24 /* Script_Extensions: mask includes Script */ -#define UPROPS_SCRIPT_X_MASK 0x00c000ff +#define UPROPS_SCRIPT_X_MASK 0x00f000ff #define UPROPS_SCRIPT_X_SHIFT 22 +// The UScriptCode or Script_Extensions index is split across two bit fields. +// (Starting with Unicode 13/ICU 66/2019 due to more varied Script_Extensions.) +// Shift the high bits right by 12 to assemble the full value. +#define UPROPS_SCRIPT_HIGH_MASK 0x00300000 +#define UPROPS_SCRIPT_HIGH_SHIFT 12 +#define UPROPS_MAX_SCRIPT 0x3ff + #define UPROPS_EA_MASK 0x000e0000 #define UPROPS_EA_SHIFT 17 #define UPROPS_BLOCK_MASK 0x0001ff00 #define UPROPS_BLOCK_SHIFT 8 -#define UPROPS_SCRIPT_MASK 0x000000ff +#define UPROPS_SCRIPT_LOW_MASK 0x000000ff /* UPROPS_SCRIPT_X_WITH_COMMON must be the lowest value that involves Script_Extensions. */ #define UPROPS_SCRIPT_X_WITH_COMMON 0x400000 #define UPROPS_SCRIPT_X_WITH_INHERITED 0x800000 #define UPROPS_SCRIPT_X_WITH_OTHER 0xc00000 +#ifdef __cplusplus + +namespace { + +inline uint32_t uprops_mergeScriptCodeOrIndex(uint32_t scriptX) { + return + ((scriptX & UPROPS_SCRIPT_HIGH_MASK) >> UPROPS_SCRIPT_HIGH_SHIFT) | + (scriptX & UPROPS_SCRIPT_LOW_MASK); +} + +} // namespace + +#endif // __cplusplus + /* * Properties in vector word 1 * Each bit encodes one binary property. diff --git a/deps/icu-small/source/common/uresbund.cpp b/deps/icu-small/source/common/uresbund.cpp index 3a9b4340bb4a38..f4efb8ccab5a0b 100644 --- a/deps/icu-small/source/common/uresbund.cpp +++ b/deps/icu-small/source/common/uresbund.cpp @@ -2611,8 +2611,8 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity, char defVal[1024] = ""; /* default value for given locale */ char defLoc[1024] = ""; /* default value for given locale */ char base[1024] = ""; /* base locale */ - char found[1024]; - char parent[1024]; + char found[1024] = ""; + char parent[1024] = ""; char full[1024] = ""; UResourceBundle bund1, bund2; UResourceBundle *res = NULL; diff --git a/deps/icu-small/source/common/uscript.cpp b/deps/icu-small/source/common/uscript.cpp index 98528c158b4387..f8bd7e7fdd1ae2 100644 --- a/deps/icu-small/source/common/uscript.cpp +++ b/deps/icu-small/source/common/uscript.cpp @@ -58,8 +58,8 @@ static int32_t getCodesFromLocale(const char *locale, UScriptCode *scripts, int32_t capacity, UErrorCode *err) { UErrorCode internalErrorCode = U_ZERO_ERROR; - char lang[8]; - char script[8]; + char lang[8] = {0}; + char script[8] = {0}; int32_t scriptLength; if(U_FAILURE(*err)) { return 0; } // Multi-script languages, equivalent to the LocaleScript data diff --git a/deps/icu-small/source/common/uscript_props.cpp b/deps/icu-small/source/common/uscript_props.cpp index ee120b4ca1d34a..25d287b57a3564 100644 --- a/deps/icu-small/source/common/uscript_props.cpp +++ b/deps/icu-small/source/common/uscript_props.cpp @@ -233,6 +233,10 @@ const int32_t SCRIPT_PROPS[] = { 0x1E108 | LIMITED_USE, // Hmnp 0x119CE | EXCLUSION, // Nand 0x1E2E1 | LIMITED_USE, // Wcho + 0x10FBF | EXCLUSION | RTL, // Chrs + 0x1190C | EXCLUSION, // Diak + 0x18C65 | EXCLUSION | LB_LETTERS, // Kits + 0x10E88 | EXCLUSION | RTL, // Yezi // End copy-paste from parsescriptmetadata.py }; diff --git a/deps/icu-small/source/common/ustr_imp.h b/deps/icu-small/source/common/ustr_imp.h index 943824fa197645..85d8e6d8ee6970 100644 --- a/deps/icu-small/source/common/ustr_imp.h +++ b/deps/icu-small/source/common/ustr_imp.h @@ -37,15 +37,27 @@ uprv_strCompare(const UChar *s1, int32_t length1, const UChar *s2, int32_t length2, UBool strncmpStyle, UBool codePointOrder); -U_CAPI int32_t U_EXPORT2 +U_INTERNAL int32_t U_EXPORT2 ustr_hashUCharsN(const UChar *str, int32_t length); -U_CAPI int32_t U_EXPORT2 +U_INTERNAL int32_t U_EXPORT2 ustr_hashCharsN(const char *str, int32_t length); -U_CAPI int32_t U_EXPORT2 +U_INTERNAL int32_t U_EXPORT2 ustr_hashICharsN(const char *str, int32_t length); +/** + * Convert an ASCII-range lowercase character to uppercase. + * + * @param c A UChar. + * @return If UChar is a lowercase ASCII character, returns the uppercase version. + * Otherwise, returns the input character. + */ +U_INTERNAL UChar U_EXPORT2 +u_asciiToUpper(UChar c); + +// TODO: Add u_asciiToLower if/when there is a need for it. + /** * NUL-terminate a UChar * string if possible. * If length < destCapacity then NUL-terminate. @@ -58,28 +70,28 @@ ustr_hashICharsN(const char *str, int32_t length); * @param pErrorCode ICU error code. * @return length */ -U_CAPI int32_t U_EXPORT2 +U_INTERNAL int32_t U_EXPORT2 u_terminateUChars(UChar *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode); /** * NUL-terminate a char * string if possible. * Same as u_terminateUChars() but for a different string type. */ -U_CAPI int32_t U_EXPORT2 +U_INTERNAL int32_t U_EXPORT2 u_terminateChars(char *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode); /** * NUL-terminate a UChar32 * string if possible. * Same as u_terminateUChars() but for a different string type. */ -U_CAPI int32_t U_EXPORT2 +U_INTERNAL int32_t U_EXPORT2 u_terminateUChar32s(UChar32 *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode); /** * NUL-terminate a wchar_t * string if possible. * Same as u_terminateUChars() but for a different string type. */ -U_CAPI int32_t U_EXPORT2 +U_INTERNAL int32_t U_EXPORT2 u_terminateWChars(wchar_t *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode); /** diff --git a/deps/icu-small/source/common/ustring.cpp b/deps/icu-small/source/common/ustring.cpp index 6886c145d9a216..375f66add44835 100644 --- a/deps/icu-small/source/common/ustring.cpp +++ b/deps/icu-small/source/common/ustring.cpp @@ -1451,6 +1451,14 @@ u_unescape(const char *src, UChar *dest, int32_t destCapacity) { } \ } UPRV_BLOCK_MACRO_END +U_CAPI UChar U_EXPORT2 +u_asciiToUpper(UChar c) { + if (u'a' <= c && c <= u'z') { + c = c + u'A' - u'a'; + } + return c; +} + U_CAPI int32_t U_EXPORT2 u_terminateUChars(UChar *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode) { __TERMINATE_STRING(dest, destCapacity, length, pErrorCode); diff --git a/deps/icu-small/source/common/utext.cpp b/deps/icu-small/source/common/utext.cpp index 324341f1ba65dc..ac828fbefa81bb 100644 --- a/deps/icu-small/source/common/utext.cpp +++ b/deps/icu-small/source/common/utext.cpp @@ -16,6 +16,8 @@ * created by: Markus W. Scherer */ +#include + #include "unicode/utypes.h" #include "unicode/ustring.h" #include "unicode/unistr.h" @@ -566,8 +568,8 @@ enum { // when a provider asks for a UText to be allocated with extra storage. struct ExtendedUText { - UText ut; - max_align_t extension; + UText ut; + std::max_align_t extension; }; static const UText emptyText = UTEXT_INITIALIZER; @@ -582,7 +584,7 @@ utext_setup(UText *ut, int32_t extraSpace, UErrorCode *status) { // We need to heap-allocate storage for the new UText int32_t spaceRequired = sizeof(UText); if (extraSpace > 0) { - spaceRequired = sizeof(ExtendedUText) + extraSpace - sizeof(max_align_t); + spaceRequired = sizeof(ExtendedUText) + extraSpace - sizeof(std::max_align_t); } ut = (UText *)uprv_malloc(spaceRequired); if (ut == NULL) { diff --git a/deps/icu-small/source/data/in/icudt65l.dat b/deps/icu-small/source/data/in/icudt67l.dat similarity index 50% rename from deps/icu-small/source/data/in/icudt65l.dat rename to deps/icu-small/source/data/in/icudt67l.dat index 5ac4e12176e634..cb69463d4e3d23 100644 Binary files a/deps/icu-small/source/data/in/icudt65l.dat and b/deps/icu-small/source/data/in/icudt67l.dat differ diff --git a/deps/icu-small/source/i18n/calendar.cpp b/deps/icu-small/source/i18n/calendar.cpp index 94625465614547..e8b718f3c4619d 100644 --- a/deps/icu-small/source/i18n/calendar.cpp +++ b/deps/icu-small/source/i18n/calendar.cpp @@ -958,7 +958,7 @@ Calendar::makeInstance(const Locale& aLocale, UErrorCode& success) { #endif c->setWeekData(aLocale, c->getType(), success); // set the correct locale (this was an indirected calendar) - char keyword[ULOC_FULLNAME_CAPACITY]; + char keyword[ULOC_FULLNAME_CAPACITY] = ""; UErrorCode tmpStatus = U_ZERO_ERROR; l.getKeywordValue("calendar", keyword, ULOC_FULLNAME_CAPACITY, tmpStatus); if (U_SUCCESS(tmpStatus) && uprv_strcmp(keyword, "iso8601") == 0) { diff --git a/deps/icu-small/source/i18n/collationfcd.cpp b/deps/icu-small/source/i18n/collationfcd.cpp index 2527f2f055a3f0..9f73ff38981f1c 100644 --- a/deps/icu-small/source/i18n/collationfcd.cpp +++ b/deps/icu-small/source/i18n/collationfcd.cpp @@ -31,18 +31,18 @@ const uint8_t CollationFCD::lcccIndex[2048]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0x26,0x26,0,0,0,0,0x27,0, 0,0,0,0,0,0x28,0,0,0,0x13,0,0,0,0,0,0, -0x29,0,0,0x2a,0,0x2b,0,0,0,0x26,0x2c,0x2d,0,0x2e,0,0x2f, -0,0x30,0,0,0,0,0x31,0x32,0,0,0,0,0,0,1,0x33, +0x29,0,0,0x2a,0,0x2b,0x2c,0,0,0x26,0x2d,0x2e,0,0x2f,0,0x30, +0,0x31,0,0,0,0,0x32,0x33,0,0,0,0,0,0,1,0x34, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0x34,0x35,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0x35,0x36,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0x36,0,0,0,0x37,0,0,0,1, +0,0,0,0,0,0,0,0x37,0,0,0,0x38,0,0,0,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0x38,0,0,0x39,0,0,0,0,0,0,0,0,0,0,0, +0,0x39,0,0,0x3a,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -101,9 +101,9 @@ const uint8_t CollationFCD::lcccIndex[2048]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0x3a,0x3b,0,0,0x3c,0,0,0,0,0,0,0,0, -0x23,0,0,0,0,0,0x2c,0x3d,0,0x3e,0x3f,0,0,0x3f,0x40,0, -0,0,0,0,0,0x41,0x42,0x43,0,0,0,0,0,0,0,0x18, +0,0,0,0x3b,0x3c,0,0,0x3d,0,0,0,0,0,0,0,0, +0x23,0x3e,0,0,0,0,0x2d,0x3f,0,0x40,0x41,0,0,0x41,0x2c,0, +0,0,0,0,0,0x42,0x43,0x44,0,0,0,0,0,0,0,0x18, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -126,7 +126,7 @@ const uint8_t CollationFCD::lcccIndex[2048]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x44,0x45,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x45,0x46,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,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, @@ -148,12 +148,12 @@ const uint8_t CollationFCD::lcccIndex[2048]={ 0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -const uint32_t CollationFCD::lcccBits[70]={ +const uint32_t CollationFCD::lcccBits[71]={ 0,0xffffffff,0xffff7fff,0xffff,0xf8,0xfffe0000,0xbfffffff,0xb6,0x7ff0000,0xfffff800,0x10000,0x9fc00000,0x3d9f,0x20000,0xffff0000,0x7ff, 0x200ff800,0xfbc00000,0x3eef,0xe000000,0xfff80000,0xfffffffb,0x10000000,0x1e2000,0x2000,0x40000000,0x602000,0x18000000,0x400,0x7000000,0xf00,0x3000000, -0x2a00000,0x3c3e0000,0xdf,0x40,0x6800000,0xe0000000,0x100000,0x20040000,0x200,0x1800000,0x9fe00001,0x3fff0000,0x10,0xff800,0xc00,0xc0040, -0x800000,0xfff70000,0x31021fd,0xfbffffff,0x1fff0000,0x1ffe2,0x38000,0x80000000,0xfc00,0x6000000,0x3ff08000,0xc0000000,0x30000,0x3ffff,0x3800,0x80000, -1,0xc19d0000,2,0x400000,0x40000fd,0x5108000 +0x2a00000,0x3c3e0000,0xdf,0x40,0x6800000,0xe0000000,0x100000,0x20040000,0x200,0x1800000,0x9fe00001,0xbfff0000,1,0x10,0xff800,0xc00, +0xc0040,0x800000,0xfff70000,0x31021fd,0xfbffffff,0x1fff0000,0x1ffe2,0x38000,0x80000000,0xfc00,0x6000000,0x3ff08000,0xc0000000,0x30000,0x1000,0x3ffff, +0x3800,0x80000,0xc19d0000,2,0x400000,0xc0000fd,0x5108000 }; const uint8_t CollationFCD::tcccIndex[2048]={ @@ -170,18 +170,18 @@ const uint8_t CollationFCD::tcccIndex[2048]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0x40,0x40,0,0,0,0,0x41,0, 0,0,0,0,0,0x42,0,0,0,0x28,0,0,0,0,0,0, -0x43,0,0,0x44,0,0x45,0,0,0,0x40,0x46,0x47,0,0x48,0,0x49, -0,0x4a,0,0,0,0,0x4b,0x4c,0,0,0,0,0,0,1,0x4d, -1,1,1,1,0x4e,1,1,0x4f,0x50,1,0x51,0x52,1,0x53,0x54,0x55, -0,0,0,0,0,0,0x56,0x57,0,0x58,0,0,0x59,0x5a,0x5b,0, -0x5c,0x5d,0x5e,0x5f,0x60,0x61,0,0x62,0,0,0,0,0,0,0,0, +0x43,0,0,0x44,0,0x45,0x46,0,0,0x40,0x47,0x48,0,0x49,0,0x4a, +0,0x4b,0,0,0,0,0x4c,0x4d,0,0,0,0,0,0,1,0x4e, +1,1,1,1,0x4f,1,1,0x50,0x51,1,0x52,0x53,1,0x54,0x55,0x56, +0,0,0,0,0,0,0x57,0x58,0,0x59,0,0,0x5a,0x5b,0x5c,0, +0x5d,0x5e,0x5f,0x60,0x61,0x62,0,0x63,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0x2d,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0x63,0,0,0,0x64,0,0,0,1, +0,0,0,0,0,0,0,0x64,0,0,0,0x65,0,0,0,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0x65,0x66,0x67,0x68,0x66,0x67,0x69,0,0,0,0,0,0,0,0, +0,0x66,0x67,0x68,0x69,0x67,0x68,0x6a,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -240,9 +240,9 @@ const uint8_t CollationFCD::tcccIndex[2048]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0x6a,0x6b,0,0,0x6c,0,0,0,0,0,0,0,0, -0x3d,0,0,0,0,0,0x46,0x6d,0,0x6e,0x6f,0,0,0x6f,0x70,0, -0,0,0,0,0,0x71,0x72,0x73,0,0,0,0,0,0,0,0x32, +0,0,0,0x6b,0x6c,0,0,0x6d,0,0,0,0,0,0,0,0, +0x3d,0x6e,0,0,0,0,0x47,0x6f,0,0x70,0x71,0,0,0x71,0x46,0, +0,0,0,0,0,0x72,0x73,0x74,0,0,0,0,0,0,0,0x32, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -265,7 +265,7 @@ const uint8_t CollationFCD::tcccIndex[2048]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x74,0x75,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x75,0x76,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -282,20 +282,20 @@ const uint8_t CollationFCD::tcccIndex[2048]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x3f,0x76,0x77,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x3f,0x77,0x78,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xe,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -const uint32_t CollationFCD::tcccBits[120]={ +const uint32_t CollationFCD::tcccBits[121]={ 0,0xffffffff,0x3e7effbf,0xbe7effbf,0xfffcffff,0x7ef1ff3f,0xfff3f1f8,0x7fffff3f,0x18003,0xdfffe000,0xff31ffcf,0xcfffffff,0xfffc0,0xffff7fff,0xffff,0x1d760, 0x1fc00,0x187c00,0x200708b,0x2000000,0x708b0000,0xc00000,0xf8,0xfccf0006,0x33ffcfc,0xfffe0000,0xbfffffff,0xb6,0x7ff0000,0x7c,0xfffff800,0x10000, 0x9fc80005,0x3d9f,0x20000,0xffff0000,0x7ff,0x200ff800,0xfbc00000,0x3eef,0xe000000,0xfff80000,0xfffffffb,0x10120200,0xff1e2000,0x10000000,0xb0002000,0x40000000, 0x10480000,0x4e002000,0x2000,0x30002000,0x602100,0x18000000,0x24000400,0x7000000,0xf00,0x3000000,0x2a00000,0x3d7e0000,0xdf,0x40,0x6800000,0xe0000000, -0x100000,0x20040000,0x200,0x1800000,0x9fe00001,0x3fff0000,0x10,0xff800,0xc00,0xc0040,0x800000,0xfff70000,0x31021fd,0xfbffffff,0xbffffff,0x3ffffff, -0x3f3fffff,0xaaff3f3f,0x3fffffff,0x1fdfffff,0xefcfffde,0x1fdc7fff,0x1fff0000,0x1ffe2,0x800,0xc000000,0x4000,0xe000,0x1210,0x50,0x292,0x333e005, -0x333,0xf000,0x3c0f,0x38000,0x80000000,0xfc00,0x55555000,0x36db02a5,0x46100000,0x47900000,0x3ff08000,0xc0000000,0x30000,0x3ffff,0x3800,0x80000, -1,0xc19d0000,2,0x400000,0x40000fd,0x5108000,0x5f7ffc00,0x7fdb +0x100000,0x20040000,0x200,0x1800000,0x9fe00001,0xbfff0000,1,0x10,0xff800,0xc00,0xc0040,0x800000,0xfff70000,0x31021fd,0xfbffffff,0xbffffff, +0x3ffffff,0x3f3fffff,0xaaff3f3f,0x3fffffff,0x1fdfffff,0xefcfffde,0x1fdc7fff,0x1fff0000,0x1ffe2,0x800,0xc000000,0x4000,0xe000,0x1210,0x50,0x292, +0x333e005,0x333,0xf000,0x3c0f,0x38000,0x80000000,0xfc00,0x55555000,0x36db02a5,0x46100000,0x47900000,0x3ff08000,0xc0000000,0x30000,0x1000,0x3ffff, +0x3800,0x80000,0xc19d0000,2,0x400000,0xc0000fd,0x5108000,0x5f7ffc00,0x7fdb }; U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/collationtailoring.h b/deps/icu-small/source/i18n/collationtailoring.h index 9a636cf1eb9aa3..e1bc34c7d7683b 100644 --- a/deps/icu-small/source/i18n/collationtailoring.h +++ b/deps/icu-small/source/i18n/collationtailoring.h @@ -92,7 +92,7 @@ struct U_I18N_API CollationTailoring : public SharedObject { CollationTailoring(const CollationTailoring &other); }; -struct CollationCacheEntry : public SharedObject { +struct U_I18N_API CollationCacheEntry : public SharedObject { CollationCacheEntry(const Locale &loc, const CollationTailoring *t) : validLocale(loc), tailoring(t) { if(t != NULL) { diff --git a/deps/icu-small/source/i18n/currunit.cpp b/deps/icu-small/source/i18n/currunit.cpp index 03347604a4c1fc..c1febf7df6d7e6 100644 --- a/deps/icu-small/source/i18n/currunit.cpp +++ b/deps/icu-small/source/i18n/currunit.cpp @@ -16,12 +16,12 @@ #include "unicode/currunit.h" #include "unicode/ustring.h" +#include "unicode/uchar.h" #include "cstring.h" #include "uinvchar.h" #include "charstr.h" - -static constexpr char16_t kDefaultCurrency[] = u"XXX"; -static constexpr char kDefaultCurrency8[] = "XXX"; +#include "ustr_imp.h" +#include "measunit_impl.h" U_NAMESPACE_BEGIN @@ -31,22 +31,25 @@ CurrencyUnit::CurrencyUnit(ConstChar16Ptr _isoCode, UErrorCode& ec) { // non-NUL-terminated string to be passed as an argument, so it is not possible to check length. // However, we allow a NUL-terminated empty string, which should have the same behavior as nullptr. // Consider NUL-terminated strings of length 1 or 2 as invalid. - const char16_t* isoCodeToUse; + bool useDefault = false; if (U_FAILURE(ec) || _isoCode == nullptr || _isoCode[0] == 0) { - isoCodeToUse = kDefaultCurrency; + useDefault = true; } else if (_isoCode[1] == 0 || _isoCode[2] == 0) { - isoCodeToUse = kDefaultCurrency; + useDefault = true; ec = U_ILLEGAL_ARGUMENT_ERROR; } else if (!uprv_isInvariantUString(_isoCode, 3)) { // TODO: Perform a more strict ASCII check like in ICU4J isAlpha3Code? - isoCodeToUse = kDefaultCurrency; + useDefault = true; ec = U_INVARIANT_CONVERSION_ERROR; } else { - isoCodeToUse = _isoCode; + for (int32_t i=0; i<3; i++) { + isoCode[i] = u_asciiToUpper(_isoCode[i]); + } + isoCode[3] = 0; + } + if (useDefault) { + uprv_memcpy(isoCode, kDefaultCurrency, sizeof(UChar) * 4); } - // TODO: Perform uppercasing here like in ICU4J Currency.getInstance()? - uprv_memcpy(isoCode, isoCodeToUse, sizeof(UChar) * 3); - isoCode[3] = 0; char simpleIsoCode[4]; u_UCharsToChars(isoCode, simpleIsoCode, 4); initCurrency(simpleIsoCode); @@ -66,13 +69,13 @@ CurrencyUnit::CurrencyUnit(StringPiece _isoCode, UErrorCode& ec) { ec = U_INVARIANT_CONVERSION_ERROR; } else { // Have to use isoCodeBuffer to ensure the string is NUL-terminated - uprv_strncpy(isoCodeBuffer, _isoCode.data(), 3); + for (int32_t i=0; i<3; i++) { + isoCodeBuffer[i] = uprv_toupper(_isoCode.data()[i]); + } isoCodeBuffer[3] = 0; isoCodeToUse = isoCodeBuffer; } - // TODO: Perform uppercasing here like in ICU4J Currency.getInstance()? - u_charsToUChars(isoCodeToUse, isoCode, 3); - isoCode[3] = 0; + u_charsToUChars(isoCodeToUse, isoCode, 4); initCurrency(isoCodeToUse); } diff --git a/deps/icu-small/source/i18n/dcfmtsym.cpp b/deps/icu-small/source/i18n/dcfmtsym.cpp index 04113785f27308..6f19182e2bfcf7 100644 --- a/deps/icu-small/source/i18n/dcfmtsym.cpp +++ b/deps/icu-small/source/i18n/dcfmtsym.cpp @@ -167,6 +167,7 @@ DecimalFormatSymbols::operator=(const DecimalFormatSymbols& rhs) fIsCustomCurrencySymbol = rhs.fIsCustomCurrencySymbol; fIsCustomIntlCurrencySymbol = rhs.fIsCustomIntlCurrencySymbol; fCodePointZero = rhs.fCodePointZero; + currPattern = rhs.currPattern; } return *this; } @@ -453,58 +454,16 @@ DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, } fCodePointZero = tempCodePointZero; - // Obtain currency data from the currency API. This is strictly - // for backward compatibility; we don't use DecimalFormatSymbols - // for currency data anymore. + // Get the default currency from the currency API. UErrorCode internalStatus = U_ZERO_ERROR; // don't propagate failures out UChar curriso[4]; UnicodeString tempStr; int32_t currisoLength = ucurr_forLocale(locStr, curriso, UPRV_LENGTHOF(curriso), &internalStatus); if (U_SUCCESS(internalStatus) && currisoLength == 3) { - uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus); - if (U_SUCCESS(internalStatus)) { - fSymbols[kIntlCurrencySymbol].setTo(curriso, currisoLength); - fSymbols[kCurrencySymbol] = tempStr; - } - } - /* else use the default values. */ - - //load the currency data - UChar ucc[4]={0}; //Currency Codes are always 3 chars long - int32_t uccLen = 4; - const char* locName = loc.getName(); - UErrorCode localStatus = U_ZERO_ERROR; - uccLen = ucurr_forLocale(locName, ucc, uccLen, &localStatus); - - // TODO: Currency pattern data loading is duplicated in number_formatimpl.cpp - if(U_SUCCESS(localStatus) && uccLen > 0) { - char cc[4]={0}; - u_UCharsToChars(ucc, cc, uccLen); - /* An explicit currency was requested */ - LocalUResourceBundlePointer currencyResource(ures_open(U_ICUDATA_CURR, locStr, &localStatus)); - LocalUResourceBundlePointer currency( - ures_getByKeyWithFallback(currencyResource.getAlias(), "Currencies", NULL, &localStatus)); - ures_getByKeyWithFallback(currency.getAlias(), cc, currency.getAlias(), &localStatus); - if(U_SUCCESS(localStatus) && ures_getSize(currency.getAlias())>2) { // the length is 3 if more data is present - ures_getByIndex(currency.getAlias(), 2, currency.getAlias(), &localStatus); - int32_t currPatternLen = 0; - currPattern = - ures_getStringByIndex(currency.getAlias(), (int32_t)0, &currPatternLen, &localStatus); - UnicodeString decimalSep = - ures_getUnicodeStringByIndex(currency.getAlias(), (int32_t)1, &localStatus); - UnicodeString groupingSep = - ures_getUnicodeStringByIndex(currency.getAlias(), (int32_t)2, &localStatus); - if(U_SUCCESS(localStatus)){ - fSymbols[kMonetaryGroupingSeparatorSymbol] = groupingSep; - fSymbols[kMonetarySeparatorSymbol] = decimalSep; - //pattern.setTo(TRUE, currPattern, currPatternLen); - status = localStatus; - } - } - /* else An explicit currency was requested and is unknown or locale data is malformed. */ - /* ucurr_* API will get the correct value later on. */ + setCurrency(curriso, status); + } else { + setCurrency(nullptr, status); } - // else ignore the error if no currency // Currency Spacing. LocalUResourceBundlePointer currencyResource(ures_open(U_ICUDATA_CURR, locStr, &status)); @@ -553,9 +512,54 @@ DecimalFormatSymbols::initialize() { fIsCustomIntlCurrencySymbol = FALSE; fCodePointZero = 0x30; U_ASSERT(fCodePointZero == fSymbols[kZeroDigitSymbol].char32At(0)); + currPattern = nullptr; } +void DecimalFormatSymbols::setCurrency(const UChar* currency, UErrorCode& status) { + // TODO: If this method is made public: + // - Adopt ICU4J behavior of not allowing currency to be null. + // - Also verify that the length of currency is 3. + if (!currency) { + return; + } + + UnicodeString tempStr; + uprv_getStaticCurrencyName(currency, locale.getName(), tempStr, status); + if (U_SUCCESS(status)) { + fSymbols[kIntlCurrencySymbol].setTo(currency, 3); + fSymbols[kCurrencySymbol] = tempStr; + } + + char cc[4]={0}; + u_UCharsToChars(currency, cc, 3); + + /* An explicit currency was requested */ + // TODO(ICU-13297): Move this data loading logic into a centralized place + UErrorCode localStatus = U_ZERO_ERROR; + LocalUResourceBundlePointer rbTop(ures_open(U_ICUDATA_CURR, locale.getName(), &localStatus)); + LocalUResourceBundlePointer rb( + ures_getByKeyWithFallback(rbTop.getAlias(), "Currencies", NULL, &localStatus)); + ures_getByKeyWithFallback(rb.getAlias(), cc, rb.getAlias(), &localStatus); + if(U_SUCCESS(localStatus) && ures_getSize(rb.getAlias())>2) { // the length is 3 if more data is present + ures_getByIndex(rb.getAlias(), 2, rb.getAlias(), &localStatus); + int32_t currPatternLen = 0; + currPattern = + ures_getStringByIndex(rb.getAlias(), (int32_t)0, &currPatternLen, &localStatus); + UnicodeString decimalSep = + ures_getUnicodeStringByIndex(rb.getAlias(), (int32_t)1, &localStatus); + UnicodeString groupingSep = + ures_getUnicodeStringByIndex(rb.getAlias(), (int32_t)2, &localStatus); + if(U_SUCCESS(localStatus)){ + fSymbols[kMonetaryGroupingSeparatorSymbol] = groupingSep; + fSymbols[kMonetarySeparatorSymbol] = decimalSep; + //pattern.setTo(TRUE, currPattern, currPatternLen); + } + } + /* else An explicit currency was requested and is unknown or locale data is malformed. */ + /* ucurr_* API will get the correct value later on. */ +} + Locale DecimalFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const { U_LOCALE_BASED(locBased, *this); diff --git a/deps/icu-small/source/i18n/decimfmt.cpp b/deps/icu-small/source/i18n/decimfmt.cpp index 6a69c9d7a300e6..275fe888a1b498 100644 --- a/deps/icu-small/source/i18n/decimfmt.cpp +++ b/deps/icu-small/source/i18n/decimfmt.cpp @@ -519,7 +519,9 @@ UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, Fie return appendTo; } UErrorCode localStatus = U_ZERO_ERROR; - FormattedNumber output = fields->formatter.formatDouble(number, localStatus); + UFormattedNumberData output; + output.quantity.setToDouble(number); + fields->formatter.formatImpl(&output, localStatus); fieldPositionHelper(output, pos, appendTo.length(), localStatus); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, localStatus); @@ -540,7 +542,9 @@ UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, Fie if (pos.getField() == FieldPosition::DONT_CARE && fastFormatDouble(number, appendTo)) { return appendTo; } - FormattedNumber output = fields->formatter.formatDouble(number, status); + UFormattedNumberData output; + output.quantity.setToDouble(number); + fields->formatter.formatImpl(&output, status); fieldPositionHelper(output, pos, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -562,7 +566,9 @@ DecimalFormat::format(double number, UnicodeString& appendTo, FieldPositionItera if (posIter == nullptr && fastFormatDouble(number, appendTo)) { return appendTo; } - FormattedNumber output = fields->formatter.formatDouble(number, status); + UFormattedNumberData output; + output.quantity.setToDouble(number); + fields->formatter.formatImpl(&output, status); fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -593,7 +599,9 @@ UnicodeString& DecimalFormat::format(int64_t number, UnicodeString& appendTo, Fi return appendTo; } UErrorCode localStatus = U_ZERO_ERROR; - FormattedNumber output = fields->formatter.formatInt(number, localStatus); + UFormattedNumberData output; + output.quantity.setToLong(number); + fields->formatter.formatImpl(&output, localStatus); fieldPositionHelper(output, pos, appendTo.length(), localStatus); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, localStatus); @@ -614,7 +622,9 @@ UnicodeString& DecimalFormat::format(int64_t number, UnicodeString& appendTo, Fi if (pos.getField() == FieldPosition::DONT_CARE && fastFormatInt64(number, appendTo)) { return appendTo; } - FormattedNumber output = fields->formatter.formatInt(number, status); + UFormattedNumberData output; + output.quantity.setToLong(number); + fields->formatter.formatImpl(&output, status); fieldPositionHelper(output, pos, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -636,7 +646,9 @@ DecimalFormat::format(int64_t number, UnicodeString& appendTo, FieldPositionIter if (posIter == nullptr && fastFormatInt64(number, appendTo)) { return appendTo; } - FormattedNumber output = fields->formatter.formatInt(number, status); + UFormattedNumberData output; + output.quantity.setToLong(number); + fields->formatter.formatImpl(&output, status); fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -655,7 +667,9 @@ DecimalFormat::format(StringPiece number, UnicodeString& appendTo, FieldPosition appendTo.setToBogus(); return appendTo; } - FormattedNumber output = fields->formatter.formatDecimal(number, status); + UFormattedNumberData output; + output.quantity.setToDecNumber(number, status); + fields->formatter.formatImpl(&output, status); fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -673,7 +687,9 @@ UnicodeString& DecimalFormat::format(const DecimalQuantity& number, UnicodeStrin appendTo.setToBogus(); return appendTo; } - FormattedNumber output = fields->formatter.formatDecimalQuantity(number, status); + UFormattedNumberData output; + output.quantity = number; + fields->formatter.formatImpl(&output, status); fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -692,7 +708,9 @@ DecimalFormat::format(const DecimalQuantity& number, UnicodeString& appendTo, Fi appendTo.setToBogus(); return appendTo; } - FormattedNumber output = fields->formatter.formatDecimalQuantity(number, status); + UFormattedNumberData output; + output.quantity = number; + fields->formatter.formatImpl(&output, status); fieldPositionHelper(output, pos, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -1502,8 +1520,11 @@ void DecimalFormat::setCurrency(const char16_t* theCurrency, UErrorCode& ec) { } NumberFormat::setCurrency(theCurrency, ec); // to set field for compatibility fields->properties.currency = currencyUnit; - // TODO: Set values in fields->symbols, too? - touchNoError(); + // In Java, the DecimalFormatSymbols is mutable. Why not in C++? + LocalPointer newSymbols(new DecimalFormatSymbols(*fields->symbols), ec); + newSymbols->setCurrency(currencyUnit.getISOCurrency(), ec); + fields->symbols.adoptInsteadAndCheckErrorCode(newSymbols.orphan(), ec); + touch(ec); } void DecimalFormat::setCurrency(const char16_t* theCurrency) { @@ -1700,8 +1721,11 @@ const numparse::impl::NumberParserImpl* DecimalFormat::getCurrencyParser(UErrorC } void -DecimalFormat::fieldPositionHelper(const number::FormattedNumber& formatted, FieldPosition& fieldPosition, - int32_t offset, UErrorCode& status) { +DecimalFormat::fieldPositionHelper( + const UFormattedNumberData& formatted, + FieldPosition& fieldPosition, + int32_t offset, + UErrorCode& status) { if (U_FAILURE(status)) { return; } // always return first occurrence: fieldPosition.setBeginIndex(0); @@ -1714,12 +1738,15 @@ DecimalFormat::fieldPositionHelper(const number::FormattedNumber& formatted, Fie } void -DecimalFormat::fieldPositionIteratorHelper(const number::FormattedNumber& formatted, FieldPositionIterator* fpi, - int32_t offset, UErrorCode& status) { +DecimalFormat::fieldPositionIteratorHelper( + const UFormattedNumberData& formatted, + FieldPositionIterator* fpi, + int32_t offset, + UErrorCode& status) { if (U_SUCCESS(status) && (fpi != nullptr)) { FieldPositionIteratorHandler fpih(fpi, status); fpih.setShift(offset); - formatted.getAllFieldPositionsImpl(fpih, status); + formatted.getAllFieldPositions(fpih, status); } } @@ -1801,7 +1828,7 @@ bool DecimalFormat::fastFormatDouble(double input, UnicodeString& output) const return false; } if (std::isnan(input) - || std::trunc(input) != input + || uprv_trunc(input) != input || input <= INT32_MIN || input > INT32_MAX) { return false; @@ -1834,7 +1861,8 @@ void DecimalFormat::doFastFormatInt32(int32_t input, bool isNegative, UnicodeStr char16_t localBuffer[localCapacity]; char16_t* ptr = localBuffer + localCapacity; int8_t group = 0; - for (int8_t i = 0; i < fields->fastData.maxInt && (input != 0 || i < fields->fastData.minInt); i++) { + int8_t minInt = (fields->fastData.minInt < 1)? 1: fields->fastData.minInt; + for (int8_t i = 0; i < fields->fastData.maxInt && (input != 0 || i < minInt); i++) { if (group++ == 3 && fields->fastData.cpGroupingSeparator != 0) { *(--ptr) = fields->fastData.cpGroupingSeparator; group = 1; diff --git a/deps/icu-small/source/i18n/double-conversion-ieee.h b/deps/icu-small/source/i18n/double-conversion-ieee.h index f4c62a9a9f8d99..31c35867de5610 100644 --- a/deps/icu-small/source/i18n/double-conversion-ieee.h +++ b/deps/icu-small/source/i18n/double-conversion-ieee.h @@ -59,6 +59,7 @@ class Double { static const uint64_t kExponentMask = DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF00000, 00000000); static const uint64_t kSignificandMask = DOUBLE_CONVERSION_UINT64_2PART_C(0x000FFFFF, FFFFFFFF); static const uint64_t kHiddenBit = DOUBLE_CONVERSION_UINT64_2PART_C(0x00100000, 00000000); + static const uint64_t kQuietNanBit = DOUBLE_CONVERSION_UINT64_2PART_C(0x00080000, 00000000); static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit. static const int kSignificandSize = 53; static const int kExponentBias = 0x3FF + kPhysicalSignificandSize; @@ -162,6 +163,15 @@ class Double { ((d64 & kSignificandMask) != 0); } + bool IsQuietNan() const { + return IsNan() && ((AsUint64() & kQuietNanBit) != 0); + } + + bool IsSignalingNan() const { + return IsNan() && ((AsUint64() & kQuietNanBit) == 0); + } + + bool IsInfinite() const { uint64_t d64 = AsUint64(); return ((d64 & kExponentMask) == kExponentMask) && @@ -280,6 +290,7 @@ class Single { static const uint32_t kExponentMask = 0x7F800000; static const uint32_t kSignificandMask = 0x007FFFFF; static const uint32_t kHiddenBit = 0x00800000; + static const uint32_t kQuietNanBit = 0x00400000; static const int kPhysicalSignificandSize = 23; // Excludes the hidden bit. static const int kSignificandSize = 24; @@ -338,6 +349,15 @@ class Single { ((d32 & kSignificandMask) != 0); } + bool IsQuietNan() const { + return IsNan() && ((AsUint32() & kQuietNanBit) != 0); + } + + bool IsSignalingNan() const { + return IsNan() && ((AsUint32() & kQuietNanBit) == 0); + } + + bool IsInfinite() const { uint32_t d32 = AsUint32(); return ((d32 & kExponentMask) == kExponentMask) && diff --git a/deps/icu-small/source/i18n/double-conversion-string-to-double.cpp b/deps/icu-small/source/i18n/double-conversion-string-to-double.cpp index 946b2b26e77aa4..548cad1f302241 100644 --- a/deps/icu-small/source/i18n/double-conversion-string-to-double.cpp +++ b/deps/icu-small/source/i18n/double-conversion-string-to-double.cpp @@ -462,11 +462,6 @@ double StringToDoubleConverter::StringToIeee( } } - // The longest form of simplified number is: "-.1eXXX\0". - const int kBufferSize = kMaxSignificantDigits + 10; - char buffer[kBufferSize]; // NOLINT: size is known at compile time. - int buffer_pos = 0; - // Exponent will be adjusted if insignificant digits of the integer part // or insignificant leading zeros of the fractional part are dropped. int exponent = 0; @@ -501,7 +496,6 @@ double StringToDoubleConverter::StringToIeee( return junk_string_value_; } - DOUBLE_CONVERSION_ASSERT(buffer_pos == 0); *processed_characters_count = static_cast(current - input); return sign ? -Double::Infinity() : Double::Infinity(); } @@ -520,7 +514,6 @@ double StringToDoubleConverter::StringToIeee( return junk_string_value_; } - DOUBLE_CONVERSION_ASSERT(buffer_pos == 0); *processed_characters_count = static_cast(current - input); return sign ? -Double::NaN() : Double::NaN(); } @@ -577,6 +570,12 @@ double StringToDoubleConverter::StringToIeee( bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0; + // The longest form of simplified number is: "-.1eXXX\0". + const int kBufferSize = kMaxSignificantDigits + 10; + DOUBLE_CONVERSION_STACK_UNINITIALIZED char + buffer[kBufferSize]; // NOLINT: size is known at compile time. + int buffer_pos = 0; + // Copy significant digits of the integer part (if any) to the buffer. while (*current >= '0' && *current <= '9') { if (significant_digits < kMaxSignificantDigits) { diff --git a/deps/icu-small/source/i18n/double-conversion-strtod.cpp b/deps/icu-small/source/i18n/double-conversion-strtod.cpp index 9cf4854426756c..ee6377782bb82f 100644 --- a/deps/icu-small/source/i18n/double-conversion-strtod.cpp +++ b/deps/icu-small/source/i18n/double-conversion-strtod.cpp @@ -49,10 +49,12 @@ U_NAMESPACE_BEGIN namespace double_conversion { +#if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) // 2^53 = 9007199254740992. // Any integer with at most 15 decimal digits will hence fit into a double // (which has a 53bit significand) without loss of precision. static const int kMaxExactDoubleIntegerDecimalDigits = 15; +#endif // #if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) // 2^64 = 18446744073709551616 > 10^19 static const int kMaxUint64DecimalDigits = 19; @@ -69,6 +71,7 @@ static const int kMinDecimalPower = -324; static const uint64_t kMaxUint64 = DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF); +#if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) static const double exact_powers_of_ten[] = { 1.0, // 10^0 10.0, @@ -96,6 +99,7 @@ static const double exact_powers_of_ten[] = { 10000000000000000000000.0 }; static const int kExactPowersOfTenSize = DOUBLE_CONVERSION_ARRAY_SIZE(exact_powers_of_ten); +#endif // #if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) // Maximum number of significant digits in the decimal representation. // In fact the value is 772 (see conversions.cc), but to give us some margin diff --git a/deps/icu-small/source/i18n/double-conversion-utils.h b/deps/icu-small/source/i18n/double-conversion-utils.h index 099298460c63d9..8c6a0e16e005fe 100644 --- a/deps/icu-small/source/i18n/double-conversion-utils.h +++ b/deps/icu-small/source/i18n/double-conversion-utils.h @@ -66,14 +66,28 @@ inline void abort_noreturn() { abort(); } #endif #endif +// Not all compilers support __has_attribute and combining a check for both +// ifdef and __has_attribute on the same preprocessor line isn't portable. +#ifdef __has_attribute +# define DOUBLE_CONVERSION_HAS_ATTRIBUTE(x) __has_attribute(x) +#else +# define DOUBLE_CONVERSION_HAS_ATTRIBUTE(x) 0 +#endif + #ifndef DOUBLE_CONVERSION_UNUSED -#ifdef __GNUC__ +#if DOUBLE_CONVERSION_HAS_ATTRIBUTE(unused) #define DOUBLE_CONVERSION_UNUSED __attribute__((unused)) #else #define DOUBLE_CONVERSION_UNUSED #endif #endif +#if DOUBLE_CONVERSION_HAS_ATTRIBUTE(uninitialized) +#define DOUBLE_CONVERSION_STACK_UNINITIALIZED __attribute__((uninitialized)) +#else +#define DOUBLE_CONVERSION_STACK_UNINITIALIZED +#endif + // Double operations detection based on target architecture. // Linux uses a 80bit wide floating point stack on x86. This induces double // rounding, which in turn leads to wrong results. @@ -104,6 +118,7 @@ int main(int argc, char** argv) { defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \ defined(__hppa__) || defined(__ia64__) || \ defined(__mips__) || \ + defined(__nios2__) || \ defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \ defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \ defined(__sparc__) || defined(__sparc) || defined(__s390__) || \ @@ -112,7 +127,8 @@ int main(int argc, char** argv) { defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \ defined(__riscv) || defined(__e2k__) || \ defined(__or1k__) || defined(__arc__) || \ - defined(__EMSCRIPTEN__) + defined(__microblaze__) || defined(__XTENSA__) || \ + defined(__EMSCRIPTEN__) || defined(__wasm32__) #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 #elif defined(__mc68000__) || \ defined(__pnacl__) || defined(__native_client__) diff --git a/deps/icu-small/source/i18n/dtitvfmt.cpp b/deps/icu-small/source/i18n/dtitvfmt.cpp index f47e7708ccc128..b71a571d1c490a 100644 --- a/deps/icu-small/source/i18n/dtitvfmt.cpp +++ b/deps/icu-small/source/i18n/dtitvfmt.cpp @@ -108,6 +108,10 @@ DateIntervalFormat::createInstance(const UnicodeString& skeleton, #endif DateIntervalInfo* dtitvinf = new DateIntervalInfo(locale, status); + if (dtitvinf == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } return create(locale, dtitvinf, &skeleton, status); } @@ -132,27 +136,27 @@ DateIntervalFormat::createInstance(const UnicodeString& skeleton, DateIntervalFormat::DateIntervalFormat() -: fInfo(NULL), - fDateFormat(NULL), - fFromCalendar(NULL), - fToCalendar(NULL), +: fInfo(nullptr), + fDateFormat(nullptr), + fFromCalendar(nullptr), + fToCalendar(nullptr), fLocale(Locale::getRoot()), - fDatePattern(NULL), - fTimePattern(NULL), - fDateTimeFormat(NULL) + fDatePattern(nullptr), + fTimePattern(nullptr), + fDateTimeFormat(nullptr) {} DateIntervalFormat::DateIntervalFormat(const DateIntervalFormat& itvfmt) : Format(itvfmt), - fInfo(NULL), - fDateFormat(NULL), - fFromCalendar(NULL), - fToCalendar(NULL), + fInfo(nullptr), + fDateFormat(nullptr), + fFromCalendar(nullptr), + fToCalendar(nullptr), fLocale(itvfmt.fLocale), - fDatePattern(NULL), - fTimePattern(NULL), - fDateTimeFormat(NULL) { + fDatePattern(nullptr), + fTimePattern(nullptr), + fDateTimeFormat(nullptr) { *this = itvfmt; } @@ -172,23 +176,23 @@ DateIntervalFormat::operator=(const DateIntervalFormat& itvfmt) { if ( itvfmt.fDateFormat ) { fDateFormat = itvfmt.fDateFormat->clone(); } else { - fDateFormat = NULL; + fDateFormat = nullptr; } if ( itvfmt.fFromCalendar ) { fFromCalendar = itvfmt.fFromCalendar->clone(); } else { - fFromCalendar = NULL; + fFromCalendar = nullptr; } if ( itvfmt.fToCalendar ) { fToCalendar = itvfmt.fToCalendar->clone(); } else { - fToCalendar = NULL; + fToCalendar = nullptr; } } if ( itvfmt.fInfo ) { fInfo = itvfmt.fInfo->clone(); } else { - fInfo = NULL; + fInfo = nullptr; } fSkeleton = itvfmt.fSkeleton; int8_t i; @@ -196,9 +200,9 @@ DateIntervalFormat::operator=(const DateIntervalFormat& itvfmt) { fIntervalPatterns[i] = itvfmt.fIntervalPatterns[i]; } fLocale = itvfmt.fLocale; - fDatePattern = (itvfmt.fDatePattern)? itvfmt.fDatePattern->clone(): NULL; - fTimePattern = (itvfmt.fTimePattern)? itvfmt.fTimePattern->clone(): NULL; - fDateTimeFormat = (itvfmt.fDateTimeFormat)? itvfmt.fDateTimeFormat->clone(): NULL; + fDatePattern = (itvfmt.fDatePattern)? itvfmt.fDatePattern->clone(): nullptr; + fTimePattern = (itvfmt.fTimePattern)? itvfmt.fTimePattern->clone(): nullptr; + fDateTimeFormat = (itvfmt.fDateTimeFormat)? itvfmt.fDateTimeFormat->clone(): nullptr; } return *this; } @@ -227,21 +231,21 @@ DateIntervalFormat::operator==(const Format& other) const { const DateIntervalFormat* fmt = (DateIntervalFormat*)&other; if (this == fmt) {return TRUE;} if (!Format::operator==(other)) {return FALSE;} - if ((fInfo != fmt->fInfo) && (fInfo == NULL || fmt->fInfo == NULL)) {return FALSE;} + if ((fInfo != fmt->fInfo) && (fInfo == nullptr || fmt->fInfo == nullptr)) {return FALSE;} if (fInfo && fmt->fInfo && (*fInfo != *fmt->fInfo )) {return FALSE;} { Mutex lock(&gFormatterMutex); - if (fDateFormat != fmt->fDateFormat && (fDateFormat == NULL || fmt->fDateFormat == NULL)) {return FALSE;} + if (fDateFormat != fmt->fDateFormat && (fDateFormat == nullptr || fmt->fDateFormat == nullptr)) {return FALSE;} if (fDateFormat && fmt->fDateFormat && (*fDateFormat != *fmt->fDateFormat)) {return FALSE;} } // note: fFromCalendar and fToCalendar hold no persistent state, and therefore do not participate in operator ==. // fDateFormat has the master calendar for the DateIntervalFormat. if (fSkeleton != fmt->fSkeleton) {return FALSE;} - if (fDatePattern != fmt->fDatePattern && (fDatePattern == NULL || fmt->fDatePattern == NULL)) {return FALSE;} + if (fDatePattern != fmt->fDatePattern && (fDatePattern == nullptr || fmt->fDatePattern == nullptr)) {return FALSE;} if (fDatePattern && fmt->fDatePattern && (*fDatePattern != *fmt->fDatePattern)) {return FALSE;} - if (fTimePattern != fmt->fTimePattern && (fTimePattern == NULL || fmt->fTimePattern == NULL)) {return FALSE;} + if (fTimePattern != fmt->fTimePattern && (fTimePattern == nullptr || fmt->fTimePattern == nullptr)) {return FALSE;} if (fTimePattern && fmt->fTimePattern && (*fTimePattern != *fmt->fTimePattern)) {return FALSE;} - if (fDateTimeFormat != fmt->fDateTimeFormat && (fDateTimeFormat == NULL || fmt->fDateTimeFormat == NULL)) {return FALSE;} + if (fDateTimeFormat != fmt->fDateTimeFormat && (fDateTimeFormat == nullptr || fmt->fDateTimeFormat == nullptr)) {return FALSE;} if (fDateTimeFormat && fmt->fDateTimeFormat && (*fDateTimeFormat != *fmt->fDateTimeFormat)) {return FALSE;} if (fLocale != fmt->fLocale) {return FALSE;} @@ -266,7 +270,7 @@ DateIntervalFormat::format(const Formattable& obj, if ( obj.getType() == Formattable::kObject ) { const UObject* formatObj = obj.getObject(); const DateInterval* interval = dynamic_cast(formatObj); - if (interval != NULL) { + if (interval != nullptr) { return format(interval, appendTo, fieldPosition, status); } } @@ -283,7 +287,7 @@ DateIntervalFormat::format(const DateInterval* dtInterval, if ( U_FAILURE(status) ) { return appendTo; } - if (fDateFormat == NULL || fInfo == NULL) { + if (fDateFormat == nullptr || fInfo == nullptr) { status = U_INVALID_STATE_ERROR; return appendTo; } @@ -300,6 +304,10 @@ DateIntervalFormat::format(const DateInterval* dtInterval, FormattedDateInterval DateIntervalFormat::formatToValue( const DateInterval& dtInterval, UErrorCode& status) const { + if (U_FAILURE(status)) { + return FormattedDateInterval(status); + } + // LocalPointer only sets OOM status if U_SUCCESS is true. LocalPointer result(new FormattedDateIntervalData(status), status); if (U_FAILURE(status)) { return FormattedDateInterval(status); @@ -350,6 +358,10 @@ FormattedDateInterval DateIntervalFormat::formatToValue( Calendar& fromCalendar, Calendar& toCalendar, UErrorCode& status) const { + if (U_FAILURE(status)) { + return FormattedDateInterval(status); + } + // LocalPointer only sets OOM status if U_SUCCESS is true. LocalPointer result(new FormattedDateIntervalData(status), status); if (U_FAILURE(status)) { return FormattedDateInterval(status); @@ -444,6 +456,9 @@ DateIntervalFormat::formatImpl(Calendar& fromCalendar, } else if ( fromCalendar.get(UCAL_SECOND, status) != toCalendar.get(UCAL_SECOND, status) ) { field = UCAL_SECOND; + } else if ( fromCalendar.get(UCAL_MILLISECOND, status) != + toCalendar.get(UCAL_MILLISECOND, status) ) { + field = UCAL_MILLISECOND; } if ( U_FAILURE(status) ) { @@ -455,7 +470,7 @@ DateIntervalFormat::formatImpl(Calendar& fromCalendar, */ return fDateFormat->_format(fromCalendar, appendTo, fphandler, status); } - UBool fromToOnSameDay = (field==UCAL_AM_PM || field==UCAL_HOUR || field==UCAL_MINUTE || field==UCAL_SECOND); + UBool fromToOnSameDay = (field==UCAL_AM_PM || field==UCAL_HOUR || field==UCAL_MINUTE || field==UCAL_SECOND || field==UCAL_MILLISECOND); // following call should not set wrong status, // all the pass-in fields are valid till here @@ -537,14 +552,17 @@ DateIntervalFormat::setDateIntervalInfo(const DateIntervalInfo& newItvPattern, UErrorCode& status) { delete fInfo; fInfo = new DateIntervalInfo(newItvPattern); + if (fInfo == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } // Delete patterns that get reset by initializePattern delete fDatePattern; - fDatePattern = NULL; + fDatePattern = nullptr; delete fTimePattern; - fTimePattern = NULL; + fTimePattern = nullptr; delete fDateTimeFormat; - fDateTimeFormat = NULL; + fDateTimeFormat = nullptr; if (fDateFormat) { initializePattern(status); @@ -562,7 +580,7 @@ DateIntervalFormat::getDateFormat() const { void DateIntervalFormat::adoptTimeZone(TimeZone* zone) { - if (fDateFormat != NULL) { + if (fDateFormat != nullptr) { fDateFormat->adoptTimeZone(zone); } // The fDateFormat has the master calendar for the DateIntervalFormat and has @@ -580,7 +598,7 @@ DateIntervalFormat::adoptTimeZone(TimeZone* zone) void DateIntervalFormat::setTimeZone(const TimeZone& zone) { - if (fDateFormat != NULL) { + if (fDateFormat != nullptr) { fDateFormat->setTimeZone(zone); } // The fDateFormat has the master calendar for the DateIntervalFormat; @@ -596,11 +614,11 @@ DateIntervalFormat::setTimeZone(const TimeZone& zone) const TimeZone& DateIntervalFormat::getTimeZone() const { - if (fDateFormat != NULL) { + if (fDateFormat != nullptr) { Mutex lock(&gFormatterMutex); return fDateFormat->getTimeZone(); } - // If fDateFormat is NULL (unexpected), create default timezone. + // If fDateFormat is nullptr (unexpected), create default timezone. return *(TimeZone::createDefault()); } @@ -608,14 +626,14 @@ DateIntervalFormat::DateIntervalFormat(const Locale& locale, DateIntervalInfo* dtItvInfo, const UnicodeString* skeleton, UErrorCode& status) -: fInfo(NULL), - fDateFormat(NULL), - fFromCalendar(NULL), - fToCalendar(NULL), +: fInfo(nullptr), + fDateFormat(nullptr), + fFromCalendar(nullptr), + fToCalendar(nullptr), fLocale(locale), - fDatePattern(NULL), - fTimePattern(NULL), - fDateTimeFormat(NULL) + fDatePattern(nullptr), + fTimePattern(nullptr), + fDateTimeFormat(nullptr) { LocalPointer info(dtItvInfo, status); LocalPointer dtfmt(static_cast( @@ -643,7 +661,7 @@ DateIntervalFormat::create(const Locale& locale, UErrorCode& status) { DateIntervalFormat* f = new DateIntervalFormat(locale, dtitvinf, skeleton, status); - if ( f == NULL ) { + if ( f == nullptr ) { status = U_MEMORY_ALLOCATION_ERROR; delete dtitvinf; } else if ( U_FAILURE(status) ) { @@ -760,7 +778,7 @@ DateIntervalFormat::initializePattern(UErrorCode& status) { // with the time interval. // The date/time pattern ( such as {0} {1} ) is saved in // calendar, that is why need to get the CalendarData here. - LocalUResourceBundlePointer dateTimePatternsRes(ures_open(NULL, locale.getBaseName(), &status)); + LocalUResourceBundlePointer dateTimePatternsRes(ures_open(nullptr, locale.getBaseName(), &status)); ures_getByKey(dateTimePatternsRes.getAlias(), gCalendarTag, dateTimePatternsRes.getAlias(), &status); ures_getByKeyWithFallback(dateTimePatternsRes.getAlias(), gGregorianTag, @@ -775,6 +793,10 @@ DateIntervalFormat::initializePattern(UErrorCode& status) { &dateTimeFormatLength, &status); if ( U_SUCCESS(status) && dateTimeFormatLength >= 3 ) { fDateTimeFormat = new UnicodeString(dateTimeFormat, dateTimeFormatLength); + if (fDateTimeFormat == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } } } @@ -798,9 +820,9 @@ DateIntervalFormat::initializePattern(UErrorCode& status) { // the first part of the pattern is empty, // the second part of the pattern is the full-pattern // should be used in fall-back. - setPatternInfo(UCAL_DATE, NULL, &pattern, fInfo->getDefaultOrder()); - setPatternInfo(UCAL_MONTH, NULL, &pattern, fInfo->getDefaultOrder()); - setPatternInfo(UCAL_YEAR, NULL, &pattern, fInfo->getDefaultOrder()); + setPatternInfo(UCAL_DATE, nullptr, &pattern, fInfo->getDefaultOrder()); + setPatternInfo(UCAL_MONTH, nullptr, &pattern, fInfo->getDefaultOrder()); + setPatternInfo(UCAL_YEAR, nullptr, &pattern, fInfo->getDefaultOrder()); } else { // TODO: fall back } @@ -824,9 +846,9 @@ DateIntervalFormat::initializePattern(UErrorCode& status) { // the first part of the pattern is empty, // the second part of the pattern is the full-pattern // should be used in fall-back. - setPatternInfo(UCAL_DATE, NULL, &pattern, fInfo->getDefaultOrder()); - setPatternInfo(UCAL_MONTH, NULL, &pattern, fInfo->getDefaultOrder()); - setPatternInfo(UCAL_YEAR, NULL, &pattern, fInfo->getDefaultOrder()); + setPatternInfo(UCAL_DATE, nullptr, &pattern, fInfo->getDefaultOrder()); + setPatternInfo(UCAL_MONTH, nullptr, &pattern, fInfo->getDefaultOrder()); + setPatternInfo(UCAL_YEAR, nullptr, &pattern, fInfo->getDefaultOrder()); } else { /* if both present, * 1) when the year, month, or day differs, @@ -861,7 +883,7 @@ DateIntervalFormat::initializePattern(UErrorCode& status) { * range expression for the time. */ - if ( fDateTimeFormat == NULL ) { + if ( fDateTimeFormat == nullptr ) { // earlier failure getting dateTimeFormat return; } @@ -1071,16 +1093,16 @@ DateIntervalFormat::setSeparateDateTimePtn( int8_t differenceInfo = 0; const UnicodeString* bestSkeleton = fInfo->getBestSkeleton(*skeleton, differenceInfo); - /* best skeleton could be NULL. + /* best skeleton could be nullptr. For example: in "ca" resource file, interval format is defined as following intervalFormats{ fallback{"{0} - {1}"} } there is no skeletons/interval patterns defined, - and the best skeleton match could be NULL + and the best skeleton match could be nullptr */ - if ( bestSkeleton == NULL ) { + if ( bestSkeleton == nullptr ) { return false; } @@ -1091,11 +1113,13 @@ DateIntervalFormat::setSeparateDateTimePtn( status = U_ZERO_ERROR; fDatePattern = new UnicodeString(DateFormat::getBestPattern( fLocale, dateSkeleton, status)); + // no way to report OOM. :( } if ( timeSkeleton.length() != 0) { status = U_ZERO_ERROR; fTimePattern = new UnicodeString(DateFormat::getBestPattern( fLocale, timeSkeleton, status)); + // no way to report OOM. :( } // difference: @@ -1151,7 +1175,7 @@ DateIntervalFormat::setFallbackPattern(UCalendarDateFields field, if ( U_FAILURE(status) ) { return; } - setPatternInfo(field, NULL, &pattern, fInfo->getDefaultOrder()); + setPatternInfo(field, nullptr, &pattern, fInfo->getDefaultOrder()); } diff --git a/deps/icu-small/source/i18n/dtitvinf.cpp b/deps/icu-small/source/i18n/dtitvinf.cpp index 35ee8c16261934..25536346ec74f0 100644 --- a/deps/icu-small/source/i18n/dtitvinf.cpp +++ b/deps/icu-small/source/i18n/dtitvinf.cpp @@ -50,6 +50,7 @@ U_NAMESPACE_BEGIN UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateIntervalInfo) static const char gCalendarTag[]="calendar"; +static const char gGenericTag[]="generic"; static const char gGregorianTag[]="gregorian"; static const char gIntervalDateTimePatternTag[]="intervalFormats"; static const char gFallbackPatternTag[]="fallback"; @@ -65,7 +66,7 @@ static const UChar gDefaultFallbackPattern[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, DateIntervalInfo::DateIntervalInfo(UErrorCode& status) : fFallbackIntervalPattern(gDefaultFallbackPattern), fFirstDateInPtnIsLaterDate(false), - fIntervalPatterns(NULL) + fIntervalPatterns(nullptr) { fIntervalPatterns = initHash(status); } @@ -75,7 +76,7 @@ DateIntervalInfo::DateIntervalInfo(UErrorCode& status) DateIntervalInfo::DateIntervalInfo(const Locale& locale, UErrorCode& status) : fFallbackIntervalPattern(gDefaultFallbackPattern), fFirstDateInPtnIsLaterDate(false), - fIntervalPatterns(NULL) + fIntervalPatterns(nullptr) { initializeData(locale, status); } @@ -125,7 +126,7 @@ DateIntervalInfo::setFallbackIntervalPattern( DateIntervalInfo::DateIntervalInfo(const DateIntervalInfo& dtitvinf) : UObject(dtitvinf), - fIntervalPatterns(NULL) + fIntervalPatterns(nullptr) { *this = dtitvinf; } @@ -160,7 +161,7 @@ DateIntervalInfo::clone() const { DateIntervalInfo::~DateIntervalInfo() { deleteHash(fIntervalPatterns); - fIntervalPatterns = NULL; + fIntervalPatterns = nullptr; } @@ -188,7 +189,7 @@ DateIntervalInfo::getIntervalPattern(const UnicodeString& skeleton, } const UnicodeString* patternsOfOneSkeleton = (UnicodeString*) fIntervalPatterns->get(skeleton); - if ( patternsOfOneSkeleton != NULL ) { + if ( patternsOfOneSkeleton != nullptr ) { IntervalPatternIndex index = calendarFieldToIntervalIndex(field, status); if ( U_FAILURE(status) ) { return result; @@ -362,7 +363,7 @@ struct DateIntervalInfo::DateIntervalSink : public ResourceSink { UnicodeString* patternsOfOneSkeleton = (UnicodeString*)(dateIntervalInfo.fIntervalPatterns->get(skeleton)); - if (patternsOfOneSkeleton == NULL || patternsOfOneSkeleton[index].isEmpty()) { + if (patternsOfOneSkeleton == nullptr || patternsOfOneSkeleton[index].isEmpty()) { UnicodeString pattern = value.getUnicodeString(errorCode); dateIntervalInfo.setIntervalPatternInternally(skeleton, lrgDiffCalUnit, pattern, errorCode); @@ -397,8 +398,8 @@ DateIntervalInfo::initializeData(const Locale& locale, UErrorCode& status) char calendarType[ULOC_KEYWORDS_CAPACITY]; // to be filled in with the type to use, if all goes well char localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY]; // obtain a locale that always has the calendar key value that should be used - (void)ures_getFunctionalEquivalent(localeWithCalendarKey, ULOC_LOCALE_IDENTIFIER_CAPACITY, NULL, - "calendar", "calendar", locName, NULL, FALSE, &status); + (void)ures_getFunctionalEquivalent(localeWithCalendarKey, ULOC_LOCALE_IDENTIFIER_CAPACITY, nullptr, + "calendar", "calendar", locName, nullptr, FALSE, &status); localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination // now get the calendar key value from that locale int32_t calendarTypeLen = uloc_getKeywordValue(localeWithCalendarKey, "calendar", calendarType, @@ -410,25 +411,47 @@ DateIntervalInfo::initializeData(const Locale& locale, UErrorCode& status) // Instantiate the resource bundles UResourceBundle *rb, *calBundle; - rb = ures_open(NULL, locName, &status); + rb = ures_open(nullptr, locName, &status); if (U_FAILURE(status)) { return; } - calBundle = ures_getByKeyWithFallback(rb, gCalendarTag, NULL, &status); + calBundle = ures_getByKeyWithFallback(rb, gCalendarTag, nullptr, &status); if (U_SUCCESS(status)) { UResourceBundle *calTypeBundle, *itvDtPtnResource; // Get the fallback pattern - const UChar* resStr; + const UChar* resStr = nullptr; int32_t resStrLen = 0; - calTypeBundle = ures_getByKeyWithFallback(calBundle, calendarTypeToUse, NULL, &status); + calTypeBundle = ures_getByKeyWithFallback(calBundle, calendarTypeToUse, nullptr, &status); itvDtPtnResource = ures_getByKeyWithFallback(calTypeBundle, - gIntervalDateTimePatternTag, NULL, &status); - resStr = ures_getStringByKeyWithFallback(itvDtPtnResource, gFallbackPatternTag, - &resStrLen, &status); + gIntervalDateTimePatternTag, nullptr, &status); + // TODO(ICU-20400): After the fixing, we should find the "fallback" from + // the rb directly by the path "calendar/${calendar}/intervalFormats/fallback". if ( U_SUCCESS(status) ) { + resStr = ures_getStringByKeyWithFallback(itvDtPtnResource, gFallbackPatternTag, + &resStrLen, &status); + if ( U_FAILURE(status) ) { + // Try to find "fallback" from "generic" to work around the bug in + // ures_getByKeyWithFallback + UErrorCode localStatus = U_ZERO_ERROR; + UResourceBundle *genericCalBundle = + ures_getByKeyWithFallback(calBundle, gGenericTag, nullptr, &localStatus); + UResourceBundle *genericItvDtPtnResource = + ures_getByKeyWithFallback( + genericCalBundle, gIntervalDateTimePatternTag, nullptr, &localStatus); + resStr = ures_getStringByKeyWithFallback( + genericItvDtPtnResource, gFallbackPatternTag, &resStrLen, &localStatus); + ures_close(genericItvDtPtnResource); + ures_close(genericCalBundle); + if ( U_SUCCESS(localStatus) ) { + status = U_USING_FALLBACK_WARNING;; + } + } + } + + if ( U_SUCCESS(status) && (resStr != nullptr)) { UnicodeString pattern = UnicodeString(TRUE, resStr, resStrLen); setFallbackIntervalPattern(pattern, status); } @@ -486,8 +509,12 @@ DateIntervalInfo::setIntervalPatternInternally(const UnicodeString& skeleton, } UnicodeString* patternsOfOneSkeleton = (UnicodeString*)(fIntervalPatterns->get(skeleton)); UBool emptyHash = false; - if ( patternsOfOneSkeleton == NULL ) { + if ( patternsOfOneSkeleton == nullptr ) { patternsOfOneSkeleton = new UnicodeString[kIPI_MAX_INDEX]; + if (patternsOfOneSkeleton == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } emptyHash = true; } @@ -585,7 +612,7 @@ DateIntervalInfo::getBestSkeleton(const UnicodeString& skeleton, parseSkeleton(*inputSkeleton, inputSkeletonFieldWidth); int32_t bestDistance = MAX_POSITIVE_INT; - const UnicodeString* bestSkeleton = NULL; + const UnicodeString* bestSkeleton = nullptr; // 0 means exact the same skeletons; // 1 means having the same field, but with different length, @@ -595,8 +622,8 @@ DateIntervalInfo::getBestSkeleton(const UnicodeString& skeleton, int8_t fieldLength = UPRV_LENGTHOF(skeletonFieldWidth); int32_t pos = UHASH_FIRST; - const UHashElement* elem = NULL; - while ( (elem = fIntervalPatterns->nextElement(pos)) != NULL ) { + const UHashElement* elem = nullptr; + while ( (elem = fIntervalPatterns->nextElement(pos)) != nullptr ) { const UHashTok keyTok = elem->key; UnicodeString* newSkeleton = (UnicodeString*)keyTok.pointer; #ifdef DTITVINF_DEBUG @@ -688,6 +715,9 @@ DateIntervalInfo::calendarFieldToIntervalIndex(UCalendarDateFields field, case UCAL_SECOND: index = kIPI_SECOND; break; + case UCAL_MILLISECOND: + index = kIPI_MILLISECOND; + break; default: status = U_ILLEGAL_ARGUMENT_ERROR; } @@ -699,12 +729,12 @@ DateIntervalInfo::calendarFieldToIntervalIndex(UCalendarDateFields field, void DateIntervalInfo::deleteHash(Hashtable* hTable) { - if ( hTable == NULL ) { + if ( hTable == nullptr ) { return; } int32_t pos = UHASH_FIRST; - const UHashElement* element = NULL; - while ( (element = hTable->nextElement(pos)) != NULL ) { + const UHashElement* element = nullptr; + while ( (element = hTable->nextElement(pos)) != nullptr ) { const UHashTok valueTok = element->value; const UnicodeString* value = (UnicodeString*)valueTok.pointer; delete[] value; @@ -742,16 +772,16 @@ U_CDECL_END Hashtable* DateIntervalInfo::initHash(UErrorCode& status) { if ( U_FAILURE(status) ) { - return NULL; + return nullptr; } Hashtable* hTable; - if ( (hTable = new Hashtable(FALSE, status)) == NULL ) { + if ( (hTable = new Hashtable(FALSE, status)) == nullptr ) { status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } if ( U_FAILURE(status) ) { delete hTable; - return NULL; + return nullptr; } hTable->setValueComparator(dtitvinfHashTableValueComparator); return hTable; @@ -766,14 +796,18 @@ DateIntervalInfo::copyHash(const Hashtable* source, return; } int32_t pos = UHASH_FIRST; - const UHashElement* element = NULL; + const UHashElement* element = nullptr; if ( source ) { - while ( (element = source->nextElement(pos)) != NULL ) { + while ( (element = source->nextElement(pos)) != nullptr ) { const UHashTok keyTok = element->key; const UnicodeString* key = (UnicodeString*)keyTok.pointer; const UHashTok valueTok = element->value; const UnicodeString* value = (UnicodeString*)valueTok.pointer; UnicodeString* copy = new UnicodeString[kIPI_MAX_INDEX]; + if (copy == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } int8_t i; for ( i = 0; i < kIPI_MAX_INDEX; ++i ) { copy[i] = value[i]; diff --git a/deps/icu-small/source/i18n/dtptngen.cpp b/deps/icu-small/source/i18n/dtptngen.cpp index 50a377259aa80e..279fb49a7aa9b9 100644 --- a/deps/icu-small/source/i18n/dtptngen.cpp +++ b/deps/icu-small/source/i18n/dtptngen.cpp @@ -324,6 +324,7 @@ DateTimePatternGenerator::createEmptyInstance(UErrorCode& status) { DateTimePatternGenerator::DateTimePatternGenerator(UErrorCode &status) : skipMatcher(nullptr), fAvailableFormatKeyHash(nullptr), + fDefaultHourFormatChar(0), internalErrorCode(U_ZERO_ERROR) { fp = new FormatParser(); @@ -338,6 +339,7 @@ DateTimePatternGenerator::DateTimePatternGenerator(UErrorCode &status) : DateTimePatternGenerator::DateTimePatternGenerator(const Locale& locale, UErrorCode &status) : skipMatcher(nullptr), fAvailableFormatKeyHash(nullptr), + fDefaultHourFormatChar(0), internalErrorCode(U_ZERO_ERROR) { fp = new FormatParser(); @@ -356,6 +358,7 @@ DateTimePatternGenerator::DateTimePatternGenerator(const DateTimePatternGenerato UObject(), skipMatcher(nullptr), fAvailableFormatKeyHash(nullptr), + fDefaultHourFormatChar(0), internalErrorCode(U_ZERO_ERROR) { fp = new FormatParser(); @@ -654,6 +657,23 @@ void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErro int32_t* allowedFormats = getAllowedHourFormatsLangCountry(language, country, status); + // We need to check if there is an hour cycle on locale + char buffer[8]; + int32_t count = locale.getKeywordValue("hours", buffer, sizeof(buffer), status); + + fDefaultHourFormatChar = 0; + if (U_SUCCESS(status) && count > 0) { + if(uprv_strcmp(buffer, "h24") == 0) { + fDefaultHourFormatChar = LOW_K; + } else if(uprv_strcmp(buffer, "h23") == 0) { + fDefaultHourFormatChar = CAP_H; + } else if(uprv_strcmp(buffer, "h12") == 0) { + fDefaultHourFormatChar = LOW_H; + } else if(uprv_strcmp(buffer, "h11") == 0) { + fDefaultHourFormatChar = CAP_K; + } + } + // Check if the region has an alias if (allowedFormats == nullptr) { UErrorCode localStatus = U_ZERO_ERROR; @@ -667,13 +687,16 @@ void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErro if (allowedFormats != nullptr) { // Lookup is successful // Here allowedFormats points to a list consisting of key for preferredFormat, // followed by one or more keys for allowedFormats, then followed by ALLOWED_HOUR_FORMAT_UNKNOWN. - switch (allowedFormats[0]) { - case ALLOWED_HOUR_FORMAT_h: fDefaultHourFormatChar = LOW_H; break; - case ALLOWED_HOUR_FORMAT_H: fDefaultHourFormatChar = CAP_H; break; - case ALLOWED_HOUR_FORMAT_K: fDefaultHourFormatChar = CAP_K; break; - case ALLOWED_HOUR_FORMAT_k: fDefaultHourFormatChar = LOW_K; break; - default: fDefaultHourFormatChar = CAP_H; break; + if (!fDefaultHourFormatChar) { + switch (allowedFormats[0]) { + case ALLOWED_HOUR_FORMAT_h: fDefaultHourFormatChar = LOW_H; break; + case ALLOWED_HOUR_FORMAT_H: fDefaultHourFormatChar = CAP_H; break; + case ALLOWED_HOUR_FORMAT_K: fDefaultHourFormatChar = CAP_K; break; + case ALLOWED_HOUR_FORMAT_k: fDefaultHourFormatChar = LOW_K; break; + default: fDefaultHourFormatChar = CAP_H; break; + } } + for (int32_t i = 0; i < UPRV_LENGTHOF(fAllowedHourFormats); ++i) { fAllowedHourFormats[i] = allowedFormats[i + 1]; if (fAllowedHourFormats[i] == ALLOWED_HOUR_FORMAT_UNKNOWN) { @@ -681,12 +704,39 @@ void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErro } } } else { // Lookup failed, twice - fDefaultHourFormatChar = CAP_H; + if (!fDefaultHourFormatChar) { + fDefaultHourFormatChar = CAP_H; + } fAllowedHourFormats[0] = ALLOWED_HOUR_FORMAT_H; fAllowedHourFormats[1] = ALLOWED_HOUR_FORMAT_UNKNOWN; } } +UDateFormatHourCycle +DateTimePatternGenerator::getDefaultHourCycle(UErrorCode& status) const { + if (U_FAILURE(status)) { + return UDAT_HOUR_CYCLE_23; + } + if (fDefaultHourFormatChar == 0) { + // We need to return something, but the caller should ignore it + // anyways since the returned status is a failure. + status = U_UNSUPPORTED_ERROR; + return UDAT_HOUR_CYCLE_23; + } + switch (fDefaultHourFormatChar) { + case CAP_K: + return UDAT_HOUR_CYCLE_11; + case LOW_H: + return UDAT_HOUR_CYCLE_12; + case CAP_H: + return UDAT_HOUR_CYCLE_23; + case LOW_K: + return UDAT_HOUR_CYCLE_24; + default: + UPRV_UNREACHABLE; + } +} + UnicodeString DateTimePatternGenerator::getSkeleton(const UnicodeString& pattern, UErrorCode& /*status*/) { @@ -1479,6 +1529,7 @@ DateTimePatternGenerator::getBestRaw(DateTimeMatcher& source, UErrorCode &status, const PtnSkeleton** specifiedSkeletonPtr) { int32_t bestDistance = 0x7fffffff; + int32_t bestMissingFieldMask = -1; DistanceInfo tempInfo; const UnicodeString *bestPattern=nullptr; const PtnSkeleton* specifiedSkeleton=nullptr; @@ -1492,8 +1543,15 @@ DateTimePatternGenerator::getBestRaw(DateTimeMatcher& source, continue; } int32_t distance=source.getDistance(trial, includeMask, tempInfo); - if (distancegetPatternFromSkeleton(*trial.getSkeletonPtr(), &specifiedSkeleton); missingFields->setTo(tempInfo); if (distance==0) { @@ -1546,14 +1604,16 @@ DateTimePatternGenerator::adjustFieldTypes(const UnicodeString& pattern, dtMatcher->skeleton.original.appendFieldTo(UDATPG_FRACTIONAL_SECOND_FIELD, field); } else if (dtMatcher->skeleton.type[typeValue]!=0) { // Here: - // - "reqField" is the field from the originally requested skeleton, with length - // "reqFieldLen". + // - "reqField" is the field from the originally requested skeleton after replacement + // of metacharacters 'j', 'C' and 'J', with length "reqFieldLen". // - "field" is the field from the found pattern. // // The adjusted field should consist of characters from the originally requested - // skeleton, except in the case of UDATPG_HOUR_FIELD or UDATPG_MONTH_FIELD or + // skeleton, except in the case of UDATPG_MONTH_FIELD or // UDATPG_WEEKDAY_FIELD or UDATPG_YEAR_FIELD, in which case it should consist - // of characters from the found pattern. + // of characters from the found pattern. In some cases of UDATPG_HOUR_FIELD, + // there is adjustment following the "defaultHourFormatChar". There is explanation + // how it is done below. // // The length of the adjusted field (adjFieldLen) should match that in the originally // requested skeleton, except that in the following cases the length of the adjusted field @@ -1591,9 +1651,28 @@ DateTimePatternGenerator::adjustFieldTypes(const UnicodeString& pattern, && (typeValue!= UDATPG_YEAR_FIELD || reqFieldChar==CAP_Y)) ? reqFieldChar : field.charAt(0); - if (typeValue == UDATPG_HOUR_FIELD && (flags & kDTPGSkeletonUsesCapJ) != 0) { - c = fDefaultHourFormatChar; + if (typeValue == UDATPG_HOUR_FIELD && fDefaultHourFormatChar != 0) { + // The adjustment here is required to match spec (https://www.unicode.org/reports/tr35/tr35-dates.html#dfst-hour). + // It is necessary to match the hour-cycle preferred by the Locale. + // Given that, we need to do the following adjustments: + // 1. When hour-cycle is h11 it should replace 'h' by 'K'. + // 2. When hour-cycle is h23 it should replace 'H' by 'k'. + // 3. When hour-cycle is h24 it should replace 'k' by 'H'. + // 4. When hour-cycle is h12 it should replace 'K' by 'h'. + + if ((flags & kDTPGSkeletonUsesCapJ) != 0 || reqFieldChar == fDefaultHourFormatChar) { + c = fDefaultHourFormatChar; + } else if (reqFieldChar == LOW_H && fDefaultHourFormatChar == CAP_K) { + c = CAP_K; + } else if (reqFieldChar == CAP_H && fDefaultHourFormatChar == LOW_K) { + c = LOW_K; + } else if (reqFieldChar == LOW_K && fDefaultHourFormatChar == CAP_H) { + c = CAP_H; + } else if (reqFieldChar == CAP_K && fDefaultHourFormatChar == LOW_H) { + c = LOW_H; + } } + field.remove(); for (int32_t j=adjFieldLen; j>0; --j) { field += c; @@ -2118,6 +2197,11 @@ DateTimeMatcher::DateTimeMatcher(const DateTimeMatcher& other) { copyFrom(other.skeleton); } +DateTimeMatcher& DateTimeMatcher::operator=(const DateTimeMatcher& other) { + copyFrom(other.skeleton); + return *this; +} + void DateTimeMatcher::set(const UnicodeString& pattern, FormatParser* fp) { @@ -2162,6 +2246,33 @@ DateTimeMatcher::set(const UnicodeString& pattern, FormatParser* fp, PtnSkeleton } skeletonResult.type[field] = subField; } + + // #20739, we have a skeleton with minutes and milliseconds, but no seconds + // + // Theoretically we would need to check and fix all fields with "gaps": + // for example year-day (no month), month-hour (no day), and so on, All the possible field combinations. + // Plus some smartness: year + hour => should we add month, or add day-of-year? + // What about month + day-of-week, or month + am/pm indicator. + // I think beyond a certain point we should not try to fix bad developer input and try guessing what they mean. + // Garbage in, garbage out. + if (!skeletonResult.original.isFieldEmpty(UDATPG_MINUTE_FIELD) + && !skeletonResult.original.isFieldEmpty(UDATPG_FRACTIONAL_SECOND_FIELD) + && skeletonResult.original.isFieldEmpty(UDATPG_SECOND_FIELD)) { + // Force the use of seconds + for (i = 0; dtTypes[i].patternChar != 0; i++) { + if (dtTypes[i].field == UDATPG_SECOND_FIELD) { + // first entry for UDATPG_SECOND_FIELD + skeletonResult.original.populate(UDATPG_SECOND_FIELD, dtTypes[i].patternChar, dtTypes[i].minLen); + skeletonResult.baseOriginal.populate(UDATPG_SECOND_FIELD, dtTypes[i].patternChar, dtTypes[i].minLen); + // We add value.length, same as above, when type is first initialized. + // The value we want to "fake" here is "s", and 1 means "s".length() + int16_t subField = dtTypes[i].type; + skeletonResult.type[UDATPG_SECOND_FIELD] = (subField > 0) ? subField + 1 : subField; + break; + } + } + } + // #13183, handle special behavior for day period characters (a, b, B) if (!skeletonResult.original.isFieldEmpty(UDATPG_HOUR_FIELD)) { if (skeletonResult.original.getFieldChar(UDATPG_HOUR_FIELD)==LOW_H || skeletonResult.original.getFieldChar(UDATPG_HOUR_FIELD)==CAP_K) { diff --git a/deps/icu-small/source/i18n/dtptngen_impl.h b/deps/icu-small/source/i18n/dtptngen_impl.h index 95219f0ba257f5..ade9f57331e769 100644 --- a/deps/icu-small/source/i18n/dtptngen_impl.h +++ b/deps/icu-small/source/i18n/dtptngen_impl.h @@ -238,6 +238,7 @@ class DateTimeMatcher: public UMemory { int32_t getDistance(const DateTimeMatcher& other, int32_t includeMask, DistanceInfo& distanceInfo) const; DateTimeMatcher(); DateTimeMatcher(const DateTimeMatcher& other); + DateTimeMatcher& operator=(const DateTimeMatcher& other); virtual ~DateTimeMatcher(); int32_t getFieldMask() const; }; diff --git a/deps/icu-small/source/i18n/formatted_string_builder.cpp b/deps/icu-small/source/i18n/formatted_string_builder.cpp index 3024bff6addacc..5aabc31cc4391b 100644 --- a/deps/icu-small/source/i18n/formatted_string_builder.cpp +++ b/deps/icu-small/source/i18n/formatted_string_builder.cpp @@ -8,6 +8,7 @@ #include "formatted_string_builder.h" #include "unicode/ustring.h" #include "unicode/utf16.h" +#include "unicode/unum.h" // for UNumberFormatFields literals namespace { @@ -246,7 +247,7 @@ void FormattedStringBuilder::writeTerminator(UErrorCode& status) { return; } getCharPtr()[position] = 0; - getFieldPtr()[position] = UNUM_FIELD_COUNT; + getFieldPtr()[position] = kUndefinedField; fLength--; } @@ -360,11 +361,11 @@ UnicodeString FormattedStringBuilder::toDebugString() const { sb.append(toUnicodeString()); sb.append(u"] [", -1); for (int i = 0; i < fLength; i++) { - if (fieldAt(i) == UNUM_FIELD_COUNT) { + if (fieldAt(i) == kUndefinedField) { sb.append(u'n'); - } else { + } else if (fieldAt(i).getCategory() == UFIELD_CATEGORY_NUMBER) { char16_t c; - switch (fieldAt(i)) { + switch (fieldAt(i).getField()) { case UNUM_SIGN_FIELD: c = u'-'; break; @@ -399,10 +400,12 @@ UnicodeString FormattedStringBuilder::toDebugString() const { c = u'$'; break; default: - c = u'?'; + c = u'0' + fieldAt(i).getField(); break; } sb.append(c); + } else { + sb.append(u'0' + fieldAt(i).getCategory()); } } sb.append(u"]>", -1); diff --git a/deps/icu-small/source/i18n/formatted_string_builder.h b/deps/icu-small/source/i18n/formatted_string_builder.h index 2949ae73e0ff9e..4567dc1d66b0ce 100644 --- a/deps/icu-small/source/i18n/formatted_string_builder.h +++ b/deps/icu-small/source/i18n/formatted_string_builder.h @@ -9,7 +9,8 @@ #include -#include "unicode/unum.h" // for UNUM_FIELD_COUNT +#include + #include "cstring.h" #include "uassert.h" #include "fphdlimp.h" @@ -55,7 +56,20 @@ class U_I18N_API FormattedStringBuilder : public UMemory { // Field category 0 implies the number category so that the number field // literals can be directly passed as a Field type. // See the helper functions in "StringBuilderFieldUtils" below. - typedef uint8_t Field; + // Exported as U_I18N_API so it can be used by other exports on Windows. + struct U_I18N_API Field { + uint8_t bits; + + Field() = default; + constexpr Field(uint8_t category, uint8_t field); + + inline UFieldCategory getCategory() const; + inline int32_t getField() const; + inline bool isNumeric() const; + inline bool isUndefined() const; + inline bool operator==(const Field& other) const; + inline bool operator!=(const Field& other) const; + }; FormattedStringBuilder &operator=(const FormattedStringBuilder &other); @@ -204,46 +218,50 @@ class U_I18N_API FormattedStringBuilder : public UMemory { friend class FormattedValueStringBuilderImpl; }; +static_assert( + std::is_pod::value, + "Field should be a POD type for efficient initialization"); + +constexpr FormattedStringBuilder::Field::Field(uint8_t category, uint8_t field) + : bits(( + U_ASSERT(category <= 0xf), + U_ASSERT(field <= 0xf), + static_cast((category << 4) | field) + )) {} + /** - * Helper functions for dealing with the Field typedef, which stores fields - * in a compressed format. + * Internal constant for the undefined field for use in FormattedStringBuilder. */ -class StringBuilderFieldUtils { -public: - struct CategoryFieldPair { - int32_t category; - int32_t field; - }; +constexpr FormattedStringBuilder::Field kUndefinedField = {UFIELD_CATEGORY_UNDEFINED, 0}; - /** Compile-time function to construct a Field from a category and a field */ - template - static constexpr FormattedStringBuilder::Field compress() { - static_assert(category != 0, "cannot use Undefined category in FieldUtils"); - static_assert(category <= 0xf, "only 4 bits for category"); - static_assert(field <= 0xf, "only 4 bits for field"); - return static_cast((category << 4) | field); - } +/** + * Internal field to signal "numeric" when fields are not supported in NumberFormat. + */ +constexpr FormattedStringBuilder::Field kGeneralNumericField = {UFIELD_CATEGORY_UNDEFINED, 1}; - /** Runtime inline function to unpack the category and field from the Field */ - static inline CategoryFieldPair expand(FormattedStringBuilder::Field field) { - if (field == UNUM_FIELD_COUNT) { - return {UFIELD_CATEGORY_UNDEFINED, 0}; - } - CategoryFieldPair ret = { - (field >> 4), - (field & 0xf) - }; - if (ret.category == 0) { - ret.category = UFIELD_CATEGORY_NUMBER; - } - return ret; - } +inline UFieldCategory FormattedStringBuilder::Field::getCategory() const { + return static_cast(bits >> 4); +} - static inline bool isNumericField(FormattedStringBuilder::Field field) { - int8_t category = field >> 4; - return category == 0 || category == UFIELD_CATEGORY_NUMBER; - } -}; +inline int32_t FormattedStringBuilder::Field::getField() const { + return bits & 0xf; +} + +inline bool FormattedStringBuilder::Field::isNumeric() const { + return getCategory() == UFIELD_CATEGORY_NUMBER || *this == kGeneralNumericField; +} + +inline bool FormattedStringBuilder::Field::isUndefined() const { + return getCategory() == UFIELD_CATEGORY_UNDEFINED; +} + +inline bool FormattedStringBuilder::Field::operator==(const Field& other) const { + return bits == other.bits; +} + +inline bool FormattedStringBuilder::Field::operator!=(const Field& other) const { + return bits != other.bits; +} U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/formattedval_impl.h b/deps/icu-small/source/i18n/formattedval_impl.h index 4ee53e4589b2e9..73ae9a3ea2ab3a 100644 --- a/deps/icu-small/source/i18n/formattedval_impl.h +++ b/deps/icu-small/source/i18n/formattedval_impl.h @@ -153,7 +153,6 @@ class U_I18N_API FormattedValueStringBuilderImpl : public UMemory, public Format bool nextPositionImpl(ConstrainedFieldPosition& cfpos, FormattedStringBuilder::Field numericField, UErrorCode& status) const; static bool isIntOrGroup(FormattedStringBuilder::Field field); - static bool isNumericField(FormattedStringBuilder::Field field); int32_t trimBack(int32_t limit) const; int32_t trimFront(int32_t start) const; }; diff --git a/deps/icu-small/source/i18n/formattedval_sbimpl.cpp b/deps/icu-small/source/i18n/formattedval_sbimpl.cpp index ca28f222813afc..dfe3af6686df2f 100644 --- a/deps/icu-small/source/i18n/formattedval_sbimpl.cpp +++ b/deps/icu-small/source/i18n/formattedval_sbimpl.cpp @@ -63,7 +63,7 @@ UBool FormattedValueStringBuilderImpl::nextFieldPosition(FieldPosition& fp, UErr ConstrainedFieldPosition cfpos; cfpos.constrainField(UFIELD_CATEGORY_NUMBER, rawField); cfpos.setState(UFIELD_CATEGORY_NUMBER, rawField, fp.getBeginIndex(), fp.getEndIndex()); - if (nextPositionImpl(cfpos, 0, status)) { + if (nextPositionImpl(cfpos, kUndefinedField, status)) { fp.setBeginIndex(cfpos.getStart()); fp.setEndIndex(cfpos.getLimit()); return TRUE; @@ -74,7 +74,7 @@ UBool FormattedValueStringBuilderImpl::nextFieldPosition(FieldPosition& fp, UErr bool inside = false; int32_t i = fString.fZero; for (; i < fString.fZero + fString.fLength; i++) { - if (isIntOrGroup(fString.getFieldPtr()[i]) || fString.getFieldPtr()[i] == UNUM_DECIMAL_SEPARATOR_FIELD) { + if (isIntOrGroup(fString.getFieldPtr()[i]) || fString.getFieldPtr()[i] == Field(UFIELD_CATEGORY_NUMBER, UNUM_DECIMAL_SEPARATOR_FIELD)) { inside = true; } else if (inside) { break; @@ -90,42 +90,40 @@ UBool FormattedValueStringBuilderImpl::nextFieldPosition(FieldPosition& fp, UErr void FormattedValueStringBuilderImpl::getAllFieldPositions(FieldPositionIteratorHandler& fpih, UErrorCode& status) const { ConstrainedFieldPosition cfpos; - while (nextPositionImpl(cfpos, 0, status)) { + while (nextPositionImpl(cfpos, kUndefinedField, status)) { fpih.addAttribute(cfpos.getField(), cfpos.getStart(), cfpos.getLimit()); } } // Signal the end of the string using a field that doesn't exist and that is -// different from UNUM_FIELD_COUNT, which is used for "null number field". -static constexpr Field kEndField = 0xff; +// different from kUndefinedField, which is used for "null field". +static constexpr Field kEndField = Field(0xf, 0xf); bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition& cfpos, Field numericField, UErrorCode& /*status*/) const { - auto numericCAF = StringBuilderFieldUtils::expand(numericField); int32_t fieldStart = -1; - Field currField = UNUM_FIELD_COUNT; + Field currField = kUndefinedField; for (int32_t i = fString.fZero + cfpos.getLimit(); i <= fString.fZero + fString.fLength; i++) { Field _field = (i < fString.fZero + fString.fLength) ? fString.getFieldPtr()[i] : kEndField; // Case 1: currently scanning a field. - if (currField != UNUM_FIELD_COUNT) { + if (currField != kUndefinedField) { if (currField != _field) { int32_t end = i - fString.fZero; // Grouping separators can be whitespace; don't throw them out! - if (currField != UNUM_GROUPING_SEPARATOR_FIELD) { + if (currField != Field(UFIELD_CATEGORY_NUMBER, UNUM_GROUPING_SEPARATOR_FIELD)) { end = trimBack(i - fString.fZero); } if (end <= fieldStart) { // Entire field position is ignorable; skip. fieldStart = -1; - currField = UNUM_FIELD_COUNT; + currField = kUndefinedField; i--; // look at this index again continue; } int32_t start = fieldStart; - if (currField != UNUM_GROUPING_SEPARATOR_FIELD) { + if (currField != Field(UFIELD_CATEGORY_NUMBER, UNUM_GROUPING_SEPARATOR_FIELD)) { start = trimFront(start); } - auto caf = StringBuilderFieldUtils::expand(currField); - cfpos.setState(caf.category, caf.field, start, end); + cfpos.setState(currField.getCategory(), currField.getField(), start, end); return true; } continue; @@ -147,51 +145,46 @@ bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition& return true; } // Special case: coalesce NUMERIC if we are pointing at the end of the NUMERIC. - if (numericField != 0 - && cfpos.matchesField(numericCAF.category, numericCAF.field) + if (numericField != kUndefinedField + && cfpos.matchesField(numericField.getCategory(), numericField.getField()) && i > fString.fZero // don't return the same field twice in a row: && (i - fString.fZero > cfpos.getLimit() - || cfpos.getCategory() != numericCAF.category - || cfpos.getField() != numericCAF.field) - && isNumericField(fString.getFieldPtr()[i - 1]) - && !isNumericField(_field)) { + || cfpos.getCategory() != numericField.getCategory() + || cfpos.getField() != numericField.getField()) + && fString.getFieldPtr()[i - 1].isNumeric() + && !_field.isNumeric()) { int j = i - 1; - for (; j >= fString.fZero && isNumericField(fString.getFieldPtr()[j]); j--) {} + for (; j >= fString.fZero && fString.getFieldPtr()[j].isNumeric(); j--) {} cfpos.setState( - numericCAF.category, - numericCAF.field, + numericField.getCategory(), + numericField.getField(), j - fString.fZero + 1, i - fString.fZero); return true; } // Special case: skip over INTEGER; will be coalesced later. - if (_field == UNUM_INTEGER_FIELD) { - _field = UNUM_FIELD_COUNT; + if (_field == Field(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD)) { + _field = kUndefinedField; } // Case 2: no field starting at this position. - if (_field == UNUM_FIELD_COUNT || _field == kEndField) { + if (_field.isUndefined() || _field == kEndField) { continue; } // Case 3: check for field starting at this position - auto caf = StringBuilderFieldUtils::expand(_field); - if (cfpos.matchesField(caf.category, caf.field)) { + if (cfpos.matchesField(_field.getCategory(), _field.getField())) { fieldStart = i - fString.fZero; currField = _field; } } - U_ASSERT(currField == UNUM_FIELD_COUNT); + U_ASSERT(currField == kUndefinedField); return false; } bool FormattedValueStringBuilderImpl::isIntOrGroup(Field field) { - return field == UNUM_INTEGER_FIELD - || field == UNUM_GROUPING_SEPARATOR_FIELD; -} - -bool FormattedValueStringBuilderImpl::isNumericField(Field field) { - return StringBuilderFieldUtils::isNumericField(field); + return field == Field(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD) + || field == Field(UFIELD_CATEGORY_NUMBER, UNUM_GROUPING_SEPARATOR_FIELD); } int32_t FormattedValueStringBuilderImpl::trimBack(int32_t limit) const { diff --git a/deps/icu-small/source/i18n/fphdlimp.h b/deps/icu-small/source/i18n/fphdlimp.h index 00937830fe7b80..b9fa9b218149d4 100644 --- a/deps/icu-small/source/i18n/fphdlimp.h +++ b/deps/icu-small/source/i18n/fphdlimp.h @@ -62,8 +62,9 @@ class FieldPositionOnlyHandler : public FieldPositionHandler { // utility subclass FieldPositionIteratorHandler +// exported as U_I18N_API for tests -class FieldPositionIteratorHandler : public FieldPositionHandler { +class U_I18N_API FieldPositionIteratorHandler : public FieldPositionHandler { FieldPositionIterator* iter; // can be NULL UVector32* vec; UErrorCode status; diff --git a/deps/icu-small/source/i18n/gender.cpp b/deps/icu-small/source/i18n/gender.cpp index 03c03cecad94ba..e3ec5ad27298f4 100644 --- a/deps/icu-small/source/i18n/gender.cpp +++ b/deps/icu-small/source/i18n/gender.cpp @@ -160,7 +160,7 @@ const GenderInfo* GenderInfo::loadInstance(const Locale& locale, UErrorCode& sta if (s == NULL) { return &gObjs[NEUTRAL]; } - char type_str[256]; + char type_str[256] = ""; u_UCharsToChars(s, type_str, resLen + 1); if (uprv_strcmp(type_str, gNeutralStr) == 0) { return &gObjs[NEUTRAL]; diff --git a/deps/icu-small/source/i18n/listformatter.cpp b/deps/icu-small/source/i18n/listformatter.cpp index 35cc00de252aa7..4b27587555219c 100644 --- a/deps/icu-small/source/i18n/listformatter.cpp +++ b/deps/icu-small/source/i18n/listformatter.cpp @@ -21,6 +21,7 @@ #include "unicode/listformatter.h" #include "unicode/simpleformatter.h" #include "unicode/ulistformatter.h" +#include "unicode/uscript.h" #include "fphdlimp.h" #include "mutex.h" #include "hash.h" @@ -35,34 +36,203 @@ U_NAMESPACE_BEGIN -struct ListFormatInternal : public UMemory { +namespace { + +class PatternHandler : public UObject { +public: + PatternHandler(const UnicodeString& two, const UnicodeString& end, UErrorCode& errorCode) : + twoPattern(two, 2, 2, errorCode), + endPattern(end, 2, 2, errorCode) { } + + PatternHandler(const SimpleFormatter& two, const SimpleFormatter& end) : + twoPattern(two), + endPattern(end) { } + + virtual ~PatternHandler(); + + virtual PatternHandler* clone() const { return new PatternHandler(twoPattern, endPattern); } + + virtual const SimpleFormatter& getTwoPattern(const UnicodeString&) const { + return twoPattern; + } + + virtual const SimpleFormatter& getEndPattern(const UnicodeString&) const { + return endPattern; + } + +protected: SimpleFormatter twoPattern; + SimpleFormatter endPattern; +}; + +PatternHandler::~PatternHandler() { +} + +class ContextualHandler : public PatternHandler { +public: + ContextualHandler(bool (*testFunc)(const UnicodeString& text), + const UnicodeString& thenTwo, + const UnicodeString& elseTwo, + const UnicodeString& thenEnd, + const UnicodeString& elseEnd, + UErrorCode& errorCode) : + PatternHandler(elseTwo, elseEnd, errorCode), + test(testFunc), + thenTwoPattern(thenTwo, 2, 2, errorCode), + thenEndPattern(thenEnd, 2, 2, errorCode) { } + + ContextualHandler(bool (*testFunc)(const UnicodeString& text), + const SimpleFormatter& thenTwo, SimpleFormatter elseTwo, + const SimpleFormatter& thenEnd, SimpleFormatter elseEnd) : + PatternHandler(elseTwo, elseEnd), + test(testFunc), + thenTwoPattern(thenTwo), + thenEndPattern(thenEnd) { } + + ~ContextualHandler() override; + + PatternHandler* clone() const override { + return new ContextualHandler( + test, thenTwoPattern, twoPattern, thenEndPattern, endPattern); + } + + const SimpleFormatter& getTwoPattern( + const UnicodeString& text) const override { + return (test)(text) ? thenTwoPattern : twoPattern; + } + + const SimpleFormatter& getEndPattern( + const UnicodeString& text) const override { + return (test)(text) ? thenEndPattern : endPattern; + } + +private: + bool (*test)(const UnicodeString&); + SimpleFormatter thenTwoPattern; + SimpleFormatter thenEndPattern; +}; + +ContextualHandler::~ContextualHandler() { +} + +static const char16_t *spanishY = u"{0} y {1}"; +static const char16_t *spanishE = u"{0} e {1}"; +static const char16_t *spanishO = u"{0} o {1}"; +static const char16_t *spanishU = u"{0} u {1}"; +static const char16_t *hebrewVav = u"{0} \u05D5{1}"; +static const char16_t *hebrewVavDash = u"{0} \u05D5-{1}"; + +// Condiction to change to e. +// Starts with "hi" or "i" but not with "hie" nor "hia" +static bool shouldChangeToE(const UnicodeString& text) { + int32_t len = text.length(); + if (len == 0) { return false; } + // Case insensitive match hi but not hie nor hia. + if ((text[0] == u'h' || text[0] == u'H') && + ((len > 1) && (text[1] == u'i' || text[1] == u'I')) && + ((len == 2) || !(text[2] == u'a' || text[2] == u'A' || text[2] == u'e' || text[2] == u'E'))) { + return true; + } + // Case insensitive for "start with i" + if (text[0] == u'i' || text[0] == u'I') { return true; } + return false; +} + +// Condiction to change to u. +// Starts with "o", "ho", and "8". Also "11" by itself. +// re: ^((o|ho|8).*|11)$ +static bool shouldChangeToU(const UnicodeString& text) { + int32_t len = text.length(); + if (len == 0) { return false; } + // Case insensitive match o.* and 8.* + if (text[0] == u'o' || text[0] == u'O' || text[0] == u'8') { return true; } + // Case insensitive match ho.* + if ((text[0] == u'h' || text[0] == u'H') && + ((len > 1) && (text[1] == 'o' || text[1] == u'O'))) { + return true; + } + // match "^11$" and "^11 .*" + if ((len >= 2) && text[0] == u'1' && text[1] == u'1' && (len == 2 || text[2] == u' ')) { return true; } + return false; +} + +// Condiction to change to VAV follow by a dash. +// Starts with non Hebrew letter. +static bool shouldChangeToVavDash(const UnicodeString& text) { + if (text.isEmpty()) { return false; } + UErrorCode status = U_ZERO_ERROR; + return uscript_getScript(text.char32At(0), &status) != USCRIPT_HEBREW; +} + +PatternHandler* createPatternHandler( + const char* lang, const UnicodeString& two, const UnicodeString& end, + UErrorCode& status) { + if (uprv_strcmp(lang, "es") == 0) { + // Spanish + UnicodeString spanishYStr(TRUE, spanishY, -1); + bool twoIsY = two == spanishYStr; + bool endIsY = end == spanishYStr; + if (twoIsY || endIsY) { + UnicodeString replacement(TRUE, spanishE, -1); + return new ContextualHandler( + shouldChangeToE, + twoIsY ? replacement : two, two, + endIsY ? replacement : end, end, status); + } + UnicodeString spanishOStr(TRUE, spanishO, -1); + bool twoIsO = two == spanishOStr; + bool endIsO = end == spanishOStr; + if (twoIsO || endIsO) { + UnicodeString replacement(TRUE, spanishU, -1); + return new ContextualHandler( + shouldChangeToU, + twoIsO ? replacement : two, two, + endIsO ? replacement : end, end, status); + } + } else if (uprv_strcmp(lang, "he") == 0 || uprv_strcmp(lang, "iw") == 0) { + // Hebrew + UnicodeString hebrewVavStr(TRUE, hebrewVav, -1); + bool twoIsVav = two == hebrewVavStr; + bool endIsVav = end == hebrewVavStr; + if (twoIsVav || endIsVav) { + UnicodeString replacement(TRUE, hebrewVavDash, -1); + return new ContextualHandler( + shouldChangeToVavDash, + twoIsVav ? replacement : two, two, + endIsVav ? replacement : end, end, status); + } + } + return new PatternHandler(two, end, status); +} + +} // namespace + +struct ListFormatInternal : public UMemory { SimpleFormatter startPattern; SimpleFormatter middlePattern; - SimpleFormatter endPattern; + LocalPointer patternHandler; ListFormatInternal( const UnicodeString& two, const UnicodeString& start, const UnicodeString& middle, const UnicodeString& end, + const Locale& locale, UErrorCode &errorCode) : - twoPattern(two, 2, 2, errorCode), startPattern(start, 2, 2, errorCode), middlePattern(middle, 2, 2, errorCode), - endPattern(end, 2, 2, errorCode) {} + patternHandler(createPatternHandler(locale.getLanguage(), two, end, errorCode), errorCode) { } ListFormatInternal(const ListFormatData &data, UErrorCode &errorCode) : - twoPattern(data.twoPattern, errorCode), startPattern(data.startPattern, errorCode), middlePattern(data.middlePattern, errorCode), - endPattern(data.endPattern, errorCode) { } + patternHandler(createPatternHandler( + data.locale.getLanguage(), data.twoPattern, data.endPattern, errorCode), errorCode) { } ListFormatInternal(const ListFormatInternal &other) : - twoPattern(other.twoPattern), startPattern(other.startPattern), middlePattern(other.middlePattern), - endPattern(other.endPattern) { } + patternHandler(other.patternHandler->clone()) { } }; @@ -80,7 +250,6 @@ UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(FormattedList) static Hashtable* listPatternHash = nullptr; -static const char STANDARD_STYLE[] = "standard"; U_CDECL_BEGIN static UBool U_CALLCONV uprv_listformatter_cleanup() { @@ -179,6 +348,52 @@ const ListFormatInternal* ListFormatter::getListFormatInternal( return result; } +#if !UCONFIG_NO_FORMATTING +static const char* typeWidthToStyleString(UListFormatterType type, UListFormatterWidth width) { + switch (type) { + case ULISTFMT_TYPE_AND: + switch (width) { + case ULISTFMT_WIDTH_WIDE: + return "standard"; + case ULISTFMT_WIDTH_SHORT: + return "standard-short"; + case ULISTFMT_WIDTH_NARROW: + return "standard-narrow"; + default: + return nullptr; + } + break; + + case ULISTFMT_TYPE_OR: + switch (width) { + case ULISTFMT_WIDTH_WIDE: + return "or"; + case ULISTFMT_WIDTH_SHORT: + return "or-short"; + case ULISTFMT_WIDTH_NARROW: + return "or-narrow"; + default: + return nullptr; + } + break; + + case ULISTFMT_TYPE_UNITS: + switch (width) { + case ULISTFMT_WIDTH_WIDE: + return "unit"; + case ULISTFMT_WIDTH_SHORT: + return "unit-short"; + case ULISTFMT_WIDTH_NARROW: + return "unit-narrow"; + default: + return nullptr; + } + } + + return nullptr; +} +#endif + static const UChar solidus = 0x2F; static const UChar aliasPrefix[] = { 0x6C,0x69,0x73,0x74,0x50,0x61,0x74,0x74,0x65,0x72,0x6E,0x2F }; // "listPattern/" enum { @@ -279,7 +494,8 @@ ListFormatInternal* ListFormatter::loadListFormatInternal( errorCode = U_MISSING_RESOURCE_ERROR; return nullptr; } - ListFormatInternal* result = new ListFormatInternal(sink.two, sink.start, sink.middle, sink.end, errorCode); + + ListFormatInternal* result = new ListFormatInternal(sink.two, sink.start, sink.middle, sink.end, locale, errorCode); if (result == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; return nullptr; @@ -297,9 +513,25 @@ ListFormatter* ListFormatter::createInstance(UErrorCode& errorCode) { } ListFormatter* ListFormatter::createInstance(const Locale& locale, UErrorCode& errorCode) { - return createInstance(locale, STANDARD_STYLE, errorCode); +#if !UCONFIG_NO_FORMATTING + return createInstance(locale, ULISTFMT_TYPE_AND, ULISTFMT_WIDTH_WIDE, errorCode); +#else + return createInstance(locale, "standard", errorCode); +#endif } +#if !UCONFIG_NO_FORMATTING +ListFormatter* ListFormatter::createInstance( + const Locale& locale, UListFormatterType type, UListFormatterWidth width, UErrorCode& errorCode) { + const char* style = typeWidthToStyleString(type, width); + if (style == nullptr) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + return createInstance(locale, style, errorCode); +} +#endif + ListFormatter* ListFormatter::createInstance(const Locale& locale, const char *style, UErrorCode& errorCode) { const ListFormatInternal* listFormatInternal = getListFormatInternal(locale, style, errorCode); if (U_FAILURE(errorCode)) { @@ -380,19 +612,6 @@ UnicodeString& ListFormatter::format( return format(items, nItems, appendTo, -1, offset, errorCode); } -#if !UCONFIG_NO_FORMATTING -UnicodeString& ListFormatter::format( - const UnicodeString items[], - int32_t nItems, - UnicodeString & appendTo, - FieldPositionIterator* posIter, - UErrorCode& errorCode) const { - int32_t offset; - FieldPositionIteratorHandler handler(posIter, errorCode); - return format_(items, nItems, appendTo, -1, offset, &handler, errorCode); -} -#endif - UnicodeString& ListFormatter::format( const UnicodeString items[], int32_t nItems, @@ -484,16 +703,29 @@ UnicodeString& ListFormatter::format_( // for n items, there are 2 * (n + 1) boundary including 0 and the upper // edge. MaybeStackArray offsets((handler != nullptr) ? 2 * (nItems + 1): 0); - joinStringsAndReplace( - nItems == 2 ? data->twoPattern : data->startPattern, - result, - items[1], - result, - index == 1, - offset, - &offsetFirst, - &offsetSecond, - errorCode); + if (nItems == 2) { + joinStringsAndReplace( + data->patternHandler->getTwoPattern(items[1]), + result, + items[1], + result, + index == 1, + offset, + &offsetFirst, + &offsetSecond, + errorCode); + } else { + joinStringsAndReplace( + data->startPattern, + result, + items[1], + result, + index == 1, + offset, + &offsetFirst, + &offsetSecond, + errorCode); + } if (handler != nullptr) { offsets[0] = 0; prefixLength += offsetFirst; @@ -517,7 +749,7 @@ UnicodeString& ListFormatter::format_( } } joinStringsAndReplace( - data->endPattern, + data->patternHandler->getEndPattern(items[nItems - 1]), result, items[nItems - 1], result, diff --git a/deps/icu-small/source/i18n/measfmt.cpp b/deps/icu-small/source/i18n/measfmt.cpp index 47ffb140cf6712..a98a6dda4705b5 100644 --- a/deps/icu-small/source/i18n/measfmt.cpp +++ b/deps/icu-small/source/i18n/measfmt.cpp @@ -38,6 +38,7 @@ #include "uassert.h" #include "unicode/numberformatter.h" #include "number_longnames.h" +#include "number_utypes.h" #include "sharednumberformat.h" #include "sharedpluralrules.h" @@ -47,6 +48,8 @@ U_NAMESPACE_BEGIN +using number::impl::UFormattedNumberData; + static constexpr int32_t WIDTH_INDEX_COUNT = UMEASFMT_WIDTH_NARROW + 1; UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MeasureFormat) @@ -504,12 +507,13 @@ UnicodeString &MeasureFormat::formatMeasurePerUnit( status = U_UNSUPPORTED_ERROR; return appendTo; } - number::FormattedNumber result; + UFormattedNumberData result; if (auto* lnf = df->toNumberFormatter(status)) { - result = lnf->unit(measure.getUnit()) + result.quantity.setToDouble(measure.getNumber().getDouble(status)); + lnf->unit(measure.getUnit()) .perUnit(perUnit) .unitWidth(getUnitWidth(fWidth)) - .formatDouble(measure.getNumber().getDouble(status), status); + .formatImpl(&result, status); } DecimalFormat::fieldPositionHelper(result, pos, appendTo.length(), status); appendTo.append(result.toTempString(status)); @@ -699,11 +703,12 @@ UnicodeString &MeasureFormat::formatMeasure( SimpleFormatter formatter(pattern, 0, 1, status); return QuantityFormatter::format(formatter, formattedNumber, appendTo, pos, status); } - number::FormattedNumber result; + UFormattedNumberData result; if (auto* lnf = df->toNumberFormatter(status)) { - result = lnf->unit(amtUnit) + result.quantity.setToDouble(amtNumber.getDouble(status)); + lnf->unit(amtUnit) .unitWidth(getUnitWidth(fWidth)) - .formatDouble(amtNumber.getDouble(status), status); + .formatImpl(&result, status); } DecimalFormat::fieldPositionHelper(result, pos, appendTo.length(), status); appendTo.append(result.toTempString(status)); @@ -774,11 +779,6 @@ UnicodeString &MeasureFormat::formatNumeric( case u's': value = seconds; break; } - // For undefined field we use UNUM_FIELD_COUNT, for historical reasons. - // See cleanup bug: https://unicode-org.atlassian.net/browse/ICU-20665 - // But we give it a clear name, to keep "the ugly part" in one place. - constexpr UNumberFormatFields undefinedField = UNUM_FIELD_COUNT; - // There is not enough info to add Field(s) for the unit because all we have are plain // text patterns. For example in "21:51" there is no text for something like "hour", // while in something like "21h51" there is ("h"). But we can't really tell... @@ -787,7 +787,7 @@ UnicodeString &MeasureFormat::formatNumeric( case u'm': case u's': if (protect) { - fsb.appendChar16(c, undefinedField, status); + fsb.appendChar16(c, kUndefinedField, status); } else { UnicodeString tmp; if ((i + 1 < patternLength) && pattern[i + 1] == c) { // doubled @@ -797,20 +797,20 @@ UnicodeString &MeasureFormat::formatNumeric( numberFormatter->format(value, tmp, status); } // TODO: Use proper Field - fsb.append(tmp, undefinedField, status); + fsb.append(tmp, kUndefinedField, status); } break; case u'\'': // '' is escaped apostrophe if ((i + 1 < patternLength) && pattern[i + 1] == c) { - fsb.appendChar16(c, undefinedField, status); + fsb.appendChar16(c, kUndefinedField, status); i++; } else { protect = !protect; } break; default: - fsb.appendChar16(c, undefinedField, status); + fsb.appendChar16(c, kUndefinedField, status); } } diff --git a/deps/icu-small/source/i18n/measunit.cpp b/deps/icu-small/source/i18n/measunit.cpp index 917c0cdfadf235..2486ca9b15a05e 100644 --- a/deps/icu-small/source/i18n/measunit.cpp +++ b/deps/icu-small/source/i18n/measunit.cpp @@ -17,9 +17,11 @@ #if !UCONFIG_NO_FORMATTING #include "unicode/uenum.h" +#include "unicode/errorcode.h" #include "ustrenum.h" #include "cstring.h" #include "uassert.h" +#include "measunit_impl.h" U_NAMESPACE_BEGIN @@ -118,7 +120,7 @@ static const char * const gTypes[] = { // Must be grouped by type and sorted alphabetically within each type. static const char * const gSubTypes[] = { "g-force", - "meter-per-second-squared", + "meter-per-square-second", "arc-minute", "arc-second", "degree", @@ -138,11 +140,11 @@ static const char * const gSubTypes[] = { "milligram-per-deciliter", "millimole-per-liter", "mole", - "part-per-million", "percent", "permille", + "permillion", "permyriad", - "liter-per-100kilometers", + "liter-per-100-kilometer", "liter-per-kilometer", "mile-per-gallon", "mile-per-gallon-imperial", @@ -535,9 +537,9 @@ static const char * const gSubTypes[] = { "solar-mass", "stone", "ton", - "base", - "percent", - "permille", + "", // TODO(ICU-21076): manual edit of what should have been generated by Java. + "percent", // TODO(ICU-21076): regenerate, deal with duplication. + "permille", // TODO(ICU-21076): regenerate, deal with duplication. "gigawatt", "horsepower", "kilowatt", @@ -547,13 +549,13 @@ static const char * const gSubTypes[] = { "atmosphere", "bar", "hectopascal", - "inch-hg", + "inch-ofhg", "kilopascal", "megapascal", "millibar", - "millimeter-of-mercury", + "millimeter-ofhg", "pascal", - "pound-per-square-inch", + "pound-force-per-square-inch", "kilometer-per-hour", "knot", "meter-per-second", @@ -563,7 +565,7 @@ static const char * const gSubTypes[] = { "generic", "kelvin", "newton-meter", - "pound-foot", + "pound-force-foot", "acre-foot", "barrel", "bushel", @@ -780,27 +782,27 @@ MeasureUnit MeasureUnit::getMole() { } MeasureUnit *MeasureUnit::createPartPerMillion(UErrorCode &status) { - return MeasureUnit::create(3, 4, status); + return MeasureUnit::create(3, 6, status); } MeasureUnit MeasureUnit::getPartPerMillion() { - return MeasureUnit(3, 4); + return MeasureUnit(3, 6); } MeasureUnit *MeasureUnit::createPercent(UErrorCode &status) { - return MeasureUnit::create(3, 5, status); + return MeasureUnit::create(3, 4, status); } MeasureUnit MeasureUnit::getPercent() { - return MeasureUnit(3, 5); + return MeasureUnit(3, 4); } MeasureUnit *MeasureUnit::createPermille(UErrorCode &status) { - return MeasureUnit::create(3, 6, status); + return MeasureUnit::create(3, 5, status); } MeasureUnit MeasureUnit::getPermille() { - return MeasureUnit(3, 6); + return MeasureUnit(3, 5); } MeasureUnit *MeasureUnit::createPermyriad(UErrorCode &status) { @@ -1990,10 +1992,10 @@ MeasureUnit MeasureUnit::getTeaspoon() { // End generated code static int32_t binarySearch( - const char * const * array, int32_t start, int32_t end, const char * key) { + const char * const * array, int32_t start, int32_t end, StringPiece key) { while (start < end) { int32_t mid = (start + end) / 2; - int32_t cmp = uprv_strcmp(array[mid], key); + int32_t cmp = StringPiece(array[mid]).compare(key); if (cmp < 0) { start = mid + 1; continue; @@ -2006,24 +2008,62 @@ static int32_t binarySearch( return -1; } -MeasureUnit::MeasureUnit() { - fCurrency[0] = 0; - fTypeId = kBaseTypeIdx; - fSubTypeId = kBaseSubTypeIdx; +MeasureUnit::MeasureUnit() : MeasureUnit(kBaseTypeIdx, kBaseSubTypeIdx) { +} + +MeasureUnit::MeasureUnit(int32_t typeId, int32_t subTypeId) + : fImpl(nullptr), fSubTypeId(subTypeId), fTypeId(typeId) { } MeasureUnit::MeasureUnit(const MeasureUnit &other) - : fTypeId(other.fTypeId), fSubTypeId(other.fSubTypeId) { - uprv_strcpy(fCurrency, other.fCurrency); + : fImpl(nullptr) { + *this = other; +} + +MeasureUnit::MeasureUnit(MeasureUnit &&other) noexcept + : fImpl(other.fImpl), + fSubTypeId(other.fSubTypeId), + fTypeId(other.fTypeId) { + other.fImpl = nullptr; +} + +MeasureUnit::MeasureUnit(MeasureUnitImpl&& impl) + : fImpl(nullptr), fSubTypeId(-1), fTypeId(-1) { + if (!findBySubType(impl.identifier.toStringPiece(), this)) { + fImpl = new MeasureUnitImpl(std::move(impl)); + } } MeasureUnit &MeasureUnit::operator=(const MeasureUnit &other) { if (this == &other) { return *this; } + delete fImpl; + if (other.fImpl) { + ErrorCode localStatus; + fImpl = new MeasureUnitImpl(other.fImpl->copy(localStatus)); + if (!fImpl || localStatus.isFailure()) { + // Unrecoverable allocation error; set to the default unit + *this = MeasureUnit(); + return *this; + } + } else { + fImpl = nullptr; + } + fTypeId = other.fTypeId; + fSubTypeId = other.fSubTypeId; + return *this; +} + +MeasureUnit &MeasureUnit::operator=(MeasureUnit &&other) noexcept { + if (this == &other) { + return *this; + } + delete fImpl; + fImpl = other.fImpl; + other.fImpl = nullptr; fTypeId = other.fTypeId; fSubTypeId = other.fSubTypeId; - uprv_strcpy(fCurrency, other.fCurrency); return *this; } @@ -2032,14 +2072,28 @@ MeasureUnit *MeasureUnit::clone() const { } MeasureUnit::~MeasureUnit() { + delete fImpl; + fImpl = nullptr; } const char *MeasureUnit::getType() const { + // We have a type & subtype only if fTypeId is present. + if (fTypeId == -1) { + return ""; + } return gTypes[fTypeId]; } const char *MeasureUnit::getSubtype() const { - return fCurrency[0] == 0 ? gSubTypes[getOffset()] : fCurrency; + // We have a type & subtype only if fTypeId is present. + if (fTypeId == -1) { + return ""; + } + return getIdentifier(); +} + +const char *MeasureUnit::getIdentifier() const { + return fImpl ? fImpl->identifier.data() : gSubTypes[getOffset()]; } UBool MeasureUnit::operator==(const UObject& other) const { @@ -2050,10 +2104,7 @@ UBool MeasureUnit::operator==(const UObject& other) const { return FALSE; } const MeasureUnit &rhs = static_cast(other); - return ( - fTypeId == rhs.fTypeId - && fSubTypeId == rhs.fSubTypeId - && uprv_strcmp(fCurrency, rhs.fCurrency) == 0); + return uprv_strcmp(getIdentifier(), rhs.getIdentifier()) == 0; } int32_t MeasureUnit::getIndex() const { @@ -2138,10 +2189,29 @@ int32_t MeasureUnit::internalGetIndexForTypeAndSubtype(const char *type, const c return gIndexes[t] + st - gOffsets[t]; } +bool MeasureUnit::findBySubType(StringPiece subType, MeasureUnit* output) { + for (int32_t t = 0; t < UPRV_LENGTHOF(gOffsets) - 1; t++) { + // Skip currency units + if (gIndexes[t] == gIndexes[t + 1]) { + continue; + } + int32_t st = binarySearch(gSubTypes, gOffsets[t], gOffsets[t + 1], subType); + if (st >= 0) { + output->setTo(t, st - gOffsets[t]); + return true; + } + } + return false; +} + MeasureUnit MeasureUnit::resolveUnitPerUnit( const MeasureUnit &unit, const MeasureUnit &perUnit, bool* isResolved) { int32_t unitOffset = unit.getOffset(); int32_t perUnitOffset = perUnit.getOffset(); + if (unitOffset == -1 || perUnitOffset == -1) { + *isResolved = false; + return MeasureUnit(); + } // binary search for (unitOffset, perUnitOffset) int32_t start = 0; @@ -2189,18 +2259,24 @@ void MeasureUnit::initTime(const char *timeId) { fSubTypeId = result - gOffsets[fTypeId]; } -void MeasureUnit::initCurrency(const char *isoCurrency) { +void MeasureUnit::initCurrency(StringPiece isoCurrency) { int32_t result = binarySearch(gTypes, 0, UPRV_LENGTHOF(gTypes), "currency"); U_ASSERT(result != -1); fTypeId = result; result = binarySearch( gSubTypes, gOffsets[fTypeId], gOffsets[fTypeId + 1], isoCurrency); - if (result != -1) { - fSubTypeId = result - gOffsets[fTypeId]; - } else { - uprv_strncpy(fCurrency, isoCurrency, UPRV_LENGTHOF(fCurrency)); - fCurrency[3] = 0; + if (result == -1) { + fImpl = new MeasureUnitImpl(MeasureUnitImpl::forCurrencyCode(isoCurrency)); + if (fImpl) { + fSubTypeId = -1; + return; + } + // malloc error: fall back to the undefined currency + result = binarySearch( + gSubTypes, gOffsets[fTypeId], gOffsets[fTypeId + 1], kDefaultCurrency8); + U_ASSERT(result != -1); } + fSubTypeId = result - gOffsets[fTypeId]; } void MeasureUnit::initNoUnit(const char *subtype) { @@ -2215,10 +2291,14 @@ void MeasureUnit::initNoUnit(const char *subtype) { void MeasureUnit::setTo(int32_t typeId, int32_t subTypeId) { fTypeId = typeId; fSubTypeId = subTypeId; - fCurrency[0] = 0; + delete fImpl; + fImpl = nullptr; } int32_t MeasureUnit::getOffset() const { + if (fTypeId < 0 || fSubTypeId < 0) { + return -1; + } return gOffsets[fTypeId] + fSubTypeId; } diff --git a/deps/icu-small/source/i18n/measunit_extra.cpp b/deps/icu-small/source/i18n/measunit_extra.cpp new file mode 100644 index 00000000000000..aeb60017a18fce --- /dev/null +++ b/deps/icu-small/source/i18n/measunit_extra.cpp @@ -0,0 +1,893 @@ +// © 2020 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +// Extra functions for MeasureUnit not needed for all clients. +// Separate .o file so that it can be removed for modularity. + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +// Allow implicit conversion from char16_t* to UnicodeString for this file: +// Helpful in toString methods and elsewhere. +#define UNISTR_FROM_STRING_EXPLICIT + +#include +#include "cstring.h" +#include "measunit_impl.h" +#include "uarrsort.h" +#include "uassert.h" +#include "ucln_in.h" +#include "umutex.h" +#include "unicode/errorcode.h" +#include "unicode/localpointer.h" +#include "unicode/measunit.h" +#include "unicode/ucharstrie.h" +#include "unicode/ucharstriebuilder.h" + +#include "cstr.h" + +U_NAMESPACE_BEGIN + + +namespace { + +// TODO: Propose a new error code for this? +constexpr UErrorCode kUnitIdentifierSyntaxError = U_ILLEGAL_ARGUMENT_ERROR; + +// Trie value offset for SI Prefixes. This is big enough to ensure we only +// insert positive integers into the trie. +constexpr int32_t kSIPrefixOffset = 64; + +// Trie value offset for compound parts, e.g. "-per-", "-", "-and-". +constexpr int32_t kCompoundPartOffset = 128; + +enum CompoundPart { + // Represents "-per-" + COMPOUND_PART_PER = kCompoundPartOffset, + // Represents "-" + COMPOUND_PART_TIMES, + // Represents "-and-" + COMPOUND_PART_AND, +}; + +// Trie value offset for "per-". +constexpr int32_t kInitialCompoundPartOffset = 192; + +enum InitialCompoundPart { + // Represents "per-", the only compound part that can appear at the start of + // an identifier. + INITIAL_COMPOUND_PART_PER = kInitialCompoundPartOffset, +}; + +// Trie value offset for powers like "square-", "cubic-", "p2-" etc. +constexpr int32_t kPowerPartOffset = 256; + +enum PowerPart { + POWER_PART_P2 = kPowerPartOffset + 2, + POWER_PART_P3, + POWER_PART_P4, + POWER_PART_P5, + POWER_PART_P6, + POWER_PART_P7, + POWER_PART_P8, + POWER_PART_P9, + POWER_PART_P10, + POWER_PART_P11, + POWER_PART_P12, + POWER_PART_P13, + POWER_PART_P14, + POWER_PART_P15, +}; + +// Trie value offset for simple units, e.g. "gram", "nautical-mile", +// "fluid-ounce-imperial". +constexpr int32_t kSimpleUnitOffset = 512; + +const struct SIPrefixStrings { + const char* const string; + UMeasureSIPrefix value; +} gSIPrefixStrings[] = { + { "yotta", UMEASURE_SI_PREFIX_YOTTA }, + { "zetta", UMEASURE_SI_PREFIX_ZETTA }, + { "exa", UMEASURE_SI_PREFIX_EXA }, + { "peta", UMEASURE_SI_PREFIX_PETA }, + { "tera", UMEASURE_SI_PREFIX_TERA }, + { "giga", UMEASURE_SI_PREFIX_GIGA }, + { "mega", UMEASURE_SI_PREFIX_MEGA }, + { "kilo", UMEASURE_SI_PREFIX_KILO }, + { "hecto", UMEASURE_SI_PREFIX_HECTO }, + { "deka", UMEASURE_SI_PREFIX_DEKA }, + { "deci", UMEASURE_SI_PREFIX_DECI }, + { "centi", UMEASURE_SI_PREFIX_CENTI }, + { "milli", UMEASURE_SI_PREFIX_MILLI }, + { "micro", UMEASURE_SI_PREFIX_MICRO }, + { "nano", UMEASURE_SI_PREFIX_NANO }, + { "pico", UMEASURE_SI_PREFIX_PICO }, + { "femto", UMEASURE_SI_PREFIX_FEMTO }, + { "atto", UMEASURE_SI_PREFIX_ATTO }, + { "zepto", UMEASURE_SI_PREFIX_ZEPTO }, + { "yocto", UMEASURE_SI_PREFIX_YOCTO }, +}; + +// TODO(ICU-21059): Get this list from data +const char16_t* const gSimpleUnits[] = { + u"candela", + u"carat", + u"gram", + u"ounce", + u"ounce-troy", + u"pound", + u"kilogram", + u"stone", + u"ton", + u"metric-ton", + u"earth-mass", + u"solar-mass", + u"point", + u"inch", + u"foot", + u"yard", + u"meter", + u"fathom", + u"furlong", + u"mile", + u"nautical-mile", + u"mile-scandinavian", + u"100-kilometer", + u"earth-radius", + u"solar-radius", + u"astronomical-unit", + u"light-year", + u"parsec", + u"second", + u"minute", + u"hour", + u"day", + u"day-person", + u"week", + u"week-person", + u"month", + u"month-person", + u"year", + u"year-person", + u"decade", + u"century", + u"ampere", + u"fahrenheit", + u"kelvin", + u"celsius", + u"arc-second", + u"arc-minute", + u"degree", + u"radian", + u"revolution", + u"item", + u"mole", + u"permillion", + u"permyriad", + u"permille", + u"percent", + u"karat", + u"portion", + u"bit", + u"byte", + u"dot", + u"pixel", + u"em", + u"hertz", + u"newton", + u"pound-force", + u"pascal", + u"bar", + u"atmosphere", + u"ofhg", + u"electronvolt", + u"dalton", + u"joule", + u"calorie", + u"british-thermal-unit", + u"foodcalorie", + u"therm-us", + u"watt", + u"horsepower", + u"solar-luminosity", + u"volt", + u"ohm", + u"dunam", + u"acre", + u"hectare", + u"teaspoon", + u"tablespoon", + u"fluid-ounce-imperial", + u"fluid-ounce", + u"cup", + u"cup-metric", + u"pint", + u"pint-metric", + u"quart", + u"liter", + u"gallon", + u"gallon-imperial", + u"bushel", + u"barrel", + u"knot", + u"g-force", + u"lux", +}; + +icu::UInitOnce gUnitExtrasInitOnce = U_INITONCE_INITIALIZER; + +char16_t* kSerializedUnitExtrasStemTrie = nullptr; + +UBool U_CALLCONV cleanupUnitExtras() { + uprv_free(kSerializedUnitExtrasStemTrie); + kSerializedUnitExtrasStemTrie = nullptr; + gUnitExtrasInitOnce.reset(); + return TRUE; +} + +void U_CALLCONV initUnitExtras(UErrorCode& status) { + ucln_i18n_registerCleanup(UCLN_I18N_UNIT_EXTRAS, cleanupUnitExtras); + + UCharsTrieBuilder b(status); + if (U_FAILURE(status)) { return; } + + // Add SI prefixes + for (const auto& siPrefixInfo : gSIPrefixStrings) { + UnicodeString uSIPrefix(siPrefixInfo.string, -1, US_INV); + b.add(uSIPrefix, siPrefixInfo.value + kSIPrefixOffset, status); + } + if (U_FAILURE(status)) { return; } + + // Add syntax parts (compound, power prefixes) + b.add(u"-per-", COMPOUND_PART_PER, status); + b.add(u"-", COMPOUND_PART_TIMES, status); + b.add(u"-and-", COMPOUND_PART_AND, status); + b.add(u"per-", INITIAL_COMPOUND_PART_PER, status); + b.add(u"square-", POWER_PART_P2, status); + b.add(u"cubic-", POWER_PART_P3, status); + b.add(u"p2-", POWER_PART_P2, status); + b.add(u"p3-", POWER_PART_P3, status); + b.add(u"p4-", POWER_PART_P4, status); + b.add(u"p5-", POWER_PART_P5, status); + b.add(u"p6-", POWER_PART_P6, status); + b.add(u"p7-", POWER_PART_P7, status); + b.add(u"p8-", POWER_PART_P8, status); + b.add(u"p9-", POWER_PART_P9, status); + b.add(u"p10-", POWER_PART_P10, status); + b.add(u"p11-", POWER_PART_P11, status); + b.add(u"p12-", POWER_PART_P12, status); + b.add(u"p13-", POWER_PART_P13, status); + b.add(u"p14-", POWER_PART_P14, status); + b.add(u"p15-", POWER_PART_P15, status); + if (U_FAILURE(status)) { return; } + + // Add sanctioned simple units by offset + int32_t simpleUnitOffset = kSimpleUnitOffset; + for (auto simpleUnit : gSimpleUnits) { + b.add(simpleUnit, simpleUnitOffset++, status); + } + + // Build the CharsTrie + // TODO: Use SLOW or FAST here? + UnicodeString result; + b.buildUnicodeString(USTRINGTRIE_BUILD_FAST, result, status); + if (U_FAILURE(status)) { return; } + + // Copy the result into the global constant pointer + size_t numBytes = result.length() * sizeof(char16_t); + kSerializedUnitExtrasStemTrie = static_cast(uprv_malloc(numBytes)); + uprv_memcpy(kSerializedUnitExtrasStemTrie, result.getBuffer(), numBytes); +} + +class Token { +public: + Token(int32_t match) : fMatch(match) {} + + enum Type { + TYPE_UNDEFINED, + TYPE_SI_PREFIX, + // Token type for "-per-", "-", and "-and-". + TYPE_COMPOUND_PART, + // Token type for "per-". + TYPE_INITIAL_COMPOUND_PART, + TYPE_POWER_PART, + TYPE_SIMPLE_UNIT, + }; + + // Calling getType() is invalid, resulting in an assertion failure, if Token + // value isn't positive. + Type getType() const { + U_ASSERT(fMatch > 0); + if (fMatch < kCompoundPartOffset) { + return TYPE_SI_PREFIX; + } + if (fMatch < kInitialCompoundPartOffset) { + return TYPE_COMPOUND_PART; + } + if (fMatch < kPowerPartOffset) { + return TYPE_INITIAL_COMPOUND_PART; + } + if (fMatch < kSimpleUnitOffset) { + return TYPE_POWER_PART; + } + return TYPE_SIMPLE_UNIT; + } + + UMeasureSIPrefix getSIPrefix() const { + U_ASSERT(getType() == TYPE_SI_PREFIX); + return static_cast(fMatch - kSIPrefixOffset); + } + + // Valid only for tokens with type TYPE_COMPOUND_PART. + int32_t getMatch() const { + U_ASSERT(getType() == TYPE_COMPOUND_PART); + return fMatch; + } + + int32_t getInitialCompoundPart() const { + // Even if there is only one InitialCompoundPart value, we have this + // function for the simplicity of code consistency. + U_ASSERT(getType() == TYPE_INITIAL_COMPOUND_PART); + // Defensive: if this assert fails, code using this function also needs + // to change. + U_ASSERT(fMatch == INITIAL_COMPOUND_PART_PER); + return fMatch; + } + + int8_t getPower() const { + U_ASSERT(getType() == TYPE_POWER_PART); + return static_cast(fMatch - kPowerPartOffset); + } + + int32_t getSimpleUnitIndex() const { + U_ASSERT(getType() == TYPE_SIMPLE_UNIT); + return fMatch - kSimpleUnitOffset; + } + +private: + int32_t fMatch; +}; + +class Parser { +public: + /** + * Factory function for parsing the given identifier. + * + * @param source The identifier to parse. This function does not make a copy + * of source: the underlying string that source points at, must outlive the + * parser. + * @param status ICU error code. + */ + static Parser from(StringPiece source, UErrorCode& status) { + if (U_FAILURE(status)) { + return Parser(); + } + umtx_initOnce(gUnitExtrasInitOnce, &initUnitExtras, status); + if (U_FAILURE(status)) { + return Parser(); + } + return Parser(source); + } + + MeasureUnitImpl parse(UErrorCode& status) { + MeasureUnitImpl result; + parseImpl(result, status); + return result; + } + +private: + // Tracks parser progress: the offset into fSource. + int32_t fIndex = 0; + + // Since we're not owning this memory, whatever is passed to the constructor + // should live longer than this Parser - and the parser shouldn't return any + // references to that string. + StringPiece fSource; + UCharsTrie fTrie; + + // Set to true when we've seen a "-per-" or a "per-", after which all units + // are in the denominator. Until we find an "-and-", at which point the + // identifier is invalid pending TODO(CLDR-13700). + bool fAfterPer = false; + + Parser() : fSource(""), fTrie(u"") {} + + Parser(StringPiece source) + : fSource(source), fTrie(kSerializedUnitExtrasStemTrie) {} + + inline bool hasNext() const { + return fIndex < fSource.length(); + } + + // Returns the next Token parsed from fSource, advancing fIndex to the end + // of that token in fSource. In case of U_FAILURE(status), the token + // returned will cause an abort if getType() is called on it. + Token nextToken(UErrorCode& status) { + fTrie.reset(); + int32_t match = -1; + // Saves the position in the fSource string for the end of the most + // recent matching token. + int32_t previ = -1; + // Find the longest token that matches a value in the trie: + while (fIndex < fSource.length()) { + auto result = fTrie.next(fSource.data()[fIndex++]); + if (result == USTRINGTRIE_NO_MATCH) { + break; + } else if (result == USTRINGTRIE_NO_VALUE) { + continue; + } + U_ASSERT(USTRINGTRIE_HAS_VALUE(result)); + match = fTrie.getValue(); + previ = fIndex; + if (result == USTRINGTRIE_FINAL_VALUE) { + break; + } + U_ASSERT(result == USTRINGTRIE_INTERMEDIATE_VALUE); + // continue; + } + + if (match < 0) { + status = kUnitIdentifierSyntaxError; + } else { + fIndex = previ; + } + return Token(match); + } + + /** + * Returns the next "single unit" via result. + * + * If a "-per-" was parsed, the result will have appropriate negative + * dimensionality. + * + * Returns an error if we parse both compound units and "-and-", since mixed + * compound units are not yet supported - TODO(CLDR-13700). + * + * @param result Will be overwritten by the result, if status shows success. + * @param sawAnd If an "-and-" was parsed prior to finding the "single + * unit", sawAnd is set to true. If not, it is left as is. + * @param status ICU error code. + */ + void nextSingleUnit(SingleUnitImpl& result, bool& sawAnd, UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } + + // state: + // 0 = no tokens seen yet (will accept power, SI prefix, or simple unit) + // 1 = power token seen (will not accept another power token) + // 2 = SI prefix token seen (will not accept a power or SI prefix token) + int32_t state = 0; + + bool atStart = fIndex == 0; + Token token = nextToken(status); + if (U_FAILURE(status)) { return; } + + if (atStart) { + // Identifiers optionally start with "per-". + if (token.getType() == Token::TYPE_INITIAL_COMPOUND_PART) { + U_ASSERT(token.getInitialCompoundPart() == INITIAL_COMPOUND_PART_PER); + fAfterPer = true; + result.dimensionality = -1; + + token = nextToken(status); + if (U_FAILURE(status)) { return; } + } + } else { + // All other SingleUnit's are separated from previous SingleUnit's + // via a compound part: + if (token.getType() != Token::TYPE_COMPOUND_PART) { + status = kUnitIdentifierSyntaxError; + return; + } + + switch (token.getMatch()) { + case COMPOUND_PART_PER: + if (sawAnd) { + // Mixed compound units not yet supported, + // TODO(CLDR-13700). + status = kUnitIdentifierSyntaxError; + return; + } + fAfterPer = true; + result.dimensionality = -1; + break; + + case COMPOUND_PART_TIMES: + if (fAfterPer) { + result.dimensionality = -1; + } + break; + + case COMPOUND_PART_AND: + if (fAfterPer) { + // Can't start with "-and-", and mixed compound units + // not yet supported, TODO(CLDR-13700). + status = kUnitIdentifierSyntaxError; + return; + } + sawAnd = true; + break; + } + + token = nextToken(status); + if (U_FAILURE(status)) { return; } + } + + // Read tokens until we have a complete SingleUnit or we reach the end. + while (true) { + switch (token.getType()) { + case Token::TYPE_POWER_PART: + if (state > 0) { + status = kUnitIdentifierSyntaxError; + return; + } + result.dimensionality *= token.getPower(); + state = 1; + break; + + case Token::TYPE_SI_PREFIX: + if (state > 1) { + status = kUnitIdentifierSyntaxError; + return; + } + result.siPrefix = token.getSIPrefix(); + state = 2; + break; + + case Token::TYPE_SIMPLE_UNIT: + result.index = token.getSimpleUnitIndex(); + return; + + default: + status = kUnitIdentifierSyntaxError; + return; + } + + if (!hasNext()) { + // We ran out of tokens before finding a complete single unit. + status = kUnitIdentifierSyntaxError; + return; + } + token = nextToken(status); + if (U_FAILURE(status)) { + return; + } + } + } + + /// @param result is modified, not overridden. Caller must pass in a + /// default-constructed (empty) MeasureUnitImpl instance. + void parseImpl(MeasureUnitImpl& result, UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } + if (fSource.empty()) { + // The dimenionless unit: nothing to parse. leave result as is. + return; + } + int32_t unitNum = 0; + while (hasNext()) { + bool sawAnd = false; + SingleUnitImpl singleUnit; + nextSingleUnit(singleUnit, sawAnd, status); + if (U_FAILURE(status)) { + return; + } + U_ASSERT(!singleUnit.isDimensionless()); + bool added = result.append(singleUnit, status); + if (sawAnd && !added) { + // Two similar units are not allowed in a mixed unit + status = kUnitIdentifierSyntaxError; + return; + } + if ((++unitNum) >= 2) { + // nextSingleUnit fails appropriately for "per" and "and" in the + // same identifier. It doesn't fail for other compound units + // (COMPOUND_PART_TIMES). Consequently we take care of that + // here. + UMeasureUnitComplexity complexity = + sawAnd ? UMEASURE_UNIT_MIXED : UMEASURE_UNIT_COMPOUND; + if (unitNum == 2) { + U_ASSERT(result.complexity == UMEASURE_UNIT_SINGLE); + result.complexity = complexity; + } else if (result.complexity != complexity) { + // Can't have mixed compound units + status = kUnitIdentifierSyntaxError; + return; + } + } + } + } +}; + +int32_t U_CALLCONV +compareSingleUnits(const void* /*context*/, const void* left, const void* right) { + auto realLeft = static_cast(left); + auto realRight = static_cast(right); + return (*realLeft)->compareTo(**realRight); +} + +/** + * Generate the identifier string for a single unit in place. + * + * Does not support the dimensionless SingleUnitImpl: calling serializeSingle + * with the dimensionless unit results in an U_INTERNAL_PROGRAM_ERROR. + * + * @param first If singleUnit is part of a compound unit, and not its first + * single unit, set this to false. Otherwise: set to true. + */ +void serializeSingle(const SingleUnitImpl& singleUnit, bool first, CharString& output, UErrorCode& status) { + if (first && singleUnit.dimensionality < 0) { + // Essentially the "unary per". For compound units with a numerator, the + // caller takes care of the "binary per". + output.append("per-", status); + } + + if (singleUnit.isDimensionless()) { + status = U_INTERNAL_PROGRAM_ERROR; + return; + } + int8_t posPower = std::abs(singleUnit.dimensionality); + if (posPower == 0) { + status = U_INTERNAL_PROGRAM_ERROR; + } else if (posPower == 1) { + // no-op + } else if (posPower == 2) { + output.append("square-", status); + } else if (posPower == 3) { + output.append("cubic-", status); + } else if (posPower < 10) { + output.append('p', status); + output.append(posPower + '0', status); + output.append('-', status); + } else if (posPower <= 15) { + output.append("p1", status); + output.append('0' + (posPower % 10), status); + output.append('-', status); + } else { + status = kUnitIdentifierSyntaxError; + } + if (U_FAILURE(status)) { + return; + } + + if (singleUnit.siPrefix != UMEASURE_SI_PREFIX_ONE) { + for (const auto& siPrefixInfo : gSIPrefixStrings) { + if (siPrefixInfo.value == singleUnit.siPrefix) { + output.append(siPrefixInfo.string, status); + break; + } + } + } + if (U_FAILURE(status)) { + return; + } + + output.appendInvariantChars(gSimpleUnits[singleUnit.index], status); +} + +/** + * Normalize a MeasureUnitImpl and generate the identifier string in place. + */ +void serialize(MeasureUnitImpl& impl, UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } + U_ASSERT(impl.identifier.isEmpty()); + if (impl.units.length() == 0) { + // Dimensionless, constructed by the default constructor: no appending + // to impl.identifier, we wish it to contain the zero-length string. + return; + } + if (impl.complexity == UMEASURE_UNIT_COMPOUND) { + // Note: don't sort a MIXED unit + uprv_sortArray( + impl.units.getAlias(), + impl.units.length(), + sizeof(impl.units[0]), + compareSingleUnits, + nullptr, + false, + &status); + if (U_FAILURE(status)) { + return; + } + } + serializeSingle(*impl.units[0], true, impl.identifier, status); + if (impl.units.length() == 1) { + return; + } + for (int32_t i = 1; i < impl.units.length(); i++) { + const SingleUnitImpl& prev = *impl.units[i-1]; + const SingleUnitImpl& curr = *impl.units[i]; + if (impl.complexity == UMEASURE_UNIT_MIXED) { + impl.identifier.append("-and-", status); + serializeSingle(curr, true, impl.identifier, status); + } else { + if (prev.dimensionality > 0 && curr.dimensionality < 0) { + impl.identifier.append("-per-", status); + } else { + impl.identifier.append('-', status); + } + serializeSingle(curr, false, impl.identifier, status); + } + } + +} + +/** + * Appends a SingleUnitImpl to a MeasureUnitImpl. + * + * @return true if a new item was added. If unit is the dimensionless unit, it + * is never added: the return value will always be false. + */ +bool appendImpl(MeasureUnitImpl& impl, const SingleUnitImpl& unit, UErrorCode& status) { + if (unit.isDimensionless()) { + // We don't append dimensionless units. + return false; + } + // Find a similar unit that already exists, to attempt to coalesce + SingleUnitImpl* oldUnit = nullptr; + for (int32_t i = 0; i < impl.units.length(); i++) { + auto* candidate = impl.units[i]; + if (candidate->isCompatibleWith(unit)) { + oldUnit = candidate; + } + } + if (oldUnit) { + // Both dimensionalities will be positive, or both will be negative, by + // virtue of isCompatibleWith(). + oldUnit->dimensionality += unit.dimensionality; + } else { + SingleUnitImpl* destination = impl.units.emplaceBack(); + if (!destination) { + status = U_MEMORY_ALLOCATION_ERROR; + return false; + } + *destination = unit; + } + return (oldUnit == nullptr); +} + +} // namespace + + +SingleUnitImpl SingleUnitImpl::forMeasureUnit(const MeasureUnit& measureUnit, UErrorCode& status) { + MeasureUnitImpl temp; + const MeasureUnitImpl& impl = MeasureUnitImpl::forMeasureUnit(measureUnit, temp, status); + if (U_FAILURE(status)) { + return {}; + } + if (impl.units.length() == 0) { + return {}; + } + if (impl.units.length() == 1) { + return *impl.units[0]; + } + status = U_ILLEGAL_ARGUMENT_ERROR; + return {}; +} + +MeasureUnit SingleUnitImpl::build(UErrorCode& status) const { + MeasureUnitImpl temp; + temp.append(*this, status); + return std::move(temp).build(status); +} + + +MeasureUnitImpl MeasureUnitImpl::forIdentifier(StringPiece identifier, UErrorCode& status) { + return Parser::from(identifier, status).parse(status); +} + +const MeasureUnitImpl& MeasureUnitImpl::forMeasureUnit( + const MeasureUnit& measureUnit, MeasureUnitImpl& memory, UErrorCode& status) { + if (measureUnit.fImpl) { + return *measureUnit.fImpl; + } else { + memory = Parser::from(measureUnit.getIdentifier(), status).parse(status); + return memory; + } +} + +MeasureUnitImpl MeasureUnitImpl::forMeasureUnitMaybeCopy( + const MeasureUnit& measureUnit, UErrorCode& status) { + if (measureUnit.fImpl) { + return measureUnit.fImpl->copy(status); + } else { + return Parser::from(measureUnit.getIdentifier(), status).parse(status); + } +} + +void MeasureUnitImpl::takeReciprocal(UErrorCode& /*status*/) { + identifier.clear(); + for (int32_t i = 0; i < units.length(); i++) { + units[i]->dimensionality *= -1; + } +} + +bool MeasureUnitImpl::append(const SingleUnitImpl& singleUnit, UErrorCode& status) { + identifier.clear(); + return appendImpl(*this, singleUnit, status); +} + +MeasureUnit MeasureUnitImpl::build(UErrorCode& status) && { + serialize(*this, status); + return MeasureUnit(std::move(*this)); +} + + +MeasureUnit MeasureUnit::forIdentifier(StringPiece identifier, UErrorCode& status) { + return Parser::from(identifier, status).parse(status).build(status); +} + +UMeasureUnitComplexity MeasureUnit::getComplexity(UErrorCode& status) const { + MeasureUnitImpl temp; + return MeasureUnitImpl::forMeasureUnit(*this, temp, status).complexity; +} + +UMeasureSIPrefix MeasureUnit::getSIPrefix(UErrorCode& status) const { + return SingleUnitImpl::forMeasureUnit(*this, status).siPrefix; +} + +MeasureUnit MeasureUnit::withSIPrefix(UMeasureSIPrefix prefix, UErrorCode& status) const { + SingleUnitImpl singleUnit = SingleUnitImpl::forMeasureUnit(*this, status); + singleUnit.siPrefix = prefix; + return singleUnit.build(status); +} + +int32_t MeasureUnit::getDimensionality(UErrorCode& status) const { + SingleUnitImpl singleUnit = SingleUnitImpl::forMeasureUnit(*this, status); + if (U_FAILURE(status)) { return 0; } + if (singleUnit.isDimensionless()) { + return 0; + } + return singleUnit.dimensionality; +} + +MeasureUnit MeasureUnit::withDimensionality(int32_t dimensionality, UErrorCode& status) const { + SingleUnitImpl singleUnit = SingleUnitImpl::forMeasureUnit(*this, status); + singleUnit.dimensionality = dimensionality; + return singleUnit.build(status); +} + +MeasureUnit MeasureUnit::reciprocal(UErrorCode& status) const { + MeasureUnitImpl impl = MeasureUnitImpl::forMeasureUnitMaybeCopy(*this, status); + impl.takeReciprocal(status); + return std::move(impl).build(status); +} + +MeasureUnit MeasureUnit::product(const MeasureUnit& other, UErrorCode& status) const { + MeasureUnitImpl impl = MeasureUnitImpl::forMeasureUnitMaybeCopy(*this, status); + MeasureUnitImpl temp; + const MeasureUnitImpl& otherImpl = MeasureUnitImpl::forMeasureUnit(other, temp, status); + if (impl.complexity == UMEASURE_UNIT_MIXED || otherImpl.complexity == UMEASURE_UNIT_MIXED) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return {}; + } + for (int32_t i = 0; i < otherImpl.units.length(); i++) { + impl.append(*otherImpl.units[i], status); + } + if (impl.units.length() > 1) { + impl.complexity = UMEASURE_UNIT_COMPOUND; + } + return std::move(impl).build(status); +} + +LocalArray MeasureUnit::splitToSingleUnits(int32_t& outCount, UErrorCode& status) const { + MeasureUnitImpl temp; + const MeasureUnitImpl& impl = MeasureUnitImpl::forMeasureUnit(*this, temp, status); + outCount = impl.units.length(); + MeasureUnit* arr = new MeasureUnit[outCount]; + for (int32_t i = 0; i < outCount; i++) { + arr[i] = impl.units[i]->build(status); + } + return LocalArray(arr, status); +} + + +U_NAMESPACE_END + +#endif /* !UNCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/measunit_impl.h b/deps/icu-small/source/i18n/measunit_impl.h new file mode 100644 index 00000000000000..c886d3c29a38b2 --- /dev/null +++ b/deps/icu-small/source/i18n/measunit_impl.h @@ -0,0 +1,213 @@ +// © 2020 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#ifndef __MEASUNIT_IMPL_H__ +#define __MEASUNIT_IMPL_H__ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/measunit.h" +#include "cmemory.h" +#include "charstr.h" + +U_NAMESPACE_BEGIN + + +static const char16_t kDefaultCurrency[] = u"XXX"; +static const char kDefaultCurrency8[] = "XXX"; + + +/** + * A struct representing a single unit (optional SI prefix and dimensionality). + */ +struct SingleUnitImpl : public UMemory { + /** + * Gets a single unit from the MeasureUnit. If there are multiple single units, sets an error + * code and returns the base dimensionless unit. Parses if necessary. + */ + static SingleUnitImpl forMeasureUnit(const MeasureUnit& measureUnit, UErrorCode& status); + + /** Transform this SingleUnitImpl into a MeasureUnit, simplifying if possible. */ + MeasureUnit build(UErrorCode& status) const; + + /** + * Compare this SingleUnitImpl to another SingleUnitImpl for the sake of + * sorting and coalescing. + * + * Takes the sign of dimensionality into account, but not the absolute + * value: per-meter is not considered the same as meter, but meter is + * considered the same as square-meter. + * + * The dimensionless unit generally does not get compared, but if it did, it + * would sort before other units by virtue of index being < 0 and + * dimensionality not being negative. + */ + int32_t compareTo(const SingleUnitImpl& other) const { + if (dimensionality < 0 && other.dimensionality > 0) { + // Positive dimensions first + return 1; + } + if (dimensionality > 0 && other.dimensionality < 0) { + return -1; + } + if (index < other.index) { + return -1; + } + if (index > other.index) { + return 1; + } + if (siPrefix < other.siPrefix) { + return -1; + } + if (siPrefix > other.siPrefix) { + return 1; + } + return 0; + } + + /** + * Return whether this SingleUnitImpl is compatible with another for the purpose of coalescing. + * + * Units with the same base unit and SI prefix should match, except that they must also have + * the same dimensionality sign, such that we don't merge numerator and denominator. + */ + bool isCompatibleWith(const SingleUnitImpl& other) const { + return (compareTo(other) == 0); + } + + /** + * Returns true if this unit is the "dimensionless base unit", as produced + * by the MeasureUnit() default constructor. (This does not include the + * likes of concentrations or angles.) + */ + bool isDimensionless() const { + return index == -1; + } + + /** + * Simple unit index, unique for every simple unit, -1 for the dimensionless + * unit. This is an index into a string list in measunit_extra.cpp. + * + * The default value is -1, meaning the dimensionless unit: + * isDimensionless() will return true, until index is changed. + */ + int32_t index = -1; + + /** + * SI prefix. + * + * This is ignored for the dimensionless unit. + */ + UMeasureSIPrefix siPrefix = UMEASURE_SI_PREFIX_ONE; + + /** + * Dimensionality. + * + * This is meaningless for the dimensionless unit. + */ + int32_t dimensionality = 1; +}; + + +/** + * Internal representation of measurement units. Capable of representing all complexities of units, + * including mixed and compound units. + */ +struct MeasureUnitImpl : public UMemory { + /** Extract the MeasureUnitImpl from a MeasureUnit. */ + static inline const MeasureUnitImpl* get(const MeasureUnit& measureUnit) { + return measureUnit.fImpl; + } + + /** + * Parse a unit identifier into a MeasureUnitImpl. + * + * @param identifier The unit identifier string. + * @param status Set if the identifier string is not valid. + * @return A newly parsed value object. Behaviour of this unit is + * unspecified if an error is returned via status. + */ + static MeasureUnitImpl forIdentifier(StringPiece identifier, UErrorCode& status); + + /** + * Extract the MeasureUnitImpl from a MeasureUnit, or parse if it is not present. + * + * @param measureUnit The source MeasureUnit. + * @param memory A place to write the new MeasureUnitImpl if parsing is required. + * @param status Set if an error occurs. + * @return A reference to either measureUnit.fImpl or memory. + */ + static const MeasureUnitImpl& forMeasureUnit( + const MeasureUnit& measureUnit, MeasureUnitImpl& memory, UErrorCode& status); + + /** + * Extract the MeasureUnitImpl from a MeasureUnit, or parse if it is not present. + * + * @param measureUnit The source MeasureUnit. + * @param status Set if an error occurs. + * @return A value object, either newly parsed or copied from measureUnit. + */ + static MeasureUnitImpl forMeasureUnitMaybeCopy( + const MeasureUnit& measureUnit, UErrorCode& status); + + /** + * Used for currency units. + */ + static inline MeasureUnitImpl forCurrencyCode(StringPiece currencyCode) { + MeasureUnitImpl result; + UErrorCode localStatus = U_ZERO_ERROR; + result.identifier.append(currencyCode, localStatus); + // localStatus is not expected to fail since currencyCode should be 3 chars long + return result; + } + + /** Transform this MeasureUnitImpl into a MeasureUnit, simplifying if possible. */ + MeasureUnit build(UErrorCode& status) &&; + + /** + * Create a copy of this MeasureUnitImpl. Don't use copy constructor to make this explicit. + */ + inline MeasureUnitImpl copy(UErrorCode& status) const { + MeasureUnitImpl result; + result.complexity = complexity; + result.units.appendAll(units, status); + result.identifier.append(identifier, status); + return result; + } + + /** Mutates this MeasureUnitImpl to take the reciprocal. */ + void takeReciprocal(UErrorCode& status); + + /** + * Mutates this MeasureUnitImpl to append a single unit. + * + * @return true if a new item was added. If unit is the dimensionless unit, + * it is never added: the return value will always be false. + */ + bool append(const SingleUnitImpl& singleUnit, UErrorCode& status); + + /** The complexity, either SINGLE, COMPOUND, or MIXED. */ + UMeasureUnitComplexity complexity = UMEASURE_UNIT_SINGLE; + + /** + * The list of simple units. These may be summed or multiplied, based on the + * value of the complexity field. + * + * The "dimensionless" unit (SingleUnitImpl default constructor) must not be + * added to this list. + */ + MaybeStackVector units; + + /** + * The full unit identifier. Owned by the MeasureUnitImpl. Empty if not computed. + */ + CharString identifier; +}; + + +U_NAMESPACE_END + +#endif /* #if !UCONFIG_NO_FORMATTING */ +#endif //__MEASUNIT_IMPL_H__ diff --git a/deps/icu-small/source/i18n/name2uni.cpp b/deps/icu-small/source/i18n/name2uni.cpp index 90bca9d71bef87..b1812178660421 100644 --- a/deps/icu-small/source/i18n/name2uni.cpp +++ b/deps/icu-small/source/i18n/name2uni.cpp @@ -190,6 +190,7 @@ void NameUnicodeTransliterator::handleTransliterate(Replaceable& text, UTransPos } if (uprv_isInvariantUString(name.getBuffer(), len)) { + cbuf[0] = 0; name.extract(0, len, cbuf, maxLen, US_INV); UErrorCode status = U_ZERO_ERROR; diff --git a/deps/icu-small/source/i18n/nounit.cpp b/deps/icu-small/source/i18n/nounit.cpp index 076f76f199c737..1d4aa05506e98d 100644 --- a/deps/icu-small/source/i18n/nounit.cpp +++ b/deps/icu-small/source/i18n/nounit.cpp @@ -11,7 +11,7 @@ U_NAMESPACE_BEGIN UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NoUnit) NoUnit U_EXPORT2 NoUnit::base() { - return NoUnit("base"); + return NoUnit(""); } NoUnit U_EXPORT2 NoUnit::percent() { diff --git a/deps/icu-small/source/i18n/number_affixutils.cpp b/deps/icu-small/source/i18n/number_affixutils.cpp index 1039a84c656124..a74ec2d634799e 100644 --- a/deps/icu-small/source/i18n/number_affixutils.cpp +++ b/deps/icu-small/source/i18n/number_affixutils.cpp @@ -131,25 +131,25 @@ UnicodeString AffixUtils::escape(const UnicodeString &input) { Field AffixUtils::getFieldForType(AffixPatternType type) { switch (type) { case TYPE_MINUS_SIGN: - return UNUM_SIGN_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_SIGN_FIELD}; case TYPE_PLUS_SIGN: - return UNUM_SIGN_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_SIGN_FIELD}; case TYPE_PERCENT: - return UNUM_PERCENT_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_PERCENT_FIELD}; case TYPE_PERMILLE: - return UNUM_PERMILL_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_PERMILL_FIELD}; case TYPE_CURRENCY_SINGLE: - return UNUM_CURRENCY_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}; case TYPE_CURRENCY_DOUBLE: - return UNUM_CURRENCY_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}; case TYPE_CURRENCY_TRIPLE: - return UNUM_CURRENCY_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}; case TYPE_CURRENCY_QUAD: - return UNUM_CURRENCY_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}; case TYPE_CURRENCY_QUINT: - return UNUM_CURRENCY_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}; case TYPE_CURRENCY_OVERFLOW: - return UNUM_CURRENCY_FIELD; + return {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}; default: UPRV_UNREACHABLE; } @@ -165,7 +165,11 @@ AffixUtils::unescape(const UnicodeString &affixPattern, FormattedStringBuilder & if (U_FAILURE(status)) { return length; } if (tag.type == TYPE_CURRENCY_OVERFLOW) { // Don't go to the provider for this special case - length += output.insertCodePoint(position + length, 0xFFFD, UNUM_CURRENCY_FIELD, status); + length += output.insertCodePoint( + position + length, + 0xFFFD, + {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}, + status); } else if (tag.type < 0) { length += output.insert( position + length, provider.getSymbol(tag.type), getFieldForType(tag.type), status); @@ -218,7 +222,7 @@ bool AffixUtils::hasCurrencySymbols(const UnicodeString &affixPattern, UErrorCod while (hasNext(tag, affixPattern)) { tag = nextToken(tag, affixPattern, status); if (U_FAILURE(status)) { return false; } - if (tag.type < 0 && getFieldForType(tag.type) == UNUM_CURRENCY_FIELD) { + if (tag.type < 0 && getFieldForType(tag.type) == Field(UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD)) { return true; } } diff --git a/deps/icu-small/source/i18n/number_asformat.cpp b/deps/icu-small/source/i18n/number_asformat.cpp index e876174fdce0ee..9d10d1f5580fbe 100644 --- a/deps/icu-small/source/i18n/number_asformat.cpp +++ b/deps/icu-small/source/i18n/number_asformat.cpp @@ -102,4 +102,16 @@ const LocalizedNumberFormatter& LocalizedNumberFormatterAsFormat::getNumberForma return fFormatter; } + +// Definitions of public API methods (put here for dependency disentanglement) + +Format* LocalizedNumberFormatter::toFormat(UErrorCode& status) const { + if (U_FAILURE(status)) { + return nullptr; + } + LocalPointer retval( + new LocalizedNumberFormatterAsFormat(*this, fMacros.locale), status); + return retval.orphan(); +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_capi.cpp b/deps/icu-small/source/i18n/number_capi.cpp index 712e0a6631db56..d61440d081e9fb 100644 --- a/deps/icu-small/source/i18n/number_capi.cpp +++ b/deps/icu-small/source/i18n/number_capi.cpp @@ -156,7 +156,7 @@ unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t buf return 0; } - return result->fImpl.toTempString(*ec).extract(buffer, bufferCapacity, *ec); + return result->fData.toTempString(*ec).extract(buffer, bufferCapacity, *ec); } U_CAPI UBool U_EXPORT2 @@ -173,7 +173,7 @@ unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* u fp.setField(ufpos->field); fp.setBeginIndex(ufpos->beginIndex); fp.setEndIndex(ufpos->endIndex); - bool retval = result->fImpl.nextFieldPosition(fp, *ec); + bool retval = result->fData.nextFieldPosition(fp, *ec); ufpos->beginIndex = fp.getBeginIndex(); ufpos->endIndex = fp.getEndIndex(); // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool @@ -192,7 +192,8 @@ unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPosition } auto* fpi = reinterpret_cast(ufpositer); - result->fImpl.getAllFieldPositions(*fpi, *ec); + FieldPositionIteratorHandler fpih(fpi, *ec); + result->fData.getAllFieldPositions(fpih, *ec); } U_CAPI void U_EXPORT2 diff --git a/deps/icu-small/source/i18n/number_compact.cpp b/deps/icu-small/source/i18n/number_compact.cpp index 3d259999d6ce52..e1fef8feb52298 100644 --- a/deps/icu-small/source/i18n/number_compact.cpp +++ b/deps/icu-small/source/i18n/number_compact.cpp @@ -215,19 +215,25 @@ void CompactData::CompactDataSink::put(const char *key, ResourceValue &value, UB /// END OF CompactData.java; BEGIN CompactNotation.java /// /////////////////////////////////////////////////////////// -CompactHandler::CompactHandler(CompactStyle compactStyle, const Locale &locale, const char *nsName, - CompactType compactType, const PluralRules *rules, - MutablePatternModifier *buildReference, const MicroPropsGenerator *parent, - UErrorCode &status) - : rules(rules), parent(parent) { +CompactHandler::CompactHandler( + CompactStyle compactStyle, + const Locale &locale, + const char *nsName, + CompactType compactType, + const PluralRules *rules, + MutablePatternModifier *buildReference, + bool safe, + const MicroPropsGenerator *parent, + UErrorCode &status) + : rules(rules), parent(parent), safe(safe) { data.populate(locale, nsName, compactStyle, compactType, status); - if (buildReference != nullptr) { + if (safe) { // Safe code path precomputeAllModifiers(*buildReference, status); - safe = TRUE; } else { // Unsafe code path - safe = FALSE; + // Store the MutablePatternModifier reference. + unsafePatternModifier = buildReference; } } @@ -260,7 +266,7 @@ void CompactHandler::precomputeAllModifiers(MutablePatternModifier &buildReferen ParsedPatternInfo patternInfo; PatternParser::parseToPatternInfo(UnicodeString(patternString), patternInfo, status); if (U_FAILURE(status)) { return; } - buildReference.setPatternInfo(&patternInfo, UNUM_COMPACT_FIELD); + buildReference.setPatternInfo(&patternInfo, {UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD}); info.mod = buildReference.createImmutable(status); if (U_FAILURE(status)) { return; } info.patternString = patternString; @@ -274,12 +280,13 @@ void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micr // Treat zero, NaN, and infinity as if they had magnitude 0 int32_t magnitude; + int32_t multiplier = 0; if (quantity.isZeroish()) { magnitude = 0; micros.rounder.apply(quantity, status); } else { // TODO: Revisit chooseMultiplierAndApply - int32_t multiplier = micros.rounder.chooseMultiplierAndApply(quantity, data, status); + multiplier = micros.rounder.chooseMultiplierAndApply(quantity, data, status); magnitude = quantity.isZeroish() ? 0 : quantity.getMagnitude(); magnitude -= multiplier; } @@ -309,10 +316,18 @@ void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micr // C++ Note: Use unsafePatternInfo for proper lifecycle. ParsedPatternInfo &patternInfo = const_cast(this)->unsafePatternInfo; PatternParser::parseToPatternInfo(UnicodeString(patternString), patternInfo, status); - static_cast(const_cast(micros.modMiddle)) - ->setPatternInfo(&patternInfo, UNUM_COMPACT_FIELD); + unsafePatternModifier->setPatternInfo( + &unsafePatternInfo, + {UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD}); + unsafePatternModifier->setNumberProperties(quantity.signum(), StandardPlural::Form::COUNT); + micros.modMiddle = unsafePatternModifier; } + // Change the exponent only after we select appropriate plural form + // for formatting purposes so that we preserve expected formatted + // string behavior. + quantity.adjustExponent(-1 * multiplier); + // We already performed rounding. Do not perform it again. micros.rounder = RoundingImpl::passThrough(); } diff --git a/deps/icu-small/source/i18n/number_compact.h b/deps/icu-small/source/i18n/number_compact.h index dda5f9f9b2dc91..199d39f65911ca 100644 --- a/deps/icu-small/source/i18n/number_compact.h +++ b/deps/icu-small/source/i18n/number_compact.h @@ -56,10 +56,16 @@ struct CompactModInfo { class CompactHandler : public MicroPropsGenerator, public UMemory { public: - CompactHandler(CompactStyle compactStyle, const Locale &locale, const char *nsName, - CompactType compactType, const PluralRules *rules, - MutablePatternModifier *buildReference, const MicroPropsGenerator *parent, - UErrorCode &status); + CompactHandler( + CompactStyle compactStyle, + const Locale &locale, + const char *nsName, + CompactType compactType, + const PluralRules *rules, + MutablePatternModifier *buildReference, + bool safe, + const MicroPropsGenerator *parent, + UErrorCode &status); ~CompactHandler() U_OVERRIDE; @@ -74,6 +80,7 @@ class CompactHandler : public MicroPropsGenerator, public UMemory { int32_t precomputedModsLength = 0; CompactData data; ParsedPatternInfo unsafePatternInfo; + MutablePatternModifier* unsafePatternModifier; UBool safe; /** Used by the safe code path */ diff --git a/deps/icu-small/source/i18n/number_decimalquantity.cpp b/deps/icu-small/source/i18n/number_decimalquantity.cpp index 2c4c2ce7e9931b..5ce9c27cbf4a76 100644 --- a/deps/icu-small/source/i18n/number_decimalquantity.cpp +++ b/deps/icu-small/source/i18n/number_decimalquantity.cpp @@ -120,6 +120,7 @@ void DecimalQuantity::copyFieldsFrom(const DecimalQuantity& other) { origDouble = other.origDouble; origDelta = other.origDelta; isApproximate = other.isApproximate; + exponent = other.exponent; } void DecimalQuantity::clear() { @@ -269,11 +270,21 @@ double DecimalQuantity::getPluralOperand(PluralOperand operand) const { return fractionCount(); case PLURAL_OPERAND_W: return fractionCountWithoutTrailingZeros(); + case PLURAL_OPERAND_E: + return static_cast(getExponent()); default: return std::abs(toDouble()); } } +int32_t DecimalQuantity::getExponent() const { + return exponent; +} + +void DecimalQuantity::adjustExponent(int delta) { + exponent = exponent + delta; +} + bool DecimalQuantity::hasIntegerValue() const { return scale >= 0; } @@ -307,11 +318,13 @@ int8_t DecimalQuantity::getDigit(int32_t magnitude) const { } int32_t DecimalQuantity::fractionCount() const { - return -getLowerDisplayMagnitude(); + int32_t fractionCountWithExponent = -getLowerDisplayMagnitude() - exponent; + return fractionCountWithExponent > 0 ? fractionCountWithExponent : 0; } int32_t DecimalQuantity::fractionCountWithoutTrailingZeros() const { - return -scale > 0 ? -scale : 0; // max(-scale, 0) + int32_t fractionCountWithExponent = -scale - exponent; + return fractionCountWithExponent > 0 ? fractionCountWithExponent : 0; // max(-fractionCountWithExponent, 0) } bool DecimalQuantity::isNegative() const { @@ -319,10 +332,14 @@ bool DecimalQuantity::isNegative() const { } Signum DecimalQuantity::signum() const { - if (isNegative()) { + bool isZero = (isZeroish() && !isInfinite()); + bool isNeg = isNegative(); + if (isZero && isNeg) { + return SIGNUM_NEG_ZERO; + } else if (isZero) { + return SIGNUM_POS_ZERO; + } else if (isNeg) { return SIGNUM_NEG; - } else if (isZeroish() && !isInfinite()) { - return SIGNUM_ZERO; } else { return SIGNUM_POS; } @@ -422,9 +439,6 @@ void DecimalQuantity::_setToDoubleFast(double n) { // TODO: Make a fast path for other types of doubles. if (!std::numeric_limits::is_iec559) { convertToAccurateDouble(); - // Turn off the approximate double flag, since the value is now exact. - isApproximate = false; - origDouble = 0.0; return; } @@ -439,8 +453,14 @@ void DecimalQuantity::_setToDoubleFast(double n) { return; } + if (exponent == -1023 || exponent == 1024) { + // The extreme values of exponent are special; use slow path. + convertToAccurateDouble(); + return; + } + // 3.3219... is log2(10) - auto fracLength = static_cast ((52 - exponent) / 3.32192809489); + auto fracLength = static_cast ((52 - exponent) / 3.32192809488736234787031942948939017586); if (fracLength >= 0) { int32_t i = fracLength; // 1e22 is the largest exact double. @@ -452,7 +472,7 @@ void DecimalQuantity::_setToDoubleFast(double n) { for (; i <= -22; i += 22) n /= 1e22; n /= DOUBLE_MULTIPLIERS[-i]; } - auto result = static_cast(std::round(n)); + auto result = static_cast(uprv_round(n)); if (result != 0) { _setToLong(result); scale -= fracLength; @@ -521,12 +541,12 @@ int64_t DecimalQuantity::toLong(bool truncateIfOverflow) const { // if (dq.fitsInLong()) { /* use dq.toLong() */ } else { /* use some fallback */ } // Fallback behavior upon truncateIfOverflow is to truncate at 17 digits. uint64_t result = 0L; - int32_t upperMagnitude = scale + precision - 1; + int32_t upperMagnitude = exponent + scale + precision - 1; if (truncateIfOverflow) { upperMagnitude = std::min(upperMagnitude, 17); } for (int32_t magnitude = upperMagnitude; magnitude >= 0; magnitude--) { - result = result * 10 + getDigitPos(magnitude - scale); + result = result * 10 + getDigitPos(magnitude - scale - exponent); } if (isNegative()) { return static_cast(0LL - result); // i.e., -result @@ -536,7 +556,7 @@ int64_t DecimalQuantity::toLong(bool truncateIfOverflow) const { uint64_t DecimalQuantity::toFractionLong(bool includeTrailingZeros) const { uint64_t result = 0L; - int32_t magnitude = -1; + int32_t magnitude = -1 - exponent; int32_t lowerMagnitude = scale; if (includeTrailingZeros) { lowerMagnitude = std::min(lowerMagnitude, rReqPos); @@ -560,7 +580,7 @@ bool DecimalQuantity::fitsInLong(bool ignoreFraction) const { if (isZeroish()) { return true; } - if (scale < 0 && !ignoreFraction) { + if (exponent + scale < 0 && !ignoreFraction) { return false; } int magnitude = getMagnitude(); @@ -877,12 +897,30 @@ UnicodeString DecimalQuantity::toPlainString() const { if (isNegative()) { sb.append(u'-'); } - if (precision == 0 || getMagnitude() < 0) { + if (precision == 0) { + sb.append(u'0'); + return sb; + } + int32_t upper = scale + precision + exponent - 1; + int32_t lower = scale + exponent; + if (upper < lReqPos - 1) { + upper = lReqPos - 1; + } + if (lower > rReqPos) { + lower = rReqPos; + } + int32_t p = upper; + if (p < 0) { sb.append(u'0'); } - for (int m = getUpperDisplayMagnitude(); m >= getLowerDisplayMagnitude(); m--) { - if (m == -1) { sb.append(u'.'); } - sb.append(getDigit(m) + u'0'); + for (; p >= 0; p--) { + sb.append(u'0' + getDigitPos(p - scale - exponent)); + } + if (lower < 0) { + sb.append(u'.'); + } + for(; p >= lower; p--) { + sb.append(u'0' + getDigitPos(p - scale - exponent)); } return sb; } @@ -908,7 +946,7 @@ UnicodeString DecimalQuantity::toScientificString() const { } } result.append(u'E'); - int32_t _scale = upperPos + scale; + int32_t _scale = upperPos + scale + exponent; if (_scale == INT32_MIN) { result.append({u"-2147483648", -1}); return result; @@ -1021,6 +1059,7 @@ void DecimalQuantity::setBcdToZero() { isApproximate = false; origDouble = 0; origDelta = 0; + exponent = 0; } void DecimalQuantity::readIntToBcd(int32_t n) { diff --git a/deps/icu-small/source/i18n/number_decimalquantity.h b/deps/icu-small/source/i18n/number_decimalquantity.h index 4ec6c5a5b2bcf7..53a9eb33b26caf 100644 --- a/deps/icu-small/source/i18n/number_decimalquantity.h +++ b/deps/icu-small/source/i18n/number_decimalquantity.h @@ -146,6 +146,26 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { */ int32_t getMagnitude() const; + /** + * @return The value of the (suppressed) exponent after the number has been + * put into a notation with exponents (ex: compact, scientific). Ex: given + * the number 1000 as "1K" / "1E3", the return value will be 3 (positive). + */ + int32_t getExponent() const; + + /** + * Adjusts the value for the (suppressed) exponent stored when using + * notation with exponents (ex: compact, scientific). + * + *

Adjusting the exponent is decoupled from {@link #adjustMagnitude} in + * order to allow flexibility for {@link StandardPlural} to be selected in + * formatting (ex: for compact notation) either with or without the exponent + * applied in the value of the number. + * @param delta + * The value to adjust the exponent by. + */ + void adjustExponent(int32_t delta); + /** * @return Whether the value represented by this {@link DecimalQuantity} is * zero, infinity, or NaN. @@ -164,9 +184,19 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { /** @return Whether the value represented by this {@link DecimalQuantity} is not a number. */ bool isNaN() const U_OVERRIDE; - /** @param truncateIfOverflow if false and the number does NOT fit, fails with an assertion error. */ + /** + * Note: this method incorporates the value of {@code exponent} + * (for cases such as compact notation) to return the proper long value + * represented by the result. + * @param truncateIfOverflow if false and the number does NOT fit, fails with an assertion error. + */ int64_t toLong(bool truncateIfOverflow = false) const; + /** + * Note: this method incorporates the value of {@code exponent} + * (for cases such as compact notation) to return the proper long value + * represented by the result. + */ uint64_t toFractionLong(bool includeTrailingZeros) const; /** @@ -351,6 +381,10 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { int32_t lReqPos = 0; int32_t rReqPos = 0; + // The value of the (suppressed) exponent after the number has been put into + // a notation with exponents (ex: compact, scientific). + int32_t exponent = 0; + /** * The BCD of the 16 digits of the number represented by this object. Every 4 bits of the long map * to one digit. For example, the number "12345" in BCD is "0x12345". @@ -423,7 +457,7 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { /** * Sets the internal representation to zero. Clears any values stored in scale, precision, - * hasDouble, origDouble, origDelta, and BCD data. + * hasDouble, origDouble, origDelta, exponent, and BCD data. */ void setBcdToZero(); diff --git a/deps/icu-small/source/i18n/number_fluent.cpp b/deps/icu-small/source/i18n/number_fluent.cpp index 2dbd2fa6cd5acf..9cdb8b7156e614 100644 --- a/deps/icu-small/source/i18n/number_fluent.cpp +++ b/deps/icu-small/source/i18n/number_fluent.cpp @@ -11,7 +11,6 @@ #include "number_formatimpl.h" #include "umutex.h" #include "number_asformat.h" -#include "number_skeletons.h" #include "number_utils.h" #include "number_utypes.h" #include "util.h" @@ -21,6 +20,16 @@ using namespace icu; using namespace icu::number; using namespace icu::number::impl; +#if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER) +// Ignore MSVC warning 4661. This is generated for NumberFormatterSettings<>::toSkeleton() as this method +// is defined elsewhere (in number_skeletons.cpp). The compiler is warning that the explicit template instantiation +// inside this single translation unit (CPP file) is incomplete, and thus it isn't sure if the template class is +// fully defined. However, since each translation unit explicitly instantiates all the necessary template classes, +// they will all be passed to the linker, and the linker will still find and export all the class members. +#pragma warning(push) +#pragma warning(disable: 4661) +#endif + template Derived NumberFormatterSettings::notation(const Notation& notation) const& { Derived copy(*this); @@ -320,16 +329,7 @@ Derived NumberFormatterSettings::macros(impl::MacroProps&& macros)&& { return move; } -template -UnicodeString NumberFormatterSettings::toSkeleton(UErrorCode& status) const { - if (U_FAILURE(status)) { - return ICU_Utility::makeBogusString(); - } - if (fMacros.copyErrorTo(status)) { - return ICU_Utility::makeBogusString(); - } - return skeleton::generate(fMacros, status); -} +// Note: toSkeleton defined in number_skeletons.cpp template LocalPointer NumberFormatterSettings::clone() const & { @@ -358,15 +358,7 @@ LocalizedNumberFormatter NumberFormatter::withLocale(const Locale& locale) { return with().locale(locale); } -UnlocalizedNumberFormatter -NumberFormatter::forSkeleton(const UnicodeString& skeleton, UErrorCode& status) { - return skeleton::create(skeleton, nullptr, status); -} - -UnlocalizedNumberFormatter -NumberFormatter::forSkeleton(const UnicodeString& skeleton, UParseError& perror, UErrorCode& status) { - return skeleton::create(skeleton, &perror, status); -} +// Note: forSkeleton defined in number_skeletons.cpp template using NFS = NumberFormatterSettings; @@ -766,14 +758,11 @@ int32_t LocalizedNumberFormatter::getCallCount() const { return umtx_loadAcquire(*callCount); } -Format* LocalizedNumberFormatter::toFormat(UErrorCode& status) const { - if (U_FAILURE(status)) { - return nullptr; - } - LocalPointer retval( - new LocalizedNumberFormatterAsFormat(*this, fMacros.locale), status); - return retval.orphan(); -} +// Note: toFormat defined in number_asformat.cpp +#if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER) +// Warning 4661. +#pragma warning(pop) +#endif #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_formatimpl.cpp b/deps/icu-small/source/i18n/number_formatimpl.cpp index 2e2c4a9620c77c..5bba09cfb5293e 100644 --- a/deps/icu-small/source/i18n/number_formatimpl.cpp +++ b/deps/icu-small/source/i18n/number_formatimpl.cpp @@ -24,45 +24,6 @@ using namespace icu; using namespace icu::number; using namespace icu::number::impl; -namespace { - -struct CurrencyFormatInfoResult { - bool exists; - const char16_t* pattern; - const char16_t* decimalSeparator; - const char16_t* groupingSeparator; -}; - -CurrencyFormatInfoResult -getCurrencyFormatInfo(const Locale& locale, const char* isoCode, UErrorCode& status) { - // TODO: Load this data in a centralized location like ICU4J? - // TODO: Move this into the CurrencySymbols class? - // TODO: Parts of this same data are loaded in dcfmtsym.cpp; should clean up. - CurrencyFormatInfoResult result = {false, nullptr, nullptr, nullptr}; - if (U_FAILURE(status)) { return result; } - CharString key; - key.append("Currencies/", status); - key.append(isoCode, status); - UErrorCode localStatus = status; - LocalUResourceBundlePointer bundle(ures_open(U_ICUDATA_CURR, locale.getName(), &localStatus)); - ures_getByKeyWithFallback(bundle.getAlias(), key.data(), bundle.getAlias(), &localStatus); - if (U_SUCCESS(localStatus) && - ures_getSize(bundle.getAlias()) > 2) { // the length is 3 if more data is present - ures_getByIndex(bundle.getAlias(), 2, bundle.getAlias(), &localStatus); - int32_t dummy; - result.exists = true; - result.pattern = ures_getStringByIndex(bundle.getAlias(), 0, &dummy, &localStatus); - result.decimalSeparator = ures_getStringByIndex(bundle.getAlias(), 1, &dummy, &localStatus); - result.groupingSeparator = ures_getStringByIndex(bundle.getAlias(), 2, &dummy, &localStatus); - status = localStatus; - } else if (localStatus != U_MISSING_RESOURCE_ERROR) { - status = localStatus; - } - return result; -} - -} // namespace - MicroPropsGenerator::~MicroPropsGenerator() = default; @@ -111,7 +72,6 @@ void NumberFormatterImpl::preProcess(DecimalQuantity& inValue, MicroProps& micro return; } fMicroPropsGenerator->processQuantity(inValue, microsOut, status); - microsOut.rounder.apply(inValue, status); microsOut.integerWidth.apply(inValue, status); } @@ -124,7 +84,6 @@ MicroProps& NumberFormatterImpl::preProcessUnsafe(DecimalQuantity& inValue, UErr return fMicros; // must always return a value } fMicroPropsGenerator->processQuantity(inValue, fMicros, status); - fMicros.rounder.apply(inValue, status); fMicros.integerWidth.apply(inValue, status); return fMicros; } @@ -181,14 +140,6 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, if (isCurrency) { currency = CurrencyUnit(macros.unit, status); // Restore CurrencyUnit from MeasureUnit } - const CurrencySymbols* currencySymbols; - if (macros.currencySymbols != nullptr) { - // Used by the DecimalFormat code path - currencySymbols = macros.currencySymbols; - } else { - fWarehouse.fCurrencySymbols = {currency, macros.locale, status}; - currencySymbols = &fWarehouse.fCurrencySymbols; - } UNumberUnitWidth unitWidth = UNUM_UNIT_WIDTH_SHORT; if (macros.unitWidth != UNUM_UNIT_WIDTH_COUNT) { unitWidth = macros.unitWidth; @@ -215,41 +166,26 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, if (macros.symbols.isDecimalFormatSymbols()) { fMicros.symbols = macros.symbols.getDecimalFormatSymbols(); } else { - auto newSymbols = new DecimalFormatSymbols(macros.locale, *ns, status); - if (newSymbols == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; + LocalPointer newSymbols( + new DecimalFormatSymbols(macros.locale, *ns, status), status); + if (U_FAILURE(status)) { return nullptr; } - fMicros.symbols = newSymbols; - // Give ownership to the NumberFormatterImpl. - fSymbols.adoptInstead(fMicros.symbols); + if (isCurrency) { + newSymbols->setCurrency(currency.getISOCurrency(), status); + if (U_FAILURE(status)) { + return nullptr; + } + } + fMicros.symbols = newSymbols.getAlias(); + fSymbols.adoptInstead(newSymbols.orphan()); } // Load and parse the pattern string. It is used for grouping sizes and affixes only. // If we are formatting currency, check for a currency-specific pattern. const char16_t* pattern = nullptr; - if (isCurrency) { - CurrencyFormatInfoResult info = getCurrencyFormatInfo( - macros.locale, currency.getSubtype(), status); - if (info.exists) { - pattern = info.pattern; - // It's clunky to clone an object here, but this code is not frequently executed. - auto symbols = new DecimalFormatSymbols(*fMicros.symbols); - if (symbols == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; - return nullptr; - } - fMicros.symbols = symbols; - fSymbols.adoptInstead(symbols); - symbols->setSymbol( - DecimalFormatSymbols::ENumberFormatSymbol::kMonetarySeparatorSymbol, - UnicodeString(info.decimalSeparator), - FALSE); - symbols->setSymbol( - DecimalFormatSymbols::ENumberFormatSymbol::kMonetaryGroupingSeparatorSymbol, - UnicodeString(info.groupingSeparator), - FALSE); - } + if (isCurrency && fMicros.symbols->getCurrencyPattern() != nullptr) { + pattern = fMicros.symbols->getCurrencyPattern(); } if (pattern == nullptr) { CldrPatternStyle patternStyle; @@ -267,6 +203,9 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, patternStyle = CLDR_PATTERN_STYLE_CURRENCY; } pattern = utils::getPatternForStyle(macros.locale, nsName, patternStyle, status); + if (U_FAILURE(status)) { + return nullptr; + } } auto patternInfo = new ParsedPatternInfo(); if (patternInfo == nullptr) { @@ -275,6 +214,9 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, } fPatternInfo.adoptInstead(patternInfo); PatternParser::parseToPatternInfo(UnicodeString(pattern), *patternInfo, status); + if (U_FAILURE(status)) { + return nullptr; + } ///////////////////////////////////////////////////////////////////////////////////// /// START POPULATING THE DEFAULT MICROPROPS AND BUILDING THE MICROPROPS GENERATOR /// @@ -305,6 +247,9 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, roundingMode = precision.fRoundingMode; } fMicros.rounder = {precision, roundingMode, currency, status}; + if (U_FAILURE(status)) { + return nullptr; + } // Grouping strategy if (!macros.grouper.isBogus()) { @@ -372,23 +317,23 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, patternModifier->setPatternInfo( macros.affixProvider != nullptr ? macros.affixProvider : static_cast(fPatternInfo.getAlias()), - UNUM_FIELD_COUNT); + kUndefinedField); patternModifier->setPatternAttributes(fMicros.sign, isPermille); if (patternModifier->needsPlurals()) { patternModifier->setSymbols( fMicros.symbols, - currencySymbols, + currency, unitWidth, - resolvePluralRules(macros.rules, macros.locale, status)); + resolvePluralRules(macros.rules, macros.locale, status), + status); } else { - patternModifier->setSymbols(fMicros.symbols, currencySymbols, unitWidth, nullptr); + patternModifier->setSymbols(fMicros.symbols, currency, unitWidth, nullptr, status); } if (safe) { - fImmutablePatternModifier.adoptInstead(patternModifier->createImmutableAndChain(chain, status)); - chain = fImmutablePatternModifier.getAlias(); - } else { - patternModifier->addToChain(chain); - chain = patternModifier; + fImmutablePatternModifier.adoptInstead(patternModifier->createImmutable(status)); + } + if (U_FAILURE(status)) { + return nullptr; } // Outer modifier (CLDR units and currency long names) @@ -416,10 +361,11 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, // No outer modifier required fMicros.modOuter = &fMicros.helpers.emptyWeakModifier; } + if (U_FAILURE(status)) { + return nullptr; + } // Compact notation - // NOTE: Compact notation can (but might not) override the middle modifier and rounding. - // It therefore needs to go at the end of the chain. if (macros.notation.fType == Notation::NTN_COMPACT) { CompactType compactType = (isCurrency && unitWidth != UNUM_UNIT_WIDTH_FULL_NAME) ? CompactType::TYPE_CURRENCY : CompactType::TYPE_DECIMAL; @@ -429,7 +375,8 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, nsName, compactType, resolvePluralRules(macros.rules, macros.locale, status), - safe ? patternModifier : nullptr, + patternModifier, + safe, chain, status); if (newCompactHandler == nullptr) { @@ -439,6 +386,18 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, fCompactHandler.adoptInstead(newCompactHandler); chain = fCompactHandler.getAlias(); } + if (U_FAILURE(status)) { + return nullptr; + } + + // Always add the pattern modifier as the last element of the chain. + if (safe) { + fImmutablePatternModifier->addToChain(chain); + chain = fImmutablePatternModifier.getAlias(); + } else { + patternModifier->addToChain(chain); + chain = patternModifier; + } return chain; } @@ -478,14 +437,14 @@ int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuanti length += string.insert( length + index, micros.symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kInfinitySymbol), - UNUM_INTEGER_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD}, status); } else if (quantity.isNaN()) { length += string.insert( length + index, micros.symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kNaNSymbol), - UNUM_INTEGER_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD}, status); } else { @@ -501,12 +460,23 @@ int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuanti .symbols ->getSymbol( DecimalFormatSymbols::ENumberFormatSymbol::kDecimalSeparatorSymbol), - UNUM_DECIMAL_SEPARATOR_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_DECIMAL_SEPARATOR_FIELD}, status); } // Add the fraction digits length += writeFractionDigits(micros, quantity, string, length + index, status); + + if (length == 0) { + // Force output of the digit for value 0 + length += utils::insertDigitFromSymbols( + string, + index, + 0, + *micros.symbols, + {UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD}, + status); + } } return length; @@ -526,14 +496,20 @@ int32_t NumberFormatterImpl::writeIntegerDigits(const MicroProps& micros, Decima DecimalFormatSymbols::ENumberFormatSymbol::kMonetaryGroupingSeparatorSymbol) : micros.symbols->getSymbol( DecimalFormatSymbols::ENumberFormatSymbol::kGroupingSeparatorSymbol), - UNUM_GROUPING_SEPARATOR_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_GROUPING_SEPARATOR_FIELD}, status); } // Get and append the next digit value int8_t nextDigit = quantity.getDigit(i); length += utils::insertDigitFromSymbols( - string, index, nextDigit, *micros.symbols, UNUM_INTEGER_FIELD, status); + string, + index, + nextDigit, + *micros.symbols, + {UFIELD_CATEGORY_NUMBER, + UNUM_INTEGER_FIELD}, + status); } return length; } @@ -547,7 +523,12 @@ int32_t NumberFormatterImpl::writeFractionDigits(const MicroProps& micros, Decim // Get and append the next digit value int8_t nextDigit = quantity.getDigit(-i - 1); length += utils::insertDigitFromSymbols( - string, length + index, nextDigit, *micros.symbols, UNUM_FRACTION_FIELD, status); + string, + length + index, + nextDigit, + *micros.symbols, + {UFIELD_CATEGORY_NUMBER, UNUM_FRACTION_FIELD}, + status); } return length; } diff --git a/deps/icu-small/source/i18n/number_formatimpl.h b/deps/icu-small/source/i18n/number_formatimpl.h index 206c5f58c576a1..084bc4a9d0b209 100644 --- a/deps/icu-small/source/i18n/number_formatimpl.h +++ b/deps/icu-small/source/i18n/number_formatimpl.h @@ -95,7 +95,7 @@ class NumberFormatterImpl : public UMemory { LocalPointer fPatternInfo; LocalPointer fScientificHandler; LocalPointer fPatternModifier; - LocalPointer fImmutablePatternModifier; + LocalPointer fImmutablePatternModifier; LocalPointer fLongNameHandler; LocalPointer fCompactHandler; diff --git a/deps/icu-small/source/i18n/number_longnames.cpp b/deps/icu-small/source/i18n/number_longnames.cpp index 817aa0e0d9c39d..bb32d0381a507e 100644 --- a/deps/icu-small/source/i18n/number_longnames.cpp +++ b/deps/icu-small/source/i18n/number_longnames.cpp @@ -188,6 +188,12 @@ LongNameHandler* LongNameHandler::forMeasureUnit(const Locale &loc, const MeasureUnit &unitRef, const MeasureUnit &perUnit, const UNumberUnitWidth &width, const PluralRules *rules, const MicroPropsGenerator *parent, UErrorCode &status) { + if (uprv_strlen(unitRef.getType()) == 0 || uprv_strlen(perUnit.getType()) == 0) { + // TODO(ICU-20941): Unsanctioned unit. Not yet fully supported. Set an error code. + status = U_UNSUPPORTED_ERROR; + return nullptr; + } + MeasureUnit unit = unitRef; if (uprv_strcmp(perUnit.getType(), "none") != 0) { // Compound unit: first try to simplify (e.g., meters per second is its own unit). @@ -209,7 +215,7 @@ LongNameHandler::forMeasureUnit(const Locale &loc, const MeasureUnit &unitRef, c UnicodeString simpleFormats[ARRAY_LENGTH]; getMeasureData(loc, unit, width, simpleFormats, status); if (U_FAILURE(status)) { return result; } - result->simpleFormatsToModifiers(simpleFormats, UNUM_MEASURE_UNIT_FIELD, status); + result->simpleFormatsToModifiers(simpleFormats, {UFIELD_CATEGORY_NUMBER, UNUM_MEASURE_UNIT_FIELD}, status); return result; } @@ -240,14 +246,15 @@ LongNameHandler::forCompoundUnit(const Locale &loc, const MeasureUnit &unit, con if (U_FAILURE(status)) { return result; } UnicodeString secondaryFormat = getWithPlural(secondaryData, StandardPlural::Form::ONE, status); if (U_FAILURE(status)) { return result; } - SimpleFormatter secondaryCompiled(secondaryFormat, 1, 1, status); + // Some "one" pattern may not contain "{0}". For example in "ar" or "ne" locale. + SimpleFormatter secondaryCompiled(secondaryFormat, 0, 1, status); if (U_FAILURE(status)) { return result; } UnicodeString secondaryString = secondaryCompiled.getTextWithNoArguments().trim(); // TODO: Why does UnicodeString need to be explicit in the following line? compiled.format(UnicodeString(u"{0}"), secondaryString, perUnitFormat, status); if (U_FAILURE(status)) { return result; } } - result->multiSimpleFormatsToModifiers(primaryData, perUnitFormat, UNUM_MEASURE_UNIT_FIELD, status); + result->multiSimpleFormatsToModifiers(primaryData, perUnitFormat, {UFIELD_CATEGORY_NUMBER, UNUM_MEASURE_UNIT_FIELD}, status); return result; } @@ -296,7 +303,7 @@ LongNameHandler* LongNameHandler::forCurrencyLongNames(const Locale &loc, const UnicodeString simpleFormats[ARRAY_LENGTH]; getCurrencyLongNameData(loc, currency, simpleFormats, status); if (U_FAILURE(status)) { return nullptr; } - result->simpleFormatsToModifiers(simpleFormats, UNUM_CURRENCY_FIELD, status); + result->simpleFormatsToModifiers(simpleFormats, {UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}, status); return result; } @@ -308,7 +315,7 @@ void LongNameHandler::simpleFormatsToModifiers(const UnicodeString *simpleFormat if (U_FAILURE(status)) { return; } SimpleFormatter compiledFormatter(simpleFormat, 0, 1, status); if (U_FAILURE(status)) { return; } - fModifiers[i] = SimpleModifier(compiledFormatter, field, false, {this, SIGNUM_ZERO, plural}); + fModifiers[i] = SimpleModifier(compiledFormatter, field, false, {this, SIGNUM_POS_ZERO, plural}); } } @@ -325,7 +332,7 @@ void LongNameHandler::multiSimpleFormatsToModifiers(const UnicodeString *leadFor if (U_FAILURE(status)) { return; } SimpleFormatter compoundCompiled(compoundFormat, 0, 1, status); if (U_FAILURE(status)) { return; } - fModifiers[i] = SimpleModifier(compoundCompiled, field, false, {this, SIGNUM_ZERO, plural}); + fModifiers[i] = SimpleModifier(compoundCompiled, field, false, {this, SIGNUM_POS_ZERO, plural}); } } diff --git a/deps/icu-small/source/i18n/number_mapper.cpp b/deps/icu-small/source/i18n/number_mapper.cpp index 40fd5284b86649..ec617438c9a9e3 100644 --- a/deps/icu-small/source/i18n/number_mapper.cpp +++ b/deps/icu-small/source/i18n/number_mapper.cpp @@ -13,7 +13,6 @@ #include "number_patternstring.h" #include "unicode/errorcode.h" #include "number_utils.h" -#include "number_currencysymbols.h" using namespace icu; using namespace icu::number; @@ -63,17 +62,8 @@ MacroProps NumberPropertyMapper::oldToNew(const DecimalFormatProperties& propert // AFFIXES // ///////////// - AffixPatternProvider* affixProvider; - if (properties.currencyPluralInfo.fPtr.isNull()) { - warehouse.currencyPluralInfoAPP.setToBogus(); - warehouse.propertiesAPP.setTo(properties, status); - affixProvider = &warehouse.propertiesAPP; - } else { - warehouse.currencyPluralInfoAPP.setTo(*properties.currencyPluralInfo.fPtr, properties, status); - warehouse.propertiesAPP.setToBogus(); - affixProvider = &warehouse.currencyPluralInfoAPP; - } - macros.affixProvider = affixProvider; + warehouse.affixProvider.setTo(properties, status); + macros.affixProvider = &warehouse.affixProvider.get(); /////////// // UNITS // @@ -83,15 +73,13 @@ MacroProps NumberPropertyMapper::oldToNew(const DecimalFormatProperties& propert !properties.currency.isNull() || !properties.currencyPluralInfo.fPtr.isNull() || !properties.currencyUsage.isNull() || - affixProvider->hasCurrencySign()); + warehouse.affixProvider.get().hasCurrencySign()); CurrencyUnit currency = resolveCurrency(properties, locale, status); UCurrencyUsage currencyUsage = properties.currencyUsage.getOrDefault(UCURR_USAGE_STANDARD); if (useCurrency) { // NOTE: Slicing is OK. macros.unit = currency; // NOLINT } - warehouse.currencySymbols = {currency, locale, symbols, status}; - macros.currencySymbols = &warehouse.currencySymbols; /////////////////////// // ROUNDING STRATEGY // @@ -125,10 +113,8 @@ MacroProps NumberPropertyMapper::oldToNew(const DecimalFormatProperties& propert } // Validate min/max int/frac. // For backwards compatibility, minimum overrides maximum if the two conflict. - // The following logic ensures that there is always a minimum of at least one digit. if (minInt == 0 && maxFrac != 0) { - // Force a digit after the decimal point. - minFrac = minFrac <= 0 ? 1 : minFrac; + minFrac = (minFrac < 0 || (minFrac == 0 && maxInt == 0)) ? 1 : minFrac; maxFrac = maxFrac < 0 ? -1 : maxFrac < minFrac ? minFrac : maxFrac; minInt = 0; maxInt = maxInt < 0 ? -1 : maxInt > kMaxIntFracSig ? -1 : maxInt; diff --git a/deps/icu-small/source/i18n/number_mapper.h b/deps/icu-small/source/i18n/number_mapper.h index de7d9c3865c8df..d18b8b3c438cf4 100644 --- a/deps/icu-small/source/i18n/number_mapper.h +++ b/deps/icu-small/source/i18n/number_mapper.h @@ -20,6 +20,10 @@ namespace number { namespace impl { +class AutoAffixPatternProvider; +class CurrencyPluralInfoAffixProvider; + + class PropertiesAffixPatternProvider : public AffixPatternProvider, public UMemory { public: bool isBogus() const { @@ -32,12 +36,6 @@ class PropertiesAffixPatternProvider : public AffixPatternProvider, public UMemo void setTo(const DecimalFormatProperties& properties, UErrorCode& status); - PropertiesAffixPatternProvider() = default; // puts instance in valid but undefined state - - PropertiesAffixPatternProvider(const DecimalFormatProperties& properties, UErrorCode& status) { - setTo(properties, status); - } - // AffixPatternProvider Methods: char16_t charAt(int32_t flags, int32_t i) const U_OVERRIDE; @@ -65,9 +63,14 @@ class PropertiesAffixPatternProvider : public AffixPatternProvider, public UMemo UnicodeString negSuffix; bool isCurrencyPattern; + PropertiesAffixPatternProvider() = default; // puts instance in valid but undefined state + const UnicodeString& getStringInternal(int32_t flags) const; bool fBogus{true}; + + friend class AutoAffixPatternProvider; + friend class CurrencyPluralInfoAffixProvider; }; @@ -107,7 +110,43 @@ class CurrencyPluralInfoAffixProvider : public AffixPatternProvider, public UMem private: PropertiesAffixPatternProvider affixesByPlural[StandardPlural::COUNT]; + CurrencyPluralInfoAffixProvider() = default; + bool fBogus{true}; + + friend class AutoAffixPatternProvider; +}; + + +class AutoAffixPatternProvider { + public: + inline AutoAffixPatternProvider() = default; + + inline AutoAffixPatternProvider(const DecimalFormatProperties& properties, UErrorCode& status) { + setTo(properties, status); + } + + inline void setTo(const DecimalFormatProperties& properties, UErrorCode& status) { + if (properties.currencyPluralInfo.fPtr.isNull()) { + propertiesAPP.setTo(properties, status); + currencyPluralInfoAPP.setToBogus(); + } else { + propertiesAPP.setToBogus(); + currencyPluralInfoAPP.setTo(*properties.currencyPluralInfo.fPtr, properties, status); + } + } + + inline const AffixPatternProvider& get() const { + if (!currencyPluralInfoAPP.isBogus()) { + return currencyPluralInfoAPP; + } else { + return propertiesAPP; + } + } + + private: + PropertiesAffixPatternProvider propertiesAPP; + CurrencyPluralInfoAffixProvider currencyPluralInfoAPP; }; @@ -115,9 +154,8 @@ class CurrencyPluralInfoAffixProvider : public AffixPatternProvider, public UMem * A struct for ownership of a few objects needed for formatting. */ struct DecimalFormatWarehouse { - PropertiesAffixPatternProvider propertiesAPP; - CurrencyPluralInfoAffixProvider currencyPluralInfoAPP; - CurrencySymbols currencySymbols; + AutoAffixPatternProvider affixProvider; + }; diff --git a/deps/icu-small/source/i18n/number_microprops.h b/deps/icu-small/source/i18n/number_microprops.h index d2393aea50c098..56512f5e6f94ac 100644 --- a/deps/icu-small/source/i18n/number_microprops.h +++ b/deps/icu-small/source/i18n/number_microprops.h @@ -37,7 +37,7 @@ struct MicroProps : public MicroPropsGenerator { // Note: This struct has no direct ownership of the following pointers. const DecimalFormatSymbols* symbols; const Modifier* modOuter; - const Modifier* modMiddle; + const Modifier* modMiddle = nullptr; const Modifier* modInner; // The following "helper" fields may optionally be used during the MicroPropsGenerator. diff --git a/deps/icu-small/source/i18n/number_modifiers.cpp b/deps/icu-small/source/i18n/number_modifiers.cpp index 3a44f8f6f15328..3becb7ba852336 100644 --- a/deps/icu-small/source/i18n/number_modifiers.cpp +++ b/deps/icu-small/source/i18n/number_modifiers.cpp @@ -89,7 +89,7 @@ bool ConstantAffixModifier::isStrong() const { return fStrong; } -bool ConstantAffixModifier::containsField(UNumberFormatFields field) const { +bool ConstantAffixModifier::containsField(Field field) const { (void)field; // This method is not currently used. UPRV_UNREACHABLE; @@ -151,7 +151,7 @@ SimpleModifier::SimpleModifier(const SimpleFormatter &simpleFormatter, Field fie } SimpleModifier::SimpleModifier() - : fField(UNUM_FIELD_COUNT), fStrong(false), fPrefixLength(0), fSuffixLength(0) { + : fField(kUndefinedField), fStrong(false), fPrefixLength(0), fSuffixLength(0) { } int32_t SimpleModifier::apply(FormattedStringBuilder &output, int leftIndex, int rightIndex, @@ -178,7 +178,7 @@ bool SimpleModifier::isStrong() const { return fStrong; } -bool SimpleModifier::containsField(UNumberFormatFields field) const { +bool SimpleModifier::containsField(Field field) const { (void)field; // This method is not currently used. UPRV_UNREACHABLE; @@ -292,7 +292,7 @@ int32_t ConstantMultiFieldModifier::apply(FormattedStringBuilder &output, int le leftIndex + length, rightIndex + length, UnicodeString(), 0, 0, - UNUM_FIELD_COUNT, status); + kUndefinedField, status); } length += output.insert(rightIndex + length, fSuffix, status); return length; @@ -310,7 +310,7 @@ bool ConstantMultiFieldModifier::isStrong() const { return fStrong; } -bool ConstantMultiFieldModifier::containsField(UNumberFormatFields field) const { +bool ConstantMultiFieldModifier::containsField(Field field) const { return fPrefix.containsField(field) || fSuffix.containsField(field); } @@ -342,7 +342,7 @@ CurrencySpacingEnabledModifier::CurrencySpacingEnabledModifier(const FormattedSt : ConstantMultiFieldModifier(prefix, suffix, overwrite, strong) { // Check for currency spacing. Do not build the UnicodeSets unless there is // a currency code point at a boundary. - if (prefix.length() > 0 && prefix.fieldAt(prefix.length() - 1) == UNUM_CURRENCY_FIELD) { + if (prefix.length() > 0 && prefix.fieldAt(prefix.length() - 1) == Field(UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD)) { int prefixCp = prefix.getLastCodePoint(); UnicodeSet prefixUnicodeSet = getUnicodeSet(symbols, IN_CURRENCY, PREFIX, status); if (prefixUnicodeSet.contains(prefixCp)) { @@ -357,8 +357,8 @@ CurrencySpacingEnabledModifier::CurrencySpacingEnabledModifier(const FormattedSt fAfterPrefixUnicodeSet.setToBogus(); fAfterPrefixInsert.setToBogus(); } - if (suffix.length() > 0 && suffix.fieldAt(0) == UNUM_CURRENCY_FIELD) { - int suffixCp = suffix.getLastCodePoint(); + if (suffix.length() > 0 && suffix.fieldAt(0) == Field(UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD)) { + int suffixCp = suffix.getFirstCodePoint(); UnicodeSet suffixUnicodeSet = getUnicodeSet(symbols, IN_CURRENCY, SUFFIX, status); if (suffixUnicodeSet.contains(suffixCp)) { fBeforeSuffixUnicodeSet = getUnicodeSet(symbols, IN_NUMBER, SUFFIX, status); @@ -381,12 +381,20 @@ int32_t CurrencySpacingEnabledModifier::apply(FormattedStringBuilder &output, in if (rightIndex - leftIndex > 0 && !fAfterPrefixUnicodeSet.isBogus() && fAfterPrefixUnicodeSet.contains(output.codePointAt(leftIndex))) { // TODO: Should we use the CURRENCY field here? - length += output.insert(leftIndex, fAfterPrefixInsert, UNUM_FIELD_COUNT, status); + length += output.insert( + leftIndex, + fAfterPrefixInsert, + kUndefinedField, + status); } if (rightIndex - leftIndex > 0 && !fBeforeSuffixUnicodeSet.isBogus() && fBeforeSuffixUnicodeSet.contains(output.codePointBefore(rightIndex))) { // TODO: Should we use the CURRENCY field here? - length += output.insert(rightIndex + length, fBeforeSuffixInsert, UNUM_FIELD_COUNT, status); + length += output.insert( + rightIndex + length, + fBeforeSuffixInsert, + kUndefinedField, + status); } // Call super for the remaining logic @@ -422,7 +430,7 @@ CurrencySpacingEnabledModifier::applyCurrencySpacingAffix(FormattedStringBuilder // This works even if the last code point in the prefix is 2 code units because the // field value gets populated to both indices in the field array. Field affixField = (affix == PREFIX) ? output.fieldAt(index - 1) : output.fieldAt(index); - if (affixField != UNUM_CURRENCY_FIELD) { + if (affixField != Field(UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD)) { return 0; } int affixCp = (affix == PREFIX) ? output.codePointBefore(index) : output.codePointAt(index); @@ -443,7 +451,7 @@ CurrencySpacingEnabledModifier::applyCurrencySpacingAffix(FormattedStringBuilder // However, the build code path is more efficient, and this is the most natural // place to put currency spacing in the non-build code path. // TODO: Should we use the CURRENCY field here? - return output.insert(index, spacingString, UNUM_FIELD_COUNT, status); + return output.insert(index, spacingString, kUndefinedField, status); } UnicodeSet diff --git a/deps/icu-small/source/i18n/number_modifiers.h b/deps/icu-small/source/i18n/number_modifiers.h index c84c6aa273ed76..375254310ca056 100644 --- a/deps/icu-small/source/i18n/number_modifiers.h +++ b/deps/icu-small/source/i18n/number_modifiers.h @@ -37,7 +37,7 @@ class U_I18N_API ConstantAffixModifier : public Modifier, public UObject { bool isStrong() const U_OVERRIDE; - bool containsField(UNumberFormatFields field) const U_OVERRIDE; + bool containsField(Field field) const U_OVERRIDE; void getParameters(Parameters& output) const U_OVERRIDE; @@ -73,7 +73,7 @@ class U_I18N_API SimpleModifier : public Modifier, public UMemory { bool isStrong() const U_OVERRIDE; - bool containsField(UNumberFormatFields field) const U_OVERRIDE; + bool containsField(Field field) const U_OVERRIDE; void getParameters(Parameters& output) const U_OVERRIDE; @@ -166,7 +166,7 @@ class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory { bool isStrong() const U_OVERRIDE; - bool containsField(UNumberFormatFields field) const U_OVERRIDE; + bool containsField(Field field) const U_OVERRIDE; void getParameters(Parameters& output) const U_OVERRIDE; @@ -255,7 +255,7 @@ class U_I18N_API EmptyModifier : public Modifier, public UMemory { return fStrong; } - bool containsField(UNumberFormatFields field) const U_OVERRIDE { + bool containsField(Field field) const U_OVERRIDE { (void)field; return false; } @@ -319,12 +319,12 @@ class U_I18N_API AdoptingModifierStore : public ModifierStore, public UMemory { private: // NOTE: mods is zero-initialized (to nullptr) - const Modifier *mods[3 * StandardPlural::COUNT] = {}; + const Modifier *mods[4 * StandardPlural::COUNT] = {}; inline static int32_t getModIndex(Signum signum, StandardPlural::Form plural) { - U_ASSERT(signum >= -1 && signum <= 1); + U_ASSERT(signum >= 0 && signum < SIGNUM_COUNT); U_ASSERT(plural >= 0 && plural < StandardPlural::COUNT); - return static_cast(plural) * 3 + (signum + 1); + return static_cast(plural) * SIGNUM_COUNT + signum; } }; diff --git a/deps/icu-small/source/i18n/number_output.cpp b/deps/icu-small/source/i18n/number_output.cpp index e2f069139a4b47..40192a9225b9de 100644 --- a/deps/icu-small/source/i18n/number_output.cpp +++ b/deps/icu-small/source/i18n/number_output.cpp @@ -19,16 +19,6 @@ UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(FormattedNumber) #define UPRV_NOARG -UBool FormattedNumber::nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const { - UPRV_FORMATTED_VALUE_METHOD_GUARD(FALSE) - return fData->nextFieldPosition(fieldPosition, status); -} - -void FormattedNumber::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const { - FieldPositionIteratorHandler fpih(&iterator, status); - getAllFieldPositionsImpl(fpih, status); -} - void FormattedNumber::toDecimalNumber(ByteSink& sink, UErrorCode& status) const { UPRV_FORMATTED_VALUE_METHOD_GUARD(UPRV_NOARG) impl::DecNum decnum; diff --git a/deps/icu-small/source/i18n/number_padding.cpp b/deps/icu-small/source/i18n/number_padding.cpp index c68a9875b2055f..c320c3ffb6fadc 100644 --- a/deps/icu-small/source/i18n/number_padding.cpp +++ b/deps/icu-small/source/i18n/number_padding.cpp @@ -21,7 +21,7 @@ addPaddingHelper(UChar32 paddingCp, int32_t requiredPadding, FormattedStringBuil UErrorCode &status) { for (int32_t i = 0; i < requiredPadding; i++) { // TODO: If appending to the end, this will cause actual insertion operations. Improve. - string.insertCodePoint(index, paddingCp, UNUM_FIELD_COUNT, status); + string.insertCodePoint(index, paddingCp, kUndefinedField, status); } return U16_LENGTH(paddingCp) * requiredPadding; } diff --git a/deps/icu-small/source/i18n/number_patternmodifier.cpp b/deps/icu-small/source/i18n/number_patternmodifier.cpp index 724f5b9741cc52..45602942aefe8e 100644 --- a/deps/icu-small/source/i18n/number_patternmodifier.cpp +++ b/deps/icu-small/source/i18n/number_patternmodifier.cpp @@ -34,11 +34,13 @@ void MutablePatternModifier::setPatternAttributes(UNumberSignDisplay signDisplay } void MutablePatternModifier::setSymbols(const DecimalFormatSymbols* symbols, - const CurrencySymbols* currencySymbols, - const UNumberUnitWidth unitWidth, const PluralRules* rules) { + const CurrencyUnit& currency, + const UNumberUnitWidth unitWidth, + const PluralRules* rules, + UErrorCode& status) { U_ASSERT((rules != nullptr) == needsPlurals()); fSymbols = symbols; - fCurrencySymbols = currencySymbols; + fCurrencySymbols = {currency, symbols->getLocale(), *symbols, status}; fUnitWidth = unitWidth; fRules = rules; } @@ -55,12 +57,6 @@ bool MutablePatternModifier::needsPlurals() const { } ImmutablePatternModifier* MutablePatternModifier::createImmutable(UErrorCode& status) { - return createImmutableAndChain(nullptr, status); -} - -ImmutablePatternModifier* -MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* parent, UErrorCode& status) { - // TODO: Move StandardPlural VALUES to standardplural.h static const StandardPlural::Form STANDARD_PLURAL_VALUES[] = { StandardPlural::Form::ZERO, @@ -81,8 +77,10 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* paren for (StandardPlural::Form plural : STANDARD_PLURAL_VALUES) { setNumberProperties(SIGNUM_POS, plural); pm->adoptModifier(SIGNUM_POS, plural, createConstantModifier(status)); - setNumberProperties(SIGNUM_ZERO, plural); - pm->adoptModifier(SIGNUM_ZERO, plural, createConstantModifier(status)); + setNumberProperties(SIGNUM_NEG_ZERO, plural); + pm->adoptModifier(SIGNUM_NEG_ZERO, plural, createConstantModifier(status)); + setNumberProperties(SIGNUM_POS_ZERO, plural); + pm->adoptModifier(SIGNUM_POS_ZERO, plural, createConstantModifier(status)); setNumberProperties(SIGNUM_NEG, plural); pm->adoptModifier(SIGNUM_NEG, plural, createConstantModifier(status)); } @@ -90,20 +88,22 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* paren delete pm; return nullptr; } - return new ImmutablePatternModifier(pm, fRules, parent); // adopts pm + return new ImmutablePatternModifier(pm, fRules); // adopts pm } else { // Faster path when plural keyword is not needed. setNumberProperties(SIGNUM_POS, StandardPlural::Form::COUNT); pm->adoptModifierWithoutPlural(SIGNUM_POS, createConstantModifier(status)); - setNumberProperties(SIGNUM_ZERO, StandardPlural::Form::COUNT); - pm->adoptModifierWithoutPlural(SIGNUM_ZERO, createConstantModifier(status)); + setNumberProperties(SIGNUM_NEG_ZERO, StandardPlural::Form::COUNT); + pm->adoptModifierWithoutPlural(SIGNUM_NEG_ZERO, createConstantModifier(status)); + setNumberProperties(SIGNUM_POS_ZERO, StandardPlural::Form::COUNT); + pm->adoptModifierWithoutPlural(SIGNUM_POS_ZERO, createConstantModifier(status)); setNumberProperties(SIGNUM_NEG, StandardPlural::Form::COUNT); pm->adoptModifierWithoutPlural(SIGNUM_NEG, createConstantModifier(status)); if (U_FAILURE(status)) { delete pm; return nullptr; } - return new ImmutablePatternModifier(pm, nullptr, parent); // adopts pm + return new ImmutablePatternModifier(pm, nullptr); // adopts pm } } @@ -120,13 +120,16 @@ ConstantMultiFieldModifier* MutablePatternModifier::createConstantModifier(UErro } } -ImmutablePatternModifier::ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules, - const MicroPropsGenerator* parent) - : pm(pm), rules(rules), parent(parent) {} +ImmutablePatternModifier::ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules) + : pm(pm), rules(rules), parent(nullptr) {} void ImmutablePatternModifier::processQuantity(DecimalQuantity& quantity, MicroProps& micros, UErrorCode& status) const { parent->processQuantity(quantity, micros, status); + micros.rounder.apply(quantity, status); + if (micros.modMiddle != nullptr) { + return; + } applyToMicros(micros, quantity, status); } @@ -148,6 +151,10 @@ const Modifier* ImmutablePatternModifier::getModifier(Signum signum, StandardPlu } } +void ImmutablePatternModifier::addToChain(const MicroPropsGenerator* parent) { + this->parent = parent; +} + /** Used by the unsafe code path. */ MicroPropsGenerator& MutablePatternModifier::addToChain(const MicroPropsGenerator* parent) { @@ -158,6 +165,10 @@ MicroPropsGenerator& MutablePatternModifier::addToChain(const MicroPropsGenerato void MutablePatternModifier::processQuantity(DecimalQuantity& fq, MicroProps& micros, UErrorCode& status) const { fParent->processQuantity(fq, micros, status); + micros.rounder.apply(fq, status); + if (micros.modMiddle != nullptr) { + return; + } // The unsafe code path performs self-mutation, so we need a const_cast. // This method needs to be const because it overrides a const method in the parent class. auto nonConstThis = const_cast(this); @@ -186,7 +197,7 @@ int32_t MutablePatternModifier::apply(FormattedStringBuilder& output, int32_t le UnicodeString(), 0, 0, - UNUM_FIELD_COUNT, + kUndefinedField, status); } CurrencySpacingEnabledModifier::applyCurrencySpacing( @@ -230,7 +241,7 @@ bool MutablePatternModifier::isStrong() const { return fStrong; } -bool MutablePatternModifier::containsField(UNumberFormatFields field) const { +bool MutablePatternModifier::containsField(Field field) const { (void)field; // This method is not currently used. UPRV_UNREACHABLE; @@ -263,7 +274,12 @@ int32_t MutablePatternModifier::insertSuffix(FormattedStringBuilder& sb, int pos /** This method contains the heart of the logic for rendering LDML affix strings. */ void MutablePatternModifier::prepareAffix(bool isPrefix) { PatternStringUtils::patternInfoToStringBuilder( - *fPatternInfo, isPrefix, fSignum, fSignDisplay, fPlural, fPerMilleReplacesPercent, currentAffix); + *fPatternInfo, + isPrefix, + PatternStringUtils::resolveSignDisplay(fSignDisplay, fSignum), + fPlural, + fPerMilleReplacesPercent, + currentAffix); } UnicodeString MutablePatternModifier::getSymbol(AffixPatternType type) const { @@ -280,23 +296,23 @@ UnicodeString MutablePatternModifier::getSymbol(AffixPatternType type) const { case AffixPatternType::TYPE_CURRENCY_SINGLE: { // UnitWidth ISO and HIDDEN overrides the singular currency symbol. if (fUnitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_ISO_CODE) { - return fCurrencySymbols->getIntlCurrencySymbol(localStatus); + return fCurrencySymbols.getIntlCurrencySymbol(localStatus); } else if (fUnitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_HIDDEN) { return UnicodeString(); } else if (fUnitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW) { - return fCurrencySymbols->getNarrowCurrencySymbol(localStatus); + return fCurrencySymbols.getNarrowCurrencySymbol(localStatus); } else { - return fCurrencySymbols->getCurrencySymbol(localStatus); + return fCurrencySymbols.getCurrencySymbol(localStatus); } } case AffixPatternType::TYPE_CURRENCY_DOUBLE: - return fCurrencySymbols->getIntlCurrencySymbol(localStatus); + return fCurrencySymbols.getIntlCurrencySymbol(localStatus); case AffixPatternType::TYPE_CURRENCY_TRIPLE: // NOTE: This is the code path only for patterns containing "¤¤¤". // Plural currencies set via the API are formatted in LongNameHandler. // This code path is used by DecimalFormat via CurrencyPluralInfo. U_ASSERT(fPlural != StandardPlural::Form::COUNT); - return fCurrencySymbols->getPluralName(fPlural, localStatus); + return fCurrencySymbols.getPluralName(fPlural, localStatus); case AffixPatternType::TYPE_CURRENCY_QUAD: return UnicodeString(u"\uFFFD"); case AffixPatternType::TYPE_CURRENCY_QUINT: diff --git a/deps/icu-small/source/i18n/number_patternmodifier.h b/deps/icu-small/source/i18n/number_patternmodifier.h index b2c90e0af76354..5ba842d5692460 100644 --- a/deps/icu-small/source/i18n/number_patternmodifier.h +++ b/deps/icu-small/source/i18n/number_patternmodifier.h @@ -50,9 +50,11 @@ class U_I18N_API ImmutablePatternModifier : public MicroPropsGenerator, public U const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const; + // Non-const method: + void addToChain(const MicroPropsGenerator* parent); + private: - ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules, - const MicroPropsGenerator* parent); + ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules); const LocalPointer pm; const PluralRules* rules; @@ -122,16 +124,18 @@ class U_I18N_API MutablePatternModifier * * @param symbols * The desired instance of DecimalFormatSymbols. - * @param currencySymbols - * The currency symbols to be used when substituting currency values into the affixes. + * @param currency + * The currency to be used when substituting currency values into the affixes. * @param unitWidth * The width used to render currencies. * @param rules * Required if the triple currency sign, "¤¤¤", appears in the pattern, which can be determined from the * convenience method {@link #needsPlurals()}. + * @param status + * Set if an error occurs while loading currency data. */ - void setSymbols(const DecimalFormatSymbols* symbols, const CurrencySymbols* currencySymbols, - UNumberUnitWidth unitWidth, const PluralRules* rules); + void setSymbols(const DecimalFormatSymbols* symbols, const CurrencyUnit& currency, + UNumberUnitWidth unitWidth, const PluralRules* rules, UErrorCode& status); /** * Sets attributes of the current number being processed. @@ -165,21 +169,6 @@ class U_I18N_API MutablePatternModifier */ ImmutablePatternModifier *createImmutable(UErrorCode &status); - /** - * Creates a new quantity-dependent Modifier that behaves the same as the current instance, but which is immutable - * and can be saved for future use. The number properties in the current instance are mutated; all other properties - * are left untouched. - * - *

- * CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP. - * - * @param parent - * The QuantityChain to which to chain this immutable. - * @return An immutable that supports both positive and negative numbers. - */ - ImmutablePatternModifier * - createImmutableAndChain(const MicroPropsGenerator *parent, UErrorCode &status); - MicroPropsGenerator &addToChain(const MicroPropsGenerator *parent); void processQuantity(DecimalQuantity &, MicroProps µs, UErrorCode &status) const U_OVERRIDE; @@ -193,7 +182,7 @@ class U_I18N_API MutablePatternModifier bool isStrong() const U_OVERRIDE; - bool containsField(UNumberFormatFields field) const U_OVERRIDE; + bool containsField(Field field) const U_OVERRIDE; void getParameters(Parameters& output) const U_OVERRIDE; @@ -219,7 +208,7 @@ class U_I18N_API MutablePatternModifier // Symbol details (initialized in setSymbols) const DecimalFormatSymbols *fSymbols; UNumberUnitWidth fUnitWidth; - const CurrencySymbols *fCurrencySymbols; + CurrencySymbols fCurrencySymbols; const PluralRules *fRules; // Number details (initialized in setNumberProperties) diff --git a/deps/icu-small/source/i18n/number_patternstring.cpp b/deps/icu-small/source/i18n/number_patternstring.cpp index c7212c1e5c23fe..9d845056069b80 100644 --- a/deps/icu-small/source/i18n/number_patternstring.cpp +++ b/deps/icu-small/source/i18n/number_patternstring.cpp @@ -686,10 +686,10 @@ UnicodeString PatternStringUtils::propertiesToPatternString(const DecimalFormatP int32_t exponentDigits = uprv_min(properties.minimumExponentDigits, dosMax); bool exponentShowPlusSign = properties.exponentSignAlwaysShown; - PropertiesAffixPatternProvider affixes(properties, status); + AutoAffixPatternProvider affixProvider(properties, status); // Prefixes - sb.append(affixes.getString(AffixPatternProvider::AFFIX_POS_PREFIX)); + sb.append(affixProvider.get().getString(AffixPatternProvider::AFFIX_POS_PREFIX)); int32_t afterPrefixPos = sb.length(); // Figure out the grouping sizes. @@ -778,7 +778,7 @@ UnicodeString PatternStringUtils::propertiesToPatternString(const DecimalFormatP // Suffixes int32_t beforeSuffixPos = sb.length(); - sb.append(affixes.getString(AffixPatternProvider::AFFIX_POS_SUFFIX)); + sb.append(affixProvider.get().getString(AffixPatternProvider::AFFIX_POS_SUFFIX)); // Resolve Padding if (paddingWidth > 0 && !paddingLocation.isNull()) { @@ -814,16 +814,16 @@ UnicodeString PatternStringUtils::propertiesToPatternString(const DecimalFormatP // Negative affixes // Ignore if the negative prefix pattern is "-" and the negative suffix is empty - if (affixes.hasNegativeSubpattern()) { + if (affixProvider.get().hasNegativeSubpattern()) { sb.append(u';'); - sb.append(affixes.getString(AffixPatternProvider::AFFIX_NEG_PREFIX)); + sb.append(affixProvider.get().getString(AffixPatternProvider::AFFIX_NEG_PREFIX)); // Copy the positive digit format into the negative. // This is optional; the pattern is the same as if '#' were appended here instead. // NOTE: It is not safe to append the UnicodeString to itself, so we need to copy. // See http://bugs.icu-project.org/trac/ticket/13707 UnicodeString copy(sb); sb.append(copy, afterPrefixPos, beforeSuffixPos - afterPrefixPos); - sb.append(affixes.getString(AffixPatternProvider::AFFIX_NEG_SUFFIX)); + sb.append(affixProvider.get().getString(AffixPatternProvider::AFFIX_NEG_SUFFIX)); } return sb; @@ -1000,23 +1000,19 @@ PatternStringUtils::convertLocalized(const UnicodeString& input, const DecimalFo } void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix, - Signum signum, UNumberSignDisplay signDisplay, + PatternSignType patternSignType, StandardPlural::Form plural, bool perMilleReplacesPercent, UnicodeString& output) { // Should the output render '+' where '-' would normally appear in the pattern? - bool plusReplacesMinusSign = signum != -1 && ( - signDisplay == UNUM_SIGN_ALWAYS || signDisplay == UNUM_SIGN_ACCOUNTING_ALWAYS || ( - signum == 1 && ( - signDisplay == UNUM_SIGN_EXCEPT_ZERO || - signDisplay == UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO))) && - patternInfo.positiveHasPlusSign() == false; - - // Should we use the affix from the negative subpattern? (If not, we will use the positive - // subpattern.) - // TODO: Deal with signum - bool useNegativeAffixPattern = patternInfo.hasNegativeSubpattern() && ( - signum == -1 || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign)); + bool plusReplacesMinusSign = (patternSignType == PATTERN_SIGN_TYPE_POS_SIGN) + && !patternInfo.positiveHasPlusSign(); + + // Should we use the affix from the negative subpattern? + // (If not, we will use the positive subpattern.) + bool useNegativeAffixPattern = patternInfo.hasNegativeSubpattern() + && (patternSignType == PATTERN_SIGN_TYPE_NEG + || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign)); // Resolve the flags for the affix pattern. int flags = 0; @@ -1035,8 +1031,8 @@ void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider& bool prependSign; if (!isPrefix || useNegativeAffixPattern) { prependSign = false; - } else if (signum == -1) { - prependSign = signDisplay != UNUM_SIGN_NEVER; + } else if (patternSignType == PATTERN_SIGN_TYPE_NEG) { + prependSign = true; } else { prependSign = plusReplacesMinusSign; } @@ -1065,4 +1061,60 @@ void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider& } } +PatternSignType PatternStringUtils::resolveSignDisplay(UNumberSignDisplay signDisplay, Signum signum) { + switch (signDisplay) { + case UNUM_SIGN_AUTO: + case UNUM_SIGN_ACCOUNTING: + switch (signum) { + case SIGNUM_NEG: + case SIGNUM_NEG_ZERO: + return PATTERN_SIGN_TYPE_NEG; + case SIGNUM_POS_ZERO: + case SIGNUM_POS: + return PATTERN_SIGN_TYPE_POS; + default: + break; + } + break; + + case UNUM_SIGN_ALWAYS: + case UNUM_SIGN_ACCOUNTING_ALWAYS: + switch (signum) { + case SIGNUM_NEG: + case SIGNUM_NEG_ZERO: + return PATTERN_SIGN_TYPE_NEG; + case SIGNUM_POS_ZERO: + case SIGNUM_POS: + return PATTERN_SIGN_TYPE_POS_SIGN; + default: + break; + } + break; + + case UNUM_SIGN_EXCEPT_ZERO: + case UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO: + switch (signum) { + case SIGNUM_NEG: + return PATTERN_SIGN_TYPE_NEG; + case SIGNUM_NEG_ZERO: + case SIGNUM_POS_ZERO: + return PATTERN_SIGN_TYPE_POS; + case SIGNUM_POS: + return PATTERN_SIGN_TYPE_POS_SIGN; + default: + break; + } + break; + + case UNUM_SIGN_NEVER: + return PATTERN_SIGN_TYPE_POS; + + default: + break; + } + + UPRV_UNREACHABLE; + return PATTERN_SIGN_TYPE_POS; +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_patternstring.h b/deps/icu-small/source/i18n/number_patternstring.h index 819c74d4bd886d..3e962cc134f98f 100644 --- a/deps/icu-small/source/i18n/number_patternstring.h +++ b/deps/icu-small/source/i18n/number_patternstring.h @@ -22,6 +22,18 @@ namespace impl { // Forward declaration class PatternParser; +// Note: the order of fields in this enum matters for parsing. +enum PatternSignType { + /** Render using normal positive subpattern rules */ + PATTERN_SIGN_TYPE_POS, + /** Render using rules to force the display of a plus sign */ + PATTERN_SIGN_TYPE_POS_SIGN, + /** Render using negative subpattern rules */ + PATTERN_SIGN_TYPE_NEG, + /** Count for looping over the possibilities */ + PATTERN_SIGN_TYPE_COUNT +}; + // Exported as U_I18N_API because it is a public member field of exported ParsedSubpatternInfo struct U_I18N_API Endpoints { int32_t start = 0; @@ -295,10 +307,12 @@ class U_I18N_API PatternStringUtils { * substitution, and plural forms for CurrencyPluralInfo. */ static void patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix, - Signum signum, UNumberSignDisplay signDisplay, + PatternSignType patternSignType, StandardPlural::Form plural, bool perMilleReplacesPercent, UnicodeString& output); + static PatternSignType resolveSignDisplay(UNumberSignDisplay signDisplay, Signum signum); + private: /** @return The number of chars inserted. */ static int escapePaddingString(UnicodeString input, UnicodeString& output, int startIndex, diff --git a/deps/icu-small/source/i18n/number_rounding.cpp b/deps/icu-small/source/i18n/number_rounding.cpp index 813d4b680d497b..3ffce673ad0885 100644 --- a/deps/icu-small/source/i18n/number_rounding.cpp +++ b/deps/icu-small/source/i18n/number_rounding.cpp @@ -294,9 +294,7 @@ RoundingImpl::RoundingImpl(const Precision& precision, UNumberFormatRoundingMode } RoundingImpl RoundingImpl::passThrough() { - RoundingImpl retval; - retval.fPassThrough = true; - return retval; + return {}; } bool RoundingImpl::isSignificantDigits() const { diff --git a/deps/icu-small/source/i18n/number_roundingutils.h b/deps/icu-small/source/i18n/number_roundingutils.h index 9c2c47b6e41b31..3e37f3195408fe 100644 --- a/deps/icu-small/source/i18n/number_roundingutils.h +++ b/deps/icu-small/source/i18n/number_roundingutils.h @@ -150,7 +150,7 @@ digits_t doubleFractionLength(double input, int8_t* singleDigit); */ class RoundingImpl { public: - RoundingImpl() = default; // default constructor: leaves object in undefined state + RoundingImpl() = default; // defaults to pass-through rounder RoundingImpl(const Precision& precision, UNumberFormatRoundingMode roundingMode, const CurrencyUnit& currency, UErrorCode& status); @@ -186,7 +186,7 @@ class RoundingImpl { private: Precision fPrecision; UNumberFormatRoundingMode fRoundingMode; - bool fPassThrough; + bool fPassThrough = true; // default value }; diff --git a/deps/icu-small/source/i18n/number_scientific.cpp b/deps/icu-small/source/i18n/number_scientific.cpp index 20aa45bff01959..33862d7a887ef4 100644 --- a/deps/icu-small/source/i18n/number_scientific.cpp +++ b/deps/icu-small/source/i18n/number_scientific.cpp @@ -44,21 +44,21 @@ int32_t ScientificModifier::apply(FormattedStringBuilder &output, int32_t /*left i += output.insert( i, fHandler->fSymbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kExponentialSymbol), - UNUM_EXPONENT_SYMBOL_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_EXPONENT_SYMBOL_FIELD}, status); if (fExponent < 0 && fHandler->fSettings.fExponentSignDisplay != UNUM_SIGN_NEVER) { i += output.insert( i, fHandler->fSymbols ->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kMinusSignSymbol), - UNUM_EXPONENT_SIGN_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_EXPONENT_SIGN_FIELD}, status); } else if (fExponent >= 0 && fHandler->fSettings.fExponentSignDisplay == UNUM_SIGN_ALWAYS) { i += output.insert( i, fHandler->fSymbols ->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kPlusSignSymbol), - UNUM_EXPONENT_SIGN_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_EXPONENT_SIGN_FIELD}, status); } // Append the exponent digits (using a simple inline algorithm) @@ -70,7 +70,7 @@ int32_t ScientificModifier::apply(FormattedStringBuilder &output, int32_t /*left i - j, d, *fHandler->fSymbols, - UNUM_EXPONENT_FIELD, + {UFIELD_CATEGORY_NUMBER, UNUM_EXPONENT_FIELD}, status); } return i - rightIndex; @@ -93,7 +93,7 @@ bool ScientificModifier::isStrong() const { return true; } -bool ScientificModifier::containsField(UNumberFormatFields field) const { +bool ScientificModifier::containsField(Field field) const { (void)field; // This method is not used for inner modifiers. UPRV_UNREACHABLE; @@ -149,6 +149,11 @@ void ScientificHandler::processQuantity(DecimalQuantity &quantity, MicroProps &m mod.set(exponent, this); micros.modInner = &mod; + // Change the exponent only after we select appropriate plural form + // for formatting purposes so that we preserve expected formatted + // string behavior. + quantity.adjustExponent(exponent); + // We already performed rounding. Do not perform it again. micros.rounder = RoundingImpl::passThrough(); } diff --git a/deps/icu-small/source/i18n/number_scientific.h b/deps/icu-small/source/i18n/number_scientific.h index 1c9ce1efa80a3f..a55d5ed1d410de 100644 --- a/deps/icu-small/source/i18n/number_scientific.h +++ b/deps/icu-small/source/i18n/number_scientific.h @@ -30,7 +30,7 @@ class U_I18N_API ScientificModifier : public UMemory, public Modifier { bool isStrong() const U_OVERRIDE; - bool containsField(UNumberFormatFields field) const U_OVERRIDE; + bool containsField(Field field) const U_OVERRIDE; void getParameters(Parameters& output) const U_OVERRIDE; diff --git a/deps/icu-small/source/i18n/number_skeletons.cpp b/deps/icu-small/source/i18n/number_skeletons.cpp index 4025539239b786..4ba2647986c755 100644 --- a/deps/icu-small/source/i18n/number_skeletons.cpp +++ b/deps/icu-small/source/i18n/number_skeletons.cpp @@ -21,6 +21,9 @@ #include "uinvchar.h" #include "charstr.h" #include "string_segment.h" +#include "unicode/errorcode.h" +#include "util.h" +#include "measunit_impl.h" using namespace icu; using namespace icu::number; @@ -93,12 +96,29 @@ void U_CALLCONV initNumberSkeletons(UErrorCode& status) { b.add(u"precision-increment", STEM_PRECISION_INCREMENT, status); b.add(u"measure-unit", STEM_MEASURE_UNIT, status); b.add(u"per-measure-unit", STEM_PER_MEASURE_UNIT, status); + b.add(u"unit", STEM_UNIT, status); b.add(u"currency", STEM_CURRENCY, status); b.add(u"integer-width", STEM_INTEGER_WIDTH, status); b.add(u"numbering-system", STEM_NUMBERING_SYSTEM, status); b.add(u"scale", STEM_SCALE, status); if (U_FAILURE(status)) { return; } + // Section 3 (concise tokens): + b.add(u"K", STEM_COMPACT_SHORT, status); + b.add(u"KK", STEM_COMPACT_LONG, status); + b.add(u"%", STEM_PERCENT, status); + b.add(u"%x100", STEM_PERCENT_100, status); + b.add(u",_", STEM_GROUP_OFF, status); + b.add(u",?", STEM_GROUP_MIN2, status); + b.add(u",!", STEM_GROUP_ON_ALIGNED, status); + b.add(u"+!", STEM_SIGN_ALWAYS, status); + b.add(u"+_", STEM_SIGN_NEVER, status); + b.add(u"()", STEM_SIGN_ACCOUNTING, status); + b.add(u"()!", STEM_SIGN_ACCOUNTING_ALWAYS, status); + b.add(u"+?", STEM_SIGN_EXCEPT_ZERO, status); + b.add(u"()?", STEM_SIGN_ACCOUNTING_EXCEPT_ZERO, status); + if (U_FAILURE(status)) { return; } + // Build the CharsTrie // TODO: Use SLOW or FAST here? UnicodeString result; @@ -529,6 +549,7 @@ MacroProps skeleton::parseSkeleton( case STATE_INCREMENT_PRECISION: case STATE_MEASURE_UNIT: case STATE_PER_MEASURE_UNIT: + case STATE_IDENTIFIER_UNIT: case STATE_CURRENCY_UNIT: case STATE_INTEGER_WIDTH: case STATE_NUMBERING_SYSTEM: @@ -557,13 +578,21 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se // First check for "blueprint" stems, which start with a "signal char" switch (segment.charAt(0)) { case u'.': - CHECK_NULL(seen, precision, status); + CHECK_NULL(seen, precision, status); blueprint_helpers::parseFractionStem(segment, macros, status); return STATE_FRACTION_PRECISION; case u'@': - CHECK_NULL(seen, precision, status); + CHECK_NULL(seen, precision, status); blueprint_helpers::parseDigitsStem(segment, macros, status); return STATE_NULL; + case u'E': + CHECK_NULL(seen, notation, status); + blueprint_helpers::parseScientificStem(segment, macros, status); + return STATE_NULL; + case u'0': + CHECK_NULL(seen, integerWidth, status); + blueprint_helpers::parseIntegerStem(segment, macros, status); + return STATE_NULL; default: break; } @@ -587,7 +616,7 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se case STEM_SCIENTIFIC: case STEM_ENGINEERING: case STEM_NOTATION_SIMPLE: - CHECK_NULL(seen, notation, status); + CHECK_NULL(seen, notation, status); macros.notation = stem_to_object::notation(stem); switch (stem) { case STEM_SCIENTIFIC: @@ -600,15 +629,22 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se case STEM_BASE_UNIT: case STEM_PERCENT: case STEM_PERMILLE: - CHECK_NULL(seen, unit, status); + CHECK_NULL(seen, unit, status); macros.unit = stem_to_object::unit(stem); return STATE_NULL; + case STEM_PERCENT_100: + CHECK_NULL(seen, scale, status); + CHECK_NULL(seen, unit, status); + macros.scale = Scale::powerOfTen(2); + macros.unit = NoUnit::percent(); + return STATE_NULL; + case STEM_PRECISION_INTEGER: case STEM_PRECISION_UNLIMITED: case STEM_PRECISION_CURRENCY_STANDARD: case STEM_PRECISION_CURRENCY_CASH: - CHECK_NULL(seen, precision, status); + CHECK_NULL(seen, precision, status); macros.precision = stem_to_object::precision(stem); switch (stem) { case STEM_PRECISION_INTEGER: @@ -625,7 +661,7 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se case STEM_ROUNDING_MODE_HALF_DOWN: case STEM_ROUNDING_MODE_HALF_UP: case STEM_ROUNDING_MODE_UNNECESSARY: - CHECK_NULL(seen, roundingMode, status); + CHECK_NULL(seen, roundingMode, status); macros.roundingMode = stem_to_object::roundingMode(stem); return STATE_NULL; @@ -634,12 +670,12 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se case STEM_GROUP_AUTO: case STEM_GROUP_ON_ALIGNED: case STEM_GROUP_THOUSANDS: - CHECK_NULL(seen, grouper, status); + CHECK_NULL(seen, grouper, status); macros.grouper = Grouper::forStrategy(stem_to_object::groupingStrategy(stem)); return STATE_NULL; case STEM_LATIN: - CHECK_NULL(seen, symbols, status); + CHECK_NULL(seen, symbols, status); macros.symbols.setTo(NumberingSystem::createInstanceByName("latn", status)); return STATE_NULL; @@ -648,7 +684,7 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se case STEM_UNIT_WIDTH_FULL_NAME: case STEM_UNIT_WIDTH_ISO_CODE: case STEM_UNIT_WIDTH_HIDDEN: - CHECK_NULL(seen, unitWidth, status); + CHECK_NULL(seen, unitWidth, status); macros.unitWidth = stem_to_object::unitWidth(stem); return STATE_NULL; @@ -659,44 +695,49 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se case STEM_SIGN_ACCOUNTING_ALWAYS: case STEM_SIGN_EXCEPT_ZERO: case STEM_SIGN_ACCOUNTING_EXCEPT_ZERO: - CHECK_NULL(seen, sign, status); + CHECK_NULL(seen, sign, status); macros.sign = stem_to_object::signDisplay(stem); return STATE_NULL; case STEM_DECIMAL_AUTO: case STEM_DECIMAL_ALWAYS: - CHECK_NULL(seen, decimal, status); + CHECK_NULL(seen, decimal, status); macros.decimal = stem_to_object::decimalSeparatorDisplay(stem); return STATE_NULL; // Stems requiring an option: case STEM_PRECISION_INCREMENT: - CHECK_NULL(seen, precision, status); + CHECK_NULL(seen, precision, status); return STATE_INCREMENT_PRECISION; case STEM_MEASURE_UNIT: - CHECK_NULL(seen, unit, status); + CHECK_NULL(seen, unit, status); return STATE_MEASURE_UNIT; case STEM_PER_MEASURE_UNIT: - CHECK_NULL(seen, perUnit, status); + CHECK_NULL(seen, perUnit, status); return STATE_PER_MEASURE_UNIT; + case STEM_UNIT: + CHECK_NULL(seen, unit, status); + CHECK_NULL(seen, perUnit, status); + return STATE_IDENTIFIER_UNIT; + case STEM_CURRENCY: - CHECK_NULL(seen, unit, status); + CHECK_NULL(seen, unit, status); return STATE_CURRENCY_UNIT; case STEM_INTEGER_WIDTH: - CHECK_NULL(seen, integerWidth, status); + CHECK_NULL(seen, integerWidth, status); return STATE_INTEGER_WIDTH; case STEM_NUMBERING_SYSTEM: - CHECK_NULL(seen, symbols, status); + CHECK_NULL(seen, symbols, status); return STATE_NUMBERING_SYSTEM; case STEM_SCALE: - CHECK_NULL(seen, scale, status); + CHECK_NULL(seen, scale, status); return STATE_SCALE; default: @@ -719,6 +760,9 @@ ParseState skeleton::parseOption(ParseState stem, const StringSegment& segment, case STATE_PER_MEASURE_UNIT: blueprint_helpers::parseMeasurePerUnitOption(segment, macros, status); return STATE_NULL; + case STATE_IDENTIFIER_UNIT: + blueprint_helpers::parseIdentifierUnitOption(segment, macros, status); + return STATE_NULL; case STATE_INCREMENT_PRECISION: blueprint_helpers::parseIncrementOption(segment, macros, status); return STATE_NULL; @@ -843,10 +887,6 @@ void GeneratorHelpers::generateSkeleton(const MacroProps& macros, UnicodeString& status = U_UNSUPPORTED_ERROR; return; } - if (macros.currencySymbols != nullptr) { - status = U_UNSUPPORTED_ERROR; - return; - } // Remove the trailing space if (sb.length() > 0) { @@ -857,7 +897,7 @@ void GeneratorHelpers::generateSkeleton(const MacroProps& macros, UnicodeString& bool blueprint_helpers::parseExponentWidthOption(const StringSegment& segment, MacroProps& macros, UErrorCode&) { - if (segment.charAt(0) != u'+') { + if (!isWildcardChar(segment.charAt(0))) { return false; } int32_t offset = 1; @@ -879,7 +919,7 @@ bool blueprint_helpers::parseExponentWidthOption(const StringSegment& segment, M void blueprint_helpers::generateExponentWidthOption(int32_t minExponentDigits, UnicodeString& sb, UErrorCode&) { - sb.append(u'+'); + sb.append(kWildcardChar); appendMultiple(sb, u'e', minExponentDigits); } @@ -981,7 +1021,7 @@ void blueprint_helpers::generateMeasureUnitOption(const MeasureUnit& measureUnit void blueprint_helpers::parseMeasurePerUnitOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status) { - // A little bit of a hack: safe the current unit (numerator), call the main measure unit + // A little bit of a hack: save the current unit (numerator), call the main measure unit // parsing code, put back the numerator unit, and put the new unit into per-unit. MeasureUnit numerator = macros.unit; parseMeasureUnitOption(segment, macros, status); @@ -990,6 +1030,33 @@ void blueprint_helpers::parseMeasurePerUnitOption(const StringSegment& segment, macros.unit = numerator; } +void blueprint_helpers::parseIdentifierUnitOption(const StringSegment& segment, MacroProps& macros, + UErrorCode& status) { + // Need to do char <-> UChar conversion... + U_ASSERT(U_SUCCESS(status)); + CharString buffer; + SKELETON_UCHAR_TO_CHAR(buffer, segment.toTempUnicodeString(), 0, segment.length(), status); + + ErrorCode internalStatus; + auto fullUnit = MeasureUnitImpl::forIdentifier(buffer.toStringPiece(), internalStatus); + if (internalStatus.isFailure()) { + // throw new SkeletonSyntaxException("Invalid core unit identifier", segment, e); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return; + } + + // TODO(ICU-20941): Clean this up. + for (int32_t i = 0; i < fullUnit.units.length(); i++) { + SingleUnitImpl* subUnit = fullUnit.units[i]; + if (subUnit->dimensionality > 0) { + macros.unit = macros.unit.product(subUnit->build(status), status); + } else { + subUnit->dimensionality *= -1; + macros.perUnit = macros.perUnit.product(subUnit->build(status), status); + } + } +} + void blueprint_helpers::parseFractionStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status) { U_ASSERT(segment.charAt(0) == u'.'); @@ -1004,7 +1071,7 @@ void blueprint_helpers::parseFractionStem(const StringSegment& segment, MacroPro } } if (offset < segment.length()) { - if (segment.charAt(offset) == u'+') { + if (isWildcardChar(segment.charAt(offset))) { maxFrac = -1; offset++; } else { @@ -1027,7 +1094,11 @@ void blueprint_helpers::parseFractionStem(const StringSegment& segment, MacroPro } // Use the public APIs to enforce bounds checking if (maxFrac == -1) { - macros.precision = Precision::minFraction(minFrac); + if (minFrac == 0) { + macros.precision = Precision::unlimited(); + } else { + macros.precision = Precision::minFraction(minFrac); + } } else { macros.precision = Precision::minMaxFraction(minFrac, maxFrac); } @@ -1042,7 +1113,7 @@ blueprint_helpers::generateFractionStem(int32_t minFrac, int32_t maxFrac, Unicod sb.append(u'.'); appendMultiple(sb, u'0', minFrac); if (maxFrac == -1) { - sb.append(u'+'); + sb.append(kWildcardChar); } else { appendMultiple(sb, u'#', maxFrac - minFrac); } @@ -1051,9 +1122,9 @@ blueprint_helpers::generateFractionStem(int32_t minFrac, int32_t maxFrac, Unicod void blueprint_helpers::parseDigitsStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status) { U_ASSERT(segment.charAt(0) == u'@'); - int offset = 0; - int minSig = 0; - int maxSig; + int32_t offset = 0; + int32_t minSig = 0; + int32_t maxSig; for (; offset < segment.length(); offset++) { if (segment.charAt(offset) == u'@') { minSig++; @@ -1062,7 +1133,7 @@ blueprint_helpers::parseDigitsStem(const StringSegment& segment, MacroProps& mac } } if (offset < segment.length()) { - if (segment.charAt(offset) == u'+') { + if (isWildcardChar(segment.charAt(offset))) { maxSig = -1; offset++; } else { @@ -1095,12 +1166,81 @@ void blueprint_helpers::generateDigitsStem(int32_t minSig, int32_t maxSig, UnicodeString& sb, UErrorCode&) { appendMultiple(sb, u'@', minSig); if (maxSig == -1) { - sb.append(u'+'); + sb.append(kWildcardChar); } else { appendMultiple(sb, u'#', maxSig - minSig); } } +void blueprint_helpers::parseScientificStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status) { + U_ASSERT(segment.charAt(0) == u'E'); + { + int32_t offset = 1; + if (segment.length() == offset) { + goto fail; + } + bool isEngineering = false; + if (segment.charAt(offset) == u'E') { + isEngineering = true; + offset++; + if (segment.length() == offset) { + goto fail; + } + } + UNumberSignDisplay signDisplay = UNUM_SIGN_AUTO; + if (segment.charAt(offset) == u'+') { + offset++; + if (segment.length() == offset) { + goto fail; + } + if (segment.charAt(offset) == u'!') { + signDisplay = UNUM_SIGN_ALWAYS; + } else if (segment.charAt(offset) == u'?') { + signDisplay = UNUM_SIGN_EXCEPT_ZERO; + } else { + goto fail; + } + offset++; + if (segment.length() == offset) { + goto fail; + } + } + int32_t minDigits = 0; + for (; offset < segment.length(); offset++) { + if (segment.charAt(offset) != u'0') { + goto fail; + } + minDigits++; + } + macros.notation = (isEngineering ? Notation::engineering() : Notation::scientific()) + .withExponentSignDisplay(signDisplay) + .withMinExponentDigits(minDigits); + return; + } + fail: void(); + // throw new SkeletonSyntaxException("Invalid scientific stem", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return; +} + +void blueprint_helpers::parseIntegerStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status) { + U_ASSERT(segment.charAt(0) == u'0'); + int32_t offset = 1; + for (; offset < segment.length(); offset++) { + if (segment.charAt(offset) != u'0') { + offset--; + break; + } + } + if (offset < segment.length()) { + // throw new SkeletonSyntaxException("Invalid integer stem", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return; + } + macros.integerWidth = IntegerWidth::zeroFillTo(offset); + return; +} + bool blueprint_helpers::parseFracSigOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status) { if (segment.charAt(0) != u'@') { @@ -1122,7 +1262,7 @@ bool blueprint_helpers::parseFracSigOption(const StringSegment& segment, MacroPr // Invalid: @, @@, @@@ // Invalid: @@#, @@##, @@@# if (offset < segment.length()) { - if (segment.charAt(offset) == u'+') { + if (isWildcardChar(segment.charAt(offset))) { maxSig = -1; offset++; } else if (minSig > 1) { @@ -1211,7 +1351,7 @@ void blueprint_helpers::parseIntegerWidthOption(const StringSegment& segment, Ma int32_t offset = 0; int32_t minInt = 0; int32_t maxInt; - if (segment.charAt(0) == u'+') { + if (isWildcardChar(segment.charAt(0))) { maxInt = -1; offset++; } else { @@ -1252,7 +1392,7 @@ void blueprint_helpers::parseIntegerWidthOption(const StringSegment& segment, Ma void blueprint_helpers::generateIntegerWidthOption(int32_t minInt, int32_t maxInt, UnicodeString& sb, UErrorCode&) { if (maxInt == -1) { - sb.append(u'+'); + sb.append(kWildcardChar); } else { appendMultiple(sb, u'#', maxInt - minInt); } @@ -1543,4 +1683,49 @@ bool GeneratorHelpers::scale(const MacroProps& macros, UnicodeString& sb, UError } +// Definitions of public API methods (put here for dependency disentanglement) + +#if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER) +// Ignore MSVC warning 4661. This is generated for NumberFormatterSettings<>::toSkeleton() as this method +// is defined elsewhere (in number_skeletons.cpp). The compiler is warning that the explicit template instantiation +// inside this single translation unit (CPP file) is incomplete, and thus it isn't sure if the template class is +// fully defined. However, since each translation unit explicitly instantiates all the necessary template classes, +// they will all be passed to the linker, and the linker will still find and export all the class members. +#pragma warning(push) +#pragma warning(disable: 4661) +#endif + +template +UnicodeString NumberFormatterSettings::toSkeleton(UErrorCode& status) const { + if (U_FAILURE(status)) { + return ICU_Utility::makeBogusString(); + } + if (fMacros.copyErrorTo(status)) { + return ICU_Utility::makeBogusString(); + } + return skeleton::generate(fMacros, status); +} + +// Declare all classes that implement NumberFormatterSettings +// See https://stackoverflow.com/a/495056/1407170 +template +class icu::number::NumberFormatterSettings; +template +class icu::number::NumberFormatterSettings; + +UnlocalizedNumberFormatter +NumberFormatter::forSkeleton(const UnicodeString& skeleton, UErrorCode& status) { + return skeleton::create(skeleton, nullptr, status); +} + +UnlocalizedNumberFormatter +NumberFormatter::forSkeleton(const UnicodeString& skeleton, UParseError& perror, UErrorCode& status) { + return skeleton::create(skeleton, &perror, status); +} + +#if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER) +// Warning 4661. +#pragma warning(pop) +#endif + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_skeletons.h b/deps/icu-small/source/i18n/number_skeletons.h index 59af771928fbd0..d9b2c0ee0b19ab 100644 --- a/deps/icu-small/source/i18n/number_skeletons.h +++ b/deps/icu-small/source/i18n/number_skeletons.h @@ -46,6 +46,7 @@ enum ParseState { STATE_INCREMENT_PRECISION, STATE_MEASURE_UNIT, STATE_PER_MEASURE_UNIT, + STATE_IDENTIFIER_UNIT, STATE_CURRENCY_UNIT, STATE_INTEGER_WIDTH, STATE_NUMBERING_SYSTEM, @@ -71,6 +72,7 @@ enum StemEnum { STEM_BASE_UNIT, STEM_PERCENT, STEM_PERMILLE, + STEM_PERCENT_100, // concise-only STEM_PRECISION_INTEGER, STEM_PRECISION_UNLIMITED, STEM_PRECISION_CURRENCY_STANDARD, @@ -109,12 +111,24 @@ enum StemEnum { STEM_PRECISION_INCREMENT, STEM_MEASURE_UNIT, STEM_PER_MEASURE_UNIT, + STEM_UNIT, STEM_CURRENCY, STEM_INTEGER_WIDTH, STEM_NUMBERING_SYSTEM, STEM_SCALE, }; +/** Default wildcard char, accepted on input and printed in output */ +constexpr char16_t kWildcardChar = u'*'; + +/** Alternative wildcard char, accept on input but not printed in output */ +constexpr char16_t kAltWildcardChar = u'+'; + +/** Checks whether the char is a wildcard on input */ +inline bool isWildcardChar(char16_t c) { + return c == kWildcardChar || c == kAltWildcardChar; +} + /** * Creates a NumberFormatter corresponding to the given skeleton string. * @@ -226,6 +240,8 @@ void generateMeasureUnitOption(const MeasureUnit& measureUnit, UnicodeString& sb void parseMeasurePerUnitOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); +void parseIdentifierUnitOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + void parseFractionStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status); void generateFractionStem(int32_t minFrac, int32_t maxFrac, UnicodeString& sb, UErrorCode& status); @@ -234,6 +250,14 @@ void parseDigitsStem(const StringSegment& segment, MacroProps& macros, UErrorCod void generateDigitsStem(int32_t minSig, int32_t maxSig, UnicodeString& sb, UErrorCode& status); +void parseScientificStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +// Note: no generateScientificStem since this syntax was added later in ICU 67 + +void parseIntegerStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +// Note: no generateIntegerStem since this syntax was added later in ICU 67 + /** @return Whether we successfully found and parsed a frac-sig option. */ bool parseFracSigOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); diff --git a/deps/icu-small/source/i18n/number_types.h b/deps/icu-small/source/i18n/number_types.h index d62aa6a66b30d3..5c2b8cf8b5d19c 100644 --- a/deps/icu-small/source/i18n/number_types.h +++ b/deps/icu-small/source/i18n/number_types.h @@ -92,9 +92,11 @@ enum CompactType { }; enum Signum { - SIGNUM_NEG = -1, - SIGNUM_ZERO = 0, - SIGNUM_POS = 1 + SIGNUM_NEG = 0, + SIGNUM_NEG_ZERO = 1, + SIGNUM_POS_ZERO = 2, + SIGNUM_POS = 3, + SIGNUM_COUNT = 4, }; @@ -192,7 +194,7 @@ class U_I18N_API Modifier { /** * Whether the modifier contains at least one occurrence of the given field. */ - virtual bool containsField(UNumberFormatFields field) const = 0; + virtual bool containsField(Field field) const = 0; /** * A fill-in for getParameters(). obj will always be set; if non-null, the other diff --git a/deps/icu-small/source/i18n/number_utypes.h b/deps/icu-small/source/i18n/number_utypes.h index 6dbe5bee68fb71..7a1b7a4e80ac31 100644 --- a/deps/icu-small/source/i18n/number_utypes.h +++ b/deps/icu-small/source/i18n/number_utypes.h @@ -30,10 +30,12 @@ const DecimalQuantity* validateUFormattedNumberToDecimalQuantity( * * The DecimalQuantity is not currently being used by FormattedNumber, but at some point it could be used * to add a toDecNumber() or similar method. + * + * Exported as U_I18N_API for tests */ -class UFormattedNumberData : public FormattedValueStringBuilderImpl { +class U_I18N_API UFormattedNumberData : public FormattedValueStringBuilderImpl { public: - UFormattedNumberData() : FormattedValueStringBuilderImpl(0) {} + UFormattedNumberData() : FormattedValueStringBuilderImpl(kUndefinedField) {} virtual ~UFormattedNumberData(); DecimalQuantity quantity; diff --git a/deps/icu-small/source/i18n/numparse_affixes.cpp b/deps/icu-small/source/i18n/numparse_affixes.cpp index 4f83e0dd4076c3..187830fb6fc0df 100644 --- a/deps/icu-small/source/i18n/numparse_affixes.cpp +++ b/deps/icu-small/source/i18n/numparse_affixes.cpp @@ -271,8 +271,6 @@ void AffixMatcherWarehouse::createAffixMatchers(const AffixPatternProvider& patt // Use initial capacity of 6, the highest possible number of AffixMatchers. UnicodeString sb; bool includeUnpaired = 0 != (parseFlags & PARSE_FLAG_INCLUDE_UNPAIRED_AFFIXES); - UNumberSignDisplay signDisplay = (0 != (parseFlags & PARSE_FLAG_PLUS_SIGN_ALLOWED)) ? UNUM_SIGN_ALWAYS - : UNUM_SIGN_AUTO; int32_t numAffixMatchers = 0; int32_t numAffixPatternMatchers = 0; @@ -281,13 +279,23 @@ void AffixMatcherWarehouse::createAffixMatchers(const AffixPatternProvider& patt AffixPatternMatcher* posSuffix = nullptr; // Pre-process the affix strings to resolve LDML rules like sign display. - for (int8_t signumInt = 1; signumInt >= -1; signumInt--) { - auto signum = static_cast(signumInt); + for (int8_t typeInt = 0; typeInt < PATTERN_SIGN_TYPE_COUNT; typeInt++) { + auto type = static_cast(typeInt); + + // Skip affixes in some cases + if (type == PATTERN_SIGN_TYPE_POS + && 0 != (parseFlags & PARSE_FLAG_PLUS_SIGN_ALLOWED)) { + continue; + } + if (type == PATTERN_SIGN_TYPE_POS_SIGN + && 0 == (parseFlags & PARSE_FLAG_PLUS_SIGN_ALLOWED)) { + continue; + } // Generate Prefix bool hasPrefix = false; PatternStringUtils::patternInfoToStringBuilder( - patternInfo, true, signum, signDisplay, StandardPlural::OTHER, false, sb); + patternInfo, true, type, StandardPlural::OTHER, false, sb); fAffixPatternMatchers[numAffixPatternMatchers] = AffixPatternMatcher::fromAffixPattern( sb, *fTokenWarehouse, parseFlags, &hasPrefix, status); AffixPatternMatcher* prefix = hasPrefix ? &fAffixPatternMatchers[numAffixPatternMatchers++] @@ -296,13 +304,13 @@ void AffixMatcherWarehouse::createAffixMatchers(const AffixPatternProvider& patt // Generate Suffix bool hasSuffix = false; PatternStringUtils::patternInfoToStringBuilder( - patternInfo, false, signum, signDisplay, StandardPlural::OTHER, false, sb); + patternInfo, false, type, StandardPlural::OTHER, false, sb); fAffixPatternMatchers[numAffixPatternMatchers] = AffixPatternMatcher::fromAffixPattern( sb, *fTokenWarehouse, parseFlags, &hasSuffix, status); AffixPatternMatcher* suffix = hasSuffix ? &fAffixPatternMatchers[numAffixPatternMatchers++] : nullptr; - if (signum == 1) { + if (type == PATTERN_SIGN_TYPE_POS) { posPrefix = prefix; posSuffix = suffix; } else if (equals(prefix, posPrefix) && equals(suffix, posSuffix)) { @@ -311,17 +319,17 @@ void AffixMatcherWarehouse::createAffixMatchers(const AffixPatternProvider& patt } // Flags for setting in the ParsedNumber; the token matchers may add more. - int flags = (signum == -1) ? FLAG_NEGATIVE : 0; + int flags = (type == PATTERN_SIGN_TYPE_NEG) ? FLAG_NEGATIVE : 0; // Note: it is indeed possible for posPrefix and posSuffix to both be null. // We still need to add that matcher for strict mode to work. fAffixMatchers[numAffixMatchers++] = {prefix, suffix, flags}; if (includeUnpaired && prefix != nullptr && suffix != nullptr) { // The following if statements are designed to prevent adding two identical matchers. - if (signum == 1 || !equals(prefix, posPrefix)) { + if (type == PATTERN_SIGN_TYPE_POS || !equals(prefix, posPrefix)) { fAffixMatchers[numAffixMatchers++] = {prefix, nullptr, flags}; } - if (signum == 1 || !equals(suffix, posSuffix)) { + if (type == PATTERN_SIGN_TYPE_POS || !equals(suffix, posSuffix)) { fAffixMatchers[numAffixMatchers++] = {nullptr, suffix, flags}; } } diff --git a/deps/icu-small/source/i18n/numparse_affixes.h b/deps/icu-small/source/i18n/numparse_affixes.h index e498483fbca8cf..2ac69df109519e 100644 --- a/deps/icu-small/source/i18n/numparse_affixes.h +++ b/deps/icu-small/source/i18n/numparse_affixes.h @@ -28,7 +28,7 @@ using ::icu::number::impl::TokenConsumer; using ::icu::number::impl::CurrencySymbols; -class CodePointMatcher : public NumberParseMatcher, public UMemory { +class U_I18N_API CodePointMatcher : public NumberParseMatcher, public UMemory { public: CodePointMatcher() = default; // WARNING: Leaves the object in an unusable state diff --git a/deps/icu-small/source/i18n/numparse_impl.cpp b/deps/icu-small/source/i18n/numparse_impl.cpp index bf5829061a1511..4b76da1c149a74 100644 --- a/deps/icu-small/source/i18n/numparse_impl.cpp +++ b/deps/icu-small/source/i18n/numparse_impl.cpp @@ -83,23 +83,14 @@ NumberParserImpl::createParserFromProperties(const number::impl::DecimalFormatPr const DecimalFormatSymbols& symbols, bool parseCurrency, UErrorCode& status) { Locale locale = symbols.getLocale(); - PropertiesAffixPatternProvider localPAPP; - CurrencyPluralInfoAffixProvider localCPIAP; - AffixPatternProvider* affixProvider; - if (properties.currencyPluralInfo.fPtr.isNull()) { - localPAPP.setTo(properties, status); - affixProvider = &localPAPP; - } else { - localCPIAP.setTo(*properties.currencyPluralInfo.fPtr, properties, status); - affixProvider = &localCPIAP; - } - if (affixProvider == nullptr || U_FAILURE(status)) { return nullptr; } + AutoAffixPatternProvider affixProvider(properties, status); + if (U_FAILURE(status)) { return nullptr; } CurrencyUnit currency = resolveCurrency(properties, locale, status); CurrencySymbols currencySymbols(currency, locale, symbols, status); bool isStrict = properties.parseMode.getOrDefault(PARSE_MODE_STRICT) == PARSE_MODE_STRICT; Grouper grouper = Grouper::forProperties(properties); int parseFlags = 0; - if (affixProvider == nullptr || U_FAILURE(status)) { return nullptr; } + if (U_FAILURE(status)) { return nullptr; } if (!properties.parseCaseSensitive) { parseFlags |= PARSE_FLAG_IGNORE_CASE; } @@ -121,7 +112,7 @@ NumberParserImpl::createParserFromProperties(const number::impl::DecimalFormatPr if (grouper.getPrimary() <= 0) { parseFlags |= PARSE_FLAG_GROUPING_DISABLED; } - if (parseCurrency || affixProvider->hasCurrencySign()) { + if (parseCurrency || affixProvider.get().hasCurrencySign()) { parseFlags |= PARSE_FLAG_MONETARY_SEPARATORS; } if (!parseCurrency) { @@ -143,13 +134,13 @@ NumberParserImpl::createParserFromProperties(const number::impl::DecimalFormatPr parser->fLocalMatchers.affixTokenMatcherWarehouse = {&affixSetupData}; parser->fLocalMatchers.affixMatcherWarehouse = {&parser->fLocalMatchers.affixTokenMatcherWarehouse}; parser->fLocalMatchers.affixMatcherWarehouse.createAffixMatchers( - *affixProvider, *parser, ignorables, parseFlags, status); + affixProvider.get(), *parser, ignorables, parseFlags, status); //////////////////////// /// CURRENCY MATCHER /// //////////////////////// - if (parseCurrency || affixProvider->hasCurrencySign()) { + if (parseCurrency || affixProvider.get().hasCurrencySign()) { parser->addMatcher(parser->fLocalMatchers.currency = {currencySymbols, symbols, parseFlags, status}); } @@ -159,10 +150,10 @@ NumberParserImpl::createParserFromProperties(const number::impl::DecimalFormatPr // ICU-TC meeting, April 11, 2018: accept percent/permille only if it is in the pattern, // and to maintain regressive behavior, divide by 100 even if no percent sign is present. - if (!isStrict && affixProvider->containsSymbolType(AffixPatternType::TYPE_PERCENT, status)) { + if (!isStrict && affixProvider.get().containsSymbolType(AffixPatternType::TYPE_PERCENT, status)) { parser->addMatcher(parser->fLocalMatchers.percent = {symbols}); } - if (!isStrict && affixProvider->containsSymbolType(AffixPatternType::TYPE_PERMILLE, status)) { + if (!isStrict && affixProvider.get().containsSymbolType(AffixPatternType::TYPE_PERMILLE, status)) { parser->addMatcher(parser->fLocalMatchers.permille = {symbols}); } diff --git a/deps/icu-small/source/i18n/numrange_fluent.cpp b/deps/icu-small/source/i18n/numrange_fluent.cpp index 654cafaf00bc82..33179026f8d2b5 100644 --- a/deps/icu-small/source/i18n/numrange_fluent.cpp +++ b/deps/icu-small/source/i18n/numrange_fluent.cpp @@ -379,23 +379,6 @@ UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(FormattedNumberRange) #define UPRV_NOARG -UBool FormattedNumberRange::nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const { - UPRV_FORMATTED_VALUE_METHOD_GUARD(FALSE) - // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool - return fData->nextFieldPosition(fieldPosition, status); -} - -void FormattedNumberRange::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const { - FieldPositionIteratorHandler fpih(&iterator, status); - getAllFieldPositionsImpl(fpih, status); -} - -void FormattedNumberRange::getAllFieldPositionsImpl( - FieldPositionIteratorHandler& fpih, UErrorCode& status) const { - UPRV_FORMATTED_VALUE_METHOD_GUARD(UPRV_NOARG) - fData->getAllFieldPositions(fpih, status); -} - UnicodeString FormattedNumberRange::getFirstDecimal(UErrorCode& status) const { UPRV_FORMATTED_VALUE_METHOD_GUARD(ICU_Utility::makeBogusString()) return fData->quantity1.toScientificString(); diff --git a/deps/icu-small/source/i18n/numrange_impl.cpp b/deps/icu-small/source/i18n/numrange_impl.cpp index 7d732b31ec177a..9fb3dee861f1f6 100644 --- a/deps/icu-small/source/i18n/numrange_impl.cpp +++ b/deps/icu-small/source/i18n/numrange_impl.cpp @@ -210,7 +210,7 @@ NumberRangeFormatterImpl::NumberRangeFormatterImpl(const RangeMacroProps& macros getNumberRangeData(macros.locale.getName(), nsName, data, status); if (U_FAILURE(status)) { return; } fRangeFormatter = data.rangePattern; - fApproximatelyModifier = {data.approximatelyPattern, UNUM_FIELD_COUNT, false}; + fApproximatelyModifier = {data.approximatelyPattern, kUndefinedField, false}; // TODO: Get locale from PluralRules instead? fPluralRanges.initialize(macros.locale, status); @@ -368,7 +368,8 @@ void NumberRangeFormatterImpl::formatRange(UFormattedNumberRangeData& data, // Only collapse if the modifier is a unit. // TODO: Make a better way to check for a unit? // TODO: Handle case where the modifier has both notation and unit (compact currency)? - if (!mm->containsField(UNUM_CURRENCY_FIELD) && !mm->containsField(UNUM_PERCENT_FIELD)) { + if (!mm->containsField({UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD}) + && !mm->containsField({UFIELD_CATEGORY_NUMBER, UNUM_PERCENT_FIELD})) { collapseMiddle = false; } } else if (fCollapse == UNUM_RANGE_COLLAPSE_AUTO) { @@ -416,7 +417,7 @@ void NumberRangeFormatterImpl::formatRange(UFormattedNumberRangeData& data, 0, &lengthPrefix, &lengthSuffix, - UNUM_FIELD_COUNT, + kUndefinedField, status); if (U_FAILURE(status)) { return; } lengthInfix = lengthRange - lengthPrefix - lengthSuffix; @@ -434,10 +435,10 @@ void NumberRangeFormatterImpl::formatRange(UFormattedNumberRangeData& data, if (repeatInner || repeatMiddle || repeatOuter) { // Add spacing if there is not already spacing if (!PatternProps::isWhiteSpace(string.charAt(UPRV_INDEX_1))) { - lengthInfix += string.insertCodePoint(UPRV_INDEX_1, u'\u0020', UNUM_FIELD_COUNT, status); + lengthInfix += string.insertCodePoint(UPRV_INDEX_1, u'\u0020', kUndefinedField, status); } if (!PatternProps::isWhiteSpace(string.charAt(UPRV_INDEX_2 - 1))) { - lengthInfix += string.insertCodePoint(UPRV_INDEX_2, u'\u0020', UNUM_FIELD_COUNT, status); + lengthInfix += string.insertCodePoint(UPRV_INDEX_2, u'\u0020', kUndefinedField, status); } } } diff --git a/deps/icu-small/source/i18n/numrange_impl.h b/deps/icu-small/source/i18n/numrange_impl.h index f88e300913642d..8f4c8a40ba2fdc 100644 --- a/deps/icu-small/source/i18n/numrange_impl.h +++ b/deps/icu-small/source/i18n/numrange_impl.h @@ -31,7 +31,7 @@ namespace impl { */ class UFormattedNumberRangeData : public FormattedValueStringBuilderImpl { public: - UFormattedNumberRangeData() : FormattedValueStringBuilderImpl(0) {} + UFormattedNumberRangeData() : FormattedValueStringBuilderImpl(kUndefinedField) {} virtual ~UFormattedNumberRangeData(); DecimalQuantity quantity1; diff --git a/deps/icu-small/source/i18n/numsys.cpp b/deps/icu-small/source/i18n/numsys.cpp index e3fe54bc1b3f7e..d8b901c0d74b68 100644 --- a/deps/icu-small/source/i18n/numsys.cpp +++ b/deps/icu-small/source/i18n/numsys.cpp @@ -118,7 +118,7 @@ NumberingSystem::createInstance(const Locale & inLocale, UErrorCode& status) { UBool nsResolved = TRUE; UBool usingFallback = FALSE; - char buffer[ULOC_KEYWORDS_CAPACITY]; + char buffer[ULOC_KEYWORDS_CAPACITY] = ""; int32_t count = inLocale.getKeywordValue("numbers", buffer, sizeof(buffer), status); if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) { // the "numbers" keyword exceeds ULOC_KEYWORDS_CAPACITY; ignore and use default. diff --git a/deps/icu-small/source/i18n/plurrule.cpp b/deps/icu-small/source/i18n/plurrule.cpp index aa950a51f0f0c6..54e3b2cd86c960 100644 --- a/deps/icu-small/source/i18n/plurrule.cpp +++ b/deps/icu-small/source/i18n/plurrule.cpp @@ -1693,6 +1693,7 @@ double FixedDecimal::getPluralOperand(PluralOperand operand) const { case PLURAL_OPERAND_F: return static_cast(decimalDigits); case PLURAL_OPERAND_T: return static_cast(decimalDigitsWithoutTrailingZeros); case PLURAL_OPERAND_V: return visibleDecimalDigitCount; + case PLURAL_OPERAND_E: return 0; default: UPRV_UNREACHABLE; // unexpected. } diff --git a/deps/icu-small/source/i18n/plurrule_impl.h b/deps/icu-small/source/i18n/plurrule_impl.h index f23ae168569d66..a18cb0847a840e 100644 --- a/deps/icu-small/source/i18n/plurrule_impl.h +++ b/deps/icu-small/source/i18n/plurrule_impl.h @@ -214,6 +214,12 @@ enum PluralOperand { */ PLURAL_OPERAND_W, + /** + * Suppressed exponent for compact notation (exponent needed in + * scientific notation with compact notation to approximate i). + */ + PLURAL_OPERAND_E, + /** * THIS OPERAND IS DEPRECATED AND HAS BEEN REMOVED FROM THE SPEC. * diff --git a/deps/icu-small/source/i18n/quantityformatter.cpp b/deps/icu-small/source/i18n/quantityformatter.cpp index e88b70fbd71795..9c9aa99b670944 100644 --- a/deps/icu-small/source/i18n/quantityformatter.cpp +++ b/deps/icu-small/source/i18n/quantityformatter.cpp @@ -204,7 +204,8 @@ void QuantityFormatter::formatAndSelect( if (U_FAILURE(status)) { return; } - output.append(result, UNUM_FIELD_COUNT, status); + // This code path is probably RBNF. Use the generic numeric field. + output.append(result, kGeneralNumericField, status); if (U_FAILURE(status)) { return; } diff --git a/deps/icu-small/source/i18n/regexcmp.cpp b/deps/icu-small/source/i18n/regexcmp.cpp index 3a6368b07afe73..7b67ce82b5db12 100644 --- a/deps/icu-small/source/i18n/regexcmp.cpp +++ b/deps/icu-small/source/i18n/regexcmp.cpp @@ -148,9 +148,6 @@ void RegexCompile::compile( if (U_FAILURE(*fStatus)) { return; } - fRXPat->fStaticSets = RegexStaticSets::gStaticSets->fPropSets; - fRXPat->fStaticSets8 = RegexStaticSets::gStaticSets->fPropSets8; - // Initialize the pattern scanning state machine fPatternLength = utext_nativeLength(pat); @@ -490,6 +487,12 @@ UBool RegexCompile::doParseActions(int32_t action) // If this is a named capture group, add the name->group number mapping. if (fCaptureName != NULL) { + if (!fRXPat->initNamedCaptureMap()) { + if (U_SUCCESS(*fStatus)) { + error(fRXPat->fDeferredStatus); + } + break; + } int32_t groupNumber = fRXPat->fGroupMap->size(); int32_t previousMapping = uhash_puti(fRXPat->fNamedCaptureMap, fCaptureName, groupNumber, fStatus); fCaptureName = NULL; // hash table takes ownership of the name (key) string. @@ -1251,11 +1254,14 @@ UBool RegexCompile::doParseActions(int32_t action) break; case doBackslashX: + #if UCONFIG_NO_BREAK_ITERATION==1 + // Grapheme Cluster Boundary requires ICU break iteration. + error(U_UNSUPPORTED_ERROR); + #endif fixLiterals(FALSE); appendOp(URX_BACKSLASH_X, 0); break; - case doBackslashZ: fixLiterals(FALSE); appendOp(URX_DOLLAR, 0); @@ -1345,7 +1351,8 @@ UBool RegexCompile::doParseActions(int32_t action) case doCompleteNamedBackRef: { - int32_t groupNumber = uhash_geti(fRXPat->fNamedCaptureMap, fCaptureName); + int32_t groupNumber = + fRXPat->fNamedCaptureMap ? uhash_geti(fRXPat->fNamedCaptureMap, fCaptureName) : 0; if (groupNumber == 0) { // Group name has not been defined. // Could be a forward reference. If we choose to support them at some @@ -1558,15 +1565,15 @@ UBool RegexCompile::doParseActions(int32_t action) case doSetBackslash_s: { UnicodeSet *set = (UnicodeSet *)fSetStack.peek(); - set->addAll(*RegexStaticSets::gStaticSets->fPropSets[URX_ISSPACE_SET]); + set->addAll(RegexStaticSets::gStaticSets->fPropSets[URX_ISSPACE_SET]); break; } case doSetBackslash_S: { UnicodeSet *set = (UnicodeSet *)fSetStack.peek(); - UnicodeSet SSet(*RegexStaticSets::gStaticSets->fPropSets[URX_ISSPACE_SET]); - SSet.complement(); + UnicodeSet SSet; + SSet.addAll(RegexStaticSets::gStaticSets->fPropSets[URX_ISSPACE_SET]).complement(); set->addAll(SSet); break; } @@ -1635,15 +1642,15 @@ UBool RegexCompile::doParseActions(int32_t action) case doSetBackslash_w: { UnicodeSet *set = (UnicodeSet *)fSetStack.peek(); - set->addAll(*RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET]); + set->addAll(RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET]); break; } case doSetBackslash_W: { UnicodeSet *set = (UnicodeSet *)fSetStack.peek(); - UnicodeSet SSet(*RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET]); - SSet.complement(); + UnicodeSet SSet; + SSet.addAll(RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET]).complement(); set->addAll(SSet); break; } @@ -2418,6 +2425,7 @@ void RegexCompile::compileSet(UnicodeSet *theSet) { // The set contains two or more chars. (the normal case) // Put it into the compiled pattern as a set. + theSet->freeze(); int32_t setNumber = fRXPat->fSets->size(); fRXPat->fSets->addElement(theSet, *fStatus); appendOp(URX_SETREF, setNumber); @@ -2811,8 +2819,8 @@ void RegexCompile::matchStartType() { if (currentLen == 0) { int32_t sn = URX_VAL(op); U_ASSERT(sn>0 && snfStaticSets[sn]; - fRXPat->fInitialChars->addAll(*s); + const UnicodeSet &s = RegexStaticSets::gStaticSets->fPropSets[sn]; + fRXPat->fInitialChars->addAll(s); numInitialStrings += 2; } currentLen = safeIncrement(currentLen, 1); @@ -2824,9 +2832,8 @@ void RegexCompile::matchStartType() { case URX_STAT_SETREF_N: if (currentLen == 0) { int32_t sn = URX_VAL(op); - const UnicodeSet *s = fRXPat->fStaticSets[sn]; - UnicodeSet sc(*s); - sc.complement(); + UnicodeSet sc; + sc.addAll(RegexStaticSets::gStaticSets->fPropSets[sn]).complement(); fRXPat->fInitialChars->addAll(sc); numInitialStrings += 2; } @@ -4413,7 +4420,8 @@ UnicodeSet *RegexCompile::createSetForProperty(const UnicodeString &propName, UB status = U_ZERO_ERROR; if (propName.caseCompare(u"word", -1, 0) == 0) { - set.adoptInsteadAndCheckErrorCode(new UnicodeSet(*(fRXPat->fStaticSets[URX_ISWORD_SET])), status); + set.adoptInsteadAndCheckErrorCode( + RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET].cloneAsThawed(), status); break; } if (propName.compare(u"all", -1) == 0) { diff --git a/deps/icu-small/source/i18n/regexcst.h b/deps/icu-small/source/i18n/regexcst.h index a07d85a277c3dd..526c253e3bcb8d 100644 --- a/deps/icu-small/source/i18n/regexcst.h +++ b/deps/icu-small/source/i18n/regexcst.h @@ -20,117 +20,117 @@ U_NAMESPACE_BEGIN // // Character classes for regex pattern scanning. // - static const uint8_t kRuleSet_ascii_letter = 128; - static const uint8_t kRuleSet_digit_char = 129; + static const uint8_t kRuleSet_digit_char = 128; + static const uint8_t kRuleSet_ascii_letter = 129; static const uint8_t kRuleSet_rule_char = 130; - + constexpr uint32_t kRuleSet_count = 131-128; enum Regex_PatternParseAction { - doSetBackslash_V, - doSetBackslash_h, - doBeginNamedBackRef, - doSetMatchMode, - doEnterQuoteMode, - doOpenCaptureParen, - doContinueNamedCapture, - doSetBackslash_d, - doBeginMatchMode, - doBackslashX, - doSetPosixProp, - doIntervalError, + doSetBackslash_D, + doBackslashh, + doBackslashH, doSetLiteralEscaped, - doSetBackslash_s, - doNOP, - doBackslashv, - doOpenLookBehind, - doPatStart, - doPossessiveInterval, - doOpenAtomicParen, doOpenLookAheadNeg, - doBackslashd, + doCompleteNamedBackRef, + doPatStart, + doBackslashS, + doBackslashD, + doNGStar, + doNOP, + doBackslashX, + doSetLiteral, + doContinueNamedCapture, + doBackslashG, + doBackslashR, + doSetBegin, + doSetBackslash_v, + doPossessivePlus, + doPerlInline, doBackslashZ, - doIntervalUpperDigit, - doBadNamedCapture, - doSetDifference2, doSetAddAmp, - doSetNamedChar, - doNamedChar, - doSetBackslash_H, - doBackslashb, - doBackslashz, doSetBeginDifference1, - doOpenLookAhead, - doMatchModeParen, - doBackslashV, - doIntevalLowerDigit, - doCaret, - doSetEnd, + doIntervalError, doSetNegate, - doBackslashS, - doOrOperator, - doBackslashB, - doBackslashw, - doBackslashR, + doIntervalInit, + doSetIntersection2, + doPossessiveInterval, doRuleError, - doDotAny, - doMatchMode, - doSetBackslash_W, - doNGPlus, - doSetBackslash_D, - doPossessiveOpt, - doSetNamedRange, + doBackslashW, + doContinueNamedBackRef, + doOpenNonCaptureParen, + doExit, + doSetNamedChar, + doSetBackslash_V, doConditionalExpr, - doBackslashs, + doEscapeError, + doBadOpenParenType, doPossessiveStar, + doSetAddDash, + doEscapedLiteralChar, + doSetBackslash_w, + doIntervalUpperDigit, + doBackslashv, + doSetBackslash_S, + doSetNoCloseError, + doSetProp, + doBackslashB, + doSetEnd, + doSetRange, + doMatchModeParen, doPlus, - doBadOpenParenType, + doBackslashV, + doSetMatchMode, + doBackslashz, + doSetNamedRange, + doOpenLookBehindNeg, + doInterval, + doBadNamedCapture, + doBeginMatchMode, + doBackslashd, + doPatFinish, + doNamedChar, + doNGPlus, + doSetDifference2, + doSetBackslash_H, doCloseParen, - doNGInterval, - doSetProp, + doDotAny, + doOpenCaptureParen, + doEnterQuoteMode, + doOpenAtomicParen, + doBadModeFlag, + doSetBackslash_d, + doSetFinish, + doProperty, + doBeginNamedBackRef, doBackRef, - doSetBeginUnion, - doEscapeError, doOpt, - doSetBeginIntersection1, - doPossessivePlus, - doBackslashD, - doOpenLookBehindNeg, - doSetBegin, - doSetIntersection2, - doCompleteNamedBackRef, - doSetRange, doDollar, - doBackslashH, - doExit, - doNGOpt, - doOpenNonCaptureParen, - doBackslashA, - doSetBackslash_v, - doBackslashh, - doBadModeFlag, - doSetNoCloseError, - doIntervalSame, - doSetAddDash, - doBackslashW, - doPerlInline, - doSetOpError, - doSetLiteral, - doPatFinish, doBeginNamedCapture, - doEscapedLiteralChar, + doNGInterval, + doSetOpError, + doSetPosixProp, + doSetBeginIntersection1, + doBackslashb, + doSetBeginUnion, + doIntevalLowerDigit, + doSetBackslash_h, + doStar, + doMatchMode, + doBackslashA, + doOpenLookBehind, + doPossessiveOpt, + doOrOperator, + doBackslashw, + doBackslashs, doLiteralChar, doSuppressComments, + doCaret, + doIntervalSame, + doNGOpt, + doOpenLookAhead, + doSetBackslash_W, doMismatchedParenErr, - doNGStar, - doSetFinish, - doInterval, - doBackslashG, - doStar, - doSetBackslash_w, - doSetBackslash_S, - doProperty, - doContinueNamedBackRef, - doIntervalInit, + doSetBackslash_s, rbbiLastAction}; //------------------------------------------------------------------------------- @@ -197,7 +197,7 @@ static const struct RegexTableEl gRuleParseStateTable[] = { , {doBadOpenParenType, 255, 206,0, FALSE} // 45 , {doOpenLookBehind, 61 /* = */, 2, 20, TRUE} // 46 open-paren-lookbehind , {doOpenLookBehindNeg, 33 /* ! */, 2, 20, TRUE} // 47 - , {doBeginNamedCapture, 128, 64,0, FALSE} // 48 + , {doBeginNamedCapture, 129, 64,0, FALSE} // 48 , {doBadOpenParenType, 255, 206,0, FALSE} // 49 , {doNOP, 41 /* ) */, 255,0, TRUE} // 50 paren-comment , {doMismatchedParenErr, 253, 206,0, FALSE} // 51 @@ -213,8 +213,8 @@ static const struct RegexTableEl gRuleParseStateTable[] = { , {doSetMatchMode, 41 /* ) */, 2,0, TRUE} // 61 , {doMatchModeParen, 58 /* : */, 2, 14, TRUE} // 62 , {doBadModeFlag, 255, 206,0, FALSE} // 63 - , {doContinueNamedCapture, 128, 64,0, TRUE} // 64 named-capture - , {doContinueNamedCapture, 129, 64,0, TRUE} // 65 + , {doContinueNamedCapture, 129, 64,0, TRUE} // 64 named-capture + , {doContinueNamedCapture, 128, 64,0, TRUE} // 65 , {doOpenCaptureParen, 62 /* > */, 2, 14, TRUE} // 66 , {doBadNamedCapture, 255, 206,0, FALSE} // 67 , {doNGStar, 63 /* ? */, 20,0, TRUE} // 68 quant-star @@ -226,13 +226,13 @@ static const struct RegexTableEl gRuleParseStateTable[] = { , {doNGOpt, 63 /* ? */, 20,0, TRUE} // 74 quant-opt , {doPossessiveOpt, 43 /* + */, 20,0, TRUE} // 75 , {doOpt, 255, 20,0, FALSE} // 76 - , {doNOP, 129, 79,0, FALSE} // 77 interval-open + , {doNOP, 128, 79,0, FALSE} // 77 interval-open , {doIntervalError, 255, 206,0, FALSE} // 78 - , {doIntevalLowerDigit, 129, 79,0, TRUE} // 79 interval-lower + , {doIntevalLowerDigit, 128, 79,0, TRUE} // 79 interval-lower , {doNOP, 44 /* , */, 83,0, TRUE} // 80 , {doIntervalSame, 125 /* } */, 86,0, TRUE} // 81 , {doIntervalError, 255, 206,0, FALSE} // 82 - , {doIntervalUpperDigit, 129, 83,0, TRUE} // 83 interval-upper + , {doIntervalUpperDigit, 128, 83,0, TRUE} // 83 interval-upper , {doNOP, 125 /* } */, 86,0, TRUE} // 84 , {doIntervalError, 255, 206,0, FALSE} // 85 , {doNGInterval, 63 /* ? */, 20,0, TRUE} // 86 interval-type @@ -261,15 +261,15 @@ static const struct RegexTableEl gRuleParseStateTable[] = { , {doBackslashX, 88 /* X */, 14,0, TRUE} // 109 , {doBackslashZ, 90 /* Z */, 2,0, TRUE} // 110 , {doBackslashz, 122 /* z */, 2,0, TRUE} // 111 - , {doBackRef, 129, 14,0, TRUE} // 112 + , {doBackRef, 128, 14,0, TRUE} // 112 , {doEscapeError, 253, 206,0, FALSE} // 113 , {doEscapedLiteralChar, 255, 14,0, TRUE} // 114 , {doBeginNamedBackRef, 60 /* < */, 117,0, TRUE} // 115 named-backref , {doBadNamedCapture, 255, 206,0, FALSE} // 116 - , {doContinueNamedBackRef, 128, 119,0, TRUE} // 117 named-backref-2 + , {doContinueNamedBackRef, 129, 119,0, TRUE} // 117 named-backref-2 , {doBadNamedCapture, 255, 206,0, FALSE} // 118 - , {doContinueNamedBackRef, 128, 119,0, TRUE} // 119 named-backref-3 - , {doContinueNamedBackRef, 129, 119,0, TRUE} // 120 + , {doContinueNamedBackRef, 129, 119,0, TRUE} // 119 named-backref-3 + , {doContinueNamedBackRef, 128, 119,0, TRUE} // 120 , {doCompleteNamedBackRef, 62 /* > */, 14,0, TRUE} // 121 , {doBadNamedCapture, 255, 206,0, FALSE} // 122 , {doSetNegate, 94 /* ^ */, 126,0, TRUE} // 123 set-open diff --git a/deps/icu-small/source/i18n/regexcst.pl b/deps/icu-small/source/i18n/regexcst.pl index 6c06b4eb5fc56a..3ae259048aec43 100755 --- a/deps/icu-small/source/i18n/regexcst.pl +++ b/deps/icu-small/source/i18n/regexcst.pl @@ -10,13 +10,13 @@ # regexcst.pl # Compile the regular expression paser state table data into initialized C data. # Usage: -# cd icu/source/i18n +# cd icu4c/source/i18n # perl regexcst.pl < regexcst.txt > regexcst.h # # The output file, regexcst.h, is included by some of the .cpp regex # implementation files. This perl script is NOT run as part # of a normal ICU build. It is run by hand when needed, and the -# regexcst.h generated file is put back into cvs. +# regexcst.h generated file is put back into the source code repository. # # See regexcst.txt for a description of the input format for this script. # @@ -201,6 +201,8 @@ die if ($errors>0); +print "// © 2016 and later: Unicode, Inc. and others.\n"; +print "// License & terms of use: http://www.unicode.org/copyright.html\n"; print "//---------------------------------------------------------------------------------\n"; print "//\n"; print "// Generated Header File. Do not edit by hand.\n"; @@ -246,6 +248,7 @@ $i++; } } +print " constexpr uint32_t kRuleSet_count = $i-128;"; print "\n\n"; # diff --git a/deps/icu-small/source/i18n/regexst.cpp b/deps/icu-small/source/i18n/regexst.cpp index ad74ee508e7133..7e3992fc80339d 100644 --- a/deps/icu-small/source/i18n/regexst.cpp +++ b/deps/icu-small/source/i18n/regexst.cpp @@ -35,216 +35,101 @@ // generated by a Perl script. #include "regexst.h" - - U_NAMESPACE_BEGIN +// "Rule Char" Characters are those with special meaning, and therefore +// need to be escaped to appear as literals in a regexp. +constexpr char16_t const *gRuleSet_rule_chars = u"*?+[(){}^$|\\."; -//------------------------------------------------------------------------------ // -// Unicode Set pattern strings for all of the required constant sets. -// Initialized with hex values for portability to EBCDIC based machines. -// Really ugly, but there's no good way to avoid it. +// The backslash escape characters that ICU's unescape() function will handle. // -//------------------------------------------------------------------------------ - -// "Rule Char" Characters are those with no special meaning, and therefore do not -// need to be escaped to appear as literals in a regexp. Expressed -// as the inverse of those needing escaping -- [^\*\?\+\[\(\)\{\}\^\$\|\\\.] -static const UChar gRuleSet_rule_char_pattern[] = { - // [ ^ \ * \ ? \ + \ [ \ ( / ) - 0x5b, 0x5e, 0x5c, 0x2a, 0x5c, 0x3f, 0x5c, 0x2b, 0x5c, 0x5b, 0x5c, 0x28, 0x5c, 0x29, - // \ { \ } \ ^ \ $ \ | \ \ \ . ] - 0x5c, 0x7b,0x5c, 0x7d, 0x5c, 0x5e, 0x5c, 0x24, 0x5c, 0x7c, 0x5c, 0x5c, 0x5c, 0x2e, 0x5d, 0}; +constexpr char16_t const *gUnescapeChars = u"acefnrtuUx"; // -// Here are the backslash escape characters that ICU's unescape() function -// will handle. +// Unicode Set pattern for Regular Expression \w // -static const UChar gUnescapeCharPattern[] = { -// [ a c e f n r t u U x ] - 0x5b, 0x61, 0x63, 0x65, 0x66, 0x6e, 0x72, 0x74, 0x75, 0x55, 0x78, 0x5d, 0}; - - -// -// Unicode Set Definitions for Regular Expression \w -// -static const UChar gIsWordPattern[] = { -// [ \ p { A l p h a b e t i c } - 0x5b, 0x5c, 0x70, 0x7b, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x65, 0x74, 0x69, 0x63, 0x7d, -// \ p { M } Mark - 0x5c, 0x70, 0x7b, 0x4d, 0x7d, -// \ p { N d } Digit_Numeric - 0x5c, 0x70, 0x7b, 0x4e, 0x64, 0x7d, -// \ p { P c } Connector_Punctuation - 0x5c, 0x70, 0x7b, 0x50, 0x63, 0x7d, -// \ u 2 0 0 c \ u 2 0 0 d ] - 0x5c, 0x75, 0x32, 0x30, 0x30, 0x63, 0x5c, 0x75, 0x32, 0x30, 0x30, 0x64, 0x5d, 0}; - +constexpr char16_t const *gIsWordPattern = u"[\\p{Alphabetic}\\p{M}\\p{Nd}\\p{Pc}\\u200c\\u200d]"; // // Unicode Set Definitions for Regular Expression \s // -static const UChar gIsSpacePattern[] = { -// [ \ p { W h i t e S p a c e } ] - 0x5b, 0x5c, 0x70, 0x7b, 0x57, 0x68, 0x69, 0x74, 0x65, 0x53, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x5d, 0}; - +constexpr char16_t const *gIsSpacePattern = u"[\\p{WhiteSpace}]"; // // UnicodeSets used in implementation of Grapheme Cluster detection, \X // -static const UChar gGC_ControlPattern[] = { -// [ [ : Z l : ] [ : Z p : ] - 0x5b, 0x5b, 0x3a, 0x5A, 0x6c, 0x3a, 0x5d, 0x5b, 0x3a, 0x5A, 0x70, 0x3a, 0x5d, -// [ : C c : ] [ : C f : ] - - 0x5b, 0x3a, 0x43, 0x63, 0x3a, 0x5d, 0x5b, 0x3a, 0x43, 0x66, 0x3a, 0x5d, 0x2d, -// [ : G r a p h e m e _ - 0x5b, 0x3a, 0x47, 0x72, 0x61, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x5f, -// E x t e n d : ] ] - 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x3a, 0x5d, 0x5d, 0}; +constexpr char16_t const *gGC_ControlPattern = u"[[:Zl:][:Zp:][:Cc:][:Cf:]-[:Grapheme_Extend:]]"; +constexpr char16_t const *gGC_ExtendPattern = u"[\\p{Grapheme_Extend}]"; +constexpr char16_t const *gGC_LPattern = u"[\\p{Hangul_Syllable_Type=L}]"; +constexpr char16_t const *gGC_VPattern = u"[\\p{Hangul_Syllable_Type=V}]"; +constexpr char16_t const *gGC_TPattern = u"[\\p{Hangul_Syllable_Type=T}]"; +constexpr char16_t const *gGC_LVPattern = u"[\\p{Hangul_Syllable_Type=LV}]"; +constexpr char16_t const *gGC_LVTPattern = u"[\\p{Hangul_Syllable_Type=LVT}]"; -static const UChar gGC_ExtendPattern[] = { -// [ \ p { G r a p h e m e _ - 0x5b, 0x5c, 0x70, 0x7b, 0x47, 0x72, 0x61, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x5f, -// E x t e n d } ] - 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x7d, 0x5d, 0}; -static const UChar gGC_LPattern[] = { -// [ \ p { H a n g u l _ S y l - 0x5b, 0x5c, 0x70, 0x7b, 0x48, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x5f, 0x53, 0x79, 0x6c, -// l a b l e _ T y p e = L } ] - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x54, 0x79, 0x70, 0x65, 0x3d, 0x4c, 0x7d, 0x5d, 0}; - -static const UChar gGC_VPattern[] = { -// [ \ p { H a n g u l _ S y l - 0x5b, 0x5c, 0x70, 0x7b, 0x48, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x5f, 0x53, 0x79, 0x6c, -// l a b l e _ T y p e = V } ] - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x54, 0x79, 0x70, 0x65, 0x3d, 0x56, 0x7d, 0x5d, 0}; - -static const UChar gGC_TPattern[] = { -// [ \ p { H a n g u l _ S y l - 0x5b, 0x5c, 0x70, 0x7b, 0x48, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x5f, 0x53, 0x79, 0x6c, -// l a b l e _ T y p e = T } ] - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x54, 0x79, 0x70, 0x65, 0x3d, 0x54, 0x7d, 0x5d, 0}; - -static const UChar gGC_LVPattern[] = { -// [ \ p { H a n g u l _ S y l - 0x5b, 0x5c, 0x70, 0x7b, 0x48, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x5f, 0x53, 0x79, 0x6c, -// l a b l e _ T y p e = L V } ] - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x54, 0x79, 0x70, 0x65, 0x3d, 0x4c, 0x56, 0x7d, 0x5d, 0}; - -static const UChar gGC_LVTPattern[] = { -// [ \ p { H a n g u l _ S y l - 0x5b, 0x5c, 0x70, 0x7b, 0x48, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x5f, 0x53, 0x79, 0x6c, -// l a b l e _ T y p e = L V T } ] - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x54, 0x79, 0x70, 0x65, 0x3d, 0x4c, 0x56, 0x54, 0x7d, 0x5d, 0}; - - -RegexStaticSets *RegexStaticSets::gStaticSets = NULL; +RegexStaticSets *RegexStaticSets::gStaticSets = nullptr; UInitOnce gStaticSetsInitOnce = U_INITONCE_INITIALIZER; -RegexStaticSets::RegexStaticSets(UErrorCode *status) -: -fUnescapeCharSet(UnicodeString(TRUE, gUnescapeCharPattern, -1), *status), -fRuleDigitsAlias(NULL), -fEmptyText(NULL) -{ - // First zero out everything - int i; - for (i=0; iremove(0xac00, 0xd7a4); - fPropSets[URX_GC_NORMAL]->removeAll(*fPropSets[URX_GC_CONTROL]); - fPropSets[URX_GC_NORMAL]->removeAll(*fPropSets[URX_GC_L]); - fPropSets[URX_GC_NORMAL]->removeAll(*fPropSets[URX_GC_V]); - fPropSets[URX_GC_NORMAL]->removeAll(*fPropSets[URX_GC_T]); + fPropSets[URX_GC_NORMAL].complement(); + fPropSets[URX_GC_NORMAL].remove(0xac00, 0xd7a4); + fPropSets[URX_GC_NORMAL].removeAll(fPropSets[URX_GC_CONTROL]); + fPropSets[URX_GC_NORMAL].removeAll(fPropSets[URX_GC_L]); + fPropSets[URX_GC_NORMAL].removeAll(fPropSets[URX_GC_V]); + fPropSets[URX_GC_NORMAL].removeAll(fPropSets[URX_GC_T]); + fPropSets[URX_GC_NORMAL].freeze(); // Initialize the 8-bit fast bit sets from the parallel full // UnicodeSets. - for (i=0; icompact(); - fPropSets8[i].init(fPropSets[i]); - } + // + // TODO: 25 Oct 2019 are these fast 8-bit sets worth keeping? + // Measured 3.5% gain on (non) matching with the pattern "x(?:\\S+)+x" + // This runs in exponential time, making it easy to adjust the time for + // convenient measuring. + // + // This 8 bit optimization dates from the early days of ICU, + // with a less optimized UnicodeSet. At the time, the difference + // was substantial. + + for (int32_t i=0; i::crea -static constexpr number::impl::Field kRDTNumericField - = StringBuilderFieldUtils::compress(); +static constexpr FormattedStringBuilder::Field kRDTNumericField + = {UFIELD_CATEGORY_RELATIVE_DATETIME, UDAT_REL_NUMERIC_FIELD}; -static constexpr number::impl::Field kRDTLiteralField - = StringBuilderFieldUtils::compress(); +static constexpr FormattedStringBuilder::Field kRDTLiteralField + = {UFIELD_CATEGORY_RELATIVE_DATETIME, UDAT_REL_LITERAL_FIELD}; class FormattedRelativeDateTimeData : public FormattedValueStringBuilderImpl { public: diff --git a/deps/icu-small/source/i18n/rematch.cpp b/deps/icu-small/source/i18n/rematch.cpp index d9af2b3ddaa77e..123aa8602ba474 100644 --- a/deps/icu-small/source/i18n/rematch.cpp +++ b/deps/icu-small/source/i18n/rematch.cpp @@ -177,6 +177,7 @@ RegexMatcher::~RegexMatcher() { #if UCONFIG_NO_BREAK_ITERATION==0 delete fWordBreakItr; + delete fGCBreakItr; #endif } @@ -222,6 +223,7 @@ void RegexMatcher::init(UErrorCode &status) { fDeferredStatus = status; fData = fSmallData; fWordBreakItr = NULL; + fGCBreakItr = NULL; fStack = NULL; fInputText = NULL; @@ -429,7 +431,7 @@ RegexMatcher &RegexMatcher::appendReplacement(UText *dest, (nextChar >= 0x31 && nextChar <= 0x39)) { // 0..9 groupName.append(nextChar); } else if (nextChar == RIGHTBRACKET) { - groupNum = uhash_geti(fPattern->fNamedCaptureMap, &groupName); + groupNum = fPattern->fNamedCaptureMap ? uhash_geti(fPattern->fNamedCaptureMap, &groupName) : 0; if (groupNum == 0) { status = U_REGEX_INVALID_CAPTURE_GROUP_NAME; } @@ -1854,12 +1856,15 @@ RegexMatcher &RegexMatcher::reset(const UnicodeString &input) { // This is for compatibility for those clients who modify the input string "live" during regex operations. fInputUniStrMaybeMutable = TRUE; - if (fWordBreakItr != NULL) { #if UCONFIG_NO_BREAK_ITERATION==0 - UErrorCode status = U_ZERO_ERROR; - fWordBreakItr->setText(fInputText, status); -#endif + if (fWordBreakItr) { + fWordBreakItr->setText(fInputText, fDeferredStatus); } + if (fGCBreakItr) { + fGCBreakItr->setText(fInputText, fDeferredStatus); + } +#endif + return *this; } @@ -1876,12 +1881,14 @@ RegexMatcher &RegexMatcher::reset(UText *input) { delete fInput; fInput = NULL; - if (fWordBreakItr != NULL) { #if UCONFIG_NO_BREAK_ITERATION==0 - UErrorCode status = U_ZERO_ERROR; - fWordBreakItr->setText(input, status); -#endif + if (fWordBreakItr) { + fWordBreakItr->setText(input, fDeferredStatus); + } + if (fGCBreakItr) { + fGCBreakItr->setText(fInputText, fDeferredStatus); } +#endif } reset(); fInputUniStrMaybeMutable = FALSE; @@ -2542,7 +2549,7 @@ UBool RegexMatcher::isWordBoundary(int64_t pos) { // Current char is a combining one. Not a boundary. return FALSE; } - cIsWord = fPattern->fStaticSets[URX_ISWORD_SET]->contains(c); + cIsWord = RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET].contains(c); } // Back up until we come to a non-combining char, determine whether @@ -2555,7 +2562,7 @@ UBool RegexMatcher::isWordBoundary(int64_t pos) { UChar32 prevChar = UTEXT_PREVIOUS32(fInputText); if (!(u_hasBinaryProperty(prevChar, UCHAR_GRAPHEME_EXTEND) || u_charType(prevChar) == U_FORMAT_CHAR)) { - prevCIsWord = fPattern->fStaticSets[URX_ISWORD_SET]->contains(prevChar); + prevCIsWord = RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET].contains(prevChar); break; } } @@ -2580,7 +2587,7 @@ UBool RegexMatcher::isChunkWordBoundary(int32_t pos) { // Current char is a combining one. Not a boundary. return FALSE; } - cIsWord = fPattern->fStaticSets[URX_ISWORD_SET]->contains(c); + cIsWord = RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET].contains(c); } // Back up until we come to a non-combining char, determine whether @@ -2594,7 +2601,7 @@ UBool RegexMatcher::isChunkWordBoundary(int32_t pos) { U16_PREV(inputBuf, fLookStart, pos, prevChar); if (!(u_hasBinaryProperty(prevChar, UCHAR_GRAPHEME_EXTEND) || u_charType(prevChar) == U_FORMAT_CHAR)) { - prevCIsWord = fPattern->fStaticSets[URX_ISWORD_SET]->contains(prevChar); + prevCIsWord = RegexStaticSets::gStaticSets->fPropSets[URX_ISWORD_SET].contains(prevChar); break; } } @@ -2611,37 +2618,60 @@ UBool RegexMatcher::isChunkWordBoundary(int32_t pos) { // parameters: pos - the current position in the input buffer // //-------------------------------------------------------------------------------- -UBool RegexMatcher::isUWordBoundary(int64_t pos) { +UBool RegexMatcher::isUWordBoundary(int64_t pos, UErrorCode &status) { UBool returnVal = FALSE; + #if UCONFIG_NO_BREAK_ITERATION==0 + // Note: this point will never be reached if break iteration is configured out. + // Regex patterns that would require this function will fail to compile. // If we haven't yet created a break iterator for this matcher, do it now. - if (fWordBreakItr == NULL) { - fWordBreakItr = - (RuleBasedBreakIterator *)BreakIterator::createWordInstance(Locale::getEnglish(), fDeferredStatus); - if (U_FAILURE(fDeferredStatus)) { + if (fWordBreakItr == nullptr) { + fWordBreakItr = BreakIterator::createWordInstance(Locale::getEnglish(), status); + if (U_FAILURE(status)) { return FALSE; } - fWordBreakItr->setText(fInputText, fDeferredStatus); + fWordBreakItr->setText(fInputText, status); } + // Note: zero width boundary tests like \b see through transparent region bounds, + // which is why fLookLimit is used here, rather than fActiveLimit. if (pos >= fLookLimit) { fHitEnd = TRUE; returnVal = TRUE; // With Unicode word rules, only positions within the interior of "real" // words are not boundaries. All non-word chars stand by themselves, // with word boundaries on both sides. } else { - if (!UTEXT_USES_U16(fInputText)) { - // !!!: Would like a better way to do this! - UErrorCode status = U_ZERO_ERROR; - pos = utext_extract(fInputText, 0, pos, NULL, 0, &status); - } returnVal = fWordBreakItr->isBoundary((int32_t)pos); } #endif return returnVal; } + +int64_t RegexMatcher::followingGCBoundary(int64_t pos, UErrorCode &status) { + int64_t result = pos; + +#if UCONFIG_NO_BREAK_ITERATION==0 + // Note: this point will never be reached if break iteration is configured out. + // Regex patterns that would require this function will fail to compile. + + // If we haven't yet created a break iterator for this matcher, do it now. + if (fGCBreakItr == nullptr) { + fGCBreakItr = BreakIterator::createCharacterInstance(Locale::getEnglish(), status); + if (U_FAILURE(status)) { + return pos; + } + fGCBreakItr->setText(fInputText, status); + } + result = fGCBreakItr->following(pos); + if (result == BreakIterator::DONE) { + result = pos; + } +#endif + return result; +} + //-------------------------------------------------------------------------------- // // IncrementTime This function is called once each TIMER_INITIAL_VALUE state @@ -3082,7 +3112,7 @@ void RegexMatcher::MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status) { case URX_BACKSLASH_BU: // Test for word boundaries, Unicode-style { - UBool success = isUWordBoundary(fp->fInputIdx); + UBool success = isUWordBoundary(fp->fInputIdx, status); success ^= (UBool)(opValue != 0); // flip sense for \B if (!success) { fp = (REStackFrame *)fStack->popFrame(fFrameSize); @@ -3184,99 +3214,21 @@ void RegexMatcher::MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status) { case URX_BACKSLASH_X: - // Match a Grapheme, as defined by Unicode TR 29. - // Differs slightly from Perl, which consumes combining marks independently - // of context. - { - - // Fail if at end of input - if (fp->fInputIdx >= fActiveLimit) { - fHitEnd = TRUE; - fp = (REStackFrame *)fStack->popFrame(fFrameSize); - break; - } - - UTEXT_SETNATIVEINDEX(fInputText, fp->fInputIdx); + // Match a Grapheme, as defined by Unicode UAX 29. - // Examine (and consume) the current char. - // Dispatch into a little state machine, based on the char. - UChar32 c; - c = UTEXT_NEXT32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - UnicodeSet **sets = fPattern->fStaticSets; - if (sets[URX_GC_NORMAL]->contains(c)) goto GC_Extend; - if (sets[URX_GC_CONTROL]->contains(c)) goto GC_Control; - if (sets[URX_GC_L]->contains(c)) goto GC_L; - if (sets[URX_GC_LV]->contains(c)) goto GC_V; - if (sets[URX_GC_LVT]->contains(c)) goto GC_T; - if (sets[URX_GC_V]->contains(c)) goto GC_V; - if (sets[URX_GC_T]->contains(c)) goto GC_T; - goto GC_Extend; - - - -GC_L: - if (fp->fInputIdx >= fActiveLimit) goto GC_Done; - c = UTEXT_NEXT32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - if (sets[URX_GC_L]->contains(c)) goto GC_L; - if (sets[URX_GC_LV]->contains(c)) goto GC_V; - if (sets[URX_GC_LVT]->contains(c)) goto GC_T; - if (sets[URX_GC_V]->contains(c)) goto GC_V; - (void)UTEXT_PREVIOUS32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - goto GC_Extend; - -GC_V: - if (fp->fInputIdx >= fActiveLimit) goto GC_Done; - c = UTEXT_NEXT32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - if (sets[URX_GC_V]->contains(c)) goto GC_V; - if (sets[URX_GC_T]->contains(c)) goto GC_T; - (void)UTEXT_PREVIOUS32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - goto GC_Extend; - -GC_T: - if (fp->fInputIdx >= fActiveLimit) goto GC_Done; - c = UTEXT_NEXT32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - if (sets[URX_GC_T]->contains(c)) goto GC_T; - (void)UTEXT_PREVIOUS32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - goto GC_Extend; - -GC_Extend: - // Combining characters are consumed here - for (;;) { - if (fp->fInputIdx >= fActiveLimit) { - break; - } - c = UTEXT_CURRENT32(fInputText); - if (sets[URX_GC_EXTEND]->contains(c) == FALSE) { - break; - } - (void)UTEXT_NEXT32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - } - goto GC_Done; - -GC_Control: - // Most control chars stand alone (don't combine with combining chars), - // except for that CR/LF sequence is a single grapheme cluster. - if (c == 0x0d && fp->fInputIdx < fActiveLimit && UTEXT_CURRENT32(fInputText) == 0x0a) { - c = UTEXT_NEXT32(fInputText); - fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); - } - -GC_Done: - if (fp->fInputIdx >= fActiveLimit) { - fHitEnd = TRUE; - } + // Fail if at end of input + if (fp->fInputIdx >= fActiveLimit) { + fHitEnd = TRUE; + fp = (REStackFrame *)fStack->popFrame(fFrameSize); break; } - + fp->fInputIdx = followingGCBoundary(fp->fInputIdx, status); + if (fp->fInputIdx >= fActiveLimit) { + fHitEnd = TRUE; + fp->fInputIdx = fActiveLimit; + } + break; case URX_BACKSLASH_Z: // Test for end of Input @@ -3310,13 +3262,13 @@ void RegexMatcher::MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status) { UTEXT_SETNATIVEINDEX(fInputText, fp->fInputIdx); UChar32 c = UTEXT_NEXT32(fInputText); if (c < 256) { - Regex8BitSet *s8 = &fPattern->fStaticSets8[opValue]; - if (s8->contains(c)) { + Regex8BitSet &s8 = RegexStaticSets::gStaticSets->fPropSets8[opValue]; + if (s8.contains(c)) { success = !success; } } else { - const UnicodeSet *s = fPattern->fStaticSets[opValue]; - if (s->contains(c)) { + const UnicodeSet &s = RegexStaticSets::gStaticSets->fPropSets[opValue]; + if (s.contains(c)) { success = !success; } } @@ -3346,14 +3298,14 @@ void RegexMatcher::MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status) { UChar32 c = UTEXT_NEXT32(fInputText); if (c < 256) { - Regex8BitSet *s8 = &fPattern->fStaticSets8[opValue]; - if (s8->contains(c) == FALSE) { + Regex8BitSet &s8 = RegexStaticSets::gStaticSets->fPropSets8[opValue]; + if (s8.contains(c) == FALSE) { fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); break; } } else { - const UnicodeSet *s = fPattern->fStaticSets[opValue]; - if (s->contains(c) == FALSE) { + const UnicodeSet &s = RegexStaticSets::gStaticSets->fPropSets[opValue]; + if (s.contains(c) == FALSE) { fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); break; } @@ -4662,7 +4614,7 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu case URX_BACKSLASH_BU: // Test for word boundaries, Unicode-style { - UBool success = isUWordBoundary(fp->fInputIdx); + UBool success = isUWordBoundary(fp->fInputIdx, status); success ^= (UBool)(opValue != 0); // flip sense for \B if (!success) { fp = (REStackFrame *)fStack->popFrame(fFrameSize); @@ -4760,12 +4712,8 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu break; - case URX_BACKSLASH_X: - // Match a Grapheme, as defined by Unicode TR 29. - // Differs slightly from Perl, which consumes combining marks independently - // of context. - { + // Match a Grapheme, as defined by Unicode UAX 29. // Fail if at end of input if (fp->fInputIdx >= fActiveLimit) { @@ -4774,76 +4722,12 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu break; } - // Examine (and consume) the current char. - // Dispatch into a little state machine, based on the char. - UChar32 c; - U16_NEXT(inputBuf, fp->fInputIdx, fActiveLimit, c); - UnicodeSet **sets = fPattern->fStaticSets; - if (sets[URX_GC_NORMAL]->contains(c)) goto GC_Extend; - if (sets[URX_GC_CONTROL]->contains(c)) goto GC_Control; - if (sets[URX_GC_L]->contains(c)) goto GC_L; - if (sets[URX_GC_LV]->contains(c)) goto GC_V; - if (sets[URX_GC_LVT]->contains(c)) goto GC_T; - if (sets[URX_GC_V]->contains(c)) goto GC_V; - if (sets[URX_GC_T]->contains(c)) goto GC_T; - goto GC_Extend; - - - -GC_L: - if (fp->fInputIdx >= fActiveLimit) goto GC_Done; - U16_NEXT(inputBuf, fp->fInputIdx, fActiveLimit, c); - if (sets[URX_GC_L]->contains(c)) goto GC_L; - if (sets[URX_GC_LV]->contains(c)) goto GC_V; - if (sets[URX_GC_LVT]->contains(c)) goto GC_T; - if (sets[URX_GC_V]->contains(c)) goto GC_V; - U16_PREV(inputBuf, 0, fp->fInputIdx, c); - goto GC_Extend; - -GC_V: - if (fp->fInputIdx >= fActiveLimit) goto GC_Done; - U16_NEXT(inputBuf, fp->fInputIdx, fActiveLimit, c); - if (sets[URX_GC_V]->contains(c)) goto GC_V; - if (sets[URX_GC_T]->contains(c)) goto GC_T; - U16_PREV(inputBuf, 0, fp->fInputIdx, c); - goto GC_Extend; - -GC_T: - if (fp->fInputIdx >= fActiveLimit) goto GC_Done; - U16_NEXT(inputBuf, fp->fInputIdx, fActiveLimit, c); - if (sets[URX_GC_T]->contains(c)) goto GC_T; - U16_PREV(inputBuf, 0, fp->fInputIdx, c); - goto GC_Extend; - -GC_Extend: - // Combining characters are consumed here - for (;;) { - if (fp->fInputIdx >= fActiveLimit) { - break; - } - U16_NEXT(inputBuf, fp->fInputIdx, fActiveLimit, c); - if (sets[URX_GC_EXTEND]->contains(c) == FALSE) { - U16_BACK_1(inputBuf, 0, fp->fInputIdx); - break; - } - } - goto GC_Done; - -GC_Control: - // Most control chars stand alone (don't combine with combining chars), - // except for that CR/LF sequence is a single grapheme cluster. - if (c == 0x0d && fp->fInputIdx < fActiveLimit && inputBuf[fp->fInputIdx] == 0x0a) { - fp->fInputIdx++; - } - -GC_Done: + fp->fInputIdx = followingGCBoundary(fp->fInputIdx, status); if (fp->fInputIdx >= fActiveLimit) { fHitEnd = TRUE; + fp->fInputIdx = fActiveLimit; } break; - } - - case URX_BACKSLASH_Z: // Test for end of Input @@ -4877,13 +4761,13 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu UChar32 c; U16_NEXT(inputBuf, fp->fInputIdx, fActiveLimit, c); if (c < 256) { - Regex8BitSet *s8 = &fPattern->fStaticSets8[opValue]; - if (s8->contains(c)) { + Regex8BitSet &s8 = RegexStaticSets::gStaticSets->fPropSets8[opValue]; + if (s8.contains(c)) { success = !success; } } else { - const UnicodeSet *s = fPattern->fStaticSets[opValue]; - if (s->contains(c)) { + const UnicodeSet &s = RegexStaticSets::gStaticSets->fPropSets[opValue]; + if (s.contains(c)) { success = !success; } } @@ -4909,13 +4793,13 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu UChar32 c; U16_NEXT(inputBuf, fp->fInputIdx, fActiveLimit, c); if (c < 256) { - Regex8BitSet *s8 = &fPattern->fStaticSets8[opValue]; - if (s8->contains(c) == FALSE) { + Regex8BitSet &s8 = RegexStaticSets::gStaticSets->fPropSets8[opValue]; + if (s8.contains(c) == FALSE) { break; } } else { - const UnicodeSet *s = fPattern->fStaticSets[opValue]; - if (s->contains(c) == FALSE) { + const UnicodeSet &s = RegexStaticSets::gStaticSets->fPropSets[opValue]; + if (s.contains(c) == FALSE) { break; } } diff --git a/deps/icu-small/source/i18n/repattrn.cpp b/deps/icu-small/source/i18n/repattrn.cpp index 6976056dc1f6e4..34886624891f49 100644 --- a/deps/icu-small/source/i18n/repattrn.cpp +++ b/deps/icu-small/source/i18n/repattrn.cpp @@ -97,8 +97,6 @@ RegexPattern &RegexPattern::operator = (const RegexPattern &other) { fMinMatchLen = other.fMinMatchLen; fFrameSize = other.fFrameSize; fDataSize = other.fDataSize; - fStaticSets = other.fStaticSets; - fStaticSets8 = other.fStaticSets8; fStartType = other.fStartType; fInitialStringIdx = other.fInitialStringIdx; @@ -138,18 +136,20 @@ RegexPattern &RegexPattern::operator = (const RegexPattern &other) { } // Copy the named capture group hash map. - int32_t hashPos = UHASH_FIRST; - while (const UHashElement *hashEl = uhash_nextElement(other.fNamedCaptureMap, &hashPos)) { - if (U_FAILURE(fDeferredStatus)) { - break; - } - const UnicodeString *name = (const UnicodeString *)hashEl->key.pointer; - UnicodeString *key = new UnicodeString(*name); - int32_t val = hashEl->value.integer; - if (key == NULL) { - fDeferredStatus = U_MEMORY_ALLOCATION_ERROR; - } else { - uhash_puti(fNamedCaptureMap, key, val, &fDeferredStatus); + if (other.fNamedCaptureMap != nullptr && initNamedCaptureMap()) { + int32_t hashPos = UHASH_FIRST; + while (const UHashElement *hashEl = uhash_nextElement(other.fNamedCaptureMap, &hashPos)) { + if (U_FAILURE(fDeferredStatus)) { + break; + } + const UnicodeString *name = (const UnicodeString *)hashEl->key.pointer; + UnicodeString *key = new UnicodeString(*name); + int32_t val = hashEl->value.integer; + if (key == NULL) { + fDeferredStatus = U_MEMORY_ALLOCATION_ERROR; + } else { + uhash_puti(fNamedCaptureMap, key, val, &fDeferredStatus); + } } } return *this; @@ -173,8 +173,6 @@ void RegexPattern::init() { fFrameSize = 0; fDataSize = 0; fGroupMap = NULL; - fStaticSets = NULL; - fStaticSets8 = NULL; fStartType = START_NO_INFO; fInitialStringIdx = 0; fInitialStringLen = 0; @@ -191,27 +189,38 @@ void RegexPattern::init() { fSets = new UVector(fDeferredStatus); fInitialChars = new UnicodeSet; fInitialChars8 = new Regex8BitSet; - fNamedCaptureMap = uhash_open(uhash_hashUnicodeString, // Key hash function - uhash_compareUnicodeString, // Key comparator function - uhash_compareLong, // Value comparator function - &fDeferredStatus); if (U_FAILURE(fDeferredStatus)) { return; } if (fCompiledPat == NULL || fGroupMap == NULL || fSets == NULL || - fInitialChars == NULL || fInitialChars8 == NULL || fNamedCaptureMap == NULL) { + fInitialChars == NULL || fInitialChars8 == NULL) { fDeferredStatus = U_MEMORY_ALLOCATION_ERROR; return; } // Slot zero of the vector of sets is reserved. Fill it here. fSets->addElement((int32_t)0, fDeferredStatus); +} + + +bool RegexPattern::initNamedCaptureMap() { + if (fNamedCaptureMap) { + return true; + } + fNamedCaptureMap = uhash_openSize(uhash_hashUnicodeString, // Key hash function + uhash_compareUnicodeString, // Key comparator function + uhash_compareLong, // Value comparator function + 7, // Initial table capacity + &fDeferredStatus); + if (U_FAILURE(fDeferredStatus)) { + return false; + } // fNamedCaptureMap owns its key strings, type (UnicodeString *) uhash_setKeyDeleter(fNamedCaptureMap, uprv_deleteUObject); + return true; } - //-------------------------------------------------------------------------- // // zap Delete everything owned by this RegexPattern. @@ -246,8 +255,10 @@ void RegexPattern::zap() { delete fPatternString; fPatternString = NULL; } - uhash_close(fNamedCaptureMap); - fNamedCaptureMap = NULL; + if (fNamedCaptureMap != NULL) { + uhash_close(fNamedCaptureMap); + fNamedCaptureMap = NULL; + } } @@ -618,7 +629,7 @@ int32_t RegexPattern::groupNumberFromName(const UnicodeString &groupName, UError // No need to explicitly check for syntactically valid names. // Invalid ones will never be in the map, and the lookup will fail. - int32_t number = uhash_geti(fNamedCaptureMap, &groupName); + int32_t number = fNamedCaptureMap ? uhash_geti(fNamedCaptureMap, &groupName) : 0; if (number == 0) { status = U_REGEX_INVALID_CAPTURE_GROUP_NAME; } @@ -790,8 +801,8 @@ void RegexPattern::dumpOp(int32_t index) const { printf("NOT "); val &= ~URX_NEG_SET; } - UnicodeSet *set = fStaticSets[val]; - set->toPattern(s, TRUE); + UnicodeSet &set = RegexStaticSets::gStaticSets->fPropSets[val]; + set.toPattern(s, TRUE); printf("%s", CStr(s)()); } break; @@ -835,7 +846,7 @@ void RegexPattern::dumpPattern() const { } printf("Named Capture Groups:\n"); - if (uhash_count(fNamedCaptureMap) == 0) { + if (!fNamedCaptureMap || uhash_count(fNamedCaptureMap) == 0) { printf(" None\n"); } else { int32_t pos = UHASH_FIRST; diff --git a/deps/icu-small/source/i18n/scriptset.cpp b/deps/icu-small/source/i18n/scriptset.cpp index 558d178e2f97ca..18a3b263b71027 100644 --- a/deps/icu-small/source/i18n/scriptset.cpp +++ b/deps/icu-small/source/i18n/scriptset.cpp @@ -29,9 +29,7 @@ U_NAMESPACE_BEGIN // //---------------------------------------------------------------------------- ScriptSet::ScriptSet() { - for (uint32_t i=0; i= (int32_t)sizeof(bits) * 8) { + if (script < 0 || (int32_t)script >= SCRIPT_LIMIT) { status = U_ILLEGAL_ARGUMENT_ERROR; return FALSE; } @@ -77,7 +71,7 @@ ScriptSet &ScriptSet::set(UScriptCode script, UErrorCode &status) { if (U_FAILURE(status)) { return *this; } - if (script < 0 || script >= (int32_t)sizeof(bits) * 8) { + if (script < 0 || (int32_t)script >= SCRIPT_LIMIT) { status = U_ILLEGAL_ARGUMENT_ERROR; return *this; } @@ -91,7 +85,7 @@ ScriptSet &ScriptSet::reset(UScriptCode script, UErrorCode &status) { if (U_FAILURE(status)) { return *this; } - if (script < 0 || script >= (int32_t)sizeof(bits) * 8) { + if (script < 0 || (int32_t)script >= SCRIPT_LIMIT) { status = U_ILLEGAL_ARGUMENT_ERROR; return *this; } @@ -151,9 +145,7 @@ ScriptSet &ScriptSet::setAll() { ScriptSet &ScriptSet::resetAll() { - for (uint32_t i=0; i scripts; UErrorCode internalStatus = U_ZERO_ERROR; int32_t script_count = -1; diff --git a/deps/icu-small/source/i18n/scriptset.h b/deps/icu-small/source/i18n/scriptset.h index 99a71ec803f36d..a41ab737a6dc38 100644 --- a/deps/icu-small/source/i18n/scriptset.h +++ b/deps/icu-small/source/i18n/scriptset.h @@ -35,6 +35,8 @@ U_NAMESPACE_BEGIN //------------------------------------------------------------------------------- class U_I18N_API ScriptSet: public UMemory { public: + static constexpr int32_t SCRIPT_LIMIT = 224; // multiple of 32! + ScriptSet(); ScriptSet(const ScriptSet &other); ~ScriptSet(); @@ -67,7 +69,7 @@ class U_I18N_API ScriptSet: public UMemory { void setScriptExtensions(UChar32 codePoint, UErrorCode& status); private: - uint32_t bits[6]; + uint32_t bits[SCRIPT_LIMIT / 32]; }; U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/smpdtfmt.cpp b/deps/icu-small/source/i18n/smpdtfmt.cpp index 5fcbb5875b2bfb..d704642b0536a4 100644 --- a/deps/icu-small/source/i18n/smpdtfmt.cpp +++ b/deps/icu-small/source/i18n/smpdtfmt.cpp @@ -583,11 +583,14 @@ SimpleDateFormat& SimpleDateFormat::operator=(const SimpleDateFormat& other) fHasMinute = other.fHasMinute; fHasSecond = other.fHasSecond; - // TimeZoneFormat in ICU4C only depends on a locale for now - if (fLocale != other.fLocale) { - delete fTimeZoneFormat; - fTimeZoneFormat = NULL; // forces lazy instantiation with the other locale - fLocale = other.fLocale; + fLocale = other.fLocale; + + // TimeZoneFormat can now be set independently via setter. + // If it is NULL, it will be lazily initialized from locale + delete fTimeZoneFormat; + fTimeZoneFormat = NULL; + if (other.fTimeZoneFormat) { + fTimeZoneFormat = new TimeZoneFormat(*other.fTimeZoneFormat); } #if !UCONFIG_NO_BREAK_ITERATION @@ -996,7 +999,8 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo, // Use subFormat() to format a repeated pattern character // when a different pattern or non-pattern character is seen if (ch != prevCh && count > 0) { - subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status); + subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, + prevCh, handler, *workCal, status); count = 0; } if (ch == QUOTE) { @@ -1023,7 +1027,8 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo, // Format the last item in the pattern, if any if (count > 0) { - subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status); + subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, + prevCh, handler, *workCal, status); } if (calClone != NULL) { @@ -1402,10 +1407,11 @@ SimpleDateFormat::processOverrideString(const Locale &locale, const UnicodeStrin //--------------------------------------------------------------------- void SimpleDateFormat::subFormat(UnicodeString &appendTo, - UChar ch, + char16_t ch, int32_t count, UDisplayContext capitalizationContext, int32_t fieldNum, + char16_t fieldToOutput, FieldPositionHandler& handler, Calendar& cal, UErrorCode& status) const @@ -1853,8 +1859,11 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, // In either case, fall back to am/pm. if (toAppend == NULL || toAppend->isBogus()) { // Reformat with identical arguments except ch, now changed to 'a'. - subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum, - handler, cal, status); + // We are passing a different fieldToOutput because we want to add + // 'b' to field position. This makes this fallback stable when + // there is a data change on locales. + subFormat(appendTo, u'a', count, capitalizationContext, fieldNum, u'b', handler, cal, status); + return; } else { appendTo += *toAppend; } @@ -1874,9 +1883,11 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, if (ruleSet == NULL) { // Data doesn't exist for the locale we're looking for. // Falling back to am/pm. - subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum, - handler, cal, status); - break; + // We are passing a different fieldToOutput because we want to add + // 'B' to field position. This makes this fallback stable when + // there is a data change on locales. + subFormat(appendTo, u'a', count, capitalizationContext, fieldNum, u'B', handler, cal, status); + return; } // Get current display time. @@ -1945,8 +1956,11 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, if (periodType == DayPeriodRules::DAYPERIOD_AM || periodType == DayPeriodRules::DAYPERIOD_PM || toAppend->isBogus()) { - subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum, - handler, cal, status); + // We are passing a different fieldToOutput because we want to add + // 'B' to field position iterator. This makes this fallback stable when + // there is a data change on locales. + subFormat(appendTo, u'a', count, capitalizationContext, fieldNum, u'B', handler, cal, status); + return; } else { appendTo += *toAppend; @@ -1990,7 +2004,7 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, } #endif - handler.addAttribute(fgPatternIndexToDateFormatField[patternCharIndex], beginOffset, appendTo.length()); + handler.addAttribute(DateFormatSymbols::getPatternCharIndex(fieldToOutput), beginOffset, appendTo.length()); } //---------------------------------------------------------------------- diff --git a/deps/icu-small/source/i18n/translit.cpp b/deps/icu-small/source/i18n/translit.cpp index 039acaf157cc93..a2ade1b4fe8578 100644 --- a/deps/icu-small/source/i18n/translit.cpp +++ b/deps/icu-small/source/i18n/translit.cpp @@ -1508,28 +1508,35 @@ UBool Transliterator::initializeRegistry(UErrorCode &status) { */ //static const char translit_index[] = "translit_index"; + UErrorCode lstatus = U_ZERO_ERROR; UResourceBundle *bundle, *transIDs, *colBund; - bundle = ures_open(U_ICUDATA_TRANSLIT, NULL/*open default locale*/, &status); - transIDs = ures_getByKey(bundle, RB_RULE_BASED_IDS, 0, &status); + bundle = ures_open(U_ICUDATA_TRANSLIT, NULL/*open default locale*/, &lstatus); + transIDs = ures_getByKey(bundle, RB_RULE_BASED_IDS, 0, &lstatus); const UnicodeString T_PART = UNICODE_STRING_SIMPLE("-t-"); int32_t row, maxRows; - if (U_SUCCESS(status)) { + if (lstatus == U_MEMORY_ALLOCATION_ERROR) { + delete registry; + registry = nullptr; + status = U_MEMORY_ALLOCATION_ERROR; + return FALSE; + } + if (U_SUCCESS(lstatus)) { maxRows = ures_getSize(transIDs); for (row = 0; row < maxRows; row++) { - colBund = ures_getByIndex(transIDs, row, 0, &status); - if (U_SUCCESS(status)) { + colBund = ures_getByIndex(transIDs, row, 0, &lstatus); + if (U_SUCCESS(lstatus)) { UnicodeString id(ures_getKey(colBund), -1, US_INV); if(id.indexOf(T_PART) != -1) { ures_close(colBund); continue; } - UResourceBundle* res = ures_getNextResource(colBund, NULL, &status); + UResourceBundle* res = ures_getNextResource(colBund, NULL, &lstatus); const char* typeStr = ures_getKey(res); UChar type; u_charsToUChars(typeStr, &type, 1); - if (U_SUCCESS(status)) { + if (U_SUCCESS(lstatus)) { int32_t len = 0; const UChar *resString; switch (type) { @@ -1539,19 +1546,19 @@ UBool Transliterator::initializeRegistry(UErrorCode &status) { // row[2]=resource, row[3]=direction { - resString = ures_getStringByKey(res, "resource", &len, &status); + resString = ures_getStringByKey(res, "resource", &len, &lstatus); UBool visible = (type == 0x0066 /*f*/); UTransDirection dir = - (ures_getUnicodeStringByKey(res, "direction", &status).charAt(0) == + (ures_getUnicodeStringByKey(res, "direction", &lstatus).charAt(0) == 0x0046 /*F*/) ? UTRANS_FORWARD : UTRANS_REVERSE; - registry->put(id, UnicodeString(TRUE, resString, len), dir, TRUE, visible, status); + registry->put(id, UnicodeString(TRUE, resString, len), dir, TRUE, visible, lstatus); } break; case 0x61: // 'a' // 'alias'; row[2]=createInstance argument - resString = ures_getString(res, &len, &status); - registry->put(id, UnicodeString(TRUE, resString, len), TRUE, TRUE, status); + resString = ures_getString(res, &len, &lstatus); + registry->put(id, UnicodeString(TRUE, resString, len), TRUE, TRUE, lstatus); break; } } diff --git a/deps/icu-small/source/i18n/ucal.cpp b/deps/icu-small/source/i18n/ucal.cpp index cca1f70cf54584..8ea7fbf4f56939 100644 --- a/deps/icu-small/source/i18n/ucal.cpp +++ b/deps/icu-small/source/i18n/ucal.cpp @@ -154,25 +154,31 @@ ucal_open( const UChar* zoneID, UCalendarType caltype, UErrorCode* status) { + if (U_FAILURE(*status)) { + return nullptr; + } - if(U_FAILURE(*status)) return 0; - - LocalPointer zone( (zoneID==NULL) ? TimeZone::createDefault() + LocalPointer zone( (zoneID==nullptr) ? TimeZone::createDefault() : _createTimeZone(zoneID, len, status), *status); if (U_FAILURE(*status)) { - return NULL; + return nullptr; } if ( caltype == UCAL_GREGORIAN ) { - char localeBuf[ULOC_LOCALE_IDENTIFIER_CAPACITY]; - if ( locale == NULL ) { + char localeBuf[ULOC_LOCALE_IDENTIFIER_CAPACITY]; + if ( locale == nullptr ) { locale = uloc_getDefault(); } - uprv_strncpy(localeBuf, locale, ULOC_LOCALE_IDENTIFIER_CAPACITY); + int32_t localeLength = static_cast(uprv_strlen(locale)); + if (localeLength >= ULOC_LOCALE_IDENTIFIER_CAPACITY) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + uprv_strcpy(localeBuf, locale); uloc_setKeywordValue("calendar", "gregorian", localeBuf, ULOC_LOCALE_IDENTIFIER_CAPACITY, status); if (U_FAILURE(*status)) { - return NULL; + return nullptr; } return (UCalendar*)Calendar::createInstance(zone.orphan(), Locale(localeBuf), *status); } @@ -182,8 +188,9 @@ ucal_open( const UChar* zoneID, U_CAPI void U_EXPORT2 ucal_close(UCalendar *cal) { - - delete (Calendar*) cal; + if (cal != nullptr) { + delete (Calendar*) cal; + } } U_CAPI UCalendar* U_EXPORT2 diff --git a/deps/icu-small/source/i18n/ucln_in.h b/deps/icu-small/source/i18n/ucln_in.h index 2f70a8500e1c09..765cdd559fb4e2 100644 --- a/deps/icu-small/source/i18n/ucln_in.h +++ b/deps/icu-small/source/i18n/ucln_in.h @@ -26,6 +26,7 @@ as the functions are suppose to be called. It's usually best to have child dependencies called first. */ typedef enum ECleanupI18NType { UCLN_I18N_START = -1, + UCLN_I18N_UNIT_EXTRAS, UCLN_I18N_NUMBER_SKELETONS, UCLN_I18N_CURRENCY_SPACING, UCLN_I18N_SPOOF, diff --git a/deps/icu-small/source/i18n/ucol_sit.cpp b/deps/icu-small/source/i18n/ucol_sit.cpp index 765613084f84e1..9fa7cd5fd73851 100644 --- a/deps/icu-small/source/i18n/ucol_sit.cpp +++ b/deps/icu-small/source/i18n/ucol_sit.cpp @@ -24,6 +24,10 @@ #include "cstring.h" #include "uresimp.h" #include "unicode/coll.h" +#include "unicode/stringpiece.h" +#include "charstr.h" + +U_NAMESPACE_USE #ifdef UCOL_TRACE_SIT # include @@ -82,7 +86,6 @@ static const char providerKeyword[] = "@sp="; static const int32_t locElementCount = UCOL_SIT_LOCELEMENT_MAX+1; static const int32_t locElementCapacity = 32; static const int32_t loc3066Capacity = 256; -static const int32_t locProviderCapacity = 10; static const int32_t internalBufferSize = 512; /* structure containing specification of a collator. Initialized @@ -90,20 +93,30 @@ static const int32_t internalBufferSize = 512; * collator instance */ struct CollatorSpec { - char locElements[locElementCount][locElementCapacity]; - char locale[loc3066Capacity]; - char provider[locProviderCapacity]; + inline CollatorSpec(); + + CharString locElements[locElementCount]; + CharString locale; UColAttributeValue options[UCOL_ATTRIBUTE_COUNT]; uint32_t variableTopValue; UChar variableTopString[locElementCapacity]; int32_t variableTopStringLen; UBool variableTopSet; - struct { - const char *start; - int32_t len; - } entries[UCOL_SIT_ITEMS_COUNT]; + CharString entries[UCOL_SIT_ITEMS_COUNT]; }; +CollatorSpec::CollatorSpec() : +locale(), +variableTopValue(0), +variableTopString(), +variableTopSet(FALSE) + { + // set collation options to default + for(int32_t i = 0; i < UCOL_ATTRIBUTE_COUNT; i++) { + options[i] = UCOL_DEFAULT; + } +} + /* structure for converting between character attribute * representation and real collation attribute value. @@ -156,18 +169,13 @@ static const char* U_CALLCONV _processLocaleElement(CollatorSpec *spec, uint32_t value, const char* string, UErrorCode *status) { - int32_t len = 0; do { if(value == UCOL_SIT_LANGUAGE || value == UCOL_SIT_KEYWORD || value == UCOL_SIT_PROVIDER) { - spec->locElements[value][len++] = uprv_tolower(*string); + spec->locElements[value].append(uprv_tolower(*string), *status); } else { - spec->locElements[value][len++] = *string; + spec->locElements[value].append(*string, *status); } - } while(*(++string) != '_' && *string && len < locElementCapacity); - if(len >= locElementCapacity) { - *status = U_BUFFER_OVERFLOW_ERROR; - return string; - } + } while(*(++string) != '_' && *string && U_SUCCESS(*status)); // don't skip the underscore at the end return string; } @@ -185,7 +193,7 @@ _processRFC3066Locale(CollatorSpec *spec, uint32_t, const char* string, *status = U_BUFFER_OVERFLOW_ERROR; return string; } else { - uprv_strncpy(spec->locale, string, end-string); + spec->locale.copyFrom(CharString(string, static_cast(end-string), *status), *status); return end+1; } } @@ -306,9 +314,12 @@ const char* ucol_sit_readOption(const char *start, CollatorSpec *spec, for(i = 0; i < UCOL_SIT_ITEMS_COUNT; i++) { if(*start == options[i].optionStart) { - spec->entries[i].start = start; const char* end = options[i].action(spec, options[i].attr, start+1, status); - spec->entries[i].len = (int32_t)(end - start); +#ifdef UCOL_TRACE_SIT + fprintf(stderr, "***Set %d to %s...\n", i, start); +#endif + // assume 'start' does not go away through all this + spec->entries[i].copyFrom(CharString(start, (int32_t)(end - start), *status), *status); return end; } } @@ -319,18 +330,6 @@ const char* ucol_sit_readOption(const char *start, CollatorSpec *spec, return start; } -static -void ucol_sit_initCollatorSpecs(CollatorSpec *spec) -{ - // reset everything - uprv_memset(spec, 0, sizeof(CollatorSpec)); - // set collation options to default - int32_t i = 0; - for(i = 0; i < UCOL_ATTRIBUTE_COUNT; i++) { - spec->options[i] = UCOL_DEFAULT; - } -} - static const char* ucol_sit_readSpecs(CollatorSpec *s, const char *string, UParseError *parseError, UErrorCode *status) @@ -357,25 +356,25 @@ int32_t ucol_sit_dumpSpecs(CollatorSpec *s, char *destination, int32_t capacity, char optName; if(U_SUCCESS(*status)) { for(i = 0; i < UCOL_SIT_ITEMS_COUNT; i++) { - if(s->entries[i].start) { + if(!s->entries[i].isEmpty()) { if(len) { if(len < capacity) { uprv_strcat(destination, "_"); } len++; } - optName = *(s->entries[i].start); + optName = s->entries[i][0]; if(optName == languageArg || optName == regionArg || optName == variantArg || optName == keywordArg) { - for(j = 0; j < s->entries[i].len; j++) { + for(j = 0; j < s->entries[i].length(); j++) { if(len + j < capacity) { - destination[len+j] = uprv_toupper(*(s->entries[i].start+j)); + destination[len+j] = uprv_toupper(s->entries[i][j]); } } - len += s->entries[i].len; + len += s->entries[i].length(); } else { - len += s->entries[i].len; + len += s->entries[i].length(); if(len < capacity) { - uprv_strncat(destination,s->entries[i].start, s->entries[i].len); + uprv_strncat(destination,s->entries[i].data(), s->entries[i].length()); } } } @@ -387,40 +386,40 @@ int32_t ucol_sit_dumpSpecs(CollatorSpec *s, char *destination, int32_t capacity, } static void -ucol_sit_calculateWholeLocale(CollatorSpec *s) { +ucol_sit_calculateWholeLocale(CollatorSpec *s, UErrorCode &status) { // put the locale together, unless we have a done // locale - if(s->locale[0] == 0) { + if(s->locale.isEmpty()) { // first the language - uprv_strcat(s->locale, s->locElements[UCOL_SIT_LANGUAGE]); + s->locale.append(s->locElements[UCOL_SIT_LANGUAGE], status); // then the script, if present - if(*(s->locElements[UCOL_SIT_SCRIPT])) { - uprv_strcat(s->locale, "_"); - uprv_strcat(s->locale, s->locElements[UCOL_SIT_SCRIPT]); + if(!s->locElements[UCOL_SIT_SCRIPT].isEmpty()) { + s->locale.append("_", status); + s->locale.append(s->locElements[UCOL_SIT_SCRIPT], status); } // then the region, if present - if(*(s->locElements[UCOL_SIT_REGION])) { - uprv_strcat(s->locale, "_"); - uprv_strcat(s->locale, s->locElements[UCOL_SIT_REGION]); - } else if(*(s->locElements[UCOL_SIT_VARIANT])) { // if there is a variant, we need an underscore - uprv_strcat(s->locale, "_"); + if(!s->locElements[UCOL_SIT_REGION].isEmpty()) { + s->locale.append("_", status); + s->locale.append(s->locElements[UCOL_SIT_REGION], status); + } else if(!s->locElements[UCOL_SIT_VARIANT].isEmpty()) { // if there is a variant, we need an underscore + s->locale.append("_", status); } // add variant, if there - if(*(s->locElements[UCOL_SIT_VARIANT])) { - uprv_strcat(s->locale, "_"); - uprv_strcat(s->locale, s->locElements[UCOL_SIT_VARIANT]); + if(!s->locElements[UCOL_SIT_VARIANT].isEmpty()) { + s->locale.append("_", status); + s->locale.append(s->locElements[UCOL_SIT_VARIANT], status); } // if there is a collation keyword, add that too - if(*(s->locElements[UCOL_SIT_KEYWORD])) { - uprv_strcat(s->locale, collationKeyword); - uprv_strcat(s->locale, s->locElements[UCOL_SIT_KEYWORD]); + if(!s->locElements[UCOL_SIT_KEYWORD].isEmpty()) { + s->locale.append(collationKeyword, status); + s->locale.append(s->locElements[UCOL_SIT_KEYWORD], status); } // if there is a provider keyword, add that too - if(*(s->locElements[UCOL_SIT_PROVIDER])) { - uprv_strcat(s->locale, providerKeyword); - uprv_strcat(s->locale, s->locElements[UCOL_SIT_PROVIDER]); + if(!s->locElements[UCOL_SIT_PROVIDER].isEmpty()) { + s->locale.append(providerKeyword, status); + s->locale.append(s->locElements[UCOL_SIT_PROVIDER], status); } } } @@ -451,13 +450,12 @@ ucol_prepareShortStringOpen( const char *definition, // analyse the string in order to get everything we need. CollatorSpec s; - ucol_sit_initCollatorSpecs(&s); ucol_sit_readSpecs(&s, definition, parseError, status); - ucol_sit_calculateWholeLocale(&s); + ucol_sit_calculateWholeLocale(&s, *status); char buffer[internalBufferSize]; uprv_memset(buffer, 0, internalBufferSize); - uloc_canonicalize(s.locale, buffer, internalBufferSize, status); + uloc_canonicalize(s.locale.data(), buffer, internalBufferSize, status); UResourceBundle *b = ures_open(U_ICUDATA_COLL, buffer, status); /* we try to find stuff from keyword */ @@ -522,13 +520,15 @@ ucol_openFromShortString( const char *definition, // analyse the string in order to get everything we need. const char *string = definition; CollatorSpec s; - ucol_sit_initCollatorSpecs(&s); string = ucol_sit_readSpecs(&s, definition, parseError, status); - ucol_sit_calculateWholeLocale(&s); + ucol_sit_calculateWholeLocale(&s, *status); char buffer[internalBufferSize]; uprv_memset(buffer, 0, internalBufferSize); - uloc_canonicalize(s.locale, buffer, internalBufferSize, status); +#ifdef UCOL_TRACE_SIT + fprintf(stderr, "DEF %s, DATA %s, ERR %s\n", definition, s.locale.data(), u_errorName(*status)); +#endif + uloc_canonicalize(s.locale.data(), buffer, internalBufferSize, status); UCollator *result = ucol_open(buffer, status); int32_t i = 0; @@ -604,7 +604,6 @@ ucol_normalizeShortDefinitionString(const char *definition, // validate CollatorSpec s; - ucol_sit_initCollatorSpecs(&s); ucol_sit_readSpecs(&s, definition, parseError, status); return ucol_sit_dumpSpecs(&s, destination, capacity, status); } diff --git a/deps/icu-small/source/i18n/udateintervalformat.cpp b/deps/icu-small/source/i18n/udateintervalformat.cpp index d9eaae4d3e23cf..388960384b563f 100644 --- a/deps/icu-small/source/i18n/udateintervalformat.cpp +++ b/deps/icu-small/source/i18n/udateintervalformat.cpp @@ -119,17 +119,36 @@ udtitvfmt_format(const UDateIntervalFormat* formatter, U_DRAFT void U_EXPORT2 udtitvfmt_formatToResult( const UDateIntervalFormat* formatter, - UFormattedDateInterval* result, UDate fromDate, UDate toDate, + UFormattedDateInterval* result, UErrorCode* status) { if (U_FAILURE(*status)) { return; } auto* resultImpl = UFormattedDateIntervalApiHelper::validate(result, *status); DateInterval interval = DateInterval(fromDate,toDate); - resultImpl->fImpl = reinterpret_cast(formatter) - ->formatToValue(interval, *status); + if (resultImpl != nullptr) { + resultImpl->fImpl = reinterpret_cast(formatter) + ->formatToValue(interval, *status); + } +} + +U_DRAFT void U_EXPORT2 +udtitvfmt_formatCalendarToResult( + const UDateIntervalFormat* formatter, + UCalendar* fromCalendar, + UCalendar* toCalendar, + UFormattedDateInterval* result, + UErrorCode* status) { + if (U_FAILURE(*status)) { + return; + } + auto* resultImpl = UFormattedDateIntervalApiHelper::validate(result, *status); + if (resultImpl != nullptr) { + resultImpl->fImpl = reinterpret_cast(formatter) + ->formatToValue(*(Calendar *)fromCalendar, *(Calendar *)toCalendar, *status); + } } diff --git a/deps/icu-small/source/i18n/udatpg.cpp b/deps/icu-small/source/i18n/udatpg.cpp index febf73b3ce499f..332636a93889f1 100644 --- a/deps/icu-small/source/i18n/udatpg.cpp +++ b/deps/icu-small/source/i18n/udatpg.cpp @@ -291,4 +291,9 @@ udatpg_getPatternForSkeleton(const UDateTimePatternGenerator *dtpg, return result.getBuffer(); } +U_CAPI UDateFormatHourCycle U_EXPORT2 +udatpg_getDefaultHourCycle(const UDateTimePatternGenerator *dtpg, UErrorCode* pErrorCode) { + return ((const DateTimePatternGenerator *)dtpg)->getDefaultHourCycle(*pErrorCode); +} + #endif diff --git a/deps/icu-small/source/i18n/ulistformatter.cpp b/deps/icu-small/source/i18n/ulistformatter.cpp index f7ad6751d338c0..bfb7cf96bd4d93 100644 --- a/deps/icu-small/source/i18n/ulistformatter.cpp +++ b/deps/icu-small/source/i18n/ulistformatter.cpp @@ -34,6 +34,21 @@ ulistfmt_open(const char* locale, } +U_CAPI UListFormatter* U_EXPORT2 +ulistfmt_openForType(const char* locale, UListFormatterType type, + UListFormatterWidth width, UErrorCode* status) +{ + if (U_FAILURE(*status)) { + return NULL; + } + LocalPointer listfmt(ListFormatter::createInstance(Locale(locale), type, width, *status)); + if (U_FAILURE(*status)) { + return NULL; + } + return (UListFormatter*)listfmt.orphan(); +} + + U_CAPI void U_EXPORT2 ulistfmt_close(UListFormatter *listfmt) { diff --git a/deps/icu-small/source/i18n/unicode/basictz.h b/deps/icu-small/source/i18n/unicode/basictz.h index e1db2a8223adde..cc8059709f49b0 100644 --- a/deps/icu-small/source/i18n/unicode/basictz.h +++ b/deps/icu-small/source/i18n/unicode/basictz.h @@ -206,6 +206,12 @@ class U_I18N_API BasicTimeZone: public TimeZone { */ BasicTimeZone(const BasicTimeZone& source); + /** + * Copy assignment. + * @stable ICU 3.8 + */ + BasicTimeZone& operator=(const BasicTimeZone&) = default; + /** * Gets the set of TimeZoneRule instances applicable to the specified time and after. * @param start The start date used for extracting time zone rules diff --git a/deps/icu-small/source/i18n/unicode/currunit.h b/deps/icu-small/source/i18n/unicode/currunit.h index 0446154e328f8f..090b964a0decee 100644 --- a/deps/icu-small/source/i18n/unicode/currunit.h +++ b/deps/icu-small/source/i18n/unicode/currunit.h @@ -56,7 +56,6 @@ class U_I18N_API CurrencyUnit: public MeasureUnit { */ CurrencyUnit(ConstChar16Ptr isoCode, UErrorCode &ec); -#ifndef U_HIDE_DRAFT_API /** * Construct an object with the given ISO currency code. * @@ -64,10 +63,9 @@ class U_I18N_API CurrencyUnit: public MeasureUnit { * length 3. If invalid, the currency is initialized to XXX. * @param ec input-output error code. If the isoCode is invalid, * then this will be set to a failing value. - * @draft ICU 64 + * @stable ICU 64 */ CurrencyUnit(StringPiece isoCode, UErrorCode &ec); -#endif /* U_HIDE_DRAFT_API */ /** * Copy constructor diff --git a/deps/icu-small/source/i18n/unicode/dcfmtsym.h b/deps/icu-small/source/i18n/unicode/dcfmtsym.h index e1e0ab6b08c523..582e7533a4aceb 100644 --- a/deps/icu-small/source/i18n/unicode/dcfmtsym.h +++ b/deps/icu-small/source/i18n/unicode/dcfmtsym.h @@ -291,6 +291,17 @@ class U_I18N_API DecimalFormatSymbols : public UObject { */ void setSymbol(ENumberFormatSymbol symbol, const UnicodeString &value, const UBool propogateDigits); +#ifndef U_HIDE_INTERNAL_API + /** + * Loads symbols for the specified currency into this instance. + * + * This method is internal. If you think it should be public, file a ticket. + * + * @internal + */ + void setCurrency(const UChar* currency, UErrorCode& status); +#endif // U_HIDE_INTERNAL_API + /** * Returns the locale for which this object was constructed. * @stable ICU 2.6 @@ -374,8 +385,6 @@ class U_I18N_API DecimalFormatSymbols : public UObject { */ void initialize(); - void setCurrencyForSymbols(); - public: #ifndef U_HIDE_INTERNAL_API diff --git a/deps/icu-small/source/i18n/unicode/decimfmt.h b/deps/icu-small/source/i18n/unicode/decimfmt.h index e539b9af233ccb..b176ee78faca49 100644 --- a/deps/icu-small/source/i18n/unicode/decimfmt.h +++ b/deps/icu-small/source/i18n/unicode/decimfmt.h @@ -53,10 +53,10 @@ class CompactDecimalFormat; namespace number { class LocalizedNumberFormatter; -class FormattedNumber; namespace impl { class DecimalQuantity; struct DecimalFormatFields; +class UFormattedNumberData; } } @@ -1283,14 +1283,13 @@ class U_I18N_API DecimalFormat : public NumberFormat { */ virtual void setNegativeSuffix(const UnicodeString& newValue); -#ifndef U_HIDE_DRAFT_API /** * Whether to show the plus sign on positive (non-negative) numbers; for example, "+12" * * For more control over sign display, use NumberFormatter. * * @return Whether the sign is shown on positive numbers and zero. - * @draft ICU 64 + * @stable ICU 64 */ UBool isSignAlwaysShown() const; @@ -1300,10 +1299,9 @@ class U_I18N_API DecimalFormat : public NumberFormat { * For more control over sign display, use NumberFormatter. * * @param value true to always show a sign; false to hide the sign on positive numbers and zero. - * @draft ICU 64 + * @stable ICU 64 */ void setSignAlwaysShown(UBool value); -#endif /* U_HIDE_DRAFT_API */ /** * Get the multiplier for use in percent, permill, etc. @@ -1650,7 +1648,6 @@ class U_I18N_API DecimalFormat : public NumberFormat { */ virtual void setSecondaryGroupingSize(int32_t newValue); -#ifndef U_HIDE_DRAFT_API /** * Returns the minimum number of grouping digits. * Grouping separators are output if there are at least this many @@ -1672,7 +1669,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * * @see setMinimumGroupingDigits * @see getGroupingSize - * @draft ICU 64 + * @stable ICU 64 */ int32_t getMinimumGroupingDigits() const; @@ -1684,11 +1681,9 @@ class U_I18N_API DecimalFormat : public NumberFormat { * * @param newValue the new value of minimum grouping digits. * @see getMinimumGroupingDigits - * @draft ICU 64 + * @stable ICU 64 */ void setMinimumGroupingDigits(int32_t newValue); -#endif /* U_HIDE_DRAFT_API */ - /** * Allows you to get the behavior of the decimal separator with integers. @@ -1729,13 +1724,12 @@ class U_I18N_API DecimalFormat : public NumberFormat { */ virtual void setDecimalPatternMatchRequired(UBool newValue); -#ifndef U_HIDE_DRAFT_API /** * Returns whether to ignore exponents when parsing. * * @return Whether to ignore exponents when parsing. * @see #setParseNoExponent - * @draft ICU 64 + * @stable ICU 64 */ UBool isParseNoExponent() const; @@ -1745,7 +1739,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * 5). * * @param value true to prevent exponents from being parsed; false to allow them to be parsed. - * @draft ICU 64 + * @stable ICU 64 */ void setParseNoExponent(UBool value); @@ -1754,7 +1748,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * * @return Whether parsing is case-sensitive. * @see #setParseCaseSensitive - * @draft ICU 64 + * @stable ICU 64 */ UBool isParseCaseSensitive() const; @@ -1767,7 +1761,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * * @param value true to enable case-sensitive parsing (the default); false to force * case-sensitive parsing behavior. - * @draft ICU 64 + * @stable ICU 64 */ void setParseCaseSensitive(UBool value); @@ -1777,7 +1771,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * * @return Whether an error code is set if high-order digits are truncated. * @see setFormatFailIfMoreThanMaxDigits - * @draft ICU 64 + * @stable ICU 64 */ UBool isFormatFailIfMoreThanMaxDigits() const; @@ -1786,11 +1780,9 @@ class U_I18N_API DecimalFormat : public NumberFormat { * By default, setMaximumIntegerDigits truncates high-order digits silently. * * @param value Whether to set an error code if high-order digits are truncated. - * @draft ICU 64 + * @stable ICU 64 */ void setFormatFailIfMoreThanMaxDigits(UBool value); -#endif /* U_HIDE_DRAFT_API */ - /** * Synthesizes a pattern string that represents the current state @@ -2067,7 +2059,6 @@ class U_I18N_API DecimalFormat : public NumberFormat { #endif /* U_HIDE_INTERNAL_API */ -#ifndef U_HIDE_DRAFT_API /** * Converts this DecimalFormat to a (Localized)NumberFormatter. Starting * in ICU 60, NumberFormatter is the recommended way to format numbers. @@ -2111,10 +2102,9 @@ class U_I18N_API DecimalFormat : public NumberFormat { * @param status Set on failure, like U_MEMORY_ALLOCATION_ERROR. * @return A pointer to an internal object, or nullptr on failure. * Do not delete the return value! - * @draft ICU 64 + * @stable ICU 64 */ const number::LocalizedNumberFormatter* toNumberFormatter(UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ /** * Return the class ID for this class. This is useful only for @@ -2168,11 +2158,17 @@ class U_I18N_API DecimalFormat : public NumberFormat { const numparse::impl::NumberParserImpl* getCurrencyParser(UErrorCode& status) const; - static void fieldPositionHelper(const number::FormattedNumber& formatted, FieldPosition& fieldPosition, - int32_t offset, UErrorCode& status); - - static void fieldPositionIteratorHelper(const number::FormattedNumber& formatted, - FieldPositionIterator* fpi, int32_t offset, UErrorCode& status); + static void fieldPositionHelper( + const number::impl::UFormattedNumberData& formatted, + FieldPosition& fieldPosition, + int32_t offset, + UErrorCode& status); + + static void fieldPositionIteratorHelper( + const number::impl::UFormattedNumberData& formatted, + FieldPositionIterator* fpi, + int32_t offset, + UErrorCode& status); void setupFastFormat(); diff --git a/deps/icu-small/source/i18n/unicode/dtitvfmt.h b/deps/icu-small/source/i18n/unicode/dtitvfmt.h index 23fc02e2a7b16b..4e4d712b4f5b5c 100644 --- a/deps/icu-small/source/i18n/unicode/dtitvfmt.h +++ b/deps/icu-small/source/i18n/unicode/dtitvfmt.h @@ -38,7 +38,6 @@ U_NAMESPACE_BEGIN class FormattedDateIntervalData; class DateIntervalFormat; -#ifndef U_HIDE_DRAFT_API /** * An immutable class containing the result of a date interval formatting operation. * @@ -54,25 +53,25 @@ class DateIntervalFormat; * * Not intended for public subclassing. * - * @draft ICU 64 + * @stable ICU 64 */ class U_I18N_API FormattedDateInterval : public UMemory, public FormattedValue { public: /** * Default constructor; makes an empty FormattedDateInterval. - * @draft ICU 64 + * @stable ICU 64 */ FormattedDateInterval() : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {} /** * Move constructor: Leaves the source FormattedDateInterval in an undefined state. - * @draft ICU 64 + * @stable ICU 64 */ FormattedDateInterval(FormattedDateInterval&& src) U_NOEXCEPT; /** * Destruct an instance of FormattedDateInterval. - * @draft ICU 64 + * @stable ICU 64 */ virtual ~FormattedDateInterval() U_OVERRIDE; @@ -84,7 +83,7 @@ class U_I18N_API FormattedDateInterval : public UMemory, public FormattedValue { /** * Move assignment: Leaves the source FormattedDateInterval in an undefined state. - * @draft ICU 64 + * @stable ICU 64 */ FormattedDateInterval& operator=(FormattedDateInterval&& src) U_NOEXCEPT; @@ -109,7 +108,6 @@ class U_I18N_API FormattedDateInterval : public UMemory, public FormattedValue { : fData(nullptr), fErrorCode(errorCode) {} friend class DateIntervalFormat; }; -#endif /* U_HIDE_DRAFT_API */ /** @@ -174,11 +172,12 @@ class U_I18N_API FormattedDateInterval : public UMemory, public FormattedValue { * *

* The calendar fields we support for interval formatting are: - * year, month, date, day-of-week, am-pm, hour, hour-of-day, minute, and second + * year, month, date, day-of-week, am-pm, hour, hour-of-day, minute, second, + * and millisecond. * (though we do not currently have specific intervalFormat date for skeletons - * with seconds). + * with seconds and millisecond). * Those calendar fields can be defined in the following order: - * year > month > date > hour (in day) > minute > second + * year > month > date > hour (in day) > minute > second > millisecond * * The largest different calendar fields between 2 calendars is the * first different calendar field in above order. @@ -503,7 +502,6 @@ class U_I18N_API DateIntervalFormat : public Format { FieldPosition& fieldPosition, UErrorCode& status) const ; -#ifndef U_HIDE_DRAFT_API /** * Format a DateInterval to produce a FormattedDateInterval. * @@ -512,12 +510,11 @@ class U_I18N_API DateIntervalFormat : public Format { * @param dtInterval DateInterval to be formatted. * @param status Set if an error occurs. * @return A FormattedDateInterval containing the format result. - * @draft ICU 64 + * @stable ICU 64 */ FormattedDateInterval formatToValue( const DateInterval& dtInterval, UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ /** * Format 2 Calendars to produce a string. @@ -548,7 +545,6 @@ class U_I18N_API DateIntervalFormat : public Format { FieldPosition& fieldPosition, UErrorCode& status) const ; -#ifndef U_HIDE_DRAFT_API /** * Format 2 Calendars to produce a FormattedDateInterval. * @@ -563,13 +559,12 @@ class U_I18N_API DateIntervalFormat : public Format { * to be formatted into date interval string * @param status Set if an error occurs. * @return A FormattedDateInterval containing the format result. - * @draft ICU 64 + * @stable ICU 64 */ FormattedDateInterval formatToValue( Calendar& fromCalendar, Calendar& toCalendar, UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ /** * Date interval parsing is not supported. Please do not use. diff --git a/deps/icu-small/source/i18n/unicode/dtitvinf.h b/deps/icu-small/source/i18n/unicode/dtitvinf.h index 3c666231abd060..50e19abb4ce2cb 100644 --- a/deps/icu-small/source/i18n/unicode/dtitvinf.h +++ b/deps/icu-small/source/i18n/unicode/dtitvinf.h @@ -137,8 +137,8 @@ U_NAMESPACE_BEGIN * After a DateIntervalInfo object is created, clients may modify * the interval patterns using setIntervalPattern function as so desired. * Currently, users can only set interval patterns when the following - * calendar fields are different: ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, - * DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY, and MINUTE. + * calendar fields are different: ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, + * DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY, MINUTE, SECOND, and MILLISECOND. * Interval patterns when other calendar fields are different is not supported. *

* DateIntervalInfo objects are cloneable. @@ -245,7 +245,7 @@ class U_I18N_API DateIntervalInfo U_FINAL : public UObject { * Restriction: * Currently, users can only set interval patterns when the following * calendar fields are different: ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, - * DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY, and MINUTE. + * DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY, MINUTE, SECOND and MILLISECOND. * Interval patterns when other calendar fields are different are * not supported. * @@ -348,7 +348,7 @@ class U_I18N_API DateIntervalInfo U_FINAL : public UObject { /** * Following is for saving the interval patterns. * We only support interval patterns on - * ERA, YEAR, MONTH, DAY, AM_PM, HOUR, and MINUTE + * ERA, YEAR, MONTH, DAY, AM_PM, HOUR, MINUTE, SECOND and MILLISECOND. */ enum IntervalPatternIndex { @@ -360,6 +360,7 @@ class U_I18N_API DateIntervalInfo U_FINAL : public UObject { kIPI_HOUR, kIPI_MINUTE, kIPI_SECOND, + kIPI_MILLISECOND, kIPI_MAX_INDEX }; public: @@ -453,8 +454,8 @@ class U_I18N_API DateIntervalInfo U_FINAL : public UObject { * hash table. * * Since we only support the following calendar fields: - * ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, DAY_OF_WEEK, - * AM_PM, HOUR, HOUR_OF_DAY, and MINUTE, + * ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, DAY_OF_WEEK, + * AM_PM, HOUR, HOUR_OF_DAY, MINUTE, SECOND, and MILLISECOND. * We reserve only 4 interval patterns for a skeleton. * * @param field calendar field diff --git a/deps/icu-small/source/i18n/unicode/dtptngen.h b/deps/icu-small/source/i18n/unicode/dtptngen.h index a71938b31cf5d8..f79c6d45dc6b29 100644 --- a/deps/icu-small/source/i18n/unicode/dtptngen.h +++ b/deps/icu-small/source/i18n/unicode/dtptngen.h @@ -483,6 +483,26 @@ class U_I18N_API DateTimePatternGenerator : public UObject { */ const UnicodeString& getDecimal() const; +#if !UCONFIG_NO_FORMATTING + +#ifndef U_HIDE_DRAFT_API + /** + * Get the default hour cycle for a locale. Uses the locale that the + * DateTimePatternGenerator was initially created with. + * + * Cannot be used on an empty DateTimePatternGenerator instance. + * + * @param status Output param set to success/failure code on exit, which + * which must not indicate a failure before the function call. + * Set to U_UNSUPPORTED_ERROR if used on an empty instance. + * @return the default hour cycle. + * @draft ICU 67 + */ + UDateFormatHourCycle getDefaultHourCycle(UErrorCode& status) const; +#endif /* U_HIDE_DRAFT_API */ + +#endif /* #if !UCONFIG_NO_FORMATTING */ + /** * ICU "poor man's RTTI", returns a UClassID for the actual class. * diff --git a/deps/icu-small/source/i18n/unicode/formattedvalue.h b/deps/icu-small/source/i18n/unicode/formattedvalue.h index 1b130bbdd9d44c..4469b6328e7cb9 100644 --- a/deps/icu-small/source/i18n/unicode/formattedvalue.h +++ b/deps/icu-small/source/i18n/unicode/formattedvalue.h @@ -25,11 +25,6 @@ U_NAMESPACE_BEGIN * of APIs throughout ICU use these classes for expressing their localized output. */ - -// The following cannot have #ifndef U_HIDE_DRAFT_API because -// class FormattedValue depends on it, and FormattedValue cannot be -// hidden becauseclass FormattedNumber (stable ICU 60) depends on it. -#ifndef U_FORCE_HIDE_DRAFT_API /** * Represents a span of a string containing a given field. * @@ -41,7 +36,7 @@ U_NAMESPACE_BEGIN * * This class is not intended for public subclassing. * - * @draft ICU 64 + * @stable ICU 64 */ class U_I18N_API ConstrainedFieldPosition : public UMemory { public: @@ -51,21 +46,20 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * * By default, the ConstrainedFieldPosition has no iteration constraints. * - * @draft ICU 64 + * @stable ICU 64 */ ConstrainedFieldPosition(); - /** @draft ICU 64 */ + /** @stable ICU 64 */ ~ConstrainedFieldPosition(); -#ifndef U_HIDE_DRAFT_API /** * Resets this ConstrainedFieldPosition to its initial state, as if it were newly created: * * - Removes any constraints that may have been set on the instance. * - Resets the iteration position. * - * @draft ICU 64 + * @stable ICU 64 */ void reset(); @@ -89,7 +83,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * does not generally have well-defined behavior. * * @param category The field category to fix when iterating. - * @draft ICU 64 + * @stable ICU 64 */ void constrainCategory(int32_t category); @@ -114,7 +108,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * * @param category The field category to fix when iterating. * @param field The field to fix when iterating. - * @draft ICU 64 + * @stable ICU 64 */ void constrainField(int32_t category, int32_t field); @@ -125,7 +119,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * FormattedValue#nextPosition returns TRUE. * * @return The field category saved in the instance. - * @draft ICU 64 + * @stable ICU 64 */ inline int32_t getCategory() const { return fCategory; @@ -138,7 +132,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * FormattedValue#nextPosition returns TRUE. * * @return The field saved in the instance. - * @draft ICU 64 + * @stable ICU 64 */ inline int32_t getField() const { return fField; @@ -150,7 +144,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * The return value is well-defined only after FormattedValue#nextPosition returns TRUE. * * @return The start index saved in the instance. - * @draft ICU 64 + * @stable ICU 64 */ inline int32_t getStart() const { return fStart; @@ -162,7 +156,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * The return value is well-defined only after FormattedValue#nextPosition returns TRUE. * * @return The end index saved in the instance. - * @draft ICU 64 + * @stable ICU 64 */ inline int32_t getLimit() const { return fLimit; @@ -181,7 +175,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * Users of FormattedValue should not need to call this method. * * @return The current iteration context from {@link #setInt64IterationContext}. - * @draft ICU 64 + * @stable ICU 64 */ inline int64_t getInt64IterationContext() const { return fContext; @@ -193,7 +187,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * Intended to be used by FormattedValue implementations. * * @param context The new iteration context. - * @draft ICU 64 + * @stable ICU 64 */ void setInt64IterationContext(int64_t context); @@ -205,7 +199,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * * @param category The category to test. * @param field The field to test. - * @draft ICU 64 + * @stable ICU 64 */ UBool matchesField(int32_t category, int32_t field) const; @@ -221,39 +215,32 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory { * @param field The new field. * @param start The new inclusive start index. * @param limit The new exclusive end index. - * @draft ICU 64 + * @stable ICU 64 */ void setState( int32_t category, int32_t field, int32_t start, int32_t limit); -#endif /* U_HIDE_DRAFT_API */ private: int64_t fContext = 0LL; int32_t fField = 0; int32_t fStart = 0; int32_t fLimit = 0; -#ifndef U_HIDE_DRAFT_API int32_t fCategory = UFIELD_CATEGORY_UNDEFINED; -#else /* U_HIDE_DRAFT_API */ - int32_t fCategory = 0; -#endif /* U_HIDE_DRAFT_API */ int8_t fConstraint = 0; }; -// The following cannot have #ifndef U_HIDE_DRAFT_API because -// class FormattedNumber (stable ICU 60) depends on it. /** * An abstract formatted value: a string with associated field attributes. * Many formatters format to classes implementing FormattedValue. * - * @draft ICU 64 + * @stable ICU 64 */ class U_I18N_API FormattedValue /* not : public UObject because this is an interface/mixin class */ { public: - /** @draft ICU 64 */ + /** @stable ICU 64 */ virtual ~FormattedValue(); /** @@ -264,7 +251,7 @@ class U_I18N_API FormattedValue /* not : public UObject because this is an inter * @param status Set if an error occurs. * @return a UnicodeString containing the formatted string. * - * @draft ICU 64 + * @stable ICU 64 */ virtual UnicodeString toString(UErrorCode& status) const = 0; @@ -280,7 +267,7 @@ class U_I18N_API FormattedValue /* not : public UObject because this is an inter * @param status Set if an error occurs. * @return a temporary UnicodeString containing the formatted string. * - * @draft ICU 64 + * @stable ICU 64 */ virtual UnicodeString toTempString(UErrorCode& status) const = 0; @@ -292,7 +279,7 @@ class U_I18N_API FormattedValue /* not : public UObject because this is an inter * @param status Set if an error occurs. * @return The same Appendable, for chaining. * - * @draft ICU 64 + * @stable ICU 64 * @see Appendable */ virtual Appendable& appendTo(Appendable& appendable, UErrorCode& status) const = 0; @@ -317,11 +304,10 @@ class U_I18N_API FormattedValue /* not : public UObject because this is an inter * @return TRUE if a new occurrence of the field was found; * FALSE otherwise or if an error was set. * - * @draft ICU 64 + * @stable ICU 64 */ virtual UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const = 0; }; -#endif // U_FORCE_HIDE_DRAFT_API U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/unicode/listformatter.h b/deps/icu-small/source/i18n/unicode/listformatter.h index 88fc46cf37b2a3..a969a8744dcf58 100644 --- a/deps/icu-small/source/i18n/unicode/listformatter.h +++ b/deps/icu-small/source/i18n/unicode/listformatter.h @@ -26,10 +26,10 @@ #include "unicode/unistr.h" #include "unicode/locid.h" #include "unicode/formattedvalue.h" +#include "unicode/ulistformatter.h" U_NAMESPACE_BEGIN -class FieldPositionIterator; class FieldPositionHandler; class FormattedListData; class ListFormatter; @@ -50,9 +50,11 @@ struct ListFormatData : public UMemory { UnicodeString startPattern; UnicodeString middlePattern; UnicodeString endPattern; + Locale locale; - ListFormatData(const UnicodeString& two, const UnicodeString& start, const UnicodeString& middle, const UnicodeString& end) : - twoPattern(two), startPattern(start), middlePattern(middle), endPattern(end) {} + ListFormatData(const UnicodeString& two, const UnicodeString& start, const UnicodeString& middle, const UnicodeString& end, + const Locale& loc) : + twoPattern(two), startPattern(start), middlePattern(middle), endPattern(end), locale(loc) {} }; /** \endcond */ @@ -64,7 +66,6 @@ struct ListFormatData : public UMemory { #if !UCONFIG_NO_FORMATTING -#ifndef U_HIDE_DRAFT_API /** * An immutable class containing the result of a list formatting operation. * @@ -79,25 +80,25 @@ struct ListFormatData : public UMemory { * * Not intended for public subclassing. * - * @draft ICU 64 + * @stable ICU 64 */ class U_I18N_API FormattedList : public UMemory, public FormattedValue { public: /** * Default constructor; makes an empty FormattedList. - * @draft ICU 64 + * @stable ICU 64 */ FormattedList() : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {} /** * Move constructor: Leaves the source FormattedList in an undefined state. - * @draft ICU 64 + * @stable ICU 64 */ FormattedList(FormattedList&& src) U_NOEXCEPT; /** * Destruct an instance of FormattedList. - * @draft ICU 64 + * @stable ICU 64 */ virtual ~FormattedList() U_OVERRIDE; @@ -109,7 +110,7 @@ class U_I18N_API FormattedList : public UMemory, public FormattedValue { /** * Move assignment: Leaves the source FormattedList in an undefined state. - * @draft ICU 64 + * @stable ICU 64 */ FormattedList& operator=(FormattedList&& src) U_NOEXCEPT; @@ -134,7 +135,6 @@ class U_I18N_API FormattedList : public UMemory, public FormattedValue { : fData(nullptr), fErrorCode(errorCode) {} friend class ListFormatter; }; -#endif /* U_HIDE_DRAFT_API */ #endif // !UCONFIG_NO_FORMATTING @@ -185,10 +185,29 @@ class U_I18N_API ListFormatter : public UObject{ */ static ListFormatter* createInstance(const Locale& locale, UErrorCode& errorCode); +#ifndef U_HIDE_DRAFT_API +#if !UCONFIG_NO_FORMATTING + /** + * Creates a ListFormatter for the given locale, list type, and style. + * + * @param locale The locale. + * @param type The type of list formatting to use. + * @param width The width of formatting to use. + * @param errorCode ICU error code, set if no data available for the given locale. + * @return A ListFormatter object created from internal data derived from CLDR data. + * @draft ICU 67 + */ + static ListFormatter* createInstance( + const Locale& locale, UListFormatterType type, UListFormatterWidth width, UErrorCode& errorCode); +#endif /* !UCONFIG_NO_FORMATTING */ +#endif /* U_HIDE_DRAFT_API */ + #ifndef U_HIDE_INTERNAL_API /** * Creates a ListFormatter appropriate for a locale and style. * + * TODO(ICU-20888): Remove this in ICU 68. + * * @param locale The locale. * @param style the style, either "standard", "or", "unit", "unit-narrow", or "unit-short" * @param errorCode ICU error code, set if no data available for the given locale. @@ -220,29 +239,7 @@ class U_I18N_API ListFormatter : public UObject{ UnicodeString& format(const UnicodeString items[], int32_t n_items, UnicodeString& appendTo, UErrorCode& errorCode) const; -#ifndef U_HIDE_DRAFT_API - /** - * Format a list of strings. - * - * @param items An array of strings to be combined and formatted. - * @param n_items Length of the array items. - * @param appendTo The string to which the formatted result will be - * appended. - * @param posIter On return, can be used to iterate over positions of - * fields generated by this format call. Field values are - * defined in UListFormatterField. Can be NULL. - * @param errorCode ICU error code returned here. - * @return Formatted string combining the elements of items, - * appended to appendTo. - * @draft ICU 63 - */ - UnicodeString& format(const UnicodeString items[], int32_t n_items, - UnicodeString & appendTo, FieldPositionIterator* posIter, - UErrorCode& errorCode) const; -#endif // U_HIDE_DRAFT_API - #if !UCONFIG_NO_FORMATTING -#ifndef U_HIDE_DRAFT_API /** * Formats a list of strings to a FormattedList, which exposes field * position information. The FormattedList contains more information than @@ -252,13 +249,12 @@ class U_I18N_API ListFormatter : public UObject{ * @param n_items Length of the array items. * @param errorCode ICU error code returned here. * @return A FormattedList containing field information. - * @draft ICU 64 + * @stable ICU 64 */ FormattedList formatStringsToValue( const UnicodeString items[], int32_t n_items, UErrorCode& errorCode) const; -#endif /* U_HIDE_DRAFT_API */ #endif // !UCONFIG_NO_FORMATTING #ifndef U_HIDE_INTERNAL_API diff --git a/deps/icu-small/source/i18n/unicode/measunit.h b/deps/icu-small/source/i18n/unicode/measunit.h index 08f337cb5bb630..8b65497e12eb63 100644 --- a/deps/icu-small/source/i18n/unicode/measunit.h +++ b/deps/icu-small/source/i18n/unicode/measunit.h @@ -20,6 +20,7 @@ #if !UCONFIG_NO_FORMATTING #include "unicode/unistr.h" +#include "unicode/localpointer.h" /** * \file @@ -29,6 +30,202 @@ U_NAMESPACE_BEGIN class StringEnumeration; +struct MeasureUnitImpl; + +#ifndef U_HIDE_DRAFT_API +/** + * Enumeration for unit complexity. There are three levels: + * + * - SINGLE: A single unit, optionally with a power and/or SI prefix. Examples: hectare, + * square-kilometer, kilojoule, per-second. + * - COMPOUND: A unit composed of the product of multiple single units. Examples: + * meter-per-second, kilowatt-hour, kilogram-meter-per-square-second. + * - MIXED: A unit composed of the sum of multiple single units. Examples: foot+inch, + * hour+minute+second, degree+arcminute+arcsecond. + * + * The complexity determines which operations are available. For example, you cannot set the power + * or SI prefix of a compound unit. + * + * @draft ICU 67 + */ +enum UMeasureUnitComplexity { + /** + * A single unit, like kilojoule. + * + * @draft ICU 67 + */ + UMEASURE_UNIT_SINGLE, + + /** + * A compound unit, like meter-per-second. + * + * @draft ICU 67 + */ + UMEASURE_UNIT_COMPOUND, + + /** + * A mixed unit, like hour+minute. + * + * @draft ICU 67 + */ + UMEASURE_UNIT_MIXED +}; + +/** + * Enumeration for SI prefixes, such as "kilo". + * + * @draft ICU 67 + */ +typedef enum UMeasureSIPrefix { + + /** + * SI prefix: yotta, 10^24. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_YOTTA = 24, + + /** + * SI prefix: zetta, 10^21. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_ZETTA = 21, + + /** + * SI prefix: exa, 10^18. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_EXA = 18, + + /** + * SI prefix: peta, 10^15. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_PETA = 15, + + /** + * SI prefix: tera, 10^12. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_TERA = 12, + + /** + * SI prefix: giga, 10^9. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_GIGA = 9, + + /** + * SI prefix: mega, 10^6. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_MEGA = 6, + + /** + * SI prefix: kilo, 10^3. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_KILO = 3, + + /** + * SI prefix: hecto, 10^2. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_HECTO = 2, + + /** + * SI prefix: deka, 10^1. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_DEKA = 1, + + /** + * The absence of an SI prefix. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_ONE = 0, + + /** + * SI prefix: deci, 10^-1. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_DECI = -1, + + /** + * SI prefix: centi, 10^-2. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_CENTI = -2, + + /** + * SI prefix: milli, 10^-3. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_MILLI = -3, + + /** + * SI prefix: micro, 10^-6. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_MICRO = -6, + + /** + * SI prefix: nano, 10^-9. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_NANO = -9, + + /** + * SI prefix: pico, 10^-12. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_PICO = -12, + + /** + * SI prefix: femto, 10^-15. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_FEMTO = -15, + + /** + * SI prefix: atto, 10^-18. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_ATTO = -18, + + /** + * SI prefix: zepto, 10^-21. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_ZEPTO = -21, + + /** + * SI prefix: yocto, 10^-24. + * + * @draft ICU 67 + */ + UMEASURE_SI_PREFIX_YOCTO = -24 +} UMeasureSIPrefix; +#endif // U_HIDE_DRAFT_API /** * A unit such as length, mass, volume, currency, etc. A unit is @@ -53,12 +250,42 @@ class U_I18N_API MeasureUnit: public UObject { */ MeasureUnit(const MeasureUnit &other); +#ifndef U_HIDE_DRAFT_API + /** + * Move constructor. + * @draft ICU 67 + */ + MeasureUnit(MeasureUnit &&other) noexcept; + + /** + * Construct a MeasureUnit from a CLDR Unit Identifier, defined in UTS 35. + * Validates and canonicalizes the identifier. + * + *

+     * MeasureUnit example = MeasureUnit::forIdentifier("furlong-per-nanosecond")
+     * 
+ * + * @param identifier The CLDR Unit Identifier + * @param status Set if the identifier is invalid. + * @draft ICU 67 + */ + static MeasureUnit forIdentifier(StringPiece identifier, UErrorCode& status); +#endif // U_HIDE_DRAFT_API + /** - * Assignment operator. + * Copy assignment operator. * @stable ICU 3.0 */ MeasureUnit &operator=(const MeasureUnit &other); +#ifndef U_HIDE_DRAFT_API + /** + * Move assignment operator. + * @draft ICU 67 + */ + MeasureUnit &operator=(MeasureUnit &&other) noexcept; +#endif // U_HIDE_DRAFT_API + /** * Returns a polymorphic clone of this object. The result will * have the same class as returned by getDynamicClassID(). @@ -90,16 +317,156 @@ class U_I18N_API MeasureUnit: public UObject { /** * Get the type. + * + * If the unit does not have a type, the empty string is returned. + * * @stable ICU 53 */ const char *getType() const; /** * Get the sub type. + * + * If the unit does not have a subtype, the empty string is returned. + * * @stable ICU 53 */ const char *getSubtype() const; +#ifndef U_HIDE_DRAFT_API + /** + * Get the CLDR Unit Identifier for this MeasureUnit, as defined in UTS 35. + * + * @return The string form of this unit, owned by this MeasureUnit. + * @draft ICU 67 + */ + const char* getIdentifier() const; + + /** + * Compute the complexity of the unit. See UMeasureUnitComplexity for more information. + * + * @param status Set if an error occurs. + * @return The unit complexity. + * @draft ICU 67 + */ + UMeasureUnitComplexity getComplexity(UErrorCode& status) const; + + /** + * Creates a MeasureUnit which is this SINGLE unit augmented with the specified SI prefix. + * For example, UMEASURE_SI_PREFIX_KILO for "kilo". + * + * There is sufficient locale data to format all standard SI prefixes. + * + * NOTE: Only works on SINGLE units. If this is a COMPOUND or MIXED unit, an error will + * occur. For more information, see UMeasureUnitComplexity. + * + * @param prefix The SI prefix, from UMeasureSIPrefix. + * @param status Set if this is not a SINGLE unit or if another error occurs. + * @return A new SINGLE unit. + * @draft ICU 67 + */ + MeasureUnit withSIPrefix(UMeasureSIPrefix prefix, UErrorCode& status) const; + + /** + * Gets the current SI prefix of this SINGLE unit. For example, if the unit has the SI prefix + * "kilo", then UMEASURE_SI_PREFIX_KILO is returned. + * + * NOTE: Only works on SINGLE units. If this is a COMPOUND or MIXED unit, an error will + * occur. For more information, see UMeasureUnitComplexity. + * + * @param status Set if this is not a SINGLE unit or if another error occurs. + * @return The SI prefix of this SINGLE unit, from UMeasureSIPrefix. + * @draft ICU 67 + */ + UMeasureSIPrefix getSIPrefix(UErrorCode& status) const; + + /** + * Creates a MeasureUnit which is this SINGLE unit augmented with the specified dimensionality + * (power). For example, if dimensionality is 2, the unit will be squared. + * + * NOTE: Only works on SINGLE units. If this is a COMPOUND or MIXED unit, an error will + * occur. For more information, see UMeasureUnitComplexity. + * + * For the base dimensionless unit, withDimensionality does nothing. + * + * @param dimensionality The dimensionality (power). + * @param status Set if this is not a SINGLE unit or if another error occurs. + * @return A new SINGLE unit. + * @draft ICU 67 + */ + MeasureUnit withDimensionality(int32_t dimensionality, UErrorCode& status) const; + + /** + * Gets the dimensionality (power) of this MeasureUnit. For example, if the unit is square, + * then 2 is returned. + * + * NOTE: Only works on SINGLE units. If this is a COMPOUND or MIXED unit, an error will + * occur. For more information, see UMeasureUnitComplexity. + * + * For the base dimensionless unit, getDimensionality returns 0. + * + * @param status Set if this is not a SINGLE unit or if another error occurs. + * @return The dimensionality (power) of this simple unit. + * @draft ICU 67 + */ + int32_t getDimensionality(UErrorCode& status) const; + + /** + * Gets the reciprocal of this MeasureUnit, with the numerator and denominator flipped. + * + * For example, if the receiver is "meter-per-second", the unit "second-per-meter" is returned. + * + * NOTE: Only works on SINGLE and COMPOUND units. If this is a MIXED unit, an error will + * occur. For more information, see UMeasureUnitComplexity. + * + * @param status Set if this is a MIXED unit or if another error occurs. + * @return The reciprocal of the target unit. + * @draft ICU 67 + */ + MeasureUnit reciprocal(UErrorCode& status) const; + + /** + * Gets the product of this unit with another unit. This is a way to build units from + * constituent parts. + * + * The numerator and denominator are preserved through this operation. + * + * For example, if the receiver is "kilowatt" and the argument is "hour-per-day", then the + * unit "kilowatt-hour-per-day" is returned. + * + * NOTE: Only works on SINGLE and COMPOUND units. If either unit (receivee and argument) is a + * MIXED unit, an error will occur. For more information, see UMeasureUnitComplexity. + * + * @param other The MeasureUnit to multiply with the target. + * @param status Set if this or other is a MIXED unit or if another error occurs. + * @return The product of the target unit with the provided unit. + * @draft ICU 67 + */ + MeasureUnit product(const MeasureUnit& other, UErrorCode& status) const; +#endif // U_HIDE_DRAFT_API + +#ifndef U_HIDE_INTERNAL_API + /** + * Gets the list of SINGLE units contained within a MIXED of COMPOUND unit. + * + * Examples: + * - Given "meter-kilogram-per-second", three units will be returned: "meter", + * "kilogram", and "per-second". + * - Given "hour+minute+second", three units will be returned: "hour", "minute", + * and "second". + * + * If this is a SINGLE unit, an array of length 1 will be returned. + * + * TODO(ICU-21021): Finalize this API and propose it as draft. + * + * @param outCount The number of elements in the return array. + * @param status Set if an error occurs. + * @return An array of single units, owned by the caller. + * @internal ICU 67 Technical Preview + */ + LocalArray splitToSingleUnits(int32_t& outCount, UErrorCode& status) const; +#endif // U_HIDE_INTERNAL_API + /** * getAvailable gets all of the available units. * If there are too many units to fit into destCapacity then the @@ -219,17 +586,15 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGForce(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of acceleration: g-force. * Also see {@link #createGForce()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGForce(); -#endif /* U_HIDE_DRAFT_API */ /** - * Returns by pointer, unit of acceleration: meter-per-second-squared. + * Returns by pointer, unit of acceleration: meter-per-square-second. * Caller owns returned value and must free it. * Also see {@link #getMeterPerSecondSquared()}. * @param status ICU error code. @@ -237,14 +602,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMeterPerSecondSquared(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** - * Returns by value, unit of acceleration: meter-per-second-squared. + * Returns by value, unit of acceleration: meter-per-square-second. * Also see {@link #createMeterPerSecondSquared()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMeterPerSecondSquared(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of angle: arc-minute. @@ -255,14 +618,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createArcMinute(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of angle: arc-minute. * Also see {@link #createArcMinute()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getArcMinute(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of angle: arc-second. @@ -273,14 +634,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createArcSecond(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of angle: arc-second. * Also see {@link #createArcSecond()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getArcSecond(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of angle: degree. @@ -291,14 +650,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createDegree(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of angle: degree. * Also see {@link #createDegree()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getDegree(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of angle: radian. @@ -309,14 +666,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createRadian(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of angle: radian. * Also see {@link #createRadian()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getRadian(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of angle: revolution. @@ -327,14 +682,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createRevolutionAngle(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of angle: revolution. * Also see {@link #createRevolutionAngle()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getRevolutionAngle(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: acre. @@ -345,32 +698,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createAcre(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: acre. * Also see {@link #createAcre()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getAcre(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of area: dunam. * Caller owns returned value and must free it. * Also see {@link #getDunam()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createDunam(UErrorCode &status); /** * Returns by value, unit of area: dunam. * Also see {@link #createDunam()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getDunam(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: hectare. @@ -381,14 +730,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createHectare(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: hectare. * Also see {@link #createHectare()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getHectare(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: square-centimeter. @@ -399,14 +746,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSquareCentimeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: square-centimeter. * Also see {@link #createSquareCentimeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSquareCentimeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: square-foot. @@ -417,14 +762,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSquareFoot(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: square-foot. * Also see {@link #createSquareFoot()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSquareFoot(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: square-inch. @@ -435,14 +778,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSquareInch(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: square-inch. * Also see {@link #createSquareInch()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSquareInch(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: square-kilometer. @@ -453,14 +794,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSquareKilometer(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: square-kilometer. * Also see {@link #createSquareKilometer()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSquareKilometer(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: square-meter. @@ -471,14 +810,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSquareMeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: square-meter. * Also see {@link #createSquareMeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSquareMeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: square-mile. @@ -489,14 +826,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSquareMile(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: square-mile. * Also see {@link #createSquareMile()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSquareMile(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of area: square-yard. @@ -507,14 +842,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSquareYard(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of area: square-yard. * Also see {@link #createSquareYard()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSquareYard(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of concentr: karat. @@ -525,14 +858,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKarat(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of concentr: karat. * Also see {@link #createKarat()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKarat(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of concentr: milligram-per-deciliter. @@ -543,14 +874,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilligramPerDeciliter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of concentr: milligram-per-deciliter. * Also see {@link #createMilligramPerDeciliter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilligramPerDeciliter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of concentr: millimole-per-liter. @@ -561,35 +890,31 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMillimolePerLiter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of concentr: millimole-per-liter. * Also see {@link #createMillimolePerLiter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMillimolePerLiter(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of concentr: mole. * Caller owns returned value and must free it. * Also see {@link #getMole()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createMole(UErrorCode &status); /** * Returns by value, unit of concentr: mole. * Also see {@link #createMole()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMole(); -#endif /* U_HIDE_DRAFT_API */ /** - * Returns by pointer, unit of concentr: part-per-million. + * Returns by pointer, unit of concentr: permillion. * Caller owns returned value and must free it. * Also see {@link #getPartPerMillion()}. * @param status ICU error code. @@ -597,14 +922,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPartPerMillion(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** - * Returns by value, unit of concentr: part-per-million. + * Returns by value, unit of concentr: permillion. * Also see {@link #createPartPerMillion()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPartPerMillion(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of concentr: percent. @@ -615,14 +938,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPercent(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of concentr: percent. * Also see {@link #createPercent()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPercent(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of concentr: permille. @@ -633,35 +954,31 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPermille(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of concentr: permille. * Also see {@link #createPermille()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPermille(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of concentr: permyriad. * Caller owns returned value and must free it. * Also see {@link #getPermyriad()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createPermyriad(UErrorCode &status); /** * Returns by value, unit of concentr: permyriad. * Also see {@link #createPermyriad()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPermyriad(); -#endif /* U_HIDE_DRAFT_API */ /** - * Returns by pointer, unit of consumption: liter-per-100kilometers. + * Returns by pointer, unit of consumption: liter-per-100-kilometer. * Caller owns returned value and must free it. * Also see {@link #getLiterPer100Kilometers()}. * @param status ICU error code. @@ -669,14 +986,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createLiterPer100Kilometers(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** - * Returns by value, unit of consumption: liter-per-100kilometers. + * Returns by value, unit of consumption: liter-per-100-kilometer. * Also see {@link #createLiterPer100Kilometers()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getLiterPer100Kilometers(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of consumption: liter-per-kilometer. @@ -687,14 +1002,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createLiterPerKilometer(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of consumption: liter-per-kilometer. * Also see {@link #createLiterPerKilometer()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getLiterPerKilometer(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of consumption: mile-per-gallon. @@ -705,14 +1018,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilePerGallon(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of consumption: mile-per-gallon. * Also see {@link #createMilePerGallon()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilePerGallon(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of consumption: mile-per-gallon-imperial. @@ -723,14 +1034,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilePerGallonImperial(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of consumption: mile-per-gallon-imperial. * Also see {@link #createMilePerGallonImperial()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilePerGallonImperial(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: bit. @@ -741,14 +1050,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createBit(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: bit. * Also see {@link #createBit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getBit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: byte. @@ -759,14 +1066,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createByte(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: byte. * Also see {@link #createByte()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getByte(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: gigabit. @@ -777,14 +1082,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGigabit(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: gigabit. * Also see {@link #createGigabit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGigabit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: gigabyte. @@ -795,14 +1098,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGigabyte(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: gigabyte. * Also see {@link #createGigabyte()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGigabyte(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: kilobit. @@ -813,14 +1114,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilobit(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: kilobit. * Also see {@link #createKilobit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilobit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: kilobyte. @@ -831,14 +1130,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilobyte(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: kilobyte. * Also see {@link #createKilobyte()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilobyte(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: megabit. @@ -849,14 +1146,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMegabit(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: megabit. * Also see {@link #createMegabit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMegabit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: megabyte. @@ -867,14 +1162,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMegabyte(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: megabyte. * Also see {@link #createMegabyte()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMegabyte(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: petabyte. @@ -885,14 +1178,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPetabyte(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: petabyte. * Also see {@link #createPetabyte()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPetabyte(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: terabit. @@ -903,14 +1194,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createTerabit(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: terabit. * Also see {@link #createTerabit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getTerabit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of digital: terabyte. @@ -921,14 +1210,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createTerabyte(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of digital: terabyte. * Also see {@link #createTerabyte()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getTerabyte(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: century. @@ -939,14 +1226,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCentury(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: century. * Also see {@link #createCentury()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCentury(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: day. @@ -957,32 +1242,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createDay(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: day. * Also see {@link #createDay()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getDay(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of duration: day-person. * Caller owns returned value and must free it. * Also see {@link #getDayPerson()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createDayPerson(UErrorCode &status); /** * Returns by value, unit of duration: day-person. * Also see {@link #createDayPerson()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getDayPerson(); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API /** @@ -1011,14 +1292,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createHour(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: hour. * Also see {@link #createHour()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getHour(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: microsecond. @@ -1029,14 +1308,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMicrosecond(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: microsecond. * Also see {@link #createMicrosecond()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMicrosecond(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: millisecond. @@ -1047,14 +1324,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMillisecond(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: millisecond. * Also see {@link #createMillisecond()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMillisecond(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: minute. @@ -1065,14 +1340,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMinute(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: minute. * Also see {@link #createMinute()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMinute(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: month. @@ -1083,32 +1356,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMonth(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: month. * Also see {@link #createMonth()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMonth(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of duration: month-person. * Caller owns returned value and must free it. * Also see {@link #getMonthPerson()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createMonthPerson(UErrorCode &status); /** * Returns by value, unit of duration: month-person. * Also see {@link #createMonthPerson()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMonthPerson(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: nanosecond. @@ -1119,14 +1388,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createNanosecond(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: nanosecond. * Also see {@link #createNanosecond()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getNanosecond(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: second. @@ -1137,14 +1404,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createSecond(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: second. * Also see {@link #createSecond()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSecond(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: week. @@ -1155,32 +1420,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createWeek(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: week. * Also see {@link #createWeek()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getWeek(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of duration: week-person. * Caller owns returned value and must free it. * Also see {@link #getWeekPerson()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createWeekPerson(UErrorCode &status); /** * Returns by value, unit of duration: week-person. * Also see {@link #createWeekPerson()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getWeekPerson(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of duration: year. @@ -1191,32 +1452,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createYear(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: year. * Also see {@link #createYear()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getYear(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of duration: year-person. * Caller owns returned value and must free it. * Also see {@link #getYearPerson()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createYearPerson(UErrorCode &status); /** * Returns by value, unit of duration: year-person. * Also see {@link #createYearPerson()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getYearPerson(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of electric: ampere. @@ -1227,14 +1484,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createAmpere(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of electric: ampere. * Also see {@link #createAmpere()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getAmpere(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of electric: milliampere. @@ -1245,14 +1500,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilliampere(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of electric: milliampere. * Also see {@link #createMilliampere()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilliampere(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of electric: ohm. @@ -1263,14 +1516,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createOhm(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of electric: ohm. * Also see {@link #createOhm()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getOhm(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of electric: volt. @@ -1281,32 +1532,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createVolt(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of electric: volt. * Also see {@link #createVolt()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getVolt(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of energy: british-thermal-unit. * Caller owns returned value and must free it. * Also see {@link #getBritishThermalUnit()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createBritishThermalUnit(UErrorCode &status); /** * Returns by value, unit of energy: british-thermal-unit. * Also see {@link #createBritishThermalUnit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getBritishThermalUnit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of energy: calorie. @@ -1317,32 +1564,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCalorie(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of energy: calorie. * Also see {@link #createCalorie()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCalorie(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of energy: electronvolt. * Caller owns returned value and must free it. * Also see {@link #getElectronvolt()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createElectronvolt(UErrorCode &status); /** * Returns by value, unit of energy: electronvolt. * Also see {@link #createElectronvolt()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getElectronvolt(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of energy: foodcalorie. @@ -1353,14 +1596,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createFoodcalorie(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of energy: foodcalorie. * Also see {@link #createFoodcalorie()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getFoodcalorie(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of energy: joule. @@ -1371,14 +1612,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createJoule(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of energy: joule. * Also see {@link #createJoule()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getJoule(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of energy: kilocalorie. @@ -1389,14 +1628,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilocalorie(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of energy: kilocalorie. * Also see {@link #createKilocalorie()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilocalorie(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of energy: kilojoule. @@ -1407,14 +1644,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilojoule(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of energy: kilojoule. * Also see {@link #createKilojoule()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilojoule(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of energy: kilowatt-hour. @@ -1425,14 +1660,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilowattHour(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of energy: kilowatt-hour. * Also see {@link #createKilowattHour()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilowattHour(); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API /** @@ -1452,41 +1685,37 @@ class U_I18N_API MeasureUnit: public UObject { static MeasureUnit getThermUs(); #endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of force: newton. * Caller owns returned value and must free it. * Also see {@link #getNewton()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createNewton(UErrorCode &status); /** * Returns by value, unit of force: newton. * Also see {@link #createNewton()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getNewton(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of force: pound-force. * Caller owns returned value and must free it. * Also see {@link #getPoundForce()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createPoundForce(UErrorCode &status); /** * Returns by value, unit of force: pound-force. * Also see {@link #createPoundForce()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPoundForce(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of frequency: gigahertz. @@ -1497,14 +1726,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGigahertz(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of frequency: gigahertz. * Also see {@link #createGigahertz()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGigahertz(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of frequency: hertz. @@ -1515,14 +1742,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createHertz(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of frequency: hertz. * Also see {@link #createHertz()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getHertz(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of frequency: kilohertz. @@ -1533,14 +1758,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilohertz(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of frequency: kilohertz. * Also see {@link #createKilohertz()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilohertz(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of frequency: megahertz. @@ -1551,14 +1774,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMegahertz(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of frequency: megahertz. * Also see {@link #createMegahertz()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMegahertz(); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API /** @@ -1695,14 +1916,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createAstronomicalUnit(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: astronomical-unit. * Also see {@link #createAstronomicalUnit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getAstronomicalUnit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: centimeter. @@ -1713,14 +1932,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCentimeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: centimeter. * Also see {@link #createCentimeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCentimeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: decimeter. @@ -1731,14 +1948,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createDecimeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: decimeter. * Also see {@link #createDecimeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getDecimeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: fathom. @@ -1749,14 +1964,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createFathom(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: fathom. * Also see {@link #createFathom()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getFathom(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: foot. @@ -1767,14 +1980,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createFoot(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: foot. * Also see {@link #createFoot()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getFoot(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: furlong. @@ -1785,14 +1996,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createFurlong(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: furlong. * Also see {@link #createFurlong()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getFurlong(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: inch. @@ -1803,14 +2012,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createInch(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: inch. * Also see {@link #createInch()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getInch(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: kilometer. @@ -1821,14 +2028,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilometer(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: kilometer. * Also see {@link #createKilometer()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilometer(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: light-year. @@ -1839,14 +2044,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createLightYear(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: light-year. * Also see {@link #createLightYear()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getLightYear(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: meter. @@ -1857,14 +2060,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: meter. * Also see {@link #createMeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: micrometer. @@ -1875,14 +2076,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMicrometer(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: micrometer. * Also see {@link #createMicrometer()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMicrometer(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: mile. @@ -1893,14 +2092,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMile(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: mile. * Also see {@link #createMile()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMile(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: mile-scandinavian. @@ -1911,14 +2108,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMileScandinavian(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: mile-scandinavian. * Also see {@link #createMileScandinavian()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMileScandinavian(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: millimeter. @@ -1929,14 +2124,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMillimeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: millimeter. * Also see {@link #createMillimeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMillimeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: nanometer. @@ -1947,14 +2140,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createNanometer(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: nanometer. * Also see {@link #createNanometer()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getNanometer(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: nautical-mile. @@ -1965,14 +2156,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createNauticalMile(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: nautical-mile. * Also see {@link #createNauticalMile()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getNauticalMile(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: parsec. @@ -1983,14 +2172,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createParsec(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: parsec. * Also see {@link #createParsec()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getParsec(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: picometer. @@ -2001,14 +2188,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPicometer(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: picometer. * Also see {@link #createPicometer()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPicometer(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: point. @@ -2019,32 +2204,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPoint(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: point. * Also see {@link #createPoint()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPoint(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of length: solar-radius. * Caller owns returned value and must free it. * Also see {@link #getSolarRadius()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createSolarRadius(UErrorCode &status); /** * Returns by value, unit of length: solar-radius. * Also see {@link #createSolarRadius()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSolarRadius(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of length: yard. @@ -2055,14 +2236,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createYard(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of length: yard. * Also see {@link #createYard()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getYard(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of light: lux. @@ -2073,32 +2252,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createLux(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of light: lux. * Also see {@link #createLux()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getLux(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of light: solar-luminosity. * Caller owns returned value and must free it. * Also see {@link #getSolarLuminosity()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createSolarLuminosity(UErrorCode &status); /** * Returns by value, unit of light: solar-luminosity. * Also see {@link #createSolarLuminosity()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSolarLuminosity(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: carat. @@ -2109,50 +2284,44 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCarat(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: carat. * Also see {@link #createCarat()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCarat(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of mass: dalton. * Caller owns returned value and must free it. * Also see {@link #getDalton()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createDalton(UErrorCode &status); /** * Returns by value, unit of mass: dalton. * Also see {@link #createDalton()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getDalton(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of mass: earth-mass. * Caller owns returned value and must free it. * Also see {@link #getEarthMass()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createEarthMass(UErrorCode &status); /** * Returns by value, unit of mass: earth-mass. * Also see {@link #createEarthMass()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getEarthMass(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: gram. @@ -2163,14 +2332,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGram(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: gram. * Also see {@link #createGram()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGram(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: kilogram. @@ -2181,14 +2348,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilogram(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: kilogram. * Also see {@link #createKilogram()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilogram(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: metric-ton. @@ -2199,14 +2364,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMetricTon(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: metric-ton. * Also see {@link #createMetricTon()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMetricTon(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: microgram. @@ -2217,14 +2380,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMicrogram(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: microgram. * Also see {@link #createMicrogram()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMicrogram(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: milligram. @@ -2235,14 +2396,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilligram(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: milligram. * Also see {@link #createMilligram()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilligram(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: ounce. @@ -2253,14 +2412,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createOunce(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: ounce. * Also see {@link #createOunce()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getOunce(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: ounce-troy. @@ -2271,14 +2428,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createOunceTroy(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: ounce-troy. * Also see {@link #createOunceTroy()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getOunceTroy(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: pound. @@ -2289,32 +2444,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPound(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: pound. * Also see {@link #createPound()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPound(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of mass: solar-mass. * Caller owns returned value and must free it. * Also see {@link #getSolarMass()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createSolarMass(UErrorCode &status); /** * Returns by value, unit of mass: solar-mass. * Also see {@link #createSolarMass()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getSolarMass(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: stone. @@ -2325,14 +2476,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createStone(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: stone. * Also see {@link #createStone()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getStone(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of mass: ton. @@ -2343,14 +2492,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createTon(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of mass: ton. * Also see {@link #createTon()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getTon(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of power: gigawatt. @@ -2361,14 +2508,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGigawatt(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of power: gigawatt. * Also see {@link #createGigawatt()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGigawatt(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of power: horsepower. @@ -2379,14 +2524,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createHorsepower(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of power: horsepower. * Also see {@link #createHorsepower()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getHorsepower(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of power: kilowatt. @@ -2397,14 +2540,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilowatt(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of power: kilowatt. * Also see {@link #createKilowatt()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilowatt(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of power: megawatt. @@ -2415,14 +2556,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMegawatt(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of power: megawatt. * Also see {@link #createMegawatt()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMegawatt(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of power: milliwatt. @@ -2433,14 +2572,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilliwatt(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of power: milliwatt. * Also see {@link #createMilliwatt()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilliwatt(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of power: watt. @@ -2451,14 +2588,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createWatt(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of power: watt. * Also see {@link #createWatt()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getWatt(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of pressure: atmosphere. @@ -2469,14 +2604,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createAtmosphere(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of pressure: atmosphere. * Also see {@link #createAtmosphere()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getAtmosphere(); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API /** @@ -2505,17 +2638,15 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createHectopascal(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of pressure: hectopascal. * Also see {@link #createHectopascal()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getHectopascal(); -#endif /* U_HIDE_DRAFT_API */ /** - * Returns by pointer, unit of pressure: inch-hg. + * Returns by pointer, unit of pressure: inch-ofhg. * Caller owns returned value and must free it. * Also see {@link #getInchHg()}. * @param status ICU error code. @@ -2523,50 +2654,44 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createInchHg(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** - * Returns by value, unit of pressure: inch-hg. + * Returns by value, unit of pressure: inch-ofhg. * Also see {@link #createInchHg()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getInchHg(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of pressure: kilopascal. * Caller owns returned value and must free it. * Also see {@link #getKilopascal()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createKilopascal(UErrorCode &status); /** * Returns by value, unit of pressure: kilopascal. * Also see {@link #createKilopascal()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilopascal(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of pressure: megapascal. * Caller owns returned value and must free it. * Also see {@link #getMegapascal()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createMegapascal(UErrorCode &status); /** * Returns by value, unit of pressure: megapascal. * Also see {@link #createMegapascal()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMegapascal(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of pressure: millibar. @@ -2577,17 +2702,15 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMillibar(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of pressure: millibar. * Also see {@link #createMillibar()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMillibar(); -#endif /* U_HIDE_DRAFT_API */ /** - * Returns by pointer, unit of pressure: millimeter-of-mercury. + * Returns by pointer, unit of pressure: millimeter-ofhg. * Caller owns returned value and must free it. * Also see {@link #getMillimeterOfMercury()}. * @param status ICU error code. @@ -2595,14 +2718,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMillimeterOfMercury(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** - * Returns by value, unit of pressure: millimeter-of-mercury. + * Returns by value, unit of pressure: millimeter-ofhg. * Also see {@link #createMillimeterOfMercury()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMillimeterOfMercury(); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API /** @@ -2623,7 +2744,7 @@ class U_I18N_API MeasureUnit: public UObject { #endif /* U_HIDE_DRAFT_API */ /** - * Returns by pointer, unit of pressure: pound-per-square-inch. + * Returns by pointer, unit of pressure: pound-force-per-square-inch. * Caller owns returned value and must free it. * Also see {@link #getPoundPerSquareInch()}. * @param status ICU error code. @@ -2631,14 +2752,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPoundPerSquareInch(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** - * Returns by value, unit of pressure: pound-per-square-inch. + * Returns by value, unit of pressure: pound-force-per-square-inch. * Also see {@link #createPoundPerSquareInch()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPoundPerSquareInch(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of speed: kilometer-per-hour. @@ -2649,14 +2768,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKilometerPerHour(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of speed: kilometer-per-hour. * Also see {@link #createKilometerPerHour()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKilometerPerHour(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of speed: knot. @@ -2667,14 +2784,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKnot(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of speed: knot. * Also see {@link #createKnot()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKnot(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of speed: meter-per-second. @@ -2685,14 +2800,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMeterPerSecond(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of speed: meter-per-second. * Also see {@link #createMeterPerSecond()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMeterPerSecond(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of speed: mile-per-hour. @@ -2703,14 +2816,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilePerHour(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of speed: mile-per-hour. * Also see {@link #createMilePerHour()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilePerHour(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of temperature: celsius. @@ -2721,14 +2832,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCelsius(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of temperature: celsius. * Also see {@link #createCelsius()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCelsius(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of temperature: fahrenheit. @@ -2739,14 +2848,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createFahrenheit(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of temperature: fahrenheit. * Also see {@link #createFahrenheit()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getFahrenheit(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of temperature: generic. @@ -2757,14 +2864,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGenericTemperature(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of temperature: generic. * Also see {@link #createGenericTemperature()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGenericTemperature(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of temperature: kelvin. @@ -2775,50 +2880,44 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createKelvin(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of temperature: kelvin. * Also see {@link #createKelvin()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getKelvin(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of torque: newton-meter. * Caller owns returned value and must free it. * Also see {@link #getNewtonMeter()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createNewtonMeter(UErrorCode &status); /** * Returns by value, unit of torque: newton-meter. * Also see {@link #createNewtonMeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getNewtonMeter(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** - * Returns by pointer, unit of torque: pound-foot. + * Returns by pointer, unit of torque: pound-force-foot. * Caller owns returned value and must free it. * Also see {@link #getPoundFoot()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createPoundFoot(UErrorCode &status); /** - * Returns by value, unit of torque: pound-foot. + * Returns by value, unit of torque: pound-force-foot. * Also see {@link #createPoundFoot()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPoundFoot(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: acre-foot. @@ -2829,32 +2928,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createAcreFoot(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: acre-foot. * Also see {@link #createAcreFoot()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getAcreFoot(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of volume: barrel. * Caller owns returned value and must free it. * Also see {@link #getBarrel()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createBarrel(UErrorCode &status); /** * Returns by value, unit of volume: barrel. * Also see {@link #createBarrel()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getBarrel(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: bushel. @@ -2865,14 +2960,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createBushel(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: bushel. * Also see {@link #createBushel()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getBushel(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: centiliter. @@ -2883,14 +2976,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCentiliter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: centiliter. * Also see {@link #createCentiliter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCentiliter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cubic-centimeter. @@ -2901,14 +2992,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCubicCentimeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cubic-centimeter. * Also see {@link #createCubicCentimeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCubicCentimeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cubic-foot. @@ -2919,14 +3008,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCubicFoot(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cubic-foot. * Also see {@link #createCubicFoot()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCubicFoot(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cubic-inch. @@ -2937,14 +3024,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCubicInch(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cubic-inch. * Also see {@link #createCubicInch()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCubicInch(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cubic-kilometer. @@ -2955,14 +3040,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCubicKilometer(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cubic-kilometer. * Also see {@link #createCubicKilometer()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCubicKilometer(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cubic-meter. @@ -2973,14 +3056,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCubicMeter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cubic-meter. * Also see {@link #createCubicMeter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCubicMeter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cubic-mile. @@ -2991,14 +3072,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCubicMile(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cubic-mile. * Also see {@link #createCubicMile()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCubicMile(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cubic-yard. @@ -3009,14 +3088,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCubicYard(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cubic-yard. * Also see {@link #createCubicYard()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCubicYard(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cup. @@ -3027,14 +3104,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCup(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cup. * Also see {@link #createCup()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCup(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: cup-metric. @@ -3045,14 +3120,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createCupMetric(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: cup-metric. * Also see {@link #createCupMetric()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getCupMetric(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: deciliter. @@ -3063,14 +3136,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createDeciliter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: deciliter. * Also see {@link #createDeciliter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getDeciliter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: fluid-ounce. @@ -3081,32 +3152,28 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createFluidOunce(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: fluid-ounce. * Also see {@link #createFluidOunce()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getFluidOunce(); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of volume: fluid-ounce-imperial. * Caller owns returned value and must free it. * Also see {@link #getFluidOunceImperial()}. * @param status ICU error code. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit *createFluidOunceImperial(UErrorCode &status); /** * Returns by value, unit of volume: fluid-ounce-imperial. * Also see {@link #createFluidOunceImperial()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getFluidOunceImperial(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: gallon. @@ -3117,14 +3184,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGallon(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: gallon. * Also see {@link #createGallon()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGallon(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: gallon-imperial. @@ -3135,14 +3200,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createGallonImperial(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: gallon-imperial. * Also see {@link #createGallonImperial()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getGallonImperial(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: hectoliter. @@ -3153,14 +3216,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createHectoliter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: hectoliter. * Also see {@link #createHectoliter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getHectoliter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: liter. @@ -3171,14 +3232,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createLiter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: liter. * Also see {@link #createLiter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getLiter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: megaliter. @@ -3189,14 +3248,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMegaliter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: megaliter. * Also see {@link #createMegaliter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMegaliter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: milliliter. @@ -3207,14 +3264,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilliliter(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: milliliter. * Also see {@link #createMilliliter()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getMilliliter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: pint. @@ -3225,14 +3280,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPint(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: pint. * Also see {@link #createPint()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPint(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: pint-metric. @@ -3243,14 +3296,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPintMetric(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: pint-metric. * Also see {@link #createPintMetric()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getPintMetric(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: quart. @@ -3261,14 +3312,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createQuart(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: quart. * Also see {@link #createQuart()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getQuart(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: tablespoon. @@ -3279,14 +3328,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createTablespoon(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: tablespoon. * Also see {@link #createTablespoon()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getTablespoon(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of volume: teaspoon. @@ -3297,14 +3344,12 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createTeaspoon(UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of volume: teaspoon. * Also see {@link #createTeaspoon()}. - * @draft ICU 64 + * @stable ICU 64 */ static MeasureUnit getTeaspoon(); -#endif /* U_HIDE_DRAFT_API */ // End generated createXXX methods @@ -3322,7 +3367,7 @@ class U_I18N_API MeasureUnit: public UObject { * For ICU use only. * @internal */ - void initCurrency(const char *isoCurrency); + void initCurrency(StringPiece isoCurrency); /** * For ICU use only. @@ -3333,16 +3378,34 @@ class U_I18N_API MeasureUnit: public UObject { #endif /* U_HIDE_INTERNAL_API */ private: - int32_t fTypeId; - int32_t fSubTypeId; - char fCurrency[4]; - MeasureUnit(int32_t typeId, int32_t subTypeId) : fTypeId(typeId), fSubTypeId(subTypeId) { - fCurrency[0] = 0; - } + // Used by new draft APIs in ICU 67. If non-null, fImpl is owned by the + // MeasureUnit. + MeasureUnitImpl* fImpl; + + // An index into a static string list in measunit.cpp. If set to -1, fImpl + // is in use instead of fTypeId and fSubTypeId. + int16_t fSubTypeId; + // An index into a static string list in measunit.cpp. If set to -1, fImpl + // is in use instead of fTypeId and fSubTypeId. + int8_t fTypeId; + + MeasureUnit(int32_t typeId, int32_t subTypeId); + MeasureUnit(MeasureUnitImpl&& impl); void setTo(int32_t typeId, int32_t subTypeId); int32_t getOffset() const; static MeasureUnit *create(int typeId, int subTypeId, UErrorCode &status); + + /** + * Sets output's typeId and subTypeId according to subType, if subType is a + * valid/known identifier. + * + * @return Whether subType is known to ICU. If false, output was not + * modified. + */ + static bool findBySubType(StringPiece subType, MeasureUnit* output); + + friend struct MeasureUnitImpl; }; U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/unicode/numberformatter.h b/deps/icu-small/source/i18n/unicode/numberformatter.h index 6d48f18ab55a4d..615cf49f7b7539 100644 --- a/deps/icu-small/source/i18n/unicode/numberformatter.h +++ b/deps/icu-small/source/i18n/unicode/numberformatter.h @@ -155,6 +155,8 @@ class DecNum; class NumberRangeFormatterImpl; struct RangeMacroProps; struct UFormattedNumberImpl; +class MutablePatternModifier; +class ImmutablePatternModifier; /** * Used for NumberRangeFormatter and implemented in numrange_fluent.cpp. @@ -980,9 +982,13 @@ class U_I18N_API IntegerWidth : public UMemory { friend struct impl::MacroProps; friend struct impl::MicroProps; - // To allow NumberFormatterImpl to access isBogus() and perform other operations: + // To allow NumberFormatterImpl to access isBogus(): friend class impl::NumberFormatterImpl; + // To allow the use of this class when formatting: + friend class impl::MutablePatternModifier; + friend class impl::ImmutablePatternModifier; + // So that NumberPropertyMapper can create instances friend class impl::NumberPropertyMapper; @@ -1409,9 +1415,6 @@ struct U_I18N_API MacroProps : public UMemory { /** @internal */ const PluralRules* rules = nullptr; // no ownership - /** @internal */ - const CurrencySymbols* currencySymbols = nullptr; // no ownership - /** @internal */ int32_t threshold = kInternalDefaultThreshold; @@ -1433,6 +1436,16 @@ struct U_I18N_API MacroProps : public UMemory { } // namespace impl +#if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER) +// Ignore MSVC warning 4661. This is generated for NumberFormatterSettings<>::toSkeleton() as this method +// is defined elsewhere (in number_skeletons.cpp). The compiler is warning that the explicit template instantiation +// inside this single translation unit (CPP file) is incomplete, and thus it isn't sure if the template class is +// fully defined. However, since each translation unit explicitly instantiates all the necessary template classes, +// they will all be passed to the linker, and the linker will still find and export all the class members. +#pragma warning(push) +#pragma warning(disable: 4661) +#endif + /** * An abstract base class for specifying settings related to number formatting. This class is implemented by * {@link UnlocalizedNumberFormatter} and {@link LocalizedNumberFormatter}. This class is not intended for @@ -2082,7 +2095,6 @@ class U_I18N_API NumberFormatterSettings { */ UnicodeString toSkeleton(UErrorCode& status) const; -#ifndef U_HIDE_DRAFT_API /** * Returns the current (Un)LocalizedNumberFormatter as a LocalPointer * wrapping a heap-allocated copy of the current object. @@ -2092,7 +2104,7 @@ class U_I18N_API NumberFormatterSettings { * * @return A wrapped (Un)LocalizedNumberFormatter pointer, or a wrapped * nullptr on failure. - * @draft ICU 64 + * @stable ICU 64 */ LocalPointer clone() const &; @@ -2101,10 +2113,9 @@ class U_I18N_API NumberFormatterSettings { * * @return A wrapped (Un)LocalizedNumberFormatter pointer, or a wrapped * nullptr on failure. - * @draft ICU 64 + * @stable ICU 64 */ LocalPointer clone() &&; -#endif /* U_HIDE_DRAFT_API */ /** * Sets the UErrorCode if an error occurred in the fluent chain. @@ -2399,6 +2410,11 @@ class U_I18N_API LocalizedNumberFormatter friend class UnlocalizedNumberFormatter; }; +#if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER) +// Warning 4661. +#pragma warning(pop) +#endif + /** * The result of a number formatting operation. This class allows the result to be exported in several data types, * including a UnicodeString and a FieldPositionIterator. @@ -2410,15 +2426,12 @@ class U_I18N_API LocalizedNumberFormatter class U_I18N_API FormattedNumber : public UMemory, public FormattedValue { public: - // Default constructor cannot have #ifndef U_HIDE_DRAFT_API -#ifndef U_FORCE_HIDE_DRAFT_API /** * Default constructor; makes an empty FormattedNumber. - * @draft ICU 64 + * @stable ICU 64 */ FormattedNumber() : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {} -#endif // U_FORCE_HIDE_DRAFT_API /** * Move constructor: Leaves the source FormattedNumber in an undefined state. @@ -2472,60 +2485,6 @@ class U_I18N_API FormattedNumber : public UMemory, public FormattedValue { /** @copydoc FormattedValue::nextPosition() */ UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE; -#ifndef U_HIDE_DRAFT_API - /** - * Determines the start (inclusive) and end (exclusive) indices of the next occurrence of the given - * field in the output string. This allows you to determine the locations of, for example, - * the integer part, fraction part, or symbols. - * - * This is a simpler but less powerful alternative to {@link #nextPosition}. - * - * If a field occurs just once, calling this method will find that occurrence and return it. If a - * field occurs multiple times, this method may be called repeatedly with the following pattern: - * - *
-     * FieldPosition fpos(UNUM_GROUPING_SEPARATOR_FIELD);
-     * while (formattedNumber.nextFieldPosition(fpos, status)) {
-     *   // do something with fpos.
-     * }
-     * 
- * - * This method is useful if you know which field to query. If you want all available field position - * information, use {@link #nextPosition} or {@link #getAllFieldPositions}. - * - * @param fieldPosition - * Input+output variable. On input, the "field" property determines which field to look - * up, and the "beginIndex" and "endIndex" properties determine where to begin the search. - * On output, the "beginIndex" is set to the beginning of the first occurrence of the - * field with either begin or end indices after the input indices; "endIndex" is set to - * the end of that occurrence of the field (exclusive index). If a field position is not - * found, the method returns FALSE and the FieldPosition may or may not be changed. - * @param status - * Set if an error occurs while populating the FieldPosition. - * @return TRUE if a new occurrence of the field was found; FALSE otherwise. - * @draft ICU 62 - * @see UNumberFormatFields - */ - UBool nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const; - - /** - * Export the formatted number to a FieldPositionIterator. This allows you to determine which characters in - * the output string correspond to which fields, such as the integer part, fraction part, and sign. - * - * This is an alternative to the more powerful #nextPosition() API. - * - * If information on only one field is needed, use #nextPosition() or #nextFieldPosition() instead. - * - * @param iterator - * The FieldPositionIterator to populate with all of the fields present in the formatted number. - * @param status - * Set if an error occurs while populating the FieldPositionIterator. - * @draft ICU 62 - * @see UNumberFormatFields - */ - void getAllFieldPositions(FieldPositionIterator &iterator, UErrorCode &status) const; -#endif /* U_HIDE_DRAFT_API */ - #ifndef U_HIDE_DRAFT_API /** * Export the formatted number as a "numeric string" conforming to the @@ -2600,7 +2559,7 @@ StringClass FormattedNumber::toDecimalNumber(UErrorCode& status) const { StringByteSink sink(&result); toDecimalNumber(sink, status); return result; -}; +} #endif // U_HIDE_DRAFT_API /** @@ -2646,7 +2605,6 @@ class U_I18N_API NumberFormatter final { */ static UnlocalizedNumberFormatter forSkeleton(const UnicodeString& skeleton, UErrorCode& status); -#ifndef U_HIDE_DRAFT_API /** * Call this method at the beginning of a NumberFormatter fluent chain to create an instance based * on a given number skeleton string. @@ -2662,11 +2620,10 @@ class U_I18N_API NumberFormatter final { * @param status * Set to U_NUMBER_SKELETON_SYNTAX_ERROR if the skeleton was invalid. * @return An UnlocalizedNumberFormatter, to be used for chaining. - * @draft ICU 64 + * @stable ICU 64 */ static UnlocalizedNumberFormatter forSkeleton(const UnicodeString& skeleton, UParseError& perror, UErrorCode& status); -#endif /** * Use factory methods instead of the constructor to create a NumberFormatter. diff --git a/deps/icu-small/source/i18n/unicode/numberrangeformatter.h b/deps/icu-small/source/i18n/unicode/numberrangeformatter.h index e3a72aa8b21257..59f14d8be53189 100644 --- a/deps/icu-small/source/i18n/unicode/numberrangeformatter.h +++ b/deps/icu-small/source/i18n/unicode/numberrangeformatter.h @@ -449,7 +449,6 @@ class U_I18N_API NumberRangeFormatterSettings { */ Derived identityFallback(UNumberRangeIdentityFallback identityFallback) &&; -#ifndef U_HIDE_DRAFT_API /** * Returns the current (Un)LocalizedNumberRangeFormatter as a LocalPointer * wrapping a heap-allocated copy of the current object. @@ -459,7 +458,7 @@ class U_I18N_API NumberRangeFormatterSettings { * * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped * nullptr on failure. - * @draft ICU 64 + * @stable ICU 64 */ LocalPointer clone() const &; @@ -468,10 +467,9 @@ class U_I18N_API NumberRangeFormatterSettings { * * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped * nullptr on failure. - * @draft ICU 64 + * @stable ICU 64 */ LocalPointer clone() &&; -#endif /* U_HIDE_DRAFT_API */ /** * Sets the UErrorCode if an error occurred in the fluent chain. @@ -728,52 +726,6 @@ class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue { UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE; #ifndef U_HIDE_DRAFT_API - /** - * Determines the start (inclusive) and end (exclusive) indices of the next occurrence of the given - * field in the output string. This allows you to determine the locations of, for example, - * the integer part, fraction part, or symbols. - * - * If both sides of the range have the same field, the field will occur twice, once before the - * range separator and once after the range separator, if applicable. - * - * If a field occurs just once, calling this method will find that occurrence and return it. If a - * field occurs multiple times, this method may be called repeatedly with the following pattern: - * - *
-     * FieldPosition fpos(UNUM_INTEGER_FIELD);
-     * while (formattedNumberRange.nextFieldPosition(fpos, status)) {
-     *   // do something with fpos.
-     * }
-     * 
- * - * This method is useful if you know which field to query. If you want all available field position - * information, use #getAllFieldPositions(). - * - * @param fieldPosition - * Input+output variable. See {@link FormattedNumber#nextFieldPosition}. - * @param status - * Set if an error occurs while populating the FieldPosition. - * @return TRUE if a new occurrence of the field was found; FALSE otherwise. - * @draft ICU 63 - * @see UNumberFormatFields - */ - UBool nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const; - - /** - * Export the formatted number range to a FieldPositionIterator. This allows you to determine which characters in - * the output string correspond to which fields, such as the integer part, fraction part, and sign. - * - * If information on only one field is needed, use #nextFieldPosition() instead. - * - * @param iterator - * The FieldPositionIterator to populate with all of the fields present in the formatted number. - * @param status - * Set if an error occurs while populating the FieldPositionIterator. - * @draft ICU 63 - * @see UNumberFormatFields - */ - void getAllFieldPositions(FieldPositionIterator &iterator, UErrorCode &status) const; - /** * Export the first formatted number as a decimal number. This endpoint * is useful for obtaining the exact number being printed after scaling diff --git a/deps/icu-small/source/i18n/unicode/numfmt.h b/deps/icu-small/source/i18n/unicode/numfmt.h index fbd4fb4e5655b3..a882b6d2e5667d 100644 --- a/deps/icu-small/source/i18n/unicode/numfmt.h +++ b/deps/icu-small/source/i18n/unicode/numfmt.h @@ -239,12 +239,10 @@ class U_I18N_API NumberFormat : public Format { kPermillField = UNUM_PERMILL_FIELD, /** @stable ICU 2.0 */ kSignField = UNUM_SIGN_FIELD, -#ifndef U_HIDE_DRAFT_API - /** @draft ICU 64 */ + /** @stable ICU 64 */ kMeasureUnitField = UNUM_MEASURE_UNIT_FIELD, - /** @draft ICU 64 */ + /** @stable ICU 64 */ kCompactField = UNUM_COMPACT_FIELD, -#endif // U_HIDE_DRAFT_API /** * These constants are provided for backwards compatibility only. diff --git a/deps/icu-small/source/i18n/unicode/numsys.h b/deps/icu-small/source/i18n/unicode/numsys.h index 4fb7f044eddb76..88c172bd422a51 100644 --- a/deps/icu-small/source/i18n/unicode/numsys.h +++ b/deps/icu-small/source/i18n/unicode/numsys.h @@ -73,6 +73,12 @@ class U_I18N_API NumberingSystem : public UObject { */ NumberingSystem(const NumberingSystem& other); + /** + * Copy assignment. + * @stable ICU 4.2 + */ + NumberingSystem& operator=(const NumberingSystem& other) = default; + /** * Destructor. * @stable ICU 4.2 diff --git a/deps/icu-small/source/i18n/unicode/plurrule.h b/deps/icu-small/source/i18n/unicode/plurrule.h index a1553567caf8f5..408efbcc4a84f8 100644 --- a/deps/icu-small/source/i18n/unicode/plurrule.h +++ b/deps/icu-small/source/i18n/unicode/plurrule.h @@ -350,7 +350,6 @@ class U_I18N_API PluralRules : public UObject { */ UnicodeString select(double number) const; -#ifndef U_HIDE_DRAFT_API /** * Given a formatted number, returns the keyword of the first rule * that applies to the number. This function can be used with @@ -364,10 +363,9 @@ class U_I18N_API PluralRules : public UObject { * @param status Set if an error occurs while selecting plural keyword. * This could happen if the FormattedNumber is invalid. * @return The keyword of the selected rule. - * @draft ICU 64 + * @stable ICU 64 */ UnicodeString select(const number::FormattedNumber& number, UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_INTERNAL_API /** diff --git a/deps/icu-small/source/i18n/unicode/regex.h b/deps/icu-small/source/i18n/unicode/regex.h index 75048af06c9aaa..2f8d31d97f012f 100644 --- a/deps/icu-small/source/i18n/unicode/regex.h +++ b/deps/icu-small/source/i18n/unicode/regex.h @@ -66,7 +66,7 @@ class RegexCImpl; class RegexMatcher; class RegexPattern; struct REStackFrame; -class RuleBasedBreakIterator; +class BreakIterator; class UnicodeSet; class UVector; class UVector32; @@ -612,12 +612,6 @@ class U_I18N_API RegexPattern U_FINAL : public UObject { UVector32 *fGroupMap; // Map from capture group number to position of // the group's variables in the matcher stack frame. - UnicodeSet **fStaticSets; // Ptr to static (shared) sets for predefined - // regex character classes, e.g. Word. - - Regex8BitSet *fStaticSets8; // Ptr to the static (shared) latin-1 only - // sets for predefined regex classes. - int32_t fStartType; // Info on how a match must start. int32_t fInitialStringIdx; // int32_t fInitialStringLen; @@ -635,8 +629,9 @@ class U_I18N_API RegexPattern U_FINAL : public UObject { // // Implementation Methods // - void init(); // Common initialization, for use by constructors. - void zap(); // Common cleanup + void init(); // Common initialization, for use by constructors. + bool initNamedCaptureMap(); // Lazy init for fNamedCaptureMap. + void zap(); // Common cleanup void dumpOp(int32_t index) const; @@ -1779,7 +1774,9 @@ class U_I18N_API RegexMatcher U_FINAL : public UObject { void MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status); inline void backTrack(int64_t &inputIdx, int32_t &patIdx); UBool isWordBoundary(int64_t pos); // perform Perl-like \b test - UBool isUWordBoundary(int64_t pos); // perform RBBI based \b test + UBool isUWordBoundary(int64_t pos, UErrorCode &status); // perform RBBI based \b test + // Find a grapheme cluster boundary using a break iterator. For handling \X in regexes. + int64_t followingGCBoundary(int64_t pos, UErrorCode &status); REStackFrame *resetStack(); inline REStackFrame *StateSave(REStackFrame *fp, int64_t savePatIdx, UErrorCode &status); void IncrementTime(UErrorCode &status); @@ -1873,7 +1870,8 @@ class U_I18N_API RegexMatcher U_FINAL : public UObject { UErrorCode fDeferredStatus; // Save error state that cannot be immediately // reported, or that permanently disables this matcher. - RuleBasedBreakIterator *fWordBreakItr; + BreakIterator *fWordBreakItr; + BreakIterator *fGCBreakItr; }; U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/unicode/reldatefmt.h b/deps/icu-small/source/i18n/unicode/reldatefmt.h index fb691a545105b6..a991bc7986b32d 100644 --- a/deps/icu-small/source/i18n/unicode/reldatefmt.h +++ b/deps/icu-small/source/i18n/unicode/reldatefmt.h @@ -264,7 +264,6 @@ class UnicodeString; class FormattedRelativeDateTime; class FormattedRelativeDateTimeData; -#ifndef U_HIDE_DRAFT_API /** * An immutable class containing the result of a relative datetime formatting operation. * @@ -272,25 +271,25 @@ class FormattedRelativeDateTimeData; * * Not intended for public subclassing. * - * @draft ICU 64 + * @stable ICU 64 */ class U_I18N_API FormattedRelativeDateTime : public UMemory, public FormattedValue { public: /** * Default constructor; makes an empty FormattedRelativeDateTime. - * @draft ICU 64 + * @stable ICU 64 */ FormattedRelativeDateTime() : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {} /** * Move constructor: Leaves the source FormattedRelativeDateTime in an undefined state. - * @draft ICU 64 + * @stable ICU 64 */ FormattedRelativeDateTime(FormattedRelativeDateTime&& src) U_NOEXCEPT; /** * Destruct an instance of FormattedRelativeDateTime. - * @draft ICU 64 + * @stable ICU 64 */ virtual ~FormattedRelativeDateTime() U_OVERRIDE; @@ -302,7 +301,7 @@ class U_I18N_API FormattedRelativeDateTime : public UMemory, public FormattedVal /** * Move assignment: Leaves the source FormattedRelativeDateTime in an undefined state. - * @draft ICU 64 + * @stable ICU 64 */ FormattedRelativeDateTime& operator=(FormattedRelativeDateTime&& src) U_NOEXCEPT; @@ -327,7 +326,6 @@ class U_I18N_API FormattedRelativeDateTime : public UMemory, public FormattedVal : fData(nullptr), fErrorCode(errorCode) {} friend class RelativeDateTimeFormatter; }; -#endif /* U_HIDE_DRAFT_API */ /** * Formats simple relative dates. There are two types of relative dates that @@ -492,7 +490,6 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { UnicodeString& appendTo, UErrorCode& status) const; -#ifndef U_HIDE_DRAFT_API /** * Formats a relative date with a quantity such as "in 5 days" or * "3 months ago" @@ -508,14 +505,13 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { * @param unit the unit e.g day? month? year? * @param status ICU error code returned here. * @return The formatted relative datetime - * @draft ICU 64 + * @stable ICU 64 */ FormattedRelativeDateTime formatToValue( double quantity, UDateDirection direction, UDateRelativeUnit unit, UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ /** * Formats a relative date without a quantity. @@ -539,7 +535,6 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { UnicodeString& appendTo, UErrorCode& status) const; -#ifndef U_HIDE_DRAFT_API /** * Formats a relative date without a quantity. * @@ -553,13 +548,12 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { * @param unit e.g SATURDAY, DAY, MONTH * @param status ICU error code returned here. * @return The formatted relative datetime - * @draft ICU 64 + * @stable ICU 64 */ FormattedRelativeDateTime formatToValue( UDateDirection direction, UDateAbsoluteUnit unit, UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ /** * Format a combination of URelativeDateTimeUnit and numeric offset @@ -587,7 +581,6 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { UnicodeString& appendTo, UErrorCode& status) const; -#ifndef U_HIDE_DRAFT_API /** * Format a combination of URelativeDateTimeUnit and numeric offset * using a numeric style, e.g. "1 week ago", "in 1 week", @@ -604,13 +597,12 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { * UDAT_REL_UNIT_FRIDAY. * @param status ICU error code returned here. * @return The formatted relative datetime - * @draft ICU 64 + * @stable ICU 64 */ FormattedRelativeDateTime formatNumericToValue( double offset, URelativeDateTimeUnit unit, UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ /** * Format a combination of URelativeDateTimeUnit and numeric offset @@ -638,7 +630,6 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { UnicodeString& appendTo, UErrorCode& status) const; -#ifndef U_HIDE_DRAFT_API /** * Format a combination of URelativeDateTimeUnit and numeric offset * using a text style if possible, e.g. "last week", "this week", @@ -655,13 +646,12 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { * UDAT_REL_UNIT_FRIDAY. * @param status ICU error code returned here. * @return The formatted relative datetime - * @draft ICU 64 + * @stable ICU 64 */ FormattedRelativeDateTime formatToValue( double offset, URelativeDateTimeUnit unit, UErrorCode& status) const; -#endif /* U_HIDE_DRAFT_API */ /** * Combines a relative date string and a time string in this object's @@ -724,13 +714,11 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { UErrorCode& status, Args... args) const; -#ifndef U_HIDE_DRAFT_API // for FormattedRelativeDateTime template FormattedRelativeDateTime doFormatToValue( F callback, UErrorCode& status, Args... args) const; -#endif // U_HIDE_DRAFT_API void formatImpl( double quantity, diff --git a/deps/icu-small/source/i18n/unicode/selfmt.h b/deps/icu-small/source/i18n/unicode/selfmt.h old mode 100755 new mode 100644 diff --git a/deps/icu-small/source/i18n/unicode/smpdtfmt.h b/deps/icu-small/source/i18n/unicode/smpdtfmt.h index 79fa817d5afb89..b4b0e5fb390801 100644 --- a/deps/icu-small/source/i18n/unicode/smpdtfmt.h +++ b/deps/icu-small/source/i18n/unicode/smpdtfmt.h @@ -1274,6 +1274,7 @@ class U_I18N_API SimpleDateFormat: public DateFormat { int32_t count, UDisplayContext capitalizationContext, int32_t fieldNum, + char16_t fieldToOutput, FieldPositionHandler& handler, Calendar& cal, UErrorCode& status) const; // in case of illegal argument diff --git a/deps/icu-small/source/i18n/unicode/udat.h b/deps/icu-small/source/i18n/unicode/udat.h index bdbd080c005821..cf7a165e70ab4f 100644 --- a/deps/icu-small/source/i18n/unicode/udat.h +++ b/deps/icu-small/source/i18n/unicode/udat.h @@ -958,7 +958,37 @@ udat_getBooleanAttribute(const UDateFormat* fmt, UDateFormatBooleanAttribute att U_CAPI void U_EXPORT2 udat_setBooleanAttribute(UDateFormat *fmt, UDateFormatBooleanAttribute attr, UBool newValue, UErrorCode* status); +#ifndef U_HIDE_DRAFT_API +/** + * Hour Cycle. + * @draft ICU 67 + */ +typedef enum UDateFormatHourCycle { + /** + * Hour in am/pm (0~11) + * @draft ICU 67 + */ + UDAT_HOUR_CYCLE_11, + + /** + * Hour in am/pm (1~12) + * @draft ICU 67 + */ + UDAT_HOUR_CYCLE_12, + + /** + * Hour in day (0~23) + * @draft ICU 67 + */ + UDAT_HOUR_CYCLE_23, + /** + * Hour in day (1~24) + * @draft ICU 67 + */ + UDAT_HOUR_CYCLE_24 +} UDateFormatHourCycle; +#endif /* U_HIDE_DRAFT_API */ #if U_SHOW_CPLUSPLUS_API diff --git a/deps/icu-small/source/i18n/unicode/udateintervalformat.h b/deps/icu-small/source/i18n/unicode/udateintervalformat.h index 112f81b31e976b..6235ab710622ce 100644 --- a/deps/icu-small/source/i18n/unicode/udateintervalformat.h +++ b/deps/icu-small/source/i18n/unicode/udateintervalformat.h @@ -14,6 +14,7 @@ #if !UCONFIG_NO_FORMATTING +#include "unicode/ucal.h" #include "unicode/umisc.h" #include "unicode/localpointer.h" #include "unicode/uformattedvalue.h" @@ -82,14 +83,12 @@ struct UDateIntervalFormat; typedef struct UDateIntervalFormat UDateIntervalFormat; /**< C typedef for struct UDateIntervalFormat. @stable ICU 4.8 */ -#ifndef U_HIDE_DRAFT_API struct UFormattedDateInterval; /** * Opaque struct to contain the results of a UDateIntervalFormat operation. - * @draft ICU 64 + * @stable ICU 64 */ typedef struct UFormattedDateInterval UFormattedDateInterval; -#endif /* U_HIDE_DRAFT_API */ /** * Open a new UDateIntervalFormat object using the predefined rules for a @@ -132,8 +131,6 @@ udtitvfmt_open(const char* locale, U_STABLE void U_EXPORT2 udtitvfmt_close(UDateIntervalFormat *formatter); - -#ifndef U_HIDE_DRAFT_API /** * Creates an object to hold the result of a UDateIntervalFormat * operation. The object can be used repeatedly; it is cleared whenever @@ -141,7 +138,7 @@ udtitvfmt_close(UDateIntervalFormat *formatter); * * @param ec Set if an error occurs. * @return A pointer needing ownership. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI UFormattedDateInterval* U_EXPORT2 udtitvfmt_openResult(UErrorCode* ec); @@ -166,7 +163,7 @@ udtitvfmt_openResult(UErrorCode* ec); * @param uresult The object containing the formatted string. * @param ec Set if an error occurs. * @return A UFormattedValue owned by the input object. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI const UFormattedValue* U_EXPORT2 udtitvfmt_resultAsValue(const UFormattedDateInterval* uresult, UErrorCode* ec); @@ -175,11 +172,10 @@ udtitvfmt_resultAsValue(const UFormattedDateInterval* uresult, UErrorCode* ec); * Releases the UFormattedDateInterval created by udtitvfmt_openResult(). * * @param uresult The object to release. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI void U_EXPORT2 udtitvfmt_closeResult(UFormattedDateInterval* uresult); -#endif /* U_HIDE_DRAFT_API */ #if U_SHOW_CPLUSPLUS_API @@ -197,7 +193,6 @@ U_NAMESPACE_BEGIN */ U_DEFINE_LOCAL_OPEN_POINTER(LocalUDateIntervalFormatPointer, UDateIntervalFormat, udtitvfmt_close); -#ifndef U_HIDE_DRAFT_API /** * \class LocalUFormattedDateIntervalPointer * "Smart pointer" class, closes a UFormattedDateInterval via udtitvfmt_close(). @@ -205,10 +200,9 @@ U_DEFINE_LOCAL_OPEN_POINTER(LocalUDateIntervalFormatPointer, UDateIntervalFormat * * @see LocalPointerBase * @see LocalPointer - * @draft ICU 64 + * @stable ICU 64 */ U_DEFINE_LOCAL_OPEN_POINTER(LocalUFormattedDateIntervalPointer, UFormattedDateInterval, udtitvfmt_closeResult); -#endif /* U_HIDE_DRAFT_API */ U_NAMESPACE_END @@ -260,23 +254,48 @@ udtitvfmt_format(const UDateIntervalFormat* formatter, * UDateIntervalFormat object. * @param formatter * The UDateIntervalFormat object specifying the format conventions. - * @param result - * The UFormattedDateInterval to contain the result of the - * formatting operation. * @param fromDate * The starting point of the range. * @param toDate * The ending point of the range. + * @param result + * The UFormattedDateInterval to contain the result of the + * formatting operation. * @param status * A pointer to a UErrorCode to receive any errors. - * @draft ICU 64 + * @draft ICU 67 */ U_DRAFT void U_EXPORT2 udtitvfmt_formatToResult( const UDateIntervalFormat* formatter, - UFormattedDateInterval* result, UDate fromDate, UDate toDate, + UFormattedDateInterval* result, + UErrorCode* status); + +/** + * Formats a date/time range using the conventions established for the + * UDateIntervalFormat object. + * @param formatter + * The UDateIntervalFormat object specifying the format conventions. + * @param fromCalendar + * The starting point of the range. + * @param toCalendar + * The ending point of the range. + * @param result + * The UFormattedDateInterval to contain the result of the + * formatting operation. + * @param status + * A pointer to a UErrorCode to receive any errors. + * @draft ICU 67 + */ + +U_DRAFT void U_EXPORT2 +udtitvfmt_formatCalendarToResult( + const UDateIntervalFormat* formatter, + UCalendar* fromCalendar, + UCalendar* toCalendar, + UFormattedDateInterval* result, UErrorCode* status); #endif /* U_HIDE_DRAFT_API */ diff --git a/deps/icu-small/source/i18n/unicode/udatpg.h b/deps/icu-small/source/i18n/unicode/udatpg.h index 81956d12705d7d..4ec4a2d05116cb 100644 --- a/deps/icu-small/source/i18n/unicode/udatpg.h +++ b/deps/icu-small/source/i18n/unicode/udatpg.h @@ -20,6 +20,7 @@ #define __UDATPG_H__ #include "unicode/utypes.h" +#include "unicode/udat.h" #include "unicode/uenum.h" #include "unicode/localpointer.h" @@ -651,4 +652,26 @@ udatpg_getPatternForSkeleton(const UDateTimePatternGenerator *dtpg, const UChar *skeleton, int32_t skeletonLength, int32_t *pLength); +#if !UCONFIG_NO_FORMATTING + +#ifndef U_HIDE_DRAFT_API +/** + * Return the default hour cycle for a locale. Uses the locale that the + * UDateTimePatternGenerator was initially created with. + * + * Cannot be used on an empty UDateTimePatternGenerator instance. + * + * @param dtpg a pointer to UDateTimePatternGenerator. + * @param pErrorCode a pointer to the UErrorCode which must not indicate a + * failure before the function call. Set to U_UNSUPPORTED_ERROR + * if used on an empty instance. + * @return the default hour cycle. + * @draft ICU 67 + */ +U_DRAFT UDateFormatHourCycle U_EXPORT2 +udatpg_getDefaultHourCycle(const UDateTimePatternGenerator *dtpg, UErrorCode* pErrorCode); +#endif /* U_HIDE_DRAFT_API */ + +#endif /* #if !UCONFIG_NO_FORMATTING */ + #endif diff --git a/deps/icu-small/source/i18n/unicode/uformattedvalue.h b/deps/icu-small/source/i18n/unicode/uformattedvalue.h index 172558f7fb716a..71a6592e9dd062 100644 --- a/deps/icu-small/source/i18n/unicode/uformattedvalue.h +++ b/deps/icu-small/source/i18n/unicode/uformattedvalue.h @@ -10,8 +10,6 @@ #include "unicode/ufieldpositer.h" -#ifndef U_HIDE_DRAFT_API - /** * \file * \brief C API: Abstract operations for localized strings. @@ -31,41 +29,41 @@ * categories 2^28 and higher or below zero (with the highest bit turned on) * are private-use and will not be used by ICU in the future. * - * @draft ICU 64 + * @stable ICU 64 */ typedef enum UFieldCategory { /** * For an undefined field category. * - * @draft ICU 64 + * @stable ICU 64 */ UFIELD_CATEGORY_UNDEFINED = 0, /** * For fields in UDateFormatField (udat.h), from ICU 3.0. * - * @draft ICU 64 + * @stable ICU 64 */ UFIELD_CATEGORY_DATE, /** * For fields in UNumberFormatFields (unum.h), from ICU 49. * - * @draft ICU 64 + * @stable ICU 64 */ UFIELD_CATEGORY_NUMBER, /** * For fields in UListFormatterField (ulistformatter.h), from ICU 63. * - * @draft ICU 64 + * @stable ICU 64 */ UFIELD_CATEGORY_LIST, /** * For fields in URelativeDateTimeFormatterField (ureldatefmt.h), from ICU 64. * - * @draft ICU 64 + * @stable ICU 64 */ UFIELD_CATEGORY_RELATIVE_DATETIME, @@ -84,14 +82,14 @@ typedef enum UFieldCategory { /** * Category for spans in a list. * - * @draft ICU 64 + * @stable ICU 64 */ UFIELD_CATEGORY_LIST_SPAN = 0x1000 + UFIELD_CATEGORY_LIST, /** * Category for spans in a date interval. * - * @draft ICU 64 + * @stable ICU 64 */ UFIELD_CATEGORY_DATE_INTERVAL_SPAN = 0x1000 + UFIELD_CATEGORY_DATE_INTERVAL, @@ -108,7 +106,7 @@ struct UConstrainedFieldPosition; * 2. It allows you to set constraints to use when iterating over field positions. * 3. It is used for the newer FormattedValue APIs. * - * @draft ICU 64 + * @stable ICU 64 */ typedef struct UConstrainedFieldPosition UConstrainedFieldPosition; @@ -120,9 +118,9 @@ typedef struct UConstrainedFieldPosition UConstrainedFieldPosition; * * @param ec Set if an error occurs. * @return The new object, or NULL if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT UConstrainedFieldPosition* U_EXPORT2 +U_STABLE UConstrainedFieldPosition* U_EXPORT2 ucfpos_open(UErrorCode* ec); @@ -133,9 +131,9 @@ ucfpos_open(UErrorCode* ec); * * @param ucfpos The instance of UConstrainedFieldPosition. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ucfpos_reset( UConstrainedFieldPosition* ucfpos, UErrorCode* ec); @@ -145,9 +143,9 @@ ucfpos_reset( * Destroys a UConstrainedFieldPosition and releases its memory. * * @param ucfpos The instance of UConstrainedFieldPosition. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ucfpos_close(UConstrainedFieldPosition* ucfpos); @@ -174,9 +172,9 @@ ucfpos_close(UConstrainedFieldPosition* ucfpos); * @param ucfpos The instance of UConstrainedFieldPosition. * @param category The field category to fix when iterating. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ucfpos_constrainCategory( UConstrainedFieldPosition* ucfpos, int32_t category, @@ -207,9 +205,9 @@ ucfpos_constrainCategory( * @param category The field category to fix when iterating. * @param field The field to fix when iterating. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ucfpos_constrainField( UConstrainedFieldPosition* ucfpos, int32_t category, @@ -227,9 +225,9 @@ ucfpos_constrainField( * @param ucfpos The instance of UConstrainedFieldPosition. * @param ec Set if an error occurs. * @return The field category saved in the instance. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT int32_t U_EXPORT2 +U_STABLE int32_t U_EXPORT2 ucfpos_getCategory( const UConstrainedFieldPosition* ucfpos, UErrorCode* ec); @@ -245,9 +243,9 @@ ucfpos_getCategory( * @param ucfpos The instance of UConstrainedFieldPosition. * @param ec Set if an error occurs. * @return The field saved in the instance. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT int32_t U_EXPORT2 +U_STABLE int32_t U_EXPORT2 ucfpos_getField( const UConstrainedFieldPosition* ucfpos, UErrorCode* ec); @@ -262,9 +260,9 @@ ucfpos_getField( * @param pStart Set to the start index saved in the instance. Ignored if nullptr. * @param pLimit Set to the end index saved in the instance. Ignored if nullptr. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ucfpos_getIndexes( const UConstrainedFieldPosition* ucfpos, int32_t* pStart, @@ -282,9 +280,9 @@ ucfpos_getIndexes( * @param ucfpos The instance of UConstrainedFieldPosition. * @param ec Set if an error occurs. * @return The current iteration context from ucfpos_setInt64IterationContext. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT int64_t U_EXPORT2 +U_STABLE int64_t U_EXPORT2 ucfpos_getInt64IterationContext( const UConstrainedFieldPosition* ucfpos, UErrorCode* ec); @@ -298,9 +296,9 @@ ucfpos_getInt64IterationContext( * @param ucfpos The instance of UConstrainedFieldPosition. * @param context The new iteration context. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ucfpos_setInt64IterationContext( UConstrainedFieldPosition* ucfpos, int64_t context, @@ -317,9 +315,9 @@ ucfpos_setInt64IterationContext( * @param category The category to test. * @param field The field to test. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT UBool U_EXPORT2 +U_STABLE UBool U_EXPORT2 ucfpos_matchesField( const UConstrainedFieldPosition* ucfpos, int32_t category, @@ -341,9 +339,9 @@ ucfpos_matchesField( * @param start The new inclusive start index. * @param limit The new exclusive end index. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ucfpos_setState( UConstrainedFieldPosition* ucfpos, int32_t category, @@ -358,7 +356,7 @@ struct UFormattedValue; * An abstract formatted value: a string with associated field attributes. * Many formatters format to types compatible with UFormattedValue. * - * @draft ICU 64 + * @stable ICU 64 */ typedef struct UFormattedValue UFormattedValue; @@ -374,9 +372,9 @@ typedef struct UFormattedValue UFormattedValue; * @param pLength Output variable for the length of the string. Ignored if NULL. * @param ec Set if an error occurs. * @return A NUL-terminated char16 string owned by the UFormattedValue. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT const UChar* U_EXPORT2 +U_STABLE const UChar* U_EXPORT2 ufmtval_getString( const UFormattedValue* ufmtval, int32_t* pLength, @@ -404,9 +402,9 @@ ufmtval_getString( * and ucfpos_constrainField. * @param ec Set if an error occurs. * @return TRUE if another position was found; FALSE otherwise. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT UBool U_EXPORT2 +U_STABLE UBool U_EXPORT2 ufmtval_nextPosition( const UFormattedValue* ufmtval, UConstrainedFieldPosition* ucfpos, @@ -426,7 +424,7 @@ U_NAMESPACE_BEGIN * LocalUConstrainedFieldPositionPointer ucfpos(ucfpos_open(ec)); * // no need to explicitly call ucfpos_close() * - * @draft ICU 64 + * @stable ICU 64 */ U_DEFINE_LOCAL_OPEN_POINTER(LocalUConstrainedFieldPositionPointer, UConstrainedFieldPosition, @@ -436,6 +434,5 @@ U_NAMESPACE_END #endif // U_SHOW_CPLUSPLUS_API -#endif /* U_HIDE_DRAFT_API */ #endif /* #if !UCONFIG_NO_FORMATTING */ #endif // __UFORMATTEDVALUE_H__ diff --git a/deps/icu-small/source/i18n/unicode/ulistformatter.h b/deps/icu-small/source/i18n/unicode/ulistformatter.h index 0fbf72c9ff6abb..66cf50190bb0eb 100644 --- a/deps/icu-small/source/i18n/unicode/ulistformatter.h +++ b/deps/icu-small/source/i18n/unicode/ulistformatter.h @@ -34,37 +34,92 @@ struct UListFormatter; typedef struct UListFormatter UListFormatter; /**< C typedef for struct UListFormatter. @stable ICU 55 */ -#ifndef U_HIDE_DRAFT_API struct UFormattedList; /** * Opaque struct to contain the results of a UListFormatter operation. - * @draft ICU 64 + * @stable ICU 64 */ typedef struct UFormattedList UFormattedList; -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * FieldPosition and UFieldPosition selectors for format fields * defined by ListFormatter. - * @draft ICU 63 + * @stable ICU 63 */ typedef enum UListFormatterField { /** * The literal text in the result which came from the resources. - * @draft ICU 63 + * @stable ICU 63 */ ULISTFMT_LITERAL_FIELD, /** * The element text in the result which came from the input strings. - * @draft ICU 63 + * @stable ICU 63 */ ULISTFMT_ELEMENT_FIELD } UListFormatterField; + +#ifndef U_HIDE_DRAFT_API +/** + * Type of meaning expressed by the list. + * + * @draft ICU 67 + */ +typedef enum UListFormatterType { + /** + * Conjunction formatting, e.g. "Alice, Bob, Charlie, and Delta". + * + * @draft ICU 67 + */ + ULISTFMT_TYPE_AND, + + /** + * Disjunction (or alternative, or simply one of) formatting, e.g. + * "Alice, Bob, Charlie, or Delta". + * + * @draft ICU 67 + */ + ULISTFMT_TYPE_OR, + + /** + * Formatting of a list of values with units, e.g. "5 pounds, 12 ounces". + * + * @draft ICU 67 + */ + ULISTFMT_TYPE_UNITS +} UListFormatterType; + +/** + * Verbosity level of the list patterns. + * + * @draft ICU 67 + */ +typedef enum UListFormatterWidth { + /** + * Use list formatting with full words (no abbreviations) when possible. + * + * @draft ICU 67 + */ + ULISTFMT_WIDTH_WIDE, + + /** + * Use list formatting of typical length. + * @draft ICU 67 + */ + ULISTFMT_WIDTH_SHORT, + + /** + * Use list formatting of the shortest possible length. + * @draft ICU 67 + */ + ULISTFMT_WIDTH_NARROW, +} UListFormatterWidth; #endif /* U_HIDE_DRAFT_API */ /** * Open a new UListFormatter object using the rules for a given locale. + * The object will be initialized with AND type and WIDE width. + * * @param locale * The locale whose rules should be used; may be NULL for * default locale. @@ -83,6 +138,34 @@ U_CAPI UListFormatter* U_EXPORT2 ulistfmt_open(const char* locale, UErrorCode* status); +#ifndef U_HIDE_DRAFT_API +/** + * Open a new UListFormatter object appropriate for the given locale, list type, + * and style. + * + * @param locale + * The locale whose rules should be used; may be NULL for + * default locale. + * @param type + * The type of list formatting to use. + * @param width + * The width of formatting to use. + * @param status + * A pointer to a standard ICU UErrorCode (input/output parameter). + * Its input value must pass the U_SUCCESS() test, or else the + * function returns immediately. The caller should check its output + * value with U_FAILURE(), or use with function chaining (see User + * Guide for details). + * @return + * A pointer to a UListFormatter object for the specified locale, + * or NULL if an error occurred. + * @draft ICU 67 + */ +U_DRAFT UListFormatter* U_EXPORT2 +ulistfmt_openForType(const char* locale, UListFormatterType type, + UListFormatterWidth width, UErrorCode* status); +#endif /* U_HIDE_DRAFT_API */ + /** * Close a UListFormatter object. Once closed it may no longer be used. * @param listfmt @@ -92,7 +175,6 @@ ulistfmt_open(const char* locale, U_CAPI void U_EXPORT2 ulistfmt_close(UListFormatter *listfmt); -#ifndef U_HIDE_DRAFT_API /** * Creates an object to hold the result of a UListFormatter * operation. The object can be used repeatedly; it is cleared whenever @@ -100,7 +182,7 @@ ulistfmt_close(UListFormatter *listfmt); * * @param ec Set if an error occurs. * @return A pointer needing ownership. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI UFormattedList* U_EXPORT2 ulistfmt_openResult(UErrorCode* ec); @@ -124,7 +206,7 @@ ulistfmt_openResult(UErrorCode* ec); * @param uresult The object containing the formatted string. * @param ec Set if an error occurs. * @return A UFormattedValue owned by the input object. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI const UFormattedValue* U_EXPORT2 ulistfmt_resultAsValue(const UFormattedList* uresult, UErrorCode* ec); @@ -133,11 +215,10 @@ ulistfmt_resultAsValue(const UFormattedList* uresult, UErrorCode* ec); * Releases the UFormattedList created by ulistfmt_openResult(). * * @param uresult The object to release. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI void U_EXPORT2 ulistfmt_closeResult(UFormattedList* uresult); -#endif /* U_HIDE_DRAFT_API */ #if U_SHOW_CPLUSPLUS_API @@ -155,7 +236,6 @@ U_NAMESPACE_BEGIN */ U_DEFINE_LOCAL_OPEN_POINTER(LocalUListFormatterPointer, UListFormatter, ulistfmt_close); -#ifndef U_HIDE_DRAFT_API /** * \class LocalUFormattedListPointer * "Smart pointer" class, closes a UFormattedList via ulistfmt_closeResult(). @@ -163,10 +243,9 @@ U_DEFINE_LOCAL_OPEN_POINTER(LocalUListFormatterPointer, UListFormatter, ulistfmt * * @see LocalPointerBase * @see LocalPointer - * @draft ICU 64 + * @stable ICU 64 */ U_DEFINE_LOCAL_OPEN_POINTER(LocalUFormattedListPointer, UFormattedList, ulistfmt_closeResult); -#endif /* U_HIDE_DRAFT_API */ U_NAMESPACE_END @@ -215,7 +294,6 @@ ulistfmt_format(const UListFormatter* listfmt, int32_t resultCapacity, UErrorCode* status); -#ifndef U_HIDE_DRAFT_API /** * Formats a list of strings to a UFormattedList, which exposes more * information than the string exported by ulistfmt_format(). @@ -240,7 +318,7 @@ ulistfmt_format(const UListFormatter* listfmt, * operation. See ulistfmt_openResult(). * @param status * Error code set if an error occurred during formatting. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI void U_EXPORT2 ulistfmt_formatStringsToResult( @@ -250,7 +328,6 @@ ulistfmt_formatStringsToResult( int32_t stringCount, UFormattedList* uresult, UErrorCode* status); -#endif /* U_HIDE_DRAFT_API */ #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/unicode/unum.h b/deps/icu-small/source/i18n/unicode/unum.h index 77cde03533f4d1..b5f21ea5859071 100644 --- a/deps/icu-small/source/i18n/unicode/unum.h +++ b/deps/icu-small/source/i18n/unicode/unum.h @@ -377,12 +377,10 @@ typedef enum UNumberFormatFields { UNUM_PERMILL_FIELD, /** @stable ICU 49 */ UNUM_SIGN_FIELD, -#ifndef U_HIDE_DRAFT_API - /** @draft ICU 64 */ + /** @stable ICU 64 */ UNUM_MEASURE_UNIT_FIELD, - /** @draft ICU 64 */ + /** @stable ICU 64 */ UNUM_COMPACT_FIELD, -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DEPRECATED_API /** @@ -1032,17 +1030,15 @@ typedef enum UNumberFormatAttribute { * @stable ICU 51 */ UNUM_SCALE = 21, -#ifndef U_HIDE_DRAFT_API /** * Minimum grouping digits; most commonly set to 2 to print "1000" instead of "1,000". * See DecimalFormat::getMinimumGroupingDigits(). * * For better control over grouping strategies, use UNumberFormatter. * - * @draft ICU 64 + * @stable ICU 64 */ UNUM_MINIMUM_GROUPING_DIGITS = 22, -#endif /* U_HIDE_DRAFT_API */ /** * if this attribute is set to 0, it is set to UNUM_CURRENCY_STANDARD purpose, @@ -1083,12 +1079,10 @@ typedef enum UNumberFormatAttribute { */ UNUM_PARSE_DECIMAL_MARK_REQUIRED = 0x1002, -#ifndef U_HIDE_DRAFT_API - /** * Parsing: if set to 1, parsing is sensitive to case (lowercase/uppercase). * - * @draft ICU 64 + * @stable ICU 64 */ UNUM_PARSE_CASE_SENSITIVE = 0x1003, @@ -1097,12 +1091,10 @@ typedef enum UNumberFormatAttribute { * * For better control over sign display, use UNumberFormatter. * - * @draft ICU 64 + * @stable ICU 64 */ UNUM_SIGN_ALWAYS_SHOWN = 0x1004, -#endif /* U_HIDE_DRAFT_API */ - #ifndef U_HIDE_INTERNAL_API /** Limit of boolean attributes. (value should * not depend on U_HIDE conditionals) diff --git a/deps/icu-small/source/i18n/unicode/unumberformatter.h b/deps/icu-small/source/i18n/unicode/unumberformatter.h index b27507f7a8f561..af98ba0027238a 100644 --- a/deps/icu-small/source/i18n/unicode/unumberformatter.h +++ b/deps/icu-small/source/i18n/unicode/unumberformatter.h @@ -336,7 +336,7 @@ typedef enum UNumberSignDisplay { /** * Show the minus sign on negative numbers and the plus sign on positive numbers. Do not show a - * sign on zero or NaN, unless the sign bit is set (-0.0 gets a sign). + * sign on zero, numbers that round to zero, or NaN. * * @stable ICU 61 */ @@ -344,9 +344,8 @@ typedef enum UNumberSignDisplay { /** * Use the locale-dependent accounting format on negative numbers, and show the plus sign on - * positive numbers. Do not show a sign on zero or NaN, unless the sign bit is set (-0.0 gets a - * sign). For more information on the accounting format, see the ACCOUNTING sign display - * strategy. + * positive numbers. Do not show a sign on zero, numbers that round to zero, or NaN. For more + * information on the accounting format, see the ACCOUNTING sign display strategy. * * @stable ICU 61 */ @@ -428,7 +427,7 @@ typedef struct UFormattedNumber UFormattedNumber; * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead. * * @param skeleton The skeleton string, like u"percent precision-integer" - * @param skeletonLen The number of UChars in the skeleton string, or -1 it it is NUL-terminated. + * @param skeletonLen The number of UChars in the skeleton string, or -1 if it is NUL-terminated. * @param locale The NUL-terminated locale ID. * @param ec Set if an error occurs. * @stable ICU 62 @@ -438,23 +437,21 @@ unumf_openForSkeletonAndLocale(const UChar* skeleton, int32_t skeletonLen, const UErrorCode* ec); -#ifndef U_HIDE_DRAFT_API /** * Like unumf_openForSkeletonAndLocale, but accepts a UParseError, which will be populated with the * location of a skeleton syntax error if such a syntax error exists. * * @param skeleton The skeleton string, like u"percent precision-integer" - * @param skeletonLen The number of UChars in the skeleton string, or -1 it it is NUL-terminated. + * @param skeletonLen The number of UChars in the skeleton string, or -1 if it is NUL-terminated. * @param locale The NUL-terminated locale ID. * @param perror A parse error struct populated if an error occurs when parsing. Can be NULL. * If no error occurs, perror->offset will be set to -1. * @param ec Set if an error occurs. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT UNumberFormatter* U_EXPORT2 +U_STABLE UNumberFormatter* U_EXPORT2 unumf_openForSkeletonAndLocaleWithError( const UChar* skeleton, int32_t skeletonLen, const char* locale, UParseError* perror, UErrorCode* ec); -#endif // U_HIDE_DRAFT_API /** @@ -532,7 +529,6 @@ U_STABLE void U_EXPORT2 unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32_t valueLen, UFormattedNumber* uresult, UErrorCode* ec); -#ifndef U_HIDE_DRAFT_API /** * Returns a representation of a UFormattedNumber as a UFormattedValue, * which can be subsequently passed to any API requiring that type. @@ -545,11 +541,10 @@ unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32 * @param uresult The object containing the formatted string. * @param ec Set if an error occurs. * @return A UFormattedValue owned by the input object. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT const UFormattedValue* U_EXPORT2 +U_STABLE const UFormattedValue* U_EXPORT2 unumf_resultAsValue(const UFormattedNumber* uresult, UErrorCode* ec); -#endif /* U_HIDE_DRAFT_API */ /** diff --git a/deps/icu-small/source/i18n/unicode/upluralrules.h b/deps/icu-small/source/i18n/unicode/upluralrules.h index fc1b2fb57173b8..9c09dfab8bb9f6 100644 --- a/deps/icu-small/source/i18n/unicode/upluralrules.h +++ b/deps/icu-small/source/i18n/unicode/upluralrules.h @@ -152,7 +152,6 @@ uplrules_select(const UPluralRules *uplrules, UChar *keyword, int32_t capacity, UErrorCode *status); -#ifndef U_HIDE_DRAFT_API /** * Given a formatted number, returns the keyword of the first rule * that applies to the number, according to the supplied UPluralRules object. @@ -168,14 +167,13 @@ uplrules_select(const UPluralRules *uplrules, * @param capacity The capacity of the keyword buffer. * @param status A pointer to a UErrorCode to receive any errors. * @return The length of the keyword. - * @draft ICU 64 + * @stable ICU 64 */ U_CAPI int32_t U_EXPORT2 uplrules_selectFormatted(const UPluralRules *uplrules, const struct UFormattedNumber* number, UChar *keyword, int32_t capacity, UErrorCode *status); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_INTERNAL_API /** diff --git a/deps/icu-small/source/i18n/unicode/ureldatefmt.h b/deps/icu-small/source/i18n/unicode/ureldatefmt.h index 1aa554dc7c0d7a..d12f0988a88ed1 100644 --- a/deps/icu-small/source/i18n/unicode/ureldatefmt.h +++ b/deps/icu-small/source/i18n/unicode/ureldatefmt.h @@ -175,25 +175,23 @@ typedef enum URelativeDateTimeUnit { #endif /* U_HIDE_DEPRECATED_API */ } URelativeDateTimeUnit; -#ifndef U_HIDE_DRAFT_API /** * FieldPosition and UFieldPosition selectors for format fields * defined by RelativeDateTimeFormatter. - * @draft ICU 64 + * @stable ICU 64 */ typedef enum URelativeDateTimeFormatterField { /** * Represents a literal text string, like "tomorrow" or "days ago". - * @draft ICU 64 + * @stable ICU 64 */ UDAT_REL_LITERAL_FIELD, /** * Represents a number quantity, like "3" in "3 days ago". - * @draft ICU 64 + * @stable ICU 64 */ UDAT_REL_NUMERIC_FIELD, } URelativeDateTimeFormatterField; -#endif // U_HIDE_DRAFT_API /** @@ -252,11 +250,10 @@ ureldatefmt_open( const char* locale, U_STABLE void U_EXPORT2 ureldatefmt_close(URelativeDateTimeFormatter *reldatefmt); -#ifndef U_HIDE_DRAFT_API struct UFormattedRelativeDateTime; /** * Opaque struct to contain the results of a URelativeDateTimeFormatter operation. - * @draft ICU 64 + * @stable ICU 64 */ typedef struct UFormattedRelativeDateTime UFormattedRelativeDateTime; @@ -267,9 +264,9 @@ typedef struct UFormattedRelativeDateTime UFormattedRelativeDateTime; * * @param ec Set if an error occurs. * @return A pointer needing ownership. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT UFormattedRelativeDateTime* U_EXPORT2 +U_STABLE UFormattedRelativeDateTime* U_EXPORT2 ureldatefmt_openResult(UErrorCode* ec); /** @@ -284,20 +281,19 @@ ureldatefmt_openResult(UErrorCode* ec); * @param ufrdt The object containing the formatted string. * @param ec Set if an error occurs. * @return A UFormattedValue owned by the input object. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT const UFormattedValue* U_EXPORT2 +U_STABLE const UFormattedValue* U_EXPORT2 ureldatefmt_resultAsValue(const UFormattedRelativeDateTime* ufrdt, UErrorCode* ec); /** * Releases the UFormattedRelativeDateTime created by ureldatefmt_openResult. * * @param ufrdt The object to release. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ureldatefmt_closeResult(UFormattedRelativeDateTime* ufrdt); -#endif /* U_HIDE_DRAFT_API */ #if U_SHOW_CPLUSPLUS_API @@ -315,7 +311,6 @@ U_NAMESPACE_BEGIN */ U_DEFINE_LOCAL_OPEN_POINTER(LocalURelativeDateTimeFormatterPointer, URelativeDateTimeFormatter, ureldatefmt_close); -#ifndef U_HIDE_DRAFT_API /** * \class LocalUFormattedRelativeDateTimePointer * "Smart pointer" class, closes a UFormattedRelativeDateTime via ureldatefmt_closeResult(). @@ -323,10 +318,9 @@ U_DEFINE_LOCAL_OPEN_POINTER(LocalURelativeDateTimeFormatterPointer, URelativeDat * * @see LocalPointerBase * @see LocalPointer - * @draft ICU 64 + * @stable ICU 64 */ U_DEFINE_LOCAL_OPEN_POINTER(LocalUFormattedRelativeDateTimePointer, UFormattedRelativeDateTime, ureldatefmt_closeResult); -#endif /* U_HIDE_DRAFT_API */ U_NAMESPACE_END @@ -368,7 +362,6 @@ ureldatefmt_formatNumeric( const URelativeDateTimeFormatter* reldatefmt, int32_t resultCapacity, UErrorCode* status); -#ifndef U_HIDE_DRAFT_API /** * Format a combination of URelativeDateTimeUnit and numeric * offset using a numeric style, e.g. "1 week ago", "in 1 week", @@ -390,16 +383,15 @@ ureldatefmt_formatNumeric( const URelativeDateTimeFormatter* reldatefmt, * A pointer to a UErrorCode to receive any errors. In * case of error status, the contents of result are * undefined. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ureldatefmt_formatNumericToResult( const URelativeDateTimeFormatter* reldatefmt, double offset, URelativeDateTimeUnit unit, UFormattedRelativeDateTime* result, UErrorCode* status); -#endif /* U_HIDE_DRAFT_API */ /** * Format a combination of URelativeDateTimeUnit and numeric offset @@ -437,7 +429,6 @@ ureldatefmt_format( const URelativeDateTimeFormatter* reldatefmt, int32_t resultCapacity, UErrorCode* status); -#ifndef U_HIDE_DRAFT_API /** * Format a combination of URelativeDateTimeUnit and numeric offset * using a text style if possible, e.g. "last week", "this week", @@ -462,16 +453,15 @@ ureldatefmt_format( const URelativeDateTimeFormatter* reldatefmt, * A pointer to a UErrorCode to receive any errors. In * case of error status, the contents of result are * undefined. - * @draft ICU 64 + * @stable ICU 64 */ -U_DRAFT void U_EXPORT2 +U_STABLE void U_EXPORT2 ureldatefmt_formatToResult( const URelativeDateTimeFormatter* reldatefmt, double offset, URelativeDateTimeUnit unit, UFormattedRelativeDateTime* result, UErrorCode* status); -#endif /* U_HIDE_DRAFT_API */ /** * Combines a relative date string and a time string in this object's diff --git a/deps/icu-small/source/i18n/uregex.cpp b/deps/icu-small/source/i18n/uregex.cpp index ff6e65b38e2d60..763a78a14a9b4d 100644 --- a/deps/icu-small/source/i18n/uregex.cpp +++ b/deps/icu-small/source/i18n/uregex.cpp @@ -1508,7 +1508,8 @@ int32_t RegexCImpl::appendReplacement(RegularExpression *regexp, (c32 >= 0x31 && c32 <= 0x39)) { // 0..9 groupName.append(c32); } else if (c32 == RIGHTBRACKET) { - groupNum = uhash_geti(regexp->fPat->fNamedCaptureMap, &groupName); + groupNum = regexp->fPat->fNamedCaptureMap ? + uhash_geti(regexp->fPat->fNamedCaptureMap, &groupName) : 0; if (groupNum == 0) { // Name not defined by pattern. *status = U_REGEX_INVALID_CAPTURE_GROUP_NAME; diff --git a/deps/icu-small/source/i18n/uspoof.cpp b/deps/icu-small/source/i18n/uspoof.cpp index c44c60028badcc..e2360924d02658 100644 --- a/deps/icu-small/source/i18n/uspoof.cpp +++ b/deps/icu-small/source/i18n/uspoof.cpp @@ -79,65 +79,66 @@ void U_CALLCONV initializeStatics(UErrorCode &status) { u"\\u030C\\u030F-\\u0311\\u0313\\u0314\\u031B\\u0323-\\u0328\\u032D\\u032E" u"\\u0330\\u0331\\u0335\\u0338\\u0339\\u0342\\u0345\\u037B-\\u037D\\u0386" u"\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03CE\\u03FC-\\u045F\\u048A-" - u"\\u0529\\u052E\\u052F\\u0531-\\u0556\\u0559\\u0560-\\u0586\\u0588\\u05B4" - u"\\u05D0-\\u05EA\\u05EF-\\u05F2\\u0620-\\u063F\\u0641-\\u0655\\u0660-\\u0669" - u"\\u0670-\\u0672\\u0674\\u0679-\\u068D\\u068F-\\u06D3\\u06D5\\u06E5\\u06E6" - u"\\u06EE-\\u06FC\\u06FF\\u0750-\\u07B1\\u08A0-\\u08AC\\u08B2\\u08B6-\\u08BD" - u"\\u0901-\\u094D\\u094F\\u0950\\u0956\\u0957\\u0960-\\u0963\\u0966-\\u096F" - u"\\u0971-\\u0977\\u0979-\\u097F\\u0981-\\u0983\\u0985-\\u098C\\u098F\\u0990" - u"\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BC-\\u09C4\\u09C7" - u"\\u09C8\\u09CB-\\u09CE\\u09D7\\u09E0-\\u09E3\\u09E6-\\u09F1\\u09FC\\u09FE" - u"\\u0A01-\\u0A03\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30" - u"\\u0A32\\u0A35\\u0A38\\u0A39\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-" - u"\\u0A4D\\u0A5C\\u0A66-\\u0A74\\u0A81-\\u0A83\\u0A85-\\u0A8D\\u0A8F-\\u0A91" - u"\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABC-\\u0AC5" - u"\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AD0\\u0AE0-\\u0AE3\\u0AE6-\\u0AEF\\u0AFA-" - u"\\u0AFF\\u0B01-\\u0B03\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-" - u"\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3C-\\u0B43\\u0B47\\u0B48\\u0B4B-" - u"\\u0B4D\\u0B56\\u0B57\\u0B5F-\\u0B61\\u0B66-\\u0B6F\\u0B71\\u0B82\\u0B83" - u"\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E" - u"\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BBE-\\u0BC2\\u0BC6-" - u"\\u0BC8\\u0BCA-\\u0BCD\\u0BD0\\u0BD7\\u0BE6-\\u0BEF\\u0C01-\\u0C0C\\u0C0E-" - u"\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D-\\u0C44\\u0C46-" - u"\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C60\\u0C61\\u0C66-\\u0C6F\\u0C80" - u"\\u0C82\\u0C83\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3" - u"\\u0CB5-\\u0CB9\\u0CBC-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6" - u"\\u0CE0-\\u0CE3\\u0CE6-\\u0CEF\\u0CF1\\u0CF2\\u0D00\\u0D02\\u0D03\\u0D05-" - u"\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D43\\u0D46-\\u0D48\\u0D4A-\\u0D4E\\u0D54-" - u"\\u0D57\\u0D60\\u0D61\\u0D66-\\u0D6F\\u0D7A-\\u0D7F\\u0D82\\u0D83\\u0D85-" - u"\\u0D8E\\u0D91-\\u0D96\\u0D9A-\\u0DA5\\u0DA7-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD" - u"\\u0DC0-\\u0DC6\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDE\\u0DF2\\u0E01-" - u"\\u0E32\\u0E34-\\u0E3A\\u0E40-\\u0E4E\\u0E50-\\u0E59\\u0E81\\u0E82\\u0E84" - u"\\u0E86-\\u0E8A\\u0E8C-\\u0EA3\\u0EA5\\u0EA7-\\u0EB2\\u0EB4-\\u0EBD\\u0EC0-" - u"\\u0EC4\\u0EC6\\u0EC8-\\u0ECD\\u0ED0-\\u0ED9\\u0EDE\\u0EDF\\u0F00\\u0F20-" - u"\\u0F29\\u0F35\\u0F37\\u0F3E-\\u0F42\\u0F44-\\u0F47\\u0F49-\\u0F4C\\u0F4E-" - u"\\u0F51\\u0F53-\\u0F56\\u0F58-\\u0F5B\\u0F5D-\\u0F68\\u0F6A-\\u0F6C\\u0F71" - u"\\u0F72\\u0F74\\u0F7A-\\u0F80\\u0F82-\\u0F84\\u0F86-\\u0F92\\u0F94-\\u0F97" - u"\\u0F99-\\u0F9C\\u0F9E-\\u0FA1\\u0FA3-\\u0FA6\\u0FA8-\\u0FAB\\u0FAD-\\u0FB8" - u"\\u0FBA-\\u0FBC\\u0FC6\\u1000-\\u1049\\u1050-\\u109D\\u10C7\\u10CD\\u10D0-" - u"\\u10F0\\u10F7-\\u10FA\\u10FD-\\u10FF\\u1200-\\u1248\\u124A-\\u124D\\u1250-" - u"\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0" - u"\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-" - u"\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u135D-\\u135F\\u1380-\\u138F\\u1780-" - u"\\u17A2\\u17A5-\\u17A7\\u17A9-\\u17B3\\u17B6-\\u17CA\\u17D2\\u17D7\\u17DC" - u"\\u17E0-\\u17E9\\u1C80-\\u1C88\\u1C90-\\u1CBA\\u1CBD-\\u1CBF\\u1E00-\\u1E99" - u"\\u1E9E\\u1EA0-\\u1EF9\\u1F00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-" - u"\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F70\\u1F72\\u1F74" - u"\\u1F76\\u1F78\\u1F7A\\u1F7C\\u1F80-\\u1FB4\\u1FB6-\\u1FBA\\u1FBC\\u1FC2-" - u"\\u1FC4\\u1FC6-\\u1FC8\\u1FCA\\u1FCC\\u1FD0-\\u1FD2\\u1FD6-\\u1FDA\\u1FE0-" - u"\\u1FE2\\u1FE4-\\u1FEA\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FF8\\u1FFA\\u1FFC" - u"\\u2D27\\u2D2D\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6" - u"\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE" - u"\\u3005-\\u3007\\u3041-\\u3096\\u3099\\u309A\\u309D\\u309E\\u30A1-\\u30FA" - u"\\u30FC-\\u30FE\\u3105-\\u312F\\u31A0-\\u31BA\\u3400-\\u4DB5\\u4E00-\\u9FEF" - u"\\uA660\\uA661\\uA674-\\uA67B\\uA67F\\uA69F\\uA717-\\uA71F\\uA788\\uA78D" - u"\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7AE\\uA7AF\\uA7B8-\\uA7BF\\uA7C2-" - u"\\uA7C6\\uA7FA\\uA9E7-\\uA9FE\\uAA60-\\uAA76\\uAA7A-\\uAA7F\\uAB01-\\uAB06" - u"\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB66\\uAB67" - u"\\uAC00-\\uD7A3\\uFA0E\\uFA0F\\uFA11\\uFA13\\uFA14\\uFA1F\\uFA21\\uFA23" - u"\\uFA24\\uFA27-\\uFA29\\U0001133B\\U0001B150-\\U0001B152\\U0001B164-" - u"\\U0001B167\\U00020000-\\U0002A6D6\\U0002A700-\\U0002B734\\U0002B740-" - u"\\U0002B81D\\U0002B820-\\U0002CEA1\\U0002CEB0-\\U0002EBE0]"; + u"\\u04FF\\u0510-\\u0529\\u052E\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0586" + u"\\u05B4\\u05D0-\\u05EA\\u05EF-\\u05F2\\u0620-\\u063F\\u0641-\\u0655\\u0660-" + u"\\u0669\\u0670-\\u0672\\u0674\\u0679-\\u068D\\u068F-\\u06A0\\u06A2-\\u06D3" + u"\\u06D5\\u06E5\\u06E6\\u06EE-\\u06FC\\u06FF\\u0750-\\u07B1\\u08A0-\\u08AC" + u"\\u08B2\\u08B6-\\u08C7\\u0901-\\u094D\\u094F\\u0950\\u0956\\u0957\\u0960-" + u"\\u0963\\u0966-\\u096F\\u0971-\\u0977\\u0979-\\u097F\\u0981-\\u0983\\u0985-" + u"\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9" + u"\\u09BC-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CE\\u09D7\\u09E0-\\u09E3\\u09E6-" + u"\\u09F1\\u09FE\\u0A01-\\u0A03\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28" + u"\\u0A2A-\\u0A30\\u0A32\\u0A35\\u0A38\\u0A39\\u0A3C\\u0A3E-\\u0A42\\u0A47" + u"\\u0A48\\u0A4B-\\u0A4D\\u0A5C\\u0A66-\\u0A74\\u0A81-\\u0A83\\u0A85-\\u0A8D" + u"\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9" + u"\\u0ABC-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AD0\\u0AE0-\\u0AE3\\u0AE6-" + u"\\u0AEF\\u0AFA-\\u0AFF\\u0B01-\\u0B03\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-" + u"\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3C-\\u0B43\\u0B47" + u"\\u0B48\\u0B4B-\\u0B4D\\u0B55-\\u0B57\\u0B5F-\\u0B61\\u0B66-\\u0B6F\\u0B71" + u"\\u0B82\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A" + u"\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BBE-" + u"\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD0\\u0BD7\\u0BE6-\\u0BEF\\u0C01-" + u"\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D-" + u"\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C60\\u0C61\\u0C66-" + u"\\u0C6F\\u0C80\\u0C82\\u0C83\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8" + u"\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBC-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD" + u"\\u0CD5\\u0CD6\\u0CE0-\\u0CE3\\u0CE6-\\u0CEF\\u0CF1\\u0CF2\\u0D00\\u0D02" + u"\\u0D03\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D-\\u0D43\\u0D46-" + u"\\u0D48\\u0D4A-\\u0D4E\\u0D54-\\u0D57\\u0D60\\u0D61\\u0D66-\\u0D6F\\u0D7A-" + u"\\u0D7F\\u0D82\\u0D83\\u0D85-\\u0D8E\\u0D91-\\u0D96\\u0D9A-\\u0DA5\\u0DA7-" + u"\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0DCA\\u0DCF-\\u0DD4\\u0DD6" + u"\\u0DD8-\\u0DDE\\u0DF2\\u0E01-\\u0E32\\u0E34-\\u0E3A\\u0E40-\\u0E4E\\u0E50-" + u"\\u0E59\\u0E81\\u0E82\\u0E84\\u0E86-\\u0E8A\\u0E8C-\\u0EA3\\u0EA5\\u0EA7-" + u"\\u0EB2\\u0EB4-\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EC8-\\u0ECD\\u0ED0-\\u0ED9" + u"\\u0EDE\\u0EDF\\u0F00\\u0F20-\\u0F29\\u0F35\\u0F37\\u0F3E-\\u0F42\\u0F44-" + u"\\u0F47\\u0F49-\\u0F4C\\u0F4E-\\u0F51\\u0F53-\\u0F56\\u0F58-\\u0F5B\\u0F5D-" + u"\\u0F68\\u0F6A-\\u0F6C\\u0F71\\u0F72\\u0F74\\u0F7A-\\u0F80\\u0F82-\\u0F84" + u"\\u0F86-\\u0F92\\u0F94-\\u0F97\\u0F99-\\u0F9C\\u0F9E-\\u0FA1\\u0FA3-\\u0FA6" + u"\\u0FA8-\\u0FAB\\u0FAD-\\u0FB8\\u0FBA-\\u0FBC\\u0FC6\\u1000-\\u1049\\u1050-" + u"\\u109D\\u10C7\\u10CD\\u10D0-\\u10F0\\u10F7-\\u10FA\\u10FD-\\u10FF\\u1200-" + u"\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288" + u"\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-" + u"\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u135D-" + u"\\u135F\\u1380-\\u138F\\u1780-\\u17A2\\u17A5-\\u17A7\\u17A9-\\u17B3\\u17B6-" + u"\\u17CA\\u17D2\\u17D7\\u17DC\\u17E0-\\u17E9\\u1C90-\\u1CBA\\u1CBD-\\u1CBF" + u"\\u1E00-\\u1E99\\u1E9E\\u1EA0-\\u1EF9\\u1F00-\\u1F15\\u1F18-\\u1F1D\\u1F20-" + u"\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F70" + u"\\u1F72\\u1F74\\u1F76\\u1F78\\u1F7A\\u1F7C\\u1F80-\\u1FB4\\u1FB6-\\u1FBA" + u"\\u1FBC\\u1FC2-\\u1FC4\\u1FC6-\\u1FC8\\u1FCA\\u1FCC\\u1FD0-\\u1FD2\\u1FD6-" + u"\\u1FDA\\u1FE0-\\u1FE2\\u1FE4-\\u1FEA\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FF8" + u"\\u1FFA\\u1FFC\\u2D27\\u2D2D\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE" + u"\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6" + u"\\u2DD8-\\u2DDE\\u3005-\\u3007\\u3041-\\u3096\\u3099\\u309A\\u309D\\u309E" + u"\\u30A1-\\u30FA\\u30FC-\\u30FE\\u3105-\\u312D\\u312F\\u31A0-\\u31BF\\u3400-" + u"\\u4DBF\\u4E00-\\u9FFC\\uA67F\\uA717-\\uA71F\\uA788\\uA78D\\uA792\\uA793" + u"\\uA7AA\\uA7AE\\uA7B8\\uA7B9\\uA7C2-\\uA7CA\\uA9E7-\\uA9FE\\uAA60-\\uAA76" + u"\\uAA7A-\\uAA7F\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26" + u"\\uAB28-\\uAB2E\\uAB66\\uAB67\\uAC00-\\uD7A3\\uFA0E\\uFA0F\\uFA11\\uFA13" + u"\\uFA14\\uFA1F\\uFA21\\uFA23\\uFA24\\uFA27-\\uFA29\\U00011301\\U00011303" + u"\\U0001133B\\U0001133C\\U00016FF0\\U00016FF1\\U0001B150-\\U0001B152" + u"\\U0001B164-\\U0001B167\\U00020000-\\U0002A6DD\\U0002A700-\\U0002B734" + u"\\U0002B740-\\U0002B81D\\U0002B820-\\U0002CEA1\\U0002CEB0-\\U0002EBE0" + u"\\U00030000-\\U0003134A]"; gRecommendedSet = new UnicodeSet(UnicodeString(recommendedPat), status); if (gRecommendedSet == NULL) { diff --git a/deps/icu-small/source/i18n/vtzone.cpp b/deps/icu-small/source/i18n/vtzone.cpp index bda3d1115e3d13..aa2e1763966710 100644 --- a/deps/icu-small/source/i18n/vtzone.cpp +++ b/deps/icu-small/source/i18n/vtzone.cpp @@ -526,15 +526,15 @@ static void parseRRULE(const UnicodeString& rrule, int32_t& month, int32_t& dow, static TimeZoneRule* createRuleByRRULE(const UnicodeString& zonename, int rawOffset, int dstSavings, UDate start, UVector* dates, int fromOffset, UErrorCode& status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } - if (dates == NULL || dates->size() == 0) { + if (dates == nullptr || dates->size() == 0) { status = U_ILLEGAL_ARGUMENT_ERROR; - return NULL; + return nullptr; } int32_t i, j; - DateTimeRule *adtr = NULL; + DateTimeRule *adtr = nullptr; // Parse the first rule UnicodeString rrule = *((UnicodeString*)dates->elementAt(0)); @@ -545,7 +545,7 @@ static TimeZoneRule* createRuleByRRULE(const UnicodeString& zonename, int rawOff parseRRULE(rrule, month, dayOfWeek, nthDayOfWeek, days, daysCount, until, status); if (U_FAILURE(status)) { - return NULL; + return nullptr; } if (dates->size() == 1) { @@ -620,7 +620,7 @@ static TimeZoneRule* createRuleByRRULE(const UnicodeString& zonename, int rawOff int32_t tmp_daysCount = UPRV_LENGTHOF(tmp_days); parseRRULE(rrule, tmp_month, tmp_dayOfWeek, tmp_nthDayOfWeek, tmp_days, tmp_daysCount, tmp_until, status); if (U_FAILURE(status)) { - return NULL; + return nullptr; } // If UNTIL is newer than previous one, use the one if (tmp_until > until) { @@ -713,14 +713,14 @@ static TimeZoneRule* createRuleByRRULE(const UnicodeString& zonename, int rawOff // first Sunday after 15th day in the month adtr = new DateTimeRule(month, dayOfMonth, dayOfWeek, TRUE, startMID, DateTimeRule::WALL_TIME); } - if (adtr == NULL) { + if (adtr == nullptr) { goto unsupportedRRule; } return new AnnualTimeZoneRule(zonename, rawOffset, dstSavings, adtr, startYear, endYear); unsupportedRRule: status = U_INVALID_STATE_ERROR; - return NULL; + return nullptr; } /* @@ -729,34 +729,35 @@ static TimeZoneRule* createRuleByRRULE(const UnicodeString& zonename, int rawOff static TimeZoneRule* createRuleByRDATE(const UnicodeString& zonename, int32_t rawOffset, int32_t dstSavings, UDate start, UVector* dates, int32_t fromOffset, UErrorCode& status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } - TimeArrayTimeZoneRule *retVal = NULL; - if (dates == NULL || dates->size() == 0) { + TimeArrayTimeZoneRule *retVal = nullptr; + if (dates == nullptr || dates->size() == 0) { // When no RDATE line is provided, use start (DTSTART) // as the transition time - retVal = new TimeArrayTimeZoneRule(zonename, rawOffset, dstSavings, - &start, 1, DateTimeRule::UTC_TIME); + retVal = new TimeArrayTimeZoneRule(zonename, rawOffset, dstSavings, &start, 1, DateTimeRule::UTC_TIME); } else { // Create an array of transition times int32_t size = dates->size(); UDate* times = (UDate*)uprv_malloc(sizeof(UDate) * size); - if (times == NULL) { + if (times == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } for (int32_t i = 0; i < size; i++) { UnicodeString *datestr = (UnicodeString*)dates->elementAt(i); times[i] = parseDateTimeString(*datestr, fromOffset, status); if (U_FAILURE(status)) { uprv_free(times); - return NULL; + return nullptr; } } - retVal = new TimeArrayTimeZoneRule(zonename, rawOffset, dstSavings, - times, size, DateTimeRule::UTC_TIME); + retVal = new TimeArrayTimeZoneRule(zonename, rawOffset, dstSavings, times, size, DateTimeRule::UTC_TIME); uprv_free(times); } + if (retVal == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } return retVal; } @@ -800,12 +801,15 @@ static UBool isEquivalentDateRule(int32_t month, int32_t weekInMonth, int32_t da /* * Convert the rule to its equivalent rule using WALL_TIME mode. - * This function returns NULL when the specified DateTimeRule is already + * This function returns nullptr when the specified DateTimeRule is already * using WALL_TIME mode. */ -static DateTimeRule* toWallTimeRule(const DateTimeRule* rule, int32_t rawOffset, int32_t dstSavings) { +static DateTimeRule *toWallTimeRule(const DateTimeRule *rule, int32_t rawOffset, int32_t dstSavings, UErrorCode &status) { + if (U_FAILURE(status)) { + return nullptr; + } if (rule->getTimeRuleType() == DateTimeRule::WALL_TIME) { - return NULL; + return nullptr; } int32_t wallt = rule->getRuleMillisInDay(); if (rule->getTimeRuleType() == DateTimeRule::UTC_TIME) { @@ -864,12 +868,14 @@ static DateTimeRule* toWallTimeRule(const DateTimeRule* rule, int32_t rawOffset, } } // Create a new rule - DateTimeRule *modifiedRule; + DateTimeRule *modifiedRule = nullptr; if (dtype == DateTimeRule::DOM) { modifiedRule = new DateTimeRule(month, dom, wallt, DateTimeRule::WALL_TIME); } else { - modifiedRule = new DateTimeRule(month, dom, dow, - (dtype == DateTimeRule::DOW_GEQ_DOM), wallt, DateTimeRule::WALL_TIME); + modifiedRule = new DateTimeRule(month, dom, dow, (dtype == DateTimeRule::DOW_GEQ_DOM), wallt, DateTimeRule::WALL_TIME); + } + if (modifiedRule == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; } return modifiedRule; } @@ -956,21 +962,24 @@ VTZReader::read(void) { UOBJECT_DEFINE_RTTI_IMPLEMENTATION(VTimeZone) VTimeZone::VTimeZone() -: BasicTimeZone(), tz(NULL), vtzlines(NULL), +: BasicTimeZone(), tz(nullptr), vtzlines(nullptr), lastmod(MAX_MILLIS) { } VTimeZone::VTimeZone(const VTimeZone& source) -: BasicTimeZone(source), tz(NULL), vtzlines(NULL), +: BasicTimeZone(source), tz(nullptr), vtzlines(nullptr), tzurl(source.tzurl), lastmod(source.lastmod), olsonzid(source.olsonzid), icutzver(source.icutzver) { - if (source.tz != NULL) { + if (source.tz != nullptr) { tz = source.tz->clone(); } - if (source.vtzlines != NULL) { + if (source.vtzlines != nullptr) { UErrorCode status = U_ZERO_ERROR; int32_t size = source.vtzlines->size(); vtzlines = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, size, status); + if (vtzlines == nullptr) { + return; + } if (U_SUCCESS(status)) { for (int32_t i = 0; i < size; i++) { UnicodeString *line = (UnicodeString*)source.vtzlines->elementAt(i); @@ -980,17 +989,17 @@ VTimeZone::VTimeZone(const VTimeZone& source) } } } - if (U_FAILURE(status) && vtzlines != NULL) { + if (U_FAILURE(status) && vtzlines != nullptr) { delete vtzlines; } } } VTimeZone::~VTimeZone() { - if (tz != NULL) { + if (tz != nullptr) { delete tz; } - if (vtzlines != NULL) { + if (vtzlines != nullptr) { delete vtzlines; } } @@ -1002,21 +1011,21 @@ VTimeZone::operator=(const VTimeZone& right) { } if (*this != right) { BasicTimeZone::operator=(right); - if (tz != NULL) { + if (tz != nullptr) { delete tz; - tz = NULL; + tz = nullptr; } - if (right.tz != NULL) { + if (right.tz != nullptr) { tz = right.tz->clone(); } - if (vtzlines != NULL) { + if (vtzlines != nullptr) { delete vtzlines; } - if (right.vtzlines != NULL) { + if (right.vtzlines != nullptr) { UErrorCode status = U_ZERO_ERROR; int32_t size = right.vtzlines->size(); vtzlines = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, size, status); - if (U_SUCCESS(status)) { + if (vtzlines != nullptr && U_SUCCESS(status)) { for (int32_t i = 0; i < size; i++) { UnicodeString *line = (UnicodeString*)right.vtzlines->elementAt(i); vtzlines->addElement(line->clone(), status); @@ -1025,9 +1034,9 @@ VTimeZone::operator=(const VTimeZone& right) { } } } - if (U_FAILURE(status) && vtzlines != NULL) { + if (U_FAILURE(status) && vtzlines != nullptr) { delete vtzlines; - vtzlines = NULL; + vtzlines = nullptr; } } tzurl = right.tzurl; @@ -1065,15 +1074,18 @@ VTimeZone::operator!=(const TimeZone& that) const { VTimeZone* VTimeZone::createVTimeZoneByID(const UnicodeString& ID) { VTimeZone *vtz = new VTimeZone(); + if (vtz == nullptr) { + return nullptr; + } vtz->tz = (BasicTimeZone*)TimeZone::createTimeZone(ID); vtz->tz->getID(vtz->olsonzid); // Set ICU tzdata version UErrorCode status = U_ZERO_ERROR; - UResourceBundle *bundle = NULL; - const UChar* versionStr = NULL; + UResourceBundle *bundle = nullptr; + const UChar* versionStr = nullptr; int32_t len = 0; - bundle = ures_openDirect(NULL, "zoneinfo64", &status); + bundle = ures_openDirect(nullptr, "zoneinfo64", &status); versionStr = ures_getStringByKey(bundle, "TZVersion", &len, &status); if (U_SUCCESS(status)) { vtz->icutzver.setTo(versionStr, len); @@ -1085,26 +1097,26 @@ VTimeZone::createVTimeZoneByID(const UnicodeString& ID) { VTimeZone* VTimeZone::createVTimeZoneFromBasicTimeZone(const BasicTimeZone& basic_time_zone, UErrorCode &status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } VTimeZone *vtz = new VTimeZone(); - if (vtz == NULL) { + if (vtz == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } vtz->tz = basic_time_zone.clone(); - if (vtz->tz == NULL) { + if (vtz->tz == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; delete vtz; - return NULL; + return nullptr; } vtz->tz->getID(vtz->olsonzid); // Set ICU tzdata version - UResourceBundle *bundle = NULL; - const UChar* versionStr = NULL; + UResourceBundle *bundle = nullptr; + const UChar* versionStr = nullptr; int32_t len = 0; - bundle = ures_openDirect(NULL, "zoneinfo64", &status); + bundle = ures_openDirect(nullptr, "zoneinfo64", &status); versionStr = ures_getStringByKey(bundle, "TZVersion", &len, &status); if (U_SUCCESS(status)) { vtz->icutzver.setTo(versionStr, len); @@ -1116,14 +1128,18 @@ VTimeZone::createVTimeZoneFromBasicTimeZone(const BasicTimeZone& basic_time_zone VTimeZone* VTimeZone::createVTimeZone(const UnicodeString& vtzdata, UErrorCode& status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } VTZReader reader(vtzdata); VTimeZone *vtz = new VTimeZone(); + if (vtz == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } vtz->load(reader, status); if (U_FAILURE(status)) { delete vtz; - return NULL; + return nullptr; } return vtz; } @@ -1251,6 +1267,9 @@ VTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial, void VTimeZone::load(VTZReader& reader, UErrorCode& status) { vtzlines = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, DEFAULT_VTIMEZONE_LINES, status); + if (vtzlines == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } if (U_FAILURE(status)) { return; } @@ -1264,10 +1283,15 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) { if (ch == 0xFFFF) { // end of file if (start && line.startsWith(ICAL_END_VTIMEZONE, -1)) { - vtzlines->addElement(new UnicodeString(line), status); + LocalPointer element(new UnicodeString(line), status); + if (U_FAILURE(status)) { + goto cleanupVtzlines; + } + vtzlines->addElement(element.getAlias(), status); if (U_FAILURE(status)) { goto cleanupVtzlines; } + element.orphan(); // on success, vtzlines owns the object. success = TRUE; } break; @@ -1281,10 +1305,15 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) { // NOT followed by TAB/SP -> new line if (start) { if (line.length() > 0) { - vtzlines->addElement(new UnicodeString(line), status); + LocalPointer element(new UnicodeString(line), status); if (U_FAILURE(status)) { goto cleanupVtzlines; } + vtzlines->addElement(element.getAlias(), status); + if (U_FAILURE(status)) { + goto cleanupVtzlines; + } + element.orphan(); // on success, vtzlines owns the object. } } line.remove(); @@ -1299,19 +1328,29 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) { eol = TRUE; if (start) { if (line.startsWith(ICAL_END_VTIMEZONE, -1)) { - vtzlines->addElement(new UnicodeString(line), status); + LocalPointer element(new UnicodeString(line), status); + if (U_FAILURE(status)) { + goto cleanupVtzlines; + } + vtzlines->addElement(element.getAlias(), status); if (U_FAILURE(status)) { goto cleanupVtzlines; } + element.orphan(); // on success, vtzlines owns the object. success = TRUE; break; } } else { if (line.startsWith(ICAL_BEGIN_VTIMEZONE, -1)) { - vtzlines->addElement(new UnicodeString(line), status); + LocalPointer element(new UnicodeString(line), status); if (U_FAILURE(status)) { goto cleanupVtzlines; } + vtzlines->addElement(element.getAlias(), status); + if (U_FAILURE(status)) { + goto cleanupVtzlines; + } + element.orphan(); // on success, vtzlines owns the object. line.remove(); start = TRUE; eol = FALSE; @@ -1333,7 +1372,7 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) { cleanupVtzlines: delete vtzlines; - vtzlines = NULL; + vtzlines = nullptr; } // parser state @@ -1349,12 +1388,12 @@ VTimeZone::parse(UErrorCode& status) { if (U_FAILURE(status)) { return; } - if (vtzlines == NULL || vtzlines->size() == 0) { + if (vtzlines == nullptr || vtzlines->size() == 0) { status = U_INVALID_STATE_ERROR; return; } - InitialTimeZoneRule *initialRule = NULL; - RuleBasedTimeZone *rbtz = NULL; + InitialTimeZoneRule *initialRule = nullptr; + RuleBasedTimeZone *rbtz = nullptr; // timezone ID UnicodeString tzid; @@ -1373,13 +1412,16 @@ VTimeZone::parse(UErrorCode& status) { UnicodeString name; // RFC2445 prop name UnicodeString value; // RFC2445 prop value - UVector *dates = NULL; // list of RDATE or RRULE strings - UVector *rules = NULL; // list of TimeZoneRule instances + UVector *dates = nullptr; // list of RDATE or RRULE strings + UVector *rules = nullptr; // list of TimeZoneRule instances int32_t finalRuleIdx = -1; int32_t finalRuleCount = 0; rules = new UVector(status); + if (rules == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } if (U_FAILURE(status)) { goto cleanupParse; } @@ -1387,11 +1429,10 @@ VTimeZone::parse(UErrorCode& status) { rules->setDeleter(deleteTimeZoneRule); dates = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); - if (U_FAILURE(status)) { - goto cleanupParse; - } - if (rules == NULL || dates == NULL) { + if (dates == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; + } + if (U_FAILURE(status)) { goto cleanupParse; } @@ -1468,7 +1509,7 @@ VTimeZone::parse(UErrorCode& status) { // by comma UBool nextDate = TRUE; int32_t dstart = 0; - UnicodeString *dstr; + UnicodeString *dstr = nullptr; while (nextDate) { int32_t dend = value.indexOf(COMMA, dstart); if (dend == -1) { @@ -1477,7 +1518,11 @@ VTimeZone::parse(UErrorCode& status) { } else { dstr = new UnicodeString(value, dstart, dend - dstart); } - dates->addElement(dstr, status); + if (dstr == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } else { + dates->addElement(dstr, status); + } if (U_FAILURE(status)) { goto cleanupParse; } @@ -1489,10 +1534,15 @@ VTimeZone::parse(UErrorCode& status) { goto cleanupParse; } isRRULE = true; - dates->addElement(new UnicodeString(value), status); + LocalPointer element(new UnicodeString(value), status); + if (U_FAILURE(status)) { + goto cleanupParse; + } + dates->addElement(element.getAlias(), status); if (U_FAILURE(status)) { goto cleanupParse; } + element.orphan(); // on success, dates owns the object. } else if (name.compare(ICAL_END, -1) == 0) { // Mandatory properties if (dtstart.length() == 0 || from.length() == 0 || to.length() == 0) { @@ -1504,7 +1554,7 @@ VTimeZone::parse(UErrorCode& status) { } // create a time zone rule - TimeZoneRule *rule = NULL; + TimeZoneRule *rule = nullptr; int32_t fromOffset = 0; int32_t toOffset = 0; int32_t rawOffset = 0; @@ -1546,7 +1596,7 @@ VTimeZone::parse(UErrorCode& status) { } else { rule = createRuleByRDATE(zonename, rawOffset, dstSavings, start, dates, fromOffset, status); } - if (U_FAILURE(status) || rule == NULL) { + if (U_FAILURE(status) || rule == nullptr) { goto cleanupParse; } else { UBool startAvail = rule->getFirstStart(fromOffset, 0, actualStart); @@ -1586,25 +1636,24 @@ VTimeZone::parse(UErrorCode& status) { // Create a initial rule getDefaultTZName(tzid, FALSE, zonename); - initialRule = new InitialTimeZoneRule(zonename, - initialRawOffset, initialDSTSavings); - if (initialRule == NULL) { + initialRule = new InitialTimeZoneRule(zonename, initialRawOffset, initialDSTSavings); + if (initialRule == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; goto cleanupParse; } // Finally, create the RuleBasedTimeZone rbtz = new RuleBasedTimeZone(tzid, initialRule); - if (rbtz == NULL) { + if (rbtz == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; goto cleanupParse; } - initialRule = NULL; // already adopted by RBTZ, no need to delete + initialRule = nullptr; // already adopted by RBTZ, no need to delete for (n = 0; n < rules->size(); n++) { TimeZoneRule *r = (TimeZoneRule*)rules->elementAt(n); AnnualTimeZoneRule *atzrule = dynamic_cast(r); - if (atzrule != NULL) { + if (atzrule != nullptr) { if (atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) { finalRuleCount++; finalRuleIdx = n; @@ -1649,7 +1698,7 @@ VTimeZone::parse(UErrorCode& status) { } } - TimeZoneRule *newRule; + TimeZoneRule *newRule = nullptr; UnicodeString tznam; if (start == finalStart) { // Transform this into a single transition @@ -1672,7 +1721,7 @@ VTimeZone::parse(UErrorCode& status) { finalRule->getStartYear(), y); } - if (newRule == NULL) { + if (newRule == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; goto cleanupParse; } @@ -1704,20 +1753,20 @@ VTimeZone::parse(UErrorCode& status) { return; cleanupParse: - if (rules != NULL) { + if (rules != nullptr) { while (!rules->isEmpty()) { TimeZoneRule *r = (TimeZoneRule*)rules->orphanElementAt(0); delete r; } delete rules; } - if (dates != NULL) { + if (dates != nullptr) { delete dates; } - if (initialRule != NULL) { + if (initialRule != nullptr) { delete initialRule; } - if (rbtz != NULL) { + if (rbtz != nullptr) { delete rbtz; } return; @@ -1725,7 +1774,7 @@ VTimeZone::parse(UErrorCode& status) { void VTimeZone::write(VTZWriter& writer, UErrorCode& status) const { - if (vtzlines != NULL) { + if (vtzlines != nullptr) { for (int32_t i = 0; i < vtzlines->size(); i++) { UnicodeString *line = (UnicodeString*)vtzlines->elementAt(i); if (line->startsWith(ICAL_TZURL, -1) @@ -1765,8 +1814,8 @@ VTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) const { if (U_FAILURE(status)) { return; } - InitialTimeZoneRule *initial = NULL; - UVector *transitionRules = NULL; + InitialTimeZoneRule *initial = nullptr; + UVector *transitionRules = nullptr; UVector customProps(uprv_deleteUObject, uhash_compareUnicodeString, status); UnicodeString tzid; @@ -1779,7 +1828,7 @@ VTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) const { // Create a RuleBasedTimeZone with the subset rule getID(tzid); RuleBasedTimeZone rbtz(tzid, initial); - if (transitionRules != NULL) { + if (transitionRules != nullptr) { while (!transitionRules->isEmpty()) { TimeZoneRule *tr = (TimeZoneRule*)transitionRules->orphanElementAt(0); rbtz.addTransitionRule(tr, status); @@ -1788,7 +1837,7 @@ VTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) const { } } delete transitionRules; - transitionRules = NULL; + transitionRules = nullptr; } rbtz.complete(status); if (U_FAILURE(status)) { @@ -1797,6 +1846,10 @@ VTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) const { if (olsonzid.length() > 0 && icutzver.length() > 0) { UnicodeString *icutzprop = new UnicodeString(ICU_TZINFO_PROP); + if (icutzprop == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + goto cleanupWritePartial; + } icutzprop->append(olsonzid); icutzprop->append((UChar)0x005B/*'['*/); icutzprop->append(icutzver); @@ -1813,10 +1866,10 @@ VTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) const { return; cleanupWritePartial: - if (initial != NULL) { + if (initial != nullptr) { delete initial; } - if (transitionRules != NULL) { + if (transitionRules != nullptr) { while (!transitionRules->isEmpty()) { TimeZoneRule *tr = (TimeZoneRule*)transitionRules->orphanElementAt(0); delete tr; @@ -1835,14 +1888,14 @@ VTimeZone::writeSimple(UDate time, VTZWriter& writer, UErrorCode& status) const UnicodeString tzid; // Extract simple rules - InitialTimeZoneRule *initial = NULL; - AnnualTimeZoneRule *std = NULL, *dst = NULL; + InitialTimeZoneRule *initial = nullptr; + AnnualTimeZoneRule *std = nullptr, *dst = nullptr; getSimpleRulesNear(time, initial, std, dst, status); if (U_SUCCESS(status)) { // Create a RuleBasedTimeZone with the subset rule getID(tzid); RuleBasedTimeZone rbtz(tzid, initial); - if (std != NULL && dst != NULL) { + if (std != nullptr && dst != nullptr) { rbtz.addTransitionRule(std, status); rbtz.addTransitionRule(dst, status); } @@ -1852,6 +1905,10 @@ VTimeZone::writeSimple(UDate time, VTZWriter& writer, UErrorCode& status) const if (olsonzid.length() > 0 && icutzver.length() > 0) { UnicodeString *icutzprop = new UnicodeString(ICU_TZINFO_PROP); + if (icutzprop == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + goto cleanupWriteSimple; + } icutzprop->append(olsonzid); icutzprop->append((UChar)0x005B/*'['*/); icutzprop->append(icutzver); @@ -1869,13 +1926,13 @@ VTimeZone::writeSimple(UDate time, VTZWriter& writer, UErrorCode& status) const return; cleanupWriteSimple: - if (initial != NULL) { + if (initial != nullptr) { delete initial; } - if (std != NULL) { + if (std != nullptr) { delete std; } - if (dst != NULL) { + if (dst != nullptr) { delete dst; } } @@ -1891,7 +1948,7 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, return; } - if (customProps != NULL) { + if (customProps != nullptr) { for (int32_t i = 0; i < customProps->size(); i++) { UnicodeString *custprop = (UnicodeString*)customProps->elementAt(i); w.write(*custprop); @@ -1912,7 +1969,7 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, UDate dstStartTime = 0.0; UDate dstUntilTime = 0.0; int32_t dstCount = 0; - AnnualTimeZoneRule *finalDstRule = NULL; + AnnualTimeZoneRule *finalDstRule = nullptr; UnicodeString stdName; int32_t stdFromOffset = 0; @@ -1926,7 +1983,7 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, UDate stdStartTime = 0.0; UDate stdUntilTime = 0.0; int32_t stdCount = 0; - AnnualTimeZoneRule *finalStdRule = NULL; + AnnualTimeZoneRule *finalStdRule = nullptr; int32_t year, month, dom, dow, doy, mid; UBool hasTransitions = FALSE; @@ -1953,8 +2010,8 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, UBool sameRule = FALSE; const AnnualTimeZoneRule *atzrule; if (isDst) { - if (finalDstRule == NULL - && (atzrule = dynamic_cast(tzt.getTo())) != NULL + if (finalDstRule == nullptr + && (atzrule = dynamic_cast(tzt.getTo())) != nullptr && atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR ) { finalDstRule = atzrule->clone(); @@ -2000,12 +2057,12 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, dstStartTime = dstUntilTime = t; dstCount = 1; } - if (finalStdRule != NULL && finalDstRule != NULL) { + if (finalStdRule != nullptr && finalDstRule != nullptr) { break; } } else { - if (finalStdRule == NULL - && (atzrule = dynamic_cast(tzt.getTo())) != NULL + if (finalStdRule == nullptr + && (atzrule = dynamic_cast(tzt.getTo())) != nullptr && atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR ) { finalStdRule = atzrule->clone(); @@ -2051,7 +2108,7 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, stdStartTime = stdUntilTime = t; stdCount = 1; } - if (finalStdRule != NULL && finalDstRule != NULL) { + if (finalStdRule != nullptr && finalDstRule != nullptr) { break; } } @@ -2075,7 +2132,7 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, } } else { if (dstCount > 0) { - if (finalDstRule == NULL) { + if (finalDstRule == nullptr) { if (dstCount == 1) { writeZonePropsByTime(w, TRUE, dstName, dstFromOffset, dstToOffset, dstStartTime, TRUE, status); @@ -2117,7 +2174,7 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, } } if (stdCount > 0) { - if (finalStdRule == NULL) { + if (finalStdRule == nullptr) { if (stdCount == 1) { writeZonePropsByTime(w, FALSE, stdName, stdFromOffset, stdToOffset, stdStartTime, TRUE, status); @@ -2163,10 +2220,10 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, cleanupWriteZone: - if (finalStdRule != NULL) { + if (finalStdRule != nullptr) { delete finalStdRule; } - if (finalDstRule != NULL) { + if (finalDstRule != nullptr) { delete finalDstRule; } } @@ -2479,8 +2536,11 @@ VTimeZone::writeFinalRule(VTZWriter& writer, UBool isDst, const AnnualTimeZoneRu return; } UBool modifiedRule = TRUE; - const DateTimeRule *dtrule = toWallTimeRule(rule->getRule(), fromRawOffset, fromDSTSavings); - if (dtrule == NULL) { + const DateTimeRule *dtrule = toWallTimeRule(rule->getRule(), fromRawOffset, fromDSTSavings, status); + if (U_FAILURE(status)) { + return; + } + if (dtrule == nullptr) { modifiedRule = FALSE; dtrule = rule->getRule(); } diff --git a/deps/icu-small/source/python/icutools/databuilder/test/sample_data/brkitr/LOCALE_DEPS.json b/deps/icu-small/source/python/icutools/databuilder/test/sample_data/brkitr/LOCALE_DEPS.json new file mode 100644 index 00000000000000..89329e87eea539 --- /dev/null +++ b/deps/icu-small/source/python/icutools/databuilder/test/sample_data/brkitr/LOCALE_DEPS.json @@ -0,0 +1,10 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +////////////////////////////////////////////////////////////// +// This is a sample LOCALE_DEPS.json file for testing only. // +////////////////////////////////////////////////////////////// + +{ + "cldrVersion": "36.1" +} diff --git a/deps/icu-small/source/python/icutools/databuilder/test/sample_data/locales/LOCALE_DEPS.json b/deps/icu-small/source/python/icutools/databuilder/test/sample_data/locales/LOCALE_DEPS.json new file mode 100644 index 00000000000000..fd28a741ef67c2 --- /dev/null +++ b/deps/icu-small/source/python/icutools/databuilder/test/sample_data/locales/LOCALE_DEPS.json @@ -0,0 +1,197 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +////////////////////////////////////////////////////////////// +// This is a sample LOCALE_DEPS.json file for testing only. // +////////////////////////////////////////////////////////////// + +{ + "cldrVersion": "36.1", + "aliases": { + "ars": "ar_SA", + "az_AZ": "az_Latn_AZ", + "bs_BA": "bs_Latn_BA", + "en_NH": "en_VU", + "en_RH": "en_ZW", + "ff_CM": "ff_Latn_CM", + "ff_GN": "ff_Latn_GN", + "ff_MR": "ff_Latn_MR", + "ff_SN": "ff_Latn_SN", + "in": "id", + "in_ID": "id_ID", + "iw": "he", + "iw_IL": "he_IL", + "mo": "ro", + "no": "nb", + "no_NO": "nb_NO", + "no_NO_NY": "nn_NO", + "pa_IN": "pa_Guru_IN", + "pa_PK": "pa_Arab_PK", + "sh": "sr_Latn", + "sh_BA": "sr_Latn_BA", + "sh_CS": "sr_Latn_RS", + "sh_YU": "sr_Latn_RS", + "shi_MA": "shi_Tfng_MA", + "sr_BA": "sr_Cyrl_BA", + "sr_CS": "sr_Cyrl_RS", + "sr_Cyrl_CS": "sr_Cyrl_RS", + "sr_Cyrl_YU": "sr_Cyrl_RS", + "sr_Latn_CS": "sr_Latn_RS", + "sr_Latn_YU": "sr_Latn_RS", + "sr_ME": "sr_Latn_ME", + "sr_RS": "sr_Cyrl_RS", + "sr_XK": "sr_Cyrl_XK", + "sr_YU": "sr_Cyrl_RS", + "tl": "fil", + "tl_PH": "fil_PH", + "uz_AF": "uz_Arab_AF", + "uz_UZ": "uz_Latn_UZ", + "vai_LR": "vai_Vaii_LR", + "yue_CN": "yue_Hans_CN", + "yue_HK": "yue_Hant_HK", + "zh_CN": "zh_Hans_CN", + "zh_HK": "zh_Hant_HK", + "zh_MO": "zh_Hant_MO", + "zh_SG": "zh_Hans_SG", + "zh_TW": "zh_Hant_TW" + }, + "parents": { + "az_Cyrl": "root", + "bs_Cyrl": "root", + "en_150": "en_001", + "en_AG": "en_001", + "en_AI": "en_001", + "en_AT": "en_150", + "en_AU": "en_001", + "en_BB": "en_001", + "en_BE": "en_150", + "en_BM": "en_001", + "en_BS": "en_001", + "en_BW": "en_001", + "en_BZ": "en_001", + "en_CA": "en_001", + "en_CC": "en_001", + "en_CH": "en_150", + "en_CK": "en_001", + "en_CM": "en_001", + "en_CX": "en_001", + "en_CY": "en_001", + "en_DE": "en_150", + "en_DG": "en_001", + "en_DK": "en_150", + "en_DM": "en_001", + "en_ER": "en_001", + "en_FI": "en_150", + "en_FJ": "en_001", + "en_FK": "en_001", + "en_FM": "en_001", + "en_GB": "en_001", + "en_GD": "en_001", + "en_GG": "en_001", + "en_GH": "en_001", + "en_GI": "en_001", + "en_GM": "en_001", + "en_GY": "en_001", + "en_HK": "en_001", + "en_IE": "en_001", + "en_IL": "en_001", + "en_IM": "en_001", + "en_IN": "en_001", + "en_IO": "en_001", + "en_JE": "en_001", + "en_JM": "en_001", + "en_KE": "en_001", + "en_KI": "en_001", + "en_KN": "en_001", + "en_KY": "en_001", + "en_LC": "en_001", + "en_LR": "en_001", + "en_LS": "en_001", + "en_MG": "en_001", + "en_MO": "en_001", + "en_MS": "en_001", + "en_MT": "en_001", + "en_MU": "en_001", + "en_MW": "en_001", + "en_MY": "en_001", + "en_NA": "en_001", + "en_NF": "en_001", + "en_NG": "en_001", + "en_NL": "en_150", + "en_NR": "en_001", + "en_NU": "en_001", + "en_NZ": "en_001", + "en_PG": "en_001", + "en_PH": "en_001", + "en_PK": "en_001", + "en_PN": "en_001", + "en_PW": "en_001", + "en_RW": "en_001", + "en_SB": "en_001", + "en_SC": "en_001", + "en_SD": "en_001", + "en_SE": "en_150", + "en_SG": "en_001", + "en_SH": "en_001", + "en_SI": "en_150", + "en_SL": "en_001", + "en_SS": "en_001", + "en_SX": "en_001", + "en_SZ": "en_001", + "en_TC": "en_001", + "en_TK": "en_001", + "en_TO": "en_001", + "en_TT": "en_001", + "en_TV": "en_001", + "en_TZ": "en_001", + "en_UG": "en_001", + "en_VC": "en_001", + "en_VG": "en_001", + "en_VU": "en_001", + "en_WS": "en_001", + "en_ZA": "en_001", + "en_ZM": "en_001", + "en_ZW": "en_001", + "es_AR": "es_419", + "es_BO": "es_419", + "es_BR": "es_419", + "es_BZ": "es_419", + "es_CL": "es_419", + "es_CO": "es_419", + "es_CR": "es_419", + "es_CU": "es_419", + "es_DO": "es_419", + "es_EC": "es_419", + "es_GT": "es_419", + "es_HN": "es_419", + "es_MX": "es_419", + "es_NI": "es_419", + "es_PA": "es_419", + "es_PE": "es_419", + "es_PR": "es_419", + "es_PY": "es_419", + "es_SV": "es_419", + "es_US": "es_419", + "es_UY": "es_419", + "es_VE": "es_419", + "pa_Arab": "root", + "pt_AO": "pt_PT", + "pt_CH": "pt_PT", + "pt_CV": "pt_PT", + "pt_GQ": "pt_PT", + "pt_GW": "pt_PT", + "pt_LU": "pt_PT", + "pt_MO": "pt_PT", + "pt_MZ": "pt_PT", + "pt_ST": "pt_PT", + "pt_TL": "pt_PT", + "shi_Latn": "root", + "sr_Latn": "root", + "uz_Arab": "root", + "uz_Cyrl": "root", + "vai_Latn": "root", + "yue_Hans": "root", + "zh_Hant": "root", + "zh_Hant_MO": "zh_Hant_HK" + } +} diff --git a/deps/icu-small/source/python/icutools/databuilder/test/sample_data/rbnf/LOCALE_DEPS.json b/deps/icu-small/source/python/icutools/databuilder/test/sample_data/rbnf/LOCALE_DEPS.json new file mode 100644 index 00000000000000..f079619a3685ba --- /dev/null +++ b/deps/icu-small/source/python/icutools/databuilder/test/sample_data/rbnf/LOCALE_DEPS.json @@ -0,0 +1,36 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +////////////////////////////////////////////////////////////// +// This is a sample LOCALE_DEPS.json file for testing only. // +////////////////////////////////////////////////////////////// + +{ + "cldrVersion": "36.1", + "aliases": { + "ars": "ar_SA", + "in": "id", + "iw": "he", + "no": "nb", + "sh": "sr_Latn", + "zh_HK": "zh_Hant_HK", + "zh_Hant_HK": "yue", + "zh_MO": "zh_Hant_MO", + "zh_TW": "zh_Hant_TW" + }, + "parents": { + "en_IN": "en_001", + "es_DO": "es_419", + "es_GT": "es_419", + "es_HN": "es_419", + "es_MX": "es_419", + "es_NI": "es_419", + "es_PA": "es_419", + "es_PR": "es_419", + "es_SV": "es_419", + "es_US": "es_419", + "sr_Latn": "root", + "yue_Hans": "root", + "zh_Hant": "root" + } +} diff --git a/deps/icu-small/source/tools/genccode/genccode.c b/deps/icu-small/source/tools/genccode/genccode.c index 91e94d7f5181c4..c5bbdf60d7d910 100644 --- a/deps/icu-small/source/tools/genccode/genccode.c +++ b/deps/icu-small/source/tools/genccode/genccode.c @@ -69,6 +69,7 @@ enum { #ifdef CAN_GENERATE_OBJECTS kOptObject, kOptMatchArch, + kOptSkipDllExport, #endif kOptFilename, kOptAssembly @@ -82,8 +83,9 @@ static UOption options[]={ UOPTION_DEF("name", 'n', UOPT_REQUIRES_ARG), UOPTION_DEF("entrypoint", 'e', UOPT_REQUIRES_ARG), #ifdef CAN_GENERATE_OBJECTS -/*5*/UOPTION_DEF("object", 'o', UOPT_NO_ARG), +/*6*/UOPTION_DEF("object", 'o', UOPT_NO_ARG), UOPTION_DEF("match-arch", 'm', UOPT_REQUIRES_ARG), + UOPTION_DEF("skip-dll-export", '\0', UOPT_NO_ARG), #endif UOPTION_DEF("filename", 'f', UOPT_REQUIRES_ARG), UOPTION_DEF("assembly", 'a', UOPT_REQUIRES_ARG) @@ -127,7 +129,8 @@ main(int argc, char* argv[]) { fprintf(stderr, "\t-o or --object write a .obj file instead of .c\n" "\t-m or --match-arch file.o match the architecture (CPU, 32/64 bits) of the specified .o\n" - "\t ELF format defaults to i386. Windows defaults to the native platform.\n"); + "\t ELF format defaults to i386. Windows defaults to the native platform.\n" + "\t--skip-dll-export Don't export the ICU data entry point symbol (for use when statically linking)\n"); #endif fprintf(stderr, "\t-f or --filename Specify an alternate base filename. (default: symbolname_typ)\n" @@ -193,7 +196,8 @@ main(int argc, char* argv[]) { options[kOptMatchArch].doesOccur ? options[kOptMatchArch].value : NULL, options[kOptFilename].doesOccur ? options[kOptFilename].value : NULL, NULL, - 0); + 0, + !options[kOptSkipDllExport].doesOccur); break; #endif default: diff --git a/deps/icu-small/source/tools/pkgdata/pkgdata.cpp b/deps/icu-small/source/tools/pkgdata/pkgdata.cpp index ad067c361f9f59..41a13406cf1f31 100644 --- a/deps/icu-small/source/tools/pkgdata/pkgdata.cpp +++ b/deps/icu-small/source/tools/pkgdata/pkgdata.cpp @@ -46,6 +46,7 @@ #include "flagparser.h" #include "filetools.h" #include "charstr.h" +#include "uassert.h" #if U_HAVE_POPEN # include @@ -66,6 +67,8 @@ U_DEFINE_LOCAL_OPEN_POINTER(LocalPipeFilePointer, FILE, pclose); #endif +using icu::LocalMemory; + static void loadLists(UPKGOptions *o, UErrorCode *status); static int32_t pkg_executeOptions(UPKGOptions *o); @@ -93,7 +96,7 @@ static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UB static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, const UBool reverseExt, UBool noVersion); static int32_t initializePkgDataFlags(UPKGOptions *o); -static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option); +static int32_t pkg_getPkgDataPath(UBool verbose, UOption *option); static int runCommand(const char* command, UBool specialHandling=FALSE); #define IN_COMMON_MODE(mode) (mode == 'a' || mode == 'c') @@ -307,7 +310,7 @@ main(int argc, char* argv[]) { #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) if(!options[BLDOPT].doesOccur && uprv_strcmp(options[MODE].value, "common") != 0) { - if (pkg_getOptionsFromICUConfig(options[VERBOSE].doesOccur, &options[BLDOPT]) != 0) { + if (pkg_getPkgDataPath(options[VERBOSE].doesOccur, &options[BLDOPT]) != 0) { fprintf(stderr, " required parameter is missing: -O is required for static and shared builds.\n"); fprintf(stderr, "Run '%s --help' for help.\n", progname); return 1; @@ -773,7 +776,8 @@ static int32_t pkg_executeOptions(UPKGOptions *o) { (optMatchArch[0] == 0 ? NULL : optMatchArch), NULL, gencFilePath, - sizeof(gencFilePath)); + sizeof(gencFilePath), + TRUE); pkg_destroyOptMatchArch(optMatchArch); #if U_PLATFORM_IS_LINUX_BASED result = pkg_generateLibraryFile(targetDir, mode, gencFilePath); @@ -1129,12 +1133,15 @@ static int32_t pkg_installLibrary(const char *installDir, const char *targetDir, int32_t result = 0; char cmd[SMALL_BUFFER_MAX_SIZE]; - sprintf(cmd, "cd %s && %s %s %s%s%s", + auto ret = snprintf(cmd, + SMALL_BUFFER_MAX_SIZE, + "cd %s && %s %s %s%s%s", targetDir, pkgDataFlags[INSTALL_CMD], libFileNames[LIB_FILE_VERSION], - installDir, PKGDATA_FILE_SEP_STRING, libFileNames[LIB_FILE_VERSION] - ); + installDir, PKGDATA_FILE_SEP_STRING, libFileNames[LIB_FILE_VERSION]); + (void)ret; + U_ASSERT(0 <= ret && ret < SMALL_BUFFER_MAX_SIZE); result = runCommand(cmd); @@ -1252,10 +1259,14 @@ static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, c buffer[bufferLength-1] = 0; } - sprintf(cmd, "%s %s%s%s %s%s%s", + auto ret = snprintf(cmd, + SMALL_BUFFER_MAX_SIZE, + "%s %s%s%s %s%s%s", pkgDataFlags[INSTALL_CMD], srcDir, PKGDATA_FILE_SEP_STRING, buffer, installDir, PKGDATA_FILE_SEP_STRING, buffer); + (void)ret; + U_ASSERT(0 <= ret && ret < SMALL_BUFFER_MAX_SIZE); result = runCommand(cmd); if (result != 0) { @@ -1527,9 +1538,7 @@ static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, c static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath) { char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = ""; - char *cmd; int32_t result = 0; - int32_t length = 0; /* Remove the ending .s and replace it with .o for the new object file. */ @@ -1539,22 +1548,22 @@ static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode length = static_cast(uprv_strlen(pkgDataFlags[COMPILER]) + uprv_strlen(pkgDataFlags[LIBFLAGS]) + uprv_strlen(tempObjectFile) + uprv_strlen(gencFilePath) + BUFFER_PADDING_SIZE); - cmd = (char *)uprv_malloc(sizeof(char) * length); - if (cmd == NULL) { + LocalMemory cmd((char *)uprv_malloc(sizeof(char) * length)); + if (cmd.isNull()) { return -1; } /* Generate the object file. */ - sprintf(cmd, "%s %s -o %s %s", + sprintf(cmd.getAlias(), "%s %s -o %s %s", pkgDataFlags[COMPILER], pkgDataFlags[LIBFLAGS], tempObjectFile, gencFilePath); - result = runCommand(cmd); - uprv_free(cmd); + result = runCommand(cmd.getAlias()); + if (result != 0) { - fprintf(stderr, "Error creating with assembly code. Failed command: %s\n", cmd); + fprintf(stderr, "Error creating with assembly code. Failed command: %s\n", cmd.getAlias()); return result; } @@ -1689,12 +1698,20 @@ static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetD break; } } - sprintf(newName, "%s_%s", + auto ret = snprintf(newName, + SMALL_BUFFER_MAX_SIZE, + "%s_%s", DATA_PREFIX[n], newNameTmp); - sprintf(dataName, "%s_%s", + (void)ret; + U_ASSERT(0 <= ret && ret < SMALL_BUFFER_MAX_SIZE); + ret = snprintf(dataName, + SMALL_BUFFER_MAX_SIZE, + "%s_%s", o->shortName, DATA_PREFIX[n]); + (void)ret; + U_ASSERT(0 <= ret && ret < SMALL_BUFFER_MAX_SIZE); } if (newName[0] != 0) { break; @@ -2158,41 +2175,46 @@ static void loadLists(UPKGOptions *o, UErrorCode *status) } /* for each file list file */ } -/* Try calling icu-config directly to get the option file. */ - static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option) { +/* Helper for pkg_getPkgDataPath() */ #if U_HAVE_POPEN - LocalPipeFilePointer p; - size_t n; - static char buf[512] = ""; +static UBool getPkgDataPath(const char *cmd, UBool verbose, char *buf, size_t items) { icu::CharString cmdBuf; UErrorCode status = U_ZERO_ERROR; - const char cmd[] = "icu-config --incpkgdatafile"; - char dirBuf[1024] = ""; - /* #1 try the same path where pkgdata was called from. */ - findDirname(progname, dirBuf, UPRV_LENGTHOF(dirBuf), &status); - if(U_SUCCESS(status)) { - cmdBuf.append(dirBuf, status); - if (cmdBuf[0] != 0) { - cmdBuf.append( U_FILE_SEP_STRING, status ); - } - cmdBuf.append( cmd, status ); - - if(verbose) { - fprintf(stdout, "# Calling icu-config: %s\n", cmdBuf.data()); - } - p.adoptInstead(popen(cmdBuf.data(), "r")); - } - - if(p.isNull() || (n = fread(buf, 1, UPRV_LENGTHOF(buf)-1, p.getAlias())) <= 0) { - if(verbose) { - fprintf(stdout, "# Calling icu-config: %s\n", cmd); - } + LocalPipeFilePointer p; + size_t n; - p.adoptInstead(popen(cmd, "r")); - if(p.isNull() || (n = fread(buf, 1, UPRV_LENGTHOF(buf)-1, p.getAlias())) <= 0) { - fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname); + cmdBuf.append(cmd, status); + if (verbose) { + fprintf(stdout, "# Calling: %s\n", cmdBuf.data()); + } + p.adoptInstead( popen(cmdBuf.data(), "r") ); + + if (p.isNull() || (n = fread(buf, 1, items-1, p.getAlias())) <= 0) { + fprintf(stderr, "%s: Error calling '%s'\n", progname, cmd); + *buf = 0; + return FALSE; + } + + return TRUE; +} +#endif + +/* Get path to pkgdata.inc. Try pkg-config first, falling back to icu-config. */ +static int32_t pkg_getPkgDataPath(UBool verbose, UOption *option) { +#if U_HAVE_POPEN + static char buf[512] = ""; + UBool pkgconfigIsValid = TRUE; + const char *pkgconfigCmd = "pkg-config --variable=pkglibdir icu-uc"; + const char *icuconfigCmd = "icu-config --incpkgdatafile"; + const char *pkgdata = "pkgdata.inc"; + + if (!getPkgDataPath(pkgconfigCmd, verbose, buf, UPRV_LENGTHOF(buf))) { + if (!getPkgDataPath(icuconfigCmd, verbose, buf, UPRV_LENGTHOF(buf))) { + fprintf(stderr, "%s: icu-config not found. Fix PATH or specify -O option\n", progname); return -1; } + + pkgconfigIsValid = FALSE; } for (int32_t length = strlen(buf) - 1; length >= 0; length--) { @@ -2203,21 +2225,18 @@ static void loadLists(UPKGOptions *o, UErrorCode *status) } } - if(buf[strlen(buf)-1]=='\n') - { - buf[strlen(buf)-1]=0; - } - - if(buf[0] == 0) - { - fprintf(stderr, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname); + if (!*buf) { + fprintf(stderr, "%s: Unable to locate pkgdata.inc. Unable to parse the results of '%s'. Check paths or use the -O option to specify the path to pkgdata.inc.\n", progname, pkgconfigIsValid ? pkgconfigCmd : icuconfigCmd); return -1; } - if(verbose) { - fprintf(stdout, "# icu-config said: %s\n", buf); + if (pkgconfigIsValid) { + uprv_strcat(buf, U_FILE_SEP_STRING); + uprv_strcat(buf, pkgdata); } + buf[strlen(buf)] = 0; + option->value = buf; option->doesOccur = TRUE; diff --git a/deps/icu-small/source/tools/toolutil/pkg_genc.cpp b/deps/icu-small/source/tools/toolutil/pkg_genc.cpp index 1a63eb0fa10225..31db2e2184b3be 100644 --- a/deps/icu-small/source/tools/toolutil/pkg_genc.cpp +++ b/deps/icu-small/source/tools/toolutil/pkg_genc.cpp @@ -131,6 +131,9 @@ static const struct AssemblyType { {"gcc", ".globl %s\n" "\t.section .note.GNU-stack,\"\",%%progbits\n" + "#ifdef __CET__\n" + "# include \n" + "#endif\n" "\t.section .rodata\n" "\t.balign 16\n" "#ifdef U_HIDE_DATA_SYMBOL\n" @@ -418,9 +421,9 @@ writeCCode( filename, destdir, buffer, - sizeof(buffer), + static_cast(sizeof(buffer)), entry + uprv_strlen(entry), - sizeof(entry) - uprv_strlen(entry), + static_cast(sizeof(entry) - uprv_strlen(entry)), ".c", optFilename); @@ -679,7 +682,7 @@ getOutFilename( outFilenameBuilder.append(destdir, status); outFilenameBuilder.ensureEndsWithFileSeparator(status); } else { - outFilenameBuilder.append(inFilename, basename - inFilename, status); + outFilenameBuilder.append(inFilename, static_cast(basename - inFilename), status); } inFilename=basename; @@ -878,7 +881,8 @@ writeObjectCode( const char *optMatchArch, const char *optFilename, char *outFilePath, - size_t outFilePathCapacity) { + size_t outFilePathCapacity, + UBool optWinDllExport) { /* common variables */ char buffer[4096], entry[96]={ 0 }; FileStream *in, *out; @@ -888,6 +892,8 @@ writeObjectCode( uint16_t cpu, bits; UBool makeBigEndian; + (void)optWinDllExport; /* unused except Windows */ + /* platform-specific variables and initialization code */ #ifdef U_ELF /* 32-bit Elf file header */ @@ -1254,12 +1260,17 @@ writeObjectCode( uprv_memset(&symbolNames, 0, sizeof(symbolNames)); /* write the linker export directive */ - uprv_strcpy(objHeader.linkerOptions, "-export:"); - length=8; - uprv_strcpy(objHeader.linkerOptions+length, entry); - length+=entryLength; - uprv_strcpy(objHeader.linkerOptions+length, ",data "); - length+=6; + if (optWinDllExport) { + uprv_strcpy(objHeader.linkerOptions, "-export:"); + length=8; + uprv_strcpy(objHeader.linkerOptions+length, entry); + length+=entryLength; + uprv_strcpy(objHeader.linkerOptions+length, ",data "); + length+=6; + } + else { + length=0; + } /* set the file header */ objHeader.fileHeader.Machine=cpu; diff --git a/deps/icu-small/source/tools/toolutil/pkg_genc.h b/deps/icu-small/source/tools/toolutil/pkg_genc.h index 47e8304a6890c5..b231aa6170c287 100644 --- a/deps/icu-small/source/tools/toolutil/pkg_genc.h +++ b/deps/icu-small/source/tools/toolutil/pkg_genc.h @@ -100,6 +100,7 @@ writeObjectCode( const char *optMatchArch, const char *optFilename, char *outFilePath, - size_t outFilePathCapacity); + size_t outFilePathCapacity, + UBool optWinDllExport); #endif diff --git a/deps/icu-small/source/tools/toolutil/toolutil.cpp b/deps/icu-small/source/tools/toolutil/toolutil.cpp index 25f9c116ee18d4..f0d6be5cf5ee2a 100644 --- a/deps/icu-small/source/tools/toolutil/toolutil.cpp +++ b/deps/icu-small/source/tools/toolutil/toolutil.cpp @@ -60,6 +60,8 @@ #include +#include + #include "unicode/errorcode.h" #include "unicode/putil.h" #include "cmemory.h" @@ -243,7 +245,7 @@ struct UToolMemory { char name[64]; int32_t capacity, maxCapacity, size, idx; void *array; - alignas(max_align_t) char staticArray[1]; + alignas(std::max_align_t) char staticArray[1]; }; U_CAPI UToolMemory * U_EXPORT2 diff --git a/deps/uv/.gitignore b/deps/uv/.gitignore index b6abc2ab464978..83370a7bb0efcd 100644 --- a/deps/uv/.gitignore +++ b/deps/uv/.gitignore @@ -37,11 +37,6 @@ vgcore.* Makefile Makefile.in -# Generated by gyp for android -*.target.mk -/android-toolchain - -/out/ /build/ /test/.libs/ diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap index 87d63bed0b14d3..2ae2968c83208d 100644 --- a/deps/uv/.mailmap +++ b/deps/uv/.mailmap @@ -17,6 +17,7 @@ Imran Iqbal Isaac Z. Schlueter Jason Williams Jesse Gorzinski +Jesse Gorzinski Justin Venus Keno Fischer Keno Fischer diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index f829778a21c1a5..410d9461ad11d5 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -413,3 +413,15 @@ Carl Lei Stefan Bender nia virtualyw +Witold Kręcicki +Dominique Dumont +Manuel BACHMANN +Marek Vavrusa +TK-one +Irek Fakhrutdinov +Lin Zhang +毛毛 +Sk Sajidul Kadir +twosee +Rikard Falkeborn +Yash Ladha diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt index 2ab6d17edddd72..c82fa2b56d8771 100644 --- a/deps/uv/CMakeLists.txt +++ b/deps/uv/CMakeLists.txt @@ -1,23 +1,55 @@ -# TODO: determine CMAKE_SYSTEM_NAME on OS/390. Currently assumes "OS/390". cmake_minimum_required(VERSION 3.4) project(libuv LANGUAGES C) +cmake_policy(SET CMP0057 NEW) # Enable IN_LIST operator +cmake_policy(SET CMP0064 NEW) # Support if (TEST) operator + +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") + include(CMakePackageConfigHelpers) include(CMakeDependentOption) +include(CheckCCompilerFlag) include(GNUInstallDirs) include(CTest) +set(CMAKE_C_VISIBILITY_PRESET hidden) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) +set(CMAKE_C_STANDARD 90) + cmake_dependent_option(LIBUV_BUILD_TESTS "Build the unit tests when BUILD_TESTING is enabled and we are the root project" ON "BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF) +cmake_dependent_option(LIBUV_BUILD_BENCH + "Build the benchmarks when building unit tests and we are the root project" ON + "LIBUV_BUILD_TESTS" OFF) -if(MSVC) - list(APPEND uv_cflags /W4) -elseif(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU") - list(APPEND uv_cflags -fvisibility=hidden --std=gnu89) - list(APPEND uv_cflags -Wall -Wextra -Wstrict-prototypes) - list(APPEND uv_cflags -Wno-unused-parameter) -endif() +# Compiler check +string(CONCAT is-msvc $, + $ +>) + +check_c_compiler_flag(/W4 UV_LINT_W4) +check_c_compiler_flag(-Wall UV_LINT_WALL) # DO NOT use this under MSVC + +# TODO: Place these into its own function +check_c_compiler_flag(-Wno-unused-parameter UV_LINT_NO_UNUSED_PARAMETER) +check_c_compiler_flag(-Wstrict-prototypes UV_LINT_STRICT_PROTOTYPES) +check_c_compiler_flag(-Wextra UV_LINT_EXTRA) + +set(lint-no-unused-parameter $<$:-Wno-unused-parameter>) +set(lint-strict-prototypes $<$:-Wstrict-prototypes>) +set(lint-extra $<$:-Wextra>) +set(lint-w4 $<$:/W4>) +# Unfortunately, this one is complicated because MSVC and clang-cl support -Wall +# but using it is like calling -Weverything +string(CONCAT lint-default $< + $,$>:-Wall +>) + +list(APPEND uv_cflags ${lint-strict-prototypes} ${lint-extra} ${lint-default} ${lint-w4}) +list(APPEND uv_cflags ${lint-no-unused-parameter}) set(uv_sources src/fs-poll.c @@ -31,172 +63,24 @@ set(uv_sources src/uv-data-getter-setters.c src/version.c) -set(uv_test_sources - test/blackhole-server.c - test/echo-server.c - test/run-tests.c - test/runner.c - test/test-active.c - test/test-async-null-cb.c - test/test-async.c - test/test-barrier.c - test/test-callback-order.c - test/test-callback-stack.c - test/test-close-fd.c - test/test-close-order.c - test/test-condvar.c - test/test-connect-unspecified.c - test/test-connection-fail.c - test/test-cwd-and-chdir.c - test/test-default-loop-close.c - test/test-delayed-accept.c - test/test-dlerror.c - test/test-eintr-handling.c - test/test-embed.c - test/test-emfile.c - test/test-env-vars.c - test/test-error.c - test/test-fail-always.c - test/test-fork.c - test/test-fs-copyfile.c - test/test-fs-event.c - test/test-fs-poll.c - test/test-fs.c - test/test-fs-readdir.c - test/test-fs-fd-hash.c - test/test-fs-open-flags.c - test/test-get-currentexe.c - test/test-get-loadavg.c - test/test-get-memory.c - test/test-get-passwd.c - test/test-getaddrinfo.c - test/test-gethostname.c - test/test-getnameinfo.c - test/test-getsockname.c - test/test-getters-setters.c - test/test-gettimeofday.c - test/test-handle-fileno.c - test/test-homedir.c - test/test-hrtime.c - test/test-idle.c - test/test-idna.c - test/test-ip4-addr.c - test/test-ip6-addr.c - test/test-ipc-heavy-traffic-deadlock-bug.c - test/test-ipc-send-recv.c - test/test-ipc.c - test/test-loop-alive.c - test/test-loop-close.c - test/test-loop-configure.c - test/test-loop-handles.c - test/test-loop-stop.c - test/test-loop-time.c - test/test-multiple-listen.c - test/test-mutexes.c - test/test-osx-select.c - test/test-pass-always.c - test/test-ping-pong.c - test/test-pipe-bind-error.c - test/test-pipe-close-stdout-read-stdin.c - test/test-pipe-connect-error.c - test/test-pipe-connect-multiple.c - test/test-pipe-connect-prepare.c - test/test-pipe-getsockname.c - test/test-pipe-pending-instances.c - test/test-pipe-sendmsg.c - test/test-pipe-server-close.c - test/test-pipe-set-fchmod.c - test/test-pipe-set-non-blocking.c - test/test-platform-output.c - test/test-poll-close-doesnt-corrupt-stack.c - test/test-poll-close.c - test/test-poll-closesocket.c - test/test-poll-oob.c - test/test-poll.c - test/test-process-priority.c - test/test-process-title-threadsafe.c - test/test-process-title.c - test/test-queue-foreach-delete.c - test/test-random.c - test/test-ref.c - test/test-run-nowait.c - test/test-run-once.c - test/test-semaphore.c - test/test-shutdown-close.c - test/test-shutdown-eof.c - test/test-shutdown-twice.c - test/test-signal-multiple-loops.c - test/test-signal-pending-on-close.c - test/test-signal.c - test/test-socket-buffer-size.c - test/test-spawn.c - test/test-stdio-over-pipes.c - test/test-strscpy.c - test/test-tcp-alloc-cb-fail.c - test/test-tcp-bind-error.c - test/test-tcp-bind6-error.c - test/test-tcp-close-accept.c - test/test-tcp-close-while-connecting.c - test/test-tcp-close.c - test/test-tcp-close-reset.c - test/test-tcp-connect-error-after-write.c - test/test-tcp-connect-error.c - test/test-tcp-connect-timeout.c - test/test-tcp-connect6-error.c - test/test-tcp-create-socket-early.c - test/test-tcp-flags.c - test/test-tcp-oob.c - test/test-tcp-open.c - test/test-tcp-read-stop.c - test/test-tcp-shutdown-after-write.c - test/test-tcp-try-write.c - test/test-tcp-try-write-error.c - test/test-tcp-unexpected-read.c - test/test-tcp-write-after-connect.c - test/test-tcp-write-fail.c - test/test-tcp-write-queue-order.c - test/test-tcp-write-to-half-open-connection.c - test/test-tcp-writealot.c - test/test-thread-equal.c - test/test-thread.c - test/test-threadpool-cancel.c - test/test-threadpool.c - test/test-timer-again.c - test/test-timer-from-check.c - test/test-timer.c - test/test-tmpdir.c - test/test-tty-duplicate-key.c - test/test-tty.c - test/test-udp-alloc-cb-fail.c - test/test-udp-bind.c - test/test-udp-connect.c - test/test-udp-create-socket-early.c - test/test-udp-dgram-too-big.c - test/test-udp-ipv6.c - test/test-udp-multicast-interface.c - test/test-udp-multicast-interface6.c - test/test-udp-multicast-join.c - test/test-udp-multicast-join6.c - test/test-udp-multicast-ttl.c - test/test-udp-open.c - test/test-udp-options.c - test/test-udp-send-and-recv.c - test/test-udp-send-hang-loop.c - test/test-udp-send-immediate.c - test/test-udp-send-unreachable.c - test/test-udp-try-send.c - test/test-uname.c - test/test-walk-handles.c - test/test-watcher-cross-stop.c) - if(WIN32) - list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0600) + if (CMAKE_SYSTEM_VERSION VERSION_GREATER 10) # Windows 10 + set(windows-version 0x0A00) + elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.3) # Windows 8.1 + set(windows-version 0x0603) + elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.2) # Windows 8 + set(windows-version 0x0602) + elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.1) # Windows 7 + set(windows-version 0x0601) + elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.0) # Windows Vista + set(windows-version 0x0600) + else() + message(FATAL_ERROR "Windows Vista is the minimum version supported") + endif() + list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=${windows-version}) list(APPEND uv_libraries - advapi32 + $<$:psapi> iphlpapi - psapi - shell32 - user32 userenv ws2_32) list(APPEND uv_sources @@ -229,7 +113,8 @@ if(WIN32) list(APPEND uv_test_sources src/win/snprintf.c test/runner-win.c) else() list(APPEND uv_defines _FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE) - if(NOT CMAKE_SYSTEM_NAME STREQUAL "Android") + if(NOT CMAKE_SYSTEM_NAME MATCHES "Android|OS390") + # TODO: This should be replaced with find_package(Threads) if possible # Android has pthread as part of its c library, not as a separate # libpthread.so. list(APPEND uv_libraries pthread) @@ -261,9 +146,12 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX") _ALL_SOURCE _LINUX_SOURCE_COMPAT _THREAD_SAFE - _XOPEN_SOURCE=500) + _XOPEN_SOURCE=500 + HAVE_SYS_AHAFS_EVPRODS_H) list(APPEND uv_libraries perfstat) - list(APPEND uv_sources src/unix/aix.c) + list(APPEND uv_sources + src/unix/aix.c + src/unix/aix-common.c) endif() if(CMAKE_SYSTEM_NAME STREQUAL "Android") @@ -275,12 +163,13 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Android") src/unix/linux-syscalls.c src/unix/procfs-exepath.c src/unix/pthread-fixes.c + src/unix/random-getentropy.c src/unix/random-getrandom.c src/unix/random-sysctl-linux.c src/unix/sysinfo-loadavg.c) endif() -if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux|OS/390") +if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux|OS390") list(APPEND uv_sources src/unix/proctitle.c) endif() @@ -334,10 +223,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") list(APPEND uv_sources src/unix/openbsd.c) endif() -if(CMAKE_SYSTEM_NAME STREQUAL "OS/390") +if(CMAKE_SYSTEM_NAME STREQUAL "OS390") list(APPEND uv_defines PATH_MAX=255) list(APPEND uv_defines _AE_BIMODAL) list(APPEND uv_defines _ALL_SOURCE) + list(APPEND uv_defines _ISOC99_SOURCE) list(APPEND uv_defines _LARGE_TIME_API) list(APPEND uv_defines _OPEN_MSGQ_EXT) list(APPEND uv_defines _OPEN_SYS_FILE_EXT) @@ -350,9 +240,25 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS/390") list(APPEND uv_defines _XOPEN_SOURCE_EXTENDED) list(APPEND uv_sources src/unix/pthread-fixes.c - src/unix/pthread-barrier.c src/unix/os390.c src/unix/os390-syscalls.c) + list(APPEND uv_cflags -Wc,DLL -Wc,exportall -Wc,xplink) + list(APPEND uv_libraries -Wl,xplink) + list(APPEND uv_test_libraries -Wl,xplink) +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "OS400") + list(APPEND uv_defines + _ALL_SOURCE + _LINUX_SOURCE_COMPAT + _THREAD_SAFE + _XOPEN_SOURCE=500) + list(APPEND uv_sources + src/unix/aix-common.c + src/unix/ibmi.c + src/unix/no-fsevents.c + src/unix/no-proctitle.c + src/unix/posix-poll.c) endif() if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") @@ -367,19 +273,222 @@ endif() add_library(uv SHARED ${uv_sources}) target_compile_definitions(uv - INTERFACE USING_UV_SHARED=1 - PRIVATE ${uv_defines} BUILDING_UV_SHARED=1) + INTERFACE + USING_UV_SHARED=1 + PRIVATE + BUILDING_UV_SHARED=1 + ${uv_defines}) target_compile_options(uv PRIVATE ${uv_cflags}) -target_include_directories(uv PUBLIC include PRIVATE src) +target_include_directories(uv + PUBLIC + $ + $ + PRIVATE + $) target_link_libraries(uv ${uv_libraries}) add_library(uv_a STATIC ${uv_sources}) target_compile_definitions(uv_a PRIVATE ${uv_defines}) target_compile_options(uv_a PRIVATE ${uv_cflags}) -target_include_directories(uv_a PUBLIC include PRIVATE src) +target_include_directories(uv_a + PUBLIC + $ + $ + PRIVATE + $) target_link_libraries(uv_a ${uv_libraries}) if(LIBUV_BUILD_TESTS) + # Small hack: use ${uv_test_sources} now to get the runner skeleton, + # before the actual tests are added. + add_executable( + uv_run_benchmarks_a + ${uv_test_sources} + test/benchmark-async-pummel.c + test/benchmark-async.c + test/benchmark-fs-stat.c + test/benchmark-getaddrinfo.c + test/benchmark-loop-count.c + test/benchmark-million-async.c + test/benchmark-million-timers.c + test/benchmark-multi-accept.c + test/benchmark-ping-pongs.c + test/benchmark-ping-udp.c + test/benchmark-pound.c + test/benchmark-pump.c + test/benchmark-sizes.c + test/benchmark-spawn.c + test/benchmark-tcp-write-batch.c + test/benchmark-thread.c + test/benchmark-udp-pummel.c + test/blackhole-server.c + test/dns-server.c + test/echo-server.c + test/run-benchmarks.c + test/runner.c) + target_compile_definitions(uv_run_benchmarks_a PRIVATE ${uv_defines}) + target_compile_options(uv_run_benchmarks_a PRIVATE ${uv_cflags}) + target_link_libraries(uv_run_benchmarks_a uv_a ${uv_test_libraries}) + + list(APPEND uv_test_sources + test/blackhole-server.c + test/echo-server.c + test/run-tests.c + test/runner.c + test/test-active.c + test/test-async-null-cb.c + test/test-async.c + test/test-barrier.c + test/test-callback-order.c + test/test-callback-stack.c + test/test-close-fd.c + test/test-close-order.c + test/test-condvar.c + test/test-connect-unspecified.c + test/test-connection-fail.c + test/test-cwd-and-chdir.c + test/test-default-loop-close.c + test/test-delayed-accept.c + test/test-dlerror.c + test/test-eintr-handling.c + test/test-embed.c + test/test-emfile.c + test/test-env-vars.c + test/test-error.c + test/test-fail-always.c + test/test-fork.c + test/test-fs-copyfile.c + test/test-fs-event.c + test/test-fs-poll.c + test/test-fs.c + test/test-fs-readdir.c + test/test-fs-fd-hash.c + test/test-fs-open-flags.c + test/test-get-currentexe.c + test/test-get-loadavg.c + test/test-get-memory.c + test/test-get-passwd.c + test/test-getaddrinfo.c + test/test-gethostname.c + test/test-getnameinfo.c + test/test-getsockname.c + test/test-getters-setters.c + test/test-gettimeofday.c + test/test-handle-fileno.c + test/test-homedir.c + test/test-hrtime.c + test/test-idle.c + test/test-idna.c + test/test-ip4-addr.c + test/test-ip6-addr.c + test/test-ipc-heavy-traffic-deadlock-bug.c + test/test-ipc-send-recv.c + test/test-ipc.c + test/test-loop-alive.c + test/test-loop-close.c + test/test-loop-configure.c + test/test-loop-handles.c + test/test-loop-stop.c + test/test-loop-time.c + test/test-multiple-listen.c + test/test-mutexes.c + test/test-osx-select.c + test/test-pass-always.c + test/test-ping-pong.c + test/test-pipe-bind-error.c + test/test-pipe-close-stdout-read-stdin.c + test/test-pipe-connect-error.c + test/test-pipe-connect-multiple.c + test/test-pipe-connect-prepare.c + test/test-pipe-getsockname.c + test/test-pipe-pending-instances.c + test/test-pipe-sendmsg.c + test/test-pipe-server-close.c + test/test-pipe-set-fchmod.c + test/test-pipe-set-non-blocking.c + test/test-platform-output.c + test/test-poll-close-doesnt-corrupt-stack.c + test/test-poll-close.c + test/test-poll-closesocket.c + test/test-poll-oob.c + test/test-poll.c + test/test-process-priority.c + test/test-process-title-threadsafe.c + test/test-process-title.c + test/test-queue-foreach-delete.c + test/test-random.c + test/test-ref.c + test/test-run-nowait.c + test/test-run-once.c + test/test-semaphore.c + test/test-shutdown-close.c + test/test-shutdown-eof.c + test/test-shutdown-twice.c + test/test-signal-multiple-loops.c + test/test-signal-pending-on-close.c + test/test-signal.c + test/test-socket-buffer-size.c + test/test-spawn.c + test/test-stdio-over-pipes.c + test/test-strscpy.c + test/test-tcp-alloc-cb-fail.c + test/test-tcp-bind-error.c + test/test-tcp-bind6-error.c + test/test-tcp-close-accept.c + test/test-tcp-close-while-connecting.c + test/test-tcp-close.c + test/test-tcp-close-reset.c + test/test-tcp-connect-error-after-write.c + test/test-tcp-connect-error.c + test/test-tcp-connect-timeout.c + test/test-tcp-connect6-error.c + test/test-tcp-create-socket-early.c + test/test-tcp-flags.c + test/test-tcp-oob.c + test/test-tcp-open.c + test/test-tcp-read-stop.c + test/test-tcp-shutdown-after-write.c + test/test-tcp-try-write.c + test/test-tcp-try-write-error.c + test/test-tcp-unexpected-read.c + test/test-tcp-write-after-connect.c + test/test-tcp-write-fail.c + test/test-tcp-write-queue-order.c + test/test-tcp-write-to-half-open-connection.c + test/test-tcp-writealot.c + test/test-thread-equal.c + test/test-thread.c + test/test-threadpool-cancel.c + test/test-threadpool.c + test/test-timer-again.c + test/test-timer-from-check.c + test/test-timer.c + test/test-tmpdir.c + test/test-tty-duplicate-key.c + test/test-tty-escape-sequence-processing.c + test/test-tty.c + test/test-udp-alloc-cb-fail.c + test/test-udp-bind.c + test/test-udp-connect.c + test/test-udp-create-socket-early.c + test/test-udp-dgram-too-big.c + test/test-udp-ipv6.c + test/test-udp-multicast-interface.c + test/test-udp-multicast-interface6.c + test/test-udp-multicast-join.c + test/test-udp-multicast-join6.c + test/test-udp-multicast-ttl.c + test/test-udp-open.c + test/test-udp-options.c + test/test-udp-send-and-recv.c + test/test-udp-send-hang-loop.c + test/test-udp-send-immediate.c + test/test-udp-send-unreachable.c + test/test-udp-try-send.c + test/test-uname.c + test/test-walk-handles.c + test/test-watcher-cross-stop.c) + add_executable(uv_run_tests ${uv_test_sources}) target_compile_definitions(uv_run_tests PRIVATE ${uv_defines} USING_UV_SHARED=1) @@ -388,6 +497,10 @@ if(LIBUV_BUILD_TESTS) add_test(NAME uv_test COMMAND uv_run_tests WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + if(CMAKE_SYSTEM_NAME STREQUAL "OS390") + set_tests_properties(uv_test PROPERTIES ENVIRONMENT + "LIBPATH=${CMAKE_BINARY_DIR}:$ENV{LIBPATH}") + endif() add_executable(uv_run_tests_a ${uv_test_sources}) target_compile_definitions(uv_run_tests_a PRIVATE ${uv_defines}) target_compile_options(uv_run_tests_a PRIVATE ${uv_cflags}) @@ -399,23 +512,26 @@ endif() if(UNIX) # Now for some gibbering horrors from beyond the stars... - foreach(x ${uv_libraries}) - set(LIBS "${LIBS} -l${x}") - endforeach(x) + foreach(lib IN LISTS uv_libraries) + list(APPEND LIBS "-l${lib}") + endforeach() + string(REPLACE ";" " " LIBS "${LIBS}") + # Consider setting project version via project() call? file(STRINGS configure.ac configure_ac REGEX ^AC_INIT) - string(REGEX MATCH [0-9]+[.][0-9]+[.][0-9]+ PACKAGE_VERSION "${configure_ac}") - string(REGEX MATCH ^[0-9]+ UV_VERSION_MAJOR "${PACKAGE_VERSION}") + string(REGEX MATCH "([0-9]+)[.][0-9]+[.][0-9]+" PACKAGE_VERSION "${configure_ac}") + set(UV_VERSION_MAJOR "${CMAKE_MATCH_1}") # The version in the filename is mirroring the behaviour of autotools. - set_target_properties(uv PROPERTIES VERSION ${UV_VERSION_MAJOR}.0.0 - SOVERSION ${UV_VERSION_MAJOR}) + set_target_properties(uv PROPERTIES + VERSION ${UV_VERSION_MAJOR}.0.0 + SOVERSION ${UV_VERSION_MAJOR}) set(includedir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}) set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) set(prefix ${CMAKE_INSTALL_PREFIX}) - configure_file(libuv.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libuv.pc @ONLY) + configure_file(libuv.pc.in libuv.pc @ONLY) install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR}) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libuv.pc + install(FILES ${PROJECT_BINARY_DIR}/libuv.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) install(TARGETS uv LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(TARGETS uv_a ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/deps/uv/CONTRIBUTING.md b/deps/uv/CONTRIBUTING.md index f22e124e3b23b9..b0abe3b40eaa25 100644 --- a/deps/uv/CONTRIBUTING.md +++ b/deps/uv/CONTRIBUTING.md @@ -48,11 +48,11 @@ the [Google C/C++ style guide]. Some of the key points, as well as some additional guidelines, are enumerated below. * Code that is specific to unix-y platforms should be placed in `src/unix`, and - declarations go into `include/uv-unix.h`. + declarations go into `include/uv/unix.h`. * Source code that is Windows-specific goes into `src/win`, and related publicly exported types, functions and macro declarations should generally - be declared in `include/uv-win.h`. + be declared in `include/uv/win.h`. * Names should be descriptive and concise. @@ -142,7 +142,6 @@ Bug fixes and features should come with tests. Add your tests in the If you add a new test file, it needs to be registered in three places: - `CMakeLists.txt`: add the file's name to the `uv_test_sources` list. - `Makefile.am`: add the file's name to the `test_run_tests_SOURCES` list. -- `uv.gyp`: add the file's name to the `sources` list in the `run-tests` target. Look at other tests to see how they should be structured (license boilerplate, the way entry points are declared, etc.). diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 9c2146dab9da7e..3544c6c01b5a31 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,184 @@ +2020.04.20, Version 1.37.0 (Stable), 02a9e1be252b623ee032a3137c0b0c94afbe6809 + +Changes since version 1.36.0: + +* timer: remove redundant check in heap compare (Yash Ladha) + +* udp: add flag to enable recvmmsg(2) explicitly (Saúl Ibarra Corretgé) + + +2020.04.16, Version 1.36.0 (Stable), 533b738838ad8407032e14b6772b29ef9af63cfa + +Changes since version 1.35.0: + +* build: add aix-common.c for AIX cmake build (Jesse Gorzinski) + +* zos: explicitly mark message queue events (Irek Fakhrutdinov) + +* zos: move mq check out of loop to save cpu cycles (Irek Fakhrutdinov) + +* zos: add checks to ensure behavior of epoll_wait (Irek Fakhrutdinov) + +* src: add uv__reallocf() (Ben Noordhuis) + +* build: ibmi support for cmake (Jesse Gorzinski) + +* build: fix gyp build for Android API >= 28 (Lin Zhang) + +* udp: return recvmmsg-ed datagrams in order (Saúl Ibarra Corretgé) + +* zos,test: fix spawn_empty_env for shared library build (Richard Lau) + +* zos: fix non-Release builds (Richard Lau) + +* zos: fix return value on expired nanosleep() call (Richard Lau) + +* build: fix z/OS cmake build (Richard Lau) + +* test: add a bunch of ASSERT macros (Santiago Gimeno) + +* test: remove unused extern declaration (Ben Noordhuis) + +* test: canonicalize argv[0] in exepath test (Ben Noordhuis) + +* test: simplify platform_init() (Ben Noordhuis) + +* ibmi: Fix isatty EBADF handling and refactor (Kevin Adler) + +* test: Test EBADF tty handling (Kevin Adler) + +* build: make cmake build benchmarks (Ben Noordhuis) + +* win: use RtlGenRandom from advapi32.dll directly (Ben Noordhuis) + +* android: fix OOB write in uv_interface_addresses() (Lin Zhang) + +* test: pass test when hostname is single character (毛毛) + +* ibmi: set the highest process priority to -10 (Xu Meng) + +* build: remove support for gyp (Ben Noordhuis) + +* doc: add note to README on cross-compiling (Ben Noordhuis) + +* fs: add uv_fs_lutime() (Sk Sajidul Kadir) + +* unix: implement cpu_relax() for arm (David Carlier) + +* linux: fix uv__accept4() (twosee) + +* win: handle file paths in uv_fs_statfs() (erw7) + +* unix: fix uv_os_environ() null pointer check (Rikard Falkeborn) + +* win: fix uv_os_environ() null pointer check (Rikard Falkeborn) + +* unix: fix compilation on macOS 32-bit architectures (Brad King) + +* win: replace alloca() with stack-based array (Ben Noordhuis) + + +2020.03.12, Version 1.35.0 (Stable), e45f1ec38db882f8dc17b51f51a6684027034609 + +Changes since version 1.34.2: + +* src: android build fix (David Carlier) + +* build: make code compilable for iOS on Xcode (ssrlive) + +* ibmi: skip unsupported fs test cases (Xu Meng) + +* ibmi: ensure that pipe backlog is not zero (Xu Meng) + +* test,udp6: fix udp_ipv6 test flakiness (Jameson Nash) + +* test: fix fs_event_watch_dir_recursive flakiness (Santiago Gimeno) + +* pipe: disallow listening on an IPC pipe (Witold Kręcicki) + +* build,cmake: improve buil experience (Isabella Muerte) + +* unix: remove support for FreeBSD < 10 (Saúl Ibarra Corretgé) + +* linux: simplify uv__accept() (Ben Noordhuis) + +* linux: assume presence of SOCK_CLOEXEC flag (Ben Noordhuis) + +* linux: simplify uv__dup2_cloexec() (Ben Noordhuis) + +* freebsd,linux: simplify uv__make_socketpair() (Ben Noordhuis) + +* unix: fix error handling in uv__make_socketpair() (Ben Noordhuis) + +* freebsd,linux: simplify uv__make_pipe() (Ben Noordhuis) + +* unix: fix error handling in uv__make_pipe() (Ben Noordhuis) + +* linux: simplify uv__async_eventfd() (Ben Noordhuis) + +* linux: assume the presence of inotify system calls (Ben Noordhuis) + +* doc: strip ICC profile from 2 jpg files (Dominique Dumont) + +* unix: make uv_tcp_keepalive predictable (Manuel BACHMANN) + +* docs: uv_setup_args() may take ownership of argv (Ben Noordhuis) + +* unix: fix error path in uv_setup_args() (Ben Noordhuis) + +* unix: fix size check in uv_get_process_title() (Ben Noordhuis) + +* doc: add erw7 to maintainers (erw7) + +* test: fixed udp4_echo_server implementation (Marek Vavrusa) + +* test: added udp ping benchmark (1,10,100 pingers) (Marek Vavrusa) + +* freebsd,linux: add recvmmsg() + sendmmsg() udp implementation (Marek Vavrusa) + +* win,pipe: DRY/simplify some code paths (Jameson Nash) + +* win: address some style nits (Jameson Nash) + +* win,pipe: ensure `req->event_handle` is defined (Elliot Saba) + +* win,pipe: consolidate overlapped initialization (Elliot Saba) + +* win,pipe: erase event_handle after deleting pointer (Jameson Nash) + +* build: fix android cmake build, build missing file (Ben Noordhuis) + +* test: skip some UDP tests on IBMi (Xu Meng) + +* test: skip some spawn test cases on IBMi (Xu Meng) + +* src: fix wrong method name in comment (TK-one) + +* test: add UV_TIMEOUT_MULTIPLIER environment var (Ben Noordhuis) + +* unix: fix uv_cpu_info always returning UV_ENOTDIR on OpenBSD (Ben Davies) + +* test: skip the pwd_shell test on IBMi (Xu Meng) + +* win,tty: Change to restore cursor shape with uv_tty_reset() (erw7) + +* win,tty: Added set cursor style to CSI sequences (erw7) + +* test: handle EINTR, fix EOF check in poll test (Ben Noordhuis) + +* unix: use socklen_t instead of size_t (Ben Noordhuis) + +* doc: fix header file location (TK-one) + +* unix: fix signal handle closing deferral (Ben Noordhuis) + +* ibmi: set the amount of memory in use to zero (Xu Meng) + +* zos: return on realloc failure in scandir() (Milad Farazmand) + +* zos: fix scandir() error path NULL pointer deref (Ben Noordhuis) + + 2020.01.24, Version 1.34.2 (Stable), f868c9ab0c307525a16fff99fd21e32a6ebc3837 Changes since version 1.34.1: diff --git a/deps/uv/MAINTAINERS.md b/deps/uv/MAINTAINERS.md index 0870b88eb6896b..268251e615a13d 100644 --- a/deps/uv/MAINTAINERS.md +++ b/deps/uv/MAINTAINERS.md @@ -17,6 +17,8 @@ libuv is currently managed by the following individuals: - GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere) * **Jameson Nash** ([@vtjnash](https://github.com/vtjnash)) * **John Barboza** ([@jbarz](https://github.com/jbarz)) +* **Kaoru Takanashi** ([@erw7](https://github.com/erw7)) + - GPG Key: 5804 F999 8A92 2AFB A398 47A0 7183 5090 6134 887F (pubkey-erw7) * **Richard Lau** ([@richardlau](https://github.com/richardlau)) - GPG key: C82F A3AE 1CBE DC6B E46B 9360 C43C EC45 C17A B93C (pubkey-richardlau) * **Santiago Gimeno** ([@santigimeno](https://github.com/santigimeno)) diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index 9a06b9ce4a73e4..23fa19dc4fc8e7 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -123,17 +123,9 @@ EXTRA_DIST = test/fixtures/empty_file \ include \ docs \ img \ - android-configure-arm \ - android-configure-arm64 \ - android-configure-x86 \ - android-configure-x86_64 \ CONTRIBUTING.md \ LICENSE \ - README.md \ - vcbuild.bat \ - common.gypi \ - gyp_uv.py \ - uv.gyp + README.md @@ -286,6 +278,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-timer.c \ test/test-tmpdir.c \ test/test-tty-duplicate-key.c \ + test/test-tty-escape-sequence-processing.c \ test/test-tty.c \ test/test-udp-alloc-cb-fail.c \ test/test-udp-bind.c \ @@ -345,7 +338,8 @@ test_run_tests_CFLAGS += -D__EXTENSIONS__ \ endif if OS390 -test_run_tests_CFLAGS += -D_UNIX03_THREADS \ +test_run_tests_CFLAGS += -D_ISOC99_SOURCE \ + -D_UNIX03_THREADS \ -D_UNIX03_SOURCE \ -D_OPEN_SYS_IF_EXT=1 \ -D_OPEN_SYS_SOCK_IPV6 \ diff --git a/deps/uv/README.md b/deps/uv/README.md index c040b4c18c8903..98007c5e7d21de 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -152,47 +152,14 @@ $ gpg --verify libuv-1.7.0.tar.gz.sign ## Build Instructions -For GCC there are two build methods: via autotools or via [GYP][]. -GYP is a meta-build system which can generate MSVS, Makefile, and XCode -backends. It is best used for integration into other projects. +For UNIX-like platforms, including macOS, there are two build methods: +autotools or [CMake][]. -To build with autotools: - -```bash -$ sh autogen.sh -$ ./configure -$ make -$ make check -$ make install -``` - -To build with [CMake](https://cmake.org/): - -```bash -$ mkdir -p out/cmake ; cd out/cmake # create build directory -$ cmake ../.. -DBUILD_TESTING=ON # generate project with test -$ cmake --build . # build -$ ctest -C Debug --output-on-failure # run tests - -# Or manually run tests: -$ ./out/cmake/uv_run_tests # shared library build -$ ./out/cmake/uv_run_tests_a # static library build -``` - -To build with GYP, first run: - -```bash -$ git clone https://chromium.googlesource.com/external/gyp build/gyp -``` - -### Windows +For Windows, [CMake][] is the only supported build method and has the +following prerequisites: -Prerequisites: +
-* [Python 2.6 or 2.7][] as it is required - by [GYP][]. - If python is not in your path, set the environment variable `PYTHON` to its - location. For example: `set PYTHON=C:\Python27\python.exe` * One of: * [Visual C++ Build Tools][] * [Visual Studio 2015 Update 3][], all editions @@ -205,67 +172,44 @@ Prerequisites: [Git for Windows][] includes Git Bash and tools which can be included in the global `PATH`. -To build, launch a git shell (e.g. Cmd or PowerShell), run `vcbuild.bat` -(to build with VS2017 you need to explicitly add a `vs2017` argument), -which will checkout the GYP code into `build/gyp`, generate `uv.sln` -as well as the necesery related project files, and start building. +
-```console -> vcbuild -``` - -Or: - -```console -> vcbuild vs2017 -``` - -To run the tests: - -```console -> vcbuild test -``` - -To see all the options that could passed to `vcbuild`: - -```console -> vcbuild help -vcbuild.bat [debug/release] [test/bench] [clean] [noprojgen] [nobuild] [vs2017] [x86/x64] [static/shared] -Examples: - vcbuild.bat : builds debug build - vcbuild.bat test : builds debug build and runs tests - vcbuild.bat release bench: builds release build and runs benchmarks -``` - - -### Unix - -For Debug builds (recommended) run: +To build with autotools: ```bash -$ ./gyp_uv.py -f make -$ make -C out +$ sh autogen.sh +$ ./configure +$ make +$ make check +$ make install ``` -For Release builds run: +To build with [CMake][]: ```bash -$ ./gyp_uv.py -f make -$ BUILDTYPE=Release make -C out -``` +$ mkdir -p build -Run `./gyp_uv.py -f make -Dtarget_arch=x32` to build [x32][] binaries. +$ (cd build && cmake .. -DBUILD_TESTING=ON) # generate project with tests +$ cmake --build build # add `-j ` with cmake >= 3.12 -### OS X +# Run tests: +$ (cd build && ctest -C Debug --output-on-failure) -Run: +# Or manually run tests: +$ build/uv_run_tests # shared library build +$ build/uv_run_tests_a # static library build +``` + +To cross-compile with [CMake][] (unsupported but generally works): ```bash -$ ./gyp_uv.py -f xcode -$ xcodebuild -ARCHS="x86_64" -project out/uv.xcodeproj -configuration Release -alltargets +$ cmake ../.. \ + -DCMAKE_SYSTEM_NAME=Windows \ + -DCMAKE_SYSTEM_VERSION=6.1 \ + -DCMAKE_C_COMPILER=i686-w64-mingw32-gcc ``` -Using Homebrew: +### Install with Homebrew ```bash $ brew install --HEAD libuv @@ -277,103 +221,48 @@ Make sure that you specify the architecture you wish to build for in the "ARCHS" flag. You can specify more than one by delimiting with a space (e.g. "x86_64 i386"). -### Android - -Run: - -For arm - -```bash -$ source ./android-configure-arm NDK_PATH gyp [API_LEVEL] -$ make -C out -``` - -or for arm64 - -```bash -$ source ./android-configure-arm64 NDK_PATH gyp [API_LEVEL] -$ make -C out -``` - -or for x86 - -```bash -$ source ./android-configure-x86 NDK_PATH gyp [API_LEVEL] -$ make -C out -``` - -or for x86_64 - -```bash -$ source ./android-configure-x86_64 NDK_PATH gyp [API_LEVEL] -$ make -C out -``` - -The default API level is 24, but a different one can be selected as follows: - -```bash -$ source ./android-configure-arm ~/android-ndk-r15b gyp 21 -$ make -C out -``` - -Note for UNIX users: compile your project with `-D_LARGEFILE_SOURCE` and -`-D_FILE_OFFSET_BITS=64`. GYP builds take care of that automatically. - -### Using Ninja - -To use ninja for build on ninja supported platforms, run: - -```bash -$ ./gyp_uv.py -f ninja -$ ninja -C out/Debug #for debug build OR -$ ninja -C out/Release -``` - - ### Running tests -#### Build - -Build (includes tests): +Some tests are timing sensitive. Relaxing test timeouts may be necessary +on slow or overloaded machines: ```bash -$ ./gyp_uv.py -f make -$ make -C out -``` - -#### Run all tests - -```bash -$ ./out/Debug/run-tests +$ env UV_TEST_TIMEOUT_MULTIPLIER=2 build/uv_run_tests # 10s instead of 5s ``` #### Run one test The list of all tests is in `test/test-list.h`. -This invocation will cause the `run-tests` driver to fork and execute `TEST_NAME` in a child process: +This invocation will cause the test driver to fork and execute `TEST_NAME` in +a child process: ```bash -$ ./out/Debug/run-tests TEST_NAME +$ build/uv_run_tests_a TEST_NAME ``` -This invocation will cause the `run-tests` driver to execute the test within the `run-tests` process: +This invocation will cause the test driver to execute the test in +the same process: ```bash -$ ./out/Debug/run-tests TEST_NAME TEST_NAME +$ build/uv_run_tests_a TEST_NAME TEST_NAME ``` #### Debugging tools -When running the test from within the `run-tests` process (`run-tests TEST_NAME TEST_NAME`), tools like gdb and valgrind work normally. -When running the test from a child of the `run-tests` process (`run-tests TEST_NAME`), use these tools in a fork-aware manner. +When running the test from within the test driver process +(`build/uv_run_tests_a TEST_NAME TEST_NAME`), tools like gdb and valgrind +work normally. + +When running the test from a child of the test driver process +(`build/uv_run_tests_a TEST_NAME`), use these tools in a fork-aware manner. ##### Fork-aware gdb Use the [follow-fork-mode](https://sourceware.org/gdb/onlinedocs/gdb/Forks.html) setting: ``` -$ gdb --args out/Debug/run-tests TEST_NAME +$ gdb --args build/uv_run_tests_a TEST_NAME (gdb) set follow-fork-mode child ... @@ -384,13 +273,14 @@ $ gdb --args out/Debug/run-tests TEST_NAME Use the `--trace-children=yes` parameter: ```bash -$ valgrind --trace-children=yes -v --tool=memcheck --leak-check=full --track-origins=yes --leak-resolution=high --show-reachable=yes --log-file=memcheck-%p.log out/Debug/run-tests TEST_NAME +$ valgrind --trace-children=yes -v --tool=memcheck --leak-check=full --track-origins=yes --leak-resolution=high --show-reachable=yes --log-file=memcheck-%p.log build/uv_run_tests_a TEST_NAME ``` ### Running benchmarks See the section on running tests. -The benchmark driver is `out/Debug/run-benchmarks` and the benchmarks are listed in `test/benchmark-list.h`. +The benchmark driver is `./uv_run_benchmarks_a` and the benchmarks are +listed in `test/benchmark-list.h`. ## Supported Platforms @@ -406,8 +296,6 @@ that is detected by `autoconf`. [IBM documentation](http://www.ibm.com/developerworks/aix/library/au-aix_event_infrastructure/) describes the package in more detail. -AIX support for filesystem events is not compiled when building with `gyp`. - ### z/OS Notes z/OS creates System V semaphores and message queues. These persist on the system @@ -419,12 +307,10 @@ Use the `ipcrm` command to manually clear up System V resources. See the [guidelines for contributing][]. +[CMake]: https://cmake.org/ [node.js]: http://nodejs.org/ -[GYP]: http://code.google.com/p/gyp/ [guidelines for contributing]: https://github.com/libuv/libuv/blob/master/CONTRIBUTING.md [libuv_banner]: https://raw.githubusercontent.com/libuv/libuv/master/img/banner.png -[x32]: https://en.wikipedia.org/wiki/X32_ABI -[Python 2.6 or 2.7]: https://www.python.org/downloads/ [Visual C++ Build Tools]: https://visualstudio.microsoft.com/visual-cpp-build-tools/ [Visual Studio 2015 Update 3]: https://www.visualstudio.com/vs/older-downloads/ [Visual Studio 2017]: https://www.visualstudio.com/downloads/ diff --git a/deps/uv/SUPPORTED_PLATFORMS.md b/deps/uv/SUPPORTED_PLATFORMS.md index 29e4844ff323d3..72e054eba067ec 100644 --- a/deps/uv/SUPPORTED_PLATFORMS.md +++ b/deps/uv/SUPPORTED_PLATFORMS.md @@ -47,8 +47,9 @@ All functionality related to the new platform must be implemented in its own file inside ``src/unix/`` unless it's already done in a common file, in which case adding an `ifdef` is fine. -Two build systems are supported: autotools and GYP. Ideally both need to be -supported, but if GYP does not support the new platform it can be left out. +Two build systems are supported: autotools and cmake. Ideally both need to be +supported, but if one of the two does not support the new platform it can be +left out. ### Windows diff --git a/deps/uv/android-configure-arm b/deps/uv/android-configure-arm deleted file mode 100755 index 331fdd9ebcf9f9..00000000000000 --- a/deps/uv/android-configure-arm +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -export TOOLCHAIN=$PWD/android-toolchain-arm -mkdir -p $TOOLCHAIN -API=${3:-24} -$1/build/tools/make-standalone-toolchain.sh \ - --toolchain=arm-linux-androideabi-4.9 \ - --arch=arm \ - --install-dir=$TOOLCHAIN \ - --platform=android-$API \ - --force -export PATH=$TOOLCHAIN/bin:$PATH -export AR=arm-linux-androideabi-ar -export CC=arm-linux-androideabi-gcc -export CXX=arm-linux-androideabi-g++ -export LINK=arm-linux-androideabi-g++ -export PLATFORM=android -export CFLAGS="-D__ANDROID_API__=$API" - -if [[ $2 == 'gyp' ]] - then - ./gyp_uv.py -Dtarget_arch=arm -DOS=android -f make-android -fi diff --git a/deps/uv/android-configure-arm64 b/deps/uv/android-configure-arm64 deleted file mode 100755 index 1acd905d775fd9..00000000000000 --- a/deps/uv/android-configure-arm64 +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -export TOOLCHAIN=$PWD/android-toolchain-arm64 -mkdir -p $TOOLCHAIN -API=${3:-24} -$1/build/tools/make-standalone-toolchain.sh \ - --toolchain=aarch64-linux-android-4.9 \ - --arch=arm64 \ - --install-dir=$TOOLCHAIN \ - --platform=android-$API \ - --force -export PATH=$TOOLCHAIN/bin:$PATH -export AR=aarch64-linux-android-ar -export CC=aarch64-linux-android-gcc -export CXX=aarch64-linux-android-g++ -export LINK=aarch64-linux-android-g++ -export PLATFORM=android -export CFLAGS="-D__ANDROID_API__=$API" - -if [[ $2 == 'gyp' ]] - then - ./gyp_uv.py -Dtarget_arch=arm64 -DOS=android -f make-android -fi diff --git a/deps/uv/android-configure-x86 b/deps/uv/android-configure-x86 deleted file mode 100755 index a149715f37547f..00000000000000 --- a/deps/uv/android-configure-x86 +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -export TOOLCHAIN=$PWD/android-toolchain-x86 -mkdir -p $TOOLCHAIN -API=${3:-24} -$1/build/tools/make-standalone-toolchain.sh \ - --toolchain=x86-4.9 \ - --arch=x86 \ - --install-dir=$TOOLCHAIN \ - --platform=android-$API \ - --force -export PATH=$TOOLCHAIN/bin:$PATH -export AR=i686-linux-android-ar -export CC=i686-linux-android-gcc -export CXX=i686-linux-android-g++ -export LINK=i686-linux-android-g++ -export PLATFORM=android -export CFLAGS="-D__ANDROID_API__=$API" - -if [[ $2 == 'gyp' ]] - then - ./gyp_uv.py -Dtarget_arch=x86 -DOS=android -f make-android -fi diff --git a/deps/uv/android-configure-x86_64 b/deps/uv/android-configure-x86_64 deleted file mode 100755 index ff045957f7138d..00000000000000 --- a/deps/uv/android-configure-x86_64 +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -export TOOLCHAIN=$PWD/android-toolchain-x86_64 -mkdir -p $TOOLCHAIN -API=${3:-24} -$1/build/tools/make-standalone-toolchain.sh \ - --toolchain=x86_64-4.9 \ - --arch=x86_64 \ - --install-dir=$TOOLCHAIN \ - --platform=android-$API \ - --force -export PATH=$TOOLCHAIN/bin:$PATH -export AR=x86_64-linux-android-ar -export CC=x86_64-linux-android-gcc -export CXX=x86_64-linux-android-g++ -export LINK=x86_64-linux-android-g++ -export PLATFORM=android -export CFLAGS="-D__ANDROID_API__=$API -fPIC" -export CXXFLAGS="-D__ANDROID_API__=$API -fPIC" -export LDFLAGS="-fPIC" - -if [[ $2 == 'gyp' ]] - then - ./gyp_uv.py -Dtarget_arch=x86_64 -DOS=android -f make-android -fi diff --git a/deps/uv/appveyor.yml b/deps/uv/appveyor.yml deleted file mode 100644 index 1b018a59cad86c..00000000000000 --- a/deps/uv/appveyor.yml +++ /dev/null @@ -1,32 +0,0 @@ -version: v1.18.0.build{build} - -init: - - git config --global core.autocrlf true - -install: - - cinst -y nsis - -matrix: - fast_finish: true - allow_failures: - - platform: x86 - configuration: Release - - platform: x64 - configuration: Release - -platform: - - x86 - - x64 - -configuration: - - Release - -build_script: - # Fixed tag version number if using a tag. - - cmd: if "%APPVEYOR_REPO_TAG%" == "true" set APPVEYOR_BUILD_VERSION=%APPVEYOR_REPO_TAG_NAME% - # vcbuild overwrites the platform variable. - - cmd: set ARCH=%platform% - - cmd: vcbuild.bat release %ARCH% shared - -cache: - - C:\projects\libuv\build\gyp diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index fba960b6b33731..cd7bab08570c8f 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.34.2], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.37.0], [https://github.com/libuv/libuv/issues]) AC_CONFIG_MACRO_DIR([m4]) m4_include([m4/libuv-extra-automake-flags.m4]) m4_include([m4/as_case.m4]) diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst index 2943ead330cc5a..a475a460307898 100644 --- a/deps/uv/docs/src/fs.rst +++ b/deps/uv/docs/src/fs.rst @@ -100,7 +100,8 @@ Data types UV_FS_OPENDIR, UV_FS_READDIR, UV_FS_CLOSEDIR, - UV_FS_MKSTEMP + UV_FS_MKSTEMP, + UV_FS_LUTIME } uv_fs_type; .. c:type:: uv_statfs_t @@ -402,12 +403,17 @@ API .. c:function:: int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb) .. c:function:: int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb) +.. c:function:: int uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb) - Equivalent to :man:`utime(2)` and :man:`futimes(3)` respectively. + Equivalent to :man:`utime(2)`, :man:`futimes(3)` and :man:`lutimes(3)` respectively. .. note:: - AIX: This function only works for AIX 7.1 and newer. It can still be called on older - versions but will return ``UV_ENOSYS``. + z/OS: `uv_fs_lutime()` is not implemented for z/OS. It can still be called but will return + ``UV_ENOSYS``. + + .. note:: + AIX: `uv_fs_futime()` and `uv_fs_lutime()` functions only work for AIX 7.1 and newer. + They can still be called on older versions but will return ``UV_ENOSYS``. .. versionchanged:: 1.10.0 sub-second precission is supported on Windows diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst index 7cfac85f571b94..8515cdbc1b040a 100644 --- a/deps/uv/docs/src/misc.rst +++ b/deps/uv/docs/src/misc.rst @@ -244,6 +244,15 @@ API .. c:function:: char** uv_setup_args(int argc, char** argv) Store the program arguments. Required for getting / setting the process title. + Libuv may take ownership of the memory that `argv` points to. This function + should be called exactly once, at program start-up. + + Example: + + :: + + argv = uv_setup_args(argc, argv); /* May return a copy of argv. */ + .. c:function:: int uv_get_process_title(char* buffer, size_t size) @@ -640,6 +649,16 @@ API On Windows, setting `PRIORITY_HIGHEST` will only work for elevated user, for others it will be silently reduced to `PRIORITY_HIGH`. + .. note:: + On IBM i PASE, the highest process priority is -10. The constant + `UV_PRIORITY_HIGHEST` is -10, `UV_PRIORITY_HIGH` is -7, + `UV_PRIORITY_ABOVE_NORMAL` is -4, `UV_PRIORITY_NORMAL` is 0, + `UV_PRIORITY_BELOW_NORMAL` is 15 and `UV_PRIORITY_LOW` is 39. + + .. note:: + On IBM i PASE, you are not allowed to change your priority unless you + have the *JOBCTL special authority (even to lower it). + .. versionadded:: 1.23.0 .. c:function:: int uv_os_uname(uv_utsname_t* buffer) diff --git a/deps/uv/docs/src/pipe.rst b/deps/uv/docs/src/pipe.rst index 5eac1b6df48e29..6437a9d9948148 100644 --- a/deps/uv/docs/src/pipe.rst +++ b/deps/uv/docs/src/pipe.rst @@ -24,6 +24,8 @@ Public members .. c:member:: int uv_pipe_t.ipc Whether this pipe is suitable for handle passing between processes. + Only a connected pipe that will be passing the handles should have this flag + set, not the listening pipe that uv_accept is called on. .. seealso:: The :c:type:`uv_stream_t` members also apply. @@ -35,7 +37,9 @@ API Initialize a pipe handle. The `ipc` argument is a boolean to indicate if this pipe will be used for handle passing between processes (which may - change the bytes on the wire). + change the bytes on the wire). Only a connected pipe that will be + passing the handles should have this flag set, not the listening pipe + that uv_accept is called on. .. c:function:: int uv_pipe_open(uv_pipe_t* handle, uv_file file) diff --git a/deps/uv/docs/src/static/diagrams.key/Data/st0-311.jpg b/deps/uv/docs/src/static/diagrams.key/Data/st0-311.jpg index 439f58109369c3..08f23a90b6ea37 100644 Binary files a/deps/uv/docs/src/static/diagrams.key/Data/st0-311.jpg and b/deps/uv/docs/src/static/diagrams.key/Data/st0-311.jpg differ diff --git a/deps/uv/docs/src/static/diagrams.key/Data/st1-475.jpg b/deps/uv/docs/src/static/diagrams.key/Data/st1-475.jpg index ffb21ff22457da..26e676a71a3c1d 100644 Binary files a/deps/uv/docs/src/static/diagrams.key/Data/st1-475.jpg and b/deps/uv/docs/src/static/diagrams.key/Data/st1-475.jpg differ diff --git a/deps/uv/docs/src/tcp.rst b/deps/uv/docs/src/tcp.rst index bcb163ea0f0356..3cc8efaac10bf6 100644 --- a/deps/uv/docs/src/tcp.rst +++ b/deps/uv/docs/src/tcp.rst @@ -60,6 +60,11 @@ API Enable / disable TCP keep-alive. `delay` is the initial delay in seconds, ignored when `enable` is zero. + After `delay` has been reached, 10 successive probes, each spaced 1 second + from the previous one, will still happen. If the connection is still lost + at the end of this procedure, then the handle is destroyed with a + ``UV_ETIMEDOUT`` error passed to the corresponding callback. + .. c:function:: int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) Enable / disable simultaneous asynchronous accept requests that are diff --git a/deps/uv/docs/src/udp.rst b/deps/uv/docs/src/udp.rst index 53b1fea4933aae..6be20345280d90 100644 --- a/deps/uv/docs/src/udp.rst +++ b/deps/uv/docs/src/udp.rst @@ -41,7 +41,16 @@ Data types * (provided they all set the flag) but only the last one to bind will receive * any traffic, in effect "stealing" the port from the previous listener. */ - UV_UDP_REUSEADDR = 4 + UV_UDP_REUSEADDR = 4, + /* + * Indicates that the message was received by recvmmsg, so the buffer provided + * must not be freed by the recv_cb callback. + */ + UV_UDP_MMSG_CHUNK = 8, + /* + * Indicates that recvmmsg should be used, if available. + */ + UV_UDP_RECVMMSG = 256 }; .. c:type:: void (*uv_udp_send_cb)(uv_udp_send_t* req, int status) @@ -62,13 +71,18 @@ Data types * `buf`: :c:type:`uv_buf_t` with the received data. * `addr`: ``struct sockaddr*`` containing the address of the sender. Can be NULL. Valid for the duration of the callback only. - * `flags`: One or more or'ed UV_UDP_* constants. Right now only - ``UV_UDP_PARTIAL`` is used. + * `flags`: One or more or'ed UV_UDP_* constants. The callee is responsible for freeing the buffer, libuv does not reuse it. The buffer may be a null buffer (where `buf->base` == NULL and `buf->len` == 0) on error. + When using :man:`recvmmsg(2)`, chunks will have the `UV_UDP_MMSG_CHUNK` flag set, + those must not be freed. There will be a final callback with `nread` set to 0, + `addr` set to NULL and the buffer pointing at the initially allocated data with + the `UV_UDP_MMSG_CHUNK` flag cleared. This is a good chance for the callee to + free the provided buffer. + .. note:: The receive callback will be called with `nread` == 0 and `addr` == NULL when there is nothing to read, and with `nread` == 0 and `addr` != NULL when an empty UDP packet is @@ -115,12 +129,17 @@ API .. c:function:: int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) - Initialize the handle with the specified flags. At the moment the lower 8 bits - of the `flags` parameter are used as the socket domain. A socket will be created - for the given domain. If the specified domain is ``AF_UNSPEC`` no socket is created, - just like :c:func:`uv_udp_init`. + Initialize the handle with the specified flags. The lower 8 bits of the `flags` + parameter are used as the socket domain. A socket will be created for the given domain. + If the specified domain is ``AF_UNSPEC`` no socket is created, just like :c:func:`uv_udp_init`. + + The remaining bits can be used to set one of these flags: + + * `UV_UDP_RECVMMSG`: if set, and the platform supports it, :man:`recvmmsg(2)` will + be used. .. versionadded:: 1.7.0 + .. versionchanged:: 1.37.0 added the `UV_UDP_RECVMMSG` flag. .. c:function:: int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) @@ -366,6 +385,13 @@ API :returns: 0 on success, or an error code < 0 on failure. + .. versionchanged:: 1.35.0 added support for :man:`recvmmsg(2)` on supported platforms). + The use of this feature requires a buffer larger than + 2 * 64KB to be passed to `alloc_cb`. + .. versionchanged:: 1.37.0 :man:`recvmmsg(2)` support is no longer enabled implicitly, + it must be explicitly requested by passing the `UV_UDP_RECVMMSG` flag to + :c:func:`uv_udp_init_ex`. + .. c:function:: int uv_udp_recv_stop(uv_udp_t* handle) Stop listening for incoming datagrams. diff --git a/deps/uv/gyp_uv.py b/deps/uv/gyp_uv.py deleted file mode 100755 index c2add5caecc7d3..00000000000000 --- a/deps/uv/gyp_uv.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python - -import os -import platform -import sys - -try: - import multiprocessing.synchronize - gyp_parallel_support = True -except ImportError: - gyp_parallel_support = False - - -CC = os.environ.get('CC', 'cc') -script_dir = os.path.dirname(__file__) -uv_root = os.path.normpath(script_dir) -output_dir = os.path.join(os.path.abspath(uv_root), 'out') - -sys.path.insert(0, os.path.join(uv_root, 'build', 'gyp', 'pylib')) -try: - import gyp -except ImportError: - print('You need to install gyp in build/gyp first. See the README.') - sys.exit(42) - - -def host_arch(): - machine = platform.machine() - if machine == 'i386': return 'ia32' - if machine == 'AMD64': return 'x64' - if machine == 'x86_64': return 'x64' - if machine.startswith('arm'): return 'arm' - if machine.startswith('mips'): return 'mips' - return machine # Return as-is and hope for the best. - - -def run_gyp(args): - rc = gyp.main(args) - if rc != 0: - print('Error running GYP') - sys.exit(rc) - - -if __name__ == '__main__': - args = sys.argv[1:] - args.extend('-I common.gypi test/test.gyp'.split(' ')) - args.append('--depth=' + uv_root) - - # There's a bug with windows which doesn't allow this feature. - if sys.platform != 'win32': - if '-f' not in args: - args.extend('-f make'.split()) - if 'eclipse' not in args and 'ninja' not in args: - args.extend(['-Goutput_dir=' + output_dir]) - args.extend(['--generator-output', output_dir]) - - if not any(a.startswith('-Dhost_arch=') for a in args): - args.append('-Dhost_arch=%s' % host_arch()) - - if not any(a.startswith('-Dtarget_arch=') for a in args): - args.append('-Dtarget_arch=%s' % host_arch()) - - if not any(a.startswith('-Duv_library=') for a in args): - args.append('-Duv_library=static_library') - - # Some platforms (OpenBSD for example) don't have multiprocessing.synchronize - # so gyp must be run with --no-parallel - if not gyp_parallel_support: - args.append('--no-parallel') - - gyp_args = list(args) - print(gyp_args) - run_gyp(gyp_args) diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 626cebabd8c9ea..a3a770db88b90e 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -605,7 +605,17 @@ enum uv_udp_flags { * (provided they all set the flag) but only the last one to bind will receive * any traffic, in effect "stealing" the port from the previous listener. */ - UV_UDP_REUSEADDR = 4 + UV_UDP_REUSEADDR = 4, + /* + * Indicates that the message was received by recvmmsg, so the buffer provided + * must not be freed by the recv_cb callback. + */ + UV_UDP_MMSG_CHUNK = 8, + + /* + * Indicates that recvmmsg should be used, if available. + */ + UV_UDP_RECVMMSG = 256 }; typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status); @@ -1177,12 +1187,22 @@ UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd); UV_EXTERN uv_pid_t uv_os_getpid(void); UV_EXTERN uv_pid_t uv_os_getppid(void); -#define UV_PRIORITY_LOW 19 -#define UV_PRIORITY_BELOW_NORMAL 10 -#define UV_PRIORITY_NORMAL 0 -#define UV_PRIORITY_ABOVE_NORMAL -7 -#define UV_PRIORITY_HIGH -14 -#define UV_PRIORITY_HIGHEST -20 +#if defined(__PASE__) +/* On IBM i PASE, the highest process priority is -10 */ +# define UV_PRIORITY_LOW 39 // RUNPTY(99) +# define UV_PRIORITY_BELOW_NORMAL 15 // RUNPTY(50) +# define UV_PRIORITY_NORMAL 0 // RUNPTY(20) +# define UV_PRIORITY_ABOVE_NORMAL -4 // RUNTY(12) +# define UV_PRIORITY_HIGH -7 // RUNPTY(6) +# define UV_PRIORITY_HIGHEST -10 // RUNPTY(1) +#else +# define UV_PRIORITY_LOW 19 +# define UV_PRIORITY_BELOW_NORMAL 10 +# define UV_PRIORITY_NORMAL 0 +# define UV_PRIORITY_ABOVE_NORMAL -7 +# define UV_PRIORITY_HIGH -14 +# define UV_PRIORITY_HIGHEST -20 +#endif UV_EXTERN int uv_os_getpriority(uv_pid_t pid, int* priority); UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority); @@ -1259,7 +1279,8 @@ typedef enum { UV_FS_READDIR, UV_FS_CLOSEDIR, UV_FS_STATFS, - UV_FS_MKSTEMP + UV_FS_MKSTEMP, + UV_FS_LUTIME } uv_fs_type; struct uv_dir_s { @@ -1432,6 +1453,12 @@ UV_EXTERN int uv_fs_futime(uv_loop_t* loop, double atime, double mtime, uv_fs_cb cb); +UV_EXTERN int uv_fs_lutime(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + double atime, + double mtime, + uv_fs_cb cb); UV_EXTERN int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h index 623ca3ef2cba71..be97adf6fff794 100644 --- a/deps/uv/include/uv/version.h +++ b/deps/uv/include/uv/version.h @@ -26,13 +26,13 @@ * Versions with the same major number are ABI stable. API is allowed to * evolve between minor releases, but only in a backwards compatible way. * Make sure you update the -soname directives in configure.ac - * and uv.gyp whenever you bump UV_VERSION_MAJOR or UV_VERSION_MINOR (but + * whenever you bump UV_VERSION_MAJOR or UV_VERSION_MINOR (but * not UV_VERSION_PATCH.) */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 34 -#define UV_VERSION_PATCH 2 +#define UV_VERSION_MINOR 37 +#define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/include/uv/win.h b/deps/uv/include/uv/win.h index 9793eee3e1e166..f5f1d3a3cc2d9b 100644 --- a/deps/uv/include/uv/win.h +++ b/deps/uv/include/uv/win.h @@ -517,7 +517,7 @@ typedef struct { /* eol conversion state */ \ unsigned char previous_eol; \ /* ansi parser state */ \ - unsigned char ansi_parser_state; \ + unsigned short ansi_parser_state; \ unsigned char ansi_csi_argc; \ unsigned short ansi_csi_argv[4]; \ COORD saved_position; \ diff --git a/deps/uv/src/timer.c b/deps/uv/src/timer.c index 8fce7f6472f9fd..4cf4ed42648650 100644 --- a/deps/uv/src/timer.c +++ b/deps/uv/src/timer.c @@ -51,12 +51,7 @@ static int timer_less_than(const struct heap_node* ha, /* Compare start_id when both have the same timeout. start_id is * allocated with loop->timer_counter in uv_timer_start(). */ - if (a->start_id < b->start_id) - return 1; - if (b->start_id < a->start_id) - return 0; - - return 0; + return a->start_id < b->start_id; } @@ -87,7 +82,7 @@ int uv_timer_start(uv_timer_t* handle, handle->timer_cb = cb; handle->timeout = clamped_timeout; handle->repeat = repeat; - /* start_id is the second index to be compared in uv__timer_cmp() */ + /* start_id is the second index to be compared in timer_less_than() */ handle->start_id = handle->loop->timer_counter++; heap_insert(timer_heap(handle->loop), diff --git a/deps/uv/src/unix/android-ifaddrs.c b/deps/uv/src/unix/android-ifaddrs.c index 7d48c6af57ca46..4765cc06b579c4 100644 --- a/deps/uv/src/unix/android-ifaddrs.c +++ b/deps/uv/src/unix/android-ifaddrs.c @@ -470,13 +470,14 @@ static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, { case IFA_ADDRESS: case IFA_LOCAL: + l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask) { /* Make room for netmask */ l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); l_addedNetmask = 1; } - break; + break; case IFA_BROADCAST: l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); break; diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c index a5c47bca05908e..26d337e0a44c0e 100644 --- a/deps/uv/src/unix/async.c +++ b/deps/uv/src/unix/async.c @@ -33,9 +33,12 @@ #include #include +#ifdef __linux__ +#include +#endif + static void uv__async_send(uv_loop_t* loop); static int uv__async_start(uv_loop_t* loop); -static int uv__async_eventfd(void); int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) { @@ -190,36 +193,18 @@ static int uv__async_start(uv_loop_t* loop) { if (loop->async_io_watcher.fd != -1) return 0; - err = uv__async_eventfd(); - if (err >= 0) { - pipefd[0] = err; - pipefd[1] = -1; - } - else if (err == UV_ENOSYS) { - err = uv__make_pipe(pipefd, UV__F_NONBLOCK); -#if defined(__linux__) - /* Save a file descriptor by opening one of the pipe descriptors as - * read/write through the procfs. That file descriptor can then - * function as both ends of the pipe. - */ - if (err == 0) { - char buf[32]; - int fd; - - snprintf(buf, sizeof(buf), "/proc/self/fd/%d", pipefd[0]); - fd = uv__open_cloexec(buf, O_RDWR); - if (fd >= 0) { - uv__close(pipefd[0]); - uv__close(pipefd[1]); - pipefd[0] = fd; - pipefd[1] = fd; - } - } -#endif - } +#ifdef __linux__ + err = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); + if (err < 0) + return UV__ERR(errno); + pipefd[0] = err; + pipefd[1] = -1; +#else + err = uv__make_pipe(pipefd, UV__F_NONBLOCK); if (err < 0) return err; +#endif uv__io_init(&loop->async_io_watcher, uv__async_io, pipefd[0]); uv__io_start(loop, &loop->async_io_watcher, POLLIN); @@ -253,46 +238,3 @@ void uv__async_stop(uv_loop_t* loop) { uv__close(loop->async_io_watcher.fd); loop->async_io_watcher.fd = -1; } - - -static int uv__async_eventfd(void) { -#if defined(__linux__) - static int no_eventfd2; - static int no_eventfd; - int fd; - - if (no_eventfd2) - goto skip_eventfd2; - - fd = uv__eventfd2(0, UV__EFD_CLOEXEC | UV__EFD_NONBLOCK); - if (fd != -1) - return fd; - - if (errno != ENOSYS) - return UV__ERR(errno); - - no_eventfd2 = 1; - -skip_eventfd2: - - if (no_eventfd) - goto skip_eventfd; - - fd = uv__eventfd(0); - if (fd != -1) { - uv__cloexec(fd, 1); - uv__nonblock(fd, 1); - return fd; - } - - if (errno != ENOSYS) - return UV__ERR(errno); - - no_eventfd = 1; - -skip_eventfd: - -#endif - - return UV_ENOSYS; -} diff --git a/deps/uv/src/unix/atomic-ops.h b/deps/uv/src/unix/atomic-ops.h index bc37c0d45d159c..347d19365f7542 100644 --- a/deps/uv/src/unix/atomic-ops.h +++ b/deps/uv/src/unix/atomic-ops.h @@ -53,6 +53,8 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { UV_UNUSED(static void cpu_relax(void)) { #if defined(__i386__) || defined(__x86_64__) __asm__ __volatile__ ("rep; nop"); /* a.k.a. PAUSE */ +#elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__) + __asm__ volatile("yield"); #endif } diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 04999dce36d193..949eefae339919 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -71,20 +71,12 @@ extern char** environ; # include # include # include -# if defined(__FreeBSD__) && __FreeBSD__ >= 10 +# if defined(__FreeBSD__) # define uv__accept4 accept4 # endif # if defined(__NetBSD__) # define uv__accept4(a, b, c, d) paccept((a), (b), (c), NULL, (d)) # endif -# if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \ - defined(__NetBSD__) || defined(__OpenBSD__) -# define UV__SOCK_NONBLOCK SOCK_NONBLOCK -# define UV__SOCK_CLOEXEC SOCK_CLOEXEC -# endif -# if !defined(F_DUP2FD_CLOEXEC) && defined(_F_DUP2FD_CLOEXEC) -# define F_DUP2FD_CLOEXEC _F_DUP2FD_CLOEXEC -# endif #endif #if defined(__ANDROID_API__) && __ANDROID_API__ < 21 @@ -96,7 +88,8 @@ extern char** environ; #endif #if defined(__linux__) -#include +# include +# define uv__accept4 accept4 #endif static int uv__run_pending(uv_loop_t* loop); @@ -179,9 +172,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { case UV_SIGNAL: uv__signal_close((uv_signal_t*) handle); - /* Signal handles may not be closed immediately. The signal code will - * itself close uv__make_close_pending whenever appropriate. */ - return; + break; default: assert(0); @@ -246,6 +237,8 @@ int uv__getiovmax(void) { static void uv__finish_close(uv_handle_t* handle) { + uv_signal_t* sh; + /* Note: while the handle is in the UV_HANDLE_CLOSING state now, it's still * possible for it to be active in the sense that uv__is_active() returns * true. @@ -268,7 +261,20 @@ static void uv__finish_close(uv_handle_t* handle) { case UV_FS_EVENT: case UV_FS_POLL: case UV_POLL: + break; + case UV_SIGNAL: + /* If there are any caught signals "trapped" in the signal pipe, + * we can't call the close callback yet. Reinserting the handle + * into the closing queue makes the event loop spin but that's + * okay because we only need to deliver the pending events. + */ + sh = (uv_signal_t*) handle; + if (sh->caught_signals > sh->dispatched_signals) { + handle->flags ^= UV_HANDLE_CLOSED; + uv__make_close_pending(handle); /* Back into the queue. */ + return; + } break; case UV_NAMED_PIPE: @@ -472,52 +478,32 @@ int uv__accept(int sockfd) { int peerfd; int err; + (void) &err; assert(sockfd >= 0); - while (1) { -#if defined(__linux__) || \ - (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \ - defined(__NetBSD__) - static int no_accept4; - - if (no_accept4) - goto skip; - - peerfd = uv__accept4(sockfd, - NULL, - NULL, - UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC); - if (peerfd != -1) - return peerfd; - - if (errno == EINTR) - continue; - - if (errno != ENOSYS) - return UV__ERR(errno); - - no_accept4 = 1; -skip: -#endif - + do +#ifdef uv__accept4 + peerfd = uv__accept4(sockfd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); +#else peerfd = accept(sockfd, NULL, NULL); - if (peerfd == -1) { - if (errno == EINTR) - continue; - return UV__ERR(errno); - } +#endif + while (peerfd == -1 && errno == EINTR); - err = uv__cloexec(peerfd, 1); - if (err == 0) - err = uv__nonblock(peerfd, 1); + if (peerfd == -1) + return UV__ERR(errno); - if (err) { - uv__close(peerfd); - return err; - } +#ifndef uv__accept4 + err = uv__cloexec(peerfd, 1); + if (err == 0) + err = uv__nonblock(peerfd, 1); - return peerfd; + if (err != 0) { + uv__close(peerfd); + return err; } +#endif + + return peerfd; } @@ -533,7 +519,7 @@ int uv__close_nocancel(int fd) { #if defined(__APPLE__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension" -#if defined(__LP64__) +#if defined(__LP64__) || TARGET_OS_IPHONE extern int close$NOCANCEL(int); return close$NOCANCEL(fd); #else @@ -849,8 +835,8 @@ static void maybe_resize(uv_loop_t* loop, unsigned int len) { } nwatchers = next_power_of_two(len + 2) - 2; - watchers = uv__realloc(loop->watchers, - (nwatchers + 2) * sizeof(loop->watchers[0])); + watchers = uv__reallocf(loop->watchers, + (nwatchers + 2) * sizeof(loop->watchers[0])); if (watchers == NULL) abort(); @@ -1031,54 +1017,30 @@ int uv__open_cloexec(const char* path, int flags) { int uv__dup2_cloexec(int oldfd, int newfd) { +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__linux__) int r; -#if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__) + r = dup3(oldfd, newfd, O_CLOEXEC); if (r == -1) return UV__ERR(errno); + return r; -#elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC) - r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd); - if (r != -1) - return r; - if (errno != EINVAL) - return UV__ERR(errno); - /* Fall through. */ -#elif defined(__linux__) - static int no_dup3; - if (!no_dup3) { - do - r = uv__dup3(oldfd, newfd, O_CLOEXEC); - while (r == -1 && errno == EBUSY); - if (r != -1) - return r; - if (errno != ENOSYS) - return UV__ERR(errno); - /* Fall through. */ - no_dup3 = 1; - } -#endif - { - int err; - do - r = dup2(oldfd, newfd); -#if defined(__linux__) - while (r == -1 && errno == EBUSY); #else - while (0); /* Never retry. */ -#endif - - if (r == -1) - return UV__ERR(errno); + int err; + int r; - err = uv__cloexec(newfd, 1); - if (err) { - uv__close(newfd); - return err; - } + r = dup2(oldfd, newfd); /* Never retry. */ + if (r == -1) + return UV__ERR(errno); - return r; + err = uv__cloexec(newfd, 1); + if (err != 0) { + uv__close(newfd); + return err; } + + return r; +#endif } @@ -1296,7 +1258,7 @@ int uv_os_environ(uv_env_item_t** envitems, int* count) { *envitems = uv__calloc(i, sizeof(**envitems)); - if (envitems == NULL) + if (*envitems == NULL) return UV_ENOMEM; for (j = 0, cnt = 0; j < i; j++) { diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c index 57bd04e240939b..ef77e127c26c39 100644 --- a/deps/uv/src/unix/freebsd.c +++ b/deps/uv/src/unix/freebsd.c @@ -288,3 +288,28 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { uv__free(cp_times); return 0; } + + +int uv__sendmmsg(int fd, + struct uv__mmsghdr* mmsg, + unsigned int vlen, + unsigned int flags) { +#if __FreeBSD__ >= 11 + return sendmmsg(fd, mmsg, vlen, flags); +#else + return errno = ENOSYS, -1; +#endif +} + + +int uv__recvmmsg(int fd, + struct uv__mmsghdr* mmsg, + unsigned int vlen, + unsigned int flags, + struct timespec* timeout) { +#if __FreeBSD__ >= 11 + return recvmmsg(fd, mmsg, vlen, flags, timeout); +#else + return errno = ENOSYS, -1; +#endif +} diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index 898bfc45cef46e..bc7fd8509daa1d 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -205,6 +205,20 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) { } +UV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) { + struct timespec ts; + ts.tv_sec = time; + ts.tv_nsec = (uint64_t)(time * 1000000) % 1000000 * 1000; + return ts; +} + +UV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) { + struct timeval tv; + tv.tv_sec = time; + tv.tv_usec = (uint64_t)(time * 1000000) % 1000000; + return tv; +} + static ssize_t uv__fs_futime(uv_fs_t* req) { #if defined(__linux__) \ || defined(_AIX71) \ @@ -213,10 +227,8 @@ static ssize_t uv__fs_futime(uv_fs_t* req) { * for the sake of consistency with other platforms. */ struct timespec ts[2]; - ts[0].tv_sec = req->atime; - ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000; - ts[1].tv_sec = req->mtime; - ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000; + ts[0] = uv__fs_to_timespec(req->atime); + ts[1] = uv__fs_to_timespec(req->mtime); #if defined(__ANDROID_API__) && __ANDROID_API__ < 21 return utimensat(req->file, NULL, ts, 0); #else @@ -230,10 +242,8 @@ static ssize_t uv__fs_futime(uv_fs_t* req) { || defined(__OpenBSD__) \ || defined(__sun) struct timeval tv[2]; - tv[0].tv_sec = req->atime; - tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000; - tv[1].tv_sec = req->mtime; - tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000; + tv[0] = uv__fs_to_timeval(req->atime); + tv[1] = uv__fs_to_timeval(req->mtime); # if defined(__sun) return futimesat(req->file, NULL, tv); # else @@ -666,7 +676,6 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { ssize_t maxlen; ssize_t len; char* buf; - char* newbuf; #if defined(_POSIX_PATH_MAX) || defined(PATH_MAX) maxlen = uv__fs_pathmax_size(req->path); @@ -710,14 +719,10 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { /* Uncommon case: resize to make room for the trailing nul byte. */ if (len == maxlen) { - newbuf = uv__realloc(buf, len + 1); + buf = uv__reallocf(buf, len + 1); - if (newbuf == NULL) { - uv__free(buf); + if (buf == NULL) return -1; - } - - buf = newbuf; } buf[len] = '\0'; @@ -977,10 +982,8 @@ static ssize_t uv__fs_utime(uv_fs_t* req) { * for the sake of consistency with other platforms. */ struct timespec ts[2]; - ts[0].tv_sec = req->atime; - ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000; - ts[1].tv_sec = req->mtime; - ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000; + ts[0] = uv__fs_to_timespec(req->atime); + ts[1] = uv__fs_to_timespec(req->mtime); return utimensat(AT_FDCWD, req->path, ts, 0); #elif defined(__APPLE__) \ || defined(__DragonFly__) \ @@ -989,10 +992,8 @@ static ssize_t uv__fs_utime(uv_fs_t* req) { || defined(__NetBSD__) \ || defined(__OpenBSD__) struct timeval tv[2]; - tv[0].tv_sec = req->atime; - tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000; - tv[1].tv_sec = req->mtime; - tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000; + tv[0] = uv__fs_to_timeval(req->atime); + tv[1] = uv__fs_to_timeval(req->mtime); return utimes(req->path, tv); #elif defined(_AIX) \ && !defined(_AIX71) @@ -1015,6 +1016,31 @@ static ssize_t uv__fs_utime(uv_fs_t* req) { } +static ssize_t uv__fs_lutime(uv_fs_t* req) { +#if defined(__linux__) || \ + defined(_AIX71) || \ + defined(__sun) || \ + defined(__HAIKU__) + struct timespec ts[2]; + ts[0] = uv__fs_to_timespec(req->atime); + ts[1] = uv__fs_to_timespec(req->mtime); + return utimensat(AT_FDCWD, req->path, ts, AT_SYMLINK_NOFOLLOW); +#elif defined(__APPLE__) || \ + defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || \ + defined(__NetBSD__) + struct timeval tv[2]; + tv[0] = uv__fs_to_timeval(req->atime); + tv[1] = uv__fs_to_timeval(req->mtime); + return lutimes(req->path, tv); +#else + errno = ENOSYS; + return -1; +#endif +} + + static ssize_t uv__fs_write(uv_fs_t* req) { #if defined(__linux__) static int no_pwritev; @@ -1528,6 +1554,7 @@ static void uv__fs_work(struct uv__work* w) { X(FSYNC, uv__fs_fsync(req)); X(FTRUNCATE, ftruncate(req->file, req->off)); X(FUTIME, uv__fs_futime(req)); + X(LUTIME, uv__fs_lutime(req)); X(LSTAT, uv__fs_lstat(req->path, &req->statbuf)); X(LINK, link(req->path, req->new_path)); X(MKDIR, mkdir(req->path, req->mode)); @@ -1714,6 +1741,19 @@ int uv_fs_futime(uv_loop_t* loop, POST; } +int uv_fs_lutime(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + double atime, + double mtime, + uv_fs_cb cb) { + INIT(LUTIME); + PATH; + req->atime = atime; + req->mtime = mtime; + POST; +} + int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { INIT(LSTAT); diff --git a/deps/uv/src/unix/ibmi.c b/deps/uv/src/unix/ibmi.c index 4dd8bb6e3758e3..ff300ea5f8f79f 100644 --- a/deps/uv/src/unix/ibmi.c +++ b/deps/uv/src/unix/ibmi.c @@ -225,22 +225,7 @@ uint64_t uv_get_free_memory(void) { if (get_ibmi_system_status(&rcvr)) return 0; - /* The amount of main storage, in kilobytes, in the system. */ - uint64_t main_storage_size = rcvr.main_storage_size; - - /* The current amount of storage in use for temporary objects. - * in millions (M) of bytes. - */ - uint64_t current_unprotected_storage_used = - rcvr.current_unprotected_storage_used * 1024ULL; - - /* Current unprotected storage includes the storage used for memory - * and disks so it is possible to exceed the amount of main storage. - */ - if (main_storage_size <= current_unprotected_storage_used) - return 0ULL; - - return (main_storage_size - current_unprotected_storage_used) * 1024ULL; + return (uint64_t)rcvr.main_storage_size * 1024ULL; } diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 47f220000dcd73..598554b607ec42 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -28,9 +28,10 @@ #include /* _POSIX_PATH_MAX, PATH_MAX */ #include /* abort */ #include /* strrchr */ -#include /* O_CLOEXEC, may be */ +#include /* O_CLOEXEC and O_NONBLOCK, if supported. */ #include #include +#include #if defined(__STRICT_ANSI__) # define inline __inline @@ -284,13 +285,12 @@ int uv___stream_fd(const uv_stream_t* handle); #define uv__stream_fd(handle) ((handle)->io_watcher.fd) #endif /* defined(__APPLE__) */ -#ifdef UV__O_NONBLOCK -# define UV__F_NONBLOCK UV__O_NONBLOCK +#ifdef O_NONBLOCK +# define UV__F_NONBLOCK O_NONBLOCK #else # define UV__F_NONBLOCK 1 #endif -int uv__make_socketpair(int fds[2], int flags); int uv__make_pipe(int fds[2], int flags); #if defined(__APPLE__) @@ -328,4 +328,27 @@ int uv__getsockpeername(const uv_handle_t* handle, struct sockaddr* name, int* namelen); +#if defined(__linux__) || \ + defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) +#define HAVE_MMSG 1 +struct uv__mmsghdr { + struct msghdr msg_hdr; + unsigned int msg_len; +}; + +int uv__recvmmsg(int fd, + struct uv__mmsghdr* mmsg, + unsigned int vlen, + unsigned int flags, + struct timespec* timeout); +int uv__sendmmsg(int fd, + struct uv__mmsghdr* mmsg, + unsigned int vlen, + unsigned int flags); +#else +#define HAVE_MMSG 0 +#endif + + #endif /* UV_UNIX_INTERNAL_H_ */ diff --git a/deps/uv/src/unix/linux-inotify.c b/deps/uv/src/unix/linux-inotify.c index 9b26202fb3366d..42b601adbf898a 100644 --- a/deps/uv/src/unix/linux-inotify.c +++ b/deps/uv/src/unix/linux-inotify.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -64,45 +65,17 @@ static void uv__inotify_read(uv_loop_t* loop, static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop); -static int new_inotify_fd(void) { - int err; - int fd; - - fd = uv__inotify_init1(UV__IN_NONBLOCK | UV__IN_CLOEXEC); - if (fd != -1) - return fd; - - if (errno != ENOSYS) - return UV__ERR(errno); - - fd = uv__inotify_init(); - if (fd == -1) - return UV__ERR(errno); - - err = uv__cloexec(fd, 1); - if (err == 0) - err = uv__nonblock(fd, 1); - - if (err) { - uv__close(fd); - return err; - } - - return fd; -} - - static int init_inotify(uv_loop_t* loop) { - int err; + int fd; if (loop->inotify_fd != -1) return 0; - err = new_inotify_fd(); - if (err < 0) - return err; + fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); + if (fd < 0) + return UV__ERR(errno); - loop->inotify_fd = err; + loop->inotify_fd = fd; uv__io_init(&loop->inotify_read_watcher, uv__inotify_read, loop->inotify_fd); uv__io_start(loop, &loop->inotify_read_watcher, POLLIN); @@ -186,7 +159,7 @@ static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) { if ((!w->iterating) && QUEUE_EMPTY(&w->watchers)) { /* No watchers left for this path. Clean up. */ RB_REMOVE(watcher_root, CAST(&loop->inotify_watchers), w); - uv__inotify_rm_watch(loop->inotify_fd, w->wd); + inotify_rm_watch(loop->inotify_fd, w->wd); uv__free(w); } } @@ -194,7 +167,7 @@ static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) { static void uv__inotify_read(uv_loop_t* loop, uv__io_t* dummy, unsigned int events) { - const struct uv__inotify_event* e; + const struct inotify_event* e; struct watcher_list* w; uv_fs_event_t* h; QUEUE queue; @@ -219,12 +192,12 @@ static void uv__inotify_read(uv_loop_t* loop, /* Now we have one or more inotify_event structs. */ for (p = buf; p < buf + size; p += sizeof(*e) + e->len) { - e = (const struct uv__inotify_event*)p; + e = (const struct inotify_event*) p; events = 0; - if (e->mask & (UV__IN_ATTRIB|UV__IN_MODIFY)) + if (e->mask & (IN_ATTRIB|IN_MODIFY)) events |= UV_CHANGE; - if (e->mask & ~(UV__IN_ATTRIB|UV__IN_MODIFY)) + if (e->mask & ~(IN_ATTRIB|IN_MODIFY)) events |= UV_RENAME; w = find_watcher(loop, e->wd); @@ -290,16 +263,16 @@ int uv_fs_event_start(uv_fs_event_t* handle, if (err) return err; - events = UV__IN_ATTRIB - | UV__IN_CREATE - | UV__IN_MODIFY - | UV__IN_DELETE - | UV__IN_DELETE_SELF - | UV__IN_MOVE_SELF - | UV__IN_MOVED_FROM - | UV__IN_MOVED_TO; + events = IN_ATTRIB + | IN_CREATE + | IN_MODIFY + | IN_DELETE + | IN_DELETE_SELF + | IN_MOVE_SELF + | IN_MOVED_FROM + | IN_MOVED_TO; - wd = uv__inotify_add_watch(handle->loop->inotify_fd, path, events); + wd = inotify_add_watch(handle->loop->inotify_fd, path, events); if (wd == -1) return UV__ERR(errno); diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c index 950387860f04cc..742f26ada8218c 100644 --- a/deps/uv/src/unix/linux-syscalls.c +++ b/deps/uv/src/unix/linux-syscalls.c @@ -26,19 +26,6 @@ #include #include -#if defined(__has_feature) -# if __has_feature(memory_sanitizer) -# define MSAN_ACTIVE 1 -# include -# endif -#endif - -#if defined(__i386__) -# ifndef __NR_socketcall -# define __NR_socketcall 102 -# endif -#endif - #if defined(__arm__) # if defined(__thumb__) || defined(__ARM_EABI__) # define UV_SYSCALL_BASE 0 @@ -47,86 +34,6 @@ # endif #endif /* __arm__ */ -#ifndef __NR_accept4 -# if defined(__x86_64__) -# define __NR_accept4 288 -# elif defined(__i386__) - /* Nothing. Handled through socketcall(). */ -# elif defined(__arm__) -# define __NR_accept4 (UV_SYSCALL_BASE + 366) -# endif -#endif /* __NR_accept4 */ - -#ifndef __NR_eventfd -# if defined(__x86_64__) -# define __NR_eventfd 284 -# elif defined(__i386__) -# define __NR_eventfd 323 -# elif defined(__arm__) -# define __NR_eventfd (UV_SYSCALL_BASE + 351) -# endif -#endif /* __NR_eventfd */ - -#ifndef __NR_eventfd2 -# if defined(__x86_64__) -# define __NR_eventfd2 290 -# elif defined(__i386__) -# define __NR_eventfd2 328 -# elif defined(__arm__) -# define __NR_eventfd2 (UV_SYSCALL_BASE + 356) -# endif -#endif /* __NR_eventfd2 */ - -#ifndef __NR_inotify_init -# if defined(__x86_64__) -# define __NR_inotify_init 253 -# elif defined(__i386__) -# define __NR_inotify_init 291 -# elif defined(__arm__) -# define __NR_inotify_init (UV_SYSCALL_BASE + 316) -# endif -#endif /* __NR_inotify_init */ - -#ifndef __NR_inotify_init1 -# if defined(__x86_64__) -# define __NR_inotify_init1 294 -# elif defined(__i386__) -# define __NR_inotify_init1 332 -# elif defined(__arm__) -# define __NR_inotify_init1 (UV_SYSCALL_BASE + 360) -# endif -#endif /* __NR_inotify_init1 */ - -#ifndef __NR_inotify_add_watch -# if defined(__x86_64__) -# define __NR_inotify_add_watch 254 -# elif defined(__i386__) -# define __NR_inotify_add_watch 292 -# elif defined(__arm__) -# define __NR_inotify_add_watch (UV_SYSCALL_BASE + 317) -# endif -#endif /* __NR_inotify_add_watch */ - -#ifndef __NR_inotify_rm_watch -# if defined(__x86_64__) -# define __NR_inotify_rm_watch 255 -# elif defined(__i386__) -# define __NR_inotify_rm_watch 293 -# elif defined(__arm__) -# define __NR_inotify_rm_watch (UV_SYSCALL_BASE + 318) -# endif -#endif /* __NR_inotify_rm_watch */ - -#ifndef __NR_pipe2 -# if defined(__x86_64__) -# define __NR_pipe2 293 -# elif defined(__i386__) -# define __NR_pipe2 331 -# elif defined(__arm__) -# define __NR_pipe2 (UV_SYSCALL_BASE + 359) -# endif -#endif /* __NR_pipe2 */ - #ifndef __NR_recvmmsg # if defined(__x86_64__) # define __NR_recvmmsg 299 @@ -219,103 +126,7 @@ # endif #endif /* __NR_getrandom */ -int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) { -#if defined(__i386__) - unsigned long args[4]; - int r; - - args[0] = (unsigned long) fd; - args[1] = (unsigned long) addr; - args[2] = (unsigned long) addrlen; - args[3] = (unsigned long) flags; - - r = syscall(__NR_socketcall, 18 /* SYS_ACCEPT4 */, args); - - /* socketcall() raises EINVAL when SYS_ACCEPT4 is not supported but so does - * a bad flags argument. Try to distinguish between the two cases. - */ - if (r == -1) - if (errno == EINVAL) - if ((flags & ~(UV__SOCK_CLOEXEC|UV__SOCK_NONBLOCK)) == 0) - errno = ENOSYS; - - return r; -#elif defined(__NR_accept4) - return syscall(__NR_accept4, fd, addr, addrlen, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__eventfd(unsigned int count) { -#if defined(__NR_eventfd) - return syscall(__NR_eventfd, count); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__eventfd2(unsigned int count, int flags) { -#if defined(__NR_eventfd2) - return syscall(__NR_eventfd2, count, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__inotify_init(void) { -#if defined(__NR_inotify_init) - return syscall(__NR_inotify_init); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__inotify_init1(int flags) { -#if defined(__NR_inotify_init1) - return syscall(__NR_inotify_init1, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__inotify_add_watch(int fd, const char* path, uint32_t mask) { -#if defined(__NR_inotify_add_watch) - return syscall(__NR_inotify_add_watch, fd, path, mask); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__inotify_rm_watch(int fd, int32_t wd) { -#if defined(__NR_inotify_rm_watch) - return syscall(__NR_inotify_rm_watch, fd, wd); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__pipe2(int pipefd[2], int flags) { -#if defined(__NR_pipe2) - int result; - result = syscall(__NR_pipe2, pipefd, flags); -#if MSAN_ACTIVE - if (!result) - __msan_unpoison(pipefd, sizeof(int[2])); -#endif - return result; -#else - return errno = ENOSYS, -1; -#endif -} - +struct uv__mmsghdr; int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, diff --git a/deps/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h index b7729b82aea9ba..2e8fa2a51979c6 100644 --- a/deps/uv/src/unix/linux-syscalls.h +++ b/deps/uv/src/unix/linux-syscalls.h @@ -31,55 +31,6 @@ #include #include -#if defined(__alpha__) -# define UV__O_CLOEXEC 0x200000 -#elif defined(__hppa__) -# define UV__O_CLOEXEC 0x200000 -#elif defined(__sparc__) -# define UV__O_CLOEXEC 0x400000 -#else -# define UV__O_CLOEXEC 0x80000 -#endif - -#if defined(__alpha__) -# define UV__O_NONBLOCK 0x4 -#elif defined(__hppa__) -# define UV__O_NONBLOCK O_NONBLOCK -#elif defined(__mips__) -# define UV__O_NONBLOCK 0x80 -#elif defined(__sparc__) -# define UV__O_NONBLOCK 0x4000 -#else -# define UV__O_NONBLOCK 0x800 -#endif - -#define UV__EFD_CLOEXEC UV__O_CLOEXEC -#define UV__EFD_NONBLOCK UV__O_NONBLOCK - -#define UV__IN_CLOEXEC UV__O_CLOEXEC -#define UV__IN_NONBLOCK UV__O_NONBLOCK - -#define UV__SOCK_CLOEXEC UV__O_CLOEXEC -#if defined(SOCK_NONBLOCK) -# define UV__SOCK_NONBLOCK SOCK_NONBLOCK -#else -# define UV__SOCK_NONBLOCK UV__O_NONBLOCK -#endif - -/* inotify flags */ -#define UV__IN_ACCESS 0x001 -#define UV__IN_MODIFY 0x002 -#define UV__IN_ATTRIB 0x004 -#define UV__IN_CLOSE_WRITE 0x008 -#define UV__IN_CLOSE_NOWRITE 0x010 -#define UV__IN_OPEN 0x020 -#define UV__IN_MOVED_FROM 0x040 -#define UV__IN_MOVED_TO 0x080 -#define UV__IN_CREATE 0x100 -#define UV__IN_DELETE 0x200 -#define UV__IN_DELETE_SELF 0x400 -#define UV__IN_MOVE_SELF 0x800 - struct uv__statx_timestamp { int64_t tv_sec; uint32_t tv_nsec; @@ -110,36 +61,6 @@ struct uv__statx { uint64_t unused1[14]; }; -struct uv__inotify_event { - int32_t wd; - uint32_t mask; - uint32_t cookie; - uint32_t len; - /* char name[0]; */ -}; - -struct uv__mmsghdr { - struct msghdr msg_hdr; - unsigned int msg_len; -}; - -int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags); -int uv__eventfd(unsigned int count); -int uv__eventfd2(unsigned int count, int flags); -int uv__inotify_init(void); -int uv__inotify_init1(int flags); -int uv__inotify_add_watch(int fd, const char* path, uint32_t mask); -int uv__inotify_rm_watch(int fd, int32_t wd); -int uv__pipe2(int pipefd[2], int flags); -int uv__recvmmsg(int fd, - struct uv__mmsghdr* mmsg, - unsigned int vlen, - unsigned int flags, - struct timespec* timeout); -int uv__sendmmsg(int fd, - struct uv__mmsghdr* mmsg, - unsigned int vlen, - unsigned int flags); ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset); ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset); int uv__dup3(int oldfd, int newfd, int flags); diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c index 5ba0db022e4a46..f32a94df38765f 100644 --- a/deps/uv/src/unix/openbsd.c +++ b/deps/uv/src/unix/openbsd.c @@ -61,7 +61,6 @@ void uv_loadavg(double avg[3]) { int uv_exepath(char* buffer, size_t* size) { int mib[4]; char **argsbuf = NULL; - char **argsbuf_tmp; size_t argsbuf_size = 100U; size_t exepath_size; pid_t mypid; @@ -73,10 +72,9 @@ int uv_exepath(char* buffer, size_t* size) { mypid = getpid(); for (;;) { err = UV_ENOMEM; - argsbuf_tmp = uv__realloc(argsbuf, argsbuf_size); - if (argsbuf_tmp == NULL) + argsbuf = uv__reallocf(argsbuf, argsbuf_size); + if (argsbuf == NULL) goto out; - argsbuf = argsbuf_tmp; mib[0] = CTL_KERN; mib[1] = KERN_PROC_ARGS; mib[2] = mypid; @@ -185,7 +183,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { char model[512]; int numcpus = 1; int which[] = {CTL_HW,HW_MODEL}; - int percpu[] = {CTL_HW,HW_CPUSPEED,0}; + int percpu[] = {CTL_KERN,KERN_CPTIME2,0}; size_t size; int i, j; uv_cpu_info_t* cpu_info; @@ -206,17 +204,15 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { i = 0; *count = numcpus; + which[1] = HW_CPUSPEED; size = sizeof(cpuspeed); - if (sysctl(which, ARRAY_SIZE(percpu), &cpuspeed, &size, NULL, 0)) + if (sysctl(which, ARRAY_SIZE(which), &cpuspeed, &size, NULL, 0)) goto error; size = sizeof(info); - percpu[0] = CTL_KERN; - percpu[1] = KERN_CPTIME2; for (i = 0; i < numcpus; i++) { percpu[2] = i; - size = sizeof(info); - if (sysctl(which, ARRAY_SIZE(percpu), &info, &size, NULL, 0)) + if (sysctl(percpu, ARRAY_SIZE(percpu), &info, &size, NULL, 0)) goto error; cpu_info = &(*cpu_infos)[i]; diff --git a/deps/uv/src/unix/os390-syscalls.c b/deps/uv/src/unix/os390-syscalls.c index d9abdebaeeda59..424cc486a86fa3 100644 --- a/deps/uv/src/unix/os390-syscalls.c +++ b/deps/uv/src/unix/os390-syscalls.c @@ -43,6 +43,7 @@ int scandir(const char* maindir, struct dirent*** namelist, int (*compar)(const struct dirent**, const struct dirent **)) { struct dirent** nl; + struct dirent** nl_copy; struct dirent* dirent; unsigned count; size_t allocated; @@ -62,19 +63,17 @@ int scandir(const char* maindir, struct dirent*** namelist, if (!filter || filter(dirent)) { struct dirent* copy; copy = uv__malloc(sizeof(*copy)); - if (!copy) { - while (count) { - dirent = nl[--count]; - uv__free(dirent); - } - uv__free(nl); - closedir(mdir); - errno = ENOMEM; - return -1; - } + if (!copy) + goto error; memcpy(copy, dirent, sizeof(*copy)); - nl = uv__realloc(nl, sizeof(*copy) * (count + 1)); + nl_copy = uv__realloc(nl, sizeof(*copy) * (count + 1)); + if (nl_copy == NULL) { + uv__free(copy); + goto error; + } + + nl = nl_copy; nl[count++] = copy; } } @@ -86,6 +85,16 @@ int scandir(const char* maindir, struct dirent*** namelist, *namelist = nl; return count; + +error: + while (count > 0) { + dirent = nl[--count]; + uv__free(dirent); + } + uv__free(nl); + closedir(mdir); + errno = ENOMEM; + return -1; } @@ -119,7 +128,7 @@ static void maybe_resize(uv__os390_epoll* lst, unsigned int len) { } newsize = next_power_of_two(len); - newlst = uv__realloc(lst->items, newsize * sizeof(lst->items[0])); + newlst = uv__reallocf(lst->items, newsize * sizeof(lst->items[0])); if (newlst == NULL) abort(); @@ -269,6 +278,8 @@ int epoll_ctl(uv__os390_epoll* lst, return 0; } +#define EP_MAX_PFDS (ULONG_MAX / sizeof(struct pollfd)) +#define EP_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event)) int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, int maxevents, int timeout) { @@ -277,18 +288,41 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, int pollret; int reventcount; int nevents; + struct pollfd msg_fd; + int i; + + if (!lst || !lst->items || !events) { + errno = EFAULT; + return -1; + } - _SET_FDS_MSGS(size, 1, lst->size - 1); + if (lst->size > EP_MAX_PFDS) { + errno = EINVAL; + return -1; + } + + if (maxevents <= 0 || maxevents > EP_MAX_EVENTS) { + errno = EINVAL; + return -1; + } + + if (lst->size > 0) + _SET_FDS_MSGS(size, 1, lst->size - 1); + else + _SET_FDS_MSGS(size, 0, 0); pfds = lst->items; pollret = poll(pfds, size, timeout); if (pollret <= 0) return pollret; + assert(lst->size > 0); + pollret = _NFDS(pollret) + _NMSGS(pollret); reventcount = 0; nevents = 0; - for (int i = 0; + msg_fd = pfds[lst->size - 1]; + for (i = 0; i < lst->size && i < maxevents && reventcount < pollret; ++i) { struct epoll_event ev; struct pollfd* pfd; @@ -299,6 +333,7 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, ev.fd = pfd->fd; ev.events = pfd->revents; + ev.is_msg = 0; if (pfd->revents & POLLIN && pfd->revents & POLLOUT) reventcount += 2; else if (pfd->revents & (POLLIN | POLLOUT)) @@ -308,6 +343,10 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, events[nevents++] = ev; } + if (msg_fd.revents != 0 && msg_fd.fd != -1) + if (i == lst->size) + events[nevents - 1].is_msg = 1; + return nevents; } @@ -369,10 +408,12 @@ int nanosleep(const struct timespec* req, struct timespec* rem) { * Don't leak EAGAIN, that just means the timeout expired. */ if (rv == -1) - if (err != EAGAIN) + if (err == EAGAIN) + rv = 0; + else errno = err; - if (rem != NULL && (rv == 0 || err == EINTR || err == EAGAIN)) { + if (rem != NULL && (rv == 0 || err == EINTR)) { rem->tv_nsec = nanorem; rem->tv_sec = secrem; } @@ -517,3 +558,28 @@ size_t strnlen(const char* str, size_t maxlen) { else return p - str; } + + +int sem_init(UV_PLATFORM_SEM_T* semid, int pshared, unsigned int value) { + UNREACHABLE(); +} + + +int sem_destroy(UV_PLATFORM_SEM_T* semid) { + UNREACHABLE(); +} + + +int sem_post(UV_PLATFORM_SEM_T* semid) { + UNREACHABLE(); +} + + +int sem_trywait(UV_PLATFORM_SEM_T* semid) { + UNREACHABLE(); +} + + +int sem_wait(UV_PLATFORM_SEM_T* semid) { + UNREACHABLE(); +} diff --git a/deps/uv/src/unix/os390-syscalls.h b/deps/uv/src/unix/os390-syscalls.h index ea599107b30281..86416bbc551e19 100644 --- a/deps/uv/src/unix/os390-syscalls.h +++ b/deps/uv/src/unix/os390-syscalls.h @@ -40,6 +40,7 @@ struct epoll_event { int events; int fd; + int is_msg; }; typedef struct { @@ -64,5 +65,10 @@ int scandir(const char* maindir, struct dirent*** namelist, char *mkdtemp(char* path); ssize_t os390_readlink(const char* path, char* buf, size_t len); size_t strnlen(const char* str, size_t maxlen); +int sem_init(UV_PLATFORM_SEM_T* semid, int pshared, unsigned int value); +int sem_destroy(UV_PLATFORM_SEM_T* semid); +int sem_post(UV_PLATFORM_SEM_T* semid); +int sem_trywait(UV_PLATFORM_SEM_T* semid); +int sem_wait(UV_PLATFORM_SEM_T* semid); #endif /* UV_OS390_SYSCALL_H_ */ diff --git a/deps/uv/src/unix/os390.c b/deps/uv/src/unix/os390.c index a7305006c1756d..dce169b9fb4268 100644 --- a/deps/uv/src/unix/os390.c +++ b/deps/uv/src/unix/os390.c @@ -923,7 +923,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { continue; ep = loop->ep; - if (fd == ep->msg_queue) { + if (pe->is_msg) { os390_message_queue_handler(ep); continue; } diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c index cdf24fa9763cb1..040d57817fa5b1 100644 --- a/deps/uv/src/unix/pipe.c +++ b/deps/uv/src/unix/pipe.c @@ -95,8 +95,12 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { if (uv__stream_fd(handle) == -1) return UV_EINVAL; -#if defined(__MVS__) + if (handle->ipc) + return UV_EINVAL; + +#if defined(__MVS__) || defined(__PASE__) /* On zOS, backlog=0 has undefined behaviour */ + /* On IBMi PASE, backlog=0 leads to "Connection refused" error */ if (backlog == 0) backlog = 1; else if (backlog < 0) diff --git a/deps/uv/src/unix/posix-poll.c b/deps/uv/src/unix/posix-poll.c index a3b9f2196d5872..766e83205d053f 100644 --- a/deps/uv/src/unix/posix-poll.c +++ b/deps/uv/src/unix/posix-poll.c @@ -61,7 +61,7 @@ static void uv__pollfds_maybe_resize(uv_loop_t* loop) { return; n = loop->poll_fds_size ? loop->poll_fds_size * 2 : 64; - p = uv__realloc(loop->poll_fds, n * sizeof(*loop->poll_fds)); + p = uv__reallocf(loop->poll_fds, n * sizeof(*loop->poll_fds)); if (p == NULL) abort(); diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c index bb6b76c9fa7005..b021aaeba87d0b 100644 --- a/deps/uv/src/unix/process.c +++ b/deps/uv/src/unix/process.c @@ -112,72 +112,64 @@ static void uv__chld(uv_signal_t* handle, int signum) { } -int uv__make_socketpair(int fds[2], int flags) { -#if defined(__linux__) - static int no_cloexec; - - if (no_cloexec) - goto skip; - - if (socketpair(AF_UNIX, SOCK_STREAM | UV__SOCK_CLOEXEC | flags, 0, fds) == 0) - return 0; - - /* Retry on EINVAL, it means SOCK_CLOEXEC is not supported. - * Anything else is a genuine error. - */ - if (errno != EINVAL) +static int uv__make_socketpair(int fds[2]) { +#if defined(__FreeBSD__) || defined(__linux__) + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds)) return UV__ERR(errno); - no_cloexec = 1; - -skip: -#endif + return 0; +#else + int err; if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) return UV__ERR(errno); - uv__cloexec(fds[0], 1); - uv__cloexec(fds[1], 1); + err = uv__cloexec(fds[0], 1); + if (err == 0) + err = uv__cloexec(fds[1], 1); - if (flags & UV__F_NONBLOCK) { - uv__nonblock(fds[0], 1); - uv__nonblock(fds[1], 1); + if (err != 0) { + uv__close(fds[0]); + uv__close(fds[1]); + return UV__ERR(errno); } return 0; +#endif } int uv__make_pipe(int fds[2], int flags) { -#if defined(__linux__) - static int no_pipe2; - - if (no_pipe2) - goto skip; - - if (uv__pipe2(fds, flags | UV__O_CLOEXEC) == 0) - return 0; - - if (errno != ENOSYS) +#if defined(__FreeBSD__) || defined(__linux__) + if (pipe2(fds, flags | O_CLOEXEC)) return UV__ERR(errno); - no_pipe2 = 1; - -skip: -#endif - + return 0; +#else if (pipe(fds)) return UV__ERR(errno); - uv__cloexec(fds[0], 1); - uv__cloexec(fds[1], 1); + if (uv__cloexec(fds[0], 1)) + goto fail; + + if (uv__cloexec(fds[1], 1)) + goto fail; if (flags & UV__F_NONBLOCK) { - uv__nonblock(fds[0], 1); - uv__nonblock(fds[1], 1); + if (uv__nonblock(fds[0], 1)) + goto fail; + + if (uv__nonblock(fds[1], 1)) + goto fail; } return 0; + +fail: + uv__close(fds[0]); + uv__close(fds[1]); + return UV__ERR(errno); +#endif } @@ -200,7 +192,7 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) { if (container->data.stream->type != UV_NAMED_PIPE) return UV_EINVAL; else - return uv__make_socketpair(fds, 0); + return uv__make_socketpair(fds); case UV_INHERIT_FD: case UV_INHERIT_STREAM: diff --git a/deps/uv/src/unix/proctitle.c b/deps/uv/src/unix/proctitle.c index 1a8c7a7090e8a6..d124d3c7fcfee0 100644 --- a/deps/uv/src/unix/proctitle.c +++ b/deps/uv/src/unix/proctitle.c @@ -24,17 +24,19 @@ #include #include +struct uv__process_title { + char* str; + size_t len; /* Length of the current process title. */ + size_t cap; /* Maximum capacity. Computed once in uv_setup_args(). */ +}; + extern void uv__set_process_title(const char* title); static uv_mutex_t process_title_mutex; static uv_once_t process_title_mutex_once = UV_ONCE_INIT; +static struct uv__process_title process_title; static void* args_mem; -static struct { - char* str; - size_t len; -} process_title; - static void init_process_title_mutex_once(void) { uv_mutex_init(&process_title_mutex); @@ -42,6 +44,7 @@ static void init_process_title_mutex_once(void) { char** uv_setup_args(int argc, char** argv) { + struct uv__process_title pt; char** new_argv; size_t size; char* s; @@ -50,53 +53,69 @@ char** uv_setup_args(int argc, char** argv) { if (argc <= 0) return argv; + pt.str = argv[0]; + pt.len = strlen(argv[0]); + pt.cap = pt.len + 1; + /* Calculate how much memory we need for the argv strings. */ - size = 0; - for (i = 0; i < argc; i++) + size = pt.cap; + for (i = 1; i < argc; i++) size += strlen(argv[i]) + 1; -#if defined(__MVS__) - /* argv is not adjacent. So just use argv[0] */ - process_title.str = argv[0]; - process_title.len = strlen(argv[0]); -#else - process_title.str = argv[0]; - process_title.len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[0]; - assert(process_title.len + 1 == size); /* argv memory should be adjacent. */ -#endif - /* Add space for the argv pointers. */ size += (argc + 1) * sizeof(char*); new_argv = uv__malloc(size); if (new_argv == NULL) return argv; - args_mem = new_argv; /* Copy over the strings and set up the pointer table. */ + i = 0; s = (char*) &new_argv[argc + 1]; - for (i = 0; i < argc; i++) { + size = pt.cap; + goto loop; + + for (/* empty */; i < argc; i++) { size = strlen(argv[i]) + 1; + loop: memcpy(s, argv[i], size); new_argv[i] = s; s += size; } new_argv[i] = NULL; + /* argv is not adjacent on z/os, we use just argv[0] on that platform. */ +#ifndef __MVS__ + pt.cap = argv[i - 1] + size - argv[0]; +#endif + + args_mem = new_argv; + process_title = pt; + return new_argv; } int uv_set_process_title(const char* title) { + struct uv__process_title* pt; + size_t len; + + pt = &process_title; + len = strlen(title); + uv_once(&process_title_mutex_once, init_process_title_mutex_once); uv_mutex_lock(&process_title_mutex); - if (process_title.len != 0) { - /* No need to terminate, byte after is always '\0'. */ - strncpy(process_title.str, title, process_title.len); - uv__set_process_title(title); + if (len >= pt->cap) { + len = 0; + if (pt->cap > 0) + len = pt->cap - 1; } + memcpy(pt->str, title, len); + memset(pt->str + len, '\0', pt->cap - len); + pt->len = len; + uv_mutex_unlock(&process_title_mutex); return 0; diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c index ba8fcc204f80a1..1e7e8ac574dfa4 100644 --- a/deps/uv/src/unix/signal.c +++ b/deps/uv/src/unix/signal.c @@ -331,16 +331,7 @@ int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) { void uv__signal_close(uv_signal_t* handle) { - uv__signal_stop(handle); - - /* If there are any caught signals "trapped" in the signal pipe, we can't - * call the close callback yet. Otherwise, add the handle to the finish_close - * queue. - */ - if (handle->caught_signals == handle->dispatched_signals) { - uv__make_close_pending((uv_handle_t*) handle); - } } @@ -472,17 +463,6 @@ static void uv__signal_event(uv_loop_t* loop, if (handle->flags & UV_SIGNAL_ONE_SHOT) uv__signal_stop(handle); - - /* If uv_close was called while there were caught signals that were not - * yet dispatched, the uv__finish_close was deferred. Make close pending - * now if this has happened. - */ - if (handle->caught_signals == handle->dispatched_signals) { - if (handle->signum == 0) - uv__handle_stop(handle); - if (handle->flags & UV_HANDLE_CLOSING) - uv__make_close_pending((uv_handle_t*) handle); - } } bytes -= end; @@ -572,6 +552,5 @@ static void uv__signal_stop(uv_signal_t* handle) { uv__signal_unlock_and_unblock(&saved_sigmask); handle->signum = 0; - if (handle->caught_signals == handle->dispatched_signals) - uv__handle_stop(handle); + uv__handle_stop(handle); } diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c index fa660f1381315e..d47e9433dbbd83 100644 --- a/deps/uv/src/unix/tcp.c +++ b/deps/uv/src/unix/tcp.c @@ -379,8 +379,16 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay) { return UV__ERR(errno); #ifdef TCP_KEEPIDLE - if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay))) - return UV__ERR(errno); + if (on) { + int intvl = 1; /* 1 second; same as default on Win32 */ + int cnt = 10; /* 10 retries; same as hardcoded on Win32 */ + if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay))) + return UV__ERR(errno); + if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl))) + return UV__ERR(errno); + if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt))) + return UV__ERR(errno); + } #endif /* Solaris/SmartOS, if you don't support keep-alive, diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c index ff7d3b17f9303d..6f60abaadb02ef 100644 --- a/deps/uv/src/unix/tty.c +++ b/deps/uv/src/unix/tty.c @@ -34,6 +34,34 @@ #define IMAXBEL 0 #endif +#if defined(__PASE__) +/* On IBM i PASE, for better compatibility with running interactive programs in + * a 5250 environment, isatty() will return true for the stdin/stdout/stderr + * streams created by QSH/QP2TERM. + * + * For more, see docs on PASE_STDIO_ISATTY in + * https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/apis/pase_environ.htm + * + * This behavior causes problems for Node as it expects that if isatty() returns + * true that TTY ioctls will be supported by that fd (which is not an + * unreasonable expectation) and when they don't it crashes with assertion + * errors. + * + * Here, we create our own version of isatty() that uses ioctl() to identify + * whether the fd is *really* a TTY or not. + */ +static int isreallyatty(int file) { + int rc; + + rc = !ioctl(file, TXISATTY + 0x81, NULL); + if (!rc && errno != EBADF) + errno = ENOTTY; + + return rc; +} +#define isatty(fd) isreallyatty(fd) +#endif + static int orig_termios_fd = -1; static struct termios orig_termios; static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER; @@ -293,14 +321,7 @@ uv_handle_type uv_guess_handle(uv_file file) { if (file < 0) return UV_UNKNOWN_HANDLE; -#if defined(__PASE__) - /* On IBMi PASE isatty() always returns true for stdin, stdout and stderr. - * Use ioctl() instead to identify whether it's actually a TTY. - */ - if (!ioctl(file, TXISATTY + 0x81, NULL) || errno != ENOTTY) -#else if (isatty(file)) -#endif return UV_TTY; if (fstat(file, &s)) diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index 98215f7e1d212b..3aa11c5beeb4ad 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -32,6 +32,8 @@ #endif #include +#define UV__UDP_DGRAM_MAXSIZE (64 * 1024) + #if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP) # define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP #endif @@ -49,6 +51,36 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, int domain, unsigned int flags); +#if HAVE_MMSG + +#define UV__MMSG_MAXWIDTH 20 + +static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf); +static void uv__udp_sendmmsg(uv_udp_t* handle); + +static int uv__recvmmsg_avail; +static int uv__sendmmsg_avail; +static uv_once_t once = UV_ONCE_INIT; + +static void uv__udp_mmsg_init(void) { + int ret; + int s; + s = uv__socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) + return; + ret = uv__sendmmsg(s, NULL, 0, 0); + if (ret == 0 || errno != ENOSYS) { + uv__sendmmsg_avail = 1; + uv__recvmmsg_avail = 1; + } else { + ret = uv__recvmmsg(s, NULL, 0, 0, NULL); + if (ret == 0 || errno != ENOSYS) + uv__recvmmsg_avail = 1; + } + uv__close(s); +} + +#endif void uv__udp_close(uv_udp_t* handle) { uv__io_close(handle->loop, &handle->io_watcher); @@ -148,6 +180,61 @@ static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents) { } } +#if HAVE_MMSG +static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf) { + struct sockaddr_in6 peers[UV__MMSG_MAXWIDTH]; + struct iovec iov[UV__MMSG_MAXWIDTH]; + struct uv__mmsghdr msgs[UV__MMSG_MAXWIDTH]; + ssize_t nread; + uv_buf_t chunk_buf; + size_t chunks; + int flags; + size_t k; + + /* prepare structures for recvmmsg */ + chunks = buf->len / UV__UDP_DGRAM_MAXSIZE; + if (chunks > ARRAY_SIZE(iov)) + chunks = ARRAY_SIZE(iov); + for (k = 0; k < chunks; ++k) { + iov[k].iov_base = buf->base + k * UV__UDP_DGRAM_MAXSIZE; + iov[k].iov_len = UV__UDP_DGRAM_MAXSIZE; + msgs[k].msg_hdr.msg_iov = iov + k; + msgs[k].msg_hdr.msg_iovlen = 1; + msgs[k].msg_hdr.msg_name = peers + k; + msgs[k].msg_hdr.msg_namelen = sizeof(peers[0]); + } + + do + nread = uv__recvmmsg(handle->io_watcher.fd, msgs, chunks, 0, NULL); + while (nread == -1 && errno == EINTR); + + if (nread < 1) { + if (nread == 0 || errno == EAGAIN || errno == EWOULDBLOCK) + handle->recv_cb(handle, 0, buf, NULL, 0); + else + handle->recv_cb(handle, UV__ERR(errno), buf, NULL, 0); + } else { + /* pass each chunk to the application */ + for (k = 0; k < (size_t) nread && handle->recv_cb != NULL; k++) { + flags = UV_UDP_MMSG_CHUNK; + if (msgs[k].msg_hdr.msg_flags & MSG_TRUNC) + flags |= UV_UDP_PARTIAL; + + chunk_buf = uv_buf_init(iov[k].iov_base, iov[k].iov_len); + handle->recv_cb(handle, + msgs[k].msg_len, + &chunk_buf, + msgs[k].msg_hdr.msg_name, + flags); + } + + /* one last callback so the original buffer is freed */ + if (handle->recv_cb != NULL) + handle->recv_cb(handle, 0, buf, NULL, 0); + } + return nread; +} +#endif static void uv__udp_recvmsg(uv_udp_t* handle) { struct sockaddr_storage peer; @@ -167,13 +254,25 @@ static void uv__udp_recvmsg(uv_udp_t* handle) { do { buf = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, 64 * 1024, &buf); + handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &buf); if (buf.base == NULL || buf.len == 0) { handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0); return; } assert(buf.base != NULL); +#if HAVE_MMSG + if (handle->flags & UV_HANDLE_UDP_RECVMMSG) { + uv_once(&once, uv__udp_mmsg_init); + if (uv__recvmmsg_avail) { + nread = uv__udp_recvmmsg(handle, &buf); + if (nread > 0) + count -= nread; + continue; + } + } +#endif + memset(&h, 0, sizeof(h)); memset(&peer, 0, sizeof(peer)); h.msg_name = &peer; @@ -199,21 +298,120 @@ static void uv__udp_recvmsg(uv_udp_t* handle) { handle->recv_cb(handle, nread, &buf, (const struct sockaddr*) &peer, flags); } + count--; } /* recv_cb callback may decide to pause or close the handle */ while (nread != -1 - && count-- > 0 + && count > 0 && handle->io_watcher.fd != -1 && handle->recv_cb != NULL); } +#if HAVE_MMSG +static void uv__udp_sendmmsg(uv_udp_t* handle) { + uv_udp_send_t* req; + struct uv__mmsghdr h[UV__MMSG_MAXWIDTH]; + struct uv__mmsghdr *p; + QUEUE* q; + ssize_t npkts; + size_t pkts; + size_t i; + + if (QUEUE_EMPTY(&handle->write_queue)) + return; + +write_queue_drain: + for (pkts = 0, q = QUEUE_HEAD(&handle->write_queue); + pkts < UV__MMSG_MAXWIDTH && q != &handle->write_queue; + ++pkts, q = QUEUE_HEAD(q)) { + assert(q != NULL); + req = QUEUE_DATA(q, uv_udp_send_t, queue); + assert(req != NULL); + + p = &h[pkts]; + memset(p, 0, sizeof(*p)); + if (req->addr.ss_family == AF_UNSPEC) { + p->msg_hdr.msg_name = NULL; + p->msg_hdr.msg_namelen = 0; + } else { + p->msg_hdr.msg_name = &req->addr; + if (req->addr.ss_family == AF_INET6) + p->msg_hdr.msg_namelen = sizeof(struct sockaddr_in6); + else if (req->addr.ss_family == AF_INET) + p->msg_hdr.msg_namelen = sizeof(struct sockaddr_in); + else if (req->addr.ss_family == AF_UNIX) + p->msg_hdr.msg_namelen = sizeof(struct sockaddr_un); + else { + assert(0 && "unsupported address family"); + abort(); + } + } + h[pkts].msg_hdr.msg_iov = (struct iovec*) req->bufs; + h[pkts].msg_hdr.msg_iovlen = req->nbufs; + } + + do + npkts = uv__sendmmsg(handle->io_watcher.fd, h, pkts, 0); + while (npkts == -1 && errno == EINTR); + + if (npkts < 1) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS) + return; + for (i = 0, q = QUEUE_HEAD(&handle->write_queue); + i < pkts && q != &handle->write_queue; + ++i, q = QUEUE_HEAD(q)) { + assert(q != NULL); + req = QUEUE_DATA(q, uv_udp_send_t, queue); + assert(req != NULL); + + req->status = UV__ERR(errno); + QUEUE_REMOVE(&req->queue); + QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue); + } + uv__io_feed(handle->loop, &handle->io_watcher); + return; + } + + for (i = 0, q = QUEUE_HEAD(&handle->write_queue); + i < pkts && q != &handle->write_queue; + ++i, q = QUEUE_HEAD(&handle->write_queue)) { + assert(q != NULL); + req = QUEUE_DATA(q, uv_udp_send_t, queue); + assert(req != NULL); + + req->status = req->bufs[0].len; + + /* Sending a datagram is an atomic operation: either all data + * is written or nothing is (and EMSGSIZE is raised). That is + * why we don't handle partial writes. Just pop the request + * off the write queue and onto the completed queue, done. + */ + QUEUE_REMOVE(&req->queue); + QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue); + } + + /* couldn't batch everything, continue sending (jump to avoid stack growth) */ + if (!QUEUE_EMPTY(&handle->write_queue)) + goto write_queue_drain; + uv__io_feed(handle->loop, &handle->io_watcher); + return; +} +#endif static void uv__udp_sendmsg(uv_udp_t* handle) { uv_udp_send_t* req; - QUEUE* q; struct msghdr h; + QUEUE* q; ssize_t size; +#if HAVE_MMSG + uv_once(&once, uv__udp_mmsg_init); + if (uv__sendmmsg_avail) { + uv__udp_sendmmsg(handle); + return; + } +#endif + while (!QUEUE_EMPTY(&handle->write_queue)) { q = QUEUE_HEAD(&handle->write_queue); assert(q != NULL); @@ -263,7 +461,6 @@ static void uv__udp_sendmsg(uv_udp_t* handle) { } } - /* On the BSDs, SO_REUSEPORT implies SO_REUSEADDR but with some additional * refinements for programs that use multicast. * @@ -653,7 +850,7 @@ static int uv__udp_set_membership6(uv_udp_t* handle, } -#if !defined(__OpenBSD__) && !defined(__NetBSD__) +#if !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__ANDROID__) static int uv__udp_set_source_membership4(uv_udp_t* handle, const struct sockaddr_in* multicast_addr, const char* interface_addr, @@ -750,6 +947,7 @@ static int uv__udp_set_source_membership6(uv_udp_t* handle, int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) { int domain; int err; + int extra_flags; int fd; /* Use the lower 8 bits for the domain */ @@ -757,7 +955,9 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) { if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC) return UV_EINVAL; - if (flags & ~0xFF) + /* Use the higher bits for extra flags */ + extra_flags = flags & ~0xFF; + if (extra_flags & ~UV_UDP_RECVMMSG) return UV_EINVAL; if (domain != AF_UNSPEC) { @@ -778,6 +978,9 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) { QUEUE_INIT(&handle->write_queue); QUEUE_INIT(&handle->write_completed_queue); + if (extra_flags & UV_UDP_RECVMMSG) + handle->flags |= UV_HANDLE_UDP_RECVMMSG; + return 0; } @@ -842,7 +1045,7 @@ int uv_udp_set_source_membership(uv_udp_t* handle, const char* interface_addr, const char* source_addr, uv_membership membership) { -#if !defined(__OpenBSD__) && !defined(__NetBSD__) +#if !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__ANDROID__) int err; struct sockaddr_storage mcast_addr; struct sockaddr_in* mcast_addr4; @@ -870,7 +1073,7 @@ int uv_udp_set_source_membership(uv_udp_t* handle, src_addr6, membership); } - + err = uv_ip4_addr(source_addr, 0, src_addr4); if (err) return err; @@ -889,7 +1092,7 @@ static int uv__setsockopt(uv_udp_t* handle, int option4, int option6, const void* val, - size_t size) { + socklen_t size) { int r; if (handle->flags & UV_HANDLE_IPV6) @@ -1012,7 +1215,7 @@ int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) { * and use the general uv__setsockopt_maybe_char call otherwise. */ #if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \ - defined(__MVS__) + defined(__MVS__) if (handle->flags & UV_HANDLE_IPV6) return uv__setsockopt(handle, IP_MULTICAST_LOOP, diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index cec4ac6281b91b..5cb1a8c898f7ae 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -100,6 +100,17 @@ void* uv__realloc(void* ptr, size_t size) { return NULL; } +void* uv__reallocf(void* ptr, size_t size) { + void* newptr; + + newptr = uv__realloc(ptr, size); + if (newptr == NULL) + if (size > 0) + uv__free(ptr); + + return newptr; +} + int uv_replace_allocator(uv_malloc_func malloc_func, uv_realloc_func realloc_func, uv_calloc_func calloc_func, diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index f788161c3955ed..f08fb8ae091e72 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -104,6 +104,7 @@ enum { /* Only used by uv_udp_t handles. */ UV_HANDLE_UDP_PROCESSING = 0x01000000, UV_HANDLE_UDP_CONNECTED = 0x02000000, + UV_HANDLE_UDP_RECVMMSG = 0x04000000, /* Only used by uv_pipe_t handles. */ UV_HANDLE_NON_OVERLAPPED_PIPE = 0x01000000, @@ -322,5 +323,6 @@ char *uv__strndup(const char* s, size_t n); void* uv__malloc(size_t size); void uv__free(void* ptr); void* uv__realloc(void* ptr, size_t size); +void* uv__reallocf(void* ptr, size_t size); #endif /* UV_COMMON_H_ */ diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 8502b072021a9e..834c44a26d44cb 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -2225,34 +2225,68 @@ INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) { return 0; } - -static void fs__utime(uv_fs_t* req) { +INLINE static DWORD fs__utime_impl_from_path(WCHAR* path, + double atime, + double mtime, + int do_lutime) { HANDLE handle; + DWORD flags; + DWORD ret; - handle = CreateFileW(req->file.pathw, + flags = FILE_FLAG_BACKUP_SEMANTICS; + if (do_lutime) { + flags |= FILE_FLAG_OPEN_REPARSE_POINT; + } + + handle = CreateFileW(path, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, + flags, NULL); if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; + ret = GetLastError(); + } else if (fs__utime_handle(handle, atime, mtime) != 0) { + ret = GetLastError(); + } else { + ret = 0; } - if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - CloseHandle(handle); + CloseHandle(handle); + return ret; +} + +INLINE static void fs__utime_impl(uv_fs_t* req, int do_lutime) { + DWORD error; + + error = fs__utime_impl_from_path(req->file.pathw, + req->fs.time.atime, + req->fs.time.mtime, + do_lutime); + + if (error != 0) { + if (do_lutime && + (error == ERROR_SYMLINK_NOT_SUPPORTED || + error == ERROR_NOT_A_REPARSE_POINT)) { + /* Opened file is a reparse point but not a symlink. Try again. */ + fs__utime_impl(req, 0); + } else { + /* utime failed. */ + SET_REQ_WIN32_ERROR(req, error); + } + return; } - CloseHandle(handle); - req->result = 0; } +static void fs__utime(uv_fs_t* req) { + fs__utime_impl(req, /* do_lutime */ 0); +} + static void fs__futime(uv_fs_t* req) { int fd = req->file.fd; @@ -2274,6 +2308,10 @@ static void fs__futime(uv_fs_t* req) { req->result = 0; } +static void fs__lutime(uv_fs_t* req) { + fs__utime_impl(req, /* do_lutime */ 1); +} + static void fs__link(uv_fs_t* req) { DWORD r = CreateHardLinkW(req->fs.info.new_pathw, req->file.pathw, NULL); @@ -2621,14 +2659,62 @@ static void fs__statfs(uv_fs_t* req) { DWORD bytes_per_sector; DWORD free_clusters; DWORD total_clusters; + WCHAR* pathw; - if (0 == GetDiskFreeSpaceW(req->file.pathw, + pathw = req->file.pathw; +retry_get_disk_free_space: + if (0 == GetDiskFreeSpaceW(pathw, §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters)) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; + DWORD err; + WCHAR* fpart; + size_t len; + DWORD ret; + BOOL is_second; + + err = GetLastError(); + is_second = pathw != req->file.pathw; + if (err != ERROR_DIRECTORY || is_second) { + if (is_second) + uv__free(pathw); + + SET_REQ_WIN32_ERROR(req, err); + return; + } + + len = MAX_PATH + 1; + pathw = uv__malloc(len * sizeof(*pathw)); + if (pathw == NULL) { + SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); + return; + } +retry_get_full_path_name: + ret = GetFullPathNameW(req->file.pathw, + len, + pathw, + &fpart); + if (ret == 0) { + uv__free(pathw); + SET_REQ_WIN32_ERROR(req, err); + return; + } else if (ret > len) { + len = ret; + pathw = uv__reallocf(pathw, len * sizeof(*pathw)); + if (pathw == NULL) { + SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); + return; + } + goto retry_get_full_path_name; + } + if (fpart != 0) + *fpart = L'\0'; + + goto retry_get_disk_free_space; + } + if (pathw != req->file.pathw) { + uv__free(pathw); } stat_fs = uv__malloc(sizeof(*stat_fs)); @@ -2670,6 +2756,7 @@ static void uv__fs_work(struct uv__work* w) { XX(FTRUNCATE, ftruncate) XX(UTIME, utime) XX(FUTIME, futime) + XX(LUTIME, lutime) XX(ACCESS, access) XX(CHMOD, chmod) XX(FCHMOD, fchmod) @@ -3222,6 +3309,21 @@ int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime, POST; } +int uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, + double mtime, uv_fs_cb cb) { + int err; + + INIT(UV_FS_LUTIME); + err = fs__capture_path(req, path, NULL, cb != NULL); + if (err) { + return uv_translate_sys_error(err); + } + + req->fs.time.atime = atime; + req->fs.time.mtime = mtime; + POST; +} + int uv_fs_statfs(uv_loop_t* loop, uv_fs_t* req, diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index 277f6497a25234..fc0112a33cf62f 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -264,8 +264,9 @@ static int uv_set_pipe_handle(uv_loop_t* loop, DWORD current_mode = 0; DWORD err = 0; - if (!(handle->flags & UV_HANDLE_PIPESERVER) && - handle->handle != INVALID_HANDLE_VALUE) + if (handle->flags & UV_HANDLE_PIPESERVER) + return UV_EINVAL; + if (handle->handle != INVALID_HANDLE_VALUE) return UV_EBUSY; if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) { @@ -312,7 +313,7 @@ static int uv_set_pipe_handle(uv_loop_t* loop, /* Overlapped pipe. Try to associate with IOCP. */ if (CreateIoCompletionPort(pipeHandle, loop->iocp, - (ULONG_PTR)handle, + (ULONG_PTR) handle, 0) == NULL) { handle->flags |= UV_HANDLE_EMULATE_IOCP; } @@ -326,6 +327,38 @@ static int uv_set_pipe_handle(uv_loop_t* loop, } +static int pipe_alloc_accept(uv_loop_t* loop, uv_pipe_t* handle, + uv_pipe_accept_t* req, BOOL firstInstance) { + assert(req->pipeHandle == INVALID_HANDLE_VALUE); + + req->pipeHandle = + CreateNamedPipeW(handle->name, + PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | WRITE_DAC | + (firstInstance ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0), + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, + PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL); + + if (req->pipeHandle == INVALID_HANDLE_VALUE) { + return 0; + } + + /* Associate it with IOCP so we can get events. */ + if (CreateIoCompletionPort(req->pipeHandle, + loop->iocp, + (ULONG_PTR) handle, + 0) == NULL) { + uv_fatal_error(GetLastError(), "CreateIoCompletionPort"); + } + + /* Stash a handle in the server object for use from places such as + * getsockname and chmod. As we transfer ownership of these to client + * objects, we'll allocate new ones here. */ + handle->handle = req->pipeHandle; + + return 1; +} + + static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) { uv_loop_t* loop; uv_pipe_t* handle; @@ -458,7 +491,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { UnregisterWait(handle->read_req.wait_handle); handle->read_req.wait_handle = INVALID_HANDLE_VALUE; } - if (handle->read_req.event_handle) { + if (handle->read_req.event_handle != NULL) { CloseHandle(handle->read_req.event_handle); handle->read_req.event_handle = NULL; } @@ -540,13 +573,10 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { * Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE. * If this fails then there's already a pipe server for the given pipe name. */ - handle->pipe.serv.accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name, - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | - FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC, - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, - PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL); - - if (handle->pipe.serv.accept_reqs[0].pipeHandle == INVALID_HANDLE_VALUE) { + if (!pipe_alloc_accept(loop, + handle, + &handle->pipe.serv.accept_reqs[0], + TRUE)) { err = GetLastError(); if (err == ERROR_ACCESS_DENIED) { err = WSAEADDRINUSE; /* Translates to UV_EADDRINUSE. */ @@ -556,15 +586,6 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { goto error; } - if (uv_set_pipe_handle(loop, - handle, - handle->pipe.serv.accept_reqs[0].pipeHandle, - -1, - 0)) { - err = GetLastError(); - goto error; - } - handle->pipe.serv.pending_accepts = NULL; handle->flags |= UV_HANDLE_PIPESERVER; handle->flags |= UV_HANDLE_BOUND; @@ -577,11 +598,6 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { handle->name = NULL; } - if (handle->pipe.serv.accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE) { - CloseHandle(handle->pipe.serv.accept_reqs[0].pipeHandle); - handle->pipe.serv.accept_reqs[0].pipeHandle = INVALID_HANDLE_VALUE; - } - return uv_translate_sys_error(err); } @@ -827,29 +843,11 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle, uv_pipe_accept_t* req, BOOL firstInstance) { assert(handle->flags & UV_HANDLE_LISTENING); - if (!firstInstance) { - assert(req->pipeHandle == INVALID_HANDLE_VALUE); - - req->pipeHandle = CreateNamedPipeW(handle->name, - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | WRITE_DAC, - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, - PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL); - - if (req->pipeHandle == INVALID_HANDLE_VALUE) { - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*) req); - handle->reqs_pending++; - return; - } - - if (uv_set_pipe_handle(loop, handle, req->pipeHandle, -1, 0)) { - CloseHandle(req->pipeHandle); - req->pipeHandle = INVALID_HANDLE_VALUE; - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*) req); - handle->reqs_pending++; - return; - } + if (!firstInstance && !pipe_alloc_accept(loop, handle, req, FALSE)) { + SET_REQ_ERROR(req, GetLastError()); + uv_insert_pending_req(loop, (uv_req_t*) req); + handle->reqs_pending++; + return; } assert(req->pipeHandle != INVALID_HANDLE_VALUE); @@ -904,7 +902,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { uv__free(item); } else { - pipe_client = (uv_pipe_t*)client; + pipe_client = (uv_pipe_t*) client; /* Find a connection instance that has been connected, but not yet * accepted. */ @@ -925,6 +923,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { req->next_pending = NULL; req->pipeHandle = INVALID_HANDLE_VALUE; + server->handle = INVALID_HANDLE_VALUE; if (!(server->flags & UV_HANDLE_CLOSING)) { uv_pipe_queue_accept(loop, server, req, FALSE); } @@ -955,6 +954,10 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { return ERROR_NOT_SUPPORTED; } + if (handle->ipc) { + return WSAEINVAL; + } + handle->flags |= UV_HANDLE_LISTENING; INCREASE_ACTIVE_COUNT(loop, handle); handle->stream.serv.connection_cb = cb; @@ -1131,6 +1134,7 @@ static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) { } else { memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { + assert(req->event_handle != NULL); req->u.io.overlapped.hEvent = (HANDLE) ((uintptr_t) req->event_handle | 1); } @@ -1148,15 +1152,9 @@ static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) { } if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - if (!req->event_handle) { - req->event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!req->event_handle) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - } if (req->wait_handle == INVALID_HANDLE_VALUE) { if (!RegisterWaitForSingleObject(&req->wait_handle, - req->u.io.overlapped.hEvent, post_completion_read_wait, (void*) req, + req->event_handle, post_completion_read_wait, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD)) { SET_REQ_ERROR(req, GetLastError()); goto error; @@ -1190,8 +1188,16 @@ int uv_pipe_read_start(uv_pipe_t* handle, /* If reading was stopped and then started again, there could still be a read * request pending. */ - if (!(handle->flags & UV_HANDLE_READ_PENDING)) + if (!(handle->flags & UV_HANDLE_READ_PENDING)) { + if (handle->flags & UV_HANDLE_EMULATE_IOCP && + handle->read_req.event_handle == NULL) { + handle->read_req.event_handle = CreateEvent(NULL, 0, 0, NULL); + if (handle->read_req.event_handle == NULL) { + uv_fatal_error(GetLastError(), "CreateEvent"); + } + } uv_pipe_queue_read(loop, handle); + } return 0; } @@ -1326,7 +1332,16 @@ static int uv__pipe_write_data(uv_loop_t* loop, req->coalesced = 0; req->event_handle = NULL; req->wait_handle = INVALID_HANDLE_VALUE; + + /* Prepare the overlapped structure. */ memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); + if (handle->flags & (UV_HANDLE_EMULATE_IOCP | UV_HANDLE_BLOCKING_WRITES)) { + req->event_handle = CreateEvent(NULL, 0, 0, NULL); + if (req->event_handle == NULL) { + uv_fatal_error(GetLastError(), "CreateEvent"); + } + req->u.io.overlapped.hEvent = (HANDLE) ((uintptr_t) req->event_handle | 1); + } req->write_buffer = uv_null_buf_; if (nbufs == 0) { @@ -1375,11 +1390,6 @@ static int uv__pipe_write_data(uv_loop_t* loop, handle->write_queue_size += req->u.io.queued_bytes; } else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) { /* Using overlapped IO, but wait for completion before returning */ - req->u.io.overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL); - if (!req->u.io.overlapped.hEvent) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - result = WriteFile(handle->handle, write_buf.base, write_buf.len, @@ -1388,7 +1398,8 @@ static int uv__pipe_write_data(uv_loop_t* loop, if (!result && GetLastError() != ERROR_IO_PENDING) { err = GetLastError(); - CloseHandle(req->u.io.overlapped.hEvent); + CloseHandle(req->event_handle); + req->event_handle = NULL; return err; } @@ -1399,14 +1410,16 @@ static int uv__pipe_write_data(uv_loop_t* loop, /* Request queued by the kernel. */ req->u.io.queued_bytes = write_buf.len; handle->write_queue_size += req->u.io.queued_bytes; - if (WaitForSingleObject(req->u.io.overlapped.hEvent, INFINITE) != + if (WaitForSingleObject(req->event_handle, INFINITE) != WAIT_OBJECT_0) { err = GetLastError(); - CloseHandle(req->u.io.overlapped.hEvent); + CloseHandle(req->event_handle); + req->event_handle = NULL; return err; } } - CloseHandle(req->u.io.overlapped.hEvent); + CloseHandle(req->event_handle); + req->event_handle = NULL; REGISTER_HANDLE_REQ(loop, handle, req); handle->reqs_pending++; @@ -1433,12 +1446,8 @@ static int uv__pipe_write_data(uv_loop_t* loop, } if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - req->event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!req->event_handle) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } if (!RegisterWaitForSingleObject(&req->wait_handle, - req->u.io.overlapped.hEvent, post_completion_write_wait, (void*) req, + req->event_handle, post_completion_write_wait, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD)) { return GetLastError(); } diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c index 9b7fdc1dc1b4e2..73543c6ed987ce 100644 --- a/deps/uv/src/win/process.c +++ b/deps/uv/src/win/process.c @@ -58,7 +58,6 @@ static const env_var_t required_vars[] = { /* keep me sorted */ E_V("USERPROFILE"), E_V("WINDIR"), }; -static size_t n_required_vars = ARRAY_SIZE(required_vars); static HANDLE uv_global_job_handle_; @@ -692,7 +691,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { WCHAR* dst_copy; WCHAR** ptr_copy; WCHAR** env_copy; - DWORD* required_vars_value_len = alloca(n_required_vars * sizeof(DWORD*)); + DWORD required_vars_value_len[ARRAY_SIZE(required_vars)]; /* first pass: determine size in UTF-16 */ for (env = env_block; *env; env++) { @@ -745,7 +744,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { qsort(env_copy, env_block_count-1, sizeof(wchar_t*), qsort_wcscmp); /* third pass: check for required variables */ - for (ptr_copy = env_copy, i = 0; i < n_required_vars; ) { + for (ptr_copy = env_copy, i = 0; i < ARRAY_SIZE(required_vars); ) { int cmp; if (!*ptr_copy) { cmp = -1; @@ -778,10 +777,10 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { } for (ptr = dst, ptr_copy = env_copy, i = 0; - *ptr_copy || i < n_required_vars; + *ptr_copy || i < ARRAY_SIZE(required_vars); ptr += len) { int cmp; - if (i >= n_required_vars) { + if (i >= ARRAY_SIZE(required_vars)) { cmp = 1; } else if (!*ptr_copy) { cmp = -1; diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index fd34c623d8c543..941c8010d3f699 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -251,7 +251,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { UnregisterWait(req->wait_handle); req->wait_handle = INVALID_HANDLE_VALUE; } - if (req->event_handle) { + if (req->event_handle != NULL) { CloseHandle(req->event_handle); req->event_handle = NULL; } @@ -268,7 +268,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { UnregisterWait(handle->read_req.wait_handle); handle->read_req.wait_handle = INVALID_HANDLE_VALUE; } - if (handle->read_req.event_handle) { + if (handle->read_req.event_handle != NULL) { CloseHandle(handle->read_req.event_handle); handle->read_req.event_handle = NULL; } @@ -428,6 +428,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { /* Prepare the overlapped structure. */ memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped)); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { + assert(req->event_handle != NULL); req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); } @@ -466,7 +467,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { closesocket(accept_socket); /* Destroy the event handle */ if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - CloseHandle(req->u.io.overlapped.hEvent); + CloseHandle(req->event_handle); req->event_handle = NULL; } } @@ -509,7 +510,7 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { /* Prepare the overlapped structure. */ memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped)); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - assert(req->event_handle); + assert(req->event_handle != NULL); req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); } @@ -612,8 +613,8 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1 : uv_simultaneous_server_accepts; - if(!handle->tcp.serv.accept_reqs) { - handle->tcp.serv.accept_reqs = (uv_tcp_accept_t*) + if (handle->tcp.serv.accept_reqs == NULL) { + handle->tcp.serv.accept_reqs = uv__malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t)); if (!handle->tcp.serv.accept_reqs) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); @@ -628,7 +629,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { req->wait_handle = INVALID_HANDLE_VALUE; if (handle->flags & UV_HANDLE_EMULATE_IOCP) { req->event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!req->event_handle) { + if (req->event_handle == NULL) { uv_fatal_error(GetLastError(), "CreateEvent"); } } else { @@ -737,9 +738,9 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb, * request pending. */ if (!(handle->flags & UV_HANDLE_READ_PENDING)) { if (handle->flags & UV_HANDLE_EMULATE_IOCP && - !handle->read_req.event_handle) { + handle->read_req.event_handle == NULL) { handle->read_req.event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!handle->read_req.event_handle) { + if (handle->read_req.event_handle == NULL) { uv_fatal_error(GetLastError(), "CreateEvent"); } } @@ -862,7 +863,7 @@ int uv_tcp_write(uv_loop_t* loop, memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped)); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { req->event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!req->event_handle) { + if (req->event_handle == NULL) { uv_fatal_error(GetLastError(), "CreateEvent"); } req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); @@ -1080,7 +1081,7 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, UnregisterWait(req->wait_handle); req->wait_handle = INVALID_HANDLE_VALUE; } - if (req->event_handle) { + if (req->event_handle != NULL) { CloseHandle(req->event_handle); req->event_handle = NULL; } diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index 517aa4af79f6e9..488d9b2a14371e 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -46,14 +46,16 @@ #define UNICODE_REPLACEMENT_CHARACTER (0xfffd) -#define ANSI_NORMAL 0x00 -#define ANSI_ESCAPE_SEEN 0x02 -#define ANSI_CSI 0x04 -#define ANSI_ST_CONTROL 0x08 -#define ANSI_IGNORE 0x10 -#define ANSI_IN_ARG 0x20 -#define ANSI_IN_STRING 0x40 -#define ANSI_BACKSLASH_SEEN 0x80 +#define ANSI_NORMAL 0x0000 +#define ANSI_ESCAPE_SEEN 0x0002 +#define ANSI_CSI 0x0004 +#define ANSI_ST_CONTROL 0x0008 +#define ANSI_IGNORE 0x0010 +#define ANSI_IN_ARG 0x0020 +#define ANSI_IN_STRING 0x0040 +#define ANSI_BACKSLASH_SEEN 0x0080 +#define ANSI_EXTENSION 0x0100 +#define ANSI_DECSCUSR 0x0200 #define MAX_INPUT_BUFFER_LENGTH 8192 #define MAX_CONSOLE_CHAR 8192 @@ -62,7 +64,12 @@ #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 #endif -static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info); +#define CURSOR_SIZE_SMALL 25 +#define CURSOR_SIZE_LARGE 100 + +static void uv_tty_capture_initial_style( + CONSOLE_SCREEN_BUFFER_INFO* screen_buffer_info, + CONSOLE_CURSOR_INFO* cursor_info); static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info); static int uv__cancel_read_console(uv_tty_t* handle); @@ -149,6 +156,8 @@ static char uv_tty_default_fg_bright = 0; static char uv_tty_default_bg_bright = 0; static char uv_tty_default_inverse = 0; +static CONSOLE_CURSOR_INFO uv_tty_default_cursor_info; + /* Determine whether or not ANSI support is enabled. */ static BOOL uv__need_check_vterm_state = TRUE; static uv_tty_vtermstate_t uv__vterm_state = UV_TTY_UNSUPPORTED; @@ -183,6 +192,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) { DWORD NumberOfEvents; HANDLE handle; CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info; + CONSOLE_CURSOR_INFO cursor_info; (void)unused; uv__once_init(); @@ -215,6 +225,11 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) { return uv_translate_sys_error(GetLastError()); } + /* Obtain the cursor info with the output handle. */ + if (!GetConsoleCursorInfo(handle, &cursor_info)) { + return uv_translate_sys_error(GetLastError()); + } + /* Obtain the tty_output_lock because the virtual window state is shared * between all uv_tty_t handles. */ uv_sem_wait(&uv_tty_output_lock); @@ -222,8 +237,8 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) { if (uv__need_check_vterm_state) uv__determine_vterm_state(handle); - /* Remember the original console text attributes. */ - uv_tty_capture_initial_style(&screen_buffer_info); + /* Remember the original console text attributes and cursor info. */ + uv_tty_capture_initial_style(&screen_buffer_info, &cursor_info); uv_tty_update_virtual_window(&screen_buffer_info); @@ -274,7 +289,9 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) { /* Set the default console text attributes based on how the console was * configured when libuv started. */ -static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info) { +static void uv_tty_capture_initial_style( + CONSOLE_SCREEN_BUFFER_INFO* screen_buffer_info, + CONSOLE_CURSOR_INFO* cursor_info) { static int style_captured = 0; /* Only do this once. @@ -283,7 +300,7 @@ static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info) { return; /* Save raw win32 attributes. */ - uv_tty_default_text_attributes = info->wAttributes; + uv_tty_default_text_attributes = screen_buffer_info->wAttributes; /* Convert black text on black background to use white text. */ if (uv_tty_default_text_attributes == 0) @@ -323,6 +340,9 @@ static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info) { if (uv_tty_default_text_attributes & COMMON_LVB_REVERSE_VIDEO) uv_tty_default_inverse = 1; + /* Save the cursor size and the cursor state. */ + uv_tty_default_cursor_info = *cursor_info; + style_captured = 1; } @@ -1230,7 +1250,7 @@ static int uv_tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative, static int uv_tty_reset(uv_tty_t* handle, DWORD* error) { const COORD origin = {0, 0}; const WORD char_attrs = uv_tty_default_text_attributes; - CONSOLE_SCREEN_BUFFER_INFO info; + CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info; DWORD count, written; if (*error != ERROR_SUCCESS) { @@ -1251,12 +1271,12 @@ static int uv_tty_reset(uv_tty_t* handle, DWORD* error) { /* Clear the screen buffer. */ retry: - if (!GetConsoleScreenBufferInfo(handle->handle, &info)) { - *error = GetLastError(); - return -1; + if (!GetConsoleScreenBufferInfo(handle->handle, &screen_buffer_info)) { + *error = GetLastError(); + return -1; } - count = info.dwSize.X * info.dwSize.Y; + count = screen_buffer_info.dwSize.X * screen_buffer_info.dwSize.Y; if (!(FillConsoleOutputCharacterW(handle->handle, L'\x20', @@ -1279,7 +1299,13 @@ static int uv_tty_reset(uv_tty_t* handle, DWORD* error) { /* Move the virtual window up to the top. */ uv_tty_virtual_offset = 0; - uv_tty_update_virtual_window(&info); + uv_tty_update_virtual_window(&screen_buffer_info); + + /* Reset the cursor size and the cursor state. */ + if (!SetConsoleCursorInfo(handle->handle, &uv_tty_default_cursor_info)) { + *error = GetLastError(); + return -1; + } return 0; } @@ -1618,6 +1644,31 @@ static int uv_tty_set_cursor_visibility(uv_tty_t* handle, return 0; } +static int uv_tty_set_cursor_shape(uv_tty_t* handle, int style, DWORD* error) { + CONSOLE_CURSOR_INFO cursor_info; + + if (!GetConsoleCursorInfo(handle->handle, &cursor_info)) { + *error = GetLastError(); + return -1; + } + + if (style == 0) { + cursor_info.dwSize = uv_tty_default_cursor_info.dwSize; + } else if (style <= 2) { + cursor_info.dwSize = CURSOR_SIZE_LARGE; + } else { + cursor_info.dwSize = CURSOR_SIZE_SMALL; + } + + if (!SetConsoleCursorInfo(handle->handle, &cursor_info)) { + *error = GetLastError(); + return -1; + } + + return 0; +} + + static int uv_tty_write_bufs(uv_tty_t* handle, const uv_buf_t bufs[], unsigned int nbufs, @@ -1645,7 +1696,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, unsigned char utf8_bytes_left = handle->tty.wr.utf8_bytes_left; unsigned int utf8_codepoint = handle->tty.wr.utf8_codepoint; unsigned char previous_eol = handle->tty.wr.previous_eol; - unsigned char ansi_parser_state = handle->tty.wr.ansi_parser_state; + unsigned short ansi_parser_state = handle->tty.wr.ansi_parser_state; /* Store the error here. If we encounter an error, stop trying to do i/o but * keep parsing the buffer so we leave the parser in a consistent state. */ @@ -1761,7 +1812,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, ansi_parser_state = ANSI_NORMAL; continue; - case '8': + case '8': /* Restore the cursor position and text attributes */ FLUSH_TEXT(); uv_tty_restore_state(handle, 1, error); @@ -1779,121 +1830,193 @@ static int uv_tty_write_bufs(uv_tty_t* handle, } } + } else if (ansi_parser_state == ANSI_IGNORE) { + /* We're ignoring this command. Stop only on command character. */ + if (utf8_codepoint >= '@' && utf8_codepoint <= '~') { + ansi_parser_state = ANSI_NORMAL; + } + continue; + + } else if (ansi_parser_state == ANSI_DECSCUSR) { + /* So far we've the sequence `ESC [ arg space`, and we're waiting for + * the final command byte. */ + if (utf8_codepoint >= '@' && utf8_codepoint <= '~') { + /* Command byte */ + if (utf8_codepoint == 'q') { + /* Change the cursor shape */ + int style = handle->tty.wr.ansi_csi_argc + ? handle->tty.wr.ansi_csi_argv[0] : 1; + if (style >= 0 && style <= 6) { + FLUSH_TEXT(); + uv_tty_set_cursor_shape(handle, style, error); + } + } + + /* Sequence ended - go back to normal state. */ + ansi_parser_state = ANSI_NORMAL; + continue; + } + /* Unexpected character, but sequence hasn't ended yet. Ignore the rest + * of the sequence. */ + ansi_parser_state = ANSI_IGNORE; + } else if (ansi_parser_state & ANSI_CSI) { - if (!(ansi_parser_state & ANSI_IGNORE)) { - if (utf8_codepoint >= '0' && utf8_codepoint <= '9') { - /* Parsing a numerical argument */ - - if (!(ansi_parser_state & ANSI_IN_ARG)) { - /* We were not currently parsing a number */ - - /* Check for too many arguments */ - if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) { - ansi_parser_state |= ANSI_IGNORE; - continue; - } - - ansi_parser_state |= ANSI_IN_ARG; - handle->tty.wr.ansi_csi_argc++; - handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = - (unsigned short) utf8_codepoint - '0'; + /* So far we've seen `ESC [`, and we may or may not have already parsed + * some of the arguments that follow. */ + + if (utf8_codepoint >= '0' && utf8_codepoint <= '9') { + /* Parse a numerical argument. */ + if (!(ansi_parser_state & ANSI_IN_ARG)) { + /* We were not currently parsing a number, add a new one. */ + /* Check for that there are too many arguments. */ + if (handle->tty.wr.ansi_csi_argc >= + ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) { + ansi_parser_state = ANSI_IGNORE; continue; - } else { - /* We were already parsing a number. Parse next digit. */ - uint32_t value = 10 * - handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1]; - - /* Check for overflow. */ - if (value > UINT16_MAX) { - ansi_parser_state |= ANSI_IGNORE; - continue; - } - - handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = - (unsigned short) value + (utf8_codepoint - '0'); - continue; } + ansi_parser_state |= ANSI_IN_ARG; + handle->tty.wr.ansi_csi_argc++; + handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = + (unsigned short) utf8_codepoint - '0'; + continue; + + } else { + /* We were already parsing a number. Parse next digit. */ + uint32_t value = 10 * + handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1]; - } else if (utf8_codepoint == ';') { - /* Denotes the end of an argument. */ - if (ansi_parser_state & ANSI_IN_ARG) { - ansi_parser_state &= ~ANSI_IN_ARG; + /* Check for overflow. */ + if (value > UINT16_MAX) { + ansi_parser_state = ANSI_IGNORE; continue; + } - } else { - /* If ANSI_IN_ARG is not set, add another argument and default it - * to 0. */ + handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = + (unsigned short) value + (utf8_codepoint - '0'); + continue; + } - /* Check for too many arguments */ - if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) { - ansi_parser_state |= ANSI_IGNORE; - continue; - } + } else if (utf8_codepoint == ';') { + /* Denotes the end of an argument. */ + if (ansi_parser_state & ANSI_IN_ARG) { + ansi_parser_state &= ~ANSI_IN_ARG; + continue; + + } else { + /* If ANSI_IN_ARG is not set, add another argument and default + * it to 0. */ - handle->tty.wr.ansi_csi_argc++; - handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = 0; + /* Check for too many arguments */ + if (handle->tty.wr.ansi_csi_argc >= + + ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) { + ansi_parser_state = ANSI_IGNORE; continue; } - } else if (utf8_codepoint == '?' && !(ansi_parser_state & ANSI_IN_ARG) && - handle->tty.wr.ansi_csi_argc == 0) { - /* Ignores '?' if it is the first character after CSI[. This is an - * extension character from the VT100 codeset that is supported and - * used by most ANSI terminals today. */ + handle->tty.wr.ansi_csi_argc++; + handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = 0; continue; + } - } else if (utf8_codepoint >= '@' && utf8_codepoint <= '~' && - (handle->tty.wr.ansi_csi_argc > 0 || utf8_codepoint != '[')) { - int x, y, d; + } else if (utf8_codepoint == '?' && + !(ansi_parser_state & ANSI_IN_ARG) && + !(ansi_parser_state & ANSI_EXTENSION) && + handle->tty.wr.ansi_csi_argc == 0) { + /* Pass through '?' if it is the first character after CSI */ + /* This is an extension character from the VT100 codeset */ + /* that is supported and used by most ANSI terminals today. */ + ansi_parser_state |= ANSI_EXTENSION; + continue; + + } else if (utf8_codepoint == ' ' && + !(ansi_parser_state & ANSI_EXTENSION)) { + /* We expect a command byte to follow after this space. The only + * command that we current support is 'set cursor style'. */ + ansi_parser_state = ANSI_DECSCUSR; + continue; + + } else if (utf8_codepoint >= '@' && utf8_codepoint <= '~') { + /* Command byte */ + if (ansi_parser_state & ANSI_EXTENSION) { + /* Sequence is `ESC [ ? args command`. */ + switch (utf8_codepoint) { + case 'l': + /* Hide the cursor */ + if (handle->tty.wr.ansi_csi_argc == 1 && + handle->tty.wr.ansi_csi_argv[0] == 25) { + FLUSH_TEXT(); + uv_tty_set_cursor_visibility(handle, 0, error); + } + break; + + case 'h': + /* Show the cursor */ + if (handle->tty.wr.ansi_csi_argc == 1 && + handle->tty.wr.ansi_csi_argv[0] == 25) { + FLUSH_TEXT(); + uv_tty_set_cursor_visibility(handle, 1, error); + } + break; + } - /* Command byte */ + } else { + /* Sequence is `ESC [ args command`. */ + int x, y, d; switch (utf8_codepoint) { case 'A': /* cursor up */ FLUSH_TEXT(); - y = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1); + y = -(handle->tty.wr.ansi_csi_argc + ? handle->tty.wr.ansi_csi_argv[0] : 1); uv_tty_move_caret(handle, 0, 1, y, 1, error); break; case 'B': /* cursor down */ FLUSH_TEXT(); - y = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1; + y = handle->tty.wr.ansi_csi_argc + ? handle->tty.wr.ansi_csi_argv[0] : 1; uv_tty_move_caret(handle, 0, 1, y, 1, error); break; case 'C': /* cursor forward */ FLUSH_TEXT(); - x = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1; + x = handle->tty.wr.ansi_csi_argc + ? handle->tty.wr.ansi_csi_argv[0] : 1; uv_tty_move_caret(handle, x, 1, 0, 1, error); break; case 'D': /* cursor back */ FLUSH_TEXT(); - x = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1); + x = -(handle->tty.wr.ansi_csi_argc + ? handle->tty.wr.ansi_csi_argv[0] : 1); uv_tty_move_caret(handle, x, 1, 0, 1, error); break; case 'E': /* cursor next line */ FLUSH_TEXT(); - y = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1; + y = handle->tty.wr.ansi_csi_argc + ? handle->tty.wr.ansi_csi_argv[0] : 1; uv_tty_move_caret(handle, 0, 0, y, 1, error); break; case 'F': /* cursor previous line */ FLUSH_TEXT(); - y = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1); + y = -(handle->tty.wr.ansi_csi_argc + ? handle->tty.wr.ansi_csi_argv[0] : 1); uv_tty_move_caret(handle, 0, 0, y, 1, error); break; case 'G': /* cursor horizontal move absolute */ FLUSH_TEXT(); - x = (handle->tty.wr.ansi_csi_argc >= 1 && handle->tty.wr.ansi_csi_argv[0]) + x = (handle->tty.wr.ansi_csi_argc >= 1 && + handle->tty.wr.ansi_csi_argv[0]) ? handle->tty.wr.ansi_csi_argv[0] - 1 : 0; uv_tty_move_caret(handle, x, 0, 0, 1, error); break; @@ -1902,9 +2025,11 @@ static int uv_tty_write_bufs(uv_tty_t* handle, case 'f': /* cursor move absolute */ FLUSH_TEXT(); - y = (handle->tty.wr.ansi_csi_argc >= 1 && handle->tty.wr.ansi_csi_argv[0]) + y = (handle->tty.wr.ansi_csi_argc >= 1 && + handle->tty.wr.ansi_csi_argv[0]) ? handle->tty.wr.ansi_csi_argv[0] - 1 : 0; - x = (handle->tty.wr.ansi_csi_argc >= 2 && handle->tty.wr.ansi_csi_argv[1]) + x = (handle->tty.wr.ansi_csi_argc >= 2 && + handle->tty.wr.ansi_csi_argv[1]) ? handle->tty.wr.ansi_csi_argv[1] - 1 : 0; uv_tty_move_caret(handle, x, 0, y, 0, error); break; @@ -1912,7 +2037,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, case 'J': /* Erase screen */ FLUSH_TEXT(); - d = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 0; + d = handle->tty.wr.ansi_csi_argc + ? handle->tty.wr.ansi_csi_argv[0] : 0; if (d >= 0 && d <= 2) { uv_tty_clear(handle, d, 1, error); } @@ -1921,7 +2047,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, case 'K': /* Erase line */ FLUSH_TEXT(); - d = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 0; + d = handle->tty.wr.ansi_csi_argc + ? handle->tty.wr.ansi_csi_argv[0] : 0; if (d >= 0 && d <= 2) { uv_tty_clear(handle, d, 0, error); } @@ -1944,41 +2071,17 @@ static int uv_tty_write_bufs(uv_tty_t* handle, FLUSH_TEXT(); uv_tty_restore_state(handle, 0, error); break; - - case 'l': - /* Hide the cursor */ - if (handle->tty.wr.ansi_csi_argc == 1 && - handle->tty.wr.ansi_csi_argv[0] == 25) { - FLUSH_TEXT(); - uv_tty_set_cursor_visibility(handle, 0, error); - } - break; - - case 'h': - /* Show the cursor */ - if (handle->tty.wr.ansi_csi_argc == 1 && - handle->tty.wr.ansi_csi_argv[0] == 25) { - FLUSH_TEXT(); - uv_tty_set_cursor_visibility(handle, 1, error); - } - break; } + } - /* Sequence ended - go back to normal state. */ - ansi_parser_state = ANSI_NORMAL; - continue; + /* Sequence ended - go back to normal state. */ + ansi_parser_state = ANSI_NORMAL; + continue; - } else { - /* We don't support commands that use private mode characters or - * intermediaries. Ignore the rest of the sequence. */ - ansi_parser_state |= ANSI_IGNORE; - continue; - } } else { - /* We're ignoring this command. Stop only on command character. */ - if (utf8_codepoint >= '@' && utf8_codepoint <= '~') { - ansi_parser_state = ANSI_NORMAL; - } + /* We don't support commands that use private mode characters or + * intermediaries. Ignore the rest of the sequence. */ + ansi_parser_state = ANSI_IGNORE; continue; } diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index 4de638f5971c35..aaa7ba0325b0e5 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -63,6 +63,9 @@ /* Maximum environment variable size, including the terminating null */ #define MAX_ENV_VAR_LENGTH 32767 +/* A RtlGenRandom() by any other name... */ +extern BOOLEAN NTAPI SystemFunction036(PVOID Buffer, ULONG BufferLength); + /* Cached copy of the process title, plus a mutex guarding it. */ static char *process_title; static CRITICAL_SECTION process_title_lock; @@ -1402,7 +1405,7 @@ int uv_os_environ(uv_env_item_t** envitems, int* count) { for (penv = env, i = 0; *penv != L'\0'; penv += wcslen(penv) + 1, i++); *envitems = uv__calloc(i, sizeof(**envitems)); - if (envitems == NULL) { + if (*envitems == NULL) { FreeEnvironmentStringsW(env); return UV_ENOMEM; } @@ -1862,13 +1865,10 @@ int uv_gettimeofday(uv_timeval64_t* tv) { } int uv__random_rtlgenrandom(void* buf, size_t buflen) { - if (pRtlGenRandom == NULL) - return UV_ENOSYS; - if (buflen == 0) return 0; - if (pRtlGenRandom(buf, buflen) == FALSE) + if (SystemFunction036(buf, buflen) == FALSE) return UV_EIO; return 0; diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c index 85a9de8a2295ec..bb86ec8ceac8ba 100644 --- a/deps/uv/src/win/winapi.c +++ b/deps/uv/src/win/winapi.c @@ -36,9 +36,6 @@ sNtQueryDirectoryFile pNtQueryDirectoryFile; sNtQuerySystemInformation pNtQuerySystemInformation; sNtQueryInformationProcess pNtQueryInformationProcess; -/* Advapi32 function pointers */ -sRtlGenRandom pRtlGenRandom; - /* Kernel32 function pointers */ sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; @@ -54,7 +51,6 @@ void uv_winapi_init(void) { HMODULE powrprof_module; HMODULE user32_module; HMODULE kernel32_module; - HMODULE advapi32_module; ntdll_module = GetModuleHandleA("ntdll.dll"); if (ntdll_module == NULL) { @@ -138,12 +134,4 @@ void uv_winapi_init(void) { pSetWinEventHook = (sSetWinEventHook) GetProcAddress(user32_module, "SetWinEventHook"); } - - advapi32_module = GetModuleHandleA("advapi32.dll"); - if (advapi32_module == NULL) { - uv_fatal_error(GetLastError(), "GetModuleHandleA"); - } - - pRtlGenRandom = - (sRtlGenRandom) GetProcAddress(advapi32_module, "SystemFunction036"); } diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h index fcc70652a9aedb..322a212dd73c19 100644 --- a/deps/uv/src/win/winapi.h +++ b/deps/uv/src/win/winapi.h @@ -4589,11 +4589,6 @@ typedef NTSTATUS (NTAPI *sNtQueryInformationProcess) ULONG Length, PULONG ReturnLength); -/* - * Advapi32 headers - */ -typedef BOOLEAN (WINAPI *sRtlGenRandom)(PVOID Buffer, ULONG BufferLength); - /* * Kernel32 headers */ @@ -4736,9 +4731,6 @@ extern sNtQueryDirectoryFile pNtQueryDirectoryFile; extern sNtQuerySystemInformation pNtQuerySystemInformation; extern sNtQueryInformationProcess pNtQueryInformationProcess; -/* Advapi32 function pointers */ -extern sRtlGenRandom pRtlGenRandom; - /* Kernel32 function pointers */ extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; diff --git a/deps/uv/test/benchmark-list.h b/deps/uv/test/benchmark-list.h index 1e843071c01c3c..29e44c30f025b3 100644 --- a/deps/uv/test/benchmark-list.h +++ b/deps/uv/test/benchmark-list.h @@ -23,6 +23,7 @@ BENCHMARK_DECLARE (sizes) BENCHMARK_DECLARE (loop_count) BENCHMARK_DECLARE (loop_count_timed) BENCHMARK_DECLARE (ping_pongs) +BENCHMARK_DECLARE (ping_udp) BENCHMARK_DECLARE (tcp_write_batch) BENCHMARK_DECLARE (tcp4_pound_100) BENCHMARK_DECLARE (tcp4_pound_1000) diff --git a/deps/uv/test/benchmark-multi-accept.c b/deps/uv/test/benchmark-multi-accept.c index 2f32c0caf4a202..5a186233f580d9 100644 --- a/deps/uv/test/benchmark-multi-accept.c +++ b/deps/uv/test/benchmark-multi-accept.c @@ -218,8 +218,12 @@ static void send_listen_handles(uv_handle_type type, } else ASSERT(0); - - ASSERT(0 == uv_pipe_init(loop, &ctx.ipc_pipe, 1)); + /* We need to initialize this pipe with ipc=0 - this is not a uv_pipe we'll + * be sending handles over, it's just for listening for new connections. + * If we accept a connection then the connected pipe must be initialized + * with ipc=1. + */ + ASSERT(0 == uv_pipe_init(loop, &ctx.ipc_pipe, 0)); ASSERT(0 == uv_pipe_bind(&ctx.ipc_pipe, IPC_PIPE_NAME)); ASSERT(0 == uv_listen((uv_stream_t*) &ctx.ipc_pipe, 128, ipc_connection_cb)); diff --git a/deps/uv/test/benchmark-ping-udp.c b/deps/uv/test/benchmark-ping-udp.c new file mode 100644 index 00000000000000..a29502a786fd7f --- /dev/null +++ b/deps/uv/test/benchmark-ping-udp.c @@ -0,0 +1,163 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +#include +#include + +/* Run the benchmark for this many ms */ +#define TIME 5000 + +typedef struct { + int pongs; + int state; + uv_udp_t udp; + struct sockaddr_in server_addr; +} pinger_t; + +typedef struct buf_s { + uv_buf_t uv_buf_t; + struct buf_s* next; +} buf_t; + +static char PING[] = "PING\n"; + +static uv_loop_t* loop; + +static int completed_pingers; +static unsigned long completed_pings; +static int64_t start_time; + + +static void buf_alloc(uv_handle_t* tcp, size_t size, uv_buf_t* buf) { + static char slab[64 * 1024]; + buf->base = slab; + buf->len = sizeof(slab); +} + + +static void buf_free(const uv_buf_t* buf) { +} + + +static void pinger_close_cb(uv_handle_t* handle) { + pinger_t* pinger; + + pinger = (pinger_t*)handle->data; +#if DEBUG + fprintf(stderr, "ping_pongs: %d roundtrips/s\n", + pinger->pongs / (TIME / 1000)); +#endif + + completed_pings += pinger->pongs; + completed_pingers++; + free(pinger); +} + +static void pinger_write_ping(pinger_t* pinger) { + uv_buf_t buf; + int r; + + buf = uv_buf_init(PING, sizeof(PING) - 1); + r = uv_udp_try_send(&pinger->udp, &buf, 1, + (const struct sockaddr*) &pinger->server_addr); + if (r < 0) + FATAL("uv_udp_send failed"); +} + +static void pinger_read_cb(uv_udp_t* udp, + ssize_t nread, + const uv_buf_t* buf, + const struct sockaddr* addr, + unsigned flags) { + ssize_t i; + pinger_t* pinger; + pinger = (pinger_t*)udp->data; + + /* Now we count the pings */ + for (i = 0; i < nread; i++) { + ASSERT(buf->base[i] == PING[pinger->state]); + pinger->state = (pinger->state + 1) % (sizeof(PING) - 1); + if (pinger->state == 0) { + pinger->pongs++; + if (uv_now(loop) - start_time > TIME) { + uv_close((uv_handle_t*)udp, pinger_close_cb); + break; + } + pinger_write_ping(pinger); + } + } + + buf_free(buf); +} + +static void udp_pinger_new(void) { + pinger_t* pinger = malloc(sizeof(*pinger)); + int r; + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &pinger->server_addr)); + pinger->state = 0; + pinger->pongs = 0; + + /* Try to do NUM_PINGS ping-pongs (connection-less). */ + r = uv_udp_init(loop, &pinger->udp); + ASSERT(r == 0); + + pinger->udp.data = pinger; + + /* Start pinging */ + if (0 != uv_udp_recv_start(&pinger->udp, buf_alloc, pinger_read_cb)) { + FATAL("uv_udp_read_start failed"); + } + pinger_write_ping(pinger); +} + +static int ping_udp(unsigned pingers) { + unsigned i; + + loop = uv_default_loop(); + start_time = uv_now(loop); + + for (i = 0; i < pingers; ++i) { + udp_pinger_new(); + } + uv_run(loop, UV_RUN_DEFAULT); + ASSERT(completed_pingers >= 1); + + fprintf(stderr, "ping_pongs: %d pingers, ~ %lu roundtrips/s\n", + completed_pingers, completed_pings / (TIME/1000)); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +#define X(PINGERS) \ +BENCHMARK_IMPL(ping_udp##PINGERS) {\ + return ping_udp(PINGERS); \ +} + +X(1) +X(10) +X(100) + +#undef X diff --git a/deps/uv/test/echo-server.c b/deps/uv/test/echo-server.c index a38e975d4841d6..c65142ff901794 100644 --- a/deps/uv/test/echo-server.c +++ b/deps/uv/test/echo-server.c @@ -37,6 +37,7 @@ static uv_tcp_t tcpServer; static uv_udp_t udpServer; static uv_pipe_t pipeServer; static uv_handle_t* server; +static uv_udp_send_t* send_freelist; static void after_write(uv_write_t* req, int status); static void after_read(uv_stream_t*, ssize_t nread, const uv_buf_t* buf); @@ -133,6 +134,14 @@ static void echo_alloc(uv_handle_t* handle, buf->len = suggested_size; } +static void slab_alloc(uv_handle_t* handle, + size_t suggested_size, + uv_buf_t* buf) { + /* up to 16 datagrams at once */ + static char slab[16 * 64 * 1024]; + buf->base = slab; + buf->len = sizeof(slab); +} static void on_connection(uv_stream_t* server, int status) { uv_stream_t* stream; @@ -178,35 +187,43 @@ static void on_server_close(uv_handle_t* handle) { ASSERT(handle == server); } +static uv_udp_send_t* send_alloc(void) { + uv_udp_send_t* req = send_freelist; + if (req != NULL) + send_freelist = req->data; + else + req = malloc(sizeof(*req)); + return req; +} -static void on_send(uv_udp_send_t* req, int status); - +static void on_send(uv_udp_send_t* req, int status) { + ASSERT(req != NULL); + ASSERT(status == 0); + req->data = send_freelist; + send_freelist = req; +} static void on_recv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* rcvbuf, const struct sockaddr* addr, unsigned flags) { - uv_udp_send_t* req; uv_buf_t sndbuf; + if (nread == 0) { + /* Everything OK, but nothing read. */ + return; + } + ASSERT(nread > 0); ASSERT(addr->sa_family == AF_INET); - req = malloc(sizeof(*req)); + uv_udp_send_t* req = send_alloc(); ASSERT(req != NULL); - - sndbuf = *rcvbuf; - ASSERT(0 == uv_udp_send(req, handle, &sndbuf, 1, addr, on_send)); -} - - -static void on_send(uv_udp_send_t* req, int status) { - ASSERT(status == 0); - free(req); + sndbuf = uv_buf_init(rcvbuf->base, nread); + ASSERT(0 <= uv_udp_send(req, handle, &sndbuf, 1, addr, on_send)); } - static int tcp4_echo_start(int port) { struct sockaddr_in addr; int r; @@ -277,8 +294,10 @@ static int tcp6_echo_start(int port) { static int udp4_echo_start(int port) { + struct sockaddr_in addr; int r; + ASSERT(0 == uv_ip4_addr("127.0.0.1", port, &addr)); server = (uv_handle_t*)&udpServer; serverType = UDP; @@ -288,7 +307,13 @@ static int udp4_echo_start(int port) { return 1; } - r = uv_udp_recv_start(&udpServer, echo_alloc, on_recv); + r = uv_udp_bind(&udpServer, (const struct sockaddr*) &addr, 0); + if (r) { + fprintf(stderr, "uv_udp_bind: %s\n", uv_strerror(r)); + return 1; + } + + r = uv_udp_recv_start(&udpServer, slab_alloc, on_recv); if (r) { fprintf(stderr, "uv_udp_recv_start: %s\n", uv_strerror(r)); return 1; diff --git a/deps/uv/test/run-benchmarks.c b/deps/uv/test/run-benchmarks.c index 6e42623d54cdec..980c9be8c12aa6 100644 --- a/deps/uv/test/run-benchmarks.c +++ b/deps/uv/test/run-benchmarks.c @@ -33,8 +33,7 @@ static int maybe_run_test(int argc, char **argv); int main(int argc, char **argv) { - if (platform_init(argc, argv)) - return EXIT_FAILURE; + platform_init(argc, argv); switch (argc) { case 1: return run_tests(1); diff --git a/deps/uv/test/run-tests.c b/deps/uv/test/run-tests.c index 2aad6a522ff5e3..e5e75e17c87e22 100644 --- a/deps/uv/test/run-tests.c +++ b/deps/uv/test/run-tests.c @@ -45,6 +45,7 @@ int ipc_helper_bind_twice(void); int ipc_helper_send_zero(void); int stdio_over_pipes_helper(void); void spawn_stdin_stdout(void); +void process_title_big_argv(void); int spawn_tcp_server_helper(void); static int maybe_run_test(int argc, char **argv); @@ -58,9 +59,7 @@ int main(int argc, char **argv) { } #endif - if (platform_init(argc, argv)) - return EXIT_FAILURE; - + platform_init(argc, argv); argv = uv_setup_args(argc, argv); switch (argc) { @@ -210,7 +209,11 @@ static int maybe_run_test(int argc, char **argv) { notify_parent_process(); ASSERT(sizeof(fd) == read(0, &fd, sizeof(fd))); ASSERT(fd > 2); +# if defined(__PASE__) /* On IBMi PASE, write() returns 1 */ + ASSERT(1 == write(fd, "x", 1)); +# else ASSERT(-1 == write(fd, "x", 1)); +# endif /* !__PASE__ */ return 1; } @@ -235,5 +238,11 @@ static int maybe_run_test(int argc, char **argv) { } #endif /* !_WIN32 */ + if (strcmp(argv[1], "process_title_big_argv_helper") == 0) { + notify_parent_process(); + process_title_big_argv(); + return 0; + } + return run_test(argv[1], 0, 1); } diff --git a/deps/uv/test/runner-unix.c b/deps/uv/test/runner-unix.c index dbb33bfa3edfd2..b7ca1f857ec1e4 100644 --- a/deps/uv/test/runner-unix.c +++ b/deps/uv/test/runner-unix.c @@ -26,7 +26,7 @@ #include /* uintptr_t */ #include -#include /* readlink, usleep */ +#include /* usleep */ #include /* strdup */ #include #include @@ -67,18 +67,12 @@ void notify_parent_process(void) { /* Do platform-specific initialization. */ -int platform_init(int argc, char **argv) { +void platform_init(int argc, char **argv) { /* Disable stdio output buffering. */ setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); signal(SIGPIPE, SIG_IGN); - - if (realpath(argv[0], executable_path) == NULL) { - perror("realpath"); - return -1; - } - - return 0; + snprintf(executable_path, sizeof(executable_path), "%s", argv[0]); } diff --git a/deps/uv/test/runner-win.c b/deps/uv/test/runner-win.c index e69b7447dcee0c..8c2a00b8a620c2 100644 --- a/deps/uv/test/runner-win.c +++ b/deps/uv/test/runner-win.c @@ -43,7 +43,7 @@ /* Do platform-specific initialization. */ -int platform_init(int argc, char **argv) { +void platform_init(int argc, char **argv) { /* Disable the "application crashed" popup. */ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); @@ -67,8 +67,6 @@ int platform_init(int argc, char **argv) { setvbuf(stderr, NULL, _IONBF, 0); strcpy(executable_path, argv[0]); - - return 0; } diff --git a/deps/uv/test/runner.c b/deps/uv/test/runner.c index a0f5df8947bac8..bb50b43b304ab6 100644 --- a/deps/uv/test/runner.c +++ b/deps/uv/test/runner.c @@ -20,6 +20,7 @@ */ #include +#include #include #include "runner.h" @@ -167,6 +168,7 @@ int run_test(const char* test, process_info_t processes[1024]; process_info_t *main_proc; task_entry_t* task; + int timeout_multiplier; int process_count; int result; int status; @@ -249,7 +251,22 @@ int run_test(const char* test, goto out; } - result = process_wait(main_proc, 1, task->timeout); + timeout_multiplier = 1; +#ifndef _WIN32 + do { + const char* var; + + var = getenv("UV_TEST_TIMEOUT_MULTIPLIER"); + if (var == NULL) + break; + + timeout_multiplier = atoi(var); + if (timeout_multiplier <= 0) + timeout_multiplier = 1; + } while (0); +#endif + + result = process_wait(main_proc, 1, task->timeout * timeout_multiplier); if (result == -1) { FATAL("process_wait failed"); } else if (result == -2) { diff --git a/deps/uv/test/runner.h b/deps/uv/test/runner.h index 1a33950852de15..6801564f961c31 100644 --- a/deps/uv/test/runner.h +++ b/deps/uv/test/runner.h @@ -84,11 +84,7 @@ typedef struct { #define TEST_HELPER HELPER_ENTRY #define BENCHMARK_HELPER HELPER_ENTRY -#ifdef PATH_MAX -extern char executable_path[PATH_MAX]; -#else extern char executable_path[4096]; -#endif /* * Include platform-dependent definitions @@ -136,7 +132,7 @@ void print_lines(const char* buffer, size_t size, FILE* stream); */ /* Do platform-specific initialization. */ -int platform_init(int argc, char** argv); +void platform_init(int argc, char** argv); /* Invoke "argv[0] test-name [test-part]". Store process info in *p. Make sure * that all stdio output of the processes is buffered up. */ diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h index 13105d0bd94a4d..27b731032e10b3 100644 --- a/deps/uv/test/task.h +++ b/deps/uv/test/task.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include #if defined(_MSC_VER) && _MSC_VER < 1600 # include "uv/stdint-msvc2008.h" @@ -109,6 +111,118 @@ typedef enum { } \ } while (0) +#define ASSERT_BASE(expr, a, operator, b, type, conv) \ + do { \ + if (!(expr)) { \ + fprintf(stderr, \ + "Assertion failed in %s on line %d: `%s %s %s` " \ + "(%"conv" %s %"conv")\n", \ + __FILE__, \ + __LINE__, \ + #a, \ + #operator, \ + #b, \ + (type)a, \ + #operator, \ + (type)b); \ + abort(); \ + } \ + } while (0) + +#define ASSERT_BASE_LEN(expr, a, operator, b, conv, len) \ + do { \ + if (!(expr)) { \ + fprintf(stderr, \ + "Assertion failed in %s on line %d: `%s %s %s` " \ + "(%.*"#conv" %s %.*"#conv")\n", \ + __FILE__, \ + __LINE__, \ + #a, \ + #operator, \ + #b, \ + (int)len, \ + a, \ + #operator, \ + (int)len, \ + b); \ + abort(); \ + } \ + } while (0) + +#define ASSERT_BASE_HEX(expr, a, operator, b, size) \ + do { \ + if (!(expr)) { \ + int i; \ + unsigned char* a_ = (unsigned char*)a; \ + unsigned char* b_ = (unsigned char*)b; \ + fprintf(stderr, \ + "Assertion failed in %s on line %d: `%s %s %s` (", \ + __FILE__, \ + __LINE__, \ + #a, \ + #operator, \ + #b); \ + for (i = 0; i < size; ++i) { \ + if (i > 0) fprintf(stderr, ":"); \ + fprintf(stderr, "%02X", a_[i]); \ + } \ + fprintf(stderr, " %s ", #operator); \ + for (i = 0; i < size; ++i) { \ + if (i > 0) fprintf(stderr, ":"); \ + fprintf(stderr, "%02X", b_[i]); \ + } \ + fprintf(stderr, ")\n"); \ + abort(); \ + } \ + } while (0) + +#define ASSERT_INT_BASE(a, operator, b, type, conv) \ + ASSERT_BASE(a operator b, a, operator, b, type, conv) + +#define ASSERT_EQ(a, b) ASSERT_INT_BASE(a, ==, b, int64_t, PRId64) +#define ASSERT_GE(a, b) ASSERT_INT_BASE(a, >=, b, int64_t, PRId64) +#define ASSERT_GT(a, b) ASSERT_INT_BASE(a, >, b, int64_t, PRId64) +#define ASSERT_LE(a, b) ASSERT_INT_BASE(a, <=, b, int64_t, PRId64) +#define ASSERT_LT(a, b) ASSERT_INT_BASE(a, <, b, int64_t, PRId64) +#define ASSERT_NE(a, b) ASSERT_INT_BASE(a, !=, b, int64_t, PRId64) + +#define ASSERT_UINT64_EQ(a, b) ASSERT_INT_BASE(a, ==, b, uint64_t, PRIu64) +#define ASSERT_UINT64_GE(a, b) ASSERT_INT_BASE(a, >=, b, uint64_t, PRIu64) +#define ASSERT_UINT64_GT(a, b) ASSERT_INT_BASE(a, >, b, uint64_t, PRIu64) +#define ASSERT_UINT64_LE(a, b) ASSERT_INT_BASE(a, <=, b, uint64_t, PRIu64) +#define ASSERT_UINT64_LT(a, b) ASSERT_INT_BASE(a, <, b, uint64_t, PRIu64) +#define ASSERT_UINT64_NE(a, b) ASSERT_INT_BASE(a, !=, b, uint64_t, PRIu64) + +#define ASSERT_STR_EQ(a, b) \ + ASSERT_BASE(strcmp(a, b) == 0, a, ==, b, char*, "s") + +#define ASSERT_STR_NE(a, b) \ + ASSERT_BASE(strcmp(a, b) != 0, a, !=, b, char*, "s") + +#define ASSERT_MEM_EQ(a, b, size) \ + ASSERT_BASE_LEN(memcmp(a, b, size) == 0, a, ==, b, s, size) + +#define ASSERT_MEM_NE(a, b, size) \ + ASSERT_BASE_LEN(memcmp(a, b, size) != 0, a, !=, b, s, size) + +#define ASSERT_MEM_HEX_EQ(a, b, size) \ + ASSERT_BASE_HEX(memcmp(a, b, size) == 0, a, ==, b, size) + +#define ASSERT_MEM_HEX_NE(a, b, size) \ + ASSERT_BASE_HEX(memcmp(a, b, size) != 0, a, !=, b, size) + +#define ASSERT_NULL(a) \ + ASSERT_BASE(a == NULL, a, ==, NULL, void*, "p") + +#define ASSERT_NOT_NULL(a) \ + ASSERT_BASE(a != NULL, a, !=, NULL, void*, "p") + +#define ASSERT_PTR_EQ(a, b) \ + ASSERT_BASE((void*)a == (void*)b, a, ==, b, void*, "p") + +#define ASSERT_PTR_NE(a, b) \ + ASSERT_BASE((void*)a != (void*)b, a, !=, b, void*, "p") + /* This macro cleans up the main loop. This is used to avoid valgrind * warnings about memory being "leaked" by the main event loop. */ diff --git a/deps/uv/test/test-cwd-and-chdir.c b/deps/uv/test/test-cwd-and-chdir.c index 5d43524c921cdd..faeed021030e83 100644 --- a/deps/uv/test/test-cwd-and-chdir.c +++ b/deps/uv/test/test-cwd-and-chdir.c @@ -23,8 +23,7 @@ #include "task.h" #include -#define PATHMAX 1024 -extern char executable_path[]; +#define PATHMAX 4096 TEST_IMPL(cwd_and_chdir) { char buffer_orig[PATHMAX]; diff --git a/deps/uv/test/test-fs-copyfile.c b/deps/uv/test/test-fs-copyfile.c index c3e698e5852cba..3335c881064ffd 100644 --- a/deps/uv/test/test-fs-copyfile.c +++ b/deps/uv/test/test-fs-copyfile.c @@ -199,8 +199,11 @@ TEST_IMPL(fs_copyfile) { touch_file(dst, 0); chmod(dst, S_IRUSR|S_IRGRP|S_IROTH); /* Sets file mode to 444 (read-only). */ r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL); + /* On IBMi PASE, qsecofr users can overwrite read-only files */ +# ifndef __PASE__ ASSERT(req.result == UV_EACCES); ASSERT(r == UV_EACCES); +# endif uv_fs_req_cleanup(&req); #endif diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c index e694d258ea9306..28a6a1ebb3f096 100644 --- a/deps/uv/test/test-fs-event.c +++ b/deps/uv/test/test-fs-event.c @@ -285,6 +285,12 @@ static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle, if (filename && strcmp(filename, file_prefix_in_subdir) == 0) return; #endif + /* It may happen that the "subdir" creation event is captured even though + * we started watching after its actual creation. + */ + if (strcmp(filename, "subdir") == 0) + return; + fs_multievent_cb_called++; ASSERT(handle == &fs_event); ASSERT(status == 0); @@ -300,11 +306,13 @@ static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle, sizeof(file_prefix_in_subdir) - 1) == 0); #endif - if (fs_event_created + fs_event_removed == fs_event_file_count) { + if (fs_event_created == fs_event_file_count && + fs_multievent_cb_called == fs_event_created) { /* Once we've processed all create events, delete all files */ ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files_in_subdir, 1, 0)); } else if (fs_multievent_cb_called == 2 * fs_event_file_count) { /* Once we've processed all create and delete events, stop watching */ + ASSERT(fs_event_removed == fs_event_file_count); uv_close((uv_handle_t*) &timer, close_cb); uv_close((uv_handle_t*) handle, close_cb); } diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 75cefe32d87edf..2966a53b79d349 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -55,7 +55,7 @@ #endif #define TOO_LONG_NAME_LENGTH 65536 -#define PATHMAX 1024 +#define PATHMAX 4096 typedef struct { const char* path; @@ -95,6 +95,7 @@ static int readlink_cb_count; static int realpath_cb_count; static int utime_cb_count; static int futime_cb_count; +static int lutime_cb_count; static int statfs_cb_count; static uv_loop_t* loop; @@ -309,6 +310,12 @@ static void chown_root_cb(uv_fs_t* req) { # if defined(__CYGWIN__) /* On Cygwin, uid 0 is invalid (no root). */ ASSERT(req->result == UV_EINVAL); +# elif defined(__PASE__) + /* On IBMi PASE, there is no root user. uid 0 is user qsecofr. + * User may grant qsecofr's privileges, including changing + * the file's ownership to uid 0. + */ + ASSERT(req->result == 0); # else ASSERT(req->result == UV_EPERM); # endif @@ -800,12 +807,19 @@ TEST_IMPL(fs_file_loop) { return 0; } -static void check_utime(const char* path, double atime, double mtime) { +static void check_utime(const char* path, + double atime, + double mtime, + int test_lutime) { uv_stat_t* s; uv_fs_t req; int r; - r = uv_fs_stat(loop, &req, path, NULL); + if (test_lutime) + r = uv_fs_lstat(loop, &req, path, NULL); + else + r = uv_fs_stat(loop, &req, path, NULL); + ASSERT(r == 0); ASSERT(req.result == 0); @@ -826,7 +840,7 @@ static void utime_cb(uv_fs_t* req) { ASSERT(req->fs_type == UV_FS_UTIME); c = req->data; - check_utime(c->path, c->atime, c->mtime); + check_utime(c->path, c->atime, c->mtime, /* test_lutime */ 0); uv_fs_req_cleanup(req); utime_cb_count++; @@ -841,13 +855,27 @@ static void futime_cb(uv_fs_t* req) { ASSERT(req->fs_type == UV_FS_FUTIME); c = req->data; - check_utime(c->path, c->atime, c->mtime); + check_utime(c->path, c->atime, c->mtime, /* test_lutime */ 0); uv_fs_req_cleanup(req); futime_cb_count++; } +static void lutime_cb(uv_fs_t* req) { + utime_check_t* c; + + ASSERT(req->result == 0); + ASSERT(req->fs_type == UV_FS_LUTIME); + + c = req->data; + check_utime(c->path, c->atime, c->mtime, /* test_lutime */ 1); + + uv_fs_req_cleanup(req); + lutime_cb_count++; +} + + TEST_IMPL(fs_file_async) { int r; @@ -2223,7 +2251,12 @@ int test_symlink_dir_impl(int type) { #ifdef _WIN32 ASSERT(((uv_stat_t*)req.ptr)->st_size == strlen(test_dir + 4)); #else +# ifdef __PASE__ + /* On IBMi PASE, st_size returns the length of the symlink itself. */ + ASSERT(((uv_stat_t*)req.ptr)->st_size == strlen("test_dir_symlink")); +# else ASSERT(((uv_stat_t*)req.ptr)->st_size == strlen(test_dir)); +# endif #endif uv_fs_req_cleanup(&req); @@ -2459,7 +2492,7 @@ TEST_IMPL(fs_utime) { r = uv_fs_stat(NULL, &req, path, NULL); ASSERT(r == 0); ASSERT(req.result == 0); - check_utime(path, atime, mtime); + check_utime(path, atime, mtime, /* test_lutime */ 0); uv_fs_req_cleanup(&req); atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */ @@ -2565,7 +2598,7 @@ TEST_IMPL(fs_futime) { r = uv_fs_stat(NULL, &req, path, NULL); ASSERT(r == 0); ASSERT(req.result == 0); - check_utime(path, atime, mtime); + check_utime(path, atime, mtime, /* test_lutime */ 0); uv_fs_req_cleanup(&req); atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */ @@ -2589,6 +2622,84 @@ TEST_IMPL(fs_futime) { } +TEST_IMPL(fs_lutime) { + utime_check_t checkme; + const char* path = "test_file"; + const char* symlink_path = "test_file_symlink"; + double atime; + double mtime; + uv_fs_t req; + int r, s; + + + /* Setup */ + loop = uv_default_loop(); + unlink(path); + r = uv_fs_open(NULL, &req, path, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL); + ASSERT(r >= 0); + ASSERT(req.result >= 0); + uv_fs_req_cleanup(&req); + uv_fs_close(loop, &req, r, NULL); + + unlink(symlink_path); + s = uv_fs_symlink(NULL, &req, path, symlink_path, 0, NULL); +#ifdef _WIN32 + if (s == UV_EPERM) { + /* + * Creating a symlink before Windows 10 Creators Update was only allowed + * when running elevated console (with admin rights) + */ + RETURN_SKIP( + "Symlink creation requires elevated console (with admin rights)"); + } +#endif + ASSERT(s == 0); + ASSERT(req.result == 0); + uv_fs_req_cleanup(&req); + + /* Test the synchronous version. */ + atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ + +#ifdef _WIN32 + mtime += 0.444; /* 1982-09-10 11:22:33.444 */ +#endif + + checkme.atime = atime; + checkme.mtime = mtime; + checkme.path = symlink_path; + req.data = &checkme; + + r = uv_fs_lutime(NULL, &req, symlink_path, atime, mtime, NULL); +#if (defined(_AIX) && !defined(_AIX71)) || \ + defined(__MVS__) + ASSERT(r == UV_ENOSYS); + RETURN_SKIP("lutime is not implemented for z/OS and AIX versions below 7.1"); +#endif + ASSERT(r == 0); + lutime_cb(&req); + ASSERT(lutime_cb_count == 1); + + /* Test the asynchronous version. */ + atime = mtime = 1291404900; /* 2010-12-03 20:35:00 */ + + checkme.atime = atime; + checkme.mtime = mtime; + checkme.path = symlink_path; + + r = uv_fs_lutime(loop, &req, symlink_path, atime, mtime, lutime_cb); + ASSERT(r == 0); + uv_run(loop, UV_RUN_DEFAULT); + ASSERT(lutime_cb_count == 2); + + /* Cleanup. */ + unlink(path); + unlink(symlink_path); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + TEST_IMPL(fs_stat_missing_path) { uv_fs_t req; int r; diff --git a/deps/uv/test/test-get-currentexe.c b/deps/uv/test/test-get-currentexe.c index 0e9d6965402daf..8c730334c205b3 100644 --- a/deps/uv/test/test-get-currentexe.c +++ b/deps/uv/test/test-get-currentexe.c @@ -23,28 +23,29 @@ #include "task.h" #include -#define PATHMAX 1024 +#ifndef _WIN32 +#include +#endif + +#define PATHMAX 4096 extern char executable_path[]; TEST_IMPL(get_currentexe) { char buffer[PATHMAX]; + char path[PATHMAX]; size_t size; char* match; - char* path; int r; size = sizeof(buffer) / sizeof(buffer[0]); r = uv_exepath(buffer, &size); ASSERT(!r); - /* uv_exepath can return an absolute path on darwin, so if the test runner - * was run with a relative prefix of "./", we need to strip that prefix off - * executable_path or we'll fail. */ - if (executable_path[0] == '.' && executable_path[1] == '/') { - path = executable_path + 2; - } else { - path = executable_path; - } +#ifdef _WIN32 + snprintf(path, sizeof(path), "%s", executable_path); +#else + ASSERT(NULL != realpath(executable_path, path)); +#endif match = strstr(buffer, path); /* Verify that the path returned from uv_exepath is a subdirectory of diff --git a/deps/uv/test/test-get-memory.c b/deps/uv/test/test-get-memory.c index 6a9a46dc81dcef..4555ba08895e7d 100644 --- a/deps/uv/test/test-get-memory.c +++ b/deps/uv/test/test-get-memory.c @@ -32,14 +32,13 @@ TEST_IMPL(get_memory) { (unsigned long long) total_mem, (unsigned long long) constrained_mem); - /* On IBMi PASE, the amount of memory in use includes storage used for - * memory and disks so it is possible to exceed the amount of main storage. - */ -#ifndef __PASE__ ASSERT(free_mem > 0); -#endif ASSERT(total_mem > 0); + /* On IBMi PASE, the amount of memory in use is always zero. */ +#ifdef __PASE__ + ASSERT(total_mem == free_mem); +#else ASSERT(total_mem > free_mem); - +#endif return 0; } diff --git a/deps/uv/test/test-get-passwd.c b/deps/uv/test/test-get-passwd.c index 8e16fb83c8f1b6..9b5273b315db6f 100644 --- a/deps/uv/test/test-get-passwd.c +++ b/deps/uv/test/test-get-passwd.c @@ -38,7 +38,9 @@ TEST_IMPL(get_passwd) { ASSERT(pwd.shell == NULL); #else len = strlen(pwd.shell); +# ifndef __PASE__ ASSERT(len > 0); +# endif #endif len = strlen(pwd.homedir); diff --git a/deps/uv/test/test-gethostname.c b/deps/uv/test/test-gethostname.c index ac636f0aba638b..1a9816d43c619e 100644 --- a/deps/uv/test/test-gethostname.c +++ b/deps/uv/test/test-gethostname.c @@ -51,7 +51,7 @@ TEST_IMPL(gethostname) { size = UV_MAXHOSTNAMESIZE; r = uv_os_gethostname(buf, &size); ASSERT(r == 0); - ASSERT(size > 1 && size == strlen(buf)); + ASSERT(size > 0 && size == strlen(buf)); ASSERT(size + 1 == enobufs_size); return 0; diff --git a/deps/uv/test/test-homedir.c b/deps/uv/test/test-homedir.c index 856534a40ceaa9..508351f72c0327 100644 --- a/deps/uv/test/test-homedir.c +++ b/deps/uv/test/test-homedir.c @@ -23,7 +23,7 @@ #include "task.h" #include -#define PATHMAX 1024 +#define PATHMAX 4096 #define SMALLPATH 1 TEST_IMPL(homedir) { diff --git a/deps/uv/test/test-ipc.c b/deps/uv/test/test-ipc.c index 8579a470292d31..39ef4f1175b0d4 100644 --- a/deps/uv/test/test-ipc.c +++ b/deps/uv/test/test-ipc.c @@ -79,16 +79,16 @@ static void on_connection(uv_stream_t* server, int status) { if (!local_conn_accepted) { /* Accept the connection and close it. Also and close the server. */ - ASSERT(status == 0); - ASSERT((uv_stream_t*)&tcp_server == server); + ASSERT_EQ(status, 0); + ASSERT_PTR_EQ(&tcp_server, server); conn = malloc(sizeof(*conn)); - ASSERT(conn); + ASSERT_NOT_NULL(conn); r = uv_tcp_init(server->loop, conn); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_accept(server, (uv_stream_t*)conn); - ASSERT(r == 0); + ASSERT_EQ(r, 0); uv_close((uv_handle_t*)conn, close_server_conn_cb); uv_close((uv_handle_t*)server, NULL); @@ -102,8 +102,8 @@ static void exit_cb(uv_process_t* process, int term_signal) { printf("exit_cb\n"); exit_cb_called++; - ASSERT(exit_status == 0); - ASSERT(term_signal == 0); + ASSERT_EQ(exit_status, 0); + ASSERT_EQ(term_signal, 0); uv_close((uv_handle_t*)process, NULL); } @@ -134,18 +134,17 @@ static void make_many_connections(void) { for (i = 0; i < CONN_COUNT; i++) { conn = malloc(sizeof(*conn)); - ASSERT(conn); + ASSERT_NOT_NULL(conn); r = uv_tcp_init(uv_default_loop(), &conn->conn); - ASSERT(r == 0); - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + ASSERT_EQ(r, 0); + ASSERT_EQ(0, uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); r = uv_tcp_connect(&conn->conn_req, (uv_tcp_t*) &conn->conn, (const struct sockaddr*) &addr, connect_cb); - ASSERT(r == 0); + ASSERT_EQ(r, 0); conn->conn.data = conn; } @@ -182,36 +181,38 @@ static void on_read(uv_stream_t* handle, pending = uv_pipe_pending_type(pipe); if (!tcp_server_listening) { - ASSERT(1 == uv_pipe_pending_count(pipe)); - ASSERT(nread > 0 && buf->base && pending != UV_UNKNOWN_HANDLE); + ASSERT_EQ(1, uv_pipe_pending_count(pipe)); + ASSERT_GT(nread, 0); + ASSERT_NOT_NULL(buf->base); + ASSERT_NE(pending, UV_UNKNOWN_HANDLE); read_cb_called++; /* Accept the pending TCP server, and start listening on it. */ - ASSERT(pending == UV_TCP); + ASSERT_EQ(pending, UV_TCP); r = uv_tcp_init(uv_default_loop(), &tcp_server); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, on_connection); - ASSERT(r == 0); + ASSERT_EQ(r, 0); tcp_server_listening = 1; /* Make sure that the expected data is correctly multiplexed. */ - ASSERT(memcmp("hello\n", buf->base, nread) == 0); + ASSERT_MEM_EQ("hello\n", buf->base, nread); outbuf = uv_buf_init("world\n", 6); r = uv_write(&write_req, (uv_stream_t*)pipe, &outbuf, 1, NULL); - ASSERT(r == 0); + ASSERT_EQ(r, 0); /* Create a bunch of connections to get both servers to accept. */ make_many_connections(); } else if (memcmp("accepted_connection\n", buf->base, nread) == 0) { /* Remote server has accepted a connection. Close the channel. */ - ASSERT(0 == uv_pipe_pending_count(pipe)); - ASSERT(pending == UV_UNKNOWN_HANDLE); + ASSERT_EQ(0, uv_pipe_pending_count(pipe)); + ASSERT_EQ(pending, UV_UNKNOWN_HANDLE); remote_conn_accepted = 1; uv_close((uv_handle_t*)&channel, NULL); } @@ -247,37 +248,39 @@ static void on_read_listen_after_bound_twice(uv_stream_t* handle, fprintf(stderr, "got %d bytes\n", (int)nread); - ASSERT(uv_pipe_pending_count(pipe) > 0); + ASSERT_GT(uv_pipe_pending_count(pipe), 0); pending = uv_pipe_pending_type(pipe); - ASSERT(nread > 0 && buf->base && pending != UV_UNKNOWN_HANDLE); + ASSERT_GT(nread, 0); + ASSERT_NOT_NULL(buf->base); + ASSERT_NE(pending, UV_UNKNOWN_HANDLE); read_cb_called++; if (read_cb_called == 1) { /* Accept the first TCP server, and start listening on it. */ - ASSERT(pending == UV_TCP); + ASSERT_EQ(pending, UV_TCP); r = uv_tcp_init(uv_default_loop(), &tcp_server); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, on_connection); - ASSERT(r == 0); + ASSERT_EQ(r, 0); } else if (read_cb_called == 2) { /* Accept the second TCP server, and start listening on it. */ - ASSERT(pending == UV_TCP); + ASSERT_EQ(pending, UV_TCP); r = uv_tcp_init(uv_default_loop(), &tcp_server2); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server2); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_listen((uv_stream_t*)&tcp_server2, BACKLOG, on_connection); - ASSERT(r == UV_EADDRINUSE); + ASSERT_EQ(r, UV_EADDRINUSE); uv_close((uv_handle_t*)&tcp_server, NULL); uv_close((uv_handle_t*)&tcp_server2, NULL); - ASSERT(0 == uv_pipe_pending_count(pipe)); + ASSERT_EQ(0, uv_pipe_pending_count(pipe)); uv_close((uv_handle_t*)&channel, NULL); } @@ -296,12 +299,12 @@ void spawn_helper(uv_pipe_t* channel, uv_stdio_container_t stdio[3]; r = uv_pipe_init(uv_default_loop(), channel, 1); - ASSERT(r == 0); - ASSERT(channel->ipc); + ASSERT_EQ(r, 0); + ASSERT_NE(channel->ipc, 0); exepath_size = sizeof(exepath); r = uv_exepath(exepath, &exepath_size); - ASSERT(r == 0); + ASSERT_EQ(r, 0); exepath[exepath_size] = '\0'; args[0] = exepath; @@ -323,13 +326,13 @@ void spawn_helper(uv_pipe_t* channel, stdio[2].data.fd = 2; r = uv_spawn(uv_default_loop(), process, &options); - ASSERT(r == 0); + ASSERT_EQ(r, 0); } static void on_tcp_write(uv_write_t* req, int status) { - ASSERT(status == 0); - ASSERT(req->handle == (uv_stream_t*)&tcp_connection); + ASSERT_EQ(status, 0); + ASSERT_PTR_EQ(req->handle, &tcp_connection); tcp_write_cb_called++; } @@ -343,9 +346,9 @@ static void on_read_alloc(uv_handle_t* handle, static void on_tcp_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { - ASSERT(nread > 0); - ASSERT(memcmp("hello again\n", buf->base, nread) == 0); - ASSERT(tcp == (uv_stream_t*)&tcp_connection); + ASSERT_GT(nread, 0); + ASSERT_MEM_EQ("hello again\n", buf->base, nread); + ASSERT_PTR_EQ(tcp, &tcp_connection); free(buf->base); tcp_read_cb_called++; @@ -382,31 +385,33 @@ static void on_read_connection(uv_stream_t* handle, fprintf(stderr, "got %d bytes\n", (int)nread); - ASSERT(1 == uv_pipe_pending_count(pipe)); + ASSERT_EQ(1, uv_pipe_pending_count(pipe)); pending = uv_pipe_pending_type(pipe); - ASSERT(nread > 0 && buf->base && pending != UV_UNKNOWN_HANDLE); + ASSERT_GT(nread, 0); + ASSERT_NOT_NULL(buf->base); + ASSERT_NE(pending, UV_UNKNOWN_HANDLE); read_cb_called++; /* Accept the pending TCP connection */ - ASSERT(pending == UV_TCP); + ASSERT_EQ(pending, UV_TCP); r = uv_tcp_init(uv_default_loop(), &tcp_connection); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_accept(handle, (uv_stream_t*)&tcp_connection); - ASSERT(r == 0); + ASSERT_EQ(r, 0); /* Make sure that the expected data is correctly multiplexed. */ - ASSERT(memcmp("hello\n", buf->base, nread) == 0); + ASSERT_MEM_EQ("hello\n", buf->base, nread); /* Write/read to/from the connection */ outbuf = uv_buf_init("world\n", 6); r = uv_write(&write_req, (uv_stream_t*)&tcp_connection, &outbuf, 1, on_tcp_write); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_read_start((uv_stream_t*)&tcp_connection, on_read_alloc, on_tcp_read); - ASSERT(r == 0); + ASSERT_EQ(r, 0); free(buf->base); } @@ -448,7 +453,7 @@ static int run_ipc_test(const char* helper, uv_read_cb read_cb) { uv_read_start((uv_stream_t*)&channel, on_alloc, read_cb); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); + ASSERT_EQ(r, 0); MAKE_VALGRIND_HAPPY(); return 0; @@ -460,10 +465,10 @@ TEST_IMPL(ipc_listen_before_write) { RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE); #endif int r = run_ipc_test("ipc_helper_listen_before_write", on_read); - ASSERT(local_conn_accepted == 1); - ASSERT(remote_conn_accepted == 1); - ASSERT(read_cb_called == 1); - ASSERT(exit_cb_called == 1); + ASSERT_EQ(local_conn_accepted, 1); + ASSERT_EQ(remote_conn_accepted, 1); + ASSERT_EQ(read_cb_called, 1); + ASSERT_EQ(exit_cb_called, 1); return r; } @@ -473,10 +478,10 @@ TEST_IMPL(ipc_listen_after_write) { RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE); #endif int r = run_ipc_test("ipc_helper_listen_after_write", on_read); - ASSERT(local_conn_accepted == 1); - ASSERT(remote_conn_accepted == 1); - ASSERT(read_cb_called == 1); - ASSERT(exit_cb_called == 1); + ASSERT_EQ(local_conn_accepted, 1); + ASSERT_EQ(remote_conn_accepted, 1); + ASSERT_EQ(read_cb_called, 1); + ASSERT_EQ(exit_cb_called, 1); return r; } @@ -486,10 +491,10 @@ TEST_IMPL(ipc_tcp_connection) { RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE); #endif int r = run_ipc_test("ipc_helper_tcp_connection", on_read_connection); - ASSERT(read_cb_called == 1); - ASSERT(tcp_write_cb_called == 1); - ASSERT(tcp_read_cb_called == 1); - ASSERT(exit_cb_called == 1); + ASSERT_EQ(read_cb_called, 1); + ASSERT_EQ(tcp_write_cb_called, 1); + ASSERT_EQ(tcp_read_cb_called, 1); + ASSERT_EQ(exit_cb_called, 1); return r; } @@ -497,7 +502,7 @@ TEST_IMPL(ipc_tcp_connection) { TEST_IMPL(ipc_closed_handle) { int r; r = run_ipc_test("ipc_helper_closed_handle", on_read_closed_handle); - ASSERT(r == 0); + ASSERT_EQ(r, 0); return 0; } #endif @@ -509,20 +514,20 @@ TEST_IMPL(listen_with_simultaneous_accepts) { int r; struct sockaddr_in addr; - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); + ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_tcp_simultaneous_accepts(&server, 1); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL); - ASSERT(r == 0); - ASSERT(server.reqs_pending == 32); + ASSERT_EQ(r, 0); + ASSERT_EQ(server.reqs_pending, 32); MAKE_VALGRIND_HAPPY(); return 0; @@ -534,20 +539,20 @@ TEST_IMPL(listen_no_simultaneous_accepts) { int r; struct sockaddr_in addr; - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); + ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_tcp_simultaneous_accepts(&server, 0); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL); - ASSERT(r == 0); - ASSERT(server.reqs_pending == 1); + ASSERT_EQ(r, 0); + ASSERT_EQ(server.reqs_pending, 1); MAKE_VALGRIND_HAPPY(); return 0; @@ -558,8 +563,8 @@ TEST_IMPL(ipc_listen_after_bind_twice) { RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE); #endif int r = run_ipc_test("ipc_helper_bind_twice", on_read_listen_after_bound_twice); - ASSERT(read_cb_called == 2); - ASSERT(exit_cb_called == 1); + ASSERT_EQ(read_cb_called, 2); + ASSERT_EQ(exit_cb_called, 1); return r; } #endif @@ -567,7 +572,7 @@ TEST_IMPL(ipc_listen_after_bind_twice) { TEST_IMPL(ipc_send_zero) { int r; r = run_ipc_test("ipc_helper_send_zero", on_read_send_zero); - ASSERT(r == 0); + ASSERT_EQ(r, 0); return 0; } @@ -589,7 +594,7 @@ static void conn_notify_write_cb(uv_write_t* req, int status) { static void tcp_connection_write_cb(uv_write_t* req, int status) { - ASSERT((uv_handle_t*)&conn.conn == (uv_handle_t*)req->handle); + ASSERT_PTR_EQ(&conn.conn, req->handle); uv_close((uv_handle_t*)req->handle, close_cb); uv_close((uv_handle_t*)&channel, close_cb); uv_close((uv_handle_t*)&tcp_server, close_cb); @@ -598,7 +603,7 @@ static void tcp_connection_write_cb(uv_write_t* req, int status) { static void closed_handle_large_write_cb(uv_write_t* req, int status) { - ASSERT(status == 0); + ASSERT_EQ(status, 0); ASSERT(closed_handle_data_read = LARGE_SIZE); if (++write_reqs_completed == ARRAY_SIZE(write_reqs)) { write_reqs_completed = 0; @@ -609,13 +614,13 @@ static void closed_handle_large_write_cb(uv_write_t* req, int status) { static void closed_handle_write_cb(uv_write_t* req, int status) { - ASSERT(status == UV_EBADF); + ASSERT_EQ(status, UV_EBADF); closed_handle_write = 1; } static void send_zero_write_cb(uv_write_t* req, int status) { - ASSERT(status == 0); + ASSERT_EQ(status, 0); send_zero_write++; } @@ -635,15 +640,15 @@ static void on_tcp_child_process_read(uv_stream_t* tcp, abort(); } - ASSERT(nread > 0); - ASSERT(memcmp("world\n", buf->base, nread) == 0); + ASSERT_GT(nread, 0); + ASSERT_MEM_EQ("world\n", buf->base, nread); on_pipe_read_called++; free(buf->base); /* Write to the socket */ outbuf = uv_buf_init("hello again\n", 12); r = uv_write(&conn.tcp_write_req, tcp, &outbuf, 1, tcp_connection_write_cb); - ASSERT(r == 0); + ASSERT_EQ(r, 0); tcp_conn_read_cb_called++; } @@ -652,9 +657,9 @@ static void on_tcp_child_process_read(uv_stream_t* tcp, static void connect_child_process_cb(uv_connect_t* req, int status) { int r; - ASSERT(status == 0); + ASSERT_EQ(status, 0); r = uv_read_start(req->handle, on_read_alloc, on_tcp_child_process_read); - ASSERT(r == 0); + ASSERT_EQ(r, 0); } @@ -667,21 +672,21 @@ static void ipc_on_connection(uv_stream_t* server, int status) { * Accept the connection and close it. Also let the other * side know. */ - ASSERT(status == 0); - ASSERT((uv_stream_t*)&tcp_server == server); + ASSERT_EQ(status, 0); + ASSERT_PTR_EQ(&tcp_server, server); r = uv_tcp_init(server->loop, &conn.conn); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_accept(server, (uv_stream_t*)&conn.conn); - ASSERT(r == 0); + ASSERT_EQ(r, 0); uv_close((uv_handle_t*)&conn.conn, close_cb); buf = uv_buf_init("accepted_connection\n", 20); r = uv_write2(&conn_notify_req, (uv_stream_t*)&channel, &buf, 1, NULL, conn_notify_write_cb); - ASSERT(r == 0); + ASSERT_EQ(r, 0); connection_accepted = 1; } @@ -693,28 +698,28 @@ static void ipc_on_connection_tcp_conn(uv_stream_t* server, int status) { uv_buf_t buf; uv_tcp_t* conn; - ASSERT(status == 0); - ASSERT((uv_stream_t*)&tcp_server == server); + ASSERT_EQ(status, 0); + ASSERT_PTR_EQ(&tcp_server, server); conn = malloc(sizeof(*conn)); - ASSERT(conn); + ASSERT_NOT_NULL(conn); r = uv_tcp_init(server->loop, conn); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_accept(server, (uv_stream_t*)conn); - ASSERT(r == 0); + ASSERT_EQ(r, 0); /* Send the accepted connection to the other process */ buf = uv_buf_init("hello\n", 6); r = uv_write2(&conn_notify_req, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)conn, NULL); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_read_start((uv_stream_t*) conn, on_read_alloc, on_tcp_child_process_read); - ASSERT(r == 0); + ASSERT_EQ(r, 0); uv_close((uv_handle_t*)conn, close_cb); } @@ -729,44 +734,44 @@ int ipc_helper(int listen_after_write) { int r; uv_buf_t buf; - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); + ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_pipe_init(uv_default_loop(), &channel, 1); - ASSERT(r == 0); + ASSERT_EQ(r, 0); uv_pipe_open(&channel, 0); - ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); - ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); - ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); + ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel)); + ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel)); + ASSERT_EQ(0, uv_is_closing((uv_handle_t*) &channel)); r = uv_tcp_init(uv_default_loop(), &tcp_server); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); + ASSERT_EQ(r, 0); if (!listen_after_write) { r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection); - ASSERT(r == 0); + ASSERT_EQ(r, 0); } buf = uv_buf_init("hello\n", 6); r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server, NULL); - ASSERT(r == 0); + ASSERT_EQ(r, 0); if (listen_after_write) { r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection); - ASSERT(r == 0); + ASSERT_EQ(r, 0); } notify_parent_process(); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); + ASSERT_EQ(r, 0); - ASSERT(connection_accepted == 1); - ASSERT(close_cb_called == 3); + ASSERT_EQ(connection_accepted, 1); + ASSERT_EQ(close_cb_called, 3); MAKE_VALGRIND_HAPPY(); return 0; @@ -783,43 +788,43 @@ int ipc_helper_tcp_connection(void) { struct sockaddr_in addr; r = uv_pipe_init(uv_default_loop(), &channel, 1); - ASSERT(r == 0); + ASSERT_EQ(r, 0); uv_pipe_open(&channel, 0); - ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); - ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); - ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); + ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel)); + ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel)); + ASSERT_EQ(0, uv_is_closing((uv_handle_t*) &channel)); r = uv_tcp_init(uv_default_loop(), &tcp_server); - ASSERT(r == 0); + ASSERT_EQ(r, 0); - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); + ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection_tcp_conn); - ASSERT(r == 0); + ASSERT_EQ(r, 0); /* Make a connection to the server */ r = uv_tcp_init(uv_default_loop(), &conn.conn); - ASSERT(r == 0); + ASSERT_EQ(r, 0); - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + ASSERT_EQ(0, uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); r = uv_tcp_connect(&conn.conn_req, (uv_tcp_t*) &conn.conn, (const struct sockaddr*) &addr, connect_child_process_cb); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); + ASSERT_EQ(r, 0); - ASSERT(tcp_conn_read_cb_called == 1); - ASSERT(tcp_conn_write_cb_called == 1); - ASSERT(close_cb_called == 4); + ASSERT_EQ(tcp_conn_read_cb_called, 1); + ASSERT_EQ(tcp_conn_write_cb_called, 1); + ASSERT_EQ(close_cb_called, 4); MAKE_VALGRIND_HAPPY(); return 0; @@ -836,7 +841,7 @@ static unsigned int write_until_data_queued() { &large_buf, 1, closed_handle_large_write_cb); - ASSERT(r == 0); + ASSERT_EQ(r, 0); i++; } while (channel.write_queue_size == 0 && i < ARRAY_SIZE(write_reqs)); @@ -849,12 +854,12 @@ static void send_handle_and_close() { struct sockaddr_in addr; r = uv_tcp_init(uv_default_loop(), &tcp_server); - ASSERT(r == 0); + ASSERT_EQ(r, 0); - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); + ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_write2(&write_req, (uv_stream_t*)&channel, @@ -862,7 +867,7 @@ static void send_handle_and_close() { 1, (uv_stream_t*)&tcp_server, closed_handle_write_cb); - ASSERT(r == 0); + ASSERT_EQ(r, 0); uv_close((uv_handle_t*)&tcp_server, NULL); } @@ -874,21 +879,21 @@ int ipc_helper_closed_handle(void) { large_buf = uv_buf_init(buffer, LARGE_SIZE); r = uv_pipe_init(uv_default_loop(), &channel, 1); - ASSERT(r == 0); + ASSERT_EQ(r, 0); uv_pipe_open(&channel, 0); - ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); - ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); - ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); + ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel)); + ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel)); + ASSERT_EQ(0, uv_is_closing((uv_handle_t*) &channel)); if (write_until_data_queued() > 0) send_handle_and_close(); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); + ASSERT_EQ(r, 0); - ASSERT(closed_handle_write == 1); + ASSERT_EQ(closed_handle_write, 1); MAKE_VALGRIND_HAPPY(); return 0; @@ -904,38 +909,38 @@ int ipc_helper_bind_twice(void) { int r; uv_buf_t buf; - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); + ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_pipe_init(uv_default_loop(), &channel, 1); - ASSERT(r == 0); + ASSERT_EQ(r, 0); uv_pipe_open(&channel, 0); - ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); - ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); - ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); + ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel)); + ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel)); + ASSERT_EQ(0, uv_is_closing((uv_handle_t*) &channel)); buf = uv_buf_init("hello\n", 6); r = uv_tcp_init(uv_default_loop(), &tcp_server); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_tcp_init(uv_default_loop(), &tcp_server2); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_tcp_bind(&tcp_server2, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server, NULL); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_write2(&write_req2, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server2, NULL); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); + ASSERT_EQ(r, 0); MAKE_VALGRIND_HAPPY(); return 0; @@ -948,13 +953,13 @@ int ipc_helper_send_zero(void) { zero_buf = uv_buf_init(0, 0); r = uv_pipe_init(uv_default_loop(), &channel, 0); - ASSERT(r == 0); + ASSERT_EQ(r, 0); uv_pipe_open(&channel, 0); - ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); - ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); - ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); + ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel)); + ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel)); + ASSERT_EQ(0, uv_is_closing((uv_handle_t*) &channel)); r = uv_write(&write_req, (uv_stream_t*)&channel, @@ -962,12 +967,12 @@ int ipc_helper_send_zero(void) { 1, send_zero_write_cb); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); + ASSERT_EQ(r, 0); - ASSERT(send_zero_write == 1); + ASSERT_EQ(send_zero_write, 1); MAKE_VALGRIND_HAPPY(); return 0; diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index a6cfc6bb9284bd..eb6665716f0718 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -56,10 +56,27 @@ TEST_DECLARE (tty_raw_cancel) TEST_DECLARE (tty_duplicate_vt100_fn_key) TEST_DECLARE (tty_duplicate_alt_modifier_key) TEST_DECLARE (tty_composing_character) +TEST_DECLARE (tty_cursor_up) +TEST_DECLARE (tty_cursor_down) +TEST_DECLARE (tty_cursor_forward) +TEST_DECLARE (tty_cursor_back) +TEST_DECLARE (tty_cursor_next_line) +TEST_DECLARE (tty_cursor_previous_line) +TEST_DECLARE (tty_cursor_horizontal_move_absolute) +TEST_DECLARE (tty_cursor_move_absolute) +TEST_DECLARE (tty_hide_show_cursor) +TEST_DECLARE (tty_set_cursor_shape) +TEST_DECLARE (tty_erase) +TEST_DECLARE (tty_erase_line) +TEST_DECLARE (tty_set_style) +TEST_DECLARE (tty_save_restore_cursor_position) +TEST_DECLARE (tty_full_reset) +TEST_DECLARE (tty_escape_sequence_processing) #endif TEST_DECLARE (tty_file) TEST_DECLARE (tty_pty) TEST_DECLARE (stdio_over_pipes) +TEST_DECLARE (stdio_emulate_iocp) TEST_DECLARE (ip6_pton) TEST_DECLARE (connect_unspecified) TEST_DECLARE (ipc_heavy_traffic_deadlock_bug) @@ -242,6 +259,7 @@ TEST_DECLARE (async_null_cb) TEST_DECLARE (eintr_handling) TEST_DECLARE (get_currentexe) TEST_DECLARE (process_title) +TEST_DECLARE (process_title_big_argv) TEST_DECLARE (process_title_threadsafe) TEST_DECLARE (cwd_and_chdir) TEST_DECLARE (get_memory) @@ -335,6 +353,7 @@ TEST_DECLARE (fs_fd_hash) #endif TEST_DECLARE (fs_utime) TEST_DECLARE (fs_futime) +TEST_DECLARE (fs_lutime) TEST_DECLARE (fs_file_open_append) TEST_DECLARE (fs_statfs) TEST_DECLARE (fs_stat_missing_path) @@ -453,6 +472,7 @@ TEST_DECLARE (we_get_signal_one_shot) TEST_DECLARE (we_get_signals_mixed) TEST_DECLARE (signal_multiple_loops) TEST_DECLARE (signal_pending_on_close) +TEST_DECLARE (signal_close_loop_alive) TEST_DECLARE (closed_fd_events) #endif #ifdef __APPLE__ @@ -545,10 +565,27 @@ TASK_LIST_START TEST_ENTRY (tty_duplicate_vt100_fn_key) TEST_ENTRY (tty_duplicate_alt_modifier_key) TEST_ENTRY (tty_composing_character) + TEST_ENTRY (tty_cursor_up) + TEST_ENTRY (tty_cursor_down) + TEST_ENTRY (tty_cursor_forward) + TEST_ENTRY (tty_cursor_back) + TEST_ENTRY (tty_cursor_next_line) + TEST_ENTRY (tty_cursor_previous_line) + TEST_ENTRY (tty_cursor_horizontal_move_absolute) + TEST_ENTRY (tty_cursor_move_absolute) + TEST_ENTRY (tty_hide_show_cursor) + TEST_ENTRY (tty_set_cursor_shape) + TEST_ENTRY (tty_erase) + TEST_ENTRY (tty_erase_line) + TEST_ENTRY (tty_set_style) + TEST_ENTRY (tty_save_restore_cursor_position) + TEST_ENTRY (tty_full_reset) + TEST_ENTRY (tty_escape_sequence_processing) #endif TEST_ENTRY (tty_file) TEST_ENTRY (tty_pty) TEST_ENTRY (stdio_over_pipes) + TEST_ENTRY (stdio_emulate_iocp) TEST_ENTRY (ip6_pton) TEST_ENTRY (connect_unspecified) TEST_ENTRY (ipc_heavy_traffic_deadlock_bug) @@ -684,11 +721,9 @@ TASK_LIST_START TEST_ENTRY (udp_try_send) TEST_ENTRY (udp_open) - TEST_HELPER (udp_open, udp4_echo_server) TEST_ENTRY (udp_open_twice) TEST_ENTRY (udp_open_bound) TEST_ENTRY (udp_open_connect) - TEST_HELPER (udp_open_connect, udp4_echo_server) #ifndef _WIN32 TEST_ENTRY (udp_send_unix) #endif @@ -788,6 +823,7 @@ TASK_LIST_START TEST_ENTRY (get_currentexe) TEST_ENTRY (process_title) + TEST_ENTRY (process_title_big_argv) TEST_ENTRY (process_title_threadsafe) TEST_ENTRY (cwd_and_chdir) @@ -903,6 +939,7 @@ TASK_LIST_START TEST_ENTRY (we_get_signals_mixed) TEST_ENTRY (signal_multiple_loops) TEST_ENTRY (signal_pending_on_close) + TEST_ENTRY (signal_close_loop_alive) TEST_ENTRY (closed_fd_events) #endif @@ -933,6 +970,7 @@ TASK_LIST_START TEST_ENTRY (fs_chown) TEST_ENTRY (fs_utime) TEST_ENTRY (fs_futime) + TEST_ENTRY (fs_lutime) TEST_ENTRY (fs_readlink) TEST_ENTRY (fs_realpath) TEST_ENTRY (fs_symlink) diff --git a/deps/uv/test/test-poll.c b/deps/uv/test/test-poll.c index cc2b5fbe59de8c..b3308446f1d81f 100644 --- a/deps/uv/test/test-poll.c +++ b/deps/uv/test/test-poll.c @@ -222,7 +222,10 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) { case 1: { /* Read a couple of bytes. */ static char buffer[74]; - r = recv(context->sock, buffer, sizeof buffer, 0); + + do + r = recv(context->sock, buffer, sizeof buffer, 0); + while (r == -1 && errno == EINTR); ASSERT(r >= 0); if (r > 0) { @@ -240,12 +243,16 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) { case 3: { /* Read until EAGAIN. */ static char buffer[931]; - r = recv(context->sock, buffer, sizeof buffer, 0); - ASSERT(r >= 0); - while (r > 0) { + for (;;) { + do + r = recv(context->sock, buffer, sizeof buffer, 0); + while (r == -1 && errno == EINTR); + + if (r <= 0) + break; + context->read += r; - r = recv(context->sock, buffer, sizeof buffer, 0); } if (r == 0) { @@ -301,7 +308,9 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) { int send_bytes = MIN(TRANSFER_BYTES - context->sent, sizeof buffer); ASSERT(send_bytes > 0); - r = send(context->sock, buffer, send_bytes, 0); + do + r = send(context->sock, buffer, send_bytes, 0); + while (r == -1 && errno == EINTR); if (r < 0) { ASSERT(got_eagain()); @@ -323,7 +332,9 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) { int send_bytes = MIN(TRANSFER_BYTES - context->sent, sizeof buffer); ASSERT(send_bytes > 0); - r = send(context->sock, buffer, send_bytes, 0); + do + r = send(context->sock, buffer, send_bytes, 0); + while (r == -1 && errno == EINTR); if (r < 0) { ASSERT(got_eagain()); @@ -339,12 +350,18 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) { send_bytes = MIN(TRANSFER_BYTES - context->sent, sizeof buffer); ASSERT(send_bytes > 0); - r = send(context->sock, buffer, send_bytes, 0); + do + r = send(context->sock, buffer, send_bytes, 0); + while (r == -1 && errno == EINTR); + ASSERT(r != 0); + + if (r < 0) { + ASSERT(got_eagain()); + break; + } - if (r <= 0) break; context->sent += r; } - ASSERT(r > 0 || got_eagain()); break; } diff --git a/deps/uv/test/test-process-title-threadsafe.c b/deps/uv/test/test-process-title-threadsafe.c index 2f12b74e14f96f..3b4168be84c6b4 100644 --- a/deps/uv/test/test-process-title-threadsafe.c +++ b/deps/uv/test/test-process-title-threadsafe.c @@ -40,14 +40,23 @@ static const char* titles[] = { static void getter_thread_body(void* arg) { char buffer[512]; + size_t len; for (;;) { ASSERT(0 == uv_get_process_title(buffer, sizeof(buffer))); + + /* The maximum size of the process title on some platforms depends on + * the total size of the argv vector. It's therefore possible to read + * back a title that's shorter than what we submitted. + */ + len = strlen(buffer); + ASSERT_GT(len, 0); + ASSERT( - 0 == strcmp(buffer, titles[0]) || - 0 == strcmp(buffer, titles[1]) || - 0 == strcmp(buffer, titles[2]) || - 0 == strcmp(buffer, titles[3])); + 0 == strncmp(buffer, titles[0], len) || + 0 == strncmp(buffer, titles[1], len) || + 0 == strncmp(buffer, titles[2], len) || + 0 == strncmp(buffer, titles[3], len)); uv_sleep(0); } diff --git a/deps/uv/test/test-process-title.c b/deps/uv/test/test-process-title.c index b49f3bc4264410..35a14809fb3ccd 100644 --- a/deps/uv/test/test-process-title.c +++ b/deps/uv/test/test-process-title.c @@ -74,3 +74,62 @@ TEST_IMPL(process_title) { return 0; } + + +static void exit_cb(uv_process_t* process, int64_t status, int signo) { + ASSERT(status == 0); + ASSERT(signo == 0); + uv_close((uv_handle_t*) process, NULL); +} + + +TEST_IMPL(process_title_big_argv) { + uv_process_options_t options; + uv_process_t process; + size_t exepath_size; + char exepath[1024]; + char jumbo[512]; + char* args[5]; + +#ifdef _WIN32 + /* Remove once https://github.com/libuv/libuv/issues/2667 is fixed. */ + uv_set_process_title("run-tests"); +#endif + + exepath_size = sizeof(exepath) - 1; + ASSERT(0 == uv_exepath(exepath, &exepath_size)); + exepath[exepath_size] = '\0'; + + memset(jumbo, 'x', sizeof(jumbo) - 1); + jumbo[sizeof(jumbo) - 1] = '\0'; + + /* Note: need to pass three arguments, not two, otherwise + * run-tests.c thinks it's the name of a test to run. + */ + args[0] = exepath; + args[1] = "process_title_big_argv_helper"; + args[2] = jumbo; + args[3] = jumbo; + args[4] = NULL; + + memset(&options, 0, sizeof(options)); + options.file = exepath; + options.args = args; + options.exit_cb = exit_cb; + + ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options)); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +/* Called by process_title_big_argv_helper. */ +void process_title_big_argv(void) { + char buf[256] = "fail"; + + /* Return value deliberately ignored. */ + uv_get_process_title(buf, sizeof(buf)); + ASSERT(0 != strcmp(buf, "fail")); +} diff --git a/deps/uv/test/test-signal-pending-on-close.c b/deps/uv/test/test-signal-pending-on-close.c index bf8d2793d51f01..23b9ec8d16f1d4 100644 --- a/deps/uv/test/test-signal-pending-on-close.c +++ b/deps/uv/test/test-signal-pending-on-close.c @@ -34,6 +34,11 @@ static char* buf; static int close_cb_called; +static void stop_loop_cb(uv_signal_t* signal, int signum) { + ASSERT(signum == SIGPIPE); + uv_stop(signal->loop); +} + static void signal_cb(uv_signal_t* signal, int signum) { ASSERT(0); } @@ -91,4 +96,24 @@ TEST_IMPL(signal_pending_on_close) { return 0; } -#endif \ No newline at end of file + +TEST_IMPL(signal_close_loop_alive) { + ASSERT(0 == uv_loop_init(&loop)); + ASSERT(0 == uv_signal_init(&loop, &signal_hdl)); + ASSERT(0 == uv_signal_start(&signal_hdl, stop_loop_cb, SIGPIPE)); + uv_unref((uv_handle_t*) &signal_hdl); + + ASSERT(0 == uv_kill(uv_os_getpid(), SIGPIPE)); + ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT)); + uv_close((uv_handle_t*) &signal_hdl, close_cb); + ASSERT(1 == uv_loop_alive(&loop)); + + ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT)); + ASSERT(0 == uv_loop_close(&loop)); + ASSERT(1 == close_cb_called); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +#endif diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index be9e2539aa6562..314a3562b02034 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -236,13 +236,14 @@ TEST_IMPL(spawn_empty_env) { char* env[1]; /* The autotools dynamic library build requires the presence of - * DYLD_LIBARY_PATH (macOS) or LD_LIBRARY_PATH (other Unices) + * DYLD_LIBARY_PATH (macOS) or LD_LIBRARY_PATH/LIBPATH (other Unices) * in the environment, but of course that doesn't work with * the empty environment that we're testing here. */ if (NULL != getenv("DYLD_LIBRARY_PATH") || - NULL != getenv("LD_LIBRARY_PATH")) { - RETURN_SKIP("doesn't work with DYLD_LIBRARY_PATH/LD_LIBRARY_PATH"); + NULL != getenv("LD_LIBRARY_PATH") || + NULL != getenv("LIBPATH")) { + RETURN_SKIP("doesn't work with DYLD_LIBRARY_PATH/LD_LIBRARY_PATH/LIBPATH"); } init_process_options("spawn_helper1", exit_cb); @@ -1420,6 +1421,8 @@ TEST_IMPL(spawn_setuid_fails) { int r; /* if root, become nobody. */ + /* On IBMi PASE, there is no nobody user. */ +#ifndef __PASE__ uv_uid_t uid = getuid(); if (uid == 0) { struct passwd* pw; @@ -1428,11 +1431,19 @@ TEST_IMPL(spawn_setuid_fails) { ASSERT(0 == setgid(pw->pw_gid)); ASSERT(0 == setuid(pw->pw_uid)); } +#endif /* !__PASE__ */ init_process_options("spawn_helper1", fail_cb); options.flags |= UV_PROCESS_SETUID; + /* On IBMi PASE, there is no root user. User may grant + * root-like privileges, including setting uid to 0. + */ +#if defined(__PASE__) + options.uid = -1; +#else options.uid = 0; +#endif /* These flags should be ignored on Unices. */ options.flags |= UV_PROCESS_WINDOWS_HIDE; @@ -1441,7 +1452,7 @@ TEST_IMPL(spawn_setuid_fails) { options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS; r = uv_spawn(uv_default_loop(), &process, &options); -#if defined(__CYGWIN__) +#if defined(__CYGWIN__) || defined(__PASE__) ASSERT(r == UV_EINVAL); #else ASSERT(r == UV_EPERM); @@ -1461,6 +1472,8 @@ TEST_IMPL(spawn_setgid_fails) { int r; /* if root, become nobody. */ + /* On IBMi PASE, there is no nobody user. */ +#ifndef __PASE__ uv_uid_t uid = getuid(); if (uid == 0) { struct passwd* pw; @@ -1469,18 +1482,22 @@ TEST_IMPL(spawn_setgid_fails) { ASSERT(0 == setgid(pw->pw_gid)); ASSERT(0 == setuid(pw->pw_uid)); } +#endif /* !__PASE__ */ init_process_options("spawn_helper1", fail_cb); options.flags |= UV_PROCESS_SETGID; -#if defined(__MVS__) + /* On IBMi PASE, there is no root user. User may grant + * root-like privileges, including setting gid to 0. + */ +#if defined(__MVS__) || defined(__PASE__) options.gid = -1; #else options.gid = 0; #endif r = uv_spawn(uv_default_loop(), &process, &options); -#if defined(__CYGWIN__) || defined(__MVS__) +#if defined(__CYGWIN__) || defined(__MVS__) || defined(__PASE__) ASSERT(r == UV_EINVAL); #else ASSERT(r == UV_EPERM); diff --git a/deps/uv/test/test-stdio-over-pipes.c b/deps/uv/test/test-stdio-over-pipes.c index a130ff6a9bc0c1..1aed47122772ab 100644 --- a/deps/uv/test/test-stdio-over-pipes.c +++ b/deps/uv/test/test-stdio-over-pipes.c @@ -94,7 +94,7 @@ static void after_write(uv_write_t* req, int status) { } -static void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* rdbuf) { +static void on_read(uv_stream_t* pipe, ssize_t nread, const uv_buf_t* rdbuf) { uv_write_t* req; uv_buf_t wrbuf; int r; @@ -103,11 +103,11 @@ static void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* rdbuf) { if (nread > 0) { output_used += nread; - if (output_used == 12) { + if (output_used % 12 == 0) { ASSERT(memcmp("hello world\n", output, 12) == 0); - wrbuf = uv_buf_init(output, output_used); + wrbuf = uv_buf_init(output, 12); req = malloc(sizeof(*req)); - r = uv_write(req, (uv_stream_t*)&in, &wrbuf, 1, after_write); + r = uv_write(req, (uv_stream_t*) &in, &wrbuf, 1, after_write); ASSERT(r == 0); } } @@ -116,10 +116,10 @@ static void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* rdbuf) { } -TEST_IMPL(stdio_over_pipes) { +static void test_stdio_over_pipes(int overlapped) { int r; uv_process_t process; - uv_stdio_container_t stdio[2]; + uv_stdio_container_t stdio[3]; loop = uv_default_loop(); @@ -129,11 +129,15 @@ TEST_IMPL(stdio_over_pipes) { uv_pipe_init(loop, &in, 0); options.stdio = stdio; - options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; - options.stdio[0].data.stream = (uv_stream_t*)∈ - options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - options.stdio[1].data.stream = (uv_stream_t*)&out; - options.stdio_count = 2; + options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE | + (overlapped ? UV_OVERLAPPED_PIPE : 0); + options.stdio[0].data.stream = (uv_stream_t*) ∈ + options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE | + (overlapped ? UV_OVERLAPPED_PIPE : 0); + options.stdio[1].data.stream = (uv_stream_t*) &out; + options.stdio[2].flags = UV_INHERIT_FD; + options.stdio[2].data.fd = 2; + options.stdio_count = 3; r = uv_spawn(loop, &process, &options); ASSERT(r == 0); @@ -145,13 +149,22 @@ TEST_IMPL(stdio_over_pipes) { ASSERT(r == 0); ASSERT(on_read_cb_called > 1); - ASSERT(after_write_cb_called == 1); + ASSERT(after_write_cb_called == 2); ASSERT(exit_cb_called == 1); ASSERT(close_cb_called == 3); - ASSERT(memcmp("hello world\n", output, 12) == 0); - ASSERT(output_used == 12); + ASSERT(memcmp("hello world\nhello world\n", output, 24) == 0); + ASSERT(output_used == 24); MAKE_VALGRIND_HAPPY(); +} + +TEST_IMPL(stdio_over_pipes) { + test_stdio_over_pipes(0); + return 0; +} + +TEST_IMPL(stdio_emulate_iocp) { + test_stdio_over_pipes(1); return 0; } @@ -160,18 +173,19 @@ TEST_IMPL(stdio_over_pipes) { static int on_pipe_read_called; static int after_write_called; -static uv_pipe_t stdin_pipe; -static uv_pipe_t stdout_pipe; +static uv_pipe_t stdin_pipe1; +static uv_pipe_t stdout_pipe1; +static uv_pipe_t stdin_pipe2; +static uv_pipe_t stdout_pipe2; -static void on_pipe_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { +static void on_pipe_read(uv_stream_t* pipe, ssize_t nread, const uv_buf_t* buf) { ASSERT(nread > 0); ASSERT(memcmp("hello world\n", buf->base, nread) == 0); on_pipe_read_called++; free(buf->base); - uv_close((uv_handle_t*)&stdin_pipe, close_cb); - uv_close((uv_handle_t*)&stdout_pipe, close_cb); + uv_read_stop(pipe); } @@ -204,52 +218,81 @@ int stdio_over_pipes_helper(void) { uv_write_t write_req[ARRAY_SIZE(buffers)]; uv_buf_t buf[ARRAY_SIZE(buffers)]; unsigned int i; + int j; int r; uv_loop_t* loop = uv_default_loop(); ASSERT(UV_NAMED_PIPE == uv_guess_handle(0)); ASSERT(UV_NAMED_PIPE == uv_guess_handle(1)); - r = uv_pipe_init(loop, &stdin_pipe, 0); + r = uv_pipe_init(loop, &stdin_pipe1, 0); + ASSERT(r == 0); + r = uv_pipe_init(loop, &stdout_pipe1, 0); + ASSERT(r == 0); + r = uv_pipe_init(loop, &stdin_pipe2, 0); ASSERT(r == 0); - r = uv_pipe_init(loop, &stdout_pipe, 0); + r = uv_pipe_init(loop, &stdout_pipe2, 0); ASSERT(r == 0); - uv_pipe_open(&stdin_pipe, 0); - uv_pipe_open(&stdout_pipe, 1); + uv_pipe_open(&stdin_pipe1, 0); + uv_pipe_open(&stdout_pipe1, 1); + uv_pipe_open(&stdin_pipe2, 0); + uv_pipe_open(&stdout_pipe2, 1); - /* Unref both stdio handles to make sure that all writes complete. */ - uv_unref((uv_handle_t*)&stdin_pipe); - uv_unref((uv_handle_t*)&stdout_pipe); + for (j = 0; j < 2; j++) { + /* Unref both stdio handles to make sure that all writes complete. */ + uv_unref((uv_handle_t*) &stdin_pipe1); + uv_unref((uv_handle_t*) &stdout_pipe1); + uv_unref((uv_handle_t*) &stdin_pipe2); + uv_unref((uv_handle_t*) &stdout_pipe2); - for (i = 0; i < ARRAY_SIZE(buffers); i++) { - buf[i] = uv_buf_init((char*)buffers[i], strlen(buffers[i])); - } + for (i = 0; i < ARRAY_SIZE(buffers); i++) { + buf[i] = uv_buf_init((char*) buffers[i], strlen(buffers[i])); + } - for (i = 0; i < ARRAY_SIZE(buffers); i++) { - r = uv_write(&write_req[i], (uv_stream_t*)&stdout_pipe, &buf[i], 1, - after_pipe_write); - ASSERT(r == 0); - } + for (i = 0; i < ARRAY_SIZE(buffers); i++) { + r = uv_write(&write_req[i], + (uv_stream_t*) (j == 0 ? &stdout_pipe1 : &stdout_pipe2), + &buf[i], + 1, + after_pipe_write); + ASSERT(r == 0); + } - notify_parent_process(); - uv_run(loop, UV_RUN_DEFAULT); + notify_parent_process(); + uv_run(loop, UV_RUN_DEFAULT); - ASSERT(after_write_called == 7); - ASSERT(on_pipe_read_called == 0); - ASSERT(close_cb_called == 0); + ASSERT(after_write_called == 7 * (j + 1)); + ASSERT(on_pipe_read_called == j); + ASSERT(close_cb_called == 0); - uv_ref((uv_handle_t*)&stdout_pipe); - uv_ref((uv_handle_t*)&stdin_pipe); + uv_ref((uv_handle_t*) &stdout_pipe1); + uv_ref((uv_handle_t*) &stdin_pipe1); + uv_ref((uv_handle_t*) &stdout_pipe2); + uv_ref((uv_handle_t*) &stdin_pipe2); - r = uv_read_start((uv_stream_t*)&stdin_pipe, on_read_alloc, on_pipe_read); - ASSERT(r == 0); + r = uv_read_start((uv_stream_t*) (j == 0 ? &stdin_pipe1 : &stdin_pipe2), + on_read_alloc, + on_pipe_read); + ASSERT(r == 0); + + uv_run(loop, UV_RUN_DEFAULT); + + ASSERT(after_write_called == 7 * (j + 1)); + ASSERT(on_pipe_read_called == j + 1); + ASSERT(close_cb_called == 0); + } + + uv_close((uv_handle_t*)&stdin_pipe1, close_cb); + uv_close((uv_handle_t*)&stdout_pipe1, close_cb); + uv_close((uv_handle_t*)&stdin_pipe2, close_cb); + uv_close((uv_handle_t*)&stdout_pipe2, close_cb); uv_run(loop, UV_RUN_DEFAULT); - ASSERT(after_write_called == 7); - ASSERT(on_pipe_read_called == 1); - ASSERT(close_cb_called == 2); + ASSERT(after_write_called == 14); + ASSERT(on_pipe_read_called == 2); + ASSERT(close_cb_called == 4); MAKE_VALGRIND_HAPPY(); return 0; diff --git a/deps/uv/test/test-tmpdir.c b/deps/uv/test/test-tmpdir.c index dac488d05804e0..86f72e25431a15 100644 --- a/deps/uv/test/test-tmpdir.c +++ b/deps/uv/test/test-tmpdir.c @@ -23,7 +23,7 @@ #include "task.h" #include -#define PATHMAX 1024 +#define PATHMAX 4096 #define SMALLPATH 1 TEST_IMPL(tmpdir) { diff --git a/deps/uv/test/test-tty-escape-sequence-processing.c b/deps/uv/test/test-tty-escape-sequence-processing.c new file mode 100644 index 00000000000000..c4461e91e06cf9 --- /dev/null +++ b/deps/uv/test/test-tty-escape-sequence-processing.c @@ -0,0 +1,1621 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef _WIN32 + +#include "task.h" +#include "uv.h" + +#include +#include + +#include +#include + +#define ESC "\033" +#define CSI ESC "[" +#define ST ESC "\\" +#define BEL "\x07" +#define HELLO "Hello" + +#define FOREGROUND_WHITE (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) +#define FOREGROUND_BLACK 0 +#define FOREGROUND_YELLOW (FOREGROUND_RED | FOREGROUND_GREEN) +#define FOREGROUND_CYAN (FOREGROUND_GREEN | FOREGROUND_BLUE) +#define FOREGROUND_MAGENTA (FOREGROUND_RED | FOREGROUND_BLUE) +#define BACKGROUND_WHITE (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE) +#define BACKGROUND_BLACK 0 +#define BACKGROUND_YELLOW (BACKGROUND_RED | BACKGROUND_GREEN) +#define BACKGROUND_CYAN (BACKGROUND_GREEN | BACKGROUND_BLUE) +#define BACKGROUND_MAGENTA (BACKGROUND_RED | BACKGROUND_BLUE) + +#define F_INTENSITY 1 +#define FB_INTENSITY 2 +#define B_INTENSITY 5 +#define INVERSE 7 +#define F_INTENSITY_OFF1 21 +#define F_INTENSITY_OFF2 22 +#define B_INTENSITY_OFF 25 +#define INVERSE_OFF 27 +#define F_BLACK 30 +#define F_RED 31 +#define F_GREEN 32 +#define F_YELLOW 33 +#define F_BLUE 34 +#define F_MAGENTA 35 +#define F_CYAN 36 +#define F_WHITE 37 +#define F_DEFAULT 39 +#define B_BLACK 40 +#define B_RED 41 +#define B_GREEN 42 +#define B_YELLOW 43 +#define B_BLUE 44 +#define B_MAGENTA 45 +#define B_CYAN 46 +#define B_WHITE 47 +#define B_DEFAULT 49 + +#define CURSOR_SIZE_SMALL 25 +#define CURSOR_SIZE_MIDDLE 50 +#define CURSOR_SIZE_LARGE 100 + +struct screen_info { + CONSOLE_SCREEN_BUFFER_INFO csbi; + int top; + int width; + int height; + int length; + WORD default_attr; +}; + +struct captured_screen { + char* text; + WORD* attributes; + struct screen_info si; +}; + +static void get_screen_info(uv_tty_t* tty_out, struct screen_info* si) { + ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &(si->csbi))); + si->width = si->csbi.dwSize.X; + si->height = si->csbi.srWindow.Bottom - si->csbi.srWindow.Top + 1; + si->length = si->width * si->height; + si->default_attr = si->csbi.wAttributes; + si->top = si->csbi.srWindow.Top; +} + +static void set_cursor_position(uv_tty_t* tty_out, COORD pos) { + HANDLE handle = tty_out->handle; + CONSOLE_SCREEN_BUFFER_INFO info; + ASSERT(GetConsoleScreenBufferInfo(handle, &info)); + pos.X -= 1; + pos.Y += info.srWindow.Top - 1; + ASSERT(SetConsoleCursorPosition(handle, pos)); +} + +static void get_cursor_position(uv_tty_t* tty_out, COORD* cursor_position) { + HANDLE handle = tty_out->handle; + CONSOLE_SCREEN_BUFFER_INFO info; + ASSERT(GetConsoleScreenBufferInfo(handle, &info)); + cursor_position->X = info.dwCursorPosition.X + 1; + cursor_position->Y = info.dwCursorPosition.Y - info.srWindow.Top + 1; +} + +static void set_cursor_to_home(uv_tty_t* tty_out) { + COORD origin = {1, 1}; + set_cursor_position(tty_out, origin); +} + +static CONSOLE_CURSOR_INFO get_cursor_info(uv_tty_t* tty_out) { + HANDLE handle = tty_out->handle; + CONSOLE_CURSOR_INFO info; + ASSERT(GetConsoleCursorInfo(handle, &info)); + return info; +} + +static void set_cursor_size(uv_tty_t* tty_out, DWORD size) { + CONSOLE_CURSOR_INFO info = get_cursor_info(tty_out); + info.dwSize = size; + ASSERT(SetConsoleCursorInfo(tty_out->handle, &info)); +} + +static DWORD get_cursor_size(uv_tty_t* tty_out) { + return get_cursor_info(tty_out).dwSize; +} + +static void set_cursor_visibility(uv_tty_t* tty_out, BOOL visible) { + CONSOLE_CURSOR_INFO info = get_cursor_info(tty_out); + info.bVisible = visible; + ASSERT(SetConsoleCursorInfo(tty_out->handle, &info)); +} + +static BOOL get_cursor_visibility(uv_tty_t* tty_out) { + return get_cursor_info(tty_out).bVisible; +} + +static BOOL is_scrolling(uv_tty_t* tty_out, struct screen_info si) { + CONSOLE_SCREEN_BUFFER_INFO info; + ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info)); + return info.srWindow.Top != si.top; +} + +static void write_console(uv_tty_t* tty_out, char* src) { + int r; + uv_buf_t buf; + + buf.base = src; + buf.len = strlen(buf.base); + + r = uv_try_write((uv_stream_t*) tty_out, &buf, 1); + ASSERT(r >= 0); + ASSERT((unsigned int) r == buf.len); +} + +static void setup_screen(uv_tty_t* tty_out) { + DWORD length, number_of_written; + COORD origin; + CONSOLE_SCREEN_BUFFER_INFO info; + ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info)); + length = info.dwSize.X * (info.srWindow.Bottom - info.srWindow.Top + 1); + origin.X = 0; + origin.Y = info.srWindow.Top; + ASSERT(FillConsoleOutputCharacter( + tty_out->handle, '.', length, origin, &number_of_written)); + ASSERT(length == number_of_written); +} + +static void clear_screen(uv_tty_t* tty_out, struct screen_info* si) { + DWORD length, number_of_written; + COORD origin; + CONSOLE_SCREEN_BUFFER_INFO info; + ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info)); + length = (info.srWindow.Bottom - info.srWindow.Top + 1) * info.dwSize.X - 1; + origin.X = 0; + origin.Y = info.srWindow.Top; + FillConsoleOutputCharacterA( + tty_out->handle, ' ', length, origin, &number_of_written); + ASSERT(length == number_of_written); + FillConsoleOutputAttribute( + tty_out->handle, si->default_attr, length, origin, &number_of_written); + ASSERT(length == number_of_written); +} + +static void free_screen(struct captured_screen* cs) { + free(cs->text); + cs->text = NULL; + free(cs->attributes); + cs->attributes = NULL; +} + +static void capture_screen(uv_tty_t* tty_out, struct captured_screen* cs) { + DWORD length; + COORD origin; + get_screen_info(tty_out, &(cs->si)); + origin.X = 0; + origin.Y = cs->si.csbi.srWindow.Top; + cs->text = malloc(cs->si.length * sizeof(*cs->text)); + ASSERT(cs->text != NULL); + cs->attributes = (WORD*) malloc(cs->si.length * sizeof(*cs->attributes)); + ASSERT(cs->attributes != NULL); + ASSERT(ReadConsoleOutputCharacter( + tty_out->handle, cs->text, cs->si.length, origin, &length)); + ASSERT((unsigned int) cs->si.length == length); + ASSERT(ReadConsoleOutputAttribute( + tty_out->handle, cs->attributes, cs->si.length, origin, &length)); + ASSERT((unsigned int) cs->si.length == length); +} + +static void make_expect_screen_erase(struct captured_screen* cs, + COORD cursor_position, + int dir, + BOOL entire_screen) { + /* beginning of line */ + char* start; + char* end; + start = cs->text + cs->si.width * (cursor_position.Y - 1); + if (dir == 0) { + if (entire_screen) { + /* erase to end of screen */ + end = cs->text + cs->si.length; + } else { + /* erase to end of line */ + end = start + cs->si.width; + } + /* erase from postition of cursor */ + start += cursor_position.X - 1; + } else if (dir == 1) { + /* erase to position of cursor */ + end = start + cursor_position.X; + if (entire_screen) { + /* erase form beginning of screen */ + start = cs->text; + } + } else if (dir == 2) { + if (entire_screen) { + /* erase form beginning of screen */ + start = cs->text; + /* erase to end of screen */ + end = cs->text + cs->si.length; + } else { + /* erase to end of line */ + end = start + cs->si.width; + } + } else { + ASSERT(FALSE); + } + ASSERT(start < end); + ASSERT(end - cs->text <= cs->si.length); + for (; start < end; start++) { + *start = ' '; + } +} + +static void make_expect_screen_write(struct captured_screen* cs, + COORD cursor_position, + const char* text) { + /* postion of cursor */ + char* start; + start = cs->text + cs->si.width * (cursor_position.Y - 1) + + cursor_position.X - 1; + size_t length = strlen(text); + size_t remain_length = cs->si.length - (cs->text - start); + length = length > remain_length ? remain_length : length; + memcpy(start, text, length); +} + +static void make_expect_screen_set_attr(struct captured_screen* cs, + COORD cursor_position, + size_t length, + WORD attr) { + WORD* start; + start = cs->attributes + cs->si.width * (cursor_position.Y - 1) + + cursor_position.X - 1; + size_t remain_length = cs->si.length - (cs->attributes - start); + length = length > remain_length ? remain_length : length; + while (length) { + *start = attr; + start++; + length--; + } +} + +static BOOL compare_screen(uv_tty_t* tty_out, + struct captured_screen* actual, + struct captured_screen* expect) { + int line, col; + BOOL result = TRUE; + int current = 0; + ASSERT(actual->text); + ASSERT(actual->attributes); + ASSERT(expect->text); + ASSERT(expect->attributes); + if (actual->si.length != expect->si.length) { + return FALSE; + } + if (actual->si.width != expect->si.width) { + return FALSE; + } + if (actual->si.height != expect->si.height) { + return FALSE; + } + while (current < actual->si.length) { + if (*(actual->text + current) != *(expect->text + current)) { + line = current / actual->si.width + 1; + col = current - actual->si.width * (line - 1) + 1; + fprintf(stderr, + "line:%d col:%d expected character '%c' but found '%c'\n", + line, + col, + *(expect->text + current), + *(actual->text + current)); + result = FALSE; + } + if (*(actual->attributes + current) != *(expect->attributes + current)) { + line = current / actual->si.width + 1; + col = current - actual->si.width * (line - 1) + 1; + fprintf(stderr, + "line:%d col:%d expected attributes '%u' but found '%u'\n", + line, + col, + *(expect->attributes + current), + *(actual->attributes + current)); + result = FALSE; + } + current++; + } + clear_screen(tty_out, &expect->si); + free_screen(expect); + free_screen(actual); + return result; +} + +static void initialize_tty(uv_tty_t* tty_out) { + int r; + int ttyout_fd; + /* Make sure we have an FD that refers to a tty */ + HANDLE handle; + + uv_tty_set_vterm_state(UV_TTY_UNSUPPORTED); + + handle = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CONSOLE_TEXTMODE_BUFFER, + NULL); + ASSERT(handle != INVALID_HANDLE_VALUE); + + ttyout_fd = _open_osfhandle((intptr_t) handle, 0); + ASSERT(ttyout_fd >= 0); + ASSERT(UV_TTY == uv_guess_handle(ttyout_fd)); + r = uv_tty_init(uv_default_loop(), tty_out, ttyout_fd, 0); /* Writable. */ + ASSERT(r == 0); +} + +static void terminate_tty(uv_tty_t* tty_out) { + set_cursor_to_home(tty_out); + uv_close((uv_handle_t*) tty_out, NULL); +} + +TEST_IMPL(tty_cursor_up) { + uv_tty_t tty_out; + uv_loop_t* loop; + COORD cursor_pos, cursor_pos_old; + char buffer[1024]; + struct screen_info si; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + get_screen_info(&tty_out, &si); + + cursor_pos_old.X = si.width / 2; + cursor_pos_old.Y = si.height / 2; + set_cursor_position(&tty_out, cursor_pos_old); + + /* cursor up one times if omitted arguments */ + snprintf(buffer, sizeof(buffer), "%sA", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y - 1 == cursor_pos.Y); + ASSERT(cursor_pos_old.X == cursor_pos.X); + + /* cursor up nth times */ + cursor_pos_old = cursor_pos; + snprintf(buffer, sizeof(buffer), "%s%dA", CSI, si.height / 4); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y - si.height / 4 == cursor_pos.Y); + ASSERT(cursor_pos_old.X == cursor_pos.X); + + /* cursor up from Window top does nothing */ + cursor_pos_old.X = 1; + cursor_pos_old.Y = 1; + set_cursor_position(&tty_out, cursor_pos_old); + snprintf(buffer, sizeof(buffer), "%sA", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y == cursor_pos.Y); + ASSERT(cursor_pos_old.X == cursor_pos.X); + ASSERT(!is_scrolling(&tty_out, si)); + + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tty_cursor_down) { + uv_tty_t tty_out; + uv_loop_t* loop; + COORD cursor_pos, cursor_pos_old; + char buffer[1024]; + struct screen_info si; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + get_screen_info(&tty_out, &si); + + cursor_pos_old.X = si.width / 2; + cursor_pos_old.Y = si.height / 2; + set_cursor_position(&tty_out, cursor_pos_old); + + /* cursor down one times if omitted arguments */ + snprintf(buffer, sizeof(buffer), "%sB", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y + 1 == cursor_pos.Y); + ASSERT(cursor_pos_old.X == cursor_pos.X); + + /* cursor down nth times */ + cursor_pos_old = cursor_pos; + snprintf(buffer, sizeof(buffer), "%s%dB", CSI, si.height / 4); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y + si.height / 4 == cursor_pos.Y); + ASSERT(cursor_pos_old.X == cursor_pos.X); + + /* cursor down from bottom line does nothing */ + cursor_pos_old.X = si.width / 2; + cursor_pos_old.Y = si.height; + set_cursor_position(&tty_out, cursor_pos_old); + snprintf(buffer, sizeof(buffer), "%sB", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y == cursor_pos.Y); + ASSERT(cursor_pos_old.X == cursor_pos.X); + ASSERT(!is_scrolling(&tty_out, si)); + + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tty_cursor_forward) { + uv_tty_t tty_out; + uv_loop_t* loop; + COORD cursor_pos, cursor_pos_old; + char buffer[1024]; + struct screen_info si; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + get_screen_info(&tty_out, &si); + + cursor_pos_old.X = si.width / 2; + cursor_pos_old.Y = si.height / 2; + set_cursor_position(&tty_out, cursor_pos_old); + + /* cursor forward one times if omitted arguments */ + snprintf(buffer, sizeof(buffer), "%sC", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y == cursor_pos.Y); + ASSERT(cursor_pos_old.X + 1 == cursor_pos.X); + + /* cursor forward nth times */ + cursor_pos_old = cursor_pos; + snprintf(buffer, sizeof(buffer), "%s%dC", CSI, si.width / 4); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y == cursor_pos.Y); + ASSERT(cursor_pos_old.X + si.width / 4 == cursor_pos.X); + + /* cursor forward from end of line does nothing*/ + cursor_pos_old.X = si.width; + cursor_pos_old.Y = si.height / 2; + set_cursor_position(&tty_out, cursor_pos_old); + snprintf(buffer, sizeof(buffer), "%sC", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y == cursor_pos.Y); + ASSERT(cursor_pos_old.X == cursor_pos.X); + + /* cursor forward from end of screen does nothing */ + cursor_pos_old.X = si.width; + cursor_pos_old.Y = si.height; + set_cursor_position(&tty_out, cursor_pos_old); + snprintf(buffer, sizeof(buffer), "%sC", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y == cursor_pos.Y); + ASSERT(cursor_pos_old.X == cursor_pos.X); + ASSERT(!is_scrolling(&tty_out, si)); + + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tty_cursor_back) { + uv_tty_t tty_out; + uv_loop_t* loop; + COORD cursor_pos, cursor_pos_old; + char buffer[1024]; + struct screen_info si; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + get_screen_info(&tty_out, &si); + + cursor_pos_old.X = si.width / 2; + cursor_pos_old.Y = si.height / 2; + set_cursor_position(&tty_out, cursor_pos_old); + + /* cursor back one times if omitted arguments */ + snprintf(buffer, sizeof(buffer), "%sD", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y == cursor_pos.Y); + ASSERT(cursor_pos_old.X - 1 == cursor_pos.X); + + /* cursor back nth times */ + cursor_pos_old = cursor_pos; + snprintf(buffer, sizeof(buffer), "%s%dD", CSI, si.width / 4); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y == cursor_pos.Y); + ASSERT(cursor_pos_old.X - si.width / 4 == cursor_pos.X); + + /* cursor back from beginning of line does nothing */ + cursor_pos_old.X = 1; + cursor_pos_old.Y = si.height / 2; + set_cursor_position(&tty_out, cursor_pos_old); + snprintf(buffer, sizeof(buffer), "%sD", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y == cursor_pos.Y); + ASSERT(cursor_pos_old.X == cursor_pos.X); + + /* cursor back from top of screen does nothing */ + cursor_pos_old.X = 1; + cursor_pos_old.Y = 1; + set_cursor_position(&tty_out, cursor_pos_old); + snprintf(buffer, sizeof(buffer), "%sD", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(1 == cursor_pos.Y); + ASSERT(1 == cursor_pos.X); + ASSERT(!is_scrolling(&tty_out, si)); + + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tty_cursor_next_line) { + uv_tty_t tty_out; + uv_loop_t* loop; + COORD cursor_pos, cursor_pos_old; + char buffer[1024]; + struct screen_info si; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + get_screen_info(&tty_out, &si); + + cursor_pos_old.X = si.width / 2; + cursor_pos_old.Y = si.height / 2; + set_cursor_position(&tty_out, cursor_pos_old); + + /* cursor next line one times if omitted arguments */ + snprintf(buffer, sizeof(buffer), "%sE", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y + 1 == cursor_pos.Y); + ASSERT(1 == cursor_pos.X); + + /* cursor next line nth times */ + cursor_pos_old = cursor_pos; + snprintf(buffer, sizeof(buffer), "%s%dE", CSI, si.height / 4); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y + si.height / 4 == cursor_pos.Y); + ASSERT(1 == cursor_pos.X); + + /* cursor next line from buttom row moves beginning of line */ + cursor_pos_old.X = si.width / 2; + cursor_pos_old.Y = si.height; + set_cursor_position(&tty_out, cursor_pos_old); + snprintf(buffer, sizeof(buffer), "%sE", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y == cursor_pos.Y); + ASSERT(1 == cursor_pos.X); + ASSERT(!is_scrolling(&tty_out, si)); + + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tty_cursor_previous_line) { + uv_tty_t tty_out; + uv_loop_t* loop; + COORD cursor_pos, cursor_pos_old; + char buffer[1024]; + struct screen_info si; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + get_screen_info(&tty_out, &si); + + cursor_pos_old.X = si.width / 2; + cursor_pos_old.Y = si.height / 2; + set_cursor_position(&tty_out, cursor_pos_old); + + /* cursor previous line one times if omitted arguments */ + snprintf(buffer, sizeof(buffer), "%sF", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y - 1 == cursor_pos.Y); + ASSERT(1 == cursor_pos.X); + + /* cursor previous line nth times */ + cursor_pos_old = cursor_pos; + snprintf(buffer, sizeof(buffer), "%s%dF", CSI, si.height / 4); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos_old.Y - si.height / 4 == cursor_pos.Y); + ASSERT(1 == cursor_pos.X); + + /* cursor previous line from top of screen does nothing */ + cursor_pos_old.X = 1; + cursor_pos_old.Y = 1; + set_cursor_position(&tty_out, cursor_pos_old); + snprintf(buffer, sizeof(buffer), "%sD", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(1 == cursor_pos.Y); + ASSERT(1 == cursor_pos.X); + ASSERT(!is_scrolling(&tty_out, si)); + + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tty_cursor_horizontal_move_absolute) { + uv_tty_t tty_out; + uv_loop_t* loop; + COORD cursor_pos, cursor_pos_old; + char buffer[1024]; + struct screen_info si; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + get_screen_info(&tty_out, &si); + + cursor_pos_old.X = si.width / 2; + cursor_pos_old.Y = si.height / 2; + set_cursor_position(&tty_out, cursor_pos_old); + + /* Move to beginning of line if omitted argument */ + snprintf(buffer, sizeof(buffer), "%sG", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(1 == cursor_pos.X); + ASSERT(cursor_pos_old.Y == cursor_pos.Y); + + /* Move cursor to nth character */ + snprintf(buffer, sizeof(buffer), "%s%dG", CSI, si.width / 4); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(si.width / 4 == cursor_pos.X); + ASSERT(cursor_pos_old.Y == cursor_pos.Y); + + /* Moving out of screen will fit within screen */ + snprintf(buffer, sizeof(buffer), "%s%dG", CSI, si.width + 1); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(si.width == cursor_pos.X); + ASSERT(cursor_pos_old.Y == cursor_pos.Y); + + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tty_cursor_move_absolute) { + uv_tty_t tty_out; + uv_loop_t* loop; + COORD cursor_pos; + char buffer[1024]; + struct screen_info si; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + get_screen_info(&tty_out, &si); + + cursor_pos.X = si.width / 2; + cursor_pos.Y = si.height / 2; + set_cursor_position(&tty_out, cursor_pos); + + /* Move the cursor to home if omitted arguments */ + snprintf(buffer, sizeof(buffer), "%sH", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(1 == cursor_pos.X); + ASSERT(1 == cursor_pos.Y); + + /* Move the cursor to the middle of the screen */ + snprintf( + buffer, sizeof(buffer), "%s%d;%df", CSI, si.height / 2, si.width / 2); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(si.width / 2 == cursor_pos.X); + ASSERT(si.height / 2 == cursor_pos.Y); + + /* Moving out of screen will fit within screen */ + snprintf( + buffer, sizeof(buffer), "%s%d;%df", CSI, si.height / 2, si.width + 1); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(si.width == cursor_pos.X); + ASSERT(si.height / 2 == cursor_pos.Y); + + snprintf( + buffer, sizeof(buffer), "%s%d;%df", CSI, si.height + 1, si.width / 2); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(si.width / 2 == cursor_pos.X); + ASSERT(si.height == cursor_pos.Y); + ASSERT(!is_scrolling(&tty_out, si)); + + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tty_hide_show_cursor) { + uv_tty_t tty_out; + uv_loop_t* loop; + char buffer[1024]; + BOOL saved_cursor_visibility; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + + saved_cursor_visibility = get_cursor_visibility(&tty_out); + + /* Hide the cursor */ + set_cursor_visibility(&tty_out, TRUE); + snprintf(buffer, sizeof(buffer), "%s?25l", CSI); + write_console(&tty_out, buffer); + ASSERT(!get_cursor_visibility(&tty_out)); + + /* Show the cursor */ + set_cursor_visibility(&tty_out, FALSE); + snprintf(buffer, sizeof(buffer), "%s?25h", CSI); + write_console(&tty_out, buffer); + ASSERT(get_cursor_visibility(&tty_out)); + + set_cursor_visibility(&tty_out, saved_cursor_visibility); + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tty_erase) { + int dir; + uv_tty_t tty_out; + uv_loop_t* loop; + COORD cursor_pos; + char buffer[1024]; + struct captured_screen actual = {0}, expect = {0}; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + + /* Erase to below if omitted argument */ + dir = 0; + setup_screen(&tty_out); + capture_screen(&tty_out, &expect); + cursor_pos.X = expect.si.width / 2; + cursor_pos.Y = expect.si.height / 2; + make_expect_screen_erase(&expect, cursor_pos, dir, TRUE); + + set_cursor_position(&tty_out, cursor_pos); + snprintf(buffer, sizeof(buffer), "%sJ", CSI); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* Erase to below(dir = 0) */ + setup_screen(&tty_out); + capture_screen(&tty_out, &expect); + make_expect_screen_erase(&expect, cursor_pos, dir, TRUE); + + set_cursor_position(&tty_out, cursor_pos); + snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* Erase to above */ + dir = 1; + setup_screen(&tty_out); + capture_screen(&tty_out, &expect); + make_expect_screen_erase(&expect, cursor_pos, dir, TRUE); + + set_cursor_position(&tty_out, cursor_pos); + snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* Erase All */ + dir = 2; + setup_screen(&tty_out); + capture_screen(&tty_out, &expect); + make_expect_screen_erase(&expect, cursor_pos, dir, TRUE); + + set_cursor_position(&tty_out, cursor_pos); + snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tty_erase_line) { + int dir; + uv_tty_t tty_out; + uv_loop_t* loop; + COORD cursor_pos; + char buffer[1024]; + struct captured_screen actual = {0}, expect = {0}; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + + /* Erase to right if omitted arguments */ + dir = 0; + setup_screen(&tty_out); + capture_screen(&tty_out, &expect); + cursor_pos.X = expect.si.width / 2; + cursor_pos.Y = expect.si.height / 2; + make_expect_screen_erase(&expect, cursor_pos, dir, FALSE); + + set_cursor_position(&tty_out, cursor_pos); + snprintf(buffer, sizeof(buffer), "%sK", CSI); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* Erase to right(dir = 0) */ + setup_screen(&tty_out); + capture_screen(&tty_out, &expect); + make_expect_screen_erase(&expect, cursor_pos, dir, FALSE); + + set_cursor_position(&tty_out, cursor_pos); + snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* Erase to Left */ + dir = 1; + setup_screen(&tty_out); + capture_screen(&tty_out, &expect); + make_expect_screen_erase(&expect, cursor_pos, dir, FALSE); + + set_cursor_position(&tty_out, cursor_pos); + snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* Erase All */ + dir = 2; + setup_screen(&tty_out); + capture_screen(&tty_out, &expect); + make_expect_screen_erase(&expect, cursor_pos, dir, FALSE); + + set_cursor_position(&tty_out, cursor_pos); + snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tty_set_cursor_shape) { + uv_tty_t tty_out; + uv_loop_t* loop; + DWORD saved_cursor_size; + char buffer[1024]; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + + saved_cursor_size = get_cursor_size(&tty_out); + + /* cursor size large if omitted arguments */ + set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE); + snprintf(buffer, sizeof(buffer), "%s q", CSI); + write_console(&tty_out, buffer); + ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE); + + /* cursor size large */ + set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE); + snprintf(buffer, sizeof(buffer), "%s1 q", CSI); + write_console(&tty_out, buffer); + ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE); + set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE); + snprintf(buffer, sizeof(buffer), "%s2 q", CSI); + write_console(&tty_out, buffer); + ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE); + + /* cursor size small */ + set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE); + snprintf(buffer, sizeof(buffer), "%s3 q", CSI); + write_console(&tty_out, buffer); + ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_SMALL); + set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE); + snprintf(buffer, sizeof(buffer), "%s6 q", CSI); + write_console(&tty_out, buffer); + ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_SMALL); + + /* Nothing occurs with arguments outside valid range */ + set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE); + snprintf(buffer, sizeof(buffer), "%s7 q", CSI); + write_console(&tty_out, buffer); + ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE); + + /* restore cursor size if arguments is zero */ + snprintf(buffer, sizeof(buffer), "%s0 q", CSI); + write_console(&tty_out, buffer); + ASSERT(get_cursor_size(&tty_out) == saved_cursor_size); + + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tty_set_style) { + uv_tty_t tty_out; + uv_loop_t* loop; + COORD cursor_pos; + char buffer[1024]; + struct captured_screen actual = {0}, expect = {0}; + WORD fg, bg; + WORD fg_attrs[9][2] = {{F_BLACK, FOREGROUND_BLACK}, + {F_RED, FOREGROUND_RED}, + {F_GREEN, FOREGROUND_GREEN}, + {F_YELLOW, FOREGROUND_YELLOW}, + {F_BLUE, FOREGROUND_BLUE}, + {F_MAGENTA, FOREGROUND_MAGENTA}, + {F_CYAN, FOREGROUND_CYAN}, + {F_WHITE, FOREGROUND_WHITE}, + {F_DEFAULT, 0}}; + WORD bg_attrs[9][2] = {{B_DEFAULT, 0}, + {B_BLACK, BACKGROUND_BLACK}, + {B_RED, BACKGROUND_RED}, + {B_GREEN, BACKGROUND_GREEN}, + {B_YELLOW, BACKGROUND_YELLOW}, + {B_BLUE, BACKGROUND_BLUE}, + {B_MAGENTA, BACKGROUND_MAGENTA}, + {B_CYAN, BACKGROUND_CYAN}, + {B_WHITE, BACKGROUND_WHITE}}; + WORD attr; + int i, length; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + + capture_screen(&tty_out, &expect); + fg_attrs[8][1] = expect.si.default_attr & FOREGROUND_WHITE; + bg_attrs[0][1] = expect.si.default_attr & BACKGROUND_WHITE; + + /* Set foreground color */ + length = ARRAY_SIZE(fg_attrs); + for (i = 0; i < length; i++) { + capture_screen(&tty_out, &expect); + cursor_pos.X = expect.si.width / 2; + cursor_pos.Y = expect.si.height / 2; + attr = (expect.si.default_attr & ~FOREGROUND_WHITE) | fg_attrs[i][1]; + make_expect_screen_write(&expect, cursor_pos, HELLO); + make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr); + + set_cursor_position(&tty_out, cursor_pos); + snprintf( + buffer, sizeof(buffer), "%s%dm%s%sm", CSI, fg_attrs[i][0], HELLO, CSI); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + + ASSERT(compare_screen(&tty_out, &actual, &expect)); + } + + /* Set background color */ + length = ARRAY_SIZE(bg_attrs); + for (i = 0; i < length; i++) { + capture_screen(&tty_out, &expect); + cursor_pos.X = expect.si.width / 2; + cursor_pos.Y = expect.si.height / 2; + attr = (expect.si.default_attr & ~BACKGROUND_WHITE) | bg_attrs[i][1]; + make_expect_screen_write(&expect, cursor_pos, HELLO); + make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr); + + set_cursor_position(&tty_out, cursor_pos); + snprintf( + buffer, sizeof(buffer), "%s%dm%s%sm", CSI, bg_attrs[i][0], HELLO, CSI); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + + ASSERT(compare_screen(&tty_out, &actual, &expect)); + } + + /* Set foregroud and background color */ + ASSERT(ARRAY_SIZE(fg_attrs) == ARRAY_SIZE(bg_attrs)); + length = ARRAY_SIZE(bg_attrs); + for (i = 0; i < length; i++) { + capture_screen(&tty_out, &expect); + cursor_pos.X = expect.si.width / 2; + cursor_pos.Y = expect.si.height / 2; + attr = expect.si.default_attr & ~FOREGROUND_WHITE & ~BACKGROUND_WHITE; + attr |= fg_attrs[i][1] | bg_attrs[i][1]; + make_expect_screen_write(&expect, cursor_pos, HELLO); + make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr); + + set_cursor_position(&tty_out, cursor_pos); + snprintf(buffer, + sizeof(buffer), + "%s%d;%dm%s%sm", + CSI, + bg_attrs[i][0], + fg_attrs[i][0], + HELLO, + CSI); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + + ASSERT(compare_screen(&tty_out, &actual, &expect)); + } + + /* Set foreground bright on */ + capture_screen(&tty_out, &expect); + cursor_pos.X = expect.si.width / 2; + cursor_pos.Y = expect.si.height / 2; + set_cursor_position(&tty_out, cursor_pos); + attr = expect.si.default_attr; + attr |= FOREGROUND_INTENSITY; + make_expect_screen_write(&expect, cursor_pos, HELLO); + make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr); + cursor_pos.X += strlen(HELLO); + make_expect_screen_write(&expect, cursor_pos, HELLO); + make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr); + + snprintf(buffer, + sizeof(buffer), + "%s%dm%s%s%dm%s%dm%s%s%dm", + CSI, + F_INTENSITY, + HELLO, + CSI, + F_INTENSITY_OFF1, + CSI, + F_INTENSITY, + HELLO, + CSI, + F_INTENSITY_OFF2); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* Set background bright on */ + capture_screen(&tty_out, &expect); + cursor_pos.X = expect.si.width / 2; + cursor_pos.Y = expect.si.height / 2; + set_cursor_position(&tty_out, cursor_pos); + attr = expect.si.default_attr; + attr |= BACKGROUND_INTENSITY; + make_expect_screen_write(&expect, cursor_pos, HELLO); + make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr); + + snprintf(buffer, + sizeof(buffer), + "%s%dm%s%s%dm", + CSI, + B_INTENSITY, + HELLO, + CSI, + B_INTENSITY_OFF); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* Inverse */ + capture_screen(&tty_out, &expect); + cursor_pos.X = expect.si.width / 2; + cursor_pos.Y = expect.si.height / 2; + set_cursor_position(&tty_out, cursor_pos); + attr = expect.si.default_attr; + fg = attr & FOREGROUND_WHITE; + bg = attr & BACKGROUND_WHITE; + attr &= (~FOREGROUND_WHITE & ~BACKGROUND_WHITE); + attr |= COMMON_LVB_REVERSE_VIDEO; + attr |= fg << 4; + attr |= bg >> 4; + make_expect_screen_write(&expect, cursor_pos, HELLO); + make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr); + cursor_pos.X += strlen(HELLO); + make_expect_screen_write(&expect, cursor_pos, HELLO); + + snprintf(buffer, + sizeof(buffer), + "%s%dm%s%s%dm%s", + CSI, + INVERSE, + HELLO, + CSI, + INVERSE_OFF, + HELLO); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tty_save_restore_cursor_position) { + uv_tty_t tty_out; + uv_loop_t* loop; + COORD cursor_pos, cursor_pos_old; + char buffer[1024]; + struct screen_info si; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + get_screen_info(&tty_out, &si); + + cursor_pos_old.X = si.width / 2; + cursor_pos_old.Y = si.height / 2; + set_cursor_position(&tty_out, cursor_pos_old); + + /* save the cursor position */ + snprintf(buffer, sizeof(buffer), "%ss", CSI); + write_console(&tty_out, buffer); + + cursor_pos.X = si.width / 4; + cursor_pos.Y = si.height / 4; + set_cursor_position(&tty_out, cursor_pos); + + /* restore the cursor postion */ + snprintf(buffer, sizeof(buffer), "%su", CSI); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos.X == cursor_pos_old.X); + ASSERT(cursor_pos.Y == cursor_pos_old.Y); + + cursor_pos_old.X = si.width / 2; + cursor_pos_old.Y = si.height / 2; + set_cursor_position(&tty_out, cursor_pos_old); + + /* save the cursor position */ + snprintf(buffer, sizeof(buffer), "%s7", ESC); + write_console(&tty_out, buffer); + + cursor_pos.X = si.width / 4; + cursor_pos.Y = si.height / 4; + set_cursor_position(&tty_out, cursor_pos); + + /* restore the cursor postion */ + snprintf(buffer, sizeof(buffer), "%s8", ESC); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos.X == cursor_pos_old.X); + ASSERT(cursor_pos.Y == cursor_pos_old.Y); + + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tty_full_reset) { + uv_tty_t tty_out; + uv_loop_t* loop; + char buffer[1024]; + struct captured_screen actual = {0}, expect = {0}; + COORD cursor_pos; + DWORD saved_cursor_size; + BOOL saved_cursor_visibility; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + + capture_screen(&tty_out, &expect); + setup_screen(&tty_out); + cursor_pos.X = expect.si.width; + cursor_pos.Y = expect.si.height; + set_cursor_position(&tty_out, cursor_pos); + snprintf(buffer, sizeof(buffer), "%s%d;%dm%s", CSI, F_CYAN, B_YELLOW, HELLO); + saved_cursor_size = get_cursor_size(&tty_out); + set_cursor_size(&tty_out, + saved_cursor_size == CURSOR_SIZE_LARGE ? CURSOR_SIZE_SMALL + : CURSOR_SIZE_LARGE); + saved_cursor_visibility = get_cursor_visibility(&tty_out); + set_cursor_visibility(&tty_out, saved_cursor_visibility ? FALSE : TRUE); + write_console(&tty_out, buffer); + snprintf(buffer, sizeof(buffer), "%sc", ESC); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + ASSERT(compare_screen(&tty_out, &actual, &expect)); + ASSERT(get_cursor_size(&tty_out) == saved_cursor_size); + ASSERT(get_cursor_visibility(&tty_out) == saved_cursor_visibility); + ASSERT(actual.si.csbi.srWindow.Top == 0); + + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tty_escape_sequence_processing) { + uv_tty_t tty_out; + uv_loop_t* loop; + COORD cursor_pos, cursor_pos_old; + DWORD saved_cursor_size; + char buffer[1024]; + struct captured_screen actual = {0}, expect = {0}; + int dir; + + loop = uv_default_loop(); + + initialize_tty(&tty_out); + + /* CSI + finaly byte does not output anything */ + cursor_pos.X = 1; + cursor_pos.Y = 1; + set_cursor_position(&tty_out, cursor_pos); + capture_screen(&tty_out, &expect); + make_expect_screen_write(&expect, cursor_pos, HELLO); + cursor_pos.X += strlen(HELLO); + make_expect_screen_write(&expect, cursor_pos, HELLO); + snprintf(buffer, sizeof(buffer), "%s@%s%s~%s", CSI, HELLO, CSI, HELLO); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* CSI(C1) + finaly byte does not output anything */ + cursor_pos.X = 1; + cursor_pos.Y = 1; + set_cursor_position(&tty_out, cursor_pos); + capture_screen(&tty_out, &expect); + make_expect_screen_write(&expect, cursor_pos, HELLO); + cursor_pos.X += strlen(HELLO); + make_expect_screen_write(&expect, cursor_pos, HELLO); + snprintf(buffer, sizeof(buffer), "\xC2\x9B@%s\xC2\x9B~%s", HELLO, HELLO); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* CSI + intermediate byte + finaly byte does not output anything */ + cursor_pos.X = 1; + cursor_pos.Y = 1; + set_cursor_position(&tty_out, cursor_pos); + capture_screen(&tty_out, &expect); + make_expect_screen_write(&expect, cursor_pos, HELLO); + cursor_pos.X += strlen(HELLO); + make_expect_screen_write(&expect, cursor_pos, HELLO); + snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* CSI + parameter byte + finaly byte does not output anything */ + cursor_pos.X = 1; + cursor_pos.Y = 1; + set_cursor_position(&tty_out, cursor_pos); + capture_screen(&tty_out, &expect); + snprintf(buffer, + sizeof(buffer), + "%s0@%s%s>~%s%s?~%s", + CSI, + HELLO, + CSI, + HELLO, + CSI, + HELLO); + make_expect_screen_write(&expect, cursor_pos, HELLO); + cursor_pos.X += strlen(HELLO); + make_expect_screen_write(&expect, cursor_pos, HELLO); + cursor_pos.X += strlen(HELLO); + make_expect_screen_write(&expect, cursor_pos, HELLO); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* ESC Single-char control does not output anyghing */ + cursor_pos.X = 1; + cursor_pos.Y = 1; + set_cursor_position(&tty_out, cursor_pos); + capture_screen(&tty_out, &expect); + make_expect_screen_write(&expect, cursor_pos, HELLO); + cursor_pos.X += strlen(HELLO); + make_expect_screen_write(&expect, cursor_pos, HELLO); + snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* Nothing is output from ESC + ^, _, P, ] to BEL or ESC \ */ + /* Operaging System Command */ + cursor_pos.X = 1; + cursor_pos.Y = 1; + set_cursor_position(&tty_out, cursor_pos); + capture_screen(&tty_out, &expect); + make_expect_screen_write(&expect, cursor_pos, HELLO); + snprintf(buffer, sizeof(buffer), "%s]0;%s%s%s", ESC, HELLO, BEL, HELLO); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + ASSERT(compare_screen(&tty_out, &actual, &expect)); + /* Device Control Sequence */ + cursor_pos.X = 1; + cursor_pos.Y = 1; + set_cursor_position(&tty_out, cursor_pos); + capture_screen(&tty_out, &expect); + make_expect_screen_write(&expect, cursor_pos, HELLO); + snprintf(buffer, sizeof(buffer), "%sP$m%s%s", ESC, ST, HELLO); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + ASSERT(compare_screen(&tty_out, &actual, &expect)); + /* Privacy Message */ + cursor_pos.X = 1; + cursor_pos.Y = 1; + set_cursor_position(&tty_out, cursor_pos); + capture_screen(&tty_out, &expect); + make_expect_screen_write(&expect, cursor_pos, HELLO); + snprintf(buffer, + sizeof(buffer), + "%s^\"%s\\\"%s\"%s%s", + ESC, + HELLO, + HELLO, + ST, + HELLO); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + ASSERT(compare_screen(&tty_out, &actual, &expect)); + /* Application Program Command */ + cursor_pos.X = 1; + cursor_pos.Y = 1; + set_cursor_position(&tty_out, cursor_pos); + capture_screen(&tty_out, &expect); + make_expect_screen_write(&expect, cursor_pos, HELLO); + snprintf(buffer, + sizeof(buffer), + "%s_\"%s%s%s\"%s%s", + ESC, + HELLO, + ST, + HELLO, + BEL, + HELLO); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* Ignore double escape */ + cursor_pos.X = 1; + cursor_pos.Y = 1; + set_cursor_position(&tty_out, cursor_pos); + capture_screen(&tty_out, &expect); + make_expect_screen_write(&expect, cursor_pos, HELLO); + cursor_pos.X += strlen(HELLO); + make_expect_screen_write(&expect, cursor_pos, HELLO); + snprintf(buffer, + sizeof(buffer), + "%s%s@%s%s%s~%s", + ESC, + CSI, + HELLO, + ESC, + CSI, + HELLO); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* Ignored if argument overflow */ + set_cursor_to_home(&tty_out); + snprintf(buffer, sizeof(buffer), "%s1;%dH", CSI, UINT16_MAX + 1); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos.X == 1); + ASSERT(cursor_pos.Y == 1); + + /* Too many argument are ignored */ + cursor_pos.X = 1; + cursor_pos.Y = 1; + set_cursor_position(&tty_out, cursor_pos); + capture_screen(&tty_out, &expect); + make_expect_screen_write(&expect, cursor_pos, HELLO); + snprintf(buffer, + sizeof(buffer), + "%s%d;%d;%d;%d;%dm%s%sm", + CSI, + F_RED, + F_INTENSITY, + INVERSE, + B_CYAN, + B_INTENSITY_OFF, + HELLO, + CSI); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* In the case of DECSCUSR, the others are ignored */ + set_cursor_to_home(&tty_out); + snprintf(buffer, + sizeof(buffer), + "%s%d;%d H", + CSI, + expect.si.height / 2, + expect.si.width / 2); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos.X == 1); + ASSERT(cursor_pos.Y == 1); + + /* Invalid sequence are ignored */ + saved_cursor_size = get_cursor_size(&tty_out); + set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE); + snprintf(buffer, sizeof(buffer), "%s 1q", CSI); + write_console(&tty_out, buffer); + ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE); + snprintf(buffer, sizeof(buffer), "%s 1 q", CSI); + write_console(&tty_out, buffer); + ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE); + set_cursor_size(&tty_out, saved_cursor_size); + + /* #1874 2. */ + snprintf(buffer, sizeof(buffer), "%s??25l", CSI); + write_console(&tty_out, buffer); + ASSERT(get_cursor_visibility(&tty_out)); + snprintf(buffer, sizeof(buffer), "%s25?l", CSI); + write_console(&tty_out, buffer); + ASSERT(get_cursor_visibility(&tty_out)); + cursor_pos_old.X = expect.si.width / 2; + cursor_pos_old.Y = expect.si.height / 2; + set_cursor_position(&tty_out, cursor_pos_old); + snprintf(buffer, + sizeof(buffer), + "%s??%d;%df", + CSI, + expect.si.height / 4, + expect.si.width / 4); + write_console(&tty_out, buffer); + get_cursor_position(&tty_out, &cursor_pos); + ASSERT(cursor_pos.X = cursor_pos_old.X); + ASSERT(cursor_pos.Y = cursor_pos_old.Y); + set_cursor_to_home(&tty_out); + + /* CSI 25 l does nothing (#1874 4.) */ + snprintf(buffer, sizeof(buffer), "%s25l", CSI); + write_console(&tty_out, buffer); + ASSERT(get_cursor_visibility(&tty_out)); + + /* Unsupported sequences are ignored(#1874 5.) */ + dir = 2; + setup_screen(&tty_out); + capture_screen(&tty_out, &expect); + set_cursor_position(&tty_out, cursor_pos); + snprintf(buffer, sizeof(buffer), "%s?%dJ", CSI, dir); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + /* Finaly byte immedately after CSI [ are also output(#1874 1.) */ + cursor_pos.X = expect.si.width / 2; + cursor_pos.Y = expect.si.height / 2; + set_cursor_position(&tty_out, cursor_pos); + capture_screen(&tty_out, &expect); + make_expect_screen_write(&expect, cursor_pos, HELLO); + snprintf(buffer, sizeof(buffer), "%s[%s", CSI, HELLO); + write_console(&tty_out, buffer); + capture_screen(&tty_out, &actual); + ASSERT(compare_screen(&tty_out, &actual, &expect)); + + terminate_tty(&tty_out); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +#else + +typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */ + +#endif /* ifdef _WIN32 */ diff --git a/deps/uv/test/test-tty.c b/deps/uv/test/test-tty.c index 688711e5082116..0c6548f95f38c8 100644 --- a/deps/uv/test/test-tty.c +++ b/deps/uv/test/test-tty.c @@ -360,6 +360,8 @@ TEST_IMPL(tty_file) { if (fd != -1) { ASSERT(UV_EINVAL == uv_tty_init(&loop, &tty, fd, 1)); ASSERT(0 == close(fd)); + /* test EBADF handling */ + ASSERT(UV_EINVAL == uv_tty_init(&loop, &tty, fd, 1)); } /* Bug on AIX where '/dev/random' returns 1 from isatty() */ diff --git a/deps/uv/test/test-udp-connect.c b/deps/uv/test/test-udp-connect.c index f44634248f7e31..58cf9475a40b57 100644 --- a/deps/uv/test/test-udp-connect.c +++ b/deps/uv/test/test-udp-connect.c @@ -98,6 +98,10 @@ static void sv_recv_cb(uv_udp_t* handle, TEST_IMPL(udp_connect) { +#if defined(__PASE__) + RETURN_SKIP( + "IBMi PASE's UDP connection can not be disconnected with AF_UNSPEC."); +#endif uv_udp_send_t req; struct sockaddr_in ext_addr; struct sockaddr_in tmp_addr; diff --git a/deps/uv/test/test-udp-ipv6.c b/deps/uv/test/test-udp-ipv6.c index 9d4db2bc4fedf0..7099953097cdd8 100644 --- a/deps/uv/test/test-udp-ipv6.c +++ b/deps/uv/test/test-udp-ipv6.c @@ -41,11 +41,13 @@ static uv_udp_t client; static uv_udp_t server; static uv_udp_send_t req_; +static char data[10]; static uv_timer_t timeout; static int send_cb_called; static int recv_cb_called; static int close_cb_called; +static uint16_t client_port; #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) static int can_ipv6_ipv4_dual(void) { @@ -83,12 +85,35 @@ static void send_cb(uv_udp_send_t* req, int status) { send_cb_called++; } +static int is_from_client(const struct sockaddr* addr) { + const struct sockaddr_in6* addr6; + char dst[256]; + int r; + + /* Debugging output, and filter out unwanted network traffic */ + if (addr != NULL) { + ASSERT(addr->sa_family == AF_INET6); + addr6 = (struct sockaddr_in6*) addr; + r = uv_inet_ntop(addr->sa_family, &addr6->sin6_addr, dst, sizeof(dst)); + if (r == 0) + printf("from [%.*s]:%d\n", (int) sizeof(dst), dst, addr6->sin6_port); + if (addr6->sin6_port != client_port) + return 0; + if (r != 0 || strcmp(dst, "::ffff:127.0.0.1")) + return 0; + } + return 1; +} + static void ipv6_recv_fail(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags) { + printf("got %d %.*s\n", (int) nread, nread > 0 ? (int) nread : 0, buf->base); + if (!is_from_client(addr) || (nread == 0 && addr == NULL)) + return; ASSERT(0 && "this function should not have been called"); } @@ -99,10 +124,14 @@ static void ipv6_recv_ok(uv_udp_t* handle, const struct sockaddr* addr, unsigned flags) { CHECK_HANDLE(handle); - ASSERT(nread >= 0); - if (nread) - recv_cb_called++; + printf("got %d %.*s\n", (int) nread, nread > 0 ? (int) nread : 0, buf->base); + if (!is_from_client(addr) || (nread == 0 && addr == NULL)) + return; + + ASSERT(nread == 9); + ASSERT(!memcmp(buf->base, data, 9)); + recv_cb_called++; } @@ -116,7 +145,10 @@ static void timeout_cb(uv_timer_t* timer) { static void do_test(uv_udp_recv_cb recv_cb, int bind_flags) { struct sockaddr_in6 addr6; struct sockaddr_in addr; + int addr6_len; + int addr_len; uv_buf_t buf; + char dst[256]; int r; ASSERT(0 == uv_ip6_addr("::0", TEST_PORT, &addr6)); @@ -127,14 +159,25 @@ static void do_test(uv_udp_recv_cb recv_cb, int bind_flags) { r = uv_udp_bind(&server, (const struct sockaddr*) &addr6, bind_flags); ASSERT(r == 0); + addr6_len = sizeof(addr6); + ASSERT(uv_udp_getsockname(&server, (struct sockaddr*) &addr6, &addr6_len) == 0); + ASSERT(uv_inet_ntop(addr6.sin6_family, &addr6.sin6_addr, dst, sizeof(dst)) == 0); + printf("on [%.*s]:%d\n", (int) sizeof(dst), dst, addr6.sin6_port); + r = uv_udp_recv_start(&server, alloc_cb, recv_cb); ASSERT(r == 0); r = uv_udp_init(uv_default_loop(), &client); ASSERT(r == 0); - buf = uv_buf_init("PING", 4); ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + ASSERT(uv_inet_ntop(addr.sin_family, &addr.sin_addr, dst, sizeof(dst)) == 0); + printf("to [%.*s]:%d\n", (int) sizeof(dst), dst, addr.sin_port); + + /* Create some unique data to send */ + ASSERT(9 == snprintf(data, sizeof(data), "PING%5u", uv_os_getpid() & 0xFFFF)); + buf = uv_buf_init(data, 9); + printf("sending %s\n", data); r = uv_udp_send(&req_, &client, @@ -144,6 +187,12 @@ static void do_test(uv_udp_recv_cb recv_cb, int bind_flags) { send_cb); ASSERT(r == 0); + addr_len = sizeof(addr); + ASSERT(uv_udp_getsockname(&client, (struct sockaddr*) &addr, &addr_len) == 0); + ASSERT(uv_inet_ntop(addr.sin_family, &addr.sin_addr, dst, sizeof(dst)) == 0); + printf("from [%.*s]:%d\n", (int) sizeof(dst), dst, addr.sin_port); + client_port = addr.sin_port; + r = uv_timer_init(uv_default_loop(), &timeout); ASSERT(r == 0); @@ -180,6 +229,8 @@ TEST_IMPL(udp_dual_stack) { do_test(ipv6_recv_ok, 0); + printf("recv_cb_called %d\n", recv_cb_called); + printf("send_cb_called %d\n", send_cb_called); ASSERT(recv_cb_called == 1); ASSERT(send_cb_called == 1); diff --git a/deps/uv/test/test-watcher-cross-stop.c b/deps/uv/test/test-watcher-cross-stop.c index 29a82a5c374029..b26deb8d88c50f 100644 --- a/deps/uv/test/test-watcher-cross-stop.c +++ b/deps/uv/test/test-watcher-cross-stop.c @@ -26,8 +26,9 @@ #include /* NOTE: Number should be big enough to trigger this problem */ -#if defined(__CYGWIN__) || defined(__MSYS__) +#if defined(__CYGWIN__) || defined(__MSYS__) || defined(__PASE__) /* Cygwin crashes or hangs in socket() with too many AF_INET sockets. */ +/* IBMi PASE timeout with too many AF_INET sockets. */ static uv_udp_t sockets[1250]; #else static uv_udp_t sockets[2500]; diff --git a/deps/uv/test/test.gyp b/deps/uv/test/test.gyp deleted file mode 100644 index 73ff42c56e431c..00000000000000 --- a/deps/uv/test/test.gyp +++ /dev/null @@ -1,293 +0,0 @@ -{ - 'targets': [ - { - 'target_name': 'run-tests', - 'type': 'executable', - 'dependencies': [ '../uv.gyp:libuv' ], - 'sources': [ - 'blackhole-server.c', - 'echo-server.c', - 'run-tests.c', - 'runner.c', - 'runner.h', - 'test-get-loadavg.c', - 'task.h', - 'test-active.c', - 'test-async.c', - 'test-async-null-cb.c', - 'test-callback-stack.c', - 'test-callback-order.c', - 'test-close-fd.c', - 'test-close-order.c', - 'test-connect-unspecified.c', - 'test-connection-fail.c', - 'test-cwd-and-chdir.c', - 'test-default-loop-close.c', - 'test-delayed-accept.c', - 'test-eintr-handling.c', - 'test-error.c', - 'test-embed.c', - 'test-emfile.c', - 'test-env-vars.c', - 'test-fail-always.c', - 'test-fork.c', - 'test-fs.c', - 'test-fs-readdir.c', - 'test-fs-copyfile.c', - 'test-fs-event.c', - 'test-fs-fd-hash.c', - 'test-fs-open-flags.c', - 'test-fs-poll.c', - 'test-getters-setters.c', - 'test-get-currentexe.c', - 'test-get-memory.c', - 'test-get-passwd.c', - 'test-getaddrinfo.c', - 'test-gethostname.c', - 'test-getnameinfo.c', - 'test-getsockname.c', - 'test-gettimeofday.c', - 'test-handle-fileno.c', - 'test-homedir.c', - 'test-hrtime.c', - 'test-idle.c', - 'test-idna.c', - 'test-ip4-addr.c', - 'test-ip6-addr.c', - 'test-ipc-heavy-traffic-deadlock-bug.c', - 'test-ipc-send-recv.c', - 'test-ipc.c', - 'test-list.h', - 'test-loop-handles.c', - 'test-loop-alive.c', - 'test-loop-close.c', - 'test-loop-stop.c', - 'test-loop-time.c', - 'test-loop-configure.c', - 'test-walk-handles.c', - 'test-watcher-cross-stop.c', - 'test-multiple-listen.c', - 'test-osx-select.c', - 'test-pass-always.c', - 'test-ping-pong.c', - 'test-pipe-bind-error.c', - 'test-pipe-connect-error.c', - 'test-pipe-connect-multiple.c', - 'test-pipe-connect-prepare.c', - 'test-pipe-getsockname.c', - 'test-pipe-pending-instances.c', - 'test-pipe-sendmsg.c', - 'test-pipe-server-close.c', - 'test-pipe-close-stdout-read-stdin.c', - 'test-pipe-set-non-blocking.c', - 'test-pipe-set-fchmod.c', - 'test-platform-output.c', - 'test-poll.c', - 'test-poll-close.c', - 'test-poll-close-doesnt-corrupt-stack.c', - 'test-poll-closesocket.c', - 'test-poll-oob.c', - 'test-process-priority.c', - 'test-process-title.c', - 'test-process-title-threadsafe.c', - 'test-queue-foreach-delete.c', - 'test-random.c', - 'test-ref.c', - 'test-run-nowait.c', - 'test-run-once.c', - 'test-semaphore.c', - 'test-shutdown-close.c', - 'test-shutdown-eof.c', - 'test-shutdown-twice.c', - 'test-signal.c', - 'test-signal-multiple-loops.c', - 'test-signal-pending-on-close.c', - 'test-socket-buffer-size.c', - 'test-spawn.c', - 'test-strscpy.c', - 'test-stdio-over-pipes.c', - 'test-tcp-alloc-cb-fail.c', - 'test-tcp-bind-error.c', - 'test-tcp-bind6-error.c', - 'test-tcp-close.c', - 'test-tcp-close-accept.c', - 'test-tcp-close-reset.c', - 'test-tcp-close-while-connecting.c', - 'test-tcp-create-socket-early.c', - 'test-tcp-connect-error-after-write.c', - 'test-tcp-shutdown-after-write.c', - 'test-tcp-flags.c', - 'test-tcp-connect-error.c', - 'test-tcp-connect-timeout.c', - 'test-tcp-connect6-error.c', - 'test-tcp-open.c', - 'test-tcp-write-to-half-open-connection.c', - 'test-tcp-write-after-connect.c', - 'test-tcp-writealot.c', - 'test-tcp-write-fail.c', - 'test-tcp-try-write.c', - 'test-tcp-try-write-error.c', - 'test-tcp-unexpected-read.c', - 'test-tcp-oob.c', - 'test-tcp-read-stop.c', - 'test-tcp-write-queue-order.c', - 'test-threadpool.c', - 'test-threadpool-cancel.c', - 'test-thread-equal.c', - 'test-tmpdir.c', - 'test-mutexes.c', - 'test-thread.c', - 'test-barrier.c', - 'test-condvar.c', - 'test-timer-again.c', - 'test-timer-from-check.c', - 'test-timer.c', - 'test-tty-duplicate-key.c', - 'test-tty.c', - 'test-udp-alloc-cb-fail.c', - 'test-udp-bind.c', - 'test-udp-connect.c', - 'test-udp-create-socket-early.c', - 'test-udp-dgram-too-big.c', - 'test-udp-ipv6.c', - 'test-udp-open.c', - 'test-udp-options.c', - 'test-udp-send-and-recv.c', - 'test-udp-send-hang-loop.c', - 'test-udp-send-immediate.c', - 'test-udp-send-unreachable.c', - 'test-udp-multicast-join.c', - 'test-udp-multicast-join6.c', - 'test-dlerror.c', - 'test-udp-multicast-ttl.c', - 'test-udp-multicast-interface.c', - 'test-udp-multicast-interface6.c', - 'test-udp-try-send.c', - 'test-uname.c', - ], - 'conditions': [ - [ 'OS=="win"', { - 'sources': [ - 'runner-win.c', - 'runner-win.h', - '../src/win/snprintf.c', - ], - 'libraries': [ '-lws2_32' ] - }, { # POSIX - 'sources': [ - 'runner-unix.c', - 'runner-unix.h', - ], - 'conditions': [ - [ 'OS != "zos"', { - 'defines': [ '_GNU_SOURCE' ], - 'cflags': [ '-Wno-long-long' ], - 'xcode_settings': { - 'WARNING_CFLAGS': [ '-Wno-long-long' ] - } - }], - ]}, - ], - [ 'OS in "mac dragonflybsd freebsd linux netbsd openbsd".split()', { - 'link_settings': { - 'libraries': [ '-lutil' ], - }, - }], - [ 'OS=="solaris"', { # make test-fs.c compile, needs _POSIX_C_SOURCE - 'defines': [ - '__EXTENSIONS__', - '_XOPEN_SOURCE=500', - ], - }], - [ 'OS=="aix"', { # make test-fs.c compile, needs _POSIX_C_SOURCE - 'defines': [ - '_ALL_SOURCE', - '_XOPEN_SOURCE=500', - ], - }], - [ 'OS == "zos"', { - 'cflags': [ '-qxplink' ], - 'ldflags': [ '-qxplink' ], - }], - ['uv_library=="shared_library"', { - 'defines': [ 'USING_UV_SHARED=1' ], - 'conditions': [ - [ 'OS == "zos"', { - 'cflags': [ '-Wc,DLL' ], - }], - ], - }], - ], - 'msvs-settings': { - 'VCLinkerTool': { - 'SubSystem': 1, # /subsystem:console - }, - }, - }, - - { - 'target_name': 'run-benchmarks', - 'type': 'executable', - 'dependencies': [ '../uv.gyp:libuv' ], - 'sources': [ - 'benchmark-async.c', - 'benchmark-async-pummel.c', - 'benchmark-fs-stat.c', - 'benchmark-getaddrinfo.c', - 'benchmark-list.h', - 'benchmark-loop-count.c', - 'benchmark-million-async.c', - 'benchmark-million-timers.c', - 'benchmark-multi-accept.c', - 'benchmark-ping-pongs.c', - 'benchmark-pound.c', - 'benchmark-pump.c', - 'benchmark-sizes.c', - 'benchmark-spawn.c', - 'benchmark-thread.c', - 'benchmark-tcp-write-batch.c', - 'benchmark-udp-pummel.c', - 'dns-server.c', - 'echo-server.c', - 'blackhole-server.c', - 'run-benchmarks.c', - 'runner.c', - 'runner.h', - 'task.h', - ], - 'conditions': [ - [ 'OS=="win"', { - 'sources': [ - 'runner-win.c', - 'runner-win.h', - '../src/win/snprintf.c', - ], - 'libraries': [ '-lws2_32' ] - }, { # POSIX - 'defines': [ '_GNU_SOURCE' ], - 'sources': [ - 'runner-unix.c', - 'runner-unix.h', - ] - }], - [ 'OS == "zos"', { - 'cflags': [ '-qxplink' ], - 'ldflags': [ '-qxplink' ], - }], - ['uv_library=="shared_library"', { - 'defines': [ 'USING_UV_SHARED=1' ], - 'conditions': [ - [ 'OS == "zos"', { - 'cflags': [ '-Wc,DLL' ], - }], - ], - }], - ], - 'msvs-settings': { - 'VCLinkerTool': { - 'SubSystem': 1, # /subsystem:console - }, - }, - }, - ], -} diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index fa0a001527d790..116b7537195618 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -261,7 +261,6 @@ 'src/unix/android-ifaddrs.c', 'src/unix/procfs-exepath.c', 'src/unix/random-getrandom.c', - 'src/unix/random-getentropy.c', 'src/unix/random-sysctl-linux.c', 'src/unix/sysinfo-loadavg.c', ], diff --git a/deps/uv/vcbuild.bat b/deps/uv/vcbuild.bat deleted file mode 100644 index c195394f37ea0b..00000000000000 --- a/deps/uv/vcbuild.bat +++ /dev/null @@ -1,184 +0,0 @@ -@echo off - -cd %~dp0 - -if /i "%1"=="help" goto help -if /i "%1"=="--help" goto help -if /i "%1"=="-help" goto help -if /i "%1"=="/help" goto help -if /i "%1"=="?" goto help -if /i "%1"=="-?" goto help -if /i "%1"=="--?" goto help -if /i "%1"=="/?" goto help - -@rem Process arguments. -set config= -set target=Build -set target_arch=ia32 -set target_env= -set noprojgen= -set nobuild= -set run= -set vs_toolset=x86 -set msbuild_platform=WIN32 -set library=static_library - -:next-arg -if "%1"=="" goto args-done -if /i "%1"=="debug" set config=Debug&goto arg-ok -if /i "%1"=="release" set config=Release&goto arg-ok -if /i "%1"=="test" set run=run-tests.exe&goto arg-ok -if /i "%1"=="bench" set run=run-benchmarks.exe&goto arg-ok -if /i "%1"=="clean" set target=Clean&goto arg-ok -if /i "%1"=="vs2017" set target_env=vs2017&goto arg-ok -if /i "%1"=="noprojgen" set noprojgen=1&goto arg-ok -if /i "%1"=="nobuild" set nobuild=1&goto arg-ok -if /i "%1"=="x86" set target_arch=ia32&set msbuild_platform=WIN32&set vs_toolset=x86&goto arg-ok -if /i "%1"=="ia32" set target_arch=ia32&set msbuild_platform=WIN32&set vs_toolset=x86&goto arg-ok -if /i "%1"=="x64" set target_arch=x64&set msbuild_platform=x64&set vs_toolset=x64&goto arg-ok -if /i "%1"=="shared" set library=shared_library&goto arg-ok -if /i "%1"=="static" set library=static_library&goto arg-ok -:arg-ok -shift -goto next-arg -:args-done - -if defined WindowsSDKDir goto select-target -if defined VCINSTALLDIR goto select-target - -@rem Look for Visual Studio 2017 only if explicitly requested. -if "%target_env%" NEQ "vs2017" goto vs-set-2015 -echo Looking for Visual Studio 2017 -@rem Check if VS2017 is already setup, and for the requested arch. -if "_%VisualStudioVersion%_" == "_15.0_" if "_%VSCMD_ARG_TGT_ARCH%_"=="_%vs_toolset%_" goto found_vs2017 -set "VSINSTALLDIR=" -call tools\vswhere_usability_wrapper.cmd -if "_%VCINSTALLDIR%_" == "__" goto vs-set-2015 -@rem Need to clear VSINSTALLDIR for vcvarsall to work as expected. -@rem Keep current working directory after call to vcvarsall -set "VSCMD_START_DIR=%CD%" -set vcvars_call="%VCINSTALLDIR%\Auxiliary\Build\vcvarsall.bat" %vs_toolset% -echo calling: %vcvars_call% -call %vcvars_call% - -:found_vs2017 -echo Found MSVS version %VisualStudioVersion% -if %VSCMD_ARG_TGT_ARCH%==x64 set target_arch=x64&set msbuild_platform=x64&set vs_toolset=x64 -set GYP_MSVS_VERSION=2017 -goto select-target - - -@rem Look for Visual Studio 2015 -:vs-set-2015 -if not defined VS140COMNTOOLS goto vc-set-2013 -if not exist "%VS140COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2013 -call "%VS140COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% -set GYP_MSVS_VERSION=2015 -echo Using Visual Studio 2015 -goto select-target - -:vc-set-2013 -@rem Look for Visual Studio 2013 -if not defined VS120COMNTOOLS goto vc-set-2012 -if not exist "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2012 -call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% -set GYP_MSVS_VERSION=2013 -echo Using Visual Studio 2013 -goto select-target - -:vc-set-2012 -@rem Look for Visual Studio 2012 -if not defined VS110COMNTOOLS goto vc-set-2010 -if not exist "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2010 -call "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% -set GYP_MSVS_VERSION=2012 -echo Using Visual Studio 2012 -goto select-target - -:vc-set-2010 -@rem Look for Visual Studio 2010 -if not defined VS100COMNTOOLS goto vc-set-2008 -if not exist "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2008 -call "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% -set GYP_MSVS_VERSION=2010 -echo Using Visual Studio 2010 -goto select-target - -:vc-set-2008 -@rem Look for Visual Studio 2008 -if not defined VS90COMNTOOLS goto vc-set-notfound -if not exist "%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-notfound -call "%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% -set GYP_MSVS_VERSION=2008 -echo Using Visual Studio 2008 -goto select-target - -:vc-set-notfound -echo Warning: Visual Studio not found - -:select-target -if not "%config%"=="" goto project-gen -if "%run%"=="run-tests.exe" set config=Debug& goto project-gen -if "%run%"=="run-benchmarks.exe" set config=Release& goto project-gen -set config=Debug - -:project-gen -@rem Skip project generation if requested. -if defined noprojgen goto msbuild - -@rem Generate the VS project. -if exist build\gyp goto have_gyp -echo git clone https://chromium.googlesource.com/external/gyp build/gyp -git clone https://chromium.googlesource.com/external/gyp build/gyp -if errorlevel 1 goto gyp_install_failed -goto have_gyp - -:gyp_install_failed -echo Failed to download gyp. Make sure you have git installed, or -echo manually install gyp into %~dp0build\gyp. -exit /b 1 - -:have_gyp -if not defined PYTHON set PYTHON=python -"%PYTHON%" gyp_uv.py -Dtarget_arch=%target_arch% -Duv_library=%library% -if errorlevel 1 goto create-msvs-files-failed -if not exist uv.sln goto create-msvs-files-failed -echo Project files generated. - -:msbuild -@rem Skip project generation if requested. -if defined nobuild goto run - -@rem Check if VS build env is available -if defined VCINSTALLDIR goto msbuild-found -if defined WindowsSDKDir goto msbuild-found -echo Build skipped. To build, this file needs to run from VS cmd prompt. -goto run - -@rem Build the sln with msbuild. -:msbuild-found -msbuild uv.sln /t:%target% /p:Configuration=%config% /p:Platform="%msbuild_platform%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo -if errorlevel 1 exit /b 1 -msbuild test\test.sln /t:%target% /p:Configuration=%config% /p:Platform="%msbuild_platform%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo -if errorlevel 1 exit /b 1 - -:run -@rem Run tests if requested. -if "%run%"=="" goto exit -echo running 'test\%config%\%run%' -test\%config%\%run% -goto exit - -:create-msvs-files-failed -echo Failed to create vc project files. -exit /b 1 - -:help -echo vcbuild.bat [debug/release] [test/bench] [clean] [noprojgen] [nobuild] [vs2017] [x86/x64] [static/shared] -echo Examples: -echo vcbuild.bat : builds debug build -echo vcbuild.bat test : builds debug build and runs tests -echo vcbuild.bat release bench: builds release build and runs benchmarks -goto exit - -:exit diff --git a/deps/uvwasi/include/fd_table.h b/deps/uvwasi/include/fd_table.h index f29b1adf88d6f0..474a0231e03baf 100644 --- a/deps/uvwasi/include/fd_table.h +++ b/deps/uvwasi/include/fd_table.h @@ -13,6 +13,7 @@ struct uvwasi_fd_wrap_t { uv_file fd; char* path; char* real_path; + char* normalized_path; uvwasi_filetype_t type; uvwasi_rights_t rights_base; uvwasi_rights_t rights_inheriting; diff --git a/deps/uvwasi/include/uvwasi.h b/deps/uvwasi/include/uvwasi.h index 39ee2f0ceb6609..f2d2d1a9fd8945 100644 --- a/deps/uvwasi/include/uvwasi.h +++ b/deps/uvwasi/include/uvwasi.h @@ -11,7 +11,7 @@ extern "C" { #define UVWASI_VERSION_MAJOR 0 #define UVWASI_VERSION_MINOR 0 -#define UVWASI_VERSION_PATCH 6 +#define UVWASI_VERSION_PATCH 8 #define UVWASI_VERSION_HEX ((UVWASI_VERSION_MAJOR << 16) | \ (UVWASI_VERSION_MINOR << 8) | \ (UVWASI_VERSION_PATCH)) @@ -66,7 +66,7 @@ typedef struct uvwasi_options_s { const uvwasi_mem_t* allocator; } uvwasi_options_t; -// Embedder API. +/* Embedder API. */ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options); void uvwasi_destroy(uvwasi_t* uvwasi); uvwasi_errno_t uvwasi_embedder_remap_fd(uvwasi_t* uvwasi, @@ -75,7 +75,7 @@ uvwasi_errno_t uvwasi_embedder_remap_fd(uvwasi_t* uvwasi, const char* uvwasi_embedder_err_code_to_string(uvwasi_errno_t code); -// WASI system call API. +/* WASI system call API. */ uvwasi_errno_t uvwasi_args_get(uvwasi_t* uvwasi, char** argv, char* argv_buf); uvwasi_errno_t uvwasi_args_sizes_get(uvwasi_t* uvwasi, size_t* argc, diff --git a/deps/uvwasi/include/wasi_types.h b/deps/uvwasi/include/wasi_types.h index ec1013663f6a76..2f93b412624c06 100644 --- a/deps/uvwasi/include/wasi_types.h +++ b/deps/uvwasi/include/wasi_types.h @@ -4,7 +4,7 @@ #include #include -/* API: https://github.com/WebAssembly/WASI/blob/master/phases/unstable/docs/wasi_unstable_preview0.md */ +/* API: https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/docs.md */ typedef uint8_t uvwasi_advice_t; #define UVWASI_ADVICE_NORMAL 0 diff --git a/deps/uvwasi/src/clocks.c b/deps/uvwasi/src/clocks.c index fd42b9e50e4d8e..b59cbd6bb192c0 100644 --- a/deps/uvwasi/src/clocks.c +++ b/deps/uvwasi/src/clocks.c @@ -153,7 +153,7 @@ uvwasi_errno_t uvwasi__clock_gettime_thread_cputime(uvwasi_timestamp_t* time) { UVWASI__WIN_TIME_AND_RETURN(GetCurrentThread(), *time); #elif defined(__APPLE__) UVWASI__OSX_THREADTIME_AND_RETURN(*time); -#elif defined(CLOCK_THREAD_CPUTIME_ID) && !defined(__sun) +#elif defined(CLOCK_THREAD_CPUTIME_ID) && !defined(__sun) && !defined(__PASE__) UVWASI__CLOCK_GETTIME_AND_RETURN(CLOCK_THREAD_CPUTIME_ID, *time); #else # if defined(RUSAGE_LWP) @@ -185,7 +185,7 @@ uvwasi_errno_t uvwasi__clock_getres_thread_cputime(uvwasi_timestamp_t* time) { UVWASI__WIN_GETRES_AND_RETURN(*time); #elif defined(__APPLE__) UVWASI__SLOW_GETRES_AND_RETURN(*time); -#elif defined(CLOCK_THREAD_CPUTIME_ID) && !defined(__sun) +#elif defined(CLOCK_THREAD_CPUTIME_ID) && !defined(__sun) && !defined(__PASE__) UVWASI__CLOCK_GETTIME_AND_RETURN(CLOCK_THREAD_CPUTIME_ID, *time); #elif defined(RUSAGE_THREAD) || defined(RUSAGE_LWP) UVWASI__SLOW_GETRES_AND_RETURN(*time); diff --git a/deps/uvwasi/src/fd_table.c b/deps/uvwasi/src/fd_table.c index f6e530d9591df2..3d134e3b7e5e2e 100644 --- a/deps/uvwasi/src/fd_table.c +++ b/deps/uvwasi/src/fd_table.c @@ -8,6 +8,7 @@ #include "uv.h" #include "fd_table.h" +#include "path_resolver.h" #include "wasi_types.h" #include "wasi_rights.h" #include "uv_mapping.h" @@ -75,20 +76,33 @@ uvwasi_errno_t uvwasi_fd_table_insert(uvwasi_t* uvwasi, char* mp_copy; size_t rp_len; char* rp_copy; + char* np_copy; mp_len = strlen(mapped_path); rp_len = strlen(real_path); + /* Reserve room for the mapped path, real path, and normalized mapped path. */ entry = (struct uvwasi_fd_wrap_t*) - uvwasi__malloc(uvwasi, sizeof(*entry) + mp_len + rp_len + 2); - if (entry == NULL) return UVWASI_ENOMEM; + uvwasi__malloc(uvwasi, sizeof(*entry) + mp_len + mp_len + rp_len + 3); + if (entry == NULL) + return UVWASI_ENOMEM; mp_copy = (char*)(entry + 1); rp_copy = mp_copy + mp_len + 1; + np_copy = rp_copy + rp_len + 1; memcpy(mp_copy, mapped_path, mp_len); mp_copy[mp_len] = '\0'; memcpy(rp_copy, real_path, rp_len); rp_copy[rp_len] = '\0'; + /* Calculate the normalized version of the mapped path, as it will be used for + any path calculations on this fd. Use the length of the mapped path as an + upper bound for the normalized path length. */ + err = uvwasi__normalize_path(mp_copy, mp_len, np_copy, mp_len); + if (err) { + uvwasi__free(uvwasi, entry); + goto exit; + } + uv_rwlock_wrlock(&table->rwlock); /* Check that there is room for a new item. If there isn't, grow the table. */ @@ -138,6 +152,7 @@ uvwasi_errno_t uvwasi_fd_table_insert(uvwasi_t* uvwasi, entry->fd = fd; entry->path = mp_copy; entry->real_path = rp_copy; + entry->normalized_path = np_copy; entry->type = type; entry->rights_base = rights_base; entry->rights_inheriting = rights_inheriting; diff --git a/deps/uvwasi/src/path_resolver.c b/deps/uvwasi/src/path_resolver.c new file mode 100644 index 00000000000000..ee0e60f7e8f4ea --- /dev/null +++ b/deps/uvwasi/src/path_resolver.c @@ -0,0 +1,492 @@ +#include + +#include "uv.h" +#include "uvwasi.h" +#include "uvwasi_alloc.h" +#include "uv_mapping.h" +#include "path_resolver.h" + +#define UVWASI__MAX_SYMLINK_FOLLOWS 32 + +#ifndef _WIN32 +# define IS_SLASH(c) ((c) == '/') +#else +# define IS_SLASH(c) ((c) == '/' || (c) == '\\') +#endif /* _WIN32 */ + + +static int uvwasi__is_absolute_path(const char* path, size_t path_len) { + /* It's expected that only Unix style paths will be generated by WASI. */ + return path != NULL && path_len > 0 && path[0] == '/'; +} + + +static char* uvwasi__strchr_slash(const char* s) { + /* strchr() that identifies /, as well as \ on Windows. */ + do { + if (IS_SLASH(*s)) + return (char*) s; + } while (*s++); + + return NULL; +} + + +uvwasi_errno_t uvwasi__normalize_path(const char* path, + size_t path_len, + char* normalized_path, + size_t normalized_len) { + const char* cur; + char* ptr; + char* next; + char* last; + size_t cur_len; + int is_absolute; + + if (path_len > normalized_len) + return UVWASI_ENOBUFS; + + is_absolute = uvwasi__is_absolute_path(path, path_len); + normalized_path[0] = '\0'; + ptr = normalized_path; + for (cur = path; cur != NULL; cur = next + 1) { + next = uvwasi__strchr_slash(cur); + cur_len = (next == NULL) ? strlen(cur) : (size_t) (next - cur); + + if (cur_len == 0) { + if (ptr == normalized_path && next != NULL && is_absolute) { + *ptr = '/'; + ptr++; + } + + *ptr = '\0'; + } else if (cur_len == 1 && cur[0] == '.') { + /* No-op. Just consume the '.' */ + } else if (cur_len == 2 && cur[0] == '.' && cur[1] == '.') { + /* Identify the path segment that preceded the current one. */ + last = ptr; + while (!IS_SLASH(*last) && last != normalized_path) { + last--; + } + + /* If the result is currently empty, or the last prior path is also '..' + then output '..'. Otherwise, remove the last path segment. */ + if (ptr == normalized_path || + (last == ptr - 2 && last[0] == '.' && last[1] == '.') || + (last == ptr - 3 && last[0] == '/' && + last[1] == '.' && last[2] == '.')) { + if (ptr != normalized_path && *(ptr - 1) != '/') { + *ptr = '/'; + ptr++; + } + + *ptr = '.'; + ptr++; + *ptr = '.'; + ptr++; + } else { + /* Strip the last segment, but make sure not to strip the '/' if that + is the entire path. */ + if (last == normalized_path && *last == '/') + ptr = last + 1; + else + ptr = last; + } + + *ptr = '\0'; + } else { + if (ptr != normalized_path && *(ptr - 1) != '/') { + *ptr = '/'; + ptr++; + } + + memcpy(ptr, cur, cur_len); + ptr += cur_len; + *ptr = '\0'; + } + + if (next == NULL) + break; + } + + /* Normalized the path to the empty string. Return either '/' or '.'. */ + if (ptr == normalized_path) { + if (1 == is_absolute) + *ptr = '/'; + else + *ptr = '.'; + + ptr++; + *ptr = '\0'; + } + + return UVWASI_ESUCCESS; +} + + +static int uvwasi__is_path_sandboxed(const char* path, + size_t path_len, + const char* fd_path, + size_t fd_path_len) { + char* ptr; + int remaining_len; + + if (1 == uvwasi__is_absolute_path(fd_path, fd_path_len)) + return path == strstr(path, fd_path) ? 1 : 0; + + /* Handle relative fds that normalized to '.' */ + if (fd_path_len == 1 && fd_path[0] == '.') { + /* If the fd's path is '.', then any path does not begin with '..' is OK. */ + if ((path_len == 2 && path[0] == '.' && path[1] == '.') || + (path_len > 2 && path[0] == '.' && path[1] == '.' && path[2] == '/')) { + return 0; + } + + return 1; + } + + if (path != strstr(path, fd_path)) + return 0; + + /* Fail if the remaining path starts with '..', '../', '/..', or '/../'. */ + ptr = (char*) path + fd_path_len; + remaining_len = path_len - fd_path_len; + if (remaining_len < 2) + return 1; + + /* Strip a leading slash so the check is only for '..' and '../'. */ + if (*ptr == '/') { + ptr++; + remaining_len--; + } + + if ((remaining_len == 2 && ptr[0] == '.' && ptr[1] == '.') || + (remaining_len > 2 && ptr[0] == '.' && ptr[1] == '.' && ptr[2] == '/')) { + return 0; + } + + return 1; +} + + +static uvwasi_errno_t uvwasi__normalize_absolute_path( + const uvwasi_t* uvwasi, + const struct uvwasi_fd_wrap_t* fd, + const char* path, + size_t path_len, + char** normalized_path, + size_t* normalized_len + ) { + /* This function resolves an absolute path to the provided file descriptor. + If the file descriptor's path is relative, then this operation will fail + with UVWASI_ENOTCAPABLE since it doesn't make sense to resolve an absolute + path to a relative prefix. If the file desciptor's path is also absolute, + then we just need to verify that the normalized path still starts with + the file descriptor's path. */ + uvwasi_errno_t err; + char* abs_path; + int abs_size; + + *normalized_path = NULL; + *normalized_len = 0; + abs_size = path_len + 1; + abs_path = uvwasi__malloc(uvwasi, abs_size); + if (abs_path == NULL) { + err = UVWASI_ENOMEM; + goto exit; + } + + /* Normalize the input path first. */ + err = uvwasi__normalize_path(path, path_len, abs_path, path_len); + if (err != UVWASI_ESUCCESS) + goto exit; + + /* Once the input is normalized, ensure that it is still sandboxed. */ + if (0 == uvwasi__is_path_sandboxed(abs_path, + path_len, + fd->normalized_path, + strlen(fd->normalized_path))) { + err = UVWASI_ENOTCAPABLE; + goto exit; + } + + *normalized_path = abs_path; + *normalized_len = abs_size - 1; + return UVWASI_ESUCCESS; + +exit: + uvwasi__free(uvwasi, abs_path); + return err; +} + + +static uvwasi_errno_t uvwasi__normalize_relative_path( + const uvwasi_t* uvwasi, + const struct uvwasi_fd_wrap_t* fd, + const char* path, + size_t path_len, + char** normalized_path, + size_t* normalized_len + ) { + /* This function resolves a relative path to the provided file descriptor. + The relative path is concatenated to the file descriptor's path, and then + normalized. */ + uvwasi_errno_t err; + char* combined; + char* normalized; + int combined_size; + int fd_path_len; + int norm_len; + int r; + + *normalized_path = NULL; + *normalized_len = 0; + + /* The max combined size is the path length + the file descriptor's path + length + 2 for a terminating NULL and a possible path separator. */ + fd_path_len = strlen(fd->normalized_path); + combined_size = path_len + fd_path_len + 2; + combined = uvwasi__malloc(uvwasi, combined_size); + if (combined == NULL) + return UVWASI_ENOMEM; + + normalized = uvwasi__malloc(uvwasi, combined_size); + if (normalized == NULL) { + err = UVWASI_ENOMEM; + goto exit; + } + + r = snprintf(combined, combined_size, "%s/%s", fd->normalized_path, path); + if (r <= 0) { + err = uvwasi__translate_uv_error(uv_translate_sys_error(errno)); + goto exit; + } + + /* Normalize the input path. */ + err = uvwasi__normalize_path(combined, + combined_size - 1, + normalized, + combined_size - 1); + if (err != UVWASI_ESUCCESS) + goto exit; + + norm_len = strlen(normalized); + + /* Once the path is normalized, ensure that it is still sandboxed. */ + if (0 == uvwasi__is_path_sandboxed(normalized, + norm_len, + fd->normalized_path, + fd_path_len)) { + err = UVWASI_ENOTCAPABLE; + goto exit; + } + + err = UVWASI_ESUCCESS; + *normalized_path = normalized; + *normalized_len = norm_len; + +exit: + if (err != UVWASI_ESUCCESS) + uvwasi__free(uvwasi, normalized); + + uvwasi__free(uvwasi, combined); + return err; +} + + +static uvwasi_errno_t uvwasi__resolve_path_to_host( + const uvwasi_t* uvwasi, + const struct uvwasi_fd_wrap_t* fd, + const char* path, + size_t path_len, + char** resolved_path, + size_t* resolved_len + ) { + /* Return the normalized path, but resolved to the host's real path. */ + char* res_path; + char* stripped_path; + int real_path_len; + int fake_path_len; + int stripped_len; +#ifdef _WIN32 + size_t i; +#endif /* _WIN32 */ + + real_path_len = strlen(fd->real_path); + fake_path_len = strlen(fd->normalized_path); + + /* If the fake path is '.' just ignore it. */ + if (fake_path_len == 1 && fd->normalized_path[0] == '.') { + fake_path_len = 0; + } + + stripped_len = path_len - fake_path_len; + + /* The resolved path's length is calculated as: the length of the fd's real + path, + 1 for a path separator, and the length of the input path (with the + fake path stripped off). */ + *resolved_len = stripped_len + real_path_len + 1; + *resolved_path = uvwasi__malloc(uvwasi, *resolved_len + 1); + + if (*resolved_path == NULL) + return UVWASI_ENOMEM; + + res_path = *resolved_path; + stripped_path = (char*) path + fake_path_len; + memcpy(res_path, fd->real_path, real_path_len); + res_path += real_path_len; + + if (stripped_len > 1 || + (stripped_len == 1 && stripped_path[0] != '/')) { + if (stripped_path[0] != '/') { + *res_path = '/'; + res_path++; + } + + memcpy(res_path, stripped_path, stripped_len); + res_path += stripped_len; + } + + *res_path = '\0'; + +#ifdef _WIN32 + /* Replace / with \ on Windows. */ + for (i = real_path_len; i < *resolved_len; i++) { + if (res_path[i] == '/') + res_path[i] = '\\'; + } +#endif /* _WIN32 */ + + return UVWASI_ESUCCESS; +} + + +uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi, + const struct uvwasi_fd_wrap_t* fd, + const char* path, + size_t path_len, + char* resolved_path, + uvwasi_lookupflags_t flags) { + uv_fs_t req; + uvwasi_errno_t err; + const char* input; + char* host_path; + char* normalized_path; + char* link_target; + size_t input_len; + size_t host_path_len; + size_t normalized_len; + int follow_count; + int r; + + input = path; + input_len = path_len; + link_target = NULL; + follow_count = 0; + host_path = NULL; + +start: + normalized_path = NULL; + err = UVWASI_ESUCCESS; + + if (1 == uvwasi__is_absolute_path(input, input_len)) { + err = uvwasi__normalize_absolute_path(uvwasi, + fd, + input, + input_len, + &normalized_path, + &normalized_len); + } else { + err = uvwasi__normalize_relative_path(uvwasi, + fd, + input, + input_len, + &normalized_path, + &normalized_len); + } + + if (err != UVWASI_ESUCCESS) + goto exit; + + uvwasi__free(uvwasi, host_path); + err = uvwasi__resolve_path_to_host(uvwasi, + fd, + normalized_path, + normalized_len, + &host_path, + &host_path_len); + if (err != UVWASI_ESUCCESS) + goto exit; + + /* TODO(cjihrig): Currently performing a bounds check here. The TODO is to + stop allocating resolved_path in every caller and instead return the + path allocated in this function. */ + if (host_path_len > PATH_MAX_BYTES) { + err = UVWASI_ENOBUFS; + goto exit; + } + + if ((flags & UVWASI_LOOKUP_SYMLINK_FOLLOW) == UVWASI_LOOKUP_SYMLINK_FOLLOW) { + r = uv_fs_readlink(NULL, &req, host_path, NULL); + + if (r != 0) { +#ifdef _WIN32 + /* uv_fs_readlink() returns UV__UNKNOWN on Windows. Try to get a better + error using uv_fs_stat(). */ + if (r == UV__UNKNOWN) { + uv_fs_req_cleanup(&req); + r = uv_fs_stat(NULL, &req, host_path, NULL); + + if (r == 0) { + if (uvwasi__stat_to_filetype(&req.statbuf) != + UVWASI_FILETYPE_SYMBOLIC_LINK) { + r = UV_EINVAL; + } + } + + /* Fall through. */ + } +#endif /* _WIN32 */ + + /* Don't report UV_EINVAL or UV_ENOENT. They mean that either the file + does not exist, or it is not a symlink. Both are OK. */ + if (r != UV_EINVAL && r != UV_ENOENT) + err = uvwasi__translate_uv_error(r); + + uv_fs_req_cleanup(&req); + goto exit; + } + + /* Clean up memory and follow the link, unless it's time to return ELOOP. */ + follow_count++; + if (follow_count >= UVWASI__MAX_SYMLINK_FOLLOWS) { + uv_fs_req_cleanup(&req); + err = UVWASI_ELOOP; + goto exit; + } + + input_len = strlen(req.ptr); + uvwasi__free(uvwasi, link_target); + link_target = uvwasi__malloc(uvwasi, input_len + 1); + if (link_target == NULL) { + uv_fs_req_cleanup(&req); + err = UVWASI_ENOMEM; + goto exit; + } + + memcpy(link_target, req.ptr, input_len + 1); + input = link_target; + uvwasi__free(uvwasi, normalized_path); + uv_fs_req_cleanup(&req); + goto start; + } + +exit: + if (err == UVWASI_ESUCCESS) + memcpy(resolved_path, host_path, host_path_len + 1); + + uvwasi__free(uvwasi, link_target); + uvwasi__free(uvwasi, normalized_path); + uvwasi__free(uvwasi, host_path); + return err; +} diff --git a/deps/uvwasi/src/path_resolver.h b/deps/uvwasi/src/path_resolver.h new file mode 100644 index 00000000000000..d5f95eafbfbf83 --- /dev/null +++ b/deps/uvwasi/src/path_resolver.h @@ -0,0 +1,28 @@ +#ifndef __UVWASI_PATH_RESOLVER_H__ +#define __UVWASI_PATH_RESOLVER_H__ + +#include "uvwasi.h" + +/* TODO(cjihrig): PATH_MAX_BYTES shouldn't be stack allocated. On Windows, paths + can be 32k long, and this PATH_MAX_BYTES is an artificial limitation. */ +#ifdef _WIN32 +/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */ +# define PATH_MAX_BYTES (MAX_PATH * 4) +#else +# include +# define PATH_MAX_BYTES (PATH_MAX) +#endif + +uvwasi_errno_t uvwasi__normalize_path(const char* path, + size_t path_len, + char* normalized_path, + size_t normalized_len); + +uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi, + const struct uvwasi_fd_wrap_t* fd, + const char* path, + size_t path_len, + char* resolved_path, + uvwasi_lookupflags_t flags); + +#endif /* __UVWASI_PATH_RESOLVER_H__ */ diff --git a/deps/uvwasi/src/uvwasi.c b/deps/uvwasi/src/uvwasi.c index c80fc7715c1dc0..0ee66be36a3951 100644 --- a/deps/uvwasi/src/uvwasi.c +++ b/deps/uvwasi/src/uvwasi.c @@ -7,14 +7,11 @@ # include # include # include -# define IS_SLASH(c) ((c) == '/') #else # include -# define IS_SLASH(c) ((c) == '/' || (c) == '\\') #endif /* _WIN32 */ #define UVWASI__READDIR_NUM_ENTRIES 1 -#define UVWASI__MAX_SYMLINK_FOLLOWS 32 #include "uvwasi.h" #include "uvwasi_alloc.h" @@ -22,18 +19,9 @@ #include "uv_mapping.h" #include "fd_table.h" #include "clocks.h" +#include "path_resolver.h" #include "wasi_rights.h" -/* TODO(cjihrig): PATH_MAX_BYTES shouldn't be stack allocated. On Windows, paths - can be 32k long, and this PATH_MAX_BYTES is an artificial limitation. */ -#ifdef _WIN32 -/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */ -# define PATH_MAX_BYTES (MAX_PATH * 4) -#else -# include -# define PATH_MAX_BYTES (PATH_MAX) -#endif - /* IBMi PASE does not support posix_fadvise() */ #ifdef __PASE__ # undef POSIX_FADV_NORMAL @@ -84,322 +72,6 @@ static const uvwasi_mem_t default_allocator = { }; -static int uvwasi__is_absolute_path(const char* path, size_t path_len) { - /* It's expected that only Unix style paths will be generated by WASI. */ - return path != NULL && path_len > 0 && path[0] == '/'; -} - - -static char* uvwasi__strchr_slash(const char* s) { - /* strchr() that identifies /, as well as \ on Windows. */ - do { - if (IS_SLASH(*s)) - return (char*) s; - } while (*s++); - - return NULL; -} - - -static uvwasi_errno_t uvwasi__normalize_path(const char* path, - size_t path_len, - char* normalized_path, - size_t normalized_len) { - const char* cur; - char* ptr; - char* next; - size_t cur_len; - - if (path_len > normalized_len) - return UVWASI_ENOBUFS; - - normalized_path[0] = '\0'; - ptr = normalized_path; - for (cur = path; cur != NULL; cur = next + 1) { - next = uvwasi__strchr_slash(cur); - cur_len = (next == NULL) ? strlen(cur) : (size_t) (next - cur); - - if (cur_len == 0 || (cur_len == 1 && cur[0] == '.')) - continue; - - if (cur_len == 2 && cur[0] == '.' && cur[1] == '.') { - while (!IS_SLASH(*ptr) && ptr != normalized_path) - ptr--; - *ptr = '\0'; - continue; - } - - *ptr = '/'; - ptr++; - memcpy(ptr, cur, cur_len); - ptr += cur_len; - *ptr = '\0'; - - if (next == NULL) - break; - } - - return UVWASI_ESUCCESS; -} - - -static uvwasi_errno_t uvwasi__resolve_path_to_host( - const uvwasi_t* uvwasi, - const struct uvwasi_fd_wrap_t* fd, - const char* path, - size_t path_len, - char** resolved_path, - size_t* resolved_len - ) { - /* Return the normalized path, but resolved to the host's real path. */ - int real_path_len; - int fake_path_len; -#ifdef _WIN32 - size_t i; -#endif /* _WIN32 */ - - real_path_len = strlen(fd->real_path); - fake_path_len = strlen(fd->path); - *resolved_len = path_len - fake_path_len + real_path_len; - *resolved_path = uvwasi__malloc(uvwasi, *resolved_len + 1); - - if (*resolved_path == NULL) - return UVWASI_ENOMEM; - - memcpy(*resolved_path, fd->real_path, real_path_len); - memcpy(*resolved_path + real_path_len, - path + fake_path_len, - path_len - fake_path_len + 1); - -#ifdef _WIN32 - /* Replace / with \ on Windows. */ - for (i = real_path_len; i < *resolved_len; i++) { - if ((*resolved_path)[i] == '/') - (*resolved_path)[i] = '\\'; - } -#endif /* _WIN32 */ - - return UVWASI_ESUCCESS; -} - - -static uvwasi_errno_t uvwasi__normalize_absolute_path( - const uvwasi_t* uvwasi, - const struct uvwasi_fd_wrap_t* fd, - const char* path, - size_t path_len, - char** normalized_path, - size_t* normalized_len - ) { - uvwasi_errno_t err; - char* abs_path; - int abs_size; - - *normalized_path = NULL; - *normalized_len = 0; - abs_size = path_len + 1; - abs_path = uvwasi__malloc(uvwasi, abs_size); - if (abs_path == NULL) { - err = UVWASI_ENOMEM; - goto exit; - } - - /* Normalize the input path first. */ - err = uvwasi__normalize_path(path, - path_len, - abs_path, - path_len); - if (err != UVWASI_ESUCCESS) - goto exit; - - /* Once the input is normalized, ensure that it is still sandboxed. */ - if (abs_path != strstr(abs_path, fd->path)) { - err = UVWASI_ENOTCAPABLE; - goto exit; - } - - *normalized_path = abs_path; - *normalized_len = abs_size - 1; - return UVWASI_ESUCCESS; - -exit: - uvwasi__free(uvwasi, abs_path); - return err; -} - - -static uvwasi_errno_t uvwasi__normalize_relative_path( - const uvwasi_t* uvwasi, - const struct uvwasi_fd_wrap_t* fd, - const char* path, - size_t path_len, - char** normalized_path, - size_t* normalized_len - ) { - uvwasi_errno_t err; - char* abs_path; - int abs_size; - int r; - - *normalized_path = NULL; - *normalized_len = 0; - abs_size = path_len + strlen(fd->path) + 2; - abs_path = uvwasi__malloc(uvwasi, abs_size); - if (abs_path == NULL) { - err = UVWASI_ENOMEM; - goto exit; - } - - /* Resolve the relative path to an absolute path based on fd's fake path. */ - r = snprintf(abs_path, abs_size, "%s/%s", fd->path, path); - if (r <= 0) { - err = uvwasi__translate_uv_error(uv_translate_sys_error(errno)); - goto exit; - } - - err = uvwasi__normalize_absolute_path(uvwasi, - fd, - abs_path, - abs_size - 1, - normalized_path, - normalized_len); -exit: - uvwasi__free(uvwasi, abs_path); - return err; -} - - -static uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi, - const struct uvwasi_fd_wrap_t* fd, - const char* path, - size_t path_len, - char* resolved_path, - uvwasi_lookupflags_t flags) { - uv_fs_t req; - uvwasi_errno_t err; - const char* input; - char* host_path; - char* normalized_path; - char* link_target; - size_t input_len; - size_t host_path_len; - size_t normalized_len; - int follow_count; - int r; - - input = path; - input_len = path_len; - link_target = NULL; - follow_count = 0; - host_path = NULL; - -start: - normalized_path = NULL; - err = UVWASI_ESUCCESS; - - if (1 == uvwasi__is_absolute_path(input, input_len)) { - err = uvwasi__normalize_absolute_path(uvwasi, - fd, - input, - input_len, - &normalized_path, - &normalized_len); - } else { - err = uvwasi__normalize_relative_path(uvwasi, - fd, - input, - input_len, - &normalized_path, - &normalized_len); - } - - if (err != UVWASI_ESUCCESS) - goto exit; - - uvwasi__free(uvwasi, host_path); - err = uvwasi__resolve_path_to_host(uvwasi, - fd, - normalized_path, - normalized_len, - &host_path, - &host_path_len); - if (err != UVWASI_ESUCCESS) - goto exit; - - /* TODO(cjihrig): Currently performing a bounds check here. The TODO is to - stop allocating resolved_path in every caller and instead return the - path allocated in this function. */ - if (host_path_len > PATH_MAX_BYTES) { - err = UVWASI_ENOBUFS; - goto exit; - } - - if ((flags & UVWASI_LOOKUP_SYMLINK_FOLLOW) == UVWASI_LOOKUP_SYMLINK_FOLLOW) { - r = uv_fs_readlink(NULL, &req, host_path, NULL); - - if (r != 0) { -#ifdef _WIN32 - /* uv_fs_readlink() returns UV__UNKNOWN on Windows. Try to get a better - error using uv_fs_stat(). */ - if (r == UV__UNKNOWN) { - uv_fs_req_cleanup(&req); - r = uv_fs_stat(NULL, &req, host_path, NULL); - - if (r == 0) { - if (uvwasi__stat_to_filetype(&req.statbuf) != - UVWASI_FILETYPE_SYMBOLIC_LINK) { - r = UV_EINVAL; - } - } - - // Fall through. - } -#endif /* _WIN32 */ - - /* Don't report UV_EINVAL or UV_ENOENT. They mean that either the file - does not exist, or it is not a symlink. Both are OK. */ - if (r != UV_EINVAL && r != UV_ENOENT) - err = uvwasi__translate_uv_error(r); - - uv_fs_req_cleanup(&req); - goto exit; - } - - /* Clean up memory and follow the link, unless it's time to return ELOOP. */ - follow_count++; - if (follow_count >= UVWASI__MAX_SYMLINK_FOLLOWS) { - uv_fs_req_cleanup(&req); - err = UVWASI_ELOOP; - goto exit; - } - - input_len = strlen(req.ptr); - uvwasi__free(uvwasi, link_target); - link_target = uvwasi__malloc(uvwasi, input_len + 1); - if (link_target == NULL) { - uv_fs_req_cleanup(&req); - err = UVWASI_ENOMEM; - goto exit; - } - - memcpy(link_target, req.ptr, input_len + 1); - input = link_target; - uvwasi__free(uvwasi, normalized_path); - uv_fs_req_cleanup(&req); - goto start; - } - -exit: - if (err == UVWASI_ESUCCESS) - memcpy(resolved_path, host_path, host_path_len + 1); - - uvwasi__free(uvwasi, link_target); - uvwasi__free(uvwasi, normalized_path); - uvwasi__free(uvwasi, host_path); - return err; -} - - static uvwasi_errno_t uvwasi__lseek(uv_file fd, uvwasi_filedelta_t offset, uvwasi_whence_t whence, diff --git a/deps/uvwasi/uvwasi.gyp b/deps/uvwasi/uvwasi.gyp index 6963cbf20a7923..42769095ecbafd 100644 --- a/deps/uvwasi/uvwasi.gyp +++ b/deps/uvwasi/uvwasi.gyp @@ -11,6 +11,7 @@ 'sources': [ 'src/clocks.c', 'src/fd_table.c', + 'src/path_resolver.c', 'src/uv_mapping.c', 'src/uvwasi.c', 'src/wasi_rights.c', diff --git a/deps/v8/src/objects/js-number-format.cc b/deps/v8/src/objects/js-number-format.cc index ff564975d6f4a1..16699ceb29a1e4 100644 --- a/deps/v8/src/objects/js-number-format.cc +++ b/deps/v8/src/objects/js-number-format.cc @@ -1257,42 +1257,31 @@ MaybeHandle JSNumberFormat::New(Isolate* isolate, } namespace { -Maybe IcuFormatNumber( +Maybe IcuFormatNumber( Isolate* isolate, const icu::number::LocalizedNumberFormatter& number_format, - Handle numeric_obj, icu::FieldPositionIterator* fp_iter) { + Handle numeric_obj, icu::number::FormattedNumber* formatted) { // If it is BigInt, handle it differently. UErrorCode status = U_ZERO_ERROR; - icu::number::FormattedNumber formatted; if (numeric_obj->IsBigInt()) { Handle big_int = Handle::cast(numeric_obj); Handle big_int_string; ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, big_int_string, BigInt::ToString(isolate, big_int), - Nothing()); - formatted = number_format.formatDecimal( + Nothing()); + *formatted = number_format.formatDecimal( {big_int_string->ToCString().get(), big_int_string->length()}, status); } else { double number = numeric_obj->Number(); - formatted = number_format.formatDouble(number, status); + *formatted = number_format.formatDouble(number, status); } if (U_FAILURE(status)) { // This happen because of icu data trimming trim out "unit". // See https://bugs.chromium.org/p/v8/issues/detail?id=8641 - THROW_NEW_ERROR_RETURN_VALUE(isolate, - NewTypeError(MessageTemplate::kIcuError), - Nothing()); - } - if (fp_iter) { - formatted.getAllFieldPositions(*fp_iter, status); + THROW_NEW_ERROR_RETURN_VALUE( + isolate, NewTypeError(MessageTemplate::kIcuError), Nothing()); } - icu::UnicodeString result = formatted.toString(status); - if (U_FAILURE(status)) { - THROW_NEW_ERROR_RETURN_VALUE(isolate, - NewTypeError(MessageTemplate::kIcuError), - Nothing()); - } - return Just(result); + return Just(true); } } // namespace @@ -1303,10 +1292,16 @@ MaybeHandle JSNumberFormat::FormatNumeric( Handle numeric_obj) { DCHECK(numeric_obj->IsNumeric()); - Maybe maybe_format = - IcuFormatNumber(isolate, number_format, numeric_obj, nullptr); + icu::number::FormattedNumber formatted; + Maybe maybe_format = + IcuFormatNumber(isolate, number_format, numeric_obj, &formatted); MAYBE_RETURN(maybe_format, Handle()); - return Intl::ToString(isolate, maybe_format.FromJust()); + UErrorCode status = U_ZERO_ERROR; + icu::UnicodeString result = formatted.toString(status); + if (U_FAILURE(status)) { + THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kIcuError), String); + } + return Intl::ToString(isolate, result); } namespace { @@ -1419,12 +1414,18 @@ std::vector FlattenRegionsToParts( } namespace { -Maybe ConstructParts(Isolate* isolate, const icu::UnicodeString& formatted, - icu::FieldPositionIterator* fp_iter, +Maybe ConstructParts(Isolate* isolate, + icu::number::FormattedNumber* formatted, Handle result, int start_index, Handle numeric_obj, bool style_is_unit) { + UErrorCode status = U_ZERO_ERROR; + icu::UnicodeString formatted_text = formatted->toString(status); + if (U_FAILURE(status)) { + THROW_NEW_ERROR_RETURN_VALUE( + isolate, NewTypeError(MessageTemplate::kIcuError), Nothing()); + } DCHECK(numeric_obj->IsNumeric()); - int32_t length = formatted.length(); + int32_t length = formatted_text.length(); int index = start_index; if (length == 0) return Just(index); @@ -1433,13 +1434,14 @@ Maybe ConstructParts(Isolate* isolate, const icu::UnicodeString& formatted, // other region covers some part of the formatted string. It's possible // there's another field with exactly the same begin and end as this backdrop, // in which case the backdrop's field_id of -1 will give it lower priority. - regions.push_back(NumberFormatSpan(-1, 0, formatted.length())); + regions.push_back(NumberFormatSpan(-1, 0, formatted_text.length())); { - icu::FieldPosition fp; - while (fp_iter->next(fp)) { - regions.push_back(NumberFormatSpan(fp.getField(), fp.getBeginIndex(), - fp.getEndIndex())); + icu::ConstrainedFieldPosition cfp; + cfp.constrainCategory(UFIELD_CATEGORY_NUMBER); + while (formatted->nextPosition(cfp, status)) { + regions.push_back( + NumberFormatSpan(cfp.getField(), cfp.getStart(), cfp.getLimit())); } } @@ -1461,7 +1463,7 @@ Maybe ConstructParts(Isolate* isolate, const icu::UnicodeString& formatted, Handle substring; ASSIGN_RETURN_ON_EXCEPTION_VALUE( isolate, substring, - Intl::ToString(isolate, formatted, part.begin_pos, part.end_pos), + Intl::ToString(isolate, formatted_text, part.begin_pos, part.end_pos), Nothing()); Intl::AddElement(isolate, result, index, field_type_string, substring); ++index; @@ -1481,14 +1483,14 @@ MaybeHandle JSNumberFormat::FormatToParts( number_format->icu_number_formatter().raw(); CHECK_NOT_NULL(fmt); - icu::FieldPositionIterator fp_iter; - Maybe maybe_format = - IcuFormatNumber(isolate, *fmt, numeric_obj, &fp_iter); + icu::number::FormattedNumber formatted; + Maybe maybe_format = + IcuFormatNumber(isolate, *fmt, numeric_obj, &formatted); MAYBE_RETURN(maybe_format, Handle()); Handle result = factory->NewJSArray(0); Maybe maybe_format_to_parts = ConstructParts( - isolate, maybe_format.FromJust(), &fp_iter, result, 0, numeric_obj, + isolate, &formatted, result, 0, numeric_obj, number_format->style() == JSNumberFormat::Style::UNIT); MAYBE_RETURN(maybe_format_to_parts, Handle()); diff --git a/deps/v8/test/cctest/parsing/test-scanner-streams.cc b/deps/v8/test/cctest/parsing/test-scanner-streams.cc index 35b7048bb01e3b..28687cef5b4b25 100644 --- a/deps/v8/test/cctest/parsing/test-scanner-streams.cc +++ b/deps/v8/test/cctest/parsing/test-scanner-streams.cc @@ -331,8 +331,8 @@ TEST(Utf8AdvanceUntilOverChunkBoundaries) { for (size_t i = 1; i < len; i++) { // Copy source string into buffer, splitting it at i. // Then add three chunks, 0..i-1, i..strlen-1, empty. - strncpy(buffer, unicode_utf8, i); - strncpy(buffer + i + 1, unicode_utf8 + i, len - i); + memcpy(buffer, unicode_utf8, i); + memcpy(buffer + i + 1, unicode_utf8 + i, len - i); buffer[i] = '\0'; buffer[len + 1] = '\n'; buffer[len + 2] = '\0'; @@ -360,8 +360,8 @@ TEST(Utf8ChunkBoundaries) { for (size_t i = 1; i < len; i++) { // Copy source string into buffer, splitting it at i. // Then add three chunks, 0..i-1, i..strlen-1, empty. - strncpy(buffer, unicode_utf8, i); - strncpy(buffer + i + 1, unicode_utf8 + i, len - i); + memcpy(buffer, unicode_utf8, i); + memcpy(buffer + i + 1, unicode_utf8 + i, len - i); buffer[i] = '\0'; buffer[len + 1] = '\0'; buffer[len + 2] = '\0'; diff --git a/deps/zlib/BUILD.gn b/deps/zlib/BUILD.gn new file mode 100644 index 00000000000000..5f8873357d35d1 --- /dev/null +++ b/deps/zlib/BUILD.gn @@ -0,0 +1,379 @@ +# Copyright (c) 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/compiler/compiler.gni") + +if (current_cpu == "arm" || current_cpu == "arm64") { + import("//build/config/arm.gni") +} + +config("zlib_config") { + include_dirs = [ "." ] +} + +config("zlib_internal_config") { + defines = [ "ZLIB_IMPLEMENTATION" ] +} + +use_arm_neon_optimizations = false +if (current_cpu == "arm" || current_cpu == "arm64") { + if (arm_use_neon) { + use_arm_neon_optimizations = true + } +} + +use_x86_x64_optimizations = + (current_cpu == "x86" || current_cpu == "x64") && !is_ios + +config("zlib_adler32_simd_config") { + if (use_x86_x64_optimizations) { + defines = [ "ADLER32_SIMD_SSSE3" ] + } + + if (use_arm_neon_optimizations) { + defines = [ "ADLER32_SIMD_NEON" ] + } +} + +source_set("zlib_adler32_simd") { + visibility = [ ":*" ] + + if (use_x86_x64_optimizations) { + sources = [ + "adler32_simd.c", + "adler32_simd.h", + ] + + if (!is_win || is_clang) { + cflags = [ "-mssse3" ] + } + } + + if (use_arm_neon_optimizations) { + sources = [ + "adler32_simd.c", + "adler32_simd.h", + ] + if (!is_debug) { + # Use optimize_speed (-O3) to output the _smallest_ code. + configs -= [ "//build/config/compiler:default_optimization" ] + configs += [ "//build/config/compiler:optimize_speed" ] + } + } + + configs += [ ":zlib_internal_config" ] + + public_configs = [ ":zlib_adler32_simd_config" ] +} + +if (use_arm_neon_optimizations) { + config("zlib_arm_crc32_config") { + # Disabled for iPhone, as described in DDI0487C_a_armv8_arm: + # "All implementations of the ARMv8.1 architecture are required to + # implement the CRC32* instructions. These are optional in ARMv8.0." + if (!is_ios) { + defines = [ "CRC32_ARMV8_CRC32" ] + if (is_android) { + defines += [ "ARMV8_OS_ANDROID" ] + } else if (is_linux || is_chromeos) { + defines += [ "ARMV8_OS_LINUX" ] + } else if (is_fuchsia) { + defines += [ "ARMV8_OS_FUCHSIA" ] + } else if (is_win) { + defines += [ "ARMV8_OS_WINDOWS" ] + } else { + assert(false, "Unsupported ARM OS") + } + } + } + + source_set("zlib_arm_crc32") { + visibility = [ ":*" ] + + if (!is_ios) { + include_dirs = [ "." ] + + if (is_android) { + import("//build/config/android/config.gni") + if (defined(android_ndk_root) && android_ndk_root != "") { + deps = [ + "//third_party/android_ndk:cpu_features", + ] + } else { + assert(false, "CPU detection requires the Android NDK") + } + } else if (!is_win && !is_clang) { + assert(!use_thin_lto, + "ThinLTO fails mixing different module-level targets") + cflags_c = [ "-march=armv8-a+crc" ] + } + + sources = [ + "arm_features.c", + "arm_features.h", + "crc32_simd.c", + "crc32_simd.h", + ] + + if (!is_debug) { + configs -= [ "//build/config/compiler:default_optimization" ] + configs += [ "//build/config/compiler:optimize_speed" ] + } + } + + configs += [ ":zlib_internal_config" ] + + public_configs = [ ":zlib_arm_crc32_config" ] + } +} + +config("zlib_inflate_chunk_simd_config") { + if (use_x86_x64_optimizations) { + defines = [ "INFLATE_CHUNK_SIMD_SSE2" ] + + if (current_cpu == "x64") { + defines += [ "INFLATE_CHUNK_READ_64LE" ] + } + } + + if (use_arm_neon_optimizations) { + defines = [ "INFLATE_CHUNK_SIMD_NEON" ] + if (current_cpu == "arm64") { + defines += [ "INFLATE_CHUNK_READ_64LE" ] + } + } +} + +source_set("zlib_inflate_chunk_simd") { + visibility = [ ":*" ] + + if (use_x86_x64_optimizations || use_arm_neon_optimizations) { + include_dirs = [ "." ] + + sources = [ + "contrib/optimizations/chunkcopy.h", + "contrib/optimizations/inffast_chunk.c", + "contrib/optimizations/inffast_chunk.h", + "contrib/optimizations/inflate.c", + ] + + if (use_arm_neon_optimizations && !is_debug) { + # Here we trade better performance on newer/bigger ARMv8 cores + # for less perf on ARMv7, per crbug.com/772870#c40 + configs -= [ "//build/config/compiler:default_optimization" ] + configs += [ "//build/config/compiler:optimize_speed" ] + } + } + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":zlib_internal_config", + "//build/config/compiler:no_chromium_code", + ] + + public_configs = [ ":zlib_inflate_chunk_simd_config" ] +} + +config("zlib_crc32_simd_config") { + if (use_x86_x64_optimizations) { + defines = [ "CRC32_SIMD_SSE42_PCLMUL" ] + } +} + +source_set("zlib_crc32_simd") { + visibility = [ ":*" ] + + if (use_x86_x64_optimizations) { + sources = [ + "crc32_simd.c", + "crc32_simd.h", + ] + + if (!is_win || is_clang) { + cflags = [ + "-msse4.2", + "-mpclmul", + ] + } + } + + configs += [ ":zlib_internal_config" ] + + public_configs = [ ":zlib_crc32_simd_config" ] +} + +source_set("zlib_x86_simd") { + visibility = [ ":*" ] + + if (use_x86_x64_optimizations) { + sources = [ + "crc_folding.c", + "fill_window_sse.c", + ] + + if (!is_win || is_clang) { + cflags = [ + "-msse4.2", + "-mpclmul", + ] + } + } else { + sources = [ + "simd_stub.c", + ] + } + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":zlib_internal_config", + "//build/config/compiler:no_chromium_code", + ] +} + +config("zlib_warnings") { + if (is_clang && use_x86_x64_optimizations) { + cflags = [ "-Wno-incompatible-pointer-types" ] + } +} + +component("zlib") { + if (!is_win) { + # Don't stomp on "libzlib" on other platforms. + output_name = "chrome_zlib" + } + + sources = [ + "adler32.c", + "chromeconf.h", + "compress.c", + "contrib/optimizations/insert_string.h", + "crc32.c", + "crc32.h", + "deflate.c", + "deflate.h", + "gzclose.c", + "gzguts.h", + "gzlib.c", + "gzread.c", + "gzwrite.c", + "infback.c", + "inffast.c", + "inffast.h", + "inffixed.h", + "inflate.h", + "inftrees.c", + "inftrees.h", + "trees.c", + "trees.h", + "uncompr.c", + "x86.h", + "zconf.h", + "zlib.h", + "zutil.c", + "zutil.h", + ] + + defines = [] + deps = [] + + if (use_x86_x64_optimizations || use_arm_neon_optimizations) { + deps += [ + ":zlib_adler32_simd", + ":zlib_inflate_chunk_simd", + ] + + if (use_x86_x64_optimizations) { + sources += [ "x86.c" ] + deps += [ ":zlib_crc32_simd" ] + } else if (use_arm_neon_optimizations) { + sources += [ "contrib/optimizations/slide_hash_neon.h" ] + deps += [ ":zlib_arm_crc32" ] + } + } else { + sources += [ "inflate.c" ] + } + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":zlib_internal_config", + "//build/config/compiler:no_chromium_code", + + # Must be after no_chromium_code for warning flags to be ordered correctly. + ":zlib_warnings", + ] + + public_configs = [ ":zlib_config" ] + + deps += [ ":zlib_x86_simd" ] + allow_circular_includes_from = deps +} + +config("minizip_warnings") { + visibility = [ ":*" ] + + if (is_clang) { + # zlib uses `if ((a == b))` for some reason. + cflags = [ "-Wno-parentheses-equality" ] + } +} + +static_library("minizip") { + sources = [ + "contrib/minizip/ioapi.c", + "contrib/minizip/ioapi.h", + "contrib/minizip/iowin32.c", + "contrib/minizip/iowin32.h", + "contrib/minizip/unzip.c", + "contrib/minizip/unzip.h", + "contrib/minizip/zip.c", + "contrib/minizip/zip.h", + ] + + if (!is_win) { + sources -= [ + "contrib/minizip/iowin32.c", + "contrib/minizip/iowin32.h", + ] + } + + if (is_mac || is_ios || is_android || is_nacl) { + # Mac, Android and the BSDs don't have fopen64, ftello64, or fseeko64. We + # use fopen, ftell, and fseek instead on these systems. + defines = [ "USE_FILE32API" ] + } + + deps = [ + ":zlib", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + "//build/config/compiler:no_chromium_code", + + # Must be after no_chromium_code for warning flags to be ordered correctly. + ":minizip_warnings", + ] + + public_configs = [ ":zlib_config" ] +} + +executable("zlib_bench") { + include_dirs = [ "." ] + + sources = [ + "contrib/bench/zlib_bench.cc", + ] + + if (!is_debug) { + configs -= [ "//build/config/compiler:default_optimization" ] + configs += [ "//build/config/compiler:optimize_speed" ] + } + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + + deps = [ + ":zlib", + ] +} diff --git a/deps/zlib/CMakeLists.txt b/deps/zlib/CMakeLists.txt deleted file mode 100644 index 0fe939df689306..00000000000000 --- a/deps/zlib/CMakeLists.txt +++ /dev/null @@ -1,249 +0,0 @@ -cmake_minimum_required(VERSION 2.4.4) -set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) - -project(zlib C) - -set(VERSION "1.2.11") - -option(ASM686 "Enable building i686 assembly implementation") -option(AMD64 "Enable building amd64 assembly implementation") - -set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") -set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") -set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") -set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages") -set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") - -include(CheckTypeSize) -include(CheckFunctionExists) -include(CheckIncludeFile) -include(CheckCSourceCompiles) -enable_testing() - -check_include_file(sys/types.h HAVE_SYS_TYPES_H) -check_include_file(stdint.h HAVE_STDINT_H) -check_include_file(stddef.h HAVE_STDDEF_H) - -# -# Check to see if we have large file support -# -set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1) -# We add these other definitions here because CheckTypeSize.cmake -# in CMake 2.4.x does not automatically do so and we want -# compatibility with CMake 2.4.x. -if(HAVE_SYS_TYPES_H) - list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H) -endif() -if(HAVE_STDINT_H) - list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H) -endif() -if(HAVE_STDDEF_H) - list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H) -endif() -check_type_size(off64_t OFF64_T) -if(HAVE_OFF64_T) - add_definitions(-D_LARGEFILE64_SOURCE=1) -endif() -set(CMAKE_REQUIRED_DEFINITIONS) # clear variable - -# -# Check for fseeko -# -check_function_exists(fseeko HAVE_FSEEKO) -if(NOT HAVE_FSEEKO) - add_definitions(-DNO_FSEEKO) -endif() - -# -# Check for unistd.h -# -check_include_file(unistd.h Z_HAVE_UNISTD_H) - -if(MSVC) - set(CMAKE_DEBUG_POSTFIX "d") - add_definitions(-D_CRT_SECURE_NO_DEPRECATE) - add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -endif() - -if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) - # If we're doing an out of source build and the user has a zconf.h - # in their source tree... - if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h) - message(STATUS "Renaming") - message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h") - message(STATUS "to 'zconf.h.included' because this file is included with zlib") - message(STATUS "but CMake generates it automatically in the build directory.") - file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included) - endif() -endif() - -set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc) -configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein - ${ZLIB_PC} @ONLY) -configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein - ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) -include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) - - -#============================================================================ -# zlib -#============================================================================ - -set(ZLIB_PUBLIC_HDRS - ${CMAKE_CURRENT_BINARY_DIR}/zconf.h - zlib.h -) -set(ZLIB_PRIVATE_HDRS - crc32.h - deflate.h - gzguts.h - inffast.h - inffixed.h - inflate.h - inftrees.h - trees.h - zutil.h -) -set(ZLIB_SRCS - adler32.c - compress.c - crc32.c - deflate.c - gzclose.c - gzlib.c - gzread.c - gzwrite.c - inflate.c - infback.c - inftrees.c - inffast.c - trees.c - uncompr.c - zutil.c -) - -if(NOT MINGW) - set(ZLIB_DLL_SRCS - win32/zlib1.rc # If present will override custom build rule below. - ) -endif() - -if(CMAKE_COMPILER_IS_GNUCC) - if(ASM686) - set(ZLIB_ASMS contrib/asm686/match.S) - elseif (AMD64) - set(ZLIB_ASMS contrib/amd64/amd64-match.S) - endif () - - if(ZLIB_ASMS) - add_definitions(-DASMV) - set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE) - endif() -endif() - -if(MSVC) - if(ASM686) - ENABLE_LANGUAGE(ASM_MASM) - set(ZLIB_ASMS - contrib/masmx86/inffas32.asm - contrib/masmx86/match686.asm - ) - elseif (AMD64) - ENABLE_LANGUAGE(ASM_MASM) - set(ZLIB_ASMS - contrib/masmx64/gvmat64.asm - contrib/masmx64/inffasx64.asm - ) - endif() - - if(ZLIB_ASMS) - add_definitions(-DASMV -DASMINF) - endif() -endif() - -# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION -file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) -string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" - "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) - -if(MINGW) - # This gets us DLL resource information when compiling on MinGW. - if(NOT CMAKE_RC_COMPILER) - set(CMAKE_RC_COMPILER windres.exe) - endif() - - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - COMMAND ${CMAKE_RC_COMPILER} - -D GCC_WINDRES - -I ${CMAKE_CURRENT_SOURCE_DIR} - -I ${CMAKE_CURRENT_BINARY_DIR} - -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) - set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) -endif(MINGW) - -add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) -add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) -set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) -set_target_properties(zlib PROPERTIES SOVERSION 1) - -if(NOT CYGWIN) - # This property causes shared libraries on Linux to have the full version - # encoded into their final filename. We disable this on Cygwin because - # it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll - # seems to be the default. - # - # This has no effect with MSVC, on that platform the version info for - # the DLL comes from the resource file win32/zlib1.rc - set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION}) -endif() - -if(UNIX) - # On unix-like platforms the library is almost always called libz - set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z) - if(NOT APPLE) - set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") - endif() -elseif(BUILD_SHARED_LIBS AND WIN32) - # Creates zlib1.dll when building shared library version - set_target_properties(zlib PROPERTIES SUFFIX "1.dll") -endif() - -if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL ) - install(TARGETS zlib zlibstatic - RUNTIME DESTINATION "${INSTALL_BIN_DIR}" - ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" - LIBRARY DESTINATION "${INSTALL_LIB_DIR}" ) -endif() -if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL ) - install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION "${INSTALL_INC_DIR}") -endif() -if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) - install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3") -endif() -if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) - install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}") -endif() - -#============================================================================ -# Example binaries -#============================================================================ - -add_executable(example test/example.c) -target_link_libraries(example zlib) -add_test(example example) - -add_executable(minigzip test/minigzip.c) -target_link_libraries(minigzip zlib) - -if(HAVE_OFF64_T) - add_executable(example64 test/example.c) - target_link_libraries(example64 zlib) - set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") - add_test(example64 example64) - - add_executable(minigzip64 test/minigzip.c) - target_link_libraries(minigzip64 zlib) - set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") -endif() diff --git a/deps/zlib/ChangeLog b/deps/zlib/ChangeLog deleted file mode 100644 index 30199a65a03daa..00000000000000 --- a/deps/zlib/ChangeLog +++ /dev/null @@ -1,1515 +0,0 @@ - - ChangeLog file for zlib - -Changes in 1.2.11 (15 Jan 2017) -- Fix deflate stored bug when pulling last block from window -- Permit immediate deflateParams changes before any deflate input - -Changes in 1.2.10 (2 Jan 2017) -- Avoid warnings on snprintf() return value -- Fix bug in deflate_stored() for zero-length input -- Fix bug in gzwrite.c that produced corrupt gzip files -- Remove files to be installed before copying them in Makefile.in -- Add warnings when compiling with assembler code - -Changes in 1.2.9 (31 Dec 2016) -- Fix contrib/minizip to permit unzipping with desktop API [Zouzou] -- Improve contrib/blast to return unused bytes -- Assure that gzoffset() is correct when appending -- Improve compress() and uncompress() to support large lengths -- Fix bug in test/example.c where error code not saved -- Remedy Coverity warning [Randers-Pehrson] -- Improve speed of gzprintf() in transparent mode -- Fix inflateInit2() bug when windowBits is 16 or 32 -- Change DEBUG macro to ZLIB_DEBUG -- Avoid uninitialized access by gzclose_w() -- Allow building zlib outside of the source directory -- Fix bug that accepted invalid zlib header when windowBits is zero -- Fix gzseek() problem on MinGW due to buggy _lseeki64 there -- Loop on write() calls in gzwrite.c in case of non-blocking I/O -- Add --warn (-w) option to ./configure for more compiler warnings -- Reject a window size of 256 bytes if not using the zlib wrapper -- Fix bug when level 0 used with Z_HUFFMAN or Z_RLE -- Add --debug (-d) option to ./configure to define ZLIB_DEBUG -- Fix bugs in creating a very large gzip header -- Add uncompress2() function, which returns the input size used -- Assure that deflateParams() will not switch functions mid-block -- Dramatically speed up deflation for level 0 (storing) -- Add gzfread(), duplicating the interface of fread() -- Add gzfwrite(), duplicating the interface of fwrite() -- Add deflateGetDictionary() function -- Use snprintf() for later versions of Microsoft C -- Fix *Init macros to use z_ prefix when requested -- Replace as400 with os400 for OS/400 support [Monnerat] -- Add crc32_z() and adler32_z() functions with size_t lengths -- Update Visual Studio project files [AraHaan] - -Changes in 1.2.8 (28 Apr 2013) -- Update contrib/minizip/iowin32.c for Windows RT [Vollant] -- Do not force Z_CONST for C++ -- Clean up contrib/vstudio [Roß] -- Correct spelling error in zlib.h -- Fix mixed line endings in contrib/vstudio - -Changes in 1.2.7.3 (13 Apr 2013) -- Fix version numbers and DLL names in contrib/vstudio/*/zlib.rc - -Changes in 1.2.7.2 (13 Apr 2013) -- Change check for a four-byte type back to hexadecimal -- Fix typo in win32/Makefile.msc -- Add casts in gzwrite.c for pointer differences - -Changes in 1.2.7.1 (24 Mar 2013) -- Replace use of unsafe string functions with snprintf if available -- Avoid including stddef.h on Windows for Z_SOLO compile [Niessink] -- Fix gzgetc undefine when Z_PREFIX set [Turk] -- Eliminate use of mktemp in Makefile (not always available) -- Fix bug in 'F' mode for gzopen() -- Add inflateGetDictionary() function -- Correct comment in deflate.h -- Use _snprintf for snprintf in Microsoft C -- On Darwin, only use /usr/bin/libtool if libtool is not Apple -- Delete "--version" file if created by "ar --version" [Richard G.] -- Fix configure check for veracity of compiler error return codes -- Fix CMake compilation of static lib for MSVC2010 x64 -- Remove unused variable in infback9.c -- Fix argument checks in gzlog_compress() and gzlog_write() -- Clean up the usage of z_const and respect const usage within zlib -- Clean up examples/gzlog.[ch] comparisons of different types -- Avoid shift equal to bits in type (caused endless loop) -- Fix uninitialized value bug in gzputc() introduced by const patches -- Fix memory allocation error in examples/zran.c [Nor] -- Fix bug where gzopen(), gzclose() would write an empty file -- Fix bug in gzclose() when gzwrite() runs out of memory -- Check for input buffer malloc failure in examples/gzappend.c -- Add note to contrib/blast to use binary mode in stdio -- Fix comparisons of differently signed integers in contrib/blast -- Check for invalid code length codes in contrib/puff -- Fix serious but very rare decompression bug in inftrees.c -- Update inflateBack() comments, since inflate() can be faster -- Use underscored I/O function names for WINAPI_FAMILY -- Add _tr_flush_bits to the external symbols prefixed by --zprefix -- Add contrib/vstudio/vc10 pre-build step for static only -- Quote --version-script argument in CMakeLists.txt -- Don't specify --version-script on Apple platforms in CMakeLists.txt -- Fix casting error in contrib/testzlib/testzlib.c -- Fix types in contrib/minizip to match result of get_crc_table() -- Simplify contrib/vstudio/vc10 with 'd' suffix -- Add TOP support to win32/Makefile.msc -- Suport i686 and amd64 assembler builds in CMakeLists.txt -- Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h -- Add vc11 and vc12 build files to contrib/vstudio -- Add gzvprintf() as an undocumented function in zlib -- Fix configure for Sun shell -- Remove runtime check in configure for four-byte integer type -- Add casts and consts to ease user conversion to C++ -- Add man pages for minizip and miniunzip -- In Makefile uninstall, don't rm if preceding cd fails -- Do not return Z_BUF_ERROR if deflateParam() has nothing to write - -Changes in 1.2.7 (2 May 2012) -- Replace use of memmove() with a simple copy for portability -- Test for existence of strerror -- Restore gzgetc_ for backward compatibility with 1.2.6 -- Fix build with non-GNU make on Solaris -- Require gcc 4.0 or later on Mac OS X to use the hidden attribute -- Include unistd.h for Watcom C -- Use __WATCOMC__ instead of __WATCOM__ -- Do not use the visibility attribute if NO_VIZ defined -- Improve the detection of no hidden visibility attribute -- Avoid using __int64 for gcc or solo compilation -- Cast to char * in gzprintf to avoid warnings [Zinser] -- Fix make_vms.com for VAX [Zinser] -- Don't use library or built-in byte swaps -- Simplify test and use of gcc hidden attribute -- Fix bug in gzclose_w() when gzwrite() fails to allocate memory -- Add "x" (O_EXCL) and "e" (O_CLOEXEC) modes support to gzopen() -- Fix bug in test/minigzip.c for configure --solo -- Fix contrib/vstudio project link errors [Mohanathas] -- Add ability to choose the builder in make_vms.com [Schweda] -- Add DESTDIR support to mingw32 win32/Makefile.gcc -- Fix comments in win32/Makefile.gcc for proper usage -- Allow overriding the default install locations for cmake -- Generate and install the pkg-config file with cmake -- Build both a static and a shared version of zlib with cmake -- Include version symbols for cmake builds -- If using cmake with MSVC, add the source directory to the includes -- Remove unneeded EXTRA_CFLAGS from win32/Makefile.gcc [Truta] -- Move obsolete emx makefile to old [Truta] -- Allow the use of -Wundef when compiling or using zlib -- Avoid the use of the -u option with mktemp -- Improve inflate() documentation on the use of Z_FINISH -- Recognize clang as gcc -- Add gzopen_w() in Windows for wide character path names -- Rename zconf.h in CMakeLists.txt to move it out of the way -- Add source directory in CMakeLists.txt for building examples -- Look in build directory for zlib.pc in CMakeLists.txt -- Remove gzflags from zlibvc.def in vc9 and vc10 -- Fix contrib/minizip compilation in the MinGW environment -- Update ./configure for Solaris, support --64 [Mooney] -- Remove -R. from Solaris shared build (possible security issue) -- Avoid race condition for parallel make (-j) running example -- Fix type mismatch between get_crc_table() and crc_table -- Fix parsing of version with "-" in CMakeLists.txt [Snider, Ziegler] -- Fix the path to zlib.map in CMakeLists.txt -- Force the native libtool in Mac OS X to avoid GNU libtool [Beebe] -- Add instructions to win32/Makefile.gcc for shared install [Torri] - -Changes in 1.2.6.1 (12 Feb 2012) -- Avoid the use of the Objective-C reserved name "id" -- Include io.h in gzguts.h for Microsoft compilers -- Fix problem with ./configure --prefix and gzgetc macro -- Include gz_header definition when compiling zlib solo -- Put gzflags() functionality back in zutil.c -- Avoid library header include in crc32.c for Z_SOLO -- Use name in GCC_CLASSIC as C compiler for coverage testing, if set -- Minor cleanup in contrib/minizip/zip.c [Vollant] -- Update make_vms.com [Zinser] -- Remove unnecessary gzgetc_ function -- Use optimized byte swap operations for Microsoft and GNU [Snyder] -- Fix minor typo in zlib.h comments [Rzesniowiecki] - -Changes in 1.2.6 (29 Jan 2012) -- Update the Pascal interface in contrib/pascal -- Fix function numbers for gzgetc_ in zlibvc.def files -- Fix configure.ac for contrib/minizip [Schiffer] -- Fix large-entry detection in minizip on 64-bit systems [Schiffer] -- Have ./configure use the compiler return code for error indication -- Fix CMakeLists.txt for cross compilation [McClure] -- Fix contrib/minizip/zip.c for 64-bit architectures [Dalsnes] -- Fix compilation of contrib/minizip on FreeBSD [Marquez] -- Correct suggested usages in win32/Makefile.msc [Shachar, Horvath] -- Include io.h for Turbo C / Borland C on all platforms [Truta] -- Make version explicit in contrib/minizip/configure.ac [Bosmans] -- Avoid warning for no encryption in contrib/minizip/zip.c [Vollant] -- Minor cleanup up contrib/minizip/unzip.c [Vollant] -- Fix bug when compiling minizip with C++ [Vollant] -- Protect for long name and extra fields in contrib/minizip [Vollant] -- Avoid some warnings in contrib/minizip [Vollant] -- Add -I../.. -L../.. to CFLAGS for minizip and miniunzip -- Add missing libs to minizip linker command -- Add support for VPATH builds in contrib/minizip -- Add an --enable-demos option to contrib/minizip/configure -- Add the generation of configure.log by ./configure -- Exit when required parameters not provided to win32/Makefile.gcc -- Have gzputc return the character written instead of the argument -- Use the -m option on ldconfig for BSD systems [Tobias] -- Correct in zlib.map when deflateResetKeep was added - -Changes in 1.2.5.3 (15 Jan 2012) -- Restore gzgetc function for binary compatibility -- Do not use _lseeki64 under Borland C++ [Truta] -- Update win32/Makefile.msc to build test/*.c [Truta] -- Remove old/visualc6 given CMakefile and other alternatives -- Update AS400 build files and documentation [Monnerat] -- Update win32/Makefile.gcc to build test/*.c [Truta] -- Permit stronger flushes after Z_BLOCK flushes -- Avoid extraneous empty blocks when doing empty flushes -- Permit Z_NULL arguments to deflatePending -- Allow deflatePrime() to insert bits in the middle of a stream -- Remove second empty static block for Z_PARTIAL_FLUSH -- Write out all of the available bits when using Z_BLOCK -- Insert the first two strings in the hash table after a flush - -Changes in 1.2.5.2 (17 Dec 2011) -- fix ld error: unable to find version dependency 'ZLIB_1.2.5' -- use relative symlinks for shared libs -- Avoid searching past window for Z_RLE strategy -- Assure that high-water mark initialization is always applied in deflate -- Add assertions to fill_window() in deflate.c to match comments -- Update python link in README -- Correct spelling error in gzread.c -- Fix bug in gzgets() for a concatenated empty gzip stream -- Correct error in comment for gz_make() -- Change gzread() and related to ignore junk after gzip streams -- Allow gzread() and related to continue after gzclearerr() -- Allow gzrewind() and gzseek() after a premature end-of-file -- Simplify gzseek() now that raw after gzip is ignored -- Change gzgetc() to a macro for speed (~40% speedup in testing) -- Fix gzclose() to return the actual error last encountered -- Always add large file support for windows -- Include zconf.h for windows large file support -- Include zconf.h.cmakein for windows large file support -- Update zconf.h.cmakein on make distclean -- Merge vestigial vsnprintf determination from zutil.h to gzguts.h -- Clarify how gzopen() appends in zlib.h comments -- Correct documentation of gzdirect() since junk at end now ignored -- Add a transparent write mode to gzopen() when 'T' is in the mode -- Update python link in zlib man page -- Get inffixed.h and MAKEFIXED result to match -- Add a ./config --solo option to make zlib subset with no library use -- Add undocumented inflateResetKeep() function for CAB file decoding -- Add --cover option to ./configure for gcc coverage testing -- Add #define ZLIB_CONST option to use const in the z_stream interface -- Add comment to gzdopen() in zlib.h to use dup() when using fileno() -- Note behavior of uncompress() to provide as much data as it can -- Add files in contrib/minizip to aid in building libminizip -- Split off AR options in Makefile.in and configure -- Change ON macro to Z_ARG to avoid application conflicts -- Facilitate compilation with Borland C++ for pragmas and vsnprintf -- Include io.h for Turbo C / Borland C++ -- Move example.c and minigzip.c to test/ -- Simplify incomplete code table filling in inflate_table() -- Remove code from inflate.c and infback.c that is impossible to execute -- Test the inflate code with full coverage -- Allow deflateSetDictionary, inflateSetDictionary at any time (in raw) -- Add deflateResetKeep and fix inflateResetKeep to retain dictionary -- Fix gzwrite.c to accommodate reduced memory zlib compilation -- Have inflate() with Z_FINISH avoid the allocation of a window -- Do not set strm->adler when doing raw inflate -- Fix gzeof() to behave just like feof() when read is not past end of file -- Fix bug in gzread.c when end-of-file is reached -- Avoid use of Z_BUF_ERROR in gz* functions except for premature EOF -- Document gzread() capability to read concurrently written files -- Remove hard-coding of resource compiler in CMakeLists.txt [Blammo] - -Changes in 1.2.5.1 (10 Sep 2011) -- Update FAQ entry on shared builds (#13) -- Avoid symbolic argument to chmod in Makefile.in -- Fix bug and add consts in contrib/puff [Oberhumer] -- Update contrib/puff/zeros.raw test file to have all block types -- Add full coverage test for puff in contrib/puff/Makefile -- Fix static-only-build install in Makefile.in -- Fix bug in unzGetCurrentFileInfo() in contrib/minizip [Kuno] -- Add libz.a dependency to shared in Makefile.in for parallel builds -- Spell out "number" (instead of "nb") in zlib.h for total_in, total_out -- Replace $(...) with `...` in configure for non-bash sh [Bowler] -- Add darwin* to Darwin* and solaris* to SunOS\ 5* in configure [Groffen] -- Add solaris* to Linux* in configure to allow gcc use [Groffen] -- Add *bsd* to Linux* case in configure [Bar-Lev] -- Add inffast.obj to dependencies in win32/Makefile.msc -- Correct spelling error in deflate.h [Kohler] -- Change libzdll.a again to libz.dll.a (!) in win32/Makefile.gcc -- Add test to configure for GNU C looking for gcc in output of $cc -v -- Add zlib.pc generation to win32/Makefile.gcc [Weigelt] -- Fix bug in zlib.h for _FILE_OFFSET_BITS set and _LARGEFILE64_SOURCE not -- Add comment in zlib.h that adler32_combine with len2 < 0 makes no sense -- Make NO_DIVIDE option in adler32.c much faster (thanks to John Reiser) -- Make stronger test in zconf.h to include unistd.h for LFS -- Apply Darwin patches for 64-bit file offsets to contrib/minizip [Slack] -- Fix zlib.h LFS support when Z_PREFIX used -- Add updated as400 support (removed from old) [Monnerat] -- Avoid deflate sensitivity to volatile input data -- Avoid division in adler32_combine for NO_DIVIDE -- Clarify the use of Z_FINISH with deflateBound() amount of space -- Set binary for output file in puff.c -- Use u4 type for crc_table to avoid conversion warnings -- Apply casts in zlib.h to avoid conversion warnings -- Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller] -- Improve inflateSync() documentation to note indeterminancy -- Add deflatePending() function to return the amount of pending output -- Correct the spelling of "specification" in FAQ [Randers-Pehrson] -- Add a check in configure for stdarg.h, use for gzprintf() -- Check that pointers fit in ints when gzprint() compiled old style -- Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler] -- Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt] -- Add debug records in assmebler code [Londer] -- Update RFC references to use http://tools.ietf.org/html/... [Li] -- Add --archs option, use of libtool to configure for Mac OS X [Borstel] - -Changes in 1.2.5 (19 Apr 2010) -- Disable visibility attribute in win32/Makefile.gcc [Bar-Lev] -- Default to libdir as sharedlibdir in configure [Nieder] -- Update copyright dates on modified source files -- Update trees.c to be able to generate modified trees.h -- Exit configure for MinGW, suggesting win32/Makefile.gcc -- Check for NULL path in gz_open [Homurlu] - -Changes in 1.2.4.5 (18 Apr 2010) -- Set sharedlibdir in configure [Torok] -- Set LDFLAGS in Makefile.in [Bar-Lev] -- Avoid mkdir objs race condition in Makefile.in [Bowler] -- Add ZLIB_INTERNAL in front of internal inter-module functions and arrays -- Define ZLIB_INTERNAL to hide internal functions and arrays for GNU C -- Don't use hidden attribute when it is a warning generator (e.g. Solaris) - -Changes in 1.2.4.4 (18 Apr 2010) -- Fix CROSS_PREFIX executable testing, CHOST extract, mingw* [Torok] -- Undefine _LARGEFILE64_SOURCE in zconf.h if it is zero, but not if empty -- Try to use bash or ksh regardless of functionality of /bin/sh -- Fix configure incompatibility with NetBSD sh -- Remove attempt to run under bash or ksh since have better NetBSD fix -- Fix win32/Makefile.gcc for MinGW [Bar-Lev] -- Add diagnostic messages when using CROSS_PREFIX in configure -- Added --sharedlibdir option to configure [Weigelt] -- Use hidden visibility attribute when available [Frysinger] - -Changes in 1.2.4.3 (10 Apr 2010) -- Only use CROSS_PREFIX in configure for ar and ranlib if they exist -- Use CROSS_PREFIX for nm [Bar-Lev] -- Assume _LARGEFILE64_SOURCE defined is equivalent to true -- Avoid use of undefined symbols in #if with && and || -- Make *64 prototypes in gzguts.h consistent with functions -- Add -shared load option for MinGW in configure [Bowler] -- Move z_off64_t to public interface, use instead of off64_t -- Remove ! from shell test in configure (not portable to Solaris) -- Change +0 macro tests to -0 for possibly increased portability - -Changes in 1.2.4.2 (9 Apr 2010) -- Add consistent carriage returns to readme.txt's in masmx86 and masmx64 -- Really provide prototypes for *64 functions when building without LFS -- Only define unlink() in minigzip.c if unistd.h not included -- Update README to point to contrib/vstudio project files -- Move projects/vc6 to old/ and remove projects/ -- Include stdlib.h in minigzip.c for setmode() definition under WinCE -- Clean up assembler builds in win32/Makefile.msc [Rowe] -- Include sys/types.h for Microsoft for off_t definition -- Fix memory leak on error in gz_open() -- Symbolize nm as $NM in configure [Weigelt] -- Use TEST_LDSHARED instead of LDSHARED to link test programs [Weigelt] -- Add +0 to _FILE_OFFSET_BITS and _LFS64_LARGEFILE in case not defined -- Fix bug in gzeof() to take into account unused input data -- Avoid initialization of structures with variables in puff.c -- Updated win32/README-WIN32.txt [Rowe] - -Changes in 1.2.4.1 (28 Mar 2010) -- Remove the use of [a-z] constructs for sed in configure [gentoo 310225] -- Remove $(SHAREDLIB) from LIBS in Makefile.in [Creech] -- Restore "for debugging" comment on sprintf() in gzlib.c -- Remove fdopen for MVS from gzguts.h -- Put new README-WIN32.txt in win32 [Rowe] -- Add check for shell to configure and invoke another shell if needed -- Fix big fat stinking bug in gzseek() on uncompressed files -- Remove vestigial F_OPEN64 define in zutil.h -- Set and check the value of _LARGEFILE_SOURCE and _LARGEFILE64_SOURCE -- Avoid errors on non-LFS systems when applications define LFS macros -- Set EXE to ".exe" in configure for MINGW [Kahle] -- Match crc32() in crc32.c exactly to the prototype in zlib.h [Sherrill] -- Add prefix for cross-compilation in win32/makefile.gcc [Bar-Lev] -- Add DLL install in win32/makefile.gcc [Bar-Lev] -- Allow Linux* or linux* from uname in configure [Bar-Lev] -- Allow ldconfig to be redefined in configure and Makefile.in [Bar-Lev] -- Add cross-compilation prefixes to configure [Bar-Lev] -- Match type exactly in gz_load() invocation in gzread.c -- Match type exactly of zcalloc() in zutil.c to zlib.h alloc_func -- Provide prototypes for *64 functions when building zlib without LFS -- Don't use -lc when linking shared library on MinGW -- Remove errno.h check in configure and vestigial errno code in zutil.h - -Changes in 1.2.4 (14 Mar 2010) -- Fix VER3 extraction in configure for no fourth subversion -- Update zlib.3, add docs to Makefile.in to make .pdf out of it -- Add zlib.3.pdf to distribution -- Don't set error code in gzerror() if passed pointer is NULL -- Apply destination directory fixes to CMakeLists.txt [Lowman] -- Move #cmakedefine's to a new zconf.in.cmakein -- Restore zconf.h for builds that don't use configure or cmake -- Add distclean to dummy Makefile for convenience -- Update and improve INDEX, README, and FAQ -- Update CMakeLists.txt for the return of zconf.h [Lowman] -- Update contrib/vstudio/vc9 and vc10 [Vollant] -- Change libz.dll.a back to libzdll.a in win32/Makefile.gcc -- Apply license and readme changes to contrib/asm686 [Raiter] -- Check file name lengths and add -c option in minigzip.c [Li] -- Update contrib/amd64 and contrib/masmx86/ [Vollant] -- Avoid use of "eof" parameter in trees.c to not shadow library variable -- Update make_vms.com for removal of zlibdefs.h [Zinser] -- Update assembler code and vstudio projects in contrib [Vollant] -- Remove outdated assembler code contrib/masm686 and contrib/asm586 -- Remove old vc7 and vc8 from contrib/vstudio -- Update win32/Makefile.msc, add ZLIB_VER_SUBREVISION [Rowe] -- Fix memory leaks in gzclose_r() and gzclose_w(), file leak in gz_open() -- Add contrib/gcc_gvmat64 for longest_match and inflate_fast [Vollant] -- Remove *64 functions from win32/zlib.def (they're not 64-bit yet) -- Fix bug in void-returning vsprintf() case in gzwrite.c -- Fix name change from inflate.h in contrib/inflate86/inffas86.c -- Check if temporary file exists before removing in make_vms.com [Zinser] -- Fix make install and uninstall for --static option -- Fix usage of _MSC_VER in gzguts.h and zutil.h [Truta] -- Update readme.txt in contrib/masmx64 and masmx86 to assemble - -Changes in 1.2.3.9 (21 Feb 2010) -- Expunge gzio.c -- Move as400 build information to old -- Fix updates in contrib/minizip and contrib/vstudio -- Add const to vsnprintf test in configure to avoid warnings [Weigelt] -- Delete zconf.h (made by configure) [Weigelt] -- Change zconf.in.h to zconf.h.in per convention [Weigelt] -- Check for NULL buf in gzgets() -- Return empty string for gzgets() with len == 1 (like fgets()) -- Fix description of gzgets() in zlib.h for end-of-file, NULL return -- Update minizip to 1.1 [Vollant] -- Avoid MSVC loss of data warnings in gzread.c, gzwrite.c -- Note in zlib.h that gzerror() should be used to distinguish from EOF -- Remove use of snprintf() from gzlib.c -- Fix bug in gzseek() -- Update contrib/vstudio, adding vc9 and vc10 [Kuno, Vollant] -- Fix zconf.h generation in CMakeLists.txt [Lowman] -- Improve comments in zconf.h where modified by configure - -Changes in 1.2.3.8 (13 Feb 2010) -- Clean up text files (tabs, trailing whitespace, etc.) [Oberhumer] -- Use z_off64_t in gz_zero() and gz_skip() to match state->skip -- Avoid comparison problem when sizeof(int) == sizeof(z_off64_t) -- Revert to Makefile.in from 1.2.3.6 (live with the clutter) -- Fix missing error return in gzflush(), add zlib.h note -- Add *64 functions to zlib.map [Levin] -- Fix signed/unsigned comparison in gz_comp() -- Use SFLAGS when testing shared linking in configure -- Add --64 option to ./configure to use -m64 with gcc -- Fix ./configure --help to correctly name options -- Have make fail if a test fails [Levin] -- Avoid buffer overrun in contrib/masmx64/gvmat64.asm [Simpson] -- Remove assembler object files from contrib - -Changes in 1.2.3.7 (24 Jan 2010) -- Always gzopen() with O_LARGEFILE if available -- Fix gzdirect() to work immediately after gzopen() or gzdopen() -- Make gzdirect() more precise when the state changes while reading -- Improve zlib.h documentation in many places -- Catch memory allocation failure in gz_open() -- Complete close operation if seek forward in gzclose_w() fails -- Return Z_ERRNO from gzclose_r() if close() fails -- Return Z_STREAM_ERROR instead of EOF for gzclose() being passed NULL -- Return zero for gzwrite() errors to match zlib.h description -- Return -1 on gzputs() error to match zlib.h description -- Add zconf.in.h to allow recovery from configure modification [Weigelt] -- Fix static library permissions in Makefile.in [Weigelt] -- Avoid warnings in configure tests that hide functionality [Weigelt] -- Add *BSD and DragonFly to Linux case in configure [gentoo 123571] -- Change libzdll.a to libz.dll.a in win32/Makefile.gcc [gentoo 288212] -- Avoid access of uninitialized data for first inflateReset2 call [Gomes] -- Keep object files in subdirectories to reduce the clutter somewhat -- Remove default Makefile and zlibdefs.h, add dummy Makefile -- Add new external functions to Z_PREFIX, remove duplicates, z_z_ -> z_ -- Remove zlibdefs.h completely -- modify zconf.h instead - -Changes in 1.2.3.6 (17 Jan 2010) -- Avoid void * arithmetic in gzread.c and gzwrite.c -- Make compilers happier with const char * for gz_error message -- Avoid unused parameter warning in inflate.c -- Avoid signed-unsigned comparison warning in inflate.c -- Indent #pragma's for traditional C -- Fix usage of strwinerror() in glib.c, change to gz_strwinerror() -- Correct email address in configure for system options -- Update make_vms.com and add make_vms.com to contrib/minizip [Zinser] -- Update zlib.map [Brown] -- Fix Makefile.in for Solaris 10 make of example64 and minizip64 [Torok] -- Apply various fixes to CMakeLists.txt [Lowman] -- Add checks on len in gzread() and gzwrite() -- Add error message for no more room for gzungetc() -- Remove zlib version check in gzwrite() -- Defer compression of gzprintf() result until need to -- Use snprintf() in gzdopen() if available -- Remove USE_MMAP configuration determination (only used by minigzip) -- Remove examples/pigz.c (available separately) -- Update examples/gun.c to 1.6 - -Changes in 1.2.3.5 (8 Jan 2010) -- Add space after #if in zutil.h for some compilers -- Fix relatively harmless bug in deflate_fast() [Exarevsky] -- Fix same problem in deflate_slow() -- Add $(SHAREDLIBV) to LIBS in Makefile.in [Brown] -- Add deflate_rle() for faster Z_RLE strategy run-length encoding -- Add deflate_huff() for faster Z_HUFFMAN_ONLY encoding -- Change name of "write" variable in inffast.c to avoid library collisions -- Fix premature EOF from gzread() in gzio.c [Brown] -- Use zlib header window size if windowBits is 0 in inflateInit2() -- Remove compressBound() call in deflate.c to avoid linking compress.o -- Replace use of errno in gz* with functions, support WinCE [Alves] -- Provide alternative to perror() in minigzip.c for WinCE [Alves] -- Don't use _vsnprintf on later versions of MSVC [Lowman] -- Add CMake build script and input file [Lowman] -- Update contrib/minizip to 1.1 [Svensson, Vollant] -- Moved nintendods directory from contrib to . -- Replace gzio.c with a new set of routines with the same functionality -- Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above -- Update contrib/minizip to 1.1b -- Change gzeof() to return 0 on error instead of -1 to agree with zlib.h - -Changes in 1.2.3.4 (21 Dec 2009) -- Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility -- Update comments in configure and Makefile.in for default --shared -- Fix test -z's in configure [Marquess] -- Build examplesh and minigzipsh when not testing -- Change NULL's to Z_NULL's in deflate.c and in comments in zlib.h -- Import LDFLAGS from the environment in configure -- Fix configure to populate SFLAGS with discovered CFLAGS options -- Adapt make_vms.com to the new Makefile.in [Zinser] -- Add zlib2ansi script for C++ compilation [Marquess] -- Add _FILE_OFFSET_BITS=64 test to make test (when applicable) -- Add AMD64 assembler code for longest match to contrib [Teterin] -- Include options from $SFLAGS when doing $LDSHARED -- Simplify 64-bit file support by introducing z_off64_t type -- Make shared object files in objs directory to work around old Sun cc -- Use only three-part version number for Darwin shared compiles -- Add rc option to ar in Makefile.in for when ./configure not run -- Add -WI,-rpath,. to LDFLAGS for OSF 1 V4* -- Set LD_LIBRARYN32_PATH for SGI IRIX shared compile -- Protect against _FILE_OFFSET_BITS being defined when compiling zlib -- Rename Makefile.in targets allstatic to static and allshared to shared -- Fix static and shared Makefile.in targets to be independent -- Correct error return bug in gz_open() by setting state [Brown] -- Put spaces before ;;'s in configure for better sh compatibility -- Add pigz.c (parallel implementation of gzip) to examples/ -- Correct constant in crc32.c to UL [Leventhal] -- Reject negative lengths in crc32_combine() -- Add inflateReset2() function to work like inflateEnd()/inflateInit2() -- Include sys/types.h for _LARGEFILE64_SOURCE [Brown] -- Correct typo in doc/algorithm.txt [Janik] -- Fix bug in adler32_combine() [Zhu] -- Catch missing-end-of-block-code error in all inflates and in puff - Assures that random input to inflate eventually results in an error -- Added enough.c (calculation of ENOUGH for inftrees.h) to examples/ -- Update ENOUGH and its usage to reflect discovered bounds -- Fix gzerror() error report on empty input file [Brown] -- Add ush casts in trees.c to avoid pedantic runtime errors -- Fix typo in zlib.h uncompress() description [Reiss] -- Correct inflate() comments with regard to automatic header detection -- Remove deprecation comment on Z_PARTIAL_FLUSH (it stays) -- Put new version of gzlog (2.0) in examples with interruption recovery -- Add puff compile option to permit invalid distance-too-far streams -- Add puff TEST command options, ability to read piped input -- Prototype the *64 functions in zlib.h when _FILE_OFFSET_BITS == 64, but - _LARGEFILE64_SOURCE not defined -- Fix Z_FULL_FLUSH to truly erase the past by resetting s->strstart -- Fix deflateSetDictionary() to use all 32K for output consistency -- Remove extraneous #define MIN_LOOKAHEAD in deflate.c (in deflate.h) -- Clear bytes after deflate lookahead to avoid use of uninitialized data -- Change a limit in inftrees.c to be more transparent to Coverity Prevent -- Update win32/zlib.def with exported symbols from zlib.h -- Correct spelling errors in zlib.h [Willem, Sobrado] -- Allow Z_BLOCK for deflate() to force a new block -- Allow negative bits in inflatePrime() to delete existing bit buffer -- Add Z_TREES flush option to inflate() to return at end of trees -- Add inflateMark() to return current state information for random access -- Add Makefile for NintendoDS to contrib [Costa] -- Add -w in configure compile tests to avoid spurious warnings [Beucler] -- Fix typos in zlib.h comments for deflateSetDictionary() -- Fix EOF detection in transparent gzread() [Maier] - -Changes in 1.2.3.3 (2 October 2006) -- Make --shared the default for configure, add a --static option -- Add compile option to permit invalid distance-too-far streams -- Add inflateUndermine() function which is required to enable above -- Remove use of "this" variable name for C++ compatibility [Marquess] -- Add testing of shared library in make test, if shared library built -- Use ftello() and fseeko() if available instead of ftell() and fseek() -- Provide two versions of all functions that use the z_off_t type for - binary compatibility -- a normal version and a 64-bit offset version, - per the Large File Support Extension when _LARGEFILE64_SOURCE is - defined; use the 64-bit versions by default when _FILE_OFFSET_BITS - is defined to be 64 -- Add a --uname= option to configure to perhaps help with cross-compiling - -Changes in 1.2.3.2 (3 September 2006) -- Turn off silly Borland warnings [Hay] -- Use off64_t and define _LARGEFILE64_SOURCE when present -- Fix missing dependency on inffixed.h in Makefile.in -- Rig configure --shared to build both shared and static [Teredesai, Truta] -- Remove zconf.in.h and instead create a new zlibdefs.h file -- Fix contrib/minizip/unzip.c non-encrypted after encrypted [Vollant] -- Add treebuild.xml (see http://treebuild.metux.de/) [Weigelt] - -Changes in 1.2.3.1 (16 August 2006) -- Add watcom directory with OpenWatcom make files [Daniel] -- Remove #undef of FAR in zconf.in.h for MVS [Fedtke] -- Update make_vms.com [Zinser] -- Use -fPIC for shared build in configure [Teredesai, Nicholson] -- Use only major version number for libz.so on IRIX and OSF1 [Reinholdtsen] -- Use fdopen() (not _fdopen()) for Interix in zutil.h [Bäck] -- Add some FAQ entries about the contrib directory -- Update the MVS question in the FAQ -- Avoid extraneous reads after EOF in gzio.c [Brown] -- Correct spelling of "successfully" in gzio.c [Randers-Pehrson] -- Add comments to zlib.h about gzerror() usage [Brown] -- Set extra flags in gzip header in gzopen() like deflate() does -- Make configure options more compatible with double-dash conventions - [Weigelt] -- Clean up compilation under Solaris SunStudio cc [Rowe, Reinholdtsen] -- Fix uninstall target in Makefile.in [Truta] -- Add pkgconfig support [Weigelt] -- Use $(DESTDIR) macro in Makefile.in [Reinholdtsen, Weigelt] -- Replace set_data_type() with a more accurate detect_data_type() in - trees.c, according to the txtvsbin.txt document [Truta] -- Swap the order of #include and #include "zlib.h" in - gzio.c, example.c and minigzip.c [Truta] -- Shut up annoying VS2005 warnings about standard C deprecation [Rowe, - Truta] (where?) -- Fix target "clean" from win32/Makefile.bor [Truta] -- Create .pdb and .manifest files in win32/makefile.msc [Ziegler, Rowe] -- Update zlib www home address in win32/DLL_FAQ.txt [Truta] -- Update contrib/masmx86/inffas32.asm for VS2005 [Vollant, Van Wassenhove] -- Enable browse info in the "Debug" and "ASM Debug" configurations in - the Visual C++ 6 project, and set (non-ASM) "Debug" as default [Truta] -- Add pkgconfig support [Weigelt] -- Add ZLIB_VER_MAJOR, ZLIB_VER_MINOR and ZLIB_VER_REVISION in zlib.h, - for use in win32/zlib1.rc [Polushin, Rowe, Truta] -- Add a document that explains the new text detection scheme to - doc/txtvsbin.txt [Truta] -- Add rfc1950.txt, rfc1951.txt and rfc1952.txt to doc/ [Truta] -- Move algorithm.txt into doc/ [Truta] -- Synchronize FAQ with website -- Fix compressBound(), was low for some pathological cases [Fearnley] -- Take into account wrapper variations in deflateBound() -- Set examples/zpipe.c input and output to binary mode for Windows -- Update examples/zlib_how.html with new zpipe.c (also web site) -- Fix some warnings in examples/gzlog.c and examples/zran.c (it seems - that gcc became pickier in 4.0) -- Add zlib.map for Linux: "All symbols from zlib-1.1.4 remain - un-versioned, the patch adds versioning only for symbols introduced in - zlib-1.2.0 or later. It also declares as local those symbols which are - not designed to be exported." [Levin] -- Update Z_PREFIX list in zconf.in.h, add --zprefix option to configure -- Do not initialize global static by default in trees.c, add a response - NO_INIT_GLOBAL_POINTERS to initialize them if needed [Marquess] -- Don't use strerror() in gzio.c under WinCE [Yakimov] -- Don't use errno.h in zutil.h under WinCE [Yakimov] -- Move arguments for AR to its usage to allow replacing ar [Marot] -- Add HAVE_VISIBILITY_PRAGMA in zconf.in.h for Mozilla [Randers-Pehrson] -- Improve inflateInit() and inflateInit2() documentation -- Fix structure size comment in inflate.h -- Change configure help option from --h* to --help [Santos] - -Changes in 1.2.3 (18 July 2005) -- Apply security vulnerability fixes to contrib/infback9 as well -- Clean up some text files (carriage returns, trailing space) -- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant] - -Changes in 1.2.2.4 (11 July 2005) -- Add inflatePrime() function for starting inflation at bit boundary -- Avoid some Visual C warnings in deflate.c -- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit - compile -- Fix some spelling errors in comments [Betts] -- Correct inflateInit2() error return documentation in zlib.h -- Add zran.c example of compressed data random access to examples - directory, shows use of inflatePrime() -- Fix cast for assignments to strm->state in inflate.c and infback.c -- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer] -- Move declarations of gf2 functions to right place in crc32.c [Oberhumer] -- Add cast in trees.c t avoid a warning [Oberhumer] -- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer] -- Update make_vms.com [Zinser] -- Initialize state->write in inflateReset() since copied in inflate_fast() -- Be more strict on incomplete code sets in inflate_table() and increase - ENOUGH and MAXD -- this repairs a possible security vulnerability for - invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for - discovering the vulnerability and providing test cases. -- Add ia64 support to configure for HP-UX [Smith] -- Add error return to gzread() for format or i/o error [Levin] -- Use malloc.h for OS/2 [Necasek] - -Changes in 1.2.2.3 (27 May 2005) -- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile -- Typecast fread() return values in gzio.c [Vollant] -- Remove trailing space in minigzip.c outmode (VC++ can't deal with it) -- Fix crc check bug in gzread() after gzungetc() [Heiner] -- Add the deflateTune() function to adjust internal compression parameters -- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack) -- Remove an incorrect assertion in examples/zpipe.c -- Add C++ wrapper in infback9.h [Donais] -- Fix bug in inflateCopy() when decoding fixed codes -- Note in zlib.h how much deflateSetDictionary() actually uses -- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used) -- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer] -- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer] -- Add gzdirect() function to indicate transparent reads -- Update contrib/minizip [Vollant] -- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer] -- Add casts in crc32.c to avoid warnings [Oberhumer] -- Add contrib/masmx64 [Vollant] -- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant] - -Changes in 1.2.2.2 (30 December 2004) -- Replace structure assignments in deflate.c and inflate.c with zmemcpy to - avoid implicit memcpy calls (portability for no-library compilation) -- Increase sprintf() buffer size in gzdopen() to allow for large numbers -- Add INFLATE_STRICT to check distances against zlib header -- Improve WinCE errno handling and comments [Chang] -- Remove comment about no gzip header processing in FAQ -- Add Z_FIXED strategy option to deflateInit2() to force fixed trees -- Add updated make_vms.com [Coghlan], update README -- Create a new "examples" directory, move gzappend.c there, add zpipe.c, - fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html. -- Add FAQ entry and comments in deflate.c on uninitialized memory access -- Add Solaris 9 make options in configure [Gilbert] -- Allow strerror() usage in gzio.c for STDC -- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer] -- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant] -- Use z_off_t for adler32_combine() and crc32_combine() lengths -- Make adler32() much faster for small len -- Use OS_CODE in deflate() default gzip header - -Changes in 1.2.2.1 (31 October 2004) -- Allow inflateSetDictionary() call for raw inflate -- Fix inflate header crc check bug for file names and comments -- Add deflateSetHeader() and gz_header structure for custom gzip headers -- Add inflateGetheader() to retrieve gzip headers -- Add crc32_combine() and adler32_combine() functions -- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list -- Use zstreamp consistently in zlib.h (inflate_back functions) -- Remove GUNZIP condition from definition of inflate_mode in inflate.h - and in contrib/inflate86/inffast.S [Truta, Anderson] -- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson] -- Update projects/README.projects and projects/visualc6 [Truta] -- Update win32/DLL_FAQ.txt [Truta] -- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta] -- Deprecate Z_ASCII; use Z_TEXT instead [Truta] -- Use a new algorithm for setting strm->data_type in trees.c [Truta] -- Do not define an exit() prototype in zutil.c unless DEBUG defined -- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta] -- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate() -- Fix Darwin build version identification [Peterson] - -Changes in 1.2.2 (3 October 2004) -- Update zlib.h comments on gzip in-memory processing -- Set adler to 1 in inflateReset() to support Java test suite [Walles] -- Add contrib/dotzlib [Ravn] -- Update win32/DLL_FAQ.txt [Truta] -- Update contrib/minizip [Vollant] -- Move contrib/visual-basic.txt to old/ [Truta] -- Fix assembler builds in projects/visualc6/ [Truta] - -Changes in 1.2.1.2 (9 September 2004) -- Update INDEX file -- Fix trees.c to update strm->data_type (no one ever noticed!) -- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown] -- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE) -- Add limited multitasking protection to DYNAMIC_CRC_TABLE -- Add NO_vsnprintf for VMS in zutil.h [Mozilla] -- Don't declare strerror() under VMS [Mozilla] -- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize -- Update contrib/ada [Anisimkov] -- Update contrib/minizip [Vollant] -- Fix configure to not hardcode directories for Darwin [Peterson] -- Fix gzio.c to not return error on empty files [Brown] -- Fix indentation; update version in contrib/delphi/ZLib.pas and - contrib/pascal/zlibpas.pas [Truta] -- Update mkasm.bat in contrib/masmx86 [Truta] -- Update contrib/untgz [Truta] -- Add projects/README.projects [Truta] -- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta] -- Update win32/DLL_FAQ.txt [Truta] -- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta] -- Remove an unnecessary assignment to curr in inftrees.c [Truta] -- Add OS/2 to exe builds in configure [Poltorak] -- Remove err dummy parameter in zlib.h [Kientzle] - -Changes in 1.2.1.1 (9 January 2004) -- Update email address in README -- Several FAQ updates -- Fix a big fat bug in inftrees.c that prevented decoding valid - dynamic blocks with only literals and no distance codes -- - Thanks to "Hot Emu" for the bug report and sample file -- Add a note to puff.c on no distance codes case. - -Changes in 1.2.1 (17 November 2003) -- Remove a tab in contrib/gzappend/gzappend.c -- Update some interfaces in contrib for new zlib functions -- Update zlib version number in some contrib entries -- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] -- Support shared libraries on Hurd and KFreeBSD [Brown] -- Fix error in NO_DIVIDE option of adler32.c - -Changes in 1.2.0.8 (4 November 2003) -- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas -- Add experimental NO_DIVIDE #define in adler32.c - - Possibly faster on some processors (let me know if it is) -- Correct Z_BLOCK to not return on first inflate call if no wrap -- Fix strm->data_type on inflate() return to correctly indicate EOB -- Add deflatePrime() function for appending in the middle of a byte -- Add contrib/gzappend for an example of appending to a stream -- Update win32/DLL_FAQ.txt [Truta] -- Delete Turbo C comment in README [Truta] -- Improve some indentation in zconf.h [Truta] -- Fix infinite loop on bad input in configure script [Church] -- Fix gzeof() for concatenated gzip files [Johnson] -- Add example to contrib/visual-basic.txt [Michael B.] -- Add -p to mkdir's in Makefile.in [vda] -- Fix configure to properly detect presence or lack of printf functions -- Add AS400 support [Monnerat] -- Add a little Cygwin support [Wilson] - -Changes in 1.2.0.7 (21 September 2003) -- Correct some debug formats in contrib/infback9 -- Cast a type in a debug statement in trees.c -- Change search and replace delimiter in configure from % to # [Beebe] -- Update contrib/untgz to 0.2 with various fixes [Truta] -- Add build support for Amiga [Nikl] -- Remove some directories in old that have been updated to 1.2 -- Add dylib building for Mac OS X in configure and Makefile.in -- Remove old distribution stuff from Makefile -- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X -- Update links in README - -Changes in 1.2.0.6 (13 September 2003) -- Minor FAQ updates -- Update contrib/minizip to 1.00 [Vollant] -- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] -- Update POSTINC comment for 68060 [Nikl] -- Add contrib/infback9 with deflate64 decoding (unsupported) -- For MVS define NO_vsnprintf and undefine FAR [van Burik] -- Add pragma for fdopen on MVS [van Burik] - -Changes in 1.2.0.5 (8 September 2003) -- Add OF to inflateBackEnd() declaration in zlib.h -- Remember start when using gzdopen in the middle of a file -- Use internal off_t counters in gz* functions to properly handle seeks -- Perform more rigorous check for distance-too-far in inffast.c -- Add Z_BLOCK flush option to return from inflate at block boundary -- Set strm->data_type on return from inflate - - Indicate bits unused, if at block boundary, and if in last block -- Replace size_t with ptrdiff_t in crc32.c, and check for correct size -- Add condition so old NO_DEFLATE define still works for compatibility -- FAQ update regarding the Windows DLL [Truta] -- INDEX update: add qnx entry, remove aix entry [Truta] -- Install zlib.3 into mandir [Wilson] -- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] -- Adapt the zlib interface to the new DLL convention guidelines [Truta] -- Introduce ZLIB_WINAPI macro to allow the export of functions using - the WINAPI calling convention, for Visual Basic [Vollant, Truta] -- Update msdos and win32 scripts and makefiles [Truta] -- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] -- Add contrib/ada [Anisimkov] -- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] -- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] -- Add contrib/masm686 [Truta] -- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm - [Truta, Vollant] -- Update contrib/delphi; rename to contrib/pascal; add example [Truta] -- Remove contrib/delphi2; add a new contrib/delphi [Truta] -- Avoid inclusion of the nonstandard in contrib/iostream, - and fix some method prototypes [Truta] -- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip - [Truta] -- Avoid the use of backslash (\) in contrib/minizip [Vollant] -- Fix file time handling in contrib/untgz; update makefiles [Truta] -- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines - [Vollant] -- Remove contrib/vstudio/vc15_16 [Vollant] -- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] -- Update README.contrib [Truta] -- Invert the assignment order of match_head and s->prev[...] in - INSERT_STRING [Truta] -- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings - [Truta] -- Compare function pointers with 0, not with NULL or Z_NULL [Truta] -- Fix prototype of syncsearch in inflate.c [Truta] -- Introduce ASMINF macro to be enabled when using an ASM implementation - of inflate_fast [Truta] -- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] -- Modify test_gzio in example.c to take a single file name as a - parameter [Truta] -- Exit the example.c program if gzopen fails [Truta] -- Add type casts around strlen in example.c [Truta] -- Remove casting to sizeof in minigzip.c; give a proper type - to the variable compared with SUFFIX_LEN [Truta] -- Update definitions of STDC and STDC99 in zconf.h [Truta] -- Synchronize zconf.h with the new Windows DLL interface [Truta] -- Use SYS16BIT instead of __32BIT__ to distinguish between - 16- and 32-bit platforms [Truta] -- Use far memory allocators in small 16-bit memory models for - Turbo C [Truta] -- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in - zlibCompileFlags [Truta] -- Cygwin has vsnprintf [Wilson] -- In Windows16, OS_CODE is 0, as in MSDOS [Truta] -- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] - -Changes in 1.2.0.4 (10 August 2003) -- Minor FAQ updates -- Be more strict when checking inflateInit2's windowBits parameter -- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well -- Add gzip wrapper option to deflateInit2 using windowBits -- Add updated QNX rule in configure and qnx directory [Bonnefoy] -- Make inflate distance-too-far checks more rigorous -- Clean up FAR usage in inflate -- Add casting to sizeof() in gzio.c and minigzip.c - -Changes in 1.2.0.3 (19 July 2003) -- Fix silly error in gzungetc() implementation [Vollant] -- Update contrib/minizip and contrib/vstudio [Vollant] -- Fix printf format in example.c -- Correct cdecl support in zconf.in.h [Anisimkov] -- Minor FAQ updates - -Changes in 1.2.0.2 (13 July 2003) -- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons -- Attempt to avoid warnings in crc32.c for pointer-int conversion -- Add AIX to configure, remove aix directory [Bakker] -- Add some casts to minigzip.c -- Improve checking after insecure sprintf() or vsprintf() calls -- Remove #elif's from crc32.c -- Change leave label to inf_leave in inflate.c and infback.c to avoid - library conflicts -- Remove inflate gzip decoding by default--only enable gzip decoding by - special request for stricter backward compatibility -- Add zlibCompileFlags() function to return compilation information -- More typecasting in deflate.c to avoid warnings -- Remove leading underscore from _Capital #defines [Truta] -- Fix configure to link shared library when testing -- Add some Windows CE target adjustments [Mai] -- Remove #define ZLIB_DLL in zconf.h [Vollant] -- Add zlib.3 [Rodgers] -- Update RFC URL in deflate.c and algorithm.txt [Mai] -- Add zlib_dll_FAQ.txt to contrib [Truta] -- Add UL to some constants [Truta] -- Update minizip and vstudio [Vollant] -- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h -- Expand use of NO_DUMMY_DECL to avoid all dummy structures -- Added iostream3 to contrib [Schwardt] -- Replace rewind() with fseek() for WinCE [Truta] -- Improve setting of zlib format compression level flags - - Report 0 for huffman and rle strategies and for level == 0 or 1 - - Report 2 only for level == 6 -- Only deal with 64K limit when necessary at compile time [Truta] -- Allow TOO_FAR check to be turned off at compile time [Truta] -- Add gzclearerr() function [Souza] -- Add gzungetc() function - -Changes in 1.2.0.1 (17 March 2003) -- Add Z_RLE strategy for run-length encoding [Truta] - - When Z_RLE requested, restrict matches to distance one - - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE -- Correct FASTEST compilation to allow level == 0 -- Clean up what gets compiled for FASTEST -- Incorporate changes to zconf.in.h [Vollant] - - Refine detection of Turbo C need for dummy returns - - Refine ZLIB_DLL compilation - - Include additional header file on VMS for off_t typedef -- Try to use _vsnprintf where it supplants vsprintf [Vollant] -- Add some casts in inffast.c -- Enchance comments in zlib.h on what happens if gzprintf() tries to - write more than 4095 bytes before compression -- Remove unused state from inflateBackEnd() -- Remove exit(0) from minigzip.c, example.c -- Get rid of all those darn tabs -- Add "check" target to Makefile.in that does the same thing as "test" -- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in -- Update contrib/inflate86 [Anderson] -- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] -- Add msdos and win32 directories with makefiles [Truta] -- More additions and improvements to the FAQ - -Changes in 1.2.0 (9 March 2003) -- New and improved inflate code - - About 20% faster - - Does not allocate 32K window unless and until needed - - Automatically detects and decompresses gzip streams - - Raw inflate no longer needs an extra dummy byte at end - - Added inflateBack functions using a callback interface--even faster - than inflate, useful for file utilities (gzip, zip) - - Added inflateCopy() function to record state for random access on - externally generated deflate streams (e.g. in gzip files) - - More readable code (I hope) -- New and improved crc32() - - About 50% faster, thanks to suggestions from Rodney Brown -- Add deflateBound() and compressBound() functions -- Fix memory leak in deflateInit2() -- Permit setting dictionary for raw deflate (for parallel deflate) -- Fix const declaration for gzwrite() -- Check for some malloc() failures in gzio.c -- Fix bug in gzopen() on single-byte file 0x1f -- Fix bug in gzread() on concatenated file with 0x1f at end of buffer - and next buffer doesn't start with 0x8b -- Fix uncompress() to return Z_DATA_ERROR on truncated input -- Free memory at end of example.c -- Remove MAX #define in trees.c (conflicted with some libraries) -- Fix static const's in deflate.c, gzio.c, and zutil.[ch] -- Declare malloc() and free() in gzio.c if STDC not defined -- Use malloc() instead of calloc() in zutil.c if int big enough -- Define STDC for AIX -- Add aix/ with approach for compiling shared library on AIX -- Add HP-UX support for shared libraries in configure -- Add OpenUNIX support for shared libraries in configure -- Use $cc instead of gcc to build shared library -- Make prefix directory if needed when installing -- Correct Macintosh avoidance of typedef Byte in zconf.h -- Correct Turbo C memory allocation when under Linux -- Use libz.a instead of -lz in Makefile (assure use of compiled library) -- Update configure to check for snprintf or vsnprintf functions and their - return value, warn during make if using an insecure function -- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that - is lost when library is used--resolution is to build new zconf.h -- Documentation improvements (in zlib.h): - - Document raw deflate and inflate - - Update RFCs URL - - Point out that zlib and gzip formats are different - - Note that Z_BUF_ERROR is not fatal - - Document string limit for gzprintf() and possible buffer overflow - - Note requirement on avail_out when flushing - - Note permitted values of flush parameter of inflate() -- Add some FAQs (and even answers) to the FAQ -- Add contrib/inflate86/ for x86 faster inflate -- Add contrib/blast/ for PKWare Data Compression Library decompression -- Add contrib/puff/ simple inflate for deflate format description - -Changes in 1.1.4 (11 March 2002) -- ZFREE was repeated on same allocation on some error conditions. - This creates a security problem described in - http://www.zlib.org/advisory-2002-03-11.txt -- Returned incorrect error (Z_MEM_ERROR) on some invalid data -- Avoid accesses before window for invalid distances with inflate window - less than 32K. -- force windowBits > 8 to avoid a bug in the encoder for a window size - of 256 bytes. (A complete fix will be available in 1.1.5). - -Changes in 1.1.3 (9 July 1998) -- fix "an inflate input buffer bug that shows up on rare but persistent - occasions" (Mark) -- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) -- fix gzseek(..., SEEK_SET) in write mode -- fix crc check after a gzeek (Frank Faubert) -- fix miniunzip when the last entry in a zip file is itself a zip file - (J Lillge) -- add contrib/asm586 and contrib/asm686 (Brian Raiter) - See http://www.muppetlabs.com/~breadbox/software/assembly.html -- add support for Delphi 3 in contrib/delphi (Bob Dellaca) -- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) -- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) -- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) -- added a FAQ file - -- Support gzdopen on Mac with Metrowerks (Jason Linhart) -- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) -- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) -- avoid some warnings with Borland C (Tom Tanner) -- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) -- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) -- allow several arguments to configure (Tim Mooney, Frodo Looijaard) -- use libdir and includedir in Makefile.in (Tim Mooney) -- support shared libraries on OSF1 V4 (Tim Mooney) -- remove so_locations in "make clean" (Tim Mooney) -- fix maketree.c compilation error (Glenn, Mark) -- Python interface to zlib now in Python 1.5 (Jeremy Hylton) -- new Makefile.riscos (Rich Walker) -- initialize static descriptors in trees.c for embedded targets (Nick Smith) -- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) -- add the OS/2 files in Makefile.in too (Andrew Zabolotny) -- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) -- fix maketree.c to allow clean compilation of inffixed.h (Mark) -- fix parameter check in deflateCopy (Gunther Nikl) -- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) -- Many portability patches by Christian Spieler: - . zutil.c, zutil.h: added "const" for zmem* - . Make_vms.com: fixed some typos - . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists - . msdos/Makefile.msc: remove "default rtl link library" info from obj files - . msdos/Makefile.*: use model-dependent name for the built zlib library - . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: - new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) -- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) -- replace __far with _far for better portability (Christian Spieler, Tom Lane) -- fix test for errno.h in configure (Tim Newsham) - -Changes in 1.1.2 (19 March 98) -- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) - See http://www.winimage.com/zLibDll/unzip.html -- preinitialize the inflate tables for fixed codes, to make the code - completely thread safe (Mark) -- some simplifications and slight speed-up to the inflate code (Mark) -- fix gzeof on non-compressed files (Allan Schrum) -- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) -- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) -- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) -- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) -- do not wrap extern "C" around system includes (Tom Lane) -- mention zlib binding for TCL in README (Andreas Kupries) -- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) -- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) -- allow "configure --prefix $HOME" (Tim Mooney) -- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) -- move Makefile.sas to amiga/Makefile.sas - -Changes in 1.1.1 (27 Feb 98) -- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) -- remove block truncation heuristic which had very marginal effect for zlib - (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the - compression ratio on some files. This also allows inlining _tr_tally for - matches in deflate_slow. -- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) - -Changes in 1.1.0 (24 Feb 98) -- do not return STREAM_END prematurely in inflate (John Bowler) -- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) -- compile with -DFASTEST to get compression code optimized for speed only -- in minigzip, try mmap'ing the input file first (Miguel Albrecht) -- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain - on Sun but significant on HP) - -- add a pointer to experimental unzip library in README (Gilles Vollant) -- initialize variable gcc in configure (Chris Herborth) - -Changes in 1.0.9 (17 Feb 1998) -- added gzputs and gzgets functions -- do not clear eof flag in gzseek (Mark Diekhans) -- fix gzseek for files in transparent mode (Mark Diekhans) -- do not assume that vsprintf returns the number of bytes written (Jens Krinke) -- replace EXPORT with ZEXPORT to avoid conflict with other programs -- added compress2 in zconf.h, zlib.def, zlib.dnt -- new asm code from Gilles Vollant in contrib/asm386 -- simplify the inflate code (Mark): - . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() - . ZALLOC the length list in inflate_trees_fixed() instead of using stack - . ZALLOC the value area for huft_build() instead of using stack - . Simplify Z_FINISH check in inflate() - -- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 -- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) -- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with - the declaration of FAR (Gilles VOllant) -- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) -- read_buf buf parameter of type Bytef* instead of charf* -- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) -- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) -- fix check for presence of directories in "make install" (Ian Willis) - -Changes in 1.0.8 (27 Jan 1998) -- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) -- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) -- added compress2() to allow setting the compression level -- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) -- use constant arrays for the static trees in trees.c instead of computing - them at run time (thanks to Ken Raeburn for this suggestion). To create - trees.h, compile with GEN_TREES_H and run "make test". -- check return code of example in "make test" and display result -- pass minigzip command line options to file_compress -- simplifying code of inflateSync to avoid gcc 2.8 bug - -- support CC="gcc -Wall" in configure -s (QingLong) -- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) -- fix test for shared library support to avoid compiler warnings -- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) -- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) -- do not use fdopen for Metrowerks on Mac (Brad Pettit)) -- add checks for gzputc and gzputc in example.c -- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) -- use const for the CRC table (Ken Raeburn) -- fixed "make uninstall" for shared libraries -- use Tracev instead of Trace in infblock.c -- in example.c use correct compressed length for test_sync -- suppress +vnocompatwarnings in configure for HPUX (not always supported) - -Changes in 1.0.7 (20 Jan 1998) -- fix gzseek which was broken in write mode -- return error for gzseek to negative absolute position -- fix configure for Linux (Chun-Chung Chen) -- increase stack space for MSC (Tim Wegner) -- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) -- define EXPORTVA for gzprintf (Gilles Vollant) -- added man page zlib.3 (Rick Rodgers) -- for contrib/untgz, fix makedir() and improve Makefile - -- check gzseek in write mode in example.c -- allocate extra buffer for seeks only if gzseek is actually called -- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) -- add inflateSyncPoint in zconf.h -- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def - -Changes in 1.0.6 (19 Jan 1998) -- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and - gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) -- Fix a deflate bug occurring only with compression level 0 (thanks to - Andy Buckler for finding this one). -- In minigzip, pass transparently also the first byte for .Z files. -- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() -- check Z_FINISH in inflate (thanks to Marc Schluper) -- Implement deflateCopy (thanks to Adam Costello) -- make static libraries by default in configure, add --shared option. -- move MSDOS or Windows specific files to directory msdos -- suppress the notion of partial flush to simplify the interface - (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) -- suppress history buffer provided by application to simplify the interface - (this feature was not implemented anyway in 1.0.4) -- next_in and avail_in must be initialized before calling inflateInit or - inflateInit2 -- add EXPORT in all exported functions (for Windows DLL) -- added Makefile.nt (thanks to Stephen Williams) -- added the unsupported "contrib" directory: - contrib/asm386/ by Gilles Vollant - 386 asm code replacing longest_match(). - contrib/iostream/ by Kevin Ruland - A C++ I/O streams interface to the zlib gz* functions - contrib/iostream2/ by Tyge Løvset - Another C++ I/O streams interface - contrib/untgz/ by "Pedro A. Aranda Guti\irrez" - A very simple tar.gz file extractor using zlib - contrib/visual-basic.txt by Carlos Rios - How to use compress(), uncompress() and the gz* functions from VB. -- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression - level) in minigzip (thanks to Tom Lane) - -- use const for rommable constants in deflate -- added test for gzseek and gztell in example.c -- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) -- add undocumented function zError to convert error code to string - (for Tim Smithers) -- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. -- Use default memcpy for Symantec MSDOS compiler. -- Add EXPORT keyword for check_func (needed for Windows DLL) -- add current directory to LD_LIBRARY_PATH for "make test" -- create also a link for libz.so.1 -- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) -- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) -- added -soname for Linux in configure (Chun-Chung Chen, -- assign numbers to the exported functions in zlib.def (for Windows DLL) -- add advice in zlib.h for best usage of deflateSetDictionary -- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) -- allow compilation with ANSI keywords only enabled for TurboC in large model -- avoid "versionString"[0] (Borland bug) -- add NEED_DUMMY_RETURN for Borland -- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). -- allow compilation with CC -- defined STDC for OS/2 (David Charlap) -- limit external names to 8 chars for MVS (Thomas Lund) -- in minigzip.c, use static buffers only for 16-bit systems -- fix suffix check for "minigzip -d foo.gz" -- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) -- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) -- added makelcc.bat for lcc-win32 (Tom St Denis) -- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) -- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. -- check for unistd.h in configure (for off_t) -- remove useless check parameter in inflate_blocks_free -- avoid useless assignment of s->check to itself in inflate_blocks_new -- do not flush twice in gzclose (thanks to Ken Raeburn) -- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h -- use NO_ERRNO_H instead of enumeration of operating systems with errno.h -- work around buggy fclose on pipes for HP/UX -- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) -- fix configure if CC is already equal to gcc - -Changes in 1.0.5 (3 Jan 98) -- Fix inflate to terminate gracefully when fed corrupted or invalid data -- Use const for rommable constants in inflate -- Eliminate memory leaks on error conditions in inflate -- Removed some vestigial code in inflate -- Update web address in README - -Changes in 1.0.4 (24 Jul 96) -- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF - bit, so the decompressor could decompress all the correct data but went - on to attempt decompressing extra garbage data. This affected minigzip too. -- zlibVersion and gzerror return const char* (needed for DLL) -- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) -- use z_error only for DEBUG (avoid problem with DLLs) - -Changes in 1.0.3 (2 Jul 96) -- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS - small and medium models; this makes the library incompatible with previous - versions for these models. (No effect in large model or on other systems.) -- return OK instead of BUF_ERROR if previous deflate call returned with - avail_out as zero but there is nothing to do -- added memcmp for non STDC compilers -- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) -- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) -- better check for 16-bit mode MSC (avoids problem with Symantec) - -Changes in 1.0.2 (23 May 96) -- added Windows DLL support -- added a function zlibVersion (for the DLL support) -- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) -- Bytef is define's instead of typedef'd only for Borland C -- avoid reading uninitialized memory in example.c -- mention in README that the zlib format is now RFC1950 -- updated Makefile.dj2 -- added algorithm.doc - -Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] -- fix array overlay in deflate.c which sometimes caused bad compressed data -- fix inflate bug with empty stored block -- fix MSDOS medium model which was broken in 0.99 -- fix deflateParams() which could generate bad compressed data. -- Bytef is define'd instead of typedef'ed (work around Borland bug) -- added an INDEX file -- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), - Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) -- speed up adler32 for modern machines without auto-increment -- added -ansi for IRIX in configure -- static_init_done in trees.c is an int -- define unlink as delete for VMS -- fix configure for QNX -- add configure branch for SCO and HPUX -- avoid many warnings (unused variables, dead assignments, etc...) -- no fdopen for BeOS -- fix the Watcom fix for 32 bit mode (define FAR as empty) -- removed redefinition of Byte for MKWERKS -- work around an MWKERKS bug (incorrect merge of all .h files) - -Changes in 0.99 (27 Jan 96) -- allow preset dictionary shared between compressor and decompressor -- allow compression level 0 (no compression) -- add deflateParams in zlib.h: allow dynamic change of compression level - and compression strategy. -- test large buffers and deflateParams in example.c -- add optional "configure" to build zlib as a shared library -- suppress Makefile.qnx, use configure instead -- fixed deflate for 64-bit systems (detected on Cray) -- fixed inflate_blocks for 64-bit systems (detected on Alpha) -- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) -- always return Z_BUF_ERROR when deflate() has nothing to do -- deflateInit and inflateInit are now macros to allow version checking -- prefix all global functions and types with z_ with -DZ_PREFIX -- make falloc completely reentrant (inftrees.c) -- fixed very unlikely race condition in ct_static_init -- free in reverse order of allocation to help memory manager -- use zlib-1.0/* instead of zlib/* inside the tar.gz -- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith - -Wconversion -Wstrict-prototypes -Wmissing-prototypes" -- allow gzread on concatenated .gz files -- deflateEnd now returns Z_DATA_ERROR if it was premature -- deflate is finally (?) fully deterministic (no matches beyond end of input) -- Document Z_SYNC_FLUSH -- add uninstall in Makefile -- Check for __cpluplus in zlib.h -- Better test in ct_align for partial flush -- avoid harmless warnings for Borland C++ -- initialize hash_head in deflate.c -- avoid warning on fdopen (gzio.c) for HP cc -Aa -- include stdlib.h for STDC compilers -- include errno.h for Cray -- ignore error if ranlib doesn't exist -- call ranlib twice for NeXTSTEP -- use exec_prefix instead of prefix for libz.a -- renamed ct_* as _tr_* to avoid conflict with applications -- clear z->msg in inflateInit2 before any error return -- initialize opaque in example.c, gzio.c, deflate.c and inflate.c -- fixed typo in zconf.h (_GNUC__ => __GNUC__) -- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) -- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) -- in fcalloc, normalize pointer if size > 65520 bytes -- don't use special fcalloc for 32 bit Borland C++ -- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... -- use Z_BINARY instead of BINARY -- document that gzclose after gzdopen will close the file -- allow "a" as mode in gzopen. -- fix error checking in gzread -- allow skipping .gz extra-field on pipes -- added reference to Perl interface in README -- put the crc table in FAR data (I dislike more and more the medium model :) -- added get_crc_table -- added a dimension to all arrays (Borland C can't count). -- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast -- guard against multiple inclusion of *.h (for precompiled header on Mac) -- Watcom C pretends to be Microsoft C small model even in 32 bit mode. -- don't use unsized arrays to avoid silly warnings by Visual C++: - warning C4746: 'inflate_mask' : unsized array treated as '__far' - (what's wrong with far data in far model?). -- define enum out of inflate_blocks_state to allow compilation with C++ - -Changes in 0.95 (16 Aug 95) -- fix MSDOS small and medium model (now easier to adapt to any compiler) -- inlined send_bits -- fix the final (:-) bug for deflate with flush (output was correct but - not completely flushed in rare occasions). -- default window size is same for compression and decompression - (it's now sufficient to set MAX_WBITS in zconf.h). -- voidp -> voidpf and voidnp -> voidp (for consistency with other - typedefs and because voidnp was not near in large model). - -Changes in 0.94 (13 Aug 95) -- support MSDOS medium model -- fix deflate with flush (could sometimes generate bad output) -- fix deflateReset (zlib header was incorrectly suppressed) -- added support for VMS -- allow a compression level in gzopen() -- gzflush now calls fflush -- For deflate with flush, flush even if no more input is provided. -- rename libgz.a as libz.a -- avoid complex expression in infcodes.c triggering Turbo C bug -- work around a problem with gcc on Alpha (in INSERT_STRING) -- don't use inline functions (problem with some gcc versions) -- allow renaming of Byte, uInt, etc... with #define. -- avoid warning about (unused) pointer before start of array in deflate.c -- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c -- avoid reserved word 'new' in trees.c - -Changes in 0.93 (25 June 95) -- temporarily disable inline functions -- make deflate deterministic -- give enough lookahead for PARTIAL_FLUSH -- Set binary mode for stdin/stdout in minigzip.c for OS/2 -- don't even use signed char in inflate (not portable enough) -- fix inflate memory leak for segmented architectures - -Changes in 0.92 (3 May 95) -- don't assume that char is signed (problem on SGI) -- Clear bit buffer when starting a stored block -- no memcpy on Pyramid -- suppressed inftest.c -- optimized fill_window, put longest_match inline for gcc -- optimized inflate on stored blocks. -- untabify all sources to simplify patches - -Changes in 0.91 (2 May 95) -- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h -- Document the memory requirements in zconf.h -- added "make install" -- fix sync search logic in inflateSync -- deflate(Z_FULL_FLUSH) now works even if output buffer too short -- after inflateSync, don't scare people with just "lo world" -- added support for DJGPP - -Changes in 0.9 (1 May 95) -- don't assume that zalloc clears the allocated memory (the TurboC bug - was Mark's bug after all :) -- let again gzread copy uncompressed data unchanged (was working in 0.71) -- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented -- added a test of inflateSync in example.c -- moved MAX_WBITS to zconf.h because users might want to change that. -- document explicitly that zalloc(64K) on MSDOS must return a normalized - pointer (zero offset) -- added Makefiles for Microsoft C, Turbo C, Borland C++ -- faster crc32() - -Changes in 0.8 (29 April 95) -- added fast inflate (inffast.c) -- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this - is incompatible with previous versions of zlib which returned Z_OK. -- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) - (actually that was not a compiler bug, see 0.81 above) -- gzread no longer reads one extra byte in certain cases -- In gzio destroy(), don't reference a freed structure -- avoid many warnings for MSDOS -- avoid the ERROR symbol which is used by MS Windows - -Changes in 0.71 (14 April 95) -- Fixed more MSDOS compilation problems :( There is still a bug with - TurboC large model. - -Changes in 0.7 (14 April 95) -- Added full inflate support. -- Simplified the crc32() interface. The pre- and post-conditioning - (one's complement) is now done inside crc32(). WARNING: this is - incompatible with previous versions; see zlib.h for the new usage. - -Changes in 0.61 (12 April 95) -- workaround for a bug in TurboC. example and minigzip now work on MSDOS. - -Changes in 0.6 (11 April 95) -- added minigzip.c -- added gzdopen to reopen a file descriptor as gzFile -- added transparent reading of non-gziped files in gzread. -- fixed bug in gzread (don't read crc as data) -- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). -- don't allocate big arrays in the stack (for MSDOS) -- fix some MSDOS compilation problems - -Changes in 0.5: -- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but - not yet Z_FULL_FLUSH. -- support decompression but only in a single step (forced Z_FINISH) -- added opaque object for zalloc and zfree. -- added deflateReset and inflateReset -- added a variable zlib_version for consistency checking. -- renamed the 'filter' parameter of deflateInit2 as 'strategy'. - Added Z_FILTERED and Z_HUFFMAN_ONLY constants. - -Changes in 0.4: -- avoid "zip" everywhere, use zlib instead of ziplib. -- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush - if compression method == 8. -- added adler32 and crc32 -- renamed deflateOptions as deflateInit2, call one or the other but not both -- added the method parameter for deflateInit2. -- added inflateInit2 -- simplied considerably deflateInit and inflateInit by not supporting - user-provided history buffer. This is supported only in deflateInit2 - and inflateInit2. - -Changes in 0.3: -- prefix all macro names with Z_ -- use Z_FINISH instead of deflateEnd to finish compression. -- added Z_HUFFMAN_ONLY -- added gzerror() diff --git a/deps/zlib/FAQ b/deps/zlib/FAQ deleted file mode 100644 index 99b7cf92e45497..00000000000000 --- a/deps/zlib/FAQ +++ /dev/null @@ -1,368 +0,0 @@ - - Frequently Asked Questions about zlib - - -If your question is not there, please check the zlib home page -http://zlib.net/ which may have more recent information. -The lastest zlib FAQ is at http://zlib.net/zlib_faq.html - - - 1. Is zlib Y2K-compliant? - - Yes. zlib doesn't handle dates. - - 2. Where can I get a Windows DLL version? - - The zlib sources can be compiled without change to produce a DLL. See the - file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the - precompiled DLL are found in the zlib web site at http://zlib.net/ . - - 3. Where can I get a Visual Basic interface to zlib? - - See - * http://marknelson.us/1997/01/01/zlib-engine/ - * win32/DLL_FAQ.txt in the zlib distribution - - 4. compress() returns Z_BUF_ERROR. - - Make sure that before the call of compress(), the length of the compressed - buffer is equal to the available size of the compressed buffer and not - zero. For Visual Basic, check that this parameter is passed by reference - ("as any"), not by value ("as long"). - - 5. deflate() or inflate() returns Z_BUF_ERROR. - - Before making the call, make sure that avail_in and avail_out are not zero. - When setting the parameter flush equal to Z_FINISH, also make sure that - avail_out is big enough to allow processing all pending input. Note that a - Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be - made with more input or output space. A Z_BUF_ERROR may in fact be - unavoidable depending on how the functions are used, since it is not - possible to tell whether or not there is more output pending when - strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a - heavily annotated example. - - 6. Where's the zlib documentation (man pages, etc.)? - - It's in zlib.h . Examples of zlib usage are in the files test/example.c - and test/minigzip.c, with more in examples/ . - - 7. Why don't you use GNU autoconf or libtool or ...? - - Because we would like to keep zlib as a very small and simple package. - zlib is rather portable and doesn't need much configuration. - - 8. I found a bug in zlib. - - Most of the time, such problems are due to an incorrect usage of zlib. - Please try to reproduce the problem with a small program and send the - corresponding source to us at zlib@gzip.org . Do not send multi-megabyte - data files without prior agreement. - - 9. Why do I get "undefined reference to gzputc"? - - If "make test" produces something like - - example.o(.text+0x154): undefined reference to `gzputc' - - check that you don't have old files libz.* in /usr/lib, /usr/local/lib or - /usr/X11R6/lib. Remove any old versions, then do "make install". - -10. I need a Delphi interface to zlib. - - See the contrib/delphi directory in the zlib distribution. - -11. Can zlib handle .zip archives? - - Not by itself, no. See the directory contrib/minizip in the zlib - distribution. - -12. Can zlib handle .Z files? - - No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt - the code of uncompress on your own. - -13. How can I make a Unix shared library? - - By default a shared (and a static) library is built for Unix. So: - - make distclean - ./configure - make - -14. How do I install a shared zlib library on Unix? - - After the above, then: - - make install - - However, many flavors of Unix come with a shared zlib already installed. - Before going to the trouble of compiling a shared version of zlib and - trying to install it, you may want to check if it's already there! If you - can #include , it's there. The -lz option will probably link to - it. You can check the version at the top of zlib.h or with the - ZLIB_VERSION symbol defined in zlib.h . - -15. I have a question about OttoPDF. - - We are not the authors of OttoPDF. The real author is on the OttoPDF web - site: Joel Hainley, jhainley@myndkryme.com. - -16. Can zlib decode Flate data in an Adobe PDF file? - - Yes. See http://www.pdflib.com/ . To modify PDF forms, see - http://sourceforge.net/projects/acroformtool/ . - -17. Why am I getting this "register_frame_info not found" error on Solaris? - - After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib - generates an error such as: - - ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so: - symbol __register_frame_info: referenced symbol not found - - The symbol __register_frame_info is not part of zlib, it is generated by - the C compiler (cc or gcc). You must recompile applications using zlib - which have this problem. This problem is specific to Solaris. See - http://www.sunfreeware.com for Solaris versions of zlib and applications - using zlib. - -18. Why does gzip give an error on a file I make with compress/deflate? - - The compress and deflate functions produce data in the zlib format, which - is different and incompatible with the gzip format. The gz* functions in - zlib on the other hand use the gzip format. Both the zlib and gzip formats - use the same compressed data format internally, but have different headers - and trailers around the compressed data. - -19. Ok, so why are there two different formats? - - The gzip format was designed to retain the directory information about a - single file, such as the name and last modification date. The zlib format - on the other hand was designed for in-memory and communication channel - applications, and has a much more compact header and trailer and uses a - faster integrity check than gzip. - -20. Well that's nice, but how do I make a gzip file in memory? - - You can request that deflate write the gzip format instead of the zlib - format using deflateInit2(). You can also request that inflate decode the - gzip format using inflateInit2(). Read zlib.h for more details. - -21. Is zlib thread-safe? - - Yes. However any library routines that zlib uses and any application- - provided memory allocation routines must also be thread-safe. zlib's gz* - functions use stdio library routines, and most of zlib's functions use the - library memory allocation routines by default. zlib's *Init* functions - allow for the application to provide custom memory allocation routines. - - Of course, you should only operate on any given zlib or gzip stream from a - single thread at a time. - -22. Can I use zlib in my commercial application? - - Yes. Please read the license in zlib.h. - -23. Is zlib under the GNU license? - - No. Please read the license in zlib.h. - -24. The license says that altered source versions must be "plainly marked". So - what exactly do I need to do to meet that requirement? - - You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In - particular, the final version number needs to be changed to "f", and an - identification string should be appended to ZLIB_VERSION. Version numbers - x.x.x.f are reserved for modifications to zlib by others than the zlib - maintainers. For example, if the version of the base zlib you are altering - is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and - ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also - update the version strings in deflate.c and inftrees.c. - - For altered source distributions, you should also note the origin and - nature of the changes in zlib.h, as well as in ChangeLog and README, along - with the dates of the alterations. The origin should include at least your - name (or your company's name), and an email address to contact for help or - issues with the library. - - Note that distributing a compiled zlib library along with zlib.h and - zconf.h is also a source distribution, and so you should change - ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes - in zlib.h as you would for a full source distribution. - -25. Will zlib work on a big-endian or little-endian architecture, and can I - exchange compressed data between them? - - Yes and yes. - -26. Will zlib work on a 64-bit machine? - - Yes. It has been tested on 64-bit machines, and has no dependence on any - data types being limited to 32-bits in length. If you have any - difficulties, please provide a complete problem report to zlib@gzip.org - -27. Will zlib decompress data from the PKWare Data Compression Library? - - No. The PKWare DCL uses a completely different compressed data format than - does PKZIP and zlib. However, you can look in zlib's contrib/blast - directory for a possible solution to your problem. - -28. Can I access data randomly in a compressed stream? - - No, not without some preparation. If when compressing you periodically use - Z_FULL_FLUSH, carefully write all the pending data at those points, and - keep an index of those locations, then you can start decompression at those - points. You have to be careful to not use Z_FULL_FLUSH too often, since it - can significantly degrade compression. Alternatively, you can scan a - deflate stream once to generate an index, and then use that index for - random access. See examples/zran.c . - -29. Does zlib work on MVS, OS/390, CICS, etc.? - - It has in the past, but we have not heard of any recent evidence. There - were working ports of zlib 1.1.4 to MVS, but those links no longer work. - If you know of recent, successful applications of zlib on these operating - systems, please let us know. Thanks. - -30. Is there some simpler, easier to read version of inflate I can look at to - understand the deflate format? - - First off, you should read RFC 1951. Second, yes. Look in zlib's - contrib/puff directory. - -31. Does zlib infringe on any patents? - - As far as we know, no. In fact, that was originally the whole point behind - zlib. Look here for some more information: - - http://www.gzip.org/#faq11 - -32. Can zlib work with greater than 4 GB of data? - - Yes. inflate() and deflate() will process any amount of data correctly. - Each call of inflate() or deflate() is limited to input and output chunks - of the maximum value that can be stored in the compiler's "unsigned int" - type, but there is no limit to the number of chunks. Note however that the - strm.total_in and strm_total_out counters may be limited to 4 GB. These - counters are provided as a convenience and are not used internally by - inflate() or deflate(). The application can easily set up its own counters - updated after each call of inflate() or deflate() to count beyond 4 GB. - compress() and uncompress() may be limited to 4 GB, since they operate in a - single call. gzseek() and gztell() may be limited to 4 GB depending on how - zlib is compiled. See the zlibCompileFlags() function in zlib.h. - - The word "may" appears several times above since there is a 4 GB limit only - if the compiler's "long" type is 32 bits. If the compiler's "long" type is - 64 bits, then the limit is 16 exabytes. - -33. Does zlib have any security vulnerabilities? - - The only one that we are aware of is potentially in gzprintf(). If zlib is - compiled to use sprintf() or vsprintf(), then there is no protection - against a buffer overflow of an 8K string space (or other value as set by - gzbuffer()), other than the caller of gzprintf() assuring that the output - will not exceed 8K. On the other hand, if zlib is compiled to use - snprintf() or vsnprintf(), which should normally be the case, then there is - no vulnerability. The ./configure script will display warnings if an - insecure variation of sprintf() will be used by gzprintf(). Also the - zlibCompileFlags() function will return information on what variant of - sprintf() is used by gzprintf(). - - If you don't have snprintf() or vsnprintf() and would like one, you can - find a portable implementation here: - - http://www.ijs.si/software/snprintf/ - - Note that you should be using the most recent version of zlib. Versions - 1.1.3 and before were subject to a double-free vulnerability, and versions - 1.2.1 and 1.2.2 were subject to an access exception when decompressing - invalid compressed data. - -34. Is there a Java version of zlib? - - Probably what you want is to use zlib in Java. zlib is already included - as part of the Java SDK in the java.util.zip package. If you really want - a version of zlib written in the Java language, look on the zlib home - page for links: http://zlib.net/ . - -35. I get this or that compiler or source-code scanner warning when I crank it - up to maximally-pedantic. Can't you guys write proper code? - - Many years ago, we gave up attempting to avoid warnings on every compiler - in the universe. It just got to be a waste of time, and some compilers - were downright silly as well as contradicted each other. So now, we simply - make sure that the code always works. - -36. Valgrind (or some similar memory access checker) says that deflate is - performing a conditional jump that depends on an uninitialized value. - Isn't that a bug? - - No. That is intentional for performance reasons, and the output of deflate - is not affected. This only started showing up recently since zlib 1.2.x - uses malloc() by default for allocations, whereas earlier versions used - calloc(), which zeros out the allocated memory. Even though the code was - correct, versions 1.2.4 and later was changed to not stimulate these - checkers. - -37. Will zlib read the (insert any ancient or arcane format here) compressed - data format? - - Probably not. Look in the comp.compression FAQ for pointers to various - formats and associated software. - -38. How can I encrypt/decrypt zip files with zlib? - - zlib doesn't support encryption. The original PKZIP encryption is very - weak and can be broken with freely available programs. To get strong - encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib - compression. For PKZIP compatible "encryption", look at - http://www.info-zip.org/ - -39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? - - "gzip" is the gzip format, and "deflate" is the zlib format. They should - probably have called the second one "zlib" instead to avoid confusion with - the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 - correctly points to the zlib specification in RFC 1950 for the "deflate" - transfer encoding, there have been reports of servers and browsers that - incorrectly produce or expect raw deflate data per the deflate - specification in RFC 1951, most notably Microsoft. So even though the - "deflate" transfer encoding using the zlib format would be the more - efficient approach (and in fact exactly what the zlib format was designed - for), using the "gzip" transfer encoding is probably more reliable due to - an unfortunate choice of name on the part of the HTTP 1.1 authors. - - Bottom line: use the gzip format for HTTP 1.1 encoding. - -40. Does zlib support the new "Deflate64" format introduced by PKWare? - - No. PKWare has apparently decided to keep that format proprietary, since - they have not documented it as they have previous compression formats. In - any case, the compression improvements are so modest compared to other more - modern approaches, that it's not worth the effort to implement. - -41. I'm having a problem with the zip functions in zlib, can you help? - - There are no zip functions in zlib. You are probably using minizip by - Giles Vollant, which is found in the contrib directory of zlib. It is not - part of zlib. In fact none of the stuff in contrib is part of zlib. The - files in there are not supported by the zlib authors. You need to contact - the authors of the respective contribution for help. - -42. The match.asm code in contrib is under the GNU General Public License. - Since it's part of zlib, doesn't that mean that all of zlib falls under the - GNU GPL? - - No. The files in contrib are not part of zlib. They were contributed by - other authors and are provided as a convenience to the user within the zlib - distribution. Each item in contrib has its own license. - -43. Is zlib subject to export controls? What is its ECCN? - - zlib is not subject to export controls, and so is classified as EAR99. - -44. Can you please sign these lengthy legal documents and fax them back to us - so that we can use your software in our product? - - No. Go away. Shoo. diff --git a/deps/zlib/INDEX b/deps/zlib/INDEX deleted file mode 100644 index 2ba0641204861d..00000000000000 --- a/deps/zlib/INDEX +++ /dev/null @@ -1,68 +0,0 @@ -CMakeLists.txt cmake build file -ChangeLog history of changes -FAQ Frequently Asked Questions about zlib -INDEX this file -Makefile dummy Makefile that tells you to ./configure -Makefile.in template for Unix Makefile -README guess what -configure configure script for Unix -make_vms.com makefile for VMS -test/example.c zlib usages examples for build testing -test/minigzip.c minimal gzip-like functionality for build testing -test/infcover.c inf*.c code coverage for build coverage testing -treebuild.xml XML description of source file dependencies -zconf.h.cmakein zconf.h template for cmake -zconf.h.in zconf.h template for configure -zlib.3 Man page for zlib -zlib.3.pdf Man page in PDF format -zlib.map Linux symbol information -zlib.pc.in Template for pkg-config descriptor -zlib.pc.cmakein zlib.pc template for cmake -zlib2ansi perl script to convert source files for C++ compilation - -amiga/ makefiles for Amiga SAS C -as400/ makefiles for AS/400 -doc/ documentation for formats and algorithms -msdos/ makefiles for MSDOS -nintendods/ makefile for Nintendo DS -old/ makefiles for various architectures and zlib documentation - files that have not yet been updated for zlib 1.2.x -qnx/ makefiles for QNX -watcom/ makefiles for OpenWatcom -win32/ makefiles for Windows - - zlib public header files (required for library use): -zconf.h -zlib.h - - private source files used to build the zlib library: -adler32.c -compress.c -crc32.c -crc32.h -deflate.c -deflate.h -gzclose.c -gzguts.h -gzlib.c -gzread.c -gzwrite.c -infback.c -inffast.c -inffast.h -inffixed.h -inflate.c -inflate.h -inftrees.c -inftrees.h -trees.c -trees.h -uncompr.c -zutil.c -zutil.h - - source files for sample programs -See examples/README.examples - - unsupported contributions by third parties -See contrib/README.contrib diff --git a/deps/zlib/LICENSE b/deps/zlib/LICENSE new file mode 100644 index 00000000000000..9f056865b5719d --- /dev/null +++ b/deps/zlib/LICENSE @@ -0,0 +1,19 @@ +version 1.2.11, January 15th, 2017 + +Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. diff --git a/deps/zlib/Makefile b/deps/zlib/Makefile deleted file mode 100644 index 6bba86c73fca2a..00000000000000 --- a/deps/zlib/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -all: - -@echo "Please use ./configure first. Thank you." - -distclean: - make -f Makefile.in distclean diff --git a/deps/zlib/Makefile.in b/deps/zlib/Makefile.in deleted file mode 100644 index 5a77949ff06857..00000000000000 --- a/deps/zlib/Makefile.in +++ /dev/null @@ -1,410 +0,0 @@ -# Makefile for zlib -# Copyright (C) 1995-2017 Jean-loup Gailly, Mark Adler -# For conditions of distribution and use, see copyright notice in zlib.h - -# To compile and test, type: -# ./configure; make test -# Normally configure builds both a static and a shared library. -# If you want to build just a static library, use: ./configure --static - -# To use the asm code, type: -# cp contrib/asm?86/match.S ./match.S -# make LOC=-DASMV OBJA=match.o - -# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: -# make install -# To install in $HOME instead of /usr/local, use: -# make install prefix=$HOME - -CC=cc - -CFLAGS=-O -#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-g -DZLIB_DEBUG -#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ -# -Wstrict-prototypes -Wmissing-prototypes - -SFLAGS=-O -LDFLAGS= -TEST_LDFLAGS=-L. libz.a -LDSHARED=$(CC) -CPP=$(CC) -E - -STATICLIB=libz.a -SHAREDLIB=libz.so -SHAREDLIBV=libz.so.1.2.11 -SHAREDLIBM=libz.so.1 -LIBS=$(STATICLIB) $(SHAREDLIBV) - -AR=ar -ARFLAGS=rc -RANLIB=ranlib -LDCONFIG=ldconfig -LDSHAREDLIBC=-lc -TAR=tar -SHELL=/bin/sh -EXE= - -prefix = /usr/local -exec_prefix = ${prefix} -libdir = ${exec_prefix}/lib -sharedlibdir = ${libdir} -includedir = ${prefix}/include -mandir = ${prefix}/share/man -man3dir = ${mandir}/man3 -pkgconfigdir = ${libdir}/pkgconfig -SRCDIR= -ZINC= -ZINCOUT=-I. - -OBJZ = adler32.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o zutil.o -OBJG = compress.o uncompr.o gzclose.o gzlib.o gzread.o gzwrite.o -OBJC = $(OBJZ) $(OBJG) - -PIC_OBJZ = adler32.lo crc32.lo deflate.lo infback.lo inffast.lo inflate.lo inftrees.lo trees.lo zutil.lo -PIC_OBJG = compress.lo uncompr.lo gzclose.lo gzlib.lo gzread.lo gzwrite.lo -PIC_OBJC = $(PIC_OBJZ) $(PIC_OBJG) - -# to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo -OBJA = -PIC_OBJA = - -OBJS = $(OBJC) $(OBJA) - -PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA) - -all: static shared - -static: example$(EXE) minigzip$(EXE) - -shared: examplesh$(EXE) minigzipsh$(EXE) - -all64: example64$(EXE) minigzip64$(EXE) - -check: test - -test: all teststatic testshared - -teststatic: static - @TMPST=tmpst_$$; \ - if echo hello world | ./minigzip | ./minigzip -d && ./example $$TMPST ; then \ - echo ' *** zlib test OK ***'; \ - else \ - echo ' *** zlib test FAILED ***'; false; \ - fi; \ - rm -f $$TMPST - -testshared: shared - @LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ - LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \ - DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \ - SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \ - TMPSH=tmpsh_$$; \ - if echo hello world | ./minigzipsh | ./minigzipsh -d && ./examplesh $$TMPSH; then \ - echo ' *** zlib shared test OK ***'; \ - else \ - echo ' *** zlib shared test FAILED ***'; false; \ - fi; \ - rm -f $$TMPSH - -test64: all64 - @TMP64=tmp64_$$; \ - if echo hello world | ./minigzip64 | ./minigzip64 -d && ./example64 $$TMP64; then \ - echo ' *** zlib 64-bit test OK ***'; \ - else \ - echo ' *** zlib 64-bit test FAILED ***'; false; \ - fi; \ - rm -f $$TMP64 - -infcover.o: $(SRCDIR)test/infcover.c $(SRCDIR)zlib.h zconf.h - $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/infcover.c - -infcover: infcover.o libz.a - $(CC) $(CFLAGS) -o $@ infcover.o libz.a - -cover: infcover - rm -f *.gcda - ./infcover - gcov inf*.c - -libz.a: $(OBJS) - $(AR) $(ARFLAGS) $@ $(OBJS) - -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 - -match.o: match.S - $(CPP) match.S > _match.s - $(CC) -c _match.s - mv _match.o match.o - rm -f _match.s - -match.lo: match.S - $(CPP) match.S > _match.s - $(CC) -c -fPIC _match.s - mv _match.o match.lo - rm -f _match.s - -example.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h - $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/example.c - -minigzip.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h - $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/minigzip.c - -example64.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h - $(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/example.c - -minigzip64.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h - $(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/minigzip.c - - -adler32.o: $(SRCDIR)adler32.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)adler32.c - -crc32.o: $(SRCDIR)crc32.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)crc32.c - -deflate.o: $(SRCDIR)deflate.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)deflate.c - -infback.o: $(SRCDIR)infback.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)infback.c - -inffast.o: $(SRCDIR)inffast.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inffast.c - -inflate.o: $(SRCDIR)inflate.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inflate.c - -inftrees.o: $(SRCDIR)inftrees.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inftrees.c - -trees.o: $(SRCDIR)trees.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)trees.c - -zutil.o: $(SRCDIR)zutil.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)zutil.c - -compress.o: $(SRCDIR)compress.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)compress.c - -uncompr.o: $(SRCDIR)uncompr.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)uncompr.c - -gzclose.o: $(SRCDIR)gzclose.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzclose.c - -gzlib.o: $(SRCDIR)gzlib.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzlib.c - -gzread.o: $(SRCDIR)gzread.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzread.c - -gzwrite.o: $(SRCDIR)gzwrite.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzwrite.c - - -adler32.lo: $(SRCDIR)adler32.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/adler32.o $(SRCDIR)adler32.c - -@mv objs/adler32.o $@ - -crc32.lo: $(SRCDIR)crc32.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/crc32.o $(SRCDIR)crc32.c - -@mv objs/crc32.o $@ - -deflate.lo: $(SRCDIR)deflate.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/deflate.o $(SRCDIR)deflate.c - -@mv objs/deflate.o $@ - -infback.lo: $(SRCDIR)infback.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/infback.o $(SRCDIR)infback.c - -@mv objs/infback.o $@ - -inffast.lo: $(SRCDIR)inffast.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inffast.o $(SRCDIR)inffast.c - -@mv objs/inffast.o $@ - -inflate.lo: $(SRCDIR)inflate.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inflate.o $(SRCDIR)inflate.c - -@mv objs/inflate.o $@ - -inftrees.lo: $(SRCDIR)inftrees.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inftrees.o $(SRCDIR)inftrees.c - -@mv objs/inftrees.o $@ - -trees.lo: $(SRCDIR)trees.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/trees.o $(SRCDIR)trees.c - -@mv objs/trees.o $@ - -zutil.lo: $(SRCDIR)zutil.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/zutil.o $(SRCDIR)zutil.c - -@mv objs/zutil.o $@ - -compress.lo: $(SRCDIR)compress.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/compress.o $(SRCDIR)compress.c - -@mv objs/compress.o $@ - -uncompr.lo: $(SRCDIR)uncompr.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/uncompr.o $(SRCDIR)uncompr.c - -@mv objs/uncompr.o $@ - -gzclose.lo: $(SRCDIR)gzclose.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzclose.o $(SRCDIR)gzclose.c - -@mv objs/gzclose.o $@ - -gzlib.lo: $(SRCDIR)gzlib.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzlib.o $(SRCDIR)gzlib.c - -@mv objs/gzlib.o $@ - -gzread.lo: $(SRCDIR)gzread.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzread.o $(SRCDIR)gzread.c - -@mv objs/gzread.o $@ - -gzwrite.lo: $(SRCDIR)gzwrite.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzwrite.o $(SRCDIR)gzwrite.c - -@mv objs/gzwrite.o $@ - - -placebo $(SHAREDLIBV): $(PIC_OBJS) libz.a - $(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) $(LDSHAREDLIBC) $(LDFLAGS) - rm -f $(SHAREDLIB) $(SHAREDLIBM) - ln -s $@ $(SHAREDLIB) - ln -s $@ $(SHAREDLIBM) - -@rmdir objs - -example$(EXE): example.o $(STATICLIB) - $(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS) - -minigzip$(EXE): minigzip.o $(STATICLIB) - $(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS) - -examplesh$(EXE): example.o $(SHAREDLIBV) - $(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV) - -minigzipsh$(EXE): minigzip.o $(SHAREDLIBV) - $(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV) - -example64$(EXE): example64.o $(STATICLIB) - $(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS) - -minigzip64$(EXE): minigzip64.o $(STATICLIB) - $(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS) - -install-libs: $(LIBS) - -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi - -@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi - -@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi - -@if [ ! -d $(DESTDIR)$(man3dir) ]; then mkdir -p $(DESTDIR)$(man3dir); fi - -@if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi - rm -f $(DESTDIR)$(libdir)/$(STATICLIB) - cp $(STATICLIB) $(DESTDIR)$(libdir) - chmod 644 $(DESTDIR)$(libdir)/$(STATICLIB) - -@($(RANLIB) $(DESTDIR)$(libdir)/libz.a || true) >/dev/null 2>&1 - -@if test -n "$(SHAREDLIBV)"; then \ - rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \ - cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir); \ - echo "cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)"; \ - chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \ - echo "chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV)"; \ - rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \ - ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB); \ - ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \ - ($(LDCONFIG) || true) >/dev/null 2>&1; \ - fi - rm -f $(DESTDIR)$(man3dir)/zlib.3 - cp $(SRCDIR)zlib.3 $(DESTDIR)$(man3dir) - chmod 644 $(DESTDIR)$(man3dir)/zlib.3 - rm -f $(DESTDIR)$(pkgconfigdir)/zlib.pc - cp zlib.pc $(DESTDIR)$(pkgconfigdir) - chmod 644 $(DESTDIR)$(pkgconfigdir)/zlib.pc -# The ranlib in install is needed on NeXTSTEP which checks file times -# ldconfig is for Linux - -install: install-libs - -@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi - rm -f $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h - cp $(SRCDIR)zlib.h zconf.h $(DESTDIR)$(includedir) - chmod 644 $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h - -uninstall: - cd $(DESTDIR)$(includedir) && rm -f zlib.h zconf.h - cd $(DESTDIR)$(libdir) && rm -f libz.a; \ - if test -n "$(SHAREDLIBV)" -a -f $(SHAREDLIBV); then \ - rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \ - fi - cd $(DESTDIR)$(man3dir) && rm -f zlib.3 - cd $(DESTDIR)$(pkgconfigdir) && rm -f zlib.pc - -docs: zlib.3.pdf - -zlib.3.pdf: $(SRCDIR)zlib.3 - groff -mandoc -f H -T ps $(SRCDIR)zlib.3 | ps2pdf - $@ - -zconf.h.cmakein: $(SRCDIR)zconf.h.in - -@ TEMPFILE=zconfh_$$; \ - echo "/#define ZCONF_H/ a\\\\\n#cmakedefine Z_PREFIX\\\\\n#cmakedefine Z_HAVE_UNISTD_H\n" >> $$TEMPFILE &&\ - sed -f $$TEMPFILE $(SRCDIR)zconf.h.in > $@ &&\ - touch -r $(SRCDIR)zconf.h.in $@ &&\ - rm $$TEMPFILE - -zconf: $(SRCDIR)zconf.h.in - cp -p $(SRCDIR)zconf.h.in zconf.h - -mostlyclean: clean -clean: - rm -f *.o *.lo *~ \ - example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ - example64$(EXE) minigzip64$(EXE) \ - infcover \ - libz.* foo.gz so_locations \ - _match.s maketree contrib/infback9/*.o - rm -rf objs - rm -f *.gcda *.gcno *.gcov - rm -f contrib/infback9/*.gcda contrib/infback9/*.gcno contrib/infback9/*.gcov - -maintainer-clean: distclean -distclean: clean zconf zconf.h.cmakein docs - rm -f Makefile zlib.pc configure.log - -@rm -f .DS_Store - @if [ -f Makefile.in ]; then \ - printf 'all:\n\t-@echo "Please use ./configure first. Thank you."\n' > Makefile ; \ - printf '\ndistclean:\n\tmake -f Makefile.in distclean\n' >> Makefile ; \ - touch -r $(SRCDIR)Makefile.in Makefile ; fi - @if [ ! -f zconf.h.in ]; then rm -f zconf.h zconf.h.cmakein ; fi - @if [ ! -f zlib.3 ]; then rm -f zlib.3.pdf ; fi - -tags: - etags $(SRCDIR)*.[ch] - -adler32.o zutil.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h -gzclose.o gzlib.o gzread.o gzwrite.o: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h -compress.o example.o minigzip.o uncompr.o: $(SRCDIR)zlib.h zconf.h -crc32.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h -deflate.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h -infback.o inflate.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h -inffast.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h -inftrees.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h -trees.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h - -adler32.lo zutil.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h -gzclose.lo gzlib.lo gzread.lo gzwrite.lo: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h -compress.lo example.lo minigzip.lo uncompr.lo: $(SRCDIR)zlib.h zconf.h -crc32.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h -deflate.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h -infback.lo inflate.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h -inffast.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h -inftrees.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h -trees.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h diff --git a/deps/zlib/OWNERS b/deps/zlib/OWNERS new file mode 100644 index 00000000000000..069bcd8c2a1445 --- /dev/null +++ b/deps/zlib/OWNERS @@ -0,0 +1,7 @@ +agl@chromium.org +cavalcantii@chromium.org +cblume@chromium.org +mtklein@chromium.org +scroggo@chromium.org + +# COMPONENT: Internals diff --git a/deps/zlib/README b/deps/zlib/README deleted file mode 100644 index 51106de4753292..00000000000000 --- a/deps/zlib/README +++ /dev/null @@ -1,115 +0,0 @@ -ZLIB DATA COMPRESSION LIBRARY - -zlib 1.2.11 is a general purpose data compression library. All the code is -thread safe. The data format used by the zlib library is described by RFCs -(Request for Comments) 1950 to 1952 in the files -http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and -rfc1952 (gzip format). - -All functions of the compression library are documented in the file zlib.h -(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example -of the library is given in the file test/example.c which also tests that -the library is working correctly. Another example is given in the file -test/minigzip.c. The compression library itself is composed of all source -files in the root directory. - -To compile all files and run the test program, follow the instructions given at -the top of Makefile.in. In short "./configure; make test", and if that goes -well, "make install" should work for most flavors of Unix. For Windows, use -one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use -make_vms.com. - -Questions about zlib should be sent to , or to Gilles Vollant - for the Windows DLL version. The zlib home page is -http://zlib.net/ . Before reporting a problem, please check this site to -verify that you have the latest version of zlib; otherwise get the latest -version and check whether the problem still exists or not. - -PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. - -Mark Nelson wrote an article about zlib for the Jan. 1997 -issue of Dr. Dobb's Journal; a copy of the article is available at -http://marknelson.us/1997/01/01/zlib-engine/ . - -The changes made in version 1.2.11 are documented in the file ChangeLog. - -Unsupported third party contributions are provided in directory contrib/ . - -zlib is available in Java using the java.util.zip package, documented at -http://java.sun.com/developer/technicalArticles/Programming/compression/ . - -A Perl interface to zlib written by Paul Marquess is available -at CPAN (Comprehensive Perl Archive Network) sites, including -http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . - -A Python interface to zlib written by A.M. Kuchling is -available in Python 1.5 and later versions, see -http://docs.python.org/library/zlib.html . - -zlib is built into tcl: http://wiki.tcl.tk/4610 . - -An experimental package to read and write files in .zip format, written on top -of zlib by Gilles Vollant , is available in the -contrib/minizip directory of zlib. - - -Notes for some targets: - -- For Windows DLL versions, please see win32/DLL_FAQ.txt - -- For 64-bit Irix, deflate.c must be compiled without any optimization. With - -O, one libpng test fails. The test works in 32 bit mode (with the -n32 - compiler flag). The compiler bug has been reported to SGI. - -- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works - when compiled with cc. - -- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is - necessary to get gzprintf working correctly. This is done by configure. - -- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with - other compilers. Use "make test" to check your compiler. - -- gzdopen is not supported on RISCOS or BEOS. - -- For PalmOs, see http://palmzlib.sourceforge.net/ - - -Acknowledgments: - - The deflate format used by zlib was defined by Phil Katz. The deflate and - zlib specifications were written by L. Peter Deutsch. Thanks to all the - people who reported problems and suggested various improvements in zlib; they - are too numerous to cite here. - -Copyright notice: - - (C) 1995-2017 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - -If you use the zlib library in a product, we would appreciate *not* receiving -lengthy legal documents to sign. The sources are provided for free but without -warranty of any kind. The library has been entirely written by Jean-loup -Gailly and Mark Adler; it does not include third-party code. - -If you redistribute modified sources, we would appreciate that you include in -the file ChangeLog history information documenting your changes. Please read -the FAQ for more information on the distribution of modified source versions. diff --git a/deps/zlib/README.chromium b/deps/zlib/README.chromium new file mode 100644 index 00000000000000..3d90f79be2ffc2 --- /dev/null +++ b/deps/zlib/README.chromium @@ -0,0 +1,28 @@ +Name: zlib +Short Name: zlib +URL: http://zlib.net/ +Version: 1.2.11 +Security Critical: yes +License: Custom license +License File: LICENSE +License Android Compatible: yes + +Description: +"A massively spiffy yet delicately unobtrusive compression library." + +zlib is a free, general-purpose, legally unencumbered lossless data-compression +library. zlib implements the "deflate" compression algorithm described by RFC +1951, which combines the LZ77 (Lempel-Ziv) algorithm with Huffman coding. zlib +also implements the zlib (RFC 1950) and gzip (RFC 1952) wrapper formats. + +Local Modifications: + - Only source code from the zlib distribution used to build the zlib and + minizip libraries are present. Many other files have been omitted. Only *.c + and *.h files from the upstream root directory and contrib/minizip were + imported. + - The contents of the google directory are original Chromium-specific + additions. + - Added chromeconf.h + - Plus the changes in 'patches' folder. + - Code in contrib/ other than contrib/minizip was added to match zlib's + contributor layout. diff --git a/deps/zlib/adler32.c b/deps/zlib/adler32.c index d0be4380a39c9c..a42f35fce2a2e0 100644 --- a/deps/zlib/adler32.c +++ b/deps/zlib/adler32.c @@ -59,6 +59,13 @@ local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); # define MOD63(a) a %= BASE #endif +#if defined(ADLER32_SIMD_SSSE3) +#include "adler32_simd.h" +#include "x86.h" +#elif defined(ADLER32_SIMD_NEON) +#include "adler32_simd.h" +#endif + /* ========================================================================= */ uLong ZEXPORT adler32_z(adler, buf, len) uLong adler; @@ -68,6 +75,14 @@ uLong ZEXPORT adler32_z(adler, buf, len) unsigned long sum2; unsigned n; +#if defined(ADLER32_SIMD_SSSE3) + if (x86_cpu_enable_ssse3 && buf && len >= 64) + return adler32_simd_(adler, buf, len); +#elif defined(ADLER32_SIMD_NEON) + if (buf && len >= 64) + return adler32_simd_(adler, buf, len); +#endif + /* split Adler-32 into component sums */ sum2 = (adler >> 16) & 0xffff; adler &= 0xffff; @@ -83,9 +98,24 @@ uLong ZEXPORT adler32_z(adler, buf, len) return adler | (sum2 << 16); } +#if defined(ADLER32_SIMD_SSSE3) + /* + * Use SSSE3 to compute the adler32. Since this routine can be + * freely used, check CPU features here. zlib convention is to + * call adler32(0, NULL, 0), before making calls to adler32(). + * So this is a good early (and infrequent) place to cache CPU + * features for those later, more interesting adler32() calls. + */ + if (buf == Z_NULL) { + if (!len) /* Assume user is calling adler32(0, NULL, 0); */ + x86_check_features(); + return 1L; + } +#else /* initial Adler-32 value (deferred check for len == 1 speed) */ if (buf == Z_NULL) return 1L; +#endif /* in case short lengths are provided, keep it somewhat fast */ if (len < 16) { diff --git a/deps/zlib/adler32_simd.c b/deps/zlib/adler32_simd.c new file mode 100644 index 00000000000000..f8b07297b93840 --- /dev/null +++ b/deps/zlib/adler32_simd.c @@ -0,0 +1,370 @@ +/* adler32_simd.c + * + * Copyright 2017 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + * + * Per http://en.wikipedia.org/wiki/Adler-32 the adler32 A value (aka s1) is + * the sum of N input data bytes D1 ... DN, + * + * A = A0 + D1 + D2 + ... + DN + * + * where A0 is the initial value. + * + * SSE2 _mm_sad_epu8() can be used for byte sums (see http://bit.ly/2wpUOeD, + * for example) and accumulating the byte sums can use SSE shuffle-adds (see + * the "Integer" section of http://bit.ly/2erPT8t for details). Arm NEON has + * similar instructions. + * + * The adler32 B value (aka s2) sums the A values from each step: + * + * B0 + (A0 + D1) + (A0 + D1 + D2) + ... + (A0 + D1 + D2 + ... + DN) or + * + * B0 + N.A0 + N.D1 + (N-1).D2 + (N-2).D3 + ... + (N-(N-1)).DN + * + * B0 being the initial value. For 32 bytes (ideal for garden-variety SIMD): + * + * B = B0 + 32.A0 + [D1 D2 D3 ... D32] x [32 31 30 ... 1]. + * + * Adjacent blocks of 32 input bytes can be iterated with the expressions to + * compute the adler32 s1 s2 of M >> 32 input bytes [1]. + * + * As M grows, the s1 s2 sums grow. If left unchecked, they would eventually + * overflow the precision of their integer representation (bad). However, s1 + * and s2 also need to be computed modulo the adler BASE value (reduced). If + * at most NMAX bytes are processed before a reduce, s1 s2 _cannot_ overflow + * a uint32_t type (the NMAX constraint) [2]. + * + * [1] the iterative equations for s2 contain constant factors; these can be + * hoisted from the n-blocks do loop of the SIMD code. + * + * [2] zlib adler32_z() uses this fact to implement NMAX-block-based updates + * of the adler s1 s2 of uint32_t type (see adler32.c). + */ + +#include "adler32_simd.h" + +/* Definitions from adler32.c: largest prime smaller than 65536 */ +#define BASE 65521U +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ +#define NMAX 5552 + +#if defined(ADLER32_SIMD_SSSE3) +#ifndef __GNUC__ +#define __attribute__() +#endif + +#include + +__attribute__((target("ssse3"))) +uint32_t ZLIB_INTERNAL adler32_simd_( /* SSSE3 */ + uint32_t adler, + const unsigned char *buf, + z_size_t len) +{ + /* + * Split Adler-32 into component sums. + */ + uint32_t s1 = adler & 0xffff; + uint32_t s2 = adler >> 16; + + /* + * Process the data in blocks. + */ + const unsigned BLOCK_SIZE = 1 << 5; + + z_size_t blocks = len / BLOCK_SIZE; + len -= blocks * BLOCK_SIZE; + + while (blocks) + { + unsigned n = NMAX / BLOCK_SIZE; /* The NMAX constraint. */ + if (n > blocks) + n = (unsigned) blocks; + blocks -= n; + + const __m128i tap1 = + _mm_setr_epi8(32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17); + const __m128i tap2 = + _mm_setr_epi8(16,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + const __m128i zero = + _mm_setr_epi8( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + const __m128i ones = + _mm_set_epi16( 1, 1, 1, 1, 1, 1, 1, 1); + + /* + * Process n blocks of data. At most NMAX data bytes can be + * processed before s2 must be reduced modulo BASE. + */ + __m128i v_ps = _mm_set_epi32(0, 0, 0, s1 * n); + __m128i v_s2 = _mm_set_epi32(0, 0, 0, s2); + __m128i v_s1 = _mm_set_epi32(0, 0, 0, 0); + + do { + /* + * Load 32 input bytes. + */ + const __m128i bytes1 = _mm_loadu_si128((__m128i*)(buf)); + const __m128i bytes2 = _mm_loadu_si128((__m128i*)(buf + 16)); + + /* + * Add previous block byte sum to v_ps. + */ + v_ps = _mm_add_epi32(v_ps, v_s1); + + /* + * Horizontally add the bytes for s1, multiply-adds the + * bytes by [ 32, 31, 30, ... ] for s2. + */ + v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes1, zero)); + const __m128i mad1 = _mm_maddubs_epi16(bytes1, tap1); + v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad1, ones)); + + v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes2, zero)); + const __m128i mad2 = _mm_maddubs_epi16(bytes2, tap2); + v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad2, ones)); + + buf += BLOCK_SIZE; + + } while (--n); + + v_s2 = _mm_add_epi32(v_s2, _mm_slli_epi32(v_ps, 5)); + + /* + * Sum epi32 ints v_s1(s2) and accumulate in s1(s2). + */ + +#define S23O1 _MM_SHUFFLE(2,3,0,1) /* A B C D -> B A D C */ +#define S1O32 _MM_SHUFFLE(1,0,3,2) /* A B C D -> C D A B */ + + v_s1 = _mm_add_epi32(v_s1, _mm_shuffle_epi32(v_s1, S23O1)); + v_s1 = _mm_add_epi32(v_s1, _mm_shuffle_epi32(v_s1, S1O32)); + + s1 += _mm_cvtsi128_si32(v_s1); + + v_s2 = _mm_add_epi32(v_s2, _mm_shuffle_epi32(v_s2, S23O1)); + v_s2 = _mm_add_epi32(v_s2, _mm_shuffle_epi32(v_s2, S1O32)); + + s2 = _mm_cvtsi128_si32(v_s2); + +#undef S23O1 +#undef S1O32 + + /* + * Reduce. + */ + s1 %= BASE; + s2 %= BASE; + } + + /* + * Handle leftover data. + */ + if (len) { + if (len >= 16) { + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + len -= 16; + } + + while (len--) { + s2 += (s1 += *buf++); + } + + if (s1 >= BASE) + s1 -= BASE; + s2 %= BASE; + } + + /* + * Return the recombined sums. + */ + return s1 | (s2 << 16); +} + +#elif defined(ADLER32_SIMD_NEON) + +#include + +uint32_t ZLIB_INTERNAL adler32_simd_( /* NEON */ + uint32_t adler, + const unsigned char *buf, + z_size_t len) +{ + /* + * Split Adler-32 into component sums. + */ + uint32_t s1 = adler & 0xffff; + uint32_t s2 = adler >> 16; + + /* + * Serially compute s1 & s2, until the data is 16-byte aligned. + */ + if ((uintptr_t)buf & 15) { + while ((uintptr_t)buf & 15) { + s2 += (s1 += *buf++); + --len; + } + + if (s1 >= BASE) + s1 -= BASE; + s2 %= BASE; + } + + /* + * Process the data in blocks. + */ + const unsigned BLOCK_SIZE = 1 << 5; + + z_size_t blocks = len / BLOCK_SIZE; + len -= blocks * BLOCK_SIZE; + + while (blocks) + { + unsigned n = NMAX / BLOCK_SIZE; /* The NMAX constraint. */ + if (n > blocks) + n = (unsigned) blocks; + blocks -= n; + + /* + * Process n blocks of data. At most NMAX data bytes can be + * processed before s2 must be reduced modulo BASE. + */ + uint32x4_t v_s2 = (uint32x4_t) { 0, 0, 0, s1 * n }; + uint32x4_t v_s1 = (uint32x4_t) { 0, 0, 0, 0 }; + + uint16x8_t v_column_sum_1 = vdupq_n_u16(0); + uint16x8_t v_column_sum_2 = vdupq_n_u16(0); + uint16x8_t v_column_sum_3 = vdupq_n_u16(0); + uint16x8_t v_column_sum_4 = vdupq_n_u16(0); + + do { + /* + * Load 32 input bytes. + */ + const uint8x16_t bytes1 = vld1q_u8((uint8_t*)(buf)); + const uint8x16_t bytes2 = vld1q_u8((uint8_t*)(buf + 16)); + + /* + * Add previous block byte sum to v_s2. + */ + v_s2 = vaddq_u32(v_s2, v_s1); + + /* + * Horizontally add the bytes for s1. + */ + v_s1 = vpadalq_u16(v_s1, vpadalq_u8(vpaddlq_u8(bytes1), bytes2)); + + /* + * Vertically add the bytes for s2. + */ + v_column_sum_1 = vaddw_u8(v_column_sum_1, vget_low_u8 (bytes1)); + v_column_sum_2 = vaddw_u8(v_column_sum_2, vget_high_u8(bytes1)); + v_column_sum_3 = vaddw_u8(v_column_sum_3, vget_low_u8 (bytes2)); + v_column_sum_4 = vaddw_u8(v_column_sum_4, vget_high_u8(bytes2)); + + buf += BLOCK_SIZE; + + } while (--n); + + v_s2 = vshlq_n_u32(v_s2, 5); + + /* + * Multiply-add bytes by [ 32, 31, 30, ... ] for s2. + */ + v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_1), + (uint16x4_t) { 32, 31, 30, 29 }); + v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_1), + (uint16x4_t) { 28, 27, 26, 25 }); + v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_2), + (uint16x4_t) { 24, 23, 22, 21 }); + v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_2), + (uint16x4_t) { 20, 19, 18, 17 }); + v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_3), + (uint16x4_t) { 16, 15, 14, 13 }); + v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_3), + (uint16x4_t) { 12, 11, 10, 9 }); + v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_4), + (uint16x4_t) { 8, 7, 6, 5 }); + v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_4), + (uint16x4_t) { 4, 3, 2, 1 }); + + /* + * Sum epi32 ints v_s1(s2) and accumulate in s1(s2). + */ + uint32x2_t sum1 = vpadd_u32(vget_low_u32(v_s1), vget_high_u32(v_s1)); + uint32x2_t sum2 = vpadd_u32(vget_low_u32(v_s2), vget_high_u32(v_s2)); + uint32x2_t s1s2 = vpadd_u32(sum1, sum2); + + s1 += vget_lane_u32(s1s2, 0); + s2 += vget_lane_u32(s1s2, 1); + + /* + * Reduce. + */ + s1 %= BASE; + s2 %= BASE; + } + + /* + * Handle leftover data. + */ + if (len) { + if (len >= 16) { + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + len -= 16; + } + + while (len--) { + s2 += (s1 += *buf++); + } + + if (s1 >= BASE) + s1 -= BASE; + s2 %= BASE; + } + + /* + * Return the recombined sums. + */ + return s1 | (s2 << 16); +} + +#endif /* ADLER32_SIMD_SSSE3 */ diff --git a/deps/zlib/adler32_simd.h b/deps/zlib/adler32_simd.h new file mode 100644 index 00000000000000..52bb14d16751c8 --- /dev/null +++ b/deps/zlib/adler32_simd.h @@ -0,0 +1,16 @@ +/* adler32_simd.h + * + * Copyright 2017 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ + +#include + +#include "zconf.h" +#include "zutil.h" + +uint32_t ZLIB_INTERNAL adler32_simd_( + uint32_t adler, + const unsigned char *buf, + z_size_t len); diff --git a/deps/zlib/amiga/Makefile.pup b/deps/zlib/amiga/Makefile.pup deleted file mode 100644 index 8940c120fbb970..00000000000000 --- a/deps/zlib/amiga/Makefile.pup +++ /dev/null @@ -1,69 +0,0 @@ -# Amiga powerUP (TM) Makefile -# makefile for libpng and SAS C V6.58/7.00 PPC compiler -# Copyright (C) 1998 by Andreas R. Kleinert - -LIBNAME = libzip.a - -CC = scppc -CFLAGS = NOSTKCHK NOSINT OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL \ - OPTLOOP OPTRDEP=8 OPTDEP=8 OPTCOMP=8 NOVER -AR = ppc-amigaos-ar cr -RANLIB = ppc-amigaos-ranlib -LD = ppc-amigaos-ld -r -LDFLAGS = -o -LDLIBS = LIB:scppc.a LIB:end.o -RM = delete quiet - -OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ - uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o - -TEST_OBJS = example.o minigzip.o - -all: example minigzip - -check: test -test: all - example - echo hello world | minigzip | minigzip -d - -$(LIBNAME): $(OBJS) - $(AR) $@ $(OBJS) - -$(RANLIB) $@ - -example: example.o $(LIBNAME) - $(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS) - -minigzip: minigzip.o $(LIBNAME) - $(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS) - -mostlyclean: clean -clean: - $(RM) *.o example minigzip $(LIBNAME) foo.gz - -zip: - zip -ul9 zlib README ChangeLog Makefile Make????.??? Makefile.?? \ - descrip.mms *.[ch] - -tgz: - cd ..; tar cfz zlib/zlib.tgz zlib/README zlib/ChangeLog zlib/Makefile \ - zlib/Make????.??? zlib/Makefile.?? zlib/descrip.mms zlib/*.[ch] - -# DO NOT DELETE THIS LINE -- make depend depends on it. - -adler32.o: zlib.h zconf.h -compress.o: zlib.h zconf.h -crc32.o: crc32.h zlib.h zconf.h -deflate.o: deflate.h zutil.h zlib.h zconf.h -example.o: zlib.h zconf.h -gzclose.o: zlib.h zconf.h gzguts.h -gzlib.o: zlib.h zconf.h gzguts.h -gzread.o: zlib.h zconf.h gzguts.h -gzwrite.o: zlib.h zconf.h gzguts.h -inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -inftrees.o: zutil.h zlib.h zconf.h inftrees.h -minigzip.o: zlib.h zconf.h -trees.o: deflate.h zutil.h zlib.h zconf.h trees.h -uncompr.o: zlib.h zconf.h -zutil.o: zutil.h zlib.h zconf.h diff --git a/deps/zlib/amiga/Makefile.sas b/deps/zlib/amiga/Makefile.sas deleted file mode 100644 index 749e2915271d25..00000000000000 --- a/deps/zlib/amiga/Makefile.sas +++ /dev/null @@ -1,68 +0,0 @@ -# SMakefile for zlib -# Modified from the standard UNIX Makefile Copyright Jean-loup Gailly -# Osma Ahvenlampi -# Amiga, SAS/C 6.56 & Smake - -CC=sc -CFLAGS=OPT -#CFLAGS=OPT CPU=68030 -#CFLAGS=DEBUG=LINE -LDFLAGS=LIB z.lib - -SCOPTIONS=OPTSCHED OPTINLINE OPTALIAS OPTTIME OPTINLOCAL STRMERGE \ - NOICONS PARMS=BOTH NOSTACKCHECK UTILLIB NOVERSION ERRORREXX \ - DEF=POSTINC - -OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ - uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o - -TEST_OBJS = example.o minigzip.o - -all: SCOPTIONS example minigzip - -check: test -test: all - example - echo hello world | minigzip | minigzip -d - -install: z.lib - copy clone zlib.h zconf.h INCLUDE: - copy clone z.lib LIB: - -z.lib: $(OBJS) - oml z.lib r $(OBJS) - -example: example.o z.lib - $(CC) $(CFLAGS) LINK TO $@ example.o $(LDFLAGS) - -minigzip: minigzip.o z.lib - $(CC) $(CFLAGS) LINK TO $@ minigzip.o $(LDFLAGS) - -mostlyclean: clean -clean: - -delete force quiet example minigzip *.o z.lib foo.gz *.lnk SCOPTIONS - -SCOPTIONS: Makefile.sas - copy to $@ + +int ZLIB_INTERNAL arm_cpu_enable_crc32 = 0; +int ZLIB_INTERNAL arm_cpu_enable_pmull = 0; + +#if defined(ARMV8_OS_ANDROID) || defined(ARMV8_OS_LINUX) || defined(ARMV8_OS_FUCHSIA) +#include +#endif + +#if defined(ARMV8_OS_ANDROID) +#include +#elif defined(ARMV8_OS_LINUX) +#include +#include +#elif defined(ARMV8_OS_FUCHSIA) +#include +#include +#include +#elif defined(ARMV8_OS_WINDOWS) +#include +#else +#error arm_features.c ARM feature detection in not defined for your platform +#endif + +static void _arm_check_features(void); + +#if defined(ARMV8_OS_ANDROID) || defined(ARMV8_OS_LINUX) || defined(ARMV8_OS_FUCHSIA) +static pthread_once_t cpu_check_inited_once = PTHREAD_ONCE_INIT; +void ZLIB_INTERNAL arm_check_features(void) +{ + pthread_once(&cpu_check_inited_once, _arm_check_features); +} +#elif defined(ARMV8_OS_WINDOWS) +static INIT_ONCE cpu_check_inited_once = INIT_ONCE_STATIC_INIT; +static BOOL CALLBACK _arm_check_features_forwarder(PINIT_ONCE once, PVOID param, PVOID* context) +{ + _arm_check_features(); + return TRUE; +} +void ZLIB_INTERNAL arm_check_features(void) +{ + InitOnceExecuteOnce(&cpu_check_inited_once, _arm_check_features_forwarder, + NULL, NULL); +} +#endif + +/* + * See http://bit.ly/2CcoEsr for run-time detection of ARM features and also + * crbug.com/931275 for android_getCpuFeatures() use in the Android sandbox. + */ +static void _arm_check_features(void) +{ +#if defined(ARMV8_OS_ANDROID) && defined(__aarch64__) + uint64_t features = android_getCpuFeatures(); + arm_cpu_enable_crc32 = !!(features & ANDROID_CPU_ARM64_FEATURE_CRC32); + arm_cpu_enable_pmull = !!(features & ANDROID_CPU_ARM64_FEATURE_PMULL); +#elif defined(ARMV8_OS_ANDROID) /* aarch32 */ + uint64_t features = android_getCpuFeatures(); + arm_cpu_enable_crc32 = !!(features & ANDROID_CPU_ARM_FEATURE_CRC32); + arm_cpu_enable_pmull = !!(features & ANDROID_CPU_ARM_FEATURE_PMULL); +#elif defined(ARMV8_OS_LINUX) && defined(__aarch64__) + unsigned long features = getauxval(AT_HWCAP); + arm_cpu_enable_crc32 = !!(features & HWCAP_CRC32); + arm_cpu_enable_pmull = !!(features & HWCAP_PMULL); +#elif defined(ARMV8_OS_LINUX) && (defined(__ARM_NEON) || defined(__ARM_NEON__)) + /* Query HWCAP2 for ARMV8-A SoCs running in aarch32 mode */ + unsigned long features = getauxval(AT_HWCAP2); + arm_cpu_enable_crc32 = !!(features & HWCAP2_CRC32); + arm_cpu_enable_pmull = !!(features & HWCAP2_PMULL); +#elif defined(ARMV8_OS_FUCHSIA) + uint32_t features; + zx_status_t rc = zx_system_get_features(ZX_FEATURE_KIND_CPU, &features); + if (rc != ZX_OK || (features & ZX_ARM64_FEATURE_ISA_ASIMD) == 0) + return; /* Report nothing if ASIMD(NEON) is missing */ + arm_cpu_enable_crc32 = !!(features & ZX_ARM64_FEATURE_ISA_CRC32); + arm_cpu_enable_pmull = !!(features & ZX_ARM64_FEATURE_ISA_PMULL); +#elif defined(ARMV8_OS_WINDOWS) + arm_cpu_enable_crc32 = IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE); + arm_cpu_enable_pmull = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE); +#endif +} diff --git a/deps/zlib/arm_features.h b/deps/zlib/arm_features.h new file mode 100644 index 00000000000000..09fec259b1c924 --- /dev/null +++ b/deps/zlib/arm_features.h @@ -0,0 +1,13 @@ +/* arm_features.h -- ARM processor features detection. + * + * Copyright 2018 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ + +#include "zlib.h" + +extern int arm_cpu_enable_crc32; +extern int arm_cpu_enable_pmull; + +void arm_check_features(void); diff --git a/deps/zlib/chromeconf.h b/deps/zlib/chromeconf.h new file mode 100644 index 00000000000000..666093d696a583 --- /dev/null +++ b/deps/zlib/chromeconf.h @@ -0,0 +1,195 @@ +/* Copyright 2017 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +#ifndef THIRD_PARTY_ZLIB_CHROMECONF_H_ +#define THIRD_PARTY_ZLIB_CHROMECONF_H_ + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) +#if defined(ZLIB_IMPLEMENTATION) +#define ZEXTERN __declspec(dllexport) +#else +#define ZEXTERN __declspec(dllimport) +#endif +#elif defined(ZLIB_IMPLEMENTATION) +#define ZEXTERN __attribute__((visibility("default"))) +#endif +#endif + +/* Rename all zlib names with a Cr_z_ prefix. This is based on the Z_PREFIX + * option from zconf.h, but with a custom prefix. Where zconf.h would rename + * both a macro and its underscore-suffixed internal implementation (such as + * deflateInit2 and deflateInit2_), only the implementation is renamed here. + * The Byte type is also omitted. + * + * To generate this list, run + * sed -rn -e 's/^# *define +([^ ]+) +(z_[^ ]+)$/#define \1 Cr_\2/p' zconf.h + * (use -E instead of -r on macOS). + * + * gzread is also addressed by modifications in gzread.c and zlib.h. */ + +#define Z_CR_PREFIX_SET + +#define _dist_code Cr_z__dist_code +#define _length_code Cr_z__length_code +#define _tr_align Cr_z__tr_align +#define _tr_flush_bits Cr_z__tr_flush_bits +#define _tr_flush_block Cr_z__tr_flush_block +#define _tr_init Cr_z__tr_init +#define _tr_stored_block Cr_z__tr_stored_block +#define _tr_tally Cr_z__tr_tally +#define adler32 Cr_z_adler32 +#define adler32_combine Cr_z_adler32_combine +#define adler32_combine64 Cr_z_adler32_combine64 +#define adler32_z Cr_z_adler32_z +#define compress Cr_z_compress +#define compress2 Cr_z_compress2 +#define compressBound Cr_z_compressBound +#define crc32 Cr_z_crc32 +#define crc32_combine Cr_z_crc32_combine +#define crc32_combine64 Cr_z_crc32_combine64 +#define crc32_z Cr_z_crc32_z +#define deflate Cr_z_deflate +#define deflateBound Cr_z_deflateBound +#define deflateCopy Cr_z_deflateCopy +#define deflateEnd Cr_z_deflateEnd +#define deflateGetDictionary Cr_z_deflateGetDictionary +/* #undef deflateInit */ +/* #undef deflateInit2 */ +#define deflateInit2_ Cr_z_deflateInit2_ +#define deflateInit_ Cr_z_deflateInit_ +#define deflateParams Cr_z_deflateParams +#define deflatePending Cr_z_deflatePending +#define deflatePrime Cr_z_deflatePrime +#define deflateReset Cr_z_deflateReset +#define deflateResetKeep Cr_z_deflateResetKeep +#define deflateSetDictionary Cr_z_deflateSetDictionary +#define deflateSetHeader Cr_z_deflateSetHeader +#define deflateTune Cr_z_deflateTune +#define deflate_copyright Cr_z_deflate_copyright +#define get_crc_table Cr_z_get_crc_table +#define gz_error Cr_z_gz_error +#define gz_intmax Cr_z_gz_intmax +#define gz_strwinerror Cr_z_gz_strwinerror +#define gzbuffer Cr_z_gzbuffer +#define gzclearerr Cr_z_gzclearerr +#define gzclose Cr_z_gzclose +#define gzclose_r Cr_z_gzclose_r +#define gzclose_w Cr_z_gzclose_w +#define gzdirect Cr_z_gzdirect +#define gzdopen Cr_z_gzdopen +#define gzeof Cr_z_gzeof +#define gzerror Cr_z_gzerror +#define gzflush Cr_z_gzflush +#define gzfread Cr_z_gzfread +#define gzfwrite Cr_z_gzfwrite +#define gzgetc Cr_z_gzgetc +#define gzgetc_ Cr_z_gzgetc_ +#define gzgets Cr_z_gzgets +#define gzoffset Cr_z_gzoffset +#define gzoffset64 Cr_z_gzoffset64 +#define gzopen Cr_z_gzopen +#define gzopen64 Cr_z_gzopen64 +#define gzopen_w Cr_z_gzopen_w +#define gzprintf Cr_z_gzprintf +#define gzputc Cr_z_gzputc +#define gzputs Cr_z_gzputs +#define gzread Cr_z_gzread +#define gzrewind Cr_z_gzrewind +#define gzseek Cr_z_gzseek +#define gzseek64 Cr_z_gzseek64 +#define gzsetparams Cr_z_gzsetparams +#define gztell Cr_z_gztell +#define gztell64 Cr_z_gztell64 +#define gzungetc Cr_z_gzungetc +#define gzvprintf Cr_z_gzvprintf +#define gzwrite Cr_z_gzwrite +#define inflate Cr_z_inflate +#define inflateBack Cr_z_inflateBack +#define inflateBackEnd Cr_z_inflateBackEnd +/* #undef inflateBackInit */ +#define inflateBackInit_ Cr_z_inflateBackInit_ +#define inflateCodesUsed Cr_z_inflateCodesUsed +#define inflateCopy Cr_z_inflateCopy +#define inflateEnd Cr_z_inflateEnd +#define inflateGetDictionary Cr_z_inflateGetDictionary +#define inflateGetHeader Cr_z_inflateGetHeader +/* #undef inflateInit */ +/* #undef inflateInit2 */ +#define inflateInit2_ Cr_z_inflateInit2_ +#define inflateInit_ Cr_z_inflateInit_ +#define inflateMark Cr_z_inflateMark +#define inflatePrime Cr_z_inflatePrime +#define inflateReset Cr_z_inflateReset +#define inflateReset2 Cr_z_inflateReset2 +#define inflateResetKeep Cr_z_inflateResetKeep +#define inflateSetDictionary Cr_z_inflateSetDictionary +#define inflateSync Cr_z_inflateSync +#define inflateSyncPoint Cr_z_inflateSyncPoint +#define inflateUndermine Cr_z_inflateUndermine +#define inflateValidate Cr_z_inflateValidate +#define inflate_copyright Cr_z_inflate_copyright +#define inflate_fast Cr_z_inflate_fast +#define inflate_table Cr_z_inflate_table +#define uncompress Cr_z_uncompress +#define uncompress2 Cr_z_uncompress2 +#define zError Cr_z_zError +#define zcalloc Cr_z_zcalloc +#define zcfree Cr_z_zcfree +#define zlibCompileFlags Cr_z_zlibCompileFlags +#define zlibVersion Cr_z_zlibVersion +/* #undef Byte */ +#define Bytef Cr_z_Bytef +#define alloc_func Cr_z_alloc_func +#define charf Cr_z_charf +#define free_func Cr_z_free_func +#define gzFile Cr_z_gzFile +#define gz_header Cr_z_gz_header +#define gz_headerp Cr_z_gz_headerp +#define in_func Cr_z_in_func +#define intf Cr_z_intf +#define out_func Cr_z_out_func +#define uInt Cr_z_uInt +#define uIntf Cr_z_uIntf +#define uLong Cr_z_uLong +#define uLongf Cr_z_uLongf +#define voidp Cr_z_voidp +#define voidpc Cr_z_voidpc +#define voidpf Cr_z_voidpf +#define gz_header_s Cr_z_gz_header_s +/* #undef internal_state */ +/* #undef z_off64_t */ + +/* An exported symbol that isn't handled by Z_PREFIX in zconf.h */ +#define z_errmsg Cr_z_z_errmsg + +/* Symbols added in simd.patch */ +#define copy_with_crc Cr_z_copy_with_crc +#define crc_finalize Cr_z_crc_finalize +#define crc_fold_512to32 Cr_z_crc_fold_512to32 +#define crc_fold_copy Cr_z_crc_fold_copy +#define crc_fold_init Cr_z_crc_fold_init +#define crc_reset Cr_z_crc_reset +#define fill_window_sse Cr_z_fill_window_sse +#define deflate_read_buf Cr_z_deflate_read_buf +#define x86_check_features Cr_z_x86_check_features +#define x86_cpu_enable_simd Cr_z_x86_cpu_enable_simd + +/* Symbols added by adler_simd.c */ +#define adler32_simd_ Cr_z_adler32_simd_ +#define x86_cpu_enable_ssse3 Cr_z_x86_cpu_enable_ssse3 + +/* Symbols added by contrib/optimizations/inffast_chunk */ +#define inflate_fast_chunk_ Cr_z_inflate_fast_chunk_ + +/* Symbols added by crc32_simd.c */ +#define crc32_sse42_simd_ Cr_z_crc32_sse42_simd_ + +/* Symbols added by armv8_crc32 */ +#define arm_cpu_enable_crc32 Cr_z_arm_cpu_enable_crc32 +#define arm_cpu_enable_pmull Cr_z_arm_cpu_enable_pmull +#define arm_check_features Cr_z_arm_check_features +#define armv8_crc32_little Cr_z_armv8_crc32_little + +#endif /* THIRD_PARTY_ZLIB_CHROMECONF_H_ */ diff --git a/deps/zlib/compress.c b/deps/zlib/compress.c index e2db404abf888b..6e8517335da018 100644 --- a/deps/zlib/compress.c +++ b/deps/zlib/compress.c @@ -81,6 +81,16 @@ int ZEXPORT compress (dest, destLen, source, sourceLen) uLong ZEXPORT compressBound (sourceLen) uLong sourceLen; { - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + - (sourceLen >> 25) + 13; + sourceLen = sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13; + /* FIXME(cavalcantii): usage of CRC32 Castagnoli as a hash function + * for the hash table of symbols used for compression has a side effect + * where for compression level [4, 5] it will increase the output buffer size + * by 0.1% (i.e. less than 1%) for a high entropy input (i.e. random data). + * To avoid a scenario where client code would fail, for safety we increase + * the expected output size by 0.8% (i.e. 8x more than the worst scenario). + * See: http://crbug.com/990489 + */ + sourceLen += sourceLen >> 7; // Equivalent to 1.0078125 + return sourceLen; } diff --git a/deps/zlib/configure b/deps/zlib/configure deleted file mode 100755 index e974d1fd799fbc..00000000000000 --- a/deps/zlib/configure +++ /dev/null @@ -1,921 +0,0 @@ -#!/bin/sh -# configure script for zlib. -# -# Normally configure builds both a static and a shared library. -# If you want to build just a static library, use: ./configure --static -# -# To impose specific compiler or flags or install directory, use for example: -# prefix=$HOME CC=cc CFLAGS="-O4" ./configure -# or for csh/tcsh users: -# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure) - -# Incorrect settings of CC or CFLAGS may prevent creating a shared library. -# If you have problems, try without defining CC and CFLAGS before reporting -# an error. - -# start off configure.log -echo -------------------- >> configure.log -echo $0 $* >> configure.log -date >> configure.log - -# get source directory -SRCDIR=`dirname $0` -if test $SRCDIR = "."; then - ZINC="" - ZINCOUT="-I." - SRCDIR="" -else - ZINC='-include zconf.h' - ZINCOUT='-I. -I$(SRCDIR)' - SRCDIR="$SRCDIR/" -fi - -# set command prefix for cross-compilation -if [ -n "${CHOST}" ]; then - uname="`echo "${CHOST}" | sed -e 's/^[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)-.*$/\1/'`" - CROSS_PREFIX="${CHOST}-" -fi - -# destination name for static library -STATICLIB=libz.a - -# extract zlib version numbers from zlib.h -VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}zlib.h` -VER3=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < ${SRCDIR}zlib.h` -VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h` -VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h` - -# establish commands for library building -if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then - AR=${AR-"${CROSS_PREFIX}ar"} - test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log -else - AR=${AR-"ar"} - test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log -fi -ARFLAGS=${ARFLAGS-"rc"} -if "${CROSS_PREFIX}ranlib" --version >/dev/null 2>/dev/null || test $? -lt 126; then - RANLIB=${RANLIB-"${CROSS_PREFIX}ranlib"} - test -n "${CROSS_PREFIX}" && echo Using ${RANLIB} | tee -a configure.log -else - RANLIB=${RANLIB-"ranlib"} -fi -if "${CROSS_PREFIX}nm" --version >/dev/null 2>/dev/null || test $? -lt 126; then - NM=${NM-"${CROSS_PREFIX}nm"} - test -n "${CROSS_PREFIX}" && echo Using ${NM} | tee -a configure.log -else - NM=${NM-"nm"} -fi - -# set defaults before processing command line options -LDCONFIG=${LDCONFIG-"ldconfig"} -LDSHAREDLIBC="${LDSHAREDLIBC--lc}" -ARCHS= -prefix=${prefix-/usr/local} -exec_prefix=${exec_prefix-'${prefix}'} -libdir=${libdir-'${exec_prefix}/lib'} -sharedlibdir=${sharedlibdir-'${libdir}'} -includedir=${includedir-'${prefix}/include'} -mandir=${mandir-'${prefix}/share/man'} -shared_ext='.so' -shared=1 -solo=0 -cover=0 -zprefix=0 -zconst=0 -build64=0 -gcc=0 -warn=0 -debug=0 -old_cc="$CC" -old_cflags="$CFLAGS" -OBJC='$(OBJZ) $(OBJG)' -PIC_OBJC='$(PIC_OBJZ) $(PIC_OBJG)' - -# leave this script, optionally in a bad way -leave() -{ - if test "$*" != "0"; then - echo "** $0 aborting." | tee -a configure.log - fi - rm -f $test.[co] $test $test$shared_ext $test.gcno ./--version - echo -------------------- >> configure.log - echo >> configure.log - echo >> configure.log - exit $1 -} - -# process command line options -while test $# -ge 1 -do -case "$1" in - -h* | --help) - echo 'usage:' | tee -a configure.log - echo ' configure [--const] [--zprefix] [--prefix=PREFIX] [--eprefix=EXPREFIX]' | tee -a configure.log - echo ' [--static] [--64] [--libdir=LIBDIR] [--sharedlibdir=LIBDIR]' | tee -a configure.log - echo ' [--includedir=INCLUDEDIR] [--archs="-arch i386 -arch x86_64"]' | tee -a configure.log - exit 0 ;; - -p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;; - -e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;; - -l*=* | --libdir=*) libdir=`echo $1 | sed 's/.*=//'`; shift ;; - --sharedlibdir=*) sharedlibdir=`echo $1 | sed 's/.*=//'`; shift ;; - -i*=* | --includedir=*) includedir=`echo $1 | sed 's/.*=//'`;shift ;; - -u*=* | --uname=*) uname=`echo $1 | sed 's/.*=//'`;shift ;; - -p* | --prefix) prefix="$2"; shift; shift ;; - -e* | --eprefix) exec_prefix="$2"; shift; shift ;; - -l* | --libdir) libdir="$2"; shift; shift ;; - -i* | --includedir) includedir="$2"; shift; shift ;; - -s* | --shared | --enable-shared) shared=1; shift ;; - -t | --static) shared=0; shift ;; - --solo) solo=1; shift ;; - --cover) cover=1; shift ;; - -z* | --zprefix) zprefix=1; shift ;; - -6* | --64) build64=1; shift ;; - -a*=* | --archs=*) ARCHS=`echo $1 | sed 's/.*=//'`; shift ;; - --sysconfdir=*) echo "ignored option: --sysconfdir" | tee -a configure.log; shift ;; - --localstatedir=*) echo "ignored option: --localstatedir" | tee -a configure.log; shift ;; - -c* | --const) zconst=1; shift ;; - -w* | --warn) warn=1; shift ;; - -d* | --debug) debug=1; shift ;; - *) - echo "unknown option: $1" | tee -a configure.log - echo "$0 --help for help" | tee -a configure.log - leave 1;; - esac -done - -# temporary file name -test=ztest$$ - -# put arguments in log, also put test file in log if used in arguments -show() -{ - case "$*" in - *$test.c*) - echo === $test.c === >> configure.log - cat $test.c >> configure.log - echo === >> configure.log;; - esac - echo $* >> configure.log -} - -# check for gcc vs. cc and set compile and link flags based on the system identified by uname -cat > $test.c <&1` in - *gcc*) gcc=1 ;; - *clang*) gcc=1 ;; -esac - -show $cc -c $test.c -if test "$gcc" -eq 1 && ($cc -c $test.c) >> configure.log 2>&1; then - echo ... using gcc >> configure.log - CC="$cc" - CFLAGS="${CFLAGS--O3}" - SFLAGS="${CFLAGS--O3} -fPIC" - if test "$ARCHS"; then - CFLAGS="${CFLAGS} ${ARCHS}" - LDFLAGS="${LDFLAGS} ${ARCHS}" - fi - if test $build64 -eq 1; then - CFLAGS="${CFLAGS} -m64" - SFLAGS="${SFLAGS} -m64" - fi - if test "$warn" -eq 1; then - if test "$zconst" -eq 1; then - CFLAGS="${CFLAGS} -Wall -Wextra -Wcast-qual -pedantic -DZLIB_CONST" - else - CFLAGS="${CFLAGS} -Wall -Wextra -pedantic" - fi - fi - if test $debug -eq 1; then - CFLAGS="${CFLAGS} -DZLIB_DEBUG" - SFLAGS="${SFLAGS} -DZLIB_DEBUG" - fi - if test -z "$uname"; then - uname=`(uname -s || echo unknown) 2>/dev/null` - fi - case "$uname" in - Linux* | linux* | GNU | GNU/* | solaris*) - LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"} ;; - *BSD | *bsd* | DragonFly) - LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"} - LDCONFIG="ldconfig -m" ;; - CYGWIN* | Cygwin* | cygwin* | OS/2*) - EXE='.exe' ;; - MINGW* | mingw*) -# temporary bypass - rm -f $test.[co] $test $test$shared_ext - echo "Please use win32/Makefile.gcc instead." | tee -a configure.log - leave 1 - LDSHARED=${LDSHARED-"$cc -shared"} - LDSHAREDLIBC="" - EXE='.exe' ;; - QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4 - # (alain.bonnefoy@icbt.com) - LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;; - HP-UX*) - LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"} - case `(uname -m || echo unknown) 2>/dev/null` in - ia64) - shared_ext='.so' - SHAREDLIB='libz.so' ;; - *) - shared_ext='.sl' - SHAREDLIB='libz.sl' ;; - esac ;; - Darwin* | darwin*) - shared_ext='.dylib' - SHAREDLIB=libz$shared_ext - SHAREDLIBV=libz.$VER$shared_ext - SHAREDLIBM=libz.$VER1$shared_ext - LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"} - if libtool -V 2>&1 | grep Apple > /dev/null; then - AR="libtool" - else - AR="/usr/bin/libtool" - fi - ARFLAGS="-o" ;; - *) LDSHARED=${LDSHARED-"$cc -shared"} ;; - esac -else - # find system name and corresponding cc options - CC=${CC-cc} - gcc=0 - echo ... using $CC >> configure.log - if test -z "$uname"; then - uname=`(uname -sr || echo unknown) 2>/dev/null` - fi - case "$uname" in - HP-UX*) SFLAGS=${CFLAGS-"-O +z"} - CFLAGS=${CFLAGS-"-O"} -# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"} - LDSHARED=${LDSHARED-"ld -b"} - case `(uname -m || echo unknown) 2>/dev/null` in - ia64) - shared_ext='.so' - SHAREDLIB='libz.so' ;; - *) - shared_ext='.sl' - SHAREDLIB='libz.sl' ;; - esac ;; - IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."} - CFLAGS=${CFLAGS-"-ansi -O2"} - LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;; - OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"} - CFLAGS=${CFLAGS-"-O -std1"} - LDFLAGS="${LDFLAGS} -Wl,-rpath,." - LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"} ;; - OSF1*) SFLAGS=${CFLAGS-"-O -std1"} - CFLAGS=${CFLAGS-"-O -std1"} - LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;; - QNX*) SFLAGS=${CFLAGS-"-4 -O"} - CFLAGS=${CFLAGS-"-4 -O"} - LDSHARED=${LDSHARED-"cc"} - RANLIB=${RANLIB-"true"} - AR="cc" - ARFLAGS="-A" ;; - SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "} - CFLAGS=${CFLAGS-"-O3"} - LDSHARED=${LDSHARED-"cc -dy -KPIC -G"} ;; - SunOS\ 5* | solaris*) - LDSHARED=${LDSHARED-"cc -G -h libz$shared_ext.$VER1"} - SFLAGS=${CFLAGS-"-fast -KPIC"} - CFLAGS=${CFLAGS-"-fast"} - if test $build64 -eq 1; then - # old versions of SunPRO/Workshop/Studio don't support -m64, - # but newer ones do. Check for it. - flag64=`$CC -flags | egrep -- '^-m64'` - if test x"$flag64" != x"" ; then - CFLAGS="${CFLAGS} -m64" - SFLAGS="${SFLAGS} -m64" - else - case `(uname -m || echo unknown) 2>/dev/null` in - i86*) - SFLAGS="$SFLAGS -xarch=amd64" - CFLAGS="$CFLAGS -xarch=amd64" ;; - *) - SFLAGS="$SFLAGS -xarch=v9" - CFLAGS="$CFLAGS -xarch=v9" ;; - esac - fi - fi - if test -n "$ZINC"; then - ZINC='-I- -I. -I$(SRCDIR)' - fi - ;; - SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"} - CFLAGS=${CFLAGS-"-O2"} - LDSHARED=${LDSHARED-"ld"} ;; - SunStudio\ 9*) SFLAGS=${CFLAGS-"-fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"} - CFLAGS=${CFLAGS-"-fast -xtarget=ultra3 -xarch=v9b"} - LDSHARED=${LDSHARED-"cc -xarch=v9b"} ;; - UNIX_System_V\ 4.2.0) - SFLAGS=${CFLAGS-"-KPIC -O"} - CFLAGS=${CFLAGS-"-O"} - LDSHARED=${LDSHARED-"cc -G"} ;; - UNIX_SV\ 4.2MP) - SFLAGS=${CFLAGS-"-Kconform_pic -O"} - CFLAGS=${CFLAGS-"-O"} - LDSHARED=${LDSHARED-"cc -G"} ;; - OpenUNIX\ 5) - SFLAGS=${CFLAGS-"-KPIC -O"} - CFLAGS=${CFLAGS-"-O"} - LDSHARED=${LDSHARED-"cc -G"} ;; - AIX*) # Courtesy of dbakker@arrayasolutions.com - SFLAGS=${CFLAGS-"-O -qmaxmem=8192"} - CFLAGS=${CFLAGS-"-O -qmaxmem=8192"} - LDSHARED=${LDSHARED-"xlc -G"} ;; - # send working options for other systems to zlib@gzip.org - *) SFLAGS=${CFLAGS-"-O"} - CFLAGS=${CFLAGS-"-O"} - LDSHARED=${LDSHARED-"cc -shared"} ;; - esac -fi - -# destination names for shared library if not defined above -SHAREDLIB=${SHAREDLIB-"libz$shared_ext"} -SHAREDLIBV=${SHAREDLIBV-"libz$shared_ext.$VER"} -SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"} - -echo >> configure.log - -# define functions for testing compiler and library characteristics and logging the results - -cat > $test.c </dev/null; then - try() - { - show $* - test "`( $* ) 2>&1 | tee -a configure.log`" = "" - } - echo - using any output from compiler to indicate an error >> configure.log -else - try() - { - show $* - ( $* ) >> configure.log 2>&1 - ret=$? - if test $ret -ne 0; then - echo "(exit code "$ret")" >> configure.log - fi - return $ret - } -fi - -tryboth() -{ - show $* - got=`( $* ) 2>&1` - ret=$? - printf %s "$got" >> configure.log - if test $ret -ne 0; then - return $ret - fi - test "$got" = "" -} - -cat > $test.c << EOF -int foo() { return 0; } -EOF -echo "Checking for obsessive-compulsive compiler options..." >> configure.log -if try $CC -c $CFLAGS $test.c; then - : -else - echo "Compiler error reporting is too harsh for $0 (perhaps remove -Werror)." | tee -a configure.log - leave 1 -fi - -echo >> configure.log - -# see if shared library build supported -cat > $test.c <> configure.log - show "$NM $test.o | grep _hello" - if test "`$NM $test.o | grep _hello | tee -a configure.log`" = ""; then - CPP="$CPP -DNO_UNDERLINE" - echo Checking for underline in external names... No. | tee -a configure.log - else - echo Checking for underline in external names... Yes. | tee -a configure.log - fi ;; -esac - -echo >> configure.log - -# check for size_t -cat > $test.c < -#include -size_t dummy = 0; -EOF -if try $CC -c $CFLAGS $test.c; then - echo "Checking for size_t... Yes." | tee -a configure.log - need_sizet=0 -else - echo "Checking for size_t... No." | tee -a configure.log - need_sizet=1 -fi - -echo >> configure.log - -# find the size_t integer type, if needed -if test $need_sizet -eq 1; then - cat > $test.c < $test.c < -int main(void) { - if (sizeof(void *) <= sizeof(int)) puts("int"); - else if (sizeof(void *) <= sizeof(long)) puts("long"); - else puts("z_longlong"); - return 0; -} -EOF - else - echo "Checking for long long... No." | tee -a configure.log - cat > $test.c < -int main(void) { - if (sizeof(void *) <= sizeof(int)) puts("int"); - else puts("long"); - return 0; -} -EOF - fi - if try $CC $CFLAGS -o $test $test.c; then - sizet=`./$test` - echo "Checking for a pointer-size integer type..." $sizet"." | tee -a configure.log - else - echo "Failed to find a pointer-size integer type." | tee -a configure.log - leave 1 - fi -fi - -if test $need_sizet -eq 1; then - CFLAGS="${CFLAGS} -DNO_SIZE_T=${sizet}" - SFLAGS="${SFLAGS} -DNO_SIZE_T=${sizet}" -fi - -echo >> configure.log - -# check for large file support, and if none, check for fseeko() -cat > $test.c < -off64_t dummy = 0; -EOF -if try $CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c; then - CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1" - SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1" - ALL="${ALL} all64" - TEST="${TEST} test64" - echo "Checking for off64_t... Yes." | tee -a configure.log - echo "Checking for fseeko... Yes." | tee -a configure.log -else - echo "Checking for off64_t... No." | tee -a configure.log - echo >> configure.log - cat > $test.c < -int main(void) { - fseeko(NULL, 0, 0); - return 0; -} -EOF - if try $CC $CFLAGS -o $test $test.c; then - echo "Checking for fseeko... Yes." | tee -a configure.log - else - CFLAGS="${CFLAGS} -DNO_FSEEKO" - SFLAGS="${SFLAGS} -DNO_FSEEKO" - echo "Checking for fseeko... No." | tee -a configure.log - fi -fi - -echo >> configure.log - -# check for strerror() for use by gz* functions -cat > $test.c < -#include -int main() { return strlen(strerror(errno)); } -EOF -if try $CC $CFLAGS -o $test $test.c; then - echo "Checking for strerror... Yes." | tee -a configure.log -else - CFLAGS="${CFLAGS} -DNO_STRERROR" - SFLAGS="${SFLAGS} -DNO_STRERROR" - echo "Checking for strerror... No." | tee -a configure.log -fi - -# copy clean zconf.h for subsequent edits -cp -p ${SRCDIR}zconf.h.in zconf.h - -echo >> configure.log - -# check for unistd.h and save result in zconf.h -cat > $test.c < -int main() { return 0; } -EOF -if try $CC -c $CFLAGS $test.c; then - sed < zconf.h "/^#ifdef HAVE_UNISTD_H.* may be/s/def HAVE_UNISTD_H\(.*\) may be/ 1\1 was/" > zconf.temp.h - mv zconf.temp.h zconf.h - echo "Checking for unistd.h... Yes." | tee -a configure.log -else - echo "Checking for unistd.h... No." | tee -a configure.log -fi - -echo >> configure.log - -# check for stdarg.h and save result in zconf.h -cat > $test.c < -int main() { return 0; } -EOF -if try $CC -c $CFLAGS $test.c; then - sed < zconf.h "/^#ifdef HAVE_STDARG_H.* may be/s/def HAVE_STDARG_H\(.*\) may be/ 1\1 was/" > zconf.temp.h - mv zconf.temp.h zconf.h - echo "Checking for stdarg.h... Yes." | tee -a configure.log -else - echo "Checking for stdarg.h... No." | tee -a configure.log -fi - -# if the z_ prefix was requested, save that in zconf.h -if test $zprefix -eq 1; then - sed < zconf.h "/#ifdef Z_PREFIX.* may be/s/def Z_PREFIX\(.*\) may be/ 1\1 was/" > zconf.temp.h - mv zconf.temp.h zconf.h - echo >> configure.log - echo "Using z_ prefix on all symbols." | tee -a configure.log -fi - -# if --solo compilation was requested, save that in zconf.h and remove gz stuff from object lists -if test $solo -eq 1; then - sed '/#define ZCONF_H/a\ -#define Z_SOLO - -' < zconf.h > zconf.temp.h - mv zconf.temp.h zconf.h -OBJC='$(OBJZ)' -PIC_OBJC='$(PIC_OBJZ)' -fi - -# if code coverage testing was requested, use older gcc if defined, e.g. "gcc-4.2" on Mac OS X -if test $cover -eq 1; then - CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage" - if test -n "$GCC_CLASSIC"; then - CC=$GCC_CLASSIC - fi -fi - -echo >> configure.log - -# conduct a series of tests to resolve eight possible cases of using "vs" or "s" printf functions -# (using stdarg or not), with or without "n" (proving size of buffer), and with or without a -# return value. The most secure result is vsnprintf() with a return value. snprintf() with a -# return value is secure as well, but then gzprintf() will be limited to 20 arguments. -cat > $test.c < -#include -#include "zconf.h" -int main() -{ -#ifndef STDC - choke me -#endif - return 0; -} -EOF -if try $CC -c $CFLAGS $test.c; then - echo "Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf()." | tee -a configure.log - - echo >> configure.log - cat > $test.c < -#include -int mytest(const char *fmt, ...) -{ - char buf[20]; - va_list ap; - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - return 0; -} -int main() -{ - return (mytest("Hello%d\n", 1)); -} -EOF - if try $CC $CFLAGS -o $test $test.c; then - echo "Checking for vsnprintf() in stdio.h... Yes." | tee -a configure.log - - echo >> configure.log - cat >$test.c < -#include -int mytest(const char *fmt, ...) -{ - int n; - char buf[20]; - va_list ap; - va_start(ap, fmt); - n = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - return n; -} -int main() -{ - return (mytest("Hello%d\n", 1)); -} -EOF - - if try $CC -c $CFLAGS $test.c; then - echo "Checking for return value of vsnprintf()... Yes." | tee -a configure.log - else - CFLAGS="$CFLAGS -DHAS_vsnprintf_void" - SFLAGS="$SFLAGS -DHAS_vsnprintf_void" - echo "Checking for return value of vsnprintf()... No." | tee -a configure.log - echo " WARNING: apparently vsnprintf() does not return a value. zlib" | tee -a configure.log - echo " can build but will be open to possible string-format security" | tee -a configure.log - echo " vulnerabilities." | tee -a configure.log - fi - else - CFLAGS="$CFLAGS -DNO_vsnprintf" - SFLAGS="$SFLAGS -DNO_vsnprintf" - echo "Checking for vsnprintf() in stdio.h... No." | tee -a configure.log - echo " WARNING: vsnprintf() not found, falling back to vsprintf(). zlib" | tee -a configure.log - echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log - echo " vulnerabilities." | tee -a configure.log - - echo >> configure.log - cat >$test.c < -#include -int mytest(const char *fmt, ...) -{ - int n; - char buf[20]; - va_list ap; - va_start(ap, fmt); - n = vsprintf(buf, fmt, ap); - va_end(ap); - return n; -} -int main() -{ - return (mytest("Hello%d\n", 1)); -} -EOF - - if try $CC -c $CFLAGS $test.c; then - echo "Checking for return value of vsprintf()... Yes." | tee -a configure.log - else - CFLAGS="$CFLAGS -DHAS_vsprintf_void" - SFLAGS="$SFLAGS -DHAS_vsprintf_void" - echo "Checking for return value of vsprintf()... No." | tee -a configure.log - echo " WARNING: apparently vsprintf() does not return a value. zlib" | tee -a configure.log - echo " can build but will be open to possible string-format security" | tee -a configure.log - echo " vulnerabilities." | tee -a configure.log - fi - fi -else - echo "Checking whether to use vs[n]printf() or s[n]printf()... using s[n]printf()." | tee -a configure.log - - echo >> configure.log - cat >$test.c < -int mytest() -{ - char buf[20]; - snprintf(buf, sizeof(buf), "%s", "foo"); - return 0; -} -int main() -{ - return (mytest()); -} -EOF - - if try $CC $CFLAGS -o $test $test.c; then - echo "Checking for snprintf() in stdio.h... Yes." | tee -a configure.log - - echo >> configure.log - cat >$test.c < -int mytest() -{ - char buf[20]; - return snprintf(buf, sizeof(buf), "%s", "foo"); -} -int main() -{ - return (mytest()); -} -EOF - - if try $CC -c $CFLAGS $test.c; then - echo "Checking for return value of snprintf()... Yes." | tee -a configure.log - else - CFLAGS="$CFLAGS -DHAS_snprintf_void" - SFLAGS="$SFLAGS -DHAS_snprintf_void" - echo "Checking for return value of snprintf()... No." | tee -a configure.log - echo " WARNING: apparently snprintf() does not return a value. zlib" | tee -a configure.log - echo " can build but will be open to possible string-format security" | tee -a configure.log - echo " vulnerabilities." | tee -a configure.log - fi - else - CFLAGS="$CFLAGS -DNO_snprintf" - SFLAGS="$SFLAGS -DNO_snprintf" - echo "Checking for snprintf() in stdio.h... No." | tee -a configure.log - echo " WARNING: snprintf() not found, falling back to sprintf(). zlib" | tee -a configure.log - echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log - echo " vulnerabilities." | tee -a configure.log - - echo >> configure.log - cat >$test.c < -int mytest() -{ - char buf[20]; - return sprintf(buf, "%s", "foo"); -} -int main() -{ - return (mytest()); -} -EOF - - if try $CC -c $CFLAGS $test.c; then - echo "Checking for return value of sprintf()... Yes." | tee -a configure.log - else - CFLAGS="$CFLAGS -DHAS_sprintf_void" - SFLAGS="$SFLAGS -DHAS_sprintf_void" - echo "Checking for return value of sprintf()... No." | tee -a configure.log - echo " WARNING: apparently sprintf() does not return a value. zlib" | tee -a configure.log - echo " can build but will be open to possible string-format security" | tee -a configure.log - echo " vulnerabilities." | tee -a configure.log - fi - fi -fi - -# see if we can hide zlib internal symbols that are linked between separate source files -if test "$gcc" -eq 1; then - echo >> configure.log - cat > $test.c <> configure.log -echo ALL = $ALL >> configure.log -echo AR = $AR >> configure.log -echo ARFLAGS = $ARFLAGS >> configure.log -echo CC = $CC >> configure.log -echo CFLAGS = $CFLAGS >> configure.log -echo CPP = $CPP >> configure.log -echo EXE = $EXE >> configure.log -echo LDCONFIG = $LDCONFIG >> configure.log -echo LDFLAGS = $LDFLAGS >> configure.log -echo LDSHARED = $LDSHARED >> configure.log -echo LDSHAREDLIBC = $LDSHAREDLIBC >> configure.log -echo OBJC = $OBJC >> configure.log -echo PIC_OBJC = $PIC_OBJC >> configure.log -echo RANLIB = $RANLIB >> configure.log -echo SFLAGS = $SFLAGS >> configure.log -echo SHAREDLIB = $SHAREDLIB >> configure.log -echo SHAREDLIBM = $SHAREDLIBM >> configure.log -echo SHAREDLIBV = $SHAREDLIBV >> configure.log -echo STATICLIB = $STATICLIB >> configure.log -echo TEST = $TEST >> configure.log -echo VER = $VER >> configure.log -echo Z_U4 = $Z_U4 >> configure.log -echo SRCDIR = $SRCDIR >> configure.log -echo exec_prefix = $exec_prefix >> configure.log -echo includedir = $includedir >> configure.log -echo libdir = $libdir >> configure.log -echo mandir = $mandir >> configure.log -echo prefix = $prefix >> configure.log -echo sharedlibdir = $sharedlibdir >> configure.log -echo uname = $uname >> configure.log - -# udpate Makefile with the configure results -sed < ${SRCDIR}Makefile.in " -/^CC *=/s#=.*#=$CC# -/^CFLAGS *=/s#=.*#=$CFLAGS# -/^SFLAGS *=/s#=.*#=$SFLAGS# -/^LDFLAGS *=/s#=.*#=$LDFLAGS# -/^LDSHARED *=/s#=.*#=$LDSHARED# -/^CPP *=/s#=.*#=$CPP# -/^STATICLIB *=/s#=.*#=$STATICLIB# -/^SHAREDLIB *=/s#=.*#=$SHAREDLIB# -/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# -/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# -/^AR *=/s#=.*#=$AR# -/^ARFLAGS *=/s#=.*#=$ARFLAGS# -/^RANLIB *=/s#=.*#=$RANLIB# -/^LDCONFIG *=/s#=.*#=$LDCONFIG# -/^LDSHAREDLIBC *=/s#=.*#=$LDSHAREDLIBC# -/^EXE *=/s#=.*#=$EXE# -/^SRCDIR *=/s#=.*#=$SRCDIR# -/^ZINC *=/s#=.*#=$ZINC# -/^ZINCOUT *=/s#=.*#=$ZINCOUT# -/^prefix *=/s#=.*#=$prefix# -/^exec_prefix *=/s#=.*#=$exec_prefix# -/^libdir *=/s#=.*#=$libdir# -/^sharedlibdir *=/s#=.*#=$sharedlibdir# -/^includedir *=/s#=.*#=$includedir# -/^mandir *=/s#=.*#=$mandir# -/^OBJC *=/s#=.*#= $OBJC# -/^PIC_OBJC *=/s#=.*#= $PIC_OBJC# -/^all: */s#:.*#: $ALL# -/^test: */s#:.*#: $TEST# -" > Makefile - -# create zlib.pc with the configure results -sed < ${SRCDIR}zlib.pc.in " -/^CC *=/s#=.*#=$CC# -/^CFLAGS *=/s#=.*#=$CFLAGS# -/^CPP *=/s#=.*#=$CPP# -/^LDSHARED *=/s#=.*#=$LDSHARED# -/^STATICLIB *=/s#=.*#=$STATICLIB# -/^SHAREDLIB *=/s#=.*#=$SHAREDLIB# -/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# -/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# -/^AR *=/s#=.*#=$AR# -/^ARFLAGS *=/s#=.*#=$ARFLAGS# -/^RANLIB *=/s#=.*#=$RANLIB# -/^EXE *=/s#=.*#=$EXE# -/^prefix *=/s#=.*#=$prefix# -/^exec_prefix *=/s#=.*#=$exec_prefix# -/^libdir *=/s#=.*#=$libdir# -/^sharedlibdir *=/s#=.*#=$sharedlibdir# -/^includedir *=/s#=.*#=$includedir# -/^mandir *=/s#=.*#=$mandir# -/^LDFLAGS *=/s#=.*#=$LDFLAGS# -" | sed -e " -s/\@VERSION\@/$VER/g; -" > zlib.pc - -# done -leave 0 diff --git a/deps/zlib/contrib/README.contrib b/deps/zlib/contrib/README.contrib deleted file mode 100644 index a411d5c396bd41..00000000000000 --- a/deps/zlib/contrib/README.contrib +++ /dev/null @@ -1,78 +0,0 @@ -All files under this contrib directory are UNSUPPORTED. There were -provided by users of zlib and were not tested by the authors of zlib. -Use at your own risk. Please contact the authors of the contributions -for help about these, not the zlib authors. Thanks. - - -ada/ by Dmitriy Anisimkov - Support for Ada - See http://zlib-ada.sourceforge.net/ - -amd64/ by Mikhail Teterin - asm code for AMD64 - See patch at http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/96393 - -asm686/ by Brian Raiter - asm code for Pentium and PPro/PII, using the AT&T (GNU as) syntax - See http://www.muppetlabs.com/~breadbox/software/assembly.html - -blast/ by Mark Adler - Decompressor for output of PKWare Data Compression Library (DCL) - -delphi/ by Cosmin Truta - Support for Delphi and C++ Builder - -dotzlib/ by Henrik Ravn - Support for Microsoft .Net and Visual C++ .Net - -gcc_gvmat64/by Gilles Vollant - GCC Version of x86 64-bit (AMD64 and Intel EM64t) code for x64 - assembler to replace longest_match() and inflate_fast() - -infback9/ by Mark Adler - Unsupported diffs to infback to decode the deflate64 format - -inflate86/ by Chris Anderson - Tuned x86 gcc asm code to replace inflate_fast() - -iostream/ by Kevin Ruland - A C++ I/O streams interface to the zlib gz* functions - -iostream2/ by Tyge Løvset - Another C++ I/O streams interface - -iostream3/ by Ludwig Schwardt - and Kevin Ruland - Yet another C++ I/O streams interface - -masmx64/ by Gilles Vollant - x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to - replace longest_match() and inflate_fast(), also masm x86 - 64-bits translation of Chris Anderson inflate_fast() - -masmx86/ by Gilles Vollant - x86 asm code to replace longest_match() and inflate_fast(), - for Visual C++ and MASM (32 bits). - Based on Brian Raiter (asm686) and Chris Anderson (inflate86) - -minizip/ by Gilles Vollant - Mini zip and unzip based on zlib - Includes Zip64 support by Mathias Svensson - See http://www.winimage.com/zLibDll/minizip.html - -pascal/ by Bob Dellaca et al. - Support for Pascal - -puff/ by Mark Adler - Small, low memory usage inflate. Also serves to provide an - unambiguous description of the deflate format. - -testzlib/ by Gilles Vollant - Example of the use of zlib - -untgz/ by Pedro A. Aranda Gutierrez - A very simple tar.gz file extractor using zlib - -vstudio/ by Gilles Vollant - Building a minizip-enhanced zlib with Microsoft Visual Studio - Includes vc11 from kreuzerkrieg and vc12 from davispuh diff --git a/deps/zlib/contrib/ada/buffer_demo.adb b/deps/zlib/contrib/ada/buffer_demo.adb deleted file mode 100644 index 46b8638107fbd5..00000000000000 --- a/deps/zlib/contrib/ada/buffer_demo.adb +++ /dev/null @@ -1,106 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2004 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- --- --- $Id: buffer_demo.adb,v 1.3 2004/09/06 06:55:35 vagul Exp $ - --- This demo program provided by Dr Steve Sangwine --- --- Demonstration of a problem with Zlib-Ada (already fixed) when a buffer --- of exactly the correct size is used for decompressed data, and the last --- few bytes passed in to Zlib are checksum bytes. - --- This program compresses a string of text, and then decompresses the --- compressed text into a buffer of the same size as the original text. - -with Ada.Streams; use Ada.Streams; -with Ada.Text_IO; - -with ZLib; use ZLib; - -procedure Buffer_Demo is - EOL : Character renames ASCII.LF; - Text : constant String - := "Four score and seven years ago our fathers brought forth," & EOL & - "upon this continent, a new nation, conceived in liberty," & EOL & - "and dedicated to the proposition that `all men are created equal'."; - - Source : Stream_Element_Array (1 .. Text'Length); - for Source'Address use Text'Address; - -begin - Ada.Text_IO.Put (Text); - Ada.Text_IO.New_Line; - Ada.Text_IO.Put_Line - ("Uncompressed size : " & Positive'Image (Text'Length) & " bytes"); - - declare - Compressed_Data : Stream_Element_Array (1 .. Text'Length); - L : Stream_Element_Offset; - begin - Compress : declare - Compressor : Filter_Type; - I : Stream_Element_Offset; - begin - Deflate_Init (Compressor); - - -- Compress the whole of T at once. - - Translate (Compressor, Source, I, Compressed_Data, L, Finish); - pragma Assert (I = Source'Last); - - Close (Compressor); - - Ada.Text_IO.Put_Line - ("Compressed size : " - & Stream_Element_Offset'Image (L) & " bytes"); - end Compress; - - -- Now we decompress the data, passing short blocks of data to Zlib - -- (because this demonstrates the problem - the last block passed will - -- contain checksum information and there will be no output, only a - -- check inside Zlib that the checksum is correct). - - Decompress : declare - Decompressor : Filter_Type; - - Uncompressed_Data : Stream_Element_Array (1 .. Text'Length); - - Block_Size : constant := 4; - -- This makes sure that the last block contains - -- only Adler checksum data. - - P : Stream_Element_Offset := Compressed_Data'First - 1; - O : Stream_Element_Offset; - begin - Inflate_Init (Decompressor); - - loop - Translate - (Decompressor, - Compressed_Data - (P + 1 .. Stream_Element_Offset'Min (P + Block_Size, L)), - P, - Uncompressed_Data - (Total_Out (Decompressor) + 1 .. Uncompressed_Data'Last), - O, - No_Flush); - - Ada.Text_IO.Put_Line - ("Total in : " & Count'Image (Total_In (Decompressor)) & - ", out : " & Count'Image (Total_Out (Decompressor))); - - exit when P = L; - end loop; - - Ada.Text_IO.New_Line; - Ada.Text_IO.Put_Line - ("Decompressed text matches original text : " - & Boolean'Image (Uncompressed_Data = Source)); - end Decompress; - end; -end Buffer_Demo; diff --git a/deps/zlib/contrib/ada/mtest.adb b/deps/zlib/contrib/ada/mtest.adb deleted file mode 100644 index c4dfd080f0c0a4..00000000000000 --- a/deps/zlib/contrib/ada/mtest.adb +++ /dev/null @@ -1,156 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2003 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- --- Continuous test for ZLib multithreading. If the test would fail --- we should provide thread safe allocation routines for the Z_Stream. --- --- $Id: mtest.adb,v 1.4 2004/07/23 07:49:54 vagul Exp $ - -with ZLib; -with Ada.Streams; -with Ada.Numerics.Discrete_Random; -with Ada.Text_IO; -with Ada.Exceptions; -with Ada.Task_Identification; - -procedure MTest is - use Ada.Streams; - use ZLib; - - Stop : Boolean := False; - - pragma Atomic (Stop); - - subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#; - - package Random_Elements is - new Ada.Numerics.Discrete_Random (Visible_Symbols); - - task type Test_Task; - - task body Test_Task is - Buffer : Stream_Element_Array (1 .. 100_000); - Gen : Random_Elements.Generator; - - Buffer_First : Stream_Element_Offset; - Compare_First : Stream_Element_Offset; - - Deflate : Filter_Type; - Inflate : Filter_Type; - - procedure Further (Item : in Stream_Element_Array); - - procedure Read_Buffer - (Item : out Ada.Streams.Stream_Element_Array; - Last : out Ada.Streams.Stream_Element_Offset); - - ------------- - -- Further -- - ------------- - - procedure Further (Item : in Stream_Element_Array) is - - procedure Compare (Item : in Stream_Element_Array); - - ------------- - -- Compare -- - ------------- - - procedure Compare (Item : in Stream_Element_Array) is - Next_First : Stream_Element_Offset := Compare_First + Item'Length; - begin - if Buffer (Compare_First .. Next_First - 1) /= Item then - raise Program_Error; - end if; - - Compare_First := Next_First; - end Compare; - - procedure Compare_Write is new ZLib.Write (Write => Compare); - begin - Compare_Write (Inflate, Item, No_Flush); - end Further; - - ----------------- - -- Read_Buffer -- - ----------------- - - procedure Read_Buffer - (Item : out Ada.Streams.Stream_Element_Array; - Last : out Ada.Streams.Stream_Element_Offset) - is - Buff_Diff : Stream_Element_Offset := Buffer'Last - Buffer_First; - Next_First : Stream_Element_Offset; - begin - if Item'Length <= Buff_Diff then - Last := Item'Last; - - Next_First := Buffer_First + Item'Length; - - Item := Buffer (Buffer_First .. Next_First - 1); - - Buffer_First := Next_First; - else - Last := Item'First + Buff_Diff; - Item (Item'First .. Last) := Buffer (Buffer_First .. Buffer'Last); - Buffer_First := Buffer'Last + 1; - end if; - end Read_Buffer; - - procedure Translate is new Generic_Translate - (Data_In => Read_Buffer, - Data_Out => Further); - - begin - Random_Elements.Reset (Gen); - - Buffer := (others => 20); - - Main : loop - for J in Buffer'Range loop - Buffer (J) := Random_Elements.Random (Gen); - - Deflate_Init (Deflate); - Inflate_Init (Inflate); - - Buffer_First := Buffer'First; - Compare_First := Buffer'First; - - Translate (Deflate); - - if Compare_First /= Buffer'Last + 1 then - raise Program_Error; - end if; - - Ada.Text_IO.Put_Line - (Ada.Task_Identification.Image - (Ada.Task_Identification.Current_Task) - & Stream_Element_Offset'Image (J) - & ZLib.Count'Image (Total_Out (Deflate))); - - Close (Deflate); - Close (Inflate); - - exit Main when Stop; - end loop; - end loop Main; - exception - when E : others => - Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Information (E)); - Stop := True; - end Test_Task; - - Test : array (1 .. 4) of Test_Task; - - pragma Unreferenced (Test); - - Dummy : Character; - -begin - Ada.Text_IO.Get_Immediate (Dummy); - Stop := True; -end MTest; diff --git a/deps/zlib/contrib/ada/read.adb b/deps/zlib/contrib/ada/read.adb deleted file mode 100644 index 1f2efbfeb80287..00000000000000 --- a/deps/zlib/contrib/ada/read.adb +++ /dev/null @@ -1,156 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2003 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- - --- $Id: read.adb,v 1.8 2004/05/31 10:53:40 vagul Exp $ - --- Test/demo program for the generic read interface. - -with Ada.Numerics.Discrete_Random; -with Ada.Streams; -with Ada.Text_IO; - -with ZLib; - -procedure Read is - - use Ada.Streams; - - ------------------------------------ - -- Test configuration parameters -- - ------------------------------------ - - File_Size : Stream_Element_Offset := 100_000; - - Continuous : constant Boolean := False; - -- If this constant is True, the test would be repeated again and again, - -- with increment File_Size for every iteration. - - Header : constant ZLib.Header_Type := ZLib.Default; - -- Do not use Header other than Default in ZLib versions 1.1.4 and older. - - Init_Random : constant := 8; - -- We are using the same random sequence, in case of we catch bug, - -- so we would be able to reproduce it. - - -- End -- - - Pack_Size : Stream_Element_Offset; - Offset : Stream_Element_Offset; - - Filter : ZLib.Filter_Type; - - subtype Visible_Symbols - is Stream_Element range 16#20# .. 16#7E#; - - package Random_Elements is new - Ada.Numerics.Discrete_Random (Visible_Symbols); - - Gen : Random_Elements.Generator; - Period : constant Stream_Element_Offset := 200; - -- Period constant variable for random generator not to be very random. - -- Bigger period, harder random. - - Read_Buffer : Stream_Element_Array (1 .. 2048); - Read_First : Stream_Element_Offset; - Read_Last : Stream_Element_Offset; - - procedure Reset; - - procedure Read - (Item : out Stream_Element_Array; - Last : out Stream_Element_Offset); - -- this procedure is for generic instantiation of - -- ZLib.Read - -- reading data from the File_In. - - procedure Read is new ZLib.Read - (Read, - Read_Buffer, - Rest_First => Read_First, - Rest_Last => Read_Last); - - ---------- - -- Read -- - ---------- - - procedure Read - (Item : out Stream_Element_Array; - Last : out Stream_Element_Offset) is - begin - Last := Stream_Element_Offset'Min - (Item'Last, - Item'First + File_Size - Offset); - - for J in Item'First .. Last loop - if J < Item'First + Period then - Item (J) := Random_Elements.Random (Gen); - else - Item (J) := Item (J - Period); - end if; - - Offset := Offset + 1; - end loop; - end Read; - - ----------- - -- Reset -- - ----------- - - procedure Reset is - begin - Random_Elements.Reset (Gen, Init_Random); - Pack_Size := 0; - Offset := 1; - Read_First := Read_Buffer'Last + 1; - Read_Last := Read_Buffer'Last; - end Reset; - -begin - Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version); - - loop - for Level in ZLib.Compression_Level'Range loop - - Ada.Text_IO.Put ("Level =" - & ZLib.Compression_Level'Image (Level)); - - -- Deflate using generic instantiation. - - ZLib.Deflate_Init - (Filter, - Level, - Header => Header); - - Reset; - - Ada.Text_IO.Put - (Stream_Element_Offset'Image (File_Size) & " ->"); - - loop - declare - Buffer : Stream_Element_Array (1 .. 1024); - Last : Stream_Element_Offset; - begin - Read (Filter, Buffer, Last); - - Pack_Size := Pack_Size + Last - Buffer'First + 1; - - exit when Last < Buffer'Last; - end; - end loop; - - Ada.Text_IO.Put_Line (Stream_Element_Offset'Image (Pack_Size)); - - ZLib.Close (Filter); - end loop; - - exit when not Continuous; - - File_Size := File_Size + 1; - end loop; -end Read; diff --git a/deps/zlib/contrib/ada/readme.txt b/deps/zlib/contrib/ada/readme.txt deleted file mode 100644 index ce4d2cadf0d928..00000000000000 --- a/deps/zlib/contrib/ada/readme.txt +++ /dev/null @@ -1,65 +0,0 @@ - ZLib for Ada thick binding (ZLib.Ada) - Release 1.3 - -ZLib.Ada is a thick binding interface to the popular ZLib data -compression library, available at http://www.gzip.org/zlib/. -It provides Ada-style access to the ZLib C library. - - - Here are the main changes since ZLib.Ada 1.2: - -- Attension: ZLib.Read generic routine have a initialization requirement - for Read_Last parameter now. It is a bit incompartible with previous version, - but extends functionality, we could use new parameters Allow_Read_Some and - Flush now. - -- Added Is_Open routines to ZLib and ZLib.Streams packages. - -- Add pragma Assert to check Stream_Element is 8 bit. - -- Fix extraction to buffer with exact known decompressed size. Error reported by - Steve Sangwine. - -- Fix definition of ULong (changed to unsigned_long), fix regression on 64 bits - computers. Patch provided by Pascal Obry. - -- Add Status_Error exception definition. - -- Add pragma Assertion that Ada.Streams.Stream_Element size is 8 bit. - - - How to build ZLib.Ada under GNAT - -You should have the ZLib library already build on your computer, before -building ZLib.Ada. Make the directory of ZLib.Ada sources current and -issue the command: - - gnatmake test -largs -L -lz - -Or use the GNAT project file build for GNAT 3.15 or later: - - gnatmake -Pzlib.gpr -L - - - How to build ZLib.Ada under Aonix ObjectAda for Win32 7.2.2 - -1. Make a project with all *.ads and *.adb files from the distribution. -2. Build the libz.a library from the ZLib C sources. -3. Rename libz.a to z.lib. -4. Add the library z.lib to the project. -5. Add the libc.lib library from the ObjectAda distribution to the project. -6. Build the executable using test.adb as a main procedure. - - - How to use ZLib.Ada - -The source files test.adb and read.adb are small demo programs that show -the main functionality of ZLib.Ada. - -The routines from the package specifications are commented. - - -Homepage: http://zlib-ada.sourceforge.net/ -Author: Dmitriy Anisimkov - -Contributors: Pascal Obry , Steve Sangwine diff --git a/deps/zlib/contrib/ada/test.adb b/deps/zlib/contrib/ada/test.adb deleted file mode 100644 index 90773acfa18669..00000000000000 --- a/deps/zlib/contrib/ada/test.adb +++ /dev/null @@ -1,463 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2003 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- - --- $Id: test.adb,v 1.17 2003/08/12 12:13:30 vagul Exp $ - --- The program has a few aims. --- 1. Test ZLib.Ada95 thick binding functionality. --- 2. Show the example of use main functionality of the ZLib.Ada95 binding. --- 3. Build this program automatically compile all ZLib.Ada95 packages under --- GNAT Ada95 compiler. - -with ZLib.Streams; -with Ada.Streams.Stream_IO; -with Ada.Numerics.Discrete_Random; - -with Ada.Text_IO; - -with Ada.Calendar; - -procedure Test is - - use Ada.Streams; - use Stream_IO; - - ------------------------------------ - -- Test configuration parameters -- - ------------------------------------ - - File_Size : Count := 100_000; - Continuous : constant Boolean := False; - - Header : constant ZLib.Header_Type := ZLib.Default; - -- ZLib.None; - -- ZLib.Auto; - -- ZLib.GZip; - -- Do not use Header other then Default in ZLib versions 1.1.4 - -- and older. - - Strategy : constant ZLib.Strategy_Type := ZLib.Default_Strategy; - Init_Random : constant := 10; - - -- End -- - - In_File_Name : constant String := "testzlib.in"; - -- Name of the input file - - Z_File_Name : constant String := "testzlib.zlb"; - -- Name of the compressed file. - - Out_File_Name : constant String := "testzlib.out"; - -- Name of the decompressed file. - - File_In : File_Type; - File_Out : File_Type; - File_Back : File_Type; - File_Z : ZLib.Streams.Stream_Type; - - Filter : ZLib.Filter_Type; - - Time_Stamp : Ada.Calendar.Time; - - procedure Generate_File; - -- Generate file of spetsified size with some random data. - -- The random data is repeatable, for the good compression. - - procedure Compare_Streams - (Left, Right : in out Root_Stream_Type'Class); - -- The procedure compearing data in 2 streams. - -- It is for compare data before and after compression/decompression. - - procedure Compare_Files (Left, Right : String); - -- Compare files. Based on the Compare_Streams. - - procedure Copy_Streams - (Source, Target : in out Root_Stream_Type'Class; - Buffer_Size : in Stream_Element_Offset := 1024); - -- Copying data from one stream to another. It is for test stream - -- interface of the library. - - procedure Data_In - (Item : out Stream_Element_Array; - Last : out Stream_Element_Offset); - -- this procedure is for generic instantiation of - -- ZLib.Generic_Translate. - -- reading data from the File_In. - - procedure Data_Out (Item : in Stream_Element_Array); - -- this procedure is for generic instantiation of - -- ZLib.Generic_Translate. - -- writing data to the File_Out. - - procedure Stamp; - -- Store the timestamp to the local variable. - - procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count); - -- Print the time statistic with the message. - - procedure Translate is new ZLib.Generic_Translate - (Data_In => Data_In, - Data_Out => Data_Out); - -- This procedure is moving data from File_In to File_Out - -- with compression or decompression, depend on initialization of - -- Filter parameter. - - ------------------- - -- Compare_Files -- - ------------------- - - procedure Compare_Files (Left, Right : String) is - Left_File, Right_File : File_Type; - begin - Open (Left_File, In_File, Left); - Open (Right_File, In_File, Right); - Compare_Streams (Stream (Left_File).all, Stream (Right_File).all); - Close (Left_File); - Close (Right_File); - end Compare_Files; - - --------------------- - -- Compare_Streams -- - --------------------- - - procedure Compare_Streams - (Left, Right : in out Ada.Streams.Root_Stream_Type'Class) - is - Left_Buffer, Right_Buffer : Stream_Element_Array (0 .. 16#FFF#); - Left_Last, Right_Last : Stream_Element_Offset; - begin - loop - Read (Left, Left_Buffer, Left_Last); - Read (Right, Right_Buffer, Right_Last); - - if Left_Last /= Right_Last then - Ada.Text_IO.Put_Line ("Compare error :" - & Stream_Element_Offset'Image (Left_Last) - & " /= " - & Stream_Element_Offset'Image (Right_Last)); - - raise Constraint_Error; - - elsif Left_Buffer (0 .. Left_Last) - /= Right_Buffer (0 .. Right_Last) - then - Ada.Text_IO.Put_Line ("ERROR: IN and OUT files is not equal."); - raise Constraint_Error; - - end if; - - exit when Left_Last < Left_Buffer'Last; - end loop; - end Compare_Streams; - - ------------------ - -- Copy_Streams -- - ------------------ - - procedure Copy_Streams - (Source, Target : in out Ada.Streams.Root_Stream_Type'Class; - Buffer_Size : in Stream_Element_Offset := 1024) - is - Buffer : Stream_Element_Array (1 .. Buffer_Size); - Last : Stream_Element_Offset; - begin - loop - Read (Source, Buffer, Last); - Write (Target, Buffer (1 .. Last)); - - exit when Last < Buffer'Last; - end loop; - end Copy_Streams; - - ------------- - -- Data_In -- - ------------- - - procedure Data_In - (Item : out Stream_Element_Array; - Last : out Stream_Element_Offset) is - begin - Read (File_In, Item, Last); - end Data_In; - - -------------- - -- Data_Out -- - -------------- - - procedure Data_Out (Item : in Stream_Element_Array) is - begin - Write (File_Out, Item); - end Data_Out; - - ------------------- - -- Generate_File -- - ------------------- - - procedure Generate_File is - subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#; - - package Random_Elements is - new Ada.Numerics.Discrete_Random (Visible_Symbols); - - Gen : Random_Elements.Generator; - Buffer : Stream_Element_Array := (1 .. 77 => 16#20#) & 10; - - Buffer_Count : constant Count := File_Size / Buffer'Length; - -- Number of same buffers in the packet. - - Density : constant Count := 30; -- from 0 to Buffer'Length - 2; - - procedure Fill_Buffer (J, D : in Count); - -- Change the part of the buffer. - - ----------------- - -- Fill_Buffer -- - ----------------- - - procedure Fill_Buffer (J, D : in Count) is - begin - for K in 0 .. D loop - Buffer - (Stream_Element_Offset ((J + K) mod (Buffer'Length - 1) + 1)) - := Random_Elements.Random (Gen); - - end loop; - end Fill_Buffer; - - begin - Random_Elements.Reset (Gen, Init_Random); - - Create (File_In, Out_File, In_File_Name); - - Fill_Buffer (1, Buffer'Length - 2); - - for J in 1 .. Buffer_Count loop - Write (File_In, Buffer); - - Fill_Buffer (J, Density); - end loop; - - -- fill remain size. - - Write - (File_In, - Buffer - (1 .. Stream_Element_Offset - (File_Size - Buffer'Length * Buffer_Count))); - - Flush (File_In); - Close (File_In); - end Generate_File; - - --------------------- - -- Print_Statistic -- - --------------------- - - procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count) is - use Ada.Calendar; - use Ada.Text_IO; - - package Count_IO is new Integer_IO (ZLib.Count); - - Curr_Dur : Duration := Clock - Time_Stamp; - begin - Put (Msg); - - Set_Col (20); - Ada.Text_IO.Put ("size ="); - - Count_IO.Put - (Data_Size, - Width => Stream_IO.Count'Image (File_Size)'Length); - - Put_Line (" duration =" & Duration'Image (Curr_Dur)); - end Print_Statistic; - - ----------- - -- Stamp -- - ----------- - - procedure Stamp is - begin - Time_Stamp := Ada.Calendar.Clock; - end Stamp; - -begin - Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version); - - loop - Generate_File; - - for Level in ZLib.Compression_Level'Range loop - - Ada.Text_IO.Put_Line ("Level =" - & ZLib.Compression_Level'Image (Level)); - - -- Test generic interface. - Open (File_In, In_File, In_File_Name); - Create (File_Out, Out_File, Z_File_Name); - - Stamp; - - -- Deflate using generic instantiation. - - ZLib.Deflate_Init - (Filter => Filter, - Level => Level, - Strategy => Strategy, - Header => Header); - - Translate (Filter); - Print_Statistic ("Generic compress", ZLib.Total_Out (Filter)); - ZLib.Close (Filter); - - Close (File_In); - Close (File_Out); - - Open (File_In, In_File, Z_File_Name); - Create (File_Out, Out_File, Out_File_Name); - - Stamp; - - -- Inflate using generic instantiation. - - ZLib.Inflate_Init (Filter, Header => Header); - - Translate (Filter); - Print_Statistic ("Generic decompress", ZLib.Total_Out (Filter)); - - ZLib.Close (Filter); - - Close (File_In); - Close (File_Out); - - Compare_Files (In_File_Name, Out_File_Name); - - -- Test stream interface. - - -- Compress to the back stream. - - Open (File_In, In_File, In_File_Name); - Create (File_Back, Out_File, Z_File_Name); - - Stamp; - - ZLib.Streams.Create - (Stream => File_Z, - Mode => ZLib.Streams.Out_Stream, - Back => ZLib.Streams.Stream_Access - (Stream (File_Back)), - Back_Compressed => True, - Level => Level, - Strategy => Strategy, - Header => Header); - - Copy_Streams - (Source => Stream (File_In).all, - Target => File_Z); - - -- Flushing internal buffers to the back stream. - - ZLib.Streams.Flush (File_Z, ZLib.Finish); - - Print_Statistic ("Write compress", - ZLib.Streams.Write_Total_Out (File_Z)); - - ZLib.Streams.Close (File_Z); - - Close (File_In); - Close (File_Back); - - -- Compare reading from original file and from - -- decompression stream. - - Open (File_In, In_File, In_File_Name); - Open (File_Back, In_File, Z_File_Name); - - ZLib.Streams.Create - (Stream => File_Z, - Mode => ZLib.Streams.In_Stream, - Back => ZLib.Streams.Stream_Access - (Stream (File_Back)), - Back_Compressed => True, - Header => Header); - - Stamp; - Compare_Streams (Stream (File_In).all, File_Z); - - Print_Statistic ("Read decompress", - ZLib.Streams.Read_Total_Out (File_Z)); - - ZLib.Streams.Close (File_Z); - Close (File_In); - Close (File_Back); - - -- Compress by reading from compression stream. - - Open (File_Back, In_File, In_File_Name); - Create (File_Out, Out_File, Z_File_Name); - - ZLib.Streams.Create - (Stream => File_Z, - Mode => ZLib.Streams.In_Stream, - Back => ZLib.Streams.Stream_Access - (Stream (File_Back)), - Back_Compressed => False, - Level => Level, - Strategy => Strategy, - Header => Header); - - Stamp; - Copy_Streams - (Source => File_Z, - Target => Stream (File_Out).all); - - Print_Statistic ("Read compress", - ZLib.Streams.Read_Total_Out (File_Z)); - - ZLib.Streams.Close (File_Z); - - Close (File_Out); - Close (File_Back); - - -- Decompress to decompression stream. - - Open (File_In, In_File, Z_File_Name); - Create (File_Back, Out_File, Out_File_Name); - - ZLib.Streams.Create - (Stream => File_Z, - Mode => ZLib.Streams.Out_Stream, - Back => ZLib.Streams.Stream_Access - (Stream (File_Back)), - Back_Compressed => False, - Header => Header); - - Stamp; - - Copy_Streams - (Source => Stream (File_In).all, - Target => File_Z); - - Print_Statistic ("Write decompress", - ZLib.Streams.Write_Total_Out (File_Z)); - - ZLib.Streams.Close (File_Z); - Close (File_In); - Close (File_Back); - - Compare_Files (In_File_Name, Out_File_Name); - end loop; - - Ada.Text_IO.Put_Line (Count'Image (File_Size) & " Ok."); - - exit when not Continuous; - - File_Size := File_Size + 1; - end loop; -end Test; diff --git a/deps/zlib/contrib/ada/zlib-streams.adb b/deps/zlib/contrib/ada/zlib-streams.adb deleted file mode 100644 index b6497bae286e50..00000000000000 --- a/deps/zlib/contrib/ada/zlib-streams.adb +++ /dev/null @@ -1,225 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2003 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- - --- $Id: zlib-streams.adb,v 1.10 2004/05/31 10:53:40 vagul Exp $ - -with Ada.Unchecked_Deallocation; - -package body ZLib.Streams is - - ----------- - -- Close -- - ----------- - - procedure Close (Stream : in out Stream_Type) is - procedure Free is new Ada.Unchecked_Deallocation - (Stream_Element_Array, Buffer_Access); - begin - if Stream.Mode = Out_Stream or Stream.Mode = Duplex then - -- We should flush the data written by the writer. - - Flush (Stream, Finish); - - Close (Stream.Writer); - end if; - - if Stream.Mode = In_Stream or Stream.Mode = Duplex then - Close (Stream.Reader); - Free (Stream.Buffer); - end if; - end Close; - - ------------ - -- Create -- - ------------ - - procedure Create - (Stream : out Stream_Type; - Mode : in Stream_Mode; - Back : in Stream_Access; - Back_Compressed : in Boolean; - Level : in Compression_Level := Default_Compression; - Strategy : in Strategy_Type := Default_Strategy; - Header : in Header_Type := Default; - Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset - := Default_Buffer_Size; - Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset - := Default_Buffer_Size) - is - - subtype Buffer_Subtype is Stream_Element_Array (1 .. Read_Buffer_Size); - - procedure Init_Filter - (Filter : in out Filter_Type; - Compress : in Boolean); - - ----------------- - -- Init_Filter -- - ----------------- - - procedure Init_Filter - (Filter : in out Filter_Type; - Compress : in Boolean) is - begin - if Compress then - Deflate_Init - (Filter, Level, Strategy, Header => Header); - else - Inflate_Init (Filter, Header => Header); - end if; - end Init_Filter; - - begin - Stream.Back := Back; - Stream.Mode := Mode; - - if Mode = Out_Stream or Mode = Duplex then - Init_Filter (Stream.Writer, Back_Compressed); - Stream.Buffer_Size := Write_Buffer_Size; - else - Stream.Buffer_Size := 0; - end if; - - if Mode = In_Stream or Mode = Duplex then - Init_Filter (Stream.Reader, not Back_Compressed); - - Stream.Buffer := new Buffer_Subtype; - Stream.Rest_First := Stream.Buffer'Last + 1; - Stream.Rest_Last := Stream.Buffer'Last; - end if; - end Create; - - ----------- - -- Flush -- - ----------- - - procedure Flush - (Stream : in out Stream_Type; - Mode : in Flush_Mode := Sync_Flush) - is - Buffer : Stream_Element_Array (1 .. Stream.Buffer_Size); - Last : Stream_Element_Offset; - begin - loop - Flush (Stream.Writer, Buffer, Last, Mode); - - Ada.Streams.Write (Stream.Back.all, Buffer (1 .. Last)); - - exit when Last < Buffer'Last; - end loop; - end Flush; - - ------------- - -- Is_Open -- - ------------- - - function Is_Open (Stream : Stream_Type) return Boolean is - begin - return Is_Open (Stream.Reader) or else Is_Open (Stream.Writer); - end Is_Open; - - ---------- - -- Read -- - ---------- - - procedure Read - (Stream : in out Stream_Type; - Item : out Stream_Element_Array; - Last : out Stream_Element_Offset) - is - - procedure Read - (Item : out Stream_Element_Array; - Last : out Stream_Element_Offset); - - ---------- - -- Read -- - ---------- - - procedure Read - (Item : out Stream_Element_Array; - Last : out Stream_Element_Offset) is - begin - Ada.Streams.Read (Stream.Back.all, Item, Last); - end Read; - - procedure Read is new ZLib.Read - (Read => Read, - Buffer => Stream.Buffer.all, - Rest_First => Stream.Rest_First, - Rest_Last => Stream.Rest_Last); - - begin - Read (Stream.Reader, Item, Last); - end Read; - - ------------------- - -- Read_Total_In -- - ------------------- - - function Read_Total_In (Stream : in Stream_Type) return Count is - begin - return Total_In (Stream.Reader); - end Read_Total_In; - - -------------------- - -- Read_Total_Out -- - -------------------- - - function Read_Total_Out (Stream : in Stream_Type) return Count is - begin - return Total_Out (Stream.Reader); - end Read_Total_Out; - - ----------- - -- Write -- - ----------- - - procedure Write - (Stream : in out Stream_Type; - Item : in Stream_Element_Array) - is - - procedure Write (Item : in Stream_Element_Array); - - ----------- - -- Write -- - ----------- - - procedure Write (Item : in Stream_Element_Array) is - begin - Ada.Streams.Write (Stream.Back.all, Item); - end Write; - - procedure Write is new ZLib.Write - (Write => Write, - Buffer_Size => Stream.Buffer_Size); - - begin - Write (Stream.Writer, Item, No_Flush); - end Write; - - -------------------- - -- Write_Total_In -- - -------------------- - - function Write_Total_In (Stream : in Stream_Type) return Count is - begin - return Total_In (Stream.Writer); - end Write_Total_In; - - --------------------- - -- Write_Total_Out -- - --------------------- - - function Write_Total_Out (Stream : in Stream_Type) return Count is - begin - return Total_Out (Stream.Writer); - end Write_Total_Out; - -end ZLib.Streams; diff --git a/deps/zlib/contrib/ada/zlib-streams.ads b/deps/zlib/contrib/ada/zlib-streams.ads deleted file mode 100644 index 8e26cd450838c6..00000000000000 --- a/deps/zlib/contrib/ada/zlib-streams.ads +++ /dev/null @@ -1,114 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2003 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- - --- $Id: zlib-streams.ads,v 1.12 2004/05/31 10:53:40 vagul Exp $ - -package ZLib.Streams is - - type Stream_Mode is (In_Stream, Out_Stream, Duplex); - - type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class; - - type Stream_Type is - new Ada.Streams.Root_Stream_Type with private; - - procedure Read - (Stream : in out Stream_Type; - Item : out Ada.Streams.Stream_Element_Array; - Last : out Ada.Streams.Stream_Element_Offset); - - procedure Write - (Stream : in out Stream_Type; - Item : in Ada.Streams.Stream_Element_Array); - - procedure Flush - (Stream : in out Stream_Type; - Mode : in Flush_Mode := Sync_Flush); - -- Flush the written data to the back stream, - -- all data placed to the compressor is flushing to the Back stream. - -- Should not be used until necessary, because it is decreasing - -- compression. - - function Read_Total_In (Stream : in Stream_Type) return Count; - pragma Inline (Read_Total_In); - -- Return total number of bytes read from back stream so far. - - function Read_Total_Out (Stream : in Stream_Type) return Count; - pragma Inline (Read_Total_Out); - -- Return total number of bytes read so far. - - function Write_Total_In (Stream : in Stream_Type) return Count; - pragma Inline (Write_Total_In); - -- Return total number of bytes written so far. - - function Write_Total_Out (Stream : in Stream_Type) return Count; - pragma Inline (Write_Total_Out); - -- Return total number of bytes written to the back stream. - - procedure Create - (Stream : out Stream_Type; - Mode : in Stream_Mode; - Back : in Stream_Access; - Back_Compressed : in Boolean; - Level : in Compression_Level := Default_Compression; - Strategy : in Strategy_Type := Default_Strategy; - Header : in Header_Type := Default; - Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset - := Default_Buffer_Size; - Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset - := Default_Buffer_Size); - -- Create the Comression/Decompression stream. - -- If mode is In_Stream then Write operation is disabled. - -- If mode is Out_Stream then Read operation is disabled. - - -- If Back_Compressed is true then - -- Data written to the Stream is compressing to the Back stream - -- and data read from the Stream is decompressed data from the Back stream. - - -- If Back_Compressed is false then - -- Data written to the Stream is decompressing to the Back stream - -- and data read from the Stream is compressed data from the Back stream. - - -- !!! When the Need_Header is False ZLib-Ada is using undocumented - -- ZLib 1.1.4 functionality to do not create/wait for ZLib headers. - - function Is_Open (Stream : Stream_Type) return Boolean; - - procedure Close (Stream : in out Stream_Type); - -private - - use Ada.Streams; - - type Buffer_Access is access all Stream_Element_Array; - - type Stream_Type - is new Root_Stream_Type with - record - Mode : Stream_Mode; - - Buffer : Buffer_Access; - Rest_First : Stream_Element_Offset; - Rest_Last : Stream_Element_Offset; - -- Buffer for Read operation. - -- We need to have this buffer in the record - -- because not all read data from back stream - -- could be processed during the read operation. - - Buffer_Size : Stream_Element_Offset; - -- Buffer size for write operation. - -- We do not need to have this buffer - -- in the record because all data could be - -- processed in the write operation. - - Back : Stream_Access; - Reader : Filter_Type; - Writer : Filter_Type; - end record; - -end ZLib.Streams; diff --git a/deps/zlib/contrib/ada/zlib-thin.adb b/deps/zlib/contrib/ada/zlib-thin.adb deleted file mode 100644 index 0ca4a712046af8..00000000000000 --- a/deps/zlib/contrib/ada/zlib-thin.adb +++ /dev/null @@ -1,141 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2003 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- - --- $Id: zlib-thin.adb,v 1.8 2003/12/14 18:27:31 vagul Exp $ - -package body ZLib.Thin is - - ZLIB_VERSION : constant Chars_Ptr := zlibVersion; - - Z_Stream_Size : constant Int := Z_Stream'Size / System.Storage_Unit; - - -------------- - -- Avail_In -- - -------------- - - function Avail_In (Strm : in Z_Stream) return UInt is - begin - return Strm.Avail_In; - end Avail_In; - - --------------- - -- Avail_Out -- - --------------- - - function Avail_Out (Strm : in Z_Stream) return UInt is - begin - return Strm.Avail_Out; - end Avail_Out; - - ------------------ - -- Deflate_Init -- - ------------------ - - function Deflate_Init - (strm : Z_Streamp; - level : Int; - method : Int; - windowBits : Int; - memLevel : Int; - strategy : Int) - return Int is - begin - return deflateInit2 - (strm, - level, - method, - windowBits, - memLevel, - strategy, - ZLIB_VERSION, - Z_Stream_Size); - end Deflate_Init; - - ------------------ - -- Inflate_Init -- - ------------------ - - function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int is - begin - return inflateInit2 (strm, windowBits, ZLIB_VERSION, Z_Stream_Size); - end Inflate_Init; - - ------------------------ - -- Last_Error_Message -- - ------------------------ - - function Last_Error_Message (Strm : in Z_Stream) return String is - use Interfaces.C.Strings; - begin - if Strm.msg = Null_Ptr then - return ""; - else - return Value (Strm.msg); - end if; - end Last_Error_Message; - - ------------ - -- Set_In -- - ------------ - - procedure Set_In - (Strm : in out Z_Stream; - Buffer : in Voidp; - Size : in UInt) is - begin - Strm.Next_In := Buffer; - Strm.Avail_In := Size; - end Set_In; - - ------------------ - -- Set_Mem_Func -- - ------------------ - - procedure Set_Mem_Func - (Strm : in out Z_Stream; - Opaque : in Voidp; - Alloc : in alloc_func; - Free : in free_func) is - begin - Strm.opaque := Opaque; - Strm.zalloc := Alloc; - Strm.zfree := Free; - end Set_Mem_Func; - - ------------- - -- Set_Out -- - ------------- - - procedure Set_Out - (Strm : in out Z_Stream; - Buffer : in Voidp; - Size : in UInt) is - begin - Strm.Next_Out := Buffer; - Strm.Avail_Out := Size; - end Set_Out; - - -------------- - -- Total_In -- - -------------- - - function Total_In (Strm : in Z_Stream) return ULong is - begin - return Strm.Total_In; - end Total_In; - - --------------- - -- Total_Out -- - --------------- - - function Total_Out (Strm : in Z_Stream) return ULong is - begin - return Strm.Total_Out; - end Total_Out; - -end ZLib.Thin; diff --git a/deps/zlib/contrib/ada/zlib-thin.ads b/deps/zlib/contrib/ada/zlib-thin.ads deleted file mode 100644 index 810173cff86fa6..00000000000000 --- a/deps/zlib/contrib/ada/zlib-thin.ads +++ /dev/null @@ -1,450 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2003 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- - --- $Id: zlib-thin.ads,v 1.11 2004/07/23 06:33:11 vagul Exp $ - -with Interfaces.C.Strings; - -with System; - -private package ZLib.Thin is - - -- From zconf.h - - MAX_MEM_LEVEL : constant := 9; -- zconf.h:105 - -- zconf.h:105 - MAX_WBITS : constant := 15; -- zconf.h:115 - -- 32K LZ77 window - -- zconf.h:115 - SEEK_SET : constant := 8#0000#; -- zconf.h:244 - -- Seek from beginning of file. - -- zconf.h:244 - SEEK_CUR : constant := 1; -- zconf.h:245 - -- Seek from current position. - -- zconf.h:245 - SEEK_END : constant := 2; -- zconf.h:246 - -- Set file pointer to EOF plus "offset" - -- zconf.h:246 - - type Byte is new Interfaces.C.unsigned_char; -- 8 bits - -- zconf.h:214 - type UInt is new Interfaces.C.unsigned; -- 16 bits or more - -- zconf.h:216 - type Int is new Interfaces.C.int; - - type ULong is new Interfaces.C.unsigned_long; -- 32 bits or more - -- zconf.h:217 - subtype Chars_Ptr is Interfaces.C.Strings.chars_ptr; - - type ULong_Access is access ULong; - type Int_Access is access Int; - - subtype Voidp is System.Address; -- zconf.h:232 - - subtype Byte_Access is Voidp; - - Nul : constant Voidp := System.Null_Address; - -- end from zconf - - Z_NO_FLUSH : constant := 8#0000#; -- zlib.h:125 - -- zlib.h:125 - Z_PARTIAL_FLUSH : constant := 1; -- zlib.h:126 - -- will be removed, use - -- Z_SYNC_FLUSH instead - -- zlib.h:126 - Z_SYNC_FLUSH : constant := 2; -- zlib.h:127 - -- zlib.h:127 - Z_FULL_FLUSH : constant := 3; -- zlib.h:128 - -- zlib.h:128 - Z_FINISH : constant := 4; -- zlib.h:129 - -- zlib.h:129 - Z_OK : constant := 8#0000#; -- zlib.h:132 - -- zlib.h:132 - Z_STREAM_END : constant := 1; -- zlib.h:133 - -- zlib.h:133 - Z_NEED_DICT : constant := 2; -- zlib.h:134 - -- zlib.h:134 - Z_ERRNO : constant := -1; -- zlib.h:135 - -- zlib.h:135 - Z_STREAM_ERROR : constant := -2; -- zlib.h:136 - -- zlib.h:136 - Z_DATA_ERROR : constant := -3; -- zlib.h:137 - -- zlib.h:137 - Z_MEM_ERROR : constant := -4; -- zlib.h:138 - -- zlib.h:138 - Z_BUF_ERROR : constant := -5; -- zlib.h:139 - -- zlib.h:139 - Z_VERSION_ERROR : constant := -6; -- zlib.h:140 - -- zlib.h:140 - Z_NO_COMPRESSION : constant := 8#0000#; -- zlib.h:145 - -- zlib.h:145 - Z_BEST_SPEED : constant := 1; -- zlib.h:146 - -- zlib.h:146 - Z_BEST_COMPRESSION : constant := 9; -- zlib.h:147 - -- zlib.h:147 - Z_DEFAULT_COMPRESSION : constant := -1; -- zlib.h:148 - -- zlib.h:148 - Z_FILTERED : constant := 1; -- zlib.h:151 - -- zlib.h:151 - Z_HUFFMAN_ONLY : constant := 2; -- zlib.h:152 - -- zlib.h:152 - Z_DEFAULT_STRATEGY : constant := 8#0000#; -- zlib.h:153 - -- zlib.h:153 - Z_BINARY : constant := 8#0000#; -- zlib.h:156 - -- zlib.h:156 - Z_ASCII : constant := 1; -- zlib.h:157 - -- zlib.h:157 - Z_UNKNOWN : constant := 2; -- zlib.h:158 - -- zlib.h:158 - Z_DEFLATED : constant := 8; -- zlib.h:161 - -- zlib.h:161 - Z_NULL : constant := 8#0000#; -- zlib.h:164 - -- for initializing zalloc, zfree, opaque - -- zlib.h:164 - type gzFile is new Voidp; -- zlib.h:646 - - type Z_Stream is private; - - type Z_Streamp is access all Z_Stream; -- zlib.h:89 - - type alloc_func is access function - (Opaque : Voidp; - Items : UInt; - Size : UInt) - return Voidp; -- zlib.h:63 - - type free_func is access procedure (opaque : Voidp; address : Voidp); - - function zlibVersion return Chars_Ptr; - - function Deflate (strm : Z_Streamp; flush : Int) return Int; - - function DeflateEnd (strm : Z_Streamp) return Int; - - function Inflate (strm : Z_Streamp; flush : Int) return Int; - - function InflateEnd (strm : Z_Streamp) return Int; - - function deflateSetDictionary - (strm : Z_Streamp; - dictionary : Byte_Access; - dictLength : UInt) - return Int; - - function deflateCopy (dest : Z_Streamp; source : Z_Streamp) return Int; - -- zlib.h:478 - - function deflateReset (strm : Z_Streamp) return Int; -- zlib.h:495 - - function deflateParams - (strm : Z_Streamp; - level : Int; - strategy : Int) - return Int; -- zlib.h:506 - - function inflateSetDictionary - (strm : Z_Streamp; - dictionary : Byte_Access; - dictLength : UInt) - return Int; -- zlib.h:548 - - function inflateSync (strm : Z_Streamp) return Int; -- zlib.h:565 - - function inflateReset (strm : Z_Streamp) return Int; -- zlib.h:580 - - function compress - (dest : Byte_Access; - destLen : ULong_Access; - source : Byte_Access; - sourceLen : ULong) - return Int; -- zlib.h:601 - - function compress2 - (dest : Byte_Access; - destLen : ULong_Access; - source : Byte_Access; - sourceLen : ULong; - level : Int) - return Int; -- zlib.h:615 - - function uncompress - (dest : Byte_Access; - destLen : ULong_Access; - source : Byte_Access; - sourceLen : ULong) - return Int; - - function gzopen (path : Chars_Ptr; mode : Chars_Ptr) return gzFile; - - function gzdopen (fd : Int; mode : Chars_Ptr) return gzFile; - - function gzsetparams - (file : gzFile; - level : Int; - strategy : Int) - return Int; - - function gzread - (file : gzFile; - buf : Voidp; - len : UInt) - return Int; - - function gzwrite - (file : in gzFile; - buf : in Voidp; - len : in UInt) - return Int; - - function gzprintf (file : in gzFile; format : in Chars_Ptr) return Int; - - function gzputs (file : in gzFile; s : in Chars_Ptr) return Int; - - function gzgets - (file : gzFile; - buf : Chars_Ptr; - len : Int) - return Chars_Ptr; - - function gzputc (file : gzFile; char : Int) return Int; - - function gzgetc (file : gzFile) return Int; - - function gzflush (file : gzFile; flush : Int) return Int; - - function gzseek - (file : gzFile; - offset : Int; - whence : Int) - return Int; - - function gzrewind (file : gzFile) return Int; - - function gztell (file : gzFile) return Int; - - function gzeof (file : gzFile) return Int; - - function gzclose (file : gzFile) return Int; - - function gzerror (file : gzFile; errnum : Int_Access) return Chars_Ptr; - - function adler32 - (adler : ULong; - buf : Byte_Access; - len : UInt) - return ULong; - - function crc32 - (crc : ULong; - buf : Byte_Access; - len : UInt) - return ULong; - - function deflateInit - (strm : Z_Streamp; - level : Int; - version : Chars_Ptr; - stream_size : Int) - return Int; - - function deflateInit2 - (strm : Z_Streamp; - level : Int; - method : Int; - windowBits : Int; - memLevel : Int; - strategy : Int; - version : Chars_Ptr; - stream_size : Int) - return Int; - - function Deflate_Init - (strm : Z_Streamp; - level : Int; - method : Int; - windowBits : Int; - memLevel : Int; - strategy : Int) - return Int; - pragma Inline (Deflate_Init); - - function inflateInit - (strm : Z_Streamp; - version : Chars_Ptr; - stream_size : Int) - return Int; - - function inflateInit2 - (strm : in Z_Streamp; - windowBits : in Int; - version : in Chars_Ptr; - stream_size : in Int) - return Int; - - function inflateBackInit - (strm : in Z_Streamp; - windowBits : in Int; - window : in Byte_Access; - version : in Chars_Ptr; - stream_size : in Int) - return Int; - -- Size of window have to be 2**windowBits. - - function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int; - pragma Inline (Inflate_Init); - - function zError (err : Int) return Chars_Ptr; - - function inflateSyncPoint (z : Z_Streamp) return Int; - - function get_crc_table return ULong_Access; - - -- Interface to the available fields of the z_stream structure. - -- The application must update next_in and avail_in when avail_in has - -- dropped to zero. It must update next_out and avail_out when avail_out - -- has dropped to zero. The application must initialize zalloc, zfree and - -- opaque before calling the init function. - - procedure Set_In - (Strm : in out Z_Stream; - Buffer : in Voidp; - Size : in UInt); - pragma Inline (Set_In); - - procedure Set_Out - (Strm : in out Z_Stream; - Buffer : in Voidp; - Size : in UInt); - pragma Inline (Set_Out); - - procedure Set_Mem_Func - (Strm : in out Z_Stream; - Opaque : in Voidp; - Alloc : in alloc_func; - Free : in free_func); - pragma Inline (Set_Mem_Func); - - function Last_Error_Message (Strm : in Z_Stream) return String; - pragma Inline (Last_Error_Message); - - function Avail_Out (Strm : in Z_Stream) return UInt; - pragma Inline (Avail_Out); - - function Avail_In (Strm : in Z_Stream) return UInt; - pragma Inline (Avail_In); - - function Total_In (Strm : in Z_Stream) return ULong; - pragma Inline (Total_In); - - function Total_Out (Strm : in Z_Stream) return ULong; - pragma Inline (Total_Out); - - function inflateCopy - (dest : in Z_Streamp; - Source : in Z_Streamp) - return Int; - - function compressBound (Source_Len : in ULong) return ULong; - - function deflateBound - (Strm : in Z_Streamp; - Source_Len : in ULong) - return ULong; - - function gzungetc (C : in Int; File : in gzFile) return Int; - - function zlibCompileFlags return ULong; - -private - - type Z_Stream is record -- zlib.h:68 - Next_In : Voidp := Nul; -- next input byte - Avail_In : UInt := 0; -- number of bytes available at next_in - Total_In : ULong := 0; -- total nb of input bytes read so far - Next_Out : Voidp := Nul; -- next output byte should be put there - Avail_Out : UInt := 0; -- remaining free space at next_out - Total_Out : ULong := 0; -- total nb of bytes output so far - msg : Chars_Ptr; -- last error message, NULL if no error - state : Voidp; -- not visible by applications - zalloc : alloc_func := null; -- used to allocate the internal state - zfree : free_func := null; -- used to free the internal state - opaque : Voidp; -- private data object passed to - -- zalloc and zfree - data_type : Int; -- best guess about the data type: - -- ascii or binary - adler : ULong; -- adler32 value of the uncompressed - -- data - reserved : ULong; -- reserved for future use - end record; - - pragma Convention (C, Z_Stream); - - pragma Import (C, zlibVersion, "zlibVersion"); - pragma Import (C, Deflate, "deflate"); - pragma Import (C, DeflateEnd, "deflateEnd"); - pragma Import (C, Inflate, "inflate"); - pragma Import (C, InflateEnd, "inflateEnd"); - pragma Import (C, deflateSetDictionary, "deflateSetDictionary"); - pragma Import (C, deflateCopy, "deflateCopy"); - pragma Import (C, deflateReset, "deflateReset"); - pragma Import (C, deflateParams, "deflateParams"); - pragma Import (C, inflateSetDictionary, "inflateSetDictionary"); - pragma Import (C, inflateSync, "inflateSync"); - pragma Import (C, inflateReset, "inflateReset"); - pragma Import (C, compress, "compress"); - pragma Import (C, compress2, "compress2"); - pragma Import (C, uncompress, "uncompress"); - pragma Import (C, gzopen, "gzopen"); - pragma Import (C, gzdopen, "gzdopen"); - pragma Import (C, gzsetparams, "gzsetparams"); - pragma Import (C, gzread, "gzread"); - pragma Import (C, gzwrite, "gzwrite"); - pragma Import (C, gzprintf, "gzprintf"); - pragma Import (C, gzputs, "gzputs"); - pragma Import (C, gzgets, "gzgets"); - pragma Import (C, gzputc, "gzputc"); - pragma Import (C, gzgetc, "gzgetc"); - pragma Import (C, gzflush, "gzflush"); - pragma Import (C, gzseek, "gzseek"); - pragma Import (C, gzrewind, "gzrewind"); - pragma Import (C, gztell, "gztell"); - pragma Import (C, gzeof, "gzeof"); - pragma Import (C, gzclose, "gzclose"); - pragma Import (C, gzerror, "gzerror"); - pragma Import (C, adler32, "adler32"); - pragma Import (C, crc32, "crc32"); - pragma Import (C, deflateInit, "deflateInit_"); - pragma Import (C, inflateInit, "inflateInit_"); - pragma Import (C, deflateInit2, "deflateInit2_"); - pragma Import (C, inflateInit2, "inflateInit2_"); - pragma Import (C, zError, "zError"); - pragma Import (C, inflateSyncPoint, "inflateSyncPoint"); - pragma Import (C, get_crc_table, "get_crc_table"); - - -- since zlib 1.2.0: - - pragma Import (C, inflateCopy, "inflateCopy"); - pragma Import (C, compressBound, "compressBound"); - pragma Import (C, deflateBound, "deflateBound"); - pragma Import (C, gzungetc, "gzungetc"); - pragma Import (C, zlibCompileFlags, "zlibCompileFlags"); - - pragma Import (C, inflateBackInit, "inflateBackInit_"); - - -- I stopped binding the inflateBack routines, because realize that - -- it does not support zlib and gzip headers for now, and have no - -- symmetric deflateBack routines. - -- ZLib-Ada is symmetric regarding deflate/inflate data transformation - -- and has a similar generic callback interface for the - -- deflate/inflate transformation based on the regular Deflate/Inflate - -- routines. - - -- pragma Import (C, inflateBack, "inflateBack"); - -- pragma Import (C, inflateBackEnd, "inflateBackEnd"); - -end ZLib.Thin; diff --git a/deps/zlib/contrib/ada/zlib.adb b/deps/zlib/contrib/ada/zlib.adb deleted file mode 100644 index 8b6fd686ac77ec..00000000000000 --- a/deps/zlib/contrib/ada/zlib.adb +++ /dev/null @@ -1,701 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2004 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- - --- $Id: zlib.adb,v 1.31 2004/09/06 06:53:19 vagul Exp $ - -with Ada.Exceptions; -with Ada.Unchecked_Conversion; -with Ada.Unchecked_Deallocation; - -with Interfaces.C.Strings; - -with ZLib.Thin; - -package body ZLib is - - use type Thin.Int; - - type Z_Stream is new Thin.Z_Stream; - - type Return_Code_Enum is - (OK, - STREAM_END, - NEED_DICT, - ERRNO, - STREAM_ERROR, - DATA_ERROR, - MEM_ERROR, - BUF_ERROR, - VERSION_ERROR); - - type Flate_Step_Function is access - function (Strm : in Thin.Z_Streamp; Flush : in Thin.Int) return Thin.Int; - pragma Convention (C, Flate_Step_Function); - - type Flate_End_Function is access - function (Ctrm : in Thin.Z_Streamp) return Thin.Int; - pragma Convention (C, Flate_End_Function); - - type Flate_Type is record - Step : Flate_Step_Function; - Done : Flate_End_Function; - end record; - - subtype Footer_Array is Stream_Element_Array (1 .. 8); - - Simple_GZip_Header : constant Stream_Element_Array (1 .. 10) - := (16#1f#, 16#8b#, -- Magic header - 16#08#, -- Z_DEFLATED - 16#00#, -- Flags - 16#00#, 16#00#, 16#00#, 16#00#, -- Time - 16#00#, -- XFlags - 16#03# -- OS code - ); - -- The simplest gzip header is not for informational, but just for - -- gzip format compatibility. - -- Note that some code below is using assumption - -- Simple_GZip_Header'Last > Footer_Array'Last, so do not make - -- Simple_GZip_Header'Last <= Footer_Array'Last. - - Return_Code : constant array (Thin.Int range <>) of Return_Code_Enum - := (0 => OK, - 1 => STREAM_END, - 2 => NEED_DICT, - -1 => ERRNO, - -2 => STREAM_ERROR, - -3 => DATA_ERROR, - -4 => MEM_ERROR, - -5 => BUF_ERROR, - -6 => VERSION_ERROR); - - Flate : constant array (Boolean) of Flate_Type - := (True => (Step => Thin.Deflate'Access, - Done => Thin.DeflateEnd'Access), - False => (Step => Thin.Inflate'Access, - Done => Thin.InflateEnd'Access)); - - Flush_Finish : constant array (Boolean) of Flush_Mode - := (True => Finish, False => No_Flush); - - procedure Raise_Error (Stream : in Z_Stream); - pragma Inline (Raise_Error); - - procedure Raise_Error (Message : in String); - pragma Inline (Raise_Error); - - procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int); - - procedure Free is new Ada.Unchecked_Deallocation - (Z_Stream, Z_Stream_Access); - - function To_Thin_Access is new Ada.Unchecked_Conversion - (Z_Stream_Access, Thin.Z_Streamp); - - procedure Translate_GZip - (Filter : in out Filter_Type; - In_Data : in Ada.Streams.Stream_Element_Array; - In_Last : out Ada.Streams.Stream_Element_Offset; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode); - -- Separate translate routine for make gzip header. - - procedure Translate_Auto - (Filter : in out Filter_Type; - In_Data : in Ada.Streams.Stream_Element_Array; - In_Last : out Ada.Streams.Stream_Element_Offset; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode); - -- translate routine without additional headers. - - ----------------- - -- Check_Error -- - ----------------- - - procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int) is - use type Thin.Int; - begin - if Code /= Thin.Z_OK then - Raise_Error - (Return_Code_Enum'Image (Return_Code (Code)) - & ": " & Last_Error_Message (Stream)); - end if; - end Check_Error; - - ----------- - -- Close -- - ----------- - - procedure Close - (Filter : in out Filter_Type; - Ignore_Error : in Boolean := False) - is - Code : Thin.Int; - begin - if not Ignore_Error and then not Is_Open (Filter) then - raise Status_Error; - end if; - - Code := Flate (Filter.Compression).Done (To_Thin_Access (Filter.Strm)); - - if Ignore_Error or else Code = Thin.Z_OK then - Free (Filter.Strm); - else - declare - Error_Message : constant String - := Last_Error_Message (Filter.Strm.all); - begin - Free (Filter.Strm); - Ada.Exceptions.Raise_Exception - (ZLib_Error'Identity, - Return_Code_Enum'Image (Return_Code (Code)) - & ": " & Error_Message); - end; - end if; - end Close; - - ----------- - -- CRC32 -- - ----------- - - function CRC32 - (CRC : in Unsigned_32; - Data : in Ada.Streams.Stream_Element_Array) - return Unsigned_32 - is - use Thin; - begin - return Unsigned_32 (crc32 (ULong (CRC), - Data'Address, - Data'Length)); - end CRC32; - - procedure CRC32 - (CRC : in out Unsigned_32; - Data : in Ada.Streams.Stream_Element_Array) is - begin - CRC := CRC32 (CRC, Data); - end CRC32; - - ------------------ - -- Deflate_Init -- - ------------------ - - procedure Deflate_Init - (Filter : in out Filter_Type; - Level : in Compression_Level := Default_Compression; - Strategy : in Strategy_Type := Default_Strategy; - Method : in Compression_Method := Deflated; - Window_Bits : in Window_Bits_Type := Default_Window_Bits; - Memory_Level : in Memory_Level_Type := Default_Memory_Level; - Header : in Header_Type := Default) - is - use type Thin.Int; - Win_Bits : Thin.Int := Thin.Int (Window_Bits); - begin - if Is_Open (Filter) then - raise Status_Error; - end if; - - -- We allow ZLib to make header only in case of default header type. - -- Otherwise we would either do header by ourselfs, or do not do - -- header at all. - - if Header = None or else Header = GZip then - Win_Bits := -Win_Bits; - end if; - - -- For the GZip CRC calculation and make headers. - - if Header = GZip then - Filter.CRC := 0; - Filter.Offset := Simple_GZip_Header'First; - else - Filter.Offset := Simple_GZip_Header'Last + 1; - end if; - - Filter.Strm := new Z_Stream; - Filter.Compression := True; - Filter.Stream_End := False; - Filter.Header := Header; - - if Thin.Deflate_Init - (To_Thin_Access (Filter.Strm), - Level => Thin.Int (Level), - method => Thin.Int (Method), - windowBits => Win_Bits, - memLevel => Thin.Int (Memory_Level), - strategy => Thin.Int (Strategy)) /= Thin.Z_OK - then - Raise_Error (Filter.Strm.all); - end if; - end Deflate_Init; - - ----------- - -- Flush -- - ----------- - - procedure Flush - (Filter : in out Filter_Type; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode) - is - No_Data : Stream_Element_Array := (1 .. 0 => 0); - Last : Stream_Element_Offset; - begin - Translate (Filter, No_Data, Last, Out_Data, Out_Last, Flush); - end Flush; - - ----------------------- - -- Generic_Translate -- - ----------------------- - - procedure Generic_Translate - (Filter : in out ZLib.Filter_Type; - In_Buffer_Size : in Integer := Default_Buffer_Size; - Out_Buffer_Size : in Integer := Default_Buffer_Size) - is - In_Buffer : Stream_Element_Array - (1 .. Stream_Element_Offset (In_Buffer_Size)); - Out_Buffer : Stream_Element_Array - (1 .. Stream_Element_Offset (Out_Buffer_Size)); - Last : Stream_Element_Offset; - In_Last : Stream_Element_Offset; - In_First : Stream_Element_Offset; - Out_Last : Stream_Element_Offset; - begin - Main : loop - Data_In (In_Buffer, Last); - - In_First := In_Buffer'First; - - loop - Translate - (Filter => Filter, - In_Data => In_Buffer (In_First .. Last), - In_Last => In_Last, - Out_Data => Out_Buffer, - Out_Last => Out_Last, - Flush => Flush_Finish (Last < In_Buffer'First)); - - if Out_Buffer'First <= Out_Last then - Data_Out (Out_Buffer (Out_Buffer'First .. Out_Last)); - end if; - - exit Main when Stream_End (Filter); - - -- The end of in buffer. - - exit when In_Last = Last; - - In_First := In_Last + 1; - end loop; - end loop Main; - - end Generic_Translate; - - ------------------ - -- Inflate_Init -- - ------------------ - - procedure Inflate_Init - (Filter : in out Filter_Type; - Window_Bits : in Window_Bits_Type := Default_Window_Bits; - Header : in Header_Type := Default) - is - use type Thin.Int; - Win_Bits : Thin.Int := Thin.Int (Window_Bits); - - procedure Check_Version; - -- Check the latest header types compatibility. - - procedure Check_Version is - begin - if Version <= "1.1.4" then - Raise_Error - ("Inflate header type " & Header_Type'Image (Header) - & " incompatible with ZLib version " & Version); - end if; - end Check_Version; - - begin - if Is_Open (Filter) then - raise Status_Error; - end if; - - case Header is - when None => - Check_Version; - - -- Inflate data without headers determined - -- by negative Win_Bits. - - Win_Bits := -Win_Bits; - when GZip => - Check_Version; - - -- Inflate gzip data defined by flag 16. - - Win_Bits := Win_Bits + 16; - when Auto => - Check_Version; - - -- Inflate with automatic detection - -- of gzip or native header defined by flag 32. - - Win_Bits := Win_Bits + 32; - when Default => null; - end case; - - Filter.Strm := new Z_Stream; - Filter.Compression := False; - Filter.Stream_End := False; - Filter.Header := Header; - - if Thin.Inflate_Init - (To_Thin_Access (Filter.Strm), Win_Bits) /= Thin.Z_OK - then - Raise_Error (Filter.Strm.all); - end if; - end Inflate_Init; - - ------------- - -- Is_Open -- - ------------- - - function Is_Open (Filter : in Filter_Type) return Boolean is - begin - return Filter.Strm /= null; - end Is_Open; - - ----------------- - -- Raise_Error -- - ----------------- - - procedure Raise_Error (Message : in String) is - begin - Ada.Exceptions.Raise_Exception (ZLib_Error'Identity, Message); - end Raise_Error; - - procedure Raise_Error (Stream : in Z_Stream) is - begin - Raise_Error (Last_Error_Message (Stream)); - end Raise_Error; - - ---------- - -- Read -- - ---------- - - procedure Read - (Filter : in out Filter_Type; - Item : out Ada.Streams.Stream_Element_Array; - Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode := No_Flush) - is - In_Last : Stream_Element_Offset; - Item_First : Ada.Streams.Stream_Element_Offset := Item'First; - V_Flush : Flush_Mode := Flush; - - begin - pragma Assert (Rest_First in Buffer'First .. Buffer'Last + 1); - pragma Assert (Rest_Last in Buffer'First - 1 .. Buffer'Last); - - loop - if Rest_Last = Buffer'First - 1 then - V_Flush := Finish; - - elsif Rest_First > Rest_Last then - Read (Buffer, Rest_Last); - Rest_First := Buffer'First; - - if Rest_Last < Buffer'First then - V_Flush := Finish; - end if; - end if; - - Translate - (Filter => Filter, - In_Data => Buffer (Rest_First .. Rest_Last), - In_Last => In_Last, - Out_Data => Item (Item_First .. Item'Last), - Out_Last => Last, - Flush => V_Flush); - - Rest_First := In_Last + 1; - - exit when Stream_End (Filter) - or else Last = Item'Last - or else (Last >= Item'First and then Allow_Read_Some); - - Item_First := Last + 1; - end loop; - end Read; - - ---------------- - -- Stream_End -- - ---------------- - - function Stream_End (Filter : in Filter_Type) return Boolean is - begin - if Filter.Header = GZip and Filter.Compression then - return Filter.Stream_End - and then Filter.Offset = Footer_Array'Last + 1; - else - return Filter.Stream_End; - end if; - end Stream_End; - - -------------- - -- Total_In -- - -------------- - - function Total_In (Filter : in Filter_Type) return Count is - begin - return Count (Thin.Total_In (To_Thin_Access (Filter.Strm).all)); - end Total_In; - - --------------- - -- Total_Out -- - --------------- - - function Total_Out (Filter : in Filter_Type) return Count is - begin - return Count (Thin.Total_Out (To_Thin_Access (Filter.Strm).all)); - end Total_Out; - - --------------- - -- Translate -- - --------------- - - procedure Translate - (Filter : in out Filter_Type; - In_Data : in Ada.Streams.Stream_Element_Array; - In_Last : out Ada.Streams.Stream_Element_Offset; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode) is - begin - if Filter.Header = GZip and then Filter.Compression then - Translate_GZip - (Filter => Filter, - In_Data => In_Data, - In_Last => In_Last, - Out_Data => Out_Data, - Out_Last => Out_Last, - Flush => Flush); - else - Translate_Auto - (Filter => Filter, - In_Data => In_Data, - In_Last => In_Last, - Out_Data => Out_Data, - Out_Last => Out_Last, - Flush => Flush); - end if; - end Translate; - - -------------------- - -- Translate_Auto -- - -------------------- - - procedure Translate_Auto - (Filter : in out Filter_Type; - In_Data : in Ada.Streams.Stream_Element_Array; - In_Last : out Ada.Streams.Stream_Element_Offset; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode) - is - use type Thin.Int; - Code : Thin.Int; - - begin - if not Is_Open (Filter) then - raise Status_Error; - end if; - - if Out_Data'Length = 0 and then In_Data'Length = 0 then - raise Constraint_Error; - end if; - - Set_Out (Filter.Strm.all, Out_Data'Address, Out_Data'Length); - Set_In (Filter.Strm.all, In_Data'Address, In_Data'Length); - - Code := Flate (Filter.Compression).Step - (To_Thin_Access (Filter.Strm), - Thin.Int (Flush)); - - if Code = Thin.Z_STREAM_END then - Filter.Stream_End := True; - else - Check_Error (Filter.Strm.all, Code); - end if; - - In_Last := In_Data'Last - - Stream_Element_Offset (Avail_In (Filter.Strm.all)); - Out_Last := Out_Data'Last - - Stream_Element_Offset (Avail_Out (Filter.Strm.all)); - end Translate_Auto; - - -------------------- - -- Translate_GZip -- - -------------------- - - procedure Translate_GZip - (Filter : in out Filter_Type; - In_Data : in Ada.Streams.Stream_Element_Array; - In_Last : out Ada.Streams.Stream_Element_Offset; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode) - is - Out_First : Stream_Element_Offset; - - procedure Add_Data (Data : in Stream_Element_Array); - -- Add data to stream from the Filter.Offset till necessary, - -- used for add gzip headr/footer. - - procedure Put_32 - (Item : in out Stream_Element_Array; - Data : in Unsigned_32); - pragma Inline (Put_32); - - -------------- - -- Add_Data -- - -------------- - - procedure Add_Data (Data : in Stream_Element_Array) is - Data_First : Stream_Element_Offset renames Filter.Offset; - Data_Last : Stream_Element_Offset; - Data_Len : Stream_Element_Offset; -- -1 - Out_Len : Stream_Element_Offset; -- -1 - begin - Out_First := Out_Last + 1; - - if Data_First > Data'Last then - return; - end if; - - Data_Len := Data'Last - Data_First; - Out_Len := Out_Data'Last - Out_First; - - if Data_Len <= Out_Len then - Out_Last := Out_First + Data_Len; - Data_Last := Data'Last; - else - Out_Last := Out_Data'Last; - Data_Last := Data_First + Out_Len; - end if; - - Out_Data (Out_First .. Out_Last) := Data (Data_First .. Data_Last); - - Data_First := Data_Last + 1; - Out_First := Out_Last + 1; - end Add_Data; - - ------------ - -- Put_32 -- - ------------ - - procedure Put_32 - (Item : in out Stream_Element_Array; - Data : in Unsigned_32) - is - D : Unsigned_32 := Data; - begin - for J in Item'First .. Item'First + 3 loop - Item (J) := Stream_Element (D and 16#FF#); - D := Shift_Right (D, 8); - end loop; - end Put_32; - - begin - Out_Last := Out_Data'First - 1; - - if not Filter.Stream_End then - Add_Data (Simple_GZip_Header); - - Translate_Auto - (Filter => Filter, - In_Data => In_Data, - In_Last => In_Last, - Out_Data => Out_Data (Out_First .. Out_Data'Last), - Out_Last => Out_Last, - Flush => Flush); - - CRC32 (Filter.CRC, In_Data (In_Data'First .. In_Last)); - end if; - - if Filter.Stream_End and then Out_Last <= Out_Data'Last then - -- This detection method would work only when - -- Simple_GZip_Header'Last > Footer_Array'Last - - if Filter.Offset = Simple_GZip_Header'Last + 1 then - Filter.Offset := Footer_Array'First; - end if; - - declare - Footer : Footer_Array; - begin - Put_32 (Footer, Filter.CRC); - Put_32 (Footer (Footer'First + 4 .. Footer'Last), - Unsigned_32 (Total_In (Filter))); - Add_Data (Footer); - end; - end if; - end Translate_GZip; - - ------------- - -- Version -- - ------------- - - function Version return String is - begin - return Interfaces.C.Strings.Value (Thin.zlibVersion); - end Version; - - ----------- - -- Write -- - ----------- - - procedure Write - (Filter : in out Filter_Type; - Item : in Ada.Streams.Stream_Element_Array; - Flush : in Flush_Mode := No_Flush) - is - Buffer : Stream_Element_Array (1 .. Buffer_Size); - In_Last : Stream_Element_Offset; - Out_Last : Stream_Element_Offset; - In_First : Stream_Element_Offset := Item'First; - begin - if Item'Length = 0 and Flush = No_Flush then - return; - end if; - - loop - Translate - (Filter => Filter, - In_Data => Item (In_First .. Item'Last), - In_Last => In_Last, - Out_Data => Buffer, - Out_Last => Out_Last, - Flush => Flush); - - if Out_Last >= Buffer'First then - Write (Buffer (1 .. Out_Last)); - end if; - - exit when In_Last = Item'Last or Stream_End (Filter); - - In_First := In_Last + 1; - end loop; - end Write; - -end ZLib; diff --git a/deps/zlib/contrib/ada/zlib.ads b/deps/zlib/contrib/ada/zlib.ads deleted file mode 100644 index 79ffc4095cf46f..00000000000000 --- a/deps/zlib/contrib/ada/zlib.ads +++ /dev/null @@ -1,328 +0,0 @@ ------------------------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2004 Dmitriy Anisimkov -- --- -- --- This library is free software; you can redistribute it and/or modify -- --- it under the terms of the GNU General Public License as published by -- --- the Free Software Foundation; either version 2 of the License, or (at -- --- your option) any later version. -- --- -- --- This library is distributed in the hope that it will be useful, but -- --- WITHOUT ANY WARRANTY; without even the implied warranty of -- --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- --- General Public License for more details. -- --- -- --- You should have received a copy of the GNU General Public License -- --- along with this library; if not, write to the Free Software Foundation, -- --- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -- --- -- --- As a special exception, if other files instantiate generics from this -- --- unit, or you link this unit with other files to produce an executable, -- --- this unit does not by itself cause the resulting executable to be -- --- covered by the GNU General Public License. This exception does not -- --- however invalidate any other reasons why the executable file might be -- --- covered by the GNU Public License. -- ------------------------------------------------------------------------------- - --- $Id: zlib.ads,v 1.26 2004/09/06 06:53:19 vagul Exp $ - -with Ada.Streams; - -with Interfaces; - -package ZLib is - - ZLib_Error : exception; - Status_Error : exception; - - type Compression_Level is new Integer range -1 .. 9; - - type Flush_Mode is private; - - type Compression_Method is private; - - type Window_Bits_Type is new Integer range 8 .. 15; - - type Memory_Level_Type is new Integer range 1 .. 9; - - type Unsigned_32 is new Interfaces.Unsigned_32; - - type Strategy_Type is private; - - type Header_Type is (None, Auto, Default, GZip); - -- Header type usage have a some limitation for inflate. - -- See comment for Inflate_Init. - - subtype Count is Ada.Streams.Stream_Element_Count; - - Default_Memory_Level : constant Memory_Level_Type := 8; - Default_Window_Bits : constant Window_Bits_Type := 15; - - ---------------------------------- - -- Compression method constants -- - ---------------------------------- - - Deflated : constant Compression_Method; - -- Only one method allowed in this ZLib version - - --------------------------------- - -- Compression level constants -- - --------------------------------- - - No_Compression : constant Compression_Level := 0; - Best_Speed : constant Compression_Level := 1; - Best_Compression : constant Compression_Level := 9; - Default_Compression : constant Compression_Level := -1; - - -------------------------- - -- Flush mode constants -- - -------------------------- - - No_Flush : constant Flush_Mode; - -- Regular way for compression, no flush - - Partial_Flush : constant Flush_Mode; - -- Will be removed, use Z_SYNC_FLUSH instead - - Sync_Flush : constant Flush_Mode; - -- All pending output is flushed to the output buffer and the output - -- is aligned on a byte boundary, so that the decompressor can get all - -- input data available so far. (In particular avail_in is zero after the - -- call if enough output space has been provided before the call.) - -- Flushing may degrade compression for some compression algorithms and so - -- it should be used only when necessary. - - Block_Flush : constant Flush_Mode; - -- Z_BLOCK requests that inflate() stop - -- if and when it get to the next deflate block boundary. When decoding the - -- zlib or gzip format, this will cause inflate() to return immediately - -- after the header and before the first block. When doing a raw inflate, - -- inflate() will go ahead and process the first block, and will return - -- when it gets to the end of that block, or when it runs out of data. - - Full_Flush : constant Flush_Mode; - -- All output is flushed as with SYNC_FLUSH, and the compression state - -- is reset so that decompression can restart from this point if previous - -- compressed data has been damaged or if random access is desired. Using - -- Full_Flush too often can seriously degrade the compression. - - Finish : constant Flush_Mode; - -- Just for tell the compressor that input data is complete. - - ------------------------------------ - -- Compression strategy constants -- - ------------------------------------ - - -- RLE stategy could be used only in version 1.2.0 and later. - - Filtered : constant Strategy_Type; - Huffman_Only : constant Strategy_Type; - RLE : constant Strategy_Type; - Default_Strategy : constant Strategy_Type; - - Default_Buffer_Size : constant := 4096; - - type Filter_Type is tagged limited private; - -- The filter is for compression and for decompression. - -- The usage of the type is depend of its initialization. - - function Version return String; - pragma Inline (Version); - -- Return string representation of the ZLib version. - - procedure Deflate_Init - (Filter : in out Filter_Type; - Level : in Compression_Level := Default_Compression; - Strategy : in Strategy_Type := Default_Strategy; - Method : in Compression_Method := Deflated; - Window_Bits : in Window_Bits_Type := Default_Window_Bits; - Memory_Level : in Memory_Level_Type := Default_Memory_Level; - Header : in Header_Type := Default); - -- Compressor initialization. - -- When Header parameter is Auto or Default, then default zlib header - -- would be provided for compressed data. - -- When Header is GZip, then gzip header would be set instead of - -- default header. - -- When Header is None, no header would be set for compressed data. - - procedure Inflate_Init - (Filter : in out Filter_Type; - Window_Bits : in Window_Bits_Type := Default_Window_Bits; - Header : in Header_Type := Default); - -- Decompressor initialization. - -- Default header type mean that ZLib default header is expecting in the - -- input compressed stream. - -- Header type None mean that no header is expecting in the input stream. - -- GZip header type mean that GZip header is expecting in the - -- input compressed stream. - -- Auto header type mean that header type (GZip or Native) would be - -- detected automatically in the input stream. - -- Note that header types parameter values None, GZip and Auto are - -- supported for inflate routine only in ZLib versions 1.2.0.2 and later. - -- Deflate_Init is supporting all header types. - - function Is_Open (Filter : in Filter_Type) return Boolean; - pragma Inline (Is_Open); - -- Is the filter opened for compression or decompression. - - procedure Close - (Filter : in out Filter_Type; - Ignore_Error : in Boolean := False); - -- Closing the compression or decompressor. - -- If stream is closing before the complete and Ignore_Error is False, - -- The exception would be raised. - - generic - with procedure Data_In - (Item : out Ada.Streams.Stream_Element_Array; - Last : out Ada.Streams.Stream_Element_Offset); - with procedure Data_Out - (Item : in Ada.Streams.Stream_Element_Array); - procedure Generic_Translate - (Filter : in out Filter_Type; - In_Buffer_Size : in Integer := Default_Buffer_Size; - Out_Buffer_Size : in Integer := Default_Buffer_Size); - -- Compress/decompress data fetch from Data_In routine and pass the result - -- to the Data_Out routine. User should provide Data_In and Data_Out - -- for compression/decompression data flow. - -- Compression or decompression depend on Filter initialization. - - function Total_In (Filter : in Filter_Type) return Count; - pragma Inline (Total_In); - -- Returns total number of input bytes read so far - - function Total_Out (Filter : in Filter_Type) return Count; - pragma Inline (Total_Out); - -- Returns total number of bytes output so far - - function CRC32 - (CRC : in Unsigned_32; - Data : in Ada.Streams.Stream_Element_Array) - return Unsigned_32; - pragma Inline (CRC32); - -- Compute CRC32, it could be necessary for make gzip format - - procedure CRC32 - (CRC : in out Unsigned_32; - Data : in Ada.Streams.Stream_Element_Array); - pragma Inline (CRC32); - -- Compute CRC32, it could be necessary for make gzip format - - ------------------------------------------------- - -- Below is more complex low level routines. -- - ------------------------------------------------- - - procedure Translate - (Filter : in out Filter_Type; - In_Data : in Ada.Streams.Stream_Element_Array; - In_Last : out Ada.Streams.Stream_Element_Offset; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode); - -- Compress/decompress the In_Data buffer and place the result into - -- Out_Data. In_Last is the index of last element from In_Data accepted by - -- the Filter. Out_Last is the last element of the received data from - -- Filter. To tell the filter that incoming data are complete put the - -- Flush parameter to Finish. - - function Stream_End (Filter : in Filter_Type) return Boolean; - pragma Inline (Stream_End); - -- Return the true when the stream is complete. - - procedure Flush - (Filter : in out Filter_Type; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode); - pragma Inline (Flush); - -- Flushing the data from the compressor. - - generic - with procedure Write - (Item : in Ada.Streams.Stream_Element_Array); - -- User should provide this routine for accept - -- compressed/decompressed data. - - Buffer_Size : in Ada.Streams.Stream_Element_Offset - := Default_Buffer_Size; - -- Buffer size for Write user routine. - - procedure Write - (Filter : in out Filter_Type; - Item : in Ada.Streams.Stream_Element_Array; - Flush : in Flush_Mode := No_Flush); - -- Compress/Decompress data from Item to the generic parameter procedure - -- Write. Output buffer size could be set in Buffer_Size generic parameter. - - generic - with procedure Read - (Item : out Ada.Streams.Stream_Element_Array; - Last : out Ada.Streams.Stream_Element_Offset); - -- User should provide data for compression/decompression - -- thru this routine. - - Buffer : in out Ada.Streams.Stream_Element_Array; - -- Buffer for keep remaining data from the previous - -- back read. - - Rest_First, Rest_Last : in out Ada.Streams.Stream_Element_Offset; - -- Rest_First have to be initialized to Buffer'Last + 1 - -- Rest_Last have to be initialized to Buffer'Last - -- before usage. - - Allow_Read_Some : in Boolean := False; - -- Is it allowed to return Last < Item'Last before end of data. - - procedure Read - (Filter : in out Filter_Type; - Item : out Ada.Streams.Stream_Element_Array; - Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode := No_Flush); - -- Compress/Decompress data from generic parameter procedure Read to the - -- Item. User should provide Buffer and initialized Rest_First, Rest_Last - -- indicators. If Allow_Read_Some is True, Read routines could return - -- Last < Item'Last only at end of stream. - -private - - use Ada.Streams; - - pragma Assert (Ada.Streams.Stream_Element'Size = 8); - pragma Assert (Ada.Streams.Stream_Element'Modulus = 2**8); - - type Flush_Mode is new Integer range 0 .. 5; - - type Compression_Method is new Integer range 8 .. 8; - - type Strategy_Type is new Integer range 0 .. 3; - - No_Flush : constant Flush_Mode := 0; - Partial_Flush : constant Flush_Mode := 1; - Sync_Flush : constant Flush_Mode := 2; - Full_Flush : constant Flush_Mode := 3; - Finish : constant Flush_Mode := 4; - Block_Flush : constant Flush_Mode := 5; - - Filtered : constant Strategy_Type := 1; - Huffman_Only : constant Strategy_Type := 2; - RLE : constant Strategy_Type := 3; - Default_Strategy : constant Strategy_Type := 0; - - Deflated : constant Compression_Method := 8; - - type Z_Stream; - - type Z_Stream_Access is access all Z_Stream; - - type Filter_Type is tagged limited record - Strm : Z_Stream_Access; - Compression : Boolean; - Stream_End : Boolean; - Header : Header_Type; - CRC : Unsigned_32; - Offset : Stream_Element_Offset; - -- Offset for gzip header/footer output. - end record; - -end ZLib; diff --git a/deps/zlib/contrib/ada/zlib.gpr b/deps/zlib/contrib/ada/zlib.gpr deleted file mode 100644 index 296b22aa966706..00000000000000 --- a/deps/zlib/contrib/ada/zlib.gpr +++ /dev/null @@ -1,20 +0,0 @@ -project Zlib is - - for Languages use ("Ada"); - for Source_Dirs use ("."); - for Object_Dir use "."; - for Main use ("test.adb", "mtest.adb", "read.adb", "buffer_demo"); - - package Compiler is - for Default_Switches ("ada") use ("-gnatwcfilopru", "-gnatVcdfimorst", "-gnatyabcefhiklmnoprst"); - end Compiler; - - package Linker is - for Default_Switches ("ada") use ("-lz"); - end Linker; - - package Builder is - for Default_Switches ("ada") use ("-s", "-gnatQ"); - end Builder; - -end Zlib; diff --git a/deps/zlib/contrib/amd64/amd64-match.S b/deps/zlib/contrib/amd64/amd64-match.S deleted file mode 100644 index 81d4a1c9494b1c..00000000000000 --- a/deps/zlib/contrib/amd64/amd64-match.S +++ /dev/null @@ -1,452 +0,0 @@ -/* - * match.S -- optimized version of longest_match() - * based on the similar work by Gilles Vollant, and Brian Raiter, written 1998 - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the BSD License. Use by owners of Che Guevarra - * parafernalia is prohibited, where possible, and highly discouraged - * elsewhere. - */ - -#ifndef NO_UNDERLINE -# define match_init _match_init -# define longest_match _longest_match -#endif - -#define scanend ebx -#define scanendw bx -#define chainlenwmask edx /* high word: current chain len low word: s->wmask */ -#define curmatch rsi -#define curmatchd esi -#define windowbestlen r8 -#define scanalign r9 -#define scanalignd r9d -#define window r10 -#define bestlen r11 -#define bestlend r11d -#define scanstart r12d -#define scanstartw r12w -#define scan r13 -#define nicematch r14d -#define limit r15 -#define limitd r15d -#define prev rcx - -/* - * The 258 is a "magic number, not a parameter -- changing it - * breaks the hell loose - */ -#define MAX_MATCH (258) -#define MIN_MATCH (3) -#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) -#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) - -/* stack frame offsets */ -#define LocalVarsSize (112) -#define _chainlenwmask ( 8-LocalVarsSize)(%rsp) -#define _windowbestlen (16-LocalVarsSize)(%rsp) -#define save_r14 (24-LocalVarsSize)(%rsp) -#define save_rsi (32-LocalVarsSize)(%rsp) -#define save_rbx (40-LocalVarsSize)(%rsp) -#define save_r12 (56-LocalVarsSize)(%rsp) -#define save_r13 (64-LocalVarsSize)(%rsp) -#define save_r15 (80-LocalVarsSize)(%rsp) - - -.globl match_init, longest_match - -/* - * On AMD64 the first argument of a function (in our case -- the pointer to - * deflate_state structure) is passed in %rdi, hence our offsets below are - * all off of that. - */ - -/* you can check the structure offset by running - -#include -#include -#include "deflate.h" - -void print_depl() -{ -deflate_state ds; -deflate_state *s=&ds; -printf("size pointer=%u\n",(int)sizeof(void*)); - -printf("#define dsWSize (%3u)(%%rdi)\n",(int)(((char*)&(s->w_size))-((char*)s))); -printf("#define dsWMask (%3u)(%%rdi)\n",(int)(((char*)&(s->w_mask))-((char*)s))); -printf("#define dsWindow (%3u)(%%rdi)\n",(int)(((char*)&(s->window))-((char*)s))); -printf("#define dsPrev (%3u)(%%rdi)\n",(int)(((char*)&(s->prev))-((char*)s))); -printf("#define dsMatchLen (%3u)(%%rdi)\n",(int)(((char*)&(s->match_length))-((char*)s))); -printf("#define dsPrevMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->prev_match))-((char*)s))); -printf("#define dsStrStart (%3u)(%%rdi)\n",(int)(((char*)&(s->strstart))-((char*)s))); -printf("#define dsMatchStart (%3u)(%%rdi)\n",(int)(((char*)&(s->match_start))-((char*)s))); -printf("#define dsLookahead (%3u)(%%rdi)\n",(int)(((char*)&(s->lookahead))-((char*)s))); -printf("#define dsPrevLen (%3u)(%%rdi)\n",(int)(((char*)&(s->prev_length))-((char*)s))); -printf("#define dsMaxChainLen (%3u)(%%rdi)\n",(int)(((char*)&(s->max_chain_length))-((char*)s))); -printf("#define dsGoodMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->good_match))-((char*)s))); -printf("#define dsNiceMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->nice_match))-((char*)s))); -} - -*/ - - -/* - to compile for XCode 3.2 on MacOSX x86_64 - - run "gcc -g -c -DXCODE_MAC_X64_STRUCTURE amd64-match.S" - */ - - -#ifndef CURRENT_LINX_XCODE_MAC_X64_STRUCTURE -#define dsWSize ( 68)(%rdi) -#define dsWMask ( 76)(%rdi) -#define dsWindow ( 80)(%rdi) -#define dsPrev ( 96)(%rdi) -#define dsMatchLen (144)(%rdi) -#define dsPrevMatch (148)(%rdi) -#define dsStrStart (156)(%rdi) -#define dsMatchStart (160)(%rdi) -#define dsLookahead (164)(%rdi) -#define dsPrevLen (168)(%rdi) -#define dsMaxChainLen (172)(%rdi) -#define dsGoodMatch (188)(%rdi) -#define dsNiceMatch (192)(%rdi) - -#else - -#ifndef STRUCT_OFFSET -# define STRUCT_OFFSET (0) -#endif - - -#define dsWSize ( 56 + STRUCT_OFFSET)(%rdi) -#define dsWMask ( 64 + STRUCT_OFFSET)(%rdi) -#define dsWindow ( 72 + STRUCT_OFFSET)(%rdi) -#define dsPrev ( 88 + STRUCT_OFFSET)(%rdi) -#define dsMatchLen (136 + STRUCT_OFFSET)(%rdi) -#define dsPrevMatch (140 + STRUCT_OFFSET)(%rdi) -#define dsStrStart (148 + STRUCT_OFFSET)(%rdi) -#define dsMatchStart (152 + STRUCT_OFFSET)(%rdi) -#define dsLookahead (156 + STRUCT_OFFSET)(%rdi) -#define dsPrevLen (160 + STRUCT_OFFSET)(%rdi) -#define dsMaxChainLen (164 + STRUCT_OFFSET)(%rdi) -#define dsGoodMatch (180 + STRUCT_OFFSET)(%rdi) -#define dsNiceMatch (184 + STRUCT_OFFSET)(%rdi) - -#endif - - - - -.text - -/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ - -longest_match: -/* - * Retrieve the function arguments. %curmatch will hold cur_match - * throughout the entire function (passed via rsi on amd64). - * rdi will hold the pointer to the deflate_state (first arg on amd64) - */ - mov %rsi, save_rsi - mov %rbx, save_rbx - mov %r12, save_r12 - mov %r13, save_r13 - mov %r14, save_r14 - mov %r15, save_r15 - -/* uInt wmask = s->w_mask; */ -/* unsigned chain_length = s->max_chain_length; */ -/* if (s->prev_length >= s->good_match) { */ -/* chain_length >>= 2; */ -/* } */ - - movl dsPrevLen, %eax - movl dsGoodMatch, %ebx - cmpl %ebx, %eax - movl dsWMask, %eax - movl dsMaxChainLen, %chainlenwmask - jl LastMatchGood - shrl $2, %chainlenwmask -LastMatchGood: - -/* chainlen is decremented once beforehand so that the function can */ -/* use the sign flag instead of the zero flag for the exit test. */ -/* It is then shifted into the high word, to make room for the wmask */ -/* value, which it will always accompany. */ - - decl %chainlenwmask - shll $16, %chainlenwmask - orl %eax, %chainlenwmask - -/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ - - movl dsNiceMatch, %eax - movl dsLookahead, %ebx - cmpl %eax, %ebx - jl LookaheadLess - movl %eax, %ebx -LookaheadLess: movl %ebx, %nicematch - -/* register Bytef *scan = s->window + s->strstart; */ - - mov dsWindow, %window - movl dsStrStart, %limitd - lea (%limit, %window), %scan - -/* Determine how many bytes the scan ptr is off from being */ -/* dword-aligned. */ - - mov %scan, %scanalign - negl %scanalignd - andl $3, %scanalignd - -/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ -/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ - - movl dsWSize, %eax - subl $MIN_LOOKAHEAD, %eax - xorl %ecx, %ecx - subl %eax, %limitd - cmovng %ecx, %limitd - -/* int best_len = s->prev_length; */ - - movl dsPrevLen, %bestlend - -/* Store the sum of s->window + best_len in %windowbestlen locally, and in memory. */ - - lea (%window, %bestlen), %windowbestlen - mov %windowbestlen, _windowbestlen - -/* register ush scan_start = *(ushf*)scan; */ -/* register ush scan_end = *(ushf*)(scan+best_len-1); */ -/* Posf *prev = s->prev; */ - - movzwl (%scan), %scanstart - movzwl -1(%scan, %bestlen), %scanend - mov dsPrev, %prev - -/* Jump into the main loop. */ - - movl %chainlenwmask, _chainlenwmask - jmp LoopEntry - -.balign 16 - -/* do { - * match = s->window + cur_match; - * if (*(ushf*)(match+best_len-1) != scan_end || - * *(ushf*)match != scan_start) continue; - * [...] - * } while ((cur_match = prev[cur_match & wmask]) > limit - * && --chain_length != 0); - * - * Here is the inner loop of the function. The function will spend the - * majority of its time in this loop, and majority of that time will - * be spent in the first ten instructions. - */ -LookupLoop: - andl %chainlenwmask, %curmatchd - movzwl (%prev, %curmatch, 2), %curmatchd - cmpl %limitd, %curmatchd - jbe LeaveNow - subl $0x00010000, %chainlenwmask - js LeaveNow -LoopEntry: cmpw -1(%windowbestlen, %curmatch), %scanendw - jne LookupLoop - cmpw %scanstartw, (%window, %curmatch) - jne LookupLoop - -/* Store the current value of chainlen. */ - movl %chainlenwmask, _chainlenwmask - -/* %scan is the string under scrutiny, and %prev to the string we */ -/* are hoping to match it up with. In actuality, %esi and %edi are */ -/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ -/* initialized to -(MAX_MATCH_8 - scanalign). */ - - mov $(-MAX_MATCH_8), %rdx - lea (%curmatch, %window), %windowbestlen - lea MAX_MATCH_8(%windowbestlen, %scanalign), %windowbestlen - lea MAX_MATCH_8(%scan, %scanalign), %prev - -/* the prefetching below makes very little difference... */ - prefetcht1 (%windowbestlen, %rdx) - prefetcht1 (%prev, %rdx) - -/* - * Test the strings for equality, 8 bytes at a time. At the end, - * adjust %rdx so that it is offset to the exact byte that mismatched. - * - * It should be confessed that this loop usually does not represent - * much of the total running time. Replacing it with a more - * straightforward "rep cmpsb" would not drastically degrade - * performance -- unrolling it, for example, makes no difference. - */ - -#undef USE_SSE /* works, but is 6-7% slower, than non-SSE... */ - -LoopCmps: -#ifdef USE_SSE - /* Preload the SSE registers */ - movdqu (%windowbestlen, %rdx), %xmm1 - movdqu (%prev, %rdx), %xmm2 - pcmpeqb %xmm2, %xmm1 - movdqu 16(%windowbestlen, %rdx), %xmm3 - movdqu 16(%prev, %rdx), %xmm4 - pcmpeqb %xmm4, %xmm3 - movdqu 32(%windowbestlen, %rdx), %xmm5 - movdqu 32(%prev, %rdx), %xmm6 - pcmpeqb %xmm6, %xmm5 - movdqu 48(%windowbestlen, %rdx), %xmm7 - movdqu 48(%prev, %rdx), %xmm8 - pcmpeqb %xmm8, %xmm7 - - /* Check the comparisions' results */ - pmovmskb %xmm1, %rax - notw %ax - bsfw %ax, %ax - jnz LeaveLoopCmps - - /* this is the only iteration of the loop with a possibility of having - incremented rdx by 0x108 (each loop iteration add 16*4 = 0x40 - and (0x40*4)+8=0x108 */ - add $8, %rdx - jz LenMaximum - add $8, %rdx - - - pmovmskb %xmm3, %rax - notw %ax - bsfw %ax, %ax - jnz LeaveLoopCmps - - - add $16, %rdx - - - pmovmskb %xmm5, %rax - notw %ax - bsfw %ax, %ax - jnz LeaveLoopCmps - - add $16, %rdx - - - pmovmskb %xmm7, %rax - notw %ax - bsfw %ax, %ax - jnz LeaveLoopCmps - - add $16, %rdx - - jmp LoopCmps -LeaveLoopCmps: add %rax, %rdx -#else - mov (%windowbestlen, %rdx), %rax - xor (%prev, %rdx), %rax - jnz LeaveLoopCmps - - mov 8(%windowbestlen, %rdx), %rax - xor 8(%prev, %rdx), %rax - jnz LeaveLoopCmps8 - - mov 16(%windowbestlen, %rdx), %rax - xor 16(%prev, %rdx), %rax - jnz LeaveLoopCmps16 - - add $24, %rdx - jnz LoopCmps - jmp LenMaximum -# if 0 -/* - * This three-liner is tantalizingly simple, but bsf is a slow instruction, - * and the complicated alternative down below is quite a bit faster. Sad... - */ - -LeaveLoopCmps: bsf %rax, %rax /* find the first non-zero bit */ - shrl $3, %eax /* divide by 8 to get the byte */ - add %rax, %rdx -# else -LeaveLoopCmps16: - add $8, %rdx -LeaveLoopCmps8: - add $8, %rdx -LeaveLoopCmps: testl $0xFFFFFFFF, %eax /* Check the first 4 bytes */ - jnz Check16 - add $4, %rdx - shr $32, %rax -Check16: testw $0xFFFF, %ax - jnz LenLower - add $2, %rdx - shrl $16, %eax -LenLower: subb $1, %al - adc $0, %rdx -# endif -#endif - -/* Calculate the length of the match. If it is longer than MAX_MATCH, */ -/* then automatically accept it as the best possible match and leave. */ - - lea (%prev, %rdx), %rax - sub %scan, %rax - cmpl $MAX_MATCH, %eax - jge LenMaximum - -/* If the length of the match is not longer than the best match we */ -/* have so far, then forget it and return to the lookup loop. */ - - cmpl %bestlend, %eax - jg LongerMatch - mov _windowbestlen, %windowbestlen - mov dsPrev, %prev - movl _chainlenwmask, %edx - jmp LookupLoop - -/* s->match_start = cur_match; */ -/* best_len = len; */ -/* if (len >= nice_match) break; */ -/* scan_end = *(ushf*)(scan+best_len-1); */ - -LongerMatch: - movl %eax, %bestlend - movl %curmatchd, dsMatchStart - cmpl %nicematch, %eax - jge LeaveNow - - lea (%window, %bestlen), %windowbestlen - mov %windowbestlen, _windowbestlen - - movzwl -1(%scan, %rax), %scanend - mov dsPrev, %prev - movl _chainlenwmask, %chainlenwmask - jmp LookupLoop - -/* Accept the current string, with the maximum possible length. */ - -LenMaximum: - movl $MAX_MATCH, %bestlend - movl %curmatchd, dsMatchStart - -/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ -/* return s->lookahead; */ - -LeaveNow: - movl dsLookahead, %eax - cmpl %eax, %bestlend - cmovngl %bestlend, %eax -LookaheadRet: - -/* Restore the registers and return from whence we came. */ - - mov save_rsi, %rsi - mov save_rbx, %rbx - mov save_r12, %r12 - mov save_r13, %r13 - mov save_r14, %r14 - mov save_r15, %r15 - - ret - -match_init: ret diff --git a/deps/zlib/contrib/asm686/README.686 b/deps/zlib/contrib/asm686/README.686 deleted file mode 100644 index a0bf3bea4aff5b..00000000000000 --- a/deps/zlib/contrib/asm686/README.686 +++ /dev/null @@ -1,51 +0,0 @@ -This is a patched version of zlib, modified to use -Pentium-Pro-optimized assembly code in the deflation algorithm. The -files changed/added by this patch are: - -README.686 -match.S - -The speedup that this patch provides varies, depending on whether the -compiler used to build the original version of zlib falls afoul of the -PPro's speed traps. My own tests show a speedup of around 10-20% at -the default compression level, and 20-30% using -9, against a version -compiled using gcc 2.7.2.3. Your mileage may vary. - -Note that this code has been tailored for the PPro/PII in particular, -and will not perform particuarly well on a Pentium. - -If you are using an assembler other than GNU as, you will have to -translate match.S to use your assembler's syntax. (Have fun.) - -Brian Raiter -breadbox@muppetlabs.com -April, 1998 - - -Added for zlib 1.1.3: - -The patches come from -http://www.muppetlabs.com/~breadbox/software/assembly.html - -To compile zlib with this asm file, copy match.S to the zlib directory -then do: - -CFLAGS="-O3 -DASMV" ./configure -make OBJA=match.o - - -Update: - -I've been ignoring these assembly routines for years, believing that -gcc's generated code had caught up with it sometime around gcc 2.95 -and the major rearchitecting of the Pentium 4. However, I recently -learned that, despite what I believed, this code still has some life -in it. On the Pentium 4 and AMD64 chips, it continues to run about 8% -faster than the code produced by gcc 4.1. - -In acknowledgement of its continuing usefulness, I've altered the -license to match that of the rest of zlib. Share and Enjoy! - -Brian Raiter -breadbox@muppetlabs.com -April, 2007 diff --git a/deps/zlib/contrib/asm686/match.S b/deps/zlib/contrib/asm686/match.S deleted file mode 100644 index fa421092785d4c..00000000000000 --- a/deps/zlib/contrib/asm686/match.S +++ /dev/null @@ -1,357 +0,0 @@ -/* match.S -- x86 assembly version of the zlib longest_match() function. - * Optimized for the Intel 686 chips (PPro and later). - * - * Copyright (C) 1998, 2007 Brian Raiter - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef NO_UNDERLINE -#define match_init _match_init -#define longest_match _longest_match -#endif - -#define MAX_MATCH (258) -#define MIN_MATCH (3) -#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) -#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) - -/* stack frame offsets */ - -#define chainlenwmask 0 /* high word: current chain len */ - /* low word: s->wmask */ -#define window 4 /* local copy of s->window */ -#define windowbestlen 8 /* s->window + bestlen */ -#define scanstart 16 /* first two bytes of string */ -#define scanend 12 /* last two bytes of string */ -#define scanalign 20 /* dword-misalignment of string */ -#define nicematch 24 /* a good enough match size */ -#define bestlen 28 /* size of best match so far */ -#define scan 32 /* ptr to string wanting match */ - -#define LocalVarsSize (36) -/* saved ebx 36 */ -/* saved edi 40 */ -/* saved esi 44 */ -/* saved ebp 48 */ -/* return address 52 */ -#define deflatestate 56 /* the function arguments */ -#define curmatch 60 - -/* All the +zlib1222add offsets are due to the addition of fields - * in zlib in the deflate_state structure since the asm code was first written - * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). - * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). - * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). - */ - -#define zlib1222add (8) - -#define dsWSize (36+zlib1222add) -#define dsWMask (44+zlib1222add) -#define dsWindow (48+zlib1222add) -#define dsPrev (56+zlib1222add) -#define dsMatchLen (88+zlib1222add) -#define dsPrevMatch (92+zlib1222add) -#define dsStrStart (100+zlib1222add) -#define dsMatchStart (104+zlib1222add) -#define dsLookahead (108+zlib1222add) -#define dsPrevLen (112+zlib1222add) -#define dsMaxChainLen (116+zlib1222add) -#define dsGoodMatch (132+zlib1222add) -#define dsNiceMatch (136+zlib1222add) - - -.file "match.S" - -.globl match_init, longest_match - -.text - -/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ -.cfi_sections .debug_frame - -longest_match: - -.cfi_startproc -/* Save registers that the compiler may be using, and adjust %esp to */ -/* make room for our stack frame. */ - - pushl %ebp - .cfi_def_cfa_offset 8 - .cfi_offset ebp, -8 - pushl %edi - .cfi_def_cfa_offset 12 - pushl %esi - .cfi_def_cfa_offset 16 - pushl %ebx - .cfi_def_cfa_offset 20 - subl $LocalVarsSize, %esp - .cfi_def_cfa_offset LocalVarsSize+20 - -/* Retrieve the function arguments. %ecx will hold cur_match */ -/* throughout the entire function. %edx will hold the pointer to the */ -/* deflate_state structure during the function's setup (before */ -/* entering the main loop). */ - - movl deflatestate(%esp), %edx - movl curmatch(%esp), %ecx - -/* uInt wmask = s->w_mask; */ -/* unsigned chain_length = s->max_chain_length; */ -/* if (s->prev_length >= s->good_match) { */ -/* chain_length >>= 2; */ -/* } */ - - movl dsPrevLen(%edx), %eax - movl dsGoodMatch(%edx), %ebx - cmpl %ebx, %eax - movl dsWMask(%edx), %eax - movl dsMaxChainLen(%edx), %ebx - jl LastMatchGood - shrl $2, %ebx -LastMatchGood: - -/* chainlen is decremented once beforehand so that the function can */ -/* use the sign flag instead of the zero flag for the exit test. */ -/* It is then shifted into the high word, to make room for the wmask */ -/* value, which it will always accompany. */ - - decl %ebx - shll $16, %ebx - orl %eax, %ebx - movl %ebx, chainlenwmask(%esp) - -/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ - - movl dsNiceMatch(%edx), %eax - movl dsLookahead(%edx), %ebx - cmpl %eax, %ebx - jl LookaheadLess - movl %eax, %ebx -LookaheadLess: movl %ebx, nicematch(%esp) - -/* register Bytef *scan = s->window + s->strstart; */ - - movl dsWindow(%edx), %esi - movl %esi, window(%esp) - movl dsStrStart(%edx), %ebp - lea (%esi,%ebp), %edi - movl %edi, scan(%esp) - -/* Determine how many bytes the scan ptr is off from being */ -/* dword-aligned. */ - - movl %edi, %eax - negl %eax - andl $3, %eax - movl %eax, scanalign(%esp) - -/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ -/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ - - movl dsWSize(%edx), %eax - subl $MIN_LOOKAHEAD, %eax - subl %eax, %ebp - jg LimitPositive - xorl %ebp, %ebp -LimitPositive: - -/* int best_len = s->prev_length; */ - - movl dsPrevLen(%edx), %eax - movl %eax, bestlen(%esp) - -/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ - - addl %eax, %esi - movl %esi, windowbestlen(%esp) - -/* register ush scan_start = *(ushf*)scan; */ -/* register ush scan_end = *(ushf*)(scan+best_len-1); */ -/* Posf *prev = s->prev; */ - - movzwl (%edi), %ebx - movl %ebx, scanstart(%esp) - movzwl -1(%edi,%eax), %ebx - movl %ebx, scanend(%esp) - movl dsPrev(%edx), %edi - -/* Jump into the main loop. */ - - movl chainlenwmask(%esp), %edx - jmp LoopEntry - -.balign 16 - -/* do { - * match = s->window + cur_match; - * if (*(ushf*)(match+best_len-1) != scan_end || - * *(ushf*)match != scan_start) continue; - * [...] - * } while ((cur_match = prev[cur_match & wmask]) > limit - * && --chain_length != 0); - * - * Here is the inner loop of the function. The function will spend the - * majority of its time in this loop, and majority of that time will - * be spent in the first ten instructions. - * - * Within this loop: - * %ebx = scanend - * %ecx = curmatch - * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) - * %esi = windowbestlen - i.e., (window + bestlen) - * %edi = prev - * %ebp = limit - */ -LookupLoop: - andl %edx, %ecx - movzwl (%edi,%ecx,2), %ecx - cmpl %ebp, %ecx - jbe LeaveNow - subl $0x00010000, %edx - js LeaveNow -LoopEntry: movzwl -1(%esi,%ecx), %eax - cmpl %ebx, %eax - jnz LookupLoop - movl window(%esp), %eax - movzwl (%eax,%ecx), %eax - cmpl scanstart(%esp), %eax - jnz LookupLoop - -/* Store the current value of chainlen. */ - - movl %edx, chainlenwmask(%esp) - -/* Point %edi to the string under scrutiny, and %esi to the string we */ -/* are hoping to match it up with. In actuality, %esi and %edi are */ -/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ -/* initialized to -(MAX_MATCH_8 - scanalign). */ - - movl window(%esp), %esi - movl scan(%esp), %edi - addl %ecx, %esi - movl scanalign(%esp), %eax - movl $(-MAX_MATCH_8), %edx - lea MAX_MATCH_8(%edi,%eax), %edi - lea MAX_MATCH_8(%esi,%eax), %esi - -/* Test the strings for equality, 8 bytes at a time. At the end, - * adjust %edx so that it is offset to the exact byte that mismatched. - * - * We already know at this point that the first three bytes of the - * strings match each other, and they can be safely passed over before - * starting the compare loop. So what this code does is skip over 0-3 - * bytes, as much as necessary in order to dword-align the %edi - * pointer. (%esi will still be misaligned three times out of four.) - * - * It should be confessed that this loop usually does not represent - * much of the total running time. Replacing it with a more - * straightforward "rep cmpsb" would not drastically degrade - * performance. - */ -LoopCmps: - movl (%esi,%edx), %eax - xorl (%edi,%edx), %eax - jnz LeaveLoopCmps - movl 4(%esi,%edx), %eax - xorl 4(%edi,%edx), %eax - jnz LeaveLoopCmps4 - addl $8, %edx - jnz LoopCmps - jmp LenMaximum -LeaveLoopCmps4: addl $4, %edx -LeaveLoopCmps: testl $0x0000FFFF, %eax - jnz LenLower - addl $2, %edx - shrl $16, %eax -LenLower: subb $1, %al - adcl $0, %edx - -/* Calculate the length of the match. If it is longer than MAX_MATCH, */ -/* then automatically accept it as the best possible match and leave. */ - - lea (%edi,%edx), %eax - movl scan(%esp), %edi - subl %edi, %eax - cmpl $MAX_MATCH, %eax - jge LenMaximum - -/* If the length of the match is not longer than the best match we */ -/* have so far, then forget it and return to the lookup loop. */ - - movl deflatestate(%esp), %edx - movl bestlen(%esp), %ebx - cmpl %ebx, %eax - jg LongerMatch - movl windowbestlen(%esp), %esi - movl dsPrev(%edx), %edi - movl scanend(%esp), %ebx - movl chainlenwmask(%esp), %edx - jmp LookupLoop - -/* s->match_start = cur_match; */ -/* best_len = len; */ -/* if (len >= nice_match) break; */ -/* scan_end = *(ushf*)(scan+best_len-1); */ - -LongerMatch: movl nicematch(%esp), %ebx - movl %eax, bestlen(%esp) - movl %ecx, dsMatchStart(%edx) - cmpl %ebx, %eax - jge LeaveNow - movl window(%esp), %esi - addl %eax, %esi - movl %esi, windowbestlen(%esp) - movzwl -1(%edi,%eax), %ebx - movl dsPrev(%edx), %edi - movl %ebx, scanend(%esp) - movl chainlenwmask(%esp), %edx - jmp LookupLoop - -/* Accept the current string, with the maximum possible length. */ - -LenMaximum: movl deflatestate(%esp), %edx - movl $MAX_MATCH, bestlen(%esp) - movl %ecx, dsMatchStart(%edx) - -/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ -/* return s->lookahead; */ - -LeaveNow: - movl deflatestate(%esp), %edx - movl bestlen(%esp), %ebx - movl dsLookahead(%edx), %eax - cmpl %eax, %ebx - jg LookaheadRet - movl %ebx, %eax -LookaheadRet: - -/* Restore the stack and return from whence we came. */ - - addl $LocalVarsSize, %esp - .cfi_def_cfa_offset 20 - popl %ebx - .cfi_def_cfa_offset 16 - popl %esi - .cfi_def_cfa_offset 12 - popl %edi - .cfi_def_cfa_offset 8 - popl %ebp - .cfi_def_cfa_offset 4 -.cfi_endproc -match_init: ret diff --git a/deps/zlib/contrib/bench/OWNERS b/deps/zlib/contrib/bench/OWNERS new file mode 100644 index 00000000000000..f1e3d4f472e484 --- /dev/null +++ b/deps/zlib/contrib/bench/OWNERS @@ -0,0 +1 @@ +noel@chromium.org diff --git a/deps/zlib/contrib/bench/zlib_bench.cc b/deps/zlib/contrib/bench/zlib_bench.cc new file mode 100644 index 00000000000000..5dcdef09f36b76 --- /dev/null +++ b/deps/zlib/contrib/bench/zlib_bench.cc @@ -0,0 +1,316 @@ +/* + * Copyright 2018 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + * + * A benchmark test harness for measuring decoding performance of gzip or zlib + * (deflate) encoded compressed data. Given a file containing any data, encode + * (compress) it into gzip or zlib format and then decode (uncompress). Output + * the median and maximum encoding and decoding rates in MB/s. + * + * Raw deflate (no gzip or zlib stream wrapper) mode is also supported. Select + * it with the [raw] argument. Use the [gzip] [zlib] arguments to select those + * stream wrappers. + * + * Note this code can be compiled outside of the Chromium build system against + * the system zlib (-lz) with g++ or clang++ as follows: + * + * g++|clang++ -O3 -Wall -std=c++11 -lstdc++ -lz zlib_bench.cc + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "zlib.h" + +void error_exit(const char* error, int code) { + fprintf(stderr, "%s (%d)\n", error, code); + exit(code); +} + +inline char* string_data(std::string* s) { + return s->empty() ? 0 : &*s->begin(); +} + +struct Data { + Data(size_t s) { data.reset(new (std::nothrow) char[size = s]); } + std::unique_ptr data; + size_t size; +}; + +Data read_file_data_or_exit(const char* name) { + std::ifstream file(name, std::ios::in | std::ios::binary); + if (!file) { + perror(name); + exit(1); + } + + file.seekg(0, std::ios::end); + Data data(file.tellg()); + file.seekg(0, std::ios::beg); + + if (file && data.data) + file.read(data.data.get(), data.size); + + if (!file || !data.data || !data.size) { + perror((std::string("failed: reading ") + name).c_str()); + exit(1); + } + + return data; +} + +size_t zlib_estimate_compressed_size(size_t input_size) { + return compressBound(input_size); +} + +enum zlib_wrapper { + kWrapperNONE, + kWrapperZLIB, + kWrapperGZIP, + kWrapperZRAW, +}; + +inline int zlib_stream_wrapper_type(zlib_wrapper type) { + if (type == kWrapperZLIB) // zlib DEFLATE stream wrapper + return MAX_WBITS; + if (type == kWrapperGZIP) // gzip DEFLATE stream wrapper + return MAX_WBITS + 16; + if (type == kWrapperZRAW) // no wrapper, use raw DEFLATE + return -MAX_WBITS; + error_exit("bad wrapper type", int(type)); + return 0; +} + +const char* zlib_wrapper_name(zlib_wrapper type) { + if (type == kWrapperZLIB) + return "ZLIB"; + if (type == kWrapperGZIP) + return "GZIP"; + if (type == kWrapperZRAW) + return "RAW"; + error_exit("bad wrapper type", int(type)); + return 0; +} + +static int zlib_compression_level; + +void zlib_compress( + const zlib_wrapper type, + const char* input, + const size_t input_size, + std::string* output, + bool resize_output = false) +{ + if (resize_output) + output->resize(zlib_estimate_compressed_size(input_size)); + size_t output_size = output->size(); + + z_stream stream; + memset(&stream, 0, sizeof(stream)); + + int result = deflateInit2(&stream, zlib_compression_level, Z_DEFLATED, + zlib_stream_wrapper_type(type), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); + if (result != Z_OK) + error_exit("deflateInit2 failed", result); + + stream.next_out = (Bytef*)string_data(output); + stream.avail_out = (uInt)output_size; + stream.next_in = (z_const Bytef*)input; + stream.avail_in = (uInt)input_size; + + result = deflate(&stream, Z_FINISH); + if (result == Z_STREAM_END) + output_size = stream.total_out; + result |= deflateEnd(&stream); + if (result != Z_STREAM_END) + error_exit("compress failed", result); + + if (resize_output) + output->resize(output_size); +} + +void zlib_uncompress( + const zlib_wrapper type, + const std::string& input, + const size_t output_size, + std::string* output) +{ + z_stream stream; + memset(&stream, 0, sizeof(stream)); + + int result = inflateInit2(&stream, zlib_stream_wrapper_type(type)); + if (result != Z_OK) + error_exit("inflateInit2 failed", result); + + stream.next_out = (Bytef*)string_data(output); + stream.avail_out = (uInt)output->size(); + stream.next_in = (z_const Bytef*)input.data(); + stream.avail_in = (uInt)input.size(); + + result = inflate(&stream, Z_FINISH); + if (stream.total_out != output_size) + result = Z_DATA_ERROR; + result |= inflateEnd(&stream); + if (result == Z_STREAM_END) + return; + + std::string error("uncompress failed: "); + if (stream.msg) + error.append(stream.msg); + error_exit(error.c_str(), result); +} + +void verify_equal(const char* input, size_t size, std::string* output) { + const char* data = string_data(output); + if (output->size() == size && !memcmp(data, input, size)) + return; + fprintf(stderr, "uncompressed data does not match the input data\n"); + exit(3); +} + +void zlib_file(const char* name, const zlib_wrapper type) { + /* + * Read the file data. + */ + const auto file = read_file_data_or_exit(name); + const int length = static_cast(file.size); + const char* data = file.data.get(); + printf("%-40s :\n", name); + + /* + * Chop the data into blocks. + */ + const int block_size = 1 << 20; + const int blocks = (length + block_size - 1) / block_size; + + std::vector input(blocks); + std::vector input_length(blocks); + std::vector compressed(blocks); + std::vector output(blocks); + + for (int b = 0; b < blocks; ++b) { + int input_start = b * block_size; + int input_limit = std::min((b + 1) * block_size, length); + input[b] = data + input_start; + input_length[b] = input_limit - input_start; + } + + /* + * Run the zlib compress/uncompress loop a few times with |repeats| to + * process about 10MB of data if the length is small relative to 10MB. + * If length is large relative to 10MB, process the data once. + */ + const int mega_byte = 1024 * 1024; + const int repeats = (10 * mega_byte + length) / (length + 1); + const int runs = 5; + double ctime[runs]; + double utime[runs]; + + for (int run = 0; run < runs; ++run) { + const auto now = [] { return std::chrono::steady_clock::now(); }; + + // Pre-grow the output buffer so we don't measure string resize time. + for (int b = 0; b < blocks; ++b) + compressed[b].resize(zlib_estimate_compressed_size(block_size)); + + auto start = now(); + for (int b = 0; b < blocks; ++b) + for (int r = 0; r < repeats; ++r) + zlib_compress(type, input[b], input_length[b], &compressed[b]); + ctime[run] = std::chrono::duration(now() - start).count(); + + // Compress again, resizing compressed, so we don't leave junk at the + // end of the compressed string that could confuse zlib_uncompress(). + for (int b = 0; b < blocks; ++b) + zlib_compress(type, input[b], input_length[b], &compressed[b], true); + + for (int b = 0; b < blocks; ++b) + output[b].resize(input_length[b]); + + start = now(); + for (int r = 0; r < repeats; ++r) + for (int b = 0; b < blocks; ++b) + zlib_uncompress(type, compressed[b], input_length[b], &output[b]); + utime[run] = std::chrono::duration(now() - start).count(); + + for (int b = 0; b < blocks; ++b) + verify_equal(input[b], input_length[b], &output[b]); + } + + /* + * Output the median/maximum compress/uncompress rates in MB/s. + */ + size_t output_length = 0; + for (size_t i = 0; i < compressed.size(); ++i) + output_length += compressed[i].size(); + + std::sort(ctime, ctime + runs); + std::sort(utime, utime + runs); + + double deflate_rate_med = length * repeats / mega_byte / ctime[runs / 2]; + double inflate_rate_med = length * repeats / mega_byte / utime[runs / 2]; + double deflate_rate_max = length * repeats / mega_byte / ctime[0]; + double inflate_rate_max = length * repeats / mega_byte / utime[0]; + + // type, block size, compression ratio, etc + printf("%s: [b %dM] bytes %6d -> %6u %4.1f%%", + zlib_wrapper_name(type), block_size / (1 << 20), length, + static_cast(output_length), output_length * 100.0 / length); + + // compress / uncompress median (max) rates + printf(" comp %5.1f (%5.1f) MB/s uncomp %5.1f (%5.1f) MB/s\n", + deflate_rate_med, deflate_rate_max, inflate_rate_med, inflate_rate_max); +} + +static int argn = 1; + +char* get_option(int argc, char* argv[], const char* option) { + if (argn < argc) + return !strcmp(argv[argn], option) ? argv[argn++] : 0; + return 0; +} + +bool get_compression(int argc, char* argv[], int* value) { + if (argn < argc) + *value = atoi(argv[argn++]); + return *value >= 1 && *value <= 9; +} + +void usage_exit(const char* program) { + printf("usage: %s gzip|zlib|raw [--compression 1:9] files...\n", program); + exit(1); +} + +int main(int argc, char* argv[]) { + zlib_wrapper type; + if (get_option(argc, argv, "zlib")) + type = kWrapperZLIB; + else if (get_option(argc, argv, "gzip")) + type = kWrapperGZIP; + else if (get_option(argc, argv, "raw")) + type = kWrapperZRAW; + else + usage_exit(argv[0]); + + if (!get_option(argc, argv, "--compression")) + zlib_compression_level = Z_DEFAULT_COMPRESSION; + else if (!get_compression(argc, argv, &zlib_compression_level)) + usage_exit(argv[0]); + + if (argn >= argc) + usage_exit(argv[0]); + while (argn < argc) + zlib_file(argv[argn++], type); + + return 0; +} diff --git a/deps/zlib/contrib/blast/Makefile b/deps/zlib/contrib/blast/Makefile deleted file mode 100644 index 9be80bafe050ee..00000000000000 --- a/deps/zlib/contrib/blast/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -blast: blast.c blast.h - cc -DTEST -o blast blast.c - -test: blast - blast < test.pk | cmp - test.txt - -clean: - rm -f blast blast.o diff --git a/deps/zlib/contrib/blast/README b/deps/zlib/contrib/blast/README deleted file mode 100644 index e3a60b3f5cce7b..00000000000000 --- a/deps/zlib/contrib/blast/README +++ /dev/null @@ -1,4 +0,0 @@ -Read blast.h for purpose and usage. - -Mark Adler -madler@alumni.caltech.edu diff --git a/deps/zlib/contrib/blast/blast.c b/deps/zlib/contrib/blast/blast.c deleted file mode 100644 index e6e659073c630a..00000000000000 --- a/deps/zlib/contrib/blast/blast.c +++ /dev/null @@ -1,466 +0,0 @@ -/* blast.c - * Copyright (C) 2003, 2012, 2013 Mark Adler - * For conditions of distribution and use, see copyright notice in blast.h - * version 1.3, 24 Aug 2013 - * - * blast.c decompresses data compressed by the PKWare Compression Library. - * This function provides functionality similar to the explode() function of - * the PKWare library, hence the name "blast". - * - * This decompressor is based on the excellent format description provided by - * Ben Rudiak-Gould in comp.compression on August 13, 2001. Interestingly, the - * example Ben provided in the post is incorrect. The distance 110001 should - * instead be 111000. When corrected, the example byte stream becomes: - * - * 00 04 82 24 25 8f 80 7f - * - * which decompresses to "AIAIAIAIAIAIA" (without the quotes). - */ - -/* - * Change history: - * - * 1.0 12 Feb 2003 - First version - * 1.1 16 Feb 2003 - Fixed distance check for > 4 GB uncompressed data - * 1.2 24 Oct 2012 - Add note about using binary mode in stdio - * - Fix comparisons of differently signed integers - * 1.3 24 Aug 2013 - Return unused input from blast() - * - Fix test code to correctly report unused input - * - Enable the provision of initial input to blast() - */ - -#include /* for NULL */ -#include /* for setjmp(), longjmp(), and jmp_buf */ -#include "blast.h" /* prototype for blast() */ - -#define local static /* for local function definitions */ -#define MAXBITS 13 /* maximum code length */ -#define MAXWIN 4096 /* maximum window size */ - -/* input and output state */ -struct state { - /* input state */ - blast_in infun; /* input function provided by user */ - void *inhow; /* opaque information passed to infun() */ - unsigned char *in; /* next input location */ - unsigned left; /* available input at in */ - int bitbuf; /* bit buffer */ - int bitcnt; /* number of bits in bit buffer */ - - /* input limit error return state for bits() and decode() */ - jmp_buf env; - - /* output state */ - blast_out outfun; /* output function provided by user */ - void *outhow; /* opaque information passed to outfun() */ - unsigned next; /* index of next write location in out[] */ - int first; /* true to check distances (for first 4K) */ - unsigned char out[MAXWIN]; /* output buffer and sliding window */ -}; - -/* - * Return need bits from the input stream. This always leaves less than - * eight bits in the buffer. bits() works properly for need == 0. - * - * Format notes: - * - * - Bits are stored in bytes from the least significant bit to the most - * significant bit. Therefore bits are dropped from the bottom of the bit - * buffer, using shift right, and new bytes are appended to the top of the - * bit buffer, using shift left. - */ -local int bits(struct state *s, int need) -{ - int val; /* bit accumulator */ - - /* load at least need bits into val */ - val = s->bitbuf; - while (s->bitcnt < need) { - if (s->left == 0) { - s->left = s->infun(s->inhow, &(s->in)); - if (s->left == 0) longjmp(s->env, 1); /* out of input */ - } - val |= (int)(*(s->in)++) << s->bitcnt; /* load eight bits */ - s->left--; - s->bitcnt += 8; - } - - /* drop need bits and update buffer, always zero to seven bits left */ - s->bitbuf = val >> need; - s->bitcnt -= need; - - /* return need bits, zeroing the bits above that */ - return val & ((1 << need) - 1); -} - -/* - * Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of - * each length, which for a canonical code are stepped through in order. - * symbol[] are the symbol values in canonical order, where the number of - * entries is the sum of the counts in count[]. The decoding process can be - * seen in the function decode() below. - */ -struct huffman { - short *count; /* number of symbols of each length */ - short *symbol; /* canonically ordered symbols */ -}; - -/* - * Decode a code from the stream s using huffman table h. Return the symbol or - * a negative value if there is an error. If all of the lengths are zero, i.e. - * an empty code, or if the code is incomplete and an invalid code is received, - * then -9 is returned after reading MAXBITS bits. - * - * Format notes: - * - * - The codes as stored in the compressed data are bit-reversed relative to - * a simple integer ordering of codes of the same lengths. Hence below the - * bits are pulled from the compressed data one at a time and used to - * build the code value reversed from what is in the stream in order to - * permit simple integer comparisons for decoding. - * - * - The first code for the shortest length is all ones. Subsequent codes of - * the same length are simply integer decrements of the previous code. When - * moving up a length, a one bit is appended to the code. For a complete - * code, the last code of the longest length will be all zeros. To support - * this ordering, the bits pulled during decoding are inverted to apply the - * more "natural" ordering starting with all zeros and incrementing. - */ -local int decode(struct state *s, struct huffman *h) -{ - int len; /* current number of bits in code */ - int code; /* len bits being decoded */ - int first; /* first code of length len */ - int count; /* number of codes of length len */ - int index; /* index of first code of length len in symbol table */ - int bitbuf; /* bits from stream */ - int left; /* bits left in next or left to process */ - short *next; /* next number of codes */ - - bitbuf = s->bitbuf; - left = s->bitcnt; - code = first = index = 0; - len = 1; - next = h->count + 1; - while (1) { - while (left--) { - code |= (bitbuf & 1) ^ 1; /* invert code */ - bitbuf >>= 1; - count = *next++; - if (code < first + count) { /* if length len, return symbol */ - s->bitbuf = bitbuf; - s->bitcnt = (s->bitcnt - len) & 7; - return h->symbol[index + (code - first)]; - } - index += count; /* else update for next length */ - first += count; - first <<= 1; - code <<= 1; - len++; - } - left = (MAXBITS+1) - len; - if (left == 0) break; - if (s->left == 0) { - s->left = s->infun(s->inhow, &(s->in)); - if (s->left == 0) longjmp(s->env, 1); /* out of input */ - } - bitbuf = *(s->in)++; - s->left--; - if (left > 8) left = 8; - } - return -9; /* ran out of codes */ -} - -/* - * Given a list of repeated code lengths rep[0..n-1], where each byte is a - * count (high four bits + 1) and a code length (low four bits), generate the - * list of code lengths. This compaction reduces the size of the object code. - * Then given the list of code lengths length[0..n-1] representing a canonical - * Huffman code for n symbols, construct the tables required to decode those - * codes. Those tables are the number of codes of each length, and the symbols - * sorted by length, retaining their original order within each length. The - * return value is zero for a complete code set, negative for an over- - * subscribed code set, and positive for an incomplete code set. The tables - * can be used if the return value is zero or positive, but they cannot be used - * if the return value is negative. If the return value is zero, it is not - * possible for decode() using that table to return an error--any stream of - * enough bits will resolve to a symbol. If the return value is positive, then - * it is possible for decode() using that table to return an error for received - * codes past the end of the incomplete lengths. - */ -local int construct(struct huffman *h, const unsigned char *rep, int n) -{ - int symbol; /* current symbol when stepping through length[] */ - int len; /* current length when stepping through h->count[] */ - int left; /* number of possible codes left of current length */ - short offs[MAXBITS+1]; /* offsets in symbol table for each length */ - short length[256]; /* code lengths */ - - /* convert compact repeat counts into symbol bit length list */ - symbol = 0; - do { - len = *rep++; - left = (len >> 4) + 1; - len &= 15; - do { - length[symbol++] = len; - } while (--left); - } while (--n); - n = symbol; - - /* count number of codes of each length */ - for (len = 0; len <= MAXBITS; len++) - h->count[len] = 0; - for (symbol = 0; symbol < n; symbol++) - (h->count[length[symbol]])++; /* assumes lengths are within bounds */ - if (h->count[0] == n) /* no codes! */ - return 0; /* complete, but decode() will fail */ - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; /* one possible code of zero length */ - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; /* one more bit, double codes left */ - left -= h->count[len]; /* deduct count from possible codes */ - if (left < 0) return left; /* over-subscribed--return negative */ - } /* left > 0 means incomplete */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + h->count[len]; - - /* - * put symbols in table sorted by length, by symbol order within each - * length - */ - for (symbol = 0; symbol < n; symbol++) - if (length[symbol] != 0) - h->symbol[offs[length[symbol]]++] = symbol; - - /* return zero for complete set, positive for incomplete set */ - return left; -} - -/* - * Decode PKWare Compression Library stream. - * - * Format notes: - * - * - First byte is 0 if literals are uncoded or 1 if they are coded. Second - * byte is 4, 5, or 6 for the number of extra bits in the distance code. - * This is the base-2 logarithm of the dictionary size minus six. - * - * - Compressed data is a combination of literals and length/distance pairs - * terminated by an end code. Literals are either Huffman coded or - * uncoded bytes. A length/distance pair is a coded length followed by a - * coded distance to represent a string that occurs earlier in the - * uncompressed data that occurs again at the current location. - * - * - A bit preceding a literal or length/distance pair indicates which comes - * next, 0 for literals, 1 for length/distance. - * - * - If literals are uncoded, then the next eight bits are the literal, in the - * normal bit order in the stream, i.e. no bit-reversal is needed. Similarly, - * no bit reversal is needed for either the length extra bits or the distance - * extra bits. - * - * - Literal bytes are simply written to the output. A length/distance pair is - * an instruction to copy previously uncompressed bytes to the output. The - * copy is from distance bytes back in the output stream, copying for length - * bytes. - * - * - Distances pointing before the beginning of the output data are not - * permitted. - * - * - Overlapped copies, where the length is greater than the distance, are - * allowed and common. For example, a distance of one and a length of 518 - * simply copies the last byte 518 times. A distance of four and a length of - * twelve copies the last four bytes three times. A simple forward copy - * ignoring whether the length is greater than the distance or not implements - * this correctly. - */ -local int decomp(struct state *s) -{ - int lit; /* true if literals are coded */ - int dict; /* log2(dictionary size) - 6 */ - int symbol; /* decoded symbol, extra bits for distance */ - int len; /* length for copy */ - unsigned dist; /* distance for copy */ - int copy; /* copy counter */ - unsigned char *from, *to; /* copy pointers */ - static int virgin = 1; /* build tables once */ - static short litcnt[MAXBITS+1], litsym[256]; /* litcode memory */ - static short lencnt[MAXBITS+1], lensym[16]; /* lencode memory */ - static short distcnt[MAXBITS+1], distsym[64]; /* distcode memory */ - static struct huffman litcode = {litcnt, litsym}; /* length code */ - static struct huffman lencode = {lencnt, lensym}; /* length code */ - static struct huffman distcode = {distcnt, distsym};/* distance code */ - /* bit lengths of literal codes */ - static const unsigned char litlen[] = { - 11, 124, 8, 7, 28, 7, 188, 13, 76, 4, 10, 8, 12, 10, 12, 10, 8, 23, 8, - 9, 7, 6, 7, 8, 7, 6, 55, 8, 23, 24, 12, 11, 7, 9, 11, 12, 6, 7, 22, 5, - 7, 24, 6, 11, 9, 6, 7, 22, 7, 11, 38, 7, 9, 8, 25, 11, 8, 11, 9, 12, - 8, 12, 5, 38, 5, 38, 5, 11, 7, 5, 6, 21, 6, 10, 53, 8, 7, 24, 10, 27, - 44, 253, 253, 253, 252, 252, 252, 13, 12, 45, 12, 45, 12, 61, 12, 45, - 44, 173}; - /* bit lengths of length codes 0..15 */ - static const unsigned char lenlen[] = {2, 35, 36, 53, 38, 23}; - /* bit lengths of distance codes 0..63 */ - static const unsigned char distlen[] = {2, 20, 53, 230, 247, 151, 248}; - static const short base[16] = { /* base for length codes */ - 3, 2, 4, 5, 6, 7, 8, 9, 10, 12, 16, 24, 40, 72, 136, 264}; - static const char extra[16] = { /* extra bits for length codes */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8}; - - /* set up decoding tables (once--might not be thread-safe) */ - if (virgin) { - construct(&litcode, litlen, sizeof(litlen)); - construct(&lencode, lenlen, sizeof(lenlen)); - construct(&distcode, distlen, sizeof(distlen)); - virgin = 0; - } - - /* read header */ - lit = bits(s, 8); - if (lit > 1) return -1; - dict = bits(s, 8); - if (dict < 4 || dict > 6) return -2; - - /* decode literals and length/distance pairs */ - do { - if (bits(s, 1)) { - /* get length */ - symbol = decode(s, &lencode); - len = base[symbol] + bits(s, extra[symbol]); - if (len == 519) break; /* end code */ - - /* get distance */ - symbol = len == 2 ? 2 : dict; - dist = decode(s, &distcode) << symbol; - dist += bits(s, symbol); - dist++; - if (s->first && dist > s->next) - return -3; /* distance too far back */ - - /* copy length bytes from distance bytes back */ - do { - to = s->out + s->next; - from = to - dist; - copy = MAXWIN; - if (s->next < dist) { - from += copy; - copy = dist; - } - copy -= s->next; - if (copy > len) copy = len; - len -= copy; - s->next += copy; - do { - *to++ = *from++; - } while (--copy); - if (s->next == MAXWIN) { - if (s->outfun(s->outhow, s->out, s->next)) return 1; - s->next = 0; - s->first = 0; - } - } while (len != 0); - } - else { - /* get literal and write it */ - symbol = lit ? decode(s, &litcode) : bits(s, 8); - s->out[s->next++] = symbol; - if (s->next == MAXWIN) { - if (s->outfun(s->outhow, s->out, s->next)) return 1; - s->next = 0; - s->first = 0; - } - } - } while (1); - return 0; -} - -/* See comments in blast.h */ -int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow, - unsigned *left, unsigned char **in) -{ - struct state s; /* input/output state */ - int err; /* return value */ - - /* initialize input state */ - s.infun = infun; - s.inhow = inhow; - if (left != NULL && *left) { - s.left = *left; - s.in = *in; - } - else - s.left = 0; - s.bitbuf = 0; - s.bitcnt = 0; - - /* initialize output state */ - s.outfun = outfun; - s.outhow = outhow; - s.next = 0; - s.first = 1; - - /* return if bits() or decode() tries to read past available input */ - if (setjmp(s.env) != 0) /* if came back here via longjmp(), */ - err = 2; /* then skip decomp(), return error */ - else - err = decomp(&s); /* decompress */ - - /* return unused input */ - if (left != NULL) - *left = s.left; - if (in != NULL) - *in = s.left ? s.in : NULL; - - /* write any leftover output and update the error code if needed */ - if (err != 1 && s.next && s.outfun(s.outhow, s.out, s.next) && err == 0) - err = 1; - return err; -} - -#ifdef TEST -/* Example of how to use blast() */ -#include -#include - -#define CHUNK 16384 - -local unsigned inf(void *how, unsigned char **buf) -{ - static unsigned char hold[CHUNK]; - - *buf = hold; - return fread(hold, 1, CHUNK, (FILE *)how); -} - -local int outf(void *how, unsigned char *buf, unsigned len) -{ - return fwrite(buf, 1, len, (FILE *)how) != len; -} - -/* Decompress a PKWare Compression Library stream from stdin to stdout */ -int main(void) -{ - int ret; - unsigned left; - - /* decompress to stdout */ - left = 0; - ret = blast(inf, stdin, outf, stdout, &left, NULL); - if (ret != 0) - fprintf(stderr, "blast error: %d\n", ret); - - /* count any leftover bytes */ - while (getchar() != EOF) - left++; - if (left) - fprintf(stderr, "blast warning: %u unused bytes of input\n", left); - - /* return blast() error code */ - return ret; -} -#endif diff --git a/deps/zlib/contrib/blast/blast.h b/deps/zlib/contrib/blast/blast.h deleted file mode 100644 index 6cf65eda16e5b8..00000000000000 --- a/deps/zlib/contrib/blast/blast.h +++ /dev/null @@ -1,83 +0,0 @@ -/* blast.h -- interface for blast.c - Copyright (C) 2003, 2012, 2013 Mark Adler - version 1.3, 24 Aug 2013 - - This software is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Mark Adler madler@alumni.caltech.edu - */ - - -/* - * blast() decompresses the PKWare Data Compression Library (DCL) compressed - * format. It provides the same functionality as the explode() function in - * that library. (Note: PKWare overused the "implode" verb, and the format - * used by their library implode() function is completely different and - * incompatible with the implode compression method supported by PKZIP.) - * - * The binary mode for stdio functions should be used to assure that the - * compressed data is not corrupted when read or written. For example: - * fopen(..., "rb") and fopen(..., "wb"). - */ - - -typedef unsigned (*blast_in)(void *how, unsigned char **buf); -typedef int (*blast_out)(void *how, unsigned char *buf, unsigned len); -/* Definitions for input/output functions passed to blast(). See below for - * what the provided functions need to do. - */ - - -int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow, - unsigned *left, unsigned char **in); -/* Decompress input to output using the provided infun() and outfun() calls. - * On success, the return value of blast() is zero. If there is an error in - * the source data, i.e. it is not in the proper format, then a negative value - * is returned. If there is not enough input available or there is not enough - * output space, then a positive error is returned. - * - * The input function is invoked: len = infun(how, &buf), where buf is set by - * infun() to point to the input buffer, and infun() returns the number of - * available bytes there. If infun() returns zero, then blast() returns with - * an input error. (blast() only asks for input if it needs it.) inhow is for - * use by the application to pass an input descriptor to infun(), if desired. - * - * If left and in are not NULL and *left is not zero when blast() is called, - * then the *left bytes are *in are consumed for input before infun() is used. - * - * The output function is invoked: err = outfun(how, buf, len), where the bytes - * to be written are buf[0..len-1]. If err is not zero, then blast() returns - * with an output error. outfun() is always called with len <= 4096. outhow - * is for use by the application to pass an output descriptor to outfun(), if - * desired. - * - * If there is any unused input, *left is set to the number of bytes that were - * read and *in points to them. Otherwise *left is set to zero and *in is set - * to NULL. If left or in are NULL, then they are not set. - * - * The return codes are: - * - * 2: ran out of input before completing decompression - * 1: output error before completing decompression - * 0: successful decompression - * -1: literal flag not zero or one - * -2: dictionary size not in 4..6 - * -3: distance is too far back - * - * At the bottom of blast.c is an example program that uses blast() that can be - * compiled to produce a command-line decompression filter by defining TEST. - */ diff --git a/deps/zlib/contrib/blast/test.pk b/deps/zlib/contrib/blast/test.pk deleted file mode 100644 index be10b2bbb25175..00000000000000 Binary files a/deps/zlib/contrib/blast/test.pk and /dev/null differ diff --git a/deps/zlib/contrib/blast/test.txt b/deps/zlib/contrib/blast/test.txt deleted file mode 100644 index bfdf1c5dca0a66..00000000000000 --- a/deps/zlib/contrib/blast/test.txt +++ /dev/null @@ -1 +0,0 @@ -AIAIAIAIAIAIA \ No newline at end of file diff --git a/deps/zlib/contrib/delphi/ZLib.pas b/deps/zlib/contrib/delphi/ZLib.pas deleted file mode 100644 index 060e1991186b19..00000000000000 --- a/deps/zlib/contrib/delphi/ZLib.pas +++ /dev/null @@ -1,557 +0,0 @@ -{*******************************************************} -{ } -{ Borland Delphi Supplemental Components } -{ ZLIB Data Compression Interface Unit } -{ } -{ Copyright (c) 1997,99 Borland Corporation } -{ } -{*******************************************************} - -{ Updated for zlib 1.2.x by Cosmin Truta } - -unit ZLib; - -interface - -uses SysUtils, Classes; - -type - TAlloc = function (AppData: Pointer; Items, Size: Integer): Pointer; cdecl; - TFree = procedure (AppData, Block: Pointer); cdecl; - - // Internal structure. Ignore. - TZStreamRec = packed record - next_in: PChar; // next input byte - avail_in: Integer; // number of bytes available at next_in - total_in: Longint; // total nb of input bytes read so far - - next_out: PChar; // next output byte should be put here - avail_out: Integer; // remaining free space at next_out - total_out: Longint; // total nb of bytes output so far - - msg: PChar; // last error message, NULL if no error - internal: Pointer; // not visible by applications - - zalloc: TAlloc; // used to allocate the internal state - zfree: TFree; // used to free the internal state - AppData: Pointer; // private data object passed to zalloc and zfree - - data_type: Integer; // best guess about the data type: ascii or binary - adler: Longint; // adler32 value of the uncompressed data - reserved: Longint; // reserved for future use - end; - - // Abstract ancestor class - TCustomZlibStream = class(TStream) - private - FStrm: TStream; - FStrmPos: Integer; - FOnProgress: TNotifyEvent; - FZRec: TZStreamRec; - FBuffer: array [Word] of Char; - protected - procedure Progress(Sender: TObject); dynamic; - property OnProgress: TNotifyEvent read FOnProgress write FOnProgress; - constructor Create(Strm: TStream); - end; - -{ TCompressionStream compresses data on the fly as data is written to it, and - stores the compressed data to another stream. - - TCompressionStream is write-only and strictly sequential. Reading from the - stream will raise an exception. Using Seek to move the stream pointer - will raise an exception. - - Output data is cached internally, written to the output stream only when - the internal output buffer is full. All pending output data is flushed - when the stream is destroyed. - - The Position property returns the number of uncompressed bytes of - data that have been written to the stream so far. - - CompressionRate returns the on-the-fly percentage by which the original - data has been compressed: (1 - (CompressedBytes / UncompressedBytes)) * 100 - If raw data size = 100 and compressed data size = 25, the CompressionRate - is 75% - - The OnProgress event is called each time the output buffer is filled and - written to the output stream. This is useful for updating a progress - indicator when you are writing a large chunk of data to the compression - stream in a single call.} - - - TCompressionLevel = (clNone, clFastest, clDefault, clMax); - - TCompressionStream = class(TCustomZlibStream) - private - function GetCompressionRate: Single; - public - constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream); - destructor Destroy; override; - function Read(var Buffer; Count: Longint): Longint; override; - function Write(const Buffer; Count: Longint): Longint; override; - function Seek(Offset: Longint; Origin: Word): Longint; override; - property CompressionRate: Single read GetCompressionRate; - property OnProgress; - end; - -{ TDecompressionStream decompresses data on the fly as data is read from it. - - Compressed data comes from a separate source stream. TDecompressionStream - is read-only and unidirectional; you can seek forward in the stream, but not - backwards. The special case of setting the stream position to zero is - allowed. Seeking forward decompresses data until the requested position in - the uncompressed data has been reached. Seeking backwards, seeking relative - to the end of the stream, requesting the size of the stream, and writing to - the stream will raise an exception. - - The Position property returns the number of bytes of uncompressed data that - have been read from the stream so far. - - The OnProgress event is called each time the internal input buffer of - compressed data is exhausted and the next block is read from the input stream. - This is useful for updating a progress indicator when you are reading a - large chunk of data from the decompression stream in a single call.} - - TDecompressionStream = class(TCustomZlibStream) - public - constructor Create(Source: TStream); - destructor Destroy; override; - function Read(var Buffer; Count: Longint): Longint; override; - function Write(const Buffer; Count: Longint): Longint; override; - function Seek(Offset: Longint; Origin: Word): Longint; override; - property OnProgress; - end; - - - -{ CompressBuf compresses data, buffer to buffer, in one call. - In: InBuf = ptr to compressed data - InBytes = number of bytes in InBuf - Out: OutBuf = ptr to newly allocated buffer containing decompressed data - OutBytes = number of bytes in OutBuf } -procedure CompressBuf(const InBuf: Pointer; InBytes: Integer; - out OutBuf: Pointer; out OutBytes: Integer); - - -{ DecompressBuf decompresses data, buffer to buffer, in one call. - In: InBuf = ptr to compressed data - InBytes = number of bytes in InBuf - OutEstimate = zero, or est. size of the decompressed data - Out: OutBuf = ptr to newly allocated buffer containing decompressed data - OutBytes = number of bytes in OutBuf } -procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; - OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer); - -{ DecompressToUserBuf decompresses data, buffer to buffer, in one call. - In: InBuf = ptr to compressed data - InBytes = number of bytes in InBuf - Out: OutBuf = ptr to user-allocated buffer to contain decompressed data - BufSize = number of bytes in OutBuf } -procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer; - const OutBuf: Pointer; BufSize: Integer); - -const - zlib_version = '1.2.11'; - -type - EZlibError = class(Exception); - ECompressionError = class(EZlibError); - EDecompressionError = class(EZlibError); - -implementation - -uses ZLibConst; - -const - Z_NO_FLUSH = 0; - Z_PARTIAL_FLUSH = 1; - Z_SYNC_FLUSH = 2; - Z_FULL_FLUSH = 3; - Z_FINISH = 4; - - Z_OK = 0; - Z_STREAM_END = 1; - Z_NEED_DICT = 2; - Z_ERRNO = (-1); - Z_STREAM_ERROR = (-2); - Z_DATA_ERROR = (-3); - Z_MEM_ERROR = (-4); - Z_BUF_ERROR = (-5); - Z_VERSION_ERROR = (-6); - - Z_NO_COMPRESSION = 0; - Z_BEST_SPEED = 1; - Z_BEST_COMPRESSION = 9; - Z_DEFAULT_COMPRESSION = (-1); - - Z_FILTERED = 1; - Z_HUFFMAN_ONLY = 2; - Z_RLE = 3; - Z_DEFAULT_STRATEGY = 0; - - Z_BINARY = 0; - Z_ASCII = 1; - Z_UNKNOWN = 2; - - Z_DEFLATED = 8; - - -{$L adler32.obj} -{$L compress.obj} -{$L crc32.obj} -{$L deflate.obj} -{$L infback.obj} -{$L inffast.obj} -{$L inflate.obj} -{$L inftrees.obj} -{$L trees.obj} -{$L uncompr.obj} -{$L zutil.obj} - -procedure adler32; external; -procedure compressBound; external; -procedure crc32; external; -procedure deflateInit2_; external; -procedure deflateParams; external; - -function _malloc(Size: Integer): Pointer; cdecl; -begin - Result := AllocMem(Size); -end; - -procedure _free(Block: Pointer); cdecl; -begin - FreeMem(Block); -end; - -procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl; -begin - FillChar(P^, count, B); -end; - -procedure _memcpy(dest, source: Pointer; count: Integer); cdecl; -begin - Move(source^, dest^, count); -end; - - - -// deflate compresses data -function deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar; - recsize: Integer): Integer; external; -function deflate(var strm: TZStreamRec; flush: Integer): Integer; external; -function deflateEnd(var strm: TZStreamRec): Integer; external; - -// inflate decompresses data -function inflateInit_(var strm: TZStreamRec; version: PChar; - recsize: Integer): Integer; external; -function inflate(var strm: TZStreamRec; flush: Integer): Integer; external; -function inflateEnd(var strm: TZStreamRec): Integer; external; -function inflateReset(var strm: TZStreamRec): Integer; external; - - -function zlibAllocMem(AppData: Pointer; Items, Size: Integer): Pointer; cdecl; -begin -// GetMem(Result, Items*Size); - Result := AllocMem(Items * Size); -end; - -procedure zlibFreeMem(AppData, Block: Pointer); cdecl; -begin - FreeMem(Block); -end; - -{function zlibCheck(code: Integer): Integer; -begin - Result := code; - if code < 0 then - raise EZlibError.Create('error'); //!! -end;} - -function CCheck(code: Integer): Integer; -begin - Result := code; - if code < 0 then - raise ECompressionError.Create('error'); //!! -end; - -function DCheck(code: Integer): Integer; -begin - Result := code; - if code < 0 then - raise EDecompressionError.Create('error'); //!! -end; - -procedure CompressBuf(const InBuf: Pointer; InBytes: Integer; - out OutBuf: Pointer; out OutBytes: Integer); -var - strm: TZStreamRec; - P: Pointer; -begin - FillChar(strm, sizeof(strm), 0); - strm.zalloc := zlibAllocMem; - strm.zfree := zlibFreeMem; - OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255; - GetMem(OutBuf, OutBytes); - try - strm.next_in := InBuf; - strm.avail_in := InBytes; - strm.next_out := OutBuf; - strm.avail_out := OutBytes; - CCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm))); - try - while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do - begin - P := OutBuf; - Inc(OutBytes, 256); - ReallocMem(OutBuf, OutBytes); - strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P))); - strm.avail_out := 256; - end; - finally - CCheck(deflateEnd(strm)); - end; - ReallocMem(OutBuf, strm.total_out); - OutBytes := strm.total_out; - except - FreeMem(OutBuf); - raise - end; -end; - - -procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; - OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer); -var - strm: TZStreamRec; - P: Pointer; - BufInc: Integer; -begin - FillChar(strm, sizeof(strm), 0); - strm.zalloc := zlibAllocMem; - strm.zfree := zlibFreeMem; - BufInc := (InBytes + 255) and not 255; - if OutEstimate = 0 then - OutBytes := BufInc - else - OutBytes := OutEstimate; - GetMem(OutBuf, OutBytes); - try - strm.next_in := InBuf; - strm.avail_in := InBytes; - strm.next_out := OutBuf; - strm.avail_out := OutBytes; - DCheck(inflateInit_(strm, zlib_version, sizeof(strm))); - try - while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do - begin - P := OutBuf; - Inc(OutBytes, BufInc); - ReallocMem(OutBuf, OutBytes); - strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P))); - strm.avail_out := BufInc; - end; - finally - DCheck(inflateEnd(strm)); - end; - ReallocMem(OutBuf, strm.total_out); - OutBytes := strm.total_out; - except - FreeMem(OutBuf); - raise - end; -end; - -procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer; - const OutBuf: Pointer; BufSize: Integer); -var - strm: TZStreamRec; -begin - FillChar(strm, sizeof(strm), 0); - strm.zalloc := zlibAllocMem; - strm.zfree := zlibFreeMem; - strm.next_in := InBuf; - strm.avail_in := InBytes; - strm.next_out := OutBuf; - strm.avail_out := BufSize; - DCheck(inflateInit_(strm, zlib_version, sizeof(strm))); - try - if DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END then - raise EZlibError.CreateRes(@sTargetBufferTooSmall); - finally - DCheck(inflateEnd(strm)); - end; -end; - -// TCustomZlibStream - -constructor TCustomZLibStream.Create(Strm: TStream); -begin - inherited Create; - FStrm := Strm; - FStrmPos := Strm.Position; - FZRec.zalloc := zlibAllocMem; - FZRec.zfree := zlibFreeMem; -end; - -procedure TCustomZLibStream.Progress(Sender: TObject); -begin - if Assigned(FOnProgress) then FOnProgress(Sender); -end; - - -// TCompressionStream - -constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel; - Dest: TStream); -const - Levels: array [TCompressionLevel] of ShortInt = - (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION); -begin - inherited Create(Dest); - FZRec.next_out := FBuffer; - FZRec.avail_out := sizeof(FBuffer); - CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec))); -end; - -destructor TCompressionStream.Destroy; -begin - FZRec.next_in := nil; - FZRec.avail_in := 0; - try - if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; - while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END) - and (FZRec.avail_out = 0) do - begin - FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); - FZRec.next_out := FBuffer; - FZRec.avail_out := sizeof(FBuffer); - end; - if FZRec.avail_out < sizeof(FBuffer) then - FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out); - finally - deflateEnd(FZRec); - end; - inherited Destroy; -end; - -function TCompressionStream.Read(var Buffer; Count: Longint): Longint; -begin - raise ECompressionError.CreateRes(@sInvalidStreamOp); -end; - -function TCompressionStream.Write(const Buffer; Count: Longint): Longint; -begin - FZRec.next_in := @Buffer; - FZRec.avail_in := Count; - if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; - while (FZRec.avail_in > 0) do - begin - CCheck(deflate(FZRec, 0)); - if FZRec.avail_out = 0 then - begin - FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); - FZRec.next_out := FBuffer; - FZRec.avail_out := sizeof(FBuffer); - FStrmPos := FStrm.Position; - Progress(Self); - end; - end; - Result := Count; -end; - -function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint; -begin - if (Offset = 0) and (Origin = soFromCurrent) then - Result := FZRec.total_in - else - raise ECompressionError.CreateRes(@sInvalidStreamOp); -end; - -function TCompressionStream.GetCompressionRate: Single; -begin - if FZRec.total_in = 0 then - Result := 0 - else - Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0; -end; - - -// TDecompressionStream - -constructor TDecompressionStream.Create(Source: TStream); -begin - inherited Create(Source); - FZRec.next_in := FBuffer; - FZRec.avail_in := 0; - DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec))); -end; - -destructor TDecompressionStream.Destroy; -begin - FStrm.Seek(-FZRec.avail_in, 1); - inflateEnd(FZRec); - inherited Destroy; -end; - -function TDecompressionStream.Read(var Buffer; Count: Longint): Longint; -begin - FZRec.next_out := @Buffer; - FZRec.avail_out := Count; - if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; - while (FZRec.avail_out > 0) do - begin - if FZRec.avail_in = 0 then - begin - FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer)); - if FZRec.avail_in = 0 then - begin - Result := Count - FZRec.avail_out; - Exit; - end; - FZRec.next_in := FBuffer; - FStrmPos := FStrm.Position; - Progress(Self); - end; - CCheck(inflate(FZRec, 0)); - end; - Result := Count; -end; - -function TDecompressionStream.Write(const Buffer; Count: Longint): Longint; -begin - raise EDecompressionError.CreateRes(@sInvalidStreamOp); -end; - -function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint; -var - I: Integer; - Buf: array [0..4095] of Char; -begin - if (Offset = 0) and (Origin = soFromBeginning) then - begin - DCheck(inflateReset(FZRec)); - FZRec.next_in := FBuffer; - FZRec.avail_in := 0; - FStrm.Position := 0; - FStrmPos := 0; - end - else if ( (Offset >= 0) and (Origin = soFromCurrent)) or - ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then - begin - if Origin = soFromBeginning then Dec(Offset, FZRec.total_out); - if Offset > 0 then - begin - for I := 1 to Offset div sizeof(Buf) do - ReadBuffer(Buf, sizeof(Buf)); - ReadBuffer(Buf, Offset mod sizeof(Buf)); - end; - end - else - raise EDecompressionError.CreateRes(@sInvalidStreamOp); - Result := FZRec.total_out; -end; - - -end. diff --git a/deps/zlib/contrib/delphi/ZLibConst.pas b/deps/zlib/contrib/delphi/ZLibConst.pas deleted file mode 100644 index cdfe13671d3544..00000000000000 --- a/deps/zlib/contrib/delphi/ZLibConst.pas +++ /dev/null @@ -1,11 +0,0 @@ -unit ZLibConst; - -interface - -resourcestring - sTargetBufferTooSmall = 'ZLib error: target buffer may be too small'; - sInvalidStreamOp = 'Invalid stream operation'; - -implementation - -end. diff --git a/deps/zlib/contrib/delphi/readme.txt b/deps/zlib/contrib/delphi/readme.txt deleted file mode 100644 index 2dc9a8bba2f96e..00000000000000 --- a/deps/zlib/contrib/delphi/readme.txt +++ /dev/null @@ -1,76 +0,0 @@ - -Overview -======== - -This directory contains an update to the ZLib interface unit, -distributed by Borland as a Delphi supplemental component. - -The original ZLib unit is Copyright (c) 1997,99 Borland Corp., -and is based on zlib version 1.0.4. There are a series of bugs -and security problems associated with that old zlib version, and -we recommend the users to update their ZLib unit. - - -Summary of modifications -======================== - -- Improved makefile, adapted to zlib version 1.2.1. - -- Some field types from TZStreamRec are changed from Integer to - Longint, for consistency with the zlib.h header, and for 64-bit - readiness. - -- The zlib_version constant is updated. - -- The new Z_RLE strategy has its corresponding symbolic constant. - -- The allocation and deallocation functions and function types - (TAlloc, TFree, zlibAllocMem and zlibFreeMem) are now cdecl, - and _malloc and _free are added as C RTL stubs. As a result, - the original C sources of zlib can be compiled out of the box, - and linked to the ZLib unit. - - -Suggestions for improvements -============================ - -Currently, the ZLib unit provides only a limited wrapper around -the zlib library, and much of the original zlib functionality is -missing. Handling compressed file formats like ZIP/GZIP or PNG -cannot be implemented without having this functionality. -Applications that handle these formats are either using their own, -duplicated code, or not using the ZLib unit at all. - -Here are a few suggestions: - -- Checksum class wrappers around adler32() and crc32(), similar - to the Java classes that implement the java.util.zip.Checksum - interface. - -- The ability to read and write raw deflate streams, without the - zlib stream header and trailer. Raw deflate streams are used - in the ZIP file format. - -- The ability to read and write gzip streams, used in the GZIP - file format, and normally produced by the gzip program. - -- The ability to select a different compression strategy, useful - to PNG and MNG image compression, and to multimedia compression - in general. Besides the compression level - - TCompressionLevel = (clNone, clFastest, clDefault, clMax); - - which, in fact, could have used the 'z' prefix and avoided - TColor-like symbols - - TCompressionLevel = (zcNone, zcFastest, zcDefault, zcMax); - - there could be a compression strategy - - TCompressionStrategy = (zsDefault, zsFiltered, zsHuffmanOnly, zsRle); - -- ZIP and GZIP stream handling via TStreams. - - --- -Cosmin Truta diff --git a/deps/zlib/contrib/delphi/zlibd32.mak b/deps/zlib/contrib/delphi/zlibd32.mak deleted file mode 100644 index 9bb00b7cc4211c..00000000000000 --- a/deps/zlib/contrib/delphi/zlibd32.mak +++ /dev/null @@ -1,99 +0,0 @@ -# Makefile for zlib -# For use with Delphi and C++ Builder under Win32 -# Updated for zlib 1.2.x by Cosmin Truta - -# ------------ Borland C++ ------------ - -# This project uses the Delphi (fastcall/register) calling convention: -LOC = -DZEXPORT=__fastcall -DZEXPORTVA=__cdecl - -CC = bcc32 -LD = bcc32 -AR = tlib -# do not use "-pr" in CFLAGS -CFLAGS = -a -d -k- -O2 $(LOC) -LDFLAGS = - - -# variables -ZLIB_LIB = zlib.lib - -OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj -OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj -OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj -OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj - - -# targets -all: $(ZLIB_LIB) example.exe minigzip.exe - -.c.obj: - $(CC) -c $(CFLAGS) $*.c - -adler32.obj: adler32.c zlib.h zconf.h - -compress.obj: compress.c zlib.h zconf.h - -crc32.obj: crc32.c zlib.h zconf.h crc32.h - -deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h - -gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h - -gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h - -gzread.obj: gzread.c zlib.h zconf.h gzguts.h - -gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h - -infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h - -inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h - -trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h - -uncompr.obj: uncompr.c zlib.h zconf.h - -zutil.obj: zutil.c zutil.h zlib.h zconf.h - -example.obj: test/example.c zlib.h zconf.h - -minigzip.obj: test/minigzip.c zlib.h zconf.h - - -# For the sake of the old Borland make, -# the command line is cut to fit in the MS-DOS 128 byte limit: -$(ZLIB_LIB): $(OBJ1) $(OBJ2) - -del $(ZLIB_LIB) - $(AR) $(ZLIB_LIB) $(OBJP1) - $(AR) $(ZLIB_LIB) $(OBJP2) - - -# testing -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -example.exe: example.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) - -minigzip.exe: minigzip.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) - - -# cleanup -clean: - -del *.obj - -del *.exe - -del *.lib - -del *.tds - -del zlib.bak - -del foo.gz - diff --git a/deps/zlib/contrib/dotzlib/DotZLib.build b/deps/zlib/contrib/dotzlib/DotZLib.build deleted file mode 100644 index 4ab1ca281e3f0a..00000000000000 --- a/deps/zlib/contrib/dotzlib/DotZLib.build +++ /dev/null @@ -1,33 +0,0 @@ - - - A .Net wrapper library around ZLib1.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/deps/zlib/contrib/dotzlib/DotZLib.chm b/deps/zlib/contrib/dotzlib/DotZLib.chm deleted file mode 100644 index f214a444aebb20..00000000000000 Binary files a/deps/zlib/contrib/dotzlib/DotZLib.chm and /dev/null differ diff --git a/deps/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs b/deps/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs deleted file mode 100644 index 724c5347f35367..00000000000000 --- a/deps/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -// -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -// -[assembly: AssemblyTitle("DotZLib")] -[assembly: AssemblyDescription(".Net bindings for ZLib compression dll 1.2.x")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Henrik Ravn")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("(c) 2004 by Henrik Ravn")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: - -[assembly: AssemblyVersion("1.0.*")] - -// -// In order to sign your assembly you must specify a key to use. Refer to the -// Microsoft .NET Framework documentation for more information on assembly signing. -// -// Use the attributes below to control which key is used for signing. -// -// Notes: -// (*) If no key is specified, the assembly is not signed. -// (*) KeyName refers to a key that has been installed in the Crypto Service -// Provider (CSP) on your machine. KeyFile refers to a file which contains -// a key. -// (*) If the KeyFile and the KeyName values are both specified, the -// following processing occurs: -// (1) If the KeyName can be found in the CSP, that key is used. -// (2) If the KeyName does not exist and the KeyFile does exist, the key -// in the KeyFile is installed into the CSP and used. -// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. -// When specifying the KeyFile, the location of the KeyFile should be -// relative to the project output directory which is -// %Project Directory%\obj\. For example, if your KeyFile is -// located in the project directory, you would specify the AssemblyKeyFile -// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] -// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework -// documentation for more information on this. -// -[assembly: AssemblyDelaySign(false)] -[assembly: AssemblyKeyFile("")] -[assembly: AssemblyKeyName("")] diff --git a/deps/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs b/deps/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs deleted file mode 100644 index b110dae6a1908d..00000000000000 --- a/deps/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs +++ /dev/null @@ -1,202 +0,0 @@ -// -// Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.Runtime.InteropServices; -using System.Text; - - -namespace DotZLib -{ - #region ChecksumGeneratorBase - /// - /// Implements the common functionality needed for all s - /// - /// - public abstract class ChecksumGeneratorBase : ChecksumGenerator - { - /// - /// The value of the current checksum - /// - protected uint _current; - - /// - /// Initializes a new instance of the checksum generator base - the current checksum is - /// set to zero - /// - public ChecksumGeneratorBase() - { - _current = 0; - } - - /// - /// Initializes a new instance of the checksum generator basewith a specified value - /// - /// The value to set the current checksum to - public ChecksumGeneratorBase(uint initialValue) - { - _current = initialValue; - } - - /// - /// Resets the current checksum to zero - /// - public void Reset() { _current = 0; } - - /// - /// Gets the current checksum value - /// - public uint Value { get { return _current; } } - - /// - /// Updates the current checksum with part of an array of bytes - /// - /// The data to update the checksum with - /// Where in data to start updating - /// The number of bytes from data to use - /// The sum of offset and count is larger than the length of data - /// data is a null reference - /// Offset or count is negative. - /// All the other Update methods are implmeneted in terms of this one. - /// This is therefore the only method a derived class has to implement - public abstract void Update(byte[] data, int offset, int count); - - /// - /// Updates the current checksum with an array of bytes. - /// - /// The data to update the checksum with - public void Update(byte[] data) - { - Update(data, 0, data.Length); - } - - /// - /// Updates the current checksum with the data from a string - /// - /// The string to update the checksum with - /// The characters in the string are converted by the UTF-8 encoding - public void Update(string data) - { - Update(Encoding.UTF8.GetBytes(data)); - } - - /// - /// Updates the current checksum with the data from a string, using a specific encoding - /// - /// The string to update the checksum with - /// The encoding to use - public void Update(string data, Encoding encoding) - { - Update(encoding.GetBytes(data)); - } - - } - #endregion - - #region CRC32 - /// - /// Implements a CRC32 checksum generator - /// - public sealed class CRC32Checksum : ChecksumGeneratorBase - { - #region DLL imports - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern uint crc32(uint crc, int data, uint length); - - #endregion - - /// - /// Initializes a new instance of the CRC32 checksum generator - /// - public CRC32Checksum() : base() {} - - /// - /// Initializes a new instance of the CRC32 checksum generator with a specified value - /// - /// The value to set the current checksum to - public CRC32Checksum(uint initialValue) : base(initialValue) {} - - /// - /// Updates the current checksum with part of an array of bytes - /// - /// The data to update the checksum with - /// Where in data to start updating - /// The number of bytes from data to use - /// The sum of offset and count is larger than the length of data - /// data is a null reference - /// Offset or count is negative. - public override void Update(byte[] data, int offset, int count) - { - if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); - if ((offset+count) > data.Length) throw new ArgumentException(); - GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); - try - { - _current = crc32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); - } - finally - { - hData.Free(); - } - } - - } - #endregion - - #region Adler - /// - /// Implements a checksum generator that computes the Adler checksum on data - /// - public sealed class AdlerChecksum : ChecksumGeneratorBase - { - #region DLL imports - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern uint adler32(uint adler, int data, uint length); - - #endregion - - /// - /// Initializes a new instance of the Adler checksum generator - /// - public AdlerChecksum() : base() {} - - /// - /// Initializes a new instance of the Adler checksum generator with a specified value - /// - /// The value to set the current checksum to - public AdlerChecksum(uint initialValue) : base(initialValue) {} - - /// - /// Updates the current checksum with part of an array of bytes - /// - /// The data to update the checksum with - /// Where in data to start updating - /// The number of bytes from data to use - /// The sum of offset and count is larger than the length of data - /// data is a null reference - /// Offset or count is negative. - public override void Update(byte[] data, int offset, int count) - { - if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); - if ((offset+count) > data.Length) throw new ArgumentException(); - GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); - try - { - _current = adler32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); - } - finally - { - hData.Free(); - } - } - - } - #endregion - -} \ No newline at end of file diff --git a/deps/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs b/deps/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs deleted file mode 100644 index 9c8d601954fafc..00000000000000 --- a/deps/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs +++ /dev/null @@ -1,83 +0,0 @@ -// -// Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.Diagnostics; - -namespace DotZLib -{ - - /// - /// This class implements a circular buffer - /// - internal class CircularBuffer - { - #region Private data - private int _capacity; - private int _head; - private int _tail; - private int _size; - private byte[] _buffer; - #endregion - - public CircularBuffer(int capacity) - { - Debug.Assert( capacity > 0 ); - _buffer = new byte[capacity]; - _capacity = capacity; - _head = 0; - _tail = 0; - _size = 0; - } - - public int Size { get { return _size; } } - - public int Put(byte[] source, int offset, int count) - { - Debug.Assert( count > 0 ); - int trueCount = Math.Min(count, _capacity - Size); - for (int i = 0; i < trueCount; ++i) - _buffer[(_tail+i) % _capacity] = source[offset+i]; - _tail += trueCount; - _tail %= _capacity; - _size += trueCount; - return trueCount; - } - - public bool Put(byte b) - { - if (Size == _capacity) // no room - return false; - _buffer[_tail++] = b; - _tail %= _capacity; - ++_size; - return true; - } - - public int Get(byte[] destination, int offset, int count) - { - int trueCount = Math.Min(count,Size); - for (int i = 0; i < trueCount; ++i) - destination[offset + i] = _buffer[(_head+i) % _capacity]; - _head += trueCount; - _head %= _capacity; - _size -= trueCount; - return trueCount; - } - - public int Get() - { - if (Size == 0) - return -1; - - int result = (int)_buffer[_head++ % _capacity]; - --_size; - return result; - } - - } -} diff --git a/deps/zlib/contrib/dotzlib/DotZLib/CodecBase.cs b/deps/zlib/contrib/dotzlib/DotZLib/CodecBase.cs deleted file mode 100644 index b0eb78a0221a48..00000000000000 --- a/deps/zlib/contrib/dotzlib/DotZLib/CodecBase.cs +++ /dev/null @@ -1,198 +0,0 @@ -// -// Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.Runtime.InteropServices; - -namespace DotZLib -{ - /// - /// Implements the common functionality needed for all s - /// - public abstract class CodecBase : Codec, IDisposable - { - - #region Data members - - /// - /// Instance of the internal zlib buffer structure that is - /// passed to all functions in the zlib dll - /// - internal ZStream _ztream = new ZStream(); - - /// - /// True if the object instance has been disposed, false otherwise - /// - protected bool _isDisposed = false; - - /// - /// The size of the internal buffers - /// - protected const int kBufferSize = 16384; - - private byte[] _outBuffer = new byte[kBufferSize]; - private byte[] _inBuffer = new byte[kBufferSize]; - - private GCHandle _hInput; - private GCHandle _hOutput; - - private uint _checksum = 0; - - #endregion - - /// - /// Initializes a new instance of the CodeBase class. - /// - public CodecBase() - { - try - { - _hInput = GCHandle.Alloc(_inBuffer, GCHandleType.Pinned); - _hOutput = GCHandle.Alloc(_outBuffer, GCHandleType.Pinned); - } - catch (Exception) - { - CleanUp(false); - throw; - } - } - - - #region Codec Members - - /// - /// Occurs when more processed data are available. - /// - public event DataAvailableHandler DataAvailable; - - /// - /// Fires the event - /// - protected void OnDataAvailable() - { - if (_ztream.total_out > 0) - { - if (DataAvailable != null) - DataAvailable( _outBuffer, 0, (int)_ztream.total_out); - resetOutput(); - } - } - - /// - /// Adds more data to the codec to be processed. - /// - /// Byte array containing the data to be added to the codec - /// Adding data may, or may not, raise the DataAvailable event - public void Add(byte[] data) - { - Add(data,0,data.Length); - } - - /// - /// Adds more data to the codec to be processed. - /// - /// Byte array containing the data to be added to the codec - /// The index of the first byte to add from data - /// The number of bytes to add - /// Adding data may, or may not, raise the DataAvailable event - /// This must be implemented by a derived class - public abstract void Add(byte[] data, int offset, int count); - - /// - /// Finishes up any pending data that needs to be processed and handled. - /// - /// This must be implemented by a derived class - public abstract void Finish(); - - /// - /// Gets the checksum of the data that has been added so far - /// - public uint Checksum { get { return _checksum; } } - - #endregion - - #region Destructor & IDisposable stuff - - /// - /// Destroys this instance - /// - ~CodecBase() - { - CleanUp(false); - } - - /// - /// Releases any unmanaged resources and calls the method of the derived class - /// - public void Dispose() - { - CleanUp(true); - } - - /// - /// Performs any codec specific cleanup - /// - /// This must be implemented by a derived class - protected abstract void CleanUp(); - - // performs the release of the handles and calls the dereived CleanUp() - private void CleanUp(bool isDisposing) - { - if (!_isDisposed) - { - CleanUp(); - if (_hInput.IsAllocated) - _hInput.Free(); - if (_hOutput.IsAllocated) - _hOutput.Free(); - - _isDisposed = true; - } - } - - - #endregion - - #region Helper methods - - /// - /// Copies a number of bytes to the internal codec buffer - ready for proccesing - /// - /// The byte array that contains the data to copy - /// The index of the first byte to copy - /// The number of bytes to copy from data - protected void copyInput(byte[] data, int startIndex, int count) - { - Array.Copy(data, startIndex, _inBuffer,0, count); - _ztream.next_in = _hInput.AddrOfPinnedObject(); - _ztream.total_in = 0; - _ztream.avail_in = (uint)count; - - } - - /// - /// Resets the internal output buffers to a known state - ready for processing - /// - protected void resetOutput() - { - _ztream.total_out = 0; - _ztream.avail_out = kBufferSize; - _ztream.next_out = _hOutput.AddrOfPinnedObject(); - } - - /// - /// Updates the running checksum property - /// - /// The new checksum value - protected void setChecksum(uint newSum) - { - _checksum = newSum; - } - #endregion - - } -} diff --git a/deps/zlib/contrib/dotzlib/DotZLib/Deflater.cs b/deps/zlib/contrib/dotzlib/DotZLib/Deflater.cs deleted file mode 100644 index 9039f41f663702..00000000000000 --- a/deps/zlib/contrib/dotzlib/DotZLib/Deflater.cs +++ /dev/null @@ -1,106 +0,0 @@ -// -// Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace DotZLib -{ - - /// - /// Implements a data compressor, using the deflate algorithm in the ZLib dll - /// - public sealed class Deflater : CodecBase - { - #region Dll imports - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] - private static extern int deflateInit_(ref ZStream sz, int level, string vs, int size); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int deflate(ref ZStream sz, int flush); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int deflateReset(ref ZStream sz); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int deflateEnd(ref ZStream sz); - #endregion - - /// - /// Constructs an new instance of the Deflater - /// - /// The compression level to use for this Deflater - public Deflater(CompressLevel level) : base() - { - int retval = deflateInit_(ref _ztream, (int)level, Info.Version, Marshal.SizeOf(_ztream)); - if (retval != 0) - throw new ZLibException(retval, "Could not initialize deflater"); - - resetOutput(); - } - - /// - /// Adds more data to the codec to be processed. - /// - /// Byte array containing the data to be added to the codec - /// The index of the first byte to add from data - /// The number of bytes to add - /// Adding data may, or may not, raise the DataAvailable event - public override void Add(byte[] data, int offset, int count) - { - if (data == null) throw new ArgumentNullException(); - if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); - if ((offset+count) > data.Length) throw new ArgumentException(); - - int total = count; - int inputIndex = offset; - int err = 0; - - while (err >= 0 && inputIndex < total) - { - copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize)); - while (err >= 0 && _ztream.avail_in > 0) - { - err = deflate(ref _ztream, (int)FlushTypes.None); - if (err == 0) - while (_ztream.avail_out == 0) - { - OnDataAvailable(); - err = deflate(ref _ztream, (int)FlushTypes.None); - } - inputIndex += (int)_ztream.total_in; - } - } - setChecksum( _ztream.adler ); - } - - - /// - /// Finishes up any pending data that needs to be processed and handled. - /// - public override void Finish() - { - int err; - do - { - err = deflate(ref _ztream, (int)FlushTypes.Finish); - OnDataAvailable(); - } - while (err == 0); - setChecksum( _ztream.adler ); - deflateReset(ref _ztream); - resetOutput(); - } - - /// - /// Closes the internal zlib deflate stream - /// - protected override void CleanUp() { deflateEnd(ref _ztream); } - - } -} diff --git a/deps/zlib/contrib/dotzlib/DotZLib/DotZLib.cs b/deps/zlib/contrib/dotzlib/DotZLib/DotZLib.cs deleted file mode 100644 index 90c7c3b3807333..00000000000000 --- a/deps/zlib/contrib/dotzlib/DotZLib/DotZLib.cs +++ /dev/null @@ -1,288 +0,0 @@ -// -// Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; - - -namespace DotZLib -{ - - #region Internal types - - /// - /// Defines constants for the various flush types used with zlib - /// - internal enum FlushTypes - { - None, Partial, Sync, Full, Finish, Block - } - - #region ZStream structure - // internal mapping of the zlib zstream structure for marshalling - [StructLayoutAttribute(LayoutKind.Sequential, Pack=4, Size=0, CharSet=CharSet.Ansi)] - internal struct ZStream - { - public IntPtr next_in; - public uint avail_in; - public uint total_in; - - public IntPtr next_out; - public uint avail_out; - public uint total_out; - - [MarshalAs(UnmanagedType.LPStr)] - string msg; - uint state; - - uint zalloc; - uint zfree; - uint opaque; - - int data_type; - public uint adler; - uint reserved; - } - - #endregion - - #endregion - - #region Public enums - /// - /// Defines constants for the available compression levels in zlib - /// - public enum CompressLevel : int - { - /// - /// The default compression level with a reasonable compromise between compression and speed - /// - Default = -1, - /// - /// No compression at all. The data are passed straight through. - /// - None = 0, - /// - /// The maximum compression rate available. - /// - Best = 9, - /// - /// The fastest available compression level. - /// - Fastest = 1 - } - #endregion - - #region Exception classes - /// - /// The exception that is thrown when an error occurs on the zlib dll - /// - public class ZLibException : ApplicationException - { - /// - /// Initializes a new instance of the class with a specified - /// error message and error code - /// - /// The zlib error code that caused the exception - /// A message that (hopefully) describes the error - public ZLibException(int errorCode, string msg) : base(String.Format("ZLib error {0} {1}", errorCode, msg)) - { - } - - /// - /// Initializes a new instance of the class with a specified - /// error code - /// - /// The zlib error code that caused the exception - public ZLibException(int errorCode) : base(String.Format("ZLib error {0}", errorCode)) - { - } - } - #endregion - - #region Interfaces - - /// - /// Declares methods and properties that enables a running checksum to be calculated - /// - public interface ChecksumGenerator - { - /// - /// Gets the current value of the checksum - /// - uint Value { get; } - - /// - /// Clears the current checksum to 0 - /// - void Reset(); - - /// - /// Updates the current checksum with an array of bytes - /// - /// The data to update the checksum with - void Update(byte[] data); - - /// - /// Updates the current checksum with part of an array of bytes - /// - /// The data to update the checksum with - /// Where in data to start updating - /// The number of bytes from data to use - /// The sum of offset and count is larger than the length of data - /// data is a null reference - /// Offset or count is negative. - void Update(byte[] data, int offset, int count); - - /// - /// Updates the current checksum with the data from a string - /// - /// The string to update the checksum with - /// The characters in the string are converted by the UTF-8 encoding - void Update(string data); - - /// - /// Updates the current checksum with the data from a string, using a specific encoding - /// - /// The string to update the checksum with - /// The encoding to use - void Update(string data, Encoding encoding); - } - - - /// - /// Represents the method that will be called from a codec when new data - /// are available. - /// - /// The byte array containing the processed data - /// The index of the first processed byte in data - /// The number of processed bytes available - /// On return from this method, the data may be overwritten, so grab it while you can. - /// You cannot assume that startIndex will be zero. - /// - public delegate void DataAvailableHandler(byte[] data, int startIndex, int count); - - /// - /// Declares methods and events for implementing compressors/decompressors - /// - public interface Codec - { - /// - /// Occurs when more processed data are available. - /// - event DataAvailableHandler DataAvailable; - - /// - /// Adds more data to the codec to be processed. - /// - /// Byte array containing the data to be added to the codec - /// Adding data may, or may not, raise the DataAvailable event - void Add(byte[] data); - - /// - /// Adds more data to the codec to be processed. - /// - /// Byte array containing the data to be added to the codec - /// The index of the first byte to add from data - /// The number of bytes to add - /// Adding data may, or may not, raise the DataAvailable event - void Add(byte[] data, int offset, int count); - - /// - /// Finishes up any pending data that needs to be processed and handled. - /// - void Finish(); - - /// - /// Gets the checksum of the data that has been added so far - /// - uint Checksum { get; } - - - } - - #endregion - - #region Classes - /// - /// Encapsulates general information about the ZLib library - /// - public class Info - { - #region DLL imports - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern uint zlibCompileFlags(); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern string zlibVersion(); - #endregion - - #region Private stuff - private uint _flags; - - // helper function that unpacks a bitsize mask - private static int bitSize(uint bits) - { - switch (bits) - { - case 0: return 16; - case 1: return 32; - case 2: return 64; - } - return -1; - } - #endregion - - /// - /// Constructs an instance of the Info class. - /// - public Info() - { - _flags = zlibCompileFlags(); - } - - /// - /// True if the library is compiled with debug info - /// - public bool HasDebugInfo { get { return 0 != (_flags & 0x100); } } - - /// - /// True if the library is compiled with assembly optimizations - /// - public bool UsesAssemblyCode { get { return 0 != (_flags & 0x200); } } - - /// - /// Gets the size of the unsigned int that was compiled into Zlib - /// - public int SizeOfUInt { get { return bitSize(_flags & 3); } } - - /// - /// Gets the size of the unsigned long that was compiled into Zlib - /// - public int SizeOfULong { get { return bitSize((_flags >> 2) & 3); } } - - /// - /// Gets the size of the pointers that were compiled into Zlib - /// - public int SizeOfPointer { get { return bitSize((_flags >> 4) & 3); } } - - /// - /// Gets the size of the z_off_t type that was compiled into Zlib - /// - public int SizeOfOffset { get { return bitSize((_flags >> 6) & 3); } } - - /// - /// Gets the version of ZLib as a string, e.g. "1.2.1" - /// - public static string Version { get { return zlibVersion(); } } - } - - #endregion - -} diff --git a/deps/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj b/deps/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj deleted file mode 100644 index dea7fb16a94a13..00000000000000 --- a/deps/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/deps/zlib/contrib/dotzlib/DotZLib/GZipStream.cs b/deps/zlib/contrib/dotzlib/DotZLib/GZipStream.cs deleted file mode 100644 index f0eada1d24bb88..00000000000000 --- a/deps/zlib/contrib/dotzlib/DotZLib/GZipStream.cs +++ /dev/null @@ -1,301 +0,0 @@ -// -// Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.IO; -using System.Runtime.InteropServices; - -namespace DotZLib -{ - /// - /// Implements a compressed , in GZip (.gz) format. - /// - public class GZipStream : Stream, IDisposable - { - #region Dll Imports - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] - private static extern IntPtr gzopen(string name, string mode); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int gzclose(IntPtr gzFile); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int gzwrite(IntPtr gzFile, int data, int length); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int gzread(IntPtr gzFile, int data, int length); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int gzgetc(IntPtr gzFile); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int gzputc(IntPtr gzFile, int c); - - #endregion - - #region Private data - private IntPtr _gzFile; - private bool _isDisposed = false; - private bool _isWriting; - #endregion - - #region Constructors - /// - /// Creates a new file as a writeable GZipStream - /// - /// The name of the compressed file to create - /// The compression level to use when adding data - /// If an error occurred in the internal zlib function - public GZipStream(string fileName, CompressLevel level) - { - _isWriting = true; - _gzFile = gzopen(fileName, String.Format("wb{0}", (int)level)); - if (_gzFile == IntPtr.Zero) - throw new ZLibException(-1, "Could not open " + fileName); - } - - /// - /// Opens an existing file as a readable GZipStream - /// - /// The name of the file to open - /// If an error occurred in the internal zlib function - public GZipStream(string fileName) - { - _isWriting = false; - _gzFile = gzopen(fileName, "rb"); - if (_gzFile == IntPtr.Zero) - throw new ZLibException(-1, "Could not open " + fileName); - - } - #endregion - - #region Access properties - /// - /// Returns true of this stream can be read from, false otherwise - /// - public override bool CanRead - { - get - { - return !_isWriting; - } - } - - - /// - /// Returns false. - /// - public override bool CanSeek - { - get - { - return false; - } - } - - /// - /// Returns true if this tsream is writeable, false otherwise - /// - public override bool CanWrite - { - get - { - return _isWriting; - } - } - #endregion - - #region Destructor & IDispose stuff - - /// - /// Destroys this instance - /// - ~GZipStream() - { - cleanUp(false); - } - - /// - /// Closes the external file handle - /// - public void Dispose() - { - cleanUp(true); - } - - // Does the actual closing of the file handle. - private void cleanUp(bool isDisposing) - { - if (!_isDisposed) - { - gzclose(_gzFile); - _isDisposed = true; - } - } - #endregion - - #region Basic reading and writing - /// - /// Attempts to read a number of bytes from the stream. - /// - /// The destination data buffer - /// The index of the first destination byte in buffer - /// The number of bytes requested - /// The number of bytes read - /// If buffer is null - /// If count or offset are negative - /// If offset + count is > buffer.Length - /// If this stream is not readable. - /// If this stream has been disposed. - public override int Read(byte[] buffer, int offset, int count) - { - if (!CanRead) throw new NotSupportedException(); - if (buffer == null) throw new ArgumentNullException(); - if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); - if ((offset+count) > buffer.Length) throw new ArgumentException(); - if (_isDisposed) throw new ObjectDisposedException("GZipStream"); - - GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); - int result; - try - { - result = gzread(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count); - if (result < 0) - throw new IOException(); - } - finally - { - h.Free(); - } - return result; - } - - /// - /// Attempts to read a single byte from the stream. - /// - /// The byte that was read, or -1 in case of error or End-Of-File - public override int ReadByte() - { - if (!CanRead) throw new NotSupportedException(); - if (_isDisposed) throw new ObjectDisposedException("GZipStream"); - return gzgetc(_gzFile); - } - - /// - /// Writes a number of bytes to the stream - /// - /// - /// - /// - /// If buffer is null - /// If count or offset are negative - /// If offset + count is > buffer.Length - /// If this stream is not writeable. - /// If this stream has been disposed. - public override void Write(byte[] buffer, int offset, int count) - { - if (!CanWrite) throw new NotSupportedException(); - if (buffer == null) throw new ArgumentNullException(); - if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); - if ((offset+count) > buffer.Length) throw new ArgumentException(); - if (_isDisposed) throw new ObjectDisposedException("GZipStream"); - - GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); - try - { - int result = gzwrite(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count); - if (result < 0) - throw new IOException(); - } - finally - { - h.Free(); - } - } - - /// - /// Writes a single byte to the stream - /// - /// The byte to add to the stream. - /// If this stream is not writeable. - /// If this stream has been disposed. - public override void WriteByte(byte value) - { - if (!CanWrite) throw new NotSupportedException(); - if (_isDisposed) throw new ObjectDisposedException("GZipStream"); - - int result = gzputc(_gzFile, (int)value); - if (result < 0) - throw new IOException(); - } - #endregion - - #region Position & length stuff - /// - /// Not supported. - /// - /// - /// Always thrown - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - /// - /// Not suppported. - /// - /// - /// - /// - /// Always thrown - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotSupportedException(); - } - - /// - /// Flushes the GZipStream. - /// - /// In this implementation, this method does nothing. This is because excessive - /// flushing may degrade the achievable compression rates. - public override void Flush() - { - // left empty on purpose - } - - /// - /// Gets/sets the current position in the GZipStream. Not suppported. - /// - /// In this implementation this property is not supported - /// Always thrown - public override long Position - { - get - { - throw new NotSupportedException(); - } - set - { - throw new NotSupportedException(); - } - } - - /// - /// Gets the size of the stream. Not suppported. - /// - /// In this implementation this property is not supported - /// Always thrown - public override long Length - { - get - { - throw new NotSupportedException(); - } - } - #endregion - } -} diff --git a/deps/zlib/contrib/dotzlib/DotZLib/Inflater.cs b/deps/zlib/contrib/dotzlib/DotZLib/Inflater.cs deleted file mode 100644 index d295f268048696..00000000000000 --- a/deps/zlib/contrib/dotzlib/DotZLib/Inflater.cs +++ /dev/null @@ -1,105 +0,0 @@ -// -// Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace DotZLib -{ - - /// - /// Implements a data decompressor, using the inflate algorithm in the ZLib dll - /// - public class Inflater : CodecBase - { - #region Dll imports - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] - private static extern int inflateInit_(ref ZStream sz, string vs, int size); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int inflate(ref ZStream sz, int flush); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int inflateReset(ref ZStream sz); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int inflateEnd(ref ZStream sz); - #endregion - - /// - /// Constructs an new instance of the Inflater - /// - public Inflater() : base() - { - int retval = inflateInit_(ref _ztream, Info.Version, Marshal.SizeOf(_ztream)); - if (retval != 0) - throw new ZLibException(retval, "Could not initialize inflater"); - - resetOutput(); - } - - - /// - /// Adds more data to the codec to be processed. - /// - /// Byte array containing the data to be added to the codec - /// The index of the first byte to add from data - /// The number of bytes to add - /// Adding data may, or may not, raise the DataAvailable event - public override void Add(byte[] data, int offset, int count) - { - if (data == null) throw new ArgumentNullException(); - if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); - if ((offset+count) > data.Length) throw new ArgumentException(); - - int total = count; - int inputIndex = offset; - int err = 0; - - while (err >= 0 && inputIndex < total) - { - copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize)); - err = inflate(ref _ztream, (int)FlushTypes.None); - if (err == 0) - while (_ztream.avail_out == 0) - { - OnDataAvailable(); - err = inflate(ref _ztream, (int)FlushTypes.None); - } - - inputIndex += (int)_ztream.total_in; - } - setChecksum( _ztream.adler ); - } - - - /// - /// Finishes up any pending data that needs to be processed and handled. - /// - public override void Finish() - { - int err; - do - { - err = inflate(ref _ztream, (int)FlushTypes.Finish); - OnDataAvailable(); - } - while (err == 0); - setChecksum( _ztream.adler ); - inflateReset(ref _ztream); - resetOutput(); - } - - /// - /// Closes the internal zlib inflate stream - /// - protected override void CleanUp() { inflateEnd(ref _ztream); } - - - } -} diff --git a/deps/zlib/contrib/dotzlib/DotZLib/UnitTests.cs b/deps/zlib/contrib/dotzlib/DotZLib/UnitTests.cs deleted file mode 100644 index 6d8aebb7994ef4..00000000000000 --- a/deps/zlib/contrib/dotzlib/DotZLib/UnitTests.cs +++ /dev/null @@ -1,274 +0,0 @@ -// -// © Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.Collections; -using System.IO; - -// uncomment the define below to include unit tests -//#define nunit -#if nunit -using NUnit.Framework; - -// Unit tests for the DotZLib class library -// ---------------------------------------- -// -// Use this with NUnit 2 from http://www.nunit.org -// - -namespace DotZLibTests -{ - using DotZLib; - - // helper methods - internal class Utils - { - public static bool byteArrEqual( byte[] lhs, byte[] rhs ) - { - if (lhs.Length != rhs.Length) - return false; - for (int i = lhs.Length-1; i >= 0; --i) - if (lhs[i] != rhs[i]) - return false; - return true; - } - - } - - - [TestFixture] - public class CircBufferTests - { - #region Circular buffer tests - [Test] - public void SinglePutGet() - { - CircularBuffer buf = new CircularBuffer(10); - Assert.AreEqual( 0, buf.Size ); - Assert.AreEqual( -1, buf.Get() ); - - Assert.IsTrue(buf.Put( 1 )); - Assert.AreEqual( 1, buf.Size ); - Assert.AreEqual( 1, buf.Get() ); - Assert.AreEqual( 0, buf.Size ); - Assert.AreEqual( -1, buf.Get() ); - } - - [Test] - public void BlockPutGet() - { - CircularBuffer buf = new CircularBuffer(10); - byte[] arr = {1,2,3,4,5,6,7,8,9,10}; - Assert.AreEqual( 10, buf.Put(arr,0,10) ); - Assert.AreEqual( 10, buf.Size ); - Assert.IsFalse( buf.Put(11) ); - Assert.AreEqual( 1, buf.Get() ); - Assert.IsTrue( buf.Put(11) ); - - byte[] arr2 = (byte[])arr.Clone(); - Assert.AreEqual( 9, buf.Get(arr2,1,9) ); - Assert.IsTrue( Utils.byteArrEqual(arr,arr2) ); - } - - #endregion - } - - [TestFixture] - public class ChecksumTests - { - #region CRC32 Tests - [Test] - public void CRC32_Null() - { - CRC32Checksum crc32 = new CRC32Checksum(); - Assert.AreEqual( 0, crc32.Value ); - - crc32 = new CRC32Checksum(1); - Assert.AreEqual( 1, crc32.Value ); - - crc32 = new CRC32Checksum(556); - Assert.AreEqual( 556, crc32.Value ); - } - - [Test] - public void CRC32_Data() - { - CRC32Checksum crc32 = new CRC32Checksum(); - byte[] data = { 1,2,3,4,5,6,7 }; - crc32.Update(data); - Assert.AreEqual( 0x70e46888, crc32.Value ); - - crc32 = new CRC32Checksum(); - crc32.Update("penguin"); - Assert.AreEqual( 0x0e5c1a120, crc32.Value ); - - crc32 = new CRC32Checksum(1); - crc32.Update("penguin"); - Assert.AreEqual(0x43b6aa94, crc32.Value); - - } - #endregion - - #region Adler tests - - [Test] - public void Adler_Null() - { - AdlerChecksum adler = new AdlerChecksum(); - Assert.AreEqual(0, adler.Value); - - adler = new AdlerChecksum(1); - Assert.AreEqual( 1, adler.Value ); - - adler = new AdlerChecksum(556); - Assert.AreEqual( 556, adler.Value ); - } - - [Test] - public void Adler_Data() - { - AdlerChecksum adler = new AdlerChecksum(1); - byte[] data = { 1,2,3,4,5,6,7 }; - adler.Update(data); - Assert.AreEqual( 0x5b001d, adler.Value ); - - adler = new AdlerChecksum(); - adler.Update("penguin"); - Assert.AreEqual(0x0bcf02f6, adler.Value ); - - adler = new AdlerChecksum(1); - adler.Update("penguin"); - Assert.AreEqual(0x0bd602f7, adler.Value); - - } - #endregion - } - - [TestFixture] - public class InfoTests - { - #region Info tests - [Test] - public void Info_Version() - { - Info info = new Info(); - Assert.AreEqual("1.2.11", Info.Version); - Assert.AreEqual(32, info.SizeOfUInt); - Assert.AreEqual(32, info.SizeOfULong); - Assert.AreEqual(32, info.SizeOfPointer); - Assert.AreEqual(32, info.SizeOfOffset); - } - #endregion - } - - [TestFixture] - public class DeflateInflateTests - { - #region Deflate tests - [Test] - public void Deflate_Init() - { - using (Deflater def = new Deflater(CompressLevel.Default)) - { - } - } - - private ArrayList compressedData = new ArrayList(); - private uint adler1; - - private ArrayList uncompressedData = new ArrayList(); - private uint adler2; - - public void CDataAvail(byte[] data, int startIndex, int count) - { - for (int i = 0; i < count; ++i) - compressedData.Add(data[i+startIndex]); - } - - [Test] - public void Deflate_Compress() - { - compressedData.Clear(); - - byte[] testData = new byte[35000]; - for (int i = 0; i < testData.Length; ++i) - testData[i] = 5; - - using (Deflater def = new Deflater((CompressLevel)5)) - { - def.DataAvailable += new DataAvailableHandler(CDataAvail); - def.Add(testData); - def.Finish(); - adler1 = def.Checksum; - } - } - #endregion - - #region Inflate tests - [Test] - public void Inflate_Init() - { - using (Inflater inf = new Inflater()) - { - } - } - - private void DDataAvail(byte[] data, int startIndex, int count) - { - for (int i = 0; i < count; ++i) - uncompressedData.Add(data[i+startIndex]); - } - - [Test] - public void Inflate_Expand() - { - uncompressedData.Clear(); - - using (Inflater inf = new Inflater()) - { - inf.DataAvailable += new DataAvailableHandler(DDataAvail); - inf.Add((byte[])compressedData.ToArray(typeof(byte))); - inf.Finish(); - adler2 = inf.Checksum; - } - Assert.AreEqual( adler1, adler2 ); - } - #endregion - } - - [TestFixture] - public class GZipStreamTests - { - #region GZipStream test - [Test] - public void GZipStream_WriteRead() - { - using (GZipStream gzOut = new GZipStream("gzstream.gz", CompressLevel.Best)) - { - BinaryWriter writer = new BinaryWriter(gzOut); - writer.Write("hi there"); - writer.Write(Math.PI); - writer.Write(42); - } - - using (GZipStream gzIn = new GZipStream("gzstream.gz")) - { - BinaryReader reader = new BinaryReader(gzIn); - string s = reader.ReadString(); - Assert.AreEqual("hi there",s); - double d = reader.ReadDouble(); - Assert.AreEqual(Math.PI, d); - int i = reader.ReadInt32(); - Assert.AreEqual(42,i); - } - - } - #endregion - } -} - -#endif diff --git a/deps/zlib/contrib/dotzlib/LICENSE_1_0.txt b/deps/zlib/contrib/dotzlib/LICENSE_1_0.txt deleted file mode 100644 index 127a5bc39ba030..00000000000000 --- a/deps/zlib/contrib/dotzlib/LICENSE_1_0.txt +++ /dev/null @@ -1,23 +0,0 @@ -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/deps/zlib/contrib/dotzlib/readme.txt b/deps/zlib/contrib/dotzlib/readme.txt deleted file mode 100644 index 4d8c2dd9324c4c..00000000000000 --- a/deps/zlib/contrib/dotzlib/readme.txt +++ /dev/null @@ -1,58 +0,0 @@ -This directory contains a .Net wrapper class library for the ZLib1.dll - -The wrapper includes support for inflating/deflating memory buffers, -.Net streaming wrappers for the gz streams part of zlib, and wrappers -for the checksum parts of zlib. See DotZLib/UnitTests.cs for examples. - -Directory structure: --------------------- - -LICENSE_1_0.txt - License file. -readme.txt - This file. -DotZLib.chm - Class library documentation -DotZLib.build - NAnt build file -DotZLib.sln - Microsoft Visual Studio 2003 solution file - -DotZLib\*.cs - Source files for the class library - -Unit tests: ------------ -The file DotZLib/UnitTests.cs contains unit tests for use with NUnit 2.1 or higher. -To include unit tests in the build, define nunit before building. - - -Build instructions: -------------------- - -1. Using Visual Studio.Net 2003: - Open DotZLib.sln in VS.Net and build from there. Output file (DotZLib.dll) - will be found ./DotZLib/bin/release or ./DotZLib/bin/debug, depending on - you are building the release or debug version of the library. Check - DotZLib/UnitTests.cs for instructions on how to include unit tests in the - build. - -2. Using NAnt: - Open a command prompt with access to the build environment and run nant - in the same directory as the DotZLib.build file. - You can define 2 properties on the nant command-line to control the build: - debug={true|false} to toggle between release/debug builds (default=true). - nunit={true|false} to include or esclude unit tests (default=true). - Also the target clean will remove binaries. - Output file (DotZLib.dll) will be found in either ./DotZLib/bin/release - or ./DotZLib/bin/debug, depending on whether you are building the release - or debug version of the library. - - Examples: - nant -D:debug=false -D:nunit=false - will build a release mode version of the library without unit tests. - nant - will build a debug version of the library with unit tests - nant clean - will remove all previously built files. - - ---------------------------------- -Copyright (c) Henrik Ravn 2004 - -Use, modification and distribution are subject to the Boost Software License, Version 1.0. -(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/deps/zlib/contrib/gcc_gvmat64/gvmat64.S b/deps/zlib/contrib/gcc_gvmat64/gvmat64.S deleted file mode 100644 index 23309fa286e535..00000000000000 --- a/deps/zlib/contrib/gcc_gvmat64/gvmat64.S +++ /dev/null @@ -1,574 +0,0 @@ -/* -;uInt longest_match_x64( -; deflate_state *s, -; IPos cur_match); // current match - -; gvmat64.S -- Asm portion of the optimized longest_match for 32 bits x86_64 -; (AMD64 on Athlon 64, Opteron, Phenom -; and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7) -; this file is translation from gvmat64.asm to GCC 4.x (for Linux, Mac XCode) -; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant. -; -; File written by Gilles Vollant, by converting to assembly the longest_match -; from Jean-loup Gailly in deflate.c of zLib and infoZip zip. -; and by taking inspiration on asm686 with masm, optimised assembly code -; from Brian Raiter, written 1998 -; -; This software is provided 'as-is', without any express or implied -; warranty. In no event will the authors be held liable for any damages -; arising from the use of this software. -; -; Permission is granted to anyone to use this software for any purpose, -; including commercial applications, and to alter it and redistribute it -; freely, subject to the following restrictions: -; -; 1. The origin of this software must not be misrepresented; you must not -; claim that you wrote the original software. If you use this software -; in a product, an acknowledgment in the product documentation would be -; appreciated but is not required. -; 2. Altered source versions must be plainly marked as such, and must not be -; misrepresented as being the original software -; 3. This notice may not be removed or altered from any source distribution. -; -; http://www.zlib.net -; http://www.winimage.com/zLibDll -; http://www.muppetlabs.com/~breadbox/software/assembly.html -; -; to compile this file for zLib, I use option: -; gcc -c -arch x86_64 gvmat64.S - - -;uInt longest_match(s, cur_match) -; deflate_state *s; -; IPos cur_match; // current match / -; -; with XCode for Mac, I had strange error with some jump on intel syntax -; this is why BEFORE_JMP and AFTER_JMP are used - */ - - -#define BEFORE_JMP .att_syntax -#define AFTER_JMP .intel_syntax noprefix - -#ifndef NO_UNDERLINE -# define match_init _match_init -# define longest_match _longest_match -#endif - -.intel_syntax noprefix - -.globl match_init, longest_match -.text -longest_match: - - - -#define LocalVarsSize 96 -/* -; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12 -; free register : r14,r15 -; register can be saved : rsp -*/ - -#define chainlenwmask (rsp + 8 - LocalVarsSize) -#define nicematch (rsp + 16 - LocalVarsSize) - -#define save_rdi (rsp + 24 - LocalVarsSize) -#define save_rsi (rsp + 32 - LocalVarsSize) -#define save_rbx (rsp + 40 - LocalVarsSize) -#define save_rbp (rsp + 48 - LocalVarsSize) -#define save_r12 (rsp + 56 - LocalVarsSize) -#define save_r13 (rsp + 64 - LocalVarsSize) -#define save_r14 (rsp + 72 - LocalVarsSize) -#define save_r15 (rsp + 80 - LocalVarsSize) - - -/* -; all the +4 offsets are due to the addition of pending_buf_size (in zlib -; in the deflate_state structure since the asm code was first written -; (if you compile with zlib 1.0.4 or older, remove the +4). -; Note : these value are good with a 8 bytes boundary pack structure -*/ - -#define MAX_MATCH 258 -#define MIN_MATCH 3 -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) - -/* -;;; Offsets for fields in the deflate_state structure. These numbers -;;; are calculated from the definition of deflate_state, with the -;;; assumption that the compiler will dword-align the fields. (Thus, -;;; changing the definition of deflate_state could easily cause this -;;; program to crash horribly, without so much as a warning at -;;; compile time. Sigh.) - -; all the +zlib1222add offsets are due to the addition of fields -; in zlib in the deflate_state structure since the asm code was first written -; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). -; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). -; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). -*/ - - - -/* you can check the structure offset by running - -#include -#include -#include "deflate.h" - -void print_depl() -{ -deflate_state ds; -deflate_state *s=&ds; -printf("size pointer=%u\n",(int)sizeof(void*)); - -printf("#define dsWSize %u\n",(int)(((char*)&(s->w_size))-((char*)s))); -printf("#define dsWMask %u\n",(int)(((char*)&(s->w_mask))-((char*)s))); -printf("#define dsWindow %u\n",(int)(((char*)&(s->window))-((char*)s))); -printf("#define dsPrev %u\n",(int)(((char*)&(s->prev))-((char*)s))); -printf("#define dsMatchLen %u\n",(int)(((char*)&(s->match_length))-((char*)s))); -printf("#define dsPrevMatch %u\n",(int)(((char*)&(s->prev_match))-((char*)s))); -printf("#define dsStrStart %u\n",(int)(((char*)&(s->strstart))-((char*)s))); -printf("#define dsMatchStart %u\n",(int)(((char*)&(s->match_start))-((char*)s))); -printf("#define dsLookahead %u\n",(int)(((char*)&(s->lookahead))-((char*)s))); -printf("#define dsPrevLen %u\n",(int)(((char*)&(s->prev_length))-((char*)s))); -printf("#define dsMaxChainLen %u\n",(int)(((char*)&(s->max_chain_length))-((char*)s))); -printf("#define dsGoodMatch %u\n",(int)(((char*)&(s->good_match))-((char*)s))); -printf("#define dsNiceMatch %u\n",(int)(((char*)&(s->nice_match))-((char*)s))); -} -*/ - -#define dsWSize 68 -#define dsWMask 76 -#define dsWindow 80 -#define dsPrev 96 -#define dsMatchLen 144 -#define dsPrevMatch 148 -#define dsStrStart 156 -#define dsMatchStart 160 -#define dsLookahead 164 -#define dsPrevLen 168 -#define dsMaxChainLen 172 -#define dsGoodMatch 188 -#define dsNiceMatch 192 - -#define window_size [ rcx + dsWSize] -#define WMask [ rcx + dsWMask] -#define window_ad [ rcx + dsWindow] -#define prev_ad [ rcx + dsPrev] -#define strstart [ rcx + dsStrStart] -#define match_start [ rcx + dsMatchStart] -#define Lookahead [ rcx + dsLookahead] //; 0ffffffffh on infozip -#define prev_length [ rcx + dsPrevLen] -#define max_chain_length [ rcx + dsMaxChainLen] -#define good_match [ rcx + dsGoodMatch] -#define nice_match [ rcx + dsNiceMatch] - -/* -; windows: -; parameter 1 in rcx(deflate state s), param 2 in rdx (cur match) - -; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and -; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp -; -; All registers must be preserved across the call, except for -; rax, rcx, rdx, r8, r9, r10, and r11, which are scratch. - -; -; gcc on macosx-linux: -; see http://www.x86-64.org/documentation/abi-0.99.pdf -; param 1 in rdi, param 2 in rsi -; rbx, rsp, rbp, r12 to r15 must be preserved - -;;; Save registers that the compiler may be using, and adjust esp to -;;; make room for our stack frame. - - -;;; Retrieve the function arguments. r8d will hold cur_match -;;; throughout the entire function. edx will hold the pointer to the -;;; deflate_state structure during the function's setup (before -;;; entering the main loop. - -; ms: parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match) -; mac: param 1 in rdi, param 2 rsi -; this clear high 32 bits of r8, which can be garbage in both r8 and rdx -*/ - mov [save_rbx],rbx - mov [save_rbp],rbp - - - mov rcx,rdi - - mov r8d,esi - - - mov [save_r12],r12 - mov [save_r13],r13 - mov [save_r14],r14 - mov [save_r15],r15 - - -//;;; uInt wmask = s->w_mask; -//;;; unsigned chain_length = s->max_chain_length; -//;;; if (s->prev_length >= s->good_match) { -//;;; chain_length >>= 2; -//;;; } - - - mov edi, prev_length - mov esi, good_match - mov eax, WMask - mov ebx, max_chain_length - cmp edi, esi - jl LastMatchGood - shr ebx, 2 -LastMatchGood: - -//;;; chainlen is decremented once beforehand so that the function can -//;;; use the sign flag instead of the zero flag for the exit test. -//;;; It is then shifted into the high word, to make room for the wmask -//;;; value, which it will always accompany. - - dec ebx - shl ebx, 16 - or ebx, eax - -//;;; on zlib only -//;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - - - - mov eax, nice_match - mov [chainlenwmask], ebx - mov r10d, Lookahead - cmp r10d, eax - cmovnl r10d, eax - mov [nicematch],r10d - - - -//;;; register Bytef *scan = s->window + s->strstart; - mov r10, window_ad - mov ebp, strstart - lea r13, [r10 + rbp] - -//;;; Determine how many bytes the scan ptr is off from being -//;;; dword-aligned. - - mov r9,r13 - neg r13 - and r13,3 - -//;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? -//;;; s->strstart - (IPos)MAX_DIST(s) : NIL; - - - mov eax, window_size - sub eax, MIN_LOOKAHEAD - - - xor edi,edi - sub ebp, eax - - mov r11d, prev_length - - cmovng ebp,edi - -//;;; int best_len = s->prev_length; - - -//;;; Store the sum of s->window + best_len in esi locally, and in esi. - - lea rsi,[r10+r11] - -//;;; register ush scan_start = *(ushf*)scan; -//;;; register ush scan_end = *(ushf*)(scan+best_len-1); -//;;; Posf *prev = s->prev; - - movzx r12d,word ptr [r9] - movzx ebx, word ptr [r9 + r11 - 1] - - mov rdi, prev_ad - -//;;; Jump into the main loop. - - mov edx, [chainlenwmask] - - cmp bx,word ptr [rsi + r8 - 1] - jz LookupLoopIsZero - - - -LookupLoop1: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - jbe LeaveNow - - - - sub edx, 0x00010000 - BEFORE_JMP - js LeaveNow - AFTER_JMP - -LoopEntry1: - cmp bx,word ptr [rsi + r8 - 1] - BEFORE_JMP - jz LookupLoopIsZero - AFTER_JMP - -LookupLoop2: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - BEFORE_JMP - jbe LeaveNow - AFTER_JMP - sub edx, 0x00010000 - BEFORE_JMP - js LeaveNow - AFTER_JMP - -LoopEntry2: - cmp bx,word ptr [rsi + r8 - 1] - BEFORE_JMP - jz LookupLoopIsZero - AFTER_JMP - -LookupLoop4: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - BEFORE_JMP - jbe LeaveNow - AFTER_JMP - sub edx, 0x00010000 - BEFORE_JMP - js LeaveNow - AFTER_JMP - -LoopEntry4: - - cmp bx,word ptr [rsi + r8 - 1] - BEFORE_JMP - jnz LookupLoop1 - jmp LookupLoopIsZero - AFTER_JMP -/* -;;; do { -;;; match = s->window + cur_match; -;;; if (*(ushf*)(match+best_len-1) != scan_end || -;;; *(ushf*)match != scan_start) continue; -;;; [...] -;;; } while ((cur_match = prev[cur_match & wmask]) > limit -;;; && --chain_length != 0); -;;; -;;; Here is the inner loop of the function. The function will spend the -;;; majority of its time in this loop, and majority of that time will -;;; be spent in the first ten instructions. -;;; -;;; Within this loop: -;;; ebx = scanend -;;; r8d = curmatch -;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) -;;; esi = windowbestlen - i.e., (window + bestlen) -;;; edi = prev -;;; ebp = limit -*/ -.balign 16 -LookupLoop: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - BEFORE_JMP - jbe LeaveNow - AFTER_JMP - sub edx, 0x00010000 - BEFORE_JMP - js LeaveNow - AFTER_JMP - -LoopEntry: - - cmp bx,word ptr [rsi + r8 - 1] - BEFORE_JMP - jnz LookupLoop1 - AFTER_JMP -LookupLoopIsZero: - cmp r12w, word ptr [r10 + r8] - BEFORE_JMP - jnz LookupLoop1 - AFTER_JMP - - -//;;; Store the current value of chainlen. - mov [chainlenwmask], edx -/* -;;; Point edi to the string under scrutiny, and esi to the string we -;;; are hoping to match it up with. In actuality, esi and edi are -;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is -;;; initialized to -(MAX_MATCH_8 - scanalign). -*/ - lea rsi,[r8+r10] - mov rdx, 0xfffffffffffffef8 //; -(MAX_MATCH_8) - lea rsi, [rsi + r13 + 0x0108] //;MAX_MATCH_8] - lea rdi, [r9 + r13 + 0x0108] //;MAX_MATCH_8] - - prefetcht1 [rsi+rdx] - prefetcht1 [rdi+rdx] - -/* -;;; Test the strings for equality, 8 bytes at a time. At the end, -;;; adjust rdx so that it is offset to the exact byte that mismatched. -;;; -;;; We already know at this point that the first three bytes of the -;;; strings match each other, and they can be safely passed over before -;;; starting the compare loop. So what this code does is skip over 0-3 -;;; bytes, as much as necessary in order to dword-align the edi -;;; pointer. (rsi will still be misaligned three times out of four.) -;;; -;;; It should be confessed that this loop usually does not represent -;;; much of the total running time. Replacing it with a more -;;; straightforward "rep cmpsb" would not drastically degrade -;;; performance. -*/ - -LoopCmps: - mov rax, [rsi + rdx] - xor rax, [rdi + rdx] - jnz LeaveLoopCmps - - mov rax, [rsi + rdx + 8] - xor rax, [rdi + rdx + 8] - jnz LeaveLoopCmps8 - - - mov rax, [rsi + rdx + 8+8] - xor rax, [rdi + rdx + 8+8] - jnz LeaveLoopCmps16 - - add rdx,8+8+8 - - BEFORE_JMP - jnz LoopCmps - jmp LenMaximum - AFTER_JMP - -LeaveLoopCmps16: add rdx,8 -LeaveLoopCmps8: add rdx,8 -LeaveLoopCmps: - - test eax, 0x0000FFFF - jnz LenLower - - test eax,0xffffffff - - jnz LenLower32 - - add rdx,4 - shr rax,32 - or ax,ax - BEFORE_JMP - jnz LenLower - AFTER_JMP - -LenLower32: - shr eax,16 - add rdx,2 - -LenLower: - sub al, 1 - adc rdx, 0 -//;;; Calculate the length of the match. If it is longer than MAX_MATCH, -//;;; then automatically accept it as the best possible match and leave. - - lea rax, [rdi + rdx] - sub rax, r9 - cmp eax, MAX_MATCH - BEFORE_JMP - jge LenMaximum - AFTER_JMP -/* -;;; If the length of the match is not longer than the best match we -;;; have so far, then forget it and return to the lookup loop. -;/////////////////////////////////// -*/ - cmp eax, r11d - jg LongerMatch - - lea rsi,[r10+r11] - - mov rdi, prev_ad - mov edx, [chainlenwmask] - BEFORE_JMP - jmp LookupLoop - AFTER_JMP -/* -;;; s->match_start = cur_match; -;;; best_len = len; -;;; if (len >= nice_match) break; -;;; scan_end = *(ushf*)(scan+best_len-1); -*/ -LongerMatch: - mov r11d, eax - mov match_start, r8d - cmp eax, [nicematch] - BEFORE_JMP - jge LeaveNow - AFTER_JMP - - lea rsi,[r10+rax] - - movzx ebx, word ptr [r9 + rax - 1] - mov rdi, prev_ad - mov edx, [chainlenwmask] - BEFORE_JMP - jmp LookupLoop - AFTER_JMP - -//;;; Accept the current string, with the maximum possible length. - -LenMaximum: - mov r11d,MAX_MATCH - mov match_start, r8d - -//;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; -//;;; return s->lookahead; - -LeaveNow: - mov eax, Lookahead - cmp r11d, eax - cmovng eax, r11d - - - -//;;; Restore the stack and return from whence we came. - - -// mov rsi,[save_rsi] -// mov rdi,[save_rdi] - mov rbx,[save_rbx] - mov rbp,[save_rbp] - mov r12,[save_r12] - mov r13,[save_r13] - mov r14,[save_r14] - mov r15,[save_r15] - - - ret 0 -//; please don't remove this string ! -//; Your can freely use gvmat64 in any free or commercial app -//; but it is far better don't remove the string in the binary! - // db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0 - - -match_init: - ret 0 - - diff --git a/deps/zlib/contrib/infback9/README b/deps/zlib/contrib/infback9/README deleted file mode 100644 index e75ed132948f3b..00000000000000 --- a/deps/zlib/contrib/infback9/README +++ /dev/null @@ -1 +0,0 @@ -See infback9.h for what this is and how to use it. diff --git a/deps/zlib/contrib/infback9/infback9.c b/deps/zlib/contrib/infback9/infback9.c deleted file mode 100644 index 05fb3e338070d6..00000000000000 --- a/deps/zlib/contrib/infback9/infback9.c +++ /dev/null @@ -1,615 +0,0 @@ -/* infback9.c -- inflate deflate64 data using a call-back interface - * Copyright (C) 1995-2008 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "infback9.h" -#include "inftree9.h" -#include "inflate9.h" - -#define WSIZE 65536UL - -/* - strm provides memory allocation functions in zalloc and zfree, or - Z_NULL to use the library memory allocation functions. - - window is a user-supplied window and output buffer that is 64K bytes. - */ -int ZEXPORT inflateBack9Init_(strm, window, version, stream_size) -z_stream FAR *strm; -unsigned char FAR *window; -const char *version; -int stream_size; -{ - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL || window == Z_NULL) - return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; - } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; - state = (struct inflate_state FAR *)ZALLOC(strm, 1, - sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (voidpf)state; - state->window = window; - return Z_OK; -} - -/* - Build and output length and distance decoding tables for fixed code - decoding. - */ -#ifdef MAKEFIXED -#include - -void makefixed9(void) -{ - unsigned sym, bits, low, size; - code *next, *lenfix, *distfix; - struct inflate_state state; - code fixed[544]; - - /* literal/length table */ - sym = 0; - while (sym < 144) state.lens[sym++] = 8; - while (sym < 256) state.lens[sym++] = 9; - while (sym < 280) state.lens[sym++] = 7; - while (sym < 288) state.lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table9(LENS, state.lens, 288, &(next), &(bits), state.work); - - /* distance table */ - sym = 0; - while (sym < 32) state.lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table9(DISTS, state.lens, 32, &(next), &(bits), state.work); - - /* write tables */ - puts(" /* inffix9.h -- table for decoding deflate64 fixed codes"); - puts(" * Generated automatically by makefixed9()."); - puts(" */"); - puts(""); - puts(" /* WARNING: this file should *not* be used by applications."); - puts(" It is part of the implementation of this library and is"); - puts(" subject to change. Applications should only use zlib.h."); - puts(" */"); - puts(""); - size = 1U << 9; - printf(" static const code lenfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 6) == 0) printf("\n "); - printf("{%u,%u,%d}", lenfix[low].op, lenfix[low].bits, - lenfix[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); - size = 1U << 5; - printf("\n static const code distfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 5) == 0) printf("\n "); - printf("{%u,%u,%d}", distfix[low].op, distfix[low].bits, - distfix[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); -} -#endif /* MAKEFIXED */ - -/* Macros for inflateBack(): */ - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Assure that some input is available. If input is requested, but denied, - then return a Z_BUF_ERROR from inflateBack(). */ -#define PULL() \ - do { \ - if (have == 0) { \ - have = in(in_desc, &next); \ - if (have == 0) { \ - next = Z_NULL; \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflateBack() - with an error if there is no input available. */ -#define PULLBYTE() \ - do { \ - PULL(); \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflateBack() with - an error. */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n <= 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* Assure that some output space is available, by writing out the window - if it's full. If the write fails, return from inflateBack() with a - Z_BUF_ERROR. */ -#define ROOM() \ - do { \ - if (left == 0) { \ - put = window; \ - left = WSIZE; \ - wrap = 1; \ - if (out(out_desc, put, (unsigned)left)) { \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* - strm provides the memory allocation functions and window buffer on input, - and provides information on the unused input on return. For Z_DATA_ERROR - returns, strm will also provide an error message. - - in() and out() are the call-back input and output functions. When - inflateBack() needs more input, it calls in(). When inflateBack() has - filled the window with output, or when it completes with data in the - window, it calls out() to write out the data. The application must not - change the provided input until in() is called again or inflateBack() - returns. The application must not change the window/output buffer until - inflateBack() returns. - - in() and out() are called with a descriptor parameter provided in the - inflateBack() call. This parameter can be a structure that provides the - information required to do the read or write, as well as accumulated - information on the input and output such as totals and check values. - - in() should return zero on failure. out() should return non-zero on - failure. If either in() or out() fails, than inflateBack() returns a - Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it - was in() or out() that caused in the error. Otherwise, inflateBack() - returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format - error, or Z_MEM_ERROR if it could not allocate memory for the state. - inflateBack() can also return Z_STREAM_ERROR if the input parameters - are not correct, i.e. strm is Z_NULL or the state was not initialized. - */ -int ZEXPORT inflateBack9(strm, in, in_desc, out, out_desc) -z_stream FAR *strm; -in_func in; -void FAR *in_desc; -out_func out; -void FAR *out_desc; -{ - struct inflate_state FAR *state; - z_const unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have; /* available input */ - unsigned long left; /* available output */ - inflate_mode mode; /* current inflate mode */ - int lastblock; /* true if processing last block */ - int wrap; /* true if the window has wrapped */ - unsigned char FAR *window; /* allocated sliding window, if needed */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned extra; /* extra bits needed */ - unsigned long length; /* literal or length of data to copy */ - unsigned long offset; /* distance back to copy string from */ - unsigned long copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code const FAR *lencode; /* starting table for length/literal codes */ - code const FAR *distcode; /* starting table for distance codes */ - unsigned lenbits; /* index bits for lencode */ - unsigned distbits; /* index bits for distcode */ - code here; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; -#include "inffix9.h" - - /* Check that the strm exists and that the state was initialized */ - if (strm == Z_NULL || strm->state == Z_NULL) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* Reset the state */ - strm->msg = Z_NULL; - mode = TYPE; - lastblock = 0; - wrap = 0; - window = state->window; - next = strm->next_in; - have = next != Z_NULL ? strm->avail_in : 0; - hold = 0; - bits = 0; - put = window; - left = WSIZE; - lencode = Z_NULL; - distcode = Z_NULL; - - /* Inflate until end of block marked as last */ - for (;;) - switch (mode) { - case TYPE: - /* determine and dispatch block type */ - if (lastblock) { - BYTEBITS(); - mode = DONE; - break; - } - NEEDBITS(3); - lastblock = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - lastblock ? " (last)" : "")); - mode = STORED; - break; - case 1: /* fixed block */ - lencode = lenfix; - lenbits = 9; - distcode = distfix; - distbits = 5; - Tracev((stderr, "inflate: fixed codes block%s\n", - lastblock ? " (last)" : "")); - mode = LEN; /* decode codes */ - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - lastblock ? " (last)" : "")); - mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - mode = BAD; - } - DROPBITS(2); - break; - - case STORED: - /* get and verify stored block length */ - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - mode = BAD; - break; - } - length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %lu\n", - length)); - INITBITS(); - - /* copy stored block from input to output */ - while (length != 0) { - copy = length; - PULL(); - ROOM(); - if (copy > have) copy = have; - if (copy > left) copy = left; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - length -= copy; - } - Tracev((stderr, "inflate: stored end\n")); - mode = TYPE; - break; - - case TABLE: - /* get dynamic table entries descriptor */ - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); - if (state->nlen > 286) { - strm->msg = (char *)"too many length symbols"; - mode = BAD; - break; - } - Tracev((stderr, "inflate: table sizes ok\n")); - - /* get code length code lengths (not a typo) */ - state->have = 0; - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - lencode = (code const FAR *)(state->next); - lenbits = 7; - ret = inflate_table9(CODES, state->lens, 19, &(state->next), - &(lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - - /* get length and distance code code lengths */ - state->have = 0; - while (state->have < state->nlen + state->ndist) { - for (;;) { - here = lencode[BITS(lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.val < 16) { - NEEDBITS(here.bits); - DROPBITS(here.bits); - state->lens[state->have++] = here.val; - } - else { - if (here.val == 16) { - NEEDBITS(here.bits + 2); - DROPBITS(here.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - mode = BAD; - break; - } - len = (unsigned)(state->lens[state->have - 1]); - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (here.val == 17) { - NEEDBITS(here.bits + 3); - DROPBITS(here.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(here.bits + 7); - DROPBITS(here.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (mode == BAD) break; - - /* check for end-of-block code (better have one) */ - if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; - mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftree9.h - concerning the ENOUGH constants, which depend on those values */ - state->next = state->codes; - lencode = (code const FAR *)(state->next); - lenbits = 9; - ret = inflate_table9(LENS, state->lens, state->nlen, - &(state->next), &(lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - mode = BAD; - break; - } - distcode = (code const FAR *)(state->next); - distbits = 6; - ret = inflate_table9(DISTS, state->lens + state->nlen, - state->ndist, &(state->next), &(distbits), - state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - mode = LEN; - - case LEN: - /* get a literal, length, or end-of-block code */ - for (;;) { - here = lencode[BITS(lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.op && (here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - length = (unsigned)here.val; - - /* process literal */ - if (here.op == 0) { - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - ROOM(); - *put++ = (unsigned char)(length); - left--; - mode = LEN; - break; - } - - /* process end of block */ - if (here.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - mode = TYPE; - break; - } - - /* invalid code */ - if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - mode = BAD; - break; - } - - /* length code -- get extra bits, if any */ - extra = (unsigned)(here.op) & 31; - if (extra != 0) { - NEEDBITS(extra); - length += BITS(extra); - DROPBITS(extra); - } - Tracevv((stderr, "inflate: length %lu\n", length)); - - /* get distance code */ - for (;;) { - here = distcode[BITS(distbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if ((here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; - mode = BAD; - break; - } - offset = (unsigned)here.val; - - /* get distance extra bits, if any */ - extra = (unsigned)(here.op) & 15; - if (extra != 0) { - NEEDBITS(extra); - offset += BITS(extra); - DROPBITS(extra); - } - if (offset > WSIZE - (wrap ? 0: left)) { - strm->msg = (char *)"invalid distance too far back"; - mode = BAD; - break; - } - Tracevv((stderr, "inflate: distance %lu\n", offset)); - - /* copy match from window to output */ - do { - ROOM(); - copy = WSIZE - offset; - if (copy < left) { - from = put + copy; - copy = left - copy; - } - else { - from = put - offset; - copy = left; - } - if (copy > length) copy = length; - length -= copy; - left -= copy; - do { - *put++ = *from++; - } while (--copy); - } while (length != 0); - break; - - case DONE: - /* inflate stream terminated properly -- write leftover output */ - ret = Z_STREAM_END; - if (left < WSIZE) { - if (out(out_desc, window, (unsigned)(WSIZE - left))) - ret = Z_BUF_ERROR; - } - goto inf_leave; - - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - - default: /* can't happen, but makes compilers happy */ - ret = Z_STREAM_ERROR; - goto inf_leave; - } - - /* Return unused input */ - inf_leave: - strm->next_in = next; - strm->avail_in = have; - return ret; -} - -int ZEXPORT inflateBack9End(strm) -z_stream FAR *strm; -{ - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) - return Z_STREAM_ERROR; - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} diff --git a/deps/zlib/contrib/infback9/infback9.h b/deps/zlib/contrib/infback9/infback9.h deleted file mode 100644 index 1073c0a38e6c2c..00000000000000 --- a/deps/zlib/contrib/infback9/infback9.h +++ /dev/null @@ -1,37 +0,0 @@ -/* infback9.h -- header for using inflateBack9 functions - * Copyright (C) 2003 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * This header file and associated patches provide a decoder for PKWare's - * undocumented deflate64 compression method (method 9). Use with infback9.c, - * inftree9.h, inftree9.c, and inffix9.h. These patches are not supported. - * This should be compiled with zlib, since it uses zutil.h and zutil.o. - * This code has not yet been tested on 16-bit architectures. See the - * comments in zlib.h for inflateBack() usage. These functions are used - * identically, except that there is no windowBits parameter, and a 64K - * window must be provided. Also if int's are 16 bits, then a zero for - * the third parameter of the "out" function actually means 65536UL. - * zlib.h must be included before this header file. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -ZEXTERN int ZEXPORT inflateBack9End OF((z_stream FAR *strm)); -ZEXTERN int ZEXPORT inflateBack9Init_ OF((z_stream FAR *strm, - unsigned char FAR *window, - const char *version, - int stream_size)); -#define inflateBack9Init(strm, window) \ - inflateBack9Init_((strm), (window), \ - ZLIB_VERSION, sizeof(z_stream)) - -#ifdef __cplusplus -} -#endif diff --git a/deps/zlib/contrib/infback9/inffix9.h b/deps/zlib/contrib/infback9/inffix9.h deleted file mode 100644 index ee5671d2df63f4..00000000000000 --- a/deps/zlib/contrib/infback9/inffix9.h +++ /dev/null @@ -1,107 +0,0 @@ - /* inffix9.h -- table for decoding deflate64 fixed codes - * Generated automatically by makefixed9(). - */ - - /* WARNING: this file should *not* be used by applications. - It is part of the implementation of this library and is - subject to change. Applications should only use zlib.h. - */ - - static const code lenfix[512] = { - {96,7,0},{0,8,80},{0,8,16},{132,8,115},{130,7,31},{0,8,112}, - {0,8,48},{0,9,192},{128,7,10},{0,8,96},{0,8,32},{0,9,160}, - {0,8,0},{0,8,128},{0,8,64},{0,9,224},{128,7,6},{0,8,88}, - {0,8,24},{0,9,144},{131,7,59},{0,8,120},{0,8,56},{0,9,208}, - {129,7,17},{0,8,104},{0,8,40},{0,9,176},{0,8,8},{0,8,136}, - {0,8,72},{0,9,240},{128,7,4},{0,8,84},{0,8,20},{133,8,227}, - {131,7,43},{0,8,116},{0,8,52},{0,9,200},{129,7,13},{0,8,100}, - {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232}, - {128,7,8},{0,8,92},{0,8,28},{0,9,152},{132,7,83},{0,8,124}, - {0,8,60},{0,9,216},{130,7,23},{0,8,108},{0,8,44},{0,9,184}, - {0,8,12},{0,8,140},{0,8,76},{0,9,248},{128,7,3},{0,8,82}, - {0,8,18},{133,8,163},{131,7,35},{0,8,114},{0,8,50},{0,9,196}, - {129,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},{0,8,130}, - {0,8,66},{0,9,228},{128,7,7},{0,8,90},{0,8,26},{0,9,148}, - {132,7,67},{0,8,122},{0,8,58},{0,9,212},{130,7,19},{0,8,106}, - {0,8,42},{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244}, - {128,7,5},{0,8,86},{0,8,22},{65,8,0},{131,7,51},{0,8,118}, - {0,8,54},{0,9,204},{129,7,15},{0,8,102},{0,8,38},{0,9,172}, - {0,8,6},{0,8,134},{0,8,70},{0,9,236},{128,7,9},{0,8,94}, - {0,8,30},{0,9,156},{132,7,99},{0,8,126},{0,8,62},{0,9,220}, - {130,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, - {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{133,8,131}, - {130,7,31},{0,8,113},{0,8,49},{0,9,194},{128,7,10},{0,8,97}, - {0,8,33},{0,9,162},{0,8,1},{0,8,129},{0,8,65},{0,9,226}, - {128,7,6},{0,8,89},{0,8,25},{0,9,146},{131,7,59},{0,8,121}, - {0,8,57},{0,9,210},{129,7,17},{0,8,105},{0,8,41},{0,9,178}, - {0,8,9},{0,8,137},{0,8,73},{0,9,242},{128,7,4},{0,8,85}, - {0,8,21},{144,8,3},{131,7,43},{0,8,117},{0,8,53},{0,9,202}, - {129,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133}, - {0,8,69},{0,9,234},{128,7,8},{0,8,93},{0,8,29},{0,9,154}, - {132,7,83},{0,8,125},{0,8,61},{0,9,218},{130,7,23},{0,8,109}, - {0,8,45},{0,9,186},{0,8,13},{0,8,141},{0,8,77},{0,9,250}, - {128,7,3},{0,8,83},{0,8,19},{133,8,195},{131,7,35},{0,8,115}, - {0,8,51},{0,9,198},{129,7,11},{0,8,99},{0,8,35},{0,9,166}, - {0,8,3},{0,8,131},{0,8,67},{0,9,230},{128,7,7},{0,8,91}, - {0,8,27},{0,9,150},{132,7,67},{0,8,123},{0,8,59},{0,9,214}, - {130,7,19},{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139}, - {0,8,75},{0,9,246},{128,7,5},{0,8,87},{0,8,23},{77,8,0}, - {131,7,51},{0,8,119},{0,8,55},{0,9,206},{129,7,15},{0,8,103}, - {0,8,39},{0,9,174},{0,8,7},{0,8,135},{0,8,71},{0,9,238}, - {128,7,9},{0,8,95},{0,8,31},{0,9,158},{132,7,99},{0,8,127}, - {0,8,63},{0,9,222},{130,7,27},{0,8,111},{0,8,47},{0,9,190}, - {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80}, - {0,8,16},{132,8,115},{130,7,31},{0,8,112},{0,8,48},{0,9,193}, - {128,7,10},{0,8,96},{0,8,32},{0,9,161},{0,8,0},{0,8,128}, - {0,8,64},{0,9,225},{128,7,6},{0,8,88},{0,8,24},{0,9,145}, - {131,7,59},{0,8,120},{0,8,56},{0,9,209},{129,7,17},{0,8,104}, - {0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},{0,9,241}, - {128,7,4},{0,8,84},{0,8,20},{133,8,227},{131,7,43},{0,8,116}, - {0,8,52},{0,9,201},{129,7,13},{0,8,100},{0,8,36},{0,9,169}, - {0,8,4},{0,8,132},{0,8,68},{0,9,233},{128,7,8},{0,8,92}, - {0,8,28},{0,9,153},{132,7,83},{0,8,124},{0,8,60},{0,9,217}, - {130,7,23},{0,8,108},{0,8,44},{0,9,185},{0,8,12},{0,8,140}, - {0,8,76},{0,9,249},{128,7,3},{0,8,82},{0,8,18},{133,8,163}, - {131,7,35},{0,8,114},{0,8,50},{0,9,197},{129,7,11},{0,8,98}, - {0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, - {128,7,7},{0,8,90},{0,8,26},{0,9,149},{132,7,67},{0,8,122}, - {0,8,58},{0,9,213},{130,7,19},{0,8,106},{0,8,42},{0,9,181}, - {0,8,10},{0,8,138},{0,8,74},{0,9,245},{128,7,5},{0,8,86}, - {0,8,22},{65,8,0},{131,7,51},{0,8,118},{0,8,54},{0,9,205}, - {129,7,15},{0,8,102},{0,8,38},{0,9,173},{0,8,6},{0,8,134}, - {0,8,70},{0,9,237},{128,7,9},{0,8,94},{0,8,30},{0,9,157}, - {132,7,99},{0,8,126},{0,8,62},{0,9,221},{130,7,27},{0,8,110}, - {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253}, - {96,7,0},{0,8,81},{0,8,17},{133,8,131},{130,7,31},{0,8,113}, - {0,8,49},{0,9,195},{128,7,10},{0,8,97},{0,8,33},{0,9,163}, - {0,8,1},{0,8,129},{0,8,65},{0,9,227},{128,7,6},{0,8,89}, - {0,8,25},{0,9,147},{131,7,59},{0,8,121},{0,8,57},{0,9,211}, - {129,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},{0,8,137}, - {0,8,73},{0,9,243},{128,7,4},{0,8,85},{0,8,21},{144,8,3}, - {131,7,43},{0,8,117},{0,8,53},{0,9,203},{129,7,13},{0,8,101}, - {0,8,37},{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235}, - {128,7,8},{0,8,93},{0,8,29},{0,9,155},{132,7,83},{0,8,125}, - {0,8,61},{0,9,219},{130,7,23},{0,8,109},{0,8,45},{0,9,187}, - {0,8,13},{0,8,141},{0,8,77},{0,9,251},{128,7,3},{0,8,83}, - {0,8,19},{133,8,195},{131,7,35},{0,8,115},{0,8,51},{0,9,199}, - {129,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, - {0,8,67},{0,9,231},{128,7,7},{0,8,91},{0,8,27},{0,9,151}, - {132,7,67},{0,8,123},{0,8,59},{0,9,215},{130,7,19},{0,8,107}, - {0,8,43},{0,9,183},{0,8,11},{0,8,139},{0,8,75},{0,9,247}, - {128,7,5},{0,8,87},{0,8,23},{77,8,0},{131,7,51},{0,8,119}, - {0,8,55},{0,9,207},{129,7,15},{0,8,103},{0,8,39},{0,9,175}, - {0,8,7},{0,8,135},{0,8,71},{0,9,239},{128,7,9},{0,8,95}, - {0,8,31},{0,9,159},{132,7,99},{0,8,127},{0,8,63},{0,9,223}, - {130,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143}, - {0,8,79},{0,9,255} - }; - - static const code distfix[32] = { - {128,5,1},{135,5,257},{131,5,17},{139,5,4097},{129,5,5}, - {137,5,1025},{133,5,65},{141,5,16385},{128,5,3},{136,5,513}, - {132,5,33},{140,5,8193},{130,5,9},{138,5,2049},{134,5,129}, - {142,5,32769},{128,5,2},{135,5,385},{131,5,25},{139,5,6145}, - {129,5,7},{137,5,1537},{133,5,97},{141,5,24577},{128,5,4}, - {136,5,769},{132,5,49},{140,5,12289},{130,5,13},{138,5,3073}, - {134,5,193},{142,5,49153} - }; diff --git a/deps/zlib/contrib/infback9/inflate9.h b/deps/zlib/contrib/infback9/inflate9.h deleted file mode 100644 index ee9a79394b6dc9..00000000000000 --- a/deps/zlib/contrib/infback9/inflate9.h +++ /dev/null @@ -1,47 +0,0 @@ -/* inflate9.h -- internal inflate state definition - * Copyright (C) 1995-2003 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Possible inflate modes between inflate() calls */ -typedef enum { - TYPE, /* i: waiting for type bits, including last-flag bit */ - STORED, /* i: waiting for stored size (length and complement) */ - TABLE, /* i: waiting for dynamic block table lengths */ - LEN, /* i: waiting for length/lit code */ - DONE, /* finished check, done -- remain here until reset */ - BAD /* got a data error -- remain here until reset */ -} inflate_mode; - -/* - State transitions between above modes - - - (most modes can go to the BAD mode -- not shown for clarity) - - Read deflate blocks: - TYPE -> STORED or TABLE or LEN or DONE - STORED -> TYPE - TABLE -> LENLENS -> CODELENS -> LEN - Read deflate codes: - LEN -> LEN or TYPE - */ - -/* state maintained between inflate() calls. Approximately 7K bytes. */ -struct inflate_state { - /* sliding window */ - unsigned char FAR *window; /* allocated sliding window, if needed */ - /* dynamic table building */ - unsigned ncode; /* number of code length code lengths */ - unsigned nlen; /* number of length code lengths */ - unsigned ndist; /* number of distance code lengths */ - unsigned have; /* number of code lengths in lens[] */ - code FAR *next; /* next available space in codes[] */ - unsigned short lens[320]; /* temporary storage for code lengths */ - unsigned short work[288]; /* work area for code table building */ - code codes[ENOUGH]; /* space for code tables */ -}; diff --git a/deps/zlib/contrib/infback9/inftree9.c b/deps/zlib/contrib/infback9/inftree9.c deleted file mode 100644 index 5f4a76798d8847..00000000000000 --- a/deps/zlib/contrib/infback9/inftree9.c +++ /dev/null @@ -1,324 +0,0 @@ -/* inftree9.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2017 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftree9.h" - -#define MAXBITS 15 - -const char inflate9_copyright[] = - " inflate9 1.2.11 Copyright 1995-2017 Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* - Build a set of tables to decode the provided canonical Huffman code. - The code lengths are lens[0..codes-1]. The result starts at *table, - whose indices are 0..2^bits-1. work is a writable array of at least - lens shorts, which is used as a work area. type is the type of code - to be generated, CODES, LENS, or DISTS. On return, zero is success, - -1 is an invalid code, and +1 means that ENOUGH isn't enough. table - on return points to the next available entry's address. bits is the - requested root table index bits, and on return it is the actual root - table index bits. It will differ if the request is greater than the - longest code or if it is less than the shortest code. - */ -int inflate_table9(type, lens, codes, table, bits, work) -codetype type; -unsigned short FAR *lens; -unsigned codes; -code FAR * FAR *table; -unsigned FAR *bits; -unsigned short FAR *work; -{ - unsigned len; /* a code's length in bits */ - unsigned sym; /* index of code symbols */ - unsigned min, max; /* minimum and maximum code lengths */ - unsigned root; /* number of index bits for root table */ - unsigned curr; /* number of index bits for current table */ - unsigned drop; /* code bits to drop for sub-table */ - int left; /* number of prefix codes available */ - unsigned used; /* code entries in table used */ - unsigned huff; /* Huffman code */ - unsigned incr; /* for incrementing code, index */ - unsigned fill; /* index for replicating entries */ - unsigned low; /* low bits for current root entry */ - unsigned mask; /* mask for low root bits */ - code this; /* table entry for duplication */ - code FAR *next; /* next available space in table */ - const unsigned short FAR *base; /* base value table to use */ - const unsigned short FAR *extra; /* extra bits table to use */ - int end; /* use base and extra for symbol > end */ - unsigned short count[MAXBITS+1]; /* number of codes of each length */ - unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ - static const unsigned short lbase[31] = { /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, - 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, - 131, 163, 195, 227, 3, 0, 0}; - static const unsigned short lext[31] = { /* Length codes 257..285 extra */ - 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129, - 130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132, - 133, 133, 133, 133, 144, 77, 202}; - static const unsigned short dbase[32] = { /* Distance codes 0..31 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, - 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, - 4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153}; - static const unsigned short dext[32] = { /* Distance codes 0..31 extra */ - 128, 128, 128, 128, 129, 129, 130, 130, 131, 131, 132, 132, - 133, 133, 134, 134, 135, 135, 136, 136, 137, 137, 138, 138, - 139, 139, 140, 140, 141, 141, 142, 142}; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) - count[len] = 0; - for (sym = 0; sym < codes; sym++) - count[lens[sym]]++; - - /* bound code lengths, force root to be within code lengths */ - root = *bits; - for (max = MAXBITS; max >= 1; max--) - if (count[max] != 0) break; - if (root > max) root = max; - if (max == 0) return -1; /* no codes! */ - for (min = 1; min <= MAXBITS; min++) - if (count[min] != 0) break; - if (root < min) root = min; - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) return -1; /* over-subscribed */ - } - if (left > 0 && (type == CODES || max != 1)) - return -1; /* incomplete set */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + count[len]; - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) - if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftree9.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - switch (type) { - case CODES: - base = extra = work; /* dummy value--not used */ - end = 19; - break; - case LENS: - base = lbase; - base -= 257; - extra = lext; - extra -= 257; - end = 256; - break; - default: /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize state for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = *table; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = (unsigned)(-1); /* trigger new sub-table when len > root */ - used = 1U << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) - return 1; - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - this.bits = (unsigned char)(len - drop); - if ((int)(work[sym]) < end) { - this.op = (unsigned char)0; - this.val = work[sym]; - } - else if ((int)(work[sym]) > end) { - this.op = (unsigned char)(extra[work[sym]]); - this.val = base[work[sym]]; - } - else { - this.op = (unsigned char)(32 + 64); /* end of block */ - this.val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1U << (len - drop); - fill = 1U << curr; - do { - fill -= incr; - next[(huff >> drop) + fill] = this; - } while (fill != 0); - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - - /* go to next symbol, update count, len */ - sym++; - if (--(count[len]) == 0) { - if (len == max) break; - len = lens[work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) != low) { - /* if first time, transition to sub-tables */ - if (drop == 0) - drop = root; - - /* increment past last table */ - next += 1U << curr; - - /* determine length of next table */ - curr = len - drop; - left = (int)(1 << curr); - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) break; - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1U << curr; - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) - return 1; - - /* point entry in root table to sub-table */ - low = huff & mask; - (*table)[low].op = (unsigned char)curr; - (*table)[low].bits = (unsigned char)root; - (*table)[low].val = (unsigned short)(next - *table); - } - } - - /* - Fill in rest of table for incomplete codes. This loop is similar to the - loop above in incrementing huff for table indices. It is assumed that - len is equal to curr + drop, so there is no loop needed to increment - through high index bits. When the current sub-table is filled, the loop - drops back to the root table to fill in any remaining entries there. - */ - this.op = (unsigned char)64; /* invalid code marker */ - this.bits = (unsigned char)(len - drop); - this.val = (unsigned short)0; - while (huff != 0) { - /* when done with sub-table, drop back to root table */ - if (drop != 0 && (huff & mask) != low) { - drop = 0; - len = root; - next = *table; - curr = root; - this.bits = (unsigned char)len; - } - - /* put invalid code marker in table */ - next[huff >> drop] = this; - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - } - - /* set return parameters */ - *table += used; - *bits = root; - return 0; -} diff --git a/deps/zlib/contrib/infback9/inftree9.h b/deps/zlib/contrib/infback9/inftree9.h deleted file mode 100644 index 5ab21f0c6d1120..00000000000000 --- a/deps/zlib/contrib/infback9/inftree9.h +++ /dev/null @@ -1,61 +0,0 @@ -/* inftree9.h -- header to use inftree9.c - * Copyright (C) 1995-2008 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Structure for decoding tables. Each entry provides either the - information needed to do the operation requested by the code that - indexed that table entry, or it provides a pointer to another - table that indexes more bits of the code. op indicates whether - the entry is a pointer to another table, a literal, a length or - distance, an end-of-block, or an invalid code. For a table - pointer, the low four bits of op is the number of index bits of - that table. For a length or distance, the low four bits of op - is the number of extra bits to get after the code. bits is - the number of bits in this code or part of the code to drop off - of the bit buffer. val is the actual byte to output in the case - of a literal, the base length or distance, or the offset from - the current table to the next table. Each entry is four bytes. */ -typedef struct { - unsigned char op; /* operation, extra bits, table bits */ - unsigned char bits; /* bits in this part of the code */ - unsigned short val; /* offset in table or code value */ -} code; - -/* op values as set by inflate_table(): - 00000000 - literal - 0000tttt - table link, tttt != 0 is the number of table index bits - 100eeeee - length or distance, eeee is the number of extra bits - 01100000 - end of block - 01000000 - invalid code - */ - -/* Maximum size of the dynamic table. The maximum number of code structures is - 1446, which is the sum of 852 for literal/length codes and 594 for distance - codes. These values were found by exhaustive searches using the program - examples/enough.c found in the zlib distribtution. The arguments to that - program are the number of symbols, the initial root table size, and the - maximum bit length of a code. "enough 286 9 15" for literal/length codes - returns returns 852, and "enough 32 6 15" for distance codes returns 594. - The initial root table size (9 or 6) is found in the fifth argument of the - inflate_table() calls in infback9.c. If the root table size is changed, - then these maximum sizes would be need to be recalculated and updated. */ -#define ENOUGH_LENS 852 -#define ENOUGH_DISTS 594 -#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) - -/* Type of code to build for inflate_table9() */ -typedef enum { - CODES, - LENS, - DISTS -} codetype; - -extern int inflate_table9 OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); diff --git a/deps/zlib/contrib/inflate86/inffas86.c b/deps/zlib/contrib/inflate86/inffas86.c deleted file mode 100644 index 7292f67b753795..00000000000000 --- a/deps/zlib/contrib/inflate86/inffas86.c +++ /dev/null @@ -1,1157 +0,0 @@ -/* inffas86.c is a hand tuned assembler version of - * - * inffast.c -- fast decoding - * Copyright (C) 1995-2003 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Copyright (C) 2003 Chris Anderson - * Please use the copyright conditions above. - * - * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also - * slightly quicker on x86 systems because, instead of using rep movsb to copy - * data, it uses rep movsw, which moves data in 2-byte chunks instead of single - * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates - * from http://fedora.linux.duke.edu/fc1_x86_64 - * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with - * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, - * when decompressing mozilla-source-1.3.tar.gz. - * - * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from - * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at - * the moment. I have successfully compiled and tested this code with gcc2.96, - * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S - * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX - * enabled. I will attempt to merge the MMX code into this version. Newer - * versions of this and inffast.S can be found at - * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -/* Mark Adler's comments from inffast.c: */ - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state->mode == LEN - strm->avail_in >= 6 - strm->avail_out >= 258 - start >= strm->avail_out - state->bits < 8 - - On return, state->mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm->avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for - output space. - */ -void inflate_fast(strm, start) -z_streamp strm; -unsigned start; /* inflate()'s starting value for strm->avail_out */ -{ - struct inflate_state FAR *state; - struct inffast_ar { -/* 64 32 x86 x86_64 */ -/* ar offset register */ -/* 0 0 */ void *esp; /* esp save */ -/* 8 4 */ void *ebp; /* ebp save */ -/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ -/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ -/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ -/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ -/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ -/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ -/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ -/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ -/* 80 40 */ unsigned long hold; /* edx rdx local strm->hold */ -/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ -/* 92 48 */ unsigned wsize; /* window size */ -/* 96 52 */ unsigned write; /* window write index */ -/*100 56 */ unsigned lmask; /* r12 mask for lcode */ -/*104 60 */ unsigned dmask; /* r13 mask for dcode */ -/*108 64 */ unsigned len; /* r14 match length */ -/*112 68 */ unsigned dist; /* r15 match distance */ -/*116 72 */ unsigned status; /* set when state chng*/ - } ar; - -#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 ) -#define PAD_AVAIL_IN 6 -#define PAD_AVAIL_OUT 258 -#else -#define PAD_AVAIL_IN 5 -#define PAD_AVAIL_OUT 257 -#endif - - /* copy state to local variables */ - state = (struct inflate_state FAR *)strm->state; - ar.in = strm->next_in; - ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); - ar.out = strm->next_out; - ar.beg = ar.out - (start - strm->avail_out); - ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); - ar.wsize = state->wsize; - ar.write = state->wnext; - ar.window = state->window; - ar.hold = state->hold; - ar.bits = state->bits; - ar.lcode = state->lencode; - ar.dcode = state->distcode; - ar.lmask = (1U << state->lenbits) - 1; - ar.dmask = (1U << state->distbits) - 1; - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - - /* align in on 1/2 hold size boundary */ - while (((unsigned long)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { - ar.hold += (unsigned long)*ar.in++ << ar.bits; - ar.bits += 8; - } - -#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 ) - __asm__ __volatile__ ( -" leaq %0, %%rax\n" -" movq %%rbp, 8(%%rax)\n" /* save regs rbp and rsp */ -" movq %%rsp, (%%rax)\n" -" movq %%rax, %%rsp\n" /* make rsp point to &ar */ -" movq 16(%%rsp), %%rsi\n" /* rsi = in */ -" movq 32(%%rsp), %%rdi\n" /* rdi = out */ -" movq 24(%%rsp), %%r9\n" /* r9 = last */ -" movq 48(%%rsp), %%r10\n" /* r10 = end */ -" movq 64(%%rsp), %%rbp\n" /* rbp = lcode */ -" movq 72(%%rsp), %%r11\n" /* r11 = dcode */ -" movq 80(%%rsp), %%rdx\n" /* rdx = hold */ -" movl 88(%%rsp), %%ebx\n" /* ebx = bits */ -" movl 100(%%rsp), %%r12d\n" /* r12d = lmask */ -" movl 104(%%rsp), %%r13d\n" /* r13d = dmask */ - /* r14d = len */ - /* r15d = dist */ -" cld\n" -" cmpq %%rdi, %%r10\n" -" je .L_one_time\n" /* if only one decode left */ -" cmpq %%rsi, %%r9\n" -" je .L_one_time\n" -" jmp .L_do_loop\n" - -".L_one_time:\n" -" movq %%r12, %%r8\n" /* r8 = lmask */ -" cmpb $32, %%bl\n" -" ja .L_get_length_code_one_time\n" - -" lodsl\n" /* eax = *(uint *)in++ */ -" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ -" addb $32, %%bl\n" /* bits += 32 */ -" shlq %%cl, %%rax\n" -" orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ -" jmp .L_get_length_code_one_time\n" - -".align 32,0x90\n" -".L_while_test:\n" -" cmpq %%rdi, %%r10\n" -" jbe .L_break_loop\n" -" cmpq %%rsi, %%r9\n" -" jbe .L_break_loop\n" - -".L_do_loop:\n" -" movq %%r12, %%r8\n" /* r8 = lmask */ -" cmpb $32, %%bl\n" -" ja .L_get_length_code\n" /* if (32 < bits) */ - -" lodsl\n" /* eax = *(uint *)in++ */ -" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ -" addb $32, %%bl\n" /* bits += 32 */ -" shlq %%cl, %%rax\n" -" orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ - -".L_get_length_code:\n" -" andq %%rdx, %%r8\n" /* r8 &= hold */ -" movl (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */ - -" movb %%ah, %%cl\n" /* cl = this.bits */ -" subb %%ah, %%bl\n" /* bits -= this.bits */ -" shrq %%cl, %%rdx\n" /* hold >>= this.bits */ - -" testb %%al, %%al\n" -" jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ - -" movq %%r12, %%r8\n" /* r8 = lmask */ -" shrl $16, %%eax\n" /* output this.val char */ -" stosb\n" - -".L_get_length_code_one_time:\n" -" andq %%rdx, %%r8\n" /* r8 &= hold */ -" movl (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */ - -".L_dolen:\n" -" movb %%ah, %%cl\n" /* cl = this.bits */ -" subb %%ah, %%bl\n" /* bits -= this.bits */ -" shrq %%cl, %%rdx\n" /* hold >>= this.bits */ - -" testb %%al, %%al\n" -" jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ - -" shrl $16, %%eax\n" /* output this.val char */ -" stosb\n" -" jmp .L_while_test\n" - -".align 32,0x90\n" -".L_test_for_length_base:\n" -" movl %%eax, %%r14d\n" /* len = this */ -" shrl $16, %%r14d\n" /* len = this.val */ -" movb %%al, %%cl\n" - -" testb $16, %%al\n" -" jz .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */ -" andb $15, %%cl\n" /* op &= 15 */ -" jz .L_decode_distance\n" /* if (!op) */ - -".L_add_bits_to_len:\n" -" subb %%cl, %%bl\n" -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" -" andl %%edx, %%eax\n" /* eax &= hold */ -" shrq %%cl, %%rdx\n" -" addl %%eax, %%r14d\n" /* len += hold & mask[op] */ - -".L_decode_distance:\n" -" movq %%r13, %%r8\n" /* r8 = dmask */ -" cmpb $32, %%bl\n" -" ja .L_get_distance_code\n" /* if (32 < bits) */ - -" lodsl\n" /* eax = *(uint *)in++ */ -" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ -" addb $32, %%bl\n" /* bits += 32 */ -" shlq %%cl, %%rax\n" -" orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ - -".L_get_distance_code:\n" -" andq %%rdx, %%r8\n" /* r8 &= hold */ -" movl (%%r11,%%r8,4), %%eax\n" /* eax = dcode[hold & dmask] */ - -".L_dodist:\n" -" movl %%eax, %%r15d\n" /* dist = this */ -" shrl $16, %%r15d\n" /* dist = this.val */ -" movb %%ah, %%cl\n" -" subb %%ah, %%bl\n" /* bits -= this.bits */ -" shrq %%cl, %%rdx\n" /* hold >>= this.bits */ -" movb %%al, %%cl\n" /* cl = this.op */ - -" testb $16, %%al\n" /* if ((op & 16) == 0) */ -" jz .L_test_for_second_level_dist\n" -" andb $15, %%cl\n" /* op &= 15 */ -" jz .L_check_dist_one\n" - -".L_add_bits_to_dist:\n" -" subb %%cl, %%bl\n" -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" /* (1 << op) - 1 */ -" andl %%edx, %%eax\n" /* eax &= hold */ -" shrq %%cl, %%rdx\n" -" addl %%eax, %%r15d\n" /* dist += hold & ((1 << op) - 1) */ - -".L_check_window:\n" -" movq %%rsi, %%r8\n" /* save in so from can use it's reg */ -" movq %%rdi, %%rax\n" -" subq 40(%%rsp), %%rax\n" /* nbytes = out - beg */ - -" cmpl %%r15d, %%eax\n" -" jb .L_clip_window\n" /* if (dist > nbytes) 4.2% */ - -" movl %%r14d, %%ecx\n" /* ecx = len */ -" movq %%rdi, %%rsi\n" -" subq %%r15, %%rsi\n" /* from = out - dist */ - -" sarl %%ecx\n" -" jnc .L_copy_two\n" /* if len % 2 == 0 */ - -" rep movsw\n" -" movb (%%rsi), %%al\n" -" movb %%al, (%%rdi)\n" -" incq %%rdi\n" - -" movq %%r8, %%rsi\n" /* move in back to %rsi, toss from */ -" jmp .L_while_test\n" - -".L_copy_two:\n" -" rep movsw\n" -" movq %%r8, %%rsi\n" /* move in back to %rsi, toss from */ -" jmp .L_while_test\n" - -".align 32,0x90\n" -".L_check_dist_one:\n" -" cmpl $1, %%r15d\n" /* if dist 1, is a memset */ -" jne .L_check_window\n" -" cmpq %%rdi, 40(%%rsp)\n" /* if out == beg, outside window */ -" je .L_check_window\n" - -" movl %%r14d, %%ecx\n" /* ecx = len */ -" movb -1(%%rdi), %%al\n" -" movb %%al, %%ah\n" - -" sarl %%ecx\n" -" jnc .L_set_two\n" -" movb %%al, (%%rdi)\n" -" incq %%rdi\n" - -".L_set_two:\n" -" rep stosw\n" -" jmp .L_while_test\n" - -".align 32,0x90\n" -".L_test_for_second_level_length:\n" -" testb $64, %%al\n" -" jnz .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */ - -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" -" andl %%edx, %%eax\n" /* eax &= hold */ -" addl %%r14d, %%eax\n" /* eax += len */ -" movl (%%rbp,%%rax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/ -" jmp .L_dolen\n" - -".align 32,0x90\n" -".L_test_for_second_level_dist:\n" -" testb $64, %%al\n" -" jnz .L_invalid_distance_code\n" /* if ((op & 64) != 0) */ - -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" -" andl %%edx, %%eax\n" /* eax &= hold */ -" addl %%r15d, %%eax\n" /* eax += dist */ -" movl (%%r11,%%rax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/ -" jmp .L_dodist\n" - -".align 32,0x90\n" -".L_clip_window:\n" -" movl %%eax, %%ecx\n" /* ecx = nbytes */ -" movl 92(%%rsp), %%eax\n" /* eax = wsize, prepare for dist cmp */ -" negl %%ecx\n" /* nbytes = -nbytes */ - -" cmpl %%r15d, %%eax\n" -" jb .L_invalid_distance_too_far\n" /* if (dist > wsize) */ - -" addl %%r15d, %%ecx\n" /* nbytes = dist - nbytes */ -" cmpl $0, 96(%%rsp)\n" -" jne .L_wrap_around_window\n" /* if (write != 0) */ - -" movq 56(%%rsp), %%rsi\n" /* from = window */ -" subl %%ecx, %%eax\n" /* eax -= nbytes */ -" addq %%rax, %%rsi\n" /* from += wsize - nbytes */ - -" movl %%r14d, %%eax\n" /* eax = len */ -" cmpl %%ecx, %%r14d\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* eax -= nbytes */ -" rep movsb\n" -" movq %%rdi, %%rsi\n" -" subq %%r15, %%rsi\n" /* from = &out[ -dist ] */ -" jmp .L_do_copy\n" - -".align 32,0x90\n" -".L_wrap_around_window:\n" -" movl 96(%%rsp), %%eax\n" /* eax = write */ -" cmpl %%eax, %%ecx\n" -" jbe .L_contiguous_in_window\n" /* if (write >= nbytes) */ - -" movl 92(%%rsp), %%esi\n" /* from = wsize */ -" addq 56(%%rsp), %%rsi\n" /* from += window */ -" addq %%rax, %%rsi\n" /* from += write */ -" subq %%rcx, %%rsi\n" /* from -= nbytes */ -" subl %%eax, %%ecx\n" /* nbytes -= write */ - -" movl %%r14d, %%eax\n" /* eax = len */ -" cmpl %%ecx, %%eax\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* len -= nbytes */ -" rep movsb\n" -" movq 56(%%rsp), %%rsi\n" /* from = window */ -" movl 96(%%rsp), %%ecx\n" /* nbytes = write */ -" cmpl %%ecx, %%eax\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* len -= nbytes */ -" rep movsb\n" -" movq %%rdi, %%rsi\n" -" subq %%r15, %%rsi\n" /* from = out - dist */ -" jmp .L_do_copy\n" - -".align 32,0x90\n" -".L_contiguous_in_window:\n" -" movq 56(%%rsp), %%rsi\n" /* rsi = window */ -" addq %%rax, %%rsi\n" -" subq %%rcx, %%rsi\n" /* from += write - nbytes */ - -" movl %%r14d, %%eax\n" /* eax = len */ -" cmpl %%ecx, %%eax\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* len -= nbytes */ -" rep movsb\n" -" movq %%rdi, %%rsi\n" -" subq %%r15, %%rsi\n" /* from = out - dist */ -" jmp .L_do_copy\n" /* if (nbytes >= len) */ - -".align 32,0x90\n" -".L_do_copy:\n" -" movl %%eax, %%ecx\n" /* ecx = len */ -" rep movsb\n" - -" movq %%r8, %%rsi\n" /* move in back to %esi, toss from */ -" jmp .L_while_test\n" - -".L_test_for_end_of_block:\n" -" testb $32, %%al\n" -" jz .L_invalid_literal_length_code\n" -" movl $1, 116(%%rsp)\n" -" jmp .L_break_loop_with_status\n" - -".L_invalid_literal_length_code:\n" -" movl $2, 116(%%rsp)\n" -" jmp .L_break_loop_with_status\n" - -".L_invalid_distance_code:\n" -" movl $3, 116(%%rsp)\n" -" jmp .L_break_loop_with_status\n" - -".L_invalid_distance_too_far:\n" -" movl $4, 116(%%rsp)\n" -" jmp .L_break_loop_with_status\n" - -".L_break_loop:\n" -" movl $0, 116(%%rsp)\n" - -".L_break_loop_with_status:\n" -/* put in, out, bits, and hold back into ar and pop esp */ -" movq %%rsi, 16(%%rsp)\n" /* in */ -" movq %%rdi, 32(%%rsp)\n" /* out */ -" movl %%ebx, 88(%%rsp)\n" /* bits */ -" movq %%rdx, 80(%%rsp)\n" /* hold */ -" movq (%%rsp), %%rax\n" /* restore rbp and rsp */ -" movq 8(%%rsp), %%rbp\n" -" movq %%rax, %%rsp\n" - : - : "m" (ar) - : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", - "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" - ); -#elif ( defined( __GNUC__ ) || defined( __ICC ) ) && defined( __i386 ) - __asm__ __volatile__ ( -" leal %0, %%eax\n" -" movl %%esp, (%%eax)\n" /* save esp, ebp */ -" movl %%ebp, 4(%%eax)\n" -" movl %%eax, %%esp\n" -" movl 8(%%esp), %%esi\n" /* esi = in */ -" movl 16(%%esp), %%edi\n" /* edi = out */ -" movl 40(%%esp), %%edx\n" /* edx = hold */ -" movl 44(%%esp), %%ebx\n" /* ebx = bits */ -" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ - -" cld\n" -" jmp .L_do_loop\n" - -".align 32,0x90\n" -".L_while_test:\n" -" cmpl %%edi, 24(%%esp)\n" /* out < end */ -" jbe .L_break_loop\n" -" cmpl %%esi, 12(%%esp)\n" /* in < last */ -" jbe .L_break_loop\n" - -".L_do_loop:\n" -" cmpb $15, %%bl\n" -" ja .L_get_length_code\n" /* if (15 < bits) */ - -" xorl %%eax, %%eax\n" -" lodsw\n" /* al = *(ushort *)in++ */ -" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ -" addb $16, %%bl\n" /* bits += 16 */ -" shll %%cl, %%eax\n" -" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ - -".L_get_length_code:\n" -" movl 56(%%esp), %%eax\n" /* eax = lmask */ -" andl %%edx, %%eax\n" /* eax &= hold */ -" movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[hold & lmask] */ - -".L_dolen:\n" -" movb %%ah, %%cl\n" /* cl = this.bits */ -" subb %%ah, %%bl\n" /* bits -= this.bits */ -" shrl %%cl, %%edx\n" /* hold >>= this.bits */ - -" testb %%al, %%al\n" -" jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ - -" shrl $16, %%eax\n" /* output this.val char */ -" stosb\n" -" jmp .L_while_test\n" - -".align 32,0x90\n" -".L_test_for_length_base:\n" -" movl %%eax, %%ecx\n" /* len = this */ -" shrl $16, %%ecx\n" /* len = this.val */ -" movl %%ecx, 64(%%esp)\n" /* save len */ -" movb %%al, %%cl\n" - -" testb $16, %%al\n" -" jz .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */ -" andb $15, %%cl\n" /* op &= 15 */ -" jz .L_decode_distance\n" /* if (!op) */ -" cmpb %%cl, %%bl\n" -" jae .L_add_bits_to_len\n" /* if (op <= bits) */ - -" movb %%cl, %%ch\n" /* stash op in ch, freeing cl */ -" xorl %%eax, %%eax\n" -" lodsw\n" /* al = *(ushort *)in++ */ -" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ -" addb $16, %%bl\n" /* bits += 16 */ -" shll %%cl, %%eax\n" -" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ -" movb %%ch, %%cl\n" /* move op back to ecx */ - -".L_add_bits_to_len:\n" -" subb %%cl, %%bl\n" -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" -" andl %%edx, %%eax\n" /* eax &= hold */ -" shrl %%cl, %%edx\n" -" addl %%eax, 64(%%esp)\n" /* len += hold & mask[op] */ - -".L_decode_distance:\n" -" cmpb $15, %%bl\n" -" ja .L_get_distance_code\n" /* if (15 < bits) */ - -" xorl %%eax, %%eax\n" -" lodsw\n" /* al = *(ushort *)in++ */ -" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ -" addb $16, %%bl\n" /* bits += 16 */ -" shll %%cl, %%eax\n" -" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ - -".L_get_distance_code:\n" -" movl 60(%%esp), %%eax\n" /* eax = dmask */ -" movl 36(%%esp), %%ecx\n" /* ecx = dcode */ -" andl %%edx, %%eax\n" /* eax &= hold */ -" movl (%%ecx,%%eax,4), %%eax\n"/* eax = dcode[hold & dmask] */ - -".L_dodist:\n" -" movl %%eax, %%ebp\n" /* dist = this */ -" shrl $16, %%ebp\n" /* dist = this.val */ -" movb %%ah, %%cl\n" -" subb %%ah, %%bl\n" /* bits -= this.bits */ -" shrl %%cl, %%edx\n" /* hold >>= this.bits */ -" movb %%al, %%cl\n" /* cl = this.op */ - -" testb $16, %%al\n" /* if ((op & 16) == 0) */ -" jz .L_test_for_second_level_dist\n" -" andb $15, %%cl\n" /* op &= 15 */ -" jz .L_check_dist_one\n" -" cmpb %%cl, %%bl\n" -" jae .L_add_bits_to_dist\n" /* if (op <= bits) 97.6% */ - -" movb %%cl, %%ch\n" /* stash op in ch, freeing cl */ -" xorl %%eax, %%eax\n" -" lodsw\n" /* al = *(ushort *)in++ */ -" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ -" addb $16, %%bl\n" /* bits += 16 */ -" shll %%cl, %%eax\n" -" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ -" movb %%ch, %%cl\n" /* move op back to ecx */ - -".L_add_bits_to_dist:\n" -" subb %%cl, %%bl\n" -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" /* (1 << op) - 1 */ -" andl %%edx, %%eax\n" /* eax &= hold */ -" shrl %%cl, %%edx\n" -" addl %%eax, %%ebp\n" /* dist += hold & ((1 << op) - 1) */ - -".L_check_window:\n" -" movl %%esi, 8(%%esp)\n" /* save in so from can use it's reg */ -" movl %%edi, %%eax\n" -" subl 20(%%esp), %%eax\n" /* nbytes = out - beg */ - -" cmpl %%ebp, %%eax\n" -" jb .L_clip_window\n" /* if (dist > nbytes) 4.2% */ - -" movl 64(%%esp), %%ecx\n" /* ecx = len */ -" movl %%edi, %%esi\n" -" subl %%ebp, %%esi\n" /* from = out - dist */ - -" sarl %%ecx\n" -" jnc .L_copy_two\n" /* if len % 2 == 0 */ - -" rep movsw\n" -" movb (%%esi), %%al\n" -" movb %%al, (%%edi)\n" -" incl %%edi\n" - -" movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ -" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ -" jmp .L_while_test\n" - -".L_copy_two:\n" -" rep movsw\n" -" movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ -" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ -" jmp .L_while_test\n" - -".align 32,0x90\n" -".L_check_dist_one:\n" -" cmpl $1, %%ebp\n" /* if dist 1, is a memset */ -" jne .L_check_window\n" -" cmpl %%edi, 20(%%esp)\n" -" je .L_check_window\n" /* out == beg, if outside window */ - -" movl 64(%%esp), %%ecx\n" /* ecx = len */ -" movb -1(%%edi), %%al\n" -" movb %%al, %%ah\n" - -" sarl %%ecx\n" -" jnc .L_set_two\n" -" movb %%al, (%%edi)\n" -" incl %%edi\n" - -".L_set_two:\n" -" rep stosw\n" -" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ -" jmp .L_while_test\n" - -".align 32,0x90\n" -".L_test_for_second_level_length:\n" -" testb $64, %%al\n" -" jnz .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */ - -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" -" andl %%edx, %%eax\n" /* eax &= hold */ -" addl 64(%%esp), %%eax\n" /* eax += len */ -" movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/ -" jmp .L_dolen\n" - -".align 32,0x90\n" -".L_test_for_second_level_dist:\n" -" testb $64, %%al\n" -" jnz .L_invalid_distance_code\n" /* if ((op & 64) != 0) */ - -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" -" andl %%edx, %%eax\n" /* eax &= hold */ -" addl %%ebp, %%eax\n" /* eax += dist */ -" movl 36(%%esp), %%ecx\n" /* ecx = dcode */ -" movl (%%ecx,%%eax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/ -" jmp .L_dodist\n" - -".align 32,0x90\n" -".L_clip_window:\n" -" movl %%eax, %%ecx\n" -" movl 48(%%esp), %%eax\n" /* eax = wsize */ -" negl %%ecx\n" /* nbytes = -nbytes */ -" movl 28(%%esp), %%esi\n" /* from = window */ - -" cmpl %%ebp, %%eax\n" -" jb .L_invalid_distance_too_far\n" /* if (dist > wsize) */ - -" addl %%ebp, %%ecx\n" /* nbytes = dist - nbytes */ -" cmpl $0, 52(%%esp)\n" -" jne .L_wrap_around_window\n" /* if (write != 0) */ - -" subl %%ecx, %%eax\n" -" addl %%eax, %%esi\n" /* from += wsize - nbytes */ - -" movl 64(%%esp), %%eax\n" /* eax = len */ -" cmpl %%ecx, %%eax\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* len -= nbytes */ -" rep movsb\n" -" movl %%edi, %%esi\n" -" subl %%ebp, %%esi\n" /* from = out - dist */ -" jmp .L_do_copy\n" - -".align 32,0x90\n" -".L_wrap_around_window:\n" -" movl 52(%%esp), %%eax\n" /* eax = write */ -" cmpl %%eax, %%ecx\n" -" jbe .L_contiguous_in_window\n" /* if (write >= nbytes) */ - -" addl 48(%%esp), %%esi\n" /* from += wsize */ -" addl %%eax, %%esi\n" /* from += write */ -" subl %%ecx, %%esi\n" /* from -= nbytes */ -" subl %%eax, %%ecx\n" /* nbytes -= write */ - -" movl 64(%%esp), %%eax\n" /* eax = len */ -" cmpl %%ecx, %%eax\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* len -= nbytes */ -" rep movsb\n" -" movl 28(%%esp), %%esi\n" /* from = window */ -" movl 52(%%esp), %%ecx\n" /* nbytes = write */ -" cmpl %%ecx, %%eax\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* len -= nbytes */ -" rep movsb\n" -" movl %%edi, %%esi\n" -" subl %%ebp, %%esi\n" /* from = out - dist */ -" jmp .L_do_copy\n" - -".align 32,0x90\n" -".L_contiguous_in_window:\n" -" addl %%eax, %%esi\n" -" subl %%ecx, %%esi\n" /* from += write - nbytes */ - -" movl 64(%%esp), %%eax\n" /* eax = len */ -" cmpl %%ecx, %%eax\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* len -= nbytes */ -" rep movsb\n" -" movl %%edi, %%esi\n" -" subl %%ebp, %%esi\n" /* from = out - dist */ -" jmp .L_do_copy\n" /* if (nbytes >= len) */ - -".align 32,0x90\n" -".L_do_copy:\n" -" movl %%eax, %%ecx\n" -" rep movsb\n" - -" movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ -" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ -" jmp .L_while_test\n" - -".L_test_for_end_of_block:\n" -" testb $32, %%al\n" -" jz .L_invalid_literal_length_code\n" -" movl $1, 72(%%esp)\n" -" jmp .L_break_loop_with_status\n" - -".L_invalid_literal_length_code:\n" -" movl $2, 72(%%esp)\n" -" jmp .L_break_loop_with_status\n" - -".L_invalid_distance_code:\n" -" movl $3, 72(%%esp)\n" -" jmp .L_break_loop_with_status\n" - -".L_invalid_distance_too_far:\n" -" movl 8(%%esp), %%esi\n" -" movl $4, 72(%%esp)\n" -" jmp .L_break_loop_with_status\n" - -".L_break_loop:\n" -" movl $0, 72(%%esp)\n" - -".L_break_loop_with_status:\n" -/* put in, out, bits, and hold back into ar and pop esp */ -" movl %%esi, 8(%%esp)\n" /* save in */ -" movl %%edi, 16(%%esp)\n" /* save out */ -" movl %%ebx, 44(%%esp)\n" /* save bits */ -" movl %%edx, 40(%%esp)\n" /* save hold */ -" movl 4(%%esp), %%ebp\n" /* restore esp, ebp */ -" movl (%%esp), %%esp\n" - : - : "m" (ar) - : "memory", "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi" - ); -#elif defined( _MSC_VER ) && ! defined( _M_AMD64 ) - __asm { - lea eax, ar - mov [eax], esp /* save esp, ebp */ - mov [eax+4], ebp - mov esp, eax - mov esi, [esp+8] /* esi = in */ - mov edi, [esp+16] /* edi = out */ - mov edx, [esp+40] /* edx = hold */ - mov ebx, [esp+44] /* ebx = bits */ - mov ebp, [esp+32] /* ebp = lcode */ - - cld - jmp L_do_loop - -ALIGN 4 -L_while_test: - cmp [esp+24], edi - jbe L_break_loop - cmp [esp+12], esi - jbe L_break_loop - -L_do_loop: - cmp bl, 15 - ja L_get_length_code /* if (15 < bits) */ - - xor eax, eax - lodsw /* al = *(ushort *)in++ */ - mov cl, bl /* cl = bits, needs it for shifting */ - add bl, 16 /* bits += 16 */ - shl eax, cl - or edx, eax /* hold |= *((ushort *)in)++ << bits */ - -L_get_length_code: - mov eax, [esp+56] /* eax = lmask */ - and eax, edx /* eax &= hold */ - mov eax, [ebp+eax*4] /* eax = lcode[hold & lmask] */ - -L_dolen: - mov cl, ah /* cl = this.bits */ - sub bl, ah /* bits -= this.bits */ - shr edx, cl /* hold >>= this.bits */ - - test al, al - jnz L_test_for_length_base /* if (op != 0) 45.7% */ - - shr eax, 16 /* output this.val char */ - stosb - jmp L_while_test - -ALIGN 4 -L_test_for_length_base: - mov ecx, eax /* len = this */ - shr ecx, 16 /* len = this.val */ - mov [esp+64], ecx /* save len */ - mov cl, al - - test al, 16 - jz L_test_for_second_level_length /* if ((op & 16) == 0) 8% */ - and cl, 15 /* op &= 15 */ - jz L_decode_distance /* if (!op) */ - cmp bl, cl - jae L_add_bits_to_len /* if (op <= bits) */ - - mov ch, cl /* stash op in ch, freeing cl */ - xor eax, eax - lodsw /* al = *(ushort *)in++ */ - mov cl, bl /* cl = bits, needs it for shifting */ - add bl, 16 /* bits += 16 */ - shl eax, cl - or edx, eax /* hold |= *((ushort *)in)++ << bits */ - mov cl, ch /* move op back to ecx */ - -L_add_bits_to_len: - sub bl, cl - xor eax, eax - inc eax - shl eax, cl - dec eax - and eax, edx /* eax &= hold */ - shr edx, cl - add [esp+64], eax /* len += hold & mask[op] */ - -L_decode_distance: - cmp bl, 15 - ja L_get_distance_code /* if (15 < bits) */ - - xor eax, eax - lodsw /* al = *(ushort *)in++ */ - mov cl, bl /* cl = bits, needs it for shifting */ - add bl, 16 /* bits += 16 */ - shl eax, cl - or edx, eax /* hold |= *((ushort *)in)++ << bits */ - -L_get_distance_code: - mov eax, [esp+60] /* eax = dmask */ - mov ecx, [esp+36] /* ecx = dcode */ - and eax, edx /* eax &= hold */ - mov eax, [ecx+eax*4]/* eax = dcode[hold & dmask] */ - -L_dodist: - mov ebp, eax /* dist = this */ - shr ebp, 16 /* dist = this.val */ - mov cl, ah - sub bl, ah /* bits -= this.bits */ - shr edx, cl /* hold >>= this.bits */ - mov cl, al /* cl = this.op */ - - test al, 16 /* if ((op & 16) == 0) */ - jz L_test_for_second_level_dist - and cl, 15 /* op &= 15 */ - jz L_check_dist_one - cmp bl, cl - jae L_add_bits_to_dist /* if (op <= bits) 97.6% */ - - mov ch, cl /* stash op in ch, freeing cl */ - xor eax, eax - lodsw /* al = *(ushort *)in++ */ - mov cl, bl /* cl = bits, needs it for shifting */ - add bl, 16 /* bits += 16 */ - shl eax, cl - or edx, eax /* hold |= *((ushort *)in)++ << bits */ - mov cl, ch /* move op back to ecx */ - -L_add_bits_to_dist: - sub bl, cl - xor eax, eax - inc eax - shl eax, cl - dec eax /* (1 << op) - 1 */ - and eax, edx /* eax &= hold */ - shr edx, cl - add ebp, eax /* dist += hold & ((1 << op) - 1) */ - -L_check_window: - mov [esp+8], esi /* save in so from can use it's reg */ - mov eax, edi - sub eax, [esp+20] /* nbytes = out - beg */ - - cmp eax, ebp - jb L_clip_window /* if (dist > nbytes) 4.2% */ - - mov ecx, [esp+64] /* ecx = len */ - mov esi, edi - sub esi, ebp /* from = out - dist */ - - sar ecx, 1 - jnc L_copy_two - - rep movsw - mov al, [esi] - mov [edi], al - inc edi - - mov esi, [esp+8] /* move in back to %esi, toss from */ - mov ebp, [esp+32] /* ebp = lcode */ - jmp L_while_test - -L_copy_two: - rep movsw - mov esi, [esp+8] /* move in back to %esi, toss from */ - mov ebp, [esp+32] /* ebp = lcode */ - jmp L_while_test - -ALIGN 4 -L_check_dist_one: - cmp ebp, 1 /* if dist 1, is a memset */ - jne L_check_window - cmp [esp+20], edi - je L_check_window /* out == beg, if outside window */ - - mov ecx, [esp+64] /* ecx = len */ - mov al, [edi-1] - mov ah, al - - sar ecx, 1 - jnc L_set_two - mov [edi], al /* memset out with from[-1] */ - inc edi - -L_set_two: - rep stosw - mov ebp, [esp+32] /* ebp = lcode */ - jmp L_while_test - -ALIGN 4 -L_test_for_second_level_length: - test al, 64 - jnz L_test_for_end_of_block /* if ((op & 64) != 0) */ - - xor eax, eax - inc eax - shl eax, cl - dec eax - and eax, edx /* eax &= hold */ - add eax, [esp+64] /* eax += len */ - mov eax, [ebp+eax*4] /* eax = lcode[val+(hold&mask[op])]*/ - jmp L_dolen - -ALIGN 4 -L_test_for_second_level_dist: - test al, 64 - jnz L_invalid_distance_code /* if ((op & 64) != 0) */ - - xor eax, eax - inc eax - shl eax, cl - dec eax - and eax, edx /* eax &= hold */ - add eax, ebp /* eax += dist */ - mov ecx, [esp+36] /* ecx = dcode */ - mov eax, [ecx+eax*4] /* eax = dcode[val+(hold&mask[op])]*/ - jmp L_dodist - -ALIGN 4 -L_clip_window: - mov ecx, eax - mov eax, [esp+48] /* eax = wsize */ - neg ecx /* nbytes = -nbytes */ - mov esi, [esp+28] /* from = window */ - - cmp eax, ebp - jb L_invalid_distance_too_far /* if (dist > wsize) */ - - add ecx, ebp /* nbytes = dist - nbytes */ - cmp dword ptr [esp+52], 0 - jne L_wrap_around_window /* if (write != 0) */ - - sub eax, ecx - add esi, eax /* from += wsize - nbytes */ - - mov eax, [esp+64] /* eax = len */ - cmp eax, ecx - jbe L_do_copy /* if (nbytes >= len) */ - - sub eax, ecx /* len -= nbytes */ - rep movsb - mov esi, edi - sub esi, ebp /* from = out - dist */ - jmp L_do_copy - -ALIGN 4 -L_wrap_around_window: - mov eax, [esp+52] /* eax = write */ - cmp ecx, eax - jbe L_contiguous_in_window /* if (write >= nbytes) */ - - add esi, [esp+48] /* from += wsize */ - add esi, eax /* from += write */ - sub esi, ecx /* from -= nbytes */ - sub ecx, eax /* nbytes -= write */ - - mov eax, [esp+64] /* eax = len */ - cmp eax, ecx - jbe L_do_copy /* if (nbytes >= len) */ - - sub eax, ecx /* len -= nbytes */ - rep movsb - mov esi, [esp+28] /* from = window */ - mov ecx, [esp+52] /* nbytes = write */ - cmp eax, ecx - jbe L_do_copy /* if (nbytes >= len) */ - - sub eax, ecx /* len -= nbytes */ - rep movsb - mov esi, edi - sub esi, ebp /* from = out - dist */ - jmp L_do_copy - -ALIGN 4 -L_contiguous_in_window: - add esi, eax - sub esi, ecx /* from += write - nbytes */ - - mov eax, [esp+64] /* eax = len */ - cmp eax, ecx - jbe L_do_copy /* if (nbytes >= len) */ - - sub eax, ecx /* len -= nbytes */ - rep movsb - mov esi, edi - sub esi, ebp /* from = out - dist */ - jmp L_do_copy - -ALIGN 4 -L_do_copy: - mov ecx, eax - rep movsb - - mov esi, [esp+8] /* move in back to %esi, toss from */ - mov ebp, [esp+32] /* ebp = lcode */ - jmp L_while_test - -L_test_for_end_of_block: - test al, 32 - jz L_invalid_literal_length_code - mov dword ptr [esp+72], 1 - jmp L_break_loop_with_status - -L_invalid_literal_length_code: - mov dword ptr [esp+72], 2 - jmp L_break_loop_with_status - -L_invalid_distance_code: - mov dword ptr [esp+72], 3 - jmp L_break_loop_with_status - -L_invalid_distance_too_far: - mov esi, [esp+4] - mov dword ptr [esp+72], 4 - jmp L_break_loop_with_status - -L_break_loop: - mov dword ptr [esp+72], 0 - -L_break_loop_with_status: -/* put in, out, bits, and hold back into ar and pop esp */ - mov [esp+8], esi /* save in */ - mov [esp+16], edi /* save out */ - mov [esp+44], ebx /* save bits */ - mov [esp+40], edx /* save hold */ - mov ebp, [esp+4] /* restore esp, ebp */ - mov esp, [esp] - } -#else -#error "x86 architecture not defined" -#endif - - if (ar.status > 1) { - if (ar.status == 2) - strm->msg = "invalid literal/length code"; - else if (ar.status == 3) - strm->msg = "invalid distance code"; - else - strm->msg = "invalid distance too far back"; - state->mode = BAD; - } - else if ( ar.status == 1 ) { - state->mode = TYPE; - } - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - ar.len = ar.bits >> 3; - ar.in -= ar.len; - ar.bits -= ar.len << 3; - ar.hold &= (1U << ar.bits) - 1; - - /* update state and return */ - strm->next_in = ar.in; - strm->next_out = ar.out; - strm->avail_in = (unsigned)(ar.in < ar.last ? - PAD_AVAIL_IN + (ar.last - ar.in) : - PAD_AVAIL_IN - (ar.in - ar.last)); - strm->avail_out = (unsigned)(ar.out < ar.end ? - PAD_AVAIL_OUT + (ar.end - ar.out) : - PAD_AVAIL_OUT - (ar.out - ar.end)); - state->hold = ar.hold; - state->bits = ar.bits; - return; -} - diff --git a/deps/zlib/contrib/inflate86/inffast.S b/deps/zlib/contrib/inflate86/inffast.S deleted file mode 100644 index 2245a2905bdf53..00000000000000 --- a/deps/zlib/contrib/inflate86/inffast.S +++ /dev/null @@ -1,1368 +0,0 @@ -/* - * inffast.S is a hand tuned assembler version of: - * - * inffast.c -- fast decoding - * Copyright (C) 1995-2003 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Copyright (C) 2003 Chris Anderson - * Please use the copyright conditions above. - * - * This version (Jan-23-2003) of inflate_fast was coded and tested under - * GNU/Linux on a pentium 3, using the gcc-3.2 compiler distribution. On that - * machine, I found that gzip style archives decompressed about 20% faster than - * the gcc-3.2 -O3 -fomit-frame-pointer compiled version. Your results will - * depend on how large of a buffer is used for z_stream.next_in & next_out - * (8K-32K worked best for my 256K cpu cache) and how much overhead there is in - * stream processing I/O and crc32/addler32. In my case, this routine used - * 70% of the cpu time and crc32 used 20%. - * - * I am confident that this version will work in the general case, but I have - * not tested a wide variety of datasets or a wide variety of platforms. - * - * Jan-24-2003 -- Added -DUSE_MMX define for slightly faster inflating. - * It should be a runtime flag instead of compile time flag... - * - * Jan-26-2003 -- Added runtime check for MMX support with cpuid instruction. - * With -DUSE_MMX, only MMX code is compiled. With -DNO_MMX, only non-MMX code - * is compiled. Without either option, runtime detection is enabled. Runtime - * detection should work on all modern cpus and the recomended algorithm (flip - * ID bit on eflags and then use the cpuid instruction) is used in many - * multimedia applications. Tested under win2k with gcc-2.95 and gas-2.12 - * distributed with cygwin3. Compiling with gcc-2.95 -c inffast.S -o - * inffast.obj generates a COFF object which can then be linked with MSVC++ - * compiled code. Tested under FreeBSD 4.7 with gcc-2.95. - * - * Jan-28-2003 -- Tested Athlon XP... MMX mode is slower than no MMX (and - * slower than compiler generated code). Adjusted cpuid check to use the MMX - * code only for Pentiums < P4 until I have more data on the P4. Speed - * improvment is only about 15% on the Athlon when compared with code generated - * with MSVC++. Not sure yet, but I think the P4 will also be slower using the - * MMX mode because many of it's x86 ALU instructions execute in .5 cycles and - * have less latency than MMX ops. Added code to buffer the last 11 bytes of - * the input stream since the MMX code grabs bits in chunks of 32, which - * differs from the inffast.c algorithm. I don't think there would have been - * read overruns where a page boundary was crossed (a segfault), but there - * could have been overruns when next_in ends on unaligned memory (unintialized - * memory read). - * - * Mar-13-2003 -- P4 MMX is slightly slower than P4 NO_MMX. I created a C - * version of the non-MMX code so that it doesn't depend on zstrm and zstate - * structure offsets which are hard coded in this file. This was last tested - * with zlib-1.2.0 which is currently in beta testing, newer versions of this - * and inffas86.c can be found at http://www.eetbeetee.com/zlib/ and - * http://www.charm.net/~christop/zlib/ - */ - - -/* - * if you have underscore linking problems (_inflate_fast undefined), try - * using -DGAS_COFF - */ -#if ! defined( GAS_COFF ) && ! defined( GAS_ELF ) - -#if defined( WIN32 ) || defined( __CYGWIN__ ) -#define GAS_COFF /* windows object format */ -#else -#define GAS_ELF -#endif - -#endif /* ! GAS_COFF && ! GAS_ELF */ - - -#if defined( GAS_COFF ) - -/* coff externals have underscores */ -#define inflate_fast _inflate_fast -#define inflate_fast_use_mmx _inflate_fast_use_mmx - -#endif /* GAS_COFF */ - - -.file "inffast.S" - -.globl inflate_fast - -.text -.align 4,0 -.L_invalid_literal_length_code_msg: -.string "invalid literal/length code" - -.align 4,0 -.L_invalid_distance_code_msg: -.string "invalid distance code" - -.align 4,0 -.L_invalid_distance_too_far_msg: -.string "invalid distance too far back" - -#if ! defined( NO_MMX ) -.align 4,0 -.L_mask: /* mask[N] = ( 1 << N ) - 1 */ -.long 0 -.long 1 -.long 3 -.long 7 -.long 15 -.long 31 -.long 63 -.long 127 -.long 255 -.long 511 -.long 1023 -.long 2047 -.long 4095 -.long 8191 -.long 16383 -.long 32767 -.long 65535 -.long 131071 -.long 262143 -.long 524287 -.long 1048575 -.long 2097151 -.long 4194303 -.long 8388607 -.long 16777215 -.long 33554431 -.long 67108863 -.long 134217727 -.long 268435455 -.long 536870911 -.long 1073741823 -.long 2147483647 -.long 4294967295 -#endif /* NO_MMX */ - -.text - -/* - * struct z_stream offsets, in zlib.h - */ -#define next_in_strm 0 /* strm->next_in */ -#define avail_in_strm 4 /* strm->avail_in */ -#define next_out_strm 12 /* strm->next_out */ -#define avail_out_strm 16 /* strm->avail_out */ -#define msg_strm 24 /* strm->msg */ -#define state_strm 28 /* strm->state */ - -/* - * struct inflate_state offsets, in inflate.h - */ -#define mode_state 0 /* state->mode */ -#define wsize_state 32 /* state->wsize */ -#define write_state 40 /* state->write */ -#define window_state 44 /* state->window */ -#define hold_state 48 /* state->hold */ -#define bits_state 52 /* state->bits */ -#define lencode_state 68 /* state->lencode */ -#define distcode_state 72 /* state->distcode */ -#define lenbits_state 76 /* state->lenbits */ -#define distbits_state 80 /* state->distbits */ - -/* - * inflate_fast's activation record - */ -#define local_var_size 64 /* how much local space for vars */ -#define strm_sp 88 /* first arg: z_stream * (local_var_size + 24) */ -#define start_sp 92 /* second arg: unsigned int (local_var_size + 28) */ - -/* - * offsets for local vars on stack - */ -#define out 60 /* unsigned char* */ -#define window 56 /* unsigned char* */ -#define wsize 52 /* unsigned int */ -#define write 48 /* unsigned int */ -#define in 44 /* unsigned char* */ -#define beg 40 /* unsigned char* */ -#define buf 28 /* char[ 12 ] */ -#define len 24 /* unsigned int */ -#define last 20 /* unsigned char* */ -#define end 16 /* unsigned char* */ -#define dcode 12 /* code* */ -#define lcode 8 /* code* */ -#define dmask 4 /* unsigned int */ -#define lmask 0 /* unsigned int */ - -/* - * typedef enum inflate_mode consts, in inflate.h - */ -#define INFLATE_MODE_TYPE 11 /* state->mode flags enum-ed in inflate.h */ -#define INFLATE_MODE_BAD 26 - - -#if ! defined( USE_MMX ) && ! defined( NO_MMX ) - -#define RUN_TIME_MMX - -#define CHECK_MMX 1 -#define DO_USE_MMX 2 -#define DONT_USE_MMX 3 - -.globl inflate_fast_use_mmx - -.data - -.align 4,0 -inflate_fast_use_mmx: /* integer flag for run time control 1=check,2=mmx,3=no */ -.long CHECK_MMX - -#if defined( GAS_ELF ) -/* elf info */ -.type inflate_fast_use_mmx,@object -.size inflate_fast_use_mmx,4 -#endif - -#endif /* RUN_TIME_MMX */ - -#if defined( GAS_COFF ) -/* coff info: scl 2 = extern, type 32 = function */ -.def inflate_fast; .scl 2; .type 32; .endef -#endif - -.text - -.align 32,0x90 -inflate_fast: - pushl %edi - pushl %esi - pushl %ebp - pushl %ebx - pushf /* save eflags (strm_sp, state_sp assumes this is 32 bits) */ - subl $local_var_size, %esp - cld - -#define strm_r %esi -#define state_r %edi - - movl strm_sp(%esp), strm_r - movl state_strm(strm_r), state_r - - /* in = strm->next_in; - * out = strm->next_out; - * last = in + strm->avail_in - 11; - * beg = out - (start - strm->avail_out); - * end = out + (strm->avail_out - 257); - */ - movl avail_in_strm(strm_r), %edx - movl next_in_strm(strm_r), %eax - - addl %eax, %edx /* avail_in += next_in */ - subl $11, %edx /* avail_in -= 11 */ - - movl %eax, in(%esp) - movl %edx, last(%esp) - - movl start_sp(%esp), %ebp - movl avail_out_strm(strm_r), %ecx - movl next_out_strm(strm_r), %ebx - - subl %ecx, %ebp /* start -= avail_out */ - negl %ebp /* start = -start */ - addl %ebx, %ebp /* start += next_out */ - - subl $257, %ecx /* avail_out -= 257 */ - addl %ebx, %ecx /* avail_out += out */ - - movl %ebx, out(%esp) - movl %ebp, beg(%esp) - movl %ecx, end(%esp) - - /* wsize = state->wsize; - * write = state->write; - * window = state->window; - * hold = state->hold; - * bits = state->bits; - * lcode = state->lencode; - * dcode = state->distcode; - * lmask = ( 1 << state->lenbits ) - 1; - * dmask = ( 1 << state->distbits ) - 1; - */ - - movl lencode_state(state_r), %eax - movl distcode_state(state_r), %ecx - - movl %eax, lcode(%esp) - movl %ecx, dcode(%esp) - - movl $1, %eax - movl lenbits_state(state_r), %ecx - shll %cl, %eax - decl %eax - movl %eax, lmask(%esp) - - movl $1, %eax - movl distbits_state(state_r), %ecx - shll %cl, %eax - decl %eax - movl %eax, dmask(%esp) - - movl wsize_state(state_r), %eax - movl write_state(state_r), %ecx - movl window_state(state_r), %edx - - movl %eax, wsize(%esp) - movl %ecx, write(%esp) - movl %edx, window(%esp) - - movl hold_state(state_r), %ebp - movl bits_state(state_r), %ebx - -#undef strm_r -#undef state_r - -#define in_r %esi -#define from_r %esi -#define out_r %edi - - movl in(%esp), in_r - movl last(%esp), %ecx - cmpl in_r, %ecx - ja .L_align_long /* if in < last */ - - addl $11, %ecx /* ecx = &in[ avail_in ] */ - subl in_r, %ecx /* ecx = avail_in */ - movl $12, %eax - subl %ecx, %eax /* eax = 12 - avail_in */ - leal buf(%esp), %edi - rep movsb /* memcpy( buf, in, avail_in ) */ - movl %eax, %ecx - xorl %eax, %eax - rep stosb /* memset( &buf[ avail_in ], 0, 12 - avail_in ) */ - leal buf(%esp), in_r /* in = buf */ - movl in_r, last(%esp) /* last = in, do just one iteration */ - jmp .L_is_aligned - - /* align in_r on long boundary */ -.L_align_long: - testl $3, in_r - jz .L_is_aligned - xorl %eax, %eax - movb (in_r), %al - incl in_r - movl %ebx, %ecx - addl $8, %ebx - shll %cl, %eax - orl %eax, %ebp - jmp .L_align_long - -.L_is_aligned: - movl out(%esp), out_r - -#if defined( NO_MMX ) - jmp .L_do_loop -#endif - -#if defined( USE_MMX ) - jmp .L_init_mmx -#endif - -/*** Runtime MMX check ***/ - -#if defined( RUN_TIME_MMX ) -.L_check_mmx: - cmpl $DO_USE_MMX, inflate_fast_use_mmx - je .L_init_mmx - ja .L_do_loop /* > 2 */ - - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushf - movl (%esp), %eax /* copy eflags to eax */ - xorl $0x200000, (%esp) /* try toggling ID bit of eflags (bit 21) - * to see if cpu supports cpuid... - * ID bit method not supported by NexGen but - * bios may load a cpuid instruction and - * cpuid may be disabled on Cyrix 5-6x86 */ - popf - pushf - popl %edx /* copy new eflags to edx */ - xorl %eax, %edx /* test if ID bit is flipped */ - jz .L_dont_use_mmx /* not flipped if zero */ - xorl %eax, %eax - cpuid - cmpl $0x756e6547, %ebx /* check for GenuineIntel in ebx,ecx,edx */ - jne .L_dont_use_mmx - cmpl $0x6c65746e, %ecx - jne .L_dont_use_mmx - cmpl $0x49656e69, %edx - jne .L_dont_use_mmx - movl $1, %eax - cpuid /* get cpu features */ - shrl $8, %eax - andl $15, %eax - cmpl $6, %eax /* check for Pentium family, is 0xf for P4 */ - jne .L_dont_use_mmx - testl $0x800000, %edx /* test if MMX feature is set (bit 23) */ - jnz .L_use_mmx - jmp .L_dont_use_mmx -.L_use_mmx: - movl $DO_USE_MMX, inflate_fast_use_mmx - jmp .L_check_mmx_pop -.L_dont_use_mmx: - movl $DONT_USE_MMX, inflate_fast_use_mmx -.L_check_mmx_pop: - popl %edx - popl %ecx - popl %ebx - popl %eax - jmp .L_check_mmx -#endif - - -/*** Non-MMX code ***/ - -#if defined ( NO_MMX ) || defined( RUN_TIME_MMX ) - -#define hold_r %ebp -#define bits_r %bl -#define bitslong_r %ebx - -.align 32,0x90 -.L_while_test: - /* while (in < last && out < end) - */ - cmpl out_r, end(%esp) - jbe .L_break_loop /* if (out >= end) */ - - cmpl in_r, last(%esp) - jbe .L_break_loop - -.L_do_loop: - /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out - * - * do { - * if (bits < 15) { - * hold |= *((unsigned short *)in)++ << bits; - * bits += 16 - * } - * this = lcode[hold & lmask] - */ - cmpb $15, bits_r - ja .L_get_length_code /* if (15 < bits) */ - - xorl %eax, %eax - lodsw /* al = *(ushort *)in++ */ - movb bits_r, %cl /* cl = bits, needs it for shifting */ - addb $16, bits_r /* bits += 16 */ - shll %cl, %eax - orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ - -.L_get_length_code: - movl lmask(%esp), %edx /* edx = lmask */ - movl lcode(%esp), %ecx /* ecx = lcode */ - andl hold_r, %edx /* edx &= hold */ - movl (%ecx,%edx,4), %eax /* eax = lcode[hold & lmask] */ - -.L_dolen: - /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out - * - * dolen: - * bits -= this.bits; - * hold >>= this.bits - */ - movb %ah, %cl /* cl = this.bits */ - subb %ah, bits_r /* bits -= this.bits */ - shrl %cl, hold_r /* hold >>= this.bits */ - - /* check if op is a literal - * if (op == 0) { - * PUP(out) = this.val; - * } - */ - testb %al, %al - jnz .L_test_for_length_base /* if (op != 0) 45.7% */ - - shrl $16, %eax /* output this.val char */ - stosb - jmp .L_while_test - -.L_test_for_length_base: - /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = len - * - * else if (op & 16) { - * len = this.val - * op &= 15 - * if (op) { - * if (op > bits) { - * hold |= *((unsigned short *)in)++ << bits; - * bits += 16 - * } - * len += hold & mask[op]; - * bits -= op; - * hold >>= op; - * } - */ -#define len_r %edx - movl %eax, len_r /* len = this */ - shrl $16, len_r /* len = this.val */ - movb %al, %cl - - testb $16, %al - jz .L_test_for_second_level_length /* if ((op & 16) == 0) 8% */ - andb $15, %cl /* op &= 15 */ - jz .L_save_len /* if (!op) */ - cmpb %cl, bits_r - jae .L_add_bits_to_len /* if (op <= bits) */ - - movb %cl, %ch /* stash op in ch, freeing cl */ - xorl %eax, %eax - lodsw /* al = *(ushort *)in++ */ - movb bits_r, %cl /* cl = bits, needs it for shifting */ - addb $16, bits_r /* bits += 16 */ - shll %cl, %eax - orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ - movb %ch, %cl /* move op back to ecx */ - -.L_add_bits_to_len: - movl $1, %eax - shll %cl, %eax - decl %eax - subb %cl, bits_r - andl hold_r, %eax /* eax &= hold */ - shrl %cl, hold_r - addl %eax, len_r /* len += hold & mask[op] */ - -.L_save_len: - movl len_r, len(%esp) /* save len */ -#undef len_r - -.L_decode_distance: - /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = dist - * - * if (bits < 15) { - * hold |= *((unsigned short *)in)++ << bits; - * bits += 16 - * } - * this = dcode[hold & dmask]; - * dodist: - * bits -= this.bits; - * hold >>= this.bits; - * op = this.op; - */ - - cmpb $15, bits_r - ja .L_get_distance_code /* if (15 < bits) */ - - xorl %eax, %eax - lodsw /* al = *(ushort *)in++ */ - movb bits_r, %cl /* cl = bits, needs it for shifting */ - addb $16, bits_r /* bits += 16 */ - shll %cl, %eax - orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ - -.L_get_distance_code: - movl dmask(%esp), %edx /* edx = dmask */ - movl dcode(%esp), %ecx /* ecx = dcode */ - andl hold_r, %edx /* edx &= hold */ - movl (%ecx,%edx,4), %eax /* eax = dcode[hold & dmask] */ - -#define dist_r %edx -.L_dodist: - movl %eax, dist_r /* dist = this */ - shrl $16, dist_r /* dist = this.val */ - movb %ah, %cl - subb %ah, bits_r /* bits -= this.bits */ - shrl %cl, hold_r /* hold >>= this.bits */ - - /* if (op & 16) { - * dist = this.val - * op &= 15 - * if (op > bits) { - * hold |= *((unsigned short *)in)++ << bits; - * bits += 16 - * } - * dist += hold & mask[op]; - * bits -= op; - * hold >>= op; - */ - movb %al, %cl /* cl = this.op */ - - testb $16, %al /* if ((op & 16) == 0) */ - jz .L_test_for_second_level_dist - andb $15, %cl /* op &= 15 */ - jz .L_check_dist_one - cmpb %cl, bits_r - jae .L_add_bits_to_dist /* if (op <= bits) 97.6% */ - - movb %cl, %ch /* stash op in ch, freeing cl */ - xorl %eax, %eax - lodsw /* al = *(ushort *)in++ */ - movb bits_r, %cl /* cl = bits, needs it for shifting */ - addb $16, bits_r /* bits += 16 */ - shll %cl, %eax - orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ - movb %ch, %cl /* move op back to ecx */ - -.L_add_bits_to_dist: - movl $1, %eax - shll %cl, %eax - decl %eax /* (1 << op) - 1 */ - subb %cl, bits_r - andl hold_r, %eax /* eax &= hold */ - shrl %cl, hold_r - addl %eax, dist_r /* dist += hold & ((1 << op) - 1) */ - jmp .L_check_window - -.L_check_window: - /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist - * %ecx = nbytes - * - * nbytes = out - beg; - * if (dist <= nbytes) { - * from = out - dist; - * do { - * PUP(out) = PUP(from); - * } while (--len > 0) { - * } - */ - - movl in_r, in(%esp) /* save in so from can use it's reg */ - movl out_r, %eax - subl beg(%esp), %eax /* nbytes = out - beg */ - - cmpl dist_r, %eax - jb .L_clip_window /* if (dist > nbytes) 4.2% */ - - movl len(%esp), %ecx - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - - subl $3, %ecx - movb (from_r), %al - movb %al, (out_r) - movb 1(from_r), %al - movb 2(from_r), %dl - addl $3, from_r - movb %al, 1(out_r) - movb %dl, 2(out_r) - addl $3, out_r - rep movsb - - movl in(%esp), in_r /* move in back to %esi, toss from */ - jmp .L_while_test - -.align 16,0x90 -.L_check_dist_one: - cmpl $1, dist_r - jne .L_check_window - cmpl out_r, beg(%esp) - je .L_check_window - - decl out_r - movl len(%esp), %ecx - movb (out_r), %al - subl $3, %ecx - - movb %al, 1(out_r) - movb %al, 2(out_r) - movb %al, 3(out_r) - addl $4, out_r - rep stosb - - jmp .L_while_test - -.align 16,0x90 -.L_test_for_second_level_length: - /* else if ((op & 64) == 0) { - * this = lcode[this.val + (hold & mask[op])]; - * } - */ - testb $64, %al - jnz .L_test_for_end_of_block /* if ((op & 64) != 0) */ - - movl $1, %eax - shll %cl, %eax - decl %eax - andl hold_r, %eax /* eax &= hold */ - addl %edx, %eax /* eax += this.val */ - movl lcode(%esp), %edx /* edx = lcode */ - movl (%edx,%eax,4), %eax /* eax = lcode[val + (hold&mask[op])] */ - jmp .L_dolen - -.align 16,0x90 -.L_test_for_second_level_dist: - /* else if ((op & 64) == 0) { - * this = dcode[this.val + (hold & mask[op])]; - * } - */ - testb $64, %al - jnz .L_invalid_distance_code /* if ((op & 64) != 0) */ - - movl $1, %eax - shll %cl, %eax - decl %eax - andl hold_r, %eax /* eax &= hold */ - addl %edx, %eax /* eax += this.val */ - movl dcode(%esp), %edx /* edx = dcode */ - movl (%edx,%eax,4), %eax /* eax = dcode[val + (hold&mask[op])] */ - jmp .L_dodist - -.align 16,0x90 -.L_clip_window: - /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist - * %ecx = nbytes - * - * else { - * if (dist > wsize) { - * invalid distance - * } - * from = window; - * nbytes = dist - nbytes; - * if (write == 0) { - * from += wsize - nbytes; - */ -#define nbytes_r %ecx - movl %eax, nbytes_r - movl wsize(%esp), %eax /* prepare for dist compare */ - negl nbytes_r /* nbytes = -nbytes */ - movl window(%esp), from_r /* from = window */ - - cmpl dist_r, %eax - jb .L_invalid_distance_too_far /* if (dist > wsize) */ - - addl dist_r, nbytes_r /* nbytes = dist - nbytes */ - cmpl $0, write(%esp) - jne .L_wrap_around_window /* if (write != 0) */ - - subl nbytes_r, %eax - addl %eax, from_r /* from += wsize - nbytes */ - - /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist - * %ecx = nbytes, %eax = len - * - * if (nbytes < len) { - * len -= nbytes; - * do { - * PUP(out) = PUP(from); - * } while (--nbytes); - * from = out - dist; - * } - * } - */ -#define len_r %eax - movl len(%esp), len_r - cmpl nbytes_r, len_r - jbe .L_do_copy1 /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - jmp .L_do_copy1 - - cmpl nbytes_r, len_r - jbe .L_do_copy1 /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - jmp .L_do_copy1 - -.L_wrap_around_window: - /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist - * %ecx = nbytes, %eax = write, %eax = len - * - * else if (write < nbytes) { - * from += wsize + write - nbytes; - * nbytes -= write; - * if (nbytes < len) { - * len -= nbytes; - * do { - * PUP(out) = PUP(from); - * } while (--nbytes); - * from = window; - * nbytes = write; - * if (nbytes < len) { - * len -= nbytes; - * do { - * PUP(out) = PUP(from); - * } while(--nbytes); - * from = out - dist; - * } - * } - * } - */ -#define write_r %eax - movl write(%esp), write_r - cmpl write_r, nbytes_r - jbe .L_contiguous_in_window /* if (write >= nbytes) */ - - addl wsize(%esp), from_r - addl write_r, from_r - subl nbytes_r, from_r /* from += wsize + write - nbytes */ - subl write_r, nbytes_r /* nbytes -= write */ -#undef write_r - - movl len(%esp), len_r - cmpl nbytes_r, len_r - jbe .L_do_copy1 /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl window(%esp), from_r /* from = window */ - movl write(%esp), nbytes_r /* nbytes = write */ - cmpl nbytes_r, len_r - jbe .L_do_copy1 /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - jmp .L_do_copy1 - -.L_contiguous_in_window: - /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist - * %ecx = nbytes, %eax = write, %eax = len - * - * else { - * from += write - nbytes; - * if (nbytes < len) { - * len -= nbytes; - * do { - * PUP(out) = PUP(from); - * } while (--nbytes); - * from = out - dist; - * } - * } - */ -#define write_r %eax - addl write_r, from_r - subl nbytes_r, from_r /* from += write - nbytes */ -#undef write_r - - movl len(%esp), len_r - cmpl nbytes_r, len_r - jbe .L_do_copy1 /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - -.L_do_copy1: - /* regs: %esi = from, %esi = in, %ebp = hold, %bl = bits, %edi = out - * %eax = len - * - * while (len > 0) { - * PUP(out) = PUP(from); - * len--; - * } - * } - * } while (in < last && out < end); - */ -#undef nbytes_r -#define in_r %esi - movl len_r, %ecx - rep movsb - - movl in(%esp), in_r /* move in back to %esi, toss from */ - jmp .L_while_test - -#undef len_r -#undef dist_r - -#endif /* NO_MMX || RUN_TIME_MMX */ - - -/*** MMX code ***/ - -#if defined( USE_MMX ) || defined( RUN_TIME_MMX ) - -.align 32,0x90 -.L_init_mmx: - emms - -#undef bits_r -#undef bitslong_r -#define bitslong_r %ebp -#define hold_mm %mm0 - movd %ebp, hold_mm - movl %ebx, bitslong_r - -#define used_mm %mm1 -#define dmask2_mm %mm2 -#define lmask2_mm %mm3 -#define lmask_mm %mm4 -#define dmask_mm %mm5 -#define tmp_mm %mm6 - - movd lmask(%esp), lmask_mm - movq lmask_mm, lmask2_mm - movd dmask(%esp), dmask_mm - movq dmask_mm, dmask2_mm - pxor used_mm, used_mm - movl lcode(%esp), %ebx /* ebx = lcode */ - jmp .L_do_loop_mmx - -.align 32,0x90 -.L_while_test_mmx: - /* while (in < last && out < end) - */ - cmpl out_r, end(%esp) - jbe .L_break_loop /* if (out >= end) */ - - cmpl in_r, last(%esp) - jbe .L_break_loop - -.L_do_loop_mmx: - psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ - - cmpl $32, bitslong_r - ja .L_get_length_code_mmx /* if (32 < bits) */ - - movd bitslong_r, tmp_mm - movd (in_r), %mm7 - addl $4, in_r - psllq tmp_mm, %mm7 - addl $32, bitslong_r - por %mm7, hold_mm /* hold_mm |= *((uint *)in)++ << bits */ - -.L_get_length_code_mmx: - pand hold_mm, lmask_mm - movd lmask_mm, %eax - movq lmask2_mm, lmask_mm - movl (%ebx,%eax,4), %eax /* eax = lcode[hold & lmask] */ - -.L_dolen_mmx: - movzbl %ah, %ecx /* ecx = this.bits */ - movd %ecx, used_mm - subl %ecx, bitslong_r /* bits -= this.bits */ - - testb %al, %al - jnz .L_test_for_length_base_mmx /* if (op != 0) 45.7% */ - - shrl $16, %eax /* output this.val char */ - stosb - jmp .L_while_test_mmx - -.L_test_for_length_base_mmx: -#define len_r %edx - movl %eax, len_r /* len = this */ - shrl $16, len_r /* len = this.val */ - - testb $16, %al - jz .L_test_for_second_level_length_mmx /* if ((op & 16) == 0) 8% */ - andl $15, %eax /* op &= 15 */ - jz .L_decode_distance_mmx /* if (!op) */ - - psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ - movd %eax, used_mm - movd hold_mm, %ecx - subl %eax, bitslong_r - andl .L_mask(,%eax,4), %ecx - addl %ecx, len_r /* len += hold & mask[op] */ - -.L_decode_distance_mmx: - psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ - - cmpl $32, bitslong_r - ja .L_get_dist_code_mmx /* if (32 < bits) */ - - movd bitslong_r, tmp_mm - movd (in_r), %mm7 - addl $4, in_r - psllq tmp_mm, %mm7 - addl $32, bitslong_r - por %mm7, hold_mm /* hold_mm |= *((uint *)in)++ << bits */ - -.L_get_dist_code_mmx: - movl dcode(%esp), %ebx /* ebx = dcode */ - pand hold_mm, dmask_mm - movd dmask_mm, %eax - movq dmask2_mm, dmask_mm - movl (%ebx,%eax,4), %eax /* eax = dcode[hold & lmask] */ - -.L_dodist_mmx: -#define dist_r %ebx - movzbl %ah, %ecx /* ecx = this.bits */ - movl %eax, dist_r - shrl $16, dist_r /* dist = this.val */ - subl %ecx, bitslong_r /* bits -= this.bits */ - movd %ecx, used_mm - - testb $16, %al /* if ((op & 16) == 0) */ - jz .L_test_for_second_level_dist_mmx - andl $15, %eax /* op &= 15 */ - jz .L_check_dist_one_mmx - -.L_add_bits_to_dist_mmx: - psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ - movd %eax, used_mm /* save bit length of current op */ - movd hold_mm, %ecx /* get the next bits on input stream */ - subl %eax, bitslong_r /* bits -= op bits */ - andl .L_mask(,%eax,4), %ecx /* ecx = hold & mask[op] */ - addl %ecx, dist_r /* dist += hold & mask[op] */ - -.L_check_window_mmx: - movl in_r, in(%esp) /* save in so from can use it's reg */ - movl out_r, %eax - subl beg(%esp), %eax /* nbytes = out - beg */ - - cmpl dist_r, %eax - jb .L_clip_window_mmx /* if (dist > nbytes) 4.2% */ - - movl len_r, %ecx - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - - subl $3, %ecx - movb (from_r), %al - movb %al, (out_r) - movb 1(from_r), %al - movb 2(from_r), %dl - addl $3, from_r - movb %al, 1(out_r) - movb %dl, 2(out_r) - addl $3, out_r - rep movsb - - movl in(%esp), in_r /* move in back to %esi, toss from */ - movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ - jmp .L_while_test_mmx - -.align 16,0x90 -.L_check_dist_one_mmx: - cmpl $1, dist_r - jne .L_check_window_mmx - cmpl out_r, beg(%esp) - je .L_check_window_mmx - - decl out_r - movl len_r, %ecx - movb (out_r), %al - subl $3, %ecx - - movb %al, 1(out_r) - movb %al, 2(out_r) - movb %al, 3(out_r) - addl $4, out_r - rep stosb - - movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ - jmp .L_while_test_mmx - -.align 16,0x90 -.L_test_for_second_level_length_mmx: - testb $64, %al - jnz .L_test_for_end_of_block /* if ((op & 64) != 0) */ - - andl $15, %eax - psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ - movd hold_mm, %ecx - andl .L_mask(,%eax,4), %ecx - addl len_r, %ecx - movl (%ebx,%ecx,4), %eax /* eax = lcode[hold & lmask] */ - jmp .L_dolen_mmx - -.align 16,0x90 -.L_test_for_second_level_dist_mmx: - testb $64, %al - jnz .L_invalid_distance_code /* if ((op & 64) != 0) */ - - andl $15, %eax - psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ - movd hold_mm, %ecx - andl .L_mask(,%eax,4), %ecx - movl dcode(%esp), %eax /* ecx = dcode */ - addl dist_r, %ecx - movl (%eax,%ecx,4), %eax /* eax = lcode[hold & lmask] */ - jmp .L_dodist_mmx - -.align 16,0x90 -.L_clip_window_mmx: -#define nbytes_r %ecx - movl %eax, nbytes_r - movl wsize(%esp), %eax /* prepare for dist compare */ - negl nbytes_r /* nbytes = -nbytes */ - movl window(%esp), from_r /* from = window */ - - cmpl dist_r, %eax - jb .L_invalid_distance_too_far /* if (dist > wsize) */ - - addl dist_r, nbytes_r /* nbytes = dist - nbytes */ - cmpl $0, write(%esp) - jne .L_wrap_around_window_mmx /* if (write != 0) */ - - subl nbytes_r, %eax - addl %eax, from_r /* from += wsize - nbytes */ - - cmpl nbytes_r, len_r - jbe .L_do_copy1_mmx /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - jmp .L_do_copy1_mmx - - cmpl nbytes_r, len_r - jbe .L_do_copy1_mmx /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - jmp .L_do_copy1_mmx - -.L_wrap_around_window_mmx: -#define write_r %eax - movl write(%esp), write_r - cmpl write_r, nbytes_r - jbe .L_contiguous_in_window_mmx /* if (write >= nbytes) */ - - addl wsize(%esp), from_r - addl write_r, from_r - subl nbytes_r, from_r /* from += wsize + write - nbytes */ - subl write_r, nbytes_r /* nbytes -= write */ -#undef write_r - - cmpl nbytes_r, len_r - jbe .L_do_copy1_mmx /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl window(%esp), from_r /* from = window */ - movl write(%esp), nbytes_r /* nbytes = write */ - cmpl nbytes_r, len_r - jbe .L_do_copy1_mmx /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - jmp .L_do_copy1_mmx - -.L_contiguous_in_window_mmx: -#define write_r %eax - addl write_r, from_r - subl nbytes_r, from_r /* from += write - nbytes */ -#undef write_r - - cmpl nbytes_r, len_r - jbe .L_do_copy1_mmx /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - -.L_do_copy1_mmx: -#undef nbytes_r -#define in_r %esi - movl len_r, %ecx - rep movsb - - movl in(%esp), in_r /* move in back to %esi, toss from */ - movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ - jmp .L_while_test_mmx - -#undef hold_r -#undef bitslong_r - -#endif /* USE_MMX || RUN_TIME_MMX */ - - -/*** USE_MMX, NO_MMX, and RUNTIME_MMX from here on ***/ - -.L_invalid_distance_code: - /* else { - * strm->msg = "invalid distance code"; - * state->mode = BAD; - * } - */ - movl $.L_invalid_distance_code_msg, %ecx - movl $INFLATE_MODE_BAD, %edx - jmp .L_update_stream_state - -.L_test_for_end_of_block: - /* else if (op & 32) { - * state->mode = TYPE; - * break; - * } - */ - testb $32, %al - jz .L_invalid_literal_length_code /* if ((op & 32) == 0) */ - - movl $0, %ecx - movl $INFLATE_MODE_TYPE, %edx - jmp .L_update_stream_state - -.L_invalid_literal_length_code: - /* else { - * strm->msg = "invalid literal/length code"; - * state->mode = BAD; - * } - */ - movl $.L_invalid_literal_length_code_msg, %ecx - movl $INFLATE_MODE_BAD, %edx - jmp .L_update_stream_state - -.L_invalid_distance_too_far: - /* strm->msg = "invalid distance too far back"; - * state->mode = BAD; - */ - movl in(%esp), in_r /* from_r has in's reg, put in back */ - movl $.L_invalid_distance_too_far_msg, %ecx - movl $INFLATE_MODE_BAD, %edx - jmp .L_update_stream_state - -.L_update_stream_state: - /* set strm->msg = %ecx, strm->state->mode = %edx */ - movl strm_sp(%esp), %eax - testl %ecx, %ecx /* if (msg != NULL) */ - jz .L_skip_msg - movl %ecx, msg_strm(%eax) /* strm->msg = msg */ -.L_skip_msg: - movl state_strm(%eax), %eax /* state = strm->state */ - movl %edx, mode_state(%eax) /* state->mode = edx (BAD | TYPE) */ - jmp .L_break_loop - -.align 32,0x90 -.L_break_loop: - -/* - * Regs: - * - * bits = %ebp when mmx, and in %ebx when non-mmx - * hold = %hold_mm when mmx, and in %ebp when non-mmx - * in = %esi - * out = %edi - */ - -#if defined( USE_MMX ) || defined( RUN_TIME_MMX ) - -#if defined( RUN_TIME_MMX ) - - cmpl $DO_USE_MMX, inflate_fast_use_mmx - jne .L_update_next_in - -#endif /* RUN_TIME_MMX */ - - movl %ebp, %ebx - -.L_update_next_in: - -#endif - -#define strm_r %eax -#define state_r %edx - - /* len = bits >> 3; - * in -= len; - * bits -= len << 3; - * hold &= (1U << bits) - 1; - * state->hold = hold; - * state->bits = bits; - * strm->next_in = in; - * strm->next_out = out; - */ - movl strm_sp(%esp), strm_r - movl %ebx, %ecx - movl state_strm(strm_r), state_r - shrl $3, %ecx - subl %ecx, in_r - shll $3, %ecx - subl %ecx, %ebx - movl out_r, next_out_strm(strm_r) - movl %ebx, bits_state(state_r) - movl %ebx, %ecx - - leal buf(%esp), %ebx - cmpl %ebx, last(%esp) - jne .L_buf_not_used /* if buf != last */ - - subl %ebx, in_r /* in -= buf */ - movl next_in_strm(strm_r), %ebx - movl %ebx, last(%esp) /* last = strm->next_in */ - addl %ebx, in_r /* in += strm->next_in */ - movl avail_in_strm(strm_r), %ebx - subl $11, %ebx - addl %ebx, last(%esp) /* last = &strm->next_in[ avail_in - 11 ] */ - -.L_buf_not_used: - movl in_r, next_in_strm(strm_r) - - movl $1, %ebx - shll %cl, %ebx - decl %ebx - -#if defined( USE_MMX ) || defined( RUN_TIME_MMX ) - -#if defined( RUN_TIME_MMX ) - - cmpl $DO_USE_MMX, inflate_fast_use_mmx - jne .L_update_hold - -#endif /* RUN_TIME_MMX */ - - psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ - movd hold_mm, %ebp - - emms - -.L_update_hold: - -#endif /* USE_MMX || RUN_TIME_MMX */ - - andl %ebx, %ebp - movl %ebp, hold_state(state_r) - -#define last_r %ebx - - /* strm->avail_in = in < last ? 11 + (last - in) : 11 - (in - last) */ - movl last(%esp), last_r - cmpl in_r, last_r - jbe .L_last_is_smaller /* if (in >= last) */ - - subl in_r, last_r /* last -= in */ - addl $11, last_r /* last += 11 */ - movl last_r, avail_in_strm(strm_r) - jmp .L_fixup_out -.L_last_is_smaller: - subl last_r, in_r /* in -= last */ - negl in_r /* in = -in */ - addl $11, in_r /* in += 11 */ - movl in_r, avail_in_strm(strm_r) - -#undef last_r -#define end_r %ebx - -.L_fixup_out: - /* strm->avail_out = out < end ? 257 + (end - out) : 257 - (out - end)*/ - movl end(%esp), end_r - cmpl out_r, end_r - jbe .L_end_is_smaller /* if (out >= end) */ - - subl out_r, end_r /* end -= out */ - addl $257, end_r /* end += 257 */ - movl end_r, avail_out_strm(strm_r) - jmp .L_done -.L_end_is_smaller: - subl end_r, out_r /* out -= end */ - negl out_r /* out = -out */ - addl $257, out_r /* out += 257 */ - movl out_r, avail_out_strm(strm_r) - -#undef end_r -#undef strm_r -#undef state_r - -.L_done: - addl $local_var_size, %esp - popf - popl %ebx - popl %ebp - popl %esi - popl %edi - ret - -#if defined( GAS_ELF ) -/* elf info */ -.type inflate_fast,@function -.size inflate_fast,.-inflate_fast -#endif diff --git a/deps/zlib/contrib/iostream/test.cpp b/deps/zlib/contrib/iostream/test.cpp deleted file mode 100644 index 7d265b3b5c0e01..00000000000000 --- a/deps/zlib/contrib/iostream/test.cpp +++ /dev/null @@ -1,24 +0,0 @@ - -#include "zfstream.h" - -int main() { - - // Construct a stream object with this filebuffer. Anything sent - // to this stream will go to standard out. - gzofstream os( 1, ios::out ); - - // This text is getting compressed and sent to stdout. - // To prove this, run 'test | zcat'. - os << "Hello, Mommy" << endl; - - os << setcompressionlevel( Z_NO_COMPRESSION ); - os << "hello, hello, hi, ho!" << endl; - - setcompressionlevel( os, Z_DEFAULT_COMPRESSION ) - << "I'm compressing again" << endl; - - os.close(); - - return 0; - -} diff --git a/deps/zlib/contrib/iostream/zfstream.cpp b/deps/zlib/contrib/iostream/zfstream.cpp deleted file mode 100644 index d0cd85faaf5b22..00000000000000 --- a/deps/zlib/contrib/iostream/zfstream.cpp +++ /dev/null @@ -1,329 +0,0 @@ - -#include "zfstream.h" - -gzfilebuf::gzfilebuf() : - file(NULL), - mode(0), - own_file_descriptor(0) -{ } - -gzfilebuf::~gzfilebuf() { - - sync(); - if ( own_file_descriptor ) - close(); - -} - -gzfilebuf *gzfilebuf::open( const char *name, - int io_mode ) { - - if ( is_open() ) - return NULL; - - char char_mode[10]; - char *p = char_mode; - - if ( io_mode & ios::in ) { - mode = ios::in; - *p++ = 'r'; - } else if ( io_mode & ios::app ) { - mode = ios::app; - *p++ = 'a'; - } else { - mode = ios::out; - *p++ = 'w'; - } - - if ( io_mode & ios::binary ) { - mode |= ios::binary; - *p++ = 'b'; - } - - // Hard code the compression level - if ( io_mode & (ios::out|ios::app )) { - *p++ = '9'; - } - - // Put the end-of-string indicator - *p = '\0'; - - if ( (file = gzopen(name, char_mode)) == NULL ) - return NULL; - - own_file_descriptor = 1; - - return this; - -} - -gzfilebuf *gzfilebuf::attach( int file_descriptor, - int io_mode ) { - - if ( is_open() ) - return NULL; - - char char_mode[10]; - char *p = char_mode; - - if ( io_mode & ios::in ) { - mode = ios::in; - *p++ = 'r'; - } else if ( io_mode & ios::app ) { - mode = ios::app; - *p++ = 'a'; - } else { - mode = ios::out; - *p++ = 'w'; - } - - if ( io_mode & ios::binary ) { - mode |= ios::binary; - *p++ = 'b'; - } - - // Hard code the compression level - if ( io_mode & (ios::out|ios::app )) { - *p++ = '9'; - } - - // Put the end-of-string indicator - *p = '\0'; - - if ( (file = gzdopen(file_descriptor, char_mode)) == NULL ) - return NULL; - - own_file_descriptor = 0; - - return this; - -} - -gzfilebuf *gzfilebuf::close() { - - if ( is_open() ) { - - sync(); - gzclose( file ); - file = NULL; - - } - - return this; - -} - -int gzfilebuf::setcompressionlevel( int comp_level ) { - - return gzsetparams(file, comp_level, -2); - -} - -int gzfilebuf::setcompressionstrategy( int comp_strategy ) { - - return gzsetparams(file, -2, comp_strategy); - -} - - -streampos gzfilebuf::seekoff( streamoff off, ios::seek_dir dir, int which ) { - - return streampos(EOF); - -} - -int gzfilebuf::underflow() { - - // If the file hasn't been opened for reading, error. - if ( !is_open() || !(mode & ios::in) ) - return EOF; - - // if a buffer doesn't exists, allocate one. - if ( !base() ) { - - if ( (allocate()) == EOF ) - return EOF; - setp(0,0); - - } else { - - if ( in_avail() ) - return (unsigned char) *gptr(); - - if ( out_waiting() ) { - if ( flushbuf() == EOF ) - return EOF; - } - - } - - // Attempt to fill the buffer. - - int result = fillbuf(); - if ( result == EOF ) { - // disable get area - setg(0,0,0); - return EOF; - } - - return (unsigned char) *gptr(); - -} - -int gzfilebuf::overflow( int c ) { - - if ( !is_open() || !(mode & ios::out) ) - return EOF; - - if ( !base() ) { - if ( allocate() == EOF ) - return EOF; - setg(0,0,0); - } else { - if (in_avail()) { - return EOF; - } - if (out_waiting()) { - if (flushbuf() == EOF) - return EOF; - } - } - - int bl = blen(); - setp( base(), base() + bl); - - if ( c != EOF ) { - - *pptr() = c; - pbump(1); - - } - - return 0; - -} - -int gzfilebuf::sync() { - - if ( !is_open() ) - return EOF; - - if ( out_waiting() ) - return flushbuf(); - - return 0; - -} - -int gzfilebuf::flushbuf() { - - int n; - char *q; - - q = pbase(); - n = pptr() - q; - - if ( gzwrite( file, q, n) < n ) - return EOF; - - setp(0,0); - - return 0; - -} - -int gzfilebuf::fillbuf() { - - int required; - char *p; - - p = base(); - - required = blen(); - - int t = gzread( file, p, required ); - - if ( t <= 0) return EOF; - - setg( base(), base(), base()+t); - - return t; - -} - -gzfilestream_common::gzfilestream_common() : - ios( gzfilestream_common::rdbuf() ) -{ } - -gzfilestream_common::~gzfilestream_common() -{ } - -void gzfilestream_common::attach( int fd, int io_mode ) { - - if ( !buffer.attach( fd, io_mode) ) - clear( ios::failbit | ios::badbit ); - else - clear(); - -} - -void gzfilestream_common::open( const char *name, int io_mode ) { - - if ( !buffer.open( name, io_mode ) ) - clear( ios::failbit | ios::badbit ); - else - clear(); - -} - -void gzfilestream_common::close() { - - if ( !buffer.close() ) - clear( ios::failbit | ios::badbit ); - -} - -gzfilebuf *gzfilestream_common::rdbuf() -{ - return &buffer; -} - -gzifstream::gzifstream() : - ios( gzfilestream_common::rdbuf() ) -{ - clear( ios::badbit ); -} - -gzifstream::gzifstream( const char *name, int io_mode ) : - ios( gzfilestream_common::rdbuf() ) -{ - gzfilestream_common::open( name, io_mode ); -} - -gzifstream::gzifstream( int fd, int io_mode ) : - ios( gzfilestream_common::rdbuf() ) -{ - gzfilestream_common::attach( fd, io_mode ); -} - -gzifstream::~gzifstream() { } - -gzofstream::gzofstream() : - ios( gzfilestream_common::rdbuf() ) -{ - clear( ios::badbit ); -} - -gzofstream::gzofstream( const char *name, int io_mode ) : - ios( gzfilestream_common::rdbuf() ) -{ - gzfilestream_common::open( name, io_mode ); -} - -gzofstream::gzofstream( int fd, int io_mode ) : - ios( gzfilestream_common::rdbuf() ) -{ - gzfilestream_common::attach( fd, io_mode ); -} - -gzofstream::~gzofstream() { } diff --git a/deps/zlib/contrib/iostream/zfstream.h b/deps/zlib/contrib/iostream/zfstream.h deleted file mode 100644 index ed79098a3adaf5..00000000000000 --- a/deps/zlib/contrib/iostream/zfstream.h +++ /dev/null @@ -1,128 +0,0 @@ - -#ifndef zfstream_h -#define zfstream_h - -#include -#include "zlib.h" - -class gzfilebuf : public streambuf { - -public: - - gzfilebuf( ); - virtual ~gzfilebuf(); - - gzfilebuf *open( const char *name, int io_mode ); - gzfilebuf *attach( int file_descriptor, int io_mode ); - gzfilebuf *close(); - - int setcompressionlevel( int comp_level ); - int setcompressionstrategy( int comp_strategy ); - - inline int is_open() const { return (file !=NULL); } - - virtual streampos seekoff( streamoff, ios::seek_dir, int ); - - virtual int sync(); - -protected: - - virtual int underflow(); - virtual int overflow( int = EOF ); - -private: - - gzFile file; - short mode; - short own_file_descriptor; - - int flushbuf(); - int fillbuf(); - -}; - -class gzfilestream_common : virtual public ios { - - friend class gzifstream; - friend class gzofstream; - friend gzofstream &setcompressionlevel( gzofstream &, int ); - friend gzofstream &setcompressionstrategy( gzofstream &, int ); - -public: - virtual ~gzfilestream_common(); - - void attach( int fd, int io_mode ); - void open( const char *name, int io_mode ); - void close(); - -protected: - gzfilestream_common(); - -private: - gzfilebuf *rdbuf(); - - gzfilebuf buffer; - -}; - -class gzifstream : public gzfilestream_common, public istream { - -public: - - gzifstream(); - gzifstream( const char *name, int io_mode = ios::in ); - gzifstream( int fd, int io_mode = ios::in ); - - virtual ~gzifstream(); - -}; - -class gzofstream : public gzfilestream_common, public ostream { - -public: - - gzofstream(); - gzofstream( const char *name, int io_mode = ios::out ); - gzofstream( int fd, int io_mode = ios::out ); - - virtual ~gzofstream(); - -}; - -template class gzomanip { - friend gzofstream &operator<<(gzofstream &, const gzomanip &); -public: - gzomanip(gzofstream &(*f)(gzofstream &, T), T v) : func(f), val(v) { } -private: - gzofstream &(*func)(gzofstream &, T); - T val; -}; - -template gzofstream &operator<<(gzofstream &s, const gzomanip &m) -{ - return (*m.func)(s, m.val); -} - -inline gzofstream &setcompressionlevel( gzofstream &s, int l ) -{ - (s.rdbuf())->setcompressionlevel(l); - return s; -} - -inline gzofstream &setcompressionstrategy( gzofstream &s, int l ) -{ - (s.rdbuf())->setcompressionstrategy(l); - return s; -} - -inline gzomanip setcompressionlevel(int l) -{ - return gzomanip(&setcompressionlevel,l); -} - -inline gzomanip setcompressionstrategy(int l) -{ - return gzomanip(&setcompressionstrategy,l); -} - -#endif diff --git a/deps/zlib/contrib/iostream2/zstream.h b/deps/zlib/contrib/iostream2/zstream.h deleted file mode 100644 index 43d2332b79b70b..00000000000000 --- a/deps/zlib/contrib/iostream2/zstream.h +++ /dev/null @@ -1,307 +0,0 @@ -/* - * - * Copyright (c) 1997 - * Christian Michelsen Research AS - * Advanced Computing - * Fantoftvegen 38, 5036 BERGEN, Norway - * http://www.cmr.no - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Christian Michelsen Research AS makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - */ - -#ifndef ZSTREAM__H -#define ZSTREAM__H - -/* - * zstream.h - C++ interface to the 'zlib' general purpose compression library - * $Id: zstream.h 1.1 1997-06-25 12:00:56+02 tyge Exp tyge $ - */ - -#include -#include -#include -#include "zlib.h" - -#if defined(_WIN32) -# include -# include -# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -#else -# define SET_BINARY_MODE(file) -#endif - -class zstringlen { -public: - zstringlen(class izstream&); - zstringlen(class ozstream&, const char*); - size_t value() const { return val.word; } -private: - struct Val { unsigned char byte; size_t word; } val; -}; - -// ----------------------------- izstream ----------------------------- - -class izstream -{ - public: - izstream() : m_fp(0) {} - izstream(FILE* fp) : m_fp(0) { open(fp); } - izstream(const char* name) : m_fp(0) { open(name); } - ~izstream() { close(); } - - /* Opens a gzip (.gz) file for reading. - * open() can be used to read a file which is not in gzip format; - * in this case read() will directly read from the file without - * decompression. errno can be checked to distinguish two error - * cases (if errno is zero, the zlib error is Z_MEM_ERROR). - */ - void open(const char* name) { - if (m_fp) close(); - m_fp = ::gzopen(name, "rb"); - } - - void open(FILE* fp) { - SET_BINARY_MODE(fp); - if (m_fp) close(); - m_fp = ::gzdopen(fileno(fp), "rb"); - } - - /* Flushes all pending input if necessary, closes the compressed file - * and deallocates all the (de)compression state. The return value is - * the zlib error number (see function error() below). - */ - int close() { - int r = ::gzclose(m_fp); - m_fp = 0; return r; - } - - /* Binary read the given number of bytes from the compressed file. - */ - int read(void* buf, size_t len) { - return ::gzread(m_fp, buf, len); - } - - /* Returns the error message for the last error which occurred on the - * given compressed file. errnum is set to zlib error number. If an - * error occurred in the file system and not in the compression library, - * errnum is set to Z_ERRNO and the application may consult errno - * to get the exact error code. - */ - const char* error(int* errnum) { - return ::gzerror(m_fp, errnum); - } - - gzFile fp() { return m_fp; } - - private: - gzFile m_fp; -}; - -/* - * Binary read the given (array of) object(s) from the compressed file. - * If the input file was not in gzip format, read() copies the objects number - * of bytes into the buffer. - * returns the number of uncompressed bytes actually read - * (0 for end of file, -1 for error). - */ -template -inline int read(izstream& zs, T* x, Items items) { - return ::gzread(zs.fp(), x, items*sizeof(T)); -} - -/* - * Binary input with the '>' operator. - */ -template -inline izstream& operator>(izstream& zs, T& x) { - ::gzread(zs.fp(), &x, sizeof(T)); - return zs; -} - - -inline zstringlen::zstringlen(izstream& zs) { - zs > val.byte; - if (val.byte == 255) zs > val.word; - else val.word = val.byte; -} - -/* - * Read length of string + the string with the '>' operator. - */ -inline izstream& operator>(izstream& zs, char* x) { - zstringlen len(zs); - ::gzread(zs.fp(), x, len.value()); - x[len.value()] = '\0'; - return zs; -} - -inline char* read_string(izstream& zs) { - zstringlen len(zs); - char* x = new char[len.value()+1]; - ::gzread(zs.fp(), x, len.value()); - x[len.value()] = '\0'; - return x; -} - -// ----------------------------- ozstream ----------------------------- - -class ozstream -{ - public: - ozstream() : m_fp(0), m_os(0) { - } - ozstream(FILE* fp, int level = Z_DEFAULT_COMPRESSION) - : m_fp(0), m_os(0) { - open(fp, level); - } - ozstream(const char* name, int level = Z_DEFAULT_COMPRESSION) - : m_fp(0), m_os(0) { - open(name, level); - } - ~ozstream() { - close(); - } - - /* Opens a gzip (.gz) file for writing. - * The compression level parameter should be in 0..9 - * errno can be checked to distinguish two error cases - * (if errno is zero, the zlib error is Z_MEM_ERROR). - */ - void open(const char* name, int level = Z_DEFAULT_COMPRESSION) { - char mode[4] = "wb\0"; - if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level; - if (m_fp) close(); - m_fp = ::gzopen(name, mode); - } - - /* open from a FILE pointer. - */ - void open(FILE* fp, int level = Z_DEFAULT_COMPRESSION) { - SET_BINARY_MODE(fp); - char mode[4] = "wb\0"; - if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level; - if (m_fp) close(); - m_fp = ::gzdopen(fileno(fp), mode); - } - - /* Flushes all pending output if necessary, closes the compressed file - * and deallocates all the (de)compression state. The return value is - * the zlib error number (see function error() below). - */ - int close() { - if (m_os) { - ::gzwrite(m_fp, m_os->str(), m_os->pcount()); - delete[] m_os->str(); delete m_os; m_os = 0; - } - int r = ::gzclose(m_fp); m_fp = 0; return r; - } - - /* Binary write the given number of bytes into the compressed file. - */ - int write(const void* buf, size_t len) { - return ::gzwrite(m_fp, (voidp) buf, len); - } - - /* Flushes all pending output into the compressed file. The parameter - * _flush is as in the deflate() function. The return value is the zlib - * error number (see function gzerror below). flush() returns Z_OK if - * the flush_ parameter is Z_FINISH and all output could be flushed. - * flush() should be called only when strictly necessary because it can - * degrade compression. - */ - int flush(int _flush) { - os_flush(); - return ::gzflush(m_fp, _flush); - } - - /* Returns the error message for the last error which occurred on the - * given compressed file. errnum is set to zlib error number. If an - * error occurred in the file system and not in the compression library, - * errnum is set to Z_ERRNO and the application may consult errno - * to get the exact error code. - */ - const char* error(int* errnum) { - return ::gzerror(m_fp, errnum); - } - - gzFile fp() { return m_fp; } - - ostream& os() { - if (m_os == 0) m_os = new ostrstream; - return *m_os; - } - - void os_flush() { - if (m_os && m_os->pcount()>0) { - ostrstream* oss = new ostrstream; - oss->fill(m_os->fill()); - oss->flags(m_os->flags()); - oss->precision(m_os->precision()); - oss->width(m_os->width()); - ::gzwrite(m_fp, m_os->str(), m_os->pcount()); - delete[] m_os->str(); delete m_os; m_os = oss; - } - } - - private: - gzFile m_fp; - ostrstream* m_os; -}; - -/* - * Binary write the given (array of) object(s) into the compressed file. - * returns the number of uncompressed bytes actually written - * (0 in case of error). - */ -template -inline int write(ozstream& zs, const T* x, Items items) { - return ::gzwrite(zs.fp(), (voidp) x, items*sizeof(T)); -} - -/* - * Binary output with the '<' operator. - */ -template -inline ozstream& operator<(ozstream& zs, const T& x) { - ::gzwrite(zs.fp(), (voidp) &x, sizeof(T)); - return zs; -} - -inline zstringlen::zstringlen(ozstream& zs, const char* x) { - val.byte = 255; val.word = ::strlen(x); - if (val.word < 255) zs < (val.byte = val.word); - else zs < val; -} - -/* - * Write length of string + the string with the '<' operator. - */ -inline ozstream& operator<(ozstream& zs, const char* x) { - zstringlen len(zs, x); - ::gzwrite(zs.fp(), (voidp) x, len.value()); - return zs; -} - -#ifdef _MSC_VER -inline ozstream& operator<(ozstream& zs, char* const& x) { - return zs < (const char*) x; -} -#endif - -/* - * Ascii write with the << operator; - */ -template -inline ostream& operator<<(ozstream& zs, const T& x) { - zs.os_flush(); - return zs.os() << x; -} - -#endif diff --git a/deps/zlib/contrib/iostream2/zstream_test.cpp b/deps/zlib/contrib/iostream2/zstream_test.cpp deleted file mode 100644 index 6273f62d62a8fa..00000000000000 --- a/deps/zlib/contrib/iostream2/zstream_test.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "zstream.h" -#include -#include -#include - -void main() { - char h[256] = "Hello"; - char* g = "Goodbye"; - ozstream out("temp.gz"); - out < "This works well" < h < g; - out.close(); - - izstream in("temp.gz"); // read it back - char *x = read_string(in), *y = new char[256], z[256]; - in > y > z; - in.close(); - cout << x << endl << y << endl << z << endl; - - out.open("temp.gz"); // try ascii output; zcat temp.gz to see the results - out << setw(50) << setfill('#') << setprecision(20) << x << endl << y << endl << z << endl; - out << z << endl << y << endl << x << endl; - out << 1.1234567890123456789 << endl; - - delete[] x; delete[] y; -} diff --git a/deps/zlib/contrib/iostream3/README b/deps/zlib/contrib/iostream3/README deleted file mode 100644 index f7b319ab91a7c7..00000000000000 --- a/deps/zlib/contrib/iostream3/README +++ /dev/null @@ -1,35 +0,0 @@ -These classes provide a C++ stream interface to the zlib library. It allows you -to do things like: - - gzofstream outf("blah.gz"); - outf << "These go into the gzip file " << 123 << endl; - -It does this by deriving a specialized stream buffer for gzipped files, which is -the way Stroustrup would have done it. :-> - -The gzifstream and gzofstream classes were originally written by Kevin Ruland -and made available in the zlib contrib/iostream directory. The older version still -compiles under gcc 2.xx, but not under gcc 3.xx, which sparked the development of -this version. - -The new classes are as standard-compliant as possible, closely following the -approach of the standard library's fstream classes. It compiles under gcc versions -3.2 and 3.3, but not under gcc 2.xx. This is mainly due to changes in the standard -library naming scheme. The new version of gzifstream/gzofstream/gzfilebuf differs -from the previous one in the following respects: -- added showmanyc -- added setbuf, with support for unbuffered output via setbuf(0,0) -- a few bug fixes of stream behavior -- gzipped output file opened with default compression level instead of maximum level -- setcompressionlevel()/strategy() members replaced by single setcompression() - -The code is provided "as is", with the permission to use, copy, modify, distribute -and sell it for any purpose without fee. - -Ludwig Schwardt - - -DSP Lab -Electrical & Electronic Engineering Department -University of Stellenbosch -South Africa diff --git a/deps/zlib/contrib/iostream3/TODO b/deps/zlib/contrib/iostream3/TODO deleted file mode 100644 index 7032f97be0469e..00000000000000 --- a/deps/zlib/contrib/iostream3/TODO +++ /dev/null @@ -1,17 +0,0 @@ -Possible upgrades to gzfilebuf: - -- The ability to do putback (e.g. putbackfail) - -- The ability to seek (zlib supports this, but could be slow/tricky) - -- Simultaneous read/write access (does it make sense?) - -- Support for ios_base::ate open mode - -- Locale support? - -- Check public interface to see which calls give problems - (due to dependence on library internals) - -- Override operator<<(ostream&, gzfilebuf*) to allow direct copying - of stream buffer to stream ( i.e. os << is.rdbuf(); ) diff --git a/deps/zlib/contrib/iostream3/test.cc b/deps/zlib/contrib/iostream3/test.cc deleted file mode 100644 index 94235334f25cd5..00000000000000 --- a/deps/zlib/contrib/iostream3/test.cc +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Test program for gzifstream and gzofstream - * - * by Ludwig Schwardt - * original version by Kevin Ruland - */ - -#include "zfstream.h" -#include // for cout - -int main() { - - gzofstream outf; - gzifstream inf; - char buf[80]; - - outf.open("test1.txt.gz"); - outf << "The quick brown fox sidestepped the lazy canine\n" - << 1.3 << "\nPlan " << 9 << std::endl; - outf.close(); - std::cout << "Wrote the following message to 'test1.txt.gz' (check with zcat or zless):\n" - << "The quick brown fox sidestepped the lazy canine\n" - << 1.3 << "\nPlan " << 9 << std::endl; - - std::cout << "\nReading 'test1.txt.gz' (buffered) produces:\n"; - inf.open("test1.txt.gz"); - while (inf.getline(buf,80,'\n')) { - std::cout << buf << "\t(" << inf.rdbuf()->in_avail() << " chars left in buffer)\n"; - } - inf.close(); - - outf.rdbuf()->pubsetbuf(0,0); - outf.open("test2.txt.gz"); - outf << setcompression(Z_NO_COMPRESSION) - << "The quick brown fox sidestepped the lazy canine\n" - << 1.3 << "\nPlan " << 9 << std::endl; - outf.close(); - std::cout << "\nWrote the same message to 'test2.txt.gz' in uncompressed form"; - - std::cout << "\nReading 'test2.txt.gz' (unbuffered) produces:\n"; - inf.rdbuf()->pubsetbuf(0,0); - inf.open("test2.txt.gz"); - while (inf.getline(buf,80,'\n')) { - std::cout << buf << "\t(" << inf.rdbuf()->in_avail() << " chars left in buffer)\n"; - } - inf.close(); - - return 0; - -} diff --git a/deps/zlib/contrib/iostream3/zfstream.cc b/deps/zlib/contrib/iostream3/zfstream.cc deleted file mode 100644 index 94eb933444a967..00000000000000 --- a/deps/zlib/contrib/iostream3/zfstream.cc +++ /dev/null @@ -1,479 +0,0 @@ -/* - * A C++ I/O streams interface to the zlib gz* functions - * - * by Ludwig Schwardt - * original version by Kevin Ruland - * - * This version is standard-compliant and compatible with gcc 3.x. - */ - -#include "zfstream.h" -#include // for strcpy, strcat, strlen (mode strings) -#include // for BUFSIZ - -// Internal buffer sizes (default and "unbuffered" versions) -#define BIGBUFSIZE BUFSIZ -#define SMALLBUFSIZE 1 - -/*****************************************************************************/ - -// Default constructor -gzfilebuf::gzfilebuf() -: file(NULL), io_mode(std::ios_base::openmode(0)), own_fd(false), - buffer(NULL), buffer_size(BIGBUFSIZE), own_buffer(true) -{ - // No buffers to start with - this->disable_buffer(); -} - -// Destructor -gzfilebuf::~gzfilebuf() -{ - // Sync output buffer and close only if responsible for file - // (i.e. attached streams should be left open at this stage) - this->sync(); - if (own_fd) - this->close(); - // Make sure internal buffer is deallocated - this->disable_buffer(); -} - -// Set compression level and strategy -int -gzfilebuf::setcompression(int comp_level, - int comp_strategy) -{ - return gzsetparams(file, comp_level, comp_strategy); -} - -// Open gzipped file -gzfilebuf* -gzfilebuf::open(const char *name, - std::ios_base::openmode mode) -{ - // Fail if file already open - if (this->is_open()) - return NULL; - // Don't support simultaneous read/write access (yet) - if ((mode & std::ios_base::in) && (mode & std::ios_base::out)) - return NULL; - - // Build mode string for gzopen and check it [27.8.1.3.2] - char char_mode[6] = "\0\0\0\0\0"; - if (!this->open_mode(mode, char_mode)) - return NULL; - - // Attempt to open file - if ((file = gzopen(name, char_mode)) == NULL) - return NULL; - - // On success, allocate internal buffer and set flags - this->enable_buffer(); - io_mode = mode; - own_fd = true; - return this; -} - -// Attach to gzipped file -gzfilebuf* -gzfilebuf::attach(int fd, - std::ios_base::openmode mode) -{ - // Fail if file already open - if (this->is_open()) - return NULL; - // Don't support simultaneous read/write access (yet) - if ((mode & std::ios_base::in) && (mode & std::ios_base::out)) - return NULL; - - // Build mode string for gzdopen and check it [27.8.1.3.2] - char char_mode[6] = "\0\0\0\0\0"; - if (!this->open_mode(mode, char_mode)) - return NULL; - - // Attempt to attach to file - if ((file = gzdopen(fd, char_mode)) == NULL) - return NULL; - - // On success, allocate internal buffer and set flags - this->enable_buffer(); - io_mode = mode; - own_fd = false; - return this; -} - -// Close gzipped file -gzfilebuf* -gzfilebuf::close() -{ - // Fail immediately if no file is open - if (!this->is_open()) - return NULL; - // Assume success - gzfilebuf* retval = this; - // Attempt to sync and close gzipped file - if (this->sync() == -1) - retval = NULL; - if (gzclose(file) < 0) - retval = NULL; - // File is now gone anyway (postcondition [27.8.1.3.8]) - file = NULL; - own_fd = false; - // Destroy internal buffer if it exists - this->disable_buffer(); - return retval; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -// Convert int open mode to mode string -bool -gzfilebuf::open_mode(std::ios_base::openmode mode, - char* c_mode) const -{ - bool testb = mode & std::ios_base::binary; - bool testi = mode & std::ios_base::in; - bool testo = mode & std::ios_base::out; - bool testt = mode & std::ios_base::trunc; - bool testa = mode & std::ios_base::app; - - // Check for valid flag combinations - see [27.8.1.3.2] (Table 92) - // Original zfstream hardcoded the compression level to maximum here... - // Double the time for less than 1% size improvement seems - // excessive though - keeping it at the default level - // To change back, just append "9" to the next three mode strings - if (!testi && testo && !testt && !testa) - strcpy(c_mode, "w"); - if (!testi && testo && !testt && testa) - strcpy(c_mode, "a"); - if (!testi && testo && testt && !testa) - strcpy(c_mode, "w"); - if (testi && !testo && !testt && !testa) - strcpy(c_mode, "r"); - // No read/write mode yet -// if (testi && testo && !testt && !testa) -// strcpy(c_mode, "r+"); -// if (testi && testo && testt && !testa) -// strcpy(c_mode, "w+"); - - // Mode string should be empty for invalid combination of flags - if (strlen(c_mode) == 0) - return false; - if (testb) - strcat(c_mode, "b"); - return true; -} - -// Determine number of characters in internal get buffer -std::streamsize -gzfilebuf::showmanyc() -{ - // Calls to underflow will fail if file not opened for reading - if (!this->is_open() || !(io_mode & std::ios_base::in)) - return -1; - // Make sure get area is in use - if (this->gptr() && (this->gptr() < this->egptr())) - return std::streamsize(this->egptr() - this->gptr()); - else - return 0; -} - -// Fill get area from gzipped file -gzfilebuf::int_type -gzfilebuf::underflow() -{ - // If something is left in the get area by chance, return it - // (this shouldn't normally happen, as underflow is only supposed - // to be called when gptr >= egptr, but it serves as error check) - if (this->gptr() && (this->gptr() < this->egptr())) - return traits_type::to_int_type(*(this->gptr())); - - // If the file hasn't been opened for reading, produce error - if (!this->is_open() || !(io_mode & std::ios_base::in)) - return traits_type::eof(); - - // Attempt to fill internal buffer from gzipped file - // (buffer must be guaranteed to exist...) - int bytes_read = gzread(file, buffer, buffer_size); - // Indicates error or EOF - if (bytes_read <= 0) - { - // Reset get area - this->setg(buffer, buffer, buffer); - return traits_type::eof(); - } - // Make all bytes read from file available as get area - this->setg(buffer, buffer, buffer + bytes_read); - - // Return next character in get area - return traits_type::to_int_type(*(this->gptr())); -} - -// Write put area to gzipped file -gzfilebuf::int_type -gzfilebuf::overflow(int_type c) -{ - // Determine whether put area is in use - if (this->pbase()) - { - // Double-check pointer range - if (this->pptr() > this->epptr() || this->pptr() < this->pbase()) - return traits_type::eof(); - // Add extra character to buffer if not EOF - if (!traits_type::eq_int_type(c, traits_type::eof())) - { - *(this->pptr()) = traits_type::to_char_type(c); - this->pbump(1); - } - // Number of characters to write to file - int bytes_to_write = this->pptr() - this->pbase(); - // Overflow doesn't fail if nothing is to be written - if (bytes_to_write > 0) - { - // If the file hasn't been opened for writing, produce error - if (!this->is_open() || !(io_mode & std::ios_base::out)) - return traits_type::eof(); - // If gzipped file won't accept all bytes written to it, fail - if (gzwrite(file, this->pbase(), bytes_to_write) != bytes_to_write) - return traits_type::eof(); - // Reset next pointer to point to pbase on success - this->pbump(-bytes_to_write); - } - } - // Write extra character to file if not EOF - else if (!traits_type::eq_int_type(c, traits_type::eof())) - { - // If the file hasn't been opened for writing, produce error - if (!this->is_open() || !(io_mode & std::ios_base::out)) - return traits_type::eof(); - // Impromptu char buffer (allows "unbuffered" output) - char_type last_char = traits_type::to_char_type(c); - // If gzipped file won't accept this character, fail - if (gzwrite(file, &last_char, 1) != 1) - return traits_type::eof(); - } - - // If you got here, you have succeeded (even if c was EOF) - // The return value should therefore be non-EOF - if (traits_type::eq_int_type(c, traits_type::eof())) - return traits_type::not_eof(c); - else - return c; -} - -// Assign new buffer -std::streambuf* -gzfilebuf::setbuf(char_type* p, - std::streamsize n) -{ - // First make sure stuff is sync'ed, for safety - if (this->sync() == -1) - return NULL; - // If buffering is turned off on purpose via setbuf(0,0), still allocate one... - // "Unbuffered" only really refers to put [27.8.1.4.10], while get needs at - // least a buffer of size 1 (very inefficient though, therefore make it bigger?) - // This follows from [27.5.2.4.3]/12 (gptr needs to point at something, it seems) - if (!p || !n) - { - // Replace existing buffer (if any) with small internal buffer - this->disable_buffer(); - buffer = NULL; - buffer_size = 0; - own_buffer = true; - this->enable_buffer(); - } - else - { - // Replace existing buffer (if any) with external buffer - this->disable_buffer(); - buffer = p; - buffer_size = n; - own_buffer = false; - this->enable_buffer(); - } - return this; -} - -// Write put area to gzipped file (i.e. ensures that put area is empty) -int -gzfilebuf::sync() -{ - return traits_type::eq_int_type(this->overflow(), traits_type::eof()) ? -1 : 0; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -// Allocate internal buffer -void -gzfilebuf::enable_buffer() -{ - // If internal buffer required, allocate one - if (own_buffer && !buffer) - { - // Check for buffered vs. "unbuffered" - if (buffer_size > 0) - { - // Allocate internal buffer - buffer = new char_type[buffer_size]; - // Get area starts empty and will be expanded by underflow as need arises - this->setg(buffer, buffer, buffer); - // Setup entire internal buffer as put area. - // The one-past-end pointer actually points to the last element of the buffer, - // so that overflow(c) can safely add the extra character c to the sequence. - // These pointers remain in place for the duration of the buffer - this->setp(buffer, buffer + buffer_size - 1); - } - else - { - // Even in "unbuffered" case, (small?) get buffer is still required - buffer_size = SMALLBUFSIZE; - buffer = new char_type[buffer_size]; - this->setg(buffer, buffer, buffer); - // "Unbuffered" means no put buffer - this->setp(0, 0); - } - } - else - { - // If buffer already allocated, reset buffer pointers just to make sure no - // stale chars are lying around - this->setg(buffer, buffer, buffer); - this->setp(buffer, buffer + buffer_size - 1); - } -} - -// Destroy internal buffer -void -gzfilebuf::disable_buffer() -{ - // If internal buffer exists, deallocate it - if (own_buffer && buffer) - { - // Preserve unbuffered status by zeroing size - if (!this->pbase()) - buffer_size = 0; - delete[] buffer; - buffer = NULL; - this->setg(0, 0, 0); - this->setp(0, 0); - } - else - { - // Reset buffer pointers to initial state if external buffer exists - this->setg(buffer, buffer, buffer); - if (buffer) - this->setp(buffer, buffer + buffer_size - 1); - else - this->setp(0, 0); - } -} - -/*****************************************************************************/ - -// Default constructor initializes stream buffer -gzifstream::gzifstream() -: std::istream(NULL), sb() -{ this->init(&sb); } - -// Initialize stream buffer and open file -gzifstream::gzifstream(const char* name, - std::ios_base::openmode mode) -: std::istream(NULL), sb() -{ - this->init(&sb); - this->open(name, mode); -} - -// Initialize stream buffer and attach to file -gzifstream::gzifstream(int fd, - std::ios_base::openmode mode) -: std::istream(NULL), sb() -{ - this->init(&sb); - this->attach(fd, mode); -} - -// Open file and go into fail() state if unsuccessful -void -gzifstream::open(const char* name, - std::ios_base::openmode mode) -{ - if (!sb.open(name, mode | std::ios_base::in)) - this->setstate(std::ios_base::failbit); - else - this->clear(); -} - -// Attach to file and go into fail() state if unsuccessful -void -gzifstream::attach(int fd, - std::ios_base::openmode mode) -{ - if (!sb.attach(fd, mode | std::ios_base::in)) - this->setstate(std::ios_base::failbit); - else - this->clear(); -} - -// Close file -void -gzifstream::close() -{ - if (!sb.close()) - this->setstate(std::ios_base::failbit); -} - -/*****************************************************************************/ - -// Default constructor initializes stream buffer -gzofstream::gzofstream() -: std::ostream(NULL), sb() -{ this->init(&sb); } - -// Initialize stream buffer and open file -gzofstream::gzofstream(const char* name, - std::ios_base::openmode mode) -: std::ostream(NULL), sb() -{ - this->init(&sb); - this->open(name, mode); -} - -// Initialize stream buffer and attach to file -gzofstream::gzofstream(int fd, - std::ios_base::openmode mode) -: std::ostream(NULL), sb() -{ - this->init(&sb); - this->attach(fd, mode); -} - -// Open file and go into fail() state if unsuccessful -void -gzofstream::open(const char* name, - std::ios_base::openmode mode) -{ - if (!sb.open(name, mode | std::ios_base::out)) - this->setstate(std::ios_base::failbit); - else - this->clear(); -} - -// Attach to file and go into fail() state if unsuccessful -void -gzofstream::attach(int fd, - std::ios_base::openmode mode) -{ - if (!sb.attach(fd, mode | std::ios_base::out)) - this->setstate(std::ios_base::failbit); - else - this->clear(); -} - -// Close file -void -gzofstream::close() -{ - if (!sb.close()) - this->setstate(std::ios_base::failbit); -} diff --git a/deps/zlib/contrib/iostream3/zfstream.h b/deps/zlib/contrib/iostream3/zfstream.h deleted file mode 100644 index 8574479ae1e7cd..00000000000000 --- a/deps/zlib/contrib/iostream3/zfstream.h +++ /dev/null @@ -1,466 +0,0 @@ -/* - * A C++ I/O streams interface to the zlib gz* functions - * - * by Ludwig Schwardt - * original version by Kevin Ruland - * - * This version is standard-compliant and compatible with gcc 3.x. - */ - -#ifndef ZFSTREAM_H -#define ZFSTREAM_H - -#include // not iostream, since we don't need cin/cout -#include -#include "zlib.h" - -/*****************************************************************************/ - -/** - * @brief Gzipped file stream buffer class. - * - * This class implements basic_filebuf for gzipped files. It doesn't yet support - * seeking (allowed by zlib but slow/limited), putback and read/write access - * (tricky). Otherwise, it attempts to be a drop-in replacement for the standard - * file streambuf. -*/ -class gzfilebuf : public std::streambuf -{ -public: - // Default constructor. - gzfilebuf(); - - // Destructor. - virtual - ~gzfilebuf(); - - /** - * @brief Set compression level and strategy on the fly. - * @param comp_level Compression level (see zlib.h for allowed values) - * @param comp_strategy Compression strategy (see zlib.h for allowed values) - * @return Z_OK on success, Z_STREAM_ERROR otherwise. - * - * Unfortunately, these parameters cannot be modified separately, as the - * previous zfstream version assumed. Since the strategy is seldom changed, - * it can default and setcompression(level) then becomes like the old - * setcompressionlevel(level). - */ - int - setcompression(int comp_level, - int comp_strategy = Z_DEFAULT_STRATEGY); - - /** - * @brief Check if file is open. - * @return True if file is open. - */ - bool - is_open() const { return (file != NULL); } - - /** - * @brief Open gzipped file. - * @param name File name. - * @param mode Open mode flags. - * @return @c this on success, NULL on failure. - */ - gzfilebuf* - open(const char* name, - std::ios_base::openmode mode); - - /** - * @brief Attach to already open gzipped file. - * @param fd File descriptor. - * @param mode Open mode flags. - * @return @c this on success, NULL on failure. - */ - gzfilebuf* - attach(int fd, - std::ios_base::openmode mode); - - /** - * @brief Close gzipped file. - * @return @c this on success, NULL on failure. - */ - gzfilebuf* - close(); - -protected: - /** - * @brief Convert ios open mode int to mode string used by zlib. - * @return True if valid mode flag combination. - */ - bool - open_mode(std::ios_base::openmode mode, - char* c_mode) const; - - /** - * @brief Number of characters available in stream buffer. - * @return Number of characters. - * - * This indicates number of characters in get area of stream buffer. - * These characters can be read without accessing the gzipped file. - */ - virtual std::streamsize - showmanyc(); - - /** - * @brief Fill get area from gzipped file. - * @return First character in get area on success, EOF on error. - * - * This actually reads characters from gzipped file to stream - * buffer. Always buffered. - */ - virtual int_type - underflow(); - - /** - * @brief Write put area to gzipped file. - * @param c Extra character to add to buffer contents. - * @return Non-EOF on success, EOF on error. - * - * This actually writes characters in stream buffer to - * gzipped file. With unbuffered output this is done one - * character at a time. - */ - virtual int_type - overflow(int_type c = traits_type::eof()); - - /** - * @brief Installs external stream buffer. - * @param p Pointer to char buffer. - * @param n Size of external buffer. - * @return @c this on success, NULL on failure. - * - * Call setbuf(0,0) to enable unbuffered output. - */ - virtual std::streambuf* - setbuf(char_type* p, - std::streamsize n); - - /** - * @brief Flush stream buffer to file. - * @return 0 on success, -1 on error. - * - * This calls underflow(EOF) to do the job. - */ - virtual int - sync(); - -// -// Some future enhancements -// -// virtual int_type uflow(); -// virtual int_type pbackfail(int_type c = traits_type::eof()); -// virtual pos_type -// seekoff(off_type off, -// std::ios_base::seekdir way, -// std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out); -// virtual pos_type -// seekpos(pos_type sp, -// std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out); - -private: - /** - * @brief Allocate internal buffer. - * - * This function is safe to call multiple times. It will ensure - * that a proper internal buffer exists if it is required. If the - * buffer already exists or is external, the buffer pointers will be - * reset to their original state. - */ - void - enable_buffer(); - - /** - * @brief Destroy internal buffer. - * - * This function is safe to call multiple times. It will ensure - * that the internal buffer is deallocated if it exists. In any - * case, it will also reset the buffer pointers. - */ - void - disable_buffer(); - - /** - * Underlying file pointer. - */ - gzFile file; - - /** - * Mode in which file was opened. - */ - std::ios_base::openmode io_mode; - - /** - * @brief True if this object owns file descriptor. - * - * This makes the class responsible for closing the file - * upon destruction. - */ - bool own_fd; - - /** - * @brief Stream buffer. - * - * For simplicity this remains allocated on the free store for the - * entire life span of the gzfilebuf object, unless replaced by setbuf. - */ - char_type* buffer; - - /** - * @brief Stream buffer size. - * - * Defaults to system default buffer size (typically 8192 bytes). - * Modified by setbuf. - */ - std::streamsize buffer_size; - - /** - * @brief True if this object owns stream buffer. - * - * This makes the class responsible for deleting the buffer - * upon destruction. - */ - bool own_buffer; -}; - -/*****************************************************************************/ - -/** - * @brief Gzipped file input stream class. - * - * This class implements ifstream for gzipped files. Seeking and putback - * is not supported yet. -*/ -class gzifstream : public std::istream -{ -public: - // Default constructor - gzifstream(); - - /** - * @brief Construct stream on gzipped file to be opened. - * @param name File name. - * @param mode Open mode flags (forced to contain ios::in). - */ - explicit - gzifstream(const char* name, - std::ios_base::openmode mode = std::ios_base::in); - - /** - * @brief Construct stream on already open gzipped file. - * @param fd File descriptor. - * @param mode Open mode flags (forced to contain ios::in). - */ - explicit - gzifstream(int fd, - std::ios_base::openmode mode = std::ios_base::in); - - /** - * Obtain underlying stream buffer. - */ - gzfilebuf* - rdbuf() const - { return const_cast(&sb); } - - /** - * @brief Check if file is open. - * @return True if file is open. - */ - bool - is_open() { return sb.is_open(); } - - /** - * @brief Open gzipped file. - * @param name File name. - * @param mode Open mode flags (forced to contain ios::in). - * - * Stream will be in state good() if file opens successfully; - * otherwise in state fail(). This differs from the behavior of - * ifstream, which never sets the state to good() and therefore - * won't allow you to reuse the stream for a second file unless - * you manually clear() the state. The choice is a matter of - * convenience. - */ - void - open(const char* name, - std::ios_base::openmode mode = std::ios_base::in); - - /** - * @brief Attach to already open gzipped file. - * @param fd File descriptor. - * @param mode Open mode flags (forced to contain ios::in). - * - * Stream will be in state good() if attach succeeded; otherwise - * in state fail(). - */ - void - attach(int fd, - std::ios_base::openmode mode = std::ios_base::in); - - /** - * @brief Close gzipped file. - * - * Stream will be in state fail() if close failed. - */ - void - close(); - -private: - /** - * Underlying stream buffer. - */ - gzfilebuf sb; -}; - -/*****************************************************************************/ - -/** - * @brief Gzipped file output stream class. - * - * This class implements ofstream for gzipped files. Seeking and putback - * is not supported yet. -*/ -class gzofstream : public std::ostream -{ -public: - // Default constructor - gzofstream(); - - /** - * @brief Construct stream on gzipped file to be opened. - * @param name File name. - * @param mode Open mode flags (forced to contain ios::out). - */ - explicit - gzofstream(const char* name, - std::ios_base::openmode mode = std::ios_base::out); - - /** - * @brief Construct stream on already open gzipped file. - * @param fd File descriptor. - * @param mode Open mode flags (forced to contain ios::out). - */ - explicit - gzofstream(int fd, - std::ios_base::openmode mode = std::ios_base::out); - - /** - * Obtain underlying stream buffer. - */ - gzfilebuf* - rdbuf() const - { return const_cast(&sb); } - - /** - * @brief Check if file is open. - * @return True if file is open. - */ - bool - is_open() { return sb.is_open(); } - - /** - * @brief Open gzipped file. - * @param name File name. - * @param mode Open mode flags (forced to contain ios::out). - * - * Stream will be in state good() if file opens successfully; - * otherwise in state fail(). This differs from the behavior of - * ofstream, which never sets the state to good() and therefore - * won't allow you to reuse the stream for a second file unless - * you manually clear() the state. The choice is a matter of - * convenience. - */ - void - open(const char* name, - std::ios_base::openmode mode = std::ios_base::out); - - /** - * @brief Attach to already open gzipped file. - * @param fd File descriptor. - * @param mode Open mode flags (forced to contain ios::out). - * - * Stream will be in state good() if attach succeeded; otherwise - * in state fail(). - */ - void - attach(int fd, - std::ios_base::openmode mode = std::ios_base::out); - - /** - * @brief Close gzipped file. - * - * Stream will be in state fail() if close failed. - */ - void - close(); - -private: - /** - * Underlying stream buffer. - */ - gzfilebuf sb; -}; - -/*****************************************************************************/ - -/** - * @brief Gzipped file output stream manipulator class. - * - * This class defines a two-argument manipulator for gzofstream. It is used - * as base for the setcompression(int,int) manipulator. -*/ -template - class gzomanip2 - { - public: - // Allows insertor to peek at internals - template - friend gzofstream& - operator<<(gzofstream&, - const gzomanip2&); - - // Constructor - gzomanip2(gzofstream& (*f)(gzofstream&, T1, T2), - T1 v1, - T2 v2); - private: - // Underlying manipulator function - gzofstream& - (*func)(gzofstream&, T1, T2); - - // Arguments for manipulator function - T1 val1; - T2 val2; - }; - -/*****************************************************************************/ - -// Manipulator function thunks through to stream buffer -inline gzofstream& -setcompression(gzofstream &gzs, int l, int s = Z_DEFAULT_STRATEGY) -{ - (gzs.rdbuf())->setcompression(l, s); - return gzs; -} - -// Manipulator constructor stores arguments -template - inline - gzomanip2::gzomanip2(gzofstream &(*f)(gzofstream &, T1, T2), - T1 v1, - T2 v2) - : func(f), val1(v1), val2(v2) - { } - -// Insertor applies underlying manipulator function to stream -template - inline gzofstream& - operator<<(gzofstream& s, const gzomanip2& m) - { return (*m.func)(s, m.val1, m.val2); } - -// Insert this onto stream to simplify setting of compression level -inline gzomanip2 -setcompression(int l, int s = Z_DEFAULT_STRATEGY) -{ return gzomanip2(&setcompression, l, s); } - -#endif // ZFSTREAM_H diff --git a/deps/zlib/contrib/masmx64/bld_ml64.bat b/deps/zlib/contrib/masmx64/bld_ml64.bat deleted file mode 100644 index f74bcef5b48d39..00000000000000 --- a/deps/zlib/contrib/masmx64/bld_ml64.bat +++ /dev/null @@ -1,2 +0,0 @@ -ml64.exe /Flinffasx64 /c /Zi inffasx64.asm -ml64.exe /Flgvmat64 /c /Zi gvmat64.asm diff --git a/deps/zlib/contrib/masmx64/gvmat64.asm b/deps/zlib/contrib/masmx64/gvmat64.asm deleted file mode 100644 index c1817f1be96d96..00000000000000 --- a/deps/zlib/contrib/masmx64/gvmat64.asm +++ /dev/null @@ -1,553 +0,0 @@ -;uInt longest_match_x64( -; deflate_state *s, -; IPos cur_match); /* current match */ - -; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86_64 -; (AMD64 on Athlon 64, Opteron, Phenom -; and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7) -; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant. -; -; File written by Gilles Vollant, by converting to assembly the longest_match -; from Jean-loup Gailly in deflate.c of zLib and infoZip zip. -; -; and by taking inspiration on asm686 with masm, optimised assembly code -; from Brian Raiter, written 1998 -; -; This software is provided 'as-is', without any express or implied -; warranty. In no event will the authors be held liable for any damages -; arising from the use of this software. -; -; Permission is granted to anyone to use this software for any purpose, -; including commercial applications, and to alter it and redistribute it -; freely, subject to the following restrictions: -; -; 1. The origin of this software must not be misrepresented; you must not -; claim that you wrote the original software. If you use this software -; in a product, an acknowledgment in the product documentation would be -; appreciated but is not required. -; 2. Altered source versions must be plainly marked as such, and must not be -; misrepresented as being the original software -; 3. This notice may not be removed or altered from any source distribution. -; -; -; -; http://www.zlib.net -; http://www.winimage.com/zLibDll -; http://www.muppetlabs.com/~breadbox/software/assembly.html -; -; to compile this file for infozip Zip, I use option: -; ml64.exe /Flgvmat64 /c /Zi /DINFOZIP gvmat64.asm -; -; to compile this file for zLib, I use option: -; ml64.exe /Flgvmat64 /c /Zi gvmat64.asm -; Be carrefull to adapt zlib1222add below to your version of zLib -; (if you use a version of zLib before 1.0.4 or after 1.2.2.2, change -; value of zlib1222add later) -; -; This file compile with Microsoft Macro Assembler (x64) for AMD64 -; -; ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK -; -; (you can get Windows WDK with ml64 for AMD64 from -; http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price) -; - - -;uInt longest_match(s, cur_match) -; deflate_state *s; -; IPos cur_match; /* current match */ -.code -longest_match PROC - - -;LocalVarsSize equ 88 - LocalVarsSize equ 72 - -; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12 -; free register : r14,r15 -; register can be saved : rsp - - chainlenwmask equ rsp + 8 - LocalVarsSize ; high word: current chain len - ; low word: s->wmask -;window equ rsp + xx - LocalVarsSize ; local copy of s->window ; stored in r10 -;windowbestlen equ rsp + xx - LocalVarsSize ; s->window + bestlen , use r10+r11 -;scanstart equ rsp + xx - LocalVarsSize ; first two bytes of string ; stored in r12w -;scanend equ rsp + xx - LocalVarsSize ; last two bytes of string use ebx -;scanalign equ rsp + xx - LocalVarsSize ; dword-misalignment of string r13 -;bestlen equ rsp + xx - LocalVarsSize ; size of best match so far -> r11d -;scan equ rsp + xx - LocalVarsSize ; ptr to string wanting match -> r9 -IFDEF INFOZIP -ELSE - nicematch equ (rsp + 16 - LocalVarsSize) ; a good enough match size -ENDIF - -save_rdi equ rsp + 24 - LocalVarsSize -save_rsi equ rsp + 32 - LocalVarsSize -save_rbx equ rsp + 40 - LocalVarsSize -save_rbp equ rsp + 48 - LocalVarsSize -save_r12 equ rsp + 56 - LocalVarsSize -save_r13 equ rsp + 64 - LocalVarsSize -;save_r14 equ rsp + 72 - LocalVarsSize -;save_r15 equ rsp + 80 - LocalVarsSize - - -; summary of register usage -; scanend ebx -; scanendw bx -; chainlenwmask edx -; curmatch rsi -; curmatchd esi -; windowbestlen r8 -; scanalign r9 -; scanalignd r9d -; window r10 -; bestlen r11 -; bestlend r11d -; scanstart r12d -; scanstartw r12w -; scan r13 -; nicematch r14d -; limit r15 -; limitd r15d -; prev rcx - -; all the +4 offsets are due to the addition of pending_buf_size (in zlib -; in the deflate_state structure since the asm code was first written -; (if you compile with zlib 1.0.4 or older, remove the +4). -; Note : these value are good with a 8 bytes boundary pack structure - - - MAX_MATCH equ 258 - MIN_MATCH equ 3 - MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) - - -;;; Offsets for fields in the deflate_state structure. These numbers -;;; are calculated from the definition of deflate_state, with the -;;; assumption that the compiler will dword-align the fields. (Thus, -;;; changing the definition of deflate_state could easily cause this -;;; program to crash horribly, without so much as a warning at -;;; compile time. Sigh.) - -; all the +zlib1222add offsets are due to the addition of fields -; in zlib in the deflate_state structure since the asm code was first written -; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). -; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). -; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). - - -IFDEF INFOZIP - -_DATA SEGMENT -COMM window_size:DWORD -; WMask ; 7fff -COMM window:BYTE:010040H -COMM prev:WORD:08000H -; MatchLen : unused -; PrevMatch : unused -COMM strstart:DWORD -COMM match_start:DWORD -; Lookahead : ignore -COMM prev_length:DWORD ; PrevLen -COMM max_chain_length:DWORD -COMM good_match:DWORD -COMM nice_match:DWORD -prev_ad equ OFFSET prev -window_ad equ OFFSET window -nicematch equ nice_match -_DATA ENDS -WMask equ 07fffh - -ELSE - - IFNDEF zlib1222add - zlib1222add equ 8 - ENDIF -dsWSize equ 56+zlib1222add+(zlib1222add/2) -dsWMask equ 64+zlib1222add+(zlib1222add/2) -dsWindow equ 72+zlib1222add -dsPrev equ 88+zlib1222add -dsMatchLen equ 128+zlib1222add -dsPrevMatch equ 132+zlib1222add -dsStrStart equ 140+zlib1222add -dsMatchStart equ 144+zlib1222add -dsLookahead equ 148+zlib1222add -dsPrevLen equ 152+zlib1222add -dsMaxChainLen equ 156+zlib1222add -dsGoodMatch equ 172+zlib1222add -dsNiceMatch equ 176+zlib1222add - -window_size equ [ rcx + dsWSize] -WMask equ [ rcx + dsWMask] -window_ad equ [ rcx + dsWindow] -prev_ad equ [ rcx + dsPrev] -strstart equ [ rcx + dsStrStart] -match_start equ [ rcx + dsMatchStart] -Lookahead equ [ rcx + dsLookahead] ; 0ffffffffh on infozip -prev_length equ [ rcx + dsPrevLen] -max_chain_length equ [ rcx + dsMaxChainLen] -good_match equ [ rcx + dsGoodMatch] -nice_match equ [ rcx + dsNiceMatch] -ENDIF - -; parameter 1 in r8(deflate state s), param 2 in rdx (cur match) - -; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and -; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp -; -; All registers must be preserved across the call, except for -; rax, rcx, rdx, r8, r9, r10, and r11, which are scratch. - - - -;;; Save registers that the compiler may be using, and adjust esp to -;;; make room for our stack frame. - - -;;; Retrieve the function arguments. r8d will hold cur_match -;;; throughout the entire function. edx will hold the pointer to the -;;; deflate_state structure during the function's setup (before -;;; entering the main loop. - -; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match) - -; this clear high 32 bits of r8, which can be garbage in both r8 and rdx - - mov [save_rdi],rdi - mov [save_rsi],rsi - mov [save_rbx],rbx - mov [save_rbp],rbp -IFDEF INFOZIP - mov r8d,ecx -ELSE - mov r8d,edx -ENDIF - mov [save_r12],r12 - mov [save_r13],r13 -; mov [save_r14],r14 -; mov [save_r15],r15 - - -;;; uInt wmask = s->w_mask; -;;; unsigned chain_length = s->max_chain_length; -;;; if (s->prev_length >= s->good_match) { -;;; chain_length >>= 2; -;;; } - - mov edi, prev_length - mov esi, good_match - mov eax, WMask - mov ebx, max_chain_length - cmp edi, esi - jl LastMatchGood - shr ebx, 2 -LastMatchGood: - -;;; chainlen is decremented once beforehand so that the function can -;;; use the sign flag instead of the zero flag for the exit test. -;;; It is then shifted into the high word, to make room for the wmask -;;; value, which it will always accompany. - - dec ebx - shl ebx, 16 - or ebx, eax - -;;; on zlib only -;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - -IFDEF INFOZIP - mov [chainlenwmask], ebx -; on infozip nice_match = [nice_match] -ELSE - mov eax, nice_match - mov [chainlenwmask], ebx - mov r10d, Lookahead - cmp r10d, eax - cmovnl r10d, eax - mov [nicematch],r10d -ENDIF - -;;; register Bytef *scan = s->window + s->strstart; - mov r10, window_ad - mov ebp, strstart - lea r13, [r10 + rbp] - -;;; Determine how many bytes the scan ptr is off from being -;;; dword-aligned. - - mov r9,r13 - neg r13 - and r13,3 - -;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? -;;; s->strstart - (IPos)MAX_DIST(s) : NIL; -IFDEF INFOZIP - mov eax,07efah ; MAX_DIST = (WSIZE-MIN_LOOKAHEAD) (0x8000-(3+8+1)) -ELSE - mov eax, window_size - sub eax, MIN_LOOKAHEAD -ENDIF - xor edi,edi - sub ebp, eax - - mov r11d, prev_length - - cmovng ebp,edi - -;;; int best_len = s->prev_length; - - -;;; Store the sum of s->window + best_len in esi locally, and in esi. - - lea rsi,[r10+r11] - -;;; register ush scan_start = *(ushf*)scan; -;;; register ush scan_end = *(ushf*)(scan+best_len-1); -;;; Posf *prev = s->prev; - - movzx r12d,word ptr [r9] - movzx ebx, word ptr [r9 + r11 - 1] - - mov rdi, prev_ad - -;;; Jump into the main loop. - - mov edx, [chainlenwmask] - - cmp bx,word ptr [rsi + r8 - 1] - jz LookupLoopIsZero - -LookupLoop1: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - jbe LeaveNow - sub edx, 00010000h - js LeaveNow - -LoopEntry1: - cmp bx,word ptr [rsi + r8 - 1] - jz LookupLoopIsZero - -LookupLoop2: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - jbe LeaveNow - sub edx, 00010000h - js LeaveNow - -LoopEntry2: - cmp bx,word ptr [rsi + r8 - 1] - jz LookupLoopIsZero - -LookupLoop4: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - jbe LeaveNow - sub edx, 00010000h - js LeaveNow - -LoopEntry4: - - cmp bx,word ptr [rsi + r8 - 1] - jnz LookupLoop1 - jmp LookupLoopIsZero - - -;;; do { -;;; match = s->window + cur_match; -;;; if (*(ushf*)(match+best_len-1) != scan_end || -;;; *(ushf*)match != scan_start) continue; -;;; [...] -;;; } while ((cur_match = prev[cur_match & wmask]) > limit -;;; && --chain_length != 0); -;;; -;;; Here is the inner loop of the function. The function will spend the -;;; majority of its time in this loop, and majority of that time will -;;; be spent in the first ten instructions. -;;; -;;; Within this loop: -;;; ebx = scanend -;;; r8d = curmatch -;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) -;;; esi = windowbestlen - i.e., (window + bestlen) -;;; edi = prev -;;; ebp = limit - -LookupLoop: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - jbe LeaveNow - sub edx, 00010000h - js LeaveNow - -LoopEntry: - - cmp bx,word ptr [rsi + r8 - 1] - jnz LookupLoop1 -LookupLoopIsZero: - cmp r12w, word ptr [r10 + r8] - jnz LookupLoop1 - - -;;; Store the current value of chainlen. - mov [chainlenwmask], edx - -;;; Point edi to the string under scrutiny, and esi to the string we -;;; are hoping to match it up with. In actuality, esi and edi are -;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is -;;; initialized to -(MAX_MATCH_8 - scanalign). - - lea rsi,[r8+r10] - mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8) - lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8] - lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8] - - prefetcht1 [rsi+rdx] - prefetcht1 [rdi+rdx] - - -;;; Test the strings for equality, 8 bytes at a time. At the end, -;;; adjust rdx so that it is offset to the exact byte that mismatched. -;;; -;;; We already know at this point that the first three bytes of the -;;; strings match each other, and they can be safely passed over before -;;; starting the compare loop. So what this code does is skip over 0-3 -;;; bytes, as much as necessary in order to dword-align the edi -;;; pointer. (rsi will still be misaligned three times out of four.) -;;; -;;; It should be confessed that this loop usually does not represent -;;; much of the total running time. Replacing it with a more -;;; straightforward "rep cmpsb" would not drastically degrade -;;; performance. - - -LoopCmps: - mov rax, [rsi + rdx] - xor rax, [rdi + rdx] - jnz LeaveLoopCmps - - mov rax, [rsi + rdx + 8] - xor rax, [rdi + rdx + 8] - jnz LeaveLoopCmps8 - - - mov rax, [rsi + rdx + 8+8] - xor rax, [rdi + rdx + 8+8] - jnz LeaveLoopCmps16 - - add rdx,8+8+8 - - jnz short LoopCmps - jmp short LenMaximum -LeaveLoopCmps16: add rdx,8 -LeaveLoopCmps8: add rdx,8 -LeaveLoopCmps: - - test eax, 0000FFFFh - jnz LenLower - - test eax,0ffffffffh - - jnz LenLower32 - - add rdx,4 - shr rax,32 - or ax,ax - jnz LenLower - -LenLower32: - shr eax,16 - add rdx,2 -LenLower: sub al, 1 - adc rdx, 0 -;;; Calculate the length of the match. If it is longer than MAX_MATCH, -;;; then automatically accept it as the best possible match and leave. - - lea rax, [rdi + rdx] - sub rax, r9 - cmp eax, MAX_MATCH - jge LenMaximum - -;;; If the length of the match is not longer than the best match we -;;; have so far, then forget it and return to the lookup loop. -;/////////////////////////////////// - - cmp eax, r11d - jg LongerMatch - - lea rsi,[r10+r11] - - mov rdi, prev_ad - mov edx, [chainlenwmask] - jmp LookupLoop - -;;; s->match_start = cur_match; -;;; best_len = len; -;;; if (len >= nice_match) break; -;;; scan_end = *(ushf*)(scan+best_len-1); - -LongerMatch: - mov r11d, eax - mov match_start, r8d - cmp eax, [nicematch] - jge LeaveNow - - lea rsi,[r10+rax] - - movzx ebx, word ptr [r9 + rax - 1] - mov rdi, prev_ad - mov edx, [chainlenwmask] - jmp LookupLoop - -;;; Accept the current string, with the maximum possible length. - -LenMaximum: - mov r11d,MAX_MATCH - mov match_start, r8d - -;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; -;;; return s->lookahead; - -LeaveNow: -IFDEF INFOZIP - mov eax,r11d -ELSE - mov eax, Lookahead - cmp r11d, eax - cmovng eax, r11d -ENDIF - -;;; Restore the stack and return from whence we came. - - - mov rsi,[save_rsi] - mov rdi,[save_rdi] - mov rbx,[save_rbx] - mov rbp,[save_rbp] - mov r12,[save_r12] - mov r13,[save_r13] -; mov r14,[save_r14] -; mov r15,[save_r15] - - - ret 0 -; please don't remove this string ! -; Your can freely use gvmat64 in any free or commercial app -; but it is far better don't remove the string in the binary! - db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0 -longest_match ENDP - -match_init PROC - ret 0 -match_init ENDP - - -END diff --git a/deps/zlib/contrib/masmx64/inffas8664.c b/deps/zlib/contrib/masmx64/inffas8664.c deleted file mode 100644 index aa861a33392ffc..00000000000000 --- a/deps/zlib/contrib/masmx64/inffas8664.c +++ /dev/null @@ -1,186 +0,0 @@ -/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding - * version for AMD64 on Windows using Microsoft C compiler - * - * Copyright (C) 1995-2003 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Copyright (C) 2003 Chris Anderson - * Please use the copyright conditions above. - * - * 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant - * - * inffas8664.c call function inffas8664fnc in inffasx64.asm - * inffasx64.asm is automatically convert from AMD64 portion of inffas86.c - * - * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also - * slightly quicker on x86 systems because, instead of using rep movsb to copy - * data, it uses rep movsw, which moves data in 2-byte chunks instead of single - * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates - * from http://fedora.linux.duke.edu/fc1_x86_64 - * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with - * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, - * when decompressing mozilla-source-1.3.tar.gz. - * - * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from - * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at - * the moment. I have successfully compiled and tested this code with gcc2.96, - * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S - * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX - * enabled. I will attempt to merge the MMX code into this version. Newer - * versions of this and inffast.S can be found at - * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ - * - */ - -#include -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -/* Mark Adler's comments from inffast.c: */ - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state->mode == LEN - strm->avail_in >= 6 - strm->avail_out >= 258 - start >= strm->avail_out - state->bits < 8 - - On return, state->mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm->avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for - output space. - */ - - - - typedef struct inffast_ar { -/* 64 32 x86 x86_64 */ -/* ar offset register */ -/* 0 0 */ void *esp; /* esp save */ -/* 8 4 */ void *ebp; /* ebp save */ -/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ -/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ -/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ -/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ -/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ -/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ -/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ -/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ -/* 80 40 */ size_t /*unsigned long */hold; /* edx rdx local strm->hold */ -/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ -/* 92 48 */ unsigned wsize; /* window size */ -/* 96 52 */ unsigned write; /* window write index */ -/*100 56 */ unsigned lmask; /* r12 mask for lcode */ -/*104 60 */ unsigned dmask; /* r13 mask for dcode */ -/*108 64 */ unsigned len; /* r14 match length */ -/*112 68 */ unsigned dist; /* r15 match distance */ -/*116 72 */ unsigned status; /* set when state chng*/ - } type_ar; -#ifdef ASMINF - -void inflate_fast(strm, start) -z_streamp strm; -unsigned start; /* inflate()'s starting value for strm->avail_out */ -{ - struct inflate_state FAR *state; - type_ar ar; - void inffas8664fnc(struct inffast_ar * par); - - - -#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64)) -#define PAD_AVAIL_IN 6 -#define PAD_AVAIL_OUT 258 -#else -#define PAD_AVAIL_IN 5 -#define PAD_AVAIL_OUT 257 -#endif - - /* copy state to local variables */ - state = (struct inflate_state FAR *)strm->state; - - ar.in = strm->next_in; - ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); - ar.out = strm->next_out; - ar.beg = ar.out - (start - strm->avail_out); - ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); - ar.wsize = state->wsize; - ar.write = state->wnext; - ar.window = state->window; - ar.hold = state->hold; - ar.bits = state->bits; - ar.lcode = state->lencode; - ar.dcode = state->distcode; - ar.lmask = (1U << state->lenbits) - 1; - ar.dmask = (1U << state->distbits) - 1; - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - - /* align in on 1/2 hold size boundary */ - while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { - ar.hold += (unsigned long)*ar.in++ << ar.bits; - ar.bits += 8; - } - - inffas8664fnc(&ar); - - if (ar.status > 1) { - if (ar.status == 2) - strm->msg = "invalid literal/length code"; - else if (ar.status == 3) - strm->msg = "invalid distance code"; - else - strm->msg = "invalid distance too far back"; - state->mode = BAD; - } - else if ( ar.status == 1 ) { - state->mode = TYPE; - } - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - ar.len = ar.bits >> 3; - ar.in -= ar.len; - ar.bits -= ar.len << 3; - ar.hold &= (1U << ar.bits) - 1; - - /* update state and return */ - strm->next_in = ar.in; - strm->next_out = ar.out; - strm->avail_in = (unsigned)(ar.in < ar.last ? - PAD_AVAIL_IN + (ar.last - ar.in) : - PAD_AVAIL_IN - (ar.in - ar.last)); - strm->avail_out = (unsigned)(ar.out < ar.end ? - PAD_AVAIL_OUT + (ar.end - ar.out) : - PAD_AVAIL_OUT - (ar.out - ar.end)); - state->hold = (unsigned long)ar.hold; - state->bits = ar.bits; - return; -} - -#endif diff --git a/deps/zlib/contrib/masmx64/inffasx64.asm b/deps/zlib/contrib/masmx64/inffasx64.asm deleted file mode 100644 index 41ec82392ed03d..00000000000000 --- a/deps/zlib/contrib/masmx64/inffasx64.asm +++ /dev/null @@ -1,396 +0,0 @@ -; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding -; version for AMD64 on Windows using Microsoft C compiler -; -; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c -; inffasx64.asm is called by inffas8664.c, which contain more info. - - -; to compile this file, I use option -; ml64.exe /Flinffasx64 /c /Zi inffasx64.asm -; with Microsoft Macro Assembler (x64) for AMD64 -; - -; This file compile with Microsoft Macro Assembler (x64) for AMD64 -; -; ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK -; -; (you can get Windows WDK with ml64 for AMD64 from -; http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price) -; - - -.code -inffas8664fnc PROC - -; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and -; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp -; -; All registers must be preserved across the call, except for -; rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch. - - - mov [rsp-8],rsi - mov [rsp-16],rdi - mov [rsp-24],r12 - mov [rsp-32],r13 - mov [rsp-40],r14 - mov [rsp-48],r15 - mov [rsp-56],rbx - - mov rax,rcx - - mov [rax+8], rbp ; /* save regs rbp and rsp */ - mov [rax], rsp - - mov rsp, rax ; /* make rsp point to &ar */ - - mov rsi, [rsp+16] ; /* rsi = in */ - mov rdi, [rsp+32] ; /* rdi = out */ - mov r9, [rsp+24] ; /* r9 = last */ - mov r10, [rsp+48] ; /* r10 = end */ - mov rbp, [rsp+64] ; /* rbp = lcode */ - mov r11, [rsp+72] ; /* r11 = dcode */ - mov rdx, [rsp+80] ; /* rdx = hold */ - mov ebx, [rsp+88] ; /* ebx = bits */ - mov r12d, [rsp+100] ; /* r12d = lmask */ - mov r13d, [rsp+104] ; /* r13d = dmask */ - ; /* r14d = len */ - ; /* r15d = dist */ - - - cld - cmp r10, rdi - je L_one_time ; /* if only one decode left */ - cmp r9, rsi - - jne L_do_loop - - -L_one_time: - mov r8, r12 ; /* r8 = lmask */ - cmp bl, 32 - ja L_get_length_code_one_time - - lodsd ; /* eax = *(uint *)in++ */ - mov cl, bl ; /* cl = bits, needs it for shifting */ - add bl, 32 ; /* bits += 32 */ - shl rax, cl - or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ - jmp L_get_length_code_one_time - -ALIGN 4 -L_while_test: - cmp r10, rdi - jbe L_break_loop - cmp r9, rsi - jbe L_break_loop - -L_do_loop: - mov r8, r12 ; /* r8 = lmask */ - cmp bl, 32 - ja L_get_length_code ; /* if (32 < bits) */ - - lodsd ; /* eax = *(uint *)in++ */ - mov cl, bl ; /* cl = bits, needs it for shifting */ - add bl, 32 ; /* bits += 32 */ - shl rax, cl - or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ - -L_get_length_code: - and r8, rdx ; /* r8 &= hold */ - mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ - - mov cl, ah ; /* cl = this.bits */ - sub bl, ah ; /* bits -= this.bits */ - shr rdx, cl ; /* hold >>= this.bits */ - - test al, al - jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ - - mov r8, r12 ; /* r8 = lmask */ - shr eax, 16 ; /* output this.val char */ - stosb - -L_get_length_code_one_time: - and r8, rdx ; /* r8 &= hold */ - mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ - -L_dolen: - mov cl, ah ; /* cl = this.bits */ - sub bl, ah ; /* bits -= this.bits */ - shr rdx, cl ; /* hold >>= this.bits */ - - test al, al - jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ - - shr eax, 16 ; /* output this.val char */ - stosb - jmp L_while_test - -ALIGN 4 -L_test_for_length_base: - mov r14d, eax ; /* len = this */ - shr r14d, 16 ; /* len = this.val */ - mov cl, al - - test al, 16 - jz L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */ - and cl, 15 ; /* op &= 15 */ - jz L_decode_distance ; /* if (!op) */ - -L_add_bits_to_len: - sub bl, cl - xor eax, eax - inc eax - shl eax, cl - dec eax - and eax, edx ; /* eax &= hold */ - shr rdx, cl - add r14d, eax ; /* len += hold & mask[op] */ - -L_decode_distance: - mov r8, r13 ; /* r8 = dmask */ - cmp bl, 32 - ja L_get_distance_code ; /* if (32 < bits) */ - - lodsd ; /* eax = *(uint *)in++ */ - mov cl, bl ; /* cl = bits, needs it for shifting */ - add bl, 32 ; /* bits += 32 */ - shl rax, cl - or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ - -L_get_distance_code: - and r8, rdx ; /* r8 &= hold */ - mov eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */ - -L_dodist: - mov r15d, eax ; /* dist = this */ - shr r15d, 16 ; /* dist = this.val */ - mov cl, ah - sub bl, ah ; /* bits -= this.bits */ - shr rdx, cl ; /* hold >>= this.bits */ - mov cl, al ; /* cl = this.op */ - - test al, 16 ; /* if ((op & 16) == 0) */ - jz L_test_for_second_level_dist - and cl, 15 ; /* op &= 15 */ - jz L_check_dist_one - -L_add_bits_to_dist: - sub bl, cl - xor eax, eax - inc eax - shl eax, cl - dec eax ; /* (1 << op) - 1 */ - and eax, edx ; /* eax &= hold */ - shr rdx, cl - add r15d, eax ; /* dist += hold & ((1 << op) - 1) */ - -L_check_window: - mov r8, rsi ; /* save in so from can use it's reg */ - mov rax, rdi - sub rax, [rsp+40] ; /* nbytes = out - beg */ - - cmp eax, r15d - jb L_clip_window ; /* if (dist > nbytes) 4.2% */ - - mov ecx, r14d ; /* ecx = len */ - mov rsi, rdi - sub rsi, r15 ; /* from = out - dist */ - - sar ecx, 1 - jnc L_copy_two ; /* if len % 2 == 0 */ - - rep movsw - mov al, [rsi] - mov [rdi], al - inc rdi - - mov rsi, r8 ; /* move in back to %rsi, toss from */ - jmp L_while_test - -L_copy_two: - rep movsw - mov rsi, r8 ; /* move in back to %rsi, toss from */ - jmp L_while_test - -ALIGN 4 -L_check_dist_one: - cmp r15d, 1 ; /* if dist 1, is a memset */ - jne L_check_window - cmp [rsp+40], rdi ; /* if out == beg, outside window */ - je L_check_window - - mov ecx, r14d ; /* ecx = len */ - mov al, [rdi-1] - mov ah, al - - sar ecx, 1 - jnc L_set_two - mov [rdi], al - inc rdi - -L_set_two: - rep stosw - jmp L_while_test - -ALIGN 4 -L_test_for_second_level_length: - test al, 64 - jnz L_test_for_end_of_block ; /* if ((op & 64) != 0) */ - - xor eax, eax - inc eax - shl eax, cl - dec eax - and eax, edx ; /* eax &= hold */ - add eax, r14d ; /* eax += len */ - mov eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/ - jmp L_dolen - -ALIGN 4 -L_test_for_second_level_dist: - test al, 64 - jnz L_invalid_distance_code ; /* if ((op & 64) != 0) */ - - xor eax, eax - inc eax - shl eax, cl - dec eax - and eax, edx ; /* eax &= hold */ - add eax, r15d ; /* eax += dist */ - mov eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/ - jmp L_dodist - -ALIGN 4 -L_clip_window: - mov ecx, eax ; /* ecx = nbytes */ - mov eax, [rsp+92] ; /* eax = wsize, prepare for dist cmp */ - neg ecx ; /* nbytes = -nbytes */ - - cmp eax, r15d - jb L_invalid_distance_too_far ; /* if (dist > wsize) */ - - add ecx, r15d ; /* nbytes = dist - nbytes */ - cmp dword ptr [rsp+96], 0 - jne L_wrap_around_window ; /* if (write != 0) */ - - mov rsi, [rsp+56] ; /* from = window */ - sub eax, ecx ; /* eax -= nbytes */ - add rsi, rax ; /* from += wsize - nbytes */ - - mov eax, r14d ; /* eax = len */ - cmp r14d, ecx - jbe L_do_copy ; /* if (nbytes >= len) */ - - sub eax, ecx ; /* eax -= nbytes */ - rep movsb - mov rsi, rdi - sub rsi, r15 ; /* from = &out[ -dist ] */ - jmp L_do_copy - -ALIGN 4 -L_wrap_around_window: - mov eax, [rsp+96] ; /* eax = write */ - cmp ecx, eax - jbe L_contiguous_in_window ; /* if (write >= nbytes) */ - - mov esi, [rsp+92] ; /* from = wsize */ - add rsi, [rsp+56] ; /* from += window */ - add rsi, rax ; /* from += write */ - sub rsi, rcx ; /* from -= nbytes */ - sub ecx, eax ; /* nbytes -= write */ - - mov eax, r14d ; /* eax = len */ - cmp eax, ecx - jbe L_do_copy ; /* if (nbytes >= len) */ - - sub eax, ecx ; /* len -= nbytes */ - rep movsb - mov rsi, [rsp+56] ; /* from = window */ - mov ecx, [rsp+96] ; /* nbytes = write */ - cmp eax, ecx - jbe L_do_copy ; /* if (nbytes >= len) */ - - sub eax, ecx ; /* len -= nbytes */ - rep movsb - mov rsi, rdi - sub rsi, r15 ; /* from = out - dist */ - jmp L_do_copy - -ALIGN 4 -L_contiguous_in_window: - mov rsi, [rsp+56] ; /* rsi = window */ - add rsi, rax - sub rsi, rcx ; /* from += write - nbytes */ - - mov eax, r14d ; /* eax = len */ - cmp eax, ecx - jbe L_do_copy ; /* if (nbytes >= len) */ - - sub eax, ecx ; /* len -= nbytes */ - rep movsb - mov rsi, rdi - sub rsi, r15 ; /* from = out - dist */ - jmp L_do_copy ; /* if (nbytes >= len) */ - -ALIGN 4 -L_do_copy: - mov ecx, eax ; /* ecx = len */ - rep movsb - - mov rsi, r8 ; /* move in back to %esi, toss from */ - jmp L_while_test - -L_test_for_end_of_block: - test al, 32 - jz L_invalid_literal_length_code - mov dword ptr [rsp+116], 1 - jmp L_break_loop_with_status - -L_invalid_literal_length_code: - mov dword ptr [rsp+116], 2 - jmp L_break_loop_with_status - -L_invalid_distance_code: - mov dword ptr [rsp+116], 3 - jmp L_break_loop_with_status - -L_invalid_distance_too_far: - mov dword ptr [rsp+116], 4 - jmp L_break_loop_with_status - -L_break_loop: - mov dword ptr [rsp+116], 0 - -L_break_loop_with_status: -; /* put in, out, bits, and hold back into ar and pop esp */ - mov [rsp+16], rsi ; /* in */ - mov [rsp+32], rdi ; /* out */ - mov [rsp+88], ebx ; /* bits */ - mov [rsp+80], rdx ; /* hold */ - - mov rax, [rsp] ; /* restore rbp and rsp */ - mov rbp, [rsp+8] - mov rsp, rax - - - - mov rsi,[rsp-8] - mov rdi,[rsp-16] - mov r12,[rsp-24] - mov r13,[rsp-32] - mov r14,[rsp-40] - mov r15,[rsp-48] - mov rbx,[rsp-56] - - ret 0 -; : -; : "m" (ar) -; : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", -; "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" -; ); - -inffas8664fnc ENDP -;_TEXT ENDS -END diff --git a/deps/zlib/contrib/masmx64/readme.txt b/deps/zlib/contrib/masmx64/readme.txt deleted file mode 100644 index 652571c7a52546..00000000000000 --- a/deps/zlib/contrib/masmx64/readme.txt +++ /dev/null @@ -1,31 +0,0 @@ -Summary -------- -This directory contains ASM implementations of the functions -longest_match() and inflate_fast(), for 64 bits x86 (both AMD64 and Intel EM64t), -for use with Microsoft Macro Assembler (x64) for AMD64 and Microsoft C++ 64 bits. - -gvmat64.asm is written by Gilles Vollant (2005), by using Brian Raiter 686/32 bits - assembly optimized version from Jean-loup Gailly original longest_match function - -inffasx64.asm and inffas8664.c were written by Chris Anderson, by optimizing - original function from Mark Adler - -Use instructions ----------------- -Assemble the .asm files using MASM and put the object files into the zlib source -directory. You can also get object files here: - - http://www.winimage.com/zLibDll/zlib124_masm_obj.zip - -define ASMV and ASMINF in your project. Include inffas8664.c in your source tree, -and inffasx64.obj and gvmat64.obj as object to link. - - -Build instructions ------------------- -run bld_64.bat with Microsoft Macro Assembler (x64) for AMD64 (ml64.exe) - -ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK - -You can get Windows 2003 server DDK with ml64 and cl for AMD64 from - http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price) diff --git a/deps/zlib/contrib/masmx86/bld_ml32.bat b/deps/zlib/contrib/masmx86/bld_ml32.bat deleted file mode 100644 index fcf5755e46aed8..00000000000000 --- a/deps/zlib/contrib/masmx86/bld_ml32.bat +++ /dev/null @@ -1,2 +0,0 @@ -ml /coff /Zi /c /Flmatch686.lst match686.asm -ml /coff /Zi /c /Flinffas32.lst inffas32.asm diff --git a/deps/zlib/contrib/masmx86/inffas32.asm b/deps/zlib/contrib/masmx86/inffas32.asm deleted file mode 100644 index cb37a81e4eea5a..00000000000000 --- a/deps/zlib/contrib/masmx86/inffas32.asm +++ /dev/null @@ -1,1080 +0,0 @@ -;/* inffas32.asm is a hand tuned assembler version of inffast.c -- fast decoding -; * -; * inffas32.asm is derivated from inffas86.c, with translation of assembly code -; * -; * Copyright (C) 1995-2003 Mark Adler -; * For conditions of distribution and use, see copyright notice in zlib.h -; * -; * Copyright (C) 2003 Chris Anderson -; * Please use the copyright conditions above. -; * -; * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from -; * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at -; * the moment. I have successfully compiled and tested this code with gcc2.96, -; * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S -; * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX -; * enabled. I will attempt to merge the MMX code into this version. Newer -; * versions of this and inffast.S can be found at -; * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ -; * -; * 2005 : modification by Gilles Vollant -; */ -; For Visual C++ 4.x and higher and ML 6.x and higher -; ml.exe is in directory \MASM611C of Win95 DDK -; ml.exe is also distributed in http://www.masm32.com/masmdl.htm -; and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/ -; -; -; compile with command line option -; ml /coff /Zi /c /Flinffas32.lst inffas32.asm - -; if you define NO_GZIP (see inflate.h), compile with -; ml /coff /Zi /c /Flinffas32.lst /DNO_GUNZIP inffas32.asm - - -; zlib122sup is 0 fort zlib 1.2.2.1 and lower -; zlib122sup is 8 fort zlib 1.2.2.2 and more (with addition of dmax and head -; in inflate_state in inflate.h) -zlib1222sup equ 8 - - -IFDEF GUNZIP - INFLATE_MODE_TYPE equ 11 - INFLATE_MODE_BAD equ 26 -ELSE - IFNDEF NO_GUNZIP - INFLATE_MODE_TYPE equ 11 - INFLATE_MODE_BAD equ 26 - ELSE - INFLATE_MODE_TYPE equ 3 - INFLATE_MODE_BAD equ 17 - ENDIF -ENDIF - - -; 75 "inffast.S" -;FILE "inffast.S" - -;;;GLOBAL _inflate_fast - -;;;SECTION .text - - - - .586p - .mmx - - name inflate_fast_x86 - .MODEL FLAT - -_DATA segment -inflate_fast_use_mmx: - dd 1 - - -_TEXT segment - - - -ALIGN 4 - db 'Fast decoding Code from Chris Anderson' - db 0 - -ALIGN 4 -invalid_literal_length_code_msg: - db 'invalid literal/length code' - db 0 - -ALIGN 4 -invalid_distance_code_msg: - db 'invalid distance code' - db 0 - -ALIGN 4 -invalid_distance_too_far_msg: - db 'invalid distance too far back' - db 0 - - -ALIGN 4 -inflate_fast_mask: -dd 0 -dd 1 -dd 3 -dd 7 -dd 15 -dd 31 -dd 63 -dd 127 -dd 255 -dd 511 -dd 1023 -dd 2047 -dd 4095 -dd 8191 -dd 16383 -dd 32767 -dd 65535 -dd 131071 -dd 262143 -dd 524287 -dd 1048575 -dd 2097151 -dd 4194303 -dd 8388607 -dd 16777215 -dd 33554431 -dd 67108863 -dd 134217727 -dd 268435455 -dd 536870911 -dd 1073741823 -dd 2147483647 -dd 4294967295 - - -mode_state equ 0 ;/* state->mode */ -wsize_state equ (32+zlib1222sup) ;/* state->wsize */ -write_state equ (36+4+zlib1222sup) ;/* state->write */ -window_state equ (40+4+zlib1222sup) ;/* state->window */ -hold_state equ (44+4+zlib1222sup) ;/* state->hold */ -bits_state equ (48+4+zlib1222sup) ;/* state->bits */ -lencode_state equ (64+4+zlib1222sup) ;/* state->lencode */ -distcode_state equ (68+4+zlib1222sup) ;/* state->distcode */ -lenbits_state equ (72+4+zlib1222sup) ;/* state->lenbits */ -distbits_state equ (76+4+zlib1222sup) ;/* state->distbits */ - - -;;SECTION .text -; 205 "inffast.S" -;GLOBAL inflate_fast_use_mmx - -;SECTION .data - - -; GLOBAL inflate_fast_use_mmx:object -;.size inflate_fast_use_mmx, 4 -; 226 "inffast.S" -;SECTION .text - -ALIGN 4 -_inflate_fast proc near -.FPO (16, 4, 0, 0, 1, 0) - push edi - push esi - push ebp - push ebx - pushfd - sub esp,64 - cld - - - - - mov esi, [esp+88] - mov edi, [esi+28] - - - - - - - - mov edx, [esi+4] - mov eax, [esi+0] - - add edx,eax - sub edx,11 - - mov [esp+44],eax - mov [esp+20],edx - - mov ebp, [esp+92] - mov ecx, [esi+16] - mov ebx, [esi+12] - - sub ebp,ecx - neg ebp - add ebp,ebx - - sub ecx,257 - add ecx,ebx - - mov [esp+60],ebx - mov [esp+40],ebp - mov [esp+16],ecx -; 285 "inffast.S" - mov eax, [edi+lencode_state] - mov ecx, [edi+distcode_state] - - mov [esp+8],eax - mov [esp+12],ecx - - mov eax,1 - mov ecx, [edi+lenbits_state] - shl eax,cl - dec eax - mov [esp+0],eax - - mov eax,1 - mov ecx, [edi+distbits_state] - shl eax,cl - dec eax - mov [esp+4],eax - - mov eax, [edi+wsize_state] - mov ecx, [edi+write_state] - mov edx, [edi+window_state] - - mov [esp+52],eax - mov [esp+48],ecx - mov [esp+56],edx - - mov ebp, [edi+hold_state] - mov ebx, [edi+bits_state] -; 321 "inffast.S" - mov esi, [esp+44] - mov ecx, [esp+20] - cmp ecx,esi - ja L_align_long - - add ecx,11 - sub ecx,esi - mov eax,12 - sub eax,ecx - lea edi, [esp+28] - rep movsb - mov ecx,eax - xor eax,eax - rep stosb - lea esi, [esp+28] - mov [esp+20],esi - jmp L_is_aligned - - -L_align_long: - test esi,3 - jz L_is_aligned - xor eax,eax - mov al, [esi] - inc esi - mov ecx,ebx - add ebx,8 - shl eax,cl - or ebp,eax - jmp L_align_long - -L_is_aligned: - mov edi, [esp+60] -; 366 "inffast.S" -L_check_mmx: - cmp dword ptr [inflate_fast_use_mmx],2 - je L_init_mmx - ja L_do_loop - - push eax - push ebx - push ecx - push edx - pushfd - mov eax, [esp] - xor dword ptr [esp],0200000h - - - - - popfd - pushfd - pop edx - xor edx,eax - jz L_dont_use_mmx - xor eax,eax - cpuid - cmp ebx,0756e6547h - jne L_dont_use_mmx - cmp ecx,06c65746eh - jne L_dont_use_mmx - cmp edx,049656e69h - jne L_dont_use_mmx - mov eax,1 - cpuid - shr eax,8 - and eax,15 - cmp eax,6 - jne L_dont_use_mmx - test edx,0800000h - jnz L_use_mmx - jmp L_dont_use_mmx -L_use_mmx: - mov dword ptr [inflate_fast_use_mmx],2 - jmp L_check_mmx_pop -L_dont_use_mmx: - mov dword ptr [inflate_fast_use_mmx],3 -L_check_mmx_pop: - pop edx - pop ecx - pop ebx - pop eax - jmp L_check_mmx -; 426 "inffast.S" -ALIGN 4 -L_do_loop: -; 437 "inffast.S" - cmp bl,15 - ja L_get_length_code - - xor eax,eax - lodsw - mov cl,bl - add bl,16 - shl eax,cl - or ebp,eax - -L_get_length_code: - mov edx, [esp+0] - mov ecx, [esp+8] - and edx,ebp - mov eax, [ecx+edx*4] - -L_dolen: - - - - - - - mov cl,ah - sub bl,ah - shr ebp,cl - - - - - - - test al,al - jnz L_test_for_length_base - - shr eax,16 - stosb - -L_while_test: - - - cmp [esp+16],edi - jbe L_break_loop - - cmp [esp+20],esi - ja L_do_loop - jmp L_break_loop - -L_test_for_length_base: -; 502 "inffast.S" - mov edx,eax - shr edx,16 - mov cl,al - - test al,16 - jz L_test_for_second_level_length - and cl,15 - jz L_save_len - cmp bl,cl - jae L_add_bits_to_len - - mov ch,cl - xor eax,eax - lodsw - mov cl,bl - add bl,16 - shl eax,cl - or ebp,eax - mov cl,ch - -L_add_bits_to_len: - mov eax,1 - shl eax,cl - dec eax - sub bl,cl - and eax,ebp - shr ebp,cl - add edx,eax - -L_save_len: - mov [esp+24],edx - - -L_decode_distance: -; 549 "inffast.S" - cmp bl,15 - ja L_get_distance_code - - xor eax,eax - lodsw - mov cl,bl - add bl,16 - shl eax,cl - or ebp,eax - -L_get_distance_code: - mov edx, [esp+4] - mov ecx, [esp+12] - and edx,ebp - mov eax, [ecx+edx*4] - - -L_dodist: - mov edx,eax - shr edx,16 - mov cl,ah - sub bl,ah - shr ebp,cl -; 584 "inffast.S" - mov cl,al - - test al,16 - jz L_test_for_second_level_dist - and cl,15 - jz L_check_dist_one - cmp bl,cl - jae L_add_bits_to_dist - - mov ch,cl - xor eax,eax - lodsw - mov cl,bl - add bl,16 - shl eax,cl - or ebp,eax - mov cl,ch - -L_add_bits_to_dist: - mov eax,1 - shl eax,cl - dec eax - sub bl,cl - and eax,ebp - shr ebp,cl - add edx,eax - jmp L_check_window - -L_check_window: -; 625 "inffast.S" - mov [esp+44],esi - mov eax,edi - sub eax, [esp+40] - - cmp eax,edx - jb L_clip_window - - mov ecx, [esp+24] - mov esi,edi - sub esi,edx - - sub ecx,3 - mov al, [esi] - mov [edi],al - mov al, [esi+1] - mov dl, [esi+2] - add esi,3 - mov [edi+1],al - mov [edi+2],dl - add edi,3 - rep movsb - - mov esi, [esp+44] - jmp L_while_test - -ALIGN 4 -L_check_dist_one: - cmp edx,1 - jne L_check_window - cmp [esp+40],edi - je L_check_window - - dec edi - mov ecx, [esp+24] - mov al, [edi] - sub ecx,3 - - mov [edi+1],al - mov [edi+2],al - mov [edi+3],al - add edi,4 - rep stosb - - jmp L_while_test - -ALIGN 4 -L_test_for_second_level_length: - - - - - test al,64 - jnz L_test_for_end_of_block - - mov eax,1 - shl eax,cl - dec eax - and eax,ebp - add eax,edx - mov edx, [esp+8] - mov eax, [edx+eax*4] - jmp L_dolen - -ALIGN 4 -L_test_for_second_level_dist: - - - - - test al,64 - jnz L_invalid_distance_code - - mov eax,1 - shl eax,cl - dec eax - and eax,ebp - add eax,edx - mov edx, [esp+12] - mov eax, [edx+eax*4] - jmp L_dodist - -ALIGN 4 -L_clip_window: -; 721 "inffast.S" - mov ecx,eax - mov eax, [esp+52] - neg ecx - mov esi, [esp+56] - - cmp eax,edx - jb L_invalid_distance_too_far - - add ecx,edx - cmp dword ptr [esp+48],0 - jne L_wrap_around_window - - sub eax,ecx - add esi,eax -; 749 "inffast.S" - mov eax, [esp+24] - cmp eax,ecx - jbe L_do_copy1 - - sub eax,ecx - rep movsb - mov esi,edi - sub esi,edx - jmp L_do_copy1 - - cmp eax,ecx - jbe L_do_copy1 - - sub eax,ecx - rep movsb - mov esi,edi - sub esi,edx - jmp L_do_copy1 - -L_wrap_around_window: -; 793 "inffast.S" - mov eax, [esp+48] - cmp ecx,eax - jbe L_contiguous_in_window - - add esi, [esp+52] - add esi,eax - sub esi,ecx - sub ecx,eax - - - mov eax, [esp+24] - cmp eax,ecx - jbe L_do_copy1 - - sub eax,ecx - rep movsb - mov esi, [esp+56] - mov ecx, [esp+48] - cmp eax,ecx - jbe L_do_copy1 - - sub eax,ecx - rep movsb - mov esi,edi - sub esi,edx - jmp L_do_copy1 - -L_contiguous_in_window: -; 836 "inffast.S" - add esi,eax - sub esi,ecx - - - mov eax, [esp+24] - cmp eax,ecx - jbe L_do_copy1 - - sub eax,ecx - rep movsb - mov esi,edi - sub esi,edx - -L_do_copy1: -; 862 "inffast.S" - mov ecx,eax - rep movsb - - mov esi, [esp+44] - jmp L_while_test -; 878 "inffast.S" -ALIGN 4 -L_init_mmx: - emms - - - - - - movd mm0,ebp - mov ebp,ebx -; 896 "inffast.S" - movd mm4,dword ptr [esp+0] - movq mm3,mm4 - movd mm5,dword ptr [esp+4] - movq mm2,mm5 - pxor mm1,mm1 - mov ebx, [esp+8] - jmp L_do_loop_mmx - -ALIGN 4 -L_do_loop_mmx: - psrlq mm0,mm1 - - cmp ebp,32 - ja L_get_length_code_mmx - - movd mm6,ebp - movd mm7,dword ptr [esi] - add esi,4 - psllq mm7,mm6 - add ebp,32 - por mm0,mm7 - -L_get_length_code_mmx: - pand mm4,mm0 - movd eax,mm4 - movq mm4,mm3 - mov eax, [ebx+eax*4] - -L_dolen_mmx: - movzx ecx,ah - movd mm1,ecx - sub ebp,ecx - - test al,al - jnz L_test_for_length_base_mmx - - shr eax,16 - stosb - -L_while_test_mmx: - - - cmp [esp+16],edi - jbe L_break_loop - - cmp [esp+20],esi - ja L_do_loop_mmx - jmp L_break_loop - -L_test_for_length_base_mmx: - - mov edx,eax - shr edx,16 - - test al,16 - jz L_test_for_second_level_length_mmx - and eax,15 - jz L_decode_distance_mmx - - psrlq mm0,mm1 - movd mm1,eax - movd ecx,mm0 - sub ebp,eax - and ecx, [inflate_fast_mask+eax*4] - add edx,ecx - -L_decode_distance_mmx: - psrlq mm0,mm1 - - cmp ebp,32 - ja L_get_dist_code_mmx - - movd mm6,ebp - movd mm7,dword ptr [esi] - add esi,4 - psllq mm7,mm6 - add ebp,32 - por mm0,mm7 - -L_get_dist_code_mmx: - mov ebx, [esp+12] - pand mm5,mm0 - movd eax,mm5 - movq mm5,mm2 - mov eax, [ebx+eax*4] - -L_dodist_mmx: - - movzx ecx,ah - mov ebx,eax - shr ebx,16 - sub ebp,ecx - movd mm1,ecx - - test al,16 - jz L_test_for_second_level_dist_mmx - and eax,15 - jz L_check_dist_one_mmx - -L_add_bits_to_dist_mmx: - psrlq mm0,mm1 - movd mm1,eax - movd ecx,mm0 - sub ebp,eax - and ecx, [inflate_fast_mask+eax*4] - add ebx,ecx - -L_check_window_mmx: - mov [esp+44],esi - mov eax,edi - sub eax, [esp+40] - - cmp eax,ebx - jb L_clip_window_mmx - - mov ecx,edx - mov esi,edi - sub esi,ebx - - sub ecx,3 - mov al, [esi] - mov [edi],al - mov al, [esi+1] - mov dl, [esi+2] - add esi,3 - mov [edi+1],al - mov [edi+2],dl - add edi,3 - rep movsb - - mov esi, [esp+44] - mov ebx, [esp+8] - jmp L_while_test_mmx - -ALIGN 4 -L_check_dist_one_mmx: - cmp ebx,1 - jne L_check_window_mmx - cmp [esp+40],edi - je L_check_window_mmx - - dec edi - mov ecx,edx - mov al, [edi] - sub ecx,3 - - mov [edi+1],al - mov [edi+2],al - mov [edi+3],al - add edi,4 - rep stosb - - mov ebx, [esp+8] - jmp L_while_test_mmx - -ALIGN 4 -L_test_for_second_level_length_mmx: - test al,64 - jnz L_test_for_end_of_block - - and eax,15 - psrlq mm0,mm1 - movd ecx,mm0 - and ecx, [inflate_fast_mask+eax*4] - add ecx,edx - mov eax, [ebx+ecx*4] - jmp L_dolen_mmx - -ALIGN 4 -L_test_for_second_level_dist_mmx: - test al,64 - jnz L_invalid_distance_code - - and eax,15 - psrlq mm0,mm1 - movd ecx,mm0 - and ecx, [inflate_fast_mask+eax*4] - mov eax, [esp+12] - add ecx,ebx - mov eax, [eax+ecx*4] - jmp L_dodist_mmx - -ALIGN 4 -L_clip_window_mmx: - - mov ecx,eax - mov eax, [esp+52] - neg ecx - mov esi, [esp+56] - - cmp eax,ebx - jb L_invalid_distance_too_far - - add ecx,ebx - cmp dword ptr [esp+48],0 - jne L_wrap_around_window_mmx - - sub eax,ecx - add esi,eax - - cmp edx,ecx - jbe L_do_copy1_mmx - - sub edx,ecx - rep movsb - mov esi,edi - sub esi,ebx - jmp L_do_copy1_mmx - - cmp edx,ecx - jbe L_do_copy1_mmx - - sub edx,ecx - rep movsb - mov esi,edi - sub esi,ebx - jmp L_do_copy1_mmx - -L_wrap_around_window_mmx: - - mov eax, [esp+48] - cmp ecx,eax - jbe L_contiguous_in_window_mmx - - add esi, [esp+52] - add esi,eax - sub esi,ecx - sub ecx,eax - - - cmp edx,ecx - jbe L_do_copy1_mmx - - sub edx,ecx - rep movsb - mov esi, [esp+56] - mov ecx, [esp+48] - cmp edx,ecx - jbe L_do_copy1_mmx - - sub edx,ecx - rep movsb - mov esi,edi - sub esi,ebx - jmp L_do_copy1_mmx - -L_contiguous_in_window_mmx: - - add esi,eax - sub esi,ecx - - - cmp edx,ecx - jbe L_do_copy1_mmx - - sub edx,ecx - rep movsb - mov esi,edi - sub esi,ebx - -L_do_copy1_mmx: - - - mov ecx,edx - rep movsb - - mov esi, [esp+44] - mov ebx, [esp+8] - jmp L_while_test_mmx -; 1174 "inffast.S" -L_invalid_distance_code: - - - - - - mov ecx, invalid_distance_code_msg - mov edx,INFLATE_MODE_BAD - jmp L_update_stream_state - -L_test_for_end_of_block: - - - - - - test al,32 - jz L_invalid_literal_length_code - - mov ecx,0 - mov edx,INFLATE_MODE_TYPE - jmp L_update_stream_state - -L_invalid_literal_length_code: - - - - - - mov ecx, invalid_literal_length_code_msg - mov edx,INFLATE_MODE_BAD - jmp L_update_stream_state - -L_invalid_distance_too_far: - - - - mov esi, [esp+44] - mov ecx, invalid_distance_too_far_msg - mov edx,INFLATE_MODE_BAD - jmp L_update_stream_state - -L_update_stream_state: - - mov eax, [esp+88] - test ecx,ecx - jz L_skip_msg - mov [eax+24],ecx -L_skip_msg: - mov eax, [eax+28] - mov [eax+mode_state],edx - jmp L_break_loop - -ALIGN 4 -L_break_loop: -; 1243 "inffast.S" - cmp dword ptr [inflate_fast_use_mmx],2 - jne L_update_next_in - - - - mov ebx,ebp - -L_update_next_in: -; 1266 "inffast.S" - mov eax, [esp+88] - mov ecx,ebx - mov edx, [eax+28] - shr ecx,3 - sub esi,ecx - shl ecx,3 - sub ebx,ecx - mov [eax+12],edi - mov [edx+bits_state],ebx - mov ecx,ebx - - lea ebx, [esp+28] - cmp [esp+20],ebx - jne L_buf_not_used - - sub esi,ebx - mov ebx, [eax+0] - mov [esp+20],ebx - add esi,ebx - mov ebx, [eax+4] - sub ebx,11 - add [esp+20],ebx - -L_buf_not_used: - mov [eax+0],esi - - mov ebx,1 - shl ebx,cl - dec ebx - - - - - - cmp dword ptr [inflate_fast_use_mmx],2 - jne L_update_hold - - - - psrlq mm0,mm1 - movd ebp,mm0 - - emms - -L_update_hold: - - - - and ebp,ebx - mov [edx+hold_state],ebp - - - - - mov ebx, [esp+20] - cmp ebx,esi - jbe L_last_is_smaller - - sub ebx,esi - add ebx,11 - mov [eax+4],ebx - jmp L_fixup_out -L_last_is_smaller: - sub esi,ebx - neg esi - add esi,11 - mov [eax+4],esi - - - - -L_fixup_out: - - mov ebx, [esp+16] - cmp ebx,edi - jbe L_end_is_smaller - - sub ebx,edi - add ebx,257 - mov [eax+16],ebx - jmp L_done -L_end_is_smaller: - sub edi,ebx - neg edi - add edi,257 - mov [eax+16],edi - - - - - -L_done: - add esp,64 - popfd - pop ebx - pop ebp - pop esi - pop edi - ret -_inflate_fast endp - -_TEXT ends -end diff --git a/deps/zlib/contrib/masmx86/match686.asm b/deps/zlib/contrib/masmx86/match686.asm deleted file mode 100644 index 69e0eed01dec79..00000000000000 --- a/deps/zlib/contrib/masmx86/match686.asm +++ /dev/null @@ -1,479 +0,0 @@ -; match686.asm -- Asm portion of the optimized longest_match for 32 bits x86 -; Copyright (C) 1995-1996 Jean-loup Gailly, Brian Raiter and Gilles Vollant. -; File written by Gilles Vollant, by converting match686.S from Brian Raiter -; for MASM. This is as assembly version of longest_match -; from Jean-loup Gailly in deflate.c -; -; http://www.zlib.net -; http://www.winimage.com/zLibDll -; http://www.muppetlabs.com/~breadbox/software/assembly.html -; -; For Visual C++ 4.x and higher and ML 6.x and higher -; ml.exe is distributed in -; http://www.microsoft.com/downloads/details.aspx?FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64 -; -; this file contain two implementation of longest_match -; -; this longest_match was written by Brian raiter (1998), optimized for Pentium Pro -; (and the faster known version of match_init on modern Core 2 Duo and AMD Phenom) -; -; for using an assembly version of longest_match, you need define ASMV in project -; -; compile the asm file running -; ml /coff /Zi /c /Flmatch686.lst match686.asm -; and do not include match686.obj in your project -; -; note: contrib of zLib 1.2.3 and earlier contained both a deprecated version for -; Pentium (prior Pentium Pro) and this version for Pentium Pro and modern processor -; with autoselect (with cpu detection code) -; if you want support the old pentium optimization, you can still use these version -; -; this file is not optimized for old pentium, but it compatible with all x86 32 bits -; processor (starting 80386) -; -; -; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2 - -;uInt longest_match(s, cur_match) -; deflate_state *s; -; IPos cur_match; /* current match */ - - NbStack equ 76 - cur_match equ dword ptr[esp+NbStack-0] - str_s equ dword ptr[esp+NbStack-4] -; 5 dword on top (ret,ebp,esi,edi,ebx) - adrret equ dword ptr[esp+NbStack-8] - pushebp equ dword ptr[esp+NbStack-12] - pushedi equ dword ptr[esp+NbStack-16] - pushesi equ dword ptr[esp+NbStack-20] - pushebx equ dword ptr[esp+NbStack-24] - - chain_length equ dword ptr [esp+NbStack-28] - limit equ dword ptr [esp+NbStack-32] - best_len equ dword ptr [esp+NbStack-36] - window equ dword ptr [esp+NbStack-40] - prev equ dword ptr [esp+NbStack-44] - scan_start equ word ptr [esp+NbStack-48] - wmask equ dword ptr [esp+NbStack-52] - match_start_ptr equ dword ptr [esp+NbStack-56] - nice_match equ dword ptr [esp+NbStack-60] - scan equ dword ptr [esp+NbStack-64] - - windowlen equ dword ptr [esp+NbStack-68] - match_start equ dword ptr [esp+NbStack-72] - strend equ dword ptr [esp+NbStack-76] - NbStackAdd equ (NbStack-24) - - .386p - - name gvmatch - .MODEL FLAT - - - -; all the +zlib1222add offsets are due to the addition of fields -; in zlib in the deflate_state structure since the asm code was first written -; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). -; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). -; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). - - zlib1222add equ 8 - -; Note : these value are good with a 8 bytes boundary pack structure - dep_chain_length equ 74h+zlib1222add - dep_window equ 30h+zlib1222add - dep_strstart equ 64h+zlib1222add - dep_prev_length equ 70h+zlib1222add - dep_nice_match equ 88h+zlib1222add - dep_w_size equ 24h+zlib1222add - dep_prev equ 38h+zlib1222add - dep_w_mask equ 2ch+zlib1222add - dep_good_match equ 84h+zlib1222add - dep_match_start equ 68h+zlib1222add - dep_lookahead equ 6ch+zlib1222add - - -_TEXT segment - -IFDEF NOUNDERLINE - public longest_match - public match_init -ELSE - public _longest_match - public _match_init -ENDIF - - MAX_MATCH equ 258 - MIN_MATCH equ 3 - MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) - - - -MAX_MATCH equ 258 -MIN_MATCH equ 3 -MIN_LOOKAHEAD equ (MAX_MATCH + MIN_MATCH + 1) -MAX_MATCH_8_ equ ((MAX_MATCH + 7) AND 0FFF0h) - - -;;; stack frame offsets - -chainlenwmask equ esp + 0 ; high word: current chain len - ; low word: s->wmask -window equ esp + 4 ; local copy of s->window -windowbestlen equ esp + 8 ; s->window + bestlen -scanstart equ esp + 16 ; first two bytes of string -scanend equ esp + 12 ; last two bytes of string -scanalign equ esp + 20 ; dword-misalignment of string -nicematch equ esp + 24 ; a good enough match size -bestlen equ esp + 28 ; size of best match so far -scan equ esp + 32 ; ptr to string wanting match - -LocalVarsSize equ 36 -; saved ebx byte esp + 36 -; saved edi byte esp + 40 -; saved esi byte esp + 44 -; saved ebp byte esp + 48 -; return address byte esp + 52 -deflatestate equ esp + 56 ; the function arguments -curmatch equ esp + 60 - -;;; Offsets for fields in the deflate_state structure. These numbers -;;; are calculated from the definition of deflate_state, with the -;;; assumption that the compiler will dword-align the fields. (Thus, -;;; changing the definition of deflate_state could easily cause this -;;; program to crash horribly, without so much as a warning at -;;; compile time. Sigh.) - -dsWSize equ 36+zlib1222add -dsWMask equ 44+zlib1222add -dsWindow equ 48+zlib1222add -dsPrev equ 56+zlib1222add -dsMatchLen equ 88+zlib1222add -dsPrevMatch equ 92+zlib1222add -dsStrStart equ 100+zlib1222add -dsMatchStart equ 104+zlib1222add -dsLookahead equ 108+zlib1222add -dsPrevLen equ 112+zlib1222add -dsMaxChainLen equ 116+zlib1222add -dsGoodMatch equ 132+zlib1222add -dsNiceMatch equ 136+zlib1222add - - -;;; match686.asm -- Pentium-Pro-optimized version of longest_match() -;;; Written for zlib 1.1.2 -;;; Copyright (C) 1998 Brian Raiter -;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html -;;; -;; -;; This software is provided 'as-is', without any express or implied -;; warranty. In no event will the authors be held liable for any damages -;; arising from the use of this software. -;; -;; Permission is granted to anyone to use this software for any purpose, -;; including commercial applications, and to alter it and redistribute it -;; freely, subject to the following restrictions: -;; -;; 1. The origin of this software must not be misrepresented; you must not -;; claim that you wrote the original software. If you use this software -;; in a product, an acknowledgment in the product documentation would be -;; appreciated but is not required. -;; 2. Altered source versions must be plainly marked as such, and must not be -;; misrepresented as being the original software -;; 3. This notice may not be removed or altered from any source distribution. -;; - -;GLOBAL _longest_match, _match_init - - -;SECTION .text - -;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch) - -;_longest_match: - IFDEF NOUNDERLINE - longest_match proc near - ELSE - _longest_match proc near - ENDIF -.FPO (9, 4, 0, 0, 1, 0) - -;;; Save registers that the compiler may be using, and adjust esp to -;;; make room for our stack frame. - - push ebp - push edi - push esi - push ebx - sub esp, LocalVarsSize - -;;; Retrieve the function arguments. ecx will hold cur_match -;;; throughout the entire function. edx will hold the pointer to the -;;; deflate_state structure during the function's setup (before -;;; entering the main loop. - - mov edx, [deflatestate] - mov ecx, [curmatch] - -;;; uInt wmask = s->w_mask; -;;; unsigned chain_length = s->max_chain_length; -;;; if (s->prev_length >= s->good_match) { -;;; chain_length >>= 2; -;;; } - - mov eax, [edx + dsPrevLen] - mov ebx, [edx + dsGoodMatch] - cmp eax, ebx - mov eax, [edx + dsWMask] - mov ebx, [edx + dsMaxChainLen] - jl LastMatchGood - shr ebx, 2 -LastMatchGood: - -;;; chainlen is decremented once beforehand so that the function can -;;; use the sign flag instead of the zero flag for the exit test. -;;; It is then shifted into the high word, to make room for the wmask -;;; value, which it will always accompany. - - dec ebx - shl ebx, 16 - or ebx, eax - mov [chainlenwmask], ebx - -;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - - mov eax, [edx + dsNiceMatch] - mov ebx, [edx + dsLookahead] - cmp ebx, eax - jl LookaheadLess - mov ebx, eax -LookaheadLess: mov [nicematch], ebx - -;;; register Bytef *scan = s->window + s->strstart; - - mov esi, [edx + dsWindow] - mov [window], esi - mov ebp, [edx + dsStrStart] - lea edi, [esi + ebp] - mov [scan], edi - -;;; Determine how many bytes the scan ptr is off from being -;;; dword-aligned. - - mov eax, edi - neg eax - and eax, 3 - mov [scanalign], eax - -;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? -;;; s->strstart - (IPos)MAX_DIST(s) : NIL; - - mov eax, [edx + dsWSize] - sub eax, MIN_LOOKAHEAD - sub ebp, eax - jg LimitPositive - xor ebp, ebp -LimitPositive: - -;;; int best_len = s->prev_length; - - mov eax, [edx + dsPrevLen] - mov [bestlen], eax - -;;; Store the sum of s->window + best_len in esi locally, and in esi. - - add esi, eax - mov [windowbestlen], esi - -;;; register ush scan_start = *(ushf*)scan; -;;; register ush scan_end = *(ushf*)(scan+best_len-1); -;;; Posf *prev = s->prev; - - movzx ebx, word ptr [edi] - mov [scanstart], ebx - movzx ebx, word ptr [edi + eax - 1] - mov [scanend], ebx - mov edi, [edx + dsPrev] - -;;; Jump into the main loop. - - mov edx, [chainlenwmask] - jmp short LoopEntry - -align 4 - -;;; do { -;;; match = s->window + cur_match; -;;; if (*(ushf*)(match+best_len-1) != scan_end || -;;; *(ushf*)match != scan_start) continue; -;;; [...] -;;; } while ((cur_match = prev[cur_match & wmask]) > limit -;;; && --chain_length != 0); -;;; -;;; Here is the inner loop of the function. The function will spend the -;;; majority of its time in this loop, and majority of that time will -;;; be spent in the first ten instructions. -;;; -;;; Within this loop: -;;; ebx = scanend -;;; ecx = curmatch -;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) -;;; esi = windowbestlen - i.e., (window + bestlen) -;;; edi = prev -;;; ebp = limit - -LookupLoop: - and ecx, edx - movzx ecx, word ptr [edi + ecx*2] - cmp ecx, ebp - jbe LeaveNow - sub edx, 00010000h - js LeaveNow -LoopEntry: movzx eax, word ptr [esi + ecx - 1] - cmp eax, ebx - jnz LookupLoop - mov eax, [window] - movzx eax, word ptr [eax + ecx] - cmp eax, [scanstart] - jnz LookupLoop - -;;; Store the current value of chainlen. - - mov [chainlenwmask], edx - -;;; Point edi to the string under scrutiny, and esi to the string we -;;; are hoping to match it up with. In actuality, esi and edi are -;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is -;;; initialized to -(MAX_MATCH_8 - scanalign). - - mov esi, [window] - mov edi, [scan] - add esi, ecx - mov eax, [scanalign] - mov edx, 0fffffef8h; -(MAX_MATCH_8) - lea edi, [edi + eax + 0108h] ;MAX_MATCH_8] - lea esi, [esi + eax + 0108h] ;MAX_MATCH_8] - -;;; Test the strings for equality, 8 bytes at a time. At the end, -;;; adjust edx so that it is offset to the exact byte that mismatched. -;;; -;;; We already know at this point that the first three bytes of the -;;; strings match each other, and they can be safely passed over before -;;; starting the compare loop. So what this code does is skip over 0-3 -;;; bytes, as much as necessary in order to dword-align the edi -;;; pointer. (esi will still be misaligned three times out of four.) -;;; -;;; It should be confessed that this loop usually does not represent -;;; much of the total running time. Replacing it with a more -;;; straightforward "rep cmpsb" would not drastically degrade -;;; performance. - -LoopCmps: - mov eax, [esi + edx] - xor eax, [edi + edx] - jnz LeaveLoopCmps - mov eax, [esi + edx + 4] - xor eax, [edi + edx + 4] - jnz LeaveLoopCmps4 - add edx, 8 - jnz LoopCmps - jmp short LenMaximum -LeaveLoopCmps4: add edx, 4 -LeaveLoopCmps: test eax, 0000FFFFh - jnz LenLower - add edx, 2 - shr eax, 16 -LenLower: sub al, 1 - adc edx, 0 - -;;; Calculate the length of the match. If it is longer than MAX_MATCH, -;;; then automatically accept it as the best possible match and leave. - - lea eax, [edi + edx] - mov edi, [scan] - sub eax, edi - cmp eax, MAX_MATCH - jge LenMaximum - -;;; If the length of the match is not longer than the best match we -;;; have so far, then forget it and return to the lookup loop. - - mov edx, [deflatestate] - mov ebx, [bestlen] - cmp eax, ebx - jg LongerMatch - mov esi, [windowbestlen] - mov edi, [edx + dsPrev] - mov ebx, [scanend] - mov edx, [chainlenwmask] - jmp LookupLoop - -;;; s->match_start = cur_match; -;;; best_len = len; -;;; if (len >= nice_match) break; -;;; scan_end = *(ushf*)(scan+best_len-1); - -LongerMatch: mov ebx, [nicematch] - mov [bestlen], eax - mov [edx + dsMatchStart], ecx - cmp eax, ebx - jge LeaveNow - mov esi, [window] - add esi, eax - mov [windowbestlen], esi - movzx ebx, word ptr [edi + eax - 1] - mov edi, [edx + dsPrev] - mov [scanend], ebx - mov edx, [chainlenwmask] - jmp LookupLoop - -;;; Accept the current string, with the maximum possible length. - -LenMaximum: mov edx, [deflatestate] - mov dword ptr [bestlen], MAX_MATCH - mov [edx + dsMatchStart], ecx - -;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; -;;; return s->lookahead; - -LeaveNow: - mov edx, [deflatestate] - mov ebx, [bestlen] - mov eax, [edx + dsLookahead] - cmp ebx, eax - jg LookaheadRet - mov eax, ebx -LookaheadRet: - -;;; Restore the stack and return from whence we came. - - add esp, LocalVarsSize - pop ebx - pop esi - pop edi - pop ebp - - ret -; please don't remove this string ! -; Your can freely use match686 in any free or commercial app if you don't remove the string in the binary! - db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah - - - IFDEF NOUNDERLINE - longest_match endp - ELSE - _longest_match endp - ENDIF - - IFDEF NOUNDERLINE - match_init proc near - ret - match_init endp - ELSE - _match_init proc near - ret - _match_init endp - ENDIF - - -_TEXT ends -end diff --git a/deps/zlib/contrib/masmx86/readme.txt b/deps/zlib/contrib/masmx86/readme.txt deleted file mode 100644 index 3f8888679fc891..00000000000000 --- a/deps/zlib/contrib/masmx86/readme.txt +++ /dev/null @@ -1,27 +0,0 @@ - -Summary -------- -This directory contains ASM implementations of the functions -longest_match() and inflate_fast(). - - -Use instructions ----------------- -Assemble using MASM, and copy the object files into the zlib source -directory, then run the appropriate makefile, as suggested below. You can -donwload MASM from here: - - http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64 - -You can also get objects files here: - - http://www.winimage.com/zLibDll/zlib124_masm_obj.zip - -Build instructions ------------------- -* With Microsoft C and MASM: -nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" OBJA="match686.obj inffas32.obj" - -* With Borland C and TASM: -make -f win32/Makefile.bor LOCAL_ZLIB="-DASMV -DASMINF" OBJA="match686.obj inffas32.obj" OBJPA="+match686c.obj+match686.obj+inffas32.obj" - diff --git a/deps/zlib/contrib/minizip/ChangeLogUnzip b/deps/zlib/contrib/minizip/ChangeLogUnzip new file mode 100644 index 00000000000000..e62af147dce682 --- /dev/null +++ b/deps/zlib/contrib/minizip/ChangeLogUnzip @@ -0,0 +1,67 @@ +Change in 1.01e (12 feb 05) +- Fix in zipOpen2 for globalcomment (Rolf Kalbermatter) +- Fix possible memory leak in unzip.c (Zoran Stevanovic) + +Change in 1.01b (20 may 04) +- Integrate patch from Debian package (submited by Mark Brown) +- Add tools mztools from Xavier Roche + +Change in 1.01 (8 may 04) +- fix buffer overrun risk in unzip.c (Xavier Roche) +- fix a minor buffer insecurity in minizip.c (Mike Whittaker) + +Change in 1.00: (10 sept 03) +- rename to 1.00 +- cosmetic code change + +Change in 0.22: (19 May 03) +- crypting support (unless you define NOCRYPT) +- append file in existing zipfile + +Change in 0.21: (10 Mar 03) +- bug fixes + +Change in 0.17: (27 Jan 02) +- bug fixes + +Change in 0.16: (19 Jan 02) +- Support of ioapi for virtualize zip file access + +Change in 0.15: (19 Mar 98) +- fix memory leak in minizip.c + +Change in 0.14: (10 Mar 98) +- fix bugs in minizip.c sample for zipping big file +- fix problem in month in date handling +- fix bug in unzlocal_GetCurrentFileInfoInternal in unzip.c for + comment handling + +Change in 0.13: (6 Mar 98) +- fix bugs in zip.c +- add real minizip sample + +Change in 0.12: (4 Mar 98) +- add zip.c and zip.h for creates .zip file +- fix change_file_date in miniunz.c for Unix (Jean-loup Gailly) +- fix miniunz.c for file without specific record for directory + +Change in 0.11: (3 Mar 98) +- fix bug in unzGetCurrentFileInfo for get extra field and comment +- enhance miniunz sample, remove the bad unztst.c sample + +Change in 0.10: (2 Mar 98) +- fix bug in unzReadCurrentFile +- rename unzip* to unz* function and structure +- remove Windows-like hungary notation variable name +- modify some structure in unzip.h +- add somes comment in source +- remove unzipGetcCurrentFile function +- replace ZUNZEXPORT by ZEXPORT +- add unzGetLocalExtrafield for get the local extrafield info +- add a new sample, miniunz.c + +Change in 0.4: (25 Feb 98) +- suppress the type unzipFileInZip. + Only on file in the zipfile can be open at the same time +- fix somes typo in code +- added tm_unz structure in unzip_file_info (date/time in readable format) diff --git a/deps/zlib/contrib/minizip/Makefile.am b/deps/zlib/contrib/minizip/Makefile.am deleted file mode 100644 index d343011ebc3b3f..00000000000000 --- a/deps/zlib/contrib/minizip/Makefile.am +++ /dev/null @@ -1,45 +0,0 @@ -lib_LTLIBRARIES = libminizip.la - -if COND_DEMOS -bin_PROGRAMS = miniunzip minizip -endif - -zlib_top_srcdir = $(top_srcdir)/../.. -zlib_top_builddir = $(top_builddir)/../.. - -AM_CPPFLAGS = -I$(zlib_top_srcdir) -AM_LDFLAGS = -L$(zlib_top_builddir) - -if WIN32 -iowin32_src = iowin32.c -iowin32_h = iowin32.h -endif - -libminizip_la_SOURCES = \ - ioapi.c \ - mztools.c \ - unzip.c \ - zip.c \ - ${iowin32_src} - -libminizip_la_LDFLAGS = $(AM_LDFLAGS) -version-info 1:0:0 -lz - -minizip_includedir = $(includedir)/minizip -minizip_include_HEADERS = \ - crypt.h \ - ioapi.h \ - mztools.h \ - unzip.h \ - zip.h \ - ${iowin32_h} - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = minizip.pc - -EXTRA_PROGRAMS = miniunzip minizip - -miniunzip_SOURCES = miniunz.c -miniunzip_LDADD = libminizip.la - -minizip_SOURCES = minizip.c -minizip_LDADD = libminizip.la -lz diff --git a/deps/zlib/contrib/minizip/MiniZip64_Changes.txt b/deps/zlib/contrib/minizip/MiniZip64_Changes.txt deleted file mode 100644 index 13a1bd91a9b00f..00000000000000 --- a/deps/zlib/contrib/minizip/MiniZip64_Changes.txt +++ /dev/null @@ -1,6 +0,0 @@ - -MiniZip 1.1 was derrived from MiniZip at version 1.01f - -Change in 1.0 (Okt 2009) - - **TODO - Add history** - diff --git a/deps/zlib/contrib/minizip/MiniZip64_info.txt b/deps/zlib/contrib/minizip/MiniZip64_info.txt deleted file mode 100644 index 57d715242087b3..00000000000000 --- a/deps/zlib/contrib/minizip/MiniZip64_info.txt +++ /dev/null @@ -1,74 +0,0 @@ -MiniZip - Copyright (c) 1998-2010 - by Gilles Vollant - version 1.1 64 bits from Mathias Svensson - -Introduction ---------------------- -MiniZip 1.1 is built from MiniZip 1.0 by Gilles Vollant ( http://www.winimage.com/zLibDll/minizip.html ) - -When adding ZIP64 support into minizip it would result into risk of breaking compatibility with minizip 1.0. -All possible work was done for compatibility. - - -Background ---------------------- -When adding ZIP64 support Mathias Svensson found that Even Rouault have added ZIP64 -support for unzip.c into minizip for a open source project called gdal ( http://www.gdal.org/ ) - -That was used as a starting point. And after that ZIP64 support was added to zip.c -some refactoring and code cleanup was also done. - - -Changed from MiniZip 1.0 to MiniZip 1.1 ---------------------------------------- -* Added ZIP64 support for unzip ( by Even Rouault ) -* Added ZIP64 support for zip ( by Mathias Svensson ) -* Reverted some changed that Even Rouault did. -* Bunch of patches received from Gulles Vollant that he received for MiniZip from various users. -* Added unzip patch for BZIP Compression method (patch create by Daniel Borca) -* Added BZIP Compress method for zip -* Did some refactoring and code cleanup - - -Credits - - Gilles Vollant - Original MiniZip author - Even Rouault - ZIP64 unzip Support - Daniel Borca - BZip Compression method support in unzip - Mathias Svensson - ZIP64 zip support - Mathias Svensson - BZip Compression method support in zip - - Resources - - ZipLayout http://result42.com/projects/ZipFileLayout - Command line tool for Windows that shows the layout and information of the headers in a zip archive. - Used when debugging and validating the creation of zip files using MiniZip64 - - - ZIP App Note http://www.pkware.com/documents/casestudies/APPNOTE.TXT - Zip File specification - - -Notes. - * To be able to use BZip compression method in zip64.c or unzip64.c the BZIP2 lib is needed and HAVE_BZIP2 need to be defined. - -License ----------------------------------------------------------- - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - ----------------------------------------------------------- - diff --git a/deps/zlib/contrib/minizip/configure.ac b/deps/zlib/contrib/minizip/configure.ac deleted file mode 100644 index 5b11970977f03d..00000000000000 --- a/deps/zlib/contrib/minizip/configure.ac +++ /dev/null @@ -1,32 +0,0 @@ -# -*- Autoconf -*- -# Process this file with autoconf to produce a configure script. - -AC_INIT([minizip], [1.2.11], [bugzilla.redhat.com]) -AC_CONFIG_SRCDIR([minizip.c]) -AM_INIT_AUTOMAKE([foreign]) -LT_INIT - -AC_MSG_CHECKING([whether to build example programs]) -AC_ARG_ENABLE([demos], AC_HELP_STRING([--enable-demos], [build example programs])) -AM_CONDITIONAL([COND_DEMOS], [test "$enable_demos" = yes]) -if test "$enable_demos" = yes -then - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi - -case "${host}" in - *-mingw* | mingw*) - WIN32="yes" - ;; - *) - ;; -esac -AM_CONDITIONAL([WIN32], [test "${WIN32}" = "yes"]) - - -AC_SUBST([HAVE_UNISTD_H], [0]) -AC_CHECK_HEADER([unistd.h], [HAVE_UNISTD_H=1], []) -AC_CONFIG_FILES([Makefile minizip.pc]) -AC_OUTPUT diff --git a/deps/zlib/contrib/minizip/ioapi.c b/deps/zlib/contrib/minizip/ioapi.c index 7f5c191b2afd16..543910b5e118a4 100644 --- a/deps/zlib/contrib/minizip/ioapi.c +++ b/deps/zlib/contrib/minizip/ioapi.c @@ -14,7 +14,7 @@ #define _CRT_SECURE_NO_WARNINGS #endif -#if defined(__APPLE__) || defined(IOAPI_NO_64) +#if defined(__APPLE__) || defined(__Fuchsia__) || defined(IOAPI_NO_64) // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions #define FOPEN_FUNC(filename, mode) fopen(filename, mode) #define FTELLO_FUNC(stream) ftello(stream) diff --git a/deps/zlib/contrib/minizip/ioapi.h b/deps/zlib/contrib/minizip/ioapi.h index 8dcbdb06e35ad5..c1b7a54847f552 100644 --- a/deps/zlib/contrib/minizip/ioapi.h +++ b/deps/zlib/contrib/minizip/ioapi.h @@ -43,7 +43,7 @@ #include #include -#include "zlib.h" +#include "third_party/zlib/zlib.h" #if defined(USE_FILE32API) #define fopen64 fopen diff --git a/deps/zlib/contrib/minizip/iowin32.c b/deps/zlib/contrib/minizip/iowin32.c index 274f39eb1dd2c6..246ceb91a13942 100644 --- a/deps/zlib/contrib/minizip/iowin32.c +++ b/deps/zlib/contrib/minizip/iowin32.c @@ -26,12 +26,19 @@ #endif +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x601 +#endif + +#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 // see Include/shared/winapifamily.h in the Windows Kit #if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API))) #if WINAPI_FAMILY_ONE_PARTITION(WINAPI_FAMILY, WINAPI_PARTITION_APP) #define IOWIN32_USING_WINRT_API 1 #endif #endif +#endif voidpf ZCALLBACK win32_open_file_func OF((voidpf opaque, const char* filename, int mode)); uLong ZCALLBACK win32_read_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); diff --git a/deps/zlib/contrib/minizip/make_vms.com b/deps/zlib/contrib/minizip/make_vms.com deleted file mode 100644 index 9ac13a98fa5fb4..00000000000000 --- a/deps/zlib/contrib/minizip/make_vms.com +++ /dev/null @@ -1,25 +0,0 @@ -$ if f$search("ioapi.h_orig") .eqs. "" then copy ioapi.h ioapi.h_orig -$ open/write zdef vmsdefs.h -$ copy sys$input: zdef -$ deck -#define unix -#define fill_zlib_filefunc64_32_def_from_filefunc32 fillzffunc64from -#define Write_Zip64EndOfCentralDirectoryLocator Write_Zip64EoDLocator -#define Write_Zip64EndOfCentralDirectoryRecord Write_Zip64EoDRecord -#define Write_EndOfCentralDirectoryRecord Write_EoDRecord -$ eod -$ close zdef -$ copy vmsdefs.h,ioapi.h_orig ioapi.h -$ cc/include=[--]/prefix=all ioapi.c -$ cc/include=[--]/prefix=all miniunz.c -$ cc/include=[--]/prefix=all unzip.c -$ cc/include=[--]/prefix=all minizip.c -$ cc/include=[--]/prefix=all zip.c -$ link miniunz,unzip,ioapi,[--]libz.olb/lib -$ link minizip,zip,ioapi,[--]libz.olb/lib -$ mcr []minizip test minizip_info.txt -$ mcr []miniunz -l test.zip -$ rename minizip_info.txt; minizip_info.txt_old -$ mcr []miniunz test.zip -$ delete test.zip;* -$exit diff --git a/deps/zlib/contrib/minizip/miniunzip.1 b/deps/zlib/contrib/minizip/miniunzip.1 deleted file mode 100644 index 111ac69190f0b2..00000000000000 --- a/deps/zlib/contrib/minizip/miniunzip.1 +++ /dev/null @@ -1,63 +0,0 @@ -.\" Hey, EMACS: -*- nroff -*- -.TH miniunzip 1 "Nov 7, 2001" -.\" Please adjust this date whenever revising the manpage. -.\" -.\" Some roff macros, for reference: -.\" .nh disable hyphenation -.\" .hy enable hyphenation -.\" .ad l left justify -.\" .ad b justify to both left and right margins -.\" .nf disable filling -.\" .fi enable filling -.\" .br insert line break -.\" .sp insert n+1 empty lines -.\" for manpage-specific macros, see man(7) -.SH NAME -miniunzip - uncompress and examine ZIP archives -.SH SYNOPSIS -.B miniunzip -.RI [ -exvlo ] -zipfile [ files_to_extract ] [-d tempdir] -.SH DESCRIPTION -.B minizip -is a simple tool which allows the extraction of compressed file -archives in the ZIP format used by the MS-DOS utility PKZIP. It was -written as a demonstration of the -.IR zlib (3) -library and therefore lack many of the features of the -.IR unzip (1) -program. -.SH OPTIONS -A number of options are supported. With the exception of -.BI \-d\ tempdir -these must be supplied before any -other arguments and are: -.TP -.BI \-l\ ,\ \-\-v -List the files in the archive without extracting them. -.TP -.B \-o -Overwrite files without prompting for confirmation. -.TP -.B \-x -Extract files (default). -.PP -The -.I zipfile -argument is the name of the archive to process. The next argument can be used -to specify a single file to extract from the archive. - -Lastly, the following option can be specified at the end of the command-line: -.TP -.BI \-d\ tempdir -Extract the archive in the directory -.I tempdir -rather than the current directory. -.SH SEE ALSO -.BR minizip (1), -.BR zlib (3), -.BR unzip (1). -.SH AUTHOR -This program was written by Gilles Vollant. This manual page was -written by Mark Brown . The -d tempdir option -was added by Dirk Eddelbuettel . diff --git a/deps/zlib/contrib/minizip/minizip.1 b/deps/zlib/contrib/minizip/minizip.1 deleted file mode 100644 index 1154484c1cc158..00000000000000 --- a/deps/zlib/contrib/minizip/minizip.1 +++ /dev/null @@ -1,46 +0,0 @@ -.\" Hey, EMACS: -*- nroff -*- -.TH minizip 1 "May 2, 2001" -.\" Please adjust this date whenever revising the manpage. -.\" -.\" Some roff macros, for reference: -.\" .nh disable hyphenation -.\" .hy enable hyphenation -.\" .ad l left justify -.\" .ad b justify to both left and right margins -.\" .nf disable filling -.\" .fi enable filling -.\" .br insert line break -.\" .sp insert n+1 empty lines -.\" for manpage-specific macros, see man(7) -.SH NAME -minizip - create ZIP archives -.SH SYNOPSIS -.B minizip -.RI [ -o ] -zipfile [ " files" ... ] -.SH DESCRIPTION -.B minizip -is a simple tool which allows the creation of compressed file archives -in the ZIP format used by the MS-DOS utility PKZIP. It was written as -a demonstration of the -.IR zlib (3) -library and therefore lack many of the features of the -.IR zip (1) -program. -.SH OPTIONS -The first argument supplied is the name of the ZIP archive to create or -.RI -o -in which case it is ignored and the second argument treated as the -name of the ZIP file. If the ZIP file already exists it will be -overwritten. -.PP -Subsequent arguments specify a list of files to place in the ZIP -archive. If none are specified then an empty archive will be created. -.SH SEE ALSO -.BR miniunzip (1), -.BR zlib (3), -.BR zip (1). -.SH AUTHOR -This program was written by Gilles Vollant. This manual page was -written by Mark Brown . - diff --git a/deps/zlib/contrib/minizip/minizip.pc.in b/deps/zlib/contrib/minizip/minizip.pc.in deleted file mode 100644 index 69b5b7fdcb3b4a..00000000000000 --- a/deps/zlib/contrib/minizip/minizip.pc.in +++ /dev/null @@ -1,12 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@/minizip - -Name: minizip -Description: Minizip zip file manipulation library -Requires: -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lminizip -Libs.private: -lz -Cflags: -I${includedir} diff --git a/deps/zlib/contrib/minizip/mztools.c b/deps/zlib/contrib/minizip/mztools.c index 96891c2e0b71ef..8bf9cca326338a 100644 --- a/deps/zlib/contrib/minizip/mztools.c +++ b/deps/zlib/contrib/minizip/mztools.c @@ -8,7 +8,7 @@ #include #include #include -#include "zlib.h" +#include "third_party/zlib/zlib.h" #include "unzip.h" #define READ_8(adr) ((unsigned char)*(adr)) diff --git a/deps/zlib/contrib/minizip/mztools.h b/deps/zlib/contrib/minizip/mztools.h index a49a426ec2fcb2..f295ffeda6afcf 100644 --- a/deps/zlib/contrib/minizip/mztools.h +++ b/deps/zlib/contrib/minizip/mztools.h @@ -12,7 +12,7 @@ extern "C" { #endif #ifndef _ZLIB_H -#include "zlib.h" +#include "third_party/zlib/zlib.h" #endif #include "unzip.h" diff --git a/deps/zlib/contrib/minizip/unzip.c b/deps/zlib/contrib/minizip/unzip.c index bcfb9416ec356d..e8b2bc5c766c8a 100644 --- a/deps/zlib/contrib/minizip/unzip.c +++ b/deps/zlib/contrib/minizip/unzip.c @@ -68,11 +68,7 @@ #include #include -#ifndef NOUNCRYPT - #define NOUNCRYPT -#endif - -#include "zlib.h" +#include "third_party/zlib/zlib.h" #include "unzip.h" #ifdef STDC @@ -1630,6 +1626,7 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, zdecode(s->keys,s->pcrc_32_tab,source[i]); s->pfile_in_zip_read->pos_in_zipfile+=12; + s->pfile_in_zip_read->rest_read_compressed-=12; s->encrypted=1; } # endif @@ -1705,11 +1702,6 @@ extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) pfile_in_zip_read_info->stream.avail_out = (uInt)len; - if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && - (!(pfile_in_zip_read_info->raw))) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_uncompressed; - if ((len>pfile_in_zip_read_info->rest_read_compressed+ pfile_in_zip_read_info->stream.avail_in) && (pfile_in_zip_read_info->raw)) diff --git a/deps/zlib/contrib/minizip/unzip.h b/deps/zlib/contrib/minizip/unzip.h index 2104e39150749b..3c0143529b9144 100644 --- a/deps/zlib/contrib/minizip/unzip.h +++ b/deps/zlib/contrib/minizip/unzip.h @@ -48,7 +48,7 @@ extern "C" { #endif #ifndef _ZLIB_H -#include "zlib.h" +#include "third_party/zlib/zlib.h" #endif #ifndef _ZLIBIOAPI_H diff --git a/deps/zlib/contrib/minizip/zip.c b/deps/zlib/contrib/minizip/zip.c index 44e88a9cb9898d..65c0c7251843c0 100644 --- a/deps/zlib/contrib/minizip/zip.c +++ b/deps/zlib/contrib/minizip/zip.c @@ -26,7 +26,7 @@ #include #include #include -#include "zlib.h" +#include "third_party/zlib/zlib.h" #include "zip.h" #ifdef STDC diff --git a/deps/zlib/contrib/minizip/zip.h b/deps/zlib/contrib/minizip/zip.h index 8aaebb623430fc..8c06c0aa7bb08b 100644 --- a/deps/zlib/contrib/minizip/zip.h +++ b/deps/zlib/contrib/minizip/zip.h @@ -47,7 +47,7 @@ extern "C" { //#define HAVE_BZIP2 #ifndef _ZLIB_H -#include "zlib.h" +#include "third_party/zlib/zlib.h" #endif #ifndef _ZLIBIOAPI_H diff --git a/deps/zlib/contrib/optimizations/chunkcopy.h b/deps/zlib/contrib/optimizations/chunkcopy.h new file mode 100644 index 00000000000000..38ba0ed8a27f45 --- /dev/null +++ b/deps/zlib/contrib/optimizations/chunkcopy.h @@ -0,0 +1,444 @@ +/* chunkcopy.h -- fast chunk copy and set operations + * Copyright (C) 2017 ARM, Inc. + * Copyright 2017 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ + +#ifndef CHUNKCOPY_H +#define CHUNKCOPY_H + +#include +#include "zutil.h" + +#define Z_STATIC_ASSERT(name, assert) typedef char name[(assert) ? 1 : -1] + +#if __STDC_VERSION__ >= 199901L +#define Z_RESTRICT restrict +#else +#define Z_RESTRICT +#endif + +#if defined(__clang__) || defined(__GNUC__) || defined(__llvm__) +#define Z_BUILTIN_MEMCPY __builtin_memcpy +#else +#define Z_BUILTIN_MEMCPY zmemcpy +#endif + +#if defined(INFLATE_CHUNK_SIMD_NEON) +#include +typedef uint8x16_t z_vec128i_t; +#elif defined(INFLATE_CHUNK_SIMD_SSE2) +#include +typedef __m128i z_vec128i_t; +#else +#error chunkcopy.h inflate chunk SIMD is not defined for your build target +#endif + +/* + * chunk copy type: the z_vec128i_t type size should be exactly 128-bits + * and equal to CHUNKCOPY_CHUNK_SIZE. + */ +#define CHUNKCOPY_CHUNK_SIZE sizeof(z_vec128i_t) + +Z_STATIC_ASSERT(vector_128_bits_wide, + CHUNKCOPY_CHUNK_SIZE == sizeof(int8_t) * 16); + +/* + * Ask the compiler to perform a wide, unaligned load with a machine + * instruction appropriate for the z_vec128i_t type. + */ +static inline z_vec128i_t loadchunk( + const unsigned char FAR* s) { + z_vec128i_t v; + Z_BUILTIN_MEMCPY(&v, s, sizeof(v)); + return v; +} + +/* + * Ask the compiler to perform a wide, unaligned store with a machine + * instruction appropriate for the z_vec128i_t type. + */ +static inline void storechunk( + unsigned char FAR* d, + const z_vec128i_t v) { + Z_BUILTIN_MEMCPY(d, &v, sizeof(v)); +} + +/* + * Perform a memcpy-like operation, assuming that length is non-zero and that + * it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if + * the length is shorter than this. + * + * It also guarantees that it will properly unroll the data if the distance + * between `out` and `from` is at least CHUNKCOPY_CHUNK_SIZE, which we rely on + * in chunkcopy_relaxed(). + * + * Aside from better memory bus utilisation, this means that short copies + * (CHUNKCOPY_CHUNK_SIZE bytes or fewer) will fall straight through the loop + * without iteration, which will hopefully make the branch prediction more + * reliable. + */ +static inline unsigned char FAR* chunkcopy_core( + unsigned char FAR* out, + const unsigned char FAR* from, + unsigned len) { + const int bump = (--len % CHUNKCOPY_CHUNK_SIZE) + 1; + storechunk(out, loadchunk(from)); + out += bump; + from += bump; + len /= CHUNKCOPY_CHUNK_SIZE; + while (len-- > 0) { + storechunk(out, loadchunk(from)); + out += CHUNKCOPY_CHUNK_SIZE; + from += CHUNKCOPY_CHUNK_SIZE; + } + return out; +} + +/* + * Like chunkcopy_core(), but avoid writing beyond of legal output. + * + * Accepts an additional pointer to the end of safe output. A generic safe + * copy would use (out + len), but it's normally the case that the end of the + * output buffer is beyond the end of the current copy, and this can still be + * exploited. + */ +static inline unsigned char FAR* chunkcopy_core_safe( + unsigned char FAR* out, + const unsigned char FAR* from, + unsigned len, + unsigned char FAR* limit) { + Assert(out + len <= limit, "chunk copy exceeds safety limit"); + if ((limit - out) < (ptrdiff_t)CHUNKCOPY_CHUNK_SIZE) { + const unsigned char FAR* Z_RESTRICT rfrom = from; + if (len & 8) { + Z_BUILTIN_MEMCPY(out, rfrom, 8); + out += 8; + rfrom += 8; + } + if (len & 4) { + Z_BUILTIN_MEMCPY(out, rfrom, 4); + out += 4; + rfrom += 4; + } + if (len & 2) { + Z_BUILTIN_MEMCPY(out, rfrom, 2); + out += 2; + rfrom += 2; + } + if (len & 1) { + *out++ = *rfrom++; + } + return out; + } + return chunkcopy_core(out, from, len); +} + +/* + * Perform short copies until distance can be rewritten as being at least + * CHUNKCOPY_CHUNK_SIZE. + * + * Assumes it's OK to overwrite at least the first 2*CHUNKCOPY_CHUNK_SIZE + * bytes of output even if the copy is shorter than this. This assumption + * holds within zlib inflate_fast(), which starts every iteration with at + * least 258 bytes of output space available (258 being the maximum length + * output from a single token; see inffast.c). + */ +static inline unsigned char FAR* chunkunroll_relaxed( + unsigned char FAR* out, + unsigned FAR* dist, + unsigned FAR* len) { + const unsigned char FAR* from = out - *dist; + while (*dist < *len && *dist < CHUNKCOPY_CHUNK_SIZE) { + storechunk(out, loadchunk(from)); + out += *dist; + *len -= *dist; + *dist += *dist; + } + return out; +} + +#if defined(INFLATE_CHUNK_SIMD_NEON) +/* + * v_load64_dup(): load *src as an unaligned 64-bit int and duplicate it in + * every 64-bit component of the 128-bit result (64-bit int splat). + */ +static inline z_vec128i_t v_load64_dup(const void* src) { + return vcombine_u8(vld1_u8(src), vld1_u8(src)); +} + +/* + * v_load32_dup(): load *src as an unaligned 32-bit int and duplicate it in + * every 32-bit component of the 128-bit result (32-bit int splat). + */ +static inline z_vec128i_t v_load32_dup(const void* src) { + int32_t i32; + Z_BUILTIN_MEMCPY(&i32, src, sizeof(i32)); + return vreinterpretq_u8_s32(vdupq_n_s32(i32)); +} + +/* + * v_load16_dup(): load *src as an unaligned 16-bit int and duplicate it in + * every 16-bit component of the 128-bit result (16-bit int splat). + */ +static inline z_vec128i_t v_load16_dup(const void* src) { + int16_t i16; + Z_BUILTIN_MEMCPY(&i16, src, sizeof(i16)); + return vreinterpretq_u8_s16(vdupq_n_s16(i16)); +} + +/* + * v_load8_dup(): load the 8-bit int *src and duplicate it in every 8-bit + * component of the 128-bit result (8-bit int splat). + */ +static inline z_vec128i_t v_load8_dup(const void* src) { + return vld1q_dup_u8((const uint8_t*)src); +} + +/* + * v_store_128(): store the 128-bit vec in a memory destination (that might + * not be 16-byte aligned) void* out. + */ +static inline void v_store_128(void* out, const z_vec128i_t vec) { + vst1q_u8(out, vec); +} + +#elif defined(INFLATE_CHUNK_SIMD_SSE2) +/* + * v_load64_dup(): load *src as an unaligned 64-bit int and duplicate it in + * every 64-bit component of the 128-bit result (64-bit int splat). + */ +static inline z_vec128i_t v_load64_dup(const void* src) { + int64_t i64; + Z_BUILTIN_MEMCPY(&i64, src, sizeof(i64)); + return _mm_set1_epi64x(i64); +} + +/* + * v_load32_dup(): load *src as an unaligned 32-bit int and duplicate it in + * every 32-bit component of the 128-bit result (32-bit int splat). + */ +static inline z_vec128i_t v_load32_dup(const void* src) { + int32_t i32; + Z_BUILTIN_MEMCPY(&i32, src, sizeof(i32)); + return _mm_set1_epi32(i32); +} + +/* + * v_load16_dup(): load *src as an unaligned 16-bit int and duplicate it in + * every 16-bit component of the 128-bit result (16-bit int splat). + */ +static inline z_vec128i_t v_load16_dup(const void* src) { + int16_t i16; + Z_BUILTIN_MEMCPY(&i16, src, sizeof(i16)); + return _mm_set1_epi16(i16); +} + +/* + * v_load8_dup(): load the 8-bit int *src and duplicate it in every 8-bit + * component of the 128-bit result (8-bit int splat). + */ +static inline z_vec128i_t v_load8_dup(const void* src) { + return _mm_set1_epi8(*(const char*)src); +} + +/* + * v_store_128(): store the 128-bit vec in a memory destination (that might + * not be 16-byte aligned) void* out. + */ +static inline void v_store_128(void* out, const z_vec128i_t vec) { + _mm_storeu_si128((__m128i*)out, vec); +} +#endif + +/* + * Perform an overlapping copy which behaves as a memset() operation, but + * supporting periods other than one, and assume that length is non-zero and + * that it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE*3 bytes of output + * even if the length is shorter than this. + */ +static inline unsigned char FAR* chunkset_core( + unsigned char FAR* out, + unsigned period, + unsigned len) { + z_vec128i_t v; + const int bump = ((len - 1) % sizeof(v)) + 1; + + switch (period) { + case 1: + v = v_load8_dup(out - 1); + v_store_128(out, v); + out += bump; + len -= bump; + while (len > 0) { + v_store_128(out, v); + out += sizeof(v); + len -= sizeof(v); + } + return out; + case 2: + v = v_load16_dup(out - 2); + v_store_128(out, v); + out += bump; + len -= bump; + if (len > 0) { + v = v_load16_dup(out - 2); + do { + v_store_128(out, v); + out += sizeof(v); + len -= sizeof(v); + } while (len > 0); + } + return out; + case 4: + v = v_load32_dup(out - 4); + v_store_128(out, v); + out += bump; + len -= bump; + if (len > 0) { + v = v_load32_dup(out - 4); + do { + v_store_128(out, v); + out += sizeof(v); + len -= sizeof(v); + } while (len > 0); + } + return out; + case 8: + v = v_load64_dup(out - 8); + v_store_128(out, v); + out += bump; + len -= bump; + if (len > 0) { + v = v_load64_dup(out - 8); + do { + v_store_128(out, v); + out += sizeof(v); + len -= sizeof(v); + } while (len > 0); + } + return out; + } + out = chunkunroll_relaxed(out, &period, &len); + return chunkcopy_core(out, out - period, len); +} + +/* + * Perform a memcpy-like operation, but assume that length is non-zero and that + * it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if + * the length is shorter than this. + * + * Unlike chunkcopy_core() above, no guarantee is made regarding the behaviour + * of overlapping buffers, regardless of the distance between the pointers. + * This is reflected in the `restrict`-qualified pointers, allowing the + * compiler to re-order loads and stores. + */ +static inline unsigned char FAR* chunkcopy_relaxed( + unsigned char FAR* Z_RESTRICT out, + const unsigned char FAR* Z_RESTRICT from, + unsigned len) { + return chunkcopy_core(out, from, len); +} + +/* + * Like chunkcopy_relaxed(), but avoid writing beyond of legal output. + * + * Unlike chunkcopy_core_safe() above, no guarantee is made regarding the + * behaviour of overlapping buffers, regardless of the distance between the + * pointers. This is reflected in the `restrict`-qualified pointers, allowing + * the compiler to re-order loads and stores. + * + * Accepts an additional pointer to the end of safe output. A generic safe + * copy would use (out + len), but it's normally the case that the end of the + * output buffer is beyond the end of the current copy, and this can still be + * exploited. + */ +static inline unsigned char FAR* chunkcopy_safe( + unsigned char FAR* out, + const unsigned char FAR* Z_RESTRICT from, + unsigned len, + unsigned char FAR* limit) { + Assert(out + len <= limit, "chunk copy exceeds safety limit"); + return chunkcopy_core_safe(out, from, len, limit); +} + +/* + * Perform chunky copy within the same buffer, where the source and destination + * may potentially overlap. + * + * Assumes that len > 0 on entry, and that it's safe to write at least + * CHUNKCOPY_CHUNK_SIZE*3 bytes to the output. + */ +static inline unsigned char FAR* chunkcopy_lapped_relaxed( + unsigned char FAR* out, + unsigned dist, + unsigned len) { + if (dist < len && dist < CHUNKCOPY_CHUNK_SIZE) { + return chunkset_core(out, dist, len); + } + return chunkcopy_core(out, out - dist, len); +} + +/* + * Behave like chunkcopy_lapped_relaxed(), but avoid writing beyond of legal + * output. + * + * Accepts an additional pointer to the end of safe output. A generic safe + * copy would use (out + len), but it's normally the case that the end of the + * output buffer is beyond the end of the current copy, and this can still be + * exploited. + */ +static inline unsigned char FAR* chunkcopy_lapped_safe( + unsigned char FAR* out, + unsigned dist, + unsigned len, + unsigned char FAR* limit) { + Assert(out + len <= limit, "chunk copy exceeds safety limit"); + if ((limit - out) < (ptrdiff_t)(3 * CHUNKCOPY_CHUNK_SIZE)) { + /* TODO(cavalcantii): try harder to optimise this */ + while (len-- > 0) { + *out = *(out - dist); + out++; + } + return out; + } + return chunkcopy_lapped_relaxed(out, dist, len); +} + +/* + * The chunk-copy code above deals with writing the decoded DEFLATE data to + * the output with SIMD methods to increase decode speed. Reading the input + * to the DEFLATE decoder with a wide, SIMD method can also increase decode + * speed. This option is supported on little endian machines, and reads the + * input data in 64-bit (8 byte) chunks. + */ + +#ifdef INFLATE_CHUNK_READ_64LE +/* + * Buffer the input in a uint64_t (8 bytes) in the wide input reading case. + */ +typedef uint64_t inflate_holder_t; + +/* + * Ask the compiler to perform a wide, unaligned load of a uint64_t using a + * machine instruction appropriate for the uint64_t type. + */ +static inline inflate_holder_t read64le(const unsigned char FAR *in) { + inflate_holder_t input; + Z_BUILTIN_MEMCPY(&input, in, sizeof(input)); + return input; +} +#else +/* + * Otherwise, buffer the input bits using zlib's default input buffer type. + */ +typedef unsigned long inflate_holder_t; + +#endif /* INFLATE_CHUNK_READ_64LE */ + +#undef Z_STATIC_ASSERT +#undef Z_RESTRICT +#undef Z_BUILTIN_MEMCPY + +#endif /* CHUNKCOPY_H */ diff --git a/deps/zlib/contrib/optimizations/inffast_chunk.c b/deps/zlib/contrib/optimizations/inffast_chunk.c new file mode 100644 index 00000000000000..4099edf3961d74 --- /dev/null +++ b/deps/zlib/contrib/optimizations/inffast_chunk.c @@ -0,0 +1,359 @@ +/* inffast_chunk.c -- fast decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "contrib/optimizations/inffast_chunk.h" +#include "contrib/optimizations/chunkcopy.h" + +#ifdef ASMINF +# pragma message("Assembler code may have bugs -- use at your own risk") +#else + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate() execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= INFLATE_FAST_MIN_INPUT (6 or 8 bytes) + strm->avail_out >= INFLATE_FAST_MIN_OUTPUT (258 bytes) + start >= strm->avail_out + state->bits < 8 + (state->hold >> state->bits) == 0 + strm->next_out[0..strm->avail_out] does not overlap with + strm->next_in[0..strm->avail_in] + strm->state->window is allocated with an additional + CHUNKCOPY_CHUNK_SIZE-1 bytes of padding beyond strm->state->wsize + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + INFLATE_FAST_MIN_INPUT: 6 or 8 bytes + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The wide input data reading option reads 64 input bits at a time. Thus, + if strm->avail_in >= 8, then there is enough input to avoid checking for + available input while decoding. Reading consumes the input with: + + hold |= read64le(in) << bits; + in += 6; + bits += 48; + + reporting 6 bytes of new input because |bits| is 0..15 (2 bytes rounded + up, worst case) and 6 bytes is enough to decode as noted above. At exit, + hold &= (1U << bits) - 1 drops excess input to keep the invariant: + + (state->hold >> state->bits) == 0 + + INFLATE_FAST_MIN_OUTPUT: 258 bytes + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + available output space while decoding. + */ +void ZLIB_INTERNAL inflate_fast_chunk_(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ + unsigned char FAR *limit; /* safety limit for chunky copies */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + inflate_holder_t hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in; + last = in + (strm->avail_in - (INFLATE_FAST_MIN_INPUT - 1)); + out = strm->next_out; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - (INFLATE_FAST_MIN_OUTPUT - 1)); + limit = out + strm->avail_out; +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = (state->wnext == 0 && whave >= wsize) ? wsize : state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { +#ifdef INFLATE_CHUNK_READ_64LE + hold |= read64le(in) << bits; + in += 6; + bits += 48; +#else + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; +#endif + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + *out++ = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { +#ifdef INFLATE_CHUNK_READ_64LE + hold |= read64le(in) << bits; + in += 6; + bits += 48; +#else + hold += (unsigned long)(*in++) << bits; + bits += 8; +#endif + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { +#ifdef INFLATE_CHUNK_READ_64LE + hold |= read64le(in) << bits; + in += 6; + bits += 48; +#else + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; +#endif + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { +#ifdef INFLATE_CHUNK_READ_64LE + hold |= read64le(in) << bits; + in += 6; + bits += 48; +#else + hold += (unsigned long)(*in++) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } +#endif + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + *out++ = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + *out++ = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + *out++ = *from++; + } while (--len); + continue; + } +#endif + } + from = window; + if (wnext >= op) { /* contiguous in window */ + from += wnext - op; + } + else { /* wrap around window */ + op -= wnext; + from += wsize - op; + if (op < len) { /* some from end of window */ + len -= op; + out = chunkcopy_safe(out, from, op, limit); + from = window; /* more from start of window */ + op = wnext; + /* This (rare) case can create a situation where + the first chunkcopy below must be checked. + */ + } + } + if (op < len) { /* still need some from output */ + out = chunkcopy_safe(out, from, op, limit); + len -= op; + /* When dist is small the amount of data that can be + copied from the window is also small, and progress + towards the dangerous end of the output buffer is + also small. This means that for trivial memsets and + for chunkunroll_relaxed() a safety check is + unnecessary. However, these conditions may not be + entered at all, and in that case it's possible that + the main copy is near the end. + */ + out = chunkunroll_relaxed(out, &dist, &len); + out = chunkcopy_safe(out, out - dist, len, limit); + } else { + /* from points to window, so there is no risk of + overlapping pointers requiring memset-like behaviour + */ + out = chunkcopy_safe(out, from, len, limit); + } + } + else { + /* Whole reference is in range of current output. No + range checks are necessary because we start with room + for at least 258 bytes of output, so unroll and roundoff + operations can write beyond `out+len` so long as they + stay within 258 bytes of `out`. + */ + out = chunkcopy_lapped_relaxed(out, dist, len); + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in; + strm->next_out = out; + strm->avail_in = (unsigned)(in < last ? + (INFLATE_FAST_MIN_INPUT - 1) + (last - in) : + (INFLATE_FAST_MIN_INPUT - 1) - (in - last)); + strm->avail_out = (unsigned)(out < end ? + (INFLATE_FAST_MIN_OUTPUT - 1) + (end - out) : + (INFLATE_FAST_MIN_OUTPUT - 1) - (out - end)); + state->hold = hold; + state->bits = bits; + + Assert((state->hold >> state->bits) == 0, "invalid input data state"); + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/deps/zlib/contrib/optimizations/inffast_chunk.h b/deps/zlib/contrib/optimizations/inffast_chunk.h new file mode 100644 index 00000000000000..39c771b863c7ed --- /dev/null +++ b/deps/zlib/contrib/optimizations/inffast_chunk.h @@ -0,0 +1,26 @@ +/* inffast_chunk.h -- header to use inffast_chunk.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * Copyright (C) 2017 ARM, Inc. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +#include "inffast.h" + +/* INFLATE_FAST_MIN_INPUT: the minimum number of input bytes needed so that + we can safely call inflate_fast() with only one up-front bounds check. One + length/distance code pair (15 bits for the length code, 5 bits for length + extra, 15 bits for the distance code, 13 bits for distance extra) requires + reading up to 48 input bits (6 bytes). The wide input data reading option + requires a little endian machine, and reads 64 input bits (8 bytes). +*/ +#ifdef INFLATE_CHUNK_READ_64LE +#undef INFLATE_FAST_MIN_INPUT +#define INFLATE_FAST_MIN_INPUT 8 +#endif + +void ZLIB_INTERNAL inflate_fast_chunk_ OF((z_streamp strm, unsigned start)); diff --git a/deps/zlib/contrib/optimizations/inflate.c b/deps/zlib/contrib/optimizations/inflate.c new file mode 100644 index 00000000000000..81d558bd6ef5fa --- /dev/null +++ b/deps/zlib/contrib/optimizations/inflate.c @@ -0,0 +1,1583 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "contrib/optimizations/inffast_chunk.h" +#include "contrib/optimizations/chunkcopy.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local int inflateStateCheck OF((z_streamp strm)); +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + unsigned copy)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, + unsigned len)); + +local int inflateStateCheck(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + state = (struct inflate_state FAR *)strm->state; + if (state == Z_NULL || state->strm != strm || + state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; +} + +int ZEXPORT inflateResetKeep(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return inflateResetKeep(strm); +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 5; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->strm = strm; + state->window = Z_NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ + state->check = 1L; /* 1L is the result of adler32() zero length data */ + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += (unsigned)value << state->bits; + state->bits += (uInt)bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, + state.lencode[low].bits, state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, end, copy) +z_streamp strm; +const Bytef *end; +unsigned copy; +{ + struct inflate_state FAR *state; + unsigned dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + unsigned wsize = 1U << state->wbits; + state->window = (unsigned char FAR *) + ZALLOC(strm, wsize + CHUNKCOPY_CHUNK_SIZE, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; +#ifdef INFLATE_CLEAR_UNUSED_UNDEFINED + /* Copies from the overflow portion of this buffer are undefined and + may cause analysis tools to raise a warning if we don't initialize + it. However, this undefined data overwrites other undefined data + and is subsequently either overwritten or left deliberately + undefined at the end of decode; so there's really no point. + */ + zmemzero(state->window + wsize, CHUNKCOPY_CHUNK_SIZE); +#endif + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state->wsize) { + zmemcpy(state->window, end - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, end - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, end - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (inflateStateCheck(strm) || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + if (state->wbits == 0) + state->wbits = 15; + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + if (len > 15 || len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if ((state->wrap & 4) && hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = ZSWAP32(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (const code FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= INFLATE_FAST_MIN_INPUT && + left >= INFLATE_FAST_MIN_OUTPUT) { + RESTORE(); + inflate_fast_chunk_(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + put = chunkcopy_safe(put, from, copy, put + left); + } + else { /* copy from output */ + copy = state->length; + if (copy > left) copy = left; + put = chunkcopy_lapped_safe(put, state->offset, copy, put + left); + } + left -= copy; + state->length -= copy; + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if ((state->wrap & 4) && ( +#ifdef GUNZIP + state->flags ? hold : +#endif + ZSWAP32(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + /* We write a defined value in the unused space to help mark + * where the stream has ended. We don't use zeros as that can + * mislead clients relying on undefined behavior (i.e. assuming + * that the data is over when the buffer has a zero/null value). + */ + if (left >= CHUNKCOPY_CHUNK_SIZE) + memset(put, 0x55, CHUNKCOPY_CHUNK_SIZE); + else + memset(put, 0x55, left); + + RESTORE(); + if (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH))) + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) +z_streamp strm; +Bytef *dictionary; +uInt *dictLength; +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, + state->whave - state->wnext); + zmemcpy(dictionary + state->whave - state->wnext, + state->window, state->wnext); + } + if (dictLength != Z_NULL) + *dictLength = state->whave; + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long dictid; + int ret; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary identifier */ + if (state->mode == DICT) { + dictid = adler32(0L, Z_NULL, 0); + dictid = adler32(dictid, dictionary, dictLength); + if (dictid != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength); + if (ret) { + state->mode = MEM; + return Z_MEM_ERROR; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +const unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (inflateStateCheck(source) || dest == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); + copy->strm = dest; + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + state->sane = !subvert; + return Z_OK; +#else + (void)subvert; + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +int ZEXPORT inflateValidate(strm, check) +z_streamp strm; +int check; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (check) + state->wrap |= 4; + else + state->wrap &= ~4; + return Z_OK; +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) + return -(1L << 16); + state = (struct inflate_state FAR *)strm->state; + return (long)(((unsigned long)((long)state->back)) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} + +unsigned long ZEXPORT inflateCodesUsed(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) return (unsigned long)-1; + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); +} diff --git a/deps/zlib/contrib/optimizations/insert_string.h b/deps/zlib/contrib/optimizations/insert_string.h new file mode 100644 index 00000000000000..69eee3dc9e91fc --- /dev/null +++ b/deps/zlib/contrib/optimizations/insert_string.h @@ -0,0 +1,122 @@ +/* insert_string.h + * + * Copyright 2019 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ +#ifdef _MSC_VER +#define INLINE __inline +#else +#define INLINE inline +#endif + +/* Optimized insert_string block */ +#if defined(CRC32_SIMD_SSE42_PCLMUL) || defined(CRC32_ARMV8_CRC32) +#define TARGET_CPU_WITH_CRC +// clang-format off +#if defined(CRC32_SIMD_SSE42_PCLMUL) + /* Required to make MSVC bot build pass. */ + #include + #if defined(__GNUC__) || defined(__clang__) + #undef TARGET_CPU_WITH_CRC + #define TARGET_CPU_WITH_CRC __attribute__((target("sse4.2"))) + #endif + + #define _cpu_crc32_u32 _mm_crc32_u32 + +#elif defined(CRC32_ARMV8_CRC32) + #include "arm_features.h" + #if defined(__clang__) + #undef TARGET_CPU_WITH_CRC + #define __crc32cw __builtin_arm_crc32cw + #endif + + #define _cpu_crc32_u32 __crc32cw + + #if defined(__aarch64__) + #define TARGET_CPU_WITH_CRC __attribute__((target("crc"))) + #else // !defined(__aarch64__) + #define TARGET_CPU_WITH_CRC __attribute__((target("armv8-a,crc"))) + #endif // defined(__aarch64__) +#endif +// clang-format on +TARGET_CPU_WITH_CRC +local INLINE Pos insert_string_optimized(deflate_state* const s, + const Pos str) { + Pos ret; + unsigned *ip, val, h = 0; + + ip = (unsigned*)&s->window[str]; + val = *ip; + + if (s->level >= 6) + val &= 0xFFFFFF; + + /* Unlike the case of data integrity checks for GZIP format where the + * polynomial used is defined (https://tools.ietf.org/html/rfc1952#page-11), + * here it is just a hash function for the hash table used while + * performing compression. + */ + h = _cpu_crc32_u32(h, val); + + ret = s->head[h & s->hash_mask]; + s->head[h & s->hash_mask] = str; + s->prev[str & s->w_mask] = ret; + return ret; +} +#endif /* Optimized insert_string block */ + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to UPDATE_HASH are made with consecutive input + * characters, so that a running hash key can be computed from the previous + * key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s, h, c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask) + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to INSERT_STRING are made with consecutive input + * characters and the first MIN_MATCH bytes of str are valid (except for + * the last MIN_MATCH-1 bytes of the input file). + */ +local INLINE Pos insert_string_c(deflate_state* const s, const Pos str) { + Pos ret; + + UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH - 1)]); +#ifdef FASTEST + ret = s->head[s->ins_h]; +#else + ret = s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = str; + + return ret; +} + +local INLINE Pos insert_string(deflate_state* const s, const Pos str) { +/* String dictionary insertion: faster symbol hashing has a positive impact + * on data compression speeds (around 20% on Intel and 36% on Arm Cortex big + * cores). + * A misfeature is that the generated compressed output will differ from + * vanilla zlib (even though it is still valid 'DEFLATE-d' content). + * + * We offer here a way to disable the optimization if there is the expectation + * that compressed content should match when compared to vanilla zlib. + */ +#if !defined(CHROMIUM_ZLIB_NO_CASTAGNOLI) + /* TODO(cavalcantii): unify CPU features code. */ +#if defined(CRC32_ARMV8_CRC32) + if (arm_cpu_enable_crc32) + return insert_string_optimized(s, str); +#elif defined(CRC32_SIMD_SSE42_PCLMUL) + if (x86_cpu_enable_simd) + return insert_string_optimized(s, str); +#endif +#endif + return insert_string_c(s, str); +} diff --git a/deps/zlib/contrib/optimizations/slide_hash_neon.h b/deps/zlib/contrib/optimizations/slide_hash_neon.h new file mode 100644 index 00000000000000..26995d70f709e7 --- /dev/null +++ b/deps/zlib/contrib/optimizations/slide_hash_neon.h @@ -0,0 +1,65 @@ +/* Copyright 2018 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ +#ifndef __SLIDE_HASH__NEON__ +#define __SLIDE_HASH__NEON__ + +#include "deflate.h" +#include + +inline static void ZLIB_INTERNAL neon_slide_hash_update(Posf *hash, + const uInt hash_size, + const ush w_size) +{ + /* NEON 'Q' registers allow to store 128 bits, so we can load 8x16-bits + * values. For further details, check: + * ARM DHT 0002A, section 1.3.2 NEON Registers. + */ + const size_t chunk = sizeof(uint16x8_t) / sizeof(uint16_t); + /* Unrolling the operation yielded a compression performance boost in both + * ARMv7 (from 11.7% to 13.4%) and ARMv8 (from 3.7% to 7.5%) for HTML4 + * content. For full benchmarking data, check: http://crbug.com/863257. + */ + const size_t stride = 2*chunk; + const uint16x8_t v = vdupq_n_u16(w_size); + + for (Posf *end = hash + hash_size; hash != end; hash += stride) { + uint16x8_t m_low = vld1q_u16(hash); + uint16x8_t m_high = vld1q_u16(hash + chunk); + + /* The first 'q' in vqsubq_u16 makes these subtracts saturate to zero, + * replacing the ternary operator expression in the original code: + * (m >= wsize ? m - wsize : NIL). + */ + m_low = vqsubq_u16(m_low, v); + m_high = vqsubq_u16(m_high, v); + + vst1q_u16(hash, m_low); + vst1q_u16(hash + chunk, m_high); + } +} + + +inline static void ZLIB_INTERNAL neon_slide_hash(Posf *head, Posf *prev, + const unsigned short w_size, + const uInt hash_size) +{ + /* + * SIMD implementation for hash table rebase assumes: + * 1. hash chain offset (Pos) is 2 bytes. + * 2. hash table size is multiple of 32 bytes. + * #1 should be true as Pos is defined as "ush" + * #2 should be true as hash_bits are greater than 7 + */ + const size_t size = hash_size * sizeof(head[0]); + Assert(sizeof(Pos) == 2, "Wrong Pos size."); + Assert((size % sizeof(uint16x8_t) * 2) == 0, "Hash table size error."); + + neon_slide_hash_update(head, hash_size, w_size); +#ifndef FASTEST + neon_slide_hash_update(prev, w_size, w_size); +#endif +} + +#endif diff --git a/deps/zlib/contrib/pascal/example.pas b/deps/zlib/contrib/pascal/example.pas deleted file mode 100644 index 5518b36a730855..00000000000000 --- a/deps/zlib/contrib/pascal/example.pas +++ /dev/null @@ -1,599 +0,0 @@ -(* example.c -- usage example of the zlib compression library - * Copyright (C) 1995-2003 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Pascal translation - * Copyright (C) 1998 by Jacques Nomssi Nzali. - * For conditions of distribution and use, see copyright notice in readme.txt - * - * Adaptation to the zlibpas interface - * Copyright (C) 2003 by Cosmin Truta. - * For conditions of distribution and use, see copyright notice in readme.txt - *) - -program example; - -{$DEFINE TEST_COMPRESS} -{DO NOT $DEFINE TEST_GZIO} -{$DEFINE TEST_DEFLATE} -{$DEFINE TEST_INFLATE} -{$DEFINE TEST_FLUSH} -{$DEFINE TEST_SYNC} -{$DEFINE TEST_DICT} - -uses SysUtils, zlibpas; - -const TESTFILE = 'foo.gz'; - -(* "hello world" would be more standard, but the repeated "hello" - * stresses the compression code better, sorry... - *) -const hello: PChar = 'hello, hello!'; - -const dictionary: PChar = 'hello'; - -var dictId: LongInt; (* Adler32 value of the dictionary *) - -procedure CHECK_ERR(err: Integer; msg: String); -begin - if err <> Z_OK then - begin - WriteLn(msg, ' error: ', err); - Halt(1); - end; -end; - -procedure EXIT_ERR(const msg: String); -begin - WriteLn('Error: ', msg); - Halt(1); -end; - -(* =========================================================================== - * Test compress and uncompress - *) -{$IFDEF TEST_COMPRESS} -procedure test_compress(compr: Pointer; comprLen: LongInt; - uncompr: Pointer; uncomprLen: LongInt); -var err: Integer; - len: LongInt; -begin - len := StrLen(hello)+1; - - err := compress(compr, comprLen, hello, len); - CHECK_ERR(err, 'compress'); - - StrCopy(PChar(uncompr), 'garbage'); - - err := uncompress(uncompr, uncomprLen, compr, comprLen); - CHECK_ERR(err, 'uncompress'); - - if StrComp(PChar(uncompr), hello) <> 0 then - EXIT_ERR('bad uncompress') - else - WriteLn('uncompress(): ', PChar(uncompr)); -end; -{$ENDIF} - -(* =========================================================================== - * Test read/write of .gz files - *) -{$IFDEF TEST_GZIO} -procedure test_gzio(const fname: PChar; (* compressed file name *) - uncompr: Pointer; - uncomprLen: LongInt); -var err: Integer; - len: Integer; - zfile: gzFile; - pos: LongInt; -begin - len := StrLen(hello)+1; - - zfile := gzopen(fname, 'wb'); - if zfile = NIL then - begin - WriteLn('gzopen error'); - Halt(1); - end; - gzputc(zfile, 'h'); - if gzputs(zfile, 'ello') <> 4 then - begin - WriteLn('gzputs err: ', gzerror(zfile, err)); - Halt(1); - end; - {$IFDEF GZ_FORMAT_STRING} - if gzprintf(zfile, ', %s!', 'hello') <> 8 then - begin - WriteLn('gzprintf err: ', gzerror(zfile, err)); - Halt(1); - end; - {$ELSE} - if gzputs(zfile, ', hello!') <> 8 then - begin - WriteLn('gzputs err: ', gzerror(zfile, err)); - Halt(1); - end; - {$ENDIF} - gzseek(zfile, 1, SEEK_CUR); (* add one zero byte *) - gzclose(zfile); - - zfile := gzopen(fname, 'rb'); - if zfile = NIL then - begin - WriteLn('gzopen error'); - Halt(1); - end; - - StrCopy(PChar(uncompr), 'garbage'); - - if gzread(zfile, uncompr, uncomprLen) <> len then - begin - WriteLn('gzread err: ', gzerror(zfile, err)); - Halt(1); - end; - if StrComp(PChar(uncompr), hello) <> 0 then - begin - WriteLn('bad gzread: ', PChar(uncompr)); - Halt(1); - end - else - WriteLn('gzread(): ', PChar(uncompr)); - - pos := gzseek(zfile, -8, SEEK_CUR); - if (pos <> 6) or (gztell(zfile) <> pos) then - begin - WriteLn('gzseek error, pos=', pos, ', gztell=', gztell(zfile)); - Halt(1); - end; - - if gzgetc(zfile) <> ' ' then - begin - WriteLn('gzgetc error'); - Halt(1); - end; - - if gzungetc(' ', zfile) <> ' ' then - begin - WriteLn('gzungetc error'); - Halt(1); - end; - - gzgets(zfile, PChar(uncompr), uncomprLen); - uncomprLen := StrLen(PChar(uncompr)); - if uncomprLen <> 7 then (* " hello!" *) - begin - WriteLn('gzgets err after gzseek: ', gzerror(zfile, err)); - Halt(1); - end; - if StrComp(PChar(uncompr), hello + 6) <> 0 then - begin - WriteLn('bad gzgets after gzseek'); - Halt(1); - end - else - WriteLn('gzgets() after gzseek: ', PChar(uncompr)); - - gzclose(zfile); -end; -{$ENDIF} - -(* =========================================================================== - * Test deflate with small buffers - *) -{$IFDEF TEST_DEFLATE} -procedure test_deflate(compr: Pointer; comprLen: LongInt); -var c_stream: z_stream; (* compression stream *) - err: Integer; - len: LongInt; -begin - len := StrLen(hello)+1; - - c_stream.zalloc := NIL; - c_stream.zfree := NIL; - c_stream.opaque := NIL; - - err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, 'deflateInit'); - - c_stream.next_in := hello; - c_stream.next_out := compr; - - while (c_stream.total_in <> len) and - (c_stream.total_out < comprLen) do - begin - c_stream.avail_out := 1; { force small buffers } - c_stream.avail_in := 1; - err := deflate(c_stream, Z_NO_FLUSH); - CHECK_ERR(err, 'deflate'); - end; - - (* Finish the stream, still forcing small buffers: *) - while TRUE do - begin - c_stream.avail_out := 1; - err := deflate(c_stream, Z_FINISH); - if err = Z_STREAM_END then - break; - CHECK_ERR(err, 'deflate'); - end; - - err := deflateEnd(c_stream); - CHECK_ERR(err, 'deflateEnd'); -end; -{$ENDIF} - -(* =========================================================================== - * Test inflate with small buffers - *) -{$IFDEF TEST_INFLATE} -procedure test_inflate(compr: Pointer; comprLen : LongInt; - uncompr: Pointer; uncomprLen : LongInt); -var err: Integer; - d_stream: z_stream; (* decompression stream *) -begin - StrCopy(PChar(uncompr), 'garbage'); - - d_stream.zalloc := NIL; - d_stream.zfree := NIL; - d_stream.opaque := NIL; - - d_stream.next_in := compr; - d_stream.avail_in := 0; - d_stream.next_out := uncompr; - - err := inflateInit(d_stream); - CHECK_ERR(err, 'inflateInit'); - - while (d_stream.total_out < uncomprLen) and - (d_stream.total_in < comprLen) do - begin - d_stream.avail_out := 1; (* force small buffers *) - d_stream.avail_in := 1; - err := inflate(d_stream, Z_NO_FLUSH); - if err = Z_STREAM_END then - break; - CHECK_ERR(err, 'inflate'); - end; - - err := inflateEnd(d_stream); - CHECK_ERR(err, 'inflateEnd'); - - if StrComp(PChar(uncompr), hello) <> 0 then - EXIT_ERR('bad inflate') - else - WriteLn('inflate(): ', PChar(uncompr)); -end; -{$ENDIF} - -(* =========================================================================== - * Test deflate with large buffers and dynamic change of compression level - *) -{$IFDEF TEST_DEFLATE} -procedure test_large_deflate(compr: Pointer; comprLen: LongInt; - uncompr: Pointer; uncomprLen: LongInt); -var c_stream: z_stream; (* compression stream *) - err: Integer; -begin - c_stream.zalloc := NIL; - c_stream.zfree := NIL; - c_stream.opaque := NIL; - - err := deflateInit(c_stream, Z_BEST_SPEED); - CHECK_ERR(err, 'deflateInit'); - - c_stream.next_out := compr; - c_stream.avail_out := Integer(comprLen); - - (* At this point, uncompr is still mostly zeroes, so it should compress - * very well: - *) - c_stream.next_in := uncompr; - c_stream.avail_in := Integer(uncomprLen); - err := deflate(c_stream, Z_NO_FLUSH); - CHECK_ERR(err, 'deflate'); - if c_stream.avail_in <> 0 then - EXIT_ERR('deflate not greedy'); - - (* Feed in already compressed data and switch to no compression: *) - deflateParams(c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); - c_stream.next_in := compr; - c_stream.avail_in := Integer(comprLen div 2); - err := deflate(c_stream, Z_NO_FLUSH); - CHECK_ERR(err, 'deflate'); - - (* Switch back to compressing mode: *) - deflateParams(c_stream, Z_BEST_COMPRESSION, Z_FILTERED); - c_stream.next_in := uncompr; - c_stream.avail_in := Integer(uncomprLen); - err := deflate(c_stream, Z_NO_FLUSH); - CHECK_ERR(err, 'deflate'); - - err := deflate(c_stream, Z_FINISH); - if err <> Z_STREAM_END then - EXIT_ERR('deflate should report Z_STREAM_END'); - - err := deflateEnd(c_stream); - CHECK_ERR(err, 'deflateEnd'); -end; -{$ENDIF} - -(* =========================================================================== - * Test inflate with large buffers - *) -{$IFDEF TEST_INFLATE} -procedure test_large_inflate(compr: Pointer; comprLen: LongInt; - uncompr: Pointer; uncomprLen: LongInt); -var err: Integer; - d_stream: z_stream; (* decompression stream *) -begin - StrCopy(PChar(uncompr), 'garbage'); - - d_stream.zalloc := NIL; - d_stream.zfree := NIL; - d_stream.opaque := NIL; - - d_stream.next_in := compr; - d_stream.avail_in := Integer(comprLen); - - err := inflateInit(d_stream); - CHECK_ERR(err, 'inflateInit'); - - while TRUE do - begin - d_stream.next_out := uncompr; (* discard the output *) - d_stream.avail_out := Integer(uncomprLen); - err := inflate(d_stream, Z_NO_FLUSH); - if err = Z_STREAM_END then - break; - CHECK_ERR(err, 'large inflate'); - end; - - err := inflateEnd(d_stream); - CHECK_ERR(err, 'inflateEnd'); - - if d_stream.total_out <> 2 * uncomprLen + comprLen div 2 then - begin - WriteLn('bad large inflate: ', d_stream.total_out); - Halt(1); - end - else - WriteLn('large_inflate(): OK'); -end; -{$ENDIF} - -(* =========================================================================== - * Test deflate with full flush - *) -{$IFDEF TEST_FLUSH} -procedure test_flush(compr: Pointer; var comprLen : LongInt); -var c_stream: z_stream; (* compression stream *) - err: Integer; - len: Integer; -begin - len := StrLen(hello)+1; - - c_stream.zalloc := NIL; - c_stream.zfree := NIL; - c_stream.opaque := NIL; - - err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, 'deflateInit'); - - c_stream.next_in := hello; - c_stream.next_out := compr; - c_stream.avail_in := 3; - c_stream.avail_out := Integer(comprLen); - err := deflate(c_stream, Z_FULL_FLUSH); - CHECK_ERR(err, 'deflate'); - - Inc(PByteArray(compr)^[3]); (* force an error in first compressed block *) - c_stream.avail_in := len - 3; - - err := deflate(c_stream, Z_FINISH); - if err <> Z_STREAM_END then - CHECK_ERR(err, 'deflate'); - - err := deflateEnd(c_stream); - CHECK_ERR(err, 'deflateEnd'); - - comprLen := c_stream.total_out; -end; -{$ENDIF} - -(* =========================================================================== - * Test inflateSync() - *) -{$IFDEF TEST_SYNC} -procedure test_sync(compr: Pointer; comprLen: LongInt; - uncompr: Pointer; uncomprLen : LongInt); -var err: Integer; - d_stream: z_stream; (* decompression stream *) -begin - StrCopy(PChar(uncompr), 'garbage'); - - d_stream.zalloc := NIL; - d_stream.zfree := NIL; - d_stream.opaque := NIL; - - d_stream.next_in := compr; - d_stream.avail_in := 2; (* just read the zlib header *) - - err := inflateInit(d_stream); - CHECK_ERR(err, 'inflateInit'); - - d_stream.next_out := uncompr; - d_stream.avail_out := Integer(uncomprLen); - - inflate(d_stream, Z_NO_FLUSH); - CHECK_ERR(err, 'inflate'); - - d_stream.avail_in := Integer(comprLen-2); (* read all compressed data *) - err := inflateSync(d_stream); (* but skip the damaged part *) - CHECK_ERR(err, 'inflateSync'); - - err := inflate(d_stream, Z_FINISH); - if err <> Z_DATA_ERROR then - EXIT_ERR('inflate should report DATA_ERROR'); - (* Because of incorrect adler32 *) - - err := inflateEnd(d_stream); - CHECK_ERR(err, 'inflateEnd'); - - WriteLn('after inflateSync(): hel', PChar(uncompr)); -end; -{$ENDIF} - -(* =========================================================================== - * Test deflate with preset dictionary - *) -{$IFDEF TEST_DICT} -procedure test_dict_deflate(compr: Pointer; comprLen: LongInt); -var c_stream: z_stream; (* compression stream *) - err: Integer; -begin - c_stream.zalloc := NIL; - c_stream.zfree := NIL; - c_stream.opaque := NIL; - - err := deflateInit(c_stream, Z_BEST_COMPRESSION); - CHECK_ERR(err, 'deflateInit'); - - err := deflateSetDictionary(c_stream, dictionary, StrLen(dictionary)); - CHECK_ERR(err, 'deflateSetDictionary'); - - dictId := c_stream.adler; - c_stream.next_out := compr; - c_stream.avail_out := Integer(comprLen); - - c_stream.next_in := hello; - c_stream.avail_in := StrLen(hello)+1; - - err := deflate(c_stream, Z_FINISH); - if err <> Z_STREAM_END then - EXIT_ERR('deflate should report Z_STREAM_END'); - - err := deflateEnd(c_stream); - CHECK_ERR(err, 'deflateEnd'); -end; -{$ENDIF} - -(* =========================================================================== - * Test inflate with a preset dictionary - *) -{$IFDEF TEST_DICT} -procedure test_dict_inflate(compr: Pointer; comprLen: LongInt; - uncompr: Pointer; uncomprLen: LongInt); -var err: Integer; - d_stream: z_stream; (* decompression stream *) -begin - StrCopy(PChar(uncompr), 'garbage'); - - d_stream.zalloc := NIL; - d_stream.zfree := NIL; - d_stream.opaque := NIL; - - d_stream.next_in := compr; - d_stream.avail_in := Integer(comprLen); - - err := inflateInit(d_stream); - CHECK_ERR(err, 'inflateInit'); - - d_stream.next_out := uncompr; - d_stream.avail_out := Integer(uncomprLen); - - while TRUE do - begin - err := inflate(d_stream, Z_NO_FLUSH); - if err = Z_STREAM_END then - break; - if err = Z_NEED_DICT then - begin - if d_stream.adler <> dictId then - EXIT_ERR('unexpected dictionary'); - err := inflateSetDictionary(d_stream, dictionary, StrLen(dictionary)); - end; - CHECK_ERR(err, 'inflate with dict'); - end; - - err := inflateEnd(d_stream); - CHECK_ERR(err, 'inflateEnd'); - - if StrComp(PChar(uncompr), hello) <> 0 then - EXIT_ERR('bad inflate with dict') - else - WriteLn('inflate with dictionary: ', PChar(uncompr)); -end; -{$ENDIF} - -var compr, uncompr: Pointer; - comprLen, uncomprLen: LongInt; - -begin - if zlibVersion^ <> ZLIB_VERSION[1] then - EXIT_ERR('Incompatible zlib version'); - - WriteLn('zlib version: ', zlibVersion); - WriteLn('zlib compile flags: ', Format('0x%x', [zlibCompileFlags])); - - comprLen := 10000 * SizeOf(Integer); (* don't overflow on MSDOS *) - uncomprLen := comprLen; - GetMem(compr, comprLen); - GetMem(uncompr, uncomprLen); - if (compr = NIL) or (uncompr = NIL) then - EXIT_ERR('Out of memory'); - (* compr and uncompr are cleared to avoid reading uninitialized - * data and to ensure that uncompr compresses well. - *) - FillChar(compr^, comprLen, 0); - FillChar(uncompr^, uncomprLen, 0); - - {$IFDEF TEST_COMPRESS} - WriteLn('** Testing compress'); - test_compress(compr, comprLen, uncompr, uncomprLen); - {$ENDIF} - - {$IFDEF TEST_GZIO} - WriteLn('** Testing gzio'); - if ParamCount >= 1 then - test_gzio(ParamStr(1), uncompr, uncomprLen) - else - test_gzio(TESTFILE, uncompr, uncomprLen); - {$ENDIF} - - {$IFDEF TEST_DEFLATE} - WriteLn('** Testing deflate with small buffers'); - test_deflate(compr, comprLen); - {$ENDIF} - {$IFDEF TEST_INFLATE} - WriteLn('** Testing inflate with small buffers'); - test_inflate(compr, comprLen, uncompr, uncomprLen); - {$ENDIF} - - {$IFDEF TEST_DEFLATE} - WriteLn('** Testing deflate with large buffers'); - test_large_deflate(compr, comprLen, uncompr, uncomprLen); - {$ENDIF} - {$IFDEF TEST_INFLATE} - WriteLn('** Testing inflate with large buffers'); - test_large_inflate(compr, comprLen, uncompr, uncomprLen); - {$ENDIF} - - {$IFDEF TEST_FLUSH} - WriteLn('** Testing deflate with full flush'); - test_flush(compr, comprLen); - {$ENDIF} - {$IFDEF TEST_SYNC} - WriteLn('** Testing inflateSync'); - test_sync(compr, comprLen, uncompr, uncomprLen); - {$ENDIF} - comprLen := uncomprLen; - - {$IFDEF TEST_DICT} - WriteLn('** Testing deflate and inflate with preset dictionary'); - test_dict_deflate(compr, comprLen); - test_dict_inflate(compr, comprLen, uncompr, uncomprLen); - {$ENDIF} - - FreeMem(compr, comprLen); - FreeMem(uncompr, uncomprLen); -end. diff --git a/deps/zlib/contrib/pascal/readme.txt b/deps/zlib/contrib/pascal/readme.txt deleted file mode 100644 index 60e87c8a331b5d..00000000000000 --- a/deps/zlib/contrib/pascal/readme.txt +++ /dev/null @@ -1,76 +0,0 @@ - -This directory contains a Pascal (Delphi, Kylix) interface to the -zlib data compression library. - - -Directory listing -================= - -zlibd32.mak makefile for Borland C++ -example.pas usage example of zlib -zlibpas.pas the Pascal interface to zlib -readme.txt this file - - -Compatibility notes -=================== - -- Although the name "zlib" would have been more normal for the - zlibpas unit, this name is already taken by Borland's ZLib unit. - This is somehow unfortunate, because that unit is not a genuine - interface to the full-fledged zlib functionality, but a suite of - class wrappers around zlib streams. Other essential features, - such as checksums, are missing. - It would have been more appropriate for that unit to have a name - like "ZStreams", or something similar. - -- The C and zlib-supplied types int, uInt, long, uLong, etc. are - translated directly into Pascal types of similar sizes (Integer, - LongInt, etc.), to avoid namespace pollution. In particular, - there is no conversion of unsigned int into a Pascal unsigned - integer. The Word type is non-portable and has the same size - (16 bits) both in a 16-bit and in a 32-bit environment, unlike - Integer. Even if there is a 32-bit Cardinal type, there is no - real need for unsigned int in zlib under a 32-bit environment. - -- Except for the callbacks, the zlib function interfaces are - assuming the calling convention normally used in Pascal - (__pascal for DOS and Windows16, __fastcall for Windows32). - Since the cdecl keyword is used, the old Turbo Pascal does - not work with this interface. - -- The gz* function interfaces are not translated, to avoid - interfacing problems with the C runtime library. Besides, - gzprintf(gzFile file, const char *format, ...) - cannot be translated into Pascal. - - -Legal issues -============ - -The zlibpas interface is: - Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler. - Copyright (C) 1998 by Bob Dellaca. - Copyright (C) 2003 by Cosmin Truta. - -The example program is: - Copyright (C) 1995-2003 by Jean-loup Gailly. - Copyright (C) 1998,1999,2000 by Jacques Nomssi Nzali. - Copyright (C) 2003 by Cosmin Truta. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - diff --git a/deps/zlib/contrib/pascal/zlibd32.mak b/deps/zlib/contrib/pascal/zlibd32.mak deleted file mode 100644 index 9bb00b7cc4211c..00000000000000 --- a/deps/zlib/contrib/pascal/zlibd32.mak +++ /dev/null @@ -1,99 +0,0 @@ -# Makefile for zlib -# For use with Delphi and C++ Builder under Win32 -# Updated for zlib 1.2.x by Cosmin Truta - -# ------------ Borland C++ ------------ - -# This project uses the Delphi (fastcall/register) calling convention: -LOC = -DZEXPORT=__fastcall -DZEXPORTVA=__cdecl - -CC = bcc32 -LD = bcc32 -AR = tlib -# do not use "-pr" in CFLAGS -CFLAGS = -a -d -k- -O2 $(LOC) -LDFLAGS = - - -# variables -ZLIB_LIB = zlib.lib - -OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj -OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj -OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj -OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj - - -# targets -all: $(ZLIB_LIB) example.exe minigzip.exe - -.c.obj: - $(CC) -c $(CFLAGS) $*.c - -adler32.obj: adler32.c zlib.h zconf.h - -compress.obj: compress.c zlib.h zconf.h - -crc32.obj: crc32.c zlib.h zconf.h crc32.h - -deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h - -gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h - -gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h - -gzread.obj: gzread.c zlib.h zconf.h gzguts.h - -gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h - -infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h - -inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h - -trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h - -uncompr.obj: uncompr.c zlib.h zconf.h - -zutil.obj: zutil.c zutil.h zlib.h zconf.h - -example.obj: test/example.c zlib.h zconf.h - -minigzip.obj: test/minigzip.c zlib.h zconf.h - - -# For the sake of the old Borland make, -# the command line is cut to fit in the MS-DOS 128 byte limit: -$(ZLIB_LIB): $(OBJ1) $(OBJ2) - -del $(ZLIB_LIB) - $(AR) $(ZLIB_LIB) $(OBJP1) - $(AR) $(ZLIB_LIB) $(OBJP2) - - -# testing -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -example.exe: example.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) - -minigzip.exe: minigzip.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) - - -# cleanup -clean: - -del *.obj - -del *.exe - -del *.lib - -del *.tds - -del zlib.bak - -del foo.gz - diff --git a/deps/zlib/contrib/pascal/zlibpas.pas b/deps/zlib/contrib/pascal/zlibpas.pas deleted file mode 100644 index a0dff11b505f45..00000000000000 --- a/deps/zlib/contrib/pascal/zlibpas.pas +++ /dev/null @@ -1,276 +0,0 @@ -(* zlibpas -- Pascal interface to the zlib data compression library - * - * Copyright (C) 2003 Cosmin Truta. - * Derived from original sources by Bob Dellaca. - * For conditions of distribution and use, see copyright notice in readme.txt - *) - -unit zlibpas; - -interface - -const - ZLIB_VERSION = '1.2.11'; - ZLIB_VERNUM = $12a0; - -type - alloc_func = function(opaque: Pointer; items, size: Integer): Pointer; - cdecl; - free_func = procedure(opaque, address: Pointer); - cdecl; - - in_func = function(opaque: Pointer; var buf: PByte): Integer; - cdecl; - out_func = function(opaque: Pointer; buf: PByte; size: Integer): Integer; - cdecl; - - z_streamp = ^z_stream; - z_stream = packed record - next_in: PChar; (* next input byte *) - avail_in: Integer; (* number of bytes available at next_in *) - total_in: LongInt; (* total nb of input bytes read so far *) - - next_out: PChar; (* next output byte should be put there *) - avail_out: Integer; (* remaining free space at next_out *) - total_out: LongInt; (* total nb of bytes output so far *) - - msg: PChar; (* last error message, NULL if no error *) - state: Pointer; (* not visible by applications *) - - zalloc: alloc_func; (* used to allocate the internal state *) - zfree: free_func; (* used to free the internal state *) - opaque: Pointer; (* private data object passed to zalloc and zfree *) - - data_type: Integer; (* best guess about the data type: ascii or binary *) - adler: LongInt; (* adler32 value of the uncompressed data *) - reserved: LongInt; (* reserved for future use *) - end; - - gz_headerp = ^gz_header; - gz_header = packed record - text: Integer; (* true if compressed data believed to be text *) - time: LongInt; (* modification time *) - xflags: Integer; (* extra flags (not used when writing a gzip file) *) - os: Integer; (* operating system *) - extra: PChar; (* pointer to extra field or Z_NULL if none *) - extra_len: Integer; (* extra field length (valid if extra != Z_NULL) *) - extra_max: Integer; (* space at extra (only when reading header) *) - name: PChar; (* pointer to zero-terminated file name or Z_NULL *) - name_max: Integer; (* space at name (only when reading header) *) - comment: PChar; (* pointer to zero-terminated comment or Z_NULL *) - comm_max: Integer; (* space at comment (only when reading header) *) - hcrc: Integer; (* true if there was or will be a header crc *) - done: Integer; (* true when done reading gzip header *) - end; - -(* constants *) -const - Z_NO_FLUSH = 0; - Z_PARTIAL_FLUSH = 1; - Z_SYNC_FLUSH = 2; - Z_FULL_FLUSH = 3; - Z_FINISH = 4; - Z_BLOCK = 5; - Z_TREES = 6; - - Z_OK = 0; - Z_STREAM_END = 1; - Z_NEED_DICT = 2; - Z_ERRNO = -1; - Z_STREAM_ERROR = -2; - Z_DATA_ERROR = -3; - Z_MEM_ERROR = -4; - Z_BUF_ERROR = -5; - Z_VERSION_ERROR = -6; - - Z_NO_COMPRESSION = 0; - Z_BEST_SPEED = 1; - Z_BEST_COMPRESSION = 9; - Z_DEFAULT_COMPRESSION = -1; - - Z_FILTERED = 1; - Z_HUFFMAN_ONLY = 2; - Z_RLE = 3; - Z_FIXED = 4; - Z_DEFAULT_STRATEGY = 0; - - Z_BINARY = 0; - Z_TEXT = 1; - Z_ASCII = 1; - Z_UNKNOWN = 2; - - Z_DEFLATED = 8; - -(* basic functions *) -function zlibVersion: PChar; -function deflateInit(var strm: z_stream; level: Integer): Integer; -function deflate(var strm: z_stream; flush: Integer): Integer; -function deflateEnd(var strm: z_stream): Integer; -function inflateInit(var strm: z_stream): Integer; -function inflate(var strm: z_stream; flush: Integer): Integer; -function inflateEnd(var strm: z_stream): Integer; - -(* advanced functions *) -function deflateInit2(var strm: z_stream; level, method, windowBits, - memLevel, strategy: Integer): Integer; -function deflateSetDictionary(var strm: z_stream; const dictionary: PChar; - dictLength: Integer): Integer; -function deflateCopy(var dest, source: z_stream): Integer; -function deflateReset(var strm: z_stream): Integer; -function deflateParams(var strm: z_stream; level, strategy: Integer): Integer; -function deflateTune(var strm: z_stream; good_length, max_lazy, nice_length, max_chain: Integer): Integer; -function deflateBound(var strm: z_stream; sourceLen: LongInt): LongInt; -function deflatePending(var strm: z_stream; var pending: Integer; var bits: Integer): Integer; -function deflatePrime(var strm: z_stream; bits, value: Integer): Integer; -function deflateSetHeader(var strm: z_stream; head: gz_header): Integer; -function inflateInit2(var strm: z_stream; windowBits: Integer): Integer; -function inflateSetDictionary(var strm: z_stream; const dictionary: PChar; - dictLength: Integer): Integer; -function inflateSync(var strm: z_stream): Integer; -function inflateCopy(var dest, source: z_stream): Integer; -function inflateReset(var strm: z_stream): Integer; -function inflateReset2(var strm: z_stream; windowBits: Integer): Integer; -function inflatePrime(var strm: z_stream; bits, value: Integer): Integer; -function inflateMark(var strm: z_stream): LongInt; -function inflateGetHeader(var strm: z_stream; var head: gz_header): Integer; -function inflateBackInit(var strm: z_stream; - windowBits: Integer; window: PChar): Integer; -function inflateBack(var strm: z_stream; in_fn: in_func; in_desc: Pointer; - out_fn: out_func; out_desc: Pointer): Integer; -function inflateBackEnd(var strm: z_stream): Integer; -function zlibCompileFlags: LongInt; - -(* utility functions *) -function compress(dest: PChar; var destLen: LongInt; - const source: PChar; sourceLen: LongInt): Integer; -function compress2(dest: PChar; var destLen: LongInt; - const source: PChar; sourceLen: LongInt; - level: Integer): Integer; -function compressBound(sourceLen: LongInt): LongInt; -function uncompress(dest: PChar; var destLen: LongInt; - const source: PChar; sourceLen: LongInt): Integer; - -(* checksum functions *) -function adler32(adler: LongInt; const buf: PChar; len: Integer): LongInt; -function adler32_combine(adler1, adler2, len2: LongInt): LongInt; -function crc32(crc: LongInt; const buf: PChar; len: Integer): LongInt; -function crc32_combine(crc1, crc2, len2: LongInt): LongInt; - -(* various hacks, don't look :) *) -function deflateInit_(var strm: z_stream; level: Integer; - const version: PChar; stream_size: Integer): Integer; -function inflateInit_(var strm: z_stream; const version: PChar; - stream_size: Integer): Integer; -function deflateInit2_(var strm: z_stream; - level, method, windowBits, memLevel, strategy: Integer; - const version: PChar; stream_size: Integer): Integer; -function inflateInit2_(var strm: z_stream; windowBits: Integer; - const version: PChar; stream_size: Integer): Integer; -function inflateBackInit_(var strm: z_stream; - windowBits: Integer; window: PChar; - const version: PChar; stream_size: Integer): Integer; - - -implementation - -{$L adler32.obj} -{$L compress.obj} -{$L crc32.obj} -{$L deflate.obj} -{$L infback.obj} -{$L inffast.obj} -{$L inflate.obj} -{$L inftrees.obj} -{$L trees.obj} -{$L uncompr.obj} -{$L zutil.obj} - -function adler32; external; -function adler32_combine; external; -function compress; external; -function compress2; external; -function compressBound; external; -function crc32; external; -function crc32_combine; external; -function deflate; external; -function deflateBound; external; -function deflateCopy; external; -function deflateEnd; external; -function deflateInit_; external; -function deflateInit2_; external; -function deflateParams; external; -function deflatePending; external; -function deflatePrime; external; -function deflateReset; external; -function deflateSetDictionary; external; -function deflateSetHeader; external; -function deflateTune; external; -function inflate; external; -function inflateBack; external; -function inflateBackEnd; external; -function inflateBackInit_; external; -function inflateCopy; external; -function inflateEnd; external; -function inflateGetHeader; external; -function inflateInit_; external; -function inflateInit2_; external; -function inflateMark; external; -function inflatePrime; external; -function inflateReset; external; -function inflateReset2; external; -function inflateSetDictionary; external; -function inflateSync; external; -function uncompress; external; -function zlibCompileFlags; external; -function zlibVersion; external; - -function deflateInit(var strm: z_stream; level: Integer): Integer; -begin - Result := deflateInit_(strm, level, ZLIB_VERSION, sizeof(z_stream)); -end; - -function deflateInit2(var strm: z_stream; level, method, windowBits, memLevel, - strategy: Integer): Integer; -begin - Result := deflateInit2_(strm, level, method, windowBits, memLevel, strategy, - ZLIB_VERSION, sizeof(z_stream)); -end; - -function inflateInit(var strm: z_stream): Integer; -begin - Result := inflateInit_(strm, ZLIB_VERSION, sizeof(z_stream)); -end; - -function inflateInit2(var strm: z_stream; windowBits: Integer): Integer; -begin - Result := inflateInit2_(strm, windowBits, ZLIB_VERSION, sizeof(z_stream)); -end; - -function inflateBackInit(var strm: z_stream; - windowBits: Integer; window: PChar): Integer; -begin - Result := inflateBackInit_(strm, windowBits, window, - ZLIB_VERSION, sizeof(z_stream)); -end; - -function _malloc(Size: Integer): Pointer; cdecl; -begin - GetMem(Result, Size); -end; - -procedure _free(Block: Pointer); cdecl; -begin - FreeMem(Block); -end; - -procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl; -begin - FillChar(P^, count, B); -end; - -procedure _memcpy(dest, source: Pointer; count: Integer); cdecl; -begin - Move(source^, dest^, count); -end; - -end. diff --git a/deps/zlib/contrib/puff/Makefile b/deps/zlib/contrib/puff/Makefile deleted file mode 100644 index 0e2594c80885c0..00000000000000 --- a/deps/zlib/contrib/puff/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -CFLAGS=-O - -puff: puff.o pufftest.o - -puff.o: puff.h - -pufftest.o: puff.h - -test: puff - puff zeros.raw - -puft: puff.c puff.h pufftest.o - cc -fprofile-arcs -ftest-coverage -o puft puff.c pufftest.o - -# puff full coverage test (should say 100%) -cov: puft - @rm -f *.gcov *.gcda - @puft -w zeros.raw 2>&1 | cat > /dev/null - @echo '04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 - @echo '00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 - @echo '00 00 00 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 254 - @echo '00 01 00 fe ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 - @echo '01 01 00 fe ff 0a' | xxd -r -p | puft -f 2>&1 | cat > /dev/null - @echo '02 7e ff ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 - @echo '02' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 - @echo '04 80 49 92 24 49 92 24 0f b4 ff ff c3 04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 - @echo '04 80 49 92 24 49 92 24 71 ff ff 93 11 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 249 - @echo '04 c0 81 08 00 00 00 00 20 7f eb 0b 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 - @echo '0b 00 00' | xxd -r -p | puft -f 2>&1 | cat > /dev/null - @echo '1a 07' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 - @echo '0c c0 81 00 00 00 00 00 90 ff 6b 04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 245 - @puft -f zeros.raw 2>&1 | cat > /dev/null - @echo 'fc 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 253 - @echo '04 00 fe ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 252 - @echo '04 00 24 49' | xxd -r -p | puft 2> /dev/null || test $$? -eq 251 - @echo '04 80 49 92 24 49 92 24 0f b4 ff ff c3 84' | xxd -r -p | puft 2> /dev/null || test $$? -eq 248 - @echo '04 00 24 e9 ff ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 250 - @echo '04 00 24 e9 ff 6d' | xxd -r -p | puft 2> /dev/null || test $$? -eq 247 - @gcov -n puff.c - -clean: - rm -f puff puft *.o *.gc* diff --git a/deps/zlib/contrib/puff/README b/deps/zlib/contrib/puff/README deleted file mode 100644 index bbc4cb595ec1a6..00000000000000 --- a/deps/zlib/contrib/puff/README +++ /dev/null @@ -1,63 +0,0 @@ -Puff -- A Simple Inflate -3 Mar 2003 -Mark Adler -madler@alumni.caltech.edu - -What this is -- - -puff.c provides the routine puff() to decompress the deflate data format. It -does so more slowly than zlib, but the code is about one-fifth the size of the -inflate code in zlib, and written to be very easy to read. - -Why I wrote this -- - -puff.c was written to document the deflate format unambiguously, by virtue of -being working C code. It is meant to supplement RFC 1951, which formally -describes the deflate format. I have received many questions on details of the -deflate format, and I hope that reading this code will answer those questions. -puff.c is heavily commented with details of the deflate format, especially -those little nooks and cranies of the format that might not be obvious from a -specification. - -puff.c may also be useful in applications where code size or memory usage is a -very limited resource, and speed is not as important. - -How to use it -- - -Well, most likely you should just be reading puff.c and using zlib for actual -applications, but if you must ... - -Include puff.h in your code, which provides this prototype: - -int puff(unsigned char *dest, /* pointer to destination pointer */ - unsigned long *destlen, /* amount of output space */ - unsigned char *source, /* pointer to source data pointer */ - unsigned long *sourcelen); /* amount of input available */ - -Then you can call puff() to decompress a deflate stream that is in memory in -its entirety at source, to a sufficiently sized block of memory for the -decompressed data at dest. puff() is the only external symbol in puff.c The -only C library functions that puff.c needs are setjmp() and longjmp(), which -are used to simplify error checking in the code to improve readabilty. puff.c -does no memory allocation, and uses less than 2K bytes off of the stack. - -If destlen is not enough space for the uncompressed data, then inflate will -return an error without writing more than destlen bytes. Note that this means -that in order to decompress the deflate data successfully, you need to know -the size of the uncompressed data ahead of time. - -If needed, puff() can determine the size of the uncompressed data with no -output space. This is done by passing dest equal to (unsigned char *)0. Then -the initial value of *destlen is ignored and *destlen is set to the length of -the uncompressed data. So if the size of the uncompressed data is not known, -then two passes of puff() can be used--first to determine the size, and second -to do the actual inflation after allocating the appropriate memory. Not -pretty, but it works. (This is one of the reasons you should be using zlib.) - -The deflate format is self-terminating. If the deflate stream does not end -in *sourcelen bytes, puff() will return an error without reading at or past -endsource. - -On return, *sourcelen is updated to the amount of input data consumed, and -*destlen is updated to the size of the uncompressed data. See the comments -in puff.c for the possible return codes for puff(). diff --git a/deps/zlib/contrib/puff/puff.c b/deps/zlib/contrib/puff/puff.c deleted file mode 100644 index c6c90d714206a3..00000000000000 --- a/deps/zlib/contrib/puff/puff.c +++ /dev/null @@ -1,840 +0,0 @@ -/* - * puff.c - * Copyright (C) 2002-2013 Mark Adler - * For conditions of distribution and use, see copyright notice in puff.h - * version 2.3, 21 Jan 2013 - * - * puff.c is a simple inflate written to be an unambiguous way to specify the - * deflate format. It is not written for speed but rather simplicity. As a - * side benefit, this code might actually be useful when small code is more - * important than speed, such as bootstrap applications. For typical deflate - * data, zlib's inflate() is about four times as fast as puff(). zlib's - * inflate compiles to around 20K on my machine, whereas puff.c compiles to - * around 4K on my machine (a PowerPC using GNU cc). If the faster decode() - * function here is used, then puff() is only twice as slow as zlib's - * inflate(). - * - * All dynamically allocated memory comes from the stack. The stack required - * is less than 2K bytes. This code is compatible with 16-bit int's and - * assumes that long's are at least 32 bits. puff.c uses the short data type, - * assumed to be 16 bits, for arrays in order to conserve memory. The code - * works whether integers are stored big endian or little endian. - * - * In the comments below are "Format notes" that describe the inflate process - * and document some of the less obvious aspects of the format. This source - * code is meant to supplement RFC 1951, which formally describes the deflate - * format: - * - * http://www.zlib.org/rfc-deflate.html - */ - -/* - * Change history: - * - * 1.0 10 Feb 2002 - First version - * 1.1 17 Feb 2002 - Clarifications of some comments and notes - * - Update puff() dest and source pointers on negative - * errors to facilitate debugging deflators - * - Remove longest from struct huffman -- not needed - * - Simplify offs[] index in construct() - * - Add input size and checking, using longjmp() to - * maintain easy readability - * - Use short data type for large arrays - * - Use pointers instead of long to specify source and - * destination sizes to avoid arbitrary 4 GB limits - * 1.2 17 Mar 2002 - Add faster version of decode(), doubles speed (!), - * but leave simple version for readabilty - * - Make sure invalid distances detected if pointers - * are 16 bits - * - Fix fixed codes table error - * - Provide a scanning mode for determining size of - * uncompressed data - * 1.3 20 Mar 2002 - Go back to lengths for puff() parameters [Gailly] - * - Add a puff.h file for the interface - * - Add braces in puff() for else do [Gailly] - * - Use indexes instead of pointers for readability - * 1.4 31 Mar 2002 - Simplify construct() code set check - * - Fix some comments - * - Add FIXLCODES #define - * 1.5 6 Apr 2002 - Minor comment fixes - * 1.6 7 Aug 2002 - Minor format changes - * 1.7 3 Mar 2003 - Added test code for distribution - * - Added zlib-like license - * 1.8 9 Jan 2004 - Added some comments on no distance codes case - * 1.9 21 Feb 2008 - Fix bug on 16-bit integer architectures [Pohland] - * - Catch missing end-of-block symbol error - * 2.0 25 Jul 2008 - Add #define to permit distance too far back - * - Add option in TEST code for puff to write the data - * - Add option in TEST code to skip input bytes - * - Allow TEST code to read from piped stdin - * 2.1 4 Apr 2010 - Avoid variable initialization for happier compilers - * - Avoid unsigned comparisons for even happier compilers - * 2.2 25 Apr 2010 - Fix bug in variable initializations [Oberhumer] - * - Add const where appropriate [Oberhumer] - * - Split if's and ?'s for coverage testing - * - Break out test code to separate file - * - Move NIL to puff.h - * - Allow incomplete code only if single code length is 1 - * - Add full code coverage test to Makefile - * 2.3 21 Jan 2013 - Check for invalid code length codes in dynamic blocks - */ - -#include /* for setjmp(), longjmp(), and jmp_buf */ -#include "puff.h" /* prototype for puff() */ - -#define local static /* for local function definitions */ - -/* - * Maximums for allocations and loops. It is not useful to change these -- - * they are fixed by the deflate format. - */ -#define MAXBITS 15 /* maximum bits in a code */ -#define MAXLCODES 286 /* maximum number of literal/length codes */ -#define MAXDCODES 30 /* maximum number of distance codes */ -#define MAXCODES (MAXLCODES+MAXDCODES) /* maximum codes lengths to read */ -#define FIXLCODES 288 /* number of fixed literal/length codes */ - -/* input and output state */ -struct state { - /* output state */ - unsigned char *out; /* output buffer */ - unsigned long outlen; /* available space at out */ - unsigned long outcnt; /* bytes written to out so far */ - - /* input state */ - const unsigned char *in; /* input buffer */ - unsigned long inlen; /* available input at in */ - unsigned long incnt; /* bytes read so far */ - int bitbuf; /* bit buffer */ - int bitcnt; /* number of bits in bit buffer */ - - /* input limit error return state for bits() and decode() */ - jmp_buf env; -}; - -/* - * Return need bits from the input stream. This always leaves less than - * eight bits in the buffer. bits() works properly for need == 0. - * - * Format notes: - * - * - Bits are stored in bytes from the least significant bit to the most - * significant bit. Therefore bits are dropped from the bottom of the bit - * buffer, using shift right, and new bytes are appended to the top of the - * bit buffer, using shift left. - */ -local int bits(struct state *s, int need) -{ - long val; /* bit accumulator (can use up to 20 bits) */ - - /* load at least need bits into val */ - val = s->bitbuf; - while (s->bitcnt < need) { - if (s->incnt == s->inlen) - longjmp(s->env, 1); /* out of input */ - val |= (long)(s->in[s->incnt++]) << s->bitcnt; /* load eight bits */ - s->bitcnt += 8; - } - - /* drop need bits and update buffer, always zero to seven bits left */ - s->bitbuf = (int)(val >> need); - s->bitcnt -= need; - - /* return need bits, zeroing the bits above that */ - return (int)(val & ((1L << need) - 1)); -} - -/* - * Process a stored block. - * - * Format notes: - * - * - After the two-bit stored block type (00), the stored block length and - * stored bytes are byte-aligned for fast copying. Therefore any leftover - * bits in the byte that has the last bit of the type, as many as seven, are - * discarded. The value of the discarded bits are not defined and should not - * be checked against any expectation. - * - * - The second inverted copy of the stored block length does not have to be - * checked, but it's probably a good idea to do so anyway. - * - * - A stored block can have zero length. This is sometimes used to byte-align - * subsets of the compressed data for random access or partial recovery. - */ -local int stored(struct state *s) -{ - unsigned len; /* length of stored block */ - - /* discard leftover bits from current byte (assumes s->bitcnt < 8) */ - s->bitbuf = 0; - s->bitcnt = 0; - - /* get length and check against its one's complement */ - if (s->incnt + 4 > s->inlen) - return 2; /* not enough input */ - len = s->in[s->incnt++]; - len |= s->in[s->incnt++] << 8; - if (s->in[s->incnt++] != (~len & 0xff) || - s->in[s->incnt++] != ((~len >> 8) & 0xff)) - return -2; /* didn't match complement! */ - - /* copy len bytes from in to out */ - if (s->incnt + len > s->inlen) - return 2; /* not enough input */ - if (s->out != NIL) { - if (s->outcnt + len > s->outlen) - return 1; /* not enough output space */ - while (len--) - s->out[s->outcnt++] = s->in[s->incnt++]; - } - else { /* just scanning */ - s->outcnt += len; - s->incnt += len; - } - - /* done with a valid stored block */ - return 0; -} - -/* - * Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of - * each length, which for a canonical code are stepped through in order. - * symbol[] are the symbol values in canonical order, where the number of - * entries is the sum of the counts in count[]. The decoding process can be - * seen in the function decode() below. - */ -struct huffman { - short *count; /* number of symbols of each length */ - short *symbol; /* canonically ordered symbols */ -}; - -/* - * Decode a code from the stream s using huffman table h. Return the symbol or - * a negative value if there is an error. If all of the lengths are zero, i.e. - * an empty code, or if the code is incomplete and an invalid code is received, - * then -10 is returned after reading MAXBITS bits. - * - * Format notes: - * - * - The codes as stored in the compressed data are bit-reversed relative to - * a simple integer ordering of codes of the same lengths. Hence below the - * bits are pulled from the compressed data one at a time and used to - * build the code value reversed from what is in the stream in order to - * permit simple integer comparisons for decoding. A table-based decoding - * scheme (as used in zlib) does not need to do this reversal. - * - * - The first code for the shortest length is all zeros. Subsequent codes of - * the same length are simply integer increments of the previous code. When - * moving up a length, a zero bit is appended to the code. For a complete - * code, the last code of the longest length will be all ones. - * - * - Incomplete codes are handled by this decoder, since they are permitted - * in the deflate format. See the format notes for fixed() and dynamic(). - */ -#ifdef SLOW -local int decode(struct state *s, const struct huffman *h) -{ - int len; /* current number of bits in code */ - int code; /* len bits being decoded */ - int first; /* first code of length len */ - int count; /* number of codes of length len */ - int index; /* index of first code of length len in symbol table */ - - code = first = index = 0; - for (len = 1; len <= MAXBITS; len++) { - code |= bits(s, 1); /* get next bit */ - count = h->count[len]; - if (code - count < first) /* if length len, return symbol */ - return h->symbol[index + (code - first)]; - index += count; /* else update for next length */ - first += count; - first <<= 1; - code <<= 1; - } - return -10; /* ran out of codes */ -} - -/* - * A faster version of decode() for real applications of this code. It's not - * as readable, but it makes puff() twice as fast. And it only makes the code - * a few percent larger. - */ -#else /* !SLOW */ -local int decode(struct state *s, const struct huffman *h) -{ - int len; /* current number of bits in code */ - int code; /* len bits being decoded */ - int first; /* first code of length len */ - int count; /* number of codes of length len */ - int index; /* index of first code of length len in symbol table */ - int bitbuf; /* bits from stream */ - int left; /* bits left in next or left to process */ - short *next; /* next number of codes */ - - bitbuf = s->bitbuf; - left = s->bitcnt; - code = first = index = 0; - len = 1; - next = h->count + 1; - while (1) { - while (left--) { - code |= bitbuf & 1; - bitbuf >>= 1; - count = *next++; - if (code - count < first) { /* if length len, return symbol */ - s->bitbuf = bitbuf; - s->bitcnt = (s->bitcnt - len) & 7; - return h->symbol[index + (code - first)]; - } - index += count; /* else update for next length */ - first += count; - first <<= 1; - code <<= 1; - len++; - } - left = (MAXBITS+1) - len; - if (left == 0) - break; - if (s->incnt == s->inlen) - longjmp(s->env, 1); /* out of input */ - bitbuf = s->in[s->incnt++]; - if (left > 8) - left = 8; - } - return -10; /* ran out of codes */ -} -#endif /* SLOW */ - -/* - * Given the list of code lengths length[0..n-1] representing a canonical - * Huffman code for n symbols, construct the tables required to decode those - * codes. Those tables are the number of codes of each length, and the symbols - * sorted by length, retaining their original order within each length. The - * return value is zero for a complete code set, negative for an over- - * subscribed code set, and positive for an incomplete code set. The tables - * can be used if the return value is zero or positive, but they cannot be used - * if the return value is negative. If the return value is zero, it is not - * possible for decode() using that table to return an error--any stream of - * enough bits will resolve to a symbol. If the return value is positive, then - * it is possible for decode() using that table to return an error for received - * codes past the end of the incomplete lengths. - * - * Not used by decode(), but used for error checking, h->count[0] is the number - * of the n symbols not in the code. So n - h->count[0] is the number of - * codes. This is useful for checking for incomplete codes that have more than - * one symbol, which is an error in a dynamic block. - * - * Assumption: for all i in 0..n-1, 0 <= length[i] <= MAXBITS - * This is assured by the construction of the length arrays in dynamic() and - * fixed() and is not verified by construct(). - * - * Format notes: - * - * - Permitted and expected examples of incomplete codes are one of the fixed - * codes and any code with a single symbol which in deflate is coded as one - * bit instead of zero bits. See the format notes for fixed() and dynamic(). - * - * - Within a given code length, the symbols are kept in ascending order for - * the code bits definition. - */ -local int construct(struct huffman *h, const short *length, int n) -{ - int symbol; /* current symbol when stepping through length[] */ - int len; /* current length when stepping through h->count[] */ - int left; /* number of possible codes left of current length */ - short offs[MAXBITS+1]; /* offsets in symbol table for each length */ - - /* count number of codes of each length */ - for (len = 0; len <= MAXBITS; len++) - h->count[len] = 0; - for (symbol = 0; symbol < n; symbol++) - (h->count[length[symbol]])++; /* assumes lengths are within bounds */ - if (h->count[0] == n) /* no codes! */ - return 0; /* complete, but decode() will fail */ - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; /* one possible code of zero length */ - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; /* one more bit, double codes left */ - left -= h->count[len]; /* deduct count from possible codes */ - if (left < 0) - return left; /* over-subscribed--return negative */ - } /* left > 0 means incomplete */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + h->count[len]; - - /* - * put symbols in table sorted by length, by symbol order within each - * length - */ - for (symbol = 0; symbol < n; symbol++) - if (length[symbol] != 0) - h->symbol[offs[length[symbol]]++] = symbol; - - /* return zero for complete set, positive for incomplete set */ - return left; -} - -/* - * Decode literal/length and distance codes until an end-of-block code. - * - * Format notes: - * - * - Compressed data that is after the block type if fixed or after the code - * description if dynamic is a combination of literals and length/distance - * pairs terminated by and end-of-block code. Literals are simply Huffman - * coded bytes. A length/distance pair is a coded length followed by a - * coded distance to represent a string that occurs earlier in the - * uncompressed data that occurs again at the current location. - * - * - Literals, lengths, and the end-of-block code are combined into a single - * code of up to 286 symbols. They are 256 literals (0..255), 29 length - * symbols (257..285), and the end-of-block symbol (256). - * - * - There are 256 possible lengths (3..258), and so 29 symbols are not enough - * to represent all of those. Lengths 3..10 and 258 are in fact represented - * by just a length symbol. Lengths 11..257 are represented as a symbol and - * some number of extra bits that are added as an integer to the base length - * of the length symbol. The number of extra bits is determined by the base - * length symbol. These are in the static arrays below, lens[] for the base - * lengths and lext[] for the corresponding number of extra bits. - * - * - The reason that 258 gets its own symbol is that the longest length is used - * often in highly redundant files. Note that 258 can also be coded as the - * base value 227 plus the maximum extra value of 31. While a good deflate - * should never do this, it is not an error, and should be decoded properly. - * - * - If a length is decoded, including its extra bits if any, then it is - * followed a distance code. There are up to 30 distance symbols. Again - * there are many more possible distances (1..32768), so extra bits are added - * to a base value represented by the symbol. The distances 1..4 get their - * own symbol, but the rest require extra bits. The base distances and - * corresponding number of extra bits are below in the static arrays dist[] - * and dext[]. - * - * - Literal bytes are simply written to the output. A length/distance pair is - * an instruction to copy previously uncompressed bytes to the output. The - * copy is from distance bytes back in the output stream, copying for length - * bytes. - * - * - Distances pointing before the beginning of the output data are not - * permitted. - * - * - Overlapped copies, where the length is greater than the distance, are - * allowed and common. For example, a distance of one and a length of 258 - * simply copies the last byte 258 times. A distance of four and a length of - * twelve copies the last four bytes three times. A simple forward copy - * ignoring whether the length is greater than the distance or not implements - * this correctly. You should not use memcpy() since its behavior is not - * defined for overlapped arrays. You should not use memmove() or bcopy() - * since though their behavior -is- defined for overlapping arrays, it is - * defined to do the wrong thing in this case. - */ -local int codes(struct state *s, - const struct huffman *lencode, - const struct huffman *distcode) -{ - int symbol; /* decoded symbol */ - int len; /* length for copy */ - unsigned dist; /* distance for copy */ - static const short lens[29] = { /* Size base for length codes 257..285 */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258}; - static const short lext[29] = { /* Extra bits for length codes 257..285 */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; - static const short dists[30] = { /* Offset base for distance codes 0..29 */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; - static const short dext[30] = { /* Extra bits for distance codes 0..29 */ - 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}; - - /* decode literals and length/distance pairs */ - do { - symbol = decode(s, lencode); - if (symbol < 0) - return symbol; /* invalid symbol */ - if (symbol < 256) { /* literal: symbol is the byte */ - /* write out the literal */ - if (s->out != NIL) { - if (s->outcnt == s->outlen) - return 1; - s->out[s->outcnt] = symbol; - } - s->outcnt++; - } - else if (symbol > 256) { /* length */ - /* get and compute length */ - symbol -= 257; - if (symbol >= 29) - return -10; /* invalid fixed code */ - len = lens[symbol] + bits(s, lext[symbol]); - - /* get and check distance */ - symbol = decode(s, distcode); - if (symbol < 0) - return symbol; /* invalid symbol */ - dist = dists[symbol] + bits(s, dext[symbol]); -#ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - if (dist > s->outcnt) - return -11; /* distance too far back */ -#endif - - /* copy length bytes from distance bytes back */ - if (s->out != NIL) { - if (s->outcnt + len > s->outlen) - return 1; - while (len--) { - s->out[s->outcnt] = -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - dist > s->outcnt ? - 0 : -#endif - s->out[s->outcnt - dist]; - s->outcnt++; - } - } - else - s->outcnt += len; - } - } while (symbol != 256); /* end of block symbol */ - - /* done with a valid fixed or dynamic block */ - return 0; -} - -/* - * Process a fixed codes block. - * - * Format notes: - * - * - This block type can be useful for compressing small amounts of data for - * which the size of the code descriptions in a dynamic block exceeds the - * benefit of custom codes for that block. For fixed codes, no bits are - * spent on code descriptions. Instead the code lengths for literal/length - * codes and distance codes are fixed. The specific lengths for each symbol - * can be seen in the "for" loops below. - * - * - The literal/length code is complete, but has two symbols that are invalid - * and should result in an error if received. This cannot be implemented - * simply as an incomplete code since those two symbols are in the "middle" - * of the code. They are eight bits long and the longest literal/length\ - * code is nine bits. Therefore the code must be constructed with those - * symbols, and the invalid symbols must be detected after decoding. - * - * - The fixed distance codes also have two invalid symbols that should result - * in an error if received. Since all of the distance codes are the same - * length, this can be implemented as an incomplete code. Then the invalid - * codes are detected while decoding. - */ -local int fixed(struct state *s) -{ - static int virgin = 1; - static short lencnt[MAXBITS+1], lensym[FIXLCODES]; - static short distcnt[MAXBITS+1], distsym[MAXDCODES]; - static struct huffman lencode, distcode; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - int symbol; - short lengths[FIXLCODES]; - - /* construct lencode and distcode */ - lencode.count = lencnt; - lencode.symbol = lensym; - distcode.count = distcnt; - distcode.symbol = distsym; - - /* literal/length table */ - for (symbol = 0; symbol < 144; symbol++) - lengths[symbol] = 8; - for (; symbol < 256; symbol++) - lengths[symbol] = 9; - for (; symbol < 280; symbol++) - lengths[symbol] = 7; - for (; symbol < FIXLCODES; symbol++) - lengths[symbol] = 8; - construct(&lencode, lengths, FIXLCODES); - - /* distance table */ - for (symbol = 0; symbol < MAXDCODES; symbol++) - lengths[symbol] = 5; - construct(&distcode, lengths, MAXDCODES); - - /* do this just once */ - virgin = 0; - } - - /* decode data until end-of-block code */ - return codes(s, &lencode, &distcode); -} - -/* - * Process a dynamic codes block. - * - * Format notes: - * - * - A dynamic block starts with a description of the literal/length and - * distance codes for that block. New dynamic blocks allow the compressor to - * rapidly adapt to changing data with new codes optimized for that data. - * - * - The codes used by the deflate format are "canonical", which means that - * the actual bits of the codes are generated in an unambiguous way simply - * from the number of bits in each code. Therefore the code descriptions - * are simply a list of code lengths for each symbol. - * - * - The code lengths are stored in order for the symbols, so lengths are - * provided for each of the literal/length symbols, and for each of the - * distance symbols. - * - * - If a symbol is not used in the block, this is represented by a zero as - * as the code length. This does not mean a zero-length code, but rather - * that no code should be created for this symbol. There is no way in the - * deflate format to represent a zero-length code. - * - * - The maximum number of bits in a code is 15, so the possible lengths for - * any code are 1..15. - * - * - The fact that a length of zero is not permitted for a code has an - * interesting consequence. Normally if only one symbol is used for a given - * code, then in fact that code could be represented with zero bits. However - * in deflate, that code has to be at least one bit. So for example, if - * only a single distance base symbol appears in a block, then it will be - * represented by a single code of length one, in particular one 0 bit. This - * is an incomplete code, since if a 1 bit is received, it has no meaning, - * and should result in an error. So incomplete distance codes of one symbol - * should be permitted, and the receipt of invalid codes should be handled. - * - * - It is also possible to have a single literal/length code, but that code - * must be the end-of-block code, since every dynamic block has one. This - * is not the most efficient way to create an empty block (an empty fixed - * block is fewer bits), but it is allowed by the format. So incomplete - * literal/length codes of one symbol should also be permitted. - * - * - If there are only literal codes and no lengths, then there are no distance - * codes. This is represented by one distance code with zero bits. - * - * - The list of up to 286 length/literal lengths and up to 30 distance lengths - * are themselves compressed using Huffman codes and run-length encoding. In - * the list of code lengths, a 0 symbol means no code, a 1..15 symbol means - * that length, and the symbols 16, 17, and 18 are run-length instructions. - * Each of 16, 17, and 18 are follwed by extra bits to define the length of - * the run. 16 copies the last length 3 to 6 times. 17 represents 3 to 10 - * zero lengths, and 18 represents 11 to 138 zero lengths. Unused symbols - * are common, hence the special coding for zero lengths. - * - * - The symbols for 0..18 are Huffman coded, and so that code must be - * described first. This is simply a sequence of up to 19 three-bit values - * representing no code (0) or the code length for that symbol (1..7). - * - * - A dynamic block starts with three fixed-size counts from which is computed - * the number of literal/length code lengths, the number of distance code - * lengths, and the number of code length code lengths (ok, you come up with - * a better name!) in the code descriptions. For the literal/length and - * distance codes, lengths after those provided are considered zero, i.e. no - * code. The code length code lengths are received in a permuted order (see - * the order[] array below) to make a short code length code length list more - * likely. As it turns out, very short and very long codes are less likely - * to be seen in a dynamic code description, hence what may appear initially - * to be a peculiar ordering. - * - * - Given the number of literal/length code lengths (nlen) and distance code - * lengths (ndist), then they are treated as one long list of nlen + ndist - * code lengths. Therefore run-length coding can and often does cross the - * boundary between the two sets of lengths. - * - * - So to summarize, the code description at the start of a dynamic block is - * three counts for the number of code lengths for the literal/length codes, - * the distance codes, and the code length codes. This is followed by the - * code length code lengths, three bits each. This is used to construct the - * code length code which is used to read the remainder of the lengths. Then - * the literal/length code lengths and distance lengths are read as a single - * set of lengths using the code length codes. Codes are constructed from - * the resulting two sets of lengths, and then finally you can start - * decoding actual compressed data in the block. - * - * - For reference, a "typical" size for the code description in a dynamic - * block is around 80 bytes. - */ -local int dynamic(struct state *s) -{ - int nlen, ndist, ncode; /* number of lengths in descriptor */ - int index; /* index of lengths[] */ - int err; /* construct() return value */ - short lengths[MAXCODES]; /* descriptor code lengths */ - short lencnt[MAXBITS+1], lensym[MAXLCODES]; /* lencode memory */ - short distcnt[MAXBITS+1], distsym[MAXDCODES]; /* distcode memory */ - struct huffman lencode, distcode; /* length and distance codes */ - static const short order[19] = /* permutation of code length codes */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - /* construct lencode and distcode */ - lencode.count = lencnt; - lencode.symbol = lensym; - distcode.count = distcnt; - distcode.symbol = distsym; - - /* get number of lengths in each table, check lengths */ - nlen = bits(s, 5) + 257; - ndist = bits(s, 5) + 1; - ncode = bits(s, 4) + 4; - if (nlen > MAXLCODES || ndist > MAXDCODES) - return -3; /* bad counts */ - - /* read code length code lengths (really), missing lengths are zero */ - for (index = 0; index < ncode; index++) - lengths[order[index]] = bits(s, 3); - for (; index < 19; index++) - lengths[order[index]] = 0; - - /* build huffman table for code lengths codes (use lencode temporarily) */ - err = construct(&lencode, lengths, 19); - if (err != 0) /* require complete code set here */ - return -4; - - /* read length/literal and distance code length tables */ - index = 0; - while (index < nlen + ndist) { - int symbol; /* decoded value */ - int len; /* last length to repeat */ - - symbol = decode(s, &lencode); - if (symbol < 0) - return symbol; /* invalid symbol */ - if (symbol < 16) /* length in 0..15 */ - lengths[index++] = symbol; - else { /* repeat instruction */ - len = 0; /* assume repeating zeros */ - if (symbol == 16) { /* repeat last length 3..6 times */ - if (index == 0) - return -5; /* no last length! */ - len = lengths[index - 1]; /* last length */ - symbol = 3 + bits(s, 2); - } - else if (symbol == 17) /* repeat zero 3..10 times */ - symbol = 3 + bits(s, 3); - else /* == 18, repeat zero 11..138 times */ - symbol = 11 + bits(s, 7); - if (index + symbol > nlen + ndist) - return -6; /* too many lengths! */ - while (symbol--) /* repeat last or zero symbol times */ - lengths[index++] = len; - } - } - - /* check for end-of-block code -- there better be one! */ - if (lengths[256] == 0) - return -9; - - /* build huffman table for literal/length codes */ - err = construct(&lencode, lengths, nlen); - if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1])) - return -7; /* incomplete code ok only for single length 1 code */ - - /* build huffman table for distance codes */ - err = construct(&distcode, lengths + nlen, ndist); - if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1])) - return -8; /* incomplete code ok only for single length 1 code */ - - /* decode data until end-of-block code */ - return codes(s, &lencode, &distcode); -} - -/* - * Inflate source to dest. On return, destlen and sourcelen are updated to the - * size of the uncompressed data and the size of the deflate data respectively. - * On success, the return value of puff() is zero. If there is an error in the - * source data, i.e. it is not in the deflate format, then a negative value is - * returned. If there is not enough input available or there is not enough - * output space, then a positive error is returned. In that case, destlen and - * sourcelen are not updated to facilitate retrying from the beginning with the - * provision of more input data or more output space. In the case of invalid - * inflate data (a negative error), the dest and source pointers are updated to - * facilitate the debugging of deflators. - * - * puff() also has a mode to determine the size of the uncompressed output with - * no output written. For this dest must be (unsigned char *)0. In this case, - * the input value of *destlen is ignored, and on return *destlen is set to the - * size of the uncompressed output. - * - * The return codes are: - * - * 2: available inflate data did not terminate - * 1: output space exhausted before completing inflate - * 0: successful inflate - * -1: invalid block type (type == 3) - * -2: stored block length did not match one's complement - * -3: dynamic block code description: too many length or distance codes - * -4: dynamic block code description: code lengths codes incomplete - * -5: dynamic block code description: repeat lengths with no first length - * -6: dynamic block code description: repeat more than specified lengths - * -7: dynamic block code description: invalid literal/length code lengths - * -8: dynamic block code description: invalid distance code lengths - * -9: dynamic block code description: missing end-of-block code - * -10: invalid literal/length or distance code in fixed or dynamic block - * -11: distance is too far back in fixed or dynamic block - * - * Format notes: - * - * - Three bits are read for each block to determine the kind of block and - * whether or not it is the last block. Then the block is decoded and the - * process repeated if it was not the last block. - * - * - The leftover bits in the last byte of the deflate data after the last - * block (if it was a fixed or dynamic block) are undefined and have no - * expected values to check. - */ -int puff(unsigned char *dest, /* pointer to destination pointer */ - unsigned long *destlen, /* amount of output space */ - const unsigned char *source, /* pointer to source data pointer */ - unsigned long *sourcelen) /* amount of input available */ -{ - struct state s; /* input/output state */ - int last, type; /* block information */ - int err; /* return value */ - - /* initialize output state */ - s.out = dest; - s.outlen = *destlen; /* ignored if dest is NIL */ - s.outcnt = 0; - - /* initialize input state */ - s.in = source; - s.inlen = *sourcelen; - s.incnt = 0; - s.bitbuf = 0; - s.bitcnt = 0; - - /* return if bits() or decode() tries to read past available input */ - if (setjmp(s.env) != 0) /* if came back here via longjmp() */ - err = 2; /* then skip do-loop, return error */ - else { - /* process blocks until last block or error */ - do { - last = bits(&s, 1); /* one if last block */ - type = bits(&s, 2); /* block type 0..3 */ - err = type == 0 ? - stored(&s) : - (type == 1 ? - fixed(&s) : - (type == 2 ? - dynamic(&s) : - -1)); /* type == 3, invalid */ - if (err != 0) - break; /* return with error */ - } while (!last); - } - - /* update the lengths and return */ - if (err <= 0) { - *destlen = s.outcnt; - *sourcelen = s.incnt; - } - return err; -} diff --git a/deps/zlib/contrib/puff/puff.h b/deps/zlib/contrib/puff/puff.h deleted file mode 100644 index e23a2454316cfa..00000000000000 --- a/deps/zlib/contrib/puff/puff.h +++ /dev/null @@ -1,35 +0,0 @@ -/* puff.h - Copyright (C) 2002-2013 Mark Adler, all rights reserved - version 2.3, 21 Jan 2013 - - This software is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Mark Adler madler@alumni.caltech.edu - */ - - -/* - * See puff.c for purpose and usage. - */ -#ifndef NIL -# define NIL ((unsigned char *)0) /* for no output option */ -#endif - -int puff(unsigned char *dest, /* pointer to destination pointer */ - unsigned long *destlen, /* amount of output space */ - const unsigned char *source, /* pointer to source data pointer */ - unsigned long *sourcelen); /* amount of input available */ diff --git a/deps/zlib/contrib/puff/pufftest.c b/deps/zlib/contrib/puff/pufftest.c deleted file mode 100644 index 776481488c90d0..00000000000000 --- a/deps/zlib/contrib/puff/pufftest.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * pufftest.c - * Copyright (C) 2002-2013 Mark Adler - * For conditions of distribution and use, see copyright notice in puff.h - * version 2.3, 21 Jan 2013 - */ - -/* Example of how to use puff(). - - Usage: puff [-w] [-f] [-nnn] file - ... | puff [-w] [-f] [-nnn] - - where file is the input file with deflate data, nnn is the number of bytes - of input to skip before inflating (e.g. to skip a zlib or gzip header), and - -w is used to write the decompressed data to stdout. -f is for coverage - testing, and causes pufftest to fail with not enough output space (-f does - a write like -w, so -w is not required). */ - -#include -#include -#include "puff.h" - -#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) -# include -# include -# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -#else -# define SET_BINARY_MODE(file) -#endif - -#define local static - -/* Return size times approximately the cube root of 2, keeping the result as 1, - 3, or 5 times a power of 2 -- the result is always > size, until the result - is the maximum value of an unsigned long, where it remains. This is useful - to keep reallocations less than ~33% over the actual data. */ -local size_t bythirds(size_t size) -{ - int n; - size_t m; - - m = size; - for (n = 0; m; n++) - m >>= 1; - if (n < 3) - return size + 1; - n -= 3; - m = size >> n; - m += m == 6 ? 2 : 1; - m <<= n; - return m > size ? m : (size_t)(-1); -} - -/* Read the input file *name, or stdin if name is NULL, into allocated memory. - Reallocate to larger buffers until the entire file is read in. Return a - pointer to the allocated data, or NULL if there was a memory allocation - failure. *len is the number of bytes of data read from the input file (even - if load() returns NULL). If the input file was empty or could not be opened - or read, *len is zero. */ -local void *load(const char *name, size_t *len) -{ - size_t size; - void *buf, *swap; - FILE *in; - - *len = 0; - buf = malloc(size = 4096); - if (buf == NULL) - return NULL; - in = name == NULL ? stdin : fopen(name, "rb"); - if (in != NULL) { - for (;;) { - *len += fread((char *)buf + *len, 1, size - *len, in); - if (*len < size) break; - size = bythirds(size); - if (size == *len || (swap = realloc(buf, size)) == NULL) { - free(buf); - buf = NULL; - break; - } - buf = swap; - } - fclose(in); - } - return buf; -} - -int main(int argc, char **argv) -{ - int ret, put = 0, fail = 0; - unsigned skip = 0; - char *arg, *name = NULL; - unsigned char *source = NULL, *dest; - size_t len = 0; - unsigned long sourcelen, destlen; - - /* process arguments */ - while (arg = *++argv, --argc) - if (arg[0] == '-') { - if (arg[1] == 'w' && arg[2] == 0) - put = 1; - else if (arg[1] == 'f' && arg[2] == 0) - fail = 1, put = 1; - else if (arg[1] >= '0' && arg[1] <= '9') - skip = (unsigned)atoi(arg + 1); - else { - fprintf(stderr, "invalid option %s\n", arg); - return 3; - } - } - else if (name != NULL) { - fprintf(stderr, "only one file name allowed\n"); - return 3; - } - else - name = arg; - source = load(name, &len); - if (source == NULL) { - fprintf(stderr, "memory allocation failure\n"); - return 4; - } - if (len == 0) { - fprintf(stderr, "could not read %s, or it was empty\n", - name == NULL ? "" : name); - free(source); - return 3; - } - if (skip >= len) { - fprintf(stderr, "skip request of %d leaves no input\n", skip); - free(source); - return 3; - } - - /* test inflate data with offset skip */ - len -= skip; - sourcelen = (unsigned long)len; - ret = puff(NIL, &destlen, source + skip, &sourcelen); - if (ret) - fprintf(stderr, "puff() failed with return code %d\n", ret); - else { - fprintf(stderr, "puff() succeeded uncompressing %lu bytes\n", destlen); - if (sourcelen < len) fprintf(stderr, "%lu compressed bytes unused\n", - len - sourcelen); - } - - /* if requested, inflate again and write decompressd data to stdout */ - if (put && ret == 0) { - if (fail) - destlen >>= 1; - dest = malloc(destlen); - if (dest == NULL) { - fprintf(stderr, "memory allocation failure\n"); - free(source); - return 4; - } - puff(dest, &destlen, source + skip, &sourcelen); - SET_BINARY_MODE(stdout); - fwrite(dest, 1, destlen, stdout); - free(dest); - } - - /* clean up */ - free(source); - return ret; -} diff --git a/deps/zlib/contrib/puff/zeros.raw b/deps/zlib/contrib/puff/zeros.raw deleted file mode 100644 index 0a90e76b300205..00000000000000 Binary files a/deps/zlib/contrib/puff/zeros.raw and /dev/null differ diff --git a/deps/zlib/contrib/tests/OWNERS b/deps/zlib/contrib/tests/OWNERS new file mode 100644 index 00000000000000..9a2fb6fbdc6b3f --- /dev/null +++ b/deps/zlib/contrib/tests/OWNERS @@ -0,0 +1 @@ +cblume@chromium.org diff --git a/deps/zlib/contrib/tests/fuzzers/BUILD.gn b/deps/zlib/contrib/tests/fuzzers/BUILD.gn new file mode 100644 index 00000000000000..c46b66440073a5 --- /dev/null +++ b/deps/zlib/contrib/tests/fuzzers/BUILD.gn @@ -0,0 +1,45 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//testing/libfuzzer/fuzzer_test.gni") + +# root BUILD depends on this target. Needed for package discovery +group("fuzzers") { +} + +fuzzer_test("zlib_uncompress_fuzzer") { + sources = [ + "uncompress_fuzzer.cc", + ] + deps = [ + "../../../:zlib", + ] +} + +fuzzer_test("zlib_inflate_fuzzer") { + sources = [ + "inflate_fuzzer.cc", + ] + deps = [ + "../../../:zlib", + ] +} + +fuzzer_test("zlib_deflate_set_dictionary_fuzzer") { + sources = [ + "deflate_set_dictionary_fuzzer.cc", + ] + deps = [ + "../../../:zlib", + ] +} + +fuzzer_test("zlib_deflate_fuzzer") { + sources = [ + "deflate_fuzzer.cc", + ] + deps = [ + "../../../:zlib", + ] +} diff --git a/deps/zlib/contrib/tests/fuzzers/OWNERS b/deps/zlib/contrib/tests/fuzzers/OWNERS new file mode 100644 index 00000000000000..6397ce69c70649 --- /dev/null +++ b/deps/zlib/contrib/tests/fuzzers/OWNERS @@ -0,0 +1,2 @@ +cblume@chromium.org +mmoroz@chromium.org diff --git a/deps/zlib/contrib/tests/fuzzers/deflate_fuzzer.cc b/deps/zlib/contrib/tests/fuzzers/deflate_fuzzer.cc new file mode 100644 index 00000000000000..6098ff162ce1c0 --- /dev/null +++ b/deps/zlib/contrib/tests/fuzzers/deflate_fuzzer.cc @@ -0,0 +1,47 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include +#include +#include + +#include "third_party/zlib/zlib.h" + +static Bytef buffer[256 * 1024] = {0}; + +// Entry point for LibFuzzer. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + // zlib's deflate requires non-zero input sizes + if (!size) + return 0; + + // We need to strip the 'const' for zlib. + std::vector input_buffer{data, data+size}; + + uLongf buffer_length = static_cast(sizeof(buffer)); + + z_stream stream; + stream.next_in = input_buffer.data(); + stream.avail_in = size; + stream.total_in = size; + stream.next_out = buffer; + stream.avail_out = buffer_length; + stream.total_out = buffer_length; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + + if (Z_OK != deflateInit(&stream, Z_DEFAULT_COMPRESSION)) { + deflateEnd(&stream); + assert(false); + } + + auto deflate_result = deflate(&stream, Z_NO_FLUSH); + deflateEnd(&stream); + if (Z_OK != deflate_result) + assert(false); + + return 0; +} diff --git a/deps/zlib/contrib/tests/fuzzers/deflate_set_dictionary_fuzzer.cc b/deps/zlib/contrib/tests/fuzzers/deflate_set_dictionary_fuzzer.cc new file mode 100644 index 00000000000000..febbfcb86f0c3e --- /dev/null +++ b/deps/zlib/contrib/tests/fuzzers/deflate_set_dictionary_fuzzer.cc @@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include +#include + +#include "third_party/zlib/zlib.h" + +static Bytef buffer[256 * 1024] = {0}; + +// Entry point for LibFuzzer. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + // We need to strip the 'const' for zlib. + std::vector input_buffer{data, data + size}; + + uLongf buffer_length = static_cast(sizeof(buffer)); + + z_stream stream; + stream.next_in = input_buffer.data(); + stream.avail_in = size; + stream.total_in = size; + stream.next_out = buffer; + stream.avail_out = buffer_length; + stream.total_out = buffer_length; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + + if (Z_OK != deflateInit(&stream, Z_DEFAULT_COMPRESSION)) { + deflateEnd(&stream); + assert(false); + } + + auto deflate_set_dictionary_result = + deflateSetDictionary(&stream, data, size); + deflateEnd(&stream); + if (Z_OK != deflate_set_dictionary_result) + assert(false); + + return 0; +} diff --git a/deps/zlib/contrib/tests/fuzzers/inflate_fuzzer.cc b/deps/zlib/contrib/tests/fuzzers/inflate_fuzzer.cc new file mode 100644 index 00000000000000..44f9c72c18df8a --- /dev/null +++ b/deps/zlib/contrib/tests/fuzzers/inflate_fuzzer.cc @@ -0,0 +1,41 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include +#include +#include + +#include "third_party/zlib/zlib.h" + +static Bytef buffer[256 * 1024] = {0}; + +// Entry point for LibFuzzer. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + // We need to strip the 'const' for zlib + std::vector input_buffer{data, data+size}; + + uLongf buffer_length = static_cast(sizeof(buffer)); + + z_stream stream; + stream.next_in = input_buffer.data(); + stream.avail_in = size; + stream.total_in = size; + stream.next_out = buffer; + stream.avail_out = buffer_length; + stream.total_out = buffer_length; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + + if (Z_OK != inflateInit(&stream)) { + inflateEnd(&stream); + assert(false); + } + + inflate(&stream, Z_NO_FLUSH); + inflateEnd(&stream); + + return 0; +} diff --git a/deps/zlib/contrib/tests/fuzzers/uncompress_fuzzer.cc b/deps/zlib/contrib/tests/fuzzers/uncompress_fuzzer.cc new file mode 100644 index 00000000000000..bca5244e8b38b4 --- /dev/null +++ b/deps/zlib/contrib/tests/fuzzers/uncompress_fuzzer.cc @@ -0,0 +1,21 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include + +#include "third_party/zlib/zlib.h" + +static Bytef buffer[256 * 1024] = {0}; + +// Entry point for LibFuzzer. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + uLongf buffer_length = static_cast(sizeof(buffer)); + if (Z_OK != + uncompress(buffer, &buffer_length, data, static_cast(size))) { + return 0; + } + return 0; +} diff --git a/deps/zlib/contrib/testzlib/testzlib.c b/deps/zlib/contrib/testzlib/testzlib.c deleted file mode 100644 index 8626c92ad17566..00000000000000 --- a/deps/zlib/contrib/testzlib/testzlib.c +++ /dev/null @@ -1,275 +0,0 @@ -#include -#include -#include - -#include "zlib.h" - - -void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B) -{ - R->HighPart = A.HighPart - B.HighPart; - if (A.LowPart >= B.LowPart) - R->LowPart = A.LowPart - B.LowPart; - else - { - R->LowPart = A.LowPart - B.LowPart; - R->HighPart --; - } -} - -#ifdef _M_X64 -// see http://msdn2.microsoft.com/library/twchhe95(en-us,vs.80).aspx for __rdtsc -unsigned __int64 __rdtsc(void); -void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) -{ - // printf("rdtsc = %I64x\n",__rdtsc()); - pbeginTime64->QuadPart=__rdtsc(); -} - -LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER LIres; - unsigned _int64 res=__rdtsc()-((unsigned _int64)(beginTime64.QuadPart)); - LIres.QuadPart=res; - // printf("rdtsc = %I64x\n",__rdtsc()); - return LIres; -} -#else -#ifdef _M_IX86 -void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) -{ - DWORD dwEdx,dwEax; - _asm - { - rdtsc - mov dwEax,eax - mov dwEdx,edx - } - pbeginTime64->LowPart=dwEax; - pbeginTime64->HighPart=dwEdx; -} - -void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) -{ - myGetRDTSC32(pbeginTime64); -} - -LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER LIres,endTime64; - myGetRDTSC32(&endTime64); - - LIres.LowPart=LIres.HighPart=0; - MyDoMinus64(&LIres,endTime64,beginTime64); - return LIres; -} -#else -void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) -{ -} - -void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) -{ -} - -LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER lr; - lr.QuadPart=0; - return lr; -} -#endif -#endif - -void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf) -{ - if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64))) - { - pbeginTime64->LowPart = GetTickCount(); - pbeginTime64->HighPart = 0; - } -} - -DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER endTime64,ticksPerSecond,ticks; - DWORDLONG ticksShifted,tickSecShifted; - DWORD dwLog=16+0; - DWORD dwRet; - if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64))) - dwRet = (GetTickCount() - beginTime64.LowPart)*1; - else - { - MyDoMinus64(&ticks,endTime64,beginTime64); - QueryPerformanceFrequency(&ticksPerSecond); - - - { - ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog); - tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog); - - } - - dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted)); - dwRet *=1; - } - return dwRet; -} - -int ReadFileMemory(const char* filename,long* plFileSize,unsigned char** pFilePtr) -{ - FILE* stream; - unsigned char* ptr; - int retVal=1; - stream=fopen(filename, "rb"); - if (stream==NULL) - return 0; - - fseek(stream,0,SEEK_END); - - *plFileSize=ftell(stream); - fseek(stream,0,SEEK_SET); - ptr=malloc((*plFileSize)+1); - if (ptr==NULL) - retVal=0; - else - { - if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize)) - retVal=0; - } - fclose(stream); - *pFilePtr=ptr; - return retVal; -} - -int main(int argc, char *argv[]) -{ - int BlockSizeCompress=0x8000; - int BlockSizeUncompress=0x8000; - int cprLevel=Z_DEFAULT_COMPRESSION ; - long lFileSize; - unsigned char* FilePtr; - long lBufferSizeCpr; - long lBufferSizeUncpr; - long lCompressedSize=0; - unsigned char* CprPtr; - unsigned char* UncprPtr; - long lSizeCpr,lSizeUncpr; - DWORD dwGetTick,dwMsecQP; - LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc; - - if (argc<=1) - { - printf("run TestZlib [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n"); - return 0; - } - - if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0) - { - printf("error reading %s\n",argv[1]); - return 1; - } - else printf("file %s read, %u bytes\n",argv[1],lFileSize); - - if (argc>=3) - BlockSizeCompress=atol(argv[2]); - - if (argc>=4) - BlockSizeUncompress=atol(argv[3]); - - if (argc>=5) - cprLevel=(int)atol(argv[4]); - - lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200; - lBufferSizeUncpr = lBufferSizeCpr; - - CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress); - - BeginCountPerfCounter(&li_qp,TRUE); - dwGetTick=GetTickCount(); - BeginCountRdtsc(&li_rdtsc); - { - z_stream zcpr; - int ret=Z_OK; - long lOrigToDo = lFileSize; - long lOrigDone = 0; - int step=0; - memset(&zcpr,0,sizeof(z_stream)); - deflateInit(&zcpr,cprLevel); - - zcpr.next_in = FilePtr; - zcpr.next_out = CprPtr; - - - do - { - long all_read_before = zcpr.total_in; - zcpr.avail_in = min(lOrigToDo,BlockSizeCompress); - zcpr.avail_out = BlockSizeCompress; - ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH); - lOrigDone += (zcpr.total_in-all_read_before); - lOrigToDo -= (zcpr.total_in-all_read_before); - step++; - } while (ret==Z_OK); - - lSizeCpr=zcpr.total_out; - deflateEnd(&zcpr); - dwGetTick=GetTickCount()-dwGetTick; - dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); - dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); - printf("total compress size = %u, in %u step\n",lSizeCpr,step); - printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); - printf("defcpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); - printf("defcpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); - } - - CprPtr=(unsigned char*)realloc(CprPtr,lSizeCpr); - UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress); - - BeginCountPerfCounter(&li_qp,TRUE); - dwGetTick=GetTickCount(); - BeginCountRdtsc(&li_rdtsc); - { - z_stream zcpr; - int ret=Z_OK; - long lOrigToDo = lSizeCpr; - long lOrigDone = 0; - int step=0; - memset(&zcpr,0,sizeof(z_stream)); - inflateInit(&zcpr); - - zcpr.next_in = CprPtr; - zcpr.next_out = UncprPtr; - - - do - { - long all_read_before = zcpr.total_in; - zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress); - zcpr.avail_out = BlockSizeUncompress; - ret=inflate(&zcpr,Z_SYNC_FLUSH); - lOrigDone += (zcpr.total_in-all_read_before); - lOrigToDo -= (zcpr.total_in-all_read_before); - step++; - } while (ret==Z_OK); - - lSizeUncpr=zcpr.total_out; - inflateEnd(&zcpr); - dwGetTick=GetTickCount()-dwGetTick; - dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); - dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); - printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step); - printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); - printf("uncpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); - printf("uncpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); - } - - if (lSizeUncpr==lFileSize) - { - if (memcmp(FilePtr,UncprPtr,lFileSize)==0) - printf("compare ok\n"); - - } - - return 0; -} diff --git a/deps/zlib/contrib/testzlib/testzlib.txt b/deps/zlib/contrib/testzlib/testzlib.txt deleted file mode 100644 index e508bb22ff4aef..00000000000000 --- a/deps/zlib/contrib/testzlib/testzlib.txt +++ /dev/null @@ -1,10 +0,0 @@ -To build testzLib with Visual Studio 2005: - -copy to a directory file from : -- root of zLib tree -- contrib/testzlib -- contrib/masmx86 -- contrib/masmx64 -- contrib/vstudio/vc7 - -and open testzlib8.sln \ No newline at end of file diff --git a/deps/zlib/contrib/untgz/Makefile b/deps/zlib/contrib/untgz/Makefile deleted file mode 100644 index b54266fba20a16..00000000000000 --- a/deps/zlib/contrib/untgz/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -CC=cc -CFLAGS=-g - -untgz: untgz.o ../../libz.a - $(CC) $(CFLAGS) -o untgz untgz.o -L../.. -lz - -untgz.o: untgz.c ../../zlib.h - $(CC) $(CFLAGS) -c -I../.. untgz.c - -../../libz.a: - cd ../..; ./configure; make - -clean: - rm -f untgz untgz.o *~ diff --git a/deps/zlib/contrib/untgz/Makefile.msc b/deps/zlib/contrib/untgz/Makefile.msc deleted file mode 100644 index 77b86022137da7..00000000000000 --- a/deps/zlib/contrib/untgz/Makefile.msc +++ /dev/null @@ -1,17 +0,0 @@ -CC=cl -CFLAGS=-MD - -untgz.exe: untgz.obj ..\..\zlib.lib - $(CC) $(CFLAGS) untgz.obj ..\..\zlib.lib - -untgz.obj: untgz.c ..\..\zlib.h - $(CC) $(CFLAGS) -c -I..\.. untgz.c - -..\..\zlib.lib: - cd ..\.. - $(MAKE) -f win32\makefile.msc - cd contrib\untgz - -clean: - -del untgz.obj - -del untgz.exe diff --git a/deps/zlib/contrib/untgz/untgz.c b/deps/zlib/contrib/untgz/untgz.c deleted file mode 100644 index 2c391e5986753d..00000000000000 --- a/deps/zlib/contrib/untgz/untgz.c +++ /dev/null @@ -1,674 +0,0 @@ -/* - * untgz.c -- Display contents and extract files from a gzip'd TAR file - * - * written by Pedro A. Aranda Gutierrez - * adaptation to Unix by Jean-loup Gailly - * various fixes by Cosmin Truta - */ - -#include -#include -#include -#include -#include - -#include "zlib.h" - -#ifdef unix -# include -#else -# include -# include -#endif - -#ifdef WIN32 -#include -# ifndef F_OK -# define F_OK 0 -# endif -# define mkdir(dirname,mode) _mkdir(dirname) -# ifdef _MSC_VER -# define access(path,mode) _access(path,mode) -# define chmod(path,mode) _chmod(path,mode) -# define strdup(str) _strdup(str) -# endif -#else -# include -#endif - - -/* values used in typeflag field */ - -#define REGTYPE '0' /* regular file */ -#define AREGTYPE '\0' /* regular file */ -#define LNKTYPE '1' /* link */ -#define SYMTYPE '2' /* reserved */ -#define CHRTYPE '3' /* character special */ -#define BLKTYPE '4' /* block special */ -#define DIRTYPE '5' /* directory */ -#define FIFOTYPE '6' /* FIFO special */ -#define CONTTYPE '7' /* reserved */ - -/* GNU tar extensions */ - -#define GNUTYPE_DUMPDIR 'D' /* file names from dumped directory */ -#define GNUTYPE_LONGLINK 'K' /* long link name */ -#define GNUTYPE_LONGNAME 'L' /* long file name */ -#define GNUTYPE_MULTIVOL 'M' /* continuation of file from another volume */ -#define GNUTYPE_NAMES 'N' /* file name that does not fit into main hdr */ -#define GNUTYPE_SPARSE 'S' /* sparse file */ -#define GNUTYPE_VOLHDR 'V' /* tape/volume header */ - - -/* tar header */ - -#define BLOCKSIZE 512 -#define SHORTNAMESIZE 100 - -struct tar_header -{ /* byte offset */ - char name[100]; /* 0 */ - char mode[8]; /* 100 */ - char uid[8]; /* 108 */ - char gid[8]; /* 116 */ - char size[12]; /* 124 */ - char mtime[12]; /* 136 */ - char chksum[8]; /* 148 */ - char typeflag; /* 156 */ - char linkname[100]; /* 157 */ - char magic[6]; /* 257 */ - char version[2]; /* 263 */ - char uname[32]; /* 265 */ - char gname[32]; /* 297 */ - char devmajor[8]; /* 329 */ - char devminor[8]; /* 337 */ - char prefix[155]; /* 345 */ - /* 500 */ -}; - -union tar_buffer -{ - char buffer[BLOCKSIZE]; - struct tar_header header; -}; - -struct attr_item -{ - struct attr_item *next; - char *fname; - int mode; - time_t time; -}; - -enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID }; - -char *TGZfname OF((const char *)); -void TGZnotfound OF((const char *)); - -int getoct OF((char *, int)); -char *strtime OF((time_t *)); -int setfiletime OF((char *, time_t)); -void push_attr OF((struct attr_item **, char *, int, time_t)); -void restore_attr OF((struct attr_item **)); - -int ExprMatch OF((char *, char *)); - -int makedir OF((char *)); -int matchname OF((int, int, char **, char *)); - -void error OF((const char *)); -int tar OF((gzFile, int, int, int, char **)); - -void help OF((int)); -int main OF((int, char **)); - -char *prog; - -const char *TGZsuffix[] = { "\0", ".tar", ".tar.gz", ".taz", ".tgz", NULL }; - -/* return the file name of the TGZ archive */ -/* or NULL if it does not exist */ - -char *TGZfname (const char *arcname) -{ - static char buffer[1024]; - int origlen,i; - - strcpy(buffer,arcname); - origlen = strlen(buffer); - - for (i=0; TGZsuffix[i]; i++) - { - strcpy(buffer+origlen,TGZsuffix[i]); - if (access(buffer,F_OK) == 0) - return buffer; - } - return NULL; -} - - -/* error message for the filename */ - -void TGZnotfound (const char *arcname) -{ - int i; - - fprintf(stderr,"%s: Couldn't find ",prog); - for (i=0;TGZsuffix[i];i++) - fprintf(stderr,(TGZsuffix[i+1]) ? "%s%s, " : "or %s%s\n", - arcname, - TGZsuffix[i]); - exit(1); -} - - -/* convert octal digits to int */ -/* on error return -1 */ - -int getoct (char *p,int width) -{ - int result = 0; - char c; - - while (width--) - { - c = *p++; - if (c == 0) - break; - if (c == ' ') - continue; - if (c < '0' || c > '7') - return -1; - result = result * 8 + (c - '0'); - } - return result; -} - - -/* convert time_t to string */ -/* use the "YYYY/MM/DD hh:mm:ss" format */ - -char *strtime (time_t *t) -{ - struct tm *local; - static char result[32]; - - local = localtime(t); - sprintf(result,"%4d/%02d/%02d %02d:%02d:%02d", - local->tm_year+1900, local->tm_mon+1, local->tm_mday, - local->tm_hour, local->tm_min, local->tm_sec); - return result; -} - - -/* set file time */ - -int setfiletime (char *fname,time_t ftime) -{ -#ifdef WIN32 - static int isWinNT = -1; - SYSTEMTIME st; - FILETIME locft, modft; - struct tm *loctm; - HANDLE hFile; - int result; - - loctm = localtime(&ftime); - if (loctm == NULL) - return -1; - - st.wYear = (WORD)loctm->tm_year + 1900; - st.wMonth = (WORD)loctm->tm_mon + 1; - st.wDayOfWeek = (WORD)loctm->tm_wday; - st.wDay = (WORD)loctm->tm_mday; - st.wHour = (WORD)loctm->tm_hour; - st.wMinute = (WORD)loctm->tm_min; - st.wSecond = (WORD)loctm->tm_sec; - st.wMilliseconds = 0; - if (!SystemTimeToFileTime(&st, &locft) || - !LocalFileTimeToFileTime(&locft, &modft)) - return -1; - - if (isWinNT < 0) - isWinNT = (GetVersion() < 0x80000000) ? 1 : 0; - hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, - (isWinNT ? FILE_FLAG_BACKUP_SEMANTICS : 0), - NULL); - if (hFile == INVALID_HANDLE_VALUE) - return -1; - result = SetFileTime(hFile, NULL, NULL, &modft) ? 0 : -1; - CloseHandle(hFile); - return result; -#else - struct utimbuf settime; - - settime.actime = settime.modtime = ftime; - return utime(fname,&settime); -#endif -} - - -/* push file attributes */ - -void push_attr(struct attr_item **list,char *fname,int mode,time_t time) -{ - struct attr_item *item; - - item = (struct attr_item *)malloc(sizeof(struct attr_item)); - if (item == NULL) - error("Out of memory"); - item->fname = strdup(fname); - item->mode = mode; - item->time = time; - item->next = *list; - *list = item; -} - - -/* restore file attributes */ - -void restore_attr(struct attr_item **list) -{ - struct attr_item *item, *prev; - - for (item = *list; item != NULL; ) - { - setfiletime(item->fname,item->time); - chmod(item->fname,item->mode); - prev = item; - item = item->next; - free(prev); - } - *list = NULL; -} - - -/* match regular expression */ - -#define ISSPECIAL(c) (((c) == '*') || ((c) == '/')) - -int ExprMatch (char *string,char *expr) -{ - while (1) - { - if (ISSPECIAL(*expr)) - { - if (*expr == '/') - { - if (*string != '\\' && *string != '/') - return 0; - string ++; expr++; - } - else if (*expr == '*') - { - if (*expr ++ == 0) - return 1; - while (*++string != *expr) - if (*string == 0) - return 0; - } - } - else - { - if (*string != *expr) - return 0; - if (*expr++ == 0) - return 1; - string++; - } - } -} - - -/* recursive mkdir */ -/* abort on ENOENT; ignore other errors like "directory already exists" */ -/* return 1 if OK */ -/* 0 on error */ - -int makedir (char *newdir) -{ - char *buffer = strdup(newdir); - char *p; - int len = strlen(buffer); - - if (len <= 0) { - free(buffer); - return 0; - } - if (buffer[len-1] == '/') { - buffer[len-1] = '\0'; - } - if (mkdir(buffer, 0755) == 0) - { - free(buffer); - return 1; - } - - p = buffer+1; - while (1) - { - char hold; - - while(*p && *p != '\\' && *p != '/') - p++; - hold = *p; - *p = 0; - if ((mkdir(buffer, 0755) == -1) && (errno == ENOENT)) - { - fprintf(stderr,"%s: Couldn't create directory %s\n",prog,buffer); - free(buffer); - return 0; - } - if (hold == 0) - break; - *p++ = hold; - } - free(buffer); - return 1; -} - - -int matchname (int arg,int argc,char **argv,char *fname) -{ - if (arg == argc) /* no arguments given (untgz tgzarchive) */ - return 1; - - while (arg < argc) - if (ExprMatch(fname,argv[arg++])) - return 1; - - return 0; /* ignore this for the moment being */ -} - - -/* tar file list or extract */ - -int tar (gzFile in,int action,int arg,int argc,char **argv) -{ - union tar_buffer buffer; - int len; - int err; - int getheader = 1; - int remaining = 0; - FILE *outfile = NULL; - char fname[BLOCKSIZE]; - int tarmode; - time_t tartime; - struct attr_item *attributes = NULL; - - if (action == TGZ_LIST) - printf(" date time size file\n" - " ---------- -------- --------- -------------------------------------\n"); - while (1) - { - len = gzread(in, &buffer, BLOCKSIZE); - if (len < 0) - error(gzerror(in, &err)); - /* - * Always expect complete blocks to process - * the tar information. - */ - if (len != BLOCKSIZE) - { - action = TGZ_INVALID; /* force error exit */ - remaining = 0; /* force I/O cleanup */ - } - - /* - * If we have to get a tar header - */ - if (getheader >= 1) - { - /* - * if we met the end of the tar - * or the end-of-tar block, - * we are done - */ - if (len == 0 || buffer.header.name[0] == 0) - break; - - tarmode = getoct(buffer.header.mode,8); - tartime = (time_t)getoct(buffer.header.mtime,12); - if (tarmode == -1 || tartime == (time_t)-1) - { - buffer.header.name[0] = 0; - action = TGZ_INVALID; - } - - if (getheader == 1) - { - strncpy(fname,buffer.header.name,SHORTNAMESIZE); - if (fname[SHORTNAMESIZE-1] != 0) - fname[SHORTNAMESIZE] = 0; - } - else - { - /* - * The file name is longer than SHORTNAMESIZE - */ - if (strncmp(fname,buffer.header.name,SHORTNAMESIZE-1) != 0) - error("bad long name"); - getheader = 1; - } - - /* - * Act according to the type flag - */ - switch (buffer.header.typeflag) - { - case DIRTYPE: - if (action == TGZ_LIST) - printf(" %s %s\n",strtime(&tartime),fname); - if (action == TGZ_EXTRACT) - { - makedir(fname); - push_attr(&attributes,fname,tarmode,tartime); - } - break; - case REGTYPE: - case AREGTYPE: - remaining = getoct(buffer.header.size,12); - if (remaining == -1) - { - action = TGZ_INVALID; - break; - } - if (action == TGZ_LIST) - printf(" %s %9d %s\n",strtime(&tartime),remaining,fname); - else if (action == TGZ_EXTRACT) - { - if (matchname(arg,argc,argv,fname)) - { - outfile = fopen(fname,"wb"); - if (outfile == NULL) { - /* try creating directory */ - char *p = strrchr(fname, '/'); - if (p != NULL) { - *p = '\0'; - makedir(fname); - *p = '/'; - outfile = fopen(fname,"wb"); - } - } - if (outfile != NULL) - printf("Extracting %s\n",fname); - else - fprintf(stderr, "%s: Couldn't create %s",prog,fname); - } - else - outfile = NULL; - } - getheader = 0; - break; - case GNUTYPE_LONGLINK: - case GNUTYPE_LONGNAME: - remaining = getoct(buffer.header.size,12); - if (remaining < 0 || remaining >= BLOCKSIZE) - { - action = TGZ_INVALID; - break; - } - len = gzread(in, fname, BLOCKSIZE); - if (len < 0) - error(gzerror(in, &err)); - if (fname[BLOCKSIZE-1] != 0 || (int)strlen(fname) > remaining) - { - action = TGZ_INVALID; - break; - } - getheader = 2; - break; - default: - if (action == TGZ_LIST) - printf(" %s <---> %s\n",strtime(&tartime),fname); - break; - } - } - else - { - unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining; - - if (outfile != NULL) - { - if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes) - { - fprintf(stderr, - "%s: Error writing %s -- skipping\n",prog,fname); - fclose(outfile); - outfile = NULL; - remove(fname); - } - } - remaining -= bytes; - } - - if (remaining == 0) - { - getheader = 1; - if (outfile != NULL) - { - fclose(outfile); - outfile = NULL; - if (action != TGZ_INVALID) - push_attr(&attributes,fname,tarmode,tartime); - } - } - - /* - * Abandon if errors are found - */ - if (action == TGZ_INVALID) - { - error("broken archive"); - break; - } - } - - /* - * Restore file modes and time stamps - */ - restore_attr(&attributes); - - if (gzclose(in) != Z_OK) - error("failed gzclose"); - - return 0; -} - - -/* ============================================================ */ - -void help(int exitval) -{ - printf("untgz version 0.2.1\n" - " using zlib version %s\n\n", - zlibVersion()); - printf("Usage: untgz file.tgz extract all files\n" - " untgz file.tgz fname ... extract selected files\n" - " untgz -l file.tgz list archive contents\n" - " untgz -h display this help\n"); - exit(exitval); -} - -void error(const char *msg) -{ - fprintf(stderr, "%s: %s\n", prog, msg); - exit(1); -} - - -/* ============================================================ */ - -#if defined(WIN32) && defined(__GNUC__) -int _CRT_glob = 0; /* disable argument globbing in MinGW */ -#endif - -int main(int argc,char **argv) -{ - int action = TGZ_EXTRACT; - int arg = 1; - char *TGZfile; - gzFile *f; - - prog = strrchr(argv[0],'\\'); - if (prog == NULL) - { - prog = strrchr(argv[0],'/'); - if (prog == NULL) - { - prog = strrchr(argv[0],':'); - if (prog == NULL) - prog = argv[0]; - else - prog++; - } - else - prog++; - } - else - prog++; - - if (argc == 1) - help(0); - - if (strcmp(argv[arg],"-l") == 0) - { - action = TGZ_LIST; - if (argc == ++arg) - help(0); - } - else if (strcmp(argv[arg],"-h") == 0) - { - help(0); - } - - if ((TGZfile = TGZfname(argv[arg])) == NULL) - TGZnotfound(argv[arg]); - - ++arg; - if ((action == TGZ_LIST) && (arg != argc)) - help(1); - -/* - * Process the TGZ file - */ - switch(action) - { - case TGZ_LIST: - case TGZ_EXTRACT: - f = gzopen(TGZfile,"rb"); - if (f == NULL) - { - fprintf(stderr,"%s: Couldn't gzopen %s\n",prog,TGZfile); - return 1; - } - exit(tar(f, action, arg, argc, argv)); - break; - - default: - error("Unknown option"); - exit(1); - } - - return 0; -} diff --git a/deps/zlib/contrib/vstudio/readme.txt b/deps/zlib/contrib/vstudio/readme.txt deleted file mode 100644 index 48cccc0d2a2636..00000000000000 --- a/deps/zlib/contrib/vstudio/readme.txt +++ /dev/null @@ -1,78 +0,0 @@ -Building instructions for the DLL versions of Zlib 1.2.11 -======================================================== - -This directory contains projects that build zlib and minizip using -Microsoft Visual C++ 9.0/10.0. - -You don't need to build these projects yourself. You can download the -binaries from: - http://www.winimage.com/zLibDll - -More information can be found at this site. - - - - - -Build instructions for Visual Studio 2008 (32 bits or 64 bits) --------------------------------------------------------------- -- Decompress current zlib, including all contrib/* files -- Compile assembly code (with Visual Studio Command Prompt) by running: - bld_ml64.bat (in contrib\masmx64) - bld_ml32.bat (in contrib\masmx86) -- Open contrib\vstudio\vc9\zlibvc.sln with Microsoft Visual C++ 2008 -- Or run: vcbuild /rebuild contrib\vstudio\vc9\zlibvc.sln "Release|Win32" - -Build instructions for Visual Studio 2010 (32 bits or 64 bits) --------------------------------------------------------------- -- Decompress current zlib, including all contrib/* files -- Open contrib\vstudio\vc10\zlibvc.sln with Microsoft Visual C++ 2010 - -Build instructions for Visual Studio 2012 (32 bits or 64 bits) --------------------------------------------------------------- -- Decompress current zlib, including all contrib/* files -- Open contrib\vstudio\vc11\zlibvc.sln with Microsoft Visual C++ 2012 - -Build instructions for Visual Studio 2013 (32 bits or 64 bits) --------------------------------------------------------------- -- Decompress current zlib, including all contrib/* files -- Open contrib\vstudio\vc12\zlibvc.sln with Microsoft Visual C++ 2013 - -Build instructions for Visual Studio 2015 (32 bits or 64 bits) --------------------------------------------------------------- -- Decompress current zlib, including all contrib/* files -- Open contrib\vstudio\vc14\zlibvc.sln with Microsoft Visual C++ 2015 - - -Important ---------- -- To use zlibwapi.dll in your application, you must define the - macro ZLIB_WINAPI when compiling your application's source files. - - -Additional notes ----------------- -- This DLL, named zlibwapi.dll, is compatible to the old zlib.dll built - by Gilles Vollant from the zlib 1.1.x sources, and distributed at - http://www.winimage.com/zLibDll - It uses the WINAPI calling convention for the exported functions, and - includes the minizip functionality. If your application needs that - particular build of zlib.dll, you can rename zlibwapi.dll to zlib.dll. - -- The new DLL was renamed because there exist several incompatible - versions of zlib.dll on the Internet. - -- There is also an official DLL build of zlib, named zlib1.dll. This one - is exporting the functions using the CDECL convention. See the file - win32\DLL_FAQ.txt found in this zlib distribution. - -- There used to be a ZLIB_DLL macro in zlib 1.1.x, but now this symbol - has a slightly different effect. To avoid compatibility problems, do - not define it here. - - -Gilles Vollant -info@winimage.com - -Visual Studio 2013 and 2015 Projects from Sean Hunt -seandhunt_7@yahoo.com diff --git a/deps/zlib/contrib/vstudio/vc10/zlib.rc b/deps/zlib/contrib/vstudio/vc10/zlib.rc deleted file mode 100644 index c4e4b016e9c895..00000000000000 --- a/deps/zlib/contrib/vstudio/vc10/zlib.rc +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#define IDR_VERSION1 1 -IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 11, 0 - PRODUCTVERSION 1, 2, 11, 0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK - FILEFLAGS 0 - FILEOS VOS_DOS_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0 // not used -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - //language ID = U.S. English, char set = Windows, Multilingual - - BEGIN - VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.11\0" - VALUE "InternalName", "zlib\0" - VALUE "OriginalFilename", "zlibwapi.dll\0" - VALUE "ProductName", "ZLib.DLL\0" - VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END -END diff --git a/deps/zlib/contrib/vstudio/vc10/zlibvc.def b/deps/zlib/contrib/vstudio/vc10/zlibvc.def deleted file mode 100644 index f876c3bcab8917..00000000000000 --- a/deps/zlib/contrib/vstudio/vc10/zlibvc.def +++ /dev/null @@ -1,153 +0,0 @@ -LIBRARY -; zlib data compression and ZIP file I/O library - -VERSION 1.2 - -EXPORTS - adler32 @1 - compress @2 - crc32 @3 - deflate @4 - deflateCopy @5 - deflateEnd @6 - deflateInit2_ @7 - deflateInit_ @8 - deflateParams @9 - deflateReset @10 - deflateSetDictionary @11 - gzclose @12 - gzdopen @13 - gzerror @14 - gzflush @15 - gzopen @16 - gzread @17 - gzwrite @18 - inflate @19 - inflateEnd @20 - inflateInit2_ @21 - inflateInit_ @22 - inflateReset @23 - inflateSetDictionary @24 - inflateSync @25 - uncompress @26 - zlibVersion @27 - gzprintf @28 - gzputc @29 - gzgetc @30 - gzseek @31 - gzrewind @32 - gztell @33 - gzeof @34 - gzsetparams @35 - zError @36 - inflateSyncPoint @37 - get_crc_table @38 - compress2 @39 - gzputs @40 - gzgets @41 - inflateCopy @42 - inflateBackInit_ @43 - inflateBack @44 - inflateBackEnd @45 - compressBound @46 - deflateBound @47 - gzclearerr @48 - gzungetc @49 - zlibCompileFlags @50 - deflatePrime @51 - deflatePending @52 - - unzOpen @61 - unzClose @62 - unzGetGlobalInfo @63 - unzGetCurrentFileInfo @64 - unzGoToFirstFile @65 - unzGoToNextFile @66 - unzOpenCurrentFile @67 - unzReadCurrentFile @68 - unzOpenCurrentFile3 @69 - unztell @70 - unzeof @71 - unzCloseCurrentFile @72 - unzGetGlobalComment @73 - unzStringFileNameCompare @74 - unzLocateFile @75 - unzGetLocalExtrafield @76 - unzOpen2 @77 - unzOpenCurrentFile2 @78 - unzOpenCurrentFilePassword @79 - - zipOpen @80 - zipOpenNewFileInZip @81 - zipWriteInFileInZip @82 - zipCloseFileInZip @83 - zipClose @84 - zipOpenNewFileInZip2 @86 - zipCloseFileInZipRaw @87 - zipOpen2 @88 - zipOpenNewFileInZip3 @89 - - unzGetFilePos @100 - unzGoToFilePos @101 - - fill_win32_filefunc @110 - -; zlibwapi v1.2.4 added: - fill_win32_filefunc64 @111 - fill_win32_filefunc64A @112 - fill_win32_filefunc64W @113 - - unzOpen64 @120 - unzOpen2_64 @121 - unzGetGlobalInfo64 @122 - unzGetCurrentFileInfo64 @124 - unzGetCurrentFileZStreamPos64 @125 - unztell64 @126 - unzGetFilePos64 @127 - unzGoToFilePos64 @128 - - zipOpen64 @130 - zipOpen2_64 @131 - zipOpenNewFileInZip64 @132 - zipOpenNewFileInZip2_64 @133 - zipOpenNewFileInZip3_64 @134 - zipOpenNewFileInZip4_64 @135 - zipCloseFileInZipRaw64 @136 - -; zlib1 v1.2.4 added: - adler32_combine @140 - crc32_combine @142 - deflateSetHeader @144 - deflateTune @145 - gzbuffer @146 - gzclose_r @147 - gzclose_w @148 - gzdirect @149 - gzoffset @150 - inflateGetHeader @156 - inflateMark @157 - inflatePrime @158 - inflateReset2 @159 - inflateUndermine @160 - -; zlib1 v1.2.6 added: - gzgetc_ @161 - inflateResetKeep @163 - deflateResetKeep @164 - -; zlib1 v1.2.7 added: - gzopen_w @165 - -; zlib1 v1.2.8 added: - inflateGetDictionary @166 - gzvprintf @167 - -; zlib1 v1.2.9 added: - inflateCodesUsed @168 - inflateValidate @169 - uncompress2 @170 - gzfread @171 - gzfwrite @172 - deflateGetDictionary @173 - adler32_z @174 - crc32_z @175 diff --git a/deps/zlib/contrib/vstudio/vc11/zlib.rc b/deps/zlib/contrib/vstudio/vc11/zlib.rc deleted file mode 100644 index c4e4b016e9c895..00000000000000 --- a/deps/zlib/contrib/vstudio/vc11/zlib.rc +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#define IDR_VERSION1 1 -IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 11, 0 - PRODUCTVERSION 1, 2, 11, 0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK - FILEFLAGS 0 - FILEOS VOS_DOS_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0 // not used -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - //language ID = U.S. English, char set = Windows, Multilingual - - BEGIN - VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.11\0" - VALUE "InternalName", "zlib\0" - VALUE "OriginalFilename", "zlibwapi.dll\0" - VALUE "ProductName", "ZLib.DLL\0" - VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END -END diff --git a/deps/zlib/contrib/vstudio/vc11/zlibvc.def b/deps/zlib/contrib/vstudio/vc11/zlibvc.def deleted file mode 100644 index f876c3bcab8917..00000000000000 --- a/deps/zlib/contrib/vstudio/vc11/zlibvc.def +++ /dev/null @@ -1,153 +0,0 @@ -LIBRARY -; zlib data compression and ZIP file I/O library - -VERSION 1.2 - -EXPORTS - adler32 @1 - compress @2 - crc32 @3 - deflate @4 - deflateCopy @5 - deflateEnd @6 - deflateInit2_ @7 - deflateInit_ @8 - deflateParams @9 - deflateReset @10 - deflateSetDictionary @11 - gzclose @12 - gzdopen @13 - gzerror @14 - gzflush @15 - gzopen @16 - gzread @17 - gzwrite @18 - inflate @19 - inflateEnd @20 - inflateInit2_ @21 - inflateInit_ @22 - inflateReset @23 - inflateSetDictionary @24 - inflateSync @25 - uncompress @26 - zlibVersion @27 - gzprintf @28 - gzputc @29 - gzgetc @30 - gzseek @31 - gzrewind @32 - gztell @33 - gzeof @34 - gzsetparams @35 - zError @36 - inflateSyncPoint @37 - get_crc_table @38 - compress2 @39 - gzputs @40 - gzgets @41 - inflateCopy @42 - inflateBackInit_ @43 - inflateBack @44 - inflateBackEnd @45 - compressBound @46 - deflateBound @47 - gzclearerr @48 - gzungetc @49 - zlibCompileFlags @50 - deflatePrime @51 - deflatePending @52 - - unzOpen @61 - unzClose @62 - unzGetGlobalInfo @63 - unzGetCurrentFileInfo @64 - unzGoToFirstFile @65 - unzGoToNextFile @66 - unzOpenCurrentFile @67 - unzReadCurrentFile @68 - unzOpenCurrentFile3 @69 - unztell @70 - unzeof @71 - unzCloseCurrentFile @72 - unzGetGlobalComment @73 - unzStringFileNameCompare @74 - unzLocateFile @75 - unzGetLocalExtrafield @76 - unzOpen2 @77 - unzOpenCurrentFile2 @78 - unzOpenCurrentFilePassword @79 - - zipOpen @80 - zipOpenNewFileInZip @81 - zipWriteInFileInZip @82 - zipCloseFileInZip @83 - zipClose @84 - zipOpenNewFileInZip2 @86 - zipCloseFileInZipRaw @87 - zipOpen2 @88 - zipOpenNewFileInZip3 @89 - - unzGetFilePos @100 - unzGoToFilePos @101 - - fill_win32_filefunc @110 - -; zlibwapi v1.2.4 added: - fill_win32_filefunc64 @111 - fill_win32_filefunc64A @112 - fill_win32_filefunc64W @113 - - unzOpen64 @120 - unzOpen2_64 @121 - unzGetGlobalInfo64 @122 - unzGetCurrentFileInfo64 @124 - unzGetCurrentFileZStreamPos64 @125 - unztell64 @126 - unzGetFilePos64 @127 - unzGoToFilePos64 @128 - - zipOpen64 @130 - zipOpen2_64 @131 - zipOpenNewFileInZip64 @132 - zipOpenNewFileInZip2_64 @133 - zipOpenNewFileInZip3_64 @134 - zipOpenNewFileInZip4_64 @135 - zipCloseFileInZipRaw64 @136 - -; zlib1 v1.2.4 added: - adler32_combine @140 - crc32_combine @142 - deflateSetHeader @144 - deflateTune @145 - gzbuffer @146 - gzclose_r @147 - gzclose_w @148 - gzdirect @149 - gzoffset @150 - inflateGetHeader @156 - inflateMark @157 - inflatePrime @158 - inflateReset2 @159 - inflateUndermine @160 - -; zlib1 v1.2.6 added: - gzgetc_ @161 - inflateResetKeep @163 - deflateResetKeep @164 - -; zlib1 v1.2.7 added: - gzopen_w @165 - -; zlib1 v1.2.8 added: - inflateGetDictionary @166 - gzvprintf @167 - -; zlib1 v1.2.9 added: - inflateCodesUsed @168 - inflateValidate @169 - uncompress2 @170 - gzfread @171 - gzfwrite @172 - deflateGetDictionary @173 - adler32_z @174 - crc32_z @175 diff --git a/deps/zlib/contrib/vstudio/vc12/zlib.rc b/deps/zlib/contrib/vstudio/vc12/zlib.rc deleted file mode 100644 index c4e4b016e9c895..00000000000000 --- a/deps/zlib/contrib/vstudio/vc12/zlib.rc +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#define IDR_VERSION1 1 -IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 11, 0 - PRODUCTVERSION 1, 2, 11, 0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK - FILEFLAGS 0 - FILEOS VOS_DOS_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0 // not used -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - //language ID = U.S. English, char set = Windows, Multilingual - - BEGIN - VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.11\0" - VALUE "InternalName", "zlib\0" - VALUE "OriginalFilename", "zlibwapi.dll\0" - VALUE "ProductName", "ZLib.DLL\0" - VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END -END diff --git a/deps/zlib/contrib/vstudio/vc12/zlibvc.def b/deps/zlib/contrib/vstudio/vc12/zlibvc.def deleted file mode 100644 index f876c3bcab8917..00000000000000 --- a/deps/zlib/contrib/vstudio/vc12/zlibvc.def +++ /dev/null @@ -1,153 +0,0 @@ -LIBRARY -; zlib data compression and ZIP file I/O library - -VERSION 1.2 - -EXPORTS - adler32 @1 - compress @2 - crc32 @3 - deflate @4 - deflateCopy @5 - deflateEnd @6 - deflateInit2_ @7 - deflateInit_ @8 - deflateParams @9 - deflateReset @10 - deflateSetDictionary @11 - gzclose @12 - gzdopen @13 - gzerror @14 - gzflush @15 - gzopen @16 - gzread @17 - gzwrite @18 - inflate @19 - inflateEnd @20 - inflateInit2_ @21 - inflateInit_ @22 - inflateReset @23 - inflateSetDictionary @24 - inflateSync @25 - uncompress @26 - zlibVersion @27 - gzprintf @28 - gzputc @29 - gzgetc @30 - gzseek @31 - gzrewind @32 - gztell @33 - gzeof @34 - gzsetparams @35 - zError @36 - inflateSyncPoint @37 - get_crc_table @38 - compress2 @39 - gzputs @40 - gzgets @41 - inflateCopy @42 - inflateBackInit_ @43 - inflateBack @44 - inflateBackEnd @45 - compressBound @46 - deflateBound @47 - gzclearerr @48 - gzungetc @49 - zlibCompileFlags @50 - deflatePrime @51 - deflatePending @52 - - unzOpen @61 - unzClose @62 - unzGetGlobalInfo @63 - unzGetCurrentFileInfo @64 - unzGoToFirstFile @65 - unzGoToNextFile @66 - unzOpenCurrentFile @67 - unzReadCurrentFile @68 - unzOpenCurrentFile3 @69 - unztell @70 - unzeof @71 - unzCloseCurrentFile @72 - unzGetGlobalComment @73 - unzStringFileNameCompare @74 - unzLocateFile @75 - unzGetLocalExtrafield @76 - unzOpen2 @77 - unzOpenCurrentFile2 @78 - unzOpenCurrentFilePassword @79 - - zipOpen @80 - zipOpenNewFileInZip @81 - zipWriteInFileInZip @82 - zipCloseFileInZip @83 - zipClose @84 - zipOpenNewFileInZip2 @86 - zipCloseFileInZipRaw @87 - zipOpen2 @88 - zipOpenNewFileInZip3 @89 - - unzGetFilePos @100 - unzGoToFilePos @101 - - fill_win32_filefunc @110 - -; zlibwapi v1.2.4 added: - fill_win32_filefunc64 @111 - fill_win32_filefunc64A @112 - fill_win32_filefunc64W @113 - - unzOpen64 @120 - unzOpen2_64 @121 - unzGetGlobalInfo64 @122 - unzGetCurrentFileInfo64 @124 - unzGetCurrentFileZStreamPos64 @125 - unztell64 @126 - unzGetFilePos64 @127 - unzGoToFilePos64 @128 - - zipOpen64 @130 - zipOpen2_64 @131 - zipOpenNewFileInZip64 @132 - zipOpenNewFileInZip2_64 @133 - zipOpenNewFileInZip3_64 @134 - zipOpenNewFileInZip4_64 @135 - zipCloseFileInZipRaw64 @136 - -; zlib1 v1.2.4 added: - adler32_combine @140 - crc32_combine @142 - deflateSetHeader @144 - deflateTune @145 - gzbuffer @146 - gzclose_r @147 - gzclose_w @148 - gzdirect @149 - gzoffset @150 - inflateGetHeader @156 - inflateMark @157 - inflatePrime @158 - inflateReset2 @159 - inflateUndermine @160 - -; zlib1 v1.2.6 added: - gzgetc_ @161 - inflateResetKeep @163 - deflateResetKeep @164 - -; zlib1 v1.2.7 added: - gzopen_w @165 - -; zlib1 v1.2.8 added: - inflateGetDictionary @166 - gzvprintf @167 - -; zlib1 v1.2.9 added: - inflateCodesUsed @168 - inflateValidate @169 - uncompress2 @170 - gzfread @171 - gzfwrite @172 - deflateGetDictionary @173 - adler32_z @174 - crc32_z @175 diff --git a/deps/zlib/contrib/vstudio/vc14/zlib.rc b/deps/zlib/contrib/vstudio/vc14/zlib.rc deleted file mode 100644 index c4e4b016e9c895..00000000000000 --- a/deps/zlib/contrib/vstudio/vc14/zlib.rc +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#define IDR_VERSION1 1 -IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 11, 0 - PRODUCTVERSION 1, 2, 11, 0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK - FILEFLAGS 0 - FILEOS VOS_DOS_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0 // not used -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - //language ID = U.S. English, char set = Windows, Multilingual - - BEGIN - VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.11\0" - VALUE "InternalName", "zlib\0" - VALUE "OriginalFilename", "zlibwapi.dll\0" - VALUE "ProductName", "ZLib.DLL\0" - VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END -END diff --git a/deps/zlib/contrib/vstudio/vc14/zlibvc.def b/deps/zlib/contrib/vstudio/vc14/zlibvc.def deleted file mode 100644 index f876c3bcab8917..00000000000000 --- a/deps/zlib/contrib/vstudio/vc14/zlibvc.def +++ /dev/null @@ -1,153 +0,0 @@ -LIBRARY -; zlib data compression and ZIP file I/O library - -VERSION 1.2 - -EXPORTS - adler32 @1 - compress @2 - crc32 @3 - deflate @4 - deflateCopy @5 - deflateEnd @6 - deflateInit2_ @7 - deflateInit_ @8 - deflateParams @9 - deflateReset @10 - deflateSetDictionary @11 - gzclose @12 - gzdopen @13 - gzerror @14 - gzflush @15 - gzopen @16 - gzread @17 - gzwrite @18 - inflate @19 - inflateEnd @20 - inflateInit2_ @21 - inflateInit_ @22 - inflateReset @23 - inflateSetDictionary @24 - inflateSync @25 - uncompress @26 - zlibVersion @27 - gzprintf @28 - gzputc @29 - gzgetc @30 - gzseek @31 - gzrewind @32 - gztell @33 - gzeof @34 - gzsetparams @35 - zError @36 - inflateSyncPoint @37 - get_crc_table @38 - compress2 @39 - gzputs @40 - gzgets @41 - inflateCopy @42 - inflateBackInit_ @43 - inflateBack @44 - inflateBackEnd @45 - compressBound @46 - deflateBound @47 - gzclearerr @48 - gzungetc @49 - zlibCompileFlags @50 - deflatePrime @51 - deflatePending @52 - - unzOpen @61 - unzClose @62 - unzGetGlobalInfo @63 - unzGetCurrentFileInfo @64 - unzGoToFirstFile @65 - unzGoToNextFile @66 - unzOpenCurrentFile @67 - unzReadCurrentFile @68 - unzOpenCurrentFile3 @69 - unztell @70 - unzeof @71 - unzCloseCurrentFile @72 - unzGetGlobalComment @73 - unzStringFileNameCompare @74 - unzLocateFile @75 - unzGetLocalExtrafield @76 - unzOpen2 @77 - unzOpenCurrentFile2 @78 - unzOpenCurrentFilePassword @79 - - zipOpen @80 - zipOpenNewFileInZip @81 - zipWriteInFileInZip @82 - zipCloseFileInZip @83 - zipClose @84 - zipOpenNewFileInZip2 @86 - zipCloseFileInZipRaw @87 - zipOpen2 @88 - zipOpenNewFileInZip3 @89 - - unzGetFilePos @100 - unzGoToFilePos @101 - - fill_win32_filefunc @110 - -; zlibwapi v1.2.4 added: - fill_win32_filefunc64 @111 - fill_win32_filefunc64A @112 - fill_win32_filefunc64W @113 - - unzOpen64 @120 - unzOpen2_64 @121 - unzGetGlobalInfo64 @122 - unzGetCurrentFileInfo64 @124 - unzGetCurrentFileZStreamPos64 @125 - unztell64 @126 - unzGetFilePos64 @127 - unzGoToFilePos64 @128 - - zipOpen64 @130 - zipOpen2_64 @131 - zipOpenNewFileInZip64 @132 - zipOpenNewFileInZip2_64 @133 - zipOpenNewFileInZip3_64 @134 - zipOpenNewFileInZip4_64 @135 - zipCloseFileInZipRaw64 @136 - -; zlib1 v1.2.4 added: - adler32_combine @140 - crc32_combine @142 - deflateSetHeader @144 - deflateTune @145 - gzbuffer @146 - gzclose_r @147 - gzclose_w @148 - gzdirect @149 - gzoffset @150 - inflateGetHeader @156 - inflateMark @157 - inflatePrime @158 - inflateReset2 @159 - inflateUndermine @160 - -; zlib1 v1.2.6 added: - gzgetc_ @161 - inflateResetKeep @163 - deflateResetKeep @164 - -; zlib1 v1.2.7 added: - gzopen_w @165 - -; zlib1 v1.2.8 added: - inflateGetDictionary @166 - gzvprintf @167 - -; zlib1 v1.2.9 added: - inflateCodesUsed @168 - inflateValidate @169 - uncompress2 @170 - gzfread @171 - gzfwrite @172 - deflateGetDictionary @173 - adler32_z @174 - crc32_z @175 diff --git a/deps/zlib/contrib/vstudio/vc9/zlib.rc b/deps/zlib/contrib/vstudio/vc9/zlib.rc deleted file mode 100644 index c4e4b016e9c895..00000000000000 --- a/deps/zlib/contrib/vstudio/vc9/zlib.rc +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#define IDR_VERSION1 1 -IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 11, 0 - PRODUCTVERSION 1, 2, 11, 0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK - FILEFLAGS 0 - FILEOS VOS_DOS_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0 // not used -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - //language ID = U.S. English, char set = Windows, Multilingual - - BEGIN - VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.11\0" - VALUE "InternalName", "zlib\0" - VALUE "OriginalFilename", "zlibwapi.dll\0" - VALUE "ProductName", "ZLib.DLL\0" - VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END -END diff --git a/deps/zlib/contrib/vstudio/vc9/zlibvc.def b/deps/zlib/contrib/vstudio/vc9/zlibvc.def deleted file mode 100644 index f876c3bcab8917..00000000000000 --- a/deps/zlib/contrib/vstudio/vc9/zlibvc.def +++ /dev/null @@ -1,153 +0,0 @@ -LIBRARY -; zlib data compression and ZIP file I/O library - -VERSION 1.2 - -EXPORTS - adler32 @1 - compress @2 - crc32 @3 - deflate @4 - deflateCopy @5 - deflateEnd @6 - deflateInit2_ @7 - deflateInit_ @8 - deflateParams @9 - deflateReset @10 - deflateSetDictionary @11 - gzclose @12 - gzdopen @13 - gzerror @14 - gzflush @15 - gzopen @16 - gzread @17 - gzwrite @18 - inflate @19 - inflateEnd @20 - inflateInit2_ @21 - inflateInit_ @22 - inflateReset @23 - inflateSetDictionary @24 - inflateSync @25 - uncompress @26 - zlibVersion @27 - gzprintf @28 - gzputc @29 - gzgetc @30 - gzseek @31 - gzrewind @32 - gztell @33 - gzeof @34 - gzsetparams @35 - zError @36 - inflateSyncPoint @37 - get_crc_table @38 - compress2 @39 - gzputs @40 - gzgets @41 - inflateCopy @42 - inflateBackInit_ @43 - inflateBack @44 - inflateBackEnd @45 - compressBound @46 - deflateBound @47 - gzclearerr @48 - gzungetc @49 - zlibCompileFlags @50 - deflatePrime @51 - deflatePending @52 - - unzOpen @61 - unzClose @62 - unzGetGlobalInfo @63 - unzGetCurrentFileInfo @64 - unzGoToFirstFile @65 - unzGoToNextFile @66 - unzOpenCurrentFile @67 - unzReadCurrentFile @68 - unzOpenCurrentFile3 @69 - unztell @70 - unzeof @71 - unzCloseCurrentFile @72 - unzGetGlobalComment @73 - unzStringFileNameCompare @74 - unzLocateFile @75 - unzGetLocalExtrafield @76 - unzOpen2 @77 - unzOpenCurrentFile2 @78 - unzOpenCurrentFilePassword @79 - - zipOpen @80 - zipOpenNewFileInZip @81 - zipWriteInFileInZip @82 - zipCloseFileInZip @83 - zipClose @84 - zipOpenNewFileInZip2 @86 - zipCloseFileInZipRaw @87 - zipOpen2 @88 - zipOpenNewFileInZip3 @89 - - unzGetFilePos @100 - unzGoToFilePos @101 - - fill_win32_filefunc @110 - -; zlibwapi v1.2.4 added: - fill_win32_filefunc64 @111 - fill_win32_filefunc64A @112 - fill_win32_filefunc64W @113 - - unzOpen64 @120 - unzOpen2_64 @121 - unzGetGlobalInfo64 @122 - unzGetCurrentFileInfo64 @124 - unzGetCurrentFileZStreamPos64 @125 - unztell64 @126 - unzGetFilePos64 @127 - unzGoToFilePos64 @128 - - zipOpen64 @130 - zipOpen2_64 @131 - zipOpenNewFileInZip64 @132 - zipOpenNewFileInZip2_64 @133 - zipOpenNewFileInZip3_64 @134 - zipOpenNewFileInZip4_64 @135 - zipCloseFileInZipRaw64 @136 - -; zlib1 v1.2.4 added: - adler32_combine @140 - crc32_combine @142 - deflateSetHeader @144 - deflateTune @145 - gzbuffer @146 - gzclose_r @147 - gzclose_w @148 - gzdirect @149 - gzoffset @150 - inflateGetHeader @156 - inflateMark @157 - inflatePrime @158 - inflateReset2 @159 - inflateUndermine @160 - -; zlib1 v1.2.6 added: - gzgetc_ @161 - inflateResetKeep @163 - deflateResetKeep @164 - -; zlib1 v1.2.7 added: - gzopen_w @165 - -; zlib1 v1.2.8 added: - inflateGetDictionary @166 - gzvprintf @167 - -; zlib1 v1.2.9 added: - inflateCodesUsed @168 - inflateValidate @169 - uncompress2 @170 - gzfread @171 - gzfwrite @172 - deflateGetDictionary @173 - adler32_z @174 - crc32_z @175 diff --git a/deps/zlib/crc32.c b/deps/zlib/crc32.c index 9580440c0e6b67..e95b9087351c1a 100644 --- a/deps/zlib/crc32.c +++ b/deps/zlib/crc32.c @@ -28,8 +28,17 @@ # endif /* !DYNAMIC_CRC_TABLE */ #endif /* MAKECRCH */ +#include "deflate.h" +#include "x86.h" #include "zutil.h" /* for STDC and FAR definitions */ +#if defined(CRC32_SIMD_SSE42_PCLMUL) +#include "crc32_simd.h" +#elif defined(CRC32_ARMV8_CRC32) +#include "arm_features.h" +#include "crc32_simd.h" +#endif + /* Definitions for doing the crc four data bytes at a time. */ #if !defined(NOBYFOUR) && defined(Z_U4) # define BYFOUR @@ -204,7 +213,39 @@ unsigned long ZEXPORT crc32_z(crc, buf, len) const unsigned char FAR *buf; z_size_t len; { - if (buf == Z_NULL) return 0UL; + /* + * zlib convention is to call crc32(0, NULL, 0); before making + * calls to crc32(). So this is a good, early (and infrequent) + * place to cache CPU features if needed for those later, more + * interesting crc32() calls. + */ +#if defined(CRC32_SIMD_SSE42_PCLMUL) + /* + * Use x86 sse4.2+pclmul SIMD to compute the crc32. Since this + * routine can be freely used, check CPU features here. + */ + if (buf == Z_NULL) { + if (!len) /* Assume user is calling crc32(0, NULL, 0); */ + x86_check_features(); + return 0UL; + } + + if (x86_cpu_enable_simd && len >= Z_CRC32_SSE42_MINIMUM_LENGTH) { + /* crc32 16-byte chunks */ + z_size_t chunk_size = len & ~Z_CRC32_SSE42_CHUNKSIZE_MASK; + crc = ~crc32_sse42_simd_(buf, chunk_size, ~(uint32_t)crc); + /* check remaining data */ + len -= chunk_size; + if (!len) + return crc; + /* Fall into the default crc32 for the remaining data. */ + buf += chunk_size; + } +#else + if (buf == Z_NULL) { + return 0UL; + } +#endif /* CRC32_SIMD_SSE42_PCLMUL */ #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) @@ -239,6 +280,22 @@ unsigned long ZEXPORT crc32(crc, buf, len) const unsigned char FAR *buf; uInt len; { +#if defined(CRC32_ARMV8_CRC32) + /* We got to verify ARM CPU features, so exploit the common usage pattern + * of calling this function with Z_NULL for an initial valid crc value. + * This allows to cache the result of the feature check and avoid extraneous + * function calls. + * TODO: try to move this to crc32_z if we don't loose performance on ARM. + */ + if (buf == Z_NULL) { + if (!len) /* Assume user is calling crc32(0, NULL, 0); */ + arm_check_features(); + return 0UL; + } + + if (arm_cpu_enable_crc32) + return armv8_crc32_little(crc, buf, len); +#endif return crc32_z(crc, buf, len); } @@ -440,3 +497,28 @@ uLong ZEXPORT crc32_combine64(crc1, crc2, len2) { return crc32_combine_(crc1, crc2, len2); } + +ZLIB_INTERNAL void crc_reset(deflate_state *const s) +{ + if (x86_cpu_enable_simd) { + crc_fold_init(s); + return; + } + s->strm->adler = crc32(0L, Z_NULL, 0); +} + +ZLIB_INTERNAL void crc_finalize(deflate_state *const s) +{ + if (x86_cpu_enable_simd) + s->strm->adler = crc_fold_512to32(s); +} + +ZLIB_INTERNAL void copy_with_crc(z_streamp strm, Bytef *dst, long size) +{ + if (x86_cpu_enable_simd) { + crc_fold_copy(strm->state, dst, strm->next_in, size); + return; + } + zmemcpy(dst, strm->next_in, size); + strm->adler = crc32(strm->adler, dst, size); +} diff --git a/deps/zlib/crc32_simd.c b/deps/zlib/crc32_simd.c new file mode 100644 index 00000000000000..27481847e97b90 --- /dev/null +++ b/deps/zlib/crc32_simd.c @@ -0,0 +1,247 @@ +/* crc32_simd.c + * + * Copyright 2017 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ + +#include "crc32_simd.h" + +#if defined(CRC32_SIMD_SSE42_PCLMUL) +#ifndef __GNUC__ +#define __attribute__() +#endif + +/* + * crc32_sse42_simd_(): compute the crc32 of the buffer, where the buffer + * length must be at least 64, and a multiple of 16. Based on: + * + * "Fast CRC Computation for Generic Polynomials Using PCLMULQDQ Instruction" + * V. Gopal, E. Ozturk, et al., 2009, http://intel.ly/2ySEwL0 + */ + +#include +#include +#include + +__attribute__((target("sse4.2,pclmul"))) +uint32_t ZLIB_INTERNAL crc32_sse42_simd_( /* SSE4.2+PCLMUL */ + const unsigned char *buf, + z_size_t len, + uint32_t crc) +{ + /* + * Definitions of the bit-reflected domain constants k1,k2,k3, etc and + * the CRC32+Barrett polynomials given at the end of the paper. + */ + static const uint64_t zalign(16) k1k2[] = { 0x0154442bd4, 0x01c6e41596 }; + static const uint64_t zalign(16) k3k4[] = { 0x01751997d0, 0x00ccaa009e }; + static const uint64_t zalign(16) k5k0[] = { 0x0163cd6124, 0x0000000000 }; + static const uint64_t zalign(16) poly[] = { 0x01db710641, 0x01f7011641 }; + + __m128i x0, x1, x2, x3, x4, x5, x6, x7, x8, y5, y6, y7, y8; + + /* + * There's at least one block of 64. + */ + x1 = _mm_loadu_si128((__m128i *)(buf + 0x00)); + x2 = _mm_loadu_si128((__m128i *)(buf + 0x10)); + x3 = _mm_loadu_si128((__m128i *)(buf + 0x20)); + x4 = _mm_loadu_si128((__m128i *)(buf + 0x30)); + + x1 = _mm_xor_si128(x1, _mm_cvtsi32_si128(crc)); + + x0 = _mm_load_si128((__m128i *)k1k2); + + buf += 64; + len -= 64; + + /* + * Parallel fold blocks of 64, if any. + */ + while (len >= 64) + { + x5 = _mm_clmulepi64_si128(x1, x0, 0x00); + x6 = _mm_clmulepi64_si128(x2, x0, 0x00); + x7 = _mm_clmulepi64_si128(x3, x0, 0x00); + x8 = _mm_clmulepi64_si128(x4, x0, 0x00); + + x1 = _mm_clmulepi64_si128(x1, x0, 0x11); + x2 = _mm_clmulepi64_si128(x2, x0, 0x11); + x3 = _mm_clmulepi64_si128(x3, x0, 0x11); + x4 = _mm_clmulepi64_si128(x4, x0, 0x11); + + y5 = _mm_loadu_si128((__m128i *)(buf + 0x00)); + y6 = _mm_loadu_si128((__m128i *)(buf + 0x10)); + y7 = _mm_loadu_si128((__m128i *)(buf + 0x20)); + y8 = _mm_loadu_si128((__m128i *)(buf + 0x30)); + + x1 = _mm_xor_si128(x1, x5); + x2 = _mm_xor_si128(x2, x6); + x3 = _mm_xor_si128(x3, x7); + x4 = _mm_xor_si128(x4, x8); + + x1 = _mm_xor_si128(x1, y5); + x2 = _mm_xor_si128(x2, y6); + x3 = _mm_xor_si128(x3, y7); + x4 = _mm_xor_si128(x4, y8); + + buf += 64; + len -= 64; + } + + /* + * Fold into 128-bits. + */ + x0 = _mm_load_si128((__m128i *)k3k4); + + x5 = _mm_clmulepi64_si128(x1, x0, 0x00); + x1 = _mm_clmulepi64_si128(x1, x0, 0x11); + x1 = _mm_xor_si128(x1, x2); + x1 = _mm_xor_si128(x1, x5); + + x5 = _mm_clmulepi64_si128(x1, x0, 0x00); + x1 = _mm_clmulepi64_si128(x1, x0, 0x11); + x1 = _mm_xor_si128(x1, x3); + x1 = _mm_xor_si128(x1, x5); + + x5 = _mm_clmulepi64_si128(x1, x0, 0x00); + x1 = _mm_clmulepi64_si128(x1, x0, 0x11); + x1 = _mm_xor_si128(x1, x4); + x1 = _mm_xor_si128(x1, x5); + + /* + * Single fold blocks of 16, if any. + */ + while (len >= 16) + { + x2 = _mm_loadu_si128((__m128i *)buf); + + x5 = _mm_clmulepi64_si128(x1, x0, 0x00); + x1 = _mm_clmulepi64_si128(x1, x0, 0x11); + x1 = _mm_xor_si128(x1, x2); + x1 = _mm_xor_si128(x1, x5); + + buf += 16; + len -= 16; + } + + /* + * Fold 128-bits to 64-bits. + */ + x2 = _mm_clmulepi64_si128(x1, x0, 0x10); + x3 = _mm_setr_epi32(~0, 0, ~0, 0); + x1 = _mm_srli_si128(x1, 8); + x1 = _mm_xor_si128(x1, x2); + + x0 = _mm_loadl_epi64((__m128i*)k5k0); + + x2 = _mm_srli_si128(x1, 4); + x1 = _mm_and_si128(x1, x3); + x1 = _mm_clmulepi64_si128(x1, x0, 0x00); + x1 = _mm_xor_si128(x1, x2); + + /* + * Barret reduce to 32-bits. + */ + x0 = _mm_load_si128((__m128i*)poly); + + x2 = _mm_and_si128(x1, x3); + x2 = _mm_clmulepi64_si128(x2, x0, 0x10); + x2 = _mm_and_si128(x2, x3); + x2 = _mm_clmulepi64_si128(x2, x0, 0x00); + x1 = _mm_xor_si128(x1, x2); + + /* + * Return the crc32. + */ + return _mm_extract_epi32(x1, 1); +} + +#elif defined(CRC32_ARMV8_CRC32) + +/* CRC32 checksums using ARMv8-a crypto instructions. + * + * TODO: implement a version using the PMULL instruction. + */ + +#if defined(__clang__) +/* CRC32 intrinsics are #ifdef'ed out of arm_acle.h unless we build with an + * armv8 target, which is incompatible with ThinLTO optimizations on Android. + * (Namely, mixing and matching different module-level targets makes ThinLTO + * warn, and Android defaults to armv7-a. This restriction does not apply to + * function-level `target`s, however.) + * + * Since we only need four crc intrinsics, and since clang's implementation of + * those are just wrappers around compiler builtins, it's simplest to #define + * those builtins directly. If this #define list grows too much (or we depend on + * an intrinsic that isn't a trivial wrapper), we may have to find a better way + * to go about this. + * + * NOTE: clang currently complains that "'+soft-float-abi' is not a recognized + * feature for this target (ignoring feature)." This appears to be a harmless + * bug in clang. + */ +#define __crc32b __builtin_arm_crc32b +#define __crc32d __builtin_arm_crc32d +#define __crc32w __builtin_arm_crc32w +#define __crc32cw __builtin_arm_crc32cw + +#if defined(__aarch64__) +#define TARGET_ARMV8_WITH_CRC __attribute__((target("crc"))) +#else // !defined(__aarch64__) +#define TARGET_ARMV8_WITH_CRC __attribute__((target("armv8-a,crc"))) +#endif // defined(__aarch64__) + +#elif defined(__GNUC__) +/* For GCC, we are setting CRC extensions at module level, so ThinLTO is not + * allowed. We can just include arm_acle.h. + */ +#include +#define TARGET_ARMV8_WITH_CRC +#else // !defined(__GNUC__) && !defined(_aarch64__) +#error ARM CRC32 SIMD extensions only supported for Clang and GCC +#endif + +TARGET_ARMV8_WITH_CRC +uint32_t ZLIB_INTERNAL armv8_crc32_little(unsigned long crc, + const unsigned char *buf, + z_size_t len) +{ + uint32_t c = (uint32_t) ~crc; + + while (len && ((uintptr_t)buf & 7)) { + c = __crc32b(c, *buf++); + --len; + } + + const uint64_t *buf8 = (const uint64_t *)buf; + + while (len >= 64) { + c = __crc32d(c, *buf8++); + c = __crc32d(c, *buf8++); + c = __crc32d(c, *buf8++); + c = __crc32d(c, *buf8++); + + c = __crc32d(c, *buf8++); + c = __crc32d(c, *buf8++); + c = __crc32d(c, *buf8++); + c = __crc32d(c, *buf8++); + len -= 64; + } + + while (len >= 8) { + c = __crc32d(c, *buf8++); + len -= 8; + } + + buf = (const unsigned char *)buf8; + + while (len--) { + c = __crc32b(c, *buf++); + } + + return ~c; +} + +#endif diff --git a/deps/zlib/crc32_simd.h b/deps/zlib/crc32_simd.h new file mode 100644 index 00000000000000..68bc235cbe1682 --- /dev/null +++ b/deps/zlib/crc32_simd.h @@ -0,0 +1,36 @@ +/* crc32_simd.h + * + * Copyright 2017 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ + +#include + +#include "zconf.h" +#include "zutil.h" +#include "deflate.h" + +/* + * crc32_sse42_simd_(): compute the crc32 of the buffer, where the buffer + * length must be at least 64, and a multiple of 16. + */ +uint32_t ZLIB_INTERNAL crc32_sse42_simd_( + const unsigned char *buf, + z_size_t len, + uint32_t crc); + +/* + * crc32_sse42_simd_ buffer size constraints: see the use in zlib/crc32.c + * for computing the crc32 of an arbitrary length buffer. + */ +#define Z_CRC32_SSE42_MINIMUM_LENGTH 64 +#define Z_CRC32_SSE42_CHUNKSIZE_MASK 15 + +/* + * CRC32 checksums using ARMv8-a crypto instructions. + */ +uint32_t ZLIB_INTERNAL armv8_crc32_little(unsigned long crc, + const unsigned char* buf, + z_size_t len); + diff --git a/deps/zlib/crc_folding.c b/deps/zlib/crc_folding.c new file mode 100644 index 00000000000000..54f4b5c9401089 --- /dev/null +++ b/deps/zlib/crc_folding.c @@ -0,0 +1,505 @@ +/* + * Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ + * instruction. + * + * A white paper describing this algorithm can be found at: + * http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * Authors: + * Wajdi Feghali + * Jim Guilford + * Vinodh Gopal + * Erdinc Ozturk + * Jim Kukunas + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "deflate.h" + +#include +#include +#include +#include + +#ifndef __GNUC__ +#define __attribute__() +#endif + +#define CRC_LOAD(s) \ + do { \ + __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)s->crc0 + 0);\ + __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)s->crc0 + 1);\ + __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)s->crc0 + 2);\ + __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)s->crc0 + 3);\ + __m128i xmm_crc_part = _mm_loadu_si128((__m128i *)s->crc0 + 4); + +#define CRC_SAVE(s) \ + _mm_storeu_si128((__m128i *)s->crc0 + 0, xmm_crc0);\ + _mm_storeu_si128((__m128i *)s->crc0 + 1, xmm_crc1);\ + _mm_storeu_si128((__m128i *)s->crc0 + 2, xmm_crc2);\ + _mm_storeu_si128((__m128i *)s->crc0 + 3, xmm_crc3);\ + _mm_storeu_si128((__m128i *)s->crc0 + 4, xmm_crc_part);\ + } while (0); + +__attribute__((target("sse4.2,pclmul"))) +ZLIB_INTERNAL void crc_fold_init(deflate_state *const s) +{ + CRC_LOAD(s) + + xmm_crc0 = _mm_cvtsi32_si128(0x9db42487); + xmm_crc1 = _mm_setzero_si128(); + xmm_crc2 = _mm_setzero_si128(); + xmm_crc3 = _mm_setzero_si128(); + + CRC_SAVE(s) + + s->strm->adler = 0; +} + +__attribute__((target("sse4.2,pclmul"))) +local void fold_1(deflate_state *const s, + __m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3) +{ + const __m128i xmm_fold4 = _mm_set_epi32( + 0x00000001, 0x54442bd4, + 0x00000001, 0xc6e41596); + + __m128i x_tmp3; + __m128 ps_crc0, ps_crc3, ps_res; + + x_tmp3 = *xmm_crc3; + + *xmm_crc3 = *xmm_crc0; + *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); + *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); + ps_crc0 = _mm_castsi128_ps(*xmm_crc0); + ps_crc3 = _mm_castsi128_ps(*xmm_crc3); + ps_res = _mm_xor_ps(ps_crc0, ps_crc3); + + *xmm_crc0 = *xmm_crc1; + *xmm_crc1 = *xmm_crc2; + *xmm_crc2 = x_tmp3; + *xmm_crc3 = _mm_castps_si128(ps_res); +} + +__attribute__((target("sse4.2,pclmul"))) +local void fold_2(deflate_state *const s, + __m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3) +{ + const __m128i xmm_fold4 = _mm_set_epi32( + 0x00000001, 0x54442bd4, + 0x00000001, 0xc6e41596); + + __m128i x_tmp3, x_tmp2; + __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res31, ps_res20; + + x_tmp3 = *xmm_crc3; + x_tmp2 = *xmm_crc2; + + *xmm_crc3 = *xmm_crc1; + *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); + *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); + ps_crc3 = _mm_castsi128_ps(*xmm_crc3); + ps_crc1 = _mm_castsi128_ps(*xmm_crc1); + ps_res31= _mm_xor_ps(ps_crc3, ps_crc1); + + *xmm_crc2 = *xmm_crc0; + *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); + *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10); + ps_crc0 = _mm_castsi128_ps(*xmm_crc0); + ps_crc2 = _mm_castsi128_ps(*xmm_crc2); + ps_res20= _mm_xor_ps(ps_crc0, ps_crc2); + + *xmm_crc0 = x_tmp2; + *xmm_crc1 = x_tmp3; + *xmm_crc2 = _mm_castps_si128(ps_res20); + *xmm_crc3 = _mm_castps_si128(ps_res31); +} + +__attribute__((target("sse4.2,pclmul"))) +local void fold_3(deflate_state *const s, + __m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3) +{ + const __m128i xmm_fold4 = _mm_set_epi32( + 0x00000001, 0x54442bd4, + 0x00000001, 0xc6e41596); + + __m128i x_tmp3; + __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res32, ps_res21, ps_res10; + + x_tmp3 = *xmm_crc3; + + *xmm_crc3 = *xmm_crc2; + *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01); + *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); + ps_crc2 = _mm_castsi128_ps(*xmm_crc2); + ps_crc3 = _mm_castsi128_ps(*xmm_crc3); + ps_res32 = _mm_xor_ps(ps_crc2, ps_crc3); + + *xmm_crc2 = *xmm_crc1; + *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); + *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10); + ps_crc1 = _mm_castsi128_ps(*xmm_crc1); + ps_crc2 = _mm_castsi128_ps(*xmm_crc2); + ps_res21= _mm_xor_ps(ps_crc1, ps_crc2); + + *xmm_crc1 = *xmm_crc0; + *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); + *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x10); + ps_crc0 = _mm_castsi128_ps(*xmm_crc0); + ps_crc1 = _mm_castsi128_ps(*xmm_crc1); + ps_res10= _mm_xor_ps(ps_crc0, ps_crc1); + + *xmm_crc0 = x_tmp3; + *xmm_crc1 = _mm_castps_si128(ps_res10); + *xmm_crc2 = _mm_castps_si128(ps_res21); + *xmm_crc3 = _mm_castps_si128(ps_res32); +} + +__attribute__((target("sse4.2,pclmul"))) +local void fold_4(deflate_state *const s, + __m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3) +{ + const __m128i xmm_fold4 = _mm_set_epi32( + 0x00000001, 0x54442bd4, + 0x00000001, 0xc6e41596); + + __m128i x_tmp0, x_tmp1, x_tmp2, x_tmp3; + __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3; + __m128 ps_t0, ps_t1, ps_t2, ps_t3; + __m128 ps_res0, ps_res1, ps_res2, ps_res3; + + x_tmp0 = *xmm_crc0; + x_tmp1 = *xmm_crc1; + x_tmp2 = *xmm_crc2; + x_tmp3 = *xmm_crc3; + + *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); + x_tmp0 = _mm_clmulepi64_si128(x_tmp0, xmm_fold4, 0x10); + ps_crc0 = _mm_castsi128_ps(*xmm_crc0); + ps_t0 = _mm_castsi128_ps(x_tmp0); + ps_res0 = _mm_xor_ps(ps_crc0, ps_t0); + + *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); + x_tmp1 = _mm_clmulepi64_si128(x_tmp1, xmm_fold4, 0x10); + ps_crc1 = _mm_castsi128_ps(*xmm_crc1); + ps_t1 = _mm_castsi128_ps(x_tmp1); + ps_res1 = _mm_xor_ps(ps_crc1, ps_t1); + + *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01); + x_tmp2 = _mm_clmulepi64_si128(x_tmp2, xmm_fold4, 0x10); + ps_crc2 = _mm_castsi128_ps(*xmm_crc2); + ps_t2 = _mm_castsi128_ps(x_tmp2); + ps_res2 = _mm_xor_ps(ps_crc2, ps_t2); + + *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x01); + x_tmp3 = _mm_clmulepi64_si128(x_tmp3, xmm_fold4, 0x10); + ps_crc3 = _mm_castsi128_ps(*xmm_crc3); + ps_t3 = _mm_castsi128_ps(x_tmp3); + ps_res3 = _mm_xor_ps(ps_crc3, ps_t3); + + *xmm_crc0 = _mm_castps_si128(ps_res0); + *xmm_crc1 = _mm_castps_si128(ps_res1); + *xmm_crc2 = _mm_castps_si128(ps_res2); + *xmm_crc3 = _mm_castps_si128(ps_res3); +} + +local const unsigned zalign(32) pshufb_shf_table[60] = { + 0x84838281,0x88878685,0x8c8b8a89,0x008f8e8d, /* shl 15 (16 - 1)/shr1 */ + 0x85848382,0x89888786,0x8d8c8b8a,0x01008f8e, /* shl 14 (16 - 3)/shr2 */ + 0x86858483,0x8a898887,0x8e8d8c8b,0x0201008f, /* shl 13 (16 - 4)/shr3 */ + 0x87868584,0x8b8a8988,0x8f8e8d8c,0x03020100, /* shl 12 (16 - 4)/shr4 */ + 0x88878685,0x8c8b8a89,0x008f8e8d,0x04030201, /* shl 11 (16 - 5)/shr5 */ + 0x89888786,0x8d8c8b8a,0x01008f8e,0x05040302, /* shl 10 (16 - 6)/shr6 */ + 0x8a898887,0x8e8d8c8b,0x0201008f,0x06050403, /* shl 9 (16 - 7)/shr7 */ + 0x8b8a8988,0x8f8e8d8c,0x03020100,0x07060504, /* shl 8 (16 - 8)/shr8 */ + 0x8c8b8a89,0x008f8e8d,0x04030201,0x08070605, /* shl 7 (16 - 9)/shr9 */ + 0x8d8c8b8a,0x01008f8e,0x05040302,0x09080706, /* shl 6 (16 -10)/shr10*/ + 0x8e8d8c8b,0x0201008f,0x06050403,0x0a090807, /* shl 5 (16 -11)/shr11*/ + 0x8f8e8d8c,0x03020100,0x07060504,0x0b0a0908, /* shl 4 (16 -12)/shr12*/ + 0x008f8e8d,0x04030201,0x08070605,0x0c0b0a09, /* shl 3 (16 -13)/shr13*/ + 0x01008f8e,0x05040302,0x09080706,0x0d0c0b0a, /* shl 2 (16 -14)/shr14*/ + 0x0201008f,0x06050403,0x0a090807,0x0e0d0c0b /* shl 1 (16 -15)/shr15*/ +}; + +__attribute__((target("sse4.2,pclmul"))) +local void partial_fold(deflate_state *const s, const size_t len, + __m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, + __m128i *xmm_crc_part) +{ + + const __m128i xmm_fold4 = _mm_set_epi32( + 0x00000001, 0x54442bd4, + 0x00000001, 0xc6e41596); + const __m128i xmm_mask3 = _mm_set1_epi32(0x80808080); + + __m128i xmm_shl, xmm_shr, xmm_tmp1, xmm_tmp2, xmm_tmp3; + __m128i xmm_a0_0, xmm_a0_1; + __m128 ps_crc3, psa0_0, psa0_1, ps_res; + + xmm_shl = _mm_load_si128((__m128i *)pshufb_shf_table + (len - 1)); + xmm_shr = xmm_shl; + xmm_shr = _mm_xor_si128(xmm_shr, xmm_mask3); + + xmm_a0_0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shl); + + *xmm_crc0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shr); + xmm_tmp1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shl); + *xmm_crc0 = _mm_or_si128(*xmm_crc0, xmm_tmp1); + + *xmm_crc1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shr); + xmm_tmp2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shl); + *xmm_crc1 = _mm_or_si128(*xmm_crc1, xmm_tmp2); + + *xmm_crc2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shr); + xmm_tmp3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shl); + *xmm_crc2 = _mm_or_si128(*xmm_crc2, xmm_tmp3); + + *xmm_crc3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shr); + *xmm_crc_part = _mm_shuffle_epi8(*xmm_crc_part, xmm_shl); + *xmm_crc3 = _mm_or_si128(*xmm_crc3, *xmm_crc_part); + + xmm_a0_1 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x10); + xmm_a0_0 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x01); + + ps_crc3 = _mm_castsi128_ps(*xmm_crc3); + psa0_0 = _mm_castsi128_ps(xmm_a0_0); + psa0_1 = _mm_castsi128_ps(xmm_a0_1); + + ps_res = _mm_xor_ps(ps_crc3, psa0_0); + ps_res = _mm_xor_ps(ps_res, psa0_1); + + *xmm_crc3 = _mm_castps_si128(ps_res); +} + +__attribute__((target("sse4.2,pclmul"))) +ZLIB_INTERNAL void crc_fold_copy(deflate_state *const s, + unsigned char *dst, const unsigned char *src, long len) +{ + unsigned long algn_diff; + __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; + + CRC_LOAD(s) + + if (len < 16) { + if (len == 0) + return; + goto partial; + } + + algn_diff = 0 - (uintptr_t)src & 0xF; + if (algn_diff) { + xmm_crc_part = _mm_loadu_si128((__m128i *)src); + _mm_storeu_si128((__m128i *)dst, xmm_crc_part); + + dst += algn_diff; + src += algn_diff; + len -= algn_diff; + + partial_fold(s, algn_diff, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, + &xmm_crc_part); + } + + while ((len -= 64) >= 0) { + xmm_t0 = _mm_load_si128((__m128i *)src); + xmm_t1 = _mm_load_si128((__m128i *)src + 1); + xmm_t2 = _mm_load_si128((__m128i *)src + 2); + xmm_t3 = _mm_load_si128((__m128i *)src + 3); + + fold_4(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + _mm_storeu_si128((__m128i *)dst, xmm_t0); + _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); + _mm_storeu_si128((__m128i *)dst + 2, xmm_t2); + _mm_storeu_si128((__m128i *)dst + 3, xmm_t3); + + xmm_crc0 = _mm_xor_si128(xmm_crc0, xmm_t0); + xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t1); + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t2); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t3); + + src += 64; + dst += 64; + } + + /* + * len = num bytes left - 64 + */ + if (len + 16 >= 0) { + len += 16; + + xmm_t0 = _mm_load_si128((__m128i *)src); + xmm_t1 = _mm_load_si128((__m128i *)src + 1); + xmm_t2 = _mm_load_si128((__m128i *)src + 2); + + fold_3(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + _mm_storeu_si128((__m128i *)dst, xmm_t0); + _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); + _mm_storeu_si128((__m128i *)dst + 2, xmm_t2); + + xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t0); + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t1); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t2); + + if (len == 0) + goto done; + + dst += 48; + src += 48; + } else if (len + 32 >= 0) { + len += 32; + + xmm_t0 = _mm_load_si128((__m128i *)src); + xmm_t1 = _mm_load_si128((__m128i *)src + 1); + + fold_2(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + _mm_storeu_si128((__m128i *)dst, xmm_t0); + _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); + + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t0); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t1); + + if (len == 0) + goto done; + + dst += 32; + src += 32; + } else if (len + 48 >= 0) { + len += 48; + + xmm_t0 = _mm_load_si128((__m128i *)src); + + fold_1(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + _mm_storeu_si128((__m128i *)dst, xmm_t0); + + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0); + + if (len == 0) + goto done; + + dst += 16; + src += 16; + } else { + len += 64; + if (len == 0) + goto done; + } + +partial: + +#if defined(_MSC_VER) + /* VS does not permit the use of _mm_set_epi64x in 32-bit builds */ + { + int32_t parts[4] = {0, 0, 0, 0}; + memcpy(&parts, src, len); + xmm_crc_part = _mm_set_epi32(parts[3], parts[2], parts[1], parts[0]); + } +#else + { + int64_t parts[2] = {0, 0}; + memcpy(&parts, src, len); + xmm_crc_part = _mm_set_epi64x(parts[1], parts[0]); + } +#endif + + _mm_storeu_si128((__m128i *)dst, xmm_crc_part); + partial_fold(s, len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, + &xmm_crc_part); +done: + CRC_SAVE(s) +} + +local const unsigned zalign(16) crc_k[] = { + 0xccaa009e, 0x00000000, /* rk1 */ + 0x751997d0, 0x00000001, /* rk2 */ + 0xccaa009e, 0x00000000, /* rk5 */ + 0x63cd6124, 0x00000001, /* rk6 */ + 0xf7011640, 0x00000001, /* rk7 */ + 0xdb710640, 0x00000001 /* rk8 */ +}; + +local const unsigned zalign(16) crc_mask[4] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000 +}; + +local const unsigned zalign(16) crc_mask2[4] = { + 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF +}; + +__attribute__((target("sse4.2,pclmul"))) +unsigned ZLIB_INTERNAL crc_fold_512to32(deflate_state *const s) +{ + const __m128i xmm_mask = _mm_load_si128((__m128i *)crc_mask); + const __m128i xmm_mask2 = _mm_load_si128((__m128i *)crc_mask2); + + unsigned crc; + __m128i x_tmp0, x_tmp1, x_tmp2, crc_fold; + + CRC_LOAD(s) + + /* + * k1 + */ + crc_fold = _mm_load_si128((__m128i *)crc_k); + + x_tmp0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x10); + xmm_crc0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x01); + xmm_crc1 = _mm_xor_si128(xmm_crc1, x_tmp0); + xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_crc0); + + x_tmp1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x10); + xmm_crc1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x01); + xmm_crc2 = _mm_xor_si128(xmm_crc2, x_tmp1); + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_crc1); + + x_tmp2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x10); + xmm_crc2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x01); + xmm_crc3 = _mm_xor_si128(xmm_crc3, x_tmp2); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); + + /* + * k5 + */ + crc_fold = _mm_load_si128((__m128i *)crc_k + 1); + + xmm_crc0 = xmm_crc3; + xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0); + xmm_crc0 = _mm_srli_si128(xmm_crc0, 8); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0); + + xmm_crc0 = xmm_crc3; + xmm_crc3 = _mm_slli_si128(xmm_crc3, 4); + xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0); + xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask2); + + /* + * k7 + */ + xmm_crc1 = xmm_crc3; + xmm_crc2 = xmm_crc3; + crc_fold = _mm_load_si128((__m128i *)crc_k + 2); + + xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); + xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask); + + xmm_crc2 = xmm_crc3; + xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc1); + + crc = _mm_extract_epi32(xmm_crc3, 2); + return ~crc; + CRC_SAVE(s) +} diff --git a/deps/zlib/deflate.c b/deps/zlib/deflate.c index 909606df01fb70..201254ac1b664e 100644 --- a/deps/zlib/deflate.c +++ b/deps/zlib/deflate.c @@ -48,8 +48,17 @@ */ /* @(#) $Id$ */ - +#include #include "deflate.h" +#include "x86.h" +#include "contrib/optimizations/insert_string.h" + +#if (defined(__ARM_NEON__) || defined(__ARM_NEON)) +#include "contrib/optimizations/slide_hash_neon.h" +#endif +#if defined(CRC32_ARMV8_CRC32) +#include "crc32_simd.h" +#endif const char deflate_copyright[] = " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler "; @@ -86,7 +95,7 @@ local block_state deflate_huff OF((deflate_state *s, int flush)); local void lm_init OF((deflate_state *s)); local void putShortMSB OF((deflate_state *s, uInt b)); local void flush_pending OF((z_streamp strm)); -local unsigned read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +unsigned ZLIB_INTERNAL deflate_read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); #ifdef ASMV # pragma message("Assembler code may have bugs -- use at your own risk") void match_init OF((void)); /* asm code initialization */ @@ -100,6 +109,11 @@ local void check_match OF((deflate_state *s, IPos start, IPos match, int length)); #endif +/* From crc32.c */ +extern void ZLIB_INTERNAL crc_reset(deflate_state *const s); +extern void ZLIB_INTERNAL crc_finalize(deflate_state *const s); +extern void ZLIB_INTERNAL copy_with_crc(z_streamp strm, Bytef *dst, long size); + /* =========================================================================== * Local data */ @@ -154,47 +168,13 @@ local const config configuration_table[10] = { /* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ #define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) -/* =========================================================================== - * Update a hash value with the given input byte - * IN assertion: all calls to UPDATE_HASH are made with consecutive input - * characters, so that a running hash key can be computed from the previous - * key instead of complete recalculation each time. - */ -#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) - - -/* =========================================================================== - * Insert string str in the dictionary and set match_head to the previous head - * of the hash chain (the most recent string with same hash key). Return - * the previous length of the hash chain. - * If this file is compiled with -DFASTEST, the compression level is forced - * to 1, and no hash chains are maintained. - * IN assertion: all calls to INSERT_STRING are made with consecutive input - * characters and the first MIN_MATCH bytes of str are valid (except for - * the last MIN_MATCH-1 bytes of the input file). - */ -#ifdef FASTEST -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#else -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#endif - /* =========================================================================== * Initialize the hash table (avoiding 64K overflow for 16 bit systems). * prev[] will be initialized on the fly. */ #define CLEAR_HASH(s) \ - do { \ - s->head[s->hash_size-1] = NIL; \ - zmemzero((Bytef *)s->head, \ - (unsigned)(s->hash_size-1)*sizeof(*s->head)); \ - } while (0) + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); /* =========================================================================== * Slide the hash table when sliding the window down (could be avoided with 32 @@ -204,6 +184,10 @@ local const config configuration_table[10] = { local void slide_hash(s) deflate_state *s; { +#if (defined(__ARM_NEON__) || defined(__ARM_NEON)) + /* NEON based hash table rebase. */ + return neon_slide_hash(s->head, s->prev, s->w_size, s->hash_size); +#endif unsigned n, m; Posf *p; uInt wsize = s->w_size; @@ -251,14 +235,20 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, const char *version; int stream_size; { + unsigned window_padding = 8; deflate_state *s; int wrap = 1; static const char my_version[] = ZLIB_VERSION; - ushf *overlay; - /* We overlay pending_buf and d_buf+l_buf. This works since the average - * output size for (length,distance) codes is <= 24 bits. - */ + // Needed to activate optimized insert_string() that helps compression + // for all wrapper formats (e.g. RAW, ZLIB, GZIP). + // Feature detection is not triggered while using RAW mode (i.e. we never + // call crc32() with a NULL buffer). +#if defined(CRC32_ARMV8_CRC32) + arm_check_features(); +#elif defined(CRC32_SIMD_SSE42_PCLMUL) + x86_check_features(); +#endif if (version == Z_NULL || version[0] != my_version[0] || stream_size != sizeof(z_stream)) { @@ -316,12 +306,19 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, s->w_size = 1 << s->w_bits; s->w_mask = s->w_size - 1; - s->hash_bits = (uInt)memLevel + 7; + if (x86_cpu_enable_simd) { + s->hash_bits = 15; + } else { + s->hash_bits = memLevel + 7; + } + s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); - s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->window = (Bytef *) ZALLOC(strm, + s->w_size + window_padding, + 2*sizeof(Byte)); s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); @@ -329,9 +326,46 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - s->pending_buf = (uchf *) overlay; - s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + /* We overlay pending_buf and sym_buf. This works since the average size + * for length/distance pairs over any compressed block is assured to be 31 + * bits or less. + * + * Analysis: The longest fixed codes are a length code of 8 bits plus 5 + * extra bits, for lengths 131 to 257. The longest fixed distance codes are + * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest + * possible fixed-codes length/distance pair is then 31 bits total. + * + * sym_buf starts one-fourth of the way into pending_buf. So there are + * three bytes in sym_buf for every four bytes in pending_buf. Each symbol + * in sym_buf is three bytes -- two for the distance and one for the + * literal/length. As each symbol is consumed, the pointer to the next + * sym_buf value to read moves forward three bytes. From that symbol, up to + * 31 bits are written to pending_buf. The closest the written pending_buf + * bits gets to the next sym_buf symbol to read is just before the last + * code is written. At that time, 31*(n-2) bits have been written, just + * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at + * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1 + * symbols are written.) The closest the writing gets to what is unread is + * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and + * can range from 128 to 32768. + * + * Therefore, at a minimum, there are 142 bits of space between what is + * written and what is read in the overlain buffers, so the symbols cannot + * be overwritten by the compressed data. That space is actually 139 bits, + * due to the three-bit fixed-code block header. + * + * That covers the case where either Z_FIXED is specified, forcing fixed + * codes, or when the use of fixed codes is chosen, because that choice + * results in a smaller compressed block than dynamic codes. That latter + * condition then assures that the above analysis also covers all dynamic + * blocks. A dynamic-code block will only be chosen to be emitted if it has + * fewer bits than a fixed-code block would for the same set of symbols. + * Therefore its average symbol length is assured to be less than 31. So + * the compressed data for a dynamic block also cannot overwrite the + * symbols from which it is being constructed. + */ + s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4); + s->pending_buf_size = (ulg)s->lit_bufsize * 4; if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || s->pending_buf == Z_NULL) { @@ -340,8 +374,12 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, deflateEnd (strm); return Z_MEM_ERROR; } - s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + s->sym_buf = s->pending_buf + s->lit_bufsize; + s->sym_end = (s->lit_bufsize - 1) * 3; + /* We avoid equality with lit_bufsize*3 because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ s->level = level; s->strategy = strategy; @@ -397,7 +435,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) /* when using zlib wrappers, compute Adler-32 for provided dictionary */ if (wrap == 1) strm->adler = adler32(strm->adler, dictionary, dictLength); - s->wrap = 0; /* avoid computing Adler-32 in read_buf */ + s->wrap = 0; /* avoid computing Adler-32 in deflate_read_buf */ /* if dictionary would fill window, just replace the history */ if (dictLength >= s->w_size) { @@ -421,11 +459,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) str = s->strstart; n = s->lookahead - (MIN_MATCH-1); do { - UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); -#ifndef FASTEST - s->prev[str & s->w_mask] = s->head[s->ins_h]; -#endif - s->head[s->ins_h] = (Pos)str; + insert_string(s, str); str++; } while (--n); s->strstart = str; @@ -552,7 +586,7 @@ int ZEXPORT deflatePrime (strm, bits, value) if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; - if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) + if (s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3)) return Z_BUF_ERROR; do { put = Buf_size - s->bi_valid; @@ -728,7 +762,7 @@ local void putShortMSB (s, b) * Flush as much pending output as possible. All deflate() output, except for * some deflate_stored() output, goes through this function so some * applications may wish to modify it to avoid allocating a large - * strm->next_out buffer and copying into it. (See also read_buf()). + * strm->next_out buffer and copying into it. (See also deflate_read_buf()). */ local void flush_pending(strm) z_streamp strm; @@ -851,7 +885,7 @@ int ZEXPORT deflate (strm, flush) #ifdef GZIP if (s->status == GZIP_STATE) { /* gzip header */ - strm->adler = crc32(0L, Z_NULL, 0); + crc_reset(s); put_byte(s, 31); put_byte(s, 139); put_byte(s, 8); @@ -1052,6 +1086,7 @@ int ZEXPORT deflate (strm, flush) /* Write the trailer */ #ifdef GZIP if (s->wrap == 2) { + crc_finalize(s); put_byte(s, (Byte)(strm->adler & 0xff)); put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); @@ -1111,7 +1146,6 @@ int ZEXPORT deflateCopy (dest, source) #else deflate_state *ds; deflate_state *ss; - ushf *overlay; if (deflateStateCheck(source) || dest == Z_NULL) { @@ -1131,8 +1165,7 @@ int ZEXPORT deflateCopy (dest, source) ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); - overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); - ds->pending_buf = (uchf *) overlay; + ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4); if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || ds->pending_buf == Z_NULL) { @@ -1146,8 +1179,7 @@ int ZEXPORT deflateCopy (dest, source) zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); - ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); - ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + ds->sym_buf = ds->pending_buf + ds->lit_bufsize; ds->l_desc.dyn_tree = ds->dyn_ltree; ds->d_desc.dyn_tree = ds->dyn_dtree; @@ -1164,7 +1196,7 @@ int ZEXPORT deflateCopy (dest, source) * allocating a large strm->next_in buffer and copying from it. * (See also flush_pending()). */ -local unsigned read_buf(strm, buf, size) +ZLIB_INTERNAL unsigned deflate_read_buf(strm, buf, size) z_streamp strm; Bytef *buf; unsigned size; @@ -1176,15 +1208,16 @@ local unsigned read_buf(strm, buf, size) strm->avail_in -= len; - zmemcpy(buf, strm->next_in, len); - if (strm->state->wrap == 1) { - strm->adler = adler32(strm->adler, buf, len); - } #ifdef GZIP - else if (strm->state->wrap == 2) { - strm->adler = crc32(strm->adler, buf, len); - } + if (strm->state->wrap == 2) + copy_with_crc(strm, buf, len); + else #endif + { + zmemcpy(buf, strm->next_in, len); + if (strm->state->wrap == 1) + strm->adler = adler32(strm->adler, buf, len); + } strm->next_in += len; strm->total_in += len; @@ -1482,7 +1515,19 @@ local void check_match(s, start, match, length) * performed for at least two bytes (required for the zip translate_eol * option -- not supported here). */ -local void fill_window(s) +local void fill_window_c(deflate_state *s); + +local void fill_window(deflate_state *s) +{ + if (x86_cpu_enable_simd) { + fill_window_sse(s); + return; + } + + fill_window_c(s); +} + +local void fill_window_c(s) deflate_state *s; { unsigned n; @@ -1534,7 +1579,7 @@ local void fill_window(s) */ Assert(more >= 2, "more < 2"); - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + n = deflate_read_buf(s->strm, s->window + s->strstart + s->lookahead, more); s->lookahead += n; /* Initialize the hash value now that we have some input: */ @@ -1723,7 +1768,7 @@ local block_state deflate_stored(s, flush) * the check value. */ if (len) { - read_buf(s->strm, s->strm->next_out, len); + deflate_read_buf(s->strm, s->strm->next_out, len); s->strm->next_out += len; s->strm->avail_out -= len; s->strm->total_out += len; @@ -1786,7 +1831,7 @@ local block_state deflate_stored(s, flush) if (have > s->strm->avail_in) have = s->strm->avail_in; if (have) { - read_buf(s->strm, s->window + s->strstart, have); + deflate_read_buf(s->strm, s->window + s->strstart, have); s->strstart += have; } if (s->high_water < s->strstart) @@ -1850,7 +1895,7 @@ local block_state deflate_fast(s, flush) */ hash_head = NIL; if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); + hash_head = insert_string(s, s->strstart); } /* Find the longest match, discarding those <= prev_length. @@ -1881,7 +1926,7 @@ local block_state deflate_fast(s, flush) s->match_length--; /* string at strstart already in table */ do { s->strstart++; - INSERT_STRING(s, s->strstart, hash_head); + hash_head = insert_string(s, s->strstart); /* strstart never exceeds WSIZE-MAX_MATCH, so there are * always MIN_MATCH bytes ahead. */ @@ -1915,7 +1960,7 @@ local block_state deflate_fast(s, flush) FLUSH_BLOCK(s, 1); return finish_done; } - if (s->last_lit) + if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } @@ -1953,7 +1998,7 @@ local block_state deflate_slow(s, flush) */ hash_head = NIL; if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); + hash_head = insert_string(s, s->strstart); } /* Find the longest match, discarding those <= prev_length. @@ -2004,7 +2049,7 @@ local block_state deflate_slow(s, flush) s->prev_length -= 2; do { if (++s->strstart <= max_insert) { - INSERT_STRING(s, s->strstart, hash_head); + hash_head = insert_string(s, s->strstart); } } while (--s->prev_length != 0); s->match_available = 0; @@ -2046,7 +2091,7 @@ local block_state deflate_slow(s, flush) FLUSH_BLOCK(s, 1); return finish_done; } - if (s->last_lit) + if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } @@ -2121,7 +2166,7 @@ local block_state deflate_rle(s, flush) FLUSH_BLOCK(s, 1); return finish_done; } - if (s->last_lit) + if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } @@ -2160,7 +2205,7 @@ local block_state deflate_huff(s, flush) FLUSH_BLOCK(s, 1); return finish_done; } - if (s->last_lit) + if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } diff --git a/deps/zlib/deflate.h b/deps/zlib/deflate.h index 23ecdd312bc06e..78ffb00a29768e 100644 --- a/deps/zlib/deflate.h +++ b/deps/zlib/deflate.h @@ -109,8 +109,8 @@ typedef struct internal_state { ulg gzindex; /* where in extra, name, or comment */ Byte method; /* can only be DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ - - /* used by deflate.c: */ + unsigned crc0[4 * 5]; + /* used by deflate.c: */ uInt w_size; /* LZ77 window size (32K by default) */ uInt w_bits; /* log2(w_size) (8..16) */ @@ -217,7 +217,7 @@ typedef struct internal_state { /* Depth of each subtree used as tie breaker for trees of equal frequency */ - uchf *l_buf; /* buffer for literals or lengths */ + uchf *sym_buf; /* buffer for distances and literals/lengths */ uInt lit_bufsize; /* Size of match buffer for literals/lengths. There are 4 reasons for @@ -239,13 +239,8 @@ typedef struct internal_state { * - I can't count above 4 */ - uInt last_lit; /* running index in l_buf */ - - ushf *d_buf; - /* Buffer for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ + uInt sym_next; /* running index in sym_buf */ + uInt sym_end; /* symbol table full when sym_next reaches this */ ulg opt_len; /* bit length of current block with optimal trees */ ulg static_len; /* bit length of current block with static trees */ @@ -325,20 +320,22 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ - s->d_buf[s->last_lit] = 0; \ - s->l_buf[s->last_lit++] = cc; \ + s->sym_buf[s->sym_next++] = 0; \ + s->sym_buf[s->sym_next++] = 0; \ + s->sym_buf[s->sym_next++] = cc; \ s->dyn_ltree[cc].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ + flush = (s->sym_next == s->sym_end); \ } # define _tr_tally_dist(s, distance, length, flush) \ { uch len = (uch)(length); \ ush dist = (ush)(distance); \ - s->d_buf[s->last_lit] = dist; \ - s->l_buf[s->last_lit++] = len; \ + s->sym_buf[s->sym_next++] = dist; \ + s->sym_buf[s->sym_next++] = dist >> 8; \ + s->sym_buf[s->sym_next++] = len; \ dist--; \ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ s->dyn_dtree[d_code(dist)].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ + flush = (s->sym_next == s->sym_end); \ } #else # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) @@ -346,4 +343,14 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, flush = _tr_tally(s, distance, length) #endif +/* Functions that are SIMD optimised on x86 */ +void ZLIB_INTERNAL crc_fold_init(deflate_state* const s); +void ZLIB_INTERNAL crc_fold_copy(deflate_state* const s, + unsigned char* dst, + const unsigned char* src, + long len); +unsigned ZLIB_INTERNAL crc_fold_512to32(deflate_state* const s); + +void ZLIB_INTERNAL fill_window_sse(deflate_state* s); + #endif /* DEFLATE_H */ diff --git a/deps/zlib/doc/algorithm.txt b/deps/zlib/doc/algorithm.txt deleted file mode 100644 index c97f495020b429..00000000000000 --- a/deps/zlib/doc/algorithm.txt +++ /dev/null @@ -1,209 +0,0 @@ -1. Compression algorithm (deflate) - -The deflation algorithm used by gzip (also zip and zlib) is a variation of -LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in -the input data. The second occurrence of a string is replaced by a -pointer to the previous string, in the form of a pair (distance, -length). Distances are limited to 32K bytes, and lengths are limited -to 258 bytes. When a string does not occur anywhere in the previous -32K bytes, it is emitted as a sequence of literal bytes. (In this -description, `string' must be taken as an arbitrary sequence of bytes, -and is not restricted to printable characters.) - -Literals or match lengths are compressed with one Huffman tree, and -match distances are compressed with another tree. The trees are stored -in a compact form at the start of each block. The blocks can have any -size (except that the compressed data for one block must fit in -available memory). A block is terminated when deflate() determines that -it would be useful to start another block with fresh trees. (This is -somewhat similar to the behavior of LZW-based _compress_.) - -Duplicated strings are found using a hash table. All input strings of -length 3 are inserted in the hash table. A hash index is computed for -the next 3 bytes. If the hash chain for this index is not empty, all -strings in the chain are compared with the current input string, and -the longest match is selected. - -The hash chains are searched starting with the most recent strings, to -favor small distances and thus take advantage of the Huffman encoding. -The hash chains are singly linked. There are no deletions from the -hash chains, the algorithm simply discards matches that are too old. - -To avoid a worst-case situation, very long hash chains are arbitrarily -truncated at a certain length, determined by a runtime option (level -parameter of deflateInit). So deflate() does not always find the longest -possible match but generally finds a match which is long enough. - -deflate() also defers the selection of matches with a lazy evaluation -mechanism. After a match of length N has been found, deflate() searches for -a longer match at the next input byte. If a longer match is found, the -previous match is truncated to a length of one (thus producing a single -literal byte) and the process of lazy evaluation begins again. Otherwise, -the original match is kept, and the next match search is attempted only N -steps later. - -The lazy match evaluation is also subject to a runtime parameter. If -the current match is long enough, deflate() reduces the search for a longer -match, thus speeding up the whole process. If compression ratio is more -important than speed, deflate() attempts a complete second search even if -the first match is already long enough. - -The lazy match evaluation is not performed for the fastest compression -modes (level parameter 1 to 3). For these fast modes, new strings -are inserted in the hash table only when no match was found, or -when the match is not too long. This degrades the compression ratio -but saves time since there are both fewer insertions and fewer searches. - - -2. Decompression algorithm (inflate) - -2.1 Introduction - -The key question is how to represent a Huffman code (or any prefix code) so -that you can decode fast. The most important characteristic is that shorter -codes are much more common than longer codes, so pay attention to decoding the -short codes fast, and let the long codes take longer to decode. - -inflate() sets up a first level table that covers some number of bits of -input less than the length of longest code. It gets that many bits from the -stream, and looks it up in the table. The table will tell if the next -code is that many bits or less and how many, and if it is, it will tell -the value, else it will point to the next level table for which inflate() -grabs more bits and tries to decode a longer code. - -How many bits to make the first lookup is a tradeoff between the time it -takes to decode and the time it takes to build the table. If building the -table took no time (and if you had infinite memory), then there would only -be a first level table to cover all the way to the longest code. However, -building the table ends up taking a lot longer for more bits since short -codes are replicated many times in such a table. What inflate() does is -simply to make the number of bits in the first table a variable, and then -to set that variable for the maximum speed. - -For inflate, which has 286 possible codes for the literal/length tree, the size -of the first table is nine bits. Also the distance trees have 30 possible -values, and the size of the first table is six bits. Note that for each of -those cases, the table ended up one bit longer than the ``average'' code -length, i.e. the code length of an approximately flat code which would be a -little more than eight bits for 286 symbols and a little less than five bits -for 30 symbols. - - -2.2 More details on the inflate table lookup - -Ok, you want to know what this cleverly obfuscated inflate tree actually -looks like. You are correct that it's not a Huffman tree. It is simply a -lookup table for the first, let's say, nine bits of a Huffman symbol. The -symbol could be as short as one bit or as long as 15 bits. If a particular -symbol is shorter than nine bits, then that symbol's translation is duplicated -in all those entries that start with that symbol's bits. For example, if the -symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a -symbol is nine bits long, it appears in the table once. - -If the symbol is longer than nine bits, then that entry in the table points -to another similar table for the remaining bits. Again, there are duplicated -entries as needed. The idea is that most of the time the symbol will be short -and there will only be one table look up. (That's whole idea behind data -compression in the first place.) For the less frequent long symbols, there -will be two lookups. If you had a compression method with really long -symbols, you could have as many levels of lookups as is efficient. For -inflate, two is enough. - -So a table entry either points to another table (in which case nine bits in -the above example are gobbled), or it contains the translation for the symbol -and the number of bits to gobble. Then you start again with the next -ungobbled bit. - -You may wonder: why not just have one lookup table for how ever many bits the -longest symbol is? The reason is that if you do that, you end up spending -more time filling in duplicate symbol entries than you do actually decoding. -At least for deflate's output that generates new trees every several 10's of -kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code -would take too long if you're only decoding several thousand symbols. At the -other extreme, you could make a new table for every bit in the code. In fact, -that's essentially a Huffman tree. But then you spend too much time -traversing the tree while decoding, even for short symbols. - -So the number of bits for the first lookup table is a trade of the time to -fill out the table vs. the time spent looking at the second level and above of -the table. - -Here is an example, scaled down: - -The code being decoded, with 10 symbols, from 1 to 6 bits long: - -A: 0 -B: 10 -C: 1100 -D: 11010 -E: 11011 -F: 11100 -G: 11101 -H: 11110 -I: 111110 -J: 111111 - -Let's make the first table three bits long (eight entries): - -000: A,1 -001: A,1 -010: A,1 -011: A,1 -100: B,2 -101: B,2 -110: -> table X (gobble 3 bits) -111: -> table Y (gobble 3 bits) - -Each entry is what the bits decode as and how many bits that is, i.e. how -many bits to gobble. Or the entry points to another table, with the number of -bits to gobble implicit in the size of the table. - -Table X is two bits long since the longest code starting with 110 is five bits -long: - -00: C,1 -01: C,1 -10: D,2 -11: E,2 - -Table Y is three bits long since the longest code starting with 111 is six -bits long: - -000: F,2 -001: F,2 -010: G,2 -011: G,2 -100: H,2 -101: H,2 -110: I,3 -111: J,3 - -So what we have here are three tables with a total of 20 entries that had to -be constructed. That's compared to 64 entries for a single table. Or -compared to 16 entries for a Huffman tree (six two entry tables and one four -entry table). Assuming that the code ideally represents the probability of -the symbols, it takes on the average 1.25 lookups per symbol. That's compared -to one lookup for the single table, or 1.66 lookups per symbol for the -Huffman tree. - -There, I think that gives you a picture of what's going on. For inflate, the -meaning of a particular symbol is often more than just a letter. It can be a -byte (a "literal"), or it can be either a length or a distance which -indicates a base value and a number of bits to fetch after the code that is -added to the base value. Or it might be the special end-of-block code. The -data structures created in inftrees.c try to encode all that information -compactly in the tables. - - -Jean-loup Gailly Mark Adler -jloup@gzip.org madler@alumni.caltech.edu - - -References: - -[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data -Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, -pp. 337-343. - -``DEFLATE Compressed Data Format Specification'' available in -http://tools.ietf.org/html/rfc1951 diff --git a/deps/zlib/doc/rfc1950.txt b/deps/zlib/doc/rfc1950.txt deleted file mode 100644 index ce6428a0f2eed4..00000000000000 --- a/deps/zlib/doc/rfc1950.txt +++ /dev/null @@ -1,619 +0,0 @@ - - - - - - -Network Working Group P. Deutsch -Request for Comments: 1950 Aladdin Enterprises -Category: Informational J-L. Gailly - Info-ZIP - May 1996 - - - ZLIB Compressed Data Format Specification version 3.3 - -Status of This Memo - - This memo provides information for the Internet community. This memo - does not specify an Internet standard of any kind. Distribution of - this memo is unlimited. - -IESG Note: - - The IESG takes no position on the validity of any Intellectual - Property Rights statements contained in this document. - -Notices - - Copyright (c) 1996 L. Peter Deutsch and Jean-Loup Gailly - - Permission is granted to copy and distribute this document for any - purpose and without charge, including translations into other - languages and incorporation into compilations, provided that the - copyright notice and this notice are preserved, and that any - substantive changes or deletions from the original are clearly - marked. - - A pointer to the latest version of this and related documentation in - HTML format can be found at the URL - . - -Abstract - - This specification defines a lossless compressed data format. The - data can be produced or consumed, even for an arbitrarily long - sequentially presented input data stream, using only an a priori - bounded amount of intermediate storage. The format presently uses - the DEFLATE compression method but can be easily extended to use - other compression methods. It can be implemented readily in a manner - not covered by patents. This specification also defines the ADLER-32 - checksum (an extension and improvement of the Fletcher checksum), - used for detection of data corruption, and provides an algorithm for - computing it. - - - - -Deutsch & Gailly Informational [Page 1] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - -Table of Contents - - 1. Introduction ................................................... 2 - 1.1. Purpose ................................................... 2 - 1.2. Intended audience ......................................... 3 - 1.3. Scope ..................................................... 3 - 1.4. Compliance ................................................ 3 - 1.5. Definitions of terms and conventions used ................ 3 - 1.6. Changes from previous versions ............................ 3 - 2. Detailed specification ......................................... 3 - 2.1. Overall conventions ....................................... 3 - 2.2. Data format ............................................... 4 - 2.3. Compliance ................................................ 7 - 3. References ..................................................... 7 - 4. Source code .................................................... 8 - 5. Security Considerations ........................................ 8 - 6. Acknowledgements ............................................... 8 - 7. Authors' Addresses ............................................. 8 - 8. Appendix: Rationale ............................................ 9 - 9. Appendix: Sample code ..........................................10 - -1. Introduction - - 1.1. Purpose - - The purpose of this specification is to define a lossless - compressed data format that: - - * Is independent of CPU type, operating system, file system, - and character set, and hence can be used for interchange; - - * Can be produced or consumed, even for an arbitrarily long - sequentially presented input data stream, using only an a - priori bounded amount of intermediate storage, and hence can - be used in data communications or similar structures such as - Unix filters; - - * Can use a number of different compression methods; - - * Can be implemented readily in a manner not covered by - patents, and hence can be practiced freely. - - The data format defined by this specification does not attempt to - allow random access to compressed data. - - - - - - - -Deutsch & Gailly Informational [Page 2] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - 1.2. Intended audience - - This specification is intended for use by implementors of software - to compress data into zlib format and/or decompress data from zlib - format. - - The text of the specification assumes a basic background in - programming at the level of bits and other primitive data - representations. - - 1.3. Scope - - The specification specifies a compressed data format that can be - used for in-memory compression of a sequence of arbitrary bytes. - - 1.4. Compliance - - Unless otherwise indicated below, a compliant decompressor must be - able to accept and decompress any data set that conforms to all - the specifications presented here; a compliant compressor must - produce data sets that conform to all the specifications presented - here. - - 1.5. Definitions of terms and conventions used - - byte: 8 bits stored or transmitted as a unit (same as an octet). - (For this specification, a byte is exactly 8 bits, even on - machines which store a character on a number of bits different - from 8.) See below, for the numbering of bits within a byte. - - 1.6. Changes from previous versions - - Version 3.1 was the first public release of this specification. - In version 3.2, some terminology was changed and the Adler-32 - sample code was rewritten for clarity. In version 3.3, the - support for a preset dictionary was introduced, and the - specification was converted to RFC style. - -2. Detailed specification - - 2.1. Overall conventions - - In the diagrams below, a box like this: - - +---+ - | | <-- the vertical bars might be missing - +---+ - - - - -Deutsch & Gailly Informational [Page 3] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - represents one byte; a box like this: - - +==============+ - | | - +==============+ - - represents a variable number of bytes. - - Bytes stored within a computer do not have a "bit order", since - they are always treated as a unit. However, a byte considered as - an integer between 0 and 255 does have a most- and least- - significant bit, and since we write numbers with the most- - significant digit on the left, we also write bytes with the most- - significant bit on the left. In the diagrams below, we number the - bits of a byte so that bit 0 is the least-significant bit, i.e., - the bits are numbered: - - +--------+ - |76543210| - +--------+ - - Within a computer, a number may occupy multiple bytes. All - multi-byte numbers in the format described here are stored with - the MOST-significant byte first (at the lower memory address). - For example, the decimal number 520 is stored as: - - 0 1 - +--------+--------+ - |00000010|00001000| - +--------+--------+ - ^ ^ - | | - | + less significant byte = 8 - + more significant byte = 2 x 256 - - 2.2. Data format - - A zlib stream has the following structure: - - 0 1 - +---+---+ - |CMF|FLG| (more-->) - +---+---+ - - - - - - - - -Deutsch & Gailly Informational [Page 4] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - (if FLG.FDICT set) - - 0 1 2 3 - +---+---+---+---+ - | DICTID | (more-->) - +---+---+---+---+ - - +=====================+---+---+---+---+ - |...compressed data...| ADLER32 | - +=====================+---+---+---+---+ - - Any data which may appear after ADLER32 are not part of the zlib - stream. - - CMF (Compression Method and flags) - This byte is divided into a 4-bit compression method and a 4- - bit information field depending on the compression method. - - bits 0 to 3 CM Compression method - bits 4 to 7 CINFO Compression info - - CM (Compression method) - This identifies the compression method used in the file. CM = 8 - denotes the "deflate" compression method with a window size up - to 32K. This is the method used by gzip and PNG (see - references [1] and [2] in Chapter 3, below, for the reference - documents). CM = 15 is reserved. It might be used in a future - version of this specification to indicate the presence of an - extra field before the compressed data. - - CINFO (Compression info) - For CM = 8, CINFO is the base-2 logarithm of the LZ77 window - size, minus eight (CINFO=7 indicates a 32K window size). Values - of CINFO above 7 are not allowed in this version of the - specification. CINFO is not defined in this specification for - CM not equal to 8. - - FLG (FLaGs) - This flag byte is divided as follows: - - bits 0 to 4 FCHECK (check bits for CMF and FLG) - bit 5 FDICT (preset dictionary) - bits 6 to 7 FLEVEL (compression level) - - The FCHECK value must be such that CMF and FLG, when viewed as - a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG), - is a multiple of 31. - - - - -Deutsch & Gailly Informational [Page 5] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - FDICT (Preset dictionary) - If FDICT is set, a DICT dictionary identifier is present - immediately after the FLG byte. The dictionary is a sequence of - bytes which are initially fed to the compressor without - producing any compressed output. DICT is the Adler-32 checksum - of this sequence of bytes (see the definition of ADLER32 - below). The decompressor can use this identifier to determine - which dictionary has been used by the compressor. - - FLEVEL (Compression level) - These flags are available for use by specific compression - methods. The "deflate" method (CM = 8) sets these flags as - follows: - - 0 - compressor used fastest algorithm - 1 - compressor used fast algorithm - 2 - compressor used default algorithm - 3 - compressor used maximum compression, slowest algorithm - - The information in FLEVEL is not needed for decompression; it - is there to indicate if recompression might be worthwhile. - - compressed data - For compression method 8, the compressed data is stored in the - deflate compressed data format as described in the document - "DEFLATE Compressed Data Format Specification" by L. Peter - Deutsch. (See reference [3] in Chapter 3, below) - - Other compressed data formats are not specified in this version - of the zlib specification. - - ADLER32 (Adler-32 checksum) - This contains a checksum value of the uncompressed data - (excluding any dictionary data) computed according to Adler-32 - algorithm. This algorithm is a 32-bit extension and improvement - of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 - standard. See references [4] and [5] in Chapter 3, below) - - Adler-32 is composed of two sums accumulated per byte: s1 is - the sum of all bytes, s2 is the sum of all s1 values. Both sums - are done modulo 65521. s1 is initialized to 1, s2 to zero. The - Adler-32 checksum is stored as s2*65536 + s1 in most- - significant-byte first (network) order. - - - - - - - - -Deutsch & Gailly Informational [Page 6] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - 2.3. Compliance - - A compliant compressor must produce streams with correct CMF, FLG - and ADLER32, but need not support preset dictionaries. When the - zlib data format is used as part of another standard data format, - the compressor may use only preset dictionaries that are specified - by this other data format. If this other format does not use the - preset dictionary feature, the compressor must not set the FDICT - flag. - - A compliant decompressor must check CMF, FLG, and ADLER32, and - provide an error indication if any of these have incorrect values. - A compliant decompressor must give an error indication if CM is - not one of the values defined in this specification (only the - value 8 is permitted in this version), since another value could - indicate the presence of new features that would cause subsequent - data to be interpreted incorrectly. A compliant decompressor must - give an error indication if FDICT is set and DICTID is not the - identifier of a known preset dictionary. A decompressor may - ignore FLEVEL and still be compliant. When the zlib data format - is being used as a part of another standard format, a compliant - decompressor must support all the preset dictionaries specified by - the other format. When the other format does not use the preset - dictionary feature, a compliant decompressor must reject any - stream in which the FDICT flag is set. - -3. References - - [1] Deutsch, L.P.,"GZIP Compressed Data Format Specification", - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ - - [2] Thomas Boutell, "PNG (Portable Network Graphics) specification", - available in ftp://ftp.uu.net/graphics/png/documents/ - - [3] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ - - [4] Fletcher, J. G., "An Arithmetic Checksum for Serial - Transmissions," IEEE Transactions on Communications, Vol. COM-30, - No. 1, January 1982, pp. 247-252. - - [5] ITU-T Recommendation X.224, Annex D, "Checksum Algorithms," - November, 1993, pp. 144, 145. (Available from - gopher://info.itu.ch). ITU-T X.244 is also the same as ISO 8073. - - - - - - - -Deutsch & Gailly Informational [Page 7] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - -4. Source code - - Source code for a C language implementation of a "zlib" compliant - library is available at ftp://ftp.uu.net/pub/archiving/zip/zlib/. - -5. Security Considerations - - A decoder that fails to check the ADLER32 checksum value may be - subject to undetected data corruption. - -6. Acknowledgements - - Trademarks cited in this document are the property of their - respective owners. - - Jean-Loup Gailly and Mark Adler designed the zlib format and wrote - the related software described in this specification. Glenn - Randers-Pehrson converted this document to RFC and HTML format. - -7. Authors' Addresses - - L. Peter Deutsch - Aladdin Enterprises - 203 Santa Margarita Ave. - Menlo Park, CA 94025 - - Phone: (415) 322-0103 (AM only) - FAX: (415) 322-1734 - EMail: - - - Jean-Loup Gailly - - EMail: - - Questions about the technical content of this specification can be - sent by email to - - Jean-Loup Gailly and - Mark Adler - - Editorial comments on this specification can be sent by email to - - L. Peter Deutsch and - Glenn Randers-Pehrson - - - - - - -Deutsch & Gailly Informational [Page 8] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - -8. Appendix: Rationale - - 8.1. Preset dictionaries - - A preset dictionary is specially useful to compress short input - sequences. The compressor can take advantage of the dictionary - context to encode the input in a more compact manner. The - decompressor can be initialized with the appropriate context by - virtually decompressing a compressed version of the dictionary - without producing any output. However for certain compression - algorithms such as the deflate algorithm this operation can be - achieved without actually performing any decompression. - - The compressor and the decompressor must use exactly the same - dictionary. The dictionary may be fixed or may be chosen among a - certain number of predefined dictionaries, according to the kind - of input data. The decompressor can determine which dictionary has - been chosen by the compressor by checking the dictionary - identifier. This document does not specify the contents of - predefined dictionaries, since the optimal dictionaries are - application specific. Standard data formats using this feature of - the zlib specification must precisely define the allowed - dictionaries. - - 8.2. The Adler-32 algorithm - - The Adler-32 algorithm is much faster than the CRC32 algorithm yet - still provides an extremely low probability of undetected errors. - - The modulo on unsigned long accumulators can be delayed for 5552 - bytes, so the modulo operation time is negligible. If the bytes - are a, b, c, the second sum is 3a + 2b + c + 3, and so is position - and order sensitive, unlike the first sum, which is just a - checksum. That 65521 is prime is important to avoid a possible - large class of two-byte errors that leave the check unchanged. - (The Fletcher checksum uses 255, which is not prime and which also - makes the Fletcher check insensitive to single byte changes 0 <-> - 255.) - - The sum s1 is initialized to 1 instead of zero to make the length - of the sequence part of s2, so that the length does not have to be - checked separately. (Any sequence of zeroes has a Fletcher - checksum of zero.) - - - - - - - - -Deutsch & Gailly Informational [Page 9] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - -9. Appendix: Sample code - - The following C code computes the Adler-32 checksum of a data buffer. - It is written for clarity, not for speed. The sample code is in the - ANSI C programming language. Non C users may find it easier to read - with these hints: - - & Bitwise AND operator. - >> Bitwise right shift operator. When applied to an - unsigned quantity, as here, right shift inserts zero bit(s) - at the left. - << Bitwise left shift operator. Left shift inserts zero - bit(s) at the right. - ++ "n++" increments the variable n. - % modulo operator: a % b is the remainder of a divided by b. - - #define BASE 65521 /* largest prime smaller than 65536 */ - - /* - Update a running Adler-32 checksum with the bytes buf[0..len-1] - and return the updated checksum. The Adler-32 checksum should be - initialized to 1. - - Usage example: - - unsigned long adler = 1L; - - while (read_buffer(buffer, length) != EOF) { - adler = update_adler32(adler, buffer, length); - } - if (adler != original_adler) error(); - */ - unsigned long update_adler32(unsigned long adler, - unsigned char *buf, int len) - { - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int n; - - for (n = 0; n < len; n++) { - s1 = (s1 + buf[n]) % BASE; - s2 = (s2 + s1) % BASE; - } - return (s2 << 16) + s1; - } - - /* Return the adler32 of the bytes buf[0..len-1] */ - - - - -Deutsch & Gailly Informational [Page 10] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - unsigned long adler32(unsigned char *buf, int len) - { - return update_adler32(1L, buf, len); - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Deutsch & Gailly Informational [Page 11] - diff --git a/deps/zlib/doc/rfc1951.txt b/deps/zlib/doc/rfc1951.txt deleted file mode 100644 index 403c8c722ff24c..00000000000000 --- a/deps/zlib/doc/rfc1951.txt +++ /dev/null @@ -1,955 +0,0 @@ - - - - - - -Network Working Group P. Deutsch -Request for Comments: 1951 Aladdin Enterprises -Category: Informational May 1996 - - - DEFLATE Compressed Data Format Specification version 1.3 - -Status of This Memo - - This memo provides information for the Internet community. This memo - does not specify an Internet standard of any kind. Distribution of - this memo is unlimited. - -IESG Note: - - The IESG takes no position on the validity of any Intellectual - Property Rights statements contained in this document. - -Notices - - Copyright (c) 1996 L. Peter Deutsch - - Permission is granted to copy and distribute this document for any - purpose and without charge, including translations into other - languages and incorporation into compilations, provided that the - copyright notice and this notice are preserved, and that any - substantive changes or deletions from the original are clearly - marked. - - A pointer to the latest version of this and related documentation in - HTML format can be found at the URL - . - -Abstract - - This specification defines a lossless compressed data format that - compresses data using a combination of the LZ77 algorithm and Huffman - coding, with efficiency comparable to the best currently available - general-purpose compression methods. The data can be produced or - consumed, even for an arbitrarily long sequentially presented input - data stream, using only an a priori bounded amount of intermediate - storage. The format can be implemented readily in a manner not - covered by patents. - - - - - - - - -Deutsch Informational [Page 1] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - -Table of Contents - - 1. Introduction ................................................... 2 - 1.1. Purpose ................................................... 2 - 1.2. Intended audience ......................................... 3 - 1.3. Scope ..................................................... 3 - 1.4. Compliance ................................................ 3 - 1.5. Definitions of terms and conventions used ................ 3 - 1.6. Changes from previous versions ............................ 4 - 2. Compressed representation overview ............................. 4 - 3. Detailed specification ......................................... 5 - 3.1. Overall conventions ....................................... 5 - 3.1.1. Packing into bytes .................................. 5 - 3.2. Compressed block format ................................... 6 - 3.2.1. Synopsis of prefix and Huffman coding ............... 6 - 3.2.2. Use of Huffman coding in the "deflate" format ....... 7 - 3.2.3. Details of block format ............................. 9 - 3.2.4. Non-compressed blocks (BTYPE=00) ................... 11 - 3.2.5. Compressed blocks (length and distance codes) ...... 11 - 3.2.6. Compression with fixed Huffman codes (BTYPE=01) .... 12 - 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) .. 13 - 3.3. Compliance ............................................... 14 - 4. Compression algorithm details ................................. 14 - 5. References .................................................... 16 - 6. Security Considerations ....................................... 16 - 7. Source code ................................................... 16 - 8. Acknowledgements .............................................. 16 - 9. Author's Address .............................................. 17 - -1. Introduction - - 1.1. Purpose - - The purpose of this specification is to define a lossless - compressed data format that: - * Is independent of CPU type, operating system, file system, - and character set, and hence can be used for interchange; - * Can be produced or consumed, even for an arbitrarily long - sequentially presented input data stream, using only an a - priori bounded amount of intermediate storage, and hence - can be used in data communications or similar structures - such as Unix filters; - * Compresses data with efficiency comparable to the best - currently available general-purpose compression methods, - and in particular considerably better than the "compress" - program; - * Can be implemented readily in a manner not covered by - patents, and hence can be practiced freely; - - - -Deutsch Informational [Page 2] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - * Is compatible with the file format produced by the current - widely used gzip utility, in that conforming decompressors - will be able to read data produced by the existing gzip - compressor. - - The data format defined by this specification does not attempt to: - - * Allow random access to compressed data; - * Compress specialized data (e.g., raster graphics) as well - as the best currently available specialized algorithms. - - A simple counting argument shows that no lossless compression - algorithm can compress every possible input data set. For the - format defined here, the worst case expansion is 5 bytes per 32K- - byte block, i.e., a size increase of 0.015% for large data sets. - English text usually compresses by a factor of 2.5 to 3; - executable files usually compress somewhat less; graphical data - such as raster images may compress much more. - - 1.2. Intended audience - - This specification is intended for use by implementors of software - to compress data into "deflate" format and/or decompress data from - "deflate" format. - - The text of the specification assumes a basic background in - programming at the level of bits and other primitive data - representations. Familiarity with the technique of Huffman coding - is helpful but not required. - - 1.3. Scope - - The specification specifies a method for representing a sequence - of bytes as a (usually shorter) sequence of bits, and a method for - packing the latter bit sequence into bytes. - - 1.4. Compliance - - Unless otherwise indicated below, a compliant decompressor must be - able to accept and decompress any data set that conforms to all - the specifications presented here; a compliant compressor must - produce data sets that conform to all the specifications presented - here. - - 1.5. Definitions of terms and conventions used - - Byte: 8 bits stored or transmitted as a unit (same as an octet). - For this specification, a byte is exactly 8 bits, even on machines - - - -Deutsch Informational [Page 3] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - which store a character on a number of bits different from eight. - See below, for the numbering of bits within a byte. - - String: a sequence of arbitrary bytes. - - 1.6. Changes from previous versions - - There have been no technical changes to the deflate format since - version 1.1 of this specification. In version 1.2, some - terminology was changed. Version 1.3 is a conversion of the - specification to RFC style. - -2. Compressed representation overview - - A compressed data set consists of a series of blocks, corresponding - to successive blocks of input data. The block sizes are arbitrary, - except that non-compressible blocks are limited to 65,535 bytes. - - Each block is compressed using a combination of the LZ77 algorithm - and Huffman coding. The Huffman trees for each block are independent - of those for previous or subsequent blocks; the LZ77 algorithm may - use a reference to a duplicated string occurring in a previous block, - up to 32K input bytes before. - - Each block consists of two parts: a pair of Huffman code trees that - describe the representation of the compressed data part, and a - compressed data part. (The Huffman trees themselves are compressed - using Huffman encoding.) The compressed data consists of a series of - elements of two types: literal bytes (of strings that have not been - detected as duplicated within the previous 32K input bytes), and - pointers to duplicated strings, where a pointer is represented as a - pair . The representation used in the - "deflate" format limits distances to 32K bytes and lengths to 258 - bytes, but does not limit the size of a block, except for - uncompressible blocks, which are limited as noted above. - - Each type of value (literals, distances, and lengths) in the - compressed data is represented using a Huffman code, using one code - tree for literals and lengths and a separate code tree for distances. - The code trees for each block appear in a compact form just before - the compressed data for that block. - - - - - - - - - - -Deutsch Informational [Page 4] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - -3. Detailed specification - - 3.1. Overall conventions In the diagrams below, a box like this: - - +---+ - | | <-- the vertical bars might be missing - +---+ - - represents one byte; a box like this: - - +==============+ - | | - +==============+ - - represents a variable number of bytes. - - Bytes stored within a computer do not have a "bit order", since - they are always treated as a unit. However, a byte considered as - an integer between 0 and 255 does have a most- and least- - significant bit, and since we write numbers with the most- - significant digit on the left, we also write bytes with the most- - significant bit on the left. In the diagrams below, we number the - bits of a byte so that bit 0 is the least-significant bit, i.e., - the bits are numbered: - - +--------+ - |76543210| - +--------+ - - Within a computer, a number may occupy multiple bytes. All - multi-byte numbers in the format described here are stored with - the least-significant byte first (at the lower memory address). - For example, the decimal number 520 is stored as: - - 0 1 - +--------+--------+ - |00001000|00000010| - +--------+--------+ - ^ ^ - | | - | + more significant byte = 2 x 256 - + less significant byte = 8 - - 3.1.1. Packing into bytes - - This document does not address the issue of the order in which - bits of a byte are transmitted on a bit-sequential medium, - since the final data format described here is byte- rather than - - - -Deutsch Informational [Page 5] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - bit-oriented. However, we describe the compressed block format - in below, as a sequence of data elements of various bit - lengths, not a sequence of bytes. We must therefore specify - how to pack these data elements into bytes to form the final - compressed byte sequence: - - * Data elements are packed into bytes in order of - increasing bit number within the byte, i.e., starting - with the least-significant bit of the byte. - * Data elements other than Huffman codes are packed - starting with the least-significant bit of the data - element. - * Huffman codes are packed starting with the most- - significant bit of the code. - - In other words, if one were to print out the compressed data as - a sequence of bytes, starting with the first byte at the - *right* margin and proceeding to the *left*, with the most- - significant bit of each byte on the left as usual, one would be - able to parse the result from right to left, with fixed-width - elements in the correct MSB-to-LSB order and Huffman codes in - bit-reversed order (i.e., with the first bit of the code in the - relative LSB position). - - 3.2. Compressed block format - - 3.2.1. Synopsis of prefix and Huffman coding - - Prefix coding represents symbols from an a priori known - alphabet by bit sequences (codes), one code for each symbol, in - a manner such that different symbols may be represented by bit - sequences of different lengths, but a parser can always parse - an encoded string unambiguously symbol-by-symbol. - - We define a prefix code in terms of a binary tree in which the - two edges descending from each non-leaf node are labeled 0 and - 1 and in which the leaf nodes correspond one-for-one with (are - labeled with) the symbols of the alphabet; then the code for a - symbol is the sequence of 0's and 1's on the edges leading from - the root to the leaf labeled with that symbol. For example: - - - - - - - - - - - -Deutsch Informational [Page 6] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - /\ Symbol Code - 0 1 ------ ---- - / \ A 00 - /\ B B 1 - 0 1 C 011 - / \ D 010 - A /\ - 0 1 - / \ - D C - - A parser can decode the next symbol from an encoded input - stream by walking down the tree from the root, at each step - choosing the edge corresponding to the next input bit. - - Given an alphabet with known symbol frequencies, the Huffman - algorithm allows the construction of an optimal prefix code - (one which represents strings with those symbol frequencies - using the fewest bits of any possible prefix codes for that - alphabet). Such a code is called a Huffman code. (See - reference [1] in Chapter 5, references for additional - information on Huffman codes.) - - Note that in the "deflate" format, the Huffman codes for the - various alphabets must not exceed certain maximum code lengths. - This constraint complicates the algorithm for computing code - lengths from symbol frequencies. Again, see Chapter 5, - references for details. - - 3.2.2. Use of Huffman coding in the "deflate" format - - The Huffman codes used for each alphabet in the "deflate" - format have two additional rules: - - * All codes of a given bit length have lexicographically - consecutive values, in the same order as the symbols - they represent; - - * Shorter codes lexicographically precede longer codes. - - - - - - - - - - - - -Deutsch Informational [Page 7] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - We could recode the example above to follow this rule as - follows, assuming that the order of the alphabet is ABCD: - - Symbol Code - ------ ---- - A 10 - B 0 - C 110 - D 111 - - I.e., 0 precedes 10 which precedes 11x, and 110 and 111 are - lexicographically consecutive. - - Given this rule, we can define the Huffman code for an alphabet - just by giving the bit lengths of the codes for each symbol of - the alphabet in order; this is sufficient to determine the - actual codes. In our example, the code is completely defined - by the sequence of bit lengths (2, 1, 3, 3). The following - algorithm generates the codes as integers, intended to be read - from most- to least-significant bit. The code lengths are - initially in tree[I].Len; the codes are produced in - tree[I].Code. - - 1) Count the number of codes for each code length. Let - bl_count[N] be the number of codes of length N, N >= 1. - - 2) Find the numerical value of the smallest code for each - code length: - - code = 0; - bl_count[0] = 0; - for (bits = 1; bits <= MAX_BITS; bits++) { - code = (code + bl_count[bits-1]) << 1; - next_code[bits] = code; - } - - 3) Assign numerical values to all codes, using consecutive - values for all codes of the same length with the base - values determined at step 2. Codes that are never used - (which have a bit length of zero) must not be assigned a - value. - - for (n = 0; n <= max_code; n++) { - len = tree[n].Len; - if (len != 0) { - tree[n].Code = next_code[len]; - next_code[len]++; - } - - - -Deutsch Informational [Page 8] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - } - - Example: - - Consider the alphabet ABCDEFGH, with bit lengths (3, 3, 3, 3, - 3, 2, 4, 4). After step 1, we have: - - N bl_count[N] - - ----------- - 2 1 - 3 5 - 4 2 - - Step 2 computes the following next_code values: - - N next_code[N] - - ------------ - 1 0 - 2 0 - 3 2 - 4 14 - - Step 3 produces the following code values: - - Symbol Length Code - ------ ------ ---- - A 3 010 - B 3 011 - C 3 100 - D 3 101 - E 3 110 - F 2 00 - G 4 1110 - H 4 1111 - - 3.2.3. Details of block format - - Each block of compressed data begins with 3 header bits - containing the following data: - - first bit BFINAL - next 2 bits BTYPE - - Note that the header bits do not necessarily begin on a byte - boundary, since a block does not necessarily occupy an integral - number of bytes. - - - - - -Deutsch Informational [Page 9] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - BFINAL is set if and only if this is the last block of the data - set. - - BTYPE specifies how the data are compressed, as follows: - - 00 - no compression - 01 - compressed with fixed Huffman codes - 10 - compressed with dynamic Huffman codes - 11 - reserved (error) - - The only difference between the two compressed cases is how the - Huffman codes for the literal/length and distance alphabets are - defined. - - In all cases, the decoding algorithm for the actual data is as - follows: - - do - read block header from input stream. - if stored with no compression - skip any remaining bits in current partially - processed byte - read LEN and NLEN (see next section) - copy LEN bytes of data to output - otherwise - if compressed with dynamic Huffman codes - read representation of code trees (see - subsection below) - loop (until end of block code recognized) - decode literal/length value from input stream - if value < 256 - copy value (literal byte) to output stream - otherwise - if value = end of block (256) - break from loop - otherwise (value = 257..285) - decode distance from input stream - - move backwards distance bytes in the output - stream, and copy length bytes from this - position to the output stream. - end loop - while not last block - - Note that a duplicated string reference may refer to a string - in a previous block; i.e., the backward distance may cross one - or more block boundaries. However a distance cannot refer past - the beginning of the output stream. (An application using a - - - -Deutsch Informational [Page 10] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - preset dictionary might discard part of the output stream; a - distance can refer to that part of the output stream anyway) - Note also that the referenced string may overlap the current - position; for example, if the last 2 bytes decoded have values - X and Y, a string reference with - adds X,Y,X,Y,X to the output stream. - - We now specify each compression method in turn. - - 3.2.4. Non-compressed blocks (BTYPE=00) - - Any bits of input up to the next byte boundary are ignored. - The rest of the block consists of the following information: - - 0 1 2 3 4... - +---+---+---+---+================================+ - | LEN | NLEN |... LEN bytes of literal data...| - +---+---+---+---+================================+ - - LEN is the number of data bytes in the block. NLEN is the - one's complement of LEN. - - 3.2.5. Compressed blocks (length and distance codes) - - As noted above, encoded data blocks in the "deflate" format - consist of sequences of symbols drawn from three conceptually - distinct alphabets: either literal bytes, from the alphabet of - byte values (0..255), or pairs, - where the length is drawn from (3..258) and the distance is - drawn from (1..32,768). In fact, the literal and length - alphabets are merged into a single alphabet (0..285), where - values 0..255 represent literal bytes, the value 256 indicates - end-of-block, and values 257..285 represent length codes - (possibly in conjunction with extra bits following the symbol - code) as follows: - - - - - - - - - - - - - - - - -Deutsch Informational [Page 11] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - Extra Extra Extra - Code Bits Length(s) Code Bits Lengths Code Bits Length(s) - ---- ---- ------ ---- ---- ------- ---- ---- ------- - 257 0 3 267 1 15,16 277 4 67-82 - 258 0 4 268 1 17,18 278 4 83-98 - 259 0 5 269 2 19-22 279 4 99-114 - 260 0 6 270 2 23-26 280 4 115-130 - 261 0 7 271 2 27-30 281 5 131-162 - 262 0 8 272 2 31-34 282 5 163-194 - 263 0 9 273 3 35-42 283 5 195-226 - 264 0 10 274 3 43-50 284 5 227-257 - 265 1 11,12 275 3 51-58 285 0 258 - 266 1 13,14 276 3 59-66 - - The extra bits should be interpreted as a machine integer - stored with the most-significant bit first, e.g., bits 1110 - represent the value 14. - - Extra Extra Extra - Code Bits Dist Code Bits Dist Code Bits Distance - ---- ---- ---- ---- ---- ------ ---- ---- -------- - 0 0 1 10 4 33-48 20 9 1025-1536 - 1 0 2 11 4 49-64 21 9 1537-2048 - 2 0 3 12 5 65-96 22 10 2049-3072 - 3 0 4 13 5 97-128 23 10 3073-4096 - 4 1 5,6 14 6 129-192 24 11 4097-6144 - 5 1 7,8 15 6 193-256 25 11 6145-8192 - 6 2 9-12 16 7 257-384 26 12 8193-12288 - 7 2 13-16 17 7 385-512 27 12 12289-16384 - 8 3 17-24 18 8 513-768 28 13 16385-24576 - 9 3 25-32 19 8 769-1024 29 13 24577-32768 - - 3.2.6. Compression with fixed Huffman codes (BTYPE=01) - - The Huffman codes for the two alphabets are fixed, and are not - represented explicitly in the data. The Huffman code lengths - for the literal/length alphabet are: - - Lit Value Bits Codes - --------- ---- ----- - 0 - 143 8 00110000 through - 10111111 - 144 - 255 9 110010000 through - 111111111 - 256 - 279 7 0000000 through - 0010111 - 280 - 287 8 11000000 through - 11000111 - - - -Deutsch Informational [Page 12] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - The code lengths are sufficient to generate the actual codes, - as described above; we show the codes in the table for added - clarity. Literal/length values 286-287 will never actually - occur in the compressed data, but participate in the code - construction. - - Distance codes 0-31 are represented by (fixed-length) 5-bit - codes, with possible additional bits as shown in the table - shown in Paragraph 3.2.5, above. Note that distance codes 30- - 31 will never actually occur in the compressed data. - - 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) - - The Huffman codes for the two alphabets appear in the block - immediately after the header bits and before the actual - compressed data, first the literal/length code and then the - distance code. Each code is defined by a sequence of code - lengths, as discussed in Paragraph 3.2.2, above. For even - greater compactness, the code length sequences themselves are - compressed using a Huffman code. The alphabet for code lengths - is as follows: - - 0 - 15: Represent code lengths of 0 - 15 - 16: Copy the previous code length 3 - 6 times. - The next 2 bits indicate repeat length - (0 = 3, ... , 3 = 6) - Example: Codes 8, 16 (+2 bits 11), - 16 (+2 bits 10) will expand to - 12 code lengths of 8 (1 + 6 + 5) - 17: Repeat a code length of 0 for 3 - 10 times. - (3 bits of length) - 18: Repeat a code length of 0 for 11 - 138 times - (7 bits of length) - - A code length of 0 indicates that the corresponding symbol in - the literal/length or distance alphabet will not occur in the - block, and should not participate in the Huffman code - construction algorithm given earlier. If only one distance - code is used, it is encoded using one bit, not zero bits; in - this case there is a single code length of one, with one unused - code. One distance code of zero bits means that there are no - distance codes used at all (the data is all literals). - - We can now define the format of the block: - - 5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286) - 5 Bits: HDIST, # of Distance codes - 1 (1 - 32) - 4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19) - - - -Deutsch Informational [Page 13] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - (HCLEN + 4) x 3 bits: code lengths for the code length - alphabet given just above, in the order: 16, 17, 18, - 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 - - These code lengths are interpreted as 3-bit integers - (0-7); as above, a code length of 0 means the - corresponding symbol (literal/length or distance code - length) is not used. - - HLIT + 257 code lengths for the literal/length alphabet, - encoded using the code length Huffman code - - HDIST + 1 code lengths for the distance alphabet, - encoded using the code length Huffman code - - The actual compressed data of the block, - encoded using the literal/length and distance Huffman - codes - - The literal/length symbol 256 (end of data), - encoded using the literal/length Huffman code - - The code length repeat codes can cross from HLIT + 257 to the - HDIST + 1 code lengths. In other words, all code lengths form - a single sequence of HLIT + HDIST + 258 values. - - 3.3. Compliance - - A compressor may limit further the ranges of values specified in - the previous section and still be compliant; for example, it may - limit the range of backward pointers to some value smaller than - 32K. Similarly, a compressor may limit the size of blocks so that - a compressible block fits in memory. - - A compliant decompressor must accept the full range of possible - values defined in the previous section, and must accept blocks of - arbitrary size. - -4. Compression algorithm details - - While it is the intent of this document to define the "deflate" - compressed data format without reference to any particular - compression algorithm, the format is related to the compressed - formats produced by LZ77 (Lempel-Ziv 1977, see reference [2] below); - since many variations of LZ77 are patented, it is strongly - recommended that the implementor of a compressor follow the general - algorithm presented here, which is known not to be patented per se. - The material in this section is not part of the definition of the - - - -Deutsch Informational [Page 14] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - specification per se, and a compressor need not follow it in order to - be compliant. - - The compressor terminates a block when it determines that starting a - new block with fresh trees would be useful, or when the block size - fills up the compressor's block buffer. - - The compressor uses a chained hash table to find duplicated strings, - using a hash function that operates on 3-byte sequences. At any - given point during compression, let XYZ be the next 3 input bytes to - be examined (not necessarily all different, of course). First, the - compressor examines the hash chain for XYZ. If the chain is empty, - the compressor simply writes out X as a literal byte and advances one - byte in the input. If the hash chain is not empty, indicating that - the sequence XYZ (or, if we are unlucky, some other 3 bytes with the - same hash function value) has occurred recently, the compressor - compares all strings on the XYZ hash chain with the actual input data - sequence starting at the current point, and selects the longest - match. - - The compressor searches the hash chains starting with the most recent - strings, to favor small distances and thus take advantage of the - Huffman encoding. The hash chains are singly linked. There are no - deletions from the hash chains; the algorithm simply discards matches - that are too old. To avoid a worst-case situation, very long hash - chains are arbitrarily truncated at a certain length, determined by a - run-time parameter. - - To improve overall compression, the compressor optionally defers the - selection of matches ("lazy matching"): after a match of length N has - been found, the compressor searches for a longer match starting at - the next input byte. If it finds a longer match, it truncates the - previous match to a length of one (thus producing a single literal - byte) and then emits the longer match. Otherwise, it emits the - original match, and, as described above, advances N bytes before - continuing. - - Run-time parameters also control this "lazy match" procedure. If - compression ratio is most important, the compressor attempts a - complete second search regardless of the length of the first match. - In the normal case, if the current match is "long enough", the - compressor reduces the search for a longer match, thus speeding up - the process. If speed is most important, the compressor inserts new - strings in the hash table only when no match was found, or when the - match is not "too long". This degrades the compression ratio but - saves time since there are both fewer insertions and fewer searches. - - - - - -Deutsch Informational [Page 15] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - -5. References - - [1] Huffman, D. A., "A Method for the Construction of Minimum - Redundancy Codes", Proceedings of the Institute of Radio - Engineers, September 1952, Volume 40, Number 9, pp. 1098-1101. - - [2] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data - Compression", IEEE Transactions on Information Theory, Vol. 23, - No. 3, pp. 337-343. - - [3] Gailly, J.-L., and Adler, M., ZLIB documentation and sources, - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ - - [4] Gailly, J.-L., and Adler, M., GZIP documentation and sources, - available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/ - - [5] Schwartz, E. S., and Kallick, B. "Generating a canonical prefix - encoding." Comm. ACM, 7,3 (Mar. 1964), pp. 166-169. - - [6] Hirschberg and Lelewer, "Efficient decoding of prefix codes," - Comm. ACM, 33,4, April 1990, pp. 449-459. - -6. Security Considerations - - Any data compression method involves the reduction of redundancy in - the data. Consequently, any corruption of the data is likely to have - severe effects and be difficult to correct. Uncompressed text, on - the other hand, will probably still be readable despite the presence - of some corrupted bytes. - - It is recommended that systems using this data format provide some - means of validating the integrity of the compressed data. See - reference [3], for example. - -7. Source code - - Source code for a C language implementation of a "deflate" compliant - compressor and decompressor is available within the zlib package at - ftp://ftp.uu.net/pub/archiving/zip/zlib/. - -8. Acknowledgements - - Trademarks cited in this document are the property of their - respective owners. - - Phil Katz designed the deflate format. Jean-Loup Gailly and Mark - Adler wrote the related software described in this specification. - Glenn Randers-Pehrson converted this document to RFC and HTML format. - - - -Deutsch Informational [Page 16] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - -9. Author's Address - - L. Peter Deutsch - Aladdin Enterprises - 203 Santa Margarita Ave. - Menlo Park, CA 94025 - - Phone: (415) 322-0103 (AM only) - FAX: (415) 322-1734 - EMail: - - Questions about the technical content of this specification can be - sent by email to: - - Jean-Loup Gailly and - Mark Adler - - Editorial comments on this specification can be sent by email to: - - L. Peter Deutsch and - Glenn Randers-Pehrson - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Deutsch Informational [Page 17] - diff --git a/deps/zlib/doc/rfc1952.txt b/deps/zlib/doc/rfc1952.txt deleted file mode 100644 index a8e51b4567fd49..00000000000000 --- a/deps/zlib/doc/rfc1952.txt +++ /dev/null @@ -1,675 +0,0 @@ - - - - - - -Network Working Group P. Deutsch -Request for Comments: 1952 Aladdin Enterprises -Category: Informational May 1996 - - - GZIP file format specification version 4.3 - -Status of This Memo - - This memo provides information for the Internet community. This memo - does not specify an Internet standard of any kind. Distribution of - this memo is unlimited. - -IESG Note: - - The IESG takes no position on the validity of any Intellectual - Property Rights statements contained in this document. - -Notices - - Copyright (c) 1996 L. Peter Deutsch - - Permission is granted to copy and distribute this document for any - purpose and without charge, including translations into other - languages and incorporation into compilations, provided that the - copyright notice and this notice are preserved, and that any - substantive changes or deletions from the original are clearly - marked. - - A pointer to the latest version of this and related documentation in - HTML format can be found at the URL - . - -Abstract - - This specification defines a lossless compressed data format that is - compatible with the widely used GZIP utility. The format includes a - cyclic redundancy check value for detecting data corruption. The - format presently uses the DEFLATE method of compression but can be - easily extended to use other compression methods. The format can be - implemented readily in a manner not covered by patents. - - - - - - - - - - -Deutsch Informational [Page 1] - -RFC 1952 GZIP File Format Specification May 1996 - - -Table of Contents - - 1. Introduction ................................................... 2 - 1.1. Purpose ................................................... 2 - 1.2. Intended audience ......................................... 3 - 1.3. Scope ..................................................... 3 - 1.4. Compliance ................................................ 3 - 1.5. Definitions of terms and conventions used ................. 3 - 1.6. Changes from previous versions ............................ 3 - 2. Detailed specification ......................................... 4 - 2.1. Overall conventions ....................................... 4 - 2.2. File format ............................................... 5 - 2.3. Member format ............................................. 5 - 2.3.1. Member header and trailer ........................... 6 - 2.3.1.1. Extra field ................................... 8 - 2.3.1.2. Compliance .................................... 9 - 3. References .................................................. 9 - 4. Security Considerations .................................... 10 - 5. Acknowledgements ........................................... 10 - 6. Author's Address ........................................... 10 - 7. Appendix: Jean-Loup Gailly's gzip utility .................. 11 - 8. Appendix: Sample CRC Code .................................. 11 - -1. Introduction - - 1.1. Purpose - - The purpose of this specification is to define a lossless - compressed data format that: - - * Is independent of CPU type, operating system, file system, - and character set, and hence can be used for interchange; - * Can compress or decompress a data stream (as opposed to a - randomly accessible file) to produce another data stream, - using only an a priori bounded amount of intermediate - storage, and hence can be used in data communications or - similar structures such as Unix filters; - * Compresses data with efficiency comparable to the best - currently available general-purpose compression methods, - and in particular considerably better than the "compress" - program; - * Can be implemented readily in a manner not covered by - patents, and hence can be practiced freely; - * Is compatible with the file format produced by the current - widely used gzip utility, in that conforming decompressors - will be able to read data produced by the existing gzip - compressor. - - - - -Deutsch Informational [Page 2] - -RFC 1952 GZIP File Format Specification May 1996 - - - The data format defined by this specification does not attempt to: - - * Provide random access to compressed data; - * Compress specialized data (e.g., raster graphics) as well as - the best currently available specialized algorithms. - - 1.2. Intended audience - - This specification is intended for use by implementors of software - to compress data into gzip format and/or decompress data from gzip - format. - - The text of the specification assumes a basic background in - programming at the level of bits and other primitive data - representations. - - 1.3. Scope - - The specification specifies a compression method and a file format - (the latter assuming only that a file can store a sequence of - arbitrary bytes). It does not specify any particular interface to - a file system or anything about character sets or encodings - (except for file names and comments, which are optional). - - 1.4. Compliance - - Unless otherwise indicated below, a compliant decompressor must be - able to accept and decompress any file that conforms to all the - specifications presented here; a compliant compressor must produce - files that conform to all the specifications presented here. The - material in the appendices is not part of the specification per se - and is not relevant to compliance. - - 1.5. Definitions of terms and conventions used - - byte: 8 bits stored or transmitted as a unit (same as an octet). - (For this specification, a byte is exactly 8 bits, even on - machines which store a character on a number of bits different - from 8.) See below for the numbering of bits within a byte. - - 1.6. Changes from previous versions - - There have been no technical changes to the gzip format since - version 4.1 of this specification. In version 4.2, some - terminology was changed, and the sample CRC code was rewritten for - clarity and to eliminate the requirement for the caller to do pre- - and post-conditioning. Version 4.3 is a conversion of the - specification to RFC style. - - - -Deutsch Informational [Page 3] - -RFC 1952 GZIP File Format Specification May 1996 - - -2. Detailed specification - - 2.1. Overall conventions - - In the diagrams below, a box like this: - - +---+ - | | <-- the vertical bars might be missing - +---+ - - represents one byte; a box like this: - - +==============+ - | | - +==============+ - - represents a variable number of bytes. - - Bytes stored within a computer do not have a "bit order", since - they are always treated as a unit. However, a byte considered as - an integer between 0 and 255 does have a most- and least- - significant bit, and since we write numbers with the most- - significant digit on the left, we also write bytes with the most- - significant bit on the left. In the diagrams below, we number the - bits of a byte so that bit 0 is the least-significant bit, i.e., - the bits are numbered: - - +--------+ - |76543210| - +--------+ - - This document does not address the issue of the order in which - bits of a byte are transmitted on a bit-sequential medium, since - the data format described here is byte- rather than bit-oriented. - - Within a computer, a number may occupy multiple bytes. All - multi-byte numbers in the format described here are stored with - the least-significant byte first (at the lower memory address). - For example, the decimal number 520 is stored as: - - 0 1 - +--------+--------+ - |00001000|00000010| - +--------+--------+ - ^ ^ - | | - | + more significant byte = 2 x 256 - + less significant byte = 8 - - - -Deutsch Informational [Page 4] - -RFC 1952 GZIP File Format Specification May 1996 - - - 2.2. File format - - A gzip file consists of a series of "members" (compressed data - sets). The format of each member is specified in the following - section. The members simply appear one after another in the file, - with no additional information before, between, or after them. - - 2.3. Member format - - Each member has the following structure: - - +---+---+---+---+---+---+---+---+---+---+ - |ID1|ID2|CM |FLG| MTIME |XFL|OS | (more-->) - +---+---+---+---+---+---+---+---+---+---+ - - (if FLG.FEXTRA set) - - +---+---+=================================+ - | XLEN |...XLEN bytes of "extra field"...| (more-->) - +---+---+=================================+ - - (if FLG.FNAME set) - - +=========================================+ - |...original file name, zero-terminated...| (more-->) - +=========================================+ - - (if FLG.FCOMMENT set) - - +===================================+ - |...file comment, zero-terminated...| (more-->) - +===================================+ - - (if FLG.FHCRC set) - - +---+---+ - | CRC16 | - +---+---+ - - +=======================+ - |...compressed blocks...| (more-->) - +=======================+ - - 0 1 2 3 4 5 6 7 - +---+---+---+---+---+---+---+---+ - | CRC32 | ISIZE | - +---+---+---+---+---+---+---+---+ - - - - -Deutsch Informational [Page 5] - -RFC 1952 GZIP File Format Specification May 1996 - - - 2.3.1. Member header and trailer - - ID1 (IDentification 1) - ID2 (IDentification 2) - These have the fixed values ID1 = 31 (0x1f, \037), ID2 = 139 - (0x8b, \213), to identify the file as being in gzip format. - - CM (Compression Method) - This identifies the compression method used in the file. CM - = 0-7 are reserved. CM = 8 denotes the "deflate" - compression method, which is the one customarily used by - gzip and which is documented elsewhere. - - FLG (FLaGs) - This flag byte is divided into individual bits as follows: - - bit 0 FTEXT - bit 1 FHCRC - bit 2 FEXTRA - bit 3 FNAME - bit 4 FCOMMENT - bit 5 reserved - bit 6 reserved - bit 7 reserved - - If FTEXT is set, the file is probably ASCII text. This is - an optional indication, which the compressor may set by - checking a small amount of the input data to see whether any - non-ASCII characters are present. In case of doubt, FTEXT - is cleared, indicating binary data. For systems which have - different file formats for ascii text and binary data, the - decompressor can use FTEXT to choose the appropriate format. - We deliberately do not specify the algorithm used to set - this bit, since a compressor always has the option of - leaving it cleared and a decompressor always has the option - of ignoring it and letting some other program handle issues - of data conversion. - - If FHCRC is set, a CRC16 for the gzip header is present, - immediately before the compressed data. The CRC16 consists - of the two least significant bytes of the CRC32 for all - bytes of the gzip header up to and not including the CRC16. - [The FHCRC bit was never set by versions of gzip up to - 1.2.4, even though it was documented with a different - meaning in gzip 1.2.4.] - - If FEXTRA is set, optional extra fields are present, as - described in a following section. - - - -Deutsch Informational [Page 6] - -RFC 1952 GZIP File Format Specification May 1996 - - - If FNAME is set, an original file name is present, - terminated by a zero byte. The name must consist of ISO - 8859-1 (LATIN-1) characters; on operating systems using - EBCDIC or any other character set for file names, the name - must be translated to the ISO LATIN-1 character set. This - is the original name of the file being compressed, with any - directory components removed, and, if the file being - compressed is on a file system with case insensitive names, - forced to lower case. There is no original file name if the - data was compressed from a source other than a named file; - for example, if the source was stdin on a Unix system, there - is no file name. - - If FCOMMENT is set, a zero-terminated file comment is - present. This comment is not interpreted; it is only - intended for human consumption. The comment must consist of - ISO 8859-1 (LATIN-1) characters. Line breaks should be - denoted by a single line feed character (10 decimal). - - Reserved FLG bits must be zero. - - MTIME (Modification TIME) - This gives the most recent modification time of the original - file being compressed. The time is in Unix format, i.e., - seconds since 00:00:00 GMT, Jan. 1, 1970. (Note that this - may cause problems for MS-DOS and other systems that use - local rather than Universal time.) If the compressed data - did not come from a file, MTIME is set to the time at which - compression started. MTIME = 0 means no time stamp is - available. - - XFL (eXtra FLags) - These flags are available for use by specific compression - methods. The "deflate" method (CM = 8) sets these flags as - follows: - - XFL = 2 - compressor used maximum compression, - slowest algorithm - XFL = 4 - compressor used fastest algorithm - - OS (Operating System) - This identifies the type of file system on which compression - took place. This may be useful in determining end-of-line - convention for text files. The currently defined values are - as follows: - - - - - - -Deutsch Informational [Page 7] - -RFC 1952 GZIP File Format Specification May 1996 - - - 0 - FAT filesystem (MS-DOS, OS/2, NT/Win32) - 1 - Amiga - 2 - VMS (or OpenVMS) - 3 - Unix - 4 - VM/CMS - 5 - Atari TOS - 6 - HPFS filesystem (OS/2, NT) - 7 - Macintosh - 8 - Z-System - 9 - CP/M - 10 - TOPS-20 - 11 - NTFS filesystem (NT) - 12 - QDOS - 13 - Acorn RISCOS - 255 - unknown - - XLEN (eXtra LENgth) - If FLG.FEXTRA is set, this gives the length of the optional - extra field. See below for details. - - CRC32 (CRC-32) - This contains a Cyclic Redundancy Check value of the - uncompressed data computed according to CRC-32 algorithm - used in the ISO 3309 standard and in section 8.1.1.6.2 of - ITU-T recommendation V.42. (See http://www.iso.ch for - ordering ISO documents. See gopher://info.itu.ch for an - online version of ITU-T V.42.) - - ISIZE (Input SIZE) - This contains the size of the original (uncompressed) input - data modulo 2^32. - - 2.3.1.1. Extra field - - If the FLG.FEXTRA bit is set, an "extra field" is present in - the header, with total length XLEN bytes. It consists of a - series of subfields, each of the form: - - +---+---+---+---+==================================+ - |SI1|SI2| LEN |... LEN bytes of subfield data ...| - +---+---+---+---+==================================+ - - SI1 and SI2 provide a subfield ID, typically two ASCII letters - with some mnemonic value. Jean-Loup Gailly - is maintaining a registry of subfield - IDs; please send him any subfield ID you wish to use. Subfield - IDs with SI2 = 0 are reserved for future use. The following - IDs are currently defined: - - - -Deutsch Informational [Page 8] - -RFC 1952 GZIP File Format Specification May 1996 - - - SI1 SI2 Data - ---------- ---------- ---- - 0x41 ('A') 0x70 ('P') Apollo file type information - - LEN gives the length of the subfield data, excluding the 4 - initial bytes. - - 2.3.1.2. Compliance - - A compliant compressor must produce files with correct ID1, - ID2, CM, CRC32, and ISIZE, but may set all the other fields in - the fixed-length part of the header to default values (255 for - OS, 0 for all others). The compressor must set all reserved - bits to zero. - - A compliant decompressor must check ID1, ID2, and CM, and - provide an error indication if any of these have incorrect - values. It must examine FEXTRA/XLEN, FNAME, FCOMMENT and FHCRC - at least so it can skip over the optional fields if they are - present. It need not examine any other part of the header or - trailer; in particular, a decompressor may ignore FTEXT and OS - and always produce binary output, and still be compliant. A - compliant decompressor must give an error indication if any - reserved bit is non-zero, since such a bit could indicate the - presence of a new field that would cause subsequent data to be - interpreted incorrectly. - -3. References - - [1] "Information Processing - 8-bit single-byte coded graphic - character sets - Part 1: Latin alphabet No.1" (ISO 8859-1:1987). - The ISO 8859-1 (Latin-1) character set is a superset of 7-bit - ASCII. Files defining this character set are available as - iso_8859-1.* in ftp://ftp.uu.net/graphics/png/documents/ - - [2] ISO 3309 - - [3] ITU-T recommendation V.42 - - [4] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ - - [5] Gailly, J.-L., GZIP documentation, available as gzip-*.tar in - ftp://prep.ai.mit.edu/pub/gnu/ - - [6] Sarwate, D.V., "Computation of Cyclic Redundancy Checks via Table - Look-Up", Communications of the ACM, 31(8), pp.1008-1013. - - - - -Deutsch Informational [Page 9] - -RFC 1952 GZIP File Format Specification May 1996 - - - [7] Schwaderer, W.D., "CRC Calculation", April 85 PC Tech Journal, - pp.118-133. - - [8] ftp://ftp.adelaide.edu.au/pub/rocksoft/papers/crc_v3.txt, - describing the CRC concept. - -4. Security Considerations - - Any data compression method involves the reduction of redundancy in - the data. Consequently, any corruption of the data is likely to have - severe effects and be difficult to correct. Uncompressed text, on - the other hand, will probably still be readable despite the presence - of some corrupted bytes. - - It is recommended that systems using this data format provide some - means of validating the integrity of the compressed data, such as by - setting and checking the CRC-32 check value. - -5. Acknowledgements - - Trademarks cited in this document are the property of their - respective owners. - - Jean-Loup Gailly designed the gzip format and wrote, with Mark Adler, - the related software described in this specification. Glenn - Randers-Pehrson converted this document to RFC and HTML format. - -6. Author's Address - - L. Peter Deutsch - Aladdin Enterprises - 203 Santa Margarita Ave. - Menlo Park, CA 94025 - - Phone: (415) 322-0103 (AM only) - FAX: (415) 322-1734 - EMail: - - Questions about the technical content of this specification can be - sent by email to: - - Jean-Loup Gailly and - Mark Adler - - Editorial comments on this specification can be sent by email to: - - L. Peter Deutsch and - Glenn Randers-Pehrson - - - -Deutsch Informational [Page 10] - -RFC 1952 GZIP File Format Specification May 1996 - - -7. Appendix: Jean-Loup Gailly's gzip utility - - The most widely used implementation of gzip compression, and the - original documentation on which this specification is based, were - created by Jean-Loup Gailly . Since this - implementation is a de facto standard, we mention some more of its - features here. Again, the material in this section is not part of - the specification per se, and implementations need not follow it to - be compliant. - - When compressing or decompressing a file, gzip preserves the - protection, ownership, and modification time attributes on the local - file system, since there is no provision for representing protection - attributes in the gzip file format itself. Since the file format - includes a modification time, the gzip decompressor provides a - command line switch that assigns the modification time from the file, - rather than the local modification time of the compressed input, to - the decompressed output. - -8. Appendix: Sample CRC Code - - The following sample code represents a practical implementation of - the CRC (Cyclic Redundancy Check). (See also ISO 3309 and ITU-T V.42 - for a formal specification.) - - The sample code is in the ANSI C programming language. Non C users - may find it easier to read with these hints: - - & Bitwise AND operator. - ^ Bitwise exclusive-OR operator. - >> Bitwise right shift operator. When applied to an - unsigned quantity, as here, right shift inserts zero - bit(s) at the left. - ! Logical NOT operator. - ++ "n++" increments the variable n. - 0xNNN 0x introduces a hexadecimal (base 16) constant. - Suffix L indicates a long value (at least 32 bits). - - /* Table of CRCs of all 8-bit messages. */ - unsigned long crc_table[256]; - - /* Flag: has the table been computed? Initially false. */ - int crc_table_computed = 0; - - /* Make the table for a fast CRC. */ - void make_crc_table(void) - { - unsigned long c; - - - -Deutsch Informational [Page 11] - -RFC 1952 GZIP File Format Specification May 1996 - - - int n, k; - for (n = 0; n < 256; n++) { - c = (unsigned long) n; - for (k = 0; k < 8; k++) { - if (c & 1) { - c = 0xedb88320L ^ (c >> 1); - } else { - c = c >> 1; - } - } - crc_table[n] = c; - } - crc_table_computed = 1; - } - - /* - Update a running crc with the bytes buf[0..len-1] and return - the updated crc. The crc should be initialized to zero. Pre- and - post-conditioning (one's complement) is performed within this - function so it shouldn't be done by the caller. Usage example: - - unsigned long crc = 0L; - - while (read_buffer(buffer, length) != EOF) { - crc = update_crc(crc, buffer, length); - } - if (crc != original_crc) error(); - */ - unsigned long update_crc(unsigned long crc, - unsigned char *buf, int len) - { - unsigned long c = crc ^ 0xffffffffL; - int n; - - if (!crc_table_computed) - make_crc_table(); - for (n = 0; n < len; n++) { - c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); - } - return c ^ 0xffffffffL; - } - - /* Return the CRC of the bytes buf[0..len-1]. */ - unsigned long crc(unsigned char *buf, int len) - { - return update_crc(0L, buf, len); - } - - - - -Deutsch Informational [Page 12] - diff --git a/deps/zlib/doc/txtvsbin.txt b/deps/zlib/doc/txtvsbin.txt deleted file mode 100644 index 3d0f0634f72e64..00000000000000 --- a/deps/zlib/doc/txtvsbin.txt +++ /dev/null @@ -1,107 +0,0 @@ -A Fast Method for Identifying Plain Text Files -============================================== - - -Introduction ------------- - -Given a file coming from an unknown source, it is sometimes desirable -to find out whether the format of that file is plain text. Although -this may appear like a simple task, a fully accurate detection of the -file type requires heavy-duty semantic analysis on the file contents. -It is, however, possible to obtain satisfactory results by employing -various heuristics. - -Previous versions of PKZip and other zip-compatible compression tools -were using a crude detection scheme: if more than 80% (4/5) of the bytes -found in a certain buffer are within the range [7..127], the file is -labeled as plain text, otherwise it is labeled as binary. A prominent -limitation of this scheme is the restriction to Latin-based alphabets. -Other alphabets, like Greek, Cyrillic or Asian, make extensive use of -the bytes within the range [128..255], and texts using these alphabets -are most often misidentified by this scheme; in other words, the rate -of false negatives is sometimes too high, which means that the recall -is low. Another weakness of this scheme is a reduced precision, due to -the false positives that may occur when binary files containing large -amounts of textual characters are misidentified as plain text. - -In this article we propose a new, simple detection scheme that features -a much increased precision and a near-100% recall. This scheme is -designed to work on ASCII, Unicode and other ASCII-derived alphabets, -and it handles single-byte encodings (ISO-8859, MacRoman, KOI8, etc.) -and variable-sized encodings (ISO-2022, UTF-8, etc.). Wider encodings -(UCS-2/UTF-16 and UCS-4/UTF-32) are not handled, however. - - -The Algorithm -------------- - -The algorithm works by dividing the set of bytecodes [0..255] into three -categories: -- The white list of textual bytecodes: - 9 (TAB), 10 (LF), 13 (CR), 32 (SPACE) to 255. -- The gray list of tolerated bytecodes: - 7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), 27 (ESC). -- The black list of undesired, non-textual bytecodes: - 0 (NUL) to 6, 14 to 31. - -If a file contains at least one byte that belongs to the white list and -no byte that belongs to the black list, then the file is categorized as -plain text; otherwise, it is categorized as binary. (The boundary case, -when the file is empty, automatically falls into the latter category.) - - -Rationale ---------- - -The idea behind this algorithm relies on two observations. - -The first observation is that, although the full range of 7-bit codes -[0..127] is properly specified by the ASCII standard, most control -characters in the range [0..31] are not used in practice. The only -widely-used, almost universally-portable control codes are 9 (TAB), -10 (LF) and 13 (CR). There are a few more control codes that are -recognized on a reduced range of platforms and text viewers/editors: -7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB) and 27 (ESC); but these -codes are rarely (if ever) used alone, without being accompanied by -some printable text. Even the newer, portable text formats such as -XML avoid using control characters outside the list mentioned here. - -The second observation is that most of the binary files tend to contain -control characters, especially 0 (NUL). Even though the older text -detection schemes observe the presence of non-ASCII codes from the range -[128..255], the precision rarely has to suffer if this upper range is -labeled as textual, because the files that are genuinely binary tend to -contain both control characters and codes from the upper range. On the -other hand, the upper range needs to be labeled as textual, because it -is used by virtually all ASCII extensions. In particular, this range is -used for encoding non-Latin scripts. - -Since there is no counting involved, other than simply observing the -presence or the absence of some byte values, the algorithm produces -consistent results, regardless what alphabet encoding is being used. -(If counting were involved, it could be possible to obtain different -results on a text encoded, say, using ISO-8859-16 versus UTF-8.) - -There is an extra category of plain text files that are "polluted" with -one or more black-listed codes, either by mistake or by peculiar design -considerations. In such cases, a scheme that tolerates a small fraction -of black-listed codes would provide an increased recall (i.e. more true -positives). This, however, incurs a reduced precision overall, since -false positives are more likely to appear in binary files that contain -large chunks of textual data. Furthermore, "polluted" plain text should -be regarded as binary by general-purpose text detection schemes, because -general-purpose text processing algorithms might not be applicable. -Under this premise, it is safe to say that our detection method provides -a near-100% recall. - -Experiments have been run on many files coming from various platforms -and applications. We tried plain text files, system logs, source code, -formatted office documents, compiled object code, etc. The results -confirm the optimistic assumptions about the capabilities of this -algorithm. - - --- -Cosmin Truta -Last updated: 2006-May-28 diff --git a/deps/zlib/examples/README.examples b/deps/zlib/examples/README.examples deleted file mode 100644 index 56a31714e566aa..00000000000000 --- a/deps/zlib/examples/README.examples +++ /dev/null @@ -1,49 +0,0 @@ -This directory contains examples of the use of zlib and other relevant -programs and documentation. - -enough.c - calculation and justification of ENOUGH parameter in inftrees.h - - calculates the maximum table space used in inflate tree - construction over all possible Huffman codes - -fitblk.c - compress just enough input to nearly fill a requested output size - - zlib isn't designed to do this, but fitblk does it anyway - -gun.c - uncompress a gzip file - - illustrates the use of inflateBack() for high speed file-to-file - decompression using call-back functions - - is approximately twice as fast as gzip -d - - also provides Unix uncompress functionality, again twice as fast - -gzappend.c - append to a gzip file - - illustrates the use of the Z_BLOCK flush parameter for inflate() - - illustrates the use of deflatePrime() to start at any bit - -gzjoin.c - join gzip files without recalculating the crc or recompressing - - illustrates the use of the Z_BLOCK flush parameter for inflate() - - illustrates the use of crc32_combine() - -gzlog.c -gzlog.h - efficiently and robustly maintain a message log file in gzip format - - illustrates use of raw deflate, Z_PARTIAL_FLUSH, deflatePrime(), - and deflateSetDictionary() - - illustrates use of a gzip header extra field - -zlib_how.html - painfully comprehensive description of zpipe.c (see below) - - describes in excruciating detail the use of deflate() and inflate() - -zpipe.c - reads and writes zlib streams from stdin to stdout - - illustrates the proper use of deflate() and inflate() - - deeply commented in zlib_how.html (see above) - -zran.c - index a zlib or gzip stream and randomly access it - - illustrates the use of Z_BLOCK, inflatePrime(), and - inflateSetDictionary() to provide random access diff --git a/deps/zlib/examples/enough.c b/deps/zlib/examples/enough.c deleted file mode 100644 index b991144305253c..00000000000000 --- a/deps/zlib/examples/enough.c +++ /dev/null @@ -1,572 +0,0 @@ -/* enough.c -- determine the maximum size of inflate's Huffman code tables over - * all possible valid and complete Huffman codes, subject to a length limit. - * Copyright (C) 2007, 2008, 2012 Mark Adler - * Version 1.4 18 August 2012 Mark Adler - */ - -/* Version history: - 1.0 3 Jan 2007 First version (derived from codecount.c version 1.4) - 1.1 4 Jan 2007 Use faster incremental table usage computation - Prune examine() search on previously visited states - 1.2 5 Jan 2007 Comments clean up - As inflate does, decrease root for short codes - Refuse cases where inflate would increase root - 1.3 17 Feb 2008 Add argument for initial root table size - Fix bug for initial root table size == max - 1 - Use a macro to compute the history index - 1.4 18 Aug 2012 Avoid shifts more than bits in type (caused endless loop!) - Clean up comparisons of different types - Clean up code indentation - */ - -/* - Examine all possible Huffman codes for a given number of symbols and a - maximum code length in bits to determine the maximum table size for zilb's - inflate. Only complete Huffman codes are counted. - - Two codes are considered distinct if the vectors of the number of codes per - length are not identical. So permutations of the symbol assignments result - in the same code for the counting, as do permutations of the assignments of - the bit values to the codes (i.e. only canonical codes are counted). - - We build a code from shorter to longer lengths, determining how many symbols - are coded at each length. At each step, we have how many symbols remain to - be coded, what the last code length used was, and how many bit patterns of - that length remain unused. Then we add one to the code length and double the - number of unused patterns to graduate to the next code length. We then - assign all portions of the remaining symbols to that code length that - preserve the properties of a correct and eventually complete code. Those - properties are: we cannot use more bit patterns than are available; and when - all the symbols are used, there are exactly zero possible bit patterns - remaining. - - The inflate Huffman decoding algorithm uses two-level lookup tables for - speed. There is a single first-level table to decode codes up to root bits - in length (root == 9 in the current inflate implementation). The table - has 1 << root entries and is indexed by the next root bits of input. Codes - shorter than root bits have replicated table entries, so that the correct - entry is pointed to regardless of the bits that follow the short code. If - the code is longer than root bits, then the table entry points to a second- - level table. The size of that table is determined by the longest code with - that root-bit prefix. If that longest code has length len, then the table - has size 1 << (len - root), to index the remaining bits in that set of - codes. Each subsequent root-bit prefix then has its own sub-table. The - total number of table entries required by the code is calculated - incrementally as the number of codes at each bit length is populated. When - all of the codes are shorter than root bits, then root is reduced to the - longest code length, resulting in a single, smaller, one-level table. - - The inflate algorithm also provides for small values of root (relative to - the log2 of the number of symbols), where the shortest code has more bits - than root. In that case, root is increased to the length of the shortest - code. This program, by design, does not handle that case, so it is verified - that the number of symbols is less than 2^(root + 1). - - In order to speed up the examination (by about ten orders of magnitude for - the default arguments), the intermediate states in the build-up of a code - are remembered and previously visited branches are pruned. The memory - required for this will increase rapidly with the total number of symbols and - the maximum code length in bits. However this is a very small price to pay - for the vast speedup. - - First, all of the possible Huffman codes are counted, and reachable - intermediate states are noted by a non-zero count in a saved-results array. - Second, the intermediate states that lead to (root + 1) bit or longer codes - are used to look at all sub-codes from those junctures for their inflate - memory usage. (The amount of memory used is not affected by the number of - codes of root bits or less in length.) Third, the visited states in the - construction of those sub-codes and the associated calculation of the table - size is recalled in order to avoid recalculating from the same juncture. - Beginning the code examination at (root + 1) bit codes, which is enabled by - identifying the reachable nodes, accounts for about six of the orders of - magnitude of improvement for the default arguments. About another four - orders of magnitude come from not revisiting previous states. Out of - approximately 2x10^16 possible Huffman codes, only about 2x10^6 sub-codes - need to be examined to cover all of the possible table memory usage cases - for the default arguments of 286 symbols limited to 15-bit codes. - - Note that an unsigned long long type is used for counting. It is quite easy - to exceed the capacity of an eight-byte integer with a large number of - symbols and a large maximum code length, so multiple-precision arithmetic - would need to replace the unsigned long long arithmetic in that case. This - program will abort if an overflow occurs. The big_t type identifies where - the counting takes place. - - An unsigned long long type is also used for calculating the number of - possible codes remaining at the maximum length. This limits the maximum - code length to the number of bits in a long long minus the number of bits - needed to represent the symbols in a flat code. The code_t type identifies - where the bit pattern counting takes place. - */ - -#include -#include -#include -#include - -#define local static - -/* special data types */ -typedef unsigned long long big_t; /* type for code counting */ -typedef unsigned long long code_t; /* type for bit pattern counting */ -struct tab { /* type for been here check */ - size_t len; /* length of bit vector in char's */ - char *vec; /* allocated bit vector */ -}; - -/* The array for saving results, num[], is indexed with this triplet: - - syms: number of symbols remaining to code - left: number of available bit patterns at length len - len: number of bits in the codes currently being assigned - - Those indices are constrained thusly when saving results: - - syms: 3..totsym (totsym == total symbols to code) - left: 2..syms - 1, but only the evens (so syms == 8 -> 2, 4, 6) - len: 1..max - 1 (max == maximum code length in bits) - - syms == 2 is not saved since that immediately leads to a single code. left - must be even, since it represents the number of available bit patterns at - the current length, which is double the number at the previous length. - left ends at syms-1 since left == syms immediately results in a single code. - (left > sym is not allowed since that would result in an incomplete code.) - len is less than max, since the code completes immediately when len == max. - - The offset into the array is calculated for the three indices with the - first one (syms) being outermost, and the last one (len) being innermost. - We build the array with length max-1 lists for the len index, with syms-3 - of those for each symbol. There are totsym-2 of those, with each one - varying in length as a function of sym. See the calculation of index in - count() for the index, and the calculation of size in main() for the size - of the array. - - For the deflate example of 286 symbols limited to 15-bit codes, the array - has 284,284 entries, taking up 2.17 MB for an 8-byte big_t. More than - half of the space allocated for saved results is actually used -- not all - possible triplets are reached in the generation of valid Huffman codes. - */ - -/* The array for tracking visited states, done[], is itself indexed identically - to the num[] array as described above for the (syms, left, len) triplet. - Each element in the array is further indexed by the (mem, rem) doublet, - where mem is the amount of inflate table space used so far, and rem is the - remaining unused entries in the current inflate sub-table. Each indexed - element is simply one bit indicating whether the state has been visited or - not. Since the ranges for mem and rem are not known a priori, each bit - vector is of a variable size, and grows as needed to accommodate the visited - states. mem and rem are used to calculate a single index in a triangular - array. Since the range of mem is expected in the default case to be about - ten times larger than the range of rem, the array is skewed to reduce the - memory usage, with eight times the range for mem than for rem. See the - calculations for offset and bit in beenhere() for the details. - - For the deflate example of 286 symbols limited to 15-bit codes, the bit - vectors grow to total approximately 21 MB, in addition to the 4.3 MB done[] - array itself. - */ - -/* Globals to avoid propagating constants or constant pointers recursively */ -local int max; /* maximum allowed bit length for the codes */ -local int root; /* size of base code table in bits */ -local int large; /* largest code table so far */ -local size_t size; /* number of elements in num and done */ -local int *code; /* number of symbols assigned to each bit length */ -local big_t *num; /* saved results array for code counting */ -local struct tab *done; /* states already evaluated array */ - -/* Index function for num[] and done[] */ -#define INDEX(i,j,k) (((size_t)((i-1)>>1)*((i-2)>>1)+(j>>1)-1)*(max-1)+k-1) - -/* Free allocated space. Uses globals code, num, and done. */ -local void cleanup(void) -{ - size_t n; - - if (done != NULL) { - for (n = 0; n < size; n++) - if (done[n].len) - free(done[n].vec); - free(done); - } - if (num != NULL) - free(num); - if (code != NULL) - free(code); -} - -/* Return the number of possible Huffman codes using bit patterns of lengths - len through max inclusive, coding syms symbols, with left bit patterns of - length len unused -- return -1 if there is an overflow in the counting. - Keep a record of previous results in num to prevent repeating the same - calculation. Uses the globals max and num. */ -local big_t count(int syms, int len, int left) -{ - big_t sum; /* number of possible codes from this juncture */ - big_t got; /* value returned from count() */ - int least; /* least number of syms to use at this juncture */ - int most; /* most number of syms to use at this juncture */ - int use; /* number of bit patterns to use in next call */ - size_t index; /* index of this case in *num */ - - /* see if only one possible code */ - if (syms == left) - return 1; - - /* note and verify the expected state */ - assert(syms > left && left > 0 && len < max); - - /* see if we've done this one already */ - index = INDEX(syms, left, len); - got = num[index]; - if (got) - return got; /* we have -- return the saved result */ - - /* we need to use at least this many bit patterns so that the code won't be - incomplete at the next length (more bit patterns than symbols) */ - least = (left << 1) - syms; - if (least < 0) - least = 0; - - /* we can use at most this many bit patterns, lest there not be enough - available for the remaining symbols at the maximum length (if there were - no limit to the code length, this would become: most = left - 1) */ - most = (((code_t)left << (max - len)) - syms) / - (((code_t)1 << (max - len)) - 1); - - /* count all possible codes from this juncture and add them up */ - sum = 0; - for (use = least; use <= most; use++) { - got = count(syms - use, len + 1, (left - use) << 1); - sum += got; - if (got == (big_t)0 - 1 || sum < got) /* overflow */ - return (big_t)0 - 1; - } - - /* verify that all recursive calls are productive */ - assert(sum != 0); - - /* save the result and return it */ - num[index] = sum; - return sum; -} - -/* Return true if we've been here before, set to true if not. Set a bit in a - bit vector to indicate visiting this state. Each (syms,len,left) state - has a variable size bit vector indexed by (mem,rem). The bit vector is - lengthened if needed to allow setting the (mem,rem) bit. */ -local int beenhere(int syms, int len, int left, int mem, int rem) -{ - size_t index; /* index for this state's bit vector */ - size_t offset; /* offset in this state's bit vector */ - int bit; /* mask for this state's bit */ - size_t length; /* length of the bit vector in bytes */ - char *vector; /* new or enlarged bit vector */ - - /* point to vector for (syms,left,len), bit in vector for (mem,rem) */ - index = INDEX(syms, left, len); - mem -= 1 << root; - offset = (mem >> 3) + rem; - offset = ((offset * (offset + 1)) >> 1) + rem; - bit = 1 << (mem & 7); - - /* see if we've been here */ - length = done[index].len; - if (offset < length && (done[index].vec[offset] & bit) != 0) - return 1; /* done this! */ - - /* we haven't been here before -- set the bit to show we have now */ - - /* see if we need to lengthen the vector in order to set the bit */ - if (length <= offset) { - /* if we have one already, enlarge it, zero out the appended space */ - if (length) { - do { - length <<= 1; - } while (length <= offset); - vector = realloc(done[index].vec, length); - if (vector != NULL) - memset(vector + done[index].len, 0, length - done[index].len); - } - - /* otherwise we need to make a new vector and zero it out */ - else { - length = 1 << (len - root); - while (length <= offset) - length <<= 1; - vector = calloc(length, sizeof(char)); - } - - /* in either case, bail if we can't get the memory */ - if (vector == NULL) { - fputs("abort: unable to allocate enough memory\n", stderr); - cleanup(); - exit(1); - } - - /* install the new vector */ - done[index].len = length; - done[index].vec = vector; - } - - /* set the bit */ - done[index].vec[offset] |= bit; - return 0; -} - -/* Examine all possible codes from the given node (syms, len, left). Compute - the amount of memory required to build inflate's decoding tables, where the - number of code structures used so far is mem, and the number remaining in - the current sub-table is rem. Uses the globals max, code, root, large, and - done. */ -local void examine(int syms, int len, int left, int mem, int rem) -{ - int least; /* least number of syms to use at this juncture */ - int most; /* most number of syms to use at this juncture */ - int use; /* number of bit patterns to use in next call */ - - /* see if we have a complete code */ - if (syms == left) { - /* set the last code entry */ - code[len] = left; - - /* complete computation of memory used by this code */ - while (rem < left) { - left -= rem; - rem = 1 << (len - root); - mem += rem; - } - assert(rem == left); - - /* if this is a new maximum, show the entries used and the sub-code */ - if (mem > large) { - large = mem; - printf("max %d: ", mem); - for (use = root + 1; use <= max; use++) - if (code[use]) - printf("%d[%d] ", code[use], use); - putchar('\n'); - fflush(stdout); - } - - /* remove entries as we drop back down in the recursion */ - code[len] = 0; - return; - } - - /* prune the tree if we can */ - if (beenhere(syms, len, left, mem, rem)) - return; - - /* we need to use at least this many bit patterns so that the code won't be - incomplete at the next length (more bit patterns than symbols) */ - least = (left << 1) - syms; - if (least < 0) - least = 0; - - /* we can use at most this many bit patterns, lest there not be enough - available for the remaining symbols at the maximum length (if there were - no limit to the code length, this would become: most = left - 1) */ - most = (((code_t)left << (max - len)) - syms) / - (((code_t)1 << (max - len)) - 1); - - /* occupy least table spaces, creating new sub-tables as needed */ - use = least; - while (rem < use) { - use -= rem; - rem = 1 << (len - root); - mem += rem; - } - rem -= use; - - /* examine codes from here, updating table space as we go */ - for (use = least; use <= most; use++) { - code[len] = use; - examine(syms - use, len + 1, (left - use) << 1, - mem + (rem ? 1 << (len - root) : 0), rem << 1); - if (rem == 0) { - rem = 1 << (len - root); - mem += rem; - } - rem--; - } - - /* remove entries as we drop back down in the recursion */ - code[len] = 0; -} - -/* Look at all sub-codes starting with root + 1 bits. Look at only the valid - intermediate code states (syms, left, len). For each completed code, - calculate the amount of memory required by inflate to build the decoding - tables. Find the maximum amount of memory required and show the code that - requires that maximum. Uses the globals max, root, and num. */ -local void enough(int syms) -{ - int n; /* number of remaing symbols for this node */ - int left; /* number of unused bit patterns at this length */ - size_t index; /* index of this case in *num */ - - /* clear code */ - for (n = 0; n <= max; n++) - code[n] = 0; - - /* look at all (root + 1) bit and longer codes */ - large = 1 << root; /* base table */ - if (root < max) /* otherwise, there's only a base table */ - for (n = 3; n <= syms; n++) - for (left = 2; left < n; left += 2) - { - /* look at all reachable (root + 1) bit nodes, and the - resulting codes (complete at root + 2 or more) */ - index = INDEX(n, left, root + 1); - if (root + 1 < max && num[index]) /* reachable node */ - examine(n, root + 1, left, 1 << root, 0); - - /* also look at root bit codes with completions at root + 1 - bits (not saved in num, since complete), just in case */ - if (num[index - 1] && n <= left << 1) - examine((n - left) << 1, root + 1, (n - left) << 1, - 1 << root, 0); - } - - /* done */ - printf("done: maximum of %d table entries\n", large); -} - -/* - Examine and show the total number of possible Huffman codes for a given - maximum number of symbols, initial root table size, and maximum code length - in bits -- those are the command arguments in that order. The default - values are 286, 9, and 15 respectively, for the deflate literal/length code. - The possible codes are counted for each number of coded symbols from two to - the maximum. The counts for each of those and the total number of codes are - shown. The maximum number of inflate table entires is then calculated - across all possible codes. Each new maximum number of table entries and the - associated sub-code (starting at root + 1 == 10 bits) is shown. - - To count and examine Huffman codes that are not length-limited, provide a - maximum length equal to the number of symbols minus one. - - For the deflate literal/length code, use "enough". For the deflate distance - code, use "enough 30 6". - - This uses the %llu printf format to print big_t numbers, which assumes that - big_t is an unsigned long long. If the big_t type is changed (for example - to a multiple precision type), the method of printing will also need to be - updated. - */ -int main(int argc, char **argv) -{ - int syms; /* total number of symbols to code */ - int n; /* number of symbols to code for this run */ - big_t got; /* return value of count() */ - big_t sum; /* accumulated number of codes over n */ - code_t word; /* for counting bits in code_t */ - - /* set up globals for cleanup() */ - code = NULL; - num = NULL; - done = NULL; - - /* get arguments -- default to the deflate literal/length code */ - syms = 286; - root = 9; - max = 15; - if (argc > 1) { - syms = atoi(argv[1]); - if (argc > 2) { - root = atoi(argv[2]); - if (argc > 3) - max = atoi(argv[3]); - } - } - if (argc > 4 || syms < 2 || root < 1 || max < 1) { - fputs("invalid arguments, need: [sym >= 2 [root >= 1 [max >= 1]]]\n", - stderr); - return 1; - } - - /* if not restricting the code length, the longest is syms - 1 */ - if (max > syms - 1) - max = syms - 1; - - /* determine the number of bits in a code_t */ - for (n = 0, word = 1; word; n++, word <<= 1) - ; - - /* make sure that the calculation of most will not overflow */ - if (max > n || (code_t)(syms - 2) >= (((code_t)0 - 1) >> (max - 1))) { - fputs("abort: code length too long for internal types\n", stderr); - return 1; - } - - /* reject impossible code requests */ - if ((code_t)(syms - 1) > ((code_t)1 << max) - 1) { - fprintf(stderr, "%d symbols cannot be coded in %d bits\n", - syms, max); - return 1; - } - - /* allocate code vector */ - code = calloc(max + 1, sizeof(int)); - if (code == NULL) { - fputs("abort: unable to allocate enough memory\n", stderr); - return 1; - } - - /* determine size of saved results array, checking for overflows, - allocate and clear the array (set all to zero with calloc()) */ - if (syms == 2) /* iff max == 1 */ - num = NULL; /* won't be saving any results */ - else { - size = syms >> 1; - if (size > ((size_t)0 - 1) / (n = (syms - 1) >> 1) || - (size *= n, size > ((size_t)0 - 1) / (n = max - 1)) || - (size *= n, size > ((size_t)0 - 1) / sizeof(big_t)) || - (num = calloc(size, sizeof(big_t))) == NULL) { - fputs("abort: unable to allocate enough memory\n", stderr); - cleanup(); - return 1; - } - } - - /* count possible codes for all numbers of symbols, add up counts */ - sum = 0; - for (n = 2; n <= syms; n++) { - got = count(n, 1, 2); - sum += got; - if (got == (big_t)0 - 1 || sum < got) { /* overflow */ - fputs("abort: can't count that high!\n", stderr); - cleanup(); - return 1; - } - printf("%llu %d-codes\n", got, n); - } - printf("%llu total codes for 2 to %d symbols", sum, syms); - if (max < syms - 1) - printf(" (%d-bit length limit)\n", max); - else - puts(" (no length limit)"); - - /* allocate and clear done array for beenhere() */ - if (syms == 2) - done = NULL; - else if (size > ((size_t)0 - 1) / sizeof(struct tab) || - (done = calloc(size, sizeof(struct tab))) == NULL) { - fputs("abort: unable to allocate enough memory\n", stderr); - cleanup(); - return 1; - } - - /* find and show maximum inflate table usage */ - if (root > max) /* reduce root to max length */ - root = max; - if ((code_t)syms < ((code_t)1 << (root + 1))) - enough(syms); - else - puts("cannot handle minimum code lengths > root"); - - /* done */ - cleanup(); - return 0; -} diff --git a/deps/zlib/examples/fitblk.c b/deps/zlib/examples/fitblk.c deleted file mode 100644 index c61de5c99672d1..00000000000000 --- a/deps/zlib/examples/fitblk.c +++ /dev/null @@ -1,233 +0,0 @@ -/* fitblk.c: example of fitting compressed output to a specified size - Not copyrighted -- provided to the public domain - Version 1.1 25 November 2004 Mark Adler */ - -/* Version history: - 1.0 24 Nov 2004 First version - 1.1 25 Nov 2004 Change deflateInit2() to deflateInit() - Use fixed-size, stack-allocated raw buffers - Simplify code moving compression to subroutines - Use assert() for internal errors - Add detailed description of approach - */ - -/* Approach to just fitting a requested compressed size: - - fitblk performs three compression passes on a portion of the input - data in order to determine how much of that input will compress to - nearly the requested output block size. The first pass generates - enough deflate blocks to produce output to fill the requested - output size plus a specfied excess amount (see the EXCESS define - below). The last deflate block may go quite a bit past that, but - is discarded. The second pass decompresses and recompresses just - the compressed data that fit in the requested plus excess sized - buffer. The deflate process is terminated after that amount of - input, which is less than the amount consumed on the first pass. - The last deflate block of the result will be of a comparable size - to the final product, so that the header for that deflate block and - the compression ratio for that block will be about the same as in - the final product. The third compression pass decompresses the - result of the second step, but only the compressed data up to the - requested size minus an amount to allow the compressed stream to - complete (see the MARGIN define below). That will result in a - final compressed stream whose length is less than or equal to the - requested size. Assuming sufficient input and a requested size - greater than a few hundred bytes, the shortfall will typically be - less than ten bytes. - - If the input is short enough that the first compression completes - before filling the requested output size, then that compressed - stream is return with no recompression. - - EXCESS is chosen to be just greater than the shortfall seen in a - two pass approach similar to the above. That shortfall is due to - the last deflate block compressing more efficiently with a smaller - header on the second pass. EXCESS is set to be large enough so - that there is enough uncompressed data for the second pass to fill - out the requested size, and small enough so that the final deflate - block of the second pass will be close in size to the final deflate - block of the third and final pass. MARGIN is chosen to be just - large enough to assure that the final compression has enough room - to complete in all cases. - */ - -#include -#include -#include -#include "zlib.h" - -#define local static - -/* print nastygram and leave */ -local void quit(char *why) -{ - fprintf(stderr, "fitblk abort: %s\n", why); - exit(1); -} - -#define RAWLEN 4096 /* intermediate uncompressed buffer size */ - -/* compress from file to def until provided buffer is full or end of - input reached; return last deflate() return value, or Z_ERRNO if - there was read error on the file */ -local int partcompress(FILE *in, z_streamp def) -{ - int ret, flush; - unsigned char raw[RAWLEN]; - - flush = Z_NO_FLUSH; - do { - def->avail_in = fread(raw, 1, RAWLEN, in); - if (ferror(in)) - return Z_ERRNO; - def->next_in = raw; - if (feof(in)) - flush = Z_FINISH; - ret = deflate(def, flush); - assert(ret != Z_STREAM_ERROR); - } while (def->avail_out != 0 && flush == Z_NO_FLUSH); - return ret; -} - -/* recompress from inf's input to def's output; the input for inf and - the output for def are set in those structures before calling; - return last deflate() return value, or Z_MEM_ERROR if inflate() - was not able to allocate enough memory when it needed to */ -local int recompress(z_streamp inf, z_streamp def) -{ - int ret, flush; - unsigned char raw[RAWLEN]; - - flush = Z_NO_FLUSH; - do { - /* decompress */ - inf->avail_out = RAWLEN; - inf->next_out = raw; - ret = inflate(inf, Z_NO_FLUSH); - assert(ret != Z_STREAM_ERROR && ret != Z_DATA_ERROR && - ret != Z_NEED_DICT); - if (ret == Z_MEM_ERROR) - return ret; - - /* compress what was decompresed until done or no room */ - def->avail_in = RAWLEN - inf->avail_out; - def->next_in = raw; - if (inf->avail_out != 0) - flush = Z_FINISH; - ret = deflate(def, flush); - assert(ret != Z_STREAM_ERROR); - } while (ret != Z_STREAM_END && def->avail_out != 0); - return ret; -} - -#define EXCESS 256 /* empirically determined stream overage */ -#define MARGIN 8 /* amount to back off for completion */ - -/* compress from stdin to fixed-size block on stdout */ -int main(int argc, char **argv) -{ - int ret; /* return code */ - unsigned size; /* requested fixed output block size */ - unsigned have; /* bytes written by deflate() call */ - unsigned char *blk; /* intermediate and final stream */ - unsigned char *tmp; /* close to desired size stream */ - z_stream def, inf; /* zlib deflate and inflate states */ - - /* get requested output size */ - if (argc != 2) - quit("need one argument: size of output block"); - ret = strtol(argv[1], argv + 1, 10); - if (argv[1][0] != 0) - quit("argument must be a number"); - if (ret < 8) /* 8 is minimum zlib stream size */ - quit("need positive size of 8 or greater"); - size = (unsigned)ret; - - /* allocate memory for buffers and compression engine */ - blk = malloc(size + EXCESS); - def.zalloc = Z_NULL; - def.zfree = Z_NULL; - def.opaque = Z_NULL; - ret = deflateInit(&def, Z_DEFAULT_COMPRESSION); - if (ret != Z_OK || blk == NULL) - quit("out of memory"); - - /* compress from stdin until output full, or no more input */ - def.avail_out = size + EXCESS; - def.next_out = blk; - ret = partcompress(stdin, &def); - if (ret == Z_ERRNO) - quit("error reading input"); - - /* if it all fit, then size was undersubscribed -- done! */ - if (ret == Z_STREAM_END && def.avail_out >= EXCESS) { - /* write block to stdout */ - have = size + EXCESS - def.avail_out; - if (fwrite(blk, 1, have, stdout) != have || ferror(stdout)) - quit("error writing output"); - - /* clean up and print results to stderr */ - ret = deflateEnd(&def); - assert(ret != Z_STREAM_ERROR); - free(blk); - fprintf(stderr, - "%u bytes unused out of %u requested (all input)\n", - size - have, size); - return 0; - } - - /* it didn't all fit -- set up for recompression */ - inf.zalloc = Z_NULL; - inf.zfree = Z_NULL; - inf.opaque = Z_NULL; - inf.avail_in = 0; - inf.next_in = Z_NULL; - ret = inflateInit(&inf); - tmp = malloc(size + EXCESS); - if (ret != Z_OK || tmp == NULL) - quit("out of memory"); - ret = deflateReset(&def); - assert(ret != Z_STREAM_ERROR); - - /* do first recompression close to the right amount */ - inf.avail_in = size + EXCESS; - inf.next_in = blk; - def.avail_out = size + EXCESS; - def.next_out = tmp; - ret = recompress(&inf, &def); - if (ret == Z_MEM_ERROR) - quit("out of memory"); - - /* set up for next reocmpression */ - ret = inflateReset(&inf); - assert(ret != Z_STREAM_ERROR); - ret = deflateReset(&def); - assert(ret != Z_STREAM_ERROR); - - /* do second and final recompression (third compression) */ - inf.avail_in = size - MARGIN; /* assure stream will complete */ - inf.next_in = tmp; - def.avail_out = size; - def.next_out = blk; - ret = recompress(&inf, &def); - if (ret == Z_MEM_ERROR) - quit("out of memory"); - assert(ret == Z_STREAM_END); /* otherwise MARGIN too small */ - - /* done -- write block to stdout */ - have = size - def.avail_out; - if (fwrite(blk, 1, have, stdout) != have || ferror(stdout)) - quit("error writing output"); - - /* clean up and print results to stderr */ - free(tmp); - ret = inflateEnd(&inf); - assert(ret != Z_STREAM_ERROR); - ret = deflateEnd(&def); - assert(ret != Z_STREAM_ERROR); - free(blk); - fprintf(stderr, - "%u bytes unused out of %u requested (%lu input)\n", - size - have, size, def.total_in); - return 0; -} diff --git a/deps/zlib/examples/gun.c b/deps/zlib/examples/gun.c deleted file mode 100644 index be44fa51ff522c..00000000000000 --- a/deps/zlib/examples/gun.c +++ /dev/null @@ -1,702 +0,0 @@ -/* gun.c -- simple gunzip to give an example of the use of inflateBack() - * Copyright (C) 2003, 2005, 2008, 2010, 2012 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - Version 1.7 12 August 2012 Mark Adler */ - -/* Version history: - 1.0 16 Feb 2003 First version for testing of inflateBack() - 1.1 21 Feb 2005 Decompress concatenated gzip streams - Remove use of "this" variable (C++ keyword) - Fix return value for in() - Improve allocation failure checking - Add typecasting for void * structures - Add -h option for command version and usage - Add a bunch of comments - 1.2 20 Mar 2005 Add Unix compress (LZW) decompression - Copy file attributes from input file to output file - 1.3 12 Jun 2005 Add casts for error messages [Oberhumer] - 1.4 8 Dec 2006 LZW decompression speed improvements - 1.5 9 Feb 2008 Avoid warning in latest version of gcc - 1.6 17 Jan 2010 Avoid signed/unsigned comparison warnings - 1.7 12 Aug 2012 Update for z_const usage in zlib 1.2.8 - */ - -/* - gun [ -t ] [ name ... ] - - decompresses the data in the named gzip files. If no arguments are given, - gun will decompress from stdin to stdout. The names must end in .gz, -gz, - .z, -z, _z, or .Z. The uncompressed data will be written to a file name - with the suffix stripped. On success, the original file is deleted. On - failure, the output file is deleted. For most failures, the command will - continue to process the remaining names on the command line. A memory - allocation failure will abort the command. If -t is specified, then the - listed files or stdin will be tested as gzip files for integrity (without - checking for a proper suffix), no output will be written, and no files - will be deleted. - - Like gzip, gun allows concatenated gzip streams and will decompress them, - writing all of the uncompressed data to the output. Unlike gzip, gun allows - an empty file on input, and will produce no error writing an empty output - file. - - gun will also decompress files made by Unix compress, which uses LZW - compression. These files are automatically detected by virtue of their - magic header bytes. Since the end of Unix compress stream is marked by the - end-of-file, they cannot be concantenated. If a Unix compress stream is - encountered in an input file, it is the last stream in that file. - - Like gunzip and uncompress, the file attributes of the original compressed - file are maintained in the final uncompressed file, to the extent that the - user permissions allow it. - - On my Mac OS X PowerPC G4, gun is almost twice as fast as gunzip (version - 1.2.4) is on the same file, when gun is linked with zlib 1.2.2. Also the - LZW decompression provided by gun is about twice as fast as the standard - Unix uncompress command. - */ - -/* external functions and related types and constants */ -#include /* fprintf() */ -#include /* malloc(), free() */ -#include /* strerror(), strcmp(), strlen(), memcpy() */ -#include /* errno */ -#include /* open() */ -#include /* read(), write(), close(), chown(), unlink() */ -#include -#include /* stat(), chmod() */ -#include /* utime() */ -#include "zlib.h" /* inflateBackInit(), inflateBack(), */ - /* inflateBackEnd(), crc32() */ - -/* function declaration */ -#define local static - -/* buffer constants */ -#define SIZE 32768U /* input and output buffer sizes */ -#define PIECE 16384 /* limits i/o chunks for 16-bit int case */ - -/* structure for infback() to pass to input function in() -- it maintains the - input file and a buffer of size SIZE */ -struct ind { - int infile; - unsigned char *inbuf; -}; - -/* Load input buffer, assumed to be empty, and return bytes loaded and a - pointer to them. read() is called until the buffer is full, or until it - returns end-of-file or error. Return 0 on error. */ -local unsigned in(void *in_desc, z_const unsigned char **buf) -{ - int ret; - unsigned len; - unsigned char *next; - struct ind *me = (struct ind *)in_desc; - - next = me->inbuf; - *buf = next; - len = 0; - do { - ret = PIECE; - if ((unsigned)ret > SIZE - len) - ret = (int)(SIZE - len); - ret = (int)read(me->infile, next, ret); - if (ret == -1) { - len = 0; - break; - } - next += ret; - len += ret; - } while (ret != 0 && len < SIZE); - return len; -} - -/* structure for infback() to pass to output function out() -- it maintains the - output file, a running CRC-32 check on the output and the total number of - bytes output, both for checking against the gzip trailer. (The length in - the gzip trailer is stored modulo 2^32, so it's ok if a long is 32 bits and - the output is greater than 4 GB.) */ -struct outd { - int outfile; - int check; /* true if checking crc and total */ - unsigned long crc; - unsigned long total; -}; - -/* Write output buffer and update the CRC-32 and total bytes written. write() - is called until all of the output is written or an error is encountered. - On success out() returns 0. For a write failure, out() returns 1. If the - output file descriptor is -1, then nothing is written. - */ -local int out(void *out_desc, unsigned char *buf, unsigned len) -{ - int ret; - struct outd *me = (struct outd *)out_desc; - - if (me->check) { - me->crc = crc32(me->crc, buf, len); - me->total += len; - } - if (me->outfile != -1) - do { - ret = PIECE; - if ((unsigned)ret > len) - ret = (int)len; - ret = (int)write(me->outfile, buf, ret); - if (ret == -1) - return 1; - buf += ret; - len -= ret; - } while (len != 0); - return 0; -} - -/* next input byte macro for use inside lunpipe() and gunpipe() */ -#define NEXT() (have ? 0 : (have = in(indp, &next)), \ - last = have ? (have--, (int)(*next++)) : -1) - -/* memory for gunpipe() and lunpipe() -- - the first 256 entries of prefix[] and suffix[] are never used, could - have offset the index, but it's faster to waste the memory */ -unsigned char inbuf[SIZE]; /* input buffer */ -unsigned char outbuf[SIZE]; /* output buffer */ -unsigned short prefix[65536]; /* index to LZW prefix string */ -unsigned char suffix[65536]; /* one-character LZW suffix */ -unsigned char match[65280 + 2]; /* buffer for reversed match or gzip - 32K sliding window */ - -/* throw out what's left in the current bits byte buffer (this is a vestigial - aspect of the compressed data format derived from an implementation that - made use of a special VAX machine instruction!) */ -#define FLUSHCODE() \ - do { \ - left = 0; \ - rem = 0; \ - if (chunk > have) { \ - chunk -= have; \ - have = 0; \ - if (NEXT() == -1) \ - break; \ - chunk--; \ - if (chunk > have) { \ - chunk = have = 0; \ - break; \ - } \ - } \ - have -= chunk; \ - next += chunk; \ - chunk = 0; \ - } while (0) - -/* Decompress a compress (LZW) file from indp to outfile. The compress magic - header (two bytes) has already been read and verified. There are have bytes - of buffered input at next. strm is used for passing error information back - to gunpipe(). - - lunpipe() will return Z_OK on success, Z_BUF_ERROR for an unexpected end of - file, read error, or write error (a write error indicated by strm->next_in - not equal to Z_NULL), or Z_DATA_ERROR for invalid input. - */ -local int lunpipe(unsigned have, z_const unsigned char *next, struct ind *indp, - int outfile, z_stream *strm) -{ - int last; /* last byte read by NEXT(), or -1 if EOF */ - unsigned chunk; /* bytes left in current chunk */ - int left; /* bits left in rem */ - unsigned rem; /* unused bits from input */ - int bits; /* current bits per code */ - unsigned code; /* code, table traversal index */ - unsigned mask; /* mask for current bits codes */ - int max; /* maximum bits per code for this stream */ - unsigned flags; /* compress flags, then block compress flag */ - unsigned end; /* last valid entry in prefix/suffix tables */ - unsigned temp; /* current code */ - unsigned prev; /* previous code */ - unsigned final; /* last character written for previous code */ - unsigned stack; /* next position for reversed string */ - unsigned outcnt; /* bytes in output buffer */ - struct outd outd; /* output structure */ - unsigned char *p; - - /* set up output */ - outd.outfile = outfile; - outd.check = 0; - - /* process remainder of compress header -- a flags byte */ - flags = NEXT(); - if (last == -1) - return Z_BUF_ERROR; - if (flags & 0x60) { - strm->msg = (char *)"unknown lzw flags set"; - return Z_DATA_ERROR; - } - max = flags & 0x1f; - if (max < 9 || max > 16) { - strm->msg = (char *)"lzw bits out of range"; - return Z_DATA_ERROR; - } - if (max == 9) /* 9 doesn't really mean 9 */ - max = 10; - flags &= 0x80; /* true if block compress */ - - /* clear table */ - bits = 9; - mask = 0x1ff; - end = flags ? 256 : 255; - - /* set up: get first 9-bit code, which is the first decompressed byte, but - don't create a table entry until the next code */ - if (NEXT() == -1) /* no compressed data is ok */ - return Z_OK; - final = prev = (unsigned)last; /* low 8 bits of code */ - if (NEXT() == -1) /* missing a bit */ - return Z_BUF_ERROR; - if (last & 1) { /* code must be < 256 */ - strm->msg = (char *)"invalid lzw code"; - return Z_DATA_ERROR; - } - rem = (unsigned)last >> 1; /* remaining 7 bits */ - left = 7; - chunk = bits - 2; /* 7 bytes left in this chunk */ - outbuf[0] = (unsigned char)final; /* write first decompressed byte */ - outcnt = 1; - - /* decode codes */ - stack = 0; - for (;;) { - /* if the table will be full after this, increment the code size */ - if (end >= mask && bits < max) { - FLUSHCODE(); - bits++; - mask <<= 1; - mask++; - } - - /* get a code of length bits */ - if (chunk == 0) /* decrement chunk modulo bits */ - chunk = bits; - code = rem; /* low bits of code */ - if (NEXT() == -1) { /* EOF is end of compressed data */ - /* write remaining buffered output */ - if (outcnt && out(&outd, outbuf, outcnt)) { - strm->next_in = outbuf; /* signal write error */ - return Z_BUF_ERROR; - } - return Z_OK; - } - code += (unsigned)last << left; /* middle (or high) bits of code */ - left += 8; - chunk--; - if (bits > left) { /* need more bits */ - if (NEXT() == -1) /* can't end in middle of code */ - return Z_BUF_ERROR; - code += (unsigned)last << left; /* high bits of code */ - left += 8; - chunk--; - } - code &= mask; /* mask to current code length */ - left -= bits; /* number of unused bits */ - rem = (unsigned)last >> (8 - left); /* unused bits from last byte */ - - /* process clear code (256) */ - if (code == 256 && flags) { - FLUSHCODE(); - bits = 9; /* initialize bits and mask */ - mask = 0x1ff; - end = 255; /* empty table */ - continue; /* get next code */ - } - - /* special code to reuse last match */ - temp = code; /* save the current code */ - if (code > end) { - /* Be picky on the allowed code here, and make sure that the code - we drop through (prev) will be a valid index so that random - input does not cause an exception. The code != end + 1 check is - empirically derived, and not checked in the original uncompress - code. If this ever causes a problem, that check could be safely - removed. Leaving this check in greatly improves gun's ability - to detect random or corrupted input after a compress header. - In any case, the prev > end check must be retained. */ - if (code != end + 1 || prev > end) { - strm->msg = (char *)"invalid lzw code"; - return Z_DATA_ERROR; - } - match[stack++] = (unsigned char)final; - code = prev; - } - - /* walk through linked list to generate output in reverse order */ - p = match + stack; - while (code >= 256) { - *p++ = suffix[code]; - code = prefix[code]; - } - stack = p - match; - match[stack++] = (unsigned char)code; - final = code; - - /* link new table entry */ - if (end < mask) { - end++; - prefix[end] = (unsigned short)prev; - suffix[end] = (unsigned char)final; - } - - /* set previous code for next iteration */ - prev = temp; - - /* write output in forward order */ - while (stack > SIZE - outcnt) { - while (outcnt < SIZE) - outbuf[outcnt++] = match[--stack]; - if (out(&outd, outbuf, outcnt)) { - strm->next_in = outbuf; /* signal write error */ - return Z_BUF_ERROR; - } - outcnt = 0; - } - p = match + stack; - do { - outbuf[outcnt++] = *--p; - } while (p > match); - stack = 0; - - /* loop for next code with final and prev as the last match, rem and - left provide the first 0..7 bits of the next code, end is the last - valid table entry */ - } -} - -/* Decompress a gzip file from infile to outfile. strm is assumed to have been - successfully initialized with inflateBackInit(). The input file may consist - of a series of gzip streams, in which case all of them will be decompressed - to the output file. If outfile is -1, then the gzip stream(s) integrity is - checked and nothing is written. - - The return value is a zlib error code: Z_MEM_ERROR if out of memory, - Z_DATA_ERROR if the header or the compressed data is invalid, or if the - trailer CRC-32 check or length doesn't match, Z_BUF_ERROR if the input ends - prematurely or a write error occurs, or Z_ERRNO if junk (not a another gzip - stream) follows a valid gzip stream. - */ -local int gunpipe(z_stream *strm, int infile, int outfile) -{ - int ret, first, last; - unsigned have, flags, len; - z_const unsigned char *next = NULL; - struct ind ind, *indp; - struct outd outd; - - /* setup input buffer */ - ind.infile = infile; - ind.inbuf = inbuf; - indp = &ind; - - /* decompress concatenated gzip streams */ - have = 0; /* no input data read in yet */ - first = 1; /* looking for first gzip header */ - strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */ - for (;;) { - /* look for the two magic header bytes for a gzip stream */ - if (NEXT() == -1) { - ret = Z_OK; - break; /* empty gzip stream is ok */ - } - if (last != 31 || (NEXT() != 139 && last != 157)) { - strm->msg = (char *)"incorrect header check"; - ret = first ? Z_DATA_ERROR : Z_ERRNO; - break; /* not a gzip or compress header */ - } - first = 0; /* next non-header is junk */ - - /* process a compress (LZW) file -- can't be concatenated after this */ - if (last == 157) { - ret = lunpipe(have, next, indp, outfile, strm); - break; - } - - /* process remainder of gzip header */ - ret = Z_BUF_ERROR; - if (NEXT() != 8) { /* only deflate method allowed */ - if (last == -1) break; - strm->msg = (char *)"unknown compression method"; - ret = Z_DATA_ERROR; - break; - } - flags = NEXT(); /* header flags */ - NEXT(); /* discard mod time, xflgs, os */ - NEXT(); - NEXT(); - NEXT(); - NEXT(); - NEXT(); - if (last == -1) break; - if (flags & 0xe0) { - strm->msg = (char *)"unknown header flags set"; - ret = Z_DATA_ERROR; - break; - } - if (flags & 4) { /* extra field */ - len = NEXT(); - len += (unsigned)(NEXT()) << 8; - if (last == -1) break; - while (len > have) { - len -= have; - have = 0; - if (NEXT() == -1) break; - len--; - } - if (last == -1) break; - have -= len; - next += len; - } - if (flags & 8) /* file name */ - while (NEXT() != 0 && last != -1) - ; - if (flags & 16) /* comment */ - while (NEXT() != 0 && last != -1) - ; - if (flags & 2) { /* header crc */ - NEXT(); - NEXT(); - } - if (last == -1) break; - - /* set up output */ - outd.outfile = outfile; - outd.check = 1; - outd.crc = crc32(0L, Z_NULL, 0); - outd.total = 0; - - /* decompress data to output */ - strm->next_in = next; - strm->avail_in = have; - ret = inflateBack(strm, in, indp, out, &outd); - if (ret != Z_STREAM_END) break; - next = strm->next_in; - have = strm->avail_in; - strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */ - - /* check trailer */ - ret = Z_BUF_ERROR; - if (NEXT() != (int)(outd.crc & 0xff) || - NEXT() != (int)((outd.crc >> 8) & 0xff) || - NEXT() != (int)((outd.crc >> 16) & 0xff) || - NEXT() != (int)((outd.crc >> 24) & 0xff)) { - /* crc error */ - if (last != -1) { - strm->msg = (char *)"incorrect data check"; - ret = Z_DATA_ERROR; - } - break; - } - if (NEXT() != (int)(outd.total & 0xff) || - NEXT() != (int)((outd.total >> 8) & 0xff) || - NEXT() != (int)((outd.total >> 16) & 0xff) || - NEXT() != (int)((outd.total >> 24) & 0xff)) { - /* length error */ - if (last != -1) { - strm->msg = (char *)"incorrect length check"; - ret = Z_DATA_ERROR; - } - break; - } - - /* go back and look for another gzip stream */ - } - - /* clean up and return */ - return ret; -} - -/* Copy file attributes, from -> to, as best we can. This is best effort, so - no errors are reported. The mode bits, including suid, sgid, and the sticky - bit are copied (if allowed), the owner's user id and group id are copied - (again if allowed), and the access and modify times are copied. */ -local void copymeta(char *from, char *to) -{ - struct stat was; - struct utimbuf when; - - /* get all of from's Unix meta data, return if not a regular file */ - if (stat(from, &was) != 0 || (was.st_mode & S_IFMT) != S_IFREG) - return; - - /* set to's mode bits, ignore errors */ - (void)chmod(to, was.st_mode & 07777); - - /* copy owner's user and group, ignore errors */ - (void)chown(to, was.st_uid, was.st_gid); - - /* copy access and modify times, ignore errors */ - when.actime = was.st_atime; - when.modtime = was.st_mtime; - (void)utime(to, &when); -} - -/* Decompress the file inname to the file outnname, of if test is true, just - decompress without writing and check the gzip trailer for integrity. If - inname is NULL or an empty string, read from stdin. If outname is NULL or - an empty string, write to stdout. strm is a pre-initialized inflateBack - structure. When appropriate, copy the file attributes from inname to - outname. - - gunzip() returns 1 if there is an out-of-memory error or an unexpected - return code from gunpipe(). Otherwise it returns 0. - */ -local int gunzip(z_stream *strm, char *inname, char *outname, int test) -{ - int ret; - int infile, outfile; - - /* open files */ - if (inname == NULL || *inname == 0) { - inname = "-"; - infile = 0; /* stdin */ - } - else { - infile = open(inname, O_RDONLY, 0); - if (infile == -1) { - fprintf(stderr, "gun cannot open %s\n", inname); - return 0; - } - } - if (test) - outfile = -1; - else if (outname == NULL || *outname == 0) { - outname = "-"; - outfile = 1; /* stdout */ - } - else { - outfile = open(outname, O_CREAT | O_TRUNC | O_WRONLY, 0666); - if (outfile == -1) { - close(infile); - fprintf(stderr, "gun cannot create %s\n", outname); - return 0; - } - } - errno = 0; - - /* decompress */ - ret = gunpipe(strm, infile, outfile); - if (outfile > 2) close(outfile); - if (infile > 2) close(infile); - - /* interpret result */ - switch (ret) { - case Z_OK: - case Z_ERRNO: - if (infile > 2 && outfile > 2) { - copymeta(inname, outname); /* copy attributes */ - unlink(inname); - } - if (ret == Z_ERRNO) - fprintf(stderr, "gun warning: trailing garbage ignored in %s\n", - inname); - break; - case Z_DATA_ERROR: - if (outfile > 2) unlink(outname); - fprintf(stderr, "gun data error on %s: %s\n", inname, strm->msg); - break; - case Z_MEM_ERROR: - if (outfile > 2) unlink(outname); - fprintf(stderr, "gun out of memory error--aborting\n"); - return 1; - case Z_BUF_ERROR: - if (outfile > 2) unlink(outname); - if (strm->next_in != Z_NULL) { - fprintf(stderr, "gun write error on %s: %s\n", - outname, strerror(errno)); - } - else if (errno) { - fprintf(stderr, "gun read error on %s: %s\n", - inname, strerror(errno)); - } - else { - fprintf(stderr, "gun unexpected end of file on %s\n", - inname); - } - break; - default: - if (outfile > 2) unlink(outname); - fprintf(stderr, "gun internal error--aborting\n"); - return 1; - } - return 0; -} - -/* Process the gun command line arguments. See the command syntax near the - beginning of this source file. */ -int main(int argc, char **argv) -{ - int ret, len, test; - char *outname; - unsigned char *window; - z_stream strm; - - /* initialize inflateBack state for repeated use */ - window = match; /* reuse LZW match buffer */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - ret = inflateBackInit(&strm, 15, window); - if (ret != Z_OK) { - fprintf(stderr, "gun out of memory error--aborting\n"); - return 1; - } - - /* decompress each file to the same name with the suffix removed */ - argc--; - argv++; - test = 0; - if (argc && strcmp(*argv, "-h") == 0) { - fprintf(stderr, "gun 1.6 (17 Jan 2010)\n"); - fprintf(stderr, "Copyright (C) 2003-2010 Mark Adler\n"); - fprintf(stderr, "usage: gun [-t] [file1.gz [file2.Z ...]]\n"); - return 0; - } - if (argc && strcmp(*argv, "-t") == 0) { - test = 1; - argc--; - argv++; - } - if (argc) - do { - if (test) - outname = NULL; - else { - len = (int)strlen(*argv); - if (strcmp(*argv + len - 3, ".gz") == 0 || - strcmp(*argv + len - 3, "-gz") == 0) - len -= 3; - else if (strcmp(*argv + len - 2, ".z") == 0 || - strcmp(*argv + len - 2, "-z") == 0 || - strcmp(*argv + len - 2, "_z") == 0 || - strcmp(*argv + len - 2, ".Z") == 0) - len -= 2; - else { - fprintf(stderr, "gun error: no gz type on %s--skipping\n", - *argv); - continue; - } - outname = malloc(len + 1); - if (outname == NULL) { - fprintf(stderr, "gun out of memory error--aborting\n"); - ret = 1; - break; - } - memcpy(outname, *argv, len); - outname[len] = 0; - } - ret = gunzip(&strm, *argv, outname, test); - if (outname != NULL) free(outname); - if (ret) break; - } while (argv++, --argc); - else - ret = gunzip(&strm, NULL, NULL, test); - - /* clean up */ - inflateBackEnd(&strm); - return ret; -} diff --git a/deps/zlib/examples/gzappend.c b/deps/zlib/examples/gzappend.c deleted file mode 100644 index 662dec3794b7c0..00000000000000 --- a/deps/zlib/examples/gzappend.c +++ /dev/null @@ -1,504 +0,0 @@ -/* gzappend -- command to append to a gzip file - - Copyright (C) 2003, 2012 Mark Adler, all rights reserved - version 1.2, 11 Oct 2012 - - This software is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Mark Adler madler@alumni.caltech.edu - */ - -/* - * Change history: - * - * 1.0 19 Oct 2003 - First version - * 1.1 4 Nov 2003 - Expand and clarify some comments and notes - * - Add version and copyright to help - * - Send help to stdout instead of stderr - * - Add some preemptive typecasts - * - Add L to constants in lseek() calls - * - Remove some debugging information in error messages - * - Use new data_type definition for zlib 1.2.1 - * - Simplfy and unify file operations - * - Finish off gzip file in gztack() - * - Use deflatePrime() instead of adding empty blocks - * - Keep gzip file clean on appended file read errors - * - Use in-place rotate instead of auxiliary buffer - * (Why you ask? Because it was fun to write!) - * 1.2 11 Oct 2012 - Fix for proper z_const usage - * - Check for input buffer malloc failure - */ - -/* - gzappend takes a gzip file and appends to it, compressing files from the - command line or data from stdin. The gzip file is written to directly, to - avoid copying that file, in case it's large. Note that this results in the - unfriendly behavior that if gzappend fails, the gzip file is corrupted. - - This program was written to illustrate the use of the new Z_BLOCK option of - zlib 1.2.x's inflate() function. This option returns from inflate() at each - block boundary to facilitate locating and modifying the last block bit at - the start of the final deflate block. Also whether using Z_BLOCK or not, - another required feature of zlib 1.2.x is that inflate() now provides the - number of unusued bits in the last input byte used. gzappend will not work - with versions of zlib earlier than 1.2.1. - - gzappend first decompresses the gzip file internally, discarding all but - the last 32K of uncompressed data, and noting the location of the last block - bit and the number of unused bits in the last byte of the compressed data. - The gzip trailer containing the CRC-32 and length of the uncompressed data - is verified. This trailer will be later overwritten. - - Then the last block bit is cleared by seeking back in the file and rewriting - the byte that contains it. Seeking forward, the last byte of the compressed - data is saved along with the number of unused bits to initialize deflate. - - A deflate process is initialized, using the last 32K of the uncompressed - data from the gzip file to initialize the dictionary. If the total - uncompressed data was less than 32K, then all of it is used to initialize - the dictionary. The deflate output bit buffer is also initialized with the - last bits from the original deflate stream. From here on, the data to - append is simply compressed using deflate, and written to the gzip file. - When that is complete, the new CRC-32 and uncompressed length are written - as the trailer of the gzip file. - */ - -#include -#include -#include -#include -#include -#include "zlib.h" - -#define local static -#define LGCHUNK 14 -#define CHUNK (1U << LGCHUNK) -#define DSIZE 32768U - -/* print an error message and terminate with extreme prejudice */ -local void bye(char *msg1, char *msg2) -{ - fprintf(stderr, "gzappend error: %s%s\n", msg1, msg2); - exit(1); -} - -/* return the greatest common divisor of a and b using Euclid's algorithm, - modified to be fast when one argument much greater than the other, and - coded to avoid unnecessary swapping */ -local unsigned gcd(unsigned a, unsigned b) -{ - unsigned c; - - while (a && b) - if (a > b) { - c = b; - while (a - c >= c) - c <<= 1; - a -= c; - } - else { - c = a; - while (b - c >= c) - c <<= 1; - b -= c; - } - return a + b; -} - -/* rotate list[0..len-1] left by rot positions, in place */ -local void rotate(unsigned char *list, unsigned len, unsigned rot) -{ - unsigned char tmp; - unsigned cycles; - unsigned char *start, *last, *to, *from; - - /* normalize rot and handle degenerate cases */ - if (len < 2) return; - if (rot >= len) rot %= len; - if (rot == 0) return; - - /* pointer to last entry in list */ - last = list + (len - 1); - - /* do simple left shift by one */ - if (rot == 1) { - tmp = *list; - memcpy(list, list + 1, len - 1); - *last = tmp; - return; - } - - /* do simple right shift by one */ - if (rot == len - 1) { - tmp = *last; - memmove(list + 1, list, len - 1); - *list = tmp; - return; - } - - /* otherwise do rotate as a set of cycles in place */ - cycles = gcd(len, rot); /* number of cycles */ - do { - start = from = list + cycles; /* start index is arbitrary */ - tmp = *from; /* save entry to be overwritten */ - for (;;) { - to = from; /* next step in cycle */ - from += rot; /* go right rot positions */ - if (from > last) from -= len; /* (pointer better not wrap) */ - if (from == start) break; /* all but one shifted */ - *to = *from; /* shift left */ - } - *to = tmp; /* complete the circle */ - } while (--cycles); -} - -/* structure for gzip file read operations */ -typedef struct { - int fd; /* file descriptor */ - int size; /* 1 << size is bytes in buf */ - unsigned left; /* bytes available at next */ - unsigned char *buf; /* buffer */ - z_const unsigned char *next; /* next byte in buffer */ - char *name; /* file name for error messages */ -} file; - -/* reload buffer */ -local int readin(file *in) -{ - int len; - - len = read(in->fd, in->buf, 1 << in->size); - if (len == -1) bye("error reading ", in->name); - in->left = (unsigned)len; - in->next = in->buf; - return len; -} - -/* read from file in, exit if end-of-file */ -local int readmore(file *in) -{ - if (readin(in) == 0) bye("unexpected end of ", in->name); - return 0; -} - -#define read1(in) (in->left == 0 ? readmore(in) : 0, \ - in->left--, *(in->next)++) - -/* skip over n bytes of in */ -local void skip(file *in, unsigned n) -{ - unsigned bypass; - - if (n > in->left) { - n -= in->left; - bypass = n & ~((1U << in->size) - 1); - if (bypass) { - if (lseek(in->fd, (off_t)bypass, SEEK_CUR) == -1) - bye("seeking ", in->name); - n -= bypass; - } - readmore(in); - if (n > in->left) - bye("unexpected end of ", in->name); - } - in->left -= n; - in->next += n; -} - -/* read a four-byte unsigned integer, little-endian, from in */ -unsigned long read4(file *in) -{ - unsigned long val; - - val = read1(in); - val += (unsigned)read1(in) << 8; - val += (unsigned long)read1(in) << 16; - val += (unsigned long)read1(in) << 24; - return val; -} - -/* skip over gzip header */ -local void gzheader(file *in) -{ - int flags; - unsigned n; - - if (read1(in) != 31 || read1(in) != 139) bye(in->name, " not a gzip file"); - if (read1(in) != 8) bye("unknown compression method in", in->name); - flags = read1(in); - if (flags & 0xe0) bye("unknown header flags set in", in->name); - skip(in, 6); - if (flags & 4) { - n = read1(in); - n += (unsigned)(read1(in)) << 8; - skip(in, n); - } - if (flags & 8) while (read1(in) != 0) ; - if (flags & 16) while (read1(in) != 0) ; - if (flags & 2) skip(in, 2); -} - -/* decompress gzip file "name", return strm with a deflate stream ready to - continue compression of the data in the gzip file, and return a file - descriptor pointing to where to write the compressed data -- the deflate - stream is initialized to compress using level "level" */ -local int gzscan(char *name, z_stream *strm, int level) -{ - int ret, lastbit, left, full; - unsigned have; - unsigned long crc, tot; - unsigned char *window; - off_t lastoff, end; - file gz; - - /* open gzip file */ - gz.name = name; - gz.fd = open(name, O_RDWR, 0); - if (gz.fd == -1) bye("cannot open ", name); - gz.buf = malloc(CHUNK); - if (gz.buf == NULL) bye("out of memory", ""); - gz.size = LGCHUNK; - gz.left = 0; - - /* skip gzip header */ - gzheader(&gz); - - /* prepare to decompress */ - window = malloc(DSIZE); - if (window == NULL) bye("out of memory", ""); - strm->zalloc = Z_NULL; - strm->zfree = Z_NULL; - strm->opaque = Z_NULL; - ret = inflateInit2(strm, -15); - if (ret != Z_OK) bye("out of memory", " or library mismatch"); - - /* decompress the deflate stream, saving append information */ - lastbit = 0; - lastoff = lseek(gz.fd, 0L, SEEK_CUR) - gz.left; - left = 0; - strm->avail_in = gz.left; - strm->next_in = gz.next; - crc = crc32(0L, Z_NULL, 0); - have = full = 0; - do { - /* if needed, get more input */ - if (strm->avail_in == 0) { - readmore(&gz); - strm->avail_in = gz.left; - strm->next_in = gz.next; - } - - /* set up output to next available section of sliding window */ - strm->avail_out = DSIZE - have; - strm->next_out = window + have; - - /* inflate and check for errors */ - ret = inflate(strm, Z_BLOCK); - if (ret == Z_STREAM_ERROR) bye("internal stream error!", ""); - if (ret == Z_MEM_ERROR) bye("out of memory", ""); - if (ret == Z_DATA_ERROR) - bye("invalid compressed data--format violated in", name); - - /* update crc and sliding window pointer */ - crc = crc32(crc, window + have, DSIZE - have - strm->avail_out); - if (strm->avail_out) - have = DSIZE - strm->avail_out; - else { - have = 0; - full = 1; - } - - /* process end of block */ - if (strm->data_type & 128) { - if (strm->data_type & 64) - left = strm->data_type & 0x1f; - else { - lastbit = strm->data_type & 0x1f; - lastoff = lseek(gz.fd, 0L, SEEK_CUR) - strm->avail_in; - } - } - } while (ret != Z_STREAM_END); - inflateEnd(strm); - gz.left = strm->avail_in; - gz.next = strm->next_in; - - /* save the location of the end of the compressed data */ - end = lseek(gz.fd, 0L, SEEK_CUR) - gz.left; - - /* check gzip trailer and save total for deflate */ - if (crc != read4(&gz)) - bye("invalid compressed data--crc mismatch in ", name); - tot = strm->total_out; - if ((tot & 0xffffffffUL) != read4(&gz)) - bye("invalid compressed data--length mismatch in", name); - - /* if not at end of file, warn */ - if (gz.left || readin(&gz)) - fprintf(stderr, - "gzappend warning: junk at end of gzip file overwritten\n"); - - /* clear last block bit */ - lseek(gz.fd, lastoff - (lastbit != 0), SEEK_SET); - if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name); - *gz.buf = (unsigned char)(*gz.buf ^ (1 << ((8 - lastbit) & 7))); - lseek(gz.fd, -1L, SEEK_CUR); - if (write(gz.fd, gz.buf, 1) != 1) bye("writing after seek to ", name); - - /* if window wrapped, build dictionary from window by rotating */ - if (full) { - rotate(window, DSIZE, have); - have = DSIZE; - } - - /* set up deflate stream with window, crc, total_in, and leftover bits */ - ret = deflateInit2(strm, level, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); - if (ret != Z_OK) bye("out of memory", ""); - deflateSetDictionary(strm, window, have); - strm->adler = crc; - strm->total_in = tot; - if (left) { - lseek(gz.fd, --end, SEEK_SET); - if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name); - deflatePrime(strm, 8 - left, *gz.buf); - } - lseek(gz.fd, end, SEEK_SET); - - /* clean up and return */ - free(window); - free(gz.buf); - return gz.fd; -} - -/* append file "name" to gzip file gd using deflate stream strm -- if last - is true, then finish off the deflate stream at the end */ -local void gztack(char *name, int gd, z_stream *strm, int last) -{ - int fd, len, ret; - unsigned left; - unsigned char *in, *out; - - /* open file to compress and append */ - fd = 0; - if (name != NULL) { - fd = open(name, O_RDONLY, 0); - if (fd == -1) - fprintf(stderr, "gzappend warning: %s not found, skipping ...\n", - name); - } - - /* allocate buffers */ - in = malloc(CHUNK); - out = malloc(CHUNK); - if (in == NULL || out == NULL) bye("out of memory", ""); - - /* compress input file and append to gzip file */ - do { - /* get more input */ - len = read(fd, in, CHUNK); - if (len == -1) { - fprintf(stderr, - "gzappend warning: error reading %s, skipping rest ...\n", - name); - len = 0; - } - strm->avail_in = (unsigned)len; - strm->next_in = in; - if (len) strm->adler = crc32(strm->adler, in, (unsigned)len); - - /* compress and write all available output */ - do { - strm->avail_out = CHUNK; - strm->next_out = out; - ret = deflate(strm, last && len == 0 ? Z_FINISH : Z_NO_FLUSH); - left = CHUNK - strm->avail_out; - while (left) { - len = write(gd, out + CHUNK - strm->avail_out - left, left); - if (len == -1) bye("writing gzip file", ""); - left -= (unsigned)len; - } - } while (strm->avail_out == 0 && ret != Z_STREAM_END); - } while (len != 0); - - /* write trailer after last entry */ - if (last) { - deflateEnd(strm); - out[0] = (unsigned char)(strm->adler); - out[1] = (unsigned char)(strm->adler >> 8); - out[2] = (unsigned char)(strm->adler >> 16); - out[3] = (unsigned char)(strm->adler >> 24); - out[4] = (unsigned char)(strm->total_in); - out[5] = (unsigned char)(strm->total_in >> 8); - out[6] = (unsigned char)(strm->total_in >> 16); - out[7] = (unsigned char)(strm->total_in >> 24); - len = 8; - do { - ret = write(gd, out + 8 - len, len); - if (ret == -1) bye("writing gzip file", ""); - len -= ret; - } while (len); - close(gd); - } - - /* clean up and return */ - free(out); - free(in); - if (fd > 0) close(fd); -} - -/* process the compression level option if present, scan the gzip file, and - append the specified files, or append the data from stdin if no other file - names are provided on the command line -- the gzip file must be writable - and seekable */ -int main(int argc, char **argv) -{ - int gd, level; - z_stream strm; - - /* ignore command name */ - argc--; argv++; - - /* provide usage if no arguments */ - if (*argv == NULL) { - printf( - "gzappend 1.2 (11 Oct 2012) Copyright (C) 2003, 2012 Mark Adler\n" - ); - printf( - "usage: gzappend [-level] file.gz [ addthis [ andthis ... ]]\n"); - return 0; - } - - /* set compression level */ - level = Z_DEFAULT_COMPRESSION; - if (argv[0][0] == '-') { - if (argv[0][1] < '0' || argv[0][1] > '9' || argv[0][2] != 0) - bye("invalid compression level", ""); - level = argv[0][1] - '0'; - if (*++argv == NULL) bye("no gzip file name after options", ""); - } - - /* prepare to append to gzip file */ - gd = gzscan(*argv++, &strm, level); - - /* append files on command line, or from stdin if none */ - if (*argv == NULL) - gztack(NULL, gd, &strm, 1); - else - do { - gztack(*argv, gd, &strm, argv[1] == NULL); - } while (*++argv != NULL); - return 0; -} diff --git a/deps/zlib/examples/gzjoin.c b/deps/zlib/examples/gzjoin.c deleted file mode 100644 index 89e8098441b6b5..00000000000000 --- a/deps/zlib/examples/gzjoin.c +++ /dev/null @@ -1,449 +0,0 @@ -/* gzjoin -- command to join gzip files into one gzip file - - Copyright (C) 2004, 2005, 2012 Mark Adler, all rights reserved - version 1.2, 14 Aug 2012 - - This software is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Mark Adler madler@alumni.caltech.edu - */ - -/* - * Change history: - * - * 1.0 11 Dec 2004 - First version - * 1.1 12 Jun 2005 - Changed ssize_t to long for portability - * 1.2 14 Aug 2012 - Clean up for z_const usage - */ - -/* - gzjoin takes one or more gzip files on the command line and writes out a - single gzip file that will uncompress to the concatenation of the - uncompressed data from the individual gzip files. gzjoin does this without - having to recompress any of the data and without having to calculate a new - crc32 for the concatenated uncompressed data. gzjoin does however have to - decompress all of the input data in order to find the bits in the compressed - data that need to be modified to concatenate the streams. - - gzjoin does not do an integrity check on the input gzip files other than - checking the gzip header and decompressing the compressed data. They are - otherwise assumed to be complete and correct. - - Each joint between gzip files removes at least 18 bytes of previous trailer - and subsequent header, and inserts an average of about three bytes to the - compressed data in order to connect the streams. The output gzip file - has a minimal ten-byte gzip header with no file name or modification time. - - This program was written to illustrate the use of the Z_BLOCK option of - inflate() and the crc32_combine() function. gzjoin will not compile with - versions of zlib earlier than 1.2.3. - */ - -#include /* fputs(), fprintf(), fwrite(), putc() */ -#include /* exit(), malloc(), free() */ -#include /* open() */ -#include /* close(), read(), lseek() */ -#include "zlib.h" - /* crc32(), crc32_combine(), inflateInit2(), inflate(), inflateEnd() */ - -#define local static - -/* exit with an error (return a value to allow use in an expression) */ -local int bail(char *why1, char *why2) -{ - fprintf(stderr, "gzjoin error: %s%s, output incomplete\n", why1, why2); - exit(1); - return 0; -} - -/* -- simple buffered file input with access to the buffer -- */ - -#define CHUNK 32768 /* must be a power of two and fit in unsigned */ - -/* bin buffered input file type */ -typedef struct { - char *name; /* name of file for error messages */ - int fd; /* file descriptor */ - unsigned left; /* bytes remaining at next */ - unsigned char *next; /* next byte to read */ - unsigned char *buf; /* allocated buffer of length CHUNK */ -} bin; - -/* close a buffered file and free allocated memory */ -local void bclose(bin *in) -{ - if (in != NULL) { - if (in->fd != -1) - close(in->fd); - if (in->buf != NULL) - free(in->buf); - free(in); - } -} - -/* open a buffered file for input, return a pointer to type bin, or NULL on - failure */ -local bin *bopen(char *name) -{ - bin *in; - - in = malloc(sizeof(bin)); - if (in == NULL) - return NULL; - in->buf = malloc(CHUNK); - in->fd = open(name, O_RDONLY, 0); - if (in->buf == NULL || in->fd == -1) { - bclose(in); - return NULL; - } - in->left = 0; - in->next = in->buf; - in->name = name; - return in; -} - -/* load buffer from file, return -1 on read error, 0 or 1 on success, with - 1 indicating that end-of-file was reached */ -local int bload(bin *in) -{ - long len; - - if (in == NULL) - return -1; - if (in->left != 0) - return 0; - in->next = in->buf; - do { - len = (long)read(in->fd, in->buf + in->left, CHUNK - in->left); - if (len < 0) - return -1; - in->left += (unsigned)len; - } while (len != 0 && in->left < CHUNK); - return len == 0 ? 1 : 0; -} - -/* get a byte from the file, bail if end of file */ -#define bget(in) (in->left ? 0 : bload(in), \ - in->left ? (in->left--, *(in->next)++) : \ - bail("unexpected end of file on ", in->name)) - -/* get a four-byte little-endian unsigned integer from file */ -local unsigned long bget4(bin *in) -{ - unsigned long val; - - val = bget(in); - val += (unsigned long)(bget(in)) << 8; - val += (unsigned long)(bget(in)) << 16; - val += (unsigned long)(bget(in)) << 24; - return val; -} - -/* skip bytes in file */ -local void bskip(bin *in, unsigned skip) -{ - /* check pointer */ - if (in == NULL) - return; - - /* easy case -- skip bytes in buffer */ - if (skip <= in->left) { - in->left -= skip; - in->next += skip; - return; - } - - /* skip what's in buffer, discard buffer contents */ - skip -= in->left; - in->left = 0; - - /* seek past multiples of CHUNK bytes */ - if (skip > CHUNK) { - unsigned left; - - left = skip & (CHUNK - 1); - if (left == 0) { - /* exact number of chunks: seek all the way minus one byte to check - for end-of-file with a read */ - lseek(in->fd, skip - 1, SEEK_CUR); - if (read(in->fd, in->buf, 1) != 1) - bail("unexpected end of file on ", in->name); - return; - } - - /* skip the integral chunks, update skip with remainder */ - lseek(in->fd, skip - left, SEEK_CUR); - skip = left; - } - - /* read more input and skip remainder */ - bload(in); - if (skip > in->left) - bail("unexpected end of file on ", in->name); - in->left -= skip; - in->next += skip; -} - -/* -- end of buffered input functions -- */ - -/* skip the gzip header from file in */ -local void gzhead(bin *in) -{ - int flags; - - /* verify gzip magic header and compression method */ - if (bget(in) != 0x1f || bget(in) != 0x8b || bget(in) != 8) - bail(in->name, " is not a valid gzip file"); - - /* get and verify flags */ - flags = bget(in); - if ((flags & 0xe0) != 0) - bail("unknown reserved bits set in ", in->name); - - /* skip modification time, extra flags, and os */ - bskip(in, 6); - - /* skip extra field if present */ - if (flags & 4) { - unsigned len; - - len = bget(in); - len += (unsigned)(bget(in)) << 8; - bskip(in, len); - } - - /* skip file name if present */ - if (flags & 8) - while (bget(in) != 0) - ; - - /* skip comment if present */ - if (flags & 16) - while (bget(in) != 0) - ; - - /* skip header crc if present */ - if (flags & 2) - bskip(in, 2); -} - -/* write a four-byte little-endian unsigned integer to out */ -local void put4(unsigned long val, FILE *out) -{ - putc(val & 0xff, out); - putc((val >> 8) & 0xff, out); - putc((val >> 16) & 0xff, out); - putc((val >> 24) & 0xff, out); -} - -/* Load up zlib stream from buffered input, bail if end of file */ -local void zpull(z_streamp strm, bin *in) -{ - if (in->left == 0) - bload(in); - if (in->left == 0) - bail("unexpected end of file on ", in->name); - strm->avail_in = in->left; - strm->next_in = in->next; -} - -/* Write header for gzip file to out and initialize trailer. */ -local void gzinit(unsigned long *crc, unsigned long *tot, FILE *out) -{ - fwrite("\x1f\x8b\x08\0\0\0\0\0\0\xff", 1, 10, out); - *crc = crc32(0L, Z_NULL, 0); - *tot = 0; -} - -/* Copy the compressed data from name, zeroing the last block bit of the last - block if clr is true, and adding empty blocks as needed to get to a byte - boundary. If clr is false, then the last block becomes the last block of - the output, and the gzip trailer is written. crc and tot maintains the - crc and length (modulo 2^32) of the output for the trailer. The resulting - gzip file is written to out. gzinit() must be called before the first call - of gzcopy() to write the gzip header and to initialize crc and tot. */ -local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot, - FILE *out) -{ - int ret; /* return value from zlib functions */ - int pos; /* where the "last block" bit is in byte */ - int last; /* true if processing the last block */ - bin *in; /* buffered input file */ - unsigned char *start; /* start of compressed data in buffer */ - unsigned char *junk; /* buffer for uncompressed data -- discarded */ - z_off_t len; /* length of uncompressed data (support > 4 GB) */ - z_stream strm; /* zlib inflate stream */ - - /* open gzip file and skip header */ - in = bopen(name); - if (in == NULL) - bail("could not open ", name); - gzhead(in); - - /* allocate buffer for uncompressed data and initialize raw inflate - stream */ - junk = malloc(CHUNK); - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit2(&strm, -15); - if (junk == NULL || ret != Z_OK) - bail("out of memory", ""); - - /* inflate and copy compressed data, clear last-block bit if requested */ - len = 0; - zpull(&strm, in); - start = in->next; - last = start[0] & 1; - if (last && clr) - start[0] &= ~1; - strm.avail_out = 0; - for (;;) { - /* if input used and output done, write used input and get more */ - if (strm.avail_in == 0 && strm.avail_out != 0) { - fwrite(start, 1, strm.next_in - start, out); - start = in->buf; - in->left = 0; - zpull(&strm, in); - } - - /* decompress -- return early when end-of-block reached */ - strm.avail_out = CHUNK; - strm.next_out = junk; - ret = inflate(&strm, Z_BLOCK); - switch (ret) { - case Z_MEM_ERROR: - bail("out of memory", ""); - case Z_DATA_ERROR: - bail("invalid compressed data in ", in->name); - } - - /* update length of uncompressed data */ - len += CHUNK - strm.avail_out; - - /* check for block boundary (only get this when block copied out) */ - if (strm.data_type & 128) { - /* if that was the last block, then done */ - if (last) - break; - - /* number of unused bits in last byte */ - pos = strm.data_type & 7; - - /* find the next last-block bit */ - if (pos != 0) { - /* next last-block bit is in last used byte */ - pos = 0x100 >> pos; - last = strm.next_in[-1] & pos; - if (last && clr) - in->buf[strm.next_in - in->buf - 1] &= ~pos; - } - else { - /* next last-block bit is in next unused byte */ - if (strm.avail_in == 0) { - /* don't have that byte yet -- get it */ - fwrite(start, 1, strm.next_in - start, out); - start = in->buf; - in->left = 0; - zpull(&strm, in); - } - last = strm.next_in[0] & 1; - if (last && clr) - in->buf[strm.next_in - in->buf] &= ~1; - } - } - } - - /* update buffer with unused input */ - in->left = strm.avail_in; - in->next = in->buf + (strm.next_in - in->buf); - - /* copy used input, write empty blocks to get to byte boundary */ - pos = strm.data_type & 7; - fwrite(start, 1, in->next - start - 1, out); - last = in->next[-1]; - if (pos == 0 || !clr) - /* already at byte boundary, or last file: write last byte */ - putc(last, out); - else { - /* append empty blocks to last byte */ - last &= ((0x100 >> pos) - 1); /* assure unused bits are zero */ - if (pos & 1) { - /* odd -- append an empty stored block */ - putc(last, out); - if (pos == 1) - putc(0, out); /* two more bits in block header */ - fwrite("\0\0\xff\xff", 1, 4, out); - } - else { - /* even -- append 1, 2, or 3 empty fixed blocks */ - switch (pos) { - case 6: - putc(last | 8, out); - last = 0; - case 4: - putc(last | 0x20, out); - last = 0; - case 2: - putc(last | 0x80, out); - putc(0, out); - } - } - } - - /* update crc and tot */ - *crc = crc32_combine(*crc, bget4(in), len); - *tot += (unsigned long)len; - - /* clean up */ - inflateEnd(&strm); - free(junk); - bclose(in); - - /* write trailer if this is the last gzip file */ - if (!clr) { - put4(*crc, out); - put4(*tot, out); - } -} - -/* join the gzip files on the command line, write result to stdout */ -int main(int argc, char **argv) -{ - unsigned long crc, tot; /* running crc and total uncompressed length */ - - /* skip command name */ - argc--; - argv++; - - /* show usage if no arguments */ - if (argc == 0) { - fputs("gzjoin usage: gzjoin f1.gz [f2.gz [f3.gz ...]] > fjoin.gz\n", - stderr); - return 0; - } - - /* join gzip files on command line and write to stdout */ - gzinit(&crc, &tot, stdout); - while (argc--) - gzcopy(*argv++, argc, &crc, &tot, stdout); - - /* done */ - return 0; -} diff --git a/deps/zlib/examples/gzlog.c b/deps/zlib/examples/gzlog.c deleted file mode 100644 index b8c29274e8b9ec..00000000000000 --- a/deps/zlib/examples/gzlog.c +++ /dev/null @@ -1,1059 +0,0 @@ -/* - * gzlog.c - * Copyright (C) 2004, 2008, 2012, 2016 Mark Adler, all rights reserved - * For conditions of distribution and use, see copyright notice in gzlog.h - * version 2.2, 14 Aug 2012 - */ - -/* - gzlog provides a mechanism for frequently appending short strings to a gzip - file that is efficient both in execution time and compression ratio. The - strategy is to write the short strings in an uncompressed form to the end of - the gzip file, only compressing when the amount of uncompressed data has - reached a given threshold. - - gzlog also provides protection against interruptions in the process due to - system crashes. The status of the operation is recorded in an extra field - in the gzip file, and is only updated once the gzip file is brought to a - valid state. The last data to be appended or compressed is saved in an - auxiliary file, so that if the operation is interrupted, it can be completed - the next time an append operation is attempted. - - gzlog maintains another auxiliary file with the last 32K of data from the - compressed portion, which is preloaded for the compression of the subsequent - data. This minimizes the impact to the compression ratio of appending. - */ - -/* - Operations Concept: - - Files (log name "foo"): - foo.gz -- gzip file with the complete log - foo.add -- last message to append or last data to compress - foo.dict -- dictionary of the last 32K of data for next compression - foo.temp -- temporary dictionary file for compression after this one - foo.lock -- lock file for reading and writing the other files - foo.repairs -- log file for log file recovery operations (not compressed) - - gzip file structure: - - fixed-length (no file name) header with extra field (see below) - - compressed data ending initially with empty stored block - - uncompressed data filling out originally empty stored block and - subsequent stored blocks as needed (16K max each) - - gzip trailer - - no junk at end (no other gzip streams) - - When appending data, the information in the first three items above plus the - foo.add file are sufficient to recover an interrupted append operation. The - extra field has the necessary information to restore the start of the last - stored block and determine where to append the data in the foo.add file, as - well as the crc and length of the gzip data before the append operation. - - The foo.add file is created before the gzip file is marked for append, and - deleted after the gzip file is marked as complete. So if the append - operation is interrupted, the data to add will still be there. If due to - some external force, the foo.add file gets deleted between when the append - operation was interrupted and when recovery is attempted, the gzip file will - still be restored, but without the appended data. - - When compressing data, the information in the first two items above plus the - foo.add file are sufficient to recover an interrupted compress operation. - The extra field has the necessary information to find the end of the - compressed data, and contains both the crc and length of just the compressed - data and of the complete set of data including the contents of the foo.add - file. - - Again, the foo.add file is maintained during the compress operation in case - of an interruption. If in the unlikely event the foo.add file with the data - to be compressed is missing due to some external force, a gzip file with - just the previous compressed data will be reconstructed. In this case, all - of the data that was to be compressed is lost (approximately one megabyte). - This will not occur if all that happened was an interruption of the compress - operation. - - The third state that is marked is the replacement of the old dictionary with - the new dictionary after a compress operation. Once compression is - complete, the gzip file is marked as being in the replace state. This - completes the gzip file, so an interrupt after being so marked does not - result in recompression. Then the dictionary file is replaced, and the gzip - file is marked as completed. This state prevents the possibility of - restarting compression with the wrong dictionary file. - - All three operations are wrapped by a lock/unlock procedure. In order to - gain exclusive access to the log files, first a foo.lock file must be - exclusively created. When all operations are complete, the lock is - released by deleting the foo.lock file. If when attempting to create the - lock file, it already exists and the modify time of the lock file is more - than five minutes old (set by the PATIENCE define below), then the old - lock file is considered stale and deleted, and the exclusive creation of - the lock file is retried. To assure that there are no false assessments - of the staleness of the lock file, the operations periodically touch the - lock file to update the modified date. - - Following is the definition of the extra field with all of the information - required to enable the above append and compress operations and their - recovery if interrupted. Multi-byte values are stored little endian - (consistent with the gzip format). File pointers are eight bytes long. - The crc's and lengths for the gzip trailer are four bytes long. (Note that - the length at the end of a gzip file is used for error checking only, and - for large files is actually the length modulo 2^32.) The stored block - length is two bytes long. The gzip extra field two-byte identification is - "ap" for append. It is assumed that writing the extra field to the file is - an "atomic" operation. That is, either all of the extra field is written - to the file, or none of it is, if the operation is interrupted right at the - point of updating the extra field. This is a reasonable assumption, since - the extra field is within the first 52 bytes of the file, which is smaller - than any expected block size for a mass storage device (usually 512 bytes or - larger). - - Extra field (35 bytes): - - Pointer to first stored block length -- this points to the two-byte length - of the first stored block, which is followed by the two-byte, one's - complement of that length. The stored block length is preceded by the - three-bit header of the stored block, which is the actual start of the - stored block in the deflate format. See the bit offset field below. - - Pointer to the last stored block length. This is the same as above, but - for the last stored block of the uncompressed data in the gzip file. - Initially this is the same as the first stored block length pointer. - When the stored block gets to 16K (see the MAX_STORE define), then a new - stored block as added, at which point the last stored block length pointer - is different from the first stored block length pointer. When they are - different, the first bit of the last stored block header is eight bits, or - one byte back from the block length. - - Compressed data crc and length. This is the crc and length of the data - that is in the compressed portion of the deflate stream. These are used - only in the event that the foo.add file containing the data to compress is - lost after a compress operation is interrupted. - - Total data crc and length. This is the crc and length of all of the data - stored in the gzip file, compressed and uncompressed. It is used to - reconstruct the gzip trailer when compressing, as well as when recovering - interrupted operations. - - Final stored block length. This is used to quickly find where to append, - and allows the restoration of the original final stored block state when - an append operation is interrupted. - - First stored block start as the number of bits back from the final stored - block first length byte. This value is in the range of 3..10, and is - stored as the low three bits of the final byte of the extra field after - subtracting three (0..7). This allows the last-block bit of the stored - block header to be updated when a new stored block is added, for the case - when the first stored block and the last stored block are the same. (When - they are different, the numbers of bits back is known to be eight.) This - also allows for new compressed data to be appended to the old compressed - data in the compress operation, overwriting the previous first stored - block, or for the compressed data to be terminated and a valid gzip file - reconstructed on the off chance that a compression operation was - interrupted and the data to compress in the foo.add file was deleted. - - The operation in process. This is the next two bits in the last byte (the - bits under the mask 0x18). The are interpreted as 0: nothing in process, - 1: append in process, 2: compress in process, 3: replace in process. - - The top three bits of the last byte in the extra field are reserved and - are currently set to zero. - - Main procedure: - - Exclusively create the foo.lock file using the O_CREAT and O_EXCL modes of - the system open() call. If the modify time of an existing lock file is - more than PATIENCE seconds old, then the lock file is deleted and the - exclusive create is retried. - - Load the extra field from the foo.gz file, and see if an operation was in - progress but not completed. If so, apply the recovery procedure below. - - Perform the append procedure with the provided data. - - If the uncompressed data in the foo.gz file is 1MB or more, apply the - compress procedure. - - Delete the foo.lock file. - - Append procedure: - - Put what to append in the foo.add file so that the operation can be - restarted if this procedure is interrupted. - - Mark the foo.gz extra field with the append operation in progress. - + Restore the original last-block bit and stored block length of the last - stored block from the information in the extra field, in case a previous - append operation was interrupted. - - Append the provided data to the last stored block, creating new stored - blocks as needed and updating the stored blocks last-block bits and - lengths. - - Update the crc and length with the new data, and write the gzip trailer. - - Write over the extra field (with a single write operation) with the new - pointers, lengths, and crc's, and mark the gzip file as not in process. - Though there is still a foo.add file, it will be ignored since nothing - is in process. If a foo.add file is leftover from a previously - completed operation, it is truncated when writing new data to it. - - Delete the foo.add file. - - Compress and replace procedures: - - Read all of the uncompressed data in the stored blocks in foo.gz and write - it to foo.add. Also write foo.temp with the last 32K of that data to - provide a dictionary for the next invocation of this procedure. - - Rewrite the extra field marking foo.gz with a compression in process. - * If there is no data provided to compress (due to a missing foo.add file - when recovering), reconstruct and truncate the foo.gz file to contain - only the previous compressed data and proceed to the step after the next - one. Otherwise ... - - Compress the data with the dictionary in foo.dict, and write to the - foo.gz file starting at the bit immediately following the last previously - compressed block. If there is no foo.dict, proceed anyway with the - compression at slightly reduced efficiency. (For the foo.dict file to be - missing requires some external failure beyond simply the interruption of - a compress operation.) During this process, the foo.lock file is - periodically touched to assure that that file is not considered stale by - another process before we're done. The deflation is terminated with a - non-last empty static block (10 bits long), that is then located and - written over by a last-bit-set empty stored block. - - Append the crc and length of the data in the gzip file (previously - calculated during the append operations). - - Write over the extra field with the updated stored block offsets, bits - back, crc's, and lengths, and mark foo.gz as in process for a replacement - of the dictionary. - @ Delete the foo.add file. - - Replace foo.dict with foo.temp. - - Write over the extra field, marking foo.gz as complete. - - Recovery procedure: - - If not a replace recovery, read in the foo.add file, and provide that data - to the appropriate recovery below. If there is no foo.add file, provide - a zero data length to the recovery. In that case, the append recovery - restores the foo.gz to the previous compressed + uncompressed data state. - For the the compress recovery, a missing foo.add file results in foo.gz - being restored to the previous compressed-only data state. - - Append recovery: - - Pick up append at + step above - - Compress recovery: - - Pick up compress at * step above - - Replace recovery: - - Pick up compress at @ step above - - Log the repair with a date stamp in foo.repairs - */ - -#include -#include /* rename, fopen, fprintf, fclose */ -#include /* malloc, free */ -#include /* strlen, strrchr, strcpy, strncpy, strcmp */ -#include /* open */ -#include /* lseek, read, write, close, unlink, sleep, */ - /* ftruncate, fsync */ -#include /* errno */ -#include /* time, ctime */ -#include /* stat */ -#include /* utimes */ -#include "zlib.h" /* crc32 */ - -#include "gzlog.h" /* header for external access */ - -#define local static -typedef unsigned int uint; -typedef unsigned long ulong; - -/* Macro for debugging to deterministically force recovery operations */ -#ifdef GZLOG_DEBUG - #include /* longjmp */ - jmp_buf gzlog_jump; /* where to go back to */ - int gzlog_bail = 0; /* which point to bail at (1..8) */ - int gzlog_count = -1; /* number of times through to wait */ -# define BAIL(n) do { if (n == gzlog_bail && gzlog_count-- == 0) \ - longjmp(gzlog_jump, gzlog_bail); } while (0) -#else -# define BAIL(n) -#endif - -/* how old the lock file can be in seconds before considering it stale */ -#define PATIENCE 300 - -/* maximum stored block size in Kbytes -- must be in 1..63 */ -#define MAX_STORE 16 - -/* number of stored Kbytes to trigger compression (must be >= 32 to allow - dictionary construction, and <= 204 * MAX_STORE, in order for >> 10 to - discard the stored block headers contribution of five bytes each) */ -#define TRIGGER 1024 - -/* size of a deflate dictionary (this cannot be changed) */ -#define DICT 32768U - -/* values for the operation (2 bits) */ -#define NO_OP 0 -#define APPEND_OP 1 -#define COMPRESS_OP 2 -#define REPLACE_OP 3 - -/* macros to extract little-endian integers from an unsigned byte buffer */ -#define PULL2(p) ((p)[0]+((uint)((p)[1])<<8)) -#define PULL4(p) (PULL2(p)+((ulong)PULL2(p+2)<<16)) -#define PULL8(p) (PULL4(p)+((off_t)PULL4(p+4)<<32)) - -/* macros to store integers into a byte buffer in little-endian order */ -#define PUT2(p,a) do {(p)[0]=a;(p)[1]=(a)>>8;} while(0) -#define PUT4(p,a) do {PUT2(p,a);PUT2(p+2,a>>16);} while(0) -#define PUT8(p,a) do {PUT4(p,a);PUT4(p+4,a>>32);} while(0) - -/* internal structure for log information */ -#define LOGID "\106\035\172" /* should be three non-zero characters */ -struct log { - char id[4]; /* contains LOGID to detect inadvertent overwrites */ - int fd; /* file descriptor for .gz file, opened read/write */ - char *path; /* allocated path, e.g. "/var/log/foo" or "foo" */ - char *end; /* end of path, for appending suffices such as ".gz" */ - off_t first; /* offset of first stored block first length byte */ - int back; /* location of first block id in bits back from first */ - uint stored; /* bytes currently in last stored block */ - off_t last; /* offset of last stored block first length byte */ - ulong ccrc; /* crc of compressed data */ - ulong clen; /* length (modulo 2^32) of compressed data */ - ulong tcrc; /* crc of total data */ - ulong tlen; /* length (modulo 2^32) of total data */ - time_t lock; /* last modify time of our lock file */ -}; - -/* gzip header for gzlog */ -local unsigned char log_gzhead[] = { - 0x1f, 0x8b, /* magic gzip id */ - 8, /* compression method is deflate */ - 4, /* there is an extra field (no file name) */ - 0, 0, 0, 0, /* no modification time provided */ - 0, 0xff, /* no extra flags, no OS specified */ - 39, 0, 'a', 'p', 35, 0 /* extra field with "ap" subfield */ - /* 35 is EXTRA, 39 is EXTRA + 4 */ -}; - -#define HEAD sizeof(log_gzhead) /* should be 16 */ - -/* initial gzip extra field content (52 == HEAD + EXTRA + 1) */ -local unsigned char log_gzext[] = { - 52, 0, 0, 0, 0, 0, 0, 0, /* offset of first stored block length */ - 52, 0, 0, 0, 0, 0, 0, 0, /* offset of last stored block length */ - 0, 0, 0, 0, 0, 0, 0, 0, /* compressed data crc and length */ - 0, 0, 0, 0, 0, 0, 0, 0, /* total data crc and length */ - 0, 0, /* final stored block data length */ - 5 /* op is NO_OP, last bit 8 bits back */ -}; - -#define EXTRA sizeof(log_gzext) /* should be 35 */ - -/* initial gzip data and trailer */ -local unsigned char log_gzbody[] = { - 1, 0, 0, 0xff, 0xff, /* empty stored block (last) */ - 0, 0, 0, 0, /* crc */ - 0, 0, 0, 0 /* uncompressed length */ -}; - -#define BODY sizeof(log_gzbody) - -/* Exclusively create foo.lock in order to negotiate exclusive access to the - foo.* files. If the modify time of an existing lock file is greater than - PATIENCE seconds in the past, then consider the lock file to have been - abandoned, delete it, and try the exclusive create again. Save the lock - file modify time for verification of ownership. Return 0 on success, or -1 - on failure, usually due to an access restriction or invalid path. Note that - if stat() or unlink() fails, it may be due to another process noticing the - abandoned lock file a smidge sooner and deleting it, so those are not - flagged as an error. */ -local int log_lock(struct log *log) -{ - int fd; - struct stat st; - - strcpy(log->end, ".lock"); - while ((fd = open(log->path, O_CREAT | O_EXCL, 0644)) < 0) { - if (errno != EEXIST) - return -1; - if (stat(log->path, &st) == 0 && time(NULL) - st.st_mtime > PATIENCE) { - unlink(log->path); - continue; - } - sleep(2); /* relinquish the CPU for two seconds while waiting */ - } - close(fd); - if (stat(log->path, &st) == 0) - log->lock = st.st_mtime; - return 0; -} - -/* Update the modify time of the lock file to now, in order to prevent another - task from thinking that the lock is stale. Save the lock file modify time - for verification of ownership. */ -local void log_touch(struct log *log) -{ - struct stat st; - - strcpy(log->end, ".lock"); - utimes(log->path, NULL); - if (stat(log->path, &st) == 0) - log->lock = st.st_mtime; -} - -/* Check the log file modify time against what is expected. Return true if - this is not our lock. If it is our lock, touch it to keep it. */ -local int log_check(struct log *log) -{ - struct stat st; - - strcpy(log->end, ".lock"); - if (stat(log->path, &st) || st.st_mtime != log->lock) - return 1; - log_touch(log); - return 0; -} - -/* Unlock a previously acquired lock, but only if it's ours. */ -local void log_unlock(struct log *log) -{ - if (log_check(log)) - return; - strcpy(log->end, ".lock"); - unlink(log->path); - log->lock = 0; -} - -/* Check the gzip header and read in the extra field, filling in the values in - the log structure. Return op on success or -1 if the gzip header was not as - expected. op is the current operation in progress last written to the extra - field. This assumes that the gzip file has already been opened, with the - file descriptor log->fd. */ -local int log_head(struct log *log) -{ - int op; - unsigned char buf[HEAD + EXTRA]; - - if (lseek(log->fd, 0, SEEK_SET) < 0 || - read(log->fd, buf, HEAD + EXTRA) != HEAD + EXTRA || - memcmp(buf, log_gzhead, HEAD)) { - return -1; - } - log->first = PULL8(buf + HEAD); - log->last = PULL8(buf + HEAD + 8); - log->ccrc = PULL4(buf + HEAD + 16); - log->clen = PULL4(buf + HEAD + 20); - log->tcrc = PULL4(buf + HEAD + 24); - log->tlen = PULL4(buf + HEAD + 28); - log->stored = PULL2(buf + HEAD + 32); - log->back = 3 + (buf[HEAD + 34] & 7); - op = (buf[HEAD + 34] >> 3) & 3; - return op; -} - -/* Write over the extra field contents, marking the operation as op. Use fsync - to assure that the device is written to, and in the requested order. This - operation, and only this operation, is assumed to be atomic in order to - assure that the log is recoverable in the event of an interruption at any - point in the process. Return -1 if the write to foo.gz failed. */ -local int log_mark(struct log *log, int op) -{ - int ret; - unsigned char ext[EXTRA]; - - PUT8(ext, log->first); - PUT8(ext + 8, log->last); - PUT4(ext + 16, log->ccrc); - PUT4(ext + 20, log->clen); - PUT4(ext + 24, log->tcrc); - PUT4(ext + 28, log->tlen); - PUT2(ext + 32, log->stored); - ext[34] = log->back - 3 + (op << 3); - fsync(log->fd); - ret = lseek(log->fd, HEAD, SEEK_SET) < 0 || - write(log->fd, ext, EXTRA) != EXTRA ? -1 : 0; - fsync(log->fd); - return ret; -} - -/* Rewrite the last block header bits and subsequent zero bits to get to a byte - boundary, setting the last block bit if last is true, and then write the - remainder of the stored block header (length and one's complement). Leave - the file pointer after the end of the last stored block data. Return -1 if - there is a read or write failure on the foo.gz file */ -local int log_last(struct log *log, int last) -{ - int back, len, mask; - unsigned char buf[6]; - - /* determine the locations of the bytes and bits to modify */ - back = log->last == log->first ? log->back : 8; - len = back > 8 ? 2 : 1; /* bytes back from log->last */ - mask = 0x80 >> ((back - 1) & 7); /* mask for block last-bit */ - - /* get the byte to modify (one or two back) into buf[0] -- don't need to - read the byte if the last-bit is eight bits back, since in that case - the entire byte will be modified */ - buf[0] = 0; - if (back != 8 && (lseek(log->fd, log->last - len, SEEK_SET) < 0 || - read(log->fd, buf, 1) != 1)) - return -1; - - /* change the last-bit of the last stored block as requested -- note - that all bits above the last-bit are set to zero, per the type bits - of a stored block being 00 and per the convention that the bits to - bring the stream to a byte boundary are also zeros */ - buf[1] = 0; - buf[2 - len] = (*buf & (mask - 1)) + (last ? mask : 0); - - /* write the modified stored block header and lengths, move the file - pointer to after the last stored block data */ - PUT2(buf + 2, log->stored); - PUT2(buf + 4, log->stored ^ 0xffff); - return lseek(log->fd, log->last - len, SEEK_SET) < 0 || - write(log->fd, buf + 2 - len, len + 4) != len + 4 || - lseek(log->fd, log->stored, SEEK_CUR) < 0 ? -1 : 0; -} - -/* Append len bytes from data to the locked and open log file. len may be zero - if recovering and no .add file was found. In that case, the previous state - of the foo.gz file is restored. The data is appended uncompressed in - deflate stored blocks. Return -1 if there was an error reading or writing - the foo.gz file. */ -local int log_append(struct log *log, unsigned char *data, size_t len) -{ - uint put; - off_t end; - unsigned char buf[8]; - - /* set the last block last-bit and length, in case recovering an - interrupted append, then position the file pointer to append to the - block */ - if (log_last(log, 1)) - return -1; - - /* append, adding stored blocks and updating the offset of the last stored - block as needed, and update the total crc and length */ - while (len) { - /* append as much as we can to the last block */ - put = (MAX_STORE << 10) - log->stored; - if (put > len) - put = (uint)len; - if (put) { - if (write(log->fd, data, put) != put) - return -1; - BAIL(1); - log->tcrc = crc32(log->tcrc, data, put); - log->tlen += put; - log->stored += put; - data += put; - len -= put; - } - - /* if we need to, add a new empty stored block */ - if (len) { - /* mark current block as not last */ - if (log_last(log, 0)) - return -1; - - /* point to new, empty stored block */ - log->last += 4 + log->stored + 1; - log->stored = 0; - } - - /* mark last block as last, update its length */ - if (log_last(log, 1)) - return -1; - BAIL(2); - } - - /* write the new crc and length trailer, and truncate just in case (could - be recovering from partial append with a missing foo.add file) */ - PUT4(buf, log->tcrc); - PUT4(buf + 4, log->tlen); - if (write(log->fd, buf, 8) != 8 || - (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end)) - return -1; - - /* write the extra field, marking the log file as done, delete .add file */ - if (log_mark(log, NO_OP)) - return -1; - strcpy(log->end, ".add"); - unlink(log->path); /* ignore error, since may not exist */ - return 0; -} - -/* Replace the foo.dict file with the foo.temp file. Also delete the foo.add - file, since the compress operation may have been interrupted before that was - done. Returns 1 if memory could not be allocated, or -1 if reading or - writing foo.gz fails, or if the rename fails for some reason other than - foo.temp not existing. foo.temp not existing is a permitted error, since - the replace operation may have been interrupted after the rename is done, - but before foo.gz is marked as complete. */ -local int log_replace(struct log *log) -{ - int ret; - char *dest; - - /* delete foo.add file */ - strcpy(log->end, ".add"); - unlink(log->path); /* ignore error, since may not exist */ - BAIL(3); - - /* rename foo.name to foo.dict, replacing foo.dict if it exists */ - strcpy(log->end, ".dict"); - dest = malloc(strlen(log->path) + 1); - if (dest == NULL) - return -2; - strcpy(dest, log->path); - strcpy(log->end, ".temp"); - ret = rename(log->path, dest); - free(dest); - if (ret && errno != ENOENT) - return -1; - BAIL(4); - - /* mark the foo.gz file as done */ - return log_mark(log, NO_OP); -} - -/* Compress the len bytes at data and append the compressed data to the - foo.gz deflate data immediately after the previous compressed data. This - overwrites the previous uncompressed data, which was stored in foo.add - and is the data provided in data[0..len-1]. If this operation is - interrupted, it picks up at the start of this routine, with the foo.add - file read in again. If there is no data to compress (len == 0), then we - simply terminate the foo.gz file after the previously compressed data, - appending a final empty stored block and the gzip trailer. Return -1 if - reading or writing the log.gz file failed, or -2 if there was a memory - allocation failure. */ -local int log_compress(struct log *log, unsigned char *data, size_t len) -{ - int fd; - uint got, max; - ssize_t dict; - off_t end; - z_stream strm; - unsigned char buf[DICT]; - - /* compress and append compressed data */ - if (len) { - /* set up for deflate, allocating memory */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8, - Z_DEFAULT_STRATEGY) != Z_OK) - return -2; - - /* read in dictionary (last 32K of data that was compressed) */ - strcpy(log->end, ".dict"); - fd = open(log->path, O_RDONLY, 0); - if (fd >= 0) { - dict = read(fd, buf, DICT); - close(fd); - if (dict < 0) { - deflateEnd(&strm); - return -1; - } - if (dict) - deflateSetDictionary(&strm, buf, (uint)dict); - } - log_touch(log); - - /* prime deflate with last bits of previous block, position write - pointer to write those bits and overwrite what follows */ - if (lseek(log->fd, log->first - (log->back > 8 ? 2 : 1), - SEEK_SET) < 0 || - read(log->fd, buf, 1) != 1 || lseek(log->fd, -1, SEEK_CUR) < 0) { - deflateEnd(&strm); - return -1; - } - deflatePrime(&strm, (8 - log->back) & 7, *buf); - - /* compress, finishing with a partial non-last empty static block */ - strm.next_in = data; - max = (((uint)0 - 1) >> 1) + 1; /* in case int smaller than size_t */ - do { - strm.avail_in = len > max ? max : (uint)len; - len -= strm.avail_in; - do { - strm.avail_out = DICT; - strm.next_out = buf; - deflate(&strm, len ? Z_NO_FLUSH : Z_PARTIAL_FLUSH); - got = DICT - strm.avail_out; - if (got && write(log->fd, buf, got) != got) { - deflateEnd(&strm); - return -1; - } - log_touch(log); - } while (strm.avail_out == 0); - } while (len); - deflateEnd(&strm); - BAIL(5); - - /* find start of empty static block -- scanning backwards the first one - bit is the second bit of the block, if the last byte is zero, then - we know the byte before that has a one in the top bit, since an - empty static block is ten bits long */ - if ((log->first = lseek(log->fd, -1, SEEK_CUR)) < 0 || - read(log->fd, buf, 1) != 1) - return -1; - log->first++; - if (*buf) { - log->back = 1; - while ((*buf & ((uint)1 << (8 - log->back++))) == 0) - ; /* guaranteed to terminate, since *buf != 0 */ - } - else - log->back = 10; - - /* update compressed crc and length */ - log->ccrc = log->tcrc; - log->clen = log->tlen; - } - else { - /* no data to compress -- fix up existing gzip stream */ - log->tcrc = log->ccrc; - log->tlen = log->clen; - } - - /* complete and truncate gzip stream */ - log->last = log->first; - log->stored = 0; - PUT4(buf, log->tcrc); - PUT4(buf + 4, log->tlen); - if (log_last(log, 1) || write(log->fd, buf, 8) != 8 || - (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end)) - return -1; - BAIL(6); - - /* mark as being in the replace operation */ - if (log_mark(log, REPLACE_OP)) - return -1; - - /* execute the replace operation and mark the file as done */ - return log_replace(log); -} - -/* log a repair record to the .repairs file */ -local void log_log(struct log *log, int op, char *record) -{ - time_t now; - FILE *rec; - - now = time(NULL); - strcpy(log->end, ".repairs"); - rec = fopen(log->path, "a"); - if (rec == NULL) - return; - fprintf(rec, "%.24s %s recovery: %s\n", ctime(&now), op == APPEND_OP ? - "append" : (op == COMPRESS_OP ? "compress" : "replace"), record); - fclose(rec); - return; -} - -/* Recover the interrupted operation op. First read foo.add for recovering an - append or compress operation. Return -1 if there was an error reading or - writing foo.gz or reading an existing foo.add, or -2 if there was a memory - allocation failure. */ -local int log_recover(struct log *log, int op) -{ - int fd, ret = 0; - unsigned char *data = NULL; - size_t len = 0; - struct stat st; - - /* log recovery */ - log_log(log, op, "start"); - - /* load foo.add file if expected and present */ - if (op == APPEND_OP || op == COMPRESS_OP) { - strcpy(log->end, ".add"); - if (stat(log->path, &st) == 0 && st.st_size) { - len = (size_t)(st.st_size); - if ((off_t)len != st.st_size || - (data = malloc(st.st_size)) == NULL) { - log_log(log, op, "allocation failure"); - return -2; - } - if ((fd = open(log->path, O_RDONLY, 0)) < 0) { - log_log(log, op, ".add file read failure"); - return -1; - } - ret = (size_t)read(fd, data, len) != len; - close(fd); - if (ret) { - log_log(log, op, ".add file read failure"); - return -1; - } - log_log(log, op, "loaded .add file"); - } - else - log_log(log, op, "missing .add file!"); - } - - /* recover the interrupted operation */ - switch (op) { - case APPEND_OP: - ret = log_append(log, data, len); - break; - case COMPRESS_OP: - ret = log_compress(log, data, len); - break; - case REPLACE_OP: - ret = log_replace(log); - } - - /* log status */ - log_log(log, op, ret ? "failure" : "complete"); - - /* clean up */ - if (data != NULL) - free(data); - return ret; -} - -/* Close the foo.gz file (if open) and release the lock. */ -local void log_close(struct log *log) -{ - if (log->fd >= 0) - close(log->fd); - log->fd = -1; - log_unlock(log); -} - -/* Open foo.gz, verify the header, and load the extra field contents, after - first creating the foo.lock file to gain exclusive access to the foo.* - files. If foo.gz does not exist or is empty, then write the initial header, - extra, and body content of an empty foo.gz log file. If there is an error - creating the lock file due to access restrictions, or an error reading or - writing the foo.gz file, or if the foo.gz file is not a proper log file for - this object (e.g. not a gzip file or does not contain the expected extra - field), then return true. If there is an error, the lock is released. - Otherwise, the lock is left in place. */ -local int log_open(struct log *log) -{ - int op; - - /* release open file resource if left over -- can occur if lock lost - between gzlog_open() and gzlog_write() */ - if (log->fd >= 0) - close(log->fd); - log->fd = -1; - - /* negotiate exclusive access */ - if (log_lock(log) < 0) - return -1; - - /* open the log file, foo.gz */ - strcpy(log->end, ".gz"); - log->fd = open(log->path, O_RDWR | O_CREAT, 0644); - if (log->fd < 0) { - log_close(log); - return -1; - } - - /* if new, initialize foo.gz with an empty log, delete old dictionary */ - if (lseek(log->fd, 0, SEEK_END) == 0) { - if (write(log->fd, log_gzhead, HEAD) != HEAD || - write(log->fd, log_gzext, EXTRA) != EXTRA || - write(log->fd, log_gzbody, BODY) != BODY) { - log_close(log); - return -1; - } - strcpy(log->end, ".dict"); - unlink(log->path); - } - - /* verify log file and load extra field information */ - if ((op = log_head(log)) < 0) { - log_close(log); - return -1; - } - - /* check for interrupted process and if so, recover */ - if (op != NO_OP && log_recover(log, op)) { - log_close(log); - return -1; - } - - /* touch the lock file to prevent another process from grabbing it */ - log_touch(log); - return 0; -} - -/* See gzlog.h for the description of the external methods below */ -gzlog *gzlog_open(char *path) -{ - size_t n; - struct log *log; - - /* check arguments */ - if (path == NULL || *path == 0) - return NULL; - - /* allocate and initialize log structure */ - log = malloc(sizeof(struct log)); - if (log == NULL) - return NULL; - strcpy(log->id, LOGID); - log->fd = -1; - - /* save path and end of path for name construction */ - n = strlen(path); - log->path = malloc(n + 9); /* allow for ".repairs" */ - if (log->path == NULL) { - free(log); - return NULL; - } - strcpy(log->path, path); - log->end = log->path + n; - - /* gain exclusive access and verify log file -- may perform a - recovery operation if needed */ - if (log_open(log)) { - free(log->path); - free(log); - return NULL; - } - - /* return pointer to log structure */ - return log; -} - -/* gzlog_compress() return values: - 0: all good - -1: file i/o error (usually access issue) - -2: memory allocation failure - -3: invalid log pointer argument */ -int gzlog_compress(gzlog *logd) -{ - int fd, ret; - uint block; - size_t len, next; - unsigned char *data, buf[5]; - struct log *log = logd; - - /* check arguments */ - if (log == NULL || strcmp(log->id, LOGID)) - return -3; - - /* see if we lost the lock -- if so get it again and reload the extra - field information (it probably changed), recover last operation if - necessary */ - if (log_check(log) && log_open(log)) - return -1; - - /* create space for uncompressed data */ - len = ((size_t)(log->last - log->first) & ~(((size_t)1 << 10) - 1)) + - log->stored; - if ((data = malloc(len)) == NULL) - return -2; - - /* do statement here is just a cheap trick for error handling */ - do { - /* read in the uncompressed data */ - if (lseek(log->fd, log->first - 1, SEEK_SET) < 0) - break; - next = 0; - while (next < len) { - if (read(log->fd, buf, 5) != 5) - break; - block = PULL2(buf + 1); - if (next + block > len || - read(log->fd, (char *)data + next, block) != block) - break; - next += block; - } - if (lseek(log->fd, 0, SEEK_CUR) != log->last + 4 + log->stored) - break; - log_touch(log); - - /* write the uncompressed data to the .add file */ - strcpy(log->end, ".add"); - fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd < 0) - break; - ret = (size_t)write(fd, data, len) != len; - if (ret | close(fd)) - break; - log_touch(log); - - /* write the dictionary for the next compress to the .temp file */ - strcpy(log->end, ".temp"); - fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd < 0) - break; - next = DICT > len ? len : DICT; - ret = (size_t)write(fd, (char *)data + len - next, next) != next; - if (ret | close(fd)) - break; - log_touch(log); - - /* roll back to compressed data, mark the compress in progress */ - log->last = log->first; - log->stored = 0; - if (log_mark(log, COMPRESS_OP)) - break; - BAIL(7); - - /* compress and append the data (clears mark) */ - ret = log_compress(log, data, len); - free(data); - return ret; - } while (0); - - /* broke out of do above on i/o error */ - free(data); - return -1; -} - -/* gzlog_write() return values: - 0: all good - -1: file i/o error (usually access issue) - -2: memory allocation failure - -3: invalid log pointer argument */ -int gzlog_write(gzlog *logd, void *data, size_t len) -{ - int fd, ret; - struct log *log = logd; - - /* check arguments */ - if (log == NULL || strcmp(log->id, LOGID)) - return -3; - if (data == NULL || len <= 0) - return 0; - - /* see if we lost the lock -- if so get it again and reload the extra - field information (it probably changed), recover last operation if - necessary */ - if (log_check(log) && log_open(log)) - return -1; - - /* create and write .add file */ - strcpy(log->end, ".add"); - fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd < 0) - return -1; - ret = (size_t)write(fd, data, len) != len; - if (ret | close(fd)) - return -1; - log_touch(log); - - /* mark log file with append in progress */ - if (log_mark(log, APPEND_OP)) - return -1; - BAIL(8); - - /* append data (clears mark) */ - if (log_append(log, data, len)) - return -1; - - /* check to see if it's time to compress -- if not, then done */ - if (((log->last - log->first) >> 10) + (log->stored >> 10) < TRIGGER) - return 0; - - /* time to compress */ - return gzlog_compress(log); -} - -/* gzlog_close() return values: - 0: ok - -3: invalid log pointer argument */ -int gzlog_close(gzlog *logd) -{ - struct log *log = logd; - - /* check arguments */ - if (log == NULL || strcmp(log->id, LOGID)) - return -3; - - /* close the log file and release the lock */ - log_close(log); - - /* free structure and return */ - if (log->path != NULL) - free(log->path); - strcpy(log->id, "bad"); - free(log); - return 0; -} diff --git a/deps/zlib/examples/gzlog.h b/deps/zlib/examples/gzlog.h deleted file mode 100644 index 86f0cecba5b402..00000000000000 --- a/deps/zlib/examples/gzlog.h +++ /dev/null @@ -1,91 +0,0 @@ -/* gzlog.h - Copyright (C) 2004, 2008, 2012 Mark Adler, all rights reserved - version 2.2, 14 Aug 2012 - - This software is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Mark Adler madler@alumni.caltech.edu - */ - -/* Version History: - 1.0 26 Nov 2004 First version - 2.0 25 Apr 2008 Complete redesign for recovery of interrupted operations - Interface changed slightly in that now path is a prefix - Compression now occurs as needed during gzlog_write() - gzlog_write() now always leaves the log file as valid gzip - 2.1 8 Jul 2012 Fix argument checks in gzlog_compress() and gzlog_write() - 2.2 14 Aug 2012 Clean up signed comparisons - */ - -/* - The gzlog object allows writing short messages to a gzipped log file, - opening the log file locked for small bursts, and then closing it. The log - object works by appending stored (uncompressed) data to the gzip file until - 1 MB has been accumulated. At that time, the stored data is compressed, and - replaces the uncompressed data in the file. The log file is truncated to - its new size at that time. After each write operation, the log file is a - valid gzip file that can decompressed to recover what was written. - - The gzlog operations can be interupted at any point due to an application or - system crash, and the log file will be recovered the next time the log is - opened with gzlog_open(). - */ - -#ifndef GZLOG_H -#define GZLOG_H - -/* gzlog object type */ -typedef void gzlog; - -/* Open a gzlog object, creating the log file if it does not exist. Return - NULL on error. Note that gzlog_open() could take a while to complete if it - has to wait to verify that a lock is stale (possibly for five minutes), or - if there is significant contention with other instantiations of this object - when locking the resource. path is the prefix of the file names created by - this object. If path is "foo", then the log file will be "foo.gz", and - other auxiliary files will be created and destroyed during the process: - "foo.dict" for a compression dictionary, "foo.temp" for a temporary (next) - dictionary, "foo.add" for data being added or compressed, "foo.lock" for the - lock file, and "foo.repairs" to log recovery operations performed due to - interrupted gzlog operations. A gzlog_open() followed by a gzlog_close() - will recover a previously interrupted operation, if any. */ -gzlog *gzlog_open(char *path); - -/* Write to a gzlog object. Return zero on success, -1 if there is a file i/o - error on any of the gzlog files (this should not happen if gzlog_open() - succeeded, unless the device has run out of space or leftover auxiliary - files have permissions or ownership that prevent their use), -2 if there is - a memory allocation failure, or -3 if the log argument is invalid (e.g. if - it was not created by gzlog_open()). This function will write data to the - file uncompressed, until 1 MB has been accumulated, at which time that data - will be compressed. The log file will be a valid gzip file upon successful - return. */ -int gzlog_write(gzlog *log, void *data, size_t len); - -/* Force compression of any uncompressed data in the log. This should be used - sparingly, if at all. The main application would be when a log file will - not be appended to again. If this is used to compress frequently while - appending, it will both significantly increase the execution time and - reduce the compression ratio. The return codes are the same as for - gzlog_write(). */ -int gzlog_compress(gzlog *log); - -/* Close a gzlog object. Return zero on success, -3 if the log argument is - invalid. The log object is freed, and so cannot be referenced again. */ -int gzlog_close(gzlog *log); - -#endif diff --git a/deps/zlib/examples/zlib_how.html b/deps/zlib/examples/zlib_how.html deleted file mode 100644 index 444ff1c9a32e85..00000000000000 --- a/deps/zlib/examples/zlib_how.html +++ /dev/null @@ -1,545 +0,0 @@ - - - - -zlib Usage Example - - - -

zlib Usage Example

-We often get questions about how the deflate() and inflate() functions should be used. -Users wonder when they should provide more input, when they should use more output, -what to do with a Z_BUF_ERROR, how to make sure the process terminates properly, and -so on. So for those who have read zlib.h (a few times), and -would like further edification, below is an annotated example in C of simple routines to compress and decompress -from an input file to an output file using deflate() and inflate() respectively. The -annotations are interspersed between lines of the code. So please read between the lines. -We hope this helps explain some of the intricacies of zlib. -

-Without further adieu, here is the program zpipe.c: -


-/* zpipe.c: example of proper use of zlib's inflate() and deflate()
-   Not copyrighted -- provided to the public domain
-   Version 1.4  11 December 2005  Mark Adler */
-
-/* Version history:
-   1.0  30 Oct 2004  First version
-   1.1   8 Nov 2004  Add void casting for unused return values
-                     Use switch statement for inflate() return values
-   1.2   9 Nov 2004  Add assertions to document zlib guarantees
-   1.3   6 Apr 2005  Remove incorrect assertion in inf()
-   1.4  11 Dec 2005  Add hack to avoid MSDOS end-of-line conversions
-                     Avoid some compiler warnings for input and output buffers
- */
-
-We now include the header files for the required definitions. From -stdio.h we use fopen(), fread(), fwrite(), -feof(), ferror(), and fclose() for file i/o, and -fputs() for error messages. From string.h we use -strcmp() for command line argument processing. -From assert.h we use the assert() macro. -From zlib.h -we use the basic compression functions deflateInit(), -deflate(), and deflateEnd(), and the basic decompression -functions inflateInit(), inflate(), and -inflateEnd(). -

-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include "zlib.h"
-
-This is an ugly hack required to avoid corruption of the input and output data on -Windows/MS-DOS systems. Without this, those systems would assume that the input and output -files are text, and try to convert the end-of-line characters from one standard to -another. That would corrupt binary data, and in particular would render the compressed data unusable. -This sets the input and output to binary which suppresses the end-of-line conversions. -SET_BINARY_MODE() will be used later on stdin and stdout, at the beginning of main(). -

-#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
-#  include <fcntl.h>
-#  include <io.h>
-#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
-#else
-#  define SET_BINARY_MODE(file)
-#endif
-
-CHUNK is simply the buffer size for feeding data to and pulling data -from the zlib routines. Larger buffer sizes would be more efficient, -especially for inflate(). If the memory is available, buffers sizes -on the order of 128K or 256K bytes should be used. -

-#define CHUNK 16384
-
-The def() routine compresses data from an input file to an output file. The output data -will be in the zlib format, which is different from the gzip or zip -formats. The zlib format has a very small header of only two bytes to identify it as -a zlib stream and to provide decoding information, and a four-byte trailer with a fast -check value to verify the integrity of the uncompressed data after decoding. -

-/* Compress from file source to file dest until EOF on source.
-   def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
-   allocated for processing, Z_STREAM_ERROR if an invalid compression
-   level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
-   version of the library linked do not match, or Z_ERRNO if there is
-   an error reading or writing the files. */
-int def(FILE *source, FILE *dest, int level)
-{
-
-Here are the local variables for def(). ret will be used for zlib -return codes. flush will keep track of the current flushing state for deflate(), -which is either no flushing, or flush to completion after the end of the input file is reached. -have is the amount of data returned from deflate(). The strm structure -is used to pass information to and from the zlib routines, and to maintain the -deflate() state. in and out are the input and output buffers for -deflate(). -

-    int ret, flush;
-    unsigned have;
-    z_stream strm;
-    unsigned char in[CHUNK];
-    unsigned char out[CHUNK];
-
-The first thing we do is to initialize the zlib state for compression using -deflateInit(). This must be done before the first use of deflate(). -The zalloc, zfree, and opaque fields in the strm -structure must be initialized before calling deflateInit(). Here they are -set to the zlib constant Z_NULL to request that zlib use -the default memory allocation routines. An application may also choose to provide -custom memory allocation routines here. deflateInit() will allocate on the -order of 256K bytes for the internal state. -(See zlib Technical Details.) -

-deflateInit() is called with a pointer to the structure to be initialized and -the compression level, which is an integer in the range of -1 to 9. Lower compression -levels result in faster execution, but less compression. Higher levels result in -greater compression, but slower execution. The zlib constant Z_DEFAULT_COMPRESSION, -equal to -1, -provides a good compromise between compression and speed and is equivalent to level 6. -Level 0 actually does no compression at all, and in fact expands the data slightly to produce -the zlib format (it is not a byte-for-byte copy of the input). -More advanced applications of zlib -may use deflateInit2() here instead. Such an application may want to reduce how -much memory will be used, at some price in compression. Or it may need to request a -gzip header and trailer instead of a zlib header and trailer, or raw -encoding with no header or trailer at all. -

-We must check the return value of deflateInit() against the zlib constant -Z_OK to make sure that it was able to -allocate memory for the internal state, and that the provided arguments were valid. -deflateInit() will also check that the version of zlib that the zlib.h -file came from matches the version of zlib actually linked with the program. This -is especially important for environments in which zlib is a shared library. -

-Note that an application can initialize multiple, independent zlib streams, which can -operate in parallel. The state information maintained in the structure allows the zlib -routines to be reentrant. -


-    /* allocate deflate state */
-    strm.zalloc = Z_NULL;
-    strm.zfree = Z_NULL;
-    strm.opaque = Z_NULL;
-    ret = deflateInit(&strm, level);
-    if (ret != Z_OK)
-        return ret;
-
-With the pleasantries out of the way, now we can get down to business. The outer do-loop -reads all of the input file and exits at the bottom of the loop once end-of-file is reached. -This loop contains the only call of deflate(). So we must make sure that all of the -input data has been processed and that all of the output data has been generated and consumed -before we fall out of the loop at the bottom. -

-    /* compress until end of file */
-    do {
-
-We start off by reading data from the input file. The number of bytes read is put directly -into avail_in, and a pointer to those bytes is put into next_in. We also -check to see if end-of-file on the input has been reached. If we are at the end of file, then flush is set to the -zlib constant Z_FINISH, which is later passed to deflate() to -indicate that this is the last chunk of input data to compress. We need to use feof() -to check for end-of-file as opposed to seeing if fewer than CHUNK bytes have been read. The -reason is that if the input file length is an exact multiple of CHUNK, we will miss -the fact that we got to the end-of-file, and not know to tell deflate() to finish -up the compressed stream. If we are not yet at the end of the input, then the zlib -constant Z_NO_FLUSH will be passed to deflate to indicate that we are still -in the middle of the uncompressed data. -

-If there is an error in reading from the input file, the process is aborted with -deflateEnd() being called to free the allocated zlib state before returning -the error. We wouldn't want a memory leak, now would we? deflateEnd() can be called -at any time after the state has been initialized. Once that's done, deflateInit() (or -deflateInit2()) would have to be called to start a new compression process. There is -no point here in checking the deflateEnd() return code. The deallocation can't fail. -


-        strm.avail_in = fread(in, 1, CHUNK, source);
-        if (ferror(source)) {
-            (void)deflateEnd(&strm);
-            return Z_ERRNO;
-        }
-        flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
-        strm.next_in = in;
-
-The inner do-loop passes our chunk of input data to deflate(), and then -keeps calling deflate() until it is done producing output. Once there is no more -new output, deflate() is guaranteed to have consumed all of the input, i.e., -avail_in will be zero. -

-        /* run deflate() on input until output buffer not full, finish
-           compression if all of source has been read in */
-        do {
-
-Output space is provided to deflate() by setting avail_out to the number -of available output bytes and next_out to a pointer to that space. -

-            strm.avail_out = CHUNK;
-            strm.next_out = out;
-
-Now we call the compression engine itself, deflate(). It takes as many of the -avail_in bytes at next_in as it can process, and writes as many as -avail_out bytes to next_out. Those counters and pointers are then -updated past the input data consumed and the output data written. It is the amount of -output space available that may limit how much input is consumed. -Hence the inner loop to make sure that -all of the input is consumed by providing more output space each time. Since avail_in -and next_in are updated by deflate(), we don't have to mess with those -between deflate() calls until it's all used up. -

-The parameters to deflate() are a pointer to the strm structure containing -the input and output information and the internal compression engine state, and a parameter -indicating whether and how to flush data to the output. Normally deflate will consume -several K bytes of input data before producing any output (except for the header), in order -to accumulate statistics on the data for optimum compression. It will then put out a burst of -compressed data, and proceed to consume more input before the next burst. Eventually, -deflate() -must be told to terminate the stream, complete the compression with provided input data, and -write out the trailer check value. deflate() will continue to compress normally as long -as the flush parameter is Z_NO_FLUSH. Once the Z_FINISH parameter is provided, -deflate() will begin to complete the compressed output stream. However depending on how -much output space is provided, deflate() may have to be called several times until it -has provided the complete compressed stream, even after it has consumed all of the input. The flush -parameter must continue to be Z_FINISH for those subsequent calls. -

-There are other values of the flush parameter that are used in more advanced applications. You can -force deflate() to produce a burst of output that encodes all of the input data provided -so far, even if it wouldn't have otherwise, for example to control data latency on a link with -compressed data. You can also ask that deflate() do that as well as erase any history up to -that point so that what follows can be decompressed independently, for example for random access -applications. Both requests will degrade compression by an amount depending on how often such -requests are made. -

-deflate() has a return value that can indicate errors, yet we do not check it here. Why -not? Well, it turns out that deflate() can do no wrong here. Let's go through -deflate()'s return values and dispense with them one by one. The possible values are -Z_OK, Z_STREAM_END, Z_STREAM_ERROR, or Z_BUF_ERROR. Z_OK -is, well, ok. Z_STREAM_END is also ok and will be returned for the last call of -deflate(). This is already guaranteed by calling deflate() with Z_FINISH -until it has no more output. Z_STREAM_ERROR is only possible if the stream is not -initialized properly, but we did initialize it properly. There is no harm in checking for -Z_STREAM_ERROR here, for example to check for the possibility that some -other part of the application inadvertently clobbered the memory containing the zlib state. -Z_BUF_ERROR will be explained further below, but -suffice it to say that this is simply an indication that deflate() could not consume -more input or produce more output. deflate() can be called again with more output space -or more available input, which it will be in this code. -


-            ret = deflate(&strm, flush);    /* no bad return value */
-            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
-
-Now we compute how much output deflate() provided on the last call, which is the -difference between how much space was provided before the call, and how much output space -is still available after the call. Then that data, if any, is written to the output file. -We can then reuse the output buffer for the next call of deflate(). Again if there -is a file i/o error, we call deflateEnd() before returning to avoid a memory leak. -

-            have = CHUNK - strm.avail_out;
-            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
-                (void)deflateEnd(&strm);
-                return Z_ERRNO;
-            }
-
-The inner do-loop is repeated until the last deflate() call fails to fill the -provided output buffer. Then we know that deflate() has done as much as it can with -the provided input, and that all of that input has been consumed. We can then fall out of this -loop and reuse the input buffer. -

-The way we tell that deflate() has no more output is by seeing that it did not fill -the output buffer, leaving avail_out greater than zero. However suppose that -deflate() has no more output, but just so happened to exactly fill the output buffer! -avail_out is zero, and we can't tell that deflate() has done all it can. -As far as we know, deflate() -has more output for us. So we call it again. But now deflate() produces no output -at all, and avail_out remains unchanged as CHUNK. That deflate() call -wasn't able to do anything, either consume input or produce output, and so it returns -Z_BUF_ERROR. (See, I told you I'd cover this later.) However this is not a problem at -all. Now we finally have the desired indication that deflate() is really done, -and so we drop out of the inner loop to provide more input to deflate(). -

-With flush set to Z_FINISH, this final set of deflate() calls will -complete the output stream. Once that is done, subsequent calls of deflate() would return -Z_STREAM_ERROR if the flush parameter is not Z_FINISH, and do no more processing -until the state is reinitialized. -

-Some applications of zlib have two loops that call deflate() -instead of the single inner loop we have here. The first loop would call -without flushing and feed all of the data to deflate(). The second loop would call -deflate() with no more -data and the Z_FINISH parameter to complete the process. As you can see from this -example, that can be avoided by simply keeping track of the current flush state. -


-        } while (strm.avail_out == 0);
-        assert(strm.avail_in == 0);     /* all input will be used */
-
-Now we check to see if we have already processed all of the input file. That information was -saved in the flush variable, so we see if that was set to Z_FINISH. If so, -then we're done and we fall out of the outer loop. We're guaranteed to get Z_STREAM_END -from the last deflate() call, since we ran it until the last chunk of input was -consumed and all of the output was generated. -

-        /* done when last data in file processed */
-    } while (flush != Z_FINISH);
-    assert(ret == Z_STREAM_END);        /* stream will be complete */
-
-The process is complete, but we still need to deallocate the state to avoid a memory leak -(or rather more like a memory hemorrhage if you didn't do this). Then -finally we can return with a happy return value. -

-    /* clean up and return */
-    (void)deflateEnd(&strm);
-    return Z_OK;
-}
-
-Now we do the same thing for decompression in the inf() routine. inf() -decompresses what is hopefully a valid zlib stream from the input file and writes the -uncompressed data to the output file. Much of the discussion above for def() -applies to inf() as well, so the discussion here will focus on the differences between -the two. -

-/* Decompress from file source to file dest until stream ends or EOF.
-   inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
-   allocated for processing, Z_DATA_ERROR if the deflate data is
-   invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
-   the version of the library linked do not match, or Z_ERRNO if there
-   is an error reading or writing the files. */
-int inf(FILE *source, FILE *dest)
-{
-
-The local variables have the same functionality as they do for def(). The -only difference is that there is no flush variable, since inflate() -can tell from the zlib stream itself when the stream is complete. -

-    int ret;
-    unsigned have;
-    z_stream strm;
-    unsigned char in[CHUNK];
-    unsigned char out[CHUNK];
-
-The initialization of the state is the same, except that there is no compression level, -of course, and two more elements of the structure are initialized. avail_in -and next_in must be initialized before calling inflateInit(). This -is because the application has the option to provide the start of the zlib stream in -order for inflateInit() to have access to information about the compression -method to aid in memory allocation. In the current implementation of zlib -(up through versions 1.2.x), the method-dependent memory allocations are deferred to the first call of -inflate() anyway. However those fields must be initialized since later versions -of zlib that provide more compression methods may take advantage of this interface. -In any case, no decompression is performed by inflateInit(), so the -avail_out and next_out fields do not need to be initialized before calling. -

-Here avail_in is set to zero and next_in is set to Z_NULL to -indicate that no input data is being provided. -


-    /* allocate inflate state */
-    strm.zalloc = Z_NULL;
-    strm.zfree = Z_NULL;
-    strm.opaque = Z_NULL;
-    strm.avail_in = 0;
-    strm.next_in = Z_NULL;
-    ret = inflateInit(&strm);
-    if (ret != Z_OK)
-        return ret;
-
-The outer do-loop decompresses input until inflate() indicates -that it has reached the end of the compressed data and has produced all of the uncompressed -output. This is in contrast to def() which processes all of the input file. -If end-of-file is reached before the compressed data self-terminates, then the compressed -data is incomplete and an error is returned. -

-    /* decompress until deflate stream ends or end of file */
-    do {
-
-We read input data and set the strm structure accordingly. If we've reached the -end of the input file, then we leave the outer loop and report an error, since the -compressed data is incomplete. Note that we may read more data than is eventually consumed -by inflate(), if the input file continues past the zlib stream. -For applications where zlib streams are embedded in other data, this routine would -need to be modified to return the unused data, or at least indicate how much of the input -data was not used, so the application would know where to pick up after the zlib stream. -

-        strm.avail_in = fread(in, 1, CHUNK, source);
-        if (ferror(source)) {
-            (void)inflateEnd(&strm);
-            return Z_ERRNO;
-        }
-        if (strm.avail_in == 0)
-            break;
-        strm.next_in = in;
-
-The inner do-loop has the same function it did in def(), which is to -keep calling inflate() until has generated all of the output it can with the -provided input. -

-        /* run inflate() on input until output buffer not full */
-        do {
-
-Just like in def(), the same output space is provided for each call of inflate(). -

-            strm.avail_out = CHUNK;
-            strm.next_out = out;
-
-Now we run the decompression engine itself. There is no need to adjust the flush parameter, since -the zlib format is self-terminating. The main difference here is that there are -return values that we need to pay attention to. Z_DATA_ERROR -indicates that inflate() detected an error in the zlib compressed data format, -which means that either the data is not a zlib stream to begin with, or that the data was -corrupted somewhere along the way since it was compressed. The other error to be processed is -Z_MEM_ERROR, which can occur since memory allocation is deferred until inflate() -needs it, unlike deflate(), whose memory is allocated at the start by deflateInit(). -

-Advanced applications may use -deflateSetDictionary() to prime deflate() with a set of likely data to improve the -first 32K or so of compression. This is noted in the zlib header, so inflate() -requests that that dictionary be provided before it can start to decompress. Without the dictionary, -correct decompression is not possible. For this routine, we have no idea what the dictionary is, -so the Z_NEED_DICT indication is converted to a Z_DATA_ERROR. -

-inflate() can also return Z_STREAM_ERROR, which should not be possible here, -but could be checked for as noted above for def(). Z_BUF_ERROR does not need to be -checked for here, for the same reasons noted for def(). Z_STREAM_END will be -checked for later. -


-            ret = inflate(&strm, Z_NO_FLUSH);
-            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
-            switch (ret) {
-            case Z_NEED_DICT:
-                ret = Z_DATA_ERROR;     /* and fall through */
-            case Z_DATA_ERROR:
-            case Z_MEM_ERROR:
-                (void)inflateEnd(&strm);
-                return ret;
-            }
-
-The output of inflate() is handled identically to that of deflate(). -

-            have = CHUNK - strm.avail_out;
-            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
-                (void)inflateEnd(&strm);
-                return Z_ERRNO;
-            }
-
-The inner do-loop ends when inflate() has no more output as indicated -by not filling the output buffer, just as for deflate(). In this case, we cannot -assert that strm.avail_in will be zero, since the deflate stream may end before the file -does. -

-        } while (strm.avail_out == 0);
-
-The outer do-loop ends when inflate() reports that it has reached the -end of the input zlib stream, has completed the decompression and integrity -check, and has provided all of the output. This is indicated by the inflate() -return value Z_STREAM_END. The inner loop is guaranteed to leave ret -equal to Z_STREAM_END if the last chunk of the input file read contained the end -of the zlib stream. So if the return value is not Z_STREAM_END, the -loop continues to read more input. -

-        /* done when inflate() says it's done */
-    } while (ret != Z_STREAM_END);
-
-At this point, decompression successfully completed, or we broke out of the loop due to no -more data being available from the input file. If the last inflate() return value -is not Z_STREAM_END, then the zlib stream was incomplete and a data error -is returned. Otherwise, we return with a happy return value. Of course, inflateEnd() -is called first to avoid a memory leak. -

-    /* clean up and return */
-    (void)inflateEnd(&strm);
-    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
-}
-
-That ends the routines that directly use zlib. The following routines make this -a command-line program by running data through the above routines from stdin to -stdout, and handling any errors reported by def() or inf(). -

-zerr() is used to interpret the possible error codes from def() -and inf(), as detailed in their comments above, and print out an error message. -Note that these are only a subset of the possible return values from deflate() -and inflate(). -


-/* report a zlib or i/o error */
-void zerr(int ret)
-{
-    fputs("zpipe: ", stderr);
-    switch (ret) {
-    case Z_ERRNO:
-        if (ferror(stdin))
-            fputs("error reading stdin\n", stderr);
-        if (ferror(stdout))
-            fputs("error writing stdout\n", stderr);
-        break;
-    case Z_STREAM_ERROR:
-        fputs("invalid compression level\n", stderr);
-        break;
-    case Z_DATA_ERROR:
-        fputs("invalid or incomplete deflate data\n", stderr);
-        break;
-    case Z_MEM_ERROR:
-        fputs("out of memory\n", stderr);
-        break;
-    case Z_VERSION_ERROR:
-        fputs("zlib version mismatch!\n", stderr);
-    }
-}
-
-Here is the main() routine used to test def() and inf(). The -zpipe command is simply a compression pipe from stdin to stdout, if -no arguments are given, or it is a decompression pipe if zpipe -d is used. If any other -arguments are provided, no compression or decompression is performed. Instead a usage -message is displayed. Examples are zpipe < foo.txt > foo.txt.z to compress, and -zpipe -d < foo.txt.z > foo.txt to decompress. -

-/* compress or decompress from stdin to stdout */
-int main(int argc, char **argv)
-{
-    int ret;
-
-    /* avoid end-of-line conversions */
-    SET_BINARY_MODE(stdin);
-    SET_BINARY_MODE(stdout);
-
-    /* do compression if no arguments */
-    if (argc == 1) {
-        ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
-        if (ret != Z_OK)
-            zerr(ret);
-        return ret;
-    }
-
-    /* do decompression if -d specified */
-    else if (argc == 2 && strcmp(argv[1], "-d") == 0) {
-        ret = inf(stdin, stdout);
-        if (ret != Z_OK)
-            zerr(ret);
-        return ret;
-    }
-
-    /* otherwise, report usage */
-    else {
-        fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr);
-        return 1;
-    }
-}
-
-
-Copyright (c) 2004, 2005 by Mark Adler
Last modified 11 December 2005
- - diff --git a/deps/zlib/examples/zpipe.c b/deps/zlib/examples/zpipe.c deleted file mode 100644 index 83535d1693580f..00000000000000 --- a/deps/zlib/examples/zpipe.c +++ /dev/null @@ -1,205 +0,0 @@ -/* zpipe.c: example of proper use of zlib's inflate() and deflate() - Not copyrighted -- provided to the public domain - Version 1.4 11 December 2005 Mark Adler */ - -/* Version history: - 1.0 30 Oct 2004 First version - 1.1 8 Nov 2004 Add void casting for unused return values - Use switch statement for inflate() return values - 1.2 9 Nov 2004 Add assertions to document zlib guarantees - 1.3 6 Apr 2005 Remove incorrect assertion in inf() - 1.4 11 Dec 2005 Add hack to avoid MSDOS end-of-line conversions - Avoid some compiler warnings for input and output buffers - */ - -#include -#include -#include -#include "zlib.h" - -#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) -# include -# include -# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -#else -# define SET_BINARY_MODE(file) -#endif - -#define CHUNK 16384 - -/* Compress from file source to file dest until EOF on source. - def() returns Z_OK on success, Z_MEM_ERROR if memory could not be - allocated for processing, Z_STREAM_ERROR if an invalid compression - level is supplied, Z_VERSION_ERROR if the version of zlib.h and the - version of the library linked do not match, or Z_ERRNO if there is - an error reading or writing the files. */ -int def(FILE *source, FILE *dest, int level) -{ - int ret, flush; - unsigned have; - z_stream strm; - unsigned char in[CHUNK]; - unsigned char out[CHUNK]; - - /* allocate deflate state */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - ret = deflateInit(&strm, level); - if (ret != Z_OK) - return ret; - - /* compress until end of file */ - do { - strm.avail_in = fread(in, 1, CHUNK, source); - if (ferror(source)) { - (void)deflateEnd(&strm); - return Z_ERRNO; - } - flush = feof(source) ? Z_FINISH : Z_NO_FLUSH; - strm.next_in = in; - - /* run deflate() on input until output buffer not full, finish - compression if all of source has been read in */ - do { - strm.avail_out = CHUNK; - strm.next_out = out; - ret = deflate(&strm, flush); /* no bad return value */ - assert(ret != Z_STREAM_ERROR); /* state not clobbered */ - have = CHUNK - strm.avail_out; - if (fwrite(out, 1, have, dest) != have || ferror(dest)) { - (void)deflateEnd(&strm); - return Z_ERRNO; - } - } while (strm.avail_out == 0); - assert(strm.avail_in == 0); /* all input will be used */ - - /* done when last data in file processed */ - } while (flush != Z_FINISH); - assert(ret == Z_STREAM_END); /* stream will be complete */ - - /* clean up and return */ - (void)deflateEnd(&strm); - return Z_OK; -} - -/* Decompress from file source to file dest until stream ends or EOF. - inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be - allocated for processing, Z_DATA_ERROR if the deflate data is - invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and - the version of the library linked do not match, or Z_ERRNO if there - is an error reading or writing the files. */ -int inf(FILE *source, FILE *dest) -{ - int ret; - unsigned have; - z_stream strm; - unsigned char in[CHUNK]; - unsigned char out[CHUNK]; - - /* allocate inflate state */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit(&strm); - if (ret != Z_OK) - return ret; - - /* decompress until deflate stream ends or end of file */ - do { - strm.avail_in = fread(in, 1, CHUNK, source); - if (ferror(source)) { - (void)inflateEnd(&strm); - return Z_ERRNO; - } - if (strm.avail_in == 0) - break; - strm.next_in = in; - - /* run inflate() on input until output buffer not full */ - do { - strm.avail_out = CHUNK; - strm.next_out = out; - ret = inflate(&strm, Z_NO_FLUSH); - assert(ret != Z_STREAM_ERROR); /* state not clobbered */ - switch (ret) { - case Z_NEED_DICT: - ret = Z_DATA_ERROR; /* and fall through */ - case Z_DATA_ERROR: - case Z_MEM_ERROR: - (void)inflateEnd(&strm); - return ret; - } - have = CHUNK - strm.avail_out; - if (fwrite(out, 1, have, dest) != have || ferror(dest)) { - (void)inflateEnd(&strm); - return Z_ERRNO; - } - } while (strm.avail_out == 0); - - /* done when inflate() says it's done */ - } while (ret != Z_STREAM_END); - - /* clean up and return */ - (void)inflateEnd(&strm); - return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; -} - -/* report a zlib or i/o error */ -void zerr(int ret) -{ - fputs("zpipe: ", stderr); - switch (ret) { - case Z_ERRNO: - if (ferror(stdin)) - fputs("error reading stdin\n", stderr); - if (ferror(stdout)) - fputs("error writing stdout\n", stderr); - break; - case Z_STREAM_ERROR: - fputs("invalid compression level\n", stderr); - break; - case Z_DATA_ERROR: - fputs("invalid or incomplete deflate data\n", stderr); - break; - case Z_MEM_ERROR: - fputs("out of memory\n", stderr); - break; - case Z_VERSION_ERROR: - fputs("zlib version mismatch!\n", stderr); - } -} - -/* compress or decompress from stdin to stdout */ -int main(int argc, char **argv) -{ - int ret; - - /* avoid end-of-line conversions */ - SET_BINARY_MODE(stdin); - SET_BINARY_MODE(stdout); - - /* do compression if no arguments */ - if (argc == 1) { - ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION); - if (ret != Z_OK) - zerr(ret); - return ret; - } - - /* do decompression if -d specified */ - else if (argc == 2 && strcmp(argv[1], "-d") == 0) { - ret = inf(stdin, stdout); - if (ret != Z_OK) - zerr(ret); - return ret; - } - - /* otherwise, report usage */ - else { - fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr); - return 1; - } -} diff --git a/deps/zlib/examples/zran.c b/deps/zlib/examples/zran.c deleted file mode 100644 index 4fec6594a6648e..00000000000000 --- a/deps/zlib/examples/zran.c +++ /dev/null @@ -1,409 +0,0 @@ -/* zran.c -- example of zlib/gzip stream indexing and random access - * Copyright (C) 2005, 2012 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - Version 1.1 29 Sep 2012 Mark Adler */ - -/* Version History: - 1.0 29 May 2005 First version - 1.1 29 Sep 2012 Fix memory reallocation error - */ - -/* Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary() - for random access of a compressed file. A file containing a zlib or gzip - stream is provided on the command line. The compressed stream is decoded in - its entirety, and an index built with access points about every SPAN bytes - in the uncompressed output. The compressed file is left open, and can then - be read randomly, having to decompress on the average SPAN/2 uncompressed - bytes before getting to the desired block of data. - - An access point can be created at the start of any deflate block, by saving - the starting file offset and bit of that block, and the 32K bytes of - uncompressed data that precede that block. Also the uncompressed offset of - that block is saved to provide a referece for locating a desired starting - point in the uncompressed stream. build_index() works by decompressing the - input zlib or gzip stream a block at a time, and at the end of each block - deciding if enough uncompressed data has gone by to justify the creation of - a new access point. If so, that point is saved in a data structure that - grows as needed to accommodate the points. - - To use the index, an offset in the uncompressed data is provided, for which - the latest access point at or preceding that offset is located in the index. - The input file is positioned to the specified location in the index, and if - necessary the first few bits of the compressed data is read from the file. - inflate is initialized with those bits and the 32K of uncompressed data, and - the decompression then proceeds until the desired offset in the file is - reached. Then the decompression continues to read the desired uncompressed - data from the file. - - Another approach would be to generate the index on demand. In that case, - requests for random access reads from the compressed data would try to use - the index, but if a read far enough past the end of the index is required, - then further index entries would be generated and added. - - There is some fair bit of overhead to starting inflation for the random - access, mainly copying the 32K byte dictionary. So if small pieces of the - file are being accessed, it would make sense to implement a cache to hold - some lookahead and avoid many calls to extract() for small lengths. - - Another way to build an index would be to use inflateCopy(). That would - not be constrained to have access points at block boundaries, but requires - more memory per access point, and also cannot be saved to file due to the - use of pointers in the state. The approach here allows for storage of the - index in a file. - */ - -#include -#include -#include -#include "zlib.h" - -#define local static - -#define SPAN 1048576L /* desired distance between access points */ -#define WINSIZE 32768U /* sliding window size */ -#define CHUNK 16384 /* file input buffer size */ - -/* access point entry */ -struct point { - off_t out; /* corresponding offset in uncompressed data */ - off_t in; /* offset in input file of first full byte */ - int bits; /* number of bits (1-7) from byte at in - 1, or 0 */ - unsigned char window[WINSIZE]; /* preceding 32K of uncompressed data */ -}; - -/* access point list */ -struct access { - int have; /* number of list entries filled in */ - int size; /* number of list entries allocated */ - struct point *list; /* allocated list */ -}; - -/* Deallocate an index built by build_index() */ -local void free_index(struct access *index) -{ - if (index != NULL) { - free(index->list); - free(index); - } -} - -/* Add an entry to the access point list. If out of memory, deallocate the - existing list and return NULL. */ -local struct access *addpoint(struct access *index, int bits, - off_t in, off_t out, unsigned left, unsigned char *window) -{ - struct point *next; - - /* if list is empty, create it (start with eight points) */ - if (index == NULL) { - index = malloc(sizeof(struct access)); - if (index == NULL) return NULL; - index->list = malloc(sizeof(struct point) << 3); - if (index->list == NULL) { - free(index); - return NULL; - } - index->size = 8; - index->have = 0; - } - - /* if list is full, make it bigger */ - else if (index->have == index->size) { - index->size <<= 1; - next = realloc(index->list, sizeof(struct point) * index->size); - if (next == NULL) { - free_index(index); - return NULL; - } - index->list = next; - } - - /* fill in entry and increment how many we have */ - next = index->list + index->have; - next->bits = bits; - next->in = in; - next->out = out; - if (left) - memcpy(next->window, window + WINSIZE - left, left); - if (left < WINSIZE) - memcpy(next->window + left, window, WINSIZE - left); - index->have++; - - /* return list, possibly reallocated */ - return index; -} - -/* Make one entire pass through the compressed stream and build an index, with - access points about every span bytes of uncompressed output -- span is - chosen to balance the speed of random access against the memory requirements - of the list, about 32K bytes per access point. Note that data after the end - of the first zlib or gzip stream in the file is ignored. build_index() - returns the number of access points on success (>= 1), Z_MEM_ERROR for out - of memory, Z_DATA_ERROR for an error in the input file, or Z_ERRNO for a - file read error. On success, *built points to the resulting index. */ -local int build_index(FILE *in, off_t span, struct access **built) -{ - int ret; - off_t totin, totout; /* our own total counters to avoid 4GB limit */ - off_t last; /* totout value of last access point */ - struct access *index; /* access points being generated */ - z_stream strm; - unsigned char input[CHUNK]; - unsigned char window[WINSIZE]; - - /* initialize inflate */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit2(&strm, 47); /* automatic zlib or gzip decoding */ - if (ret != Z_OK) - return ret; - - /* inflate the input, maintain a sliding window, and build an index -- this - also validates the integrity of the compressed data using the check - information at the end of the gzip or zlib stream */ - totin = totout = last = 0; - index = NULL; /* will be allocated by first addpoint() */ - strm.avail_out = 0; - do { - /* get some compressed data from input file */ - strm.avail_in = fread(input, 1, CHUNK, in); - if (ferror(in)) { - ret = Z_ERRNO; - goto build_index_error; - } - if (strm.avail_in == 0) { - ret = Z_DATA_ERROR; - goto build_index_error; - } - strm.next_in = input; - - /* process all of that, or until end of stream */ - do { - /* reset sliding window if necessary */ - if (strm.avail_out == 0) { - strm.avail_out = WINSIZE; - strm.next_out = window; - } - - /* inflate until out of input, output, or at end of block -- - update the total input and output counters */ - totin += strm.avail_in; - totout += strm.avail_out; - ret = inflate(&strm, Z_BLOCK); /* return at end of block */ - totin -= strm.avail_in; - totout -= strm.avail_out; - if (ret == Z_NEED_DICT) - ret = Z_DATA_ERROR; - if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) - goto build_index_error; - if (ret == Z_STREAM_END) - break; - - /* if at end of block, consider adding an index entry (note that if - data_type indicates an end-of-block, then all of the - uncompressed data from that block has been delivered, and none - of the compressed data after that block has been consumed, - except for up to seven bits) -- the totout == 0 provides an - entry point after the zlib or gzip header, and assures that the - index always has at least one access point; we avoid creating an - access point after the last block by checking bit 6 of data_type - */ - if ((strm.data_type & 128) && !(strm.data_type & 64) && - (totout == 0 || totout - last > span)) { - index = addpoint(index, strm.data_type & 7, totin, - totout, strm.avail_out, window); - if (index == NULL) { - ret = Z_MEM_ERROR; - goto build_index_error; - } - last = totout; - } - } while (strm.avail_in != 0); - } while (ret != Z_STREAM_END); - - /* clean up and return index (release unused entries in list) */ - (void)inflateEnd(&strm); - index->list = realloc(index->list, sizeof(struct point) * index->have); - index->size = index->have; - *built = index; - return index->size; - - /* return error */ - build_index_error: - (void)inflateEnd(&strm); - if (index != NULL) - free_index(index); - return ret; -} - -/* Use the index to read len bytes from offset into buf, return bytes read or - negative for error (Z_DATA_ERROR or Z_MEM_ERROR). If data is requested past - the end of the uncompressed data, then extract() will return a value less - than len, indicating how much as actually read into buf. This function - should not return a data error unless the file was modified since the index - was generated. extract() may also return Z_ERRNO if there is an error on - reading or seeking the input file. */ -local int extract(FILE *in, struct access *index, off_t offset, - unsigned char *buf, int len) -{ - int ret, skip; - z_stream strm; - struct point *here; - unsigned char input[CHUNK]; - unsigned char discard[WINSIZE]; - - /* proceed only if something reasonable to do */ - if (len < 0) - return 0; - - /* find where in stream to start */ - here = index->list; - ret = index->have; - while (--ret && here[1].out <= offset) - here++; - - /* initialize file and inflate state to start there */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit2(&strm, -15); /* raw inflate */ - if (ret != Z_OK) - return ret; - ret = fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET); - if (ret == -1) - goto extract_ret; - if (here->bits) { - ret = getc(in); - if (ret == -1) { - ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR; - goto extract_ret; - } - (void)inflatePrime(&strm, here->bits, ret >> (8 - here->bits)); - } - (void)inflateSetDictionary(&strm, here->window, WINSIZE); - - /* skip uncompressed bytes until offset reached, then satisfy request */ - offset -= here->out; - strm.avail_in = 0; - skip = 1; /* while skipping to offset */ - do { - /* define where to put uncompressed data, and how much */ - if (offset == 0 && skip) { /* at offset now */ - strm.avail_out = len; - strm.next_out = buf; - skip = 0; /* only do this once */ - } - if (offset > WINSIZE) { /* skip WINSIZE bytes */ - strm.avail_out = WINSIZE; - strm.next_out = discard; - offset -= WINSIZE; - } - else if (offset != 0) { /* last skip */ - strm.avail_out = (unsigned)offset; - strm.next_out = discard; - offset = 0; - } - - /* uncompress until avail_out filled, or end of stream */ - do { - if (strm.avail_in == 0) { - strm.avail_in = fread(input, 1, CHUNK, in); - if (ferror(in)) { - ret = Z_ERRNO; - goto extract_ret; - } - if (strm.avail_in == 0) { - ret = Z_DATA_ERROR; - goto extract_ret; - } - strm.next_in = input; - } - ret = inflate(&strm, Z_NO_FLUSH); /* normal inflate */ - if (ret == Z_NEED_DICT) - ret = Z_DATA_ERROR; - if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) - goto extract_ret; - if (ret == Z_STREAM_END) - break; - } while (strm.avail_out != 0); - - /* if reach end of stream, then don't keep trying to get more */ - if (ret == Z_STREAM_END) - break; - - /* do until offset reached and requested data read, or stream ends */ - } while (skip); - - /* compute number of uncompressed bytes read after offset */ - ret = skip ? 0 : len - strm.avail_out; - - /* clean up and return bytes read or error */ - extract_ret: - (void)inflateEnd(&strm); - return ret; -} - -/* Demonstrate the use of build_index() and extract() by processing the file - provided on the command line, and the extracting 16K from about 2/3rds of - the way through the uncompressed output, and writing that to stdout. */ -int main(int argc, char **argv) -{ - int len; - off_t offset; - FILE *in; - struct access *index = NULL; - unsigned char buf[CHUNK]; - - /* open input file */ - if (argc != 2) { - fprintf(stderr, "usage: zran file.gz\n"); - return 1; - } - in = fopen(argv[1], "rb"); - if (in == NULL) { - fprintf(stderr, "zran: could not open %s for reading\n", argv[1]); - return 1; - } - - /* build index */ - len = build_index(in, SPAN, &index); - if (len < 0) { - fclose(in); - switch (len) { - case Z_MEM_ERROR: - fprintf(stderr, "zran: out of memory\n"); - break; - case Z_DATA_ERROR: - fprintf(stderr, "zran: compressed data error in %s\n", argv[1]); - break; - case Z_ERRNO: - fprintf(stderr, "zran: read error on %s\n", argv[1]); - break; - default: - fprintf(stderr, "zran: error %d while building index\n", len); - } - return 1; - } - fprintf(stderr, "zran: built index with %d access points\n", len); - - /* use index by reading some bytes from an arbitrary offset */ - offset = (index->list[index->have - 1].out << 1) / 3; - len = extract(in, index, offset, buf, CHUNK); - if (len < 0) - fprintf(stderr, "zran: extraction failed: %s error\n", - len == Z_MEM_ERROR ? "out of memory" : "input corrupted"); - else { - fwrite(buf, 1, len, stdout); - fprintf(stderr, "zran: extracted %d bytes at %llu\n", len, offset); - } - - /* clean up and exit */ - free_index(index); - fclose(in); - return 0; -} diff --git a/deps/zlib/fill_window_sse.c b/deps/zlib/fill_window_sse.c new file mode 100644 index 00000000000000..ed1e5d1d6735b1 --- /dev/null +++ b/deps/zlib/fill_window_sse.c @@ -0,0 +1,177 @@ +/* + * Fill Window with SSE2-optimized hash shifting + * + * Copyright (C) 2013 Intel Corporation + * Authors: + * Arjan van de Ven + * Jim Kukunas + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include +#include "deflate.h" + +#define UPDATE_HASH(s,h,i) \ + {\ + if (s->level < 6) { \ + h = (3483 * (s->window[i]) +\ + 23081* (s->window[i+1]) +\ + 6954 * (s->window[i+2]) +\ + 20947* (s->window[i+3])) & s->hash_mask;\ + } else {\ + h = (25881* (s->window[i]) +\ + 24674* (s->window[i+1]) +\ + 25811* (s->window[i+2])) & s->hash_mask;\ + }\ + }\ + +extern int deflate_read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); + +void fill_window_sse(deflate_state *s) +{ + const __m128i xmm_wsize = _mm_set1_epi16(s->w_size); + + register unsigned n; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + p -= 8; + do { + __m128i value, result; + + value = _mm_loadu_si128((__m128i *)p); + result = _mm_subs_epu16(value, xmm_wsize); + _mm_storeu_si128((__m128i *)p, result); + + p -= 8; + n -= 8; + } while (n > 0); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + p -= 8; + do { + __m128i value, result; + + value = _mm_loadu_si128((__m128i *)p); + result = _mm_subs_epu16(value, xmm_wsize); + _mm_storeu_si128((__m128i *)p, result); + + p -= 8; + n -= 8; + } while (n > 0); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) break; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = deflate_read_buf(s->strm, + s->window + s->strstart + s->lookahead, + more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + uInt str = s->strstart; + s->ins_h = s->window[str]; + if (str >= 1) + UPDATE_HASH(s, s->ins_h, str + 1 - (MIN_MATCH-1)); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + ulg curr = s->strstart + (ulg)(s->lookahead); + ulg init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + zmemzero(s->window + curr, (unsigned)init); + s->high_water = curr + init; + } + else if (s->high_water < (ulg)curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = (ulg)curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + zmemzero(s->window + s->high_water, (unsigned)init); + s->high_water += init; + } + } + + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "not enough room for search"); +} diff --git a/deps/zlib/google/BUILD.gn b/deps/zlib/google/BUILD.gn new file mode 100644 index 00000000000000..4024836205f64c --- /dev/null +++ b/deps/zlib/google/BUILD.gn @@ -0,0 +1,48 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build_overrides/build.gni") + +if (build_with_chromium) { + static_library("zip") { + sources = [ + "zip.cc", + "zip.h", + "zip_internal.cc", + "zip_internal.h", + "zip_reader.cc", + "zip_reader.h", + "zip_writer.cc", + "zip_writer.h", + ] + deps = [ + "//base", + "//third_party/zlib:minizip", + ] + } + + static_library("compression_utils") { + sources = [ + "compression_utils.cc", + "compression_utils.h", + ] + deps = [ + ":compression_utils_portable", + "//base", + "//third_party/zlib", + ] + } +} + +# This allows other users of Chromium's zlib library, but don't use Chromium's +# //base, to reuse some boilerplate code. +static_library("compression_utils_portable") { + sources = [ + "compression_utils_portable.cc", + "compression_utils_portable.h", + ] + deps = [ + "//third_party/zlib", + ] +} diff --git a/deps/zlib/google/DEPS b/deps/zlib/google/DEPS new file mode 100644 index 00000000000000..144fbd149295b3 --- /dev/null +++ b/deps/zlib/google/DEPS @@ -0,0 +1,5 @@ +include_rules = [ + '+base', + '+build', + '+testing', +] diff --git a/deps/zlib/google/OWNERS b/deps/zlib/google/OWNERS new file mode 100644 index 00000000000000..1ca25314631124 --- /dev/null +++ b/deps/zlib/google/OWNERS @@ -0,0 +1,5 @@ +satorux@chromium.org + +# compression_utils* +asvitkine@chromium.org +isherman@chromium.org diff --git a/deps/zlib/google/compression_utils.cc b/deps/zlib/google/compression_utils.cc new file mode 100644 index 00000000000000..9f63a840167d47 --- /dev/null +++ b/deps/zlib/google/compression_utils.cc @@ -0,0 +1,116 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/zlib/google/compression_utils.h" + +#include "base/bit_cast.h" +#include "base/logging.h" +#include "base/process/memory.h" +#include "base/strings/string_piece.h" +#include "base/sys_byteorder.h" + +#include "third_party/zlib/google/compression_utils_portable.h" + +namespace compression { + +bool GzipCompress(base::StringPiece input, + char* output_buffer, + size_t output_buffer_size, + size_t* compressed_size, + void* (*malloc_fn)(size_t), + void (*free_fn)(void*)) { + static_assert(sizeof(Bytef) == 1, ""); + + // uLongf can be larger than size_t. + uLongf compressed_size_long = static_cast(output_buffer_size); + if (zlib_internal::GzipCompressHelper( + bit_cast(output_buffer), &compressed_size_long, + bit_cast(input.data()), + static_cast(input.size()), malloc_fn, free_fn) != Z_OK) { + return false; + } + // No overflow, as compressed_size_long <= output.size() which is a size_t. + *compressed_size = static_cast(compressed_size_long); + return true; +} + +bool GzipCompress(base::StringPiece input, std::string* output) { + // Not using std::vector<> because allocation failures are recoverable, + // which is hidden by std::vector<>. + static_assert(sizeof(Bytef) == 1, ""); + const uLongf input_size = static_cast(input.size()); + + uLongf compressed_data_size = + zlib_internal::GzipExpectedCompressedSize(input_size); + + Bytef* compressed_data; + if (!base::UncheckedMalloc(compressed_data_size, + reinterpret_cast(&compressed_data))) { + return false; + } + + if (zlib_internal::GzipCompressHelper(compressed_data, &compressed_data_size, + bit_cast(input.data()), + input_size, nullptr, nullptr) != Z_OK) { + free(compressed_data); + return false; + } + + Bytef* resized_data = + reinterpret_cast(realloc(compressed_data, compressed_data_size)); + if (!resized_data) { + free(compressed_data); + return false; + } + output->assign(resized_data, resized_data + compressed_data_size); + DCHECK_EQ(input_size, GetUncompressedSize(*output)); + + free(resized_data); + return true; +} + +bool GzipUncompress(const std::string& input, std::string* output) { + std::string uncompressed_output; + uLongf uncompressed_size = static_cast(GetUncompressedSize(input)); + if (uncompressed_size > uncompressed_output.max_size()) + return false; + + uncompressed_output.resize(uncompressed_size); + if (zlib_internal::GzipUncompressHelper( + bit_cast(uncompressed_output.data()), &uncompressed_size, + bit_cast(input.data()), + static_cast(input.length())) == Z_OK) { + output->swap(uncompressed_output); + return true; + } + return false; +} + +bool GzipUncompress(base::StringPiece input, base::StringPiece output) { + uLongf uncompressed_size = GetUncompressedSize(input); + if (uncompressed_size > output.size()) + return false; + return zlib_internal::GzipUncompressHelper( + bit_cast(output.data()), &uncompressed_size, + bit_cast(input.data()), + static_cast(input.length())) == Z_OK; +} + +bool GzipUncompress(base::StringPiece input, std::string* output) { + // Disallow in-place usage, i.e., |input| using |*output| as underlying data. + DCHECK_NE(input.data(), output->data()); + uLongf uncompressed_size = GetUncompressedSize(input); + output->resize(uncompressed_size); + return zlib_internal::GzipUncompressHelper( + bit_cast(output->data()), &uncompressed_size, + bit_cast(input.data()), + static_cast(input.length())) == Z_OK; +} + +uint32_t GetUncompressedSize(base::StringPiece compressed_data) { + return zlib_internal::GetGzipUncompressedSize( + bit_cast(compressed_data.data()), compressed_data.length()); +} + +} // namespace compression diff --git a/deps/zlib/google/compression_utils.h b/deps/zlib/google/compression_utils.h new file mode 100644 index 00000000000000..516220719ff43c --- /dev/null +++ b/deps/zlib/google/compression_utils.h @@ -0,0 +1,56 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_ZLIB_GOOGLE_COMPRESSION_UTILS_H_ +#define THIRD_PARTY_ZLIB_GOOGLE_COMPRESSION_UTILS_H_ + +#include + +#include "base/strings/string_piece.h" + +namespace compression { + +// Compresses the data in |input| using gzip, storing the result in +// |output_buffer|, of size |output_buffer_size|. If the buffer is large enough +// and compression succeeds, |compressed_size| points to the compressed data +// size after the call. +// |malloc_fn| and |free_fn| are pointers to malloc() and free()-like functions, +// or nullptr to use the standard ones. +// Returns true for success. +bool GzipCompress(base::StringPiece input, + char* output_buffer, + size_t output_buffer_size, + size_t* compressed_size, + void* (*malloc_fn)(size_t), + void (*free_fn)(void*)); + +// Compresses the data in |input| using gzip, storing the result in |output|. +// |input| and |output| are allowed to point to the same string (in-place +// operation). +// Returns true for success. +bool GzipCompress(base::StringPiece input, std::string* output); + +// Uncompresses the data in |input| using gzip, storing the result in |output|. +// |input| and |output| are allowed to be the same string (in-place operation). +// Returns true for success. +bool GzipUncompress(const std::string& input, std::string* output); + +// Like the above method, but uses base::StringPiece to avoid allocations if +// needed. |output|'s size must be at least as large as the return value from +// GetUncompressedSize. +// Returns true for success. +bool GzipUncompress(base::StringPiece input, base::StringPiece output); + +// Uncompresses the data in |input| using gzip, and writes the results to +// |output|, which must NOT be the underlying string of |input|, and is resized +// if necessary. +// Returns true for success. +bool GzipUncompress(base::StringPiece input, std::string* output); + +// Returns the uncompressed size from GZIP-compressed |compressed_data|. +uint32_t GetUncompressedSize(base::StringPiece compressed_data); + +} // namespace compression + +#endif // THIRD_PARTY_ZLIB_GOOGLE_COMPRESSION_UTILS_H_ diff --git a/deps/zlib/google/compression_utils_portable.cc b/deps/zlib/google/compression_utils_portable.cc new file mode 100644 index 00000000000000..191e349e31ad30 --- /dev/null +++ b/deps/zlib/google/compression_utils_portable.cc @@ -0,0 +1,205 @@ +/* compression_utils_portable.cc + * + * Copyright 2019 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ + +#include "third_party/zlib/google/compression_utils_portable.h" + +#include +#include +#include + +namespace zlib_internal { + +// The difference in bytes between a zlib header and a gzip header. +const size_t kGzipZlibHeaderDifferenceBytes = 16; + +// Pass an integer greater than the following get a gzip header instead of a +// zlib header when calling deflateInit2() and inflateInit2(). +const int kWindowBitsToGetGzipHeader = 16; + +// This describes the amount of memory zlib uses to compress data. It can go +// from 1 to 9, with 8 being the default. For details, see: +// http://www.zlib.net/manual.html (search for memLevel). +const int kZlibMemoryLevel = 8; + +// The expected compressed size is based on the input size factored by +// internal Zlib constants (e.g. window size, etc) plus the wrapper +// header size. +uLongf GzipExpectedCompressedSize(uLongf input_size) { + return kGzipZlibHeaderDifferenceBytes + compressBound(input_size); +} + +// The expected decompressed size is stored in the last +// 4 bytes of |input| in LE. See https://tools.ietf.org/html/rfc1952#page-5 +uint32_t GetGzipUncompressedSize(const Bytef* compressed_data, size_t length) { + uint32_t size; + if (length < sizeof(size)) + return 0; + + memcpy(&size, &compressed_data[length - sizeof(size)], sizeof(size)); +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + return size; +#else + return __builtin_bswap32(size); +#endif +} + +// The number of window bits determines the type of wrapper to use - see +// https://cs.chromium.org/chromium/src/third_party/zlib/zlib.h?l=566 +inline int ZlibStreamWrapperType(WrapperType type) { + if (type == ZLIB) // zlib DEFLATE stream wrapper + return MAX_WBITS; + if (type == GZIP) // gzip DEFLATE stream wrapper + return MAX_WBITS + kWindowBitsToGetGzipHeader; + if (type == ZRAW) // no wrapper, use raw DEFLATE + return -MAX_WBITS; + return 0; +} + +int GzipCompressHelper(Bytef* dest, + uLongf* dest_length, + const Bytef* source, + uLong source_length, + void* (*malloc_fn)(size_t), + void (*free_fn)(void*)) { + return CompressHelper(GZIP, dest, dest_length, source, source_length, + Z_DEFAULT_COMPRESSION, malloc_fn, free_fn); +} + +// This code is taken almost verbatim from third_party/zlib/compress.c. The only +// difference is deflateInit2() is called which allows different window bits to +// be set. > 16 causes a gzip header to be emitted rather than a zlib header, +// and negative causes no header to emitted. +// +// Compression level can be a number from 1-9, with 1 being the fastest, 9 being +// the best compression. The default, which the GZIP helper uses, is 6. +int CompressHelper(WrapperType wrapper_type, + Bytef* dest, + uLongf* dest_length, + const Bytef* source, + uLong source_length, + int compression_level, + void* (*malloc_fn)(size_t), + void (*free_fn)(void*)) { + if (compression_level < 1 || compression_level > 9) { + compression_level = Z_DEFAULT_COMPRESSION; + } + + z_stream stream; + + // FIXME(cavalcantii): z_const is not defined as 'const'. + stream.next_in = static_cast(const_cast(source)); + stream.avail_in = static_cast(source_length); + stream.next_out = dest; + stream.avail_out = static_cast(*dest_length); + if (static_cast(stream.avail_out) != *dest_length) + return Z_BUF_ERROR; + + // Cannot convert capturing lambdas to function pointers directly, hence the + // structure. + struct MallocFreeFunctions { + void* (*malloc_fn)(size_t); + void (*free_fn)(void*); + } malloc_free = {malloc_fn, free_fn}; + + if (malloc_fn) { + if (!free_fn) + return Z_BUF_ERROR; + + auto zalloc = [](void* opaque, uInt items, uInt size) { + return reinterpret_cast(opaque)->malloc_fn(items * + size); + }; + auto zfree = [](void* opaque, void* address) { + return reinterpret_cast(opaque)->free_fn(address); + }; + + stream.zalloc = static_cast(zalloc); + stream.zfree = static_cast(zfree); + stream.opaque = static_cast(&malloc_free); + } else { + stream.zalloc = static_cast(0); + stream.zfree = static_cast(0); + stream.opaque = static_cast(0); + } + + int err = deflateInit2(&stream, compression_level, Z_DEFLATED, + ZlibStreamWrapperType(wrapper_type), kZlibMemoryLevel, + Z_DEFAULT_STRATEGY); + if (err != Z_OK) + return err; + + // This has to exist outside of the if statement to prevent it going off the + // stack before deflate(), which will use this object. + gz_header gzip_header; + if (wrapper_type == GZIP) { + memset(&gzip_header, 0, sizeof(gzip_header)); + err = deflateSetHeader(&stream, &gzip_header); + if (err != Z_OK) + return err; + } + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *dest_length = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +int GzipUncompressHelper(Bytef* dest, + uLongf* dest_length, + const Bytef* source, + uLong source_length) { + return UncompressHelper(GZIP, dest, dest_length, source, source_length); +} + +// This code is taken almost verbatim from third_party/zlib/uncompr.c. The only +// difference is inflateInit2() is called which allows different window bits to +// be set. > 16 causes a gzip header to be emitted rather than a zlib header, +// and negative causes no header to emitted. +int UncompressHelper(WrapperType wrapper_type, + Bytef* dest, + uLongf* dest_length, + const Bytef* source, + uLong source_length) { + z_stream stream; + + // FIXME(cavalcantii): z_const is not defined as 'const'. + stream.next_in = static_cast(const_cast(source)); + stream.avail_in = static_cast(source_length); + if (static_cast(stream.avail_in) != source_length) + return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = static_cast(*dest_length); + if (static_cast(stream.avail_out) != *dest_length) + return Z_BUF_ERROR; + + stream.zalloc = static_cast(0); + stream.zfree = static_cast(0); + + int err = inflateInit2(&stream, ZlibStreamWrapperType(wrapper_type)); + if (err != Z_OK) + return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *dest_length = stream.total_out; + + err = inflateEnd(&stream); + return err; +} + +} // namespace zlib_internal diff --git a/deps/zlib/google/compression_utils_portable.h b/deps/zlib/google/compression_utils_portable.h new file mode 100644 index 00000000000000..cd004e86cf515c --- /dev/null +++ b/deps/zlib/google/compression_utils_portable.h @@ -0,0 +1,59 @@ +/* compression_utils_portable.h + * + * Copyright 2019 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ +#ifndef THIRD_PARTY_ZLIB_GOOGLE_COMPRESSION_UTILS_PORTABLE_H_ +#define THIRD_PARTY_ZLIB_GOOGLE_COMPRESSION_UTILS_PORTABLE_H_ + +#include + +#if defined(USE_SYSTEM_ZLIB) +#include +#else +#include "third_party/zlib/zlib.h" +#endif + +namespace zlib_internal { + +enum WrapperType { + ZLIB, + GZIP, + ZRAW, +}; + +uLongf GzipExpectedCompressedSize(uLongf input_size); + +uint32_t GetGzipUncompressedSize(const Bytef* compressed_data, size_t length); + +int GzipCompressHelper(Bytef* dest, + uLongf* dest_length, + const Bytef* source, + uLong source_length, + void* (*malloc_fn)(size_t), + void (*free_fn)(void*)); + +int CompressHelper(WrapperType wrapper_type, + Bytef* dest, + uLongf* dest_length, + const Bytef* source, + uLong source_length, + int compression_level, + void* (*malloc_fn)(size_t), + void (*free_fn)(void*)); + +int GzipUncompressHelper(Bytef* dest, + uLongf* dest_length, + const Bytef* source, + uLong source_length); + +int UncompressHelper(WrapperType wrapper_type, + Bytef* dest, + uLongf* dest_length, + const Bytef* source, + uLong source_length); + +} // namespace zlib_internal + +#endif // THIRD_PARTY_ZLIB_GOOGLE_COMPRESSION_UTILS_PORTABLE_H_ diff --git a/deps/zlib/google/compression_utils_unittest.cc b/deps/zlib/google/compression_utils_unittest.cc new file mode 100644 index 00000000000000..b0e04b8c973633 --- /dev/null +++ b/deps/zlib/google/compression_utils_unittest.cc @@ -0,0 +1,104 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/zlib/google/compression_utils.h" + +#include +#include + +#include + +#include "base/logging.h" +#include "base/stl_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace compression { + +namespace { + +// The data to be compressed by gzip. This is the hex representation of "hello +// world". +const uint8_t kData[] = {0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, + 0x77, 0x6f, 0x72, 0x6c, 0x64}; + +// This is the string representation of gzip compressed string above. It was +// obtained by running echo -n "hello world" | gzip -c | hexdump -e '8 1 ", +// 0x%x"' followed by 0'ing out the OS byte (10th byte) in the header. This is +// so that the test passes on all platforms (that run various OS'es). +const uint8_t kCompressedData[] = { + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, + 0x48, 0xcd, 0xc9, 0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0x01, + 0x00, 0x85, 0x11, 0x4a, 0x0d, 0x0b, 0x00, 0x00, 0x00}; + +} // namespace + +TEST(CompressionUtilsTest, GzipCompression) { + std::string data(reinterpret_cast(kData), base::size(kData)); + std::string compressed_data; + EXPECT_TRUE(GzipCompress(data, &compressed_data)); + std::string golden_compressed_data( + reinterpret_cast(kCompressedData), + base::size(kCompressedData)); + EXPECT_EQ(golden_compressed_data, compressed_data); +} + +TEST(CompressionUtilsTest, GzipUncompression) { + std::string compressed_data(reinterpret_cast(kCompressedData), + base::size(kCompressedData)); + + std::string uncompressed_data; + EXPECT_TRUE(GzipUncompress(compressed_data, &uncompressed_data)); + + std::string golden_data(reinterpret_cast(kData), + base::size(kData)); + EXPECT_EQ(golden_data, uncompressed_data); +} + +TEST(CompressionUtilsTest, GzipUncompressionFromStringPieceToString) { + base::StringPiece compressed_data( + reinterpret_cast(kCompressedData), + base::size(kCompressedData)); + + std::string uncompressed_data; + EXPECT_TRUE(GzipUncompress(compressed_data, &uncompressed_data)); + + std::string golden_data(reinterpret_cast(kData), + base::size(kData)); + EXPECT_EQ(golden_data, uncompressed_data); +} + +// Checks that compressing/decompressing input > 256 bytes works as expected. +TEST(CompressionUtilsTest, LargeInput) { + const size_t kSize = 32 * 1024; + + // Generate a data string of |kSize| for testing. + std::string data; + data.resize(kSize); + for (size_t i = 0; i < kSize; ++i) + data[i] = static_cast(i & 0xFF); + + std::string compressed_data; + EXPECT_TRUE(GzipCompress(data, &compressed_data)); + + std::string uncompressed_data; + EXPECT_TRUE(GzipUncompress(compressed_data, &uncompressed_data)); + + EXPECT_EQ(data, uncompressed_data); +} + +TEST(CompressionUtilsTest, InPlace) { + const std::string original_data(reinterpret_cast(kData), + base::size(kData)); + const std::string golden_compressed_data( + reinterpret_cast(kCompressedData), + base::size(kCompressedData)); + + std::string data(original_data); + EXPECT_TRUE(GzipCompress(data, &data)); + EXPECT_EQ(golden_compressed_data, data); + EXPECT_TRUE(GzipUncompress(data, &data)); + EXPECT_EQ(original_data, data); +} + +} // namespace compression diff --git a/deps/zlib/google/test/data/create_test_zip.sh b/deps/zlib/google/test/data/create_test_zip.sh new file mode 100755 index 00000000000000..f4cc635c2cf7a4 --- /dev/null +++ b/deps/zlib/google/test/data/create_test_zip.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# +# Copyright (c) 2011 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Run this script in its directory to recreate test.zip, test_nocompress.zip, +# and test_encrypted.zip + +rm test.zip +rm test_nocompress.zip +rm test_encrypted.zip +pushd test +zip -r ../test.zip . +zip -r -0 ../test_nocompress.zip . +zip -P "fake_password" -r ../test_encrypted.zip . +popd diff --git a/deps/zlib/google/test/data/evil.zip b/deps/zlib/google/test/data/evil.zip new file mode 100644 index 00000000000000..8fb908a96abdf0 Binary files /dev/null and b/deps/zlib/google/test/data/evil.zip differ diff --git a/deps/zlib/google/test/data/evil_via_absolute_file_name.zip b/deps/zlib/google/test/data/evil_via_absolute_file_name.zip new file mode 100644 index 00000000000000..2415f81b63751b Binary files /dev/null and b/deps/zlib/google/test/data/evil_via_absolute_file_name.zip differ diff --git a/deps/zlib/google/test/data/evil_via_invalid_utf8.zip b/deps/zlib/google/test/data/evil_via_invalid_utf8.zip new file mode 100644 index 00000000000000..94b633e0aa5c2c Binary files /dev/null and b/deps/zlib/google/test/data/evil_via_invalid_utf8.zip differ diff --git a/deps/zlib/google/test/data/test.zip b/deps/zlib/google/test/data/test.zip new file mode 100644 index 00000000000000..4bafe30898eb9c Binary files /dev/null and b/deps/zlib/google/test/data/test.zip differ diff --git a/deps/zlib/google/test/data/test/foo.txt b/deps/zlib/google/test/data/test/foo.txt new file mode 100644 index 00000000000000..257cc5642cb1a0 --- /dev/null +++ b/deps/zlib/google/test/data/test/foo.txt @@ -0,0 +1 @@ +foo diff --git a/deps/zlib/google/test/data/test/foo/bar.txt b/deps/zlib/google/test/data/test/foo/bar.txt new file mode 100644 index 00000000000000..5716ca5987cbf9 --- /dev/null +++ b/deps/zlib/google/test/data/test/foo/bar.txt @@ -0,0 +1 @@ +bar diff --git a/deps/zlib/google/test/data/test/foo/bar/.hidden b/deps/zlib/google/test/data/test/foo/bar/.hidden new file mode 100644 index 00000000000000..136c05e0d0290e --- /dev/null +++ b/deps/zlib/google/test/data/test/foo/bar/.hidden @@ -0,0 +1 @@ +hidden diff --git a/deps/zlib/google/test/data/test/foo/bar/baz.txt b/deps/zlib/google/test/data/test/foo/bar/baz.txt new file mode 100644 index 00000000000000..76018072e09c5d --- /dev/null +++ b/deps/zlib/google/test/data/test/foo/bar/baz.txt @@ -0,0 +1 @@ +baz diff --git a/deps/zlib/google/test/data/test/foo/bar/quux.txt b/deps/zlib/google/test/data/test/foo/bar/quux.txt new file mode 100644 index 00000000000000..479787951d98bf --- /dev/null +++ b/deps/zlib/google/test/data/test/foo/bar/quux.txt @@ -0,0 +1,39 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sem urna, semper ac, adipiscing sed, varius eget, quam. Fusce ipsum dolor, condimentum et, ornare in, consequat ac, nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nulla feugiat justo ac enim. Ut vehicula dapibus elit. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam lacus sem, viverra in, laoreet quis, cursus non, odio. Maecenas in elit. Pellentesque vitae dui. Ut dictum tellus et orci. Sed consectetur. Fusce tincidunt. Cras vulputate adipiscing metus. Aliquam lacinia. Vestibulum leo. Donec enim. Etiam imperdiet libero. Nam tellus ante, lobortis eget, dapibus vel, accumsan ultricies, nibh. In ultrices mauris at est. + +Phasellus ac elit sit amet felis aliquet venenatis. Sed porta libero at massa. Fusce blandit diam eget lorem. Nullam velit diam, fermentum eget, scelerisque non, faucibus a, tellus. Ut accumsan eros vitae velit. Proin vehicula aliquam felis. Proin ligula augue, gravida a, fermentum sit amet, sodales ac, purus. Phasellus sagittis scelerisque tellus. Ut gravida metus quis enim. Curabitur malesuada orci in massa. Pellentesque nibh turpis, adipiscing vel, rutrum quis, rhoncus vel, dolor. Pellentesque suscipit, arcu in egestas semper, lorem sapien vehicula nunc, non scelerisque lectus ante at diam. Etiam varius leo. Sed dictum, ante sed imperdiet ornare, felis leo lobortis eros, eu tincidunt lorem tellus sit amet mi. Mauris nisl elit, placerat non, scelerisque id, congue non, ligula. Nulla eget mi eu dolor scelerisque tempor. Fusce non lorem vel nibh mattis blandit. + +Vivamus sit amet urna quis eros varius condimentum. Phasellus placerat ligula ac felis. Vivamus tempor, metus id fermentum feugiat, justo ligula malesuada nisl, ut vulputate nisi arcu in eros. Vestibulum non erat in massa laoreet luctus. Praesent tempor, tortor eget sodales condimentum, purus odio gravida tellus, pellentesque euismod enim diam id augue. Duis malesuada lacus eu felis. Suspendisse tristique faucibus arcu. Etiam ac sapien. Aenean dolor enim, semper auctor, dapibus cursus, varius et, arcu. Aenean pede nunc, varius nec, pulvinar a, accumsan id, dui. Nulla a risus eget nibh pharetra rutrum. Quisque adipiscing adipiscing neque. Praesent faucibus lacus eu nulla. Vestibulum nec nunc vel quam cursus sollicitudin. Nam at quam at neque pharetra elementum. Sed ornare ullamcorper nibh. + +Aliquam aliquam vulputate diam. Ut molestie pharetra neque. Pellentesque sodales blandit nibh. Donec eget mauris eget mauris blandit pharetra. Etiam imperdiet commodo tellus. Nulla felis justo, vestibulum hendrerit, posuere vitae, viverra ut, risus. Pellentesque auctor, ante egestas suscipit vestibulum, sem dolor posuere urna, pellentesque dignissim ante orci a lectus. Suspendisse potenti. Sed et pede pretium arcu porttitor porta. Nullam nec nulla. Fusce lacinia, massa ac fermentum congue, dui quam varius mauris, vitae ullamcorper pede lacus at nisl. Suspendisse aliquam pede a sapien. Morbi pellentesque, mi id mattis aliquet, nisl erat tincidunt lorem, eu bibendum nunc nisi nec erat. Suspendisse commodo dapibus dolor. Quisque id risus. Nullam gravida est tempor lectus. + +Morbi mattis. Cras sagittis. Sed eleifend odio sit amet nibh. Cras sit amet massa. Donec congue nulla vel augue. Maecenas fermentum turpis at diam. In lobortis. Phasellus aliquet. Etiam eu diam. Integer accumsan. Integer sagittis tempor mi. Aliquam interdum lectus id augue. Donec vel eros. Donec vitae orci a sapien imperdiet consectetur. + +Maecenas est lorem, luctus vel, fringilla sed, rutrum nec, nisl. Donec sapien. Vestibulum at metus. Praesent erat. Nulla semper metus a lacus. Morbi ultrices. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus odio. Ut mauris. Fusce et risus. Proin at mauris a eros imperdiet mollis. Sed adipiscing hendrerit nisl. Curabitur libero. Donec nulla. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. + +Nullam non lacus. Vivamus rhoncus dolor sit amet ipsum. Vivamus volutpat eleifend odio. Vestibulum nunc. In at magna a pede gravida vulputate. Praesent ligula tellus, rhoncus elementum, pulvinar a, condimentum vitae, libero. Donec ornare dui. Proin non lorem quis massa placerat interdum. Nam justo. Aliquam rutrum dignissim mi. Mauris tellus. Proin dui felis, lacinia quis, volutpat a, blandit sed, neque. Etiam non dolor eu justo interdum tristique. Morbi volutpat, elit vitae rutrum iaculis, augue mi accumsan metus, sed porttitor felis mi sed felis. + +Nulla quam lectus, pharetra non, sodales sit amet, pretium quis, massa. Aliquam orci. Duis id massa. Pellentesque porttitor nibh id quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec convallis, pede vitae volutpat consequat, justo lorem ultricies nisi, ut scelerisque leo lorem in tellus. Cras bibendum. Sed hendrerit placerat tortor. Sed felis. Aliquam erat volutpat. Praesent rhoncus nisi. Vestibulum justo felis, tincidunt luctus, suscipit sed, tincidunt ut, lorem. Proin non risus ac mi mattis volutpat. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam pellentesque nisl sit amet sapien rutrum porta. + +Phasellus ut pede non odio ultricies egestas. Aenean nibh. Mauris magna felis, posuere non, tempus et, bibendum ut, felis. Donec vel ipsum ac nisi dapibus lobortis. Sed congue ligula at est. Vivamus elit est, rhoncus vitae, tempus at, consectetur nec, elit. Duis vehicula tellus vitae sem. Suspendisse rhoncus felis sit amet magna. Maecenas vulputate risus in diam. Nunc sollicitudin risus eget quam. Nam pretium purus eleifend dolor. Integer erat nulla, mattis eu, sollicitudin sed, sagittis nec, metus. + +Donec ante felis, ultrices nec, pellentesque nec, elementum et, nunc. Pellentesque in tortor sit amet urna aliquet tincidunt. Praesent ultrices. Sed tincidunt. Donec turpis enim, feugiat eu, cursus ut, viverra ut, odio. Morbi in orci quis enim vehicula lobortis. Proin in neque. Pellentesque venenatis neque sit amet augue. Proin suscipit nibh. Praesent et diam. + +In eget ligula quis libero vulputate eleifend. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nunc non urna vitae mi vulputate adipiscing. Nulla vitae arcu. Nullam ut nisl ac enim pulvinar auctor. Suspendisse tortor pede, consectetur in, volutpat at, condimentum vel, ligula. Pellentesque nisi est, vulputate vitae, hendrerit id, venenatis sit amet, urna. Nunc lobortis. Sed rhoncus, tortor vitae pellentesque facilisis, massa ante interdum massa, feugiat faucibus pede nunc et tellus. Quisque auctor sollicitudin nibh. Aliquam congue. Praesent ullamcorper mi id lacus. Nullam ac risus et velit ullamcorper vehicula. Vestibulum consectetur convallis neque. Donec dapibus, ante a rutrum interdum, mi dui auctor lacus, quis posuere eros diam eu nisl. Integer nec velit vel purus eleifend condimentum. Cras quis nunc. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. + +Sed euismod, metus eu consectetur dictum, felis eros sodales pede, ac pellentesque lacus orci sed velit. Praesent a justo. Aliquam massa dolor, condimentum non, dapibus quis, vestibulum a, purus. Duis gravida porta dolor. Nullam sit amet mi sagittis massa pretium ultricies. Ut fringilla. Aliquam venenatis feugiat dui. Pellentesque tempor, leo et ullamcorper placerat, felis libero blandit nisl, sit amet pharetra nisl erat sit amet dolor. In sem erat, porta rhoncus, auctor ac, convallis feugiat, dui. Sed tempus metus at erat. Cras gravida. Cras urna nisi, fermentum non, sodales sed, adipiscing sed, nulla. + +Donec pellentesque, velit sit amet ultricies dictum, sem quam posuere arcu, tristique mollis nibh dui ac libero. Vestibulum consectetur velit sed dolor. Nullam ornare sodales nisi. Sed facilisis sollicitudin arcu. Proin vitae lectus vel nulla auctor faucibus. Aenean nec nisl sit amet risus faucibus tincidunt. Ut sed nisl. Vivamus vehicula ligula a nunc. Curabitur mauris. Integer est felis, fermentum aliquam, dignissim id, gravida id, purus. Nullam porta felis eget ante. Phasellus lacinia, odio et elementum viverra, dui neque tempus massa, ac adipiscing lectus velit vitae turpis. Integer scelerisque neque in tortor. Duis et elit. Mauris elementum urna sed risus. Nunc aliquet, ipsum ac venenatis elementum, sapien orci vulputate lacus, eu lobortis sapien lorem non enim. Donec enim sapien, gravida vitae, vestibulum et, mattis dapibus, sem. Phasellus mi. + +Cras a lorem nec diam aliquet viverra. Aliquam sed leo sit amet neque porta venenatis. Nulla facilisi. Duis lectus felis, fermentum quis, sagittis a, vestibulum consectetur, orci. Suspendisse sodales odio vitae lectus. Curabitur nunc. Phasellus cursus diam sit amet ipsum. Aenean cursus tellus eget nunc. Vivamus mattis urna a lorem. Mauris vitae mi. Morbi luctus molestie pede. Vestibulum lobortis lacus sed lacus. Aliquam nisl libero, pellentesque sed, facilisis ut, varius vehicula, lacus. Mauris orci. Pellentesque sed risus id quam sodales lobortis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed facilisis, odio vitae laoreet auctor, nulla dui sagittis lectus, sit amet viverra orci arcu et lectus. Pellentesque ut sem. Maecenas a est. + +Suspendisse tincidunt. Sed bibendum molestie ligula. Suspendisse massa mauris, cursus a, luctus eget, posuere sed, nulla. Fusce vitae urna. Duis fermentum. Donec a neque ac pede lobortis mollis. Donec massa ligula, facilisis et, dapibus sed, ultrices non, sem. Phasellus diam. Maecenas velit arcu, viverra ut, gravida ac, tincidunt eget, nunc. Sed sit amet enim non dui tristique lacinia. Vivamus eu orci. Duis metus. Nulla facilisi. Phasellus at lectus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus mauris. Duis dictum, erat eu scelerisque sollicitudin, mi augue tincidunt lorem, vel lacinia lectus nibh quis dui. Ut ornare dignissim elit. Phasellus posuere ligula vel justo. + +Sed neque. Quisque porttitor lorem vel arcu. Praesent a mi et risus suscipit egestas. Proin est lectus, rhoncus sit amet, aliquet non, fermentum ut, nulla. Aenean erat nisl, rutrum dictum, placerat vel, malesuada ac, arcu. Suspendisse posuere, ante sed consequat gravida, velit mi dignissim sem, et pretium dui diam in elit. Sed dictum nulla. Duis tristique tincidunt eros. Morbi velit. Donec a lorem. Aliquam cursus. Vivamus dapibus varius neque. Quisque eget diam. Nulla facilisi. Pellentesque eu sapien. Curabitur egestas cursus risus. Proin odio tortor, interdum eget, fringilla venenatis, luctus et, turpis. Phasellus nulla lorem, ullamcorper ut, elementum rhoncus, ultrices sed, ipsum. Nam volutpat. + +Quisque eu purus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur non nulla. Donec dignissim porta lorem. Mauris ornare venenatis odio. Aenean eu lectus at eros porta molestie. Vivamus neque. Morbi aliquam. Nulla tincidunt enim id ligula. Nunc gravida felis consectetur dolor. Phasellus tempus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla nec libero quis ipsum auctor vehicula. Maecenas consectetur tempor turpis. Integer commodo. In hac habitasse platea dictumst. Donec nec justo quis sem placerat gravida. Donec sollicitudin, turpis sit amet bibendum elementum, nisl ligula venenatis ipsum, vel sollicitudin justo arcu eu leo. Phasellus aliquet faucibus libero. + +Nam molestie nulla eu risus. Fusce id erat. Maecenas volutpat nunc eu ligula. Sed tortor est, imperdiet quis, viverra et, ornare in, ipsum. Praesent aliquet. Nulla suscipit. In posuere enim in odio. Nullam ante ipsum, imperdiet id, convallis id, hendrerit id, libero. Donec convallis libero ut felis. Curabitur venenatis placerat justo. Vestibulum mauris arcu, scelerisque et, dapibus vel, scelerisque a, lectus. Sed sit amet orci id felis tristique tincidunt. Curabitur adipiscing, nulla vel pretium tristique, tellus ipsum lacinia eros, vitae venenatis pede lectus sit amet neque. Nulla feugiat. Aenean euismod, nunc vel rutrum mattis, lorem purus venenatis sapien, sed facilisis pede enim at elit. Vivamus viverra. Cras vitae purus ac felis fringilla condimentum. Nullam ac nisi vitae massa faucibus aliquet. + +Etiam ut nibh nec neque elementum iaculis. Maecenas facilisis nulla at lorem. Pellentesque elit sapien, ultricies at, dignissim nec, cursus eu, pede. Morbi gravida, ipsum eget malesuada eleifend, est arcu pulvinar nisl, et fermentum urna felis sed tellus. Mauris fermentum sollicitudin neque. Nunc at odio. Pellentesque et turpis. Cras congue congue nisi. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam feugiat dapibus tellus. Aenean aliquam, mi id interdum feugiat, nunc lorem laoreet massa, ac semper urna sem vel purus. Quisque bibendum tellus ut est. + +Morbi aliquam lectus sit amet nisi. Praesent urna purus, porttitor vitae, accumsan in, sollicitudin at, lorem. Donec diam dui, hendrerit eget, tincidunt ut, ultrices vehicula, dolor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam erat volutpat. Pellentesque iaculis iaculis lacus. Fusce auctor. Morbi vulputate purus at felis. Maecenas a pede nec metus vulputate ullamcorper. Cras non lectus. Suspendisse lacinia. diff --git a/deps/zlib/google/test/data/test_encrypted.zip b/deps/zlib/google/test/data/test_encrypted.zip new file mode 100644 index 00000000000000..5e2a75759a1914 Binary files /dev/null and b/deps/zlib/google/test/data/test_encrypted.zip differ diff --git a/deps/zlib/google/test/data/test_mismatch_size.zip b/deps/zlib/google/test/data/test_mismatch_size.zip new file mode 100644 index 00000000000000..b83c66fe79125c Binary files /dev/null and b/deps/zlib/google/test/data/test_mismatch_size.zip differ diff --git a/deps/zlib/google/test/data/test_nocompress.zip b/deps/zlib/google/test/data/test_nocompress.zip new file mode 100644 index 00000000000000..25d66c287e2c75 Binary files /dev/null and b/deps/zlib/google/test/data/test_nocompress.zip differ diff --git a/deps/zlib/google/zip.cc b/deps/zlib/google/zip.cc new file mode 100644 index 00000000000000..907e5da72e974d --- /dev/null +++ b/deps/zlib/google/zip.cc @@ -0,0 +1,271 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/zlib/google/zip.h" + +#include +#include +#include + +#include "base/bind.h" +#include "base/files/file.h" +#include "base/files/file_enumerator.h" +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/strings/string_util.h" +#include "build/build_config.h" +#include "third_party/zlib/google/zip_internal.h" +#include "third_party/zlib/google/zip_reader.h" +#include "third_party/zlib/google/zip_writer.h" + +namespace zip { +namespace { + +bool IsHiddenFile(const base::FilePath& file_path) { + return file_path.BaseName().value()[0] == '.'; +} + +bool ExcludeNoFilesFilter(const base::FilePath& file_path) { + return true; +} + +bool ExcludeHiddenFilesFilter(const base::FilePath& file_path) { + return !IsHiddenFile(file_path); +} + +// Creates a directory at |extract_dir|/|entry_path|, including any parents. +bool CreateDirectory(const base::FilePath& extract_dir, + const base::FilePath& entry_path) { + return base::CreateDirectory(extract_dir.Append(entry_path)); +} + +// Creates a WriterDelegate that can write a file at |extract_dir|/|entry_path|. +std::unique_ptr CreateFilePathWriterDelegate( + const base::FilePath& extract_dir, + const base::FilePath& entry_path) { + return std::make_unique( + extract_dir.Append(entry_path)); +} + +class DirectFileAccessor : public FileAccessor { + public: + explicit DirectFileAccessor(base::FilePath src_dir) : src_dir_(src_dir) {} + ~DirectFileAccessor() override = default; + + std::vector OpenFilesForReading( + const std::vector& paths) override { + std::vector files; + for (const auto& path : paths) { + base::File file; + if (base::PathExists(path) && !base::DirectoryExists(path)) { + file = base::File(path, base::File::FLAG_OPEN | base::File::FLAG_READ); + } + files.push_back(std::move(file)); + } + return files; + } + + bool DirectoryExists(const base::FilePath& file) override { + return base::DirectoryExists(file); + } + + std::vector ListDirectoryContent( + const base::FilePath& dir) override { + std::vector files; + base::FileEnumerator file_enumerator( + dir, false /* recursive */, + base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); + for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); + path = file_enumerator.Next()) { + files.push_back(DirectoryContentEntry(path, base::DirectoryExists(path))); + } + return files; + } + + base::Time GetLastModifiedTime(const base::FilePath& path) override { + base::File::Info file_info; + if (!base::GetFileInfo(path, &file_info)) { + LOG(ERROR) << "Failed to retrieve file modification time for " + << path.value(); + } + return file_info.last_modified; + } + + private: + base::FilePath src_dir_; + + DISALLOW_COPY_AND_ASSIGN(DirectFileAccessor); +}; + +} // namespace + +ZipParams::ZipParams(const base::FilePath& src_dir, + const base::FilePath& dest_file) + : src_dir_(src_dir), + dest_file_(dest_file), + file_accessor_(new DirectFileAccessor(src_dir)) {} + +#if defined(OS_POSIX) +// Does not take ownership of |fd|. +ZipParams::ZipParams(const base::FilePath& src_dir, int dest_fd) + : src_dir_(src_dir), + dest_fd_(dest_fd), + file_accessor_(new DirectFileAccessor(src_dir)) {} +#endif + +bool Zip(const ZipParams& params) { + // Using a pointer to avoid copies of a potentially large array. + const std::vector* files_to_add = ¶ms.files_to_zip(); + std::vector all_files; + if (files_to_add->empty()) { + // Include all files from the src_dir (modulo the src_dir itself and + // filtered and hidden files). + + files_to_add = &all_files; + // Using a list so we can call push_back while iterating. + std::list entries; + entries.push_back(FileAccessor::DirectoryContentEntry( + params.src_dir(), true /* is directory*/)); + const FilterCallback& filter_callback = params.filter_callback(); + for (auto iter = entries.begin(); iter != entries.end(); ++iter) { + const base::FilePath& entry_path = iter->path; + if (iter != entries.begin() && // Don't filter the root dir. + ((!params.include_hidden_files() && IsHiddenFile(entry_path)) || + (filter_callback && !filter_callback.Run(entry_path)))) { + continue; + } + + if (iter != entries.begin()) { // Exclude the root dir from the ZIP file. + // Make the path relative for AddEntryToZip. + base::FilePath relative_path; + bool success = + params.src_dir().AppendRelativePath(entry_path, &relative_path); + DCHECK(success); + all_files.push_back(relative_path); + } + + if (iter->is_directory) { + std::vector subentries = + params.file_accessor()->ListDirectoryContent(entry_path); + entries.insert(entries.end(), subentries.begin(), subentries.end()); + } + } + } + + std::unique_ptr zip_writer; +#if defined(OS_POSIX) + if (params.dest_fd() != base::kInvalidPlatformFile) { + DCHECK(params.dest_file().empty()); + zip_writer = internal::ZipWriter::CreateWithFd( + params.dest_fd(), params.src_dir(), params.file_accessor()); + if (!zip_writer) + return false; + } +#endif + if (!zip_writer) { + zip_writer = internal::ZipWriter::Create( + params.dest_file(), params.src_dir(), params.file_accessor()); + if (!zip_writer) + return false; + } + return zip_writer->WriteEntries(*files_to_add); +} + +bool Unzip(const base::FilePath& src_file, const base::FilePath& dest_dir) { + return UnzipWithFilterCallback( + src_file, dest_dir, base::BindRepeating(&ExcludeNoFilesFilter), true); +} + +bool UnzipWithFilterCallback(const base::FilePath& src_file, + const base::FilePath& dest_dir, + const FilterCallback& filter_cb, + bool log_skipped_files) { + base::File file(src_file, base::File::FLAG_OPEN | base::File::FLAG_READ); + if (!file.IsValid()) { + DLOG(WARNING) << "Failed to open " << src_file.value(); + return false; + } + return UnzipWithFilterAndWriters( + file.GetPlatformFile(), + base::BindRepeating(&CreateFilePathWriterDelegate, dest_dir), + base::BindRepeating(&CreateDirectory, dest_dir), filter_cb, + log_skipped_files); +} + +bool UnzipWithFilterAndWriters(const base::PlatformFile& src_file, + const WriterFactory& writer_factory, + const DirectoryCreator& directory_creator, + const FilterCallback& filter_cb, + bool log_skipped_files) { + ZipReader reader; + if (!reader.OpenFromPlatformFile(src_file)) { + DLOG(WARNING) << "Failed to open src_file " << src_file; + return false; + } + while (reader.HasMore()) { + if (!reader.OpenCurrentEntryInZip()) { + DLOG(WARNING) << "Failed to open the current file in zip"; + return false; + } + const base::FilePath& entry_path = reader.current_entry_info()->file_path(); + if (reader.current_entry_info()->is_unsafe()) { + DLOG(WARNING) << "Found an unsafe file in zip " << entry_path; + return false; + } + if (filter_cb.Run(entry_path)) { + if (reader.current_entry_info()->is_directory()) { + if (!directory_creator.Run(entry_path)) + return false; + } else { + std::unique_ptr writer = writer_factory.Run(entry_path); + if (!reader.ExtractCurrentEntry(writer.get(), + std::numeric_limits::max())) { + DLOG(WARNING) << "Failed to extract " << entry_path; + return false; + } + } + } else if (log_skipped_files) { + DLOG(WARNING) << "Skipped file " << entry_path; + } + + if (!reader.AdvanceToNextEntry()) { + DLOG(WARNING) << "Failed to advance to the next file"; + return false; + } + } + return true; +} + +bool ZipWithFilterCallback(const base::FilePath& src_dir, + const base::FilePath& dest_file, + const FilterCallback& filter_cb) { + DCHECK(base::DirectoryExists(src_dir)); + ZipParams params(src_dir, dest_file); + params.set_filter_callback(filter_cb); + return Zip(params); +} + +bool Zip(const base::FilePath& src_dir, const base::FilePath& dest_file, + bool include_hidden_files) { + if (include_hidden_files) { + return ZipWithFilterCallback(src_dir, dest_file, + base::BindRepeating(&ExcludeNoFilesFilter)); + } else { + return ZipWithFilterCallback( + src_dir, dest_file, base::BindRepeating(&ExcludeHiddenFilesFilter)); + } +} + +#if defined(OS_POSIX) +bool ZipFiles(const base::FilePath& src_dir, + const std::vector& src_relative_paths, + int dest_fd) { + DCHECK(base::DirectoryExists(src_dir)); + ZipParams params(src_dir, dest_fd); + params.set_files_to_zip(src_relative_paths); + return Zip(params); +} +#endif // defined(OS_POSIX) + +} // namespace zip diff --git a/deps/zlib/google/zip.h b/deps/zlib/google/zip.h new file mode 100644 index 00000000000000..4f64a8aca883a8 --- /dev/null +++ b/deps/zlib/google/zip.h @@ -0,0 +1,181 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_ZLIB_GOOGLE_ZIP_H_ +#define THIRD_PARTY_ZLIB_GOOGLE_ZIP_H_ + +#include + +#include "base/callback.h" +#include "base/files/file_path.h" +#include "base/files/platform_file.h" +#include "base/time/time.h" +#include "build/build_config.h" + +namespace base { +class File; +} + +namespace zip { + +class WriterDelegate; + +// Abstraction for file access operation required by Zip(). +// Can be passed to the ZipParams for providing custom access to the files, +// for example over IPC. +// If none is provided, the files are accessed directly. +// All parameters paths are expected to be absolute. +class FileAccessor { + public: + virtual ~FileAccessor() = default; + + struct DirectoryContentEntry { + DirectoryContentEntry(const base::FilePath& path, bool is_directory) + : path(path), is_directory(is_directory) {} + base::FilePath path; + bool is_directory = false; + }; + + // Opens files specified in |paths|. + // Directories should be mapped to invalid files. + virtual std::vector OpenFilesForReading( + const std::vector& paths) = 0; + + virtual bool DirectoryExists(const base::FilePath& path) = 0; + virtual std::vector ListDirectoryContent( + const base::FilePath& dir_path) = 0; + virtual base::Time GetLastModifiedTime(const base::FilePath& path) = 0; +}; + +class ZipParams { + public: + ZipParams(const base::FilePath& src_dir, const base::FilePath& dest_file); +#if defined(OS_POSIX) + // Does not take ownership of |dest_fd|. + ZipParams(const base::FilePath& src_dir, int dest_fd); + + int dest_fd() const { return dest_fd_; } +#endif + + const base::FilePath& src_dir() const { return src_dir_; } + + const base::FilePath& dest_file() const { return dest_file_; } + + // Restricts the files actually zipped to the paths listed in + // |src_relative_paths|. They must be relative to the |src_dir| passed in the + // constructor and will be used as the file names in the created zip file. All + // source paths must be under |src_dir| in the file system hierarchy. + void set_files_to_zip(const std::vector& src_relative_paths) { + src_files_ = src_relative_paths; + } + const std::vector& files_to_zip() const { return src_files_; } + + using FilterCallback = base::RepeatingCallback; + void set_filter_callback(FilterCallback filter_callback) { + filter_callback_ = filter_callback; + } + const FilterCallback& filter_callback() const { return filter_callback_; } + + void set_include_hidden_files(bool include_hidden_files) { + include_hidden_files_ = include_hidden_files; + } + bool include_hidden_files() const { return include_hidden_files_; } + + // Sets a custom file accessor for file operations. Default is to directly + // access the files (with fopen and the rest). + // Useful in cases where running in a sandbox process and file access has to + // go through IPC, for example. + void set_file_accessor(std::unique_ptr file_accessor) { + file_accessor_ = std::move(file_accessor); + } + FileAccessor* file_accessor() const { return file_accessor_.get(); } + + private: + base::FilePath src_dir_; + + base::FilePath dest_file_; +#if defined(OS_POSIX) + int dest_fd_ = base::kInvalidPlatformFile; +#endif + + // The relative paths to the files that should be included in the zip file. If + // this is empty, all files in |src_dir_| are included. + std::vector src_files_; + + // Filter used to exclude files from the ZIP file. Only effective when + // |src_files_| is empty. + FilterCallback filter_callback_; + + // Whether hidden files should be included in the ZIP file. Only effective + // when |src_files_| is empty. + bool include_hidden_files_ = true; + + // Abstraction around file system access used to read files. An implementation + // that accesses files directly is provided by default. + std::unique_ptr file_accessor_; +}; + +// Zip files specified into a ZIP archives. The source files and ZIP destination +// files (as well as other settings) are specified in |params|. +bool Zip(const ZipParams& params); + +// Zip the contents of src_dir into dest_file. src_path must be a directory. +// An entry will *not* be created in the zip for the root folder -- children +// of src_dir will be at the root level of the created zip. For each file in +// src_dir, include it only if the callback |filter_cb| returns true. Otherwise +// omit it. +using FilterCallback = base::RepeatingCallback; +bool ZipWithFilterCallback(const base::FilePath& src_dir, + const base::FilePath& dest_file, + const FilterCallback& filter_cb); + +// Convenience method for callers who don't need to set up the filter callback. +// If |include_hidden_files| is true, files starting with "." are included. +// Otherwise they are omitted. +bool Zip(const base::FilePath& src_dir, const base::FilePath& dest_file, + bool include_hidden_files); + +#if defined(OS_POSIX) +// Zips files listed in |src_relative_paths| to destination specified by file +// descriptor |dest_fd|, without taking ownership of |dest_fd|. The paths listed +// in |src_relative_paths| are relative to the |src_dir| and will be used as the +// file names in the created zip file. All source paths must be under |src_dir| +// in the file system hierarchy. +bool ZipFiles(const base::FilePath& src_dir, + const std::vector& src_relative_paths, + int dest_fd); +#endif // defined(OS_POSIX) + +// Unzip the contents of zip_file into dest_dir. +// For each file in zip_file, include it only if the callback |filter_cb| +// returns true. Otherwise omit it. +// If |log_skipped_files| is true, files skipped during extraction are printed +// to debug log. +using FilterCallback = base::RepeatingCallback; +bool UnzipWithFilterCallback(const base::FilePath& zip_file, + const base::FilePath& dest_dir, + const FilterCallback& filter_cb, + bool log_skipped_files); + +// Unzip the contents of zip_file, using the writers provided by writer_factory. +// For each file in zip_file, include it only if the callback |filter_cb| +// returns true. Otherwise omit it. +// If |log_skipped_files| is true, files skipped during extraction are printed +// to debug log. +typedef base::RepeatingCallback( + const base::FilePath&)> + WriterFactory; +typedef base::RepeatingCallback DirectoryCreator; +bool UnzipWithFilterAndWriters(const base::PlatformFile& zip_file, + const WriterFactory& writer_factory, + const DirectoryCreator& directory_creator, + const FilterCallback& filter_cb, + bool log_skipped_files); + +// Unzip the contents of zip_file into dest_dir. +bool Unzip(const base::FilePath& zip_file, const base::FilePath& dest_dir); + +} // namespace zip + +#endif // THIRD_PARTY_ZLIB_GOOGLE_ZIP_H_ diff --git a/deps/zlib/google/zip_internal.cc b/deps/zlib/google/zip_internal.cc new file mode 100644 index 00000000000000..314740f5447c03 --- /dev/null +++ b/deps/zlib/google/zip_internal.cc @@ -0,0 +1,379 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/zlib/google/zip_internal.h" + +#include + +#include + +#include "base/logging.h" +#include "base/strings/utf_string_conversions.h" + +#if defined(USE_SYSTEM_MINIZIP) +#include +#include +#include +#else +#include "third_party/zlib/contrib/minizip/unzip.h" +#include "third_party/zlib/contrib/minizip/zip.h" +#if defined(OS_WIN) +#include "third_party/zlib/contrib/minizip/iowin32.h" +#elif defined(OS_POSIX) +#include "third_party/zlib/contrib/minizip/ioapi.h" +#endif // defined(OS_POSIX) +#endif // defined(USE_SYSTEM_MINIZIP) + +namespace { + +#if defined(OS_WIN) +typedef struct { + HANDLE hf; + int error; +} WIN32FILE_IOWIN; + +// This function is derived from third_party/minizip/iowin32.c. +// Its only difference is that it treats the char* as UTF8 and +// uses the Unicode version of CreateFile. +void* ZipOpenFunc(void *opaque, const char* filename, int mode) { + DWORD desired_access = 0, creation_disposition = 0; + DWORD share_mode = 0, flags_and_attributes = 0; + HANDLE file = 0; + void* ret = NULL; + + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) { + desired_access = GENERIC_READ; + creation_disposition = OPEN_EXISTING; + share_mode = FILE_SHARE_READ; + } else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) { + desired_access = GENERIC_WRITE | GENERIC_READ; + creation_disposition = OPEN_EXISTING; + } else if (mode & ZLIB_FILEFUNC_MODE_CREATE) { + desired_access = GENERIC_WRITE | GENERIC_READ; + creation_disposition = CREATE_ALWAYS; + } + + base::string16 filename16 = base::UTF8ToUTF16(filename); + if ((filename != NULL) && (desired_access != 0)) { + file = CreateFile(filename16.c_str(), desired_access, share_mode, + NULL, creation_disposition, flags_and_attributes, NULL); + } + + if (file == INVALID_HANDLE_VALUE) + file = NULL; + + if (file != NULL) { + WIN32FILE_IOWIN file_ret; + file_ret.hf = file; + file_ret.error = 0; + ret = malloc(sizeof(WIN32FILE_IOWIN)); + if (ret == NULL) + CloseHandle(file); + else + *(static_cast(ret)) = file_ret; + } + return ret; +} +#endif + +#if defined(OS_POSIX) +// Callback function for zlib that opens a file stream from a file descriptor. +// Since we do not own the file descriptor, dup it so that we can fdopen/fclose +// a file stream. +void* FdOpenFileFunc(void* opaque, const char* filename, int mode) { + FILE* file = NULL; + const char* mode_fopen = NULL; + + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename != NULL) && (mode_fopen != NULL)) { + int fd = dup(*static_cast(opaque)); + if (fd != -1) + file = fdopen(fd, mode_fopen); + } + + return file; +} + +int FdCloseFileFunc(void* opaque, void* stream) { + fclose(static_cast(stream)); + free(opaque); // malloc'ed in FillFdOpenFileFunc() + return 0; +} + +// Fills |pzlib_filecunc_def| appropriately to handle the zip file +// referred to by |fd|. +void FillFdOpenFileFunc(zlib_filefunc_def* pzlib_filefunc_def, int fd) { + fill_fopen_filefunc(pzlib_filefunc_def); + pzlib_filefunc_def->zopen_file = FdOpenFileFunc; + pzlib_filefunc_def->zclose_file = FdCloseFileFunc; + int* ptr_fd = static_cast(malloc(sizeof(fd))); + *ptr_fd = fd; + pzlib_filefunc_def->opaque = ptr_fd; +} +#endif // defined(OS_POSIX) + +#if defined(OS_WIN) +// Callback function for zlib that opens a file stream from a Windows handle. +// Does not take ownership of the handle. +void* HandleOpenFileFunc(void* opaque, const char* filename, int mode) { + WIN32FILE_IOWIN file_ret; + file_ret.hf = static_cast(opaque); + file_ret.error = 0; + if (file_ret.hf == INVALID_HANDLE_VALUE) + return NULL; + + void* ret = malloc(sizeof(WIN32FILE_IOWIN)); + if (ret != NULL) + *(static_cast(ret)) = file_ret; + return ret; +} + +int HandleCloseFileFunc(void* opaque, void* stream) { + free(stream); // malloc'ed in HandleOpenFileFunc() + return 0; +} +#endif + +// A struct that contains data required for zlib functions to extract files from +// a zip archive stored in memory directly. The following I/O API functions +// expect their opaque parameters refer to this struct. +struct ZipBuffer { + const char* data; // weak + size_t length; + size_t offset; +}; + +// Opens the specified file. When this function returns a non-NULL pointer, zlib +// uses this pointer as a stream parameter while compressing or uncompressing +// data. (Returning NULL represents an error.) This function initializes the +// given opaque parameter and returns it because this parameter stores all +// information needed for uncompressing data. (This function does not support +// writing compressed data and it returns NULL for this case.) +void* OpenZipBuffer(void* opaque, const char* /*filename*/, int mode) { + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) != ZLIB_FILEFUNC_MODE_READ) { + NOTREACHED(); + return NULL; + } + ZipBuffer* buffer = static_cast(opaque); + if (!buffer || !buffer->data || !buffer->length) + return NULL; + buffer->offset = 0; + return opaque; +} + +// Reads compressed data from the specified stream. This function copies data +// refered by the opaque parameter and returns the size actually copied. +uLong ReadZipBuffer(void* opaque, void* /*stream*/, void* buf, uLong size) { + ZipBuffer* buffer = static_cast(opaque); + DCHECK_LE(buffer->offset, buffer->length); + size_t remaining_bytes = buffer->length - buffer->offset; + if (!buffer || !buffer->data || !remaining_bytes) + return 0; + size = std::min(size, static_cast(remaining_bytes)); + memcpy(buf, &buffer->data[buffer->offset], size); + buffer->offset += size; + return size; +} + +// Writes compressed data to the stream. This function always returns zero +// because this implementation is only for reading compressed data. +uLong WriteZipBuffer(void* /*opaque*/, + void* /*stream*/, + const void* /*buf*/, + uLong /*size*/) { + NOTREACHED(); + return 0; +} + +// Returns the offset from the beginning of the data. +long GetOffsetOfZipBuffer(void* opaque, void* /*stream*/) { + ZipBuffer* buffer = static_cast(opaque); + if (!buffer) + return -1; + return static_cast(buffer->offset); +} + +// Moves the current offset to the specified position. +long SeekZipBuffer(void* opaque, void* /*stream*/, uLong offset, int origin) { + ZipBuffer* buffer = static_cast(opaque); + if (!buffer) + return -1; + if (origin == ZLIB_FILEFUNC_SEEK_CUR) { + buffer->offset = std::min(buffer->offset + static_cast(offset), + buffer->length); + return 0; + } + if (origin == ZLIB_FILEFUNC_SEEK_END) { + buffer->offset = (buffer->length > offset) ? buffer->length - offset : 0; + return 0; + } + if (origin == ZLIB_FILEFUNC_SEEK_SET) { + buffer->offset = std::min(buffer->length, static_cast(offset)); + return 0; + } + NOTREACHED(); + return -1; +} + +// Closes the input offset and deletes all resources used for compressing or +// uncompressing data. This function deletes the ZipBuffer object referred by +// the opaque parameter since zlib deletes the unzFile object and it does not +// use this object any longer. +int CloseZipBuffer(void* opaque, void* /*stream*/) { + if (opaque) + free(opaque); + return 0; +} + +// Returns the last error happened when reading or writing data. This function +// always returns zero, which means there are not any errors. +int GetErrorOfZipBuffer(void* /*opaque*/, void* /*stream*/) { + return 0; +} + +// Returns a zip_fileinfo struct with the time represented by |file_time|. +zip_fileinfo TimeToZipFileInfo(const base::Time& file_time) { + base::Time::Exploded file_time_parts; + file_time.LocalExplode(&file_time_parts); + + zip_fileinfo zip_info = {}; + if (file_time_parts.year >= 1980) { + // This if check works around the handling of the year value in + // contrib/minizip/zip.c in function zip64local_TmzDateToDosDate + // It assumes that dates below 1980 are in the double digit format. + // Hence the fail safe option is to leave the date unset. Some programs + // might show the unset date as 1980-0-0 which is invalid. + zip_info.tmz_date.tm_year = file_time_parts.year; + zip_info.tmz_date.tm_mon = file_time_parts.month - 1; + zip_info.tmz_date.tm_mday = file_time_parts.day_of_month; + zip_info.tmz_date.tm_hour = file_time_parts.hour; + zip_info.tmz_date.tm_min = file_time_parts.minute; + zip_info.tmz_date.tm_sec = file_time_parts.second; + } + + return zip_info; +} +} // namespace + +namespace zip { +namespace internal { + +unzFile OpenForUnzipping(const std::string& file_name_utf8) { + zlib_filefunc_def* zip_func_ptrs = NULL; +#if defined(OS_WIN) + zlib_filefunc_def zip_funcs; + fill_win32_filefunc(&zip_funcs); + zip_funcs.zopen_file = ZipOpenFunc; + zip_func_ptrs = &zip_funcs; +#endif + return unzOpen2(file_name_utf8.c_str(), zip_func_ptrs); +} + +#if defined(OS_POSIX) +unzFile OpenFdForUnzipping(int zip_fd) { + zlib_filefunc_def zip_funcs; + FillFdOpenFileFunc(&zip_funcs, zip_fd); + // Passing dummy "fd" filename to zlib. + return unzOpen2("fd", &zip_funcs); +} +#endif + +#if defined(OS_WIN) +unzFile OpenHandleForUnzipping(HANDLE zip_handle) { + zlib_filefunc_def zip_funcs; + fill_win32_filefunc(&zip_funcs); + zip_funcs.zopen_file = HandleOpenFileFunc; + zip_funcs.zclose_file = HandleCloseFileFunc; + zip_funcs.opaque = zip_handle; + return unzOpen2("fd", &zip_funcs); +} +#endif + +// static +unzFile PrepareMemoryForUnzipping(const std::string& data) { + if (data.empty()) + return NULL; + + ZipBuffer* buffer = static_cast(malloc(sizeof(ZipBuffer))); + if (!buffer) + return NULL; + buffer->data = data.data(); + buffer->length = data.length(); + buffer->offset = 0; + + zlib_filefunc_def zip_functions; + zip_functions.zopen_file = OpenZipBuffer; + zip_functions.zread_file = ReadZipBuffer; + zip_functions.zwrite_file = WriteZipBuffer; + zip_functions.ztell_file = GetOffsetOfZipBuffer; + zip_functions.zseek_file = SeekZipBuffer; + zip_functions.zclose_file = CloseZipBuffer; + zip_functions.zerror_file = GetErrorOfZipBuffer; + zip_functions.opaque = static_cast(buffer); + return unzOpen2(NULL, &zip_functions); +} + +zipFile OpenForZipping(const std::string& file_name_utf8, int append_flag) { + zlib_filefunc_def* zip_func_ptrs = NULL; +#if defined(OS_WIN) + zlib_filefunc_def zip_funcs; + fill_win32_filefunc(&zip_funcs); + zip_funcs.zopen_file = ZipOpenFunc; + zip_func_ptrs = &zip_funcs; +#endif + return zipOpen2(file_name_utf8.c_str(), + append_flag, + NULL, // global comment + zip_func_ptrs); +} + +#if defined(OS_POSIX) +zipFile OpenFdForZipping(int zip_fd, int append_flag) { + zlib_filefunc_def zip_funcs; + FillFdOpenFileFunc(&zip_funcs, zip_fd); + // Passing dummy "fd" filename to zlib. + return zipOpen2("fd", append_flag, NULL, &zip_funcs); +} +#endif + +bool ZipOpenNewFileInZip(zipFile zip_file, + const std::string& str_path, + base::Time last_modified_time) { + // Section 4.4.4 http://www.pkware.com/documents/casestudies/APPNOTE.TXT + // Setting the Language encoding flag so the file is told to be in utf-8. + const uLong LANGUAGE_ENCODING_FLAG = 0x1 << 11; + + zip_fileinfo file_info = TimeToZipFileInfo(last_modified_time); + if (ZIP_OK != zipOpenNewFileInZip4(zip_file, // file + str_path.c_str(), // filename + &file_info, // zip_fileinfo + NULL, // extrafield_local, + 0u, // size_extrafield_local + NULL, // extrafield_global + 0u, // size_extrafield_global + NULL, // comment + Z_DEFLATED, // method + Z_DEFAULT_COMPRESSION, // level + 0, // raw + -MAX_WBITS, // windowBits + DEF_MEM_LEVEL, // memLevel + Z_DEFAULT_STRATEGY, // strategy + NULL, // password + 0, // crcForCrypting + 0, // versionMadeBy + LANGUAGE_ENCODING_FLAG)) { // flagBase + DLOG(ERROR) << "Could not open zip file entry " << str_path; + return false; + } + return true; +} + +} // namespace internal +} // namespace zip diff --git a/deps/zlib/google/zip_internal.h b/deps/zlib/google/zip_internal.h new file mode 100644 index 00000000000000..49fb902a7408e7 --- /dev/null +++ b/deps/zlib/google/zip_internal.h @@ -0,0 +1,74 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_ZLIB_GOOGLE_ZIP_INTERNAL_H_ +#define THIRD_PARTY_ZLIB_GOOGLE_ZIP_INTERNAL_H_ + +#include + +#include "base/time/time.h" +#include "build/build_config.h" + +#if defined(OS_WIN) +#include +#endif + +#if defined(USE_SYSTEM_MINIZIP) +#include +#include +#else +#include "third_party/zlib/contrib/minizip/unzip.h" +#include "third_party/zlib/contrib/minizip/zip.h" +#endif + +namespace base { +class FilePath; +} + +// Utility functions and constants used internally for the zip file +// library in the directory. Don't use them outside of the library. +namespace zip { +namespace internal { + +// Opens the given file name in UTF-8 for unzipping, with some setup for +// Windows. +unzFile OpenForUnzipping(const std::string& file_name_utf8); + +#if defined(OS_POSIX) +// Opens the file referred to by |zip_fd| for unzipping. +unzFile OpenFdForUnzipping(int zip_fd); +#endif + +#if defined(OS_WIN) +// Opens the file referred to by |zip_handle| for unzipping. +unzFile OpenHandleForUnzipping(HANDLE zip_handle); +#endif + +// Creates a custom unzFile object which reads data from the specified string. +// This custom unzFile object overrides the I/O API functions of zlib so it can +// read data from the specified string. +unzFile PrepareMemoryForUnzipping(const std::string& data); + +// Opens the given file name in UTF-8 for zipping, with some setup for +// Windows. |append_flag| will be passed to zipOpen2(). +zipFile OpenForZipping(const std::string& file_name_utf8, int append_flag); + +#if defined(OS_POSIX) +// Opens the file referred to by |zip_fd| for zipping. |append_flag| will be +// passed to zipOpen2(). +zipFile OpenFdForZipping(int zip_fd, int append_flag); +#endif + +// Wrapper around zipOpenNewFileInZip4 which passes most common options. +bool ZipOpenNewFileInZip(zipFile zip_file, + const std::string& str_path, + base::Time last_modified_time); + +const int kZipMaxPath = 256; +const int kZipBufSize = 8192; + +} // namespace internal +} // namespace zip + +#endif // THIRD_PARTY_ZLIB_GOOGLE_ZIP_INTERNAL_H_ diff --git a/deps/zlib/google/zip_reader.cc b/deps/zlib/google/zip_reader.cc new file mode 100644 index 00000000000000..8b4bb4aee782bf --- /dev/null +++ b/deps/zlib/google/zip_reader.cc @@ -0,0 +1,502 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/zlib/google/zip_reader.h" + +#include + +#include "base/bind.h" +#include "base/files/file.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/single_thread_task_runner.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/threading/thread_task_runner_handle.h" +#include "build/build_config.h" +#include "third_party/zlib/google/zip_internal.h" + +#if defined(USE_SYSTEM_MINIZIP) +#include +#else +#include "third_party/zlib/contrib/minizip/unzip.h" +#if defined(OS_WIN) +#include "third_party/zlib/contrib/minizip/iowin32.h" +#endif // defined(OS_WIN) +#endif // defined(USE_SYSTEM_MINIZIP) + +namespace zip { + +namespace { + +// StringWriterDelegate -------------------------------------------------------- + +// A writer delegate that writes no more than |max_read_bytes| to a given +// std::string. +class StringWriterDelegate : public WriterDelegate { + public: + StringWriterDelegate(size_t max_read_bytes, std::string* output); + ~StringWriterDelegate() override; + + // WriterDelegate methods: + + // Returns true. + bool PrepareOutput() override; + + // Appends |num_bytes| bytes from |data| to the output string. Returns false + // if |num_bytes| will cause the string to exceed |max_read_bytes|. + bool WriteBytes(const char* data, int num_bytes) override; + + void SetTimeModified(const base::Time& time) override; + + private: + size_t max_read_bytes_; + std::string* output_; + + DISALLOW_COPY_AND_ASSIGN(StringWriterDelegate); +}; + +StringWriterDelegate::StringWriterDelegate(size_t max_read_bytes, + std::string* output) + : max_read_bytes_(max_read_bytes), + output_(output) { +} + +StringWriterDelegate::~StringWriterDelegate() { +} + +bool StringWriterDelegate::PrepareOutput() { + return true; +} + +bool StringWriterDelegate::WriteBytes(const char* data, int num_bytes) { + if (output_->size() + num_bytes > max_read_bytes_) + return false; + output_->append(data, num_bytes); + return true; +} + +void StringWriterDelegate::SetTimeModified(const base::Time& time) { + // Do nothing. +} + +} // namespace + +// TODO(satorux): The implementation assumes that file names in zip files +// are encoded in UTF-8. This is true for zip files created by Zip() +// function in zip.h, but not true for user-supplied random zip files. +ZipReader::EntryInfo::EntryInfo(const std::string& file_name_in_zip, + const unz_file_info& raw_file_info) + : file_path_(base::FilePath::FromUTF8Unsafe(file_name_in_zip)), + is_directory_(false), + is_unsafe_(false), + is_encrypted_(false) { + original_size_ = raw_file_info.uncompressed_size; + + // Directory entries in zip files end with "/". + is_directory_ = base::EndsWith(file_name_in_zip, "/", + base::CompareCase::INSENSITIVE_ASCII); + + // Check the file name here for directory traversal issues. + is_unsafe_ = file_path_.ReferencesParent(); + + // We also consider that the file name is unsafe, if it's invalid UTF-8. + base::string16 file_name_utf16; + if (!base::UTF8ToUTF16(file_name_in_zip.data(), file_name_in_zip.size(), + &file_name_utf16)) { + is_unsafe_ = true; + } + + // We also consider that the file name is unsafe, if it's absolute. + // On Windows, IsAbsolute() returns false for paths starting with "/". + if (file_path_.IsAbsolute() || + base::StartsWith(file_name_in_zip, "/", + base::CompareCase::INSENSITIVE_ASCII)) + is_unsafe_ = true; + + // Whether the file is encrypted is bit 0 of the flag. + is_encrypted_ = raw_file_info.flag & 1; + + // Construct the last modified time. The timezone info is not present in + // zip files, so we construct the time as local time. + base::Time::Exploded exploded_time = {}; // Zero-clear. + exploded_time.year = raw_file_info.tmu_date.tm_year; + // The month in zip file is 0-based, whereas ours is 1-based. + exploded_time.month = raw_file_info.tmu_date.tm_mon + 1; + exploded_time.day_of_month = raw_file_info.tmu_date.tm_mday; + exploded_time.hour = raw_file_info.tmu_date.tm_hour; + exploded_time.minute = raw_file_info.tmu_date.tm_min; + exploded_time.second = raw_file_info.tmu_date.tm_sec; + exploded_time.millisecond = 0; + + if (!base::Time::FromLocalExploded(exploded_time, &last_modified_)) + last_modified_ = base::Time::UnixEpoch(); +} + +ZipReader::ZipReader() { + Reset(); +} + +ZipReader::~ZipReader() { + Close(); +} + +bool ZipReader::Open(const base::FilePath& zip_file_path) { + DCHECK(!zip_file_); + + // Use of "Unsafe" function does not look good, but there is no way to do + // this safely on Linux. See file_util.h for details. + zip_file_ = internal::OpenForUnzipping(zip_file_path.AsUTF8Unsafe()); + if (!zip_file_) { + return false; + } + + return OpenInternal(); +} + +bool ZipReader::OpenFromPlatformFile(base::PlatformFile zip_fd) { + DCHECK(!zip_file_); + +#if defined(OS_POSIX) + zip_file_ = internal::OpenFdForUnzipping(zip_fd); +#elif defined(OS_WIN) + zip_file_ = internal::OpenHandleForUnzipping(zip_fd); +#endif + if (!zip_file_) { + return false; + } + + return OpenInternal(); +} + +bool ZipReader::OpenFromString(const std::string& data) { + zip_file_ = internal::PrepareMemoryForUnzipping(data); + if (!zip_file_) + return false; + return OpenInternal(); +} + +void ZipReader::Close() { + if (zip_file_) { + unzClose(zip_file_); + } + Reset(); +} + +bool ZipReader::HasMore() { + return !reached_end_; +} + +bool ZipReader::AdvanceToNextEntry() { + DCHECK(zip_file_); + + // Should not go further if we already reached the end. + if (reached_end_) + return false; + + unz_file_pos position = {}; + if (unzGetFilePos(zip_file_, &position) != UNZ_OK) + return false; + const int current_entry_index = position.num_of_file; + // If we are currently at the last entry, then the next position is the + // end of the zip file, so mark that we reached the end. + if (current_entry_index + 1 == num_entries_) { + reached_end_ = true; + } else { + DCHECK_LT(current_entry_index + 1, num_entries_); + if (unzGoToNextFile(zip_file_) != UNZ_OK) { + return false; + } + } + current_entry_info_.reset(); + return true; +} + +bool ZipReader::OpenCurrentEntryInZip() { + DCHECK(zip_file_); + + unz_file_info raw_file_info = {}; + char raw_file_name_in_zip[internal::kZipMaxPath] = {}; + const int result = unzGetCurrentFileInfo(zip_file_, + &raw_file_info, + raw_file_name_in_zip, + sizeof(raw_file_name_in_zip) - 1, + NULL, // extraField. + 0, // extraFieldBufferSize. + NULL, // szComment. + 0); // commentBufferSize. + if (result != UNZ_OK) + return false; + if (raw_file_name_in_zip[0] == '\0') + return false; + current_entry_info_.reset( + new EntryInfo(raw_file_name_in_zip, raw_file_info)); + return true; +} + +bool ZipReader::ExtractCurrentEntry(WriterDelegate* delegate, + uint64_t num_bytes_to_extract) const { + DCHECK(zip_file_); + + const int open_result = unzOpenCurrentFile(zip_file_); + if (open_result != UNZ_OK) + return false; + + if (!delegate->PrepareOutput()) + return false; + std::unique_ptr buf(new char[internal::kZipBufSize]); + + uint64_t remaining_capacity = num_bytes_to_extract; + bool entire_file_extracted = false; + + while (remaining_capacity > 0) { + const int num_bytes_read = + unzReadCurrentFile(zip_file_, buf.get(), internal::kZipBufSize); + + if (num_bytes_read == 0) { + entire_file_extracted = true; + break; + } else if (num_bytes_read < 0) { + // If num_bytes_read < 0, then it's a specific UNZ_* error code. + break; + } else if (num_bytes_read > 0) { + uint64_t num_bytes_to_write = std::min( + remaining_capacity, base::checked_cast(num_bytes_read)); + if (!delegate->WriteBytes(buf.get(), num_bytes_to_write)) + break; + if (remaining_capacity == base::checked_cast(num_bytes_read)) { + // Ensures function returns true if the entire file has been read. + entire_file_extracted = + (unzReadCurrentFile(zip_file_, buf.get(), 1) == 0); + } + CHECK_GE(remaining_capacity, num_bytes_to_write); + remaining_capacity -= num_bytes_to_write; + } + } + + unzCloseCurrentFile(zip_file_); + + if (entire_file_extracted && + current_entry_info()->last_modified() != base::Time::UnixEpoch()) { + delegate->SetTimeModified(current_entry_info()->last_modified()); + } + + return entire_file_extracted; +} + +void ZipReader::ExtractCurrentEntryToFilePathAsync( + const base::FilePath& output_file_path, + SuccessCallback success_callback, + FailureCallback failure_callback, + const ProgressCallback& progress_callback) { + DCHECK(zip_file_); + DCHECK(current_entry_info_.get()); + + // If this is a directory, just create it and return. + if (current_entry_info()->is_directory()) { + if (base::CreateDirectory(output_file_path)) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, std::move(success_callback)); + } else { + DVLOG(1) << "Unzip failed: unable to create directory."; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, std::move(failure_callback)); + } + return; + } + + if (unzOpenCurrentFile(zip_file_) != UNZ_OK) { + DVLOG(1) << "Unzip failed: unable to open current zip entry."; + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + std::move(failure_callback)); + return; + } + + base::FilePath output_dir_path = output_file_path.DirName(); + if (!base::CreateDirectory(output_dir_path)) { + DVLOG(1) << "Unzip failed: unable to create containing directory."; + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + std::move(failure_callback)); + return; + } + + const int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE; + base::File output_file(output_file_path, flags); + + if (!output_file.IsValid()) { + DVLOG(1) << "Unzip failed: unable to create platform file at " + << output_file_path.value(); + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + std::move(failure_callback)); + return; + } + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&ZipReader::ExtractChunk, weak_ptr_factory_.GetWeakPtr(), + Passed(std::move(output_file)), + std::move(success_callback), std::move(failure_callback), + progress_callback, 0 /* initial offset */)); +} + +bool ZipReader::ExtractCurrentEntryToString(uint64_t max_read_bytes, + std::string* output) const { + DCHECK(output); + DCHECK(zip_file_); + + if (max_read_bytes == 0) { + output->clear(); + return true; + } + + if (current_entry_info()->is_directory()) { + output->clear(); + return true; + } + + // The original_size() is the best hint for the real size, so it saves + // doing reallocations for the common case when the uncompressed size is + // correct. However, we need to assume that the uncompressed size could be + // incorrect therefore this function needs to read as much data as possible. + std::string contents; + contents.reserve( + static_cast(std::min(base::checked_cast(max_read_bytes), + current_entry_info()->original_size()))); + + StringWriterDelegate writer(max_read_bytes, &contents); + if (!ExtractCurrentEntry(&writer, max_read_bytes)) { + if (contents.length() < max_read_bytes) { + // There was an error in extracting entry. If ExtractCurrentEntry() + // returns false, the entire file was not read - in which case + // contents.length() should equal |max_read_bytes| unless an error + // occurred which caused extraction to be aborted. + output->clear(); + } else { + // |num_bytes| is less than the length of current entry. + output->swap(contents); + } + return false; + } + output->swap(contents); + return true; +} + +bool ZipReader::OpenInternal() { + DCHECK(zip_file_); + + unz_global_info zip_info = {}; // Zero-clear. + if (unzGetGlobalInfo(zip_file_, &zip_info) != UNZ_OK) { + return false; + } + num_entries_ = zip_info.number_entry; + if (num_entries_ < 0) + return false; + + // We are already at the end if the zip file is empty. + reached_end_ = (num_entries_ == 0); + return true; +} + +void ZipReader::Reset() { + zip_file_ = NULL; + num_entries_ = 0; + reached_end_ = false; + current_entry_info_.reset(); +} + +void ZipReader::ExtractChunk(base::File output_file, + SuccessCallback success_callback, + FailureCallback failure_callback, + const ProgressCallback& progress_callback, + const int64_t offset) { + char buffer[internal::kZipBufSize]; + + const int num_bytes_read = unzReadCurrentFile(zip_file_, + buffer, + internal::kZipBufSize); + + if (num_bytes_read == 0) { + unzCloseCurrentFile(zip_file_); + std::move(success_callback).Run(); + } else if (num_bytes_read < 0) { + DVLOG(1) << "Unzip failed: error while reading zipfile " + << "(" << num_bytes_read << ")"; + std::move(failure_callback).Run(); + } else { + if (num_bytes_read != output_file.Write(offset, buffer, num_bytes_read)) { + DVLOG(1) << "Unzip failed: unable to write all bytes to target."; + std::move(failure_callback).Run(); + return; + } + + int64_t current_progress = offset + num_bytes_read; + + progress_callback.Run(current_progress); + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&ZipReader::ExtractChunk, weak_ptr_factory_.GetWeakPtr(), + Passed(std::move(output_file)), + std::move(success_callback), std::move(failure_callback), + progress_callback, current_progress)); + } +} + +// FileWriterDelegate ---------------------------------------------------------- + +FileWriterDelegate::FileWriterDelegate(base::File* file) : file_(file) {} + +FileWriterDelegate::FileWriterDelegate(std::unique_ptr file) + : file_(file.get()), owned_file_(std::move(file)) {} + +FileWriterDelegate::~FileWriterDelegate() { + if (!file_->SetLength(file_length_)) { + DVPLOG(1) << "Failed updating length of written file"; + } +} + +bool FileWriterDelegate::PrepareOutput() { + return file_->Seek(base::File::FROM_BEGIN, 0) >= 0; +} + +bool FileWriterDelegate::WriteBytes(const char* data, int num_bytes) { + int bytes_written = file_->WriteAtCurrentPos(data, num_bytes); + if (bytes_written > 0) + file_length_ += bytes_written; + return bytes_written == num_bytes; +} + +void FileWriterDelegate::SetTimeModified(const base::Time& time) { + file_->SetTimes(base::Time::Now(), time); +} + +// FilePathWriterDelegate ------------------------------------------------------ + +FilePathWriterDelegate::FilePathWriterDelegate( + const base::FilePath& output_file_path) + : output_file_path_(output_file_path) {} + +FilePathWriterDelegate::~FilePathWriterDelegate() {} + +bool FilePathWriterDelegate::PrepareOutput() { + // We can't rely on parent directory entries being specified in the + // zip, so we make sure they are created. + if (!base::CreateDirectory(output_file_path_.DirName())) + return false; + + file_.Initialize(output_file_path_, + base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); + return file_.IsValid(); +} + +bool FilePathWriterDelegate::WriteBytes(const char* data, int num_bytes) { + return num_bytes == file_.WriteAtCurrentPos(data, num_bytes); +} + +void FilePathWriterDelegate::SetTimeModified(const base::Time& time) { + file_.Close(); + base::TouchFile(output_file_path_, base::Time::Now(), time); +} + +} // namespace zip diff --git a/deps/zlib/google/zip_reader.h b/deps/zlib/google/zip_reader.h new file mode 100644 index 00000000000000..d442d428591e50 --- /dev/null +++ b/deps/zlib/google/zip_reader.h @@ -0,0 +1,301 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef THIRD_PARTY_ZLIB_GOOGLE_ZIP_READER_H_ +#define THIRD_PARTY_ZLIB_GOOGLE_ZIP_READER_H_ + +#include +#include + +#include +#include + +#include "base/callback.h" +#include "base/files/file.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" + +#if defined(USE_SYSTEM_MINIZIP) +#include +#else +#include "third_party/zlib/contrib/minizip/unzip.h" +#endif + +namespace zip { + +// A delegate interface used to stream out an entry; see +// ZipReader::ExtractCurrentEntry. +class WriterDelegate { + public: + virtual ~WriterDelegate() {} + + // Invoked once before any data is streamed out to pave the way (e.g., to open + // the output file). Return false on failure to cancel extraction. + virtual bool PrepareOutput() = 0; + + // Invoked to write the next chunk of data. Return false on failure to cancel + // extraction. + virtual bool WriteBytes(const char* data, int num_bytes) = 0; + + // Sets the last-modified time of the data. + virtual void SetTimeModified(const base::Time& time) = 0; +}; + +// This class is used for reading zip files. A typical use case of this +// class is to scan entries in a zip file and extract them. The code will +// look like: +// +// ZipReader reader; +// reader.Open(zip_file_path); +// while (reader.HasMore()) { +// reader.OpenCurrentEntryInZip(); +// const base::FilePath& entry_path = +// reader.current_entry_info()->file_path(); +// auto writer = CreateFilePathWriterDelegate(extract_dir, entry_path); +// reader.ExtractCurrentEntry(writer, std::numeric_limits::max()); +// reader.AdvanceToNextEntry(); +// } +// +// For simplicity, error checking is omitted in the example code above. The +// production code should check return values from all of these functions. +// +class ZipReader { + public: + // A callback that is called when the operation is successful. + using SuccessCallback = base::OnceClosure; + // A callback that is called when the operation fails. + using FailureCallback = base::OnceClosure; + // A callback that is called periodically during the operation with the number + // of bytes that have been processed so far. + using ProgressCallback = base::RepeatingCallback; + + // This class represents information of an entry (file or directory) in + // a zip file. + class EntryInfo { + public: + EntryInfo(const std::string& filename_in_zip, + const unz_file_info& raw_file_info); + + // Returns the file path. The path is usually relative like + // "foo/bar.txt", but if it's absolute, is_unsafe() returns true. + const base::FilePath& file_path() const { return file_path_; } + + // Returns the size of the original file (i.e. after uncompressed). + // Returns 0 if the entry is a directory. + // Note: this value should not be trusted, because it is stored as metadata + // in the zip archive and can be different from the real uncompressed size. + int64_t original_size() const { return original_size_; } + + // Returns the last modified time. If the time stored in the zip file was + // not valid, the unix epoch will be returned. + // + // The time stored in the zip archive uses the MS-DOS date and time format. + // http://msdn.microsoft.com/en-us/library/ms724247(v=vs.85).aspx + // As such the following limitations apply: + // * only years from 1980 to 2107 can be represented. + // * the time stamp has a 2 second resolution. + // * there's no timezone information, so the time is interpreted as local. + base::Time last_modified() const { return last_modified_; } + + // Returns true if the entry is a directory. + bool is_directory() const { return is_directory_; } + + // Returns true if the entry is unsafe, like having ".." or invalid + // UTF-8 characters in its file name, or the file path is absolute. + bool is_unsafe() const { return is_unsafe_; } + + // Returns true if the entry is encrypted. + bool is_encrypted() const { return is_encrypted_; } + + private: + const base::FilePath file_path_; + int64_t original_size_; + base::Time last_modified_; + bool is_directory_; + bool is_unsafe_; + bool is_encrypted_; + DISALLOW_COPY_AND_ASSIGN(EntryInfo); + }; + + ZipReader(); + ~ZipReader(); + + // Opens the zip file specified by |zip_file_path|. Returns true on + // success. + bool Open(const base::FilePath& zip_file_path); + + // Opens the zip file referred to by the platform file |zip_fd|, without + // taking ownership of |zip_fd|. Returns true on success. + bool OpenFromPlatformFile(base::PlatformFile zip_fd); + + // Opens the zip data stored in |data|. This class uses a weak reference to + // the given sring while extracting files, i.e. the caller should keep the + // string until it finishes extracting files. + bool OpenFromString(const std::string& data); + + // Closes the currently opened zip file. This function is called in the + // destructor of the class, so you usually don't need to call this. + void Close(); + + // Returns true if there is at least one entry to read. This function is + // used to scan entries with AdvanceToNextEntry(), like: + // + // while (reader.HasMore()) { + // // Do something with the current file here. + // reader.AdvanceToNextEntry(); + // } + bool HasMore(); + + // Advances the next entry. Returns true on success. + bool AdvanceToNextEntry(); + + // Opens the current entry in the zip file. On success, returns true and + // updates the the current entry state (i.e. current_entry_info() is + // updated). This function should be called before operations over the + // current entry like ExtractCurrentEntryToFile(). + // + // Note that there is no CloseCurrentEntryInZip(). The the current entry + // state is reset automatically as needed. + bool OpenCurrentEntryInZip(); + + // Extracts |num_bytes_to_extract| bytes of the current entry to |delegate|, + // starting from the beginning of the entry. Return value specifies whether + // the entire file was extracted. + bool ExtractCurrentEntry(WriterDelegate* delegate, + uint64_t num_bytes_to_extract) const; + + // Asynchronously extracts the current entry to the given output file path. + // If the current entry is a directory it just creates the directory + // synchronously instead. OpenCurrentEntryInZip() must be called beforehand. + // success_callback will be called on success and failure_callback will be + // called on failure. progress_callback will be called at least once. + // Callbacks will be posted to the current MessageLoop in-order. + void ExtractCurrentEntryToFilePathAsync( + const base::FilePath& output_file_path, + SuccessCallback success_callback, + FailureCallback failure_callback, + const ProgressCallback& progress_callback); + + // Extracts the current entry into memory. If the current entry is a + // directory, the |output| parameter is set to the empty string. If the + // current entry is a file, the |output| parameter is filled with its + // contents. OpenCurrentEntryInZip() must be called beforehand. Note: the + // |output| parameter can be filled with a big amount of data, avoid passing + // it around by value, but by reference or pointer. Note: the value returned + // by EntryInfo::original_size() cannot be trusted, so the real size of the + // uncompressed contents can be different. |max_read_bytes| limits the ammount + // of memory used to carry the entry. Returns true if the entire content is + // read. If the entry is bigger than |max_read_bytes|, returns false and + // |output| is filled with |max_read_bytes| of data. If an error occurs, + // returns false, and |output| is set to the empty string. + bool ExtractCurrentEntryToString(uint64_t max_read_bytes, + std::string* output) const; + + // Returns the current entry info. Returns NULL if the current entry is + // not yet opened. OpenCurrentEntryInZip() must be called beforehand. + EntryInfo* current_entry_info() const { + return current_entry_info_.get(); + } + + // Returns the number of entries in the zip file. + // Open() must be called beforehand. + int num_entries() const { return num_entries_; } + + private: + // Common code used both in Open and OpenFromFd. + bool OpenInternal(); + + // Resets the internal state. + void Reset(); + + // Extracts a chunk of the file to the target. Will post a task for the next + // chunk and success/failure/progress callbacks as necessary. + void ExtractChunk(base::File target_file, + SuccessCallback success_callback, + FailureCallback failure_callback, + const ProgressCallback& progress_callback, + const int64_t offset); + + unzFile zip_file_; + int num_entries_; + bool reached_end_; + std::unique_ptr current_entry_info_; + + base::WeakPtrFactory weak_ptr_factory_{this}; + + DISALLOW_COPY_AND_ASSIGN(ZipReader); +}; + +// A writer delegate that writes to a given File. +class FileWriterDelegate : public WriterDelegate { + public: + // Constructs a FileWriterDelegate that manipulates |file|. The delegate will + // not own |file|, therefore the caller must guarantee |file| will outlive the + // delegate. + explicit FileWriterDelegate(base::File* file); + + // Constructs a FileWriterDelegate that takes ownership of |file|. + explicit FileWriterDelegate(std::unique_ptr file); + + // Truncates the file to the number of bytes written. + ~FileWriterDelegate() override; + + // WriterDelegate methods: + + // Seeks to the beginning of the file, returning false if the seek fails. + bool PrepareOutput() override; + + // Writes |num_bytes| bytes of |data| to the file, returning false on error or + // if not all bytes could be written. + bool WriteBytes(const char* data, int num_bytes) override; + + // Sets the last-modified time of the data. + void SetTimeModified(const base::Time& time) override; + + // Return the actual size of the file. + int64_t file_length() { return file_length_; } + + private: + // The file the delegate modifies. + base::File* file_; + + // The delegate can optionally own the file it modifies, in which case + // owned_file_ is set and file_ is an alias for owned_file_. + std::unique_ptr owned_file_; + + int64_t file_length_ = 0; + + DISALLOW_COPY_AND_ASSIGN(FileWriterDelegate); +}; + +// A writer delegate that writes a file at a given path. +class FilePathWriterDelegate : public WriterDelegate { + public: + explicit FilePathWriterDelegate(const base::FilePath& output_file_path); + ~FilePathWriterDelegate() override; + + // WriterDelegate methods: + + // Creates the output file and any necessary intermediate directories. + bool PrepareOutput() override; + + // Writes |num_bytes| bytes of |data| to the file, returning false if not all + // bytes could be written. + bool WriteBytes(const char* data, int num_bytes) override; + + // Sets the last-modified time of the data. + void SetTimeModified(const base::Time& time) override; + + private: + base::FilePath output_file_path_; + base::File file_; + + DISALLOW_COPY_AND_ASSIGN(FilePathWriterDelegate); +}; + +} // namespace zip + +#endif // THIRD_PARTY_ZLIB_GOOGLE_ZIP_READER_H_ diff --git a/deps/zlib/google/zip_reader_unittest.cc b/deps/zlib/google/zip_reader_unittest.cc new file mode 100644 index 00000000000000..87190c7e0dee76 --- /dev/null +++ b/deps/zlib/google/zip_reader_unittest.cc @@ -0,0 +1,672 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/zlib/google/zip_reader.h" + +#include +#include +#include + +#include +#include + +#include "base/bind.h" +#include "base/files/file.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/hash/md5.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/run_loop.h" +#include "base/stl_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/task_environment.h" +#include "base/time/time.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" +#include "third_party/zlib/google/zip_internal.h" + +using ::testing::Return; +using ::testing::_; + +namespace { + +const static std::string kQuuxExpectedMD5 = "d1ae4ac8a17a0e09317113ab284b57a6"; + +class FileWrapper { + public: + typedef enum { + READ_ONLY, + READ_WRITE + } AccessMode; + + FileWrapper(const base::FilePath& path, AccessMode mode) { + int flags = base::File::FLAG_READ; + if (mode == READ_ONLY) + flags |= base::File::FLAG_OPEN; + else + flags |= base::File::FLAG_WRITE | base::File::FLAG_CREATE_ALWAYS; + + file_.Initialize(path, flags); + } + + ~FileWrapper() {} + + base::PlatformFile platform_file() { return file_.GetPlatformFile(); } + + base::File* file() { return &file_; } + + private: + base::File file_; +}; + +// A mock that provides methods that can be used as callbacks in asynchronous +// unzip functions. Tracks the number of calls and number of bytes reported. +// Assumes that progress callbacks will be executed in-order. +class MockUnzipListener : public base::SupportsWeakPtr { + public: + MockUnzipListener() + : success_calls_(0), + failure_calls_(0), + progress_calls_(0), + current_progress_(0) { + } + + // Success callback for async functions. + void OnUnzipSuccess() { + success_calls_++; + } + + // Failure callback for async functions. + void OnUnzipFailure() { + failure_calls_++; + } + + // Progress callback for async functions. + void OnUnzipProgress(int64_t progress) { + DCHECK(progress > current_progress_); + progress_calls_++; + current_progress_ = progress; + } + + int success_calls() { return success_calls_; } + int failure_calls() { return failure_calls_; } + int progress_calls() { return progress_calls_; } + int current_progress() { return current_progress_; } + + private: + int success_calls_; + int failure_calls_; + int progress_calls_; + + int64_t current_progress_; +}; + +class MockWriterDelegate : public zip::WriterDelegate { + public: + MOCK_METHOD0(PrepareOutput, bool()); + MOCK_METHOD2(WriteBytes, bool(const char*, int)); + MOCK_METHOD1(SetTimeModified, void(const base::Time&)); +}; + +bool ExtractCurrentEntryToFilePath(zip::ZipReader* reader, + base::FilePath path) { + zip::FilePathWriterDelegate writer(path); + return reader->ExtractCurrentEntry(&writer, + std::numeric_limits::max()); +} + +bool LocateAndOpenEntry(zip::ZipReader* reader, + const base::FilePath& path_in_zip) { + // The underlying library can do O(1) access, but ZipReader does not expose + // that. O(N) access is acceptable for these tests. + while (reader->HasMore()) { + if (!reader->OpenCurrentEntryInZip()) + return false; + if (reader->current_entry_info()->file_path() == path_in_zip) + return true; + reader->AdvanceToNextEntry(); + } + return false; +} + +} // namespace + +namespace zip { + +// Make the test a PlatformTest to setup autorelease pools properly on Mac. +class ZipReaderTest : public PlatformTest { + protected: + virtual void SetUp() { + PlatformTest::SetUp(); + + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + test_dir_ = temp_dir_.GetPath(); + + ASSERT_TRUE(GetTestDataDirectory(&test_data_dir_)); + + test_zip_file_ = test_data_dir_.AppendASCII("test.zip"); + encrypted_zip_file_ = test_data_dir_.AppendASCII("test_encrypted.zip"); + evil_zip_file_ = test_data_dir_.AppendASCII("evil.zip"); + evil_via_invalid_utf8_zip_file_ = test_data_dir_.AppendASCII( + "evil_via_invalid_utf8.zip"); + evil_via_absolute_file_name_zip_file_ = test_data_dir_.AppendASCII( + "evil_via_absolute_file_name.zip"); + + test_zip_contents_.insert(base::FilePath(FILE_PATH_LITERAL("foo/"))); + test_zip_contents_.insert(base::FilePath(FILE_PATH_LITERAL("foo/bar/"))); + test_zip_contents_.insert( + base::FilePath(FILE_PATH_LITERAL("foo/bar/baz.txt"))); + test_zip_contents_.insert( + base::FilePath(FILE_PATH_LITERAL("foo/bar/quux.txt"))); + test_zip_contents_.insert( + base::FilePath(FILE_PATH_LITERAL("foo/bar.txt"))); + test_zip_contents_.insert(base::FilePath(FILE_PATH_LITERAL("foo.txt"))); + test_zip_contents_.insert( + base::FilePath(FILE_PATH_LITERAL("foo/bar/.hidden"))); + } + + virtual void TearDown() { + PlatformTest::TearDown(); + } + + bool GetTestDataDirectory(base::FilePath* path) { + bool success = base::PathService::Get(base::DIR_SOURCE_ROOT, path); + EXPECT_TRUE(success); + if (!success) + return false; + *path = path->AppendASCII("third_party"); + *path = path->AppendASCII("zlib"); + *path = path->AppendASCII("google"); + *path = path->AppendASCII("test"); + *path = path->AppendASCII("data"); + return true; + } + + bool CompareFileAndMD5(const base::FilePath& path, + const std::string expected_md5) { + // Read the output file and compute the MD5. + std::string output; + if (!base::ReadFileToString(path, &output)) + return false; + const std::string md5 = base::MD5String(output); + return expected_md5 == md5; + } + + // The path to temporary directory used to contain the test operations. + base::FilePath test_dir_; + // The path to the test data directory where test.zip etc. are located. + base::FilePath test_data_dir_; + // The path to test.zip in the test data directory. + base::FilePath test_zip_file_; + // The path to test_encrypted.zip in the test data directory. + base::FilePath encrypted_zip_file_; + // The path to evil.zip in the test data directory. + base::FilePath evil_zip_file_; + // The path to evil_via_invalid_utf8.zip in the test data directory. + base::FilePath evil_via_invalid_utf8_zip_file_; + // The path to evil_via_absolute_file_name.zip in the test data directory. + base::FilePath evil_via_absolute_file_name_zip_file_; + std::set test_zip_contents_; + + base::ScopedTempDir temp_dir_; + + base::test::TaskEnvironment task_environment_; +}; + +TEST_F(ZipReaderTest, Open_ValidZipFile) { + ZipReader reader; + ASSERT_TRUE(reader.Open(test_zip_file_)); +} + +TEST_F(ZipReaderTest, Open_ValidZipPlatformFile) { + ZipReader reader; + FileWrapper zip_fd_wrapper(test_zip_file_, FileWrapper::READ_ONLY); + ASSERT_TRUE(reader.OpenFromPlatformFile(zip_fd_wrapper.platform_file())); +} + +TEST_F(ZipReaderTest, Open_NonExistentFile) { + ZipReader reader; + ASSERT_FALSE(reader.Open(test_data_dir_.AppendASCII("nonexistent.zip"))); +} + +TEST_F(ZipReaderTest, Open_ExistentButNonZipFile) { + ZipReader reader; + ASSERT_FALSE(reader.Open(test_data_dir_.AppendASCII("create_test_zip.sh"))); +} + +// Iterate through the contents in the test zip file, and compare that the +// contents collected from the zip reader matches the expected contents. +TEST_F(ZipReaderTest, Iteration) { + std::set actual_contents; + ZipReader reader; + ASSERT_TRUE(reader.Open(test_zip_file_)); + while (reader.HasMore()) { + ASSERT_TRUE(reader.OpenCurrentEntryInZip()); + actual_contents.insert(reader.current_entry_info()->file_path()); + ASSERT_TRUE(reader.AdvanceToNextEntry()); + } + EXPECT_FALSE(reader.AdvanceToNextEntry()); // Shouldn't go further. + EXPECT_EQ(test_zip_contents_.size(), + static_cast(reader.num_entries())); + EXPECT_EQ(test_zip_contents_.size(), actual_contents.size()); + EXPECT_EQ(test_zip_contents_, actual_contents); +} + +// Open the test zip file from a file descriptor, iterate through its contents, +// and compare that they match the expected contents. +TEST_F(ZipReaderTest, PlatformFileIteration) { + std::set actual_contents; + ZipReader reader; + FileWrapper zip_fd_wrapper(test_zip_file_, FileWrapper::READ_ONLY); + ASSERT_TRUE(reader.OpenFromPlatformFile(zip_fd_wrapper.platform_file())); + while (reader.HasMore()) { + ASSERT_TRUE(reader.OpenCurrentEntryInZip()); + actual_contents.insert(reader.current_entry_info()->file_path()); + ASSERT_TRUE(reader.AdvanceToNextEntry()); + } + EXPECT_FALSE(reader.AdvanceToNextEntry()); // Shouldn't go further. + EXPECT_EQ(test_zip_contents_.size(), + static_cast(reader.num_entries())); + EXPECT_EQ(test_zip_contents_.size(), actual_contents.size()); + EXPECT_EQ(test_zip_contents_, actual_contents); +} + +TEST_F(ZipReaderTest, current_entry_info_RegularFile) { + ZipReader reader; + ASSERT_TRUE(reader.Open(test_zip_file_)); + base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt")); + ASSERT_TRUE(LocateAndOpenEntry(&reader, target_path)); + ZipReader::EntryInfo* current_entry_info = reader.current_entry_info(); + + EXPECT_EQ(target_path, current_entry_info->file_path()); + EXPECT_EQ(13527, current_entry_info->original_size()); + + // The expected time stamp: 2009-05-29 06:22:20 + base::Time::Exploded exploded = {}; // Zero-clear. + current_entry_info->last_modified().LocalExplode(&exploded); + EXPECT_EQ(2009, exploded.year); + EXPECT_EQ(5, exploded.month); + EXPECT_EQ(29, exploded.day_of_month); + EXPECT_EQ(6, exploded.hour); + EXPECT_EQ(22, exploded.minute); + EXPECT_EQ(20, exploded.second); + EXPECT_EQ(0, exploded.millisecond); + + EXPECT_FALSE(current_entry_info->is_unsafe()); + EXPECT_FALSE(current_entry_info->is_directory()); +} + +TEST_F(ZipReaderTest, current_entry_info_DotDotFile) { + ZipReader reader; + ASSERT_TRUE(reader.Open(evil_zip_file_)); + base::FilePath target_path(FILE_PATH_LITERAL( + "../levilevilevilevilevilevilevilevilevilevilevilevil")); + ASSERT_TRUE(LocateAndOpenEntry(&reader, target_path)); + ZipReader::EntryInfo* current_entry_info = reader.current_entry_info(); + EXPECT_EQ(target_path, current_entry_info->file_path()); + + // This file is unsafe because of ".." in the file name. + EXPECT_TRUE(current_entry_info->is_unsafe()); + EXPECT_FALSE(current_entry_info->is_directory()); +} + +TEST_F(ZipReaderTest, current_entry_info_InvalidUTF8File) { + ZipReader reader; + ASSERT_TRUE(reader.Open(evil_via_invalid_utf8_zip_file_)); + // The evil file is the 2nd file in the zip file. + // We cannot locate by the file name ".\x80.\\evil.txt", + // as FilePath may internally convert the string. + ASSERT_TRUE(reader.AdvanceToNextEntry()); + ASSERT_TRUE(reader.OpenCurrentEntryInZip()); + ZipReader::EntryInfo* current_entry_info = reader.current_entry_info(); + + // This file is unsafe because of invalid UTF-8 in the file name. + EXPECT_TRUE(current_entry_info->is_unsafe()); + EXPECT_FALSE(current_entry_info->is_directory()); +} + +TEST_F(ZipReaderTest, current_entry_info_AbsoluteFile) { + ZipReader reader; + ASSERT_TRUE(reader.Open(evil_via_absolute_file_name_zip_file_)); + base::FilePath target_path(FILE_PATH_LITERAL("/evil.txt")); + ASSERT_TRUE(LocateAndOpenEntry(&reader, target_path)); + ZipReader::EntryInfo* current_entry_info = reader.current_entry_info(); + EXPECT_EQ(target_path, current_entry_info->file_path()); + + // This file is unsafe because of the absolute file name. + EXPECT_TRUE(current_entry_info->is_unsafe()); + EXPECT_FALSE(current_entry_info->is_directory()); +} + +TEST_F(ZipReaderTest, current_entry_info_Directory) { + ZipReader reader; + ASSERT_TRUE(reader.Open(test_zip_file_)); + base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/")); + ASSERT_TRUE(LocateAndOpenEntry(&reader, target_path)); + ZipReader::EntryInfo* current_entry_info = reader.current_entry_info(); + + EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("foo/bar/")), + current_entry_info->file_path()); + // The directory size should be zero. + EXPECT_EQ(0, current_entry_info->original_size()); + + // The expected time stamp: 2009-05-31 15:49:52 + base::Time::Exploded exploded = {}; // Zero-clear. + current_entry_info->last_modified().LocalExplode(&exploded); + EXPECT_EQ(2009, exploded.year); + EXPECT_EQ(5, exploded.month); + EXPECT_EQ(31, exploded.day_of_month); + EXPECT_EQ(15, exploded.hour); + EXPECT_EQ(49, exploded.minute); + EXPECT_EQ(52, exploded.second); + EXPECT_EQ(0, exploded.millisecond); + + EXPECT_FALSE(current_entry_info->is_unsafe()); + EXPECT_TRUE(current_entry_info->is_directory()); +} + +TEST_F(ZipReaderTest, current_entry_info_EncryptedFile) { + ZipReader reader; + base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt")); + + ASSERT_TRUE(reader.Open(encrypted_zip_file_)); + ASSERT_TRUE(LocateAndOpenEntry(&reader, target_path)); + EXPECT_TRUE(reader.current_entry_info()->is_encrypted()); + reader.Close(); + + ASSERT_TRUE(reader.Open(test_zip_file_)); + ASSERT_TRUE(LocateAndOpenEntry(&reader, target_path)); + EXPECT_FALSE(reader.current_entry_info()->is_encrypted()); +} + +// Verifies that the ZipReader class can extract a file from a zip archive +// stored in memory. This test opens a zip archive in a std::string object, +// extracts its content, and verifies the content is the same as the expected +// text. +TEST_F(ZipReaderTest, OpenFromString) { + // A zip archive consisting of one file "test.txt", which is a 16-byte text + // file that contains "This is a test.\n". + const char kTestData[] = + "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00\xa4\x66\x24\x41\x13\xe8" + "\xcb\x27\x10\x00\x00\x00\x10\x00\x00\x00\x08\x00\x1c\x00\x74\x65" + "\x73\x74\x2e\x74\x78\x74\x55\x54\x09\x00\x03\x34\x89\x45\x50\x34" + "\x89\x45\x50\x75\x78\x0b\x00\x01\x04\x8e\xf0\x00\x00\x04\x88\x13" + "\x00\x00\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74" + "\x2e\x0a\x50\x4b\x01\x02\x1e\x03\x0a\x00\x00\x00\x00\x00\xa4\x66" + "\x24\x41\x13\xe8\xcb\x27\x10\x00\x00\x00\x10\x00\x00\x00\x08\x00" + "\x18\x00\x00\x00\x00\x00\x01\x00\x00\x00\xa4\x81\x00\x00\x00\x00" + "\x74\x65\x73\x74\x2e\x74\x78\x74\x55\x54\x05\x00\x03\x34\x89\x45" + "\x50\x75\x78\x0b\x00\x01\x04\x8e\xf0\x00\x00\x04\x88\x13\x00\x00" + "\x50\x4b\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00\x4e\x00\x00\x00" + "\x52\x00\x00\x00\x00\x00"; + std::string data(kTestData, base::size(kTestData)); + ZipReader reader; + ASSERT_TRUE(reader.OpenFromString(data)); + base::FilePath target_path(FILE_PATH_LITERAL("test.txt")); + ASSERT_TRUE(LocateAndOpenEntry(&reader, target_path)); + ASSERT_TRUE(ExtractCurrentEntryToFilePath(&reader, + test_dir_.AppendASCII("test.txt"))); + + std::string actual; + ASSERT_TRUE(base::ReadFileToString( + test_dir_.AppendASCII("test.txt"), &actual)); + EXPECT_EQ(std::string("This is a test.\n"), actual); +} + +// Verifies that the asynchronous extraction to a file works. +TEST_F(ZipReaderTest, ExtractToFileAsync_RegularFile) { + MockUnzipListener listener; + + ZipReader reader; + base::FilePath target_file = test_dir_.AppendASCII("quux.txt"); + base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt")); + ASSERT_TRUE(reader.Open(test_zip_file_)); + ASSERT_TRUE(LocateAndOpenEntry(&reader, target_path)); + reader.ExtractCurrentEntryToFilePathAsync( + target_file, + base::BindOnce(&MockUnzipListener::OnUnzipSuccess, listener.AsWeakPtr()), + base::BindOnce(&MockUnzipListener::OnUnzipFailure, listener.AsWeakPtr()), + base::BindRepeating(&MockUnzipListener::OnUnzipProgress, + listener.AsWeakPtr())); + + EXPECT_EQ(0, listener.success_calls()); + EXPECT_EQ(0, listener.failure_calls()); + EXPECT_EQ(0, listener.progress_calls()); + + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(1, listener.success_calls()); + EXPECT_EQ(0, listener.failure_calls()); + EXPECT_LE(1, listener.progress_calls()); + + std::string output; + ASSERT_TRUE(base::ReadFileToString(test_dir_.AppendASCII("quux.txt"), + &output)); + const std::string md5 = base::MD5String(output); + EXPECT_EQ(kQuuxExpectedMD5, md5); + + int64_t file_size = 0; + ASSERT_TRUE(base::GetFileSize(target_file, &file_size)); + + EXPECT_EQ(file_size, listener.current_progress()); +} + +// Verifies that the asynchronous extraction to a file works. +TEST_F(ZipReaderTest, ExtractToFileAsync_Directory) { + MockUnzipListener listener; + + ZipReader reader; + base::FilePath target_file = test_dir_.AppendASCII("foo"); + base::FilePath target_path(FILE_PATH_LITERAL("foo/")); + ASSERT_TRUE(reader.Open(test_zip_file_)); + ASSERT_TRUE(LocateAndOpenEntry(&reader, target_path)); + reader.ExtractCurrentEntryToFilePathAsync( + target_file, + base::BindOnce(&MockUnzipListener::OnUnzipSuccess, listener.AsWeakPtr()), + base::BindOnce(&MockUnzipListener::OnUnzipFailure, listener.AsWeakPtr()), + base::BindRepeating(&MockUnzipListener::OnUnzipProgress, + listener.AsWeakPtr())); + + EXPECT_EQ(0, listener.success_calls()); + EXPECT_EQ(0, listener.failure_calls()); + EXPECT_EQ(0, listener.progress_calls()); + + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(1, listener.success_calls()); + EXPECT_EQ(0, listener.failure_calls()); + EXPECT_GE(0, listener.progress_calls()); + + ASSERT_TRUE(base::DirectoryExists(target_file)); +} + +TEST_F(ZipReaderTest, ExtractCurrentEntryToString) { + // test_mismatch_size.zip contains files with names from 0.txt to 7.txt with + // sizes from 0 to 7 bytes respectively, being the contents of each file a + // substring of "0123456" starting at '0'. + base::FilePath test_zip_file = + test_data_dir_.AppendASCII("test_mismatch_size.zip"); + + ZipReader reader; + std::string contents; + ASSERT_TRUE(reader.Open(test_zip_file)); + + for (size_t i = 0; i < 8; i++) { + SCOPED_TRACE(base::StringPrintf("Processing %d.txt", static_cast(i))); + + base::FilePath file_name = base::FilePath::FromUTF8Unsafe( + base::StringPrintf("%d.txt", static_cast(i))); + ASSERT_TRUE(LocateAndOpenEntry(&reader, file_name)); + + if (i > 1) { + // Off by one byte read limit: must fail. + EXPECT_FALSE(reader.ExtractCurrentEntryToString(i - 1, &contents)); + } + + if (i > 0) { + // Exact byte read limit: must pass. + EXPECT_TRUE(reader.ExtractCurrentEntryToString(i, &contents)); + EXPECT_EQ(base::StringPiece("0123456", i).as_string(), contents); + } + + // More than necessary byte read limit: must pass. + EXPECT_TRUE(reader.ExtractCurrentEntryToString(16, &contents)); + EXPECT_EQ(base::StringPiece("0123456", i).as_string(), contents); + } + reader.Close(); +} + +TEST_F(ZipReaderTest, ExtractPartOfCurrentEntry) { + // test_mismatch_size.zip contains files with names from 0.txt to 7.txt with + // sizes from 0 to 7 bytes respectively, being the contents of each file a + // substring of "0123456" starting at '0'. + base::FilePath test_zip_file = + test_data_dir_.AppendASCII("test_mismatch_size.zip"); + + ZipReader reader; + std::string contents; + ASSERT_TRUE(reader.Open(test_zip_file)); + + base::FilePath file_name0 = base::FilePath::FromUTF8Unsafe("0.txt"); + ASSERT_TRUE(LocateAndOpenEntry(&reader, file_name0)); + EXPECT_TRUE(reader.ExtractCurrentEntryToString(0, &contents)); + EXPECT_EQ("", contents); + EXPECT_TRUE(reader.ExtractCurrentEntryToString(1, &contents)); + EXPECT_EQ("", contents); + + base::FilePath file_name1 = base::FilePath::FromUTF8Unsafe("1.txt"); + ASSERT_TRUE(LocateAndOpenEntry(&reader, file_name1)); + EXPECT_TRUE(reader.ExtractCurrentEntryToString(0, &contents)); + EXPECT_EQ("", contents); + EXPECT_TRUE(reader.ExtractCurrentEntryToString(1, &contents)); + EXPECT_EQ("0", contents); + EXPECT_TRUE(reader.ExtractCurrentEntryToString(2, &contents)); + EXPECT_EQ("0", contents); + + base::FilePath file_name4 = base::FilePath::FromUTF8Unsafe("4.txt"); + ASSERT_TRUE(LocateAndOpenEntry(&reader, file_name4)); + EXPECT_TRUE(reader.ExtractCurrentEntryToString(0, &contents)); + EXPECT_EQ("", contents); + EXPECT_FALSE(reader.ExtractCurrentEntryToString(2, &contents)); + EXPECT_EQ("01", contents); + EXPECT_TRUE(reader.ExtractCurrentEntryToString(4, &contents)); + EXPECT_EQ("0123", contents); + // Checks that entire file is extracted and function returns true when + // |max_read_bytes| is larger than file size. + EXPECT_TRUE(reader.ExtractCurrentEntryToString(5, &contents)); + EXPECT_EQ("0123", contents); + + reader.Close(); +} + +// This test exposes http://crbug.com/430959, at least on OS X +TEST_F(ZipReaderTest, DISABLED_LeakDetectionTest) { + for (int i = 0; i < 100000; ++i) { + FileWrapper zip_fd_wrapper(test_zip_file_, FileWrapper::READ_ONLY); + ZipReader reader; + ASSERT_TRUE(reader.OpenFromPlatformFile(zip_fd_wrapper.platform_file())); + } +} + +// Test that when WriterDelegate::PrepareMock returns false, no other methods on +// the delegate are called and the extraction fails. +TEST_F(ZipReaderTest, ExtractCurrentEntryPrepareFailure) { + testing::StrictMock mock_writer; + + EXPECT_CALL(mock_writer, PrepareOutput()) + .WillOnce(Return(false)); + + base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt")); + ZipReader reader; + + ASSERT_TRUE(reader.Open(test_zip_file_)); + ASSERT_TRUE(LocateAndOpenEntry(&reader, target_path)); + ASSERT_FALSE(reader.ExtractCurrentEntry( + &mock_writer, std::numeric_limits::max())); +} + +// Test that when WriterDelegate::WriteBytes returns false, no other methods on +// the delegate are called and the extraction fails. +TEST_F(ZipReaderTest, ExtractCurrentEntryWriteBytesFailure) { + testing::StrictMock mock_writer; + + EXPECT_CALL(mock_writer, PrepareOutput()) + .WillOnce(Return(true)); + EXPECT_CALL(mock_writer, WriteBytes(_, _)) + .WillOnce(Return(false)); + + base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt")); + ZipReader reader; + + ASSERT_TRUE(reader.Open(test_zip_file_)); + ASSERT_TRUE(LocateAndOpenEntry(&reader, target_path)); + ASSERT_FALSE(reader.ExtractCurrentEntry( + &mock_writer, std::numeric_limits::max())); +} + +// Test that extraction succeeds when the writer delegate reports all is well. +TEST_F(ZipReaderTest, ExtractCurrentEntrySuccess) { + testing::StrictMock mock_writer; + + EXPECT_CALL(mock_writer, PrepareOutput()) + .WillOnce(Return(true)); + EXPECT_CALL(mock_writer, WriteBytes(_, _)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(mock_writer, SetTimeModified(_)); + + base::FilePath target_path(FILE_PATH_LITERAL("foo/bar/quux.txt")); + ZipReader reader; + + ASSERT_TRUE(reader.Open(test_zip_file_)); + ASSERT_TRUE(LocateAndOpenEntry(&reader, target_path)); + ASSERT_TRUE(reader.ExtractCurrentEntry(&mock_writer, + std::numeric_limits::max())); +} + +class FileWriterDelegateTest : public ::testing::Test { + protected: + void SetUp() override { + ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path_)); + file_.Initialize(temp_file_path_, (base::File::FLAG_CREATE_ALWAYS | + base::File::FLAG_READ | + base::File::FLAG_WRITE | + base::File::FLAG_TEMPORARY | + base::File::FLAG_DELETE_ON_CLOSE)); + ASSERT_TRUE(file_.IsValid()); + } + + // Writes data to the file, leaving the current position at the end of the + // write. + void PopulateFile() { + static const char kSomeData[] = "this sure is some data."; + static const size_t kSomeDataLen = sizeof(kSomeData) - 1; + ASSERT_NE(-1LL, file_.Write(0LL, kSomeData, kSomeDataLen)); + } + + base::FilePath temp_file_path_; + base::File file_; +}; + +TEST_F(FileWriterDelegateTest, WriteToStartAndTruncate) { + // Write stuff and advance. + PopulateFile(); + + // This should rewind, write, then truncate. + static const char kSomeData[] = "short"; + static const int kSomeDataLen = sizeof(kSomeData) - 1; + { + FileWriterDelegate writer(&file_); + ASSERT_TRUE(writer.PrepareOutput()); + ASSERT_TRUE(writer.WriteBytes(kSomeData, kSomeDataLen)); + } + ASSERT_EQ(kSomeDataLen, file_.GetLength()); + char buf[kSomeDataLen] = {}; + ASSERT_EQ(kSomeDataLen, file_.Read(0LL, buf, kSomeDataLen)); + ASSERT_EQ(std::string(kSomeData), std::string(buf, kSomeDataLen)); +} + +} // namespace zip diff --git a/deps/zlib/google/zip_unittest.cc b/deps/zlib/google/zip_unittest.cc new file mode 100644 index 00000000000000..7ea3c36c2a80f1 --- /dev/null +++ b/deps/zlib/google/zip_unittest.cc @@ -0,0 +1,559 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include + +#include +#include +#include +#include + +#include "base/bind.h" +#include "base/files/file.h" +#include "base/files/file_enumerator.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/macros.h" +#include "base/path_service.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "build/build_config.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" +#include "third_party/zlib/google/zip.h" +#include "third_party/zlib/google/zip_reader.h" + +namespace { + +bool CreateFile(const std::string& content, + base::FilePath* file_path, + base::File* file) { + if (!base::CreateTemporaryFile(file_path)) + return false; + + if (base::WriteFile(*file_path, content.data(), content.size()) == -1) + return false; + + *file = base::File( + *file_path, base::File::Flags::FLAG_OPEN | base::File::Flags::FLAG_READ); + return file->IsValid(); +} + +// A virtual file system containing: +// /test +// /test/foo.txt +// /test/bar/bar1.txt +// /test/bar/bar2.txt +// Used to test providing a custom zip::FileAccessor when unzipping. +class VirtualFileSystem : public zip::FileAccessor { + public: + static constexpr char kFooContent[] = "This is foo."; + static constexpr char kBar1Content[] = "This is bar."; + static constexpr char kBar2Content[] = "This is bar too."; + + VirtualFileSystem() { + base::FilePath test_dir(FILE_PATH_LITERAL("/test")); + base::FilePath foo_txt_path = test_dir.Append(FILE_PATH_LITERAL("foo.txt")); + + base::FilePath file_path; + base::File file; + bool success = CreateFile(kFooContent, &file_path, &file); + DCHECK(success); + files_[foo_txt_path] = std::move(file); + + base::FilePath bar_dir = test_dir.Append(FILE_PATH_LITERAL("bar")); + base::FilePath bar1_txt_path = + bar_dir.Append(FILE_PATH_LITERAL("bar1.txt")); + success = CreateFile(kBar1Content, &file_path, &file); + DCHECK(success); + files_[bar1_txt_path] = std::move(file); + + base::FilePath bar2_txt_path = + bar_dir.Append(FILE_PATH_LITERAL("bar2.txt")); + success = CreateFile(kBar2Content, &file_path, &file); + DCHECK(success); + files_[bar2_txt_path] = std::move(file); + + file_tree_[test_dir] = std::vector{ + DirectoryContentEntry(foo_txt_path, /*is_dir=*/false), + DirectoryContentEntry(bar_dir, /*is_dir=*/true)}; + file_tree_[bar_dir] = std::vector{ + DirectoryContentEntry(bar1_txt_path, /*is_dir=*/false), + DirectoryContentEntry(bar2_txt_path, /*is_dir=*/false)}; + } + ~VirtualFileSystem() override = default; + + private: + std::vector OpenFilesForReading( + const std::vector& paths) override { + std::vector files; + for (const auto& path : paths) { + auto iter = files_.find(path); + files.push_back(iter == files_.end() ? base::File() + : std::move(iter->second)); + } + return files; + } + + bool DirectoryExists(const base::FilePath& file) override { + return file_tree_.count(file) == 1 && files_.count(file) == 0; + } + + std::vector ListDirectoryContent( + const base::FilePath& dir) override { + auto iter = file_tree_.find(dir); + if (iter == file_tree_.end()) { + NOTREACHED(); + return std::vector(); + } + return iter->second; + } + + base::Time GetLastModifiedTime(const base::FilePath& path) override { + return base::Time::FromDoubleT(172097977); // Some random date. + } + + std::map> file_tree_; + std::map files_; + + DISALLOW_COPY_AND_ASSIGN(VirtualFileSystem); +}; + +// static +constexpr char VirtualFileSystem::kFooContent[]; +constexpr char VirtualFileSystem::kBar1Content[]; +constexpr char VirtualFileSystem::kBar2Content[]; + +// Make the test a PlatformTest to setup autorelease pools properly on Mac. +class ZipTest : public PlatformTest { + protected: + enum ValidYearType { + VALID_YEAR, + INVALID_YEAR + }; + + virtual void SetUp() { + PlatformTest::SetUp(); + + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + test_dir_ = temp_dir_.GetPath(); + + base::FilePath zip_path(test_dir_); + zip_contents_.insert(zip_path.Append(FILE_PATH_LITERAL("foo.txt"))); + zip_path = zip_path.Append(FILE_PATH_LITERAL("foo")); + zip_contents_.insert(zip_path); + zip_contents_.insert(zip_path.Append(FILE_PATH_LITERAL("bar.txt"))); + zip_path = zip_path.Append(FILE_PATH_LITERAL("bar")); + zip_contents_.insert(zip_path); + zip_contents_.insert(zip_path.Append(FILE_PATH_LITERAL("baz.txt"))); + zip_contents_.insert(zip_path.Append(FILE_PATH_LITERAL("quux.txt"))); + zip_contents_.insert(zip_path.Append(FILE_PATH_LITERAL(".hidden"))); + + // Include a subset of files in |zip_file_list_| to test ZipFiles(). + zip_file_list_.push_back(base::FilePath(FILE_PATH_LITERAL("foo.txt"))); + zip_file_list_.push_back( + base::FilePath(FILE_PATH_LITERAL("foo/bar/quux.txt"))); + zip_file_list_.push_back( + base::FilePath(FILE_PATH_LITERAL("foo/bar/.hidden"))); + } + + virtual void TearDown() { + PlatformTest::TearDown(); + } + + bool GetTestDataDirectory(base::FilePath* path) { + bool success = base::PathService::Get(base::DIR_SOURCE_ROOT, path); + EXPECT_TRUE(success); + if (!success) + return false; + *path = path->AppendASCII("third_party"); + *path = path->AppendASCII("zlib"); + *path = path->AppendASCII("google"); + *path = path->AppendASCII("test"); + *path = path->AppendASCII("data"); + return true; + } + + void TestUnzipFile(const base::FilePath::StringType& filename, + bool expect_hidden_files) { + base::FilePath test_dir; + ASSERT_TRUE(GetTestDataDirectory(&test_dir)); + TestUnzipFile(test_dir.Append(filename), expect_hidden_files); + } + + void TestUnzipFile(const base::FilePath& path, bool expect_hidden_files) { + ASSERT_TRUE(base::PathExists(path)) << "no file " << path.value(); + ASSERT_TRUE(zip::Unzip(path, test_dir_)); + + base::FilePath original_dir; + ASSERT_TRUE(GetTestDataDirectory(&original_dir)); + original_dir = original_dir.AppendASCII("test"); + + base::FileEnumerator files(test_dir_, true, + base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); + base::FilePath unzipped_entry_path = files.Next(); + size_t count = 0; + while (!unzipped_entry_path.value().empty()) { + EXPECT_EQ(zip_contents_.count(unzipped_entry_path), 1U) + << "Couldn't find " << unzipped_entry_path.value(); + count++; + + if (base::PathExists(unzipped_entry_path) && + !base::DirectoryExists(unzipped_entry_path)) { + // It's a file, check its contents are what we zipped. + // TODO(774156): figure out why the commented out EXPECT_TRUE below + // fails on the build bots (but not on the try-bots). + base::FilePath relative_path; + bool append_relative_path_success = + test_dir_.AppendRelativePath(unzipped_entry_path, &relative_path); + if (!append_relative_path_success) { + LOG(ERROR) << "Append relative path failed, params: " + << test_dir_.value() << " and " + << unzipped_entry_path.value(); + } + base::FilePath original_path = original_dir.Append(relative_path); + LOG(ERROR) << "Comparing original " << original_path.value() + << " and unzipped file " << unzipped_entry_path.value() + << " result: " + << base::ContentsEqual(original_path, unzipped_entry_path); + // EXPECT_TRUE(base::ContentsEqual(original_path, unzipped_entry_path)) + // << "Contents differ between original " << original_path.value() + // << " and unzipped file " << unzipped_entry_path.value(); + } + unzipped_entry_path = files.Next(); + } + + size_t expected_count = 0; + for (std::set::iterator iter = zip_contents_.begin(); + iter != zip_contents_.end(); ++iter) { + if (expect_hidden_files || iter->BaseName().value()[0] != '.') + ++expected_count; + } + + EXPECT_EQ(expected_count, count); + } + + // This function does the following: + // 1) Creates a test.txt file with the given last modification timestamp + // 2) Zips test.txt and extracts it back into a different location. + // 3) Confirms that test.txt in the output directory has the specified + // last modification timestamp if it is valid (|valid_year| is true). + // If the timestamp is not supported by the zip format, the last + // modification defaults to the current time. + void TestTimeStamp(const char* date_time, ValidYearType valid_year) { + SCOPED_TRACE(std::string("TestTimeStamp(") + date_time + ")"); + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + + base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out.zip"); + base::FilePath src_dir = temp_dir.GetPath().AppendASCII("input"); + base::FilePath out_dir = temp_dir.GetPath().AppendASCII("output"); + + base::FilePath src_file = src_dir.AppendASCII("test.txt"); + base::FilePath out_file = out_dir.AppendASCII("test.txt"); + + EXPECT_TRUE(base::CreateDirectory(src_dir)); + EXPECT_TRUE(base::CreateDirectory(out_dir)); + + base::Time test_mtime; + ASSERT_TRUE(base::Time::FromString(date_time, &test_mtime)); + + // Adjusting the current timestamp to the resolution that the zip file + // supports, which is 2 seconds. Note that between this call to Time::Now() + // and zip::Zip() the clock can advance a bit, hence the use of EXPECT_GE. + base::Time::Exploded now_parts; + base::Time::Now().LocalExplode(&now_parts); + now_parts.second = now_parts.second & ~1; + now_parts.millisecond = 0; + base::Time now_time; + EXPECT_TRUE(base::Time::FromLocalExploded(now_parts, &now_time)); + + EXPECT_EQ(1, base::WriteFile(src_file, "1", 1)); + EXPECT_TRUE(base::TouchFile(src_file, base::Time::Now(), test_mtime)); + + EXPECT_TRUE(zip::Zip(src_dir, zip_file, true)); + ASSERT_TRUE(zip::Unzip(zip_file, out_dir)); + + base::File::Info file_info; + EXPECT_TRUE(base::GetFileInfo(out_file, &file_info)); + EXPECT_EQ(file_info.size, 1); + + if (valid_year == VALID_YEAR) { + EXPECT_EQ(file_info.last_modified, test_mtime); + } else { + // Invalid date means the modification time will default to 'now'. + EXPECT_GE(file_info.last_modified, now_time); + } + } + + // The path to temporary directory used to contain the test operations. + base::FilePath test_dir_; + + base::ScopedTempDir temp_dir_; + + // Hard-coded contents of a known zip file. + std::set zip_contents_; + + // Hard-coded list of relative paths for a zip file created with ZipFiles. + std::vector zip_file_list_; +}; + +TEST_F(ZipTest, Unzip) { + TestUnzipFile(FILE_PATH_LITERAL("test.zip"), true); +} + +TEST_F(ZipTest, UnzipUncompressed) { + TestUnzipFile(FILE_PATH_LITERAL("test_nocompress.zip"), true); +} + +TEST_F(ZipTest, UnzipEvil) { + base::FilePath path; + ASSERT_TRUE(GetTestDataDirectory(&path)); + path = path.AppendASCII("evil.zip"); + // Unzip the zip file into a sub directory of test_dir_ so evil.zip + // won't create a persistent file outside test_dir_ in case of a + // failure. + base::FilePath output_dir = test_dir_.AppendASCII("out"); + ASSERT_FALSE(zip::Unzip(path, output_dir)); + base::FilePath evil_file = output_dir; + evil_file = evil_file.AppendASCII( + "../levilevilevilevilevilevilevilevilevilevilevilevil"); + ASSERT_FALSE(base::PathExists(evil_file)); +} + +TEST_F(ZipTest, UnzipEvil2) { + base::FilePath path; + ASSERT_TRUE(GetTestDataDirectory(&path)); + // The zip file contains an evil file with invalid UTF-8 in its file + // name. + path = path.AppendASCII("evil_via_invalid_utf8.zip"); + // See the comment at UnzipEvil() for why we do this. + base::FilePath output_dir = test_dir_.AppendASCII("out"); + // This should fail as it contains an evil file. + ASSERT_FALSE(zip::Unzip(path, output_dir)); + base::FilePath evil_file = output_dir; + evil_file = evil_file.AppendASCII("../evil.txt"); + ASSERT_FALSE(base::PathExists(evil_file)); +} + +TEST_F(ZipTest, UnzipWithFilter) { + auto filter = base::BindRepeating([](const base::FilePath& path) { + return path.BaseName().MaybeAsASCII() == "foo.txt"; + }); + base::FilePath path; + ASSERT_TRUE(GetTestDataDirectory(&path)); + ASSERT_TRUE(zip::UnzipWithFilterCallback(path.AppendASCII("test.zip"), + test_dir_, filter, false)); + // Only foo.txt should have been extracted. The following paths should not + // be extracted: + // foo/ + // foo/bar.txt + // foo/bar/ + // foo/bar/.hidden + // foo/bar/baz.txt + // foo/bar/quux.txt + ASSERT_TRUE(base::PathExists(test_dir_.AppendASCII("foo.txt"))); + base::FileEnumerator extractedFiles( + test_dir_, + false, // Do not enumerate recursively - the file must be in the root. + base::FileEnumerator::FileType::FILES); + int extracted_count = 0; + while (!extractedFiles.Next().empty()) + ++extracted_count; + ASSERT_EQ(1, extracted_count); + + base::FileEnumerator extractedDirs( + test_dir_, + false, // Do not enumerate recursively - we require zero directories. + base::FileEnumerator::FileType::DIRECTORIES); + extracted_count = 0; + while (!extractedDirs.Next().empty()) + ++extracted_count; + ASSERT_EQ(0, extracted_count); +} + +TEST_F(ZipTest, UnzipWithDelegates) { + auto filter = + base::BindRepeating([](const base::FilePath& path) { return true; }); + auto dir_creator = base::BindRepeating( + [](const base::FilePath& extract_dir, const base::FilePath& entry_path) { + return base::CreateDirectory(extract_dir.Append(entry_path)); + }, + test_dir_); + auto writer = base::BindRepeating( + [](const base::FilePath& extract_dir, const base::FilePath& entry_path) + -> std::unique_ptr { + return std::make_unique( + extract_dir.Append(entry_path)); + }, + test_dir_); + base::FilePath path; + ASSERT_TRUE(GetTestDataDirectory(&path)); + base::File file(path.AppendASCII("test.zip"), + base::File::Flags::FLAG_OPEN | base::File::Flags::FLAG_READ); + ASSERT_TRUE(zip::UnzipWithFilterAndWriters(file.GetPlatformFile(), writer, + dir_creator, filter, false)); + base::FilePath dir = test_dir_; + base::FilePath dir_foo = dir.AppendASCII("foo"); + base::FilePath dir_foo_bar = dir_foo.AppendASCII("bar"); + ASSERT_TRUE(base::PathExists(dir.AppendASCII("foo.txt"))); + ASSERT_TRUE(base::PathExists(dir_foo)); + ASSERT_TRUE(base::PathExists(dir_foo.AppendASCII("bar.txt"))); + ASSERT_TRUE(base::PathExists(dir_foo_bar)); + ASSERT_TRUE(base::PathExists(dir_foo_bar.AppendASCII(".hidden"))); + ASSERT_TRUE(base::PathExists(dir_foo_bar.AppendASCII("baz.txt"))); + ASSERT_TRUE(base::PathExists(dir_foo_bar.AppendASCII("quux.txt"))); +} + +TEST_F(ZipTest, Zip) { + base::FilePath src_dir; + ASSERT_TRUE(GetTestDataDirectory(&src_dir)); + src_dir = src_dir.AppendASCII("test"); + + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out.zip"); + + EXPECT_TRUE(zip::Zip(src_dir, zip_file, /*include_hidden_files=*/true)); + TestUnzipFile(zip_file, true); +} + +TEST_F(ZipTest, ZipIgnoreHidden) { + base::FilePath src_dir; + ASSERT_TRUE(GetTestDataDirectory(&src_dir)); + src_dir = src_dir.AppendASCII("test"); + + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out.zip"); + + EXPECT_TRUE(zip::Zip(src_dir, zip_file, /*include_hidden_files=*/false)); + TestUnzipFile(zip_file, false); +} + +TEST_F(ZipTest, ZipNonASCIIDir) { + base::FilePath src_dir; + ASSERT_TRUE(GetTestDataDirectory(&src_dir)); + src_dir = src_dir.AppendASCII("test"); + + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + // Append 'Тест' (in cyrillic). + base::FilePath src_dir_russian = temp_dir.GetPath().Append( + base::FilePath::FromUTF8Unsafe("\xD0\xA2\xD0\xB5\xD1\x81\xD1\x82")); + base::CopyDirectory(src_dir, src_dir_russian, true); + base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out_russian.zip"); + + EXPECT_TRUE(zip::Zip(src_dir_russian, zip_file, true)); + TestUnzipFile(zip_file, true); +} + +TEST_F(ZipTest, ZipTimeStamp) { + // The dates tested are arbitrary, with some constraints. The zip format can + // only store years from 1980 to 2107 and an even number of seconds, due to it + // using the ms dos date format. + + // Valid arbitrary date. + TestTimeStamp("23 Oct 1997 23:22:20", VALID_YEAR); + + // Date before 1980, zip format limitation, must default to unix epoch. + TestTimeStamp("29 Dec 1979 21:00:10", INVALID_YEAR); + + // Despite the minizip headers telling the maximum year should be 2044, it + // can actually go up to 2107. Beyond that, the dos date format cannot store + // the year (2107-1980=127). To test that limit, the input file needs to be + // touched, but the code that modifies the file access and modification times + // relies on time_t which is defined as long, therefore being in many + // platforms just a 4-byte integer, like 32-bit Mac OSX or linux. As such, it + // suffers from the year-2038 bug. Therefore 2038 is the highest we can test + // in all platforms reliably. + TestTimeStamp("02 Jan 2038 23:59:58", VALID_YEAR); +} + +#if defined(OS_POSIX) +TEST_F(ZipTest, ZipFiles) { + base::FilePath src_dir; + ASSERT_TRUE(GetTestDataDirectory(&src_dir)); + src_dir = src_dir.AppendASCII("test"); + + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + base::FilePath zip_name = temp_dir.GetPath().AppendASCII("out.zip"); + + base::File zip_file(zip_name, + base::File::FLAG_CREATE | base::File::FLAG_WRITE); + ASSERT_TRUE(zip_file.IsValid()); + EXPECT_TRUE(zip::ZipFiles(src_dir, zip_file_list_, + zip_file.GetPlatformFile())); + zip_file.Close(); + + zip::ZipReader reader; + EXPECT_TRUE(reader.Open(zip_name)); + EXPECT_EQ(zip_file_list_.size(), static_cast(reader.num_entries())); + for (size_t i = 0; i < zip_file_list_.size(); ++i) { + EXPECT_TRUE(reader.HasMore()); + EXPECT_TRUE(reader.OpenCurrentEntryInZip()); + const zip::ZipReader::EntryInfo* entry_info = reader.current_entry_info(); + EXPECT_EQ(entry_info->file_path(), zip_file_list_[i]); + reader.AdvanceToNextEntry(); + } +} +#endif // defined(OS_POSIX) + +TEST_F(ZipTest, UnzipFilesWithIncorrectSize) { + base::FilePath test_data_folder; + ASSERT_TRUE(GetTestDataDirectory(&test_data_folder)); + + // test_mismatch_size.zip contains files with names from 0.txt to 7.txt with + // sizes from 0 to 7 bytes respectively, but the metadata in the zip file says + // the uncompressed size is 3 bytes. The ZipReader and minizip code needs to + // be clever enough to get all the data out. + base::FilePath test_zip_file = + test_data_folder.AppendASCII("test_mismatch_size.zip"); + + base::ScopedTempDir scoped_temp_dir; + ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); + const base::FilePath& temp_dir = scoped_temp_dir.GetPath(); + + ASSERT_TRUE(zip::Unzip(test_zip_file, temp_dir)); + EXPECT_TRUE(base::DirectoryExists(temp_dir.AppendASCII("d"))); + + for (int i = 0; i < 8; i++) { + SCOPED_TRACE(base::StringPrintf("Processing %d.txt", i)); + base::FilePath file_path = temp_dir.AppendASCII( + base::StringPrintf("%d.txt", i)); + int64_t file_size = -1; + EXPECT_TRUE(base::GetFileSize(file_path, &file_size)); + EXPECT_EQ(static_cast(i), file_size); + } +} + +TEST_F(ZipTest, ZipWithFileAccessor) { + base::FilePath zip_file; + ASSERT_TRUE(base::CreateTemporaryFile(&zip_file)); + zip::ZipParams params(base::FilePath(FILE_PATH_LITERAL("/test")), zip_file); + params.set_file_accessor(std::make_unique()); + ASSERT_TRUE(zip::Zip(params)); + + base::ScopedTempDir scoped_temp_dir; + ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); + const base::FilePath& temp_dir = scoped_temp_dir.GetPath(); + ASSERT_TRUE(zip::Unzip(zip_file, temp_dir)); + base::FilePath bar_dir = temp_dir.Append(FILE_PATH_LITERAL("bar")); + EXPECT_TRUE(base::DirectoryExists(bar_dir)); + std::string file_content; + EXPECT_TRUE(base::ReadFileToString( + temp_dir.Append(FILE_PATH_LITERAL("foo.txt")), &file_content)); + EXPECT_EQ(VirtualFileSystem::kFooContent, file_content); + EXPECT_TRUE(base::ReadFileToString( + bar_dir.Append(FILE_PATH_LITERAL("bar1.txt")), &file_content)); + EXPECT_EQ(VirtualFileSystem::kBar1Content, file_content); + EXPECT_TRUE(base::ReadFileToString( + bar_dir.Append(FILE_PATH_LITERAL("bar2.txt")), &file_content)); + EXPECT_EQ(VirtualFileSystem::kBar2Content, file_content); +} + +} // namespace diff --git a/deps/zlib/google/zip_writer.cc b/deps/zlib/google/zip_writer.cc new file mode 100644 index 00000000000000..1f2f073b30cb32 --- /dev/null +++ b/deps/zlib/google/zip_writer.cc @@ -0,0 +1,203 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/zlib/google/zip_writer.h" + +#include "base/files/file.h" +#include "base/strings/string_util.h" +#include "third_party/zlib/google/zip_internal.h" + +namespace zip { +namespace internal { + +namespace { + +// Numbers of pending entries that trigger writting them to the ZIP file. +constexpr size_t kMaxPendingEntriesCount = 50; + +bool AddFileContentToZip(zipFile zip_file, + base::File file, + const base::FilePath& file_path) { + int num_bytes; + char buf[zip::internal::kZipBufSize]; + do { + num_bytes = file.ReadAtCurrentPos(buf, zip::internal::kZipBufSize); + + if (num_bytes > 0) { + if (zipWriteInFileInZip(zip_file, buf, num_bytes) != ZIP_OK) { + DLOG(ERROR) << "Could not write data to zip for path " + << file_path.value(); + return false; + } + } + } while (num_bytes > 0); + + return true; +} + +bool OpenNewFileEntry(zipFile zip_file, + const base::FilePath& path, + bool is_directory, + base::Time last_modified) { + std::string str_path = path.AsUTF8Unsafe(); +#if defined(OS_WIN) + base::ReplaceSubstringsAfterOffset(&str_path, 0u, "\\", "/"); +#endif + if (is_directory) + str_path += "/"; + + return zip::internal::ZipOpenNewFileInZip(zip_file, str_path, last_modified); +} + +bool CloseNewFileEntry(zipFile zip_file) { + return zipCloseFileInZip(zip_file) == ZIP_OK; +} + +bool AddFileEntryToZip(zipFile zip_file, + const base::FilePath& path, + base::File file) { + base::File::Info file_info; + if (!file.GetInfo(&file_info)) + return false; + + if (!OpenNewFileEntry(zip_file, path, /*is_directory=*/false, + file_info.last_modified)) + return false; + + bool success = AddFileContentToZip(zip_file, std::move(file), path); + if (!CloseNewFileEntry(zip_file)) + return false; + + return success; +} + +bool AddDirectoryEntryToZip(zipFile zip_file, + const base::FilePath& path, + base::Time last_modified) { + return OpenNewFileEntry(zip_file, path, /*is_directory=*/true, + last_modified) && + CloseNewFileEntry(zip_file); +} + +} // namespace + +#if defined(OS_POSIX) +// static +std::unique_ptr ZipWriter::CreateWithFd( + int zip_file_fd, + const base::FilePath& root_dir, + FileAccessor* file_accessor) { + DCHECK(zip_file_fd != base::kInvalidPlatformFile); + zipFile zip_file = + internal::OpenFdForZipping(zip_file_fd, APPEND_STATUS_CREATE); + if (!zip_file) { + DLOG(ERROR) << "Couldn't create ZIP file for FD " << zip_file_fd; + return nullptr; + } + return std::unique_ptr( + new ZipWriter(zip_file, root_dir, file_accessor)); +} +#endif + +// static +std::unique_ptr ZipWriter::Create( + const base::FilePath& zip_file_path, + const base::FilePath& root_dir, + FileAccessor* file_accessor) { + DCHECK(!zip_file_path.empty()); + zipFile zip_file = internal::OpenForZipping(zip_file_path.AsUTF8Unsafe(), + APPEND_STATUS_CREATE); + if (!zip_file) { + DLOG(ERROR) << "Couldn't create ZIP file at path " << zip_file_path; + return nullptr; + } + return std::unique_ptr( + new ZipWriter(zip_file, root_dir, file_accessor)); +} + +ZipWriter::ZipWriter(zipFile zip_file, + const base::FilePath& root_dir, + FileAccessor* file_accessor) + : zip_file_(zip_file), root_dir_(root_dir), file_accessor_(file_accessor) {} + +ZipWriter::~ZipWriter() { + DCHECK(pending_entries_.empty()); +} + +bool ZipWriter::WriteEntries(const std::vector& paths) { + return AddEntries(paths) && Close(); +} + +bool ZipWriter::AddEntries(const std::vector& paths) { + DCHECK(zip_file_); + pending_entries_.insert(pending_entries_.end(), paths.begin(), paths.end()); + return FlushEntriesIfNeeded(/*force=*/false); +} + +bool ZipWriter::Close() { + bool success = FlushEntriesIfNeeded(/*force=*/true) && + zipClose(zip_file_, nullptr) == ZIP_OK; + zip_file_ = nullptr; + return success; +} + +bool ZipWriter::FlushEntriesIfNeeded(bool force) { + if (pending_entries_.size() < kMaxPendingEntriesCount && !force) + return true; + + while (pending_entries_.size() >= kMaxPendingEntriesCount || + (force && !pending_entries_.empty())) { + size_t entry_count = + std::min(pending_entries_.size(), kMaxPendingEntriesCount); + std::vector relative_paths; + std::vector absolute_paths; + relative_paths.insert(relative_paths.begin(), pending_entries_.begin(), + pending_entries_.begin() + entry_count); + for (auto iter = pending_entries_.begin(); + iter != pending_entries_.begin() + entry_count; ++iter) { + // The FileAccessor requires absolute paths. + absolute_paths.push_back(root_dir_.Append(*iter)); + } + pending_entries_.erase(pending_entries_.begin(), + pending_entries_.begin() + entry_count); + + // We don't know which paths are files and which ones are directories, and + // we want to avoid making a call to file_accessor_ for each entry. Open the + // files instead, invalid files are returned for directories. + std::vector files = + file_accessor_->OpenFilesForReading(absolute_paths); + DCHECK_EQ(files.size(), relative_paths.size()); + for (size_t i = 0; i < files.size(); i++) { + const base::FilePath& relative_path = relative_paths[i]; + const base::FilePath& absolute_path = absolute_paths[i]; + base::File file = std::move(files[i]); + if (file.IsValid()) { + if (!AddFileEntryToZip(zip_file_, relative_path, std::move(file))) { + LOG(ERROR) << "Failed to write file " << relative_path.value() + << " to ZIP file."; + return false; + } + } else { + // Missing file or directory case. + base::Time last_modified = + file_accessor_->GetLastModifiedTime(absolute_path); + if (last_modified.is_null()) { + LOG(ERROR) << "Failed to write entry " << relative_path.value() + << " to ZIP file."; + return false; + } + DCHECK(file_accessor_->DirectoryExists(absolute_path)); + if (!AddDirectoryEntryToZip(zip_file_, relative_path, last_modified)) { + LOG(ERROR) << "Failed to write directory " << relative_path.value() + << " to ZIP file."; + return false; + } + } + } + } + return true; +} + +} // namespace internal +} // namespace zip diff --git a/deps/zlib/google/zip_writer.h b/deps/zlib/google/zip_writer.h new file mode 100644 index 00000000000000..bd2a727b94d408 --- /dev/null +++ b/deps/zlib/google/zip_writer.h @@ -0,0 +1,91 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_ZLIB_GOOGLE_ZIP_WRITER_H_ +#define THIRD_PARTY_ZLIB_GOOGLE_ZIP_WRITER_H_ + +#include +#include + +#include "base/files/file_path.h" +#include "build/build_config.h" +#include "third_party/zlib/google/zip.h" + +#if defined(USE_SYSTEM_MINIZIP) +#include +#include +#else +#include "third_party/zlib/contrib/minizip/unzip.h" +#include "third_party/zlib/contrib/minizip/zip.h" +#endif + +namespace zip { +namespace internal { + +// A class used to write entries to a ZIP file and buffering the reading of +// files to limit the number of calls to the FileAccessor. This is for +// performance reasons as these calls may be expensive when IPC based). +// This class is so far internal and only used by zip.cc, but could be made +// public if needed. +class ZipWriter { + public: +// Creates a writer that will write a ZIP file to |zip_file_fd|/|zip_file| +// and which entries (specifies with AddEntries) are relative to |root_dir|. +// All file reads are performed using |file_accessor|. +#if defined(OS_POSIX) + static std::unique_ptr CreateWithFd(int zip_file_fd, + const base::FilePath& root_dir, + FileAccessor* file_accessor); +#endif + static std::unique_ptr Create(const base::FilePath& zip_file, + const base::FilePath& root_dir, + FileAccessor* file_accessor); + ~ZipWriter(); + + // Writes the files at |paths| to the ZIP file and closes this Zip file. + // Note that the the FilePaths must be relative to |root_dir| specified in the + // Create method. + // Returns true if all entries were written successfuly. + bool WriteEntries(const std::vector& paths); + + private: + ZipWriter(zipFile zip_file, + const base::FilePath& root_dir, + FileAccessor* file_accessor); + + // Writes the pending entries to the ZIP file if there are at least + // |kMaxPendingEntriesCount| of them. If |force| is true, all pending entries + // are written regardless of how many there are. + // Returns false if writing an entry fails, true if no entry was written or + // there was no error writing entries. + bool FlushEntriesIfNeeded(bool force); + + // Adds the files at |paths| to the ZIP file. These FilePaths must be relative + // to |root_dir| specified in the Create method. + bool AddEntries(const std::vector& paths); + + // Closes the ZIP file. + // Returns true if successful, false otherwise (typically if an entry failed + // to be written). + bool Close(); + + // The entries that have been added but not yet written to the ZIP file. + std::vector pending_entries_; + + // The actual zip file. + zipFile zip_file_; + + // Path to the directory entry paths are relative to. + base::FilePath root_dir_; + + // Abstraction over file access methods used to read files. + FileAccessor* file_accessor_; + + DISALLOW_COPY_AND_ASSIGN(ZipWriter); +}; + +} // namespace internal +} // namespace zip + +#endif // THIRD_PARTY_ZLIB_GOOGLE_ZIP_WRITER_H_ \ No newline at end of file diff --git a/deps/zlib/gzread.c b/deps/zlib/gzread.c index 956b91ea7d9e2a..832d3ef98c5948 100644 --- a/deps/zlib/gzread.c +++ b/deps/zlib/gzread.c @@ -443,7 +443,11 @@ z_size_t ZEXPORT gzfread(buf, size, nitems, file) # undef z_gzgetc #else # undef gzgetc +# ifdef Z_CR_PREFIX_SET +# define gzgetc Cr_z_gzgetc +# endif #endif + int ZEXPORT gzgetc(file) gzFile file; { diff --git a/deps/zlib/infback.c b/deps/zlib/infback.c index 59679ecbfc5d77..aab14b4848effa 100644 --- a/deps/zlib/infback.c +++ b/deps/zlib/infback.c @@ -480,7 +480,8 @@ void FAR *out_desc; case LEN: /* use inflate_fast() if we have enough input and output */ - if (have >= 6 && left >= 258) { + if (have >= INFLATE_FAST_MIN_INPUT && + left >= INFLATE_FAST_MIN_OUTPUT) { RESTORE(); if (state->whave < state->wsize) state->whave = state->wsize - left; diff --git a/deps/zlib/inffast.c b/deps/zlib/inffast.c index 0dbd1dbc09f2f6..2797e8a03c5151 100644 --- a/deps/zlib/inffast.c +++ b/deps/zlib/inffast.c @@ -18,13 +18,13 @@ available, an end-of-block is encountered, or a data error is encountered. When large enough input and output buffers are supplied to inflate(), for example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. + inflate() execution time is spent in this routine. Entry assumptions: state->mode == LEN - strm->avail_in >= 6 - strm->avail_out >= 258 + strm->avail_in >= INFLATE_FAST_MIN_INPUT (6 bytes) + strm->avail_out >= INFLATE_FAST_MIN_OUTPUT (258 bytes) start >= strm->avail_out state->bits < 8 @@ -36,16 +36,20 @@ Notes: + INFLATE_FAST_MIN_INPUT: 6 bytes + - The maximum input bits used by a length/distance pair is 15 bits for the length code, 5 bits for the length extra, 15 bits for the distance code, and 13 bits for the distance extra. This totals 48 bits, or six bytes. Therefore if strm->avail_in >= 6, then there is enough input to avoid checking for available input while decoding. + INFLATE_FAST_MIN_OUTPUT: 258 bytes + - The maximum bytes that a single length/distance pair can output is 258 bytes, which is the maximum length that can be coded. inflate_fast() requires strm->avail_out >= 258 for each loop to avoid checking for - output space. + available output space while decoding. */ void ZLIB_INTERNAL inflate_fast(strm, start) z_streamp strm; @@ -80,10 +84,10 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ /* copy state to local variables */ state = (struct inflate_state FAR *)strm->state; in = strm->next_in; - last = in + (strm->avail_in - 5); + last = in + (strm->avail_in - (INFLATE_FAST_MIN_INPUT - 1)); out = strm->next_out; beg = out - (start - strm->avail_out); - end = out + (strm->avail_out - 257); + end = out + (strm->avail_out - (INFLATE_FAST_MIN_OUTPUT - 1)); #ifdef INFLATE_STRICT dmax = state->dmax; #endif @@ -298,9 +302,12 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ /* update state and return */ strm->next_in = in; strm->next_out = out; - strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_in = (unsigned)(in < last ? + (INFLATE_FAST_MIN_INPUT - 1) + (last - in) : + (INFLATE_FAST_MIN_INPUT - 1) - (in - last)); strm->avail_out = (unsigned)(out < end ? - 257 + (end - out) : 257 - (out - end)); + (INFLATE_FAST_MIN_OUTPUT - 1) + (end - out) : + (INFLATE_FAST_MIN_OUTPUT - 1) - (out - end)); state->hold = hold; state->bits = bits; return; diff --git a/deps/zlib/inffast.h b/deps/zlib/inffast.h index e5c1aa4ca8cd52..c7c1c09808e5e9 100644 --- a/deps/zlib/inffast.h +++ b/deps/zlib/inffast.h @@ -8,4 +8,19 @@ subject to change. Applications should only use zlib.h. */ +/* INFLATE_FAST_MIN_INPUT: the minimum number of input bytes needed so that + we can safely call inflate_fast() with only one up-front bounds check. One + length/distance code pair (15 bits for the length code, 5 bits for length + extra, 15 bits for the distance code, 13 bits for distance extra) requires + reading up to 48 input bits (6 bytes). +*/ +#define INFLATE_FAST_MIN_INPUT 6 + +/* INFLATE_FAST_MIN_OUTPUT: the minimum number of output bytes needed so that + we can safely call inflate_fast() with only one up-front bounds check. One + length/distance code pair can output up to 258 bytes, which is the maximum + length that can be coded. + */ +#define INFLATE_FAST_MIN_OUTPUT 258 + void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/deps/zlib/inflate.c b/deps/zlib/inflate.c index ac333e8c2edae9..68902e81bd4be9 100644 --- a/deps/zlib/inflate.c +++ b/deps/zlib/inflate.c @@ -228,6 +228,7 @@ int stream_size; state->strm = strm; state->window = Z_NULL; state->mode = HEAD; /* to pass state test in inflateReset2() */ + state->check = 1L; /* 1L is the result of adler32() zero length data */ ret = inflateReset2(strm, windowBits); if (ret != Z_OK) { ZFREE(strm, state); @@ -1042,7 +1043,8 @@ int flush; case LEN_: state->mode = LEN; case LEN: - if (have >= 6 && left >= 258) { + if (have >= INFLATE_FAST_MIN_INPUT && + left >= INFLATE_FAST_MIN_OUTPUT) { RESTORE(); inflate_fast(strm, out); LOAD(); diff --git a/deps/zlib/make_vms.com b/deps/zlib/make_vms.com deleted file mode 100644 index 65e9d0cbc8e1dd..00000000000000 --- a/deps/zlib/make_vms.com +++ /dev/null @@ -1,867 +0,0 @@ -$! make libz under VMS written by -$! Martin P.J. Zinser -$! -$! In case of problems with the install you might contact me at -$! zinser@zinser.no-ip.info(preferred) or -$! martin.zinser@eurexchange.com (work) -$! -$! Make procedure history for Zlib -$! -$!------------------------------------------------------------------------------ -$! Version history -$! 0.01 20060120 First version to receive a number -$! 0.02 20061008 Adapt to new Makefile.in -$! 0.03 20091224 Add support for large file check -$! 0.04 20100110 Add new gzclose, gzlib, gzread, gzwrite -$! 0.05 20100221 Exchange zlibdefs.h by zconf.h.in -$! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new exmples -$! subdir path, update module search in makefile.in -$! 0.07 20120115 Triggered by work done by Alexey Chupahin completly redesigned -$! shared image creation -$! 0.08 20120219 Make it work on VAX again, pre-load missing symbols to shared -$! image -$! 0.09 20120305 SMS. P1 sets builder ("MMK", "MMS", " " (built-in)). -$! "" -> automatic, preference: MMK, MMS, built-in. -$! -$ on error then goto err_exit -$! -$ true = 1 -$ false = 0 -$ tmpnam = "temp_" + f$getjpi("","pid") -$ tt = tmpnam + ".txt" -$ tc = tmpnam + ".c" -$ th = tmpnam + ".h" -$ define/nolog tconfig 'th' -$ its_decc = false -$ its_vaxc = false -$ its_gnuc = false -$ s_case = False -$! -$! Setup variables holding "config" information -$! -$ Make = "''p1'" -$ name = "Zlib" -$ version = "?.?.?" -$ v_string = "ZLIB_VERSION" -$ v_file = "zlib.h" -$ ccopt = "/include = []" -$ lopts = "" -$ dnsrl = "" -$ aconf_in_file = "zconf.h.in#zconf.h_in#zconf_h.in" -$ conf_check_string = "" -$ linkonly = false -$ optfile = name + ".opt" -$ mapfile = name + ".map" -$ libdefs = "" -$ vax = f$getsyi("HW_MODEL").lt.1024 -$ axp = f$getsyi("HW_MODEL").ge.1024 .and. f$getsyi("HW_MODEL").lt.4096 -$ ia64 = f$getsyi("HW_MODEL").ge.4096 -$! -$! 2012-03-05 SMS. -$! Why is this needed? And if it is needed, why not simply ".not. vax"? -$! -$!!! if axp .or. ia64 then set proc/parse=extended -$! -$ whoami = f$parse(f$environment("Procedure"),,,,"NO_CONCEAL") -$ mydef = F$parse(whoami,,,"DEVICE") -$ mydir = f$parse(whoami,,,"DIRECTORY") - "][" -$ myproc = f$parse(whoami,,,"Name") + f$parse(whoami,,,"type") -$! -$! Check for MMK/MMS -$! -$ if (Make .eqs. "") -$ then -$ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS" -$ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK" -$ else -$ Make = f$edit( Make, "trim") -$ endif -$! -$ gosub find_version -$! -$ open/write topt tmp.opt -$ open/write optf 'optfile' -$! -$ gosub check_opts -$! -$! Look for the compiler used -$! -$ gosub check_compiler -$ close topt -$ close optf -$! -$ if its_decc -$ then -$ ccopt = "/prefix=all" + ccopt -$ if f$trnlnm("SYS") .eqs. "" -$ then -$ if axp -$ then -$ define sys sys$library: -$ else -$ ccopt = "/decc" + ccopt -$ define sys decc$library_include: -$ endif -$ endif -$! -$! 2012-03-05 SMS. -$! Why /NAMES = AS_IS? Why not simply ".not. vax"? And why not on VAX? -$! -$ if axp .or. ia64 -$ then -$ ccopt = ccopt + "/name=as_is/opt=(inline=speed)" -$ s_case = true -$ endif -$ endif -$ if its_vaxc .or. its_gnuc -$ then -$ if f$trnlnm("SYS").eqs."" then define sys sys$library: -$ endif -$! -$! Build a fake configure input header -$! -$ open/write conf_hin config.hin -$ write conf_hin "#undef _LARGEFILE64_SOURCE" -$ close conf_hin -$! -$! -$ i = 0 -$FIND_ACONF: -$ fname = f$element(i,"#",aconf_in_file) -$ if fname .eqs. "#" then goto AMISS_ERR -$ if f$search(fname) .eqs. "" -$ then -$ i = i + 1 -$ goto find_aconf -$ endif -$ open/read/err=aconf_err aconf_in 'fname' -$ open/write aconf zconf.h -$ACONF_LOOP: -$ read/end_of_file=aconf_exit aconf_in line -$ work = f$edit(line, "compress,trim") -$ if f$extract(0,6,work) .nes. "#undef" -$ then -$ if f$extract(0,12,work) .nes. "#cmakedefine" -$ then -$ write aconf line -$ endif -$ else -$ cdef = f$element(1," ",work) -$ gosub check_config -$ endif -$ goto aconf_loop -$ACONF_EXIT: -$ write aconf "" -$ write aconf "/* VMS specifics added by make_vms.com: */" -$ write aconf "#define VMS 1" -$ write aconf "#include " -$ write aconf "#include " -$ write aconf "#ifdef _LARGEFILE" -$ write aconf "# define off64_t __off64_t" -$ write aconf "# define fopen64 fopen" -$ write aconf "# define fseeko64 fseeko" -$ write aconf "# define lseek64 lseek" -$ write aconf "# define ftello64 ftell" -$ write aconf "#endif" -$ write aconf "#if !defined( __VAX) && (__CRTL_VER >= 70312000)" -$ write aconf "# define HAVE_VSNPRINTF" -$ write aconf "#endif" -$ close aconf_in -$ close aconf -$ if f$search("''th'") .nes. "" then delete 'th';* -$! Build the thing plain or with mms -$! -$ write sys$output "Compiling Zlib sources ..." -$ if make.eqs."" -$ then -$ if (f$search( "example.obj;*") .nes. "") then delete example.obj;* -$ if (f$search( "minigzip.obj;*") .nes. "") then delete minigzip.obj;* -$ CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" - - adler32.c zlib.h zconf.h -$ CALL MAKE compress.OBJ "CC ''CCOPT' compress" - - compress.c zlib.h zconf.h -$ CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" - - crc32.c zlib.h zconf.h -$ CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" - - deflate.c deflate.h zutil.h zlib.h zconf.h -$ CALL MAKE gzclose.OBJ "CC ''CCOPT' gzclose" - - gzclose.c zutil.h zlib.h zconf.h -$ CALL MAKE gzlib.OBJ "CC ''CCOPT' gzlib" - - gzlib.c zutil.h zlib.h zconf.h -$ CALL MAKE gzread.OBJ "CC ''CCOPT' gzread" - - gzread.c zutil.h zlib.h zconf.h -$ CALL MAKE gzwrite.OBJ "CC ''CCOPT' gzwrite" - - gzwrite.c zutil.h zlib.h zconf.h -$ CALL MAKE infback.OBJ "CC ''CCOPT' infback" - - infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h -$ CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" - - inffast.c zutil.h zlib.h zconf.h inffast.h -$ CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" - - inflate.c zutil.h zlib.h zconf.h infblock.h -$ CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" - - inftrees.c zutil.h zlib.h zconf.h inftrees.h -$ CALL MAKE trees.OBJ "CC ''CCOPT' trees" - - trees.c deflate.h zutil.h zlib.h zconf.h -$ CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" - - uncompr.c zlib.h zconf.h -$ CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" - - zutil.c zutil.h zlib.h zconf.h -$ write sys$output "Building Zlib ..." -$ CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ -$ write sys$output "Building example..." -$ CALL MAKE example.OBJ "CC ''CCOPT' [.test]example" - - [.test]example.c zlib.h zconf.h -$ call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb -$ write sys$output "Building minigzip..." -$ CALL MAKE minigzip.OBJ "CC ''CCOPT' [.test]minigzip" - - [.test]minigzip.c zlib.h zconf.h -$ call make minigzip.exe - - "LINK minigzip,libz.olb/lib" - - minigzip.obj libz.olb -$ else -$ gosub crea_mms -$ write sys$output "Make ''name' ''version' with ''Make' " -$ 'make' -$ endif -$! -$! Create shareable image -$! -$ gosub crea_olist -$ write sys$output "Creating libzshr.exe" -$ call map_2_shopt 'mapfile' 'optfile' -$ LINK_'lopts'/SHARE=libzshr.exe modules.opt/opt,'optfile'/opt -$ write sys$output "Zlib build completed" -$ delete/nolog tmp.opt;* -$ exit -$AMISS_ERR: -$ write sys$output "No source for config.hin found." -$ write sys$output "Tried any of ''aconf_in_file'" -$ goto err_exit -$CC_ERR: -$ write sys$output "C compiler required to build ''name'" -$ goto err_exit -$ERR_EXIT: -$ set message/facil/ident/sever/text -$ close/nolog optf -$ close/nolog topt -$ close/nolog aconf_in -$ close/nolog aconf -$ close/nolog out -$ close/nolog min -$ close/nolog mod -$ close/nolog h_in -$ write sys$output "Exiting..." -$ exit 2 -$! -$! -$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES -$ V = 'F$Verify(0) -$! P1 = What we are trying to make -$! P2 = Command to make it -$! P3 - P8 What it depends on -$ -$ If F$Search(P1) .Eqs. "" Then Goto Makeit -$ Time = F$CvTime(F$File(P1,"RDT")) -$arg=3 -$Loop: -$ Argument = P'arg -$ If Argument .Eqs. "" Then Goto Exit -$ El=0 -$Loop2: -$ File = F$Element(El," ",Argument) -$ If File .Eqs. " " Then Goto Endl -$ AFile = "" -$Loop3: -$ OFile = AFile -$ AFile = F$Search(File) -$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl -$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit -$ Goto Loop3 -$NextEL: -$ El = El + 1 -$ Goto Loop2 -$EndL: -$ arg=arg+1 -$ If arg .Le. 8 Then Goto Loop -$ Goto Exit -$ -$Makeit: -$ VV=F$VERIFY(0) -$ write sys$output P2 -$ 'P2 -$ VV='F$Verify(VV) -$Exit: -$ If V Then Set Verify -$ENDSUBROUTINE -$!------------------------------------------------------------------------------ -$! -$! Check command line options and set symbols accordingly -$! -$!------------------------------------------------------------------------------ -$! Version history -$! 0.01 20041206 First version to receive a number -$! 0.02 20060126 Add new "HELP" target -$ CHECK_OPTS: -$ i = 1 -$ OPT_LOOP: -$ if i .lt. 9 -$ then -$ cparm = f$edit(p'i',"upcase") -$! -$! Check if parameter actually contains something -$! -$ if f$edit(cparm,"trim") .nes. "" -$ then -$ if cparm .eqs. "DEBUG" -$ then -$ ccopt = ccopt + "/noopt/deb" -$ lopts = lopts + "/deb" -$ endif -$ if f$locate("CCOPT=",cparm) .lt. f$length(cparm) -$ then -$ start = f$locate("=",cparm) + 1 -$ len = f$length(cparm) - start -$ ccopt = ccopt + f$extract(start,len,cparm) -$ if f$locate("AS_IS",f$edit(ccopt,"UPCASE")) .lt. f$length(ccopt) - - then s_case = true -$ endif -$ if cparm .eqs. "LINK" then linkonly = true -$ if f$locate("LOPTS=",cparm) .lt. f$length(cparm) -$ then -$ start = f$locate("=",cparm) + 1 -$ len = f$length(cparm) - start -$ lopts = lopts + f$extract(start,len,cparm) -$ endif -$ if f$locate("CC=",cparm) .lt. f$length(cparm) -$ then -$ start = f$locate("=",cparm) + 1 -$ len = f$length(cparm) - start -$ cc_com = f$extract(start,len,cparm) - if (cc_com .nes. "DECC") .and. - - (cc_com .nes. "VAXC") .and. - - (cc_com .nes. "GNUC") -$ then -$ write sys$output "Unsupported compiler choice ''cc_com' ignored" -$ write sys$output "Use DECC, VAXC, or GNUC instead" -$ else -$ if cc_com .eqs. "DECC" then its_decc = true -$ if cc_com .eqs. "VAXC" then its_vaxc = true -$ if cc_com .eqs. "GNUC" then its_gnuc = true -$ endif -$ endif -$ if f$locate("MAKE=",cparm) .lt. f$length(cparm) -$ then -$ start = f$locate("=",cparm) + 1 -$ len = f$length(cparm) - start -$ mmks = f$extract(start,len,cparm) -$ if (mmks .eqs. "MMK") .or. (mmks .eqs. "MMS") -$ then -$ make = mmks -$ else -$ write sys$output "Unsupported make choice ''mmks' ignored" -$ write sys$output "Use MMK or MMS instead" -$ endif -$ endif -$ if cparm .eqs. "HELP" then gosub bhelp -$ endif -$ i = i + 1 -$ goto opt_loop -$ endif -$ return -$!------------------------------------------------------------------------------ -$! -$! Look for the compiler used -$! -$! Version history -$! 0.01 20040223 First version to receive a number -$! 0.02 20040229 Save/set value of decc$no_rooted_search_lists -$! 0.03 20060202 Extend handling of GNU C -$! 0.04 20090402 Compaq -> hp -$CHECK_COMPILER: -$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc)) -$ then -$ its_decc = (f$search("SYS$SYSTEM:DECC$COMPILER.EXE") .nes. "") -$ its_vaxc = .not. its_decc .and. (F$Search("SYS$System:VAXC.Exe") .nes. "") -$ its_gnuc = .not. (its_decc .or. its_vaxc) .and. (f$trnlnm("gnu_cc") .nes. "") -$ endif -$! -$! Exit if no compiler available -$! -$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc)) -$ then goto CC_ERR -$ else -$ if its_decc -$ then -$ write sys$output "CC compiler check ... hp C" -$ if f$trnlnm("decc$no_rooted_search_lists") .nes. "" -$ then -$ dnrsl = f$trnlnm("decc$no_rooted_search_lists") -$ endif -$ define/nolog decc$no_rooted_search_lists 1 -$ else -$ if its_vaxc then write sys$output "CC compiler check ... VAX C" -$ if its_gnuc -$ then -$ write sys$output "CC compiler check ... GNU C" -$ if f$trnlnm(topt) then write topt "gnu_cc:[000000]gcclib.olb/lib" -$ if f$trnlnm(optf) then write optf "gnu_cc:[000000]gcclib.olb/lib" -$ cc = "gcc" -$ endif -$ if f$trnlnm(topt) then write topt "sys$share:vaxcrtl.exe/share" -$ if f$trnlnm(optf) then write optf "sys$share:vaxcrtl.exe/share" -$ endif -$ endif -$ return -$!------------------------------------------------------------------------------ -$! -$! If MMS/MMK are available dump out the descrip.mms if required -$! -$CREA_MMS: -$ write sys$output "Creating descrip.mms..." -$ create descrip.mms -$ open/append out descrip.mms -$ copy sys$input: out -$ deck -# descrip.mms: MMS description file for building zlib on VMS -# written by Martin P.J. Zinser -# - -OBJS = adler32.obj, compress.obj, crc32.obj, gzclose.obj, gzlib.obj\ - gzread.obj, gzwrite.obj, uncompr.obj, infback.obj\ - deflate.obj, trees.obj, zutil.obj, inflate.obj, \ - inftrees.obj, inffast.obj - -$ eod -$ write out "CFLAGS=", ccopt -$ write out "LOPTS=", lopts -$ write out "all : example.exe minigzip.exe libz.olb" -$ copy sys$input: out -$ deck - @ write sys$output " Example applications available" - -libz.olb : libz.olb($(OBJS)) - @ write sys$output " libz available" - -example.exe : example.obj libz.olb - link $(LOPTS) example,libz.olb/lib - -minigzip.exe : minigzip.obj libz.olb - link $(LOPTS) minigzip,libz.olb/lib - -clean : - delete *.obj;*,libz.olb;*,*.opt;*,*.exe;* - - -# Other dependencies. -adler32.obj : adler32.c zutil.h zlib.h zconf.h -compress.obj : compress.c zlib.h zconf.h -crc32.obj : crc32.c zutil.h zlib.h zconf.h -deflate.obj : deflate.c deflate.h zutil.h zlib.h zconf.h -example.obj : [.test]example.c zlib.h zconf.h -gzclose.obj : gzclose.c zutil.h zlib.h zconf.h -gzlib.obj : gzlib.c zutil.h zlib.h zconf.h -gzread.obj : gzread.c zutil.h zlib.h zconf.h -gzwrite.obj : gzwrite.c zutil.h zlib.h zconf.h -inffast.obj : inffast.c zutil.h zlib.h zconf.h inftrees.h inffast.h -inflate.obj : inflate.c zutil.h zlib.h zconf.h -inftrees.obj : inftrees.c zutil.h zlib.h zconf.h inftrees.h -minigzip.obj : [.test]minigzip.c zlib.h zconf.h -trees.obj : trees.c deflate.h zutil.h zlib.h zconf.h -uncompr.obj : uncompr.c zlib.h zconf.h -zutil.obj : zutil.c zutil.h zlib.h zconf.h -infback.obj : infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h -$ eod -$ close out -$ return -$!------------------------------------------------------------------------------ -$! -$! Read list of core library sources from makefile.in and create options -$! needed to build shareable image -$! -$CREA_OLIST: -$ open/read min makefile.in -$ open/write mod modules.opt -$ src_check_list = "OBJZ =#OBJG =" -$MRLOOP: -$ read/end=mrdone min rec -$ i = 0 -$SRC_CHECK_LOOP: -$ src_check = f$element(i, "#", src_check_list) -$ i = i+1 -$ if src_check .eqs. "#" then goto mrloop -$ if (f$extract(0,6,rec) .nes. src_check) then goto src_check_loop -$ rec = rec - src_check -$ gosub extra_filnam -$ if (f$element(1,"\",rec) .eqs. "\") then goto mrloop -$MRSLOOP: -$ read/end=mrdone min rec -$ gosub extra_filnam -$ if (f$element(1,"\",rec) .nes. "\") then goto mrsloop -$MRDONE: -$ close min -$ close mod -$ return -$!------------------------------------------------------------------------------ -$! -$! Take record extracted in crea_olist and split it into single filenames -$! -$EXTRA_FILNAM: -$ myrec = f$edit(rec - "\", "trim,compress") -$ i = 0 -$FELOOP: -$ srcfil = f$element(i," ", myrec) -$ if (srcfil .nes. " ") -$ then -$ write mod f$parse(srcfil,,,"NAME"), ".obj" -$ i = i + 1 -$ goto feloop -$ endif -$ return -$!------------------------------------------------------------------------------ -$! -$! Find current Zlib version number -$! -$FIND_VERSION: -$ open/read h_in 'v_file' -$hloop: -$ read/end=hdone h_in rec -$ rec = f$edit(rec,"TRIM") -$ if (f$extract(0,1,rec) .nes. "#") then goto hloop -$ rec = f$edit(rec - "#", "TRIM") -$ if f$element(0," ",rec) .nes. "define" then goto hloop -$ if f$element(1," ",rec) .eqs. v_string -$ then -$ version = 'f$element(2," ",rec)' -$ goto hdone -$ endif -$ goto hloop -$hdone: -$ close h_in -$ return -$!------------------------------------------------------------------------------ -$! -$CHECK_CONFIG: -$! -$ in_ldef = f$locate(cdef,libdefs) -$ if (in_ldef .lt. f$length(libdefs)) -$ then -$ write aconf "#define ''cdef' 1" -$ libdefs = f$extract(0,in_ldef,libdefs) + - - f$extract(in_ldef + f$length(cdef) + 1, - - f$length(libdefs) - in_ldef - f$length(cdef) - 1, - - libdefs) -$ else -$ if (f$type('cdef') .eqs. "INTEGER") -$ then -$ write aconf "#define ''cdef' ", 'cdef' -$ else -$ if (f$type('cdef') .eqs. "STRING") -$ then -$ write aconf "#define ''cdef' ", """", '''cdef'', """" -$ else -$ gosub check_cc_def -$ endif -$ endif -$ endif -$ return -$!------------------------------------------------------------------------------ -$! -$! Check if this is a define relating to the properties of the C/C++ -$! compiler -$! -$ CHECK_CC_DEF: -$ if (cdef .eqs. "_LARGEFILE64_SOURCE") -$ then -$ copy sys$input: 'tc' -$ deck -#include "tconfig" -#define _LARGEFILE -#include - -int main(){ -FILE *fp; - fp = fopen("temp.txt","r"); - fseeko(fp,1,SEEK_SET); - fclose(fp); -} - -$ eod -$ test_inv = false -$ comm_h = false -$ gosub cc_prop_check -$ return -$ endif -$ write aconf "/* ", line, " */" -$ return -$!------------------------------------------------------------------------------ -$! -$! Check for properties of C/C++ compiler -$! -$! Version history -$! 0.01 20031020 First version to receive a number -$! 0.02 20031022 Added logic for defines with value -$! 0.03 20040309 Make sure local config file gets not deleted -$! 0.04 20041230 Also write include for configure run -$! 0.05 20050103 Add processing of "comment defines" -$CC_PROP_CHECK: -$ cc_prop = true -$ is_need = false -$ is_need = (f$extract(0,4,cdef) .eqs. "NEED") .or. (test_inv .eq. true) -$ if f$search(th) .eqs. "" then create 'th' -$ set message/nofac/noident/nosever/notext -$ on error then continue -$ cc 'tmpnam' -$ if .not. ($status) then cc_prop = false -$ on error then continue -$! The headers might lie about the capabilities of the RTL -$ link 'tmpnam',tmp.opt/opt -$ if .not. ($status) then cc_prop = false -$ set message/fac/ident/sever/text -$ on error then goto err_exit -$ delete/nolog 'tmpnam'.*;*/exclude='th' -$ if (cc_prop .and. .not. is_need) .or. - - (.not. cc_prop .and. is_need) -$ then -$ write sys$output "Checking for ''cdef'... yes" -$ if f$type('cdef_val'_yes) .nes. "" -$ then -$ if f$type('cdef_val'_yes) .eqs. "INTEGER" - - then call write_config f$fao("#define !AS !UL",cdef,'cdef_val'_yes) -$ if f$type('cdef_val'_yes) .eqs. "STRING" - - then call write_config f$fao("#define !AS !AS",cdef,'cdef_val'_yes) -$ else -$ call write_config f$fao("#define !AS 1",cdef) -$ endif -$ if (cdef .eqs. "HAVE_FSEEKO") .or. (cdef .eqs. "_LARGE_FILES") .or. - - (cdef .eqs. "_LARGEFILE64_SOURCE") then - - call write_config f$string("#define _LARGEFILE 1") -$ else -$ write sys$output "Checking for ''cdef'... no" -$ if (comm_h) -$ then - call write_config f$fao("/* !AS */",line) -$ else -$ if f$type('cdef_val'_no) .nes. "" -$ then -$ if f$type('cdef_val'_no) .eqs. "INTEGER" - - then call write_config f$fao("#define !AS !UL",cdef,'cdef_val'_no) -$ if f$type('cdef_val'_no) .eqs. "STRING" - - then call write_config f$fao("#define !AS !AS",cdef,'cdef_val'_no) -$ else -$ call write_config f$fao("#undef !AS",cdef) -$ endif -$ endif -$ endif -$ return -$!------------------------------------------------------------------------------ -$! -$! Check for properties of C/C++ compiler with multiple result values -$! -$! Version history -$! 0.01 20040127 First version -$! 0.02 20050103 Reconcile changes from cc_prop up to version 0.05 -$CC_MPROP_CHECK: -$ cc_prop = true -$ i = 1 -$ idel = 1 -$ MT_LOOP: -$ if f$type(result_'i') .eqs. "STRING" -$ then -$ set message/nofac/noident/nosever/notext -$ on error then continue -$ cc 'tmpnam'_'i' -$ if .not. ($status) then cc_prop = false -$ on error then continue -$! The headers might lie about the capabilities of the RTL -$ link 'tmpnam'_'i',tmp.opt/opt -$ if .not. ($status) then cc_prop = false -$ set message/fac/ident/sever/text -$ on error then goto err_exit -$ delete/nolog 'tmpnam'_'i'.*;* -$ if (cc_prop) -$ then -$ write sys$output "Checking for ''cdef'... ", mdef_'i' -$ if f$type(mdef_'i') .eqs. "INTEGER" - - then call write_config f$fao("#define !AS !UL",cdef,mdef_'i') -$ if f$type('cdef_val'_yes) .eqs. "STRING" - - then call write_config f$fao("#define !AS !AS",cdef,mdef_'i') -$ goto msym_clean -$ else -$ i = i + 1 -$ goto mt_loop -$ endif -$ endif -$ write sys$output "Checking for ''cdef'... no" -$ call write_config f$fao("#undef !AS",cdef) -$ MSYM_CLEAN: -$ if (idel .le. msym_max) -$ then -$ delete/sym mdef_'idel' -$ idel = idel + 1 -$ goto msym_clean -$ endif -$ return -$!------------------------------------------------------------------------------ -$! -$! Write configuration to both permanent and temporary config file -$! -$! Version history -$! 0.01 20031029 First version to receive a number -$! -$WRITE_CONFIG: SUBROUTINE -$ write aconf 'p1' -$ open/append confh 'th' -$ write confh 'p1' -$ close confh -$ENDSUBROUTINE -$!------------------------------------------------------------------------------ -$! -$! Analyze the project map file and create the symbol vector for a shareable -$! image from it -$! -$! Version history -$! 0.01 20120128 First version -$! 0.02 20120226 Add pre-load logic -$! -$ MAP_2_SHOPT: Subroutine -$! -$ SAY := "WRITE_ SYS$OUTPUT" -$! -$ IF F$SEARCH("''P1'") .EQS. "" -$ THEN -$ SAY "MAP_2_SHOPT-E-NOSUCHFILE: Error, inputfile ''p1' not available" -$ goto exit_m2s -$ ENDIF -$ IF "''P2'" .EQS. "" -$ THEN -$ SAY "MAP_2_SHOPT: Error, no output file provided" -$ goto exit_m2s -$ ENDIF -$! -$ module1 = "deflate#deflateEnd#deflateInit_#deflateParams#deflateSetDictionary" -$ module2 = "gzclose#gzerror#gzgetc#gzgets#gzopen#gzprintf#gzputc#gzputs#gzread" -$ module3 = "gzseek#gztell#inflate#inflateEnd#inflateInit_#inflateSetDictionary" -$ module4 = "inflateSync#uncompress#zlibVersion#compress" -$ open/read map 'p1 -$ if axp .or. ia64 -$ then -$ open/write aopt a.opt -$ open/write bopt b.opt -$ write aopt " CASE_SENSITIVE=YES" -$ write bopt "SYMBOL_VECTOR= (-" -$ mod_sym_num = 1 -$ MOD_SYM_LOOP: -$ if f$type(module'mod_sym_num') .nes. "" -$ then -$ mod_in = 0 -$ MOD_SYM_IN: -$ shared_proc = f$element(mod_in, "#", module'mod_sym_num') -$ if shared_proc .nes. "#" -$ then -$ write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",- - f$edit(shared_proc,"upcase"),shared_proc) -$ write bopt f$fao("!AS=PROCEDURE,-",shared_proc) -$ mod_in = mod_in + 1 -$ goto mod_sym_in -$ endif -$ mod_sym_num = mod_sym_num + 1 -$ goto mod_sym_loop -$ endif -$MAP_LOOP: -$ read/end=map_end map line -$ if (f$locate("{",line).lt. f$length(line)) .or. - - (f$locate("global:", line) .lt. f$length(line)) -$ then -$ proc = true -$ goto map_loop -$ endif -$ if f$locate("}",line).lt. f$length(line) then proc = false -$ if f$locate("local:", line) .lt. f$length(line) then proc = false -$ if proc -$ then -$ shared_proc = f$edit(line,"collapse") -$ chop_semi = f$locate(";", shared_proc) -$ if chop_semi .lt. f$length(shared_proc) then - - shared_proc = f$extract(0, chop_semi, shared_proc) -$ write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",- - f$edit(shared_proc,"upcase"),shared_proc) -$ write bopt f$fao("!AS=PROCEDURE,-",shared_proc) -$ endif -$ goto map_loop -$MAP_END: -$ close/nolog aopt -$ close/nolog bopt -$ open/append libopt 'p2' -$ open/read aopt a.opt -$ open/read bopt b.opt -$ALOOP: -$ read/end=aloop_end aopt line -$ write libopt line -$ goto aloop -$ALOOP_END: -$ close/nolog aopt -$ sv = "" -$BLOOP: -$ read/end=bloop_end bopt svn -$ if (svn.nes."") -$ then -$ if (sv.nes."") then write libopt sv -$ sv = svn -$ endif -$ goto bloop -$BLOOP_END: -$ write libopt f$extract(0,f$length(sv)-2,sv), "-" -$ write libopt ")" -$ close/nolog bopt -$ delete/nolog/noconf a.opt;*,b.opt;* -$ else -$ if vax -$ then -$ open/append libopt 'p2' -$ mod_sym_num = 1 -$ VMOD_SYM_LOOP: -$ if f$type(module'mod_sym_num') .nes. "" -$ then -$ mod_in = 0 -$ VMOD_SYM_IN: -$ shared_proc = f$element(mod_in, "#", module'mod_sym_num') -$ if shared_proc .nes. "#" -$ then -$ write libopt f$fao("UNIVERSAL=!AS",- - f$edit(shared_proc,"upcase")) -$ mod_in = mod_in + 1 -$ goto vmod_sym_in -$ endif -$ mod_sym_num = mod_sym_num + 1 -$ goto vmod_sym_loop -$ endif -$VMAP_LOOP: -$ read/end=vmap_end map line -$ if (f$locate("{",line).lt. f$length(line)) .or. - - (f$locate("global:", line) .lt. f$length(line)) -$ then -$ proc = true -$ goto vmap_loop -$ endif -$ if f$locate("}",line).lt. f$length(line) then proc = false -$ if f$locate("local:", line) .lt. f$length(line) then proc = false -$ if proc -$ then -$ shared_proc = f$edit(line,"collapse") -$ chop_semi = f$locate(";", shared_proc) -$ if chop_semi .lt. f$length(shared_proc) then - - shared_proc = f$extract(0, chop_semi, shared_proc) -$ write libopt f$fao("UNIVERSAL=!AS",- - f$edit(shared_proc,"upcase")) -$ endif -$ goto vmap_loop -$VMAP_END: -$ else -$ write sys$output "Unknown Architecture (Not VAX, AXP, or IA64)" -$ write sys$output "No options file created" -$ endif -$ endif -$ EXIT_M2S: -$ close/nolog map -$ close/nolog libopt -$ endsubroutine diff --git a/deps/zlib/msdos/Makefile.bor b/deps/zlib/msdos/Makefile.bor deleted file mode 100644 index 3d12a2c25270a4..00000000000000 --- a/deps/zlib/msdos/Makefile.bor +++ /dev/null @@ -1,115 +0,0 @@ -# Makefile for zlib -# Borland C++ -# Last updated: 15-Mar-2003 - -# To use, do "make -fmakefile.bor" -# To compile in small model, set below: MODEL=s - -# WARNING: the small model is supported but only for small values of -# MAX_WBITS and MAX_MEM_LEVEL. For example: -# -DMAX_WBITS=11 -DDEF_WBITS=11 -DMAX_MEM_LEVEL=3 -# If you wish to reduce the memory requirements (default 256K for big -# objects plus a few K), you can add to the LOC macro below: -# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 -# See zconf.h for details about the memory requirements. - -# ------------ Turbo C++, Borland C++ ------------ - -# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) -# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added -# to the declaration of LOC here: -LOC = $(LOCAL_ZLIB) - -# type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. -CPU_TYP = 0 - -# memory model: one of s, m, c, l (small, medium, compact, large) -MODEL=l - -# replace bcc with tcc for Turbo C++ 1.0, with bcc32 for the 32 bit version -CC=bcc -LD=bcc -AR=tlib - -# compiler flags -# replace "-O2" by "-O -G -a -d" for Turbo C++ 1.0 -CFLAGS=-O2 -Z -m$(MODEL) $(LOC) - -LDFLAGS=-m$(MODEL) -f- - - -# variables -ZLIB_LIB = zlib_$(MODEL).lib - -OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj -OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj -OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj -OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj - - -# targets -all: $(ZLIB_LIB) example.exe minigzip.exe - -.c.obj: - $(CC) -c $(CFLAGS) $*.c - -adler32.obj: adler32.c zlib.h zconf.h - -compress.obj: compress.c zlib.h zconf.h - -crc32.obj: crc32.c zlib.h zconf.h crc32.h - -deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h - -gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h - -gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h - -gzread.obj: gzread.c zlib.h zconf.h gzguts.h - -gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h - -infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h - -inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h - -trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h - -uncompr.obj: uncompr.c zlib.h zconf.h - -zutil.obj: zutil.c zutil.h zlib.h zconf.h - -example.obj: test/example.c zlib.h zconf.h - -minigzip.obj: test/minigzip.c zlib.h zconf.h - - -# the command line is cut to fit in the MS-DOS 128 byte limit: -$(ZLIB_LIB): $(OBJ1) $(OBJ2) - -del $(ZLIB_LIB) - $(AR) $(ZLIB_LIB) $(OBJP1) - $(AR) $(ZLIB_LIB) $(OBJP2) - -example.exe: example.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) - -minigzip.exe: minigzip.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) - -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -clean: - -del *.obj - -del *.lib - -del *.exe - -del zlib_*.bak - -del foo.gz diff --git a/deps/zlib/msdos/Makefile.dj2 b/deps/zlib/msdos/Makefile.dj2 deleted file mode 100644 index 59d2037d69c4e8..00000000000000 --- a/deps/zlib/msdos/Makefile.dj2 +++ /dev/null @@ -1,104 +0,0 @@ -# Makefile for zlib. Modified for djgpp v2.0 by F. J. Donahoe, 3/15/96. -# Copyright (C) 1995-1998 Jean-loup Gailly. -# For conditions of distribution and use, see copyright notice in zlib.h - -# To compile, or to compile and test, type: -# -# make -fmakefile.dj2; make test -fmakefile.dj2 -# -# To install libz.a, zconf.h and zlib.h in the djgpp directories, type: -# -# make install -fmakefile.dj2 -# -# after first defining LIBRARY_PATH and INCLUDE_PATH in djgpp.env as -# in the sample below if the pattern of the DJGPP distribution is to -# be followed. Remember that, while 'es around <=> are ignored in -# makefiles, they are *not* in batch files or in djgpp.env. -# - - - - - -# [make] -# INCLUDE_PATH=%\>;INCLUDE_PATH%%\DJDIR%\include -# LIBRARY_PATH=%\>;LIBRARY_PATH%%\DJDIR%\lib -# BUTT=-m486 -# - - - - - -# Alternately, these variables may be defined below, overriding the values -# in djgpp.env, as -# INCLUDE_PATH=c:\usr\include -# LIBRARY_PATH=c:\usr\lib - -CC=gcc - -#CFLAGS=-MMD -O -#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-MMD -g -DZLIB_DEBUG -CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ - -Wstrict-prototypes -Wmissing-prototypes - -# If cp.exe is available, replace "copy /Y" with "cp -fp" . -CP=copy /Y -# If gnu install.exe is available, replace $(CP) with ginstall. -INSTALL=$(CP) -# The default value of RM is "rm -f." If "rm.exe" is found, comment out: -RM=del -LDLIBS=-L. -lz -LD=$(CC) -s -o -LDSHARED=$(CC) - -INCL=zlib.h zconf.h -LIBS=libz.a - -AR=ar rcs - -prefix=/usr/local -exec_prefix = $(prefix) - -OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ - uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o - -OBJA = -# to use the asm code: make OBJA=match.o - -TEST_OBJS = example.o minigzip.o - -all: example.exe minigzip.exe - -check: test -test: all - ./example - echo hello world | .\minigzip | .\minigzip -d - -%.o : %.c - $(CC) $(CFLAGS) -c $< -o $@ - -libz.a: $(OBJS) $(OBJA) - $(AR) $@ $(OBJS) $(OBJA) - -%.exe : %.o $(LIBS) - $(LD) $@ $< $(LDLIBS) - -# INCLUDE_PATH and LIBRARY_PATH were set for [make] in djgpp.env . - -.PHONY : uninstall clean - -install: $(INCL) $(LIBS) - -@if not exist $(INCLUDE_PATH)\nul mkdir $(INCLUDE_PATH) - -@if not exist $(LIBRARY_PATH)\nul mkdir $(LIBRARY_PATH) - $(INSTALL) zlib.h $(INCLUDE_PATH) - $(INSTALL) zconf.h $(INCLUDE_PATH) - $(INSTALL) libz.a $(LIBRARY_PATH) - -uninstall: - $(RM) $(INCLUDE_PATH)\zlib.h - $(RM) $(INCLUDE_PATH)\zconf.h - $(RM) $(LIBRARY_PATH)\libz.a - -clean: - $(RM) *.d - $(RM) *.o - $(RM) *.exe - $(RM) libz.a - $(RM) foo.gz - -DEPS := $(wildcard *.d) -ifneq ($(DEPS),) -include $(DEPS) -endif diff --git a/deps/zlib/msdos/Makefile.emx b/deps/zlib/msdos/Makefile.emx deleted file mode 100644 index e30f67bed68e86..00000000000000 --- a/deps/zlib/msdos/Makefile.emx +++ /dev/null @@ -1,69 +0,0 @@ -# Makefile for zlib. Modified for emx 0.9c by Chr. Spieler, 6/17/98. -# Copyright (C) 1995-1998 Jean-loup Gailly. -# For conditions of distribution and use, see copyright notice in zlib.h - -# To compile, or to compile and test, type: -# -# make -fmakefile.emx; make test -fmakefile.emx -# - -CC=gcc - -#CFLAGS=-MMD -O -#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-MMD -g -DZLIB_DEBUG -CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ - -Wstrict-prototypes -Wmissing-prototypes - -# If cp.exe is available, replace "copy /Y" with "cp -fp" . -CP=copy /Y -# If gnu install.exe is available, replace $(CP) with ginstall. -INSTALL=$(CP) -# The default value of RM is "rm -f." If "rm.exe" is found, comment out: -RM=del -LDLIBS=-L. -lzlib -LD=$(CC) -s -o -LDSHARED=$(CC) - -INCL=zlib.h zconf.h -LIBS=zlib.a - -AR=ar rcs - -prefix=/usr/local -exec_prefix = $(prefix) - -OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ - uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o - -TEST_OBJS = example.o minigzip.o - -all: example.exe minigzip.exe - -test: all - ./example - echo hello world | .\minigzip | .\minigzip -d - -%.o : %.c - $(CC) $(CFLAGS) -c $< -o $@ - -zlib.a: $(OBJS) - $(AR) $@ $(OBJS) - -%.exe : %.o $(LIBS) - $(LD) $@ $< $(LDLIBS) - - -.PHONY : clean - -clean: - $(RM) *.d - $(RM) *.o - $(RM) *.exe - $(RM) zlib.a - $(RM) foo.gz - -DEPS := $(wildcard *.d) -ifneq ($(DEPS),) -include $(DEPS) -endif diff --git a/deps/zlib/msdos/Makefile.msc b/deps/zlib/msdos/Makefile.msc deleted file mode 100644 index ae8378615ec6bc..00000000000000 --- a/deps/zlib/msdos/Makefile.msc +++ /dev/null @@ -1,112 +0,0 @@ -# Makefile for zlib -# Microsoft C 5.1 or later -# Last updated: 19-Mar-2003 - -# To use, do "make makefile.msc" -# To compile in small model, set below: MODEL=S - -# If you wish to reduce the memory requirements (default 256K for big -# objects plus a few K), you can add to the LOC macro below: -# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 -# See zconf.h for details about the memory requirements. - -# ------------- Microsoft C 5.1 and later ------------- - -# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) -# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added -# to the declaration of LOC here: -LOC = $(LOCAL_ZLIB) - -# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. -CPU_TYP = 0 - -# Memory model: one of S, M, C, L (small, medium, compact, large) -MODEL=L - -CC=cl -CFLAGS=-nologo -A$(MODEL) -G$(CPU_TYP) -W3 -Oait -Gs $(LOC) -#-Ox generates bad code with MSC 5.1 -LIB_CFLAGS=-Zl $(CFLAGS) - -LD=link -LDFLAGS=/noi/e/st:0x1500/noe/farcall/packcode -# "/farcall/packcode" are only useful for `large code' memory models -# but should be a "no-op" for small code models. - - -# variables -ZLIB_LIB = zlib_$(MODEL).lib - -OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj -OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj - - -# targets -all: $(ZLIB_LIB) example.exe minigzip.exe - -.c.obj: - $(CC) -c $(LIB_CFLAGS) $*.c - -adler32.obj: adler32.c zlib.h zconf.h - -compress.obj: compress.c zlib.h zconf.h - -crc32.obj: crc32.c zlib.h zconf.h crc32.h - -deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h - -gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h - -gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h - -gzread.obj: gzread.c zlib.h zconf.h gzguts.h - -gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h - -infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h - -inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h - -trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h - -uncompr.obj: uncompr.c zlib.h zconf.h - -zutil.obj: zutil.c zutil.h zlib.h zconf.h - -example.obj: test/example.c zlib.h zconf.h - $(CC) -c $(CFLAGS) $*.c - -minigzip.obj: test/minigzip.c zlib.h zconf.h - $(CC) -c $(CFLAGS) $*.c - - -# the command line is cut to fit in the MS-DOS 128 byte limit: -$(ZLIB_LIB): $(OBJ1) $(OBJ2) - if exist $(ZLIB_LIB) del $(ZLIB_LIB) - lib $(ZLIB_LIB) $(OBJ1); - lib $(ZLIB_LIB) $(OBJ2); - -example.exe: example.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) example.obj,,,$(ZLIB_LIB); - -minigzip.exe: minigzip.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) minigzip.obj,,,$(ZLIB_LIB); - -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -clean: - -del *.obj - -del *.lib - -del *.exe - -del *.map - -del zlib_*.bak - -del foo.gz diff --git a/deps/zlib/msdos/Makefile.tc b/deps/zlib/msdos/Makefile.tc deleted file mode 100644 index 5aec82a9d58c45..00000000000000 --- a/deps/zlib/msdos/Makefile.tc +++ /dev/null @@ -1,100 +0,0 @@ -# Makefile for zlib -# Turbo C 2.01, Turbo C++ 1.01 -# Last updated: 15-Mar-2003 - -# To use, do "make -fmakefile.tc" -# To compile in small model, set below: MODEL=s - -# WARNING: the small model is supported but only for small values of -# MAX_WBITS and MAX_MEM_LEVEL. For example: -# -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 -# If you wish to reduce the memory requirements (default 256K for big -# objects plus a few K), you can add to CFLAGS below: -# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 -# See zconf.h for details about the memory requirements. - -# ------------ Turbo C 2.01, Turbo C++ 1.01 ------------ -MODEL=l -CC=tcc -LD=tcc -AR=tlib -# CFLAGS=-O2 -G -Z -m$(MODEL) -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 -CFLAGS=-O2 -G -Z -m$(MODEL) -LDFLAGS=-m$(MODEL) -f- - - -# variables -ZLIB_LIB = zlib_$(MODEL).lib - -OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj -OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj -OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj -OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj - - -# targets -all: $(ZLIB_LIB) example.exe minigzip.exe - -.c.obj: - $(CC) -c $(CFLAGS) $*.c - -adler32.obj: adler32.c zlib.h zconf.h - -compress.obj: compress.c zlib.h zconf.h - -crc32.obj: crc32.c zlib.h zconf.h crc32.h - -deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h - -gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h - -gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h - -gzread.obj: gzread.c zlib.h zconf.h gzguts.h - -gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h - -infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h - -inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h - -trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h - -uncompr.obj: uncompr.c zlib.h zconf.h - -zutil.obj: zutil.c zutil.h zlib.h zconf.h - -example.obj: test/example.c zlib.h zconf.h - -minigzip.obj: test/minigzip.c zlib.h zconf.h - - -# the command line is cut to fit in the MS-DOS 128 byte limit: -$(ZLIB_LIB): $(OBJ1) $(OBJ2) - -del $(ZLIB_LIB) - $(AR) $(ZLIB_LIB) $(OBJP1) - $(AR) $(ZLIB_LIB) $(OBJP2) - -example.exe: example.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) - -minigzip.exe: minigzip.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) - -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -clean: - -del *.obj - -del *.lib - -del *.exe - -del zlib_*.bak - -del foo.gz diff --git a/deps/zlib/nintendods/Makefile b/deps/zlib/nintendods/Makefile deleted file mode 100644 index 21337d01ab2fe2..00000000000000 --- a/deps/zlib/nintendods/Makefile +++ /dev/null @@ -1,126 +0,0 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- - -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") -endif - -include $(DEVKITARM)/ds_rules - -#--------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# DATA is a list of directories containing data files -# INCLUDES is a list of directories containing header files -#--------------------------------------------------------------------------------- -TARGET := $(shell basename $(CURDIR)) -BUILD := build -SOURCES := ../../ -DATA := data -INCLUDES := include - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- -ARCH := -mthumb -mthumb-interwork - -CFLAGS := -Wall -O2\ - -march=armv5te -mtune=arm946e-s \ - -fomit-frame-pointer -ffast-math \ - $(ARCH) - -CFLAGS += $(INCLUDE) -DARM9 -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions - -ASFLAGS := $(ARCH) -march=armv5te -mtune=arm946e-s -LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := $(LIBNDS) - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- - -export OUTPUT := $(CURDIR)/lib/libz.a - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -export DEPSDIR := $(CURDIR)/$(BUILD) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) -#--------------------------------------------------------------------------------- - export LD := $(CC) -#--------------------------------------------------------------------------------- -else -#--------------------------------------------------------------------------------- - export LD := $(CXX) -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- - -export OFILES := $(addsuffix .o,$(BINFILES)) \ - $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) - -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) - -.PHONY: $(BUILD) clean all - -#--------------------------------------------------------------------------------- -all: $(BUILD) - @[ -d $@ ] || mkdir -p include - @cp ../../*.h include - -lib: - @[ -d $@ ] || mkdir -p $@ - -$(BUILD): lib - @[ -d $@ ] || mkdir -p $@ - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile - -#--------------------------------------------------------------------------------- -clean: - @echo clean ... - @rm -fr $(BUILD) lib - -#--------------------------------------------------------------------------------- -else - -DEPENDS := $(OFILES:.o=.d) - -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- -$(OUTPUT) : $(OFILES) - -#--------------------------------------------------------------------------------- -%.bin.o : %.bin -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - - --include $(DEPENDS) - -#--------------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------------- diff --git a/deps/zlib/nintendods/README b/deps/zlib/nintendods/README deleted file mode 100644 index ba7a37dbe8e916..00000000000000 --- a/deps/zlib/nintendods/README +++ /dev/null @@ -1,5 +0,0 @@ -This Makefile requires devkitARM (http://www.devkitpro.org/category/devkitarm/) and works inside "contrib/nds". It is based on a devkitARM template. - -Eduardo Costa -January 3, 2009 - diff --git a/deps/zlib/old/Makefile.emx b/deps/zlib/old/Makefile.emx deleted file mode 100644 index 612b03791583cb..00000000000000 --- a/deps/zlib/old/Makefile.emx +++ /dev/null @@ -1,69 +0,0 @@ -# Makefile for zlib. Modified for emx/rsxnt by Chr. Spieler, 6/16/98. -# Copyright (C) 1995-1998 Jean-loup Gailly. -# For conditions of distribution and use, see copyright notice in zlib.h - -# To compile, or to compile and test, type: -# -# make -fmakefile.emx; make test -fmakefile.emx -# - -CC=gcc -Zwin32 - -#CFLAGS=-MMD -O -#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-MMD -g -DZLIB_DEBUG -CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ - -Wstrict-prototypes -Wmissing-prototypes - -# If cp.exe is available, replace "copy /Y" with "cp -fp" . -CP=copy /Y -# If gnu install.exe is available, replace $(CP) with ginstall. -INSTALL=$(CP) -# The default value of RM is "rm -f." If "rm.exe" is found, comment out: -RM=del -LDLIBS=-L. -lzlib -LD=$(CC) -s -o -LDSHARED=$(CC) - -INCL=zlib.h zconf.h -LIBS=zlib.a - -AR=ar rcs - -prefix=/usr/local -exec_prefix = $(prefix) - -OBJS = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o \ - gzwrite.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o - -TEST_OBJS = example.o minigzip.o - -all: example.exe minigzip.exe - -test: all - ./example - echo hello world | .\minigzip | .\minigzip -d - -%.o : %.c - $(CC) $(CFLAGS) -c $< -o $@ - -zlib.a: $(OBJS) - $(AR) $@ $(OBJS) - -%.exe : %.o $(LIBS) - $(LD) $@ $< $(LDLIBS) - - -.PHONY : clean - -clean: - $(RM) *.d - $(RM) *.o - $(RM) *.exe - $(RM) zlib.a - $(RM) foo.gz - -DEPS := $(wildcard *.d) -ifneq ($(DEPS),) -include $(DEPS) -endif diff --git a/deps/zlib/old/Makefile.riscos b/deps/zlib/old/Makefile.riscos deleted file mode 100644 index 57e29d3fba9177..00000000000000 --- a/deps/zlib/old/Makefile.riscos +++ /dev/null @@ -1,151 +0,0 @@ -# Project: zlib_1_03 -# Patched for zlib 1.1.2 rw@shadow.org.uk 19980430 -# test works out-of-the-box, installs `somewhere' on demand - -# Toolflags: -CCflags = -c -depend !Depend -IC: -g -throwback -DRISCOS -fah -C++flags = -c -depend !Depend -IC: -throwback -Linkflags = -aif -c++ -o $@ -ObjAsmflags = -throwback -NoCache -depend !Depend -CMHGflags = -LibFileflags = -c -l -o $@ -Squeezeflags = -o $@ - -# change the line below to where _you_ want the library installed. -libdest = lib:zlib - -# Final targets: -@.lib: @.o.adler32 @.o.compress @.o.crc32 @.o.deflate @.o.gzio \ - @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil @.o.trees \ - @.o.uncompr @.o.zutil - LibFile $(LibFileflags) @.o.adler32 @.o.compress @.o.crc32 @.o.deflate \ - @.o.gzio @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil \ - @.o.trees @.o.uncompr @.o.zutil -test: @.minigzip @.example @.lib - @copy @.lib @.libc A~C~DF~L~N~P~Q~RS~TV - @echo running tests: hang on. - @/@.minigzip -f -9 libc - @/@.minigzip -d libc-gz - @/@.minigzip -f -1 libc - @/@.minigzip -d libc-gz - @/@.minigzip -h -9 libc - @/@.minigzip -d libc-gz - @/@.minigzip -h -1 libc - @/@.minigzip -d libc-gz - @/@.minigzip -9 libc - @/@.minigzip -d libc-gz - @/@.minigzip -1 libc - @/@.minigzip -d libc-gz - @diff @.lib @.libc - @echo that should have reported '@.lib and @.libc identical' if you have diff. - @/@.example @.fred @.fred - @echo that will have given lots of hello!'s. - -@.minigzip: @.o.minigzip @.lib C:o.Stubs - Link $(Linkflags) @.o.minigzip @.lib C:o.Stubs -@.example: @.o.example @.lib C:o.Stubs - Link $(Linkflags) @.o.example @.lib C:o.Stubs - -install: @.lib - cdir $(libdest) - cdir $(libdest).h - @copy @.h.zlib $(libdest).h.zlib A~C~DF~L~N~P~Q~RS~TV - @copy @.h.zconf $(libdest).h.zconf A~C~DF~L~N~P~Q~RS~TV - @copy @.lib $(libdest).lib A~C~DF~L~N~P~Q~RS~TV - @echo okay, installed zlib in $(libdest) - -clean:; remove @.minigzip - remove @.example - remove @.libc - -wipe @.o.* F~r~cV - remove @.fred - -# User-editable dependencies: -.c.o: - cc $(ccflags) -o $@ $< - -# Static dependencies: - -# Dynamic dependencies: -o.example: c.example -o.example: h.zlib -o.example: h.zconf -o.minigzip: c.minigzip -o.minigzip: h.zlib -o.minigzip: h.zconf -o.adler32: c.adler32 -o.adler32: h.zlib -o.adler32: h.zconf -o.compress: c.compress -o.compress: h.zlib -o.compress: h.zconf -o.crc32: c.crc32 -o.crc32: h.zlib -o.crc32: h.zconf -o.deflate: c.deflate -o.deflate: h.deflate -o.deflate: h.zutil -o.deflate: h.zlib -o.deflate: h.zconf -o.gzio: c.gzio -o.gzio: h.zutil -o.gzio: h.zlib -o.gzio: h.zconf -o.infblock: c.infblock -o.infblock: h.zutil -o.infblock: h.zlib -o.infblock: h.zconf -o.infblock: h.infblock -o.infblock: h.inftrees -o.infblock: h.infcodes -o.infblock: h.infutil -o.infcodes: c.infcodes -o.infcodes: h.zutil -o.infcodes: h.zlib -o.infcodes: h.zconf -o.infcodes: h.inftrees -o.infcodes: h.infblock -o.infcodes: h.infcodes -o.infcodes: h.infutil -o.infcodes: h.inffast -o.inffast: c.inffast -o.inffast: h.zutil -o.inffast: h.zlib -o.inffast: h.zconf -o.inffast: h.inftrees -o.inffast: h.infblock -o.inffast: h.infcodes -o.inffast: h.infutil -o.inffast: h.inffast -o.inflate: c.inflate -o.inflate: h.zutil -o.inflate: h.zlib -o.inflate: h.zconf -o.inflate: h.infblock -o.inftrees: c.inftrees -o.inftrees: h.zutil -o.inftrees: h.zlib -o.inftrees: h.zconf -o.inftrees: h.inftrees -o.inftrees: h.inffixed -o.infutil: c.infutil -o.infutil: h.zutil -o.infutil: h.zlib -o.infutil: h.zconf -o.infutil: h.infblock -o.infutil: h.inftrees -o.infutil: h.infcodes -o.infutil: h.infutil -o.trees: c.trees -o.trees: h.deflate -o.trees: h.zutil -o.trees: h.zlib -o.trees: h.zconf -o.trees: h.trees -o.uncompr: c.uncompr -o.uncompr: h.zlib -o.uncompr: h.zconf -o.zutil: c.zutil -o.zutil: h.zutil -o.zutil: h.zlib -o.zutil: h.zconf diff --git a/deps/zlib/old/README b/deps/zlib/old/README deleted file mode 100644 index 800bf079827b7b..00000000000000 --- a/deps/zlib/old/README +++ /dev/null @@ -1,3 +0,0 @@ -This directory contains files that have not been updated for zlib 1.2.x - -(Volunteers are encouraged to help clean this up. Thanks.) diff --git a/deps/zlib/old/descrip.mms b/deps/zlib/old/descrip.mms deleted file mode 100644 index 7066da5b557e89..00000000000000 --- a/deps/zlib/old/descrip.mms +++ /dev/null @@ -1,48 +0,0 @@ -# descrip.mms: MMS description file for building zlib on VMS -# written by Martin P.J. Zinser - -cc_defs = -c_deb = - -.ifdef __DECC__ -pref = /prefix=all -.endif - -OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj,\ - deflate.obj, trees.obj, zutil.obj, inflate.obj, infblock.obj,\ - inftrees.obj, infcodes.obj, infutil.obj, inffast.obj - -CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF) - -all : example.exe minigzip.exe - @ write sys$output " Example applications available" -libz.olb : libz.olb($(OBJS)) - @ write sys$output " libz available" - -example.exe : example.obj libz.olb - link example,libz.olb/lib - -minigzip.exe : minigzip.obj libz.olb - link minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib - -clean : - delete *.obj;*,libz.olb;* - - -# Other dependencies. -adler32.obj : zutil.h zlib.h zconf.h -compress.obj : zlib.h zconf.h -crc32.obj : zutil.h zlib.h zconf.h -deflate.obj : deflate.h zutil.h zlib.h zconf.h -example.obj : zlib.h zconf.h -gzio.obj : zutil.h zlib.h zconf.h -infblock.obj : zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h -infcodes.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h -inffast.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h -inflate.obj : zutil.h zlib.h zconf.h infblock.h -inftrees.obj : zutil.h zlib.h zconf.h inftrees.h -infutil.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h -minigzip.obj : zlib.h zconf.h -trees.obj : deflate.h zutil.h zlib.h zconf.h -uncompr.obj : zlib.h zconf.h -zutil.obj : zutil.h zlib.h zconf.h diff --git a/deps/zlib/old/os2/Makefile.os2 b/deps/zlib/old/os2/Makefile.os2 deleted file mode 100644 index bb426c0d8e68df..00000000000000 --- a/deps/zlib/old/os2/Makefile.os2 +++ /dev/null @@ -1,136 +0,0 @@ -# Makefile for zlib under OS/2 using GCC (PGCC) -# For conditions of distribution and use, see copyright notice in zlib.h - -# To compile and test, type: -# cp Makefile.os2 .. -# cd .. -# make -f Makefile.os2 test - -# This makefile will build a static library z.lib, a shared library -# z.dll and a import library zdll.lib. You can use either z.lib or -# zdll.lib by specifying either -lz or -lzdll on gcc's command line - -CC=gcc -Zomf -s - -CFLAGS=-O6 -Wall -#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-g -DZLIB_DEBUG -#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ -# -Wstrict-prototypes -Wmissing-prototypes - -#################### BUG WARNING: ##################### -## infcodes.c hits a bug in pgcc-1.0, so you have to use either -## -O# where # <= 4 or one of (-fno-ommit-frame-pointer or -fno-force-mem) -## This bug is reportedly fixed in pgcc >1.0, but this was not tested -CFLAGS+=-fno-force-mem - -LDFLAGS=-s -L. -lzdll -Zcrtdll -LDSHARED=$(CC) -s -Zomf -Zdll -Zcrtdll - -VER=1.1.0 -ZLIB=z.lib -SHAREDLIB=z.dll -SHAREDLIBIMP=zdll.lib -LIBS=$(ZLIB) $(SHAREDLIB) $(SHAREDLIBIMP) - -AR=emxomfar cr -IMPLIB=emximp -RANLIB=echo -TAR=tar -SHELL=bash - -prefix=/usr/local -exec_prefix = $(prefix) - -OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ - zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o - -TEST_OBJS = example.o minigzip.o - -DISTFILES = README INDEX ChangeLog configure Make*[a-z0-9] *.[ch] descrip.mms \ - algorithm.txt zlib.3 msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \ - nt/Makefile.nt nt/zlib.dnt contrib/README.contrib contrib/*.txt \ - contrib/asm386/*.asm contrib/asm386/*.c \ - contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/iostream/*.cpp \ - contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \ - contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 - -all: example.exe minigzip.exe - -test: all - @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ - echo hello world | ./minigzip | ./minigzip -d || \ - echo ' *** minigzip test FAILED ***' ; \ - if ./example; then \ - echo ' *** zlib test OK ***'; \ - else \ - echo ' *** zlib test FAILED ***'; \ - fi - -$(ZLIB): $(OBJS) - $(AR) $@ $(OBJS) - -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 - -$(SHAREDLIB): $(OBJS) os2/z.def - $(LDSHARED) -o $@ $^ - -$(SHAREDLIBIMP): os2/z.def - $(IMPLIB) -o $@ $^ - -example.exe: example.o $(LIBS) - $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) - -minigzip.exe: minigzip.o $(LIBS) - $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) - -clean: - rm -f *.o *~ example minigzip libz.a libz.so* foo.gz - -distclean: clean - -zip: - mv Makefile Makefile~; cp -p Makefile.in Makefile - rm -f test.c ztest*.c - v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ - zip -ul9 zlib$$v $(DISTFILES) - mv Makefile~ Makefile - -dist: - mv Makefile Makefile~; cp -p Makefile.in Makefile - rm -f test.c ztest*.c - d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ - rm -f $$d.tar.gz; \ - if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \ - files=""; \ - for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \ - cd ..; \ - GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \ - if test ! -d $$d; then rm -f $$d; fi - mv Makefile~ Makefile - -tags: - etags *.[ch] - -depend: - makedepend -- $(CFLAGS) -- *.[ch] - -# DO NOT DELETE THIS LINE -- make depend depends on it. - -adler32.o: zlib.h zconf.h -compress.o: zlib.h zconf.h -crc32.o: zlib.h zconf.h -deflate.o: deflate.h zutil.h zlib.h zconf.h -example.o: zlib.h zconf.h -gzio.o: zutil.h zlib.h zconf.h -infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h -infcodes.o: zutil.h zlib.h zconf.h -infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h -inffast.o: zutil.h zlib.h zconf.h inftrees.h -inffast.o: infblock.h infcodes.h infutil.h inffast.h -inflate.o: zutil.h zlib.h zconf.h infblock.h -inftrees.o: zutil.h zlib.h zconf.h inftrees.h -infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h -minigzip.o: zlib.h zconf.h -trees.o: deflate.h zutil.h zlib.h zconf.h trees.h -uncompr.o: zlib.h zconf.h -zutil.o: zutil.h zlib.h zconf.h diff --git a/deps/zlib/old/os2/zlib.def b/deps/zlib/old/os2/zlib.def deleted file mode 100644 index 4c753f1a3b9938..00000000000000 --- a/deps/zlib/old/os2/zlib.def +++ /dev/null @@ -1,51 +0,0 @@ -; -; Slightly modified version of ../nt/zlib.dnt :-) -; - -LIBRARY Z -DESCRIPTION "Zlib compression library for OS/2" -CODE PRELOAD MOVEABLE DISCARDABLE -DATA PRELOAD MOVEABLE MULTIPLE - -EXPORTS - adler32 - compress - crc32 - deflate - deflateCopy - deflateEnd - deflateInit2_ - deflateInit_ - deflateParams - deflateReset - deflateSetDictionary - gzclose - gzdopen - gzerror - gzflush - gzopen - gzread - gzwrite - inflate - inflateEnd - inflateInit2_ - inflateInit_ - inflateReset - inflateSetDictionary - inflateSync - uncompress - zlibVersion - gzprintf - gzputc - gzgetc - gzseek - gzrewind - gztell - gzeof - gzsetparams - zError - inflateSyncPoint - get_crc_table - compress2 - gzputs - gzgets diff --git a/deps/zlib/old/visual-basic.txt b/deps/zlib/old/visual-basic.txt deleted file mode 100644 index 57efe58124eed6..00000000000000 --- a/deps/zlib/old/visual-basic.txt +++ /dev/null @@ -1,160 +0,0 @@ -See below some functions declarations for Visual Basic. - -Frequently Asked Question: - -Q: Each time I use the compress function I get the -5 error (not enough - room in the output buffer). - -A: Make sure that the length of the compressed buffer is passed by - reference ("as any"), not by value ("as long"). Also check that - before the call of compress this length is equal to the total size of - the compressed buffer and not zero. - - -From: "Jon Caruana" -Subject: Re: How to port zlib declares to vb? -Date: Mon, 28 Oct 1996 18:33:03 -0600 - -Got the answer! (I haven't had time to check this but it's what I got, and -looks correct): - -He has the following routines working: - compress - uncompress - gzopen - gzwrite - gzread - gzclose - -Declares follow: (Quoted from Carlos Rios , in Vb4 form) - -#If Win16 Then 'Use Win16 calls. -Declare Function compress Lib "ZLIB.DLL" (ByVal compr As - String, comprLen As Any, ByVal buf As String, ByVal buflen - As Long) As Integer -Declare Function uncompress Lib "ZLIB.DLL" (ByVal uncompr - As String, uncomprLen As Any, ByVal compr As String, ByVal - lcompr As Long) As Integer -Declare Function gzopen Lib "ZLIB.DLL" (ByVal filePath As - String, ByVal mode As String) As Long -Declare Function gzread Lib "ZLIB.DLL" (ByVal file As - Long, ByVal uncompr As String, ByVal uncomprLen As Integer) - As Integer -Declare Function gzwrite Lib "ZLIB.DLL" (ByVal file As - Long, ByVal uncompr As String, ByVal uncomprLen As Integer) - As Integer -Declare Function gzclose Lib "ZLIB.DLL" (ByVal file As - Long) As Integer -#Else -Declare Function compress Lib "ZLIB32.DLL" - (ByVal compr As String, comprLen As Any, ByVal buf As - String, ByVal buflen As Long) As Integer -Declare Function uncompress Lib "ZLIB32.DLL" - (ByVal uncompr As String, uncomprLen As Any, ByVal compr As - String, ByVal lcompr As Long) As Long -Declare Function gzopen Lib "ZLIB32.DLL" - (ByVal file As String, ByVal mode As String) As Long -Declare Function gzread Lib "ZLIB32.DLL" - (ByVal file As Long, ByVal uncompr As String, ByVal - uncomprLen As Long) As Long -Declare Function gzwrite Lib "ZLIB32.DLL" - (ByVal file As Long, ByVal uncompr As String, ByVal - uncomprLen As Long) As Long -Declare Function gzclose Lib "ZLIB32.DLL" - (ByVal file As Long) As Long -#End If - --Jon Caruana -jon-net@usa.net -Microsoft Sitebuilder Network Level 1 Member - HTML Writer's Guild Member - - -Here is another example from Michael that he -says conforms to the VB guidelines, and that solves the problem of not -knowing the uncompressed size by storing it at the end of the file: - -'Calling the functions: -'bracket meaning: [optional] {Range of possible values} -'Call subCompressFile( [, , [level of compression {1..9}]]) -'Call subUncompressFile() - -Option Explicit -Private lngpvtPcnSml As Long 'Stores value for 'lngPercentSmaller' -Private Const SUCCESS As Long = 0 -Private Const strFilExt As String = ".cpr" -Private Declare Function lngfncCpr Lib "zlib.dll" Alias "compress2" (ByRef -dest As Any, ByRef destLen As Any, ByRef src As Any, ByVal srcLen As Long, -ByVal level As Integer) As Long -Private Declare Function lngfncUcp Lib "zlib.dll" Alias "uncompress" (ByRef -dest As Any, ByRef destLen As Any, ByRef src As Any, ByVal srcLen As Long) -As Long - -Public Sub subCompressFile(ByVal strargOriFilPth As String, Optional ByVal -strargCprFilPth As String, Optional ByVal intLvl As Integer = 9) - Dim strCprPth As String - Dim lngOriSiz As Long - Dim lngCprSiz As Long - Dim bytaryOri() As Byte - Dim bytaryCpr() As Byte - lngOriSiz = FileLen(strargOriFilPth) - ReDim bytaryOri(lngOriSiz - 1) - Open strargOriFilPth For Binary Access Read As #1 - Get #1, , bytaryOri() - Close #1 - strCprPth = IIf(strargCprFilPth = "", strargOriFilPth, strargCprFilPth) -'Select file path and name - strCprPth = strCprPth & IIf(Right(strCprPth, Len(strFilExt)) = -strFilExt, "", strFilExt) 'Add file extension if not exists - lngCprSiz = (lngOriSiz * 1.01) + 12 'Compression needs temporary a bit -more space then original file size - ReDim bytaryCpr(lngCprSiz - 1) - If lngfncCpr(bytaryCpr(0), lngCprSiz, bytaryOri(0), lngOriSiz, intLvl) = -SUCCESS Then - lngpvtPcnSml = (1# - (lngCprSiz / lngOriSiz)) * 100 - ReDim Preserve bytaryCpr(lngCprSiz - 1) - Open strCprPth For Binary Access Write As #1 - Put #1, , bytaryCpr() - Put #1, , lngOriSiz 'Add the the original size value to the end -(last 4 bytes) - Close #1 - Else - MsgBox "Compression error" - End If - Erase bytaryCpr - Erase bytaryOri -End Sub - -Public Sub subUncompressFile(ByVal strargFilPth As String) - Dim bytaryCpr() As Byte - Dim bytaryOri() As Byte - Dim lngOriSiz As Long - Dim lngCprSiz As Long - Dim strOriPth As String - lngCprSiz = FileLen(strargFilPth) - ReDim bytaryCpr(lngCprSiz - 1) - Open strargFilPth For Binary Access Read As #1 - Get #1, , bytaryCpr() - Close #1 - 'Read the original file size value: - lngOriSiz = bytaryCpr(lngCprSiz - 1) * (2 ^ 24) _ - + bytaryCpr(lngCprSiz - 2) * (2 ^ 16) _ - + bytaryCpr(lngCprSiz - 3) * (2 ^ 8) _ - + bytaryCpr(lngCprSiz - 4) - ReDim Preserve bytaryCpr(lngCprSiz - 5) 'Cut of the original size value - ReDim bytaryOri(lngOriSiz - 1) - If lngfncUcp(bytaryOri(0), lngOriSiz, bytaryCpr(0), lngCprSiz) = SUCCESS -Then - strOriPth = Left(strargFilPth, Len(strargFilPth) - Len(strFilExt)) - Open strOriPth For Binary Access Write As #1 - Put #1, , bytaryOri() - Close #1 - Else - MsgBox "Uncompression error" - End If - Erase bytaryCpr - Erase bytaryOri -End Sub -Public Property Get lngPercentSmaller() As Long - lngPercentSmaller = lngpvtPcnSml -End Property diff --git a/deps/zlib/os400/README400 b/deps/zlib/os400/README400 deleted file mode 100644 index 4f98334f5ac5f4..00000000000000 --- a/deps/zlib/os400/README400 +++ /dev/null @@ -1,48 +0,0 @@ - ZLIB version 1.2.11 for OS/400 installation instructions - -1) Download and unpack the zlib tarball to some IFS directory. - (i.e.: /path/to/the/zlib/ifs/source/directory) - - If the installed IFS command suppors gzip format, this is straightforward, -else you have to unpack first to some directory on a system supporting it, -then move the whole directory to the IFS via the network (via SMB or FTP). - -2) Edit the configuration parameters in the compilation script. - - EDTF STMF('/path/to/the/zlib/ifs/source/directory/os400/make.sh') - -Tune the parameters according to your needs if not matching the defaults. -Save the file and exit after edition. - -3) Enter qshell, then work in the zlib OS/400 specific directory. - - QSH - cd /path/to/the/zlib/ifs/source/directory/os400 - -4) Compile and install - - sh make.sh - -The script will: -- create the libraries, objects and IFS directories for the zlib environment, -- compile all modules, -- create a service program, -- create a static and a dynamic binding directory, -- install header files for C/C++ and for ILE/RPG, both for compilation in - DB2 and IFS environments. - -That's all. - - -Notes: For OS/400 ILE RPG programmers, a /copy member defining the ZLIB - API prototypes for ILE RPG can be found in ZLIB/H(ZLIB.INC). - In the ILE environment, the same definitions are available from - file zlib.inc located in the same IFS include directory as the - C/C++ header files. - Please read comments in this member for more information. - - Remember that most foreign textual data are ASCII coded: this - implementation does not handle conversion from/to ASCII, so - text data code conversions must be done explicitely. - - Mainly for the reason above, always open zipped files in binary mode. diff --git a/deps/zlib/os400/bndsrc b/deps/zlib/os400/bndsrc deleted file mode 100644 index 5e6e0a2f0af3a8..00000000000000 --- a/deps/zlib/os400/bndsrc +++ /dev/null @@ -1,119 +0,0 @@ -STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('ZLIB') - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/* Version 1.1.3 entry points. */ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - EXPORT SYMBOL("adler32") - EXPORT SYMBOL("compress") - EXPORT SYMBOL("compress2") - EXPORT SYMBOL("crc32") - EXPORT SYMBOL("get_crc_table") - EXPORT SYMBOL("deflate") - EXPORT SYMBOL("deflateEnd") - EXPORT SYMBOL("deflateSetDictionary") - EXPORT SYMBOL("deflateCopy") - EXPORT SYMBOL("deflateReset") - EXPORT SYMBOL("deflateParams") - EXPORT SYMBOL("deflatePrime") - EXPORT SYMBOL("deflateInit_") - EXPORT SYMBOL("deflateInit2_") - EXPORT SYMBOL("gzopen") - EXPORT SYMBOL("gzdopen") - EXPORT SYMBOL("gzsetparams") - EXPORT SYMBOL("gzread") - EXPORT SYMBOL("gzwrite") - EXPORT SYMBOL("gzprintf") - EXPORT SYMBOL("gzputs") - EXPORT SYMBOL("gzgets") - EXPORT SYMBOL("gzputc") - EXPORT SYMBOL("gzgetc") - EXPORT SYMBOL("gzflush") - EXPORT SYMBOL("gzseek") - EXPORT SYMBOL("gzrewind") - EXPORT SYMBOL("gztell") - EXPORT SYMBOL("gzeof") - EXPORT SYMBOL("gzclose") - EXPORT SYMBOL("gzerror") - EXPORT SYMBOL("inflate") - EXPORT SYMBOL("inflateEnd") - EXPORT SYMBOL("inflateSetDictionary") - EXPORT SYMBOL("inflateSync") - EXPORT SYMBOL("inflateReset") - EXPORT SYMBOL("inflateInit_") - EXPORT SYMBOL("inflateInit2_") - EXPORT SYMBOL("inflateSyncPoint") - EXPORT SYMBOL("uncompress") - EXPORT SYMBOL("zlibVersion") - EXPORT SYMBOL("zError") - EXPORT SYMBOL("z_errmsg") - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/* Version 1.2.1 additional entry points. */ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - EXPORT SYMBOL("compressBound") - EXPORT SYMBOL("deflateBound") - EXPORT SYMBOL("deflatePending") - EXPORT SYMBOL("gzungetc") - EXPORT SYMBOL("gzclearerr") - EXPORT SYMBOL("inflateBack") - EXPORT SYMBOL("inflateBackEnd") - EXPORT SYMBOL("inflateBackInit_") - EXPORT SYMBOL("inflateCopy") - EXPORT SYMBOL("zlibCompileFlags") - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/* Version 1.2.4 additional entry points. */ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - EXPORT SYMBOL("adler32_combine") - EXPORT SYMBOL("adler32_combine64") - EXPORT SYMBOL("crc32_combine") - EXPORT SYMBOL("crc32_combine64") - EXPORT SYMBOL("deflateSetHeader") - EXPORT SYMBOL("deflateTune") - EXPORT SYMBOL("gzbuffer") - EXPORT SYMBOL("gzclose_r") - EXPORT SYMBOL("gzclose_w") - EXPORT SYMBOL("gzdirect") - EXPORT SYMBOL("gzoffset") - EXPORT SYMBOL("gzoffset64") - EXPORT SYMBOL("gzopen64") - EXPORT SYMBOL("gzseek64") - EXPORT SYMBOL("gztell64") - EXPORT SYMBOL("inflateGetHeader") - EXPORT SYMBOL("inflateMark") - EXPORT SYMBOL("inflatePrime") - EXPORT SYMBOL("inflateReset2") - EXPORT SYMBOL("inflateUndermine") - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/* Version 1.2.6 additional entry points. */ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - EXPORT SYMBOL("deflateResetKeep") - EXPORT SYMBOL("gzgetc_") - EXPORT SYMBOL("inflateResetKeep") - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/* Version 1.2.8 additional entry points. */ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - EXPORT SYMBOL("gzvprintf") - EXPORT SYMBOL("inflateGetDictionary") - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/* Version 1.2.9 additional entry points. */ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - EXPORT SYMBOL("adler32_z") - EXPORT SYMBOL("crc32_z") - EXPORT SYMBOL("deflateGetDictionary") - EXPORT SYMBOL("gzfread") - EXPORT SYMBOL("gzfwrite") - EXPORT SYMBOL("inflateCodesUsed") - EXPORT SYMBOL("inflateValidate") - EXPORT SYMBOL("uncompress2") - -ENDPGMEXP diff --git a/deps/zlib/os400/make.sh b/deps/zlib/os400/make.sh deleted file mode 100644 index 19eec117a678ce..00000000000000 --- a/deps/zlib/os400/make.sh +++ /dev/null @@ -1,366 +0,0 @@ -#!/bin/sh -# -# ZLIB compilation script for the OS/400. -# -# -# This is a shell script since make is not a standard component of OS/400. - - -################################################################################ -# -# Tunable configuration parameters. -# -################################################################################ - -TARGETLIB='ZLIB' # Target OS/400 program library -STATBNDDIR='ZLIB_A' # Static binding directory. -DYNBNDDIR='ZLIB' # Dynamic binding directory. -SRVPGM="ZLIB" # Service program. -IFSDIR='/zlib' # IFS support base directory. -TGTCCSID='500' # Target CCSID of objects -DEBUG='*NONE' # Debug level -OPTIMIZE='40' # Optimisation level -OUTPUT='*NONE' # Compilation output option. -TGTRLS='V6R1M0' # Target OS release - -export TARGETLIB STATBNDDIR DYNBNDDIR SRVPGM IFSDIR -export TGTCCSID DEBUG OPTIMIZE OUTPUT TGTRLS - - -################################################################################ -# -# OS/400 specific definitions. -# -################################################################################ - -LIBIFSNAME="/QSYS.LIB/${TARGETLIB}.LIB" - - -################################################################################ -# -# Procedures. -# -################################################################################ - -# action_needed dest [src] -# -# dest is an object to build -# if specified, src is an object on which dest depends. -# -# exit 0 (succeeds) if some action has to be taken, else 1. - -action_needed() - -{ - [ ! -e "${1}" ] && return 0 - [ "${2}" ] || return 1 - [ "${1}" -ot "${2}" ] && return 0 - return 1 -} - - -# make_module module_name source_name [additional_definitions] -# -# Compile source name into module if needed. -# As side effect, append the module name to variable MODULES. -# Set LINK to "YES" if the module has been compiled. - -make_module() - -{ - MODULES="${MODULES} ${1}" - MODIFSNAME="${LIBIFSNAME}/${1}.MODULE" - CSRC="`basename \"${2}\"`" - - if action_needed "${MODIFSNAME}" "${2}" - then : - elif [ ! "`sed -e \"//,/<\\\\/source>/!d\" \ - -e '/ tmphdrfile - - # Need to translate to target CCSID. - - CMD="CPY OBJ('`pwd`/tmphdrfile') TOOBJ('${DEST}')" - CMD="${CMD} TOCCSID(${TGTCCSID}) DTAFMT(*TEXT) REPLACE(*YES)" - system "${CMD}" - # touch -r "${HFILE}" "${DEST}" - rm -f tmphdrfile - fi - - IFSFILE="${IFSDIR}/include/`basename \"${HFILE}\"`" - - if action_needed "${IFSFILE}" "${DEST}" - then rm -f "${IFSFILE}" - ln -s "${DEST}" "${IFSFILE}" - fi -done - - -# Install the ILE/RPG header file. - - -HFILE="${SCRIPTDIR}/zlib.inc" -DEST="${SRCPF}/ZLIB.INC.MBR" - -if action_needed "${DEST}" "${HFILE}" -then CMD="CPY OBJ('${HFILE}') TOOBJ('${DEST}')" - CMD="${CMD} TOCCSID(${TGTCCSID}) DTAFMT(*TEXT) REPLACE(*YES)" - system "${CMD}" - # touch -r "${HFILE}" "${DEST}" -fi - -IFSFILE="${IFSDIR}/include/`basename \"${HFILE}\"`" - -if action_needed "${IFSFILE}" "${DEST}" -then rm -f "${IFSFILE}" - ln -s "${DEST}" "${IFSFILE}" -fi - - -# Create and compile the identification source file. - -echo '#pragma comment(user, "ZLIB version '"${VERSION}"'")' > os400.c -echo '#pragma comment(user, __DATE__)' >> os400.c -echo '#pragma comment(user, __TIME__)' >> os400.c -echo '#pragma comment(copyright, "Copyright (C) 1995-2017 Jean-Loup Gailly, Mark Adler. OS/400 version by P. Monnerat.")' >> os400.c -make_module OS400 os400.c -LINK= # No need to rebuild service program yet. -MODULES= - - -# Get source list. - -CSOURCES=`sed -e '/ + #include +-#include "zlib.h" ++#include "third_party/zlib/zlib.h" + + #if defined(USE_FILE32API) + #define fopen64 fopen +diff --git a/contrib/minizip/iowin32.c b/contrib/minizip/iowin32.c +index 274f39eb1dd2..246ceb91a139 100644 +--- a/contrib/minizip/iowin32.c ++++ b/contrib/minizip/iowin32.c +@@ -26,12 +26,19 @@ + #endif + + ++#ifdef _WIN32_WINNT ++#undef _WIN32_WINNT ++#define _WIN32_WINNT 0x601 ++#endif ++ ++#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 + // see Include/shared/winapifamily.h in the Windows Kit + #if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API))) + #if WINAPI_FAMILY_ONE_PARTITION(WINAPI_FAMILY, WINAPI_PARTITION_APP) + #define IOWIN32_USING_WINRT_API 1 + #endif + #endif ++#endif + + voidpf ZCALLBACK win32_open_file_func OF((voidpf opaque, const char* filename, int mode)); + uLong ZCALLBACK win32_read_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +diff --git a/contrib/minizip/mztools.c b/contrib/minizip/mztools.c +index 96891c2e0b71..8bf9cca32633 100644 +--- a/contrib/minizip/mztools.c ++++ b/contrib/minizip/mztools.c +@@ -8,7 +8,7 @@ + #include + #include + #include +-#include "zlib.h" ++#include "third_party/zlib/zlib.h" + #include "unzip.h" + + #define READ_8(adr) ((unsigned char)*(adr)) +diff --git a/contrib/minizip/mztools.h b/contrib/minizip/mztools.h +index a49a426ec2fc..f295ffeda6af 100644 +--- a/contrib/minizip/mztools.h ++++ b/contrib/minizip/mztools.h +@@ -12,7 +12,7 @@ extern "C" { + #endif + + #ifndef _ZLIB_H +-#include "zlib.h" ++#include "third_party/zlib/zlib.h" + #endif + + #include "unzip.h" +diff --git a/contrib/minizip/unzip.c b/contrib/minizip/unzip.c +index bcfb9416ec35..199b4723fcfc 100644 +--- a/contrib/minizip/unzip.c ++++ b/contrib/minizip/unzip.c +@@ -72,7 +72,7 @@ + #define NOUNCRYPT + #endif + +-#include "zlib.h" ++#include "third_party/zlib/zlib.h" + #include "unzip.h" + + #ifdef STDC +@@ -1705,11 +1705,6 @@ extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + +- if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && +- (!(pfile_in_zip_read_info->raw))) +- pfile_in_zip_read_info->stream.avail_out = +- (uInt)pfile_in_zip_read_info->rest_read_uncompressed; +- + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) +diff --git a/contrib/minizip/unzip.h b/contrib/minizip/unzip.h +index 2104e3915074..3c0143529b91 100644 +--- a/contrib/minizip/unzip.h ++++ b/contrib/minizip/unzip.h +@@ -48,7 +48,7 @@ extern "C" { + #endif + + #ifndef _ZLIB_H +-#include "zlib.h" ++#include "third_party/zlib/zlib.h" + #endif + + #ifndef _ZLIBIOAPI_H +diff --git a/contrib/minizip/zip.c b/contrib/minizip/zip.c +index 44e88a9cb989..65c0c7251843 100644 +--- a/contrib/minizip/zip.c ++++ b/contrib/minizip/zip.c +@@ -26,7 +26,7 @@ + #include + #include + #include +-#include "zlib.h" ++#include "third_party/zlib/zlib.h" + #include "zip.h" + + #ifdef STDC +diff --git a/contrib/minizip/zip.h b/contrib/minizip/zip.h +index 8aaebb623430..8c06c0aa7bb0 100644 +--- a/contrib/minizip/zip.h ++++ b/contrib/minizip/zip.h +@@ -47,7 +47,7 @@ extern "C" { + //#define HAVE_BZIP2 + + #ifndef _ZLIB_H +-#include "zlib.h" ++#include "third_party/zlib/zlib.h" + #endif + + #ifndef _ZLIBIOAPI_H +diff --git a/gzread.c b/gzread.c +index 956b91ea7d9e..832d3ef98c59 100644 +--- a/gzread.c ++++ b/gzread.c +@@ -443,7 +443,11 @@ z_size_t ZEXPORT gzfread(buf, size, nitems, file) + # undef z_gzgetc + #else + # undef gzgetc ++# ifdef Z_CR_PREFIX_SET ++# define gzgetc Cr_z_gzgetc ++# endif + #endif ++ + int ZEXPORT gzgetc(file) + gzFile file; + { +diff --git a/zconf.h b/zconf.h +index 5e1d68a004e9..a7a815f575a7 100644 +--- a/zconf.h ++++ b/zconf.h +@@ -8,6 +8,10 @@ + #ifndef ZCONF_H + #define ZCONF_H + ++/* ++ * This library is also built as a part of AOSP, which does not need to include ++ * chromeconf.h. This config does not want chromeconf.h, so it can set this ++ * macro to opt out. While this works today, there's no guarantee that building ++ * zlib outside of Chromium keeps working in the future. ++ */ ++#if !defined(CHROMIUM_ZLIB_NO_CHROMECONF) ++/* This include does prefixing as below, but with an updated set of names. Also ++ * sets up export macros in component builds. */ ++#include "chromeconf.h" ++#endif ++ + /* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. +@@ -431,7 +434,7 @@ typedef uLong FAR uLongf; + typedef unsigned long z_crc_t; + #endif + +-#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ ++#if !defined(_WIN32) + # define Z_HAVE_UNISTD_H + #endif + +diff --git a/zlib.h b/zlib.h +index f09cdaf1e054..99fd467f6b1a 100644 +--- a/zlib.h ++++ b/zlib.h +@@ -1824,6 +1824,11 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ + # undef z_gzgetc + # define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) ++#elif defined(Z_CR_PREFIX_SET) ++# undef gzgetc ++# define gzgetc(g) \ ++ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) \ ++ : (Cr_z_gzgetc)(g)) + #else + # define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +@@ -1853,11 +1858,29 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ + # define z_adler32_combine z_adler32_combine64 + # define z_crc32_combine z_crc32_combine64 + # else ++# ifdef gzopen ++# undef gzopen ++# endif + # define gzopen gzopen64 ++# ifdef gzseek ++# undef gzseek ++# endif + # define gzseek gzseek64 ++# ifdef gztell ++# undef gztell ++# endif + # define gztell gztell64 ++# ifdef gzoffset ++# undef gzoffset ++# endif + # define gzoffset gzoffset64 ++# ifdef adler32_combine ++# undef adler32_combine ++# endif + # define adler32_combine adler32_combine64 ++# ifdef crc32_combine ++# undef crc32_combine ++# endif + # define crc32_combine crc32_combine64 + # endif + # ifndef Z_LARGE64 +diff --git a/zutil.h b/zutil.h +index b079ea6a80f5..80375b8b6109 100644 +--- a/zutil.h ++++ b/zutil.h +@@ -28,6 +28,21 @@ + # include + # include + #endif ++#ifdef NO_ERRNO_H ++# ifdef _WIN32_WCE ++ /* The Microsoft C Run-Time Library for Windows CE doesn't have ++ * errno. We define it as a global variable to simplify porting. ++ * Its value is always 0 and should not be used. We rename it to ++ * avoid conflict with other libraries that use the same workaround. ++ */ ++# define errno z_errno ++# endif ++ extern int errno; ++#else ++# ifndef _WIN32_WCE ++# include ++# endif ++#endif + + #ifdef Z_SOLO + typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ diff --git a/deps/zlib/patches/0001-simd.patch b/deps/zlib/patches/0001-simd.patch new file mode 100644 index 00000000000000..9434ca0cc4a68c --- /dev/null +++ b/deps/zlib/patches/0001-simd.patch @@ -0,0 +1,1214 @@ +diff --git a/crc32.c b/crc32.c +index 9580440c0e6b..9162429cc7b4 100644 +--- a/crc32.c ++++ b/crc32.c +@@ -28,6 +28,8 @@ + # endif /* !DYNAMIC_CRC_TABLE */ + #endif /* MAKECRCH */ + ++#include "deflate.h" ++#include "x86.h" + #include "zutil.h" /* for STDC and FAR definitions */ + + /* Definitions for doing the crc four data bytes at a time. */ +@@ -440,3 +442,28 @@ uLong ZEXPORT crc32_combine64(crc1, crc2, len2) + { + return crc32_combine_(crc1, crc2, len2); + } ++ ++ZLIB_INTERNAL void crc_reset(deflate_state *const s) ++{ ++ if (x86_cpu_enable_simd) { ++ crc_fold_init(s); ++ return; ++ } ++ s->strm->adler = crc32(0L, Z_NULL, 0); ++} ++ ++ZLIB_INTERNAL void crc_finalize(deflate_state *const s) ++{ ++ if (x86_cpu_enable_simd) ++ s->strm->adler = crc_fold_512to32(s); ++} ++ ++ZLIB_INTERNAL void copy_with_crc(z_streamp strm, Bytef *dst, long size) ++{ ++ if (x86_cpu_enable_simd) { ++ crc_fold_copy(strm->state, dst, strm->next_in, size); ++ return; ++ } ++ zmemcpy(dst, strm->next_in, size); ++ strm->adler = crc32(strm->adler, dst, size); ++} +diff --git a/crc_folding.c b/crc_folding.c +new file mode 100644 +index 000000000000..48d77744aaf4 +--- /dev/null ++++ b/crc_folding.c +@@ -0,0 +1,493 @@ ++/* ++ * Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ ++ * instruction. ++ * ++ * A white paper describing this algorithm can be found at: ++ * http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf ++ * ++ * Copyright (C) 2013 Intel Corporation. All rights reserved. ++ * Authors: ++ * Wajdi Feghali ++ * Jim Guilford ++ * Vinodh Gopal ++ * Erdinc Ozturk ++ * Jim Kukunas ++ * ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++#include "deflate.h" ++ ++#include ++#include ++#include ++#include ++ ++#define CRC_LOAD(s) \ ++ do { \ ++ __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)s->crc0 + 0);\ ++ __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)s->crc0 + 1);\ ++ __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)s->crc0 + 2);\ ++ __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)s->crc0 + 3);\ ++ __m128i xmm_crc_part = _mm_loadu_si128((__m128i *)s->crc0 + 4); ++ ++#define CRC_SAVE(s) \ ++ _mm_storeu_si128((__m128i *)s->crc0 + 0, xmm_crc0);\ ++ _mm_storeu_si128((__m128i *)s->crc0 + 1, xmm_crc1);\ ++ _mm_storeu_si128((__m128i *)s->crc0 + 2, xmm_crc2);\ ++ _mm_storeu_si128((__m128i *)s->crc0 + 3, xmm_crc3);\ ++ _mm_storeu_si128((__m128i *)s->crc0 + 4, xmm_crc_part);\ ++ } while (0); ++ ++ZLIB_INTERNAL void crc_fold_init(deflate_state *const s) ++{ ++ CRC_LOAD(s) ++ ++ xmm_crc0 = _mm_cvtsi32_si128(0x9db42487); ++ xmm_crc1 = _mm_setzero_si128(); ++ xmm_crc2 = _mm_setzero_si128(); ++ xmm_crc3 = _mm_setzero_si128(); ++ ++ CRC_SAVE(s) ++ ++ s->strm->adler = 0; ++} ++ ++local void fold_1(deflate_state *const s, ++ __m128i *xmm_crc0, __m128i *xmm_crc1, ++ __m128i *xmm_crc2, __m128i *xmm_crc3) ++{ ++ const __m128i xmm_fold4 = _mm_set_epi32( ++ 0x00000001, 0x54442bd4, ++ 0x00000001, 0xc6e41596); ++ ++ __m128i x_tmp3; ++ __m128 ps_crc0, ps_crc3, ps_res; ++ ++ x_tmp3 = *xmm_crc3; ++ ++ *xmm_crc3 = *xmm_crc0; ++ *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); ++ *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); ++ ps_crc0 = _mm_castsi128_ps(*xmm_crc0); ++ ps_crc3 = _mm_castsi128_ps(*xmm_crc3); ++ ps_res = _mm_xor_ps(ps_crc0, ps_crc3); ++ ++ *xmm_crc0 = *xmm_crc1; ++ *xmm_crc1 = *xmm_crc2; ++ *xmm_crc2 = x_tmp3; ++ *xmm_crc3 = _mm_castps_si128(ps_res); ++} ++ ++local void fold_2(deflate_state *const s, ++ __m128i *xmm_crc0, __m128i *xmm_crc1, ++ __m128i *xmm_crc2, __m128i *xmm_crc3) ++{ ++ const __m128i xmm_fold4 = _mm_set_epi32( ++ 0x00000001, 0x54442bd4, ++ 0x00000001, 0xc6e41596); ++ ++ __m128i x_tmp3, x_tmp2; ++ __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res31, ps_res20; ++ ++ x_tmp3 = *xmm_crc3; ++ x_tmp2 = *xmm_crc2; ++ ++ *xmm_crc3 = *xmm_crc1; ++ *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); ++ *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); ++ ps_crc3 = _mm_castsi128_ps(*xmm_crc3); ++ ps_crc1 = _mm_castsi128_ps(*xmm_crc1); ++ ps_res31= _mm_xor_ps(ps_crc3, ps_crc1); ++ ++ *xmm_crc2 = *xmm_crc0; ++ *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); ++ *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10); ++ ps_crc0 = _mm_castsi128_ps(*xmm_crc0); ++ ps_crc2 = _mm_castsi128_ps(*xmm_crc2); ++ ps_res20= _mm_xor_ps(ps_crc0, ps_crc2); ++ ++ *xmm_crc0 = x_tmp2; ++ *xmm_crc1 = x_tmp3; ++ *xmm_crc2 = _mm_castps_si128(ps_res20); ++ *xmm_crc3 = _mm_castps_si128(ps_res31); ++} ++ ++local void fold_3(deflate_state *const s, ++ __m128i *xmm_crc0, __m128i *xmm_crc1, ++ __m128i *xmm_crc2, __m128i *xmm_crc3) ++{ ++ const __m128i xmm_fold4 = _mm_set_epi32( ++ 0x00000001, 0x54442bd4, ++ 0x00000001, 0xc6e41596); ++ ++ __m128i x_tmp3; ++ __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res32, ps_res21, ps_res10; ++ ++ x_tmp3 = *xmm_crc3; ++ ++ *xmm_crc3 = *xmm_crc2; ++ *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01); ++ *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); ++ ps_crc2 = _mm_castsi128_ps(*xmm_crc2); ++ ps_crc3 = _mm_castsi128_ps(*xmm_crc3); ++ ps_res32 = _mm_xor_ps(ps_crc2, ps_crc3); ++ ++ *xmm_crc2 = *xmm_crc1; ++ *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); ++ *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10); ++ ps_crc1 = _mm_castsi128_ps(*xmm_crc1); ++ ps_crc2 = _mm_castsi128_ps(*xmm_crc2); ++ ps_res21= _mm_xor_ps(ps_crc1, ps_crc2); ++ ++ *xmm_crc1 = *xmm_crc0; ++ *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); ++ *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x10); ++ ps_crc0 = _mm_castsi128_ps(*xmm_crc0); ++ ps_crc1 = _mm_castsi128_ps(*xmm_crc1); ++ ps_res10= _mm_xor_ps(ps_crc0, ps_crc1); ++ ++ *xmm_crc0 = x_tmp3; ++ *xmm_crc1 = _mm_castps_si128(ps_res10); ++ *xmm_crc2 = _mm_castps_si128(ps_res21); ++ *xmm_crc3 = _mm_castps_si128(ps_res32); ++} ++ ++local void fold_4(deflate_state *const s, ++ __m128i *xmm_crc0, __m128i *xmm_crc1, ++ __m128i *xmm_crc2, __m128i *xmm_crc3) ++{ ++ const __m128i xmm_fold4 = _mm_set_epi32( ++ 0x00000001, 0x54442bd4, ++ 0x00000001, 0xc6e41596); ++ ++ __m128i x_tmp0, x_tmp1, x_tmp2, x_tmp3; ++ __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3; ++ __m128 ps_t0, ps_t1, ps_t2, ps_t3; ++ __m128 ps_res0, ps_res1, ps_res2, ps_res3; ++ ++ x_tmp0 = *xmm_crc0; ++ x_tmp1 = *xmm_crc1; ++ x_tmp2 = *xmm_crc2; ++ x_tmp3 = *xmm_crc3; ++ ++ *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); ++ x_tmp0 = _mm_clmulepi64_si128(x_tmp0, xmm_fold4, 0x10); ++ ps_crc0 = _mm_castsi128_ps(*xmm_crc0); ++ ps_t0 = _mm_castsi128_ps(x_tmp0); ++ ps_res0 = _mm_xor_ps(ps_crc0, ps_t0); ++ ++ *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); ++ x_tmp1 = _mm_clmulepi64_si128(x_tmp1, xmm_fold4, 0x10); ++ ps_crc1 = _mm_castsi128_ps(*xmm_crc1); ++ ps_t1 = _mm_castsi128_ps(x_tmp1); ++ ps_res1 = _mm_xor_ps(ps_crc1, ps_t1); ++ ++ *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01); ++ x_tmp2 = _mm_clmulepi64_si128(x_tmp2, xmm_fold4, 0x10); ++ ps_crc2 = _mm_castsi128_ps(*xmm_crc2); ++ ps_t2 = _mm_castsi128_ps(x_tmp2); ++ ps_res2 = _mm_xor_ps(ps_crc2, ps_t2); ++ ++ *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x01); ++ x_tmp3 = _mm_clmulepi64_si128(x_tmp3, xmm_fold4, 0x10); ++ ps_crc3 = _mm_castsi128_ps(*xmm_crc3); ++ ps_t3 = _mm_castsi128_ps(x_tmp3); ++ ps_res3 = _mm_xor_ps(ps_crc3, ps_t3); ++ ++ *xmm_crc0 = _mm_castps_si128(ps_res0); ++ *xmm_crc1 = _mm_castps_si128(ps_res1); ++ *xmm_crc2 = _mm_castps_si128(ps_res2); ++ *xmm_crc3 = _mm_castps_si128(ps_res3); ++} ++ ++local const unsigned zalign(32) pshufb_shf_table[60] = { ++ 0x84838281,0x88878685,0x8c8b8a89,0x008f8e8d, /* shl 15 (16 - 1)/shr1 */ ++ 0x85848382,0x89888786,0x8d8c8b8a,0x01008f8e, /* shl 14 (16 - 3)/shr2 */ ++ 0x86858483,0x8a898887,0x8e8d8c8b,0x0201008f, /* shl 13 (16 - 4)/shr3 */ ++ 0x87868584,0x8b8a8988,0x8f8e8d8c,0x03020100, /* shl 12 (16 - 4)/shr4 */ ++ 0x88878685,0x8c8b8a89,0x008f8e8d,0x04030201, /* shl 11 (16 - 5)/shr5 */ ++ 0x89888786,0x8d8c8b8a,0x01008f8e,0x05040302, /* shl 10 (16 - 6)/shr6 */ ++ 0x8a898887,0x8e8d8c8b,0x0201008f,0x06050403, /* shl 9 (16 - 7)/shr7 */ ++ 0x8b8a8988,0x8f8e8d8c,0x03020100,0x07060504, /* shl 8 (16 - 8)/shr8 */ ++ 0x8c8b8a89,0x008f8e8d,0x04030201,0x08070605, /* shl 7 (16 - 9)/shr9 */ ++ 0x8d8c8b8a,0x01008f8e,0x05040302,0x09080706, /* shl 6 (16 -10)/shr10*/ ++ 0x8e8d8c8b,0x0201008f,0x06050403,0x0a090807, /* shl 5 (16 -11)/shr11*/ ++ 0x8f8e8d8c,0x03020100,0x07060504,0x0b0a0908, /* shl 4 (16 -12)/shr12*/ ++ 0x008f8e8d,0x04030201,0x08070605,0x0c0b0a09, /* shl 3 (16 -13)/shr13*/ ++ 0x01008f8e,0x05040302,0x09080706,0x0d0c0b0a, /* shl 2 (16 -14)/shr14*/ ++ 0x0201008f,0x06050403,0x0a090807,0x0e0d0c0b /* shl 1 (16 -15)/shr15*/ ++}; ++ ++local void partial_fold(deflate_state *const s, const size_t len, ++ __m128i *xmm_crc0, __m128i *xmm_crc1, ++ __m128i *xmm_crc2, __m128i *xmm_crc3, ++ __m128i *xmm_crc_part) ++{ ++ ++ const __m128i xmm_fold4 = _mm_set_epi32( ++ 0x00000001, 0x54442bd4, ++ 0x00000001, 0xc6e41596); ++ const __m128i xmm_mask3 = _mm_set1_epi32(0x80808080); ++ ++ __m128i xmm_shl, xmm_shr, xmm_tmp1, xmm_tmp2, xmm_tmp3; ++ __m128i xmm_a0_0, xmm_a0_1; ++ __m128 ps_crc3, psa0_0, psa0_1, ps_res; ++ ++ xmm_shl = _mm_load_si128((__m128i *)pshufb_shf_table + (len - 1)); ++ xmm_shr = xmm_shl; ++ xmm_shr = _mm_xor_si128(xmm_shr, xmm_mask3); ++ ++ xmm_a0_0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shl); ++ ++ *xmm_crc0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shr); ++ xmm_tmp1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shl); ++ *xmm_crc0 = _mm_or_si128(*xmm_crc0, xmm_tmp1); ++ ++ *xmm_crc1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shr); ++ xmm_tmp2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shl); ++ *xmm_crc1 = _mm_or_si128(*xmm_crc1, xmm_tmp2); ++ ++ *xmm_crc2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shr); ++ xmm_tmp3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shl); ++ *xmm_crc2 = _mm_or_si128(*xmm_crc2, xmm_tmp3); ++ ++ *xmm_crc3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shr); ++ *xmm_crc_part = _mm_shuffle_epi8(*xmm_crc_part, xmm_shl); ++ *xmm_crc3 = _mm_or_si128(*xmm_crc3, *xmm_crc_part); ++ ++ xmm_a0_1 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x10); ++ xmm_a0_0 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x01); ++ ++ ps_crc3 = _mm_castsi128_ps(*xmm_crc3); ++ psa0_0 = _mm_castsi128_ps(xmm_a0_0); ++ psa0_1 = _mm_castsi128_ps(xmm_a0_1); ++ ++ ps_res = _mm_xor_ps(ps_crc3, psa0_0); ++ ps_res = _mm_xor_ps(ps_res, psa0_1); ++ ++ *xmm_crc3 = _mm_castps_si128(ps_res); ++} ++ ++ZLIB_INTERNAL void crc_fold_copy(deflate_state *const s, ++ unsigned char *dst, const unsigned char *src, long len) ++{ ++ unsigned long algn_diff; ++ __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; ++ ++ CRC_LOAD(s) ++ ++ if (len < 16) { ++ if (len == 0) ++ return; ++ goto partial; ++ } ++ ++ algn_diff = 0 - (uintptr_t)src & 0xF; ++ if (algn_diff) { ++ xmm_crc_part = _mm_loadu_si128((__m128i *)src); ++ _mm_storeu_si128((__m128i *)dst, xmm_crc_part); ++ ++ dst += algn_diff; ++ src += algn_diff; ++ len -= algn_diff; ++ ++ partial_fold(s, algn_diff, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, ++ &xmm_crc_part); ++ } ++ ++ while ((len -= 64) >= 0) { ++ xmm_t0 = _mm_load_si128((__m128i *)src); ++ xmm_t1 = _mm_load_si128((__m128i *)src + 1); ++ xmm_t2 = _mm_load_si128((__m128i *)src + 2); ++ xmm_t3 = _mm_load_si128((__m128i *)src + 3); ++ ++ fold_4(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); ++ ++ _mm_storeu_si128((__m128i *)dst, xmm_t0); ++ _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); ++ _mm_storeu_si128((__m128i *)dst + 2, xmm_t2); ++ _mm_storeu_si128((__m128i *)dst + 3, xmm_t3); ++ ++ xmm_crc0 = _mm_xor_si128(xmm_crc0, xmm_t0); ++ xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t1); ++ xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t2); ++ xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t3); ++ ++ src += 64; ++ dst += 64; ++ } ++ ++ /* ++ * len = num bytes left - 64 ++ */ ++ if (len + 16 >= 0) { ++ len += 16; ++ ++ xmm_t0 = _mm_load_si128((__m128i *)src); ++ xmm_t1 = _mm_load_si128((__m128i *)src + 1); ++ xmm_t2 = _mm_load_si128((__m128i *)src + 2); ++ ++ fold_3(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); ++ ++ _mm_storeu_si128((__m128i *)dst, xmm_t0); ++ _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); ++ _mm_storeu_si128((__m128i *)dst + 2, xmm_t2); ++ ++ xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t0); ++ xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t1); ++ xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t2); ++ ++ if (len == 0) ++ goto done; ++ ++ dst += 48; ++ src += 48; ++ } else if (len + 32 >= 0) { ++ len += 32; ++ ++ xmm_t0 = _mm_load_si128((__m128i *)src); ++ xmm_t1 = _mm_load_si128((__m128i *)src + 1); ++ ++ fold_2(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); ++ ++ _mm_storeu_si128((__m128i *)dst, xmm_t0); ++ _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); ++ ++ xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t0); ++ xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t1); ++ ++ if (len == 0) ++ goto done; ++ ++ dst += 32; ++ src += 32; ++ } else if (len + 48 >= 0) { ++ len += 48; ++ ++ xmm_t0 = _mm_load_si128((__m128i *)src); ++ ++ fold_1(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); ++ ++ _mm_storeu_si128((__m128i *)dst, xmm_t0); ++ ++ xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0); ++ ++ if (len == 0) ++ goto done; ++ ++ dst += 16; ++ src += 16; ++ } else { ++ len += 64; ++ if (len == 0) ++ goto done; ++ } ++ ++partial: ++ ++#if defined(_MSC_VER) ++ /* VS does not permit the use of _mm_set_epi64x in 32-bit builds */ ++ { ++ int32_t parts[4] = {0, 0, 0, 0}; ++ memcpy(&parts, src, len); ++ xmm_crc_part = _mm_set_epi32(parts[3], parts[2], parts[1], parts[0]); ++ } ++#else ++ { ++ int64_t parts[2] = {0, 0}; ++ memcpy(&parts, src, len); ++ xmm_crc_part = _mm_set_epi64x(parts[1], parts[0]); ++ } ++#endif ++ ++ _mm_storeu_si128((__m128i *)dst, xmm_crc_part); ++ partial_fold(s, len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, ++ &xmm_crc_part); ++done: ++ CRC_SAVE(s) ++} ++ ++local const unsigned zalign(16) crc_k[] = { ++ 0xccaa009e, 0x00000000, /* rk1 */ ++ 0x751997d0, 0x00000001, /* rk2 */ ++ 0xccaa009e, 0x00000000, /* rk5 */ ++ 0x63cd6124, 0x00000001, /* rk6 */ ++ 0xf7011640, 0x00000001, /* rk7 */ ++ 0xdb710640, 0x00000001 /* rk8 */ ++}; ++ ++local const unsigned zalign(16) crc_mask[4] = { ++ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000 ++}; ++ ++local const unsigned zalign(16) crc_mask2[4] = { ++ 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF ++}; ++ ++unsigned ZLIB_INTERNAL crc_fold_512to32(deflate_state *const s) ++{ ++ const __m128i xmm_mask = _mm_load_si128((__m128i *)crc_mask); ++ const __m128i xmm_mask2 = _mm_load_si128((__m128i *)crc_mask2); ++ ++ unsigned crc; ++ __m128i x_tmp0, x_tmp1, x_tmp2, crc_fold; ++ ++ CRC_LOAD(s) ++ ++ /* ++ * k1 ++ */ ++ crc_fold = _mm_load_si128((__m128i *)crc_k); ++ ++ x_tmp0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x10); ++ xmm_crc0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x01); ++ xmm_crc1 = _mm_xor_si128(xmm_crc1, x_tmp0); ++ xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_crc0); ++ ++ x_tmp1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x10); ++ xmm_crc1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x01); ++ xmm_crc2 = _mm_xor_si128(xmm_crc2, x_tmp1); ++ xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_crc1); ++ ++ x_tmp2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x10); ++ xmm_crc2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x01); ++ xmm_crc3 = _mm_xor_si128(xmm_crc3, x_tmp2); ++ xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); ++ ++ /* ++ * k5 ++ */ ++ crc_fold = _mm_load_si128((__m128i *)crc_k + 1); ++ ++ xmm_crc0 = xmm_crc3; ++ xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0); ++ xmm_crc0 = _mm_srli_si128(xmm_crc0, 8); ++ xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0); ++ ++ xmm_crc0 = xmm_crc3; ++ xmm_crc3 = _mm_slli_si128(xmm_crc3, 4); ++ xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10); ++ xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0); ++ xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask2); ++ ++ /* ++ * k7 ++ */ ++ xmm_crc1 = xmm_crc3; ++ xmm_crc2 = xmm_crc3; ++ crc_fold = _mm_load_si128((__m128i *)crc_k + 2); ++ ++ xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0); ++ xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); ++ xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask); ++ ++ xmm_crc2 = xmm_crc3; ++ xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10); ++ xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); ++ xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc1); ++ ++ crc = _mm_extract_epi32(xmm_crc3, 2); ++ return ~crc; ++ CRC_SAVE(s) ++} +diff --git a/deflate.c b/deflate.c +index 1ec761448de9..aa0c9c67a6dc 100644 +--- a/deflate.c ++++ b/deflate.c +@@ -48,8 +48,9 @@ + */ + + /* @(#) $Id$ */ +- ++#include + #include "deflate.h" ++#include "x86.h" + + const char deflate_copyright[] = + " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler "; +@@ -86,7 +87,7 @@ local block_state deflate_huff OF((deflate_state *s, int flush)); + local void lm_init OF((deflate_state *s)); + local void putShortMSB OF((deflate_state *s, uInt b)); + local void flush_pending OF((z_streamp strm)); +-local unsigned read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); ++unsigned ZLIB_INTERNAL deflate_read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); + #ifdef ASMV + # pragma message("Assembler code may have bugs -- use at your own risk") + void match_init OF((void)); /* asm code initialization */ +@@ -100,6 +101,20 @@ local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); + #endif + ++/* From crc32.c */ ++extern void ZLIB_INTERNAL crc_reset(deflate_state *const s); ++extern void ZLIB_INTERNAL crc_finalize(deflate_state *const s); ++extern void ZLIB_INTERNAL copy_with_crc(z_streamp strm, Bytef *dst, long size); ++ ++#ifdef _MSC_VER ++#define INLINE __inline ++#else ++#define INLINE inline ++#endif ++ ++/* Inline optimisation */ ++local INLINE Pos insert_string_sse(deflate_state *const s, const Pos str); ++ + /* =========================================================================== + * Local data + */ +@@ -162,7 +177,6 @@ local const config configuration_table[10] = { + */ + #define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + +- + /* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return +@@ -173,17 +187,28 @@ local const config configuration_table[10] = { + * characters and the first MIN_MATCH bytes of str are valid (except for + * the last MIN_MATCH-1 bytes of the input file). + */ ++local INLINE Pos insert_string_c(deflate_state *const s, const Pos str) ++{ ++ Pos ret; ++ ++ UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]); + #ifdef FASTEST +-#define INSERT_STRING(s, str, match_head) \ +- (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ +- match_head = s->head[s->ins_h], \ +- s->head[s->ins_h] = (Pos)(str)) ++ ret = s->head[s->ins_h]; + #else +-#define INSERT_STRING(s, str, match_head) \ +- (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ +- match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ +- s->head[s->ins_h] = (Pos)(str)) ++ ret = s->prev[str & s->w_mask] = s->head[s->ins_h]; + #endif ++ s->head[s->ins_h] = str; ++ ++ return ret; ++} ++ ++local INLINE Pos insert_string(deflate_state *const s, const Pos str) ++{ ++ if (x86_cpu_enable_simd) ++ return insert_string_sse(s, str); ++ return insert_string_c(s, str); ++} ++ + + /* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). +@@ -248,6 +273,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + const char *version; + int stream_size; + { ++ unsigned window_padding = 8; + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; +@@ -257,6 +283,8 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + * output size for (length,distance) codes is <= 24 bits. + */ + ++ x86_check_features(); ++ + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; +@@ -313,12 +341,19 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + +- s->hash_bits = (uInt)memLevel + 7; ++ if (x86_cpu_enable_simd) { ++ s->hash_bits = 15; ++ } else { ++ s->hash_bits = memLevel + 7; ++ } ++ + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + +- s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); ++ s->window = (Bytef *) ZALLOC(strm, ++ s->w_size + window_padding, ++ 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + +@@ -418,11 +453,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + str = s->strstart; + n = s->lookahead - (MIN_MATCH-1); + do { +- UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +-#ifndef FASTEST +- s->prev[str & s->w_mask] = s->head[s->ins_h]; +-#endif +- s->head[s->ins_h] = (Pos)str; ++ insert_string(s, str); + str++; + } while (--n); + s->strstart = str; +@@ -848,7 +879,7 @@ int ZEXPORT deflate (strm, flush) + #ifdef GZIP + if (s->status == GZIP_STATE) { + /* gzip header */ +- strm->adler = crc32(0L, Z_NULL, 0); ++ crc_reset(s); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); +@@ -1049,6 +1080,7 @@ int ZEXPORT deflate (strm, flush) + /* Write the trailer */ + #ifdef GZIP + if (s->wrap == 2) { ++ crc_finalize(s); + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); +@@ -1161,7 +1193,7 @@ int ZEXPORT deflateCopy (dest, source) + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +-local unsigned read_buf(strm, buf, size) ++ZLIB_INTERNAL unsigned deflate_read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +@@ -1173,15 +1205,16 @@ local unsigned read_buf(strm, buf, size) + + strm->avail_in -= len; + +- zmemcpy(buf, strm->next_in, len); +- if (strm->state->wrap == 1) { +- strm->adler = adler32(strm->adler, buf, len); +- } + #ifdef GZIP +- else if (strm->state->wrap == 2) { +- strm->adler = crc32(strm->adler, buf, len); +- } ++ if (strm->state->wrap == 2) ++ copy_with_crc(strm, buf, len); ++ else + #endif ++ { ++ zmemcpy(buf, strm->next_in, len); ++ if (strm->state->wrap == 1) ++ strm->adler = adler32(strm->adler, buf, len); ++ } + strm->next_in += len; + strm->total_in += len; + +@@ -1479,7 +1512,19 @@ local void check_match(s, start, match, length) + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +-local void fill_window(s) ++local void fill_window_c(deflate_state *s); ++ ++local void fill_window(deflate_state *s) ++{ ++ if (x86_cpu_enable_simd) { ++ fill_window_sse(s); ++ return; ++ } ++ ++ fill_window_c(s); ++} ++ ++local void fill_window_c(s) + deflate_state *s; + { + unsigned n; +@@ -1847,7 +1892,7 @@ local block_state deflate_fast(s, flush) + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { +- INSERT_STRING(s, s->strstart, hash_head); ++ hash_head = insert_string(s, s->strstart); + } + + /* Find the longest match, discarding those <= prev_length. +@@ -1878,7 +1923,7 @@ local block_state deflate_fast(s, flush) + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; +- INSERT_STRING(s, s->strstart, hash_head); ++ hash_head = insert_string(s, s->strstart); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ +@@ -1950,7 +1995,7 @@ local block_state deflate_slow(s, flush) + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { +- INSERT_STRING(s, s->strstart, hash_head); ++ hash_head = insert_string(s, s->strstart); + } + + /* Find the longest match, discarding those <= prev_length. +@@ -2001,7 +2046,7 @@ local block_state deflate_slow(s, flush) + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { +- INSERT_STRING(s, s->strstart, hash_head); ++ hash_head = insert_string(s, s->strstart); + } + } while (--s->prev_length != 0); + s->match_available = 0; +@@ -2161,3 +2206,37 @@ local block_state deflate_huff(s, flush) + FLUSH_BLOCK(s, 0); + return block_done; + } ++ ++/* Safe to inline this as GCC/clang will use inline asm and Visual Studio will ++ * use intrinsic without extra params ++ */ ++local INLINE Pos insert_string_sse(deflate_state *const s, const Pos str) ++{ ++ Pos ret; ++ unsigned *ip, val, h = 0; ++ ++ ip = (unsigned *)&s->window[str]; ++ val = *ip; ++ ++ if (s->level >= 6) ++ val &= 0xFFFFFF; ++ ++/* Windows clang should use inline asm */ ++#if defined(_MSC_VER) && !defined(__clang__) ++ h = _mm_crc32_u32(h, val); ++#elif defined(__i386__) || defined(__amd64__) ++ __asm__ __volatile__ ( ++ "crc32 %1,%0\n\t" ++ : "+r" (h) ++ : "r" (val) ++ ); ++#else ++ /* This should never happen */ ++ assert(0); ++#endif ++ ++ ret = s->head[h & s->hash_mask]; ++ s->head[h & s->hash_mask] = str; ++ s->prev[str & s->w_mask] = ret; ++ return ret; ++} +diff --git a/deflate.h b/deflate.h +index 23ecdd312bc0..ab56df7663b6 100644 +--- a/deflate.h ++++ b/deflate.h +@@ -109,7 +109,7 @@ typedef struct internal_state { + ulg gzindex; /* where in extra, name, or comment */ + Byte method; /* can only be DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ +- ++ unsigned zalign(16) crc0[4 * 5]; + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ +@@ -346,4 +346,14 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, + flush = _tr_tally(s, distance, length) + #endif + ++/* Functions that are SIMD optimised on x86 */ ++void ZLIB_INTERNAL crc_fold_init(deflate_state* const s); ++void ZLIB_INTERNAL crc_fold_copy(deflate_state* const s, ++ unsigned char* dst, ++ const unsigned char* src, ++ long len); ++unsigned ZLIB_INTERNAL crc_fold_512to32(deflate_state* const s); ++ ++void ZLIB_INTERNAL fill_window_sse(deflate_state* s); ++ + #endif /* DEFLATE_H */ +diff --git a/fill_window_sse.c b/fill_window_sse.c +new file mode 100644 +index 000000000000..949ccce1ba9c +--- /dev/null ++++ b/fill_window_sse.c +@@ -0,0 +1,177 @@ ++/* ++ * Fill Window with SSE2-optimized hash shifting ++ * ++ * Copyright (C) 2013 Intel Corporation ++ * Authors: ++ * Arjan van de Ven ++ * Jim Kukunas ++ * ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++#include ++#include "deflate.h" ++ ++#define UPDATE_HASH(s,h,i) \ ++ {\ ++ if (s->level < 6) { \ ++ h = (3483 * (s->window[i]) +\ ++ 23081* (s->window[i+1]) +\ ++ 6954 * (s->window[i+2]) +\ ++ 20947* (s->window[i+3])) & s->hash_mask;\ ++ } else {\ ++ h = (25881* (s->window[i]) +\ ++ 24674* (s->window[i+1]) +\ ++ 25811* (s->window[i+2])) & s->hash_mask;\ ++ }\ ++ }\ ++ ++extern int deflate_read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); ++ ++void fill_window_sse(deflate_state *s) ++{ ++ const __m128i xmm_wsize = _mm_set1_epi16(s->w_size); ++ ++ register unsigned n; ++ register Posf *p; ++ unsigned more; /* Amount of free space at the end of the window. */ ++ uInt wsize = s->w_size; ++ ++ Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); ++ ++ do { ++ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); ++ ++ /* Deal with !@#$% 64K limit: */ ++ if (sizeof(int) <= 2) { ++ if (more == 0 && s->strstart == 0 && s->lookahead == 0) { ++ more = wsize; ++ ++ } else if (more == (unsigned)(-1)) { ++ /* Very unlikely, but possible on 16 bit machine if ++ * strstart == 0 && lookahead == 1 (input done a byte at time) ++ */ ++ more--; ++ } ++ } ++ ++ /* If the window is almost full and there is insufficient lookahead, ++ * move the upper half to the lower one to make room in the upper half. ++ */ ++ if (s->strstart >= wsize+MAX_DIST(s)) { ++ ++ zmemcpy(s->window, s->window+wsize, (unsigned)wsize); ++ s->match_start -= wsize; ++ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ ++ s->block_start -= (long) wsize; ++ ++ /* Slide the hash table (could be avoided with 32 bit values ++ at the expense of memory usage). We slide even when level == 0 ++ to keep the hash table consistent if we switch back to level > 0 ++ later. (Using level 0 permanently is not an optimal usage of ++ zlib, so we don't care about this pathological case.) ++ */ ++ n = s->hash_size; ++ p = &s->head[n]; ++ p -= 8; ++ do { ++ __m128i value, result; ++ ++ value = _mm_loadu_si128((__m128i *)p); ++ result = _mm_subs_epu16(value, xmm_wsize); ++ _mm_storeu_si128((__m128i *)p, result); ++ ++ p -= 8; ++ n -= 8; ++ } while (n > 0); ++ ++ n = wsize; ++#ifndef FASTEST ++ p = &s->prev[n]; ++ p -= 8; ++ do { ++ __m128i value, result; ++ ++ value = _mm_loadu_si128((__m128i *)p); ++ result = _mm_subs_epu16(value, xmm_wsize); ++ _mm_storeu_si128((__m128i *)p, result); ++ ++ p -= 8; ++ n -= 8; ++ } while (n > 0); ++#endif ++ more += wsize; ++ } ++ if (s->strm->avail_in == 0) break; ++ ++ /* If there was no sliding: ++ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && ++ * more == window_size - lookahead - strstart ++ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) ++ * => more >= window_size - 2*WSIZE + 2 ++ * In the BIG_MEM or MMAP case (not yet supported), ++ * window_size == input_size + MIN_LOOKAHEAD && ++ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. ++ * Otherwise, window_size == 2*WSIZE so more >= 2. ++ * If there was sliding, more >= WSIZE. So in all cases, more >= 2. ++ */ ++ Assert(more >= 2, "more < 2"); ++ ++ n = deflate_read_buf(s->strm, ++ s->window + s->strstart + s->lookahead, ++ more); ++ s->lookahead += n; ++ ++ /* Initialize the hash value now that we have some input: */ ++ if (s->lookahead >= MIN_MATCH) { ++ uInt str = s->strstart; ++ s->ins_h = s->window[str]; ++ if (str >= 1) ++ UPDATE_HASH(s, s->ins_h, str + 1 - (MIN_MATCH-1)); ++#if MIN_MATCH != 3 ++ Call UPDATE_HASH() MIN_MATCH-3 more times ++#endif ++ } ++ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, ++ * but this is not important since only literal bytes will be emitted. ++ */ ++ ++ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); ++ ++ /* If the WIN_INIT bytes after the end of the current data have never been ++ * written, then zero those bytes in order to avoid memory check reports of ++ * the use of uninitialized (or uninitialised as Julian writes) bytes by ++ * the longest match routines. Update the high water mark for the next ++ * time through here. WIN_INIT is set to MAX_MATCH since the longest match ++ * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. ++ */ ++ if (s->high_water < s->window_size) { ++ ulg curr = s->strstart + (ulg)(s->lookahead); ++ ulg init; ++ ++ if (s->high_water < curr) { ++ /* Previous high water mark below current data -- zero WIN_INIT ++ * bytes or up to end of window, whichever is less. ++ */ ++ init = s->window_size - curr; ++ if (init > WIN_INIT) ++ init = WIN_INIT; ++ zmemzero(s->window + curr, (unsigned)init); ++ s->high_water = curr + init; ++ } ++ else if (s->high_water < (ulg)curr + WIN_INIT) { ++ /* High water mark at or above current data, but below current data ++ * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up ++ * to end of window, whichever is less. ++ */ ++ init = (ulg)curr + WIN_INIT - s->high_water; ++ if (init > s->window_size - s->high_water) ++ init = s->window_size - s->high_water; ++ zmemzero(s->window + s->high_water, (unsigned)init); ++ s->high_water += init; ++ } ++ } ++ ++ Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, ++ "not enough room for search"); ++} +diff --git a/simd_stub.c b/simd_stub.c +new file mode 100644 +index 000000000000..c6d46051498f +--- /dev/null ++++ b/simd_stub.c +@@ -0,0 +1,35 @@ ++/* simd_stub.c -- stub implementations ++* Copyright (C) 2014 Intel Corporation ++* For conditions of distribution and use, see copyright notice in zlib.h ++*/ ++#include ++ ++#include "deflate.h" ++#include "x86.h" ++ ++int ZLIB_INTERNAL x86_cpu_enable_simd = 0; ++ ++void ZLIB_INTERNAL crc_fold_init(deflate_state *const s) { ++ assert(0); ++} ++ ++void ZLIB_INTERNAL crc_fold_copy(deflate_state *const s, ++ unsigned char *dst, ++ const unsigned char *src, ++ long len) { ++ assert(0); ++} ++ ++unsigned ZLIB_INTERNAL crc_fold_512to32(deflate_state *const s) { ++ assert(0); ++ return 0; ++} ++ ++void ZLIB_INTERNAL fill_window_sse(deflate_state *s) ++{ ++ assert(0); ++} ++ ++void x86_check_features(void) ++{ ++} +diff --git a/x86.c b/x86.c +new file mode 100644 +index 000000000000..e56fe8b85a39 +--- /dev/null ++++ b/x86.c +@@ -0,0 +1,92 @@ ++/* ++ * x86 feature check ++ * ++ * Copyright (C) 2013 Intel Corporation. All rights reserved. ++ * Author: ++ * Jim Kukunas ++ * ++ * For conditions of distribution and use, see copyright notice in zlib.h ++ */ ++ ++#include "x86.h" ++#include "zutil.h" ++ ++int ZLIB_INTERNAL x86_cpu_enable_simd = 0; ++ ++#ifndef _MSC_VER ++#include ++ ++pthread_once_t cpu_check_inited_once = PTHREAD_ONCE_INIT; ++static void _x86_check_features(void); ++ ++void x86_check_features(void) ++{ ++ pthread_once(&cpu_check_inited_once, _x86_check_features); ++} ++ ++static void _x86_check_features(void) ++{ ++ int x86_cpu_has_sse2; ++ int x86_cpu_has_sse42; ++ int x86_cpu_has_pclmulqdq; ++ unsigned eax, ebx, ecx, edx; ++ ++ eax = 1; ++#ifdef __i386__ ++ __asm__ __volatile__ ( ++ "xchg %%ebx, %1\n\t" ++ "cpuid\n\t" ++ "xchg %1, %%ebx\n\t" ++ : "+a" (eax), "=S" (ebx), "=c" (ecx), "=d" (edx) ++ ); ++#else ++ __asm__ __volatile__ ( ++ "cpuid\n\t" ++ : "+a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) ++ ); ++#endif /* (__i386__) */ ++ ++ x86_cpu_has_sse2 = edx & 0x4000000; ++ x86_cpu_has_sse42 = ecx & 0x100000; ++ x86_cpu_has_pclmulqdq = ecx & 0x2; ++ ++ x86_cpu_enable_simd = x86_cpu_has_sse2 && ++ x86_cpu_has_sse42 && ++ x86_cpu_has_pclmulqdq; ++} ++#else ++#include ++#include ++ ++static BOOL CALLBACK _x86_check_features(PINIT_ONCE once, ++ PVOID param, ++ PVOID *context); ++static INIT_ONCE cpu_check_inited_once = INIT_ONCE_STATIC_INIT; ++ ++void x86_check_features(void) ++{ ++ InitOnceExecuteOnce(&cpu_check_inited_once, _x86_check_features, ++ NULL, NULL); ++} ++ ++static BOOL CALLBACK _x86_check_features(PINIT_ONCE once, ++ PVOID param, ++ PVOID *context) ++{ ++ int x86_cpu_has_sse2; ++ int x86_cpu_has_sse42; ++ int x86_cpu_has_pclmulqdq; ++ int regs[4]; ++ ++ __cpuid(regs, 1); ++ ++ x86_cpu_has_sse2 = regs[3] & 0x4000000; ++ x86_cpu_has_sse42= regs[2] & 0x100000; ++ x86_cpu_has_pclmulqdq = regs[2] & 0x2; ++ ++ x86_cpu_enable_simd = x86_cpu_has_sse2 && ++ x86_cpu_has_sse42 && ++ x86_cpu_has_pclmulqdq; ++ return TRUE; ++} ++#endif /* _MSC_VER */ +diff --git a/x86.h b/x86.h +new file mode 100644 +index 000000000000..ebcf10ab09d2 +--- /dev/null ++++ b/x86.h +@@ -0,0 +1,15 @@ ++/* x86.h -- check for x86 CPU features ++* Copyright (C) 2013 Intel Corporation Jim Kukunas ++* For conditions of distribution and use, see copyright notice in zlib.h ++*/ ++ ++#ifndef X86_H ++#define X86_H ++ ++#include "zlib.h" ++ ++extern int x86_cpu_enable_simd; ++ ++void x86_check_features(void); ++ ++#endif /* X86_H */ +diff --git a/zutil.h b/zutil.h +index 80375b8b6109..4425bcf75eb3 100644 +--- a/zutil.h ++++ b/zutil.h +@@ -283,4 +283,10 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ + #define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + ++#ifdef _MSC_VER ++#define zalign(x) __declspec(align(x)) ++#else ++#define zalign(x) __attribute__((aligned((x)))) ++#endif ++ + #endif /* ZUTIL_H */ diff --git a/deps/zlib/patches/0002-uninitializedcheck.patch b/deps/zlib/patches/0002-uninitializedcheck.patch new file mode 100644 index 00000000000000..7c497839d30b87 --- /dev/null +++ b/deps/zlib/patches/0002-uninitializedcheck.patch @@ -0,0 +1,27 @@ +From 1a03e7aec95d89c659fd91f195b99893b6458cd7 Mon Sep 17 00:00:00 2001 +From: Adenilson Cavalcanti +Date: Wed, 27 Sep 2017 13:59:04 -0700 +Subject: [PATCH] Zlib patch: prevent uninitialized use of state->check + +No need to call the Adler32 checksum function, just set +the struct field to the expected value. + +Upstream bug: madler/zlib#245 +--- + third_party/zlib/inflate.c | 2 +- + 1 files changed, 1 insertion(+), 1 deletions(-) + delete mode 100644 third_party/zlib/patches/0002-uninitializedcheck.patch + +diff --git a/third_party/zlib/inflate.c b/third_party/zlib/inflate.c +index bec9497..5c40cf1 100644 +--- a/third_party/zlib/inflate.c ++++ b/third_party/zlib/inflate.c +@@ -228,7 +228,7 @@ int stream_size; + state->strm = strm; + state->window = Z_NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ +- state->check = adler32(0L, Z_NULL, 0); ++ state->check = 1L; /* 1L is the result of adler32() zero length data */ + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); diff --git a/deps/zlib/patches/README b/deps/zlib/patches/README new file mode 100644 index 00000000000000..b21d309ff91984 --- /dev/null +++ b/deps/zlib/patches/README @@ -0,0 +1,43 @@ +== Patches applied on top of zlib == + + - 0000-build.patch: changes from the upstream version, mostly related to the + build. + - 0001-simd.patch: integrate Intel SIMD optimizations from + https://github.com/jtkukunas/zlib/ + - 0002-uninitializedcheck.patch: prevent uninitialized use of state->check + +== Procedure to create a patch file == + + Assuming you are working in a new feature branch: + - git format-patch master --stdout > foo.patch # where naming follows a growing + # number plus patch description. + - git add foo.patch + - git commit -a -m "Local patch." + - git rebase -i HEAD~2 # Squashing the second commit + + As patches created in this way will feature a ChangeLog, there is no longer +the need to append this file with a description of what the patch does. This +should help to solve frequent conflicts in pending new patches on +Chromium's zlib. + + The plan for the near future is to better insulate the platform specific +changes to ease update adoption with new releases of zlib. This insulation +happens by making changes inside contrib/ rather than the root directory +(where conflicts can happen). + + If a change modifies enough things inside the root directory that the +intention is not immediately clear, generate a .patch file to go with your +change. If the change's modifications in the root directory are small, like: + +#ifdef FEATURE_FLAG +use_special_feature(); +#elif +use_default_behavior(); +#endif + + then the intent is clear and a .patch file doesn't need to be generated (since +it would not provide much value). + + Ideally local changes should have a merge request featured in either: + - canonical zlib: https://github.com/madler/zlib/ + - zlib-ng: https://github.com/Dead2/zlib-ng diff --git a/deps/zlib/qnx/package.qpg b/deps/zlib/qnx/package.qpg deleted file mode 100644 index 31e8e90db4dcd9..00000000000000 --- a/deps/zlib/qnx/package.qpg +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Library - - Medium - - 2.0 - - - - zlib - zlib - alain.bonnefoy@icbt.com - Public - public - www.gzip.org/zlib - - - Jean-Loup Gailly,Mark Adler - www.gzip.org/zlib - - zlib@gzip.org - - - A massively spiffy yet delicately unobtrusive compression library. - zlib is designed to be a free, general-purpose, legally unencumbered, lossless data compression library for use on virtually any computer hardware and operating system. - http://www.gzip.org/zlib - - - - - 1.2.11 - Medium - Stable - - - - - - - No License - - - - Software Development/Libraries and Extensions/C Libraries - zlib,compression - qnx6 - qnx6 - None - Developer - - - - - - - - - - - - - - Install - Post - No - Ignore - - No - Optional - - - - - - - - - - - - - InstallOver - zlib - - - - - - - - - - - - - InstallOver - zlib-dev - - - - - - - - - diff --git a/deps/zlib/simd_stub.c b/deps/zlib/simd_stub.c new file mode 100644 index 00000000000000..c6d46051498f36 --- /dev/null +++ b/deps/zlib/simd_stub.c @@ -0,0 +1,35 @@ +/* simd_stub.c -- stub implementations +* Copyright (C) 2014 Intel Corporation +* For conditions of distribution and use, see copyright notice in zlib.h +*/ +#include + +#include "deflate.h" +#include "x86.h" + +int ZLIB_INTERNAL x86_cpu_enable_simd = 0; + +void ZLIB_INTERNAL crc_fold_init(deflate_state *const s) { + assert(0); +} + +void ZLIB_INTERNAL crc_fold_copy(deflate_state *const s, + unsigned char *dst, + const unsigned char *src, + long len) { + assert(0); +} + +unsigned ZLIB_INTERNAL crc_fold_512to32(deflate_state *const s) { + assert(0); + return 0; +} + +void ZLIB_INTERNAL fill_window_sse(deflate_state *s) +{ + assert(0); +} + +void x86_check_features(void) +{ +} diff --git a/deps/zlib/test/example.c b/deps/zlib/test/example.c deleted file mode 100644 index eee17ce7c1591f..00000000000000 --- a/deps/zlib/test/example.c +++ /dev/null @@ -1,602 +0,0 @@ -/* example.c -- usage example of the zlib compression library - * Copyright (C) 1995-2006, 2011, 2016 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zlib.h" -#include - -#ifdef STDC -# include -# include -#endif - -#if defined(VMS) || defined(RISCOS) -# define TESTFILE "foo-gz" -#else -# define TESTFILE "foo.gz" -#endif - -#define CHECK_ERR(err, msg) { \ - if (err != Z_OK) { \ - fprintf(stderr, "%s error: %d\n", msg, err); \ - exit(1); \ - } \ -} - -static z_const char hello[] = "hello, hello!"; -/* "hello world" would be more standard, but the repeated "hello" - * stresses the compression code better, sorry... - */ - -static const char dictionary[] = "hello"; -static uLong dictId; /* Adler32 value of the dictionary */ - -void test_deflate OF((Byte *compr, uLong comprLen)); -void test_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_large_deflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_large_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_flush OF((Byte *compr, uLong *comprLen)); -void test_sync OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_dict_deflate OF((Byte *compr, uLong comprLen)); -void test_dict_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -int main OF((int argc, char *argv[])); - - -#ifdef Z_SOLO - -void *myalloc OF((void *, unsigned, unsigned)); -void myfree OF((void *, void *)); - -void *myalloc(q, n, m) - void *q; - unsigned n, m; -{ - (void)q; - return calloc(n, m); -} - -void myfree(void *q, void *p) -{ - (void)q; - free(p); -} - -static alloc_func zalloc = myalloc; -static free_func zfree = myfree; - -#else /* !Z_SOLO */ - -static alloc_func zalloc = (alloc_func)0; -static free_func zfree = (free_func)0; - -void test_compress OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_gzio OF((const char *fname, - Byte *uncompr, uLong uncomprLen)); - -/* =========================================================================== - * Test compress() and uncompress() - */ -void test_compress(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - uLong len = (uLong)strlen(hello)+1; - - err = compress(compr, &comprLen, (const Bytef*)hello, len); - CHECK_ERR(err, "compress"); - - strcpy((char*)uncompr, "garbage"); - - err = uncompress(uncompr, &uncomprLen, compr, comprLen); - CHECK_ERR(err, "uncompress"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad uncompress\n"); - exit(1); - } else { - printf("uncompress(): %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Test read/write of .gz files - */ -void test_gzio(fname, uncompr, uncomprLen) - const char *fname; /* compressed file name */ - Byte *uncompr; - uLong uncomprLen; -{ -#ifdef NO_GZCOMPRESS - fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); -#else - int err; - int len = (int)strlen(hello)+1; - gzFile file; - z_off_t pos; - - file = gzopen(fname, "wb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - exit(1); - } - gzputc(file, 'h'); - if (gzputs(file, "ello") != 4) { - fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); - exit(1); - } - if (gzprintf(file, ", %s!", "hello") != 8) { - fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); - exit(1); - } - gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ - gzclose(file); - - file = gzopen(fname, "rb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - exit(1); - } - strcpy((char*)uncompr, "garbage"); - - if (gzread(file, uncompr, (unsigned)uncomprLen) != len) { - fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); - exit(1); - } else { - printf("gzread(): %s\n", (char*)uncompr); - } - - pos = gzseek(file, -8L, SEEK_CUR); - if (pos != 6 || gztell(file) != pos) { - fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", - (long)pos, (long)gztell(file)); - exit(1); - } - - if (gzgetc(file) != ' ') { - fprintf(stderr, "gzgetc error\n"); - exit(1); - } - - if (gzungetc(' ', file) != ' ') { - fprintf(stderr, "gzungetc error\n"); - exit(1); - } - - gzgets(file, (char*)uncompr, (int)uncomprLen); - if (strlen((char*)uncompr) != 7) { /* " hello!" */ - fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello + 6)) { - fprintf(stderr, "bad gzgets after gzseek\n"); - exit(1); - } else { - printf("gzgets() after gzseek: %s\n", (char*)uncompr); - } - - gzclose(file); -#endif -} - -#endif /* Z_SOLO */ - -/* =========================================================================== - * Test deflate() with small buffers - */ -void test_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - uLong len = (uLong)strlen(hello)+1; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.next_out = compr; - - while (c_stream.total_in != len && c_stream.total_out < comprLen) { - c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - } - /* Finish the stream, still forcing small buffers: */ - for (;;) { - c_stream.avail_out = 1; - err = deflate(&c_stream, Z_FINISH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "deflate"); - } - - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with small buffers - */ -void test_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = 0; - d_stream.next_out = uncompr; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { - d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "inflate"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad inflate\n"); - exit(1); - } else { - printf("inflate(): %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Test deflate() with large buffers and dynamic change of compression level - */ -void test_large_deflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_BEST_SPEED); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_out = compr; - c_stream.avail_out = (uInt)comprLen; - - /* At this point, uncompr is still mostly zeroes, so it should compress - * very well: - */ - c_stream.next_in = uncompr; - c_stream.avail_in = (uInt)uncomprLen; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - if (c_stream.avail_in != 0) { - fprintf(stderr, "deflate not greedy\n"); - exit(1); - } - - /* Feed in already compressed data and switch to no compression: */ - deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); - c_stream.next_in = compr; - c_stream.avail_in = (uInt)comprLen/2; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - - /* Switch back to compressing mode: */ - deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); - c_stream.next_in = uncompr; - c_stream.avail_in = (uInt)uncomprLen; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with large buffers - */ -void test_large_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = (uInt)comprLen; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - for (;;) { - d_stream.next_out = uncompr; /* discard the output */ - d_stream.avail_out = (uInt)uncomprLen; - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "large inflate"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (d_stream.total_out != 2*uncomprLen + comprLen/2) { - fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); - exit(1); - } else { - printf("large_inflate(): OK\n"); - } -} - -/* =========================================================================== - * Test deflate() with full flush - */ -void test_flush(compr, comprLen) - Byte *compr; - uLong *comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - uInt len = (uInt)strlen(hello)+1; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.next_out = compr; - c_stream.avail_in = 3; - c_stream.avail_out = (uInt)*comprLen; - err = deflate(&c_stream, Z_FULL_FLUSH); - CHECK_ERR(err, "deflate"); - - compr[3]++; /* force an error in first compressed block */ - c_stream.avail_in = len - 3; - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - CHECK_ERR(err, "deflate"); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); - - *comprLen = c_stream.total_out; -} - -/* =========================================================================== - * Test inflateSync() - */ -void test_sync(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = 2; /* just read the zlib header */ - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - d_stream.next_out = uncompr; - d_stream.avail_out = (uInt)uncomprLen; - - err = inflate(&d_stream, Z_NO_FLUSH); - CHECK_ERR(err, "inflate"); - - d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ - err = inflateSync(&d_stream); /* but skip the damaged part */ - CHECK_ERR(err, "inflateSync"); - - err = inflate(&d_stream, Z_FINISH); - if (err != Z_DATA_ERROR) { - fprintf(stderr, "inflate should report DATA_ERROR\n"); - /* Because of incorrect adler32 */ - exit(1); - } - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - printf("after inflateSync(): hel%s\n", (char *)uncompr); -} - -/* =========================================================================== - * Test deflate() with preset dictionary - */ -void test_dict_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_BEST_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - err = deflateSetDictionary(&c_stream, - (const Bytef*)dictionary, (int)sizeof(dictionary)); - CHECK_ERR(err, "deflateSetDictionary"); - - dictId = c_stream.adler; - c_stream.next_out = compr; - c_stream.avail_out = (uInt)comprLen; - - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.avail_in = (uInt)strlen(hello)+1; - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with a preset dictionary - */ -void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = (uInt)comprLen; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - d_stream.next_out = uncompr; - d_stream.avail_out = (uInt)uncomprLen; - - for (;;) { - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - if (err == Z_NEED_DICT) { - if (d_stream.adler != dictId) { - fprintf(stderr, "unexpected dictionary"); - exit(1); - } - err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, - (int)sizeof(dictionary)); - } - CHECK_ERR(err, "inflate with dict"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad inflate with dict\n"); - exit(1); - } else { - printf("inflate with dictionary: %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Usage: example [output.gz [input.gz]] - */ - -int main(argc, argv) - int argc; - char *argv[]; -{ - Byte *compr, *uncompr; - uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ - uLong uncomprLen = comprLen; - static const char* myVersion = ZLIB_VERSION; - - if (zlibVersion()[0] != myVersion[0]) { - fprintf(stderr, "incompatible zlib version\n"); - exit(1); - - } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { - fprintf(stderr, "warning: different zlib version\n"); - } - - printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n", - ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags()); - - compr = (Byte*)calloc((uInt)comprLen, 1); - uncompr = (Byte*)calloc((uInt)uncomprLen, 1); - /* compr and uncompr are cleared to avoid reading uninitialized - * data and to ensure that uncompr compresses well. - */ - if (compr == Z_NULL || uncompr == Z_NULL) { - printf("out of memory\n"); - exit(1); - } - -#ifdef Z_SOLO - (void)argc; - (void)argv; -#else - test_compress(compr, comprLen, uncompr, uncomprLen); - - test_gzio((argc > 1 ? argv[1] : TESTFILE), - uncompr, uncomprLen); -#endif - - test_deflate(compr, comprLen); - test_inflate(compr, comprLen, uncompr, uncomprLen); - - test_large_deflate(compr, comprLen, uncompr, uncomprLen); - test_large_inflate(compr, comprLen, uncompr, uncomprLen); - - test_flush(compr, &comprLen); - test_sync(compr, comprLen, uncompr, uncomprLen); - comprLen = uncomprLen; - - test_dict_deflate(compr, comprLen); - test_dict_inflate(compr, comprLen, uncompr, uncomprLen); - - free(compr); - free(uncompr); - - return 0; -} diff --git a/deps/zlib/test/infcover.c b/deps/zlib/test/infcover.c deleted file mode 100644 index 2be01646cec3c6..00000000000000 --- a/deps/zlib/test/infcover.c +++ /dev/null @@ -1,671 +0,0 @@ -/* infcover.c -- test zlib's inflate routines with full code coverage - * Copyright (C) 2011, 2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* to use, do: ./configure --cover && make cover */ - -#include -#include -#include -#include -#include "zlib.h" - -/* get definition of internal structure so we can mess with it (see pull()), - and so we can call inflate_trees() (see cover5()) */ -#define ZLIB_INTERNAL -#include "inftrees.h" -#include "inflate.h" - -#define local static - -/* -- memory tracking routines -- */ - -/* - These memory tracking routines are provided to zlib and track all of zlib's - allocations and deallocations, check for LIFO operations, keep a current - and high water mark of total bytes requested, optionally set a limit on the - total memory that can be allocated, and when done check for memory leaks. - - They are used as follows: - - z_stream strm; - mem_setup(&strm) initializes the memory tracking and sets the - zalloc, zfree, and opaque members of strm to use - memory tracking for all zlib operations on strm - mem_limit(&strm, limit) sets a limit on the total bytes requested -- a - request that exceeds this limit will result in an - allocation failure (returns NULL) -- setting the - limit to zero means no limit, which is the default - after mem_setup() - mem_used(&strm, "msg") prints to stderr "msg" and the total bytes used - mem_high(&strm, "msg") prints to stderr "msg" and the high water mark - mem_done(&strm, "msg") ends memory tracking, releases all allocations - for the tracking as well as leaked zlib blocks, if - any. If there was anything unusual, such as leaked - blocks, non-FIFO frees, or frees of addresses not - allocated, then "msg" and information about the - problem is printed to stderr. If everything is - normal, nothing is printed. mem_done resets the - strm members to Z_NULL to use the default memory - allocation routines on the next zlib initialization - using strm. - */ - -/* these items are strung together in a linked list, one for each allocation */ -struct mem_item { - void *ptr; /* pointer to allocated memory */ - size_t size; /* requested size of allocation */ - struct mem_item *next; /* pointer to next item in list, or NULL */ -}; - -/* this structure is at the root of the linked list, and tracks statistics */ -struct mem_zone { - struct mem_item *first; /* pointer to first item in list, or NULL */ - size_t total, highwater; /* total allocations, and largest total */ - size_t limit; /* memory allocation limit, or 0 if no limit */ - int notlifo, rogue; /* counts of non-LIFO frees and rogue frees */ -}; - -/* memory allocation routine to pass to zlib */ -local void *mem_alloc(void *mem, unsigned count, unsigned size) -{ - void *ptr; - struct mem_item *item; - struct mem_zone *zone = mem; - size_t len = count * (size_t)size; - - /* induced allocation failure */ - if (zone == NULL || (zone->limit && zone->total + len > zone->limit)) - return NULL; - - /* perform allocation using the standard library, fill memory with a - non-zero value to make sure that the code isn't depending on zeros */ - ptr = malloc(len); - if (ptr == NULL) - return NULL; - memset(ptr, 0xa5, len); - - /* create a new item for the list */ - item = malloc(sizeof(struct mem_item)); - if (item == NULL) { - free(ptr); - return NULL; - } - item->ptr = ptr; - item->size = len; - - /* insert item at the beginning of the list */ - item->next = zone->first; - zone->first = item; - - /* update the statistics */ - zone->total += item->size; - if (zone->total > zone->highwater) - zone->highwater = zone->total; - - /* return the allocated memory */ - return ptr; -} - -/* memory free routine to pass to zlib */ -local void mem_free(void *mem, void *ptr) -{ - struct mem_item *item, *next; - struct mem_zone *zone = mem; - - /* if no zone, just do a free */ - if (zone == NULL) { - free(ptr); - return; - } - - /* point next to the item that matches ptr, or NULL if not found -- remove - the item from the linked list if found */ - next = zone->first; - if (next) { - if (next->ptr == ptr) - zone->first = next->next; /* first one is it, remove from list */ - else { - do { /* search the linked list */ - item = next; - next = item->next; - } while (next != NULL && next->ptr != ptr); - if (next) { /* if found, remove from linked list */ - item->next = next->next; - zone->notlifo++; /* not a LIFO free */ - } - - } - } - - /* if found, update the statistics and free the item */ - if (next) { - zone->total -= next->size; - free(next); - } - - /* if not found, update the rogue count */ - else - zone->rogue++; - - /* in any case, do the requested free with the standard library function */ - free(ptr); -} - -/* set up a controlled memory allocation space for monitoring, set the stream - parameters to the controlled routines, with opaque pointing to the space */ -local void mem_setup(z_stream *strm) -{ - struct mem_zone *zone; - - zone = malloc(sizeof(struct mem_zone)); - assert(zone != NULL); - zone->first = NULL; - zone->total = 0; - zone->highwater = 0; - zone->limit = 0; - zone->notlifo = 0; - zone->rogue = 0; - strm->opaque = zone; - strm->zalloc = mem_alloc; - strm->zfree = mem_free; -} - -/* set a limit on the total memory allocation, or 0 to remove the limit */ -local void mem_limit(z_stream *strm, size_t limit) -{ - struct mem_zone *zone = strm->opaque; - - zone->limit = limit; -} - -/* show the current total requested allocations in bytes */ -local void mem_used(z_stream *strm, char *prefix) -{ - struct mem_zone *zone = strm->opaque; - - fprintf(stderr, "%s: %lu allocated\n", prefix, zone->total); -} - -/* show the high water allocation in bytes */ -local void mem_high(z_stream *strm, char *prefix) -{ - struct mem_zone *zone = strm->opaque; - - fprintf(stderr, "%s: %lu high water mark\n", prefix, zone->highwater); -} - -/* release the memory allocation zone -- if there are any surprises, notify */ -local void mem_done(z_stream *strm, char *prefix) -{ - int count = 0; - struct mem_item *item, *next; - struct mem_zone *zone = strm->opaque; - - /* show high water mark */ - mem_high(strm, prefix); - - /* free leftover allocations and item structures, if any */ - item = zone->first; - while (item != NULL) { - free(item->ptr); - next = item->next; - free(item); - item = next; - count++; - } - - /* issue alerts about anything unexpected */ - if (count || zone->total) - fprintf(stderr, "** %s: %lu bytes in %d blocks not freed\n", - prefix, zone->total, count); - if (zone->notlifo) - fprintf(stderr, "** %s: %d frees not LIFO\n", prefix, zone->notlifo); - if (zone->rogue) - fprintf(stderr, "** %s: %d frees not recognized\n", - prefix, zone->rogue); - - /* free the zone and delete from the stream */ - free(zone); - strm->opaque = Z_NULL; - strm->zalloc = Z_NULL; - strm->zfree = Z_NULL; -} - -/* -- inflate test routines -- */ - -/* Decode a hexadecimal string, set *len to length, in[] to the bytes. This - decodes liberally, in that hex digits can be adjacent, in which case two in - a row writes a byte. Or they can be delimited by any non-hex character, - where the delimiters are ignored except when a single hex digit is followed - by a delimiter, where that single digit writes a byte. The returned data is - allocated and must eventually be freed. NULL is returned if out of memory. - If the length is not needed, then len can be NULL. */ -local unsigned char *h2b(const char *hex, unsigned *len) -{ - unsigned char *in, *re; - unsigned next, val; - - in = malloc((strlen(hex) + 1) >> 1); - if (in == NULL) - return NULL; - next = 0; - val = 1; - do { - if (*hex >= '0' && *hex <= '9') - val = (val << 4) + *hex - '0'; - else if (*hex >= 'A' && *hex <= 'F') - val = (val << 4) + *hex - 'A' + 10; - else if (*hex >= 'a' && *hex <= 'f') - val = (val << 4) + *hex - 'a' + 10; - else if (val != 1 && val < 32) /* one digit followed by delimiter */ - val += 240; /* make it look like two digits */ - if (val > 255) { /* have two digits */ - in[next++] = val & 0xff; /* save the decoded byte */ - val = 1; /* start over */ - } - } while (*hex++); /* go through the loop with the terminating null */ - if (len != NULL) - *len = next; - re = realloc(in, next); - return re == NULL ? in : re; -} - -/* generic inflate() run, where hex is the hexadecimal input data, what is the - text to include in an error message, step is how much input data to feed - inflate() on each call, or zero to feed it all, win is the window bits - parameter to inflateInit2(), len is the size of the output buffer, and err - is the error code expected from the first inflate() call (the second - inflate() call is expected to return Z_STREAM_END). If win is 47, then - header information is collected with inflateGetHeader(). If a zlib stream - is looking for a dictionary, then an empty dictionary is provided. - inflate() is run until all of the input data is consumed. */ -local void inf(char *hex, char *what, unsigned step, int win, unsigned len, - int err) -{ - int ret; - unsigned have; - unsigned char *in, *out; - z_stream strm, copy; - gz_header head; - - mem_setup(&strm); - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit2(&strm, win); - if (ret != Z_OK) { - mem_done(&strm, what); - return; - } - out = malloc(len); assert(out != NULL); - if (win == 47) { - head.extra = out; - head.extra_max = len; - head.name = out; - head.name_max = len; - head.comment = out; - head.comm_max = len; - ret = inflateGetHeader(&strm, &head); assert(ret == Z_OK); - } - in = h2b(hex, &have); assert(in != NULL); - if (step == 0 || step > have) - step = have; - strm.avail_in = step; - have -= step; - strm.next_in = in; - do { - strm.avail_out = len; - strm.next_out = out; - ret = inflate(&strm, Z_NO_FLUSH); assert(err == 9 || ret == err); - if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_NEED_DICT) - break; - if (ret == Z_NEED_DICT) { - ret = inflateSetDictionary(&strm, in, 1); - assert(ret == Z_DATA_ERROR); - mem_limit(&strm, 1); - ret = inflateSetDictionary(&strm, out, 0); - assert(ret == Z_MEM_ERROR); - mem_limit(&strm, 0); - ((struct inflate_state *)strm.state)->mode = DICT; - ret = inflateSetDictionary(&strm, out, 0); - assert(ret == Z_OK); - ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_BUF_ERROR); - } - ret = inflateCopy(©, &strm); assert(ret == Z_OK); - ret = inflateEnd(©); assert(ret == Z_OK); - err = 9; /* don't care next time around */ - have += strm.avail_in; - strm.avail_in = step > have ? have : step; - have -= strm.avail_in; - } while (strm.avail_in); - free(in); - free(out); - ret = inflateReset2(&strm, -8); assert(ret == Z_OK); - ret = inflateEnd(&strm); assert(ret == Z_OK); - mem_done(&strm, what); -} - -/* cover all of the lines in inflate.c up to inflate() */ -local void cover_support(void) -{ - int ret; - z_stream strm; - - mem_setup(&strm); - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit(&strm); assert(ret == Z_OK); - mem_used(&strm, "inflate init"); - ret = inflatePrime(&strm, 5, 31); assert(ret == Z_OK); - ret = inflatePrime(&strm, -1, 0); assert(ret == Z_OK); - ret = inflateSetDictionary(&strm, Z_NULL, 0); - assert(ret == Z_STREAM_ERROR); - ret = inflateEnd(&strm); assert(ret == Z_OK); - mem_done(&strm, "prime"); - - inf("63 0", "force window allocation", 0, -15, 1, Z_OK); - inf("63 18 5", "force window replacement", 0, -8, 259, Z_OK); - inf("63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, Z_OK); - inf("3 0", "use fixed blocks", 0, -15, 1, Z_STREAM_END); - inf("", "bad window size", 0, 1, 0, Z_STREAM_ERROR); - - mem_setup(&strm); - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit_(&strm, ZLIB_VERSION - 1, (int)sizeof(z_stream)); - assert(ret == Z_VERSION_ERROR); - mem_done(&strm, "wrong version"); - - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit(&strm); assert(ret == Z_OK); - ret = inflateEnd(&strm); assert(ret == Z_OK); - fputs("inflate built-in memory routines\n", stderr); -} - -/* cover all inflate() header and trailer cases and code after inflate() */ -local void cover_wrap(void) -{ - int ret; - z_stream strm, copy; - unsigned char dict[257]; - - ret = inflate(Z_NULL, 0); assert(ret == Z_STREAM_ERROR); - ret = inflateEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); - ret = inflateCopy(Z_NULL, Z_NULL); assert(ret == Z_STREAM_ERROR); - fputs("inflate bad parameters\n", stderr); - - inf("1f 8b 0 0", "bad gzip method", 0, 31, 0, Z_DATA_ERROR); - inf("1f 8b 8 80", "bad gzip flags", 0, 31, 0, Z_DATA_ERROR); - inf("77 85", "bad zlib method", 0, 15, 0, Z_DATA_ERROR); - inf("8 99", "set window size from header", 0, 0, 0, Z_OK); - inf("78 9c", "bad zlib window size", 0, 8, 0, Z_DATA_ERROR); - inf("78 9c 63 0 0 0 1 0 1", "check adler32", 0, 15, 1, Z_STREAM_END); - inf("1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0", "bad header crc", 0, 47, 1, - Z_DATA_ERROR); - inf("1f 8b 8 2 0 0 0 0 0 0 1d 26 3 0 0 0 0 0 0 0 0 0", "check gzip length", - 0, 47, 0, Z_STREAM_END); - inf("78 90", "bad zlib header check", 0, 47, 0, Z_DATA_ERROR); - inf("8 b8 0 0 0 1", "need dictionary", 0, 8, 0, Z_NEED_DICT); - inf("78 9c 63 0", "compute adler32", 0, 15, 1, Z_OK); - - mem_setup(&strm); - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit2(&strm, -8); - strm.avail_in = 2; - strm.next_in = (void *)"\x63"; - strm.avail_out = 1; - strm.next_out = (void *)&ret; - mem_limit(&strm, 1); - ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); - ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); - mem_limit(&strm, 0); - memset(dict, 0, 257); - ret = inflateSetDictionary(&strm, dict, 257); - assert(ret == Z_OK); - mem_limit(&strm, (sizeof(struct inflate_state) << 1) + 256); - ret = inflatePrime(&strm, 16, 0); assert(ret == Z_OK); - strm.avail_in = 2; - strm.next_in = (void *)"\x80"; - ret = inflateSync(&strm); assert(ret == Z_DATA_ERROR); - ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_STREAM_ERROR); - strm.avail_in = 4; - strm.next_in = (void *)"\0\0\xff\xff"; - ret = inflateSync(&strm); assert(ret == Z_OK); - (void)inflateSyncPoint(&strm); - ret = inflateCopy(©, &strm); assert(ret == Z_MEM_ERROR); - mem_limit(&strm, 0); - ret = inflateUndermine(&strm, 1); assert(ret == Z_DATA_ERROR); - (void)inflateMark(&strm); - ret = inflateEnd(&strm); assert(ret == Z_OK); - mem_done(&strm, "miscellaneous, force memory errors"); -} - -/* input and output functions for inflateBack() */ -local unsigned pull(void *desc, unsigned char **buf) -{ - static unsigned int next = 0; - static unsigned char dat[] = {0x63, 0, 2, 0}; - struct inflate_state *state; - - if (desc == Z_NULL) { - next = 0; - return 0; /* no input (already provided at next_in) */ - } - state = (void *)((z_stream *)desc)->state; - if (state != Z_NULL) - state->mode = SYNC; /* force an otherwise impossible situation */ - return next < sizeof(dat) ? (*buf = dat + next++, 1) : 0; -} - -local int push(void *desc, unsigned char *buf, unsigned len) -{ - buf += len; - return desc != Z_NULL; /* force error if desc not null */ -} - -/* cover inflateBack() up to common deflate data cases and after those */ -local void cover_back(void) -{ - int ret; - z_stream strm; - unsigned char win[32768]; - - ret = inflateBackInit_(Z_NULL, 0, win, 0, 0); - assert(ret == Z_VERSION_ERROR); - ret = inflateBackInit(Z_NULL, 0, win); assert(ret == Z_STREAM_ERROR); - ret = inflateBack(Z_NULL, Z_NULL, Z_NULL, Z_NULL, Z_NULL); - assert(ret == Z_STREAM_ERROR); - ret = inflateBackEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); - fputs("inflateBack bad parameters\n", stderr); - - mem_setup(&strm); - ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); - strm.avail_in = 2; - strm.next_in = (void *)"\x03"; - ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); - assert(ret == Z_STREAM_END); - /* force output error */ - strm.avail_in = 3; - strm.next_in = (void *)"\x63\x00"; - ret = inflateBack(&strm, pull, Z_NULL, push, &strm); - assert(ret == Z_BUF_ERROR); - /* force mode error by mucking with state */ - ret = inflateBack(&strm, pull, &strm, push, Z_NULL); - assert(ret == Z_STREAM_ERROR); - ret = inflateBackEnd(&strm); assert(ret == Z_OK); - mem_done(&strm, "inflateBack bad state"); - - ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); - ret = inflateBackEnd(&strm); assert(ret == Z_OK); - fputs("inflateBack built-in memory routines\n", stderr); -} - -/* do a raw inflate of data in hexadecimal with both inflate and inflateBack */ -local int try(char *hex, char *id, int err) -{ - int ret; - unsigned len, size; - unsigned char *in, *out, *win; - char *prefix; - z_stream strm; - - /* convert to hex */ - in = h2b(hex, &len); - assert(in != NULL); - - /* allocate work areas */ - size = len << 3; - out = malloc(size); - assert(out != NULL); - win = malloc(32768); - assert(win != NULL); - prefix = malloc(strlen(id) + 6); - assert(prefix != NULL); - - /* first with inflate */ - strcpy(prefix, id); - strcat(prefix, "-late"); - mem_setup(&strm); - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit2(&strm, err < 0 ? 47 : -15); - assert(ret == Z_OK); - strm.avail_in = len; - strm.next_in = in; - do { - strm.avail_out = size; - strm.next_out = out; - ret = inflate(&strm, Z_TREES); - assert(ret != Z_STREAM_ERROR && ret != Z_MEM_ERROR); - if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT) - break; - } while (strm.avail_in || strm.avail_out == 0); - if (err) { - assert(ret == Z_DATA_ERROR); - assert(strcmp(id, strm.msg) == 0); - } - inflateEnd(&strm); - mem_done(&strm, prefix); - - /* then with inflateBack */ - if (err >= 0) { - strcpy(prefix, id); - strcat(prefix, "-back"); - mem_setup(&strm); - ret = inflateBackInit(&strm, 15, win); - assert(ret == Z_OK); - strm.avail_in = len; - strm.next_in = in; - ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); - assert(ret != Z_STREAM_ERROR); - if (err) { - assert(ret == Z_DATA_ERROR); - assert(strcmp(id, strm.msg) == 0); - } - inflateBackEnd(&strm); - mem_done(&strm, prefix); - } - - /* clean up */ - free(prefix); - free(win); - free(out); - free(in); - return ret; -} - -/* cover deflate data cases in both inflate() and inflateBack() */ -local void cover_inflate(void) -{ - try("0 0 0 0 0", "invalid stored block lengths", 1); - try("3 0", "fixed", 0); - try("6", "invalid block type", 1); - try("1 1 0 fe ff 0", "stored", 0); - try("fc 0 0", "too many length or distance symbols", 1); - try("4 0 fe ff", "invalid code lengths set", 1); - try("4 0 24 49 0", "invalid bit length repeat", 1); - try("4 0 24 e9 ff ff", "invalid bit length repeat", 1); - try("4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1); - try("4 80 49 92 24 49 92 24 71 ff ff 93 11 0", - "invalid literal/lengths set", 1); - try("4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1); - try("4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1); - try("2 7e ff ff", "invalid distance code", 1); - try("c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1); - - /* also trailer mismatch just in inflate() */ - try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1); - try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1", - "incorrect length check", -1); - try("5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0); - try("5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f", - "long code", 0); - try("ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0); - try("ed cf c1 b1 2c 47 10 c4 30 fa 6f 35 1d 1 82 59 3d fb be 2e 2a fc f c", - "long distance and extra", 0); - try("ed c0 81 0 0 0 0 80 a0 fd a9 17 a9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " - "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0); - inf("2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258, - Z_STREAM_END); - inf("63 18 5 40 c 0", "window wrap", 3, -8, 300, Z_OK); -} - -/* cover remaining lines in inftrees.c */ -local void cover_trees(void) -{ - int ret; - unsigned bits; - unsigned short lens[16], work[16]; - code *next, table[ENOUGH_DISTS]; - - /* we need to call inflate_table() directly in order to manifest not- - enough errors, since zlib insures that enough is always enough */ - for (bits = 0; bits < 15; bits++) - lens[bits] = (unsigned short)(bits + 1); - lens[15] = 15; - next = table; - bits = 15; - ret = inflate_table(DISTS, lens, 16, &next, &bits, work); - assert(ret == 1); - next = table; - bits = 1; - ret = inflate_table(DISTS, lens, 16, &next, &bits, work); - assert(ret == 1); - fputs("inflate_table not enough errors\n", stderr); -} - -/* cover remaining inffast.c decoding and window copying */ -local void cover_fast(void) -{ - inf("e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68" - " ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, Z_DATA_ERROR); - inf("25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49" - " 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258, - Z_DATA_ERROR); - inf("3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258, - Z_DATA_ERROR); - inf("1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258, - Z_DATA_ERROR); - inf("d c7 1 ae eb 38 c 4 41 a0 87 72 de df fb 1f b8 36 b1 38 5d ff ff 0", - "fast 2nd level codes and too far back", 0, -8, 258, Z_DATA_ERROR); - inf("63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, Z_OK); - inf("63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0", - "contiguous and wrap around window", 6, -8, 259, Z_OK); - inf("63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259, - Z_STREAM_END); -} - -int main(void) -{ - fprintf(stderr, "%s\n", zlibVersion()); - cover_support(); - cover_wrap(); - cover_back(); - cover_inflate(); - cover_trees(); - cover_fast(); - return 0; -} diff --git a/deps/zlib/test/minigzip.c b/deps/zlib/test/minigzip.c deleted file mode 100644 index e22fb08c0a2921..00000000000000 --- a/deps/zlib/test/minigzip.c +++ /dev/null @@ -1,651 +0,0 @@ -/* minigzip.c -- simulate gzip using the zlib compression library - * Copyright (C) 1995-2006, 2010, 2011, 2016 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * minigzip is a minimal implementation of the gzip utility. This is - * only an example of using zlib and isn't meant to replace the - * full-featured gzip. No attempt is made to deal with file systems - * limiting names to 14 or 8+3 characters, etc... Error checking is - * very limited. So use minigzip only for testing; use gzip for the - * real thing. On MSDOS, use only on file names without extension - * or in pipe mode. - */ - -/* @(#) $Id$ */ - -#include "zlib.h" -#include - -#ifdef STDC -# include -# include -#endif - -#ifdef USE_MMAP -# include -# include -# include -#endif - -#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) -# include -# include -# ifdef UNDER_CE -# include -# endif -# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -#else -# define SET_BINARY_MODE(file) -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1900 -# define snprintf _snprintf -#endif - -#ifdef VMS -# define unlink delete -# define GZ_SUFFIX "-gz" -#endif -#ifdef RISCOS -# define unlink remove -# define GZ_SUFFIX "-gz" -# define fileno(file) file->__file -#endif -#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include /* for fileno */ -#endif - -#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) -#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ - extern int unlink OF((const char *)); -#endif -#endif - -#if defined(UNDER_CE) -# include -# define perror(s) pwinerror(s) - -/* Map the Windows error number in ERROR to a locale-dependent error - message string and return a pointer to it. Typically, the values - for ERROR come from GetLastError. - - The string pointed to shall not be modified by the application, - but may be overwritten by a subsequent call to strwinerror - - The strwinerror function does not change the current setting - of GetLastError. */ - -static char *strwinerror (error) - DWORD error; -{ - static char buf[1024]; - - wchar_t *msgbuf; - DWORD lasterr = GetLastError(); - DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_ALLOCATE_BUFFER, - NULL, - error, - 0, /* Default language */ - (LPVOID)&msgbuf, - 0, - NULL); - if (chars != 0) { - /* If there is an \r\n appended, zap it. */ - if (chars >= 2 - && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { - chars -= 2; - msgbuf[chars] = 0; - } - - if (chars > sizeof (buf) - 1) { - chars = sizeof (buf) - 1; - msgbuf[chars] = 0; - } - - wcstombs(buf, msgbuf, chars + 1); - LocalFree(msgbuf); - } - else { - sprintf(buf, "unknown win32 error (%ld)", error); - } - - SetLastError(lasterr); - return buf; -} - -static void pwinerror (s) - const char *s; -{ - if (s && *s) - fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ())); - else - fprintf(stderr, "%s\n", strwinerror(GetLastError ())); -} - -#endif /* UNDER_CE */ - -#ifndef GZ_SUFFIX -# define GZ_SUFFIX ".gz" -#endif -#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) - -#define BUFLEN 16384 -#define MAX_NAME_LEN 1024 - -#ifdef MAXSEG_64K -# define local static - /* Needed for systems with limitation on stack size. */ -#else -# define local -#endif - -#ifdef Z_SOLO -/* for Z_SOLO, create simplified gz* functions using deflate and inflate */ - -#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE) -# include /* for unlink() */ -#endif - -void *myalloc OF((void *, unsigned, unsigned)); -void myfree OF((void *, void *)); - -void *myalloc(q, n, m) - void *q; - unsigned n, m; -{ - (void)q; - return calloc(n, m); -} - -void myfree(q, p) - void *q, *p; -{ - (void)q; - free(p); -} - -typedef struct gzFile_s { - FILE *file; - int write; - int err; - char *msg; - z_stream strm; -} *gzFile; - -gzFile gzopen OF((const char *, const char *)); -gzFile gzdopen OF((int, const char *)); -gzFile gz_open OF((const char *, int, const char *)); - -gzFile gzopen(path, mode) -const char *path; -const char *mode; -{ - return gz_open(path, -1, mode); -} - -gzFile gzdopen(fd, mode) -int fd; -const char *mode; -{ - return gz_open(NULL, fd, mode); -} - -gzFile gz_open(path, fd, mode) - const char *path; - int fd; - const char *mode; -{ - gzFile gz; - int ret; - - gz = malloc(sizeof(struct gzFile_s)); - if (gz == NULL) - return NULL; - gz->write = strchr(mode, 'w') != NULL; - gz->strm.zalloc = myalloc; - gz->strm.zfree = myfree; - gz->strm.opaque = Z_NULL; - if (gz->write) - ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0); - else { - gz->strm.next_in = 0; - gz->strm.avail_in = Z_NULL; - ret = inflateInit2(&(gz->strm), 15 + 16); - } - if (ret != Z_OK) { - free(gz); - return NULL; - } - gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") : - fopen(path, gz->write ? "wb" : "rb"); - if (gz->file == NULL) { - gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm)); - free(gz); - return NULL; - } - gz->err = 0; - gz->msg = ""; - return gz; -} - -int gzwrite OF((gzFile, const void *, unsigned)); - -int gzwrite(gz, buf, len) - gzFile gz; - const void *buf; - unsigned len; -{ - z_stream *strm; - unsigned char out[BUFLEN]; - - if (gz == NULL || !gz->write) - return 0; - strm = &(gz->strm); - strm->next_in = (void *)buf; - strm->avail_in = len; - do { - strm->next_out = out; - strm->avail_out = BUFLEN; - (void)deflate(strm, Z_NO_FLUSH); - fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); - } while (strm->avail_out == 0); - return len; -} - -int gzread OF((gzFile, void *, unsigned)); - -int gzread(gz, buf, len) - gzFile gz; - void *buf; - unsigned len; -{ - int ret; - unsigned got; - unsigned char in[1]; - z_stream *strm; - - if (gz == NULL || gz->write) - return 0; - if (gz->err) - return 0; - strm = &(gz->strm); - strm->next_out = (void *)buf; - strm->avail_out = len; - do { - got = fread(in, 1, 1, gz->file); - if (got == 0) - break; - strm->next_in = in; - strm->avail_in = 1; - ret = inflate(strm, Z_NO_FLUSH); - if (ret == Z_DATA_ERROR) { - gz->err = Z_DATA_ERROR; - gz->msg = strm->msg; - return 0; - } - if (ret == Z_STREAM_END) - inflateReset(strm); - } while (strm->avail_out); - return len - strm->avail_out; -} - -int gzclose OF((gzFile)); - -int gzclose(gz) - gzFile gz; -{ - z_stream *strm; - unsigned char out[BUFLEN]; - - if (gz == NULL) - return Z_STREAM_ERROR; - strm = &(gz->strm); - if (gz->write) { - strm->next_in = Z_NULL; - strm->avail_in = 0; - do { - strm->next_out = out; - strm->avail_out = BUFLEN; - (void)deflate(strm, Z_FINISH); - fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); - } while (strm->avail_out == 0); - deflateEnd(strm); - } - else - inflateEnd(strm); - fclose(gz->file); - free(gz); - return Z_OK; -} - -const char *gzerror OF((gzFile, int *)); - -const char *gzerror(gz, err) - gzFile gz; - int *err; -{ - *err = gz->err; - return gz->msg; -} - -#endif - -static char *prog; - -void error OF((const char *msg)); -void gz_compress OF((FILE *in, gzFile out)); -#ifdef USE_MMAP -int gz_compress_mmap OF((FILE *in, gzFile out)); -#endif -void gz_uncompress OF((gzFile in, FILE *out)); -void file_compress OF((char *file, char *mode)); -void file_uncompress OF((char *file)); -int main OF((int argc, char *argv[])); - -/* =========================================================================== - * Display error message and exit - */ -void error(msg) - const char *msg; -{ - fprintf(stderr, "%s: %s\n", prog, msg); - exit(1); -} - -/* =========================================================================== - * Compress input to output then close both files. - */ - -void gz_compress(in, out) - FILE *in; - gzFile out; -{ - local char buf[BUFLEN]; - int len; - int err; - -#ifdef USE_MMAP - /* Try first compressing with mmap. If mmap fails (minigzip used in a - * pipe), use the normal fread loop. - */ - if (gz_compress_mmap(in, out) == Z_OK) return; -#endif - for (;;) { - len = (int)fread(buf, 1, sizeof(buf), in); - if (ferror(in)) { - perror("fread"); - exit(1); - } - if (len == 0) break; - - if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); - } - fclose(in); - if (gzclose(out) != Z_OK) error("failed gzclose"); -} - -#ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ - -/* Try compressing the input file at once using mmap. Return Z_OK if - * if success, Z_ERRNO otherwise. - */ -int gz_compress_mmap(in, out) - FILE *in; - gzFile out; -{ - int len; - int err; - int ifd = fileno(in); - caddr_t buf; /* mmap'ed buffer for the entire input file */ - off_t buf_len; /* length of the input file */ - struct stat sb; - - /* Determine the size of the file, needed for mmap: */ - if (fstat(ifd, &sb) < 0) return Z_ERRNO; - buf_len = sb.st_size; - if (buf_len <= 0) return Z_ERRNO; - - /* Now do the actual mmap: */ - buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); - if (buf == (caddr_t)(-1)) return Z_ERRNO; - - /* Compress the whole file at once: */ - len = gzwrite(out, (char *)buf, (unsigned)buf_len); - - if (len != (int)buf_len) error(gzerror(out, &err)); - - munmap(buf, buf_len); - fclose(in); - if (gzclose(out) != Z_OK) error("failed gzclose"); - return Z_OK; -} -#endif /* USE_MMAP */ - -/* =========================================================================== - * Uncompress input to output then close both files. - */ -void gz_uncompress(in, out) - gzFile in; - FILE *out; -{ - local char buf[BUFLEN]; - int len; - int err; - - for (;;) { - len = gzread(in, buf, sizeof(buf)); - if (len < 0) error (gzerror(in, &err)); - if (len == 0) break; - - if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { - error("failed fwrite"); - } - } - if (fclose(out)) error("failed fclose"); - - if (gzclose(in) != Z_OK) error("failed gzclose"); -} - - -/* =========================================================================== - * Compress the given file: create a corresponding .gz file and remove the - * original. - */ -void file_compress(file, mode) - char *file; - char *mode; -{ - local char outfile[MAX_NAME_LEN]; - FILE *in; - gzFile out; - - if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) { - fprintf(stderr, "%s: filename too long\n", prog); - exit(1); - } - -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX); -#else - strcpy(outfile, file); - strcat(outfile, GZ_SUFFIX); -#endif - - in = fopen(file, "rb"); - if (in == NULL) { - perror(file); - exit(1); - } - out = gzopen(outfile, mode); - if (out == NULL) { - fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); - exit(1); - } - gz_compress(in, out); - - unlink(file); -} - - -/* =========================================================================== - * Uncompress the given file and remove the original. - */ -void file_uncompress(file) - char *file; -{ - local char buf[MAX_NAME_LEN]; - char *infile, *outfile; - FILE *out; - gzFile in; - unsigned len = strlen(file); - - if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { - fprintf(stderr, "%s: filename too long\n", prog); - exit(1); - } - -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(buf, sizeof(buf), "%s", file); -#else - strcpy(buf, file); -#endif - - if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { - infile = file; - outfile = buf; - outfile[len-3] = '\0'; - } else { - outfile = file; - infile = buf; -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX); -#else - strcat(infile, GZ_SUFFIX); -#endif - } - in = gzopen(infile, "rb"); - if (in == NULL) { - fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); - exit(1); - } - out = fopen(outfile, "wb"); - if (out == NULL) { - perror(file); - exit(1); - } - - gz_uncompress(in, out); - - unlink(infile); -} - - -/* =========================================================================== - * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...] - * -c : write to standard output - * -d : decompress - * -f : compress with Z_FILTERED - * -h : compress with Z_HUFFMAN_ONLY - * -r : compress with Z_RLE - * -1 to -9 : compression level - */ - -int main(argc, argv) - int argc; - char *argv[]; -{ - int copyout = 0; - int uncompr = 0; - gzFile file; - char *bname, outmode[20]; - -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(outmode, sizeof(outmode), "%s", "wb6 "); -#else - strcpy(outmode, "wb6 "); -#endif - - prog = argv[0]; - bname = strrchr(argv[0], '/'); - if (bname) - bname++; - else - bname = argv[0]; - argc--, argv++; - - if (!strcmp(bname, "gunzip")) - uncompr = 1; - else if (!strcmp(bname, "zcat")) - copyout = uncompr = 1; - - while (argc > 0) { - if (strcmp(*argv, "-c") == 0) - copyout = 1; - else if (strcmp(*argv, "-d") == 0) - uncompr = 1; - else if (strcmp(*argv, "-f") == 0) - outmode[3] = 'f'; - else if (strcmp(*argv, "-h") == 0) - outmode[3] = 'h'; - else if (strcmp(*argv, "-r") == 0) - outmode[3] = 'R'; - else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && - (*argv)[2] == 0) - outmode[2] = (*argv)[1]; - else - break; - argc--, argv++; - } - if (outmode[3] == ' ') - outmode[3] = 0; - if (argc == 0) { - SET_BINARY_MODE(stdin); - SET_BINARY_MODE(stdout); - if (uncompr) { - file = gzdopen(fileno(stdin), "rb"); - if (file == NULL) error("can't gzdopen stdin"); - gz_uncompress(file, stdout); - } else { - file = gzdopen(fileno(stdout), outmode); - if (file == NULL) error("can't gzdopen stdout"); - gz_compress(stdin, file); - } - } else { - if (copyout) { - SET_BINARY_MODE(stdout); - } - do { - if (uncompr) { - if (copyout) { - file = gzopen(*argv, "rb"); - if (file == NULL) - fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv); - else - gz_uncompress(file, stdout); - } else { - file_uncompress(*argv); - } - } else { - if (copyout) { - FILE * in = fopen(*argv, "rb"); - - if (in == NULL) { - perror(*argv); - } else { - file = gzdopen(fileno(stdout), outmode); - if (file == NULL) error("can't gzdopen stdout"); - - gz_compress(in, file); - } - - } else { - file_compress(*argv, outmode); - } - } - } while (argv++, --argc); - } - return 0; -} diff --git a/deps/zlib/treebuild.xml b/deps/zlib/treebuild.xml deleted file mode 100644 index fd75525f99595d..00000000000000 --- a/deps/zlib/treebuild.xml +++ /dev/null @@ -1,116 +0,0 @@ - - - - zip compression library - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/deps/zlib/trees.c b/deps/zlib/trees.c index 50cf4b4571cfec..5f89d056ef9692 100644 --- a/deps/zlib/trees.c +++ b/deps/zlib/trees.c @@ -416,7 +416,7 @@ local void init_block(s) s->dyn_ltree[END_BLOCK].Freq = 1; s->opt_len = s->static_len = 0L; - s->last_lit = s->matches = 0; + s->sym_next = s->matches = 0; } #define SMALLEST 1 @@ -947,7 +947,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->last_lit)); + s->sym_next / 3)); if (static_lenb <= opt_lenb) opt_lenb = static_lenb; @@ -1016,8 +1016,9 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc) unsigned dist; /* distance of matched string */ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ { - s->d_buf[s->last_lit] = (ush)dist; - s->l_buf[s->last_lit++] = (uch)lc; + s->sym_buf[s->sym_next++] = dist; + s->sym_buf[s->sym_next++] = dist >> 8; + s->sym_buf[s->sym_next++] = lc; if (dist == 0) { /* lc is the unmatched char */ s->dyn_ltree[lc].Freq++; @@ -1032,30 +1033,7 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc) s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; s->dyn_dtree[d_code(dist)].Freq++; } - -#ifdef TRUNCATE_BLOCK - /* Try to guess if it is profitable to stop the current block here */ - if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { - /* Compute an upper bound for the compressed length */ - ulg out_length = (ulg)s->last_lit*8L; - ulg in_length = (ulg)((long)s->strstart - s->block_start); - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (ulg)s->dyn_dtree[dcode].Freq * - (5L+extra_dbits[dcode]); - } - out_length >>= 3; - Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - s->last_lit, in_length, out_length, - 100L - out_length*100L/in_length)); - if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; - } -#endif - return (s->last_lit == s->lit_bufsize-1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ + return (s->sym_next == s->sym_end); } /* =========================================================================== @@ -1068,13 +1046,14 @@ local void compress_block(s, ltree, dtree) { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ + unsigned sx = 0; /* running index in sym_buf */ unsigned code; /* the code to send */ int extra; /* number of extra bits to send */ - if (s->last_lit != 0) do { - dist = s->d_buf[lx]; - lc = s->l_buf[lx++]; + if (s->sym_next != 0) do { + dist = s->sym_buf[sx++] & 0xff; + dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8; + lc = s->sym_buf[sx++]; if (dist == 0) { send_code(s, lc, ltree); /* send a literal byte */ Tracecv(isgraph(lc), (stderr," '%c' ", lc)); @@ -1099,11 +1078,10 @@ local void compress_block(s, ltree, dtree) } } /* literal or match pair ? */ - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - "pendingBuf overflow"); + /* Check that the overlay between pending_buf and sym_buf is ok: */ + Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); - } while (lx < s->last_lit); + } while (sx < s->sym_next); send_code(s, END_BLOCK, ltree); } diff --git a/deps/zlib/watcom/watcom_f.mak b/deps/zlib/watcom/watcom_f.mak deleted file mode 100644 index 37f4d74c19c0a3..00000000000000 --- a/deps/zlib/watcom/watcom_f.mak +++ /dev/null @@ -1,43 +0,0 @@ -# Makefile for zlib -# OpenWatcom flat model -# Last updated: 28-Dec-2005 - -# To use, do "wmake -f watcom_f.mak" - -C_SOURCE = adler32.c compress.c crc32.c deflate.c & - gzclose.c gzlib.c gzread.c gzwrite.c & - infback.c inffast.c inflate.c inftrees.c & - trees.c uncompr.c zutil.c - -OBJS = adler32.obj compress.obj crc32.obj deflate.obj & - gzclose.obj gzlib.obj gzread.obj gzwrite.obj & - infback.obj inffast.obj inflate.obj inftrees.obj & - trees.obj uncompr.obj zutil.obj - -CC = wcc386 -LINKER = wcl386 -CFLAGS = -zq -mf -3r -fp3 -s -bt=dos -oilrtfm -fr=nul -wx -ZLIB_LIB = zlib_f.lib - -.C.OBJ: - $(CC) $(CFLAGS) $[@ - -all: $(ZLIB_LIB) example.exe minigzip.exe - -$(ZLIB_LIB): $(OBJS) - wlib -b -c $(ZLIB_LIB) -+adler32.obj -+compress.obj -+crc32.obj - wlib -b -c $(ZLIB_LIB) -+gzclose.obj -+gzlib.obj -+gzread.obj -+gzwrite.obj - wlib -b -c $(ZLIB_LIB) -+deflate.obj -+infback.obj - wlib -b -c $(ZLIB_LIB) -+inffast.obj -+inflate.obj -+inftrees.obj - wlib -b -c $(ZLIB_LIB) -+trees.obj -+uncompr.obj -+zutil.obj - -example.exe: $(ZLIB_LIB) example.obj - $(LINKER) -ldos32a -fe=example.exe example.obj $(ZLIB_LIB) - -minigzip.exe: $(ZLIB_LIB) minigzip.obj - $(LINKER) -ldos32a -fe=minigzip.exe minigzip.obj $(ZLIB_LIB) - -clean: .SYMBOLIC - del *.obj - del $(ZLIB_LIB) - @echo Cleaning done diff --git a/deps/zlib/watcom/watcom_l.mak b/deps/zlib/watcom/watcom_l.mak deleted file mode 100644 index 193eed7b318a60..00000000000000 --- a/deps/zlib/watcom/watcom_l.mak +++ /dev/null @@ -1,43 +0,0 @@ -# Makefile for zlib -# OpenWatcom large model -# Last updated: 28-Dec-2005 - -# To use, do "wmake -f watcom_l.mak" - -C_SOURCE = adler32.c compress.c crc32.c deflate.c & - gzclose.c gzlib.c gzread.c gzwrite.c & - infback.c inffast.c inflate.c inftrees.c & - trees.c uncompr.c zutil.c - -OBJS = adler32.obj compress.obj crc32.obj deflate.obj & - gzclose.obj gzlib.obj gzread.obj gzwrite.obj & - infback.obj inffast.obj inflate.obj inftrees.obj & - trees.obj uncompr.obj zutil.obj - -CC = wcc -LINKER = wcl -CFLAGS = -zq -ml -s -bt=dos -oilrtfm -fr=nul -wx -ZLIB_LIB = zlib_l.lib - -.C.OBJ: - $(CC) $(CFLAGS) $[@ - -all: $(ZLIB_LIB) example.exe minigzip.exe - -$(ZLIB_LIB): $(OBJS) - wlib -b -c $(ZLIB_LIB) -+adler32.obj -+compress.obj -+crc32.obj - wlib -b -c $(ZLIB_LIB) -+gzclose.obj -+gzlib.obj -+gzread.obj -+gzwrite.obj - wlib -b -c $(ZLIB_LIB) -+deflate.obj -+infback.obj - wlib -b -c $(ZLIB_LIB) -+inffast.obj -+inflate.obj -+inftrees.obj - wlib -b -c $(ZLIB_LIB) -+trees.obj -+uncompr.obj -+zutil.obj - -example.exe: $(ZLIB_LIB) example.obj - $(LINKER) -fe=example.exe example.obj $(ZLIB_LIB) - -minigzip.exe: $(ZLIB_LIB) minigzip.obj - $(LINKER) -fe=minigzip.exe minigzip.obj $(ZLIB_LIB) - -clean: .SYMBOLIC - del *.obj - del $(ZLIB_LIB) - @echo Cleaning done diff --git a/deps/zlib/win32/DLL_FAQ.txt b/deps/zlib/win32/DLL_FAQ.txt deleted file mode 100644 index 12c009018c3775..00000000000000 --- a/deps/zlib/win32/DLL_FAQ.txt +++ /dev/null @@ -1,397 +0,0 @@ - - Frequently Asked Questions about ZLIB1.DLL - - -This document describes the design, the rationale, and the usage -of the official DLL build of zlib, named ZLIB1.DLL. If you have -general questions about zlib, you should see the file "FAQ" found -in the zlib distribution, or at the following location: - http://www.gzip.org/zlib/zlib_faq.html - - - 1. What is ZLIB1.DLL, and how can I get it? - - - ZLIB1.DLL is the official build of zlib as a DLL. - (Please remark the character '1' in the name.) - - Pointers to a precompiled ZLIB1.DLL can be found in the zlib - web site at: - http://www.zlib.net/ - - Applications that link to ZLIB1.DLL can rely on the following - specification: - - * The exported symbols are exclusively defined in the source - files "zlib.h" and "zlib.def", found in an official zlib - source distribution. - * The symbols are exported by name, not by ordinal. - * The exported names are undecorated. - * The calling convention of functions is "C" (CDECL). - * The ZLIB1.DLL binary is linked to MSVCRT.DLL. - - The archive in which ZLIB1.DLL is bundled contains compiled - test programs that must run with a valid build of ZLIB1.DLL. - It is recommended to download the prebuilt DLL from the zlib - web site, instead of building it yourself, to avoid potential - incompatibilities that could be introduced by your compiler - and build settings. If you do build the DLL yourself, please - make sure that it complies with all the above requirements, - and it runs with the precompiled test programs, bundled with - the original ZLIB1.DLL distribution. - - If, for any reason, you need to build an incompatible DLL, - please use a different file name. - - - 2. Why did you change the name of the DLL to ZLIB1.DLL? - What happened to the old ZLIB.DLL? - - - The old ZLIB.DLL, built from zlib-1.1.4 or earlier, required - compilation settings that were incompatible to those used by - a static build. The DLL settings were supposed to be enabled - by defining the macro ZLIB_DLL, before including "zlib.h". - Incorrect handling of this macro was silently accepted at - build time, resulting in two major problems: - - * ZLIB_DLL was missing from the old makefile. When building - the DLL, not all people added it to the build options. In - consequence, incompatible incarnations of ZLIB.DLL started - to circulate around the net. - - * When switching from using the static library to using the - DLL, applications had to define the ZLIB_DLL macro and - to recompile all the sources that contained calls to zlib - functions. Failure to do so resulted in creating binaries - that were unable to run with the official ZLIB.DLL build. - - The only possible solution that we could foresee was to make - a binary-incompatible change in the DLL interface, in order to - remove the dependency on the ZLIB_DLL macro, and to release - the new DLL under a different name. - - We chose the name ZLIB1.DLL, where '1' indicates the major - zlib version number. We hope that we will not have to break - the binary compatibility again, at least not as long as the - zlib-1.x series will last. - - There is still a ZLIB_DLL macro, that can trigger a more - efficient build and use of the DLL, but compatibility no - longer dependents on it. - - - 3. Can I build ZLIB.DLL from the new zlib sources, and replace - an old ZLIB.DLL, that was built from zlib-1.1.4 or earlier? - - - In principle, you can do it by assigning calling convention - keywords to the macros ZEXPORT and ZEXPORTVA. In practice, - it depends on what you mean by "an old ZLIB.DLL", because the - old DLL exists in several mutually-incompatible versions. - You have to find out first what kind of calling convention is - being used in your particular ZLIB.DLL build, and to use the - same one in the new build. If you don't know what this is all - about, you might be better off if you would just leave the old - DLL intact. - - - 4. Can I compile my application using the new zlib interface, and - link it to an old ZLIB.DLL, that was built from zlib-1.1.4 or - earlier? - - - The official answer is "no"; the real answer depends again on - what kind of ZLIB.DLL you have. Even if you are lucky, this - course of action is unreliable. - - If you rebuild your application and you intend to use a newer - version of zlib (post- 1.1.4), it is strongly recommended to - link it to the new ZLIB1.DLL. - - - 5. Why are the zlib symbols exported by name, and not by ordinal? - - - Although exporting symbols by ordinal is a little faster, it - is risky. Any single glitch in the maintenance or use of the - DEF file that contains the ordinals can result in incompatible - builds and frustrating crashes. Simply put, the benefits of - exporting symbols by ordinal do not justify the risks. - - Technically, it should be possible to maintain ordinals in - the DEF file, and still export the symbols by name. Ordinals - exist in every DLL, and even if the dynamic linking performed - at the DLL startup is searching for names, ordinals serve as - hints, for a faster name lookup. However, if the DEF file - contains ordinals, the Microsoft linker automatically builds - an implib that will cause the executables linked to it to use - those ordinals, and not the names. It is interesting to - notice that the GNU linker for Win32 does not suffer from this - problem. - - It is possible to avoid the DEF file if the exported symbols - are accompanied by a "__declspec(dllexport)" attribute in the - source files. You can do this in zlib by predefining the - ZLIB_DLL macro. - - - 6. I see that the ZLIB1.DLL functions use the "C" (CDECL) calling - convention. Why not use the STDCALL convention? - STDCALL is the standard convention in Win32, and I need it in - my Visual Basic project! - - (For readability, we use CDECL to refer to the convention - triggered by the "__cdecl" keyword, STDCALL to refer to - the convention triggered by "__stdcall", and FASTCALL to - refer to the convention triggered by "__fastcall".) - - - Most of the native Windows API functions (without varargs) use - indeed the WINAPI convention (which translates to STDCALL in - Win32), but the standard C functions use CDECL. If a user - application is intrinsically tied to the Windows API (e.g. - it calls native Windows API functions such as CreateFile()), - sometimes it makes sense to decorate its own functions with - WINAPI. But if ANSI C or POSIX portability is a goal (e.g. - it calls standard C functions such as fopen()), it is not a - sound decision to request the inclusion of , or to - use non-ANSI constructs, for the sole purpose to make the user - functions STDCALL-able. - - The functionality offered by zlib is not in the category of - "Windows functionality", but is more like "C functionality". - - Technically, STDCALL is not bad; in fact, it is slightly - faster than CDECL, and it works with variable-argument - functions, just like CDECL. It is unfortunate that, in spite - of using STDCALL in the Windows API, it is not the default - convention used by the C compilers that run under Windows. - The roots of the problem reside deep inside the unsafety of - the K&R-style function prototypes, where the argument types - are not specified; but that is another story for another day. - - The remaining fact is that CDECL is the default convention. - Even if an explicit convention is hard-coded into the function - prototypes inside C headers, problems may appear. The - necessity to expose the convention in users' callbacks is one - of these problems. - - The calling convention issues are also important when using - zlib in other programming languages. Some of them, like Ada - (GNAT) and Fortran (GNU G77), have C bindings implemented - initially on Unix, and relying on the C calling convention. - On the other hand, the pre- .NET versions of Microsoft Visual - Basic require STDCALL, while Borland Delphi prefers, although - it does not require, FASTCALL. - - In fairness to all possible uses of zlib outside the C - programming language, we choose the default "C" convention. - Anyone interested in different bindings or conventions is - encouraged to maintain specialized projects. The "contrib/" - directory from the zlib distribution already holds a couple - of foreign bindings, such as Ada, C++, and Delphi. - - - 7. I need a DLL for my Visual Basic project. What can I do? - - - Define the ZLIB_WINAPI macro before including "zlib.h", when - building both the DLL and the user application (except that - you don't need to define anything when using the DLL in Visual - Basic). The ZLIB_WINAPI macro will switch on the WINAPI - (STDCALL) convention. The name of this DLL must be different - than the official ZLIB1.DLL. - - Gilles Vollant has contributed a build named ZLIBWAPI.DLL, - with the ZLIB_WINAPI macro turned on, and with the minizip - functionality built in. For more information, please read - the notes inside "contrib/vstudio/readme.txt", found in the - zlib distribution. - - - 8. I need to use zlib in my Microsoft .NET project. What can I - do? - - - Henrik Ravn has contributed a .NET wrapper around zlib. Look - into contrib/dotzlib/, inside the zlib distribution. - - - 9. If my application uses ZLIB1.DLL, should I link it to - MSVCRT.DLL? Why? - - - It is not required, but it is recommended to link your - application to MSVCRT.DLL, if it uses ZLIB1.DLL. - - The executables (.EXE, .DLL, etc.) that are involved in the - same process and are using the C run-time library (i.e. they - are calling standard C functions), must link to the same - library. There are several libraries in the Win32 system: - CRTDLL.DLL, MSVCRT.DLL, the static C libraries, etc. - Since ZLIB1.DLL is linked to MSVCRT.DLL, the executables that - depend on it should also be linked to MSVCRT.DLL. - - -10. Why are you saying that ZLIB1.DLL and my application should - be linked to the same C run-time (CRT) library? I linked my - application and my DLLs to different C libraries (e.g. my - application to a static library, and my DLLs to MSVCRT.DLL), - and everything works fine. - - - If a user library invokes only pure Win32 API (accessible via - and the related headers), its DLL build will work - in any context. But if this library invokes standard C API, - things get more complicated. - - There is a single Win32 library in a Win32 system. Every - function in this library resides in a single DLL module, that - is safe to call from anywhere. On the other hand, there are - multiple versions of the C library, and each of them has its - own separate internal state. Standalone executables and user - DLLs that call standard C functions must link to a C run-time - (CRT) library, be it static or shared (DLL). Intermixing - occurs when an executable (not necessarily standalone) and a - DLL are linked to different CRTs, and both are running in the - same process. - - Intermixing multiple CRTs is possible, as long as their - internal states are kept intact. The Microsoft Knowledge Base - articles KB94248 "HOWTO: Use the C Run-Time" and KB140584 - "HOWTO: Link with the Correct C Run-Time (CRT) Library" - mention the potential problems raised by intermixing. - - If intermixing works for you, it's because your application - and DLLs are avoiding the corruption of each of the CRTs' - internal states, maybe by careful design, or maybe by fortune. - - Also note that linking ZLIB1.DLL to non-Microsoft CRTs, such - as those provided by Borland, raises similar problems. - - -11. Why are you linking ZLIB1.DLL to MSVCRT.DLL? - - - MSVCRT.DLL exists on every Windows 95 with a new service pack - installed, or with Microsoft Internet Explorer 4 or later, and - on all other Windows 4.x or later (Windows 98, Windows NT 4, - or later). It is freely distributable; if not present in the - system, it can be downloaded from Microsoft or from other - software provider for free. - - The fact that MSVCRT.DLL does not exist on a virgin Windows 95 - is not so problematic. Windows 95 is scarcely found nowadays, - Microsoft ended its support a long time ago, and many recent - applications from various vendors, including Microsoft, do not - even run on it. Furthermore, no serious user should run - Windows 95 without a proper update installed. - - -12. Why are you not linking ZLIB1.DLL to - <> ? - - - We considered and abandoned the following alternatives: - - * Linking ZLIB1.DLL to a static C library (LIBC.LIB, or - LIBCMT.LIB) is not a good option. People are using the DLL - mainly to save disk space. If you are linking your program - to a static C library, you may as well consider linking zlib - in statically, too. - - * Linking ZLIB1.DLL to CRTDLL.DLL looks appealing, because - CRTDLL.DLL is present on every Win32 installation. - Unfortunately, it has a series of problems: it does not - work properly with Microsoft's C++ libraries, it does not - provide support for 64-bit file offsets, (and so on...), - and Microsoft discontinued its support a long time ago. - - * Linking ZLIB1.DLL to MSVCR70.DLL or MSVCR71.DLL, supplied - with the Microsoft .NET platform, and Visual C++ 7.0/7.1, - raises problems related to the status of ZLIB1.DLL as a - system component. According to the Microsoft Knowledge Base - article KB326922 "INFO: Redistribution of the Shared C - Runtime Component in Visual C++ .NET", MSVCR70.DLL and - MSVCR71.DLL are not supposed to function as system DLLs, - because they may clash with MSVCRT.DLL. Instead, the - application's installer is supposed to put these DLLs - (if needed) in the application's private directory. - If ZLIB1.DLL depends on a non-system runtime, it cannot - function as a redistributable system component. - - * Linking ZLIB1.DLL to non-Microsoft runtimes, such as - Borland's, or Cygwin's, raises problems related to the - reliable presence of these runtimes on Win32 systems. - It's easier to let the DLL build of zlib up to the people - who distribute these runtimes, and who may proceed as - explained in the answer to Question 14. - - -13. If ZLIB1.DLL cannot be linked to MSVCR70.DLL or MSVCR71.DLL, - how can I build/use ZLIB1.DLL in Microsoft Visual C++ 7.0 - (Visual Studio .NET) or newer? - - - Due to the problems explained in the Microsoft Knowledge Base - article KB326922 (see the previous answer), the C runtime that - comes with the VC7 environment is no longer considered a - system component. That is, it should not be assumed that this - runtime exists, or may be installed in a system directory. - Since ZLIB1.DLL is supposed to be a system component, it may - not depend on a non-system component. - - In order to link ZLIB1.DLL and your application to MSVCRT.DLL - in VC7, you need the library of Visual C++ 6.0 or older. If - you don't have this library at hand, it's probably best not to - use ZLIB1.DLL. - - We are hoping that, in the future, Microsoft will provide a - way to build applications linked to a proper system runtime, - from the Visual C++ environment. Until then, you have a - couple of alternatives, such as linking zlib in statically. - If your application requires dynamic linking, you may proceed - as explained in the answer to Question 14. - - -14. I need to link my own DLL build to a CRT different than - MSVCRT.DLL. What can I do? - - - Feel free to rebuild the DLL from the zlib sources, and link - it the way you want. You should, however, clearly state that - your build is unofficial. You should give it a different file - name, and/or install it in a private directory that can be - accessed by your application only, and is not visible to the - others (i.e. it's neither in the PATH, nor in the SYSTEM or - SYSTEM32 directories). Otherwise, your build may clash with - applications that link to the official build. - - For example, in Cygwin, zlib is linked to the Cygwin runtime - CYGWIN1.DLL, and it is distributed under the name CYGZ.DLL. - - -15. May I include additional pieces of code that I find useful, - link them in ZLIB1.DLL, and export them? - - - No. A legitimate build of ZLIB1.DLL must not include code - that does not originate from the official zlib source code. - But you can make your own private DLL build, under a different - file name, as suggested in the previous answer. - - For example, zlib is a part of the VCL library, distributed - with Borland Delphi and C++ Builder. The DLL build of VCL - is a redistributable file, named VCLxx.DLL. - - -16. May I remove some functionality out of ZLIB1.DLL, by enabling - macros like NO_GZCOMPRESS or NO_GZIP at compile time? - - - No. A legitimate build of ZLIB1.DLL must provide the complete - zlib functionality, as implemented in the official zlib source - code. But you can make your own private DLL build, under a - different file name, as suggested in the previous answer. - - -17. I made my own ZLIB1.DLL build. Can I test it for compliance? - - - We prefer that you download the official DLL from the zlib - web site. If you need something peculiar from this DLL, you - can send your suggestion to the zlib mailing list. - - However, in case you do rebuild the DLL yourself, you can run - it with the test programs found in the DLL distribution. - Running these test programs is not a guarantee of compliance, - but a failure can imply a detected problem. - -** - -This document is written and maintained by -Cosmin Truta diff --git a/deps/zlib/win32/Makefile.bor b/deps/zlib/win32/Makefile.bor deleted file mode 100644 index d152bbb7ffd951..00000000000000 --- a/deps/zlib/win32/Makefile.bor +++ /dev/null @@ -1,110 +0,0 @@ -# Makefile for zlib -# Borland C++ for Win32 -# -# Usage: -# make -f win32/Makefile.bor -# make -f win32/Makefile.bor LOCAL_ZLIB=-DASMV OBJA=match.obj OBJPA=+match.obj - -# ------------ Borland C++ ------------ - -# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) -# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or -# added to the declaration of LOC here: -LOC = $(LOCAL_ZLIB) - -CC = bcc32 -AS = bcc32 -LD = bcc32 -AR = tlib -CFLAGS = -a -d -k- -O2 $(LOC) -ASFLAGS = $(LOC) -LDFLAGS = $(LOC) - - -# variables -ZLIB_LIB = zlib.lib - -OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj -OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj -#OBJA = -OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj -OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj -#OBJPA= - - -# targets -all: $(ZLIB_LIB) example.exe minigzip.exe - -.c.obj: - $(CC) -c $(CFLAGS) $< - -.asm.obj: - $(AS) -c $(ASFLAGS) $< - -adler32.obj: adler32.c zlib.h zconf.h - -compress.obj: compress.c zlib.h zconf.h - -crc32.obj: crc32.c zlib.h zconf.h crc32.h - -deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h - -gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h - -gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h - -gzread.obj: gzread.c zlib.h zconf.h gzguts.h - -gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h - -infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h - -inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h - -trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h - -uncompr.obj: uncompr.c zlib.h zconf.h - -zutil.obj: zutil.c zutil.h zlib.h zconf.h - -example.obj: test/example.c zlib.h zconf.h - -minigzip.obj: test/minigzip.c zlib.h zconf.h - - -# For the sake of the old Borland make, -# the command line is cut to fit in the MS-DOS 128 byte limit: -$(ZLIB_LIB): $(OBJ1) $(OBJ2) $(OBJA) - -del $(ZLIB_LIB) - $(AR) $(ZLIB_LIB) $(OBJP1) - $(AR) $(ZLIB_LIB) $(OBJP2) - $(AR) $(ZLIB_LIB) $(OBJPA) - - -# testing -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -example.exe: example.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) - -minigzip.exe: minigzip.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) - - -# cleanup -clean: - -del $(ZLIB_LIB) - -del *.obj - -del *.exe - -del *.tds - -del zlib.bak - -del foo.gz diff --git a/deps/zlib/win32/Makefile.gcc b/deps/zlib/win32/Makefile.gcc deleted file mode 100644 index 305be50afef665..00000000000000 --- a/deps/zlib/win32/Makefile.gcc +++ /dev/null @@ -1,182 +0,0 @@ -# Makefile for zlib, derived from Makefile.dj2. -# Modified for mingw32 by C. Spieler, 6/16/98. -# Updated for zlib 1.2.x by Christian Spieler and Cosmin Truta, Mar-2003. -# Last updated: Mar 2012. -# Tested under Cygwin and MinGW. - -# Copyright (C) 1995-2003 Jean-loup Gailly. -# For conditions of distribution and use, see copyright notice in zlib.h - -# To compile, or to compile and test, type from the top level zlib directory: -# -# make -fwin32/Makefile.gcc; make test testdll -fwin32/Makefile.gcc -# -# To use the asm code, type: -# cp contrib/asm?86/match.S ./match.S -# make LOC=-DASMV OBJA=match.o -fwin32/Makefile.gcc -# -# To install libz.a, zconf.h and zlib.h in the system directories, type: -# -# make install -fwin32/Makefile.gcc -# -# BINARY_PATH, INCLUDE_PATH and LIBRARY_PATH must be set. -# -# To install the shared lib, append SHARED_MODE=1 to the make command : -# -# make install -fwin32/Makefile.gcc SHARED_MODE=1 - -# Note: -# If the platform is *not* MinGW (e.g. it is Cygwin or UWIN), -# the DLL name should be changed from "zlib1.dll". - -STATICLIB = libz.a -SHAREDLIB = zlib1.dll -IMPLIB = libz.dll.a - -# -# Set to 1 if shared object needs to be installed -# -SHARED_MODE=0 - -#LOC = -DASMV -#LOC = -DZLIB_DEBUG -g - -PREFIX = -CC = $(PREFIX)gcc -CFLAGS = $(LOC) -O3 -Wall - -AS = $(CC) -ASFLAGS = $(LOC) -Wall - -LD = $(CC) -LDFLAGS = $(LOC) - -AR = $(PREFIX)ar -ARFLAGS = rcs - -RC = $(PREFIX)windres -RCFLAGS = --define GCC_WINDRES - -STRIP = $(PREFIX)strip - -CP = cp -fp -# If GNU install is available, replace $(CP) with install. -INSTALL = $(CP) -RM = rm -f - -prefix ?= /usr/local -exec_prefix = $(prefix) - -OBJS = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o \ - gzwrite.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o -OBJA = - -all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) example.exe minigzip.exe example_d.exe minigzip_d.exe - -test: example.exe minigzip.exe - ./example - echo hello world | ./minigzip | ./minigzip -d - -testdll: example_d.exe minigzip_d.exe - ./example_d - echo hello world | ./minigzip_d | ./minigzip_d -d - -.c.o: - $(CC) $(CFLAGS) -c -o $@ $< - -.S.o: - $(AS) $(ASFLAGS) -c -o $@ $< - -$(STATICLIB): $(OBJS) $(OBJA) - $(AR) $(ARFLAGS) $@ $(OBJS) $(OBJA) - -$(IMPLIB): $(SHAREDLIB) - -$(SHAREDLIB): win32/zlib.def $(OBJS) $(OBJA) zlibrc.o - $(CC) -shared -Wl,--out-implib,$(IMPLIB) $(LDFLAGS) \ - -o $@ win32/zlib.def $(OBJS) $(OBJA) zlibrc.o - $(STRIP) $@ - -example.exe: example.o $(STATICLIB) - $(LD) $(LDFLAGS) -o $@ example.o $(STATICLIB) - $(STRIP) $@ - -minigzip.exe: minigzip.o $(STATICLIB) - $(LD) $(LDFLAGS) -o $@ minigzip.o $(STATICLIB) - $(STRIP) $@ - -example_d.exe: example.o $(IMPLIB) - $(LD) $(LDFLAGS) -o $@ example.o $(IMPLIB) - $(STRIP) $@ - -minigzip_d.exe: minigzip.o $(IMPLIB) - $(LD) $(LDFLAGS) -o $@ minigzip.o $(IMPLIB) - $(STRIP) $@ - -example.o: test/example.c zlib.h zconf.h - $(CC) $(CFLAGS) -I. -c -o $@ test/example.c - -minigzip.o: test/minigzip.c zlib.h zconf.h - $(CC) $(CFLAGS) -I. -c -o $@ test/minigzip.c - -zlibrc.o: win32/zlib1.rc - $(RC) $(RCFLAGS) -o $@ win32/zlib1.rc - -.PHONY: install uninstall clean - -install: zlib.h zconf.h $(STATICLIB) $(IMPLIB) - @if test -z "$(DESTDIR)$(INCLUDE_PATH)" -o -z "$(DESTDIR)$(LIBRARY_PATH)" -o -z "$(DESTDIR)$(BINARY_PATH)"; then \ - echo INCLUDE_PATH, LIBRARY_PATH, and BINARY_PATH must be specified; \ - exit 1; \ - fi - -@mkdir -p '$(DESTDIR)$(INCLUDE_PATH)' - -@mkdir -p '$(DESTDIR)$(LIBRARY_PATH)' '$(DESTDIR)$(LIBRARY_PATH)'/pkgconfig - -if [ "$(SHARED_MODE)" = "1" ]; then \ - mkdir -p '$(DESTDIR)$(BINARY_PATH)'; \ - $(INSTALL) $(SHAREDLIB) '$(DESTDIR)$(BINARY_PATH)'; \ - $(INSTALL) $(IMPLIB) '$(DESTDIR)$(LIBRARY_PATH)'; \ - fi - -$(INSTALL) zlib.h '$(DESTDIR)$(INCLUDE_PATH)' - -$(INSTALL) zconf.h '$(DESTDIR)$(INCLUDE_PATH)' - -$(INSTALL) $(STATICLIB) '$(DESTDIR)$(LIBRARY_PATH)' - sed \ - -e 's|@prefix@|${prefix}|g' \ - -e 's|@exec_prefix@|${exec_prefix}|g' \ - -e 's|@libdir@|$(LIBRARY_PATH)|g' \ - -e 's|@sharedlibdir@|$(LIBRARY_PATH)|g' \ - -e 's|@includedir@|$(INCLUDE_PATH)|g' \ - -e 's|@VERSION@|'`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' zlib.h`'|g' \ - zlib.pc.in > '$(DESTDIR)$(LIBRARY_PATH)'/pkgconfig/zlib.pc - -uninstall: - -if [ "$(SHARED_MODE)" = "1" ]; then \ - $(RM) '$(DESTDIR)$(BINARY_PATH)'/$(SHAREDLIB); \ - $(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(IMPLIB); \ - fi - -$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zlib.h - -$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zconf.h - -$(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(STATICLIB) - -clean: - -$(RM) $(STATICLIB) - -$(RM) $(SHAREDLIB) - -$(RM) $(IMPLIB) - -$(RM) *.o - -$(RM) *.exe - -$(RM) foo.gz - -adler32.o: zlib.h zconf.h -compress.o: zlib.h zconf.h -crc32.o: crc32.h zlib.h zconf.h -deflate.o: deflate.h zutil.h zlib.h zconf.h -gzclose.o: zlib.h zconf.h gzguts.h -gzlib.o: zlib.h zconf.h gzguts.h -gzread.o: zlib.h zconf.h gzguts.h -gzwrite.o: zlib.h zconf.h gzguts.h -inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -inftrees.o: zutil.h zlib.h zconf.h inftrees.h -trees.o: deflate.h zutil.h zlib.h zconf.h trees.h -uncompr.o: zlib.h zconf.h -zutil.o: zutil.h zlib.h zconf.h diff --git a/deps/zlib/win32/Makefile.msc b/deps/zlib/win32/Makefile.msc deleted file mode 100644 index 6831882de43e6c..00000000000000 --- a/deps/zlib/win32/Makefile.msc +++ /dev/null @@ -1,163 +0,0 @@ -# Makefile for zlib using Microsoft (Visual) C -# zlib is copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler -# -# Usage: -# nmake -f win32/Makefile.msc (standard build) -# nmake -f win32/Makefile.msc LOC=-DFOO (nonstandard build) -# nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" \ -# OBJA="inffas32.obj match686.obj" (use ASM code, x86) -# nmake -f win32/Makefile.msc AS=ml64 LOC="-DASMV -DASMINF -I." \ -# OBJA="inffasx64.obj gvmat64.obj inffas8664.obj" (use ASM code, x64) - -# The toplevel directory of the source tree. -# -TOP = . - -# optional build flags -LOC = - -# variables -STATICLIB = zlib.lib -SHAREDLIB = zlib1.dll -IMPLIB = zdll.lib - -CC = cl -AS = ml -LD = link -AR = lib -RC = rc -CFLAGS = -nologo -MD -W3 -O2 -Oy- -Zi -Fd"zlib" $(LOC) -WFLAGS = -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -ASFLAGS = -coff -Zi $(LOC) -LDFLAGS = -nologo -debug -incremental:no -opt:ref -ARFLAGS = -nologo -RCFLAGS = /dWIN32 /r - -OBJS = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj \ - gzwrite.obj infback.obj inflate.obj inftrees.obj inffast.obj trees.obj uncompr.obj zutil.obj -OBJA = - - -# targets -all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \ - example.exe minigzip.exe example_d.exe minigzip_d.exe - -$(STATICLIB): $(OBJS) $(OBJA) - $(AR) $(ARFLAGS) -out:$@ $(OBJS) $(OBJA) - -$(IMPLIB): $(SHAREDLIB) - -$(SHAREDLIB): $(TOP)/win32/zlib.def $(OBJS) $(OBJA) zlib1.res - $(LD) $(LDFLAGS) -def:$(TOP)/win32/zlib.def -dll -implib:$(IMPLIB) \ - -out:$@ -base:0x5A4C0000 $(OBJS) $(OBJA) zlib1.res - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;2 - -example.exe: example.obj $(STATICLIB) - $(LD) $(LDFLAGS) example.obj $(STATICLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -minigzip.exe: minigzip.obj $(STATICLIB) - $(LD) $(LDFLAGS) minigzip.obj $(STATICLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -example_d.exe: example.obj $(IMPLIB) - $(LD) $(LDFLAGS) -out:$@ example.obj $(IMPLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -minigzip_d.exe: minigzip.obj $(IMPLIB) - $(LD) $(LDFLAGS) -out:$@ minigzip.obj $(IMPLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -{$(TOP)}.c.obj: - $(CC) -c $(WFLAGS) $(CFLAGS) $< - -{$(TOP)/test}.c.obj: - $(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) $< - -{$(TOP)/contrib/masmx64}.c.obj: - $(CC) -c $(WFLAGS) $(CFLAGS) $< - -{$(TOP)/contrib/masmx64}.asm.obj: - $(AS) -c $(ASFLAGS) $< - -{$(TOP)/contrib/masmx86}.asm.obj: - $(AS) -c $(ASFLAGS) $< - -adler32.obj: $(TOP)/adler32.c $(TOP)/zlib.h $(TOP)/zconf.h - -compress.obj: $(TOP)/compress.c $(TOP)/zlib.h $(TOP)/zconf.h - -crc32.obj: $(TOP)/crc32.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/crc32.h - -deflate.obj: $(TOP)/deflate.c $(TOP)/deflate.h $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h - -gzclose.obj: $(TOP)/gzclose.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h - -gzlib.obj: $(TOP)/gzlib.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h - -gzread.obj: $(TOP)/gzread.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h - -gzwrite.obj: $(TOP)/gzwrite.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h - -infback.obj: $(TOP)/infback.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \ - $(TOP)/inffast.h $(TOP)/inffixed.h - -inffast.obj: $(TOP)/inffast.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \ - $(TOP)/inffast.h - -inflate.obj: $(TOP)/inflate.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \ - $(TOP)/inffast.h $(TOP)/inffixed.h - -inftrees.obj: $(TOP)/inftrees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h - -trees.obj: $(TOP)/trees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/deflate.h $(TOP)/trees.h - -uncompr.obj: $(TOP)/uncompr.c $(TOP)/zlib.h $(TOP)/zconf.h - -zutil.obj: $(TOP)/zutil.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h - -gvmat64.obj: $(TOP)/contrib\masmx64\gvmat64.asm - -inffasx64.obj: $(TOP)/contrib\masmx64\inffasx64.asm - -inffas8664.obj: $(TOP)/contrib\masmx64\inffas8664.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h \ - $(TOP)/inftrees.h $(TOP)/inflate.h $(TOP)/inffast.h - -inffas32.obj: $(TOP)/contrib\masmx86\inffas32.asm - -match686.obj: $(TOP)/contrib\masmx86\match686.asm - -example.obj: $(TOP)/test/example.c $(TOP)/zlib.h $(TOP)/zconf.h - -minigzip.obj: $(TOP)/test/minigzip.c $(TOP)/zlib.h $(TOP)/zconf.h - -zlib1.res: $(TOP)/win32/zlib1.rc - $(RC) $(RCFLAGS) /fo$@ $(TOP)/win32/zlib1.rc - -# testing -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -testdll: example_d.exe minigzip_d.exe - example_d - echo hello world | minigzip_d | minigzip_d -d - - -# cleanup -clean: - -del $(STATICLIB) - -del $(SHAREDLIB) - -del $(IMPLIB) - -del *.obj - -del *.res - -del *.exp - -del *.exe - -del *.pdb - -del *.manifest - -del foo.gz diff --git a/deps/zlib/win32/README-WIN32.txt b/deps/zlib/win32/README-WIN32.txt deleted file mode 100644 index df7ab7f4b34f90..00000000000000 --- a/deps/zlib/win32/README-WIN32.txt +++ /dev/null @@ -1,103 +0,0 @@ -ZLIB DATA COMPRESSION LIBRARY - -zlib 1.2.11 is a general purpose data compression library. All the code is -thread safe. The data format used by the zlib library is described by RFCs -(Request for Comments) 1950 to 1952 in the files -http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) -and rfc1952.txt (gzip format). - -All functions of the compression library are documented in the file zlib.h -(volunteer to write man pages welcome, contact zlib@gzip.org). Two compiled -examples are distributed in this package, example and minigzip. The example_d -and minigzip_d flavors validate that the zlib1.dll file is working correctly. - -Questions about zlib should be sent to . The zlib home page -is http://zlib.net/ . Before reporting a problem, please check this site to -verify that you have the latest version of zlib; otherwise get the latest -version and check whether the problem still exists or not. - -PLEASE read DLL_FAQ.txt, and the the zlib FAQ http://zlib.net/zlib_faq.html -before asking for help. - - -Manifest: - -The package zlib-1.2.11-win32-x86.zip will contain the following files: - - README-WIN32.txt This document - ChangeLog Changes since previous zlib packages - DLL_FAQ.txt Frequently asked questions about zlib1.dll - zlib.3.pdf Documentation of this library in Adobe Acrobat format - - example.exe A statically-bound example (using zlib.lib, not the dll) - example.pdb Symbolic information for debugging example.exe - - example_d.exe A zlib1.dll bound example (using zdll.lib) - example_d.pdb Symbolic information for debugging example_d.exe - - minigzip.exe A statically-bound test program (using zlib.lib, not the dll) - minigzip.pdb Symbolic information for debugging minigzip.exe - - minigzip_d.exe A zlib1.dll bound test program (using zdll.lib) - minigzip_d.pdb Symbolic information for debugging minigzip_d.exe - - zlib.h Install these files into the compilers' INCLUDE path to - zconf.h compile programs which use zlib.lib or zdll.lib - - zdll.lib Install these files into the compilers' LIB path if linking - zdll.exp a compiled program to the zlib1.dll binary - - zlib.lib Install these files into the compilers' LIB path to link zlib - zlib.pdb into compiled programs, without zlib1.dll runtime dependency - (zlib.pdb provides debugging info to the compile time linker) - - zlib1.dll Install this binary shared library into the system PATH, or - the program's runtime directory (where the .exe resides) - zlib1.pdb Install in the same directory as zlib1.dll, in order to debug - an application crash using WinDbg or similar tools. - -All .pdb files above are entirely optional, but are very useful to a developer -attempting to diagnose program misbehavior or a crash. Many additional -important files for developers can be found in the zlib127.zip source package -available from http://zlib.net/ - review that package's README file for details. - - -Acknowledgments: - -The deflate format used by zlib was defined by Phil Katz. The deflate and -zlib specifications were written by L. Peter Deutsch. Thanks to all the -people who reported problems and suggested various improvements in zlib; they -are too numerous to cite here. - - -Copyright notice: - - (C) 1995-2017 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - -If you use the zlib library in a product, we would appreciate *not* receiving -lengthy legal documents to sign. The sources are provided for free but without -warranty of any kind. The library has been entirely written by Jean-loup -Gailly and Mark Adler; it does not include third-party code. - -If you redistribute modified sources, we would appreciate that you include in -the file ChangeLog history information documenting your changes. Please read -the FAQ for more information on the distribution of modified source versions. diff --git a/deps/zlib/win32/VisualC.txt b/deps/zlib/win32/VisualC.txt deleted file mode 100644 index 1005b219410c77..00000000000000 --- a/deps/zlib/win32/VisualC.txt +++ /dev/null @@ -1,3 +0,0 @@ - -To build zlib using the Microsoft Visual C++ environment, -use the appropriate project from the contrib/vstudio/ directory. diff --git a/deps/zlib/win32/zlib1.rc b/deps/zlib/win32/zlib1.rc deleted file mode 100644 index 234e641c32947a..00000000000000 --- a/deps/zlib/win32/zlib1.rc +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include "../zlib.h" - -#ifdef GCC_WINDRES -VS_VERSION_INFO VERSIONINFO -#else -VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE -#endif - FILEVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 - PRODUCTVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS 1 -#else - FILEFLAGS 0 -#endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0 // not used -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - //language ID = U.S. English, char set = Windows, Multilingual - BEGIN - VALUE "FileDescription", "zlib data compression library\0" - VALUE "FileVersion", ZLIB_VERSION "\0" - VALUE "InternalName", "zlib1.dll\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" - VALUE "OriginalFilename", "zlib1.dll\0" - VALUE "ProductName", "zlib\0" - VALUE "ProductVersion", ZLIB_VERSION "\0" - VALUE "Comments", "For more information visit http://www.zlib.net/\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END -END diff --git a/deps/zlib/x86.c b/deps/zlib/x86.c new file mode 100644 index 00000000000000..7488ad08b976c8 --- /dev/null +++ b/deps/zlib/x86.c @@ -0,0 +1,101 @@ +/* + * x86 feature check + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * Author: + * Jim Kukunas + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "x86.h" +#include "zutil.h" + +int ZLIB_INTERNAL x86_cpu_enable_ssse3 = 0; +int ZLIB_INTERNAL x86_cpu_enable_simd = 0; + +#ifndef _MSC_VER +#include + +pthread_once_t cpu_check_inited_once = PTHREAD_ONCE_INIT; +static void _x86_check_features(void); + +void x86_check_features(void) +{ + pthread_once(&cpu_check_inited_once, _x86_check_features); +} + +static void _x86_check_features(void) +{ + int x86_cpu_has_sse2; + int x86_cpu_has_ssse3; + int x86_cpu_has_sse42; + int x86_cpu_has_pclmulqdq; + unsigned eax, ebx, ecx, edx; + + eax = 1; +#ifdef __i386__ + __asm__ __volatile__ ( + "xchg %%ebx, %1\n\t" + "cpuid\n\t" + "xchg %1, %%ebx\n\t" + : "+a" (eax), "=S" (ebx), "=c" (ecx), "=d" (edx) + ); +#else + __asm__ __volatile__ ( + "cpuid\n\t" + : "+a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) + ); +#endif /* (__i386__) */ + + x86_cpu_has_sse2 = edx & 0x4000000; + x86_cpu_has_ssse3 = ecx & 0x000200; + x86_cpu_has_sse42 = ecx & 0x100000; + x86_cpu_has_pclmulqdq = ecx & 0x2; + + x86_cpu_enable_ssse3 = x86_cpu_has_ssse3; + + x86_cpu_enable_simd = x86_cpu_has_sse2 && + x86_cpu_has_sse42 && + x86_cpu_has_pclmulqdq; +} +#else +#include +#include + +static BOOL CALLBACK _x86_check_features(PINIT_ONCE once, + PVOID param, + PVOID *context); +static INIT_ONCE cpu_check_inited_once = INIT_ONCE_STATIC_INIT; + +void x86_check_features(void) +{ + InitOnceExecuteOnce(&cpu_check_inited_once, _x86_check_features, + NULL, NULL); +} + +static BOOL CALLBACK _x86_check_features(PINIT_ONCE once, + PVOID param, + PVOID *context) +{ + int x86_cpu_has_sse2; + int x86_cpu_has_ssse3; + int x86_cpu_has_sse42; + int x86_cpu_has_pclmulqdq; + int regs[4]; + + __cpuid(regs, 1); + + x86_cpu_has_sse2 = regs[3] & 0x4000000; + x86_cpu_has_ssse3 = regs[2] & 0x000200; + x86_cpu_has_sse42 = regs[2] & 0x100000; + x86_cpu_has_pclmulqdq = regs[2] & 0x2; + + x86_cpu_enable_ssse3 = x86_cpu_has_ssse3; + + x86_cpu_enable_simd = x86_cpu_has_sse2 && + x86_cpu_has_sse42 && + x86_cpu_has_pclmulqdq; + return TRUE; +} +#endif /* _MSC_VER */ diff --git a/deps/zlib/x86.h b/deps/zlib/x86.h new file mode 100644 index 00000000000000..7205d50265c356 --- /dev/null +++ b/deps/zlib/x86.h @@ -0,0 +1,16 @@ +/* x86.h -- check for x86 CPU features +* Copyright (C) 2013 Intel Corporation Jim Kukunas +* For conditions of distribution and use, see copyright notice in zlib.h +*/ + +#ifndef X86_H +#define X86_H + +#include "zlib.h" + +extern int x86_cpu_enable_ssse3; +extern int x86_cpu_enable_simd; + +void x86_check_features(void); + +#endif /* X86_H */ diff --git a/deps/zlib/zconf.h b/deps/zlib/zconf.h index 5e1d68a004e974..353fd36f17e3e5 100644 --- a/deps/zlib/zconf.h +++ b/deps/zlib/zconf.h @@ -8,6 +8,18 @@ #ifndef ZCONF_H #define ZCONF_H +/* + * This library is also built as a part of AOSP, which does not need to include + * chromeconf.h. This config does not want chromeconf.h, so it can set this + * macro to opt out. While this works today, there's no guarantee that building + * zlib outside of Chromium keeps working in the future. + */ +#if !defined(CHROMIUM_ZLIB_NO_CHROMECONF) +/* This include does prefixing as below, but with an updated set of names. Also + * sets up export macros in component builds. */ +//#include "chromeconf.h" +#endif + /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. @@ -386,6 +398,9 @@ #ifndef FAR # define FAR #endif +#ifndef far +# define far +#endif #if !defined(__MACTYPES__) typedef unsigned char Byte; /* 8 bits */ @@ -431,7 +446,7 @@ typedef uLong FAR uLongf; typedef unsigned long z_crc_t; #endif -#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +#if !defined(_WIN32) # define Z_HAVE_UNISTD_H #endif diff --git a/deps/zlib/zconf.h.cmakein b/deps/zlib/zconf.h.cmakein deleted file mode 100644 index a7f24cce60ff7a..00000000000000 --- a/deps/zlib/zconf.h.cmakein +++ /dev/null @@ -1,536 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef ZCONF_H -#define ZCONF_H -#cmakedefine Z_PREFIX -#cmakedefine Z_HAVE_UNISTD_H - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - * Even better than compiling with -DZ_PREFIX would be to use configure to set - * this permanently in zconf.h using "./configure --zprefix". - */ -#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ -# define Z_PREFIX_SET - -/* all linked symbols and init macros */ -# define _dist_code z__dist_code -# define _length_code z__length_code -# define _tr_align z__tr_align -# define _tr_flush_bits z__tr_flush_bits -# define _tr_flush_block z__tr_flush_block -# define _tr_init z__tr_init -# define _tr_stored_block z__tr_stored_block -# define _tr_tally z__tr_tally -# define adler32 z_adler32 -# define adler32_combine z_adler32_combine -# define adler32_combine64 z_adler32_combine64 -# define adler32_z z_adler32_z -# ifndef Z_SOLO -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# endif -# define crc32 z_crc32 -# define crc32_combine z_crc32_combine -# define crc32_combine64 z_crc32_combine64 -# define crc32_z z_crc32_z -# define deflate z_deflate -# define deflateBound z_deflateBound -# define deflateCopy z_deflateCopy -# define deflateEnd z_deflateEnd -# define deflateGetDictionary z_deflateGetDictionary -# define deflateInit z_deflateInit -# define deflateInit2 z_deflateInit2 -# define deflateInit2_ z_deflateInit2_ -# define deflateInit_ z_deflateInit_ -# define deflateParams z_deflateParams -# define deflatePending z_deflatePending -# define deflatePrime z_deflatePrime -# define deflateReset z_deflateReset -# define deflateResetKeep z_deflateResetKeep -# define deflateSetDictionary z_deflateSetDictionary -# define deflateSetHeader z_deflateSetHeader -# define deflateTune z_deflateTune -# define deflate_copyright z_deflate_copyright -# define get_crc_table z_get_crc_table -# ifndef Z_SOLO -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzfread z_gzfread -# define gzfwrite z_gzfwrite -# define gzgetc z_gzgetc -# define gzgetc_ z_gzgetc_ -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# ifdef _WIN32 -# define gzopen_w z_gzopen_w -# endif -# define gzprintf z_gzprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzvprintf z_gzvprintf -# define gzwrite z_gzwrite -# endif -# define inflate z_inflate -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define inflateBackInit z_inflateBackInit -# define inflateBackInit_ z_inflateBackInit_ -# define inflateCodesUsed z_inflateCodesUsed -# define inflateCopy z_inflateCopy -# define inflateEnd z_inflateEnd -# define inflateGetDictionary z_inflateGetDictionary -# define inflateGetHeader z_inflateGetHeader -# define inflateInit z_inflateInit -# define inflateInit2 z_inflateInit2 -# define inflateInit2_ z_inflateInit2_ -# define inflateInit_ z_inflateInit_ -# define inflateMark z_inflateMark -# define inflatePrime z_inflatePrime -# define inflateReset z_inflateReset -# define inflateReset2 z_inflateReset2 -# define inflateResetKeep z_inflateResetKeep -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateUndermine z_inflateUndermine -# define inflateValidate z_inflateValidate -# define inflate_copyright z_inflate_copyright -# define inflate_fast z_inflate_fast -# define inflate_table z_inflate_table -# ifndef Z_SOLO -# define uncompress z_uncompress -# define uncompress2 z_uncompress2 -# endif -# define zError z_zError -# ifndef Z_SOLO -# define zcalloc z_zcalloc -# define zcfree z_zcfree -# endif -# define zlibCompileFlags z_zlibCompileFlags -# define zlibVersion z_zlibVersion - -/* all zlib typedefs in zlib.h and zconf.h */ -# define Byte z_Byte -# define Bytef z_Bytef -# define alloc_func z_alloc_func -# define charf z_charf -# define free_func z_free_func -# ifndef Z_SOLO -# define gzFile z_gzFile -# endif -# define gz_header z_gz_header -# define gz_headerp z_gz_headerp -# define in_func z_in_func -# define intf z_intf -# define out_func z_out_func -# define uInt z_uInt -# define uIntf z_uIntf -# define uLong z_uLong -# define uLongf z_uLongf -# define voidp z_voidp -# define voidpc z_voidpc -# define voidpf z_voidpf - -/* all zlib structs in zlib.h and zconf.h */ -# define gz_header_s z_gz_header_s -# define internal_state z_internal_state - -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -#if defined(ZLIB_CONST) && !defined(z_const) -# define z_const const -#else -# define z_const -#endif - -#ifdef Z_SOLO - typedef unsigned long z_size_t; -#else -# define z_longlong long long -# if defined(NO_SIZE_T) - typedef unsigned NO_SIZE_T z_size_t; -# elif defined(STDC) -# include - typedef size_t z_size_t; -# else - typedef unsigned long z_size_t; -# endif -# undef z_longlong -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus about 7 kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -#ifndef Z_ARG /* function prototypes for stdarg */ -# if defined(STDC) || defined(Z_HAVE_STDARG_H) -# define Z_ARG(args) args -# else -# define Z_ARG(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) -# include -# if (UINT_MAX == 0xffffffffUL) -# define Z_U4 unsigned -# elif (ULONG_MAX == 0xffffffffUL) -# define Z_U4 unsigned long -# elif (USHRT_MAX == 0xffffffffUL) -# define Z_U4 unsigned short -# endif -#endif - -#ifdef Z_U4 - typedef Z_U4 z_crc_t; -#else - typedef unsigned long z_crc_t; -#endif - -#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_UNISTD_H -#endif - -#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_STDARG_H -#endif - -#ifdef STDC -# ifndef Z_SOLO -# include /* for off_t */ -# endif -#endif - -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifndef Z_SOLO -# include /* for va_list */ -# endif -#endif - -#ifdef _WIN32 -# ifndef Z_SOLO -# include /* for wchar_t */ -# endif -#endif - -/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and - * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even - * though the former does not conform to the LFS document), but considering - * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as - * equivalently requesting no 64-bit operations - */ -#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 -# undef _LARGEFILE64_SOURCE -#endif - -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H -#endif -#ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t -# endif -# endif -#endif - -#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 -# define Z_LFS64 -#endif - -#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) -# define Z_LARGE64 -#endif - -#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) -# define Z_WANT64 -#endif - -#if !defined(SEEK_SET) && !defined(Z_SOLO) -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif - -#ifndef z_off_t -# define z_off_t long -#endif - -#if !defined(_WIN32) && defined(Z_LARGE64) -# define z_off64_t off64_t -#else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) -# define z_off64_t __int64 -# else -# define z_off64_t z_off_t -# endif -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) - #pragma map(deflateInit_,"DEIN") - #pragma map(deflateInit2_,"DEIN2") - #pragma map(deflateEnd,"DEEND") - #pragma map(deflateBound,"DEBND") - #pragma map(inflateInit_,"ININ") - #pragma map(inflateInit2_,"ININ2") - #pragma map(inflateEnd,"INEND") - #pragma map(inflateSync,"INSY") - #pragma map(inflateSetDictionary,"INSEDI") - #pragma map(compressBound,"CMBND") - #pragma map(inflate_table,"INTABL") - #pragma map(inflate_fast,"INFA") - #pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/deps/zlib/zconf.h.in b/deps/zlib/zconf.h.in deleted file mode 100644 index 5e1d68a004e974..00000000000000 --- a/deps/zlib/zconf.h.in +++ /dev/null @@ -1,534 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef ZCONF_H -#define ZCONF_H - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - * Even better than compiling with -DZ_PREFIX would be to use configure to set - * this permanently in zconf.h using "./configure --zprefix". - */ -#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ -# define Z_PREFIX_SET - -/* all linked symbols and init macros */ -# define _dist_code z__dist_code -# define _length_code z__length_code -# define _tr_align z__tr_align -# define _tr_flush_bits z__tr_flush_bits -# define _tr_flush_block z__tr_flush_block -# define _tr_init z__tr_init -# define _tr_stored_block z__tr_stored_block -# define _tr_tally z__tr_tally -# define adler32 z_adler32 -# define adler32_combine z_adler32_combine -# define adler32_combine64 z_adler32_combine64 -# define adler32_z z_adler32_z -# ifndef Z_SOLO -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# endif -# define crc32 z_crc32 -# define crc32_combine z_crc32_combine -# define crc32_combine64 z_crc32_combine64 -# define crc32_z z_crc32_z -# define deflate z_deflate -# define deflateBound z_deflateBound -# define deflateCopy z_deflateCopy -# define deflateEnd z_deflateEnd -# define deflateGetDictionary z_deflateGetDictionary -# define deflateInit z_deflateInit -# define deflateInit2 z_deflateInit2 -# define deflateInit2_ z_deflateInit2_ -# define deflateInit_ z_deflateInit_ -# define deflateParams z_deflateParams -# define deflatePending z_deflatePending -# define deflatePrime z_deflatePrime -# define deflateReset z_deflateReset -# define deflateResetKeep z_deflateResetKeep -# define deflateSetDictionary z_deflateSetDictionary -# define deflateSetHeader z_deflateSetHeader -# define deflateTune z_deflateTune -# define deflate_copyright z_deflate_copyright -# define get_crc_table z_get_crc_table -# ifndef Z_SOLO -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzfread z_gzfread -# define gzfwrite z_gzfwrite -# define gzgetc z_gzgetc -# define gzgetc_ z_gzgetc_ -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# ifdef _WIN32 -# define gzopen_w z_gzopen_w -# endif -# define gzprintf z_gzprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzvprintf z_gzvprintf -# define gzwrite z_gzwrite -# endif -# define inflate z_inflate -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define inflateBackInit z_inflateBackInit -# define inflateBackInit_ z_inflateBackInit_ -# define inflateCodesUsed z_inflateCodesUsed -# define inflateCopy z_inflateCopy -# define inflateEnd z_inflateEnd -# define inflateGetDictionary z_inflateGetDictionary -# define inflateGetHeader z_inflateGetHeader -# define inflateInit z_inflateInit -# define inflateInit2 z_inflateInit2 -# define inflateInit2_ z_inflateInit2_ -# define inflateInit_ z_inflateInit_ -# define inflateMark z_inflateMark -# define inflatePrime z_inflatePrime -# define inflateReset z_inflateReset -# define inflateReset2 z_inflateReset2 -# define inflateResetKeep z_inflateResetKeep -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateUndermine z_inflateUndermine -# define inflateValidate z_inflateValidate -# define inflate_copyright z_inflate_copyright -# define inflate_fast z_inflate_fast -# define inflate_table z_inflate_table -# ifndef Z_SOLO -# define uncompress z_uncompress -# define uncompress2 z_uncompress2 -# endif -# define zError z_zError -# ifndef Z_SOLO -# define zcalloc z_zcalloc -# define zcfree z_zcfree -# endif -# define zlibCompileFlags z_zlibCompileFlags -# define zlibVersion z_zlibVersion - -/* all zlib typedefs in zlib.h and zconf.h */ -# define Byte z_Byte -# define Bytef z_Bytef -# define alloc_func z_alloc_func -# define charf z_charf -# define free_func z_free_func -# ifndef Z_SOLO -# define gzFile z_gzFile -# endif -# define gz_header z_gz_header -# define gz_headerp z_gz_headerp -# define in_func z_in_func -# define intf z_intf -# define out_func z_out_func -# define uInt z_uInt -# define uIntf z_uIntf -# define uLong z_uLong -# define uLongf z_uLongf -# define voidp z_voidp -# define voidpc z_voidpc -# define voidpf z_voidpf - -/* all zlib structs in zlib.h and zconf.h */ -# define gz_header_s z_gz_header_s -# define internal_state z_internal_state - -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -#if defined(ZLIB_CONST) && !defined(z_const) -# define z_const const -#else -# define z_const -#endif - -#ifdef Z_SOLO - typedef unsigned long z_size_t; -#else -# define z_longlong long long -# if defined(NO_SIZE_T) - typedef unsigned NO_SIZE_T z_size_t; -# elif defined(STDC) -# include - typedef size_t z_size_t; -# else - typedef unsigned long z_size_t; -# endif -# undef z_longlong -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus about 7 kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -#ifndef Z_ARG /* function prototypes for stdarg */ -# if defined(STDC) || defined(Z_HAVE_STDARG_H) -# define Z_ARG(args) args -# else -# define Z_ARG(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) -# include -# if (UINT_MAX == 0xffffffffUL) -# define Z_U4 unsigned -# elif (ULONG_MAX == 0xffffffffUL) -# define Z_U4 unsigned long -# elif (USHRT_MAX == 0xffffffffUL) -# define Z_U4 unsigned short -# endif -#endif - -#ifdef Z_U4 - typedef Z_U4 z_crc_t; -#else - typedef unsigned long z_crc_t; -#endif - -#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_UNISTD_H -#endif - -#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_STDARG_H -#endif - -#ifdef STDC -# ifndef Z_SOLO -# include /* for off_t */ -# endif -#endif - -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifndef Z_SOLO -# include /* for va_list */ -# endif -#endif - -#ifdef _WIN32 -# ifndef Z_SOLO -# include /* for wchar_t */ -# endif -#endif - -/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and - * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even - * though the former does not conform to the LFS document), but considering - * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as - * equivalently requesting no 64-bit operations - */ -#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 -# undef _LARGEFILE64_SOURCE -#endif - -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H -#endif -#ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t -# endif -# endif -#endif - -#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 -# define Z_LFS64 -#endif - -#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) -# define Z_LARGE64 -#endif - -#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) -# define Z_WANT64 -#endif - -#if !defined(SEEK_SET) && !defined(Z_SOLO) -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif - -#ifndef z_off_t -# define z_off_t long -#endif - -#if !defined(_WIN32) && defined(Z_LARGE64) -# define z_off64_t off64_t -#else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) -# define z_off64_t __int64 -# else -# define z_off64_t z_off_t -# endif -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) - #pragma map(deflateInit_,"DEIN") - #pragma map(deflateInit2_,"DEIN2") - #pragma map(deflateEnd,"DEEND") - #pragma map(deflateBound,"DEBND") - #pragma map(inflateInit_,"ININ") - #pragma map(inflateInit2_,"ININ2") - #pragma map(inflateEnd,"INEND") - #pragma map(inflateSync,"INSY") - #pragma map(inflateSetDictionary,"INSEDI") - #pragma map(compressBound,"CMBND") - #pragma map(inflate_table,"INTABL") - #pragma map(inflate_fast,"INFA") - #pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/deps/zlib/zlib.3 b/deps/zlib/zlib.3 deleted file mode 100644 index bda4eb0737090c..00000000000000 --- a/deps/zlib/zlib.3 +++ /dev/null @@ -1,149 +0,0 @@ -.TH ZLIB 3 "15 Jan 2017" -.SH NAME -zlib \- compression/decompression library -.SH SYNOPSIS -[see -.I zlib.h -for full description] -.SH DESCRIPTION -The -.I zlib -library is a general purpose data compression library. -The code is thread safe, assuming that the standard library functions -used are thread safe, such as memory allocation routines. -It provides in-memory compression and decompression functions, -including integrity checks of the uncompressed data. -This version of the library supports only one compression method (deflation) -but other algorithms may be added later -with the same stream interface. -.LP -Compression can be done in a single step if the buffers are large enough -or can be done by repeated calls of the compression function. -In the latter case, -the application must provide more input and/or consume the output -(providing more output space) before each call. -.LP -The library also supports reading and writing files in -.IR gzip (1) -(.gz) format -with an interface similar to that of stdio. -.LP -The library does not install any signal handler. -The decoder checks the consistency of the compressed data, -so the library should never crash even in the case of corrupted input. -.LP -All functions of the compression library are documented in the file -.IR zlib.h . -The distribution source includes examples of use of the library -in the files -.I test/example.c -and -.IR test/minigzip.c, -as well as other examples in the -.IR examples/ -directory. -.LP -Changes to this version are documented in the file -.I ChangeLog -that accompanies the source. -.LP -.I zlib -is built in to many languages and operating systems, including but not limited to -Java, Python, .NET, PHP, Perl, Ruby, Swift, and Go. -.LP -An experimental package to read and write files in the .zip format, -written on top of -.I zlib -by Gilles Vollant (info@winimage.com), -is available at: -.IP -http://www.winimage.com/zLibDll/minizip.html -and also in the -.I contrib/minizip -directory of the main -.I zlib -source distribution. -.SH "SEE ALSO" -The -.I zlib -web site can be found at: -.IP -http://zlib.net/ -.LP -The data format used by the -.I zlib -library is described by RFC -(Request for Comments) 1950 to 1952 in the files: -.IP -http://tools.ietf.org/html/rfc1950 (for the zlib header and trailer format) -.br -http://tools.ietf.org/html/rfc1951 (for the deflate compressed data format) -.br -http://tools.ietf.org/html/rfc1952 (for the gzip header and trailer format) -.LP -Mark Nelson wrote an article about -.I zlib -for the Jan. 1997 issue of Dr. Dobb's Journal; -a copy of the article is available at: -.IP -http://marknelson.us/1997/01/01/zlib-engine/ -.SH "REPORTING PROBLEMS" -Before reporting a problem, -please check the -.I zlib -web site to verify that you have the latest version of -.IR zlib ; -otherwise, -obtain the latest version and see if the problem still exists. -Please read the -.I zlib -FAQ at: -.IP -http://zlib.net/zlib_faq.html -.LP -before asking for help. -Send questions and/or comments to zlib@gzip.org, -or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). -.SH AUTHORS AND LICENSE -Version 1.2.11 -.LP -Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler -.LP -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. -.LP -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: -.LP -.nr step 1 1 -.IP \n[step]. 3 -The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software -in a product, an acknowledgment in the product documentation would be -appreciated but is not required. -.IP \n+[step]. -Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. -.IP \n+[step]. -This notice may not be removed or altered from any source distribution. -.LP -Jean-loup Gailly Mark Adler -.br -jloup@gzip.org madler@alumni.caltech.edu -.LP -The deflate format used by -.I zlib -was defined by Phil Katz. -The deflate and -.I zlib -specifications were written by L. Peter Deutsch. -Thanks to all the people who reported problems and suggested various -improvements in -.IR zlib ; -who are too numerous to cite here. -.LP -UNIX manual page by R. P. C. Rodgers, -U.S. National Library of Medicine (rodgers@nlm.nih.gov). -.\" end of man page diff --git a/deps/zlib/zlib.3.pdf b/deps/zlib/zlib.3.pdf deleted file mode 100644 index 6fa519c5bdf5df..00000000000000 Binary files a/deps/zlib/zlib.3.pdf and /dev/null differ diff --git a/deps/zlib/zlib.gyp b/deps/zlib/zlib.gyp index 970bc787bae1ea..6f5a8ce3464b31 100644 --- a/deps/zlib/zlib.gyp +++ b/deps/zlib/zlib.gyp @@ -4,7 +4,9 @@ { 'variables': { - 'use_system_zlib%': 0 + 'use_system_zlib%': 0, + 'arm_fpu%': '', + 'llvm_version%': '0.0', }, 'conditions': [ ['use_system_zlib==0', { @@ -15,6 +17,7 @@ 'sources': [ 'adler32.c', 'compress.c', + 'contrib/optimizations/insert_string.h', 'crc32.c', 'crc32.h', 'deflate.c', @@ -28,13 +31,13 @@ 'inffast.c', 'inffast.h', 'inffixed.h', - 'inflate.c', 'inflate.h', 'inftrees.c', 'inftrees.h', 'trees.c', 'trees.h', 'uncompr.c', + 'x86.h', 'zconf.h', 'zlib.h', 'zutil.c', @@ -51,7 +54,7 @@ 'conditions': [ ['OS!="win"', { 'cflags!': [ '-ansi' ], - 'defines': [ 'Z_HAVE_UNISTD_H', 'HAVE_HIDDEN' ], + 'defines': [ 'HAVE_HIDDEN' ], }], ['OS=="mac" or OS=="ios" or OS=="freebsd" or OS=="android"', { # Mac, Android and the BSDs don't have fopen64, ftello64, or @@ -61,6 +64,79 @@ 'USE_FILE32API' ], }], + ['(target_arch in "ia32 x64 x32" and OS!="ios") or arm_fpu=="neon"', { + 'sources': [ + 'adler32_simd.c', + 'adler32_simd.h', + 'contrib/optimizations/chunkcopy.h', + 'contrib/optimizations/inffast_chunk.c', + 'contrib/optimizations/inffast_chunk.h', + 'contrib/optimizations/inflate.c', + ], + }, { + 'sources': [ 'inflate.c', ], + }], + # Incorporate optimizations where possible + ['target_arch in "ia32 x64 x32" and OS!="ios"', { + 'defines': [ + 'ADLER32_SIMD_SSSE3', + 'INFLATE_CHUNK_SIMD_SSE2', + 'CRC32_SIMD_SSE42_PCLMUL', + ], + 'sources': [ + 'crc32_simd.c', + 'crc32_simd.h', + 'crc_folding.c', + 'fill_window_sse.c', + 'x86.c', + ], + 'conditions': [ + ['target_arch=="x64"', { + 'defines': [ 'INFLATE_CHUNK_READ_64LE' ], + }], + ], + }, { + 'sources': [ 'simd_stub.c', ], + }], + ['arm_fpu=="neon"', { + 'defines': [ + 'ADLER32_SIMD_NEON', + 'INFLATE_CHUNK_SIMD_NEON', + ], + 'sources': [ + 'contrib/optimizations/slide_hash_neon.h', + ], + 'conditions': [ + ['OS!="ios"', { + 'defines': [ 'CRC32_ARMV8_CRC32' ], + 'sources': [ + 'arm_features.c', + 'arm_features.h', + 'crc32_simd.c', + 'crc32_simd.h', + ], + 'conditions': [ + ['OS=="android"', { + 'defines': [ 'ARMV8_OS_ANDROID' ], + }], + ['OS=="linux"', { + 'defines': [ 'ARMV8_OS_LINUX' ], + }], + ['OS="win"', { + 'defines': [ 'ARMV8_OS_WINDOWS' ], + }], + ['OS!="android" and OS!="win" and llvm_version=="0.0"', { + 'cflags': [ + '-march=armv8-a+crc', + ], + }], + ], + }], + ['target_arch=="arm64"', { + 'defines': [ 'INFLATE_CHUNK_READ_64LE' ], + }], + ], + }], ], }, ], diff --git a/deps/zlib/zlib.h b/deps/zlib/zlib.h index f09cdaf1e0543d..99fd467f6b1a54 100644 --- a/deps/zlib/zlib.h +++ b/deps/zlib/zlib.h @@ -1824,6 +1824,11 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ # undef z_gzgetc # define z_gzgetc(g) \ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#elif defined(Z_CR_PREFIX_SET) +# undef gzgetc +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) \ + : (Cr_z_gzgetc)(g)) #else # define gzgetc(g) \ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) @@ -1853,11 +1858,29 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ # define z_adler32_combine z_adler32_combine64 # define z_crc32_combine z_crc32_combine64 # else +# ifdef gzopen +# undef gzopen +# endif # define gzopen gzopen64 +# ifdef gzseek +# undef gzseek +# endif # define gzseek gzseek64 +# ifdef gztell +# undef gztell +# endif # define gztell gztell64 +# ifdef gzoffset +# undef gzoffset +# endif # define gzoffset gzoffset64 +# ifdef adler32_combine +# undef adler32_combine +# endif # define adler32_combine adler32_combine64 +# ifdef crc32_combine +# undef crc32_combine +# endif # define crc32_combine crc32_combine64 # endif # ifndef Z_LARGE64 diff --git a/deps/zlib/zlib.map b/deps/zlib/zlib.map deleted file mode 100644 index 82ce98cf7decc9..00000000000000 --- a/deps/zlib/zlib.map +++ /dev/null @@ -1,94 +0,0 @@ -ZLIB_1.2.0 { - global: - compressBound; - deflateBound; - inflateBack; - inflateBackEnd; - inflateBackInit_; - inflateCopy; - local: - deflate_copyright; - inflate_copyright; - inflate_fast; - inflate_table; - zcalloc; - zcfree; - z_errmsg; - gz_error; - gz_intmax; - _*; -}; - -ZLIB_1.2.0.2 { - gzclearerr; - gzungetc; - zlibCompileFlags; -} ZLIB_1.2.0; - -ZLIB_1.2.0.8 { - deflatePrime; -} ZLIB_1.2.0.2; - -ZLIB_1.2.2 { - adler32_combine; - crc32_combine; - deflateSetHeader; - inflateGetHeader; -} ZLIB_1.2.0.8; - -ZLIB_1.2.2.3 { - deflateTune; - gzdirect; -} ZLIB_1.2.2; - -ZLIB_1.2.2.4 { - inflatePrime; -} ZLIB_1.2.2.3; - -ZLIB_1.2.3.3 { - adler32_combine64; - crc32_combine64; - gzopen64; - gzseek64; - gztell64; - inflateUndermine; -} ZLIB_1.2.2.4; - -ZLIB_1.2.3.4 { - inflateReset2; - inflateMark; -} ZLIB_1.2.3.3; - -ZLIB_1.2.3.5 { - gzbuffer; - gzoffset; - gzoffset64; - gzclose_r; - gzclose_w; -} ZLIB_1.2.3.4; - -ZLIB_1.2.5.1 { - deflatePending; -} ZLIB_1.2.3.5; - -ZLIB_1.2.5.2 { - deflateResetKeep; - gzgetc_; - inflateResetKeep; -} ZLIB_1.2.5.1; - -ZLIB_1.2.7.1 { - inflateGetDictionary; - gzvprintf; -} ZLIB_1.2.5.2; - -ZLIB_1.2.9 { - inflateCodesUsed; - inflateValidate; - uncompress2; - gzfread; - gzfwrite; - deflateGetDictionary; - adler32_z; - crc32_z; -} ZLIB_1.2.7.1; diff --git a/deps/zlib/zlib.pc.cmakein b/deps/zlib/zlib.pc.cmakein deleted file mode 100644 index a5e642938c6985..00000000000000 --- a/deps/zlib/zlib.pc.cmakein +++ /dev/null @@ -1,13 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -exec_prefix=@CMAKE_INSTALL_PREFIX@ -libdir=@INSTALL_LIB_DIR@ -sharedlibdir=@INSTALL_LIB_DIR@ -includedir=@INSTALL_INC_DIR@ - -Name: zlib -Description: zlib compression library -Version: @VERSION@ - -Requires: -Libs: -L${libdir} -L${sharedlibdir} -lz -Cflags: -I${includedir} diff --git a/deps/zlib/zlib.pc.in b/deps/zlib/zlib.pc.in deleted file mode 100644 index 7e5acf9c77e774..00000000000000 --- a/deps/zlib/zlib.pc.in +++ /dev/null @@ -1,13 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -sharedlibdir=@sharedlibdir@ -includedir=@includedir@ - -Name: zlib -Description: zlib compression library -Version: @VERSION@ - -Requires: -Libs: -L${libdir} -L${sharedlibdir} -lz -Cflags: -I${includedir} diff --git a/deps/zlib/zlib2ansi b/deps/zlib/zlib2ansi deleted file mode 100755 index 15e3e165f37dec..00000000000000 --- a/deps/zlib/zlib2ansi +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/perl - -# Transform K&R C function definitions into ANSI equivalent. -# -# Author: Paul Marquess -# Version: 1.0 -# Date: 3 October 2006 - -# TODO -# -# Asumes no function pointer parameters. unless they are typedefed. -# Assumes no literal strings that look like function definitions -# Assumes functions start at the beginning of a line - -use strict; -use warnings; - -local $/; -$_ = <>; - -my $sp = qr{ \s* (?: /\* .*? \*/ )? \s* }x; # assume no nested comments - -my $d1 = qr{ $sp (?: [\w\*\s]+ $sp)* $sp \w+ $sp [\[\]\s]* $sp }x ; -my $decl = qr{ $sp (?: \w+ $sp )+ $d1 }xo ; -my $dList = qr{ $sp $decl (?: $sp , $d1 )* $sp ; $sp }xo ; - - -while (s/^ - ( # Start $1 - ( # Start $2 - .*? # Minimal eat content - ( ^ \w [\w\s\*]+ ) # $3 -- function name - \s* # optional whitespace - ) # $2 - Matched up to before parameter list - - \( \s* # Literal "(" + optional whitespace - ( [^\)]+ ) # $4 - one or more anythings except ")" - \s* \) # optional whitespace surrounding a Literal ")" - - ( (?: $dList )+ ) # $5 - - $sp ^ { # literal "{" at start of line - ) # Remember to $1 - //xsom - ) -{ - my $all = $1 ; - my $prefix = $2; - my $param_list = $4 ; - my $params = $5; - - StripComments($params); - StripComments($param_list); - $param_list =~ s/^\s+//; - $param_list =~ s/\s+$//; - - my $i = 0 ; - my %pList = map { $_ => $i++ } - split /\s*,\s*/, $param_list; - my $pMatch = '(\b' . join('|', keys %pList) . '\b)\W*$' ; - - my @params = split /\s*;\s*/, $params; - my @outParams = (); - foreach my $p (@params) - { - if ($p =~ /,/) - { - my @bits = split /\s*,\s*/, $p; - my $first = shift @bits; - $first =~ s/^\s*//; - push @outParams, $first; - $first =~ /^(\w+\s*)/; - my $type = $1 ; - push @outParams, map { $type . $_ } @bits; - } - else - { - $p =~ s/^\s+//; - push @outParams, $p; - } - } - - - my %tmp = map { /$pMatch/; $_ => $pList{$1} } - @outParams ; - - @outParams = map { " $_" } - sort { $tmp{$a} <=> $tmp{$b} } - @outParams ; - - print $prefix ; - print "(\n" . join(",\n", @outParams) . ")\n"; - print "{" ; - -} - -# Output any trailing code. -print ; -exit 0; - - -sub StripComments -{ - - no warnings; - - # Strip C & C++ coments - # From the perlfaq - $_[0] =~ - - s{ - /\* ## Start of /* ... */ comment - [^*]*\*+ ## Non-* followed by 1-or-more *'s - ( - [^/*][^*]*\*+ - )* ## 0-or-more things which don't start with / - ## but do end with '*' - / ## End of /* ... */ comment - - | ## OR C++ Comment - // ## Start of C++ comment // - [^\n]* ## followed by 0-or-more non end of line characters - - | ## OR various things which aren't comments: - - ( - " ## Start of " ... " string - ( - \\. ## Escaped char - | ## OR - [^"\\] ## Non "\ - )* - " ## End of " ... " string - - | ## OR - - ' ## Start of ' ... ' string - ( - \\. ## Escaped char - | ## OR - [^'\\] ## Non '\ - )* - ' ## End of ' ... ' string - - | ## OR - - . ## Anything other char - [^/"'\\]* ## Chars which doesn't start a comment, string or escape - ) - }{$2}gxs; - -} diff --git a/deps/zlib/zutil.h b/deps/zlib/zutil.h index b079ea6a80f5ab..4425bcf75eb38c 100644 --- a/deps/zlib/zutil.h +++ b/deps/zlib/zutil.h @@ -28,6 +28,21 @@ # include # include #endif +#ifdef NO_ERRNO_H +# ifdef _WIN32_WCE + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. We rename it to + * avoid conflict with other libraries that use the same workaround. + */ +# define errno z_errno +# endif + extern int errno; +#else +# ifndef _WIN32_WCE +# include +# endif +#endif #ifdef Z_SOLO typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ @@ -268,4 +283,10 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) +#ifdef _MSC_VER +#define zalign(x) __declspec(align(x)) +#else +#define zalign(x) __attribute__((aligned((x)))) +#endif + #endif /* ZUTIL_H */ diff --git a/doc/api/addons.md b/doc/api/addons.md index 9dacf0c8ff018c..ffbecb02d8ff4d 100644 --- a/doc/api/addons.md +++ b/doc/api/addons.md @@ -8,8 +8,8 @@ Addons are dynamically-linked shared objects written in C++. The Addons provide an interface between JavaScript and C/C++ libraries. There are three options for implementing Addons: N-API, nan, or direct -use of internal V8, libuv and Node.js libraries. Unless you need direct -access to functionality which is not exposed by N-API, use N-API. +use of internal V8, libuv and Node.js libraries. Unless there is a need for +direct access to functionality which is not exposed by N-API, use N-API. Refer to [C/C++ Addons with N-API](n-api.html) for more information on N-API. When not using N-API, implementing Addons is complicated, diff --git a/doc/api/async_hooks.md b/doc/api/async_hooks.md index 813f2735ea5141..d071820a298369 100644 --- a/doc/api/async_hooks.md +++ b/doc/api/async_hooks.md @@ -464,6 +464,62 @@ init for PROMISE with id 6, trigger id: 5 # the Promise returned by then() after 6 ``` +#### `async_hooks.executionAsyncResource()` + + + +* Returns: {Object} The resource representing the current execution. + Useful to store data within the resource. + +Resource objects returned by `executionAsyncResource()` are most often internal +Node.js handle objects with undocumented APIs. Using any functions or properties +on the object is likely to crash your application and should be avoided. + +Using `executionAsyncResource()` in the top-level execution context will +return an empty object as there is no handle or request object to use, +but having an object representing the top-level can be helpful. + +```js +const { open } = require('fs'); +const { executionAsyncId, executionAsyncResource } = require('async_hooks'); + +console.log(executionAsyncId(), executionAsyncResource()); // 1 {} +open(__filename, 'r', (err, fd) => { + console.log(executionAsyncId(), executionAsyncResource()); // 7 FSReqWrap +}); +``` + +This can be used to implement continuation local storage without the +use of a tracking `Map` to store the metadata: + +```js +const { createServer } = require('http'); +const { + executionAsyncId, + executionAsyncResource, + createHook +} = require('async_hooks'); +const sym = Symbol('state'); // Private symbol to avoid pollution + +createHook({ + init(asyncId, type, triggerAsyncId, resource) { + const cr = executionAsyncResource(); + if (cr) { + resource[sym] = cr[sym]; + } + } +}).enable(); + +const server = createServer(function(req, res) { + executionAsyncResource()[sym] = { state: req.url }; + setTimeout(function() { + res.end(JSON.stringify(executionAsyncResource()[sym])); + }, 100); +}).listen(3000); +``` + #### `async_hooks.executionAsyncId()` + +This class is used to create asynchronous state within callbacks and promise +chains. It allows storing data throughout the lifetime of a web request +or any other asynchronous duration. It is similar to thread-local storage +in other languages. + +The following example uses `AsyncLocalStorage` to build a simple logger +that assigns IDs to incoming HTTP requests and includes them in messages +logged within each request. + +```js +const http = require('http'); +const { AsyncLocalStorage } = require('async_hooks'); + +const asyncLocalStorage = new AsyncLocalStorage(); + +function logWithId(msg) { + const id = asyncLocalStorage.getStore(); + console.log(`${id !== undefined ? id : '-'}:`, msg); +} + +let idSeq = 0; +http.createServer((req, res) => { + asyncLocalStorage.run(idSeq++, () => { + logWithId('start'); + // Imagine any chain of async operations here + setImmediate(() => { + logWithId('finish'); + res.end(); + }); + }); +}).listen(8080); + +http.get('http://localhost:8080'); +http.get('http://localhost:8080'); +// Prints: +// 0: start +// 1: start +// 0: finish +// 1: finish +``` + +When having multiple instances of `AsyncLocalStorage`, they are independent +from each other. It is safe to instantiate this class multiple times. + +### `new AsyncLocalStorage()` + + +Creates a new instance of `AsyncLocalStorage`. Store is only provided within a +`run` method call. + +### `asyncLocalStorage.disable()` + + +This method disables the instance of `AsyncLocalStorage`. All subsequent calls +to `asyncLocalStorage.getStore()` will return `undefined` until +`asyncLocalStorage.run()` is called again. + +When calling `asyncLocalStorage.disable()`, all current contexts linked to the +instance will be exited. + +Calling `asyncLocalStorage.disable()` is required before the +`asyncLocalStorage` can be garbage collected. This does not apply to stores +provided by the `asyncLocalStorage`, as those objects are garbage collected +along with the corresponding async resources. + +This method is to be used when the `asyncLocalStorage` is not in use anymore +in the current process. + +### `asyncLocalStorage.getStore()` + + +* Returns: {any} + +This method returns the current store. +If this method is called outside of an asynchronous context initialized by +calling `asyncLocalStorage.run`, it will return `undefined`. + +### `asyncLocalStorage.enterWith(store)` + + +* `store` {any} + +Calling `asyncLocalStorage.enterWith(store)` will transition into the context +for the remainder of the current synchronous execution and will persist +through any following asynchronous calls. + +Example: + +```js +const store = { id: 1 }; +asyncLocalStorage.enterWith(store); +asyncLocalStorage.getStore(); // Returns the store object +someAsyncOperation(() => { + asyncLocalStorage.getStore(); // Returns the same object +}); +``` + +This transition will continue for the _entire_ synchronous execution. +This means that if, for example, the context is entered within an event +handler subsequent event handlers will also run within that context unless +specifically bound to another context with an `AsyncResource`. + +```js +const store = { id: 1 }; + +emitter.on('my-event', () => { + asyncLocalStorage.enterWith(store); +}); +emitter.on('my-event', () => { + asyncLocalStorage.getStore(); // Returns the same object +}); + +asyncLocalStorage.getStore(); // Returns undefined +emitter.emit('my-event'); +asyncLocalStorage.getStore(); // Returns the same object +``` + +### `asyncLocalStorage.run(store, callback[, ...args])` + + +* `store` {any} +* `callback` {Function} +* `...args` {any} + +This methods runs a function synchronously within a context and return its +return value. The store is not accessible outside of the callback function or +the asynchronous operations created within the callback. + +Optionally, arguments can be passed to the function. They will be passed to +the callback function. + +If the callback function throws an error, it will be thrown by `run` too. +The stacktrace will not be impacted by this call and the context will +be exited. + +Example: + +```js +const store = { id: 2 }; +try { + asyncLocalStorage.run(store, () => { + asyncLocalStorage.getStore(); // Returns the store object + throw new Error(); + }); +} catch (e) { + asyncLocalStorage.getStore(); // Returns undefined + // The error will be caught here +} +``` + +### `asyncLocalStorage.exit(callback[, ...args])` + + +* `callback` {Function} +* `...args` {any} + +This methods runs a function synchronously outside of a context and return its +return value. The store is not accessible within the callback function or +the asynchronous operations created within the callback. + +Optionally, arguments can be passed to the function. They will be passed to +the callback function. + +If the callback function throws an error, it will be thrown by `exit` too. +The stacktrace will not be impacted by this call and +the context will be re-entered. + +Example: + +```js +// Within a call to run +try { + asyncLocalStorage.getStore(); // Returns the store object or value + asyncLocalStorage.exit(() => { + asyncLocalStorage.getStore(); // Returns undefined + throw new Error(); + }); +} catch (e) { + asyncLocalStorage.getStore(); // Returns the same object or value + // The error will be caught here +} +``` + +### Usage with `async/await` + +If, within an async function, only one `await` call is to run within a context, +the following pattern should be used: + +```js +async function fn() { + await asyncLocalStorage.run(new Map(), () => { + asyncLocalStorage.getStore().set('key', value); + return foo(); // The return value of foo will be awaited + }); +} +``` + +In this example, the store is only available in the callback function and the +functions called by `foo`. Outside of `run`, calling `getStore` will return +`undefined`. + [`after` callback]: #async_hooks_after_asyncid [`before` callback]: #async_hooks_before_asyncid [`destroy` callback]: #async_hooks_destroy_asyncid diff --git a/doc/api/buffer.md b/doc/api/buffer.md index 28f306f09ab870..b839f0cebad093 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -379,9 +379,10 @@ A `TypeError` will be thrown if `size` is not a number. The `Buffer` module pre-allocates an internal `Buffer` instance of size [`Buffer.poolSize`][] that is used as a pool for the fast allocation of new -`Buffer` instances created using [`Buffer.allocUnsafe()`][] and the deprecated -`new Buffer(size)` constructor only when `size` is less than or equal to -`Buffer.poolSize >> 1` (floor of [`Buffer.poolSize`][] divided by two). +`Buffer` instances created using [`Buffer.allocUnsafe()`][], +[`Buffer.from(array)`][], and the deprecated `new Buffer(size)` constructor only +when `size` is less than or equal to `Buffer.poolSize >> 1` (floor of +[`Buffer.poolSize`][] divided by two). Use of this pre-allocated internal memory pool is a key difference between calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`. @@ -571,6 +572,9 @@ const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]); A `TypeError` will be thrown if `array` is not an `Array` or other type appropriate for `Buffer.from()` variants. +`Buffer.from(array)` and [`Buffer.from(string)`][] may also use the internal +`Buffer` pool like [`Buffer.allocUnsafe()`][] does. + ### Class Method: `Buffer.from(arrayBuffer[, byteOffset[, length]])` + +Disable the `Object.prototype.__proto__` property. If `mode` is `delete`, the +property will be removed entirely. If `mode` is `throw`, accesses to the +property will throw an exception with the code `ERR_PROTO_ACCESS`. + ### `--disallow-code-generation-from-strings` -Enable experimental ES module support and caching modules. +Enable latest experimental modules features (deprecated). ### `--experimental-policy` - -Enable experimental diagnostic report feature. - ### `--experimental-specifier-resolution=mode` -Used with `--experimental-modules`, this configures Node.js to interpret string -input as CommonJS or as an ES module. String input is input via `--eval`, -`--print`, or `STDIN`. +This configures Node.js to interpret string input as CommonJS or as an ES +module. String input is input via `--eval`, `--print`, or `STDIN`. Valid values are `"commonjs"` and `"module"`. The default is `"commonjs"`. @@ -622,10 +623,22 @@ file will be created if it does not exist, and will be appended to if it does. If an error occurs while attempting to write the warning to the file, the warning will be written to stderr instead. +### `--report-compact` + + +Write reports in a compact format, single-line JSON, more easily consumable +by log processing systems than the default multi-line format designed for +human consumption. + ### `--report-directory=directory` Enables report to be generated upon receiving the specified (or predefined) -signal to the running Node.js process, if `--experimental-report` is enabled. -The signal to trigger the report is specified through `--report-signal`. +signal to the running Node.js process. The signal to trigger the report is +specified through `--report-signal`. ### `--report-signal=signal` -Enables report to be generated on un-caught exceptions, if -`--experimental-report` is enabled. Useful when inspecting JavaScript stack in -conjunction with native stack and other runtime environment data. +Enables report to be generated on uncaught exceptions. Useful when inspecting +the JavaScript stack in conjunction with native stack and other runtime +environment data. ### `--throw-deprecation` + +Prints a stack trace on SIGINT. + ### `--trace-sync-io` + +Re-map the Node.js static code to large memory pages at startup. If supported on +the target system, this will cause the Node.js static code to be moved onto 2 +MiB pages instead of 4 KiB pages. + +The following values are valid for `mode`: +* `off`: No mapping will be attempted. This is the default. +* `on`: If supported by the OS, mapping will be attempted. Failure to map will + be ignored and a message will be printed to standard error. +* `silent`: If supported by the OS, mapping will be attempted. Failure to map + will be ignored and will not be reported. + ### `--v8-options` +* `--disable-proto` * `--enable-fips` * `--enable-source-maps` * `--experimental-import-meta-resolve` @@ -1098,7 +1150,6 @@ Node.js options that are allowed are: * `--experimental-modules` * `--experimental-policy` * `--experimental-repl-await` -* `--experimental-report` * `--experimental-specifier-resolution` * `--experimental-vm-modules` * `--experimental-wasi-unstable-preview1` @@ -1128,6 +1179,7 @@ Node.js options that are allowed are: * `--preserve-symlinks` * `--prof-process` * `--redirect-warnings` +* `--report-compact` * `--report-directory` * `--report-filename` * `--report-on-fatalerror` @@ -1150,6 +1202,7 @@ Node.js options that are allowed are: * `--trace-event-file-pattern` * `--trace-events-enabled` * `--trace-exit` +* `--trace-sigint` * `--trace-sync-io` * `--trace-tls` * `--trace-uncaught` @@ -1157,6 +1210,7 @@ Node.js options that are allowed are: * `--track-heap-objects` * `--unhandled-rejections` * `--use-bundled-ca` +* `--use-largepages` * `--use-openssl-ca` * `--v8-pool-size` * `--zero-fill-buffers` @@ -1166,6 +1220,7 @@ V8 options that are allowed are: * `--abort-on-uncaught-exception` * `--disallow-code-generation-from-strings` +* `--huge-max-old-generation-size` * `--interpreted-frames-native-stack` * `--jitless` * `--max-old-space-size` diff --git a/doc/api/console.md b/doc/api/console.md index 66fa862de88178..1498c6d30e5132 100644 --- a/doc/api/console.md +++ b/doc/api/console.md @@ -81,16 +81,19 @@ const { Console } = console; ### `new Console(options)` * `options` {Object} @@ -107,6 +110,8 @@ changes: **Default:** `'auto'`. * `inspectOptions` {Object} Specifies options that are passed along to [`util.inspect()`][]. + * `groupIndentation` {number} Set group indentation. + **Default:** `2`. Creates a new `Console` with one or two writable stream instances. `stdout` is a writable stream to print log or info output. `stderr` is used for warning or @@ -306,7 +311,8 @@ added: v8.5.0 * `...label` {any} -Increases indentation of subsequent lines by two spaces. +Increases indentation of subsequent lines by spaces for `groupIndentation` +length. If one or more `label`s are provided, those are printed first without the additional indentation. @@ -323,7 +329,8 @@ An alias for [`console.group()`][]. added: v8.5.0 --> -Decreases indentation of subsequent lines by two spaces. +Decreases indentation of subsequent lines by spaces for `groupIndentation` +length. ### `console.info([data][, ...args])` + +* `options`: {Object} + * `privateKey`: {KeyObject} + * `publicKey`: {KeyObject} +* Returns: {Buffer} + +Computes the Diffie-Hellman secret based on a `privateKey` and a `publicKey`. +Both keys must have the same `asymmetricKeyType`, which must be one of `'dh'` +(for Diffie-Hellman), `'ec'` (for ECDH), `'x448'`, or `'x25519'` (for ECDH-ES). + ### `crypto.generateKeyPair(type, options, callback)` * `type`: {string} Must be `'rsa'`, `'dsa'`, `'ec'`, `'ed25519'`, `'ed448'`, - `'x25519'`, or `'x448'`. + `'x25519'`, `'x448'`, or `'dh'`. * `options`: {Object} * `modulusLength`: {number} Key size in bits (RSA, DSA). * `publicExponent`: {number} Public exponent (RSA). **Default:** `0x10001`. * `divisorLength`: {number} Size of `q` in bits (DSA). * `namedCurve`: {string} Name of the curve to use (EC). + * `prime`: {Buffer} The prime parameter (DH). + * `primeLength`: {number} Prime length in bits (DH). + * `generator`: {number} Custom generator (DH). **Default:** `2`. + * `groupName`: {string} Diffie-Hellman group name (DH). See + [`crypto.getDiffieHellman()`][]. * `publicKeyEncoding`: {Object} See [`keyObject.export()`][]. * `privateKeyEncoding`: {Object} See [`keyObject.export()`][]. * `callback`: {Function} @@ -2115,8 +2141,8 @@ changes: * `publicKey`: {string | Buffer | KeyObject} * `privateKey`: {string | Buffer | KeyObject} -Generates a new asymmetric key pair of the given `type`. RSA, DSA, EC, Ed25519 -and Ed448 are currently supported. +Generates a new asymmetric key pair of the given `type`. RSA, DSA, EC, Ed25519, +Ed448, X25519, X448, and DH are currently supported. If a `publicKeyEncoding` or `privateKeyEncoding` was specified, this function behaves as if [`keyObject.export()`][] had been called on its result. Otherwise, @@ -2154,6 +2180,9 @@ a `Promise` for an `Object` with `publicKey` and `privateKey` properties. -* `type`: {string} Must be `'rsa'`, `'dsa'`, `'ec'`, `'ed25519'`, or `'ed448'`. +* `type`: {string} Must be `'rsa'`, `'dsa'`, `'ec'`, `'ed25519'`, `'ed448'`, + `'x25519'`, `'x448'`, or `'dh'`. * `options`: {Object} * `modulusLength`: {number} Key size in bits (RSA, DSA). * `publicExponent`: {number} Public exponent (RSA). **Default:** `0x10001`. * `divisorLength`: {number} Size of `q` in bits (DSA). * `namedCurve`: {string} Name of the curve to use (EC). + * `prime`: {Buffer} The prime parameter (DH). + * `primeLength`: {number} Prime length in bits (DH). + * `generator`: {number} Custom generator (DH). **Default:** `2`. + * `groupName`: {string} Diffie-Hellman group name (DH). See + [`crypto.getDiffieHellman()`][]. * `publicKeyEncoding`: {Object} See [`keyObject.export()`][]. * `privateKeyEncoding`: {Object} See [`keyObject.export()`][]. * Returns: {Object} * `publicKey`: {string | Buffer | KeyObject} * `privateKey`: {string | Buffer | KeyObject} -Generates a new asymmetric key pair of the given `type`. RSA, DSA, EC, Ed25519 -and Ed448 are currently supported. +Generates a new asymmetric key pair of the given `type`. RSA, DSA, EC, Ed25519, +Ed448, X25519, X448, and DH are currently supported. If a `publicKeyEncoding` or `privateKeyEncoding` was specified, this function behaves as if [`keyObject.export()`][] had been called on its result. Otherwise, the respective part of the key is returned as a [`KeyObject`][]. When encoding public keys, it is recommended to use `'spki'`. When encoding -private keys, it is recommended to use `'pks8'` with a strong passphrase, and to -keep the passphrase confidential. +private keys, it is recommended to use `'pkcs8'` with a strong passphrase, +and to keep the passphrase confidential. ```js const { generateKeyPairSync } = require('crypto'); diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index 75170482015ab7..7bff22c958cbb4 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -2334,7 +2334,7 @@ The undocumented `net._setSimultaneousAccepts()` function was originally intended for debugging and performance tuning when using the `child_process` and `cluster` modules on Windows. The function is not generally useful and is being removed. See discussion here: -https://github.com/nodejs/node/issues/18391 + ### DEP0122: `tls` `Server.prototype.setOptions()` diff --git a/doc/api/dns.md b/doc/api/dns.md index cea7db52f9b9d4..4467b53b94b8f4 100644 --- a/doc/api/dns.md +++ b/doc/api/dns.md @@ -200,6 +200,12 @@ is not set to `true`, it returns a `Promise` for an `Object` with `address` and `family` properties. ### Supported getaddrinfo flags + The following flags can be passed as hints to [`dns.lookup()`][]. @@ -210,6 +216,8 @@ configured. Loopback addresses are not considered. * `dns.V4MAPPED`: If the IPv6 family was specified, but no IPv6 addresses were found, then return IPv4 mapped IPv6 addresses. It is not supported on some operating systems (e.g FreeBSD 10.1). +* `dns.ALL`: If `dns.V4MAPPED` is specified, return resolved IPv6 addresses as +well as IPv4 mapped IPv6 addresses. ## `dns.lookupService(address, port, callback)` + +The TLS socket must be connected and securily established. Ensure the 'secure' +event is emitted before continuing. + ### `ERR_TLS_INVALID_PROTOCOL_METHOD` @@ -1999,6 +2045,16 @@ the following reasons: * It is being linked (`linkingStatus` is `'linking'`) * Linking has failed for this module (`linkingStatus` is `'errored'`) + +### `ERR_VM_MODULE_CACHED_DATA_REJECTED` + +The `cachedData` option passed to a module constructor is invalid. + + +### `ERR_VM_MODULE_CANNOT_CREATE_CACHED_DATA` + +Cached data cannot be created for modules which have already been evaluated. + ### `ERR_VM_MODULE_DIFFERENT_CONTEXT` @@ -2037,6 +2093,11 @@ The `Worker` initialization failed. The `execArgv` option passed to the `Worker` constructor contains invalid flags. + +### `ERR_WORKER_NOT_RUNNING` + +An operation failed because the `Worker` instance is not currently running. + ### `ERR_WORKER_OUT_OF_MEMORY` @@ -2421,14 +2482,18 @@ This `Error` is thrown when a read is attempted on a TTY `WriteStream`, such as `process.stdout.on('data')`. [`'uncaughtException'`]: process.html#process_event_uncaughtexception +[`--disable-proto=throw`]: cli.html#cli_disable_proto_mode [`--force-fips`]: cli.html#cli_force_fips [`Class: assert.AssertionError`]: assert.html#assert_class_assert_assertionerror [`ERR_INVALID_ARG_TYPE`]: #ERR_INVALID_ARG_TYPE [`EventEmitter`]: events.html#events_class_eventemitter +[`Object.getPrototypeOf`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf +[`Object.setPrototypeOf`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf [`REPL`]: repl.html [`Writable`]: stream.html#stream_class_stream_writable [`child_process`]: child_process.html [`cipher.getAuthTag()`]: crypto.html#crypto_cipher_getauthtag +[`crypto.getDiffieHellman()`]: crypto.html#crypto_crypto_getdiffiehellman_groupname [`crypto.scrypt()`]: crypto.html#crypto_crypto_scrypt_password_salt_keylen_options_callback [`crypto.scryptSync()`]: crypto.html#crypto_crypto_scryptsync_password_salt_keylen_options [`crypto.timingSafeEqual()`]: crypto.html#crypto_crypto_timingsafeequal_a_b diff --git a/doc/api/esm.md b/doc/api/esm.md index da2f5184ed9d4d..5949758d26ca5e 100644 --- a/doc/api/esm.md +++ b/doc/api/esm.md @@ -27,12 +27,9 @@ specifier resolution, and default behavior. -The `--experimental-modules` flag can be used to enable support for -ECMAScript modules (ES modules). - -Once enabled, Node.js will treat the following as ES modules when passed to -`node` as the initial input, or when referenced by `import` statements within -ES module code: +Experimental support for ECMAScript modules is enabled by default. +Node.js will treat the following as ES modules when passed to `node` as the +initial input, or when referenced by `import` statements within ES module code: * Files ending in `.mjs`. @@ -78,7 +75,7 @@ until the root of the volume is reached. ```sh # In same folder as above package.json -node --experimental-modules my-app.js # Runs as ES module +node my-app.js # Runs as ES module ``` If the nearest parent `package.json` lacks a `"type"` field, or contains @@ -113,9 +110,8 @@ project’s `node_modules` folder contains its own `package.json` file, so each project’s dependencies have their own package scopes. A `package.json` lacking a `"type"` field is treated as if it contained `"type": "commonjs"`. -The package scope applies not only to initial entry points (`node ---experimental-modules my-app.js`) but also to files referenced by `import` -statements and `import()` expressions. +The package scope applies not only to initial entry points (`node my-app.js`) +but also to files referenced by `import` statements and `import()` expressions. ```js // my-app.js, in an ES module package scope because there is a package.json @@ -168,11 +164,9 @@ piped to `node` via `STDIN`, will be treated as ES modules when the `--input-type=module` flag is set. ```sh -node --experimental-modules --input-type=module --eval \ - "import { sep } from 'path'; console.log(sep);" +node --input-type=module --eval "import { sep } from 'path'; console.log(sep);" -echo "import { sep } from 'path'; console.log(sep);" | \ - node --experimental-modules --input-type=module +echo "import { sep } from 'path'; console.log(sep);" | node --input-type=module ``` For completeness there is also `--input-type=commonjs`, for explicitly running @@ -1004,8 +998,8 @@ The `--experimental-json-modules` flag is needed for the module to work. ```bash -node --experimental-modules index.mjs # fails -node --experimental-modules --experimental-json-modules index.mjs # works +node index.mjs # fails +node --experimental-json-modules index.mjs # works ``` ## Experimental Wasm Modules @@ -1027,7 +1021,7 @@ console.log(M); executed under: ```bash -node --experimental-modules --experimental-wasm-modules index.mjs +node --experimental-wasm-modules index.mjs ``` would provide the exports interface for the instantiation of `module.wasm`. @@ -1056,11 +1050,22 @@ and parent URL. The module specifier is the string in an `import` statement or `import()` expression, and the parent URL is the URL of the module that imported this one, or `undefined` if this is the main entry point for the application. +The `conditions` property on the `context` is an array of conditions for +[Conditional Exports][] that apply to this resolution request. They can be used +for looking up conditional mappings elsewhere or to modify the list when calling +the default resolution logic. + +The [current set of Node.js default conditions][Conditional Exports] will always +be in the `context.conditions` list passed to the hook. If the hook wants to +ensure Node.js-compatible resolution logic, all items from this default +condition list **must** be passed through to the `defaultResolve` function. + ```js /** * @param {string} specifier * @param {object} context * @param {string} context.parentURL + * @param {string[]} context.conditions * @param {function} defaultResolve * @returns {object} response * @returns {string} response.url @@ -1075,6 +1080,14 @@ export async function resolve(specifier, context, defaultResolve) { new URL(specifier, parentURL).href : new URL(specifier).href }; } + if (anotherCondition) { + // When calling the defaultResolve, the arguments can be modified. In this + // case it's adding another value for matching conditional exports. + return defaultResolve(specifier, { + ...context, + conditions: [...context.conditions, 'another-condition'], + }); + } // Defer to Node.js for all other specifiers. return defaultResolve(specifier, context, defaultResolve); } @@ -1154,7 +1167,7 @@ export async function getSource(url, context, defaultGetSource) { #### transformSource hook ```console -NODE_OPTIONS='--experimental-modules --experimental-loader ./custom-loader.mjs' node x.js +NODE_OPTIONS='--experimental-loader ./custom-loader.mjs' node x.js ``` > Note: The loaders API is being redesigned. This hook may disappear or its @@ -1222,7 +1235,7 @@ console.log('I just set some globals!'); const { createRequire } = getBuiltin('module'); -const require = createRequire(process.cwd + '/'); +const require = createRequire(process.cwd() + '/'); // [...] `; } @@ -1592,13 +1605,6 @@ The resolver can throw the following errors: > 1. Return **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, > _mainExport_, _""_). > 1. Throw a _Package Path Not Exported_ error. -> 1. If _pjson.main_ is a String, then -> 1. Let _resolvedMain_ be the URL resolution of _packageURL_, "/", and -> _pjson.main_. -> 1. If the file at _resolvedMain_ exists, then -> 1. Return _resolvedMain_. -> 1. If _pjson.type_ is equal to _"module"_, then -> 1. Throw a _Module Not Found_ error. > 1. Let _legacyMainURL_ be the result applying the legacy > **LOAD_AS_DIRECTORY** CommonJS resolver to _packageURL_, throwing a > _Module Not Found_ error for no resolution. @@ -1652,13 +1658,15 @@ The resolver can throw the following errors: > loop on any _Package Path Not Exported_ error. > 1. Throw a _Package Path Not Exported_ error. > 1. Otherwise, if _target_ is an Array, then -> 1. If _target.length is zero, throw an _Invalid Package Target_ error. +> 1. If _target.length is zero, throw a _Package Path Not Exported_ error. > 1. For each item _targetValue_ in _target_, do > 1. If _targetValue_ is an Array, continue the loop. > 1. Return the result of **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, > _targetValue_, _subpath_, _env_), continuing the loop on any > _Package Path Not Exported_ or _Invalid Package Target_ error. > 1. Throw the last fallback resolution error. +> 1. Otherwise, if _target_ is _null_, throw a _Package Path Not Exported_ +> error. > 1. Otherwise throw an _Invalid Package Target_ error. **ESM_FORMAT**(_url_) @@ -1712,11 +1720,11 @@ automatic extension resolution and importing from directories that include an index file use the `node` mode. ```bash -$ node --experimental-modules index.mjs +$ node index.mjs success! -$ node --experimental-modules index #Failure! +$ node index # Failure! Error: Cannot find module -$ node --experimental-modules --experimental-specifier-resolution=node index +$ node --experimental-specifier-resolution=node index success! ``` diff --git a/doc/api/events.md b/doc/api/events.md index 854150de3a4982..0a18091fdf7804 100644 --- a/doc/api/events.md +++ b/doc/api/events.md @@ -155,6 +155,18 @@ myEmitter.emit('error', new Error('whoops!')); // Prints: whoops! there was an error ``` +It is possible to monitor `'error'` events without consuming the emitted error +by installing a listener using the symbol `errorMonitor`. + +```js +const myEmitter = new MyEmitter(); +myEmitter.on(EventEmitter.errorMonitor, (err) => { + MyMonitoringTool.log(err); +}); +myEmitter.emit('error', new Error('whoops!')); +// Still throws and crashes Node.js +``` + ## Capture Rejections of Promises > Stability: 1 - captureRejections is experimental. @@ -348,6 +360,19 @@ the event emitter instance, the event’s name and the number of attached listeners, respectively. Its `name` property is set to `'MaxListenersExceededWarning'`. +### `EventEmitter.errorMonitor` + + +This symbol shall be used to install a listener for only monitoring `'error'` +events. Listeners installed using this symbol are called before the regular +`'error'` listeners are called. + +Installing a listener using this symbol does not change the behavior once an +`'error'` event is emitted, therefore the process will still crash if no +regular `'error'` listener is installed. + ### `emitter.addListener(eventName, listener)` -A representation of a directory entry, as returned by reading from an -[`fs.Dir`][]. +A representation of a directory entry, which can be a file or a subdirectory +within the directory, as returned by reading from an [`fs.Dir`][]. The +directory entry is a combination of the file name and file type pairs. Additionally, when [`fs.readdir()`][] or [`fs.readdirSync()`][] is called with the `withFileTypes` option set to `true`, the resulting array is filled with @@ -1674,6 +1675,10 @@ changes: - version: v2.3.0 pr-url: https://github.com/nodejs/node/pull/1845 description: The passed `options` object can be a string now. + - version: v12.17.0 + pr-url: https://github.com/nodejs/node/pull/29083 + description: The `fs` options allow overriding the used `fs` + implementation. --> * `path` {string|Buffer|URL} @@ -1688,7 +1693,8 @@ changes: * `start` {integer} * `end` {integer} **Default:** `Infinity` * `highWaterMark` {integer} **Default:** `64 * 1024` -* Returns: {fs.ReadStream} + * `fs` {Object|null} **Default:** `null` +* Returns: {fs.ReadStream} See [Readable Stream][]. Unlike the 16 kb default `highWaterMark` for a readable stream, the stream returned by this method has a default `highWaterMark` of 64 kb. @@ -1715,6 +1721,10 @@ By default, the stream will not emit a `'close'` event after it has been destroyed. This is the opposite of the default for other `Readable` streams. Set the `emitClose` option to `true` to change this behavior. +By providing the `fs` option, it is possible to override the corresponding `fs` +implementations for `open`, `read`, and `close`. When providing the `fs` option, +overrides for `open`, `read`, and `close` are required. + ```js const fs = require('fs'); // Create a stream from some character device. @@ -1768,6 +1778,10 @@ changes: - version: v2.3.0 pr-url: https://github.com/nodejs/node/pull/1845 description: The passed `options` object can be a string now. + - version: v12.17.0 + pr-url: https://github.com/nodejs/node/pull/v12.17.0 + description: The `fs` options allow overriding the used `fs` + implementation. --> * `path` {string|Buffer|URL} @@ -1780,7 +1794,8 @@ changes: * `autoClose` {boolean} **Default:** `true` * `emitClose` {boolean} **Default:** `false` * `start` {integer} -* Returns: {fs.WriteStream} + * `fs` {Object|null} **Default:** `null` +* Returns: {fs.WriteStream} See [Writable Stream][]. `options` may also include a `start` option to allow writing data at some position past the beginning of the file, allowed values are in the @@ -1799,6 +1814,12 @@ By default, the stream will not emit a `'close'` event after it has been destroyed. This is the opposite of the default for other `Writable` streams. Set the `emitClose` option to `true` to change this behavior. +By providing the `fs` option it is possible to override the corresponding `fs` +implementations for `open`, `write`, `writev` and `close`. Overriding `write()` +without `writev()` can reduce performance as some optimizations (`_writev()`) +will be disabled. When providing the `fs` option, overrides for `open`, +`close`, and at least one of `write` and `writev` are required. + Like [`ReadStream`][], if `fd` is specified, [`WriteStream`][] will ignore the `path` argument and will use the specified file descriptor. This means that no `'open'` event will be emitted. `fd` should be blocking; non-blocking `fd`s @@ -2418,6 +2439,10 @@ Synchronous lstat(2). +* `fd` {integer} +* `options` {Object} + * `buffer` {Buffer|TypedArray|DataView} **Default:** `Buffer.alloc(16384)` + * `offset` {integer} **Default:** `0` + * `length` {integer} **Default:** `buffer.length` + * `position` {integer} **Default:** `null` +* `callback` {Function} + * `err` {Error} + * `bytesRead` {integer} + * `buffer` {Buffer} + +Similar to the above `fs.read` function, this version takes an optional `options` object. +If no `options` object is specified, it will default with the above values. + ## `fs.readdir(path[, options], callback)` + +* `fd` {integer} +* `buffer` {Buffer|TypedArray|DataView} +* `options` {Object} + * `offset` {integer} **Default:** `0` + * `length` {integer} **Default:** `buffer.length` + * `position` {integer} **Default:** `null` +* Returns: {number} + +Returns the number of `bytesRead`. + +Similar to the above `fs.readSync` function, this version takes an optional `options` object. +If no `options` object is specified, it will default with the above values. + +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.read()`][]. + +## `fs.readv(fd, buffers[, position], callback)` + + +* `fd` {integer} +* `buffers` {ArrayBufferView[]} +* `position` {integer} +* `callback` {Function} + * `err` {Error} + * `bytesRead` {integer} + * `buffers` {ArrayBufferView[]} + +Read from a file specified by `fd` and write to an array of `ArrayBufferView`s +using `readv()`. + +`position` is the offset from the beginning of the file from where data +should be read. If `typeof position !== 'number'`, the data will be read +from the current position. + +The callback will be given three arguments: `err`, `bytesRead`, and +`buffers`. `bytesRead` is how many bytes were read from the file. + +## `fs.readvSync(fd, buffers[, position])` + + +* `fd` {integer} +* `buffers` {ArrayBufferView[]} +* `position` {integer} +* Returns: {number} The number of bytes read. + +For detailed information, see the documentation of the asynchronous version of +this API: [`fs.readv()`][]. + ## `fs.realpath(path[, options], callback)` +* `options` {Object} + * `buffer` {Buffer|Uint8Array} **Default:** `Buffer.alloc(16384)` + * `offset` {integer} **Default:** `0` + * `length` {integer} **Default:** `buffer.length` + * `position` {integer} **Default:** `null` +* Returns: {Promise} + #### `filehandle.readFile(options)` + +* `buffers` {ArrayBufferView[]} +* `position` {integer} +* Returns: {Promise} + +Read from a file and write to an array of `ArrayBufferView`s + +The `Promise` is resolved with an object containing a `bytesRead` property +identifying the number of bytes read, and a `buffers` property containing +a reference to the `buffers` input. + +`position` is the offset from the beginning of the file where this data +should be read from. If `typeof position !== 'number'`, the data will be read +from the current position. + #### `filehandle.stat([options])` -* {number} **Default:** `40000` +* {number} **Default:** `60000` Limit the amount of time the parser will wait to receive the complete HTTP headers. @@ -1122,6 +1122,8 @@ event is emitted on the server object, and (by default) the socket is destroyed. See [`server.timeout`][] for more information on how timeout behavior can be customized. +A value of `0` will disable the HTTP headers timeout check. + ### `server.listen()` Starts the HTTP server listening for connections. @@ -1705,12 +1707,10 @@ const server = http.createServer((req, res) => { }); ``` -`Content-Length` is given in bytes not characters. The above example -works because the string `'hello world'` contains only single byte characters. -If the body contains higher coded characters then `Buffer.byteLength()` -should be used to determine the number of bytes in a given encoding. -And Node.js does not check whether `Content-Length` and the length of the body -which has been transmitted are equal or not. +`Content-Length` is given in bytes, not characters. Use +[`Buffer.byteLength()`][] to determine the length of the body in bytes. Node.js +does not check whether `Content-Length` and the length of the body which has +been transmitted are equal or not. Attempting to set a header field name or value that contains invalid characters will result in a [`TypeError`][] being thrown. @@ -2346,6 +2346,7 @@ not abort the request or do anything besides add a `'timeout'` event. [`'response'`]: #http_event_response [`'upgrade'`]: #http_event_upgrade [`Agent`]: #http_class_http_agent +[`Buffer.byteLength()`]: buffer.html#buffer_class_method_buffer_bytelength_string_encoding [`Duplex`]: stream.html#stream_class_stream_duplex [`TypeError`]: errors.html#errors_class_typeerror [`URL`]: url.html#url_the_whatwg_url_api diff --git a/doc/api/https.md b/doc/api/https.md index 08f48eaa392460..c685b3fe636c5a 100644 --- a/doc/api/https.md +++ b/doc/api/https.md @@ -94,7 +94,7 @@ See [`server.close()`][`http.close()`] from the HTTP module for details. added: v11.3.0 --> -* {number} **Default:** `40000` +* {number} **Default:** `60000` See [`http.Server#headersTimeout`][]. @@ -123,13 +123,9 @@ See [`http.Server#setTimeout()`][]. ### `server.timeout` -* {number} **Default:** 0 (no timeout) +* {number} **Default:** `120000` (2 minutes) See [`http.Server#timeout`][]. diff --git a/doc/api/modules.md b/doc/api/modules.md index eda6855e3c2488..8b06b02f2f2c6b 100644 --- a/doc/api/modules.md +++ b/doc/api/modules.md @@ -1024,6 +1024,86 @@ import('fs').then((esmFS) => { }); ``` +## Source Map V3 Support + + +> Stability: 1 - Experimental + +Helpers for interacting with the source map cache. This cache is +populated when source map parsing is enabled and +[source map include directives][] are found in a modules' footer. + +To enable source map parsing, Node.js must be run with the flag +[`--enable-source-maps`][], or with code coverage enabled by setting +[`NODE_V8_COVERAGE=dir`][]. + +```js +const { findSourceMap, SourceMap } = require('module'); +``` + +### `module.findSourceMap(path[, error])` + + +* `path` {string} +* `error` {Error} +* Returns: {module.SourceMap} + +`path` is the resolved path for the file for which a corresponding source map +should be fetched. + +The `error` instance should be passed as the second parameter to `findSourceMap` +in exceptional flows, e.g., when an overridden +[`Error.prepareStackTrace(error, trace)`][] is invoked. Modules are not added to +the module cache until they are successfully loaded, in these cases source maps +will be associated with the `error` instance along with the `path`. + +### Class: `module.SourceMap` + + +#### `new SourceMap(payload)` + +* `payload` {Object} + +Creates a new `sourceMap` instance. + +`payload` is an object with keys matching the [Source Map V3 format][]: + +* `file`: {string} +* `version`: {number} +* `sources`: {string[]} +* `sourcesContent`: {string[]} +* `names`: {string[]} +* `mappings`: {string} +* `sourceRoot`: {string} + +#### `sourceMap.payload` + +* Returns: {Object} + +Getter for the payload used to construct the [`SourceMap`][] instance. + +#### `sourceMap.findEntry(lineNumber, columnNumber)` + +* `lineNumber` {number} +* `columnNumber` {number} +* Returns: {Object} + +Given a line number and column number in the generated source file, returns +an object representing the position in the original file. The object returned +consists of the following keys: + +* generatedLine: {number} +* generatedColumn: {number} +* originalSource: {string} +* originalLine: {number} +* originalColumn: {number} + [GLOBAL_FOLDERS]: #modules_loading_from_the_global_folders [`Error`]: errors.html#errors_class_error [`__dirname`]: #modules_dirname @@ -1037,3 +1117,9 @@ import('fs').then((esmFS) => { [module resolution]: #modules_all_together [module wrapper]: #modules_the_module_wrapper [native addons]: addons.html +[source map include directives]: https://sourcemaps.info/spec.html#h.lmz475t4mvbx +[`--enable-source-maps`]: cli.html#cli_enable_source_maps +[`NODE_V8_COVERAGE=dir`]: cli.html#cli_node_v8_coverage_dir +[`Error.prepareStackTrace(error, trace)`]: https://v8.dev/docs/stack-trace-api#customizing-stack-traces +[`SourceMap`]: modules.html#modules_class_module_sourcemap +[Source Map V3 format]: https://sourcemaps.info/spec.html#h.mofvlxcwqzej diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 77b3d3b4a4a46f..d635ccba26af37 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -241,15 +241,16 @@ from version 3 with some additions. This means that it is not necessary to recompile for new versions of Node.js which are listed as supporting a later version. -| | 1 | 2 | 3 | 4 | 5 | -|-------|---------|----------|----------|----------|-----------| -| v6.x | | | v6.14.2* | | | -| v8.x | v8.0.0* | v8.10.0* | v8.11.2 | v8.16.0 | | -| v9.x | v9.0.0* | v9.3.0* | v9.11.0* | | | -| v10.x | | | v10.0.0 | | | -| v11.x | | | v11.0.0 | v11.8.0 | | -| v12.x | | | | v12.0.0 | v12.11.0 | -| v13.x | | | | | | +| | 1 | 2 | 3 | 4 | 5 | 6 | +|-------|---------|----------|----------|----------|-----------|-----------| +| v6.x | | | v6.14.2* | | | | +| v8.x | v8.0.0* | v8.10.0* | v8.11.2 | v8.16.0 | | | +| v9.x | v9.0.0* | v9.3.0* | v9.11.0* | | | | +| v10.x | v10.0.0 | v10.0.0 | v10.0.0 | v10.16.0 | v10.17.0 | v10.20.0 | +| v11.x | v11.0.0 | v11.0.0 | v11.0.0 | v11.8.0 | | | +| v12.x | v12.0.0 | v12.0.0 | v12.0.0 | v12.0.0 | v12.11.0 | v12.17.0 | +| v13.x | v13.0.0 | v13.0.0 | v13.0.0 | v13.0.0 | v13.0.0 | | +| v14.x | v14.0.0 | v14.0.0 | v14.0.0 | v14.0.0 | v14.0.0 | v14.0.0 | \* Indicates that the N-API version was released as experimental @@ -374,6 +375,7 @@ tied to the life cycle of the Agent. ### napi_set_instance_data ```C @@ -401,6 +403,7 @@ by the previous call, it will not be called. ### napi_get_instance_data ```C @@ -858,7 +861,7 @@ SemVer applying. In order to support this model with N-API, both in internal functionality and for module specific functionality (as its good practice), the `throw_` and `create_` functions take an optional code parameter which is the string for the code -to be added to the error object. If the optional parameter is NULL +to be added to the error object. If the optional parameter is `NULL` then no code will be associated with the error. If a code is provided, the name associated with the error is also updated to be: @@ -1056,7 +1059,7 @@ napi_status napi_get_and_clear_last_exception(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[out] result`: The exception if one is pending, NULL otherwise. +* `[out] result`: The exception if one is pending, `NULL` otherwise. Returns `napi_ok` if the API succeeded. @@ -1348,7 +1351,7 @@ then be modified through [`napi_reference_ref`][] and [`napi_reference_unref`][]. If an object is collected while the count for a reference is 0, all subsequent calls to get the object associated with the reference [`napi_get_reference_value`][] -will return NULL for the returned `napi_value`. An attempt to call +will return `NULL` for the returned `napi_value`. An attempt to call [`napi_reference_ref`][] for a reference whose object has been collected will result in an error. @@ -1471,7 +1474,7 @@ Returns `napi_ok` if the API succeeded. If still valid, this API returns the `napi_value` representing the JavaScript `Object` associated with the `napi_ref`. Otherwise, result -will be NULL. +will be `NULL`. ### Cleanup on exit of the current Node.js instance @@ -1547,7 +1550,7 @@ napi_value Init(napi_env env, napi_value exports); The return value from `Init` is treated as the `exports` object for the module. The `Init` method is passed an empty object via the `exports` parameter as a -convenience. If `Init` returns NULL, the parameter passed as `exports` is +convenience. If `Init` returns `NULL`, the parameter passed as `exports` is exported by the module. N-API modules cannot modify the `module` object but can specify anything as the `exports` property of the module. @@ -1659,6 +1662,63 @@ However, for better performance, it's better for the caller to make sure that the `napi_value` in question is of the JavaScript type expected by the API. ### Enum types +#### napi_key_collection_mode + + +```C +typedef enum { + napi_key_include_prototypes, + napi_key_own_only +} napi_key_collection_mode; +``` + +Describes the `Keys/Properties` filter enums: + +`napi_key_collection_mode` limits the range of collected properties. + +`napi_key_own_only` limits the collected properties to the given +object only. `napi_key_include_prototypes` will include all keys +of the objects's prototype chain as well. + +#### napi_key_filter + + +```C +typedef enum { + napi_key_all_properties = 0, + napi_key_writable = 1, + napi_key_enumerable = 1 << 1, + napi_key_configurable = 1 << 2, + napi_key_skip_strings = 1 << 3, + napi_key_skip_symbols = 1 << 4 +} napi_key_filter; +``` + +Property filter bits. They can be or'ed to build a composite filter. + +#### napi_key_conversion + + +```C +typedef enum { + napi_key_keep_numbers, + napi_key_numbers_to_strings +} napi_key_conversion; +``` + +`napi_key_numbers_to_strings` will convert integer indices to +strings. `napi_key_keep_numbers` will return numbers for integer +indices. + #### napi_valuetype ```C @@ -2201,10 +2261,9 @@ The JavaScript `Number` type is described in #### napi_create_bigint_int64 -> Stability: 1 - Experimental - ```C napi_status napi_create_bigint_int64(napi_env env, int64_t value, @@ -2222,10 +2281,9 @@ This API converts the C `int64_t` type to the JavaScript `BigInt` type. #### napi_create_bigint_uint64 -> Stability: 1 - Experimental - ```C napi_status napi_create_bigint_uint64(napi_env env, uint64_t value, @@ -2243,10 +2301,9 @@ This API converts the C `uint64_t` type to the JavaScript `BigInt` type. #### napi_create_bigint_words -> Stability: 1 - Experimental - ```C napi_status napi_create_bigint_words(napi_env env, int sign_bit, @@ -2596,10 +2653,9 @@ This API returns the C double primitive equivalent of the given JavaScript #### napi_get_value_bigint_int64 -> Stability: 1 - Experimental - ```C napi_status napi_get_value_bigint_int64(napi_env env, napi_value value, @@ -2623,10 +2679,9 @@ This API returns the C `int64_t` primitive equivalent of the given JavaScript #### napi_get_value_bigint_uint64 -> Stability: 1 - Experimental - ```C napi_status napi_get_value_bigint_uint64(napi_env env, napi_value value, @@ -2650,10 +2705,9 @@ This API returns the C `uint64_t` primitive equivalent of the given JavaScript #### napi_get_value_bigint_words -> Stability: 1 - Experimental - ```C napi_status napi_get_value_bigint_words(napi_env env, napi_value value, @@ -2774,7 +2828,7 @@ napi_status napi_get_value_string_latin1(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing JavaScript string. -* `[in] buf`: Buffer to write the ISO-8859-1-encoded string into. If NULL is +* `[in] buf`: Buffer to write the ISO-8859-1-encoded string into. If `NULL` is passed in, the length of the string (in bytes) is returned. * `[in] bufsize`: Size of the destination buffer. When this value is insufficient, the returned string will be truncated. @@ -2803,7 +2857,7 @@ napi_status napi_get_value_string_utf8(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing JavaScript string. -* `[in] buf`: Buffer to write the UTF8-encoded string into. If NULL is passed +* `[in] buf`: Buffer to write the UTF8-encoded string into. If `NULL` is passed in, the length of the string (in bytes) is returned. * `[in] bufsize`: Size of the destination buffer. When this value is insufficient, the returned string will be truncated. @@ -2831,7 +2885,7 @@ napi_status napi_get_value_string_utf16(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing JavaScript string. -* `[in] buf`: Buffer to write the UTF16-LE-encoded string into. If NULL is +* `[in] buf`: Buffer to write the UTF16-LE-encoded string into. If `NULL` is passed in, the length of the string (in 2-byte code units) is returned. * `[in] bufsize`: Size of the destination buffer. When this value is insufficient, the returned string will be truncated. @@ -3535,6 +3589,36 @@ This API returns the names of the enumerable properties of `object` as an array of strings. The properties of `object` whose key is a symbol will not be included. +#### napi_get_all_property_names + + +```C +napi_get_all_property_names(napi_env env, + napi_value object, + napi_key_collection_mode key_mode, + napi_key_filter key_filter, + napi_key_conversion key_conversion, + napi_value* result); +``` + +* `[in] env`: The environment that the N-API call is invoked under. +* `[in] object`: The object from which to retrieve the properties. +* `[in] key_mode`: Whether to retrieve prototype properties as well. +* `[in] key_filter`: Which properties to retrieve +(enumerable/readable/writable). +* `[in] key_conversion`: Whether to convert numbered property keys to strings. +* `[out] result`: A `napi_value` representing an array of JavaScript values +that represent the property names of the object. [`napi_get_array_length`][] and +[`napi_get_element`][] can be used to iterate over `result`. + +Returns `napi_ok` if the API succeeded. + +This API returns an array containing the names of the available properties +of this object. + #### napi_set_property -* `exception` {Object} +* `error` {Object} * Returns: {net.Socket} -Ensures that no more I/O activity happens on this socket. Only necessary in -case of errors (parse error or so). +Ensures that no more I/O activity happens on this socket. +Destroys the stream and closes the connection. -If `exception` is specified, an [`'error'`][] event will be emitted and any -listeners for that event will receive `exception` as an argument. +See [`writable.destroy()`][] for further details. ### `socket.destroyed` * {boolean} Indicates if the connection is destroyed or not. Once a connection is destroyed no further data can be transferred using it. +See [`writable.destroyed`][] for further details. + ### `socket.end([data[, encoding]][, callback])` + +* Returns {string} + +Returns a string identifying the kernel version. + +On POSIX systems, the operating system release is determined by calling +[uname(3)][]. On Windows, `RtlGetVersion()` is used, and if it is not available, +`GetVersionExW()` will be used. See + for more information. + ## OS Constants The following constants are exported by `os.constants`. diff --git a/doc/api/perf_hooks.md b/doc/api/perf_hooks.md index a34d41ce3f250f..c17c95c3d62e22 100644 --- a/doc/api/perf_hooks.md +++ b/doc/api/perf_hooks.md @@ -209,6 +209,25 @@ The value may be one of: * `perf_hooks.constants.NODE_PERFORMANCE_GC_INCREMENTAL` * `perf_hooks.constants.NODE_PERFORMANCE_GC_WEAKCB` +### performanceEntry.flags + + +* {number} + +When `performanceEntry.entryType` is equal to `'gc'`, the `performance.flags` +property contains additional information about garbage collection operation. +The value may be one of: + +* `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_NO` +* `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED` +* `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_FORCED` +* `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING` +* `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE` +* `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY` +* `perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE` + ## Class: `PerformanceNodeTiming extends PerformanceEntry` + +* `err` {Error} The uncaught exception. +* `origin` {string} Indicates if the exception originates from an unhandled + rejection or from synchronous errors. Can either be `'uncaughtException'` or + `'unhandledRejection'`. + +The `'uncaughtExceptionMonitor'` event is emitted before an +`'uncaughtException'` event is emitted or a hook installed via +[`process.setUncaughtExceptionCaptureCallback()`][] is called. + +Installing an `'uncaughtExceptionMonitor'` listener does not change the behavior +once an `'uncaughtException'` event is emitted. The process will +still crash if no `'uncaughtException'` listener is installed. + +```js +process.on('uncaughtExceptionMonitor', (err, origin) => { + MyMonitoringTool.logSync(err, origin); +}); + +// Intentionally cause an exception, but don't catch it. +nonexistentFunc(); +// Still crashes Node.js +``` + ### Event: `'unhandledRejection'` -> Stability: 1 - Experimental - * {Object} `process.report` is an object whose methods are used to generate diagnostic reports for the current process. Additional documentation is available in the [report documentation][]. +### `process.report.compact` + + +* {boolean} + +Write reports in a compact format, single-line JSON, more easily consumable +by log processing systems than the default multi-line format designed for +human consumption. + +```js +console.log(`Reports are compact? ${process.report.compact}`); +``` + ### `process.report.directory` -> Stability: 1 - Experimental - * {string} Directory where the report is written. The default value is the empty string, @@ -1746,10 +1804,12 @@ console.log(`Report directory is ${process.report.directory}`); ### `process.report.filename` -> Stability: 1 - Experimental - * {string} Filename where the report is written. If set to the empty string, the output @@ -1763,10 +1823,12 @@ console.log(`Report filename is ${process.report.filename}`); ### `process.report.getReport([err])` -> Stability: 1 - Experimental - * `err` {Error} A custom error used for reporting the JavaScript stack. * Returns: {Object} @@ -1804,10 +1866,12 @@ console.log(`Report on fatal error: ${process.report.reportOnFatalError}`); ### `process.report.reportOnSignal` -> Stability: 1 - Experimental - * {boolean} If `true`, a diagnostic report is generated when the process receives the @@ -1820,10 +1884,12 @@ console.log(`Report on signal: ${process.report.reportOnSignal}`); ### `process.report.reportOnUncaughtException` -> Stability: 1 - Experimental - * {boolean} If `true`, a diagnostic report is generated on uncaught exception. @@ -1835,10 +1901,12 @@ console.log(`Report on exception: ${process.report.reportOnUncaughtException}`); ### `process.report.signal` -> Stability: 1 - Experimental - * {string} The signal used to trigger the creation of a diagnostic report. Defaults to @@ -1851,10 +1919,12 @@ console.log(`Report signal: ${process.report.signal}`); ### `process.report.writeReport([filename][, err])` -> Stability: 1 - Experimental - * `filename` {string} Name of the file where the report is written. This should be a relative path, that will be appended to the directory specified in `process.report.directory`, or the current working directory of the Node.js @@ -2465,6 +2535,7 @@ cases: [`'exit'`]: #process_event_exit [`'message'`]: child_process.html#child_process_event_message [`'uncaughtException'`]: #process_event_uncaughtexception +[`Buffer`]: buffer.html [`ChildProcess.disconnect()`]: child_process.html#child_process_subprocess_disconnect [`ChildProcess.send()`]: child_process.html#child_process_subprocess_send_message_sendhandle_options_callback [`ChildProcess`]: child_process.html#child_process_class_childprocess diff --git a/doc/api/readline.md b/doc/api/readline.md index 0474de8ad6cf46..bd0f544def6fe1 100644 --- a/doc/api/readline.md +++ b/doc/api/readline.md @@ -293,7 +293,8 @@ added: v0.1.98 The `rl.write()` method will write either `data` or a key sequence identified by `key` to the `output`. The `key` argument is supported only if `output` is -a [TTY][] text terminal. +a [TTY][] text terminal. See [TTY keybindings][] for a list of key +combinations. If `key` is specified, `data` is ignored. @@ -722,6 +723,131 @@ const { createInterface } = require('readline'); })(); ``` +## TTY keybindings + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeybindingsDescriptionNotes
ctrl + shift + backspaceDelete line leftDoesn't work on Linux, Mac and Windows
ctrl + shift + deleteDelete line rightDoesn't work on Linux and Mac
ctrl + cEmit SIGINT or close the readline instance
ctrl + hDelete left
ctrl + dDelete right or close the readline instance in case the current line is empty / EOFDoesn't work on Windows
ctrl + uDelete from the current position to the line start
ctrl + kDelete from the current position to the end of line
ctrl + aGo to start of line
ctrl + eGo to to end of line
ctrl + bBack one character
ctrl + fForward one character
ctrl + lClear screen
ctrl + nNext history item
ctrl + pPrevious history item
ctrl + zMoves running process into background. Type + fg and press enter + to return.Doesn't work on Windows
ctrl + w or ctrl + + backspaceDelete backwards to a word boundaryctrl + backspace Doesn't + work as expected on Windows
ctrl + deleteDelete forward to a word boundaryDoesn't work on Mac
ctrl + left or + meta + bWord leftctrl + left Doesn't work + on Mac
ctrl + right or + meta + fWord rightctrl + right Doesn't work + on Mac
meta + d or meta + + deleteDelete word rightmeta + delete Doesn't work + on windows
meta + backspaceDelete word leftDoesn't work on Mac
+ [`'SIGCONT'`]: readline.html#readline_event_sigcont [`'SIGTSTP'`]: readline.html#readline_event_sigtstp [`'line'`]: #readline_event_line @@ -731,5 +857,6 @@ const { createInterface } = require('readline'); [`rl.close()`]: #readline_rl_close [Readable]: stream.html#stream_readable_streams [TTY]: tty.html +[TTY keybindings]: #readline_tty_keybindings [Writable]: stream.html#stream_writable_streams [reading files]: #readline_example_read_file_stream_line_by_line diff --git a/doc/api/repl.md b/doc/api/repl.md index 8d5fa87f2c3f17..50845785cf9c71 100644 --- a/doc/api/repl.md +++ b/doc/api/repl.md @@ -21,9 +21,12 @@ result. Input and output may be from `stdin` and `stdout`, respectively, or may be connected to any Node.js [stream][]. Instances of [`repl.REPLServer`][] support automatic completion of inputs, -simplistic Emacs-style line editing, multi-line inputs, ANSI-styled output, -saving and restoring current REPL session state, error recovery, and -customizable evaluation functions. +completion preview, simplistic Emacs-style line editing, multi-line inputs, +[ZSH][]-like reverse-i-search, [ZSH][]-like substring-based history search, +ANSI-styled output, saving and restoring current REPL session state, error +recovery, and customizable evaluation functions. Terminals that do not support +ANSI styles and Emacs-style line editing automatically fall back to a limited +feature set. ### Commands and Special Keys @@ -66,6 +69,9 @@ The following key combinations in the REPL have these special effects: variables. When pressed while entering other input, displays relevant autocompletion options. +For key bindings related to the reverse-i-search, see [`reverse-i-search`][]. +For all other key bindings, see [TTY keybindings][]. + ### Default Evaluation By default, all instances of [`repl.REPLServer`][] use an evaluation function @@ -232,6 +238,24 @@ undefined undefined ``` +### Reverse-i-search + + +The REPL supports bi-directional reverse-i-search similar to [ZSH][]. It is +triggered with ` + R` to search backwards and ` + S` to search +forwards. + +Duplicated history entires will be skipped. + +Entries are accepted as soon as any button is pressed that doesn't correspond +with the reverse search. Cancelling is possible by pressing `escape` or +` + C`. + +Changing the direction immediately searches for the next entry in the expected +direction from the current position on. + ### Custom Evaluation Functions When a new [`repl.REPLServer`][] is created, a custom evaluation function may be @@ -520,6 +544,9 @@ with REPL instances programmatically. -> Stability: 1 - Experimental +> Stability: 2 - Stable @@ -32,7 +32,6 @@ is provided below for reference. "cwd": "/home/nodeuser/project/node", "commandLine": [ "/home/nodeuser/project/node/out/Release/node", - "--experimental-report", "--report-uncaught-exception", "/home/nodeuser/project/node/test/report/test-exception.js", "child" @@ -393,14 +392,10 @@ is provided below for reference. ## Usage ```bash -node --experimental-report --report-uncaught-exception \ - --report-on-signal --report-on-fatalerror app.js +node --report-uncaught-exception --report-on-signal \ +--report-on-fatalerror app.js ``` -* `--experimental-report` Enables the diagnostic report feature. - In the absence of this flag, use of all other related options will result in - an error. - * `--report-uncaught-exception` Enables report to be generated on un-caught exceptions. Useful when inspecting JavaScript stack in conjunction with native stack and other runtime environment data. @@ -425,6 +420,10 @@ that leads to termination of the application. Useful to inspect various diagnostic data elements such as heap, stack, event loop state, resource consumption etc. to reason about the fatal error. +* `--report-compact` Write reports in a compact format, single-line JSON, more +easily consumable by log processing systems than the default multi-line format +designed for human consumption. + * `--report-directory` Location at which the report will be generated. @@ -570,7 +569,7 @@ Configuration on module initialization is also available via environment variables: ```bash -NODE_OPTIONS="--experimental-report --report-uncaught-exception \ +NODE_OPTIONS="--report-uncaught-exception \ --report-on-fatalerror --report-on-signal \ --report-signal=SIGUSR2 --report-filename=./report.json \ --report-directory=/home/nodeuser" diff --git a/doc/api/stream.md b/doc/api/stream.md index ee7746564a0227..ae29a38b8f4b5d 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -1422,7 +1422,7 @@ If the loop terminates with a `break` or a `throw`, the stream will be destroyed. In other terms, iterating over a stream will consume the stream fully. The stream will be read in chunks of size equal to the `highWaterMark` option. In the code example above, data will be in a single chunk if the file -has less then 64kb of data because no `highWaterMark` option is provided to +has less then 64KB of data because no `highWaterMark` option is provided to [`fs.createReadStream()`][]. ### Duplex and Transform Streams @@ -1470,6 +1470,7 @@ added: v8.0.0 --> * `error` {Error} +* Returns: {this} Destroy the stream, and optionally emit an `'error'` event. After this call, the transform stream would release any internal resources. @@ -1620,7 +1621,8 @@ added: --> * `iterable` {Iterable} Object implementing the `Symbol.asyncIterator` or - `Symbol.iterator` iterable protocol. + `Symbol.iterator` iterable protocol. Emits an 'error' event if a null + value is passed. * `options` {Object} Options provided to `new stream.Readable([options])`. By default, `Readable.from()` will set `options.objectMode` to `true`, unless this is explicitly opted out by setting `options.objectMode` to `false`. @@ -1748,7 +1750,7 @@ changes: * `options` {Object} * `highWaterMark` {number} Buffer level when [`stream.write()`][stream-write] starts returning `false`. **Default:** - `16384` (16kb), or `16` for `objectMode` streams. + `16384` (16KB), or `16` for `objectMode` streams. * `decodeStrings` {boolean} Whether to encode `string`s passed to [`stream.write()`][stream-write] to `Buffer`s (with the encoding specified in the [`stream.write()`][stream-write] call) before passing @@ -2024,7 +2026,7 @@ changes: * `options` {Object} * `highWaterMark` {number} The maximum [number of bytes][hwm-gotcha] to store in the internal buffer before ceasing to read from the underlying resource. - **Default:** `16384` (16kb), or `16` for `objectMode` streams. + **Default:** `16384` (16KB), or `16` for `objectMode` streams. * `encoding` {string} If specified, then buffers will be decoded to strings using the specified encoding. **Default:** `null`. * `objectMode` {boolean} Whether this stream should behave diff --git a/doc/api/tls.md b/doc/api/tls.md index 51f5cf9b4adf1b..9528819b33c285 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -1094,6 +1094,39 @@ See [SSL_get_shared_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information. +### `tlsSocket.exportKeyingMaterial(length, label[, context])` + + +* `length` {number} number of bytes to retrieve from keying material +* `label` {string} an application specific label, typically this will be a +value from the +[IANA Exporter Label Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). +* `context` {Buffer} Optionally provide a context. + +* Returns: {Buffer} requested bytes of the keying material + +Keying material is used for validations to prevent different kind of attacks in +network protocols, for example in the specifications of IEEE 802.1X. + +Example + +```js +const keyingMaterial = tlsSocket.exportKeyingMaterial( + 128, + 'client finished'); + +/** + Example return value of keyingMaterial: + +*/ +``` +See the OpenSSL [`SSL_export_keying_material`][] documentation for more +information. + ### `tlsSocket.getTLSTicket()` + +* `value` {any} +* Returns: {boolean} + +Returns `true` if the value is an instance of one of the [`ArrayBuffer`][] +views, such as typed array objects or [`DataView`][]. Equivalent to +[`ArrayBuffer.isView()`][]. + +```js +util.types.isArrayBufferView(new Int8Array()); // true +util.types.isArrayBufferView(Buffer.from('hello world')); // true +util.types.isArrayBufferView(new DataView(new ArrayBuffer(16))); // true +util.types.isArrayBufferView(new ArrayBuffer()); // false +``` + ### `util.types.isArgumentsObject(value)` + +* Returns: {Buffer} + +Creates a code cache that can be used with the SourceTextModule constructor's +`cachedData` option. Returns a Buffer. This method may be called any number +of times before the module has been evaluated. + +```js +// Create an initial module +const module = new vm.SourceTextModule('const a = 1;'); + +// Create cached data from this module +const cachedData = module.createCachedData(); + +// Create a new module using the cached data. The code must be the same. +const module2 = new vm.SourceTextModule('const a = 1;', { cachedData }); +``` + ## Class: `vm.SyntheticModule` -* `filename` {string} The path to the Worker’s main script. Must be - either an absolute path or a relative path (i.e. relative to the - current working directory) starting with `./` or `../`. +* `filename` {string|URL} The path to the Worker’s main script or module. Must + be either an absolute path or a relative path (i.e. relative to the + current working directory) starting with `./` or `../`, or a WHATWG `URL` + object using `file:` protocol. If `options.eval` is `true`, this is a string containing JavaScript code rather than a path. * `options` {Object} @@ -536,8 +544,9 @@ changes: to specify that the parent thread and the child thread should share their environment variables; in that case, changes to one thread’s `process.env` object will affect the other thread as well. **Default:** `process.env`. - * `eval` {boolean} If `true`, interpret the first argument to the constructor - as a script that is executed once the worker is online. + * `eval` {boolean} If `true` and the first argument is a `string`, interpret + the first argument to the constructor as a script that is executed once the + worker is online. * `execArgv` {string[]} List of node CLI options passed to the worker. V8 options (such as `--max-old-space-size`) and options that affect the process (such as `--title`) are not supported. If set, this will be provided @@ -555,6 +564,10 @@ changes: occur as described in the [HTML structured clone algorithm][], and an error will be thrown if the object cannot be cloned (e.g. because it contains `function`s). + * `transferList` {Object[]} If one or more `MessagePort`-like objects + are passed in `workerData`, a `transferList` is required for those + items or [`ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST`][] will be thrown. + See [`port.postMessage()`][] for more information. * `resourceLimits` {Object} An optional set of resource limits for the new JS engine instance. Reaching these limits will lead to termination of the `Worker` instance. These limits only affect the JS engine, and no external @@ -612,6 +625,21 @@ added: v10.5.0 The `'online'` event is emitted when the worker thread has started executing JavaScript code. +### `worker.getHeapSnapshot()` + + +* Returns: {Promise} A promise for a Readable Stream containing + a V8 heap snapshot + +Returns a readable stream for a V8 snapshot of the current state of the Worker. +See [`v8.getHeapSnapshot()`][] for more details. + +If the Worker thread is no longer running, which may occur before the +[`'exit'` event][] is emitted, the returned `Promise` will be rejected +immediately with an [`ERR_WORKER_NOT_RUNNING`][] error. + ### `worker.postMessage(value[, transferList])` + diff --git a/doc/changelogs/CHANGELOG_IOJS.md b/doc/changelogs/CHANGELOG_IOJS.md index 6c5f87e557443a..b96333970650be 100644 --- a/doc/changelogs/CHANGELOG_IOJS.md +++ b/doc/changelogs/CHANGELOG_IOJS.md @@ -2,6 +2,7 @@ +
diff --git a/doc/changelogs/CHANGELOG_V010.md b/doc/changelogs/CHANGELOG_V010.md index e91115c3ee9229..dee227da5c7648 100644 --- a/doc/changelogs/CHANGELOG_V010.md +++ b/doc/changelogs/CHANGELOG_V010.md @@ -2,6 +2,7 @@ +
diff --git a/doc/changelogs/CHANGELOG_V012.md b/doc/changelogs/CHANGELOG_V012.md index db88e9795cfe68..eff6838e4218df 100644 --- a/doc/changelogs/CHANGELOG_V012.md +++ b/doc/changelogs/CHANGELOG_V012.md @@ -2,6 +2,7 @@ +
diff --git a/doc/changelogs/CHANGELOG_V10.md b/doc/changelogs/CHANGELOG_V10.md index 18e221555b930e..d82d481ab0ad7b 100644 --- a/doc/changelogs/CHANGELOG_V10.md +++ b/doc/changelogs/CHANGELOG_V10.md @@ -2,6 +2,7 @@ +
diff --git a/doc/changelogs/CHANGELOG_V11.md b/doc/changelogs/CHANGELOG_V11.md index de6a0a68786bb3..453e4c1dd68b70 100644 --- a/doc/changelogs/CHANGELOG_V11.md +++ b/doc/changelogs/CHANGELOG_V11.md @@ -2,6 +2,7 @@ +
diff --git a/doc/changelogs/CHANGELOG_V12.md b/doc/changelogs/CHANGELOG_V12.md index bc9463d95eb697..2aa5ff36e2ef37 100644 --- a/doc/changelogs/CHANGELOG_V12.md +++ b/doc/changelogs/CHANGELOG_V12.md @@ -2,6 +2,7 @@ +
@@ -10,6 +11,7 @@
+12.17.0
12.16.3
12.16.2
12.16.1
@@ -56,6 +58,649 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + +## 2020-05-26, Version 12.17.0 'Erbium' (LTS), @targos + +### Notable Changes + +#### ECMAScript Modules - `--experimental-modules` flag removal + +As of Node.js 12.17.0, the `--experimental-modules` flag is no longer necessary +to use ECMAScript modules (ESM). However, the ESM implementation in Node.js +remains experimental. As per our stability index: “The feature is not subject +to Semantic Versioning rules. Non-backward compatible changes or removal may +occur in any future release.” Users should be cautious when using the feature +in production environments. + +Unlike Node.js 14, using ESM will still emit a runtime experimental warning, +either when a module is used a the application's entrypoint or the first time +dynamic `import()` is called. + +Please keep in mind that the implementation of ESM in Node.js differs from the +developer experience you might be familiar with. Most transpilation workflows +support features such as named exports from CommonJS module imports, optional +file extensions or JSON modules that the Node.js ESM implementation does not +support. It is highly likely that modules from transpiled environments will +require a certain degree of refactoring to work in Node.js. It is worth +mentioning that many of our design decisions were made with two primary goals. +Spec compliance and Web Compatibility. It is our belief that the current +implementation offers a future proof model to authoring ESM modules that paves +the path to Universal JavaScript. Please read more in our documentation. + +The ESM implementation in Node.js is still experimental but we do believe that +we are getting very close to being able to call ESM in Node.js “stable”. +Removing the flag is a huge step in that direction. + +We expect to remove the warning Node.js 12 later this year, possibly in late +October, when Node.js 14 will become LTS. + +#### AsyncLocalStorage API (experimental) + +The `AsyncLocalStorage` class has been introduced in the Async Hooks module. + +This API allows keeping a context across asynchronous operations. For instance, +if a sequence id is stored within an instance of `AsyncLocalStorage` for each +HTTP request entering in a server, it will be possible to retrieve this id +without having access the current HTTP request: + +```js +const http = require('http'); +const { AsyncLocalStorage } = require('async_hooks'); + +const asyncLocalStorage = new AsyncLocalStorage(); + +function logWithId(msg) { + const id = asyncLocalStorage.getStore(); + console.log(`${id !== undefined ? id : '-'}: `, msg); +} + +let idSeq = 0; +http.createServer((req, res) => { + asyncLocalStorage.run(idSeq++, () => { + logWithId('start'); + // Imagine any chain of async operations here. + setImmediate(() => { + logWithId('finish'); + res.end(); + }); + }); +}).listen(8080); +``` + +In this example, the `logWithId` function will always know what the current +request id is, even when there are multiple requests in parallel. + +##### What can this API be used for + +Use cases of this API include: +* Logging +* User identification +* Performance tracking +* Error tracking and handling +* Much more! + +*Note: This API is still experimental and some methods might change in future releases of Node.js* + +Contributed by Vladimir de Turckheim - [#26540](https://github.com/nodejs/node/pull/26540). + +#### REPL previews + +If further input is predicable, a suggestion is inserted as preview. + +The REPL now supports previews similar to the Chrome DevTools console. An input +suggestion is inserted as preview in case further input is predicable. The +suggestion may be accepted by either pressing `` or `` at the end of +the input. +On top of that, output is previewed when entering variable names or function +calls that have no side effect. + +![image](https://user-images.githubusercontent.com/8822573/80928108-afb03300-8da2-11ea-8898-499d8c2dbc7a.png) +![image](https://user-images.githubusercontent.com/8822573/80928118-c191d600-8da2-11ea-9739-32e8becc68fe.png) + +[Check the preview in action](https://asciinema.org/a/ePQx0GfCYQGdnQTzwlnSIyxbN) +and try it out on your own. Just access the REPL on your terminal by starting +the Node.js executable without any further command. + +Contributed by Ruben Bridgewater - [#30907](https://github.com/nodejs/node/pull/30907), [#30811](https://github.com/nodejs/node/pull/30811). + +#### REPL reverse-i-search + +The REPL supports bi-directional reverse-i-search similar to +[ZSH](https://en.wikipedia.org/wiki/Z_shell). It is triggered with ` + R` +to search backwards and ` + S` to search forwards. + +Entries are accepted as soon as any button is pressed that doesn't correspond +with the reverse search. Cancelling is possible by pressing `escape` or +` + C`. + +Changing the direction immediately searches for the next entry in the expected +direction from the current position on. + +![image](https://user-images.githubusercontent.com/8822573/80928291-f3f00300-8da3-11ea-97d8-12e85e2e3d2c.png) + +[Reverse-i-search in action](https://asciinema.org/a/shV3YOFu74BcBakJcvY4USNqv). + +Contributed by Ruben Bridgewater - [#31006](https://github.com/nodejs/node/pull/31006). + +#### REPL substring-based search + +It is now possible to access former history entries very fast by writing the +first characters of the formerly entered code you are looking for. Then push +`` or `` to go through the history entries that start with those +characters. + +It works similar to the [Fish Shell](https://fishshell.com/) substring-based +history search. + +Contributed by Ruben Bridgewater - [#31112](https://github.com/nodejs/node/pull/31112). + +#### Error monitoring + +##### Monitoring `error` events + +It is now possible to monitor `'error'` events on an `EventEmitter` without +consuming the emitted error by installing a listener using the symbol +`EventEmitter.errorMonitor`: + +```js +const myEmitter = new MyEmitter(); + +myEmitter.on(EventEmitter.errorMonitor, (err) => { + MyMonitoringTool.log(err); +}); + +myEmitter.emit('error', new Error('whoops!')); +// Still throws and crashes Node.js +``` + +Contributed by Gerhard Stoebich - [#30932](https://github.com/nodejs/node/pull/30932). + +#### Monitoring uncaught exceptions + +It is now possible to monitor `'uncaughtException'` events without overriding +the default behavior that exits the process by installing an +`'uncaughtExceptionMonitor'` listener: + +```js +process.on('uncaughtExceptionMonitor', (err, origin) => { + MyMonitoringTool.logSync(err, origin); +}); + +// Intentionally cause an exception, but do not catch it. +nonexistentFunc(); +// Still crashes Node.js +``` + +Contributed by Gerhard Stoebich - [#31257](https://github.com/nodejs/node/pull/31257). + +#### File system APIs + +##### New function: `fs.readv` + +This new function (along with its sync and promisified versions) takes an array +of `ArrayBufferView` elements and will write the data it reads sequentially to +the buffers. + +Contributed by Sk Sajidul Kadir - [#32356](https://github.com/nodejs/node/pull/32356). + +##### Optional parameters in `fs.read` + +A new overload is available for `fs.read` (along with its sync and promisified +versions), which allows to optionally pass any of the `offset`, `length` and +`position` parameters. + +Contributed by Lucas Holmquist - [#31402](https://github.com/nodejs/node/pull/31402). + +#### Console `groupIndentation` option + +The Console constructor (`require('console').Console`) now supports different group indentations. + +This is useful in case you want different grouping width than 2 spaces. + +```js +const { Console } = require('console'); +const customConsole = new Console({ + stdout: process.stdout, + stderr: process.stderr, + groupIndentation: 10 +}); + +customConsole.log('foo'); +// 'foo' +customConsole.group(); +customConsole.log('foo'); +// 'foo' +``` + +Contributed by rickyes - [#32964](https://github.com/nodejs/node/pull/32964). + +#### `maxStringLength` option for `util.inspect()` + +It is now possible to limit the length of strings while inspecting objects. +This is possible by passing through the `maxStringLength` option similar to: + +```js +const { inspect } = require('util'); + +const string = inspect(['a'.repeat(1e8)], { maxStringLength: 10 }); + +console.log(string); +// "[ 'aaaaaaaaaa'... 99999990 more characters ]" +``` + +Contributed by rosaxny - [#32392](https://github.com/nodejs/node/pull/32392). + +#### Stable N-API release 6 + +The following N-API features are now stable as part of the N-API 6 release: + +* [`napi_set_instance_data`](https://nodejs.org/dist/latest-v12.x/docs/api/n-api.html#n_api_napi_set_instance_data) +* [`napi_get_instance_data`](https://nodejs.org/dist/latest-v12.x/docs/api/n-api.html#n_api_napi_get_instance_data) +* [`napi_key_collection_mode`](https://nodejs.org/dist/latest-v12.x/docs/api/n-api.html#n_api_napi_key_collection_mode) +* [`napi_key_filter`](https://nodejs.org/dist/latest-v12.x/docs/api/n-api.html#n_api_napi_key_filter) +* [`napi_key_conversion`](https://nodejs.org/dist/latest-v12.x/docs/api/n-api.html#n_api_napi_key_conversion) +* [`napi_create_bigint_int64`](https://nodejs.org/dist/latest-v12.x/docs/api/n-api.html#n_api_napi_create_bigint_int64) +* [`napi_create_bigint_uint64`](https://nodejs.org/dist/latest-v12.x/docs/api/n-api.html#n_api_napi_create_bigint_uint64) +* [`napi_create_bigint_words`](https://nodejs.org/dist/latest-v12.x/docs/api/n-api.html#n_api_napi_create_bigint_words) +* [`napi_get_value_bigint_int64`](https://nodejs.org/dist/latest-v12.x/docs/api/n-api.html#n_api_napi_get_value_bigint_int64) +* [`napi_get_value_bigint_uint64`](https://nodejs.org/dist/latest-v12.x/docs/api/n-api.html#n_api_napi_get_value_bigint_uint64) +* [`napi_get_value_bigint_words`](https://nodejs.org/dist/latest-v12.x/docs/api/n-api.html#n_api_napi_get_value_bigint_words) +* [`napi_get_all_property_names`](https://nodejs.org/dist/latest-v12.x/docs/api/n-api.html#n_api_napi_get_all_property_names) + +#### Stable diagnostic reports + +The [Diagnostic Report](https://nodejs.org/dist/latest-v12.x/docs/api/report.html) +feature is now stable and supports a new `--report-compact` flag to write the +reports in a compact, single-line JSON format, more easily consumable by log +processing systems than the default multi-line format designed for human +consumption. + +#### Increase of the default server headers timeout + +The default value of `server.headersTimeout` for `http` and `https` servers was +increased from `40000` to `60000` (60 seconds). This to accomodate for systems +like AWS ELB that have a timeout of 60 seconds. + +Contributed by Tim Costa - [#30071](https://github.com/nodejs/node/pull/30071). + +#### Other changes + +* **cli**: + * Added a `--trace-sigint` CLI flag that will print the current execution + stack on SIGINT (legendecas) [#29207](https://github.com/nodejs/node/pull/29207). +* **crypto**: + * Various crypto APIs now support Diffie-Hellman secrets (Tobias Nießen) [#31178](https://github.com/nodejs/node/pull/31178). +* **dns**: + * Added the `dns.ALL` flag, that can be passed to `dns.lookup()` with `dns.V4MAPPED` + to return resolved IPv6 addresses as well as IPv4 mapped IPv6 addresses (murgatroid99) [#32183](https://github.com/nodejs/node/pull/32183). +* **module** + * Added a new experimental API to interact with Source Map V3 data (Benjamin Coe) [#31132](https://github.com/nodejs/node/pull/31132). +* **worker**: + * Added support for passing a `transferList` along with `workerData` to the + `Worker` constructor (Juan José Arboleda) [#32278](https://github.com/nodejs/node/pull/32278). + +### Commits + +#### Semver-minor commits + +* [[`a35e88caf5`](https://github.com/nodejs/node/commit/a35e88caf5)] - **(SEMVER-MINOR)** **async_hooks**: merge run and exit methods (Andrey Pechkurov) [#31950](https://github.com/nodejs/node/pull/31950) +* [[`3eb34068a2`](https://github.com/nodejs/node/commit/3eb34068a2)] - **(SEMVER-MINOR)** **async_hooks**: prevent sync methods of async storage exiting outer context (Stephen Belanger) [#31950](https://github.com/nodejs/node/pull/31950) +* [[`22db34caa7`](https://github.com/nodejs/node/commit/22db34caa7)] - **(SEMVER-MINOR)** **async_hooks**: add sync enterWith to ALS (Stephen Belanger) [#31945](https://github.com/nodejs/node/pull/31945) +* [[`16e8b11708`](https://github.com/nodejs/node/commit/16e8b11708)] - **(SEMVER-MINOR)** **async_hooks**: introduce async-context API (Vladimir de Turckheim) [#26540](https://github.com/nodejs/node/pull/26540) +* [[`f7adfcc1df`](https://github.com/nodejs/node/commit/f7adfcc1df)] - **(SEMVER-MINOR)** **async_hooks**: add executionAsyncResource (Matteo Collina) [#30959](https://github.com/nodejs/node/pull/30959) +* [[`984ae304f2`](https://github.com/nodejs/node/commit/984ae304f2)] - **(SEMVER-MINOR)** **build**: make --without-report a no-op (Colin Ihrig) [#32242](https://github.com/nodejs/node/pull/32242) +* [[`e67b97ee53`](https://github.com/nodejs/node/commit/e67b97ee53)] - **(SEMVER-MINOR)** **cli**: allow --huge-max-old-generation-size in NODE\_OPTIONS (Anna Henningsen) [#32251](https://github.com/nodejs/node/pull/32251) +* [[`154b18ffca`](https://github.com/nodejs/node/commit/154b18ffca)] - **(SEMVER-MINOR)** **console**: support console constructor groupIndentation option (rickyes) [#32964](https://github.com/nodejs/node/pull/32964) +* [[`40253cc1c8`](https://github.com/nodejs/node/commit/40253cc1c8)] - **(SEMVER-MINOR)** **crypto**: add crypto.diffieHellman (Tobias Nießen) [#31178](https://github.com/nodejs/node/pull/31178) +* [[`1977136a19`](https://github.com/nodejs/node/commit/1977136a19)] - **(SEMVER-MINOR)** **crypto**: add DH support to generateKeyPair (Tobias Nießen) [#31178](https://github.com/nodejs/node/pull/31178) +* [[`9f85585b13`](https://github.com/nodejs/node/commit/9f85585b13)] - **(SEMVER-MINOR)** **crypto**: add key type 'dh' (Tobias Nießen) [#31178](https://github.com/nodejs/node/pull/31178) +* [[`6ffe4ed3b5`](https://github.com/nodejs/node/commit/6ffe4ed3b5)] - **(SEMVER-MINOR)** **deps**: upgrade to libuv 1.37.0 (Colin Ihrig) [#32866](https://github.com/nodejs/node/pull/32866) +* [[`2d7a7592ec`](https://github.com/nodejs/node/commit/2d7a7592ec)] - **(SEMVER-MINOR)** **deps**: upgrade to libuv 1.36.0 (Colin Ihrig) [#32866](https://github.com/nodejs/node/pull/32866) +* [[`ae83f0f993`](https://github.com/nodejs/node/commit/ae83f0f993)] - **(SEMVER-MINOR)** **deps**: upgrade to libuv 1.35.0 (Colin Ihrig) [#32204](https://github.com/nodejs/node/pull/32204) +* [[`b7d264edaf`](https://github.com/nodejs/node/commit/b7d264edaf)] - **(SEMVER-MINOR)** **dns**: add dns.ALL hints flag constant (murgatroid99) [#32183](https://github.com/nodejs/node/pull/32183) +* [[`fd2486ea44`](https://github.com/nodejs/node/commit/fd2486ea44)] - **(SEMVER-MINOR)** **doc**: update stability of report features (Colin Ihrig) [#32242](https://github.com/nodejs/node/pull/32242) +* [[`90d35adccd`](https://github.com/nodejs/node/commit/90d35adccd)] - **(SEMVER-MINOR)** **doc,lib,src,test**: make --experimental-report a nop (Colin Ihrig) [#32242](https://github.com/nodejs/node/pull/32242) +* [[`93226a5097`](https://github.com/nodejs/node/commit/93226a5097)] - **(SEMVER-MINOR)** **esm**: unflag --experimental-modules (Guy Bedford) [#29866](https://github.com/nodejs/node/pull/29866) +* [[`8c497f8969`](https://github.com/nodejs/node/commit/8c497f8969)] - **(SEMVER-MINOR)** **events**: allow monitoring error events (Gerhard Stoebich) [#30932](https://github.com/nodejs/node/pull/30932) +* [[`a100709fa8`](https://github.com/nodejs/node/commit/a100709fa8)] - **(SEMVER-MINOR)** **fs**: make parameters optional for readSync (Lucas Holmquist) [#32460](https://github.com/nodejs/node/pull/32460) +* [[`6601fac06a`](https://github.com/nodejs/node/commit/6601fac06a)] - **(SEMVER-MINOR)** **fs**: add fs.readv() (Sk Sajidul Kadir) [#32356](https://github.com/nodejs/node/pull/32356) +* [[`16a913f702`](https://github.com/nodejs/node/commit/16a913f702)] - **(SEMVER-MINOR)** **fs**: make fs.read params optional (Lucas Holmquist) [#31402](https://github.com/nodejs/node/pull/31402) +* [[`7260ede9e6`](https://github.com/nodejs/node/commit/7260ede9e6)] - **(SEMVER-MINOR)** **fs**: return first folder made by mkdir recursive (Benjamin Coe) [#31530](https://github.com/nodejs/node/pull/31530) +* [[`a15e712ef6`](https://github.com/nodejs/node/commit/a15e712ef6)] - **(SEMVER-MINOR)** **fs**: allow overriding fs for streams (Robert Nagy) [#29083](https://github.com/nodejs/node/pull/29083) +* [[`b5983213c1`](https://github.com/nodejs/node/commit/b5983213c1)] - **(SEMVER-MINOR)** **lib**: add option to disable \_\_proto\_\_ (Gus Caplan) [#32279](https://github.com/nodejs/node/pull/32279) +* [[`784fb8f08c`](https://github.com/nodejs/node/commit/784fb8f08c)] - **(SEMVER-MINOR)** **module**: add API for interacting with source maps (Benjamin Coe) [#31132](https://github.com/nodejs/node/pull/31132) +* [[`e22d853c5d`](https://github.com/nodejs/node/commit/e22d853c5d)] - **(SEMVER-MINOR)** **n-api**: define release 6 (Gabriel Schulhof) [#32058](https://github.com/nodejs/node/pull/32058) +* [[`f56c4dd933`](https://github.com/nodejs/node/commit/f56c4dd933)] - **(SEMVER-MINOR)** **n-api**: add napi\_get\_all\_property\_names (himself65) [#30006](https://github.com/nodejs/node/pull/30006) +* [[`9eeee0d9f2`](https://github.com/nodejs/node/commit/9eeee0d9f2)] - **(SEMVER-MINOR)** **perf_hooks**: add property flags to GCPerformanceEntry (Kirill Fomichev) [#29547](https://github.com/nodejs/node/pull/29547) +* [[`5ec9295034`](https://github.com/nodejs/node/commit/5ec9295034)] - **(SEMVER-MINOR)** **process**: report ArrayBuffer memory in `memoryUsage()` (Anna Henningsen) [#31550](https://github.com/nodejs/node/pull/31550) +* [[`de3603f0a6`](https://github.com/nodejs/node/commit/de3603f0a6)] - **(SEMVER-MINOR)** **process**: allow monitoring uncaughtException (Gerhard Stoebich) [#31257](https://github.com/nodejs/node/pull/31257) +* [[`cf28afeeb6`](https://github.com/nodejs/node/commit/cf28afeeb6)] - **(SEMVER-MINOR)** **readline,repl**: improve history up/previous (Ruben Bridgewater) [#31112](https://github.com/nodejs/node/pull/31112) +* [[`a0eb3e4ed2`](https://github.com/nodejs/node/commit/a0eb3e4ed2)] - **(SEMVER-MINOR)** **readline,repl**: skip history entries identical to the current line (Ruben Bridgewater) [#31112](https://github.com/nodejs/node/pull/31112) +* [[`d7e153bddb`](https://github.com/nodejs/node/commit/d7e153bddb)] - **(SEMVER-MINOR)** **readline,repl**: add substring based history search (Ruben Bridgewater) [#31112](https://github.com/nodejs/node/pull/31112) +* [[`936c85c309`](https://github.com/nodejs/node/commit/936c85c309)] - **(SEMVER-MINOR)** **repl**: implement reverse search (Ruben Bridgewater) [#31006](https://github.com/nodejs/node/pull/31006) +* [[`bf9ff16412`](https://github.com/nodejs/node/commit/bf9ff16412)] - **(SEMVER-MINOR)** **repl**: add completion preview (Ruben Bridgewater) [#30907](https://github.com/nodejs/node/pull/30907) +* [[`b14440fb5c`](https://github.com/nodejs/node/commit/b14440fb5c)] - **(SEMVER-MINOR)** **repl**: support previews by eager evaluating input (Ruben Bridgewater) [#30811](https://github.com/nodejs/node/pull/30811) +* [[`0b310df532`](https://github.com/nodejs/node/commit/0b310df532)] - **(SEMVER-MINOR)** **src**: unconditionally include report feature (Colin Ihrig) [#32242](https://github.com/nodejs/node/pull/32242) +* [[`394487e3e8`](https://github.com/nodejs/node/commit/394487e3e8)] - **(SEMVER-MINOR)** **src**: create a getter for kernel version (Juan José Arboleda) [#31732](https://github.com/nodejs/node/pull/31732) +* [[`4ec25b4865`](https://github.com/nodejs/node/commit/4ec25b4865)] - **(SEMVER-MINOR)** **src,cli**: support compact (one-line) JSON reports (Sam Roberts) [#32254](https://github.com/nodejs/node/pull/32254) +* [[`b038ad91f5`](https://github.com/nodejs/node/commit/b038ad91f5)] - **(SEMVER-MINOR)** **src,lib**: make ^C print a JS stack trace (legendecas) [#29207](https://github.com/nodejs/node/pull/29207) +* [[`6348fae690`](https://github.com/nodejs/node/commit/6348fae690)] - **(SEMVER-MINOR)** **tls**: expose SSL\_export\_keying\_material (simon) [#31814](https://github.com/nodejs/node/pull/31814) +* [[`6aa3869688`](https://github.com/nodejs/node/commit/6aa3869688)] - **(SEMVER-MINOR)** **util**: add `maxStrLength` option to `inspect` function (unknown) [#32392](https://github.com/nodejs/node/pull/32392) +* [[`eda6665799`](https://github.com/nodejs/node/commit/eda6665799)] - **(SEMVER-MINOR)** **vm**: add code cache support for SourceTextModule (Gus Caplan) [#31278](https://github.com/nodejs/node/pull/31278) +* [[`5c81b8d814`](https://github.com/nodejs/node/commit/5c81b8d814)] - **(SEMVER-MINOR)** **wasi**: add returnOnExit option (Colin Ihrig) [#32101](https://github.com/nodejs/node/pull/32101) +* [[`ca4e65273f`](https://github.com/nodejs/node/commit/ca4e65273f)] - **(SEMVER-MINOR)** **worker**: support MessagePort to workers data (Juan José Arboleda) [#32278](https://github.com/nodejs/node/pull/32278) +* [[`217e3dfea6`](https://github.com/nodejs/node/commit/217e3dfea6)] - **(SEMVER-MINOR)** **worker**: allow URL in Worker constructor (Antoine du HAMEL) [#31664](https://github.com/nodejs/node/pull/31664) +* [[`ab8f38b551`](https://github.com/nodejs/node/commit/ab8f38b551)] - **(SEMVER-MINOR)** **worker**: add ability to take heap snapshot from parent thread (Anna Henningsen) [#31569](https://github.com/nodejs/node/pull/31569) + +#### Semver-patch commits + +* [[`06d607d50f`](https://github.com/nodejs/node/commit/06d607d50f)] - **async_hooks**: fix ctx loss after nested ALS calls (Andrey Pechkurov) [#32085](https://github.com/nodejs/node/pull/32085) +* [[`96d1f14005`](https://github.com/nodejs/node/commit/96d1f14005)] - **async_hooks**: add store arg in AsyncLocalStorage (Andrey Pechkurov) [#31930](https://github.com/nodejs/node/pull/31930) +* [[`b4ca132254`](https://github.com/nodejs/node/commit/b4ca132254)] - **async_hooks**: executionAsyncResource matches in hooks (Gerhard Stoebich) [#31821](https://github.com/nodejs/node/pull/31821) +* [[`02f99d289d`](https://github.com/nodejs/node/commit/02f99d289d)] - **buffer**: add type check in bidirectionalIndexOf (Gerhard Stoebich) [#32770](https://github.com/nodejs/node/pull/32770) +* [[`b53193a33b`](https://github.com/nodejs/node/commit/b53193a33b)] - **buffer**: mark pool ArrayBuffer as untransferable (Anna Henningsen) [#32759](https://github.com/nodejs/node/pull/32759) +* [[`b555a772cc`](https://github.com/nodejs/node/commit/b555a772cc)] - **build**: fix vcbuild error for missing Visual Studio (Thomas) [#32658](https://github.com/nodejs/node/pull/32658) +* [[`6f1931de25`](https://github.com/nodejs/node/commit/6f1931de25)] - **build**: remove .git folders when testing V8 (Richard Lau) [#32877](https://github.com/nodejs/node/pull/32877) +* [[`c0805f0cab`](https://github.com/nodejs/node/commit/c0805f0cab)] - **build**: add configure flag to build V8 with DCHECKs (Anna Henningsen) [#32787](https://github.com/nodejs/node/pull/32787) +* [[`60660c35ee`](https://github.com/nodejs/node/commit/60660c35ee)] - **build**: use same flags as V8 for ASAN (Matheus Marchini) [#32776](https://github.com/nodejs/node/pull/32776) +* [[`26fee8b323`](https://github.com/nodejs/node/commit/26fee8b323)] - **build**: remove `.txt` files from .gitignore (Rich Trott) [#32710](https://github.com/nodejs/node/pull/32710) +* [[`70eaba12a1`](https://github.com/nodejs/node/commit/70eaba12a1)] - **build**: remove node\_report option in node.gyp (Colin Ihrig) [#32242](https://github.com/nodejs/node/pull/32242) +* [[`e765d597fd`](https://github.com/nodejs/node/commit/e765d597fd)] - **build**: add missing comma in node.gyp (Colin Ihrig) [#31959](https://github.com/nodejs/node/pull/31959) +* [[`49ddd36f13`](https://github.com/nodejs/node/commit/49ddd36f13)] - **build**: fix building with ninja (Richard Lau) [#32071](https://github.com/nodejs/node/pull/32071) +* [[`e097980cfe`](https://github.com/nodejs/node/commit/e097980cfe)] - **build**: warn upon --use-largepages config option (Gabriel Schulhof) [#31103](https://github.com/nodejs/node/pull/31103) +* [[`c3efd2cb9a`](https://github.com/nodejs/node/commit/c3efd2cb9a)] - **build**: switch realpath to pwd (Benjamin Coe) [#31095](https://github.com/nodejs/node/pull/31095) +* [[`0190a62f58`](https://github.com/nodejs/node/commit/0190a62f58)] - **build**: re-introduce --use-largepages as no-op (Gabriel Schulhof) +* [[`e2a090b693`](https://github.com/nodejs/node/commit/e2a090b693)] - **build**: enable loading internal modules from disk (Gus Caplan) [#31321](https://github.com/nodejs/node/pull/31321) +* [[`c4da682437`](https://github.com/nodejs/node/commit/c4da682437)] - **cli, report**: move --report-on-fatalerror to stable (Colin Ihrig) [#32496](https://github.com/nodejs/node/pull/32496) +* [[`e05c29db3f`](https://github.com/nodejs/node/commit/e05c29db3f)] - **cluster**: fix error on worker disconnect/destroy (Santiago Gimeno) [#32793](https://github.com/nodejs/node/pull/32793) +* [[`d217b792bc`](https://github.com/nodejs/node/commit/d217b792bc)] - **cluster**: removed unused addressType argument from constructor (Yash Ladha) [#32963](https://github.com/nodejs/node/pull/32963) +* [[`71bccdde76`](https://github.com/nodejs/node/commit/71bccdde76)] - **crypto**: check DiffieHellman p and g params (Ben Noordhuis) [#32739](https://github.com/nodejs/node/pull/32739) +* [[`c1b767471a`](https://github.com/nodejs/node/commit/c1b767471a)] - **crypto**: generator must be int32 in DiffieHellman() (Ben Noordhuis) [#32739](https://github.com/nodejs/node/pull/32739) +* [[`4236175878`](https://github.com/nodejs/node/commit/4236175878)] - **crypto**: key size must be int32 in DiffieHellman() (Ben Noordhuis) [#32739](https://github.com/nodejs/node/pull/32739) +* [[`0847bc3788`](https://github.com/nodejs/node/commit/0847bc3788)] - **crypto**: simplify exportKeyingMaterial (Tobias Nießen) [#31922](https://github.com/nodejs/node/pull/31922) +* [[`907252d4cf`](https://github.com/nodejs/node/commit/907252d4cf)] - **crypto**: improve errors in DiffieHellmanGroup (Tobias Nießen) [#31445](https://github.com/nodejs/node/pull/31445) +* [[`30633acf20`](https://github.com/nodejs/node/commit/30633acf20)] - **crypto**: assign and use ERR\_CRYPTO\_UNKNOWN\_CIPHER (Tobias Nießen) [#31437](https://github.com/nodejs/node/pull/31437) +* [[`5dab489d50`](https://github.com/nodejs/node/commit/5dab489d50)] - **crypto**: simplify DH groups (Tobias Nießen) [#31178](https://github.com/nodejs/node/pull/31178) +* [[`5c0232a632`](https://github.com/nodejs/node/commit/5c0232a632)] - **deps**: backport ICU-21081 for ICU 67.x (constexpr) (Steven R. Loomis) [#33337](https://github.com/nodejs/node/pull/33337) +* [[`2d76ae7497`](https://github.com/nodejs/node/commit/2d76ae7497)] - **deps**: update to ICU 67.1 (Michaël Zasso) [#33337](https://github.com/nodejs/node/pull/33337) +* [[`e073da095e`](https://github.com/nodejs/node/commit/e073da095e)] - **deps**: update to uvwasi 0.0.8 (Colin Ihrig) [#33078](https://github.com/nodejs/node/pull/33078) +* [[`eb33d523da`](https://github.com/nodejs/node/commit/eb33d523da)] - **deps**: V8: backport 3f8dc4b2e5ba (Ujjwal Sharma) [#32993](https://github.com/nodejs/node/pull/32993) +* [[`56313daff6`](https://github.com/nodejs/node/commit/56313daff6)] - **deps**: V8: cherry-pick e1eac1b16c96 (Milad Farazmand) [#32974](https://github.com/nodejs/node/pull/32974) +* [[`65db9b210d`](https://github.com/nodejs/node/commit/65db9b210d)] - **deps**: fix zlib compilation for CPUs without SIMD features (Anna Henningsen) [#32627](https://github.com/nodejs/node/pull/32627) +* [[`1b53e179b8`](https://github.com/nodejs/node/commit/1b53e179b8)] - **deps**: update zlib to upstream d7f3ca9 (Sam Roberts) [#31800](https://github.com/nodejs/node/pull/31800) +* [[`9a89718410`](https://github.com/nodejs/node/commit/9a89718410)] - **deps**: move zlib maintenance info to guides (Sam Roberts) [#31800](https://github.com/nodejs/node/pull/31800) +* [[`9e33f97c4e`](https://github.com/nodejs/node/commit/9e33f97c4e)] - **deps**: switch to chromium's zlib implementation (Brian White) [#31201](https://github.com/nodejs/node/pull/31201) +* [[`322a9986fe`](https://github.com/nodejs/node/commit/322a9986fe)] - **dgram**: make UDPWrap more reusable (Anna Henningsen) [#31871](https://github.com/nodejs/node/pull/31871) +* [[`ea4302bd46`](https://github.com/nodejs/node/commit/ea4302bd46)] - **errors**: drop pronouns from ERR\_WORKER\_PATH message (Colin Ihrig) [#32285](https://github.com/nodejs/node/pull/32285) +* [[`daf1d842cc`](https://github.com/nodejs/node/commit/daf1d842cc)] - **esm**: improve commonjs hint on module not found (Daniele Belardi) [#31906](https://github.com/nodejs/node/pull/31906) +* [[`7410e8d63a`](https://github.com/nodejs/node/commit/7410e8d63a)] - **esm**: port loader code to JS (Anna Henningsen) [#32201](https://github.com/nodejs/node/pull/32201) +* [[`3241aee0f7`](https://github.com/nodejs/node/commit/3241aee0f7)] - **events**: convert errorMonitor to a normal property (Gerhard Stoebich) [#31848](https://github.com/nodejs/node/pull/31848) +* [[`2093f13333`](https://github.com/nodejs/node/commit/2093f13333)] - **fs**: update validateOffsetLengthRead in utils.js (daemon1024) [#32896](https://github.com/nodejs/node/pull/32896) +* [[`9c18838e8e`](https://github.com/nodejs/node/commit/9c18838e8e)] - **fs**: remove unnecessary else statement (Jesus Hernandez) [#32662](https://github.com/nodejs/node/pull/32662) +* [[`6d6bb2a3dc`](https://github.com/nodejs/node/commit/6d6bb2a3dc)] - **fs**: use finished over destroy w/ cb (Robert Nagy) [#32809](https://github.com/nodejs/node/pull/32809) +* [[`bde08377a1`](https://github.com/nodejs/node/commit/bde08377a1)] - **fs**: fix fs.read when passing null value (himself65) [#32479](https://github.com/nodejs/node/pull/32479) +* [[`ebd9090240`](https://github.com/nodejs/node/commit/ebd9090240)] - **http**: disable headersTimeout check when set to zero (Paolo Insogna) [#33307](https://github.com/nodejs/node/pull/33307) +* [[`a3decf5e59`](https://github.com/nodejs/node/commit/a3decf5e59)] - **http**: simplify sending header (Robert Nagy) [#33200](https://github.com/nodejs/node/pull/33200) +* [[`12b8345db8`](https://github.com/nodejs/node/commit/12b8345db8)] - **http, async_hooks**: remove unneeded reference to wrapping resource (Gerhard Stoebich) [#32054](https://github.com/nodejs/node/pull/32054) +* [[`d60988161d`](https://github.com/nodejs/node/commit/d60988161d)] - **http,https**: increase server headers timeout (Tim Costa) [#30071](https://github.com/nodejs/node/pull/30071) +* [[`d883024884`](https://github.com/nodejs/node/commit/d883024884)] - **http2**: wait for secureConnect before initializing (Benjamin Coe) [#32958](https://github.com/nodejs/node/pull/32958) +* [[`79e95e49f7`](https://github.com/nodejs/node/commit/79e95e49f7)] - **inspector**: only write coverage in fully bootstrapped Environments (Joyee Cheung) [#32960](https://github.com/nodejs/node/pull/32960) +* [[`9570644194`](https://github.com/nodejs/node/commit/9570644194)] - **lib**: cosmetic change to builtinLibs list for maintainability (James M Snell) [#33106](https://github.com/nodejs/node/pull/33106) +* [[`6356ad42ab`](https://github.com/nodejs/node/commit/6356ad42ab)] - **lib**: fix validateport error message when allowZero is false (rickyes) [#32861](https://github.com/nodejs/node/pull/32861) +* [[`698e21b346`](https://github.com/nodejs/node/commit/698e21b346)] - **lib**: add warning on dynamic import es modules (Juan José Arboleda) [#30720](https://github.com/nodejs/node/pull/30720) +* [[`4dba3fcafd`](https://github.com/nodejs/node/commit/4dba3fcafd)] - **lib**: unnecessary const assignment for class (Yash Ladha) [#32962](https://github.com/nodejs/node/pull/32962) +* [[`84571cec7e`](https://github.com/nodejs/node/commit/84571cec7e)] - **lib**: remove unnecesary else block (David Daza) [#32644](https://github.com/nodejs/node/pull/32644) +* [[`5885b37bcc`](https://github.com/nodejs/node/commit/5885b37bcc)] - **lib**: created isValidCallback helper (Yash Ladha) [#32665](https://github.com/nodejs/node/pull/32665) +* [[`5b1c34651e`](https://github.com/nodejs/node/commit/5b1c34651e)] - **lib**: removed unused error code (Yash Ladha) [#32481](https://github.com/nodejs/node/pull/32481) +* [[`965452dbad`](https://github.com/nodejs/node/commit/965452dbad)] - **lib**: replace Array to ArrayIsArray by primordials (himself65) [#32258](https://github.com/nodejs/node/pull/32258) +* [[`434ca8766a`](https://github.com/nodejs/node/commit/434ca8766a)] - **lib**: move isLegalPort to validators, refactor (James M Snell) [#31851](https://github.com/nodejs/node/pull/31851) +* [[`65ebfb2f12`](https://github.com/nodejs/node/commit/65ebfb2f12)] - **lib**: delete dead code in SourceMap (Justin Ridgewell) [#31512](https://github.com/nodejs/node/pull/31512) +* [[`b1f08b8359`](https://github.com/nodejs/node/commit/b1f08b8359)] - **module**: no type module resolver side effects (Guy Bedford) [#33086](https://github.com/nodejs/node/pull/33086) +* [[`a1fa180079`](https://github.com/nodejs/node/commit/a1fa180079)] - **module**: partial doc removal of --experimental-modules (Myles Borins) [#32915](https://github.com/nodejs/node/pull/32915) +* [[`195043f910`](https://github.com/nodejs/node/commit/195043f910)] - **module**: refactor condition (Myles Borins) [#32989](https://github.com/nodejs/node/pull/32989) +* [[`1811a10415`](https://github.com/nodejs/node/commit/1811a10415)] - **module**: exports not exported for null resolutions (Guy Bedford) [#32838](https://github.com/nodejs/node/pull/32838) +* [[`3dc3772bb0`](https://github.com/nodejs/node/commit/3dc3772bb0)] - **module**: improve error for invalid package targets (Myles Borins) [#32052](https://github.com/nodejs/node/pull/32052) +* [[`6489a5b1d8`](https://github.com/nodejs/node/commit/6489a5b1d8)] - **module**: fix memory leak when require error occurs (Qinhui Chen) [#32837](https://github.com/nodejs/node/pull/32837) +* [[`b62910c851`](https://github.com/nodejs/node/commit/b62910c851)] - **module**: expose exports conditions to loaders (Jan Krems) [#31303](https://github.com/nodejs/node/pull/31303) +* [[`b62db597af`](https://github.com/nodejs/node/commit/b62db597af)] - **module**: port source map sort logic from chromium (Benjamin Coe) [#31927](https://github.com/nodejs/node/pull/31927) +* [[`4d7f9869f3`](https://github.com/nodejs/node/commit/4d7f9869f3)] - **n-api**: simplify uv\_idle wrangling (Ben Noordhuis) [#32997](https://github.com/nodejs/node/pull/32997) +* [[`d08be9c8ca`](https://github.com/nodejs/node/commit/d08be9c8ca)] - **n-api**: fix false assumption on napi\_async\_context structures (legendecas) [#32928](https://github.com/nodejs/node/pull/32928) +* [[`fbd39436a0`](https://github.com/nodejs/node/commit/fbd39436a0)] - **n-api**: fix comment on expected N-API version (Michael Dawson) [#32236](https://github.com/nodejs/node/pull/32236) +* [[`d50fe6c1ea`](https://github.com/nodejs/node/commit/d50fe6c1ea)] - **path**: fix comment grammar (thecodrr) [#32942](https://github.com/nodejs/node/pull/32942) +* [[`8dcb22f735`](https://github.com/nodejs/node/commit/8dcb22f735)] - **perf_hooks**: remove unnecessary assignment when name is undefined (rickyes) [#32910](https://github.com/nodejs/node/pull/32910) +* [[`f537377957`](https://github.com/nodejs/node/commit/f537377957)] - **process**: fix two overflow cases in SourceMap VLQ decoding (Justin Ridgewell) [#31490](https://github.com/nodejs/node/pull/31490) +* [[`7582bce58d`](https://github.com/nodejs/node/commit/7582bce58d)] - **readline**: improve unicode support and tab completion (Ruben Bridgewater) [#31288](https://github.com/nodejs/node/pull/31288) +* [[`5231c84396`](https://github.com/nodejs/node/commit/5231c84396)] - **readline**: move charLengthLeft() and charLengthAt() (Ruben Bridgewater) [#31112](https://github.com/nodejs/node/pull/31112) +* [[`03efa716f0`](https://github.com/nodejs/node/commit/03efa716f0)] - **readline**: improve getStringWidth() (Ruben Bridgewater) [#31112](https://github.com/nodejs/node/pull/31112) +* [[`e894eeb22d`](https://github.com/nodejs/node/commit/e894eeb22d)] - **readline**: set null as callback return in case there's no error (Ruben Bridgewater) [#31006](https://github.com/nodejs/node/pull/31006) +* [[`3946cadf89`](https://github.com/nodejs/node/commit/3946cadf89)] - **readline**: small refactoring (Ruben Bridgewater) [#31006](https://github.com/nodejs/node/pull/31006) +* [[`0bafe087e4`](https://github.com/nodejs/node/commit/0bafe087e4)] - **readline**: update ansi-regex (Ruben Bridgewater) [#30907](https://github.com/nodejs/node/pull/30907) +* [[`4e9e4402c5`](https://github.com/nodejs/node/commit/4e9e4402c5)] - **readline,repl**: support tabs properly (Ruben Bridgewater) [#31112](https://github.com/nodejs/node/pull/31112) +* [[`3903aec0b4`](https://github.com/nodejs/node/commit/3903aec0b4)] - **repl**: align preview with the actual executed code (Ruben Bridgewater) [#32154](https://github.com/nodejs/node/pull/32154) +* [[`709d3e5eb3`](https://github.com/nodejs/node/commit/709d3e5eb3)] - **repl**: eager-evaluate input in parens (Shelley Vohr) [#31943](https://github.com/nodejs/node/pull/31943) +* [[`ce5c9d771c`](https://github.com/nodejs/node/commit/ce5c9d771c)] - **repl**: do not preview while pasting code (Ruben Bridgewater) [#31315](https://github.com/nodejs/node/pull/31315) +* [[`3867f2095e`](https://github.com/nodejs/node/commit/3867f2095e)] - **repl**: fix preview cursor position (Ruben Bridgewater) [#31293](https://github.com/nodejs/node/pull/31293) +* [[`ee40b67413`](https://github.com/nodejs/node/commit/ee40b67413)] - **repl**: change preview default in case of custom eval functions (Ruben Bridgewater) [#31259](https://github.com/nodejs/node/pull/31259) +* [[`a4ca3787ea`](https://github.com/nodejs/node/commit/a4ca3787ea)] - **repl**: activate previews for lines exceeding the terminal columns (Ruben Bridgewater) [#31112](https://github.com/nodejs/node/pull/31112) +* [[`a892b4d00c`](https://github.com/nodejs/node/commit/a892b4d00c)] - **repl**: improve preview length calculation (Ruben Bridgewater) [#31112](https://github.com/nodejs/node/pull/31112) +* [[`9abe0e32d8`](https://github.com/nodejs/node/commit/9abe0e32d8)] - **repl**: use public getCursorPos() (Colin Ihrig) [#31091](https://github.com/nodejs/node/pull/31091) +* [[`85f8654415`](https://github.com/nodejs/node/commit/85f8654415)] - **repl**: fix preview of lines that exceed the terminal columns (Ruben Bridgewater) [#31006](https://github.com/nodejs/node/pull/31006) +* [[`47dfa22adb`](https://github.com/nodejs/node/commit/47dfa22adb)] - **repl**: fix preview bug in case of long lines (Ruben Bridgewater) [#30907](https://github.com/nodejs/node/pull/30907) +* [[`7131de5f77`](https://github.com/nodejs/node/commit/7131de5f77)] - **repl**: improve completion (Ruben Bridgewater) [#30907](https://github.com/nodejs/node/pull/30907) +* [[`61886507ce`](https://github.com/nodejs/node/commit/61886507ce)] - **repl**: simplify code (Ruben Bridgewater) [#30907](https://github.com/nodejs/node/pull/30907) +* [[`9b893e1bee`](https://github.com/nodejs/node/commit/9b893e1bee)] - **repl**: simplify repl autocompletion (Ruben Bridgewater) [#30907](https://github.com/nodejs/node/pull/30907) +* [[`78dcdee35f`](https://github.com/nodejs/node/commit/78dcdee35f)] - **repl**: remove dead code (Ruben Bridgewater) [#30907](https://github.com/nodejs/node/pull/30907) +* [[`f588301f2d`](https://github.com/nodejs/node/commit/f588301f2d)] - **repl,readline**: clean up code (Ruben Bridgewater) [#31288](https://github.com/nodejs/node/pull/31288) +* [[`8be00314a6`](https://github.com/nodejs/node/commit/8be00314a6)] - **repl,readline**: refactor for simplicity (Ruben Bridgewater) [#30907](https://github.com/nodejs/node/pull/30907) +* [[`6eda28c69f`](https://github.com/nodejs/node/commit/6eda28c69f)] - **repl,readline**: refactor common code (Ruben Bridgewater) [#30907](https://github.com/nodejs/node/pull/30907) +* [[`f945a5e3e1`](https://github.com/nodejs/node/commit/f945a5e3e1)] - **report**: fix stderr matching for fatal error (gengjiawen) [#32699](https://github.com/nodejs/node/pull/32699) +* [[`4b96fc522c`](https://github.com/nodejs/node/commit/4b96fc522c)] - **report**: add missing locks for report\_on\_fatalerror accessors (Anna Henningsen) [#32535](https://github.com/nodejs/node/pull/32535) +* [[`c126d28c2e`](https://github.com/nodejs/node/commit/c126d28c2e)] - **report**: handle on-fatalerror better (Harshitha KP) [#32207](https://github.com/nodejs/node/pull/32207) +* [[`85ef383bc5`](https://github.com/nodejs/node/commit/85ef383bc5)] - **src**: remove unused v8 Message namespace (Adrian Estrada) [#33180](https://github.com/nodejs/node/pull/33180) +* [[`ffca498ca2`](https://github.com/nodejs/node/commit/ffca498ca2)] - **src**: use unique\_ptr for CachedData in ContextifyScript::New (Anna Henningsen) [#33113](https://github.com/nodejs/node/pull/33113) +* [[`b3f0417830`](https://github.com/nodejs/node/commit/b3f0417830)] - **src**: return undefined when validation err == 0 (James M Snell) [#33107](https://github.com/nodejs/node/pull/33107) +* [[`1436977984`](https://github.com/nodejs/node/commit/1436977984)] - **src**: crypto::UseSNIContext to use BaseObjectPtr (James M Snell) [#33107](https://github.com/nodejs/node/pull/33107) +* [[`6b1e2359c2`](https://github.com/nodejs/node/commit/6b1e2359c2)] - **src**: separate out NgLibMemoryManagerBase (James M Snell) [#33104](https://github.com/nodejs/node/pull/33104) +* [[`8864353c6e`](https://github.com/nodejs/node/commit/8864353c6e)] - **src**: remove unnecessary fully qualified names (rickyes) [#33077](https://github.com/nodejs/node/pull/33077) +* [[`62f29534de`](https://github.com/nodejs/node/commit/62f29534de)] - **src**: add AsyncWrapObject constructor template factory (Stephen Belanger) [#33051](https://github.com/nodejs/node/pull/33051) +* [[`08b66f223d`](https://github.com/nodejs/node/commit/08b66f223d)] - **src**: do not compare against wide characters (Christopher Beeson) [#32921](https://github.com/nodejs/node/pull/32921) +* [[`60db9afde5`](https://github.com/nodejs/node/commit/60db9afde5)] - **src**: fix empty-named env var assertion failure (Christopher Beeson) [#32921](https://github.com/nodejs/node/pull/32921) +* [[`b893c5b7ba`](https://github.com/nodejs/node/commit/b893c5b7ba)] - **src**: assignment to valid type (Yash Ladha) [#32879](https://github.com/nodejs/node/pull/32879) +* [[`846d7bdbbf`](https://github.com/nodejs/node/commit/846d7bdbbf)] - **src**: delete MicroTaskPolicy namespace (Juan José Arboleda) [#32853](https://github.com/nodejs/node/pull/32853) +* [[`05059a2469`](https://github.com/nodejs/node/commit/05059a2469)] - **src**: use using NewStringType (rickyes) [#32843](https://github.com/nodejs/node/pull/32843) +* [[`cf16cb7ed5`](https://github.com/nodejs/node/commit/cf16cb7ed5)] - **src**: fix null deref in AllocatedBuffer::clear (Matt Kulukundis) [#32892](https://github.com/nodejs/node/pull/32892) +* [[`0745f8884c`](https://github.com/nodejs/node/commit/0745f8884c)] - **src**: remove validation of unreachable code (Juan José Arboleda) [#32818](https://github.com/nodejs/node/pull/32818) +* [[`9c216640d7`](https://github.com/nodejs/node/commit/9c216640d7)] - **src**: elevate v8 namespaces (Nimit) [#32872](https://github.com/nodejs/node/pull/32872) +* [[`71bdcaeac7`](https://github.com/nodejs/node/commit/71bdcaeac7)] - **src**: remove redundant v8::HeapSnapshot namespace (Juan José Arboleda) [#32854](https://github.com/nodejs/node/pull/32854) +* [[`bb1481fd23`](https://github.com/nodejs/node/commit/bb1481fd23)] - **src**: remove unused using in node\_worker.cc (Daniel Bevenius) [#32840](https://github.com/nodejs/node/pull/32840) +* [[`8a38726826`](https://github.com/nodejs/node/commit/8a38726826)] - **src**: ignore GCC -Wcast-function-type for v8.h (Daniel Bevenius) [#32679](https://github.com/nodejs/node/pull/32679) +* [[`c26637b7da`](https://github.com/nodejs/node/commit/c26637b7da)] - **src**: remove unused v8 Array namespace (Juan José Arboleda) [#32749](https://github.com/nodejs/node/pull/32749) +* [[`c0d3fc28ec`](https://github.com/nodejs/node/commit/c0d3fc28ec)] - **src**: sync access for report and openssl options (Sam Roberts) [#32618](https://github.com/nodejs/node/pull/32618) +* [[`9a010a3ea5`](https://github.com/nodejs/node/commit/9a010a3ea5)] - **src**: munmap(2) upon class instance destructor (Gabriel Schulhof) [#32570](https://github.com/nodejs/node/pull/32570) +* [[`06953df051`](https://github.com/nodejs/node/commit/06953df051)] - **src**: fix extra includes of "env.h" and "env-inl.h" (Nick Kreeger) [#32293](https://github.com/nodejs/node/pull/32293) +* [[`7432d0a170`](https://github.com/nodejs/node/commit/7432d0a170)] - **src**: avoid using elevated v8 namespaces in node\_perf.h (James M Snell) [#32468](https://github.com/nodejs/node/pull/32468) +* [[`6175a22b87`](https://github.com/nodejs/node/commit/6175a22b87)] - **src**: avoid using elevated v8 namespaces in node\_errors.h (James M Snell) [#32468](https://github.com/nodejs/node/pull/32468) +* [[`464ff85ddd`](https://github.com/nodejs/node/commit/464ff85ddd)] - **src**: remove loop\_init\_failed\_ from Worker class (Anna Henningsen) [#32562](https://github.com/nodejs/node/pull/32562) +* [[`9f6ed724e0`](https://github.com/nodejs/node/commit/9f6ed724e0)] - **src**: clean up worker thread creation code (Anna Henningsen) [#32562](https://github.com/nodejs/node/pull/32562) +* [[`73c55d39f3`](https://github.com/nodejs/node/commit/73c55d39f3)] - **src**: include AsyncWrap provider strings in snapshot (Anna Henningsen) [#32572](https://github.com/nodejs/node/pull/32572) +* [[`29eca36ea8`](https://github.com/nodejs/node/commit/29eca36ea8)] - **src**: move JSONWriter into its own file (Anna Henningsen) [#32552](https://github.com/nodejs/node/pull/32552) +* [[`8e3dd47db7`](https://github.com/nodejs/node/commit/8e3dd47db7)] - **src**: handle report options on fatalerror (Sam Roberts) [#32497](https://github.com/nodejs/node/pull/32497) +* [[`e0351945bc`](https://github.com/nodejs/node/commit/e0351945bc)] - **src**: refactoring and cleanup of node\_i18n (James M Snell) [#32438](https://github.com/nodejs/node/pull/32438) +* [[`23f8f35022`](https://github.com/nodejs/node/commit/23f8f35022)] - **src**: unify Linux and FreeBSD large pages implem (Gabriel Schulhof) [#32534](https://github.com/nodejs/node/pull/32534) +* [[`16d85d9328`](https://github.com/nodejs/node/commit/16d85d9328)] - **src**: fix compiler warnings in node\_report\_module (Daniel Bevenius) [#32498](https://github.com/nodejs/node/pull/32498) +* [[`58aadcdacf`](https://github.com/nodejs/node/commit/58aadcdacf)] - **src**: simplify large pages mapping code (Gabriel Schulhof) [#32396](https://github.com/nodejs/node/pull/32396) +* [[`2da974e15e`](https://github.com/nodejs/node/commit/2da974e15e)] - **src**: use single ObjectTemplate for TextDecoder (Anna Henningsen) [#32426](https://github.com/nodejs/node/pull/32426) +* [[`8f7f4e5aba`](https://github.com/nodejs/node/commit/8f7f4e5aba)] - **src**: avoid Isolate::GetCurrent() for platform implementation (Anna Henningsen) [#32269](https://github.com/nodejs/node/pull/32269) +* [[`df046dec97`](https://github.com/nodejs/node/commit/df046dec97)] - **src**: add debug option to report large page stats (Gabriel Schulhof) [#32331](https://github.com/nodejs/node/pull/32331) +* [[`43e9ae8317`](https://github.com/nodejs/node/commit/43e9ae8317)] - **src**: prefer OnScopeLeave over shared\_ptr\ (Anna Henningsen) [#32247](https://github.com/nodejs/node/pull/32247) +* [[`2f976d783f`](https://github.com/nodejs/node/commit/2f976d783f)] - **src**: find .text section using dl\_iterate\_phdr (Gabriel Schulhof) [#32244](https://github.com/nodejs/node/pull/32244) +* [[`40c5d58095`](https://github.com/nodejs/node/commit/40c5d58095)] - ***Revert*** "**src**: keep main-thread Isolate attached to platform during Dispose" (Anna Henningsen) [#31853](https://github.com/nodejs/node/pull/31853) +* [[`51a345674e`](https://github.com/nodejs/node/commit/51a345674e)] - **src**: handle NULL env scenario (Harshitha KP) [#31899](https://github.com/nodejs/node/pull/31899) +* [[`154da1f0d3`](https://github.com/nodejs/node/commit/154da1f0d3)] - **src**: add missing namespace using statements in node\_watchdog.h (legendecas) [#32117](https://github.com/nodejs/node/pull/32117) +* [[`83c47b6079`](https://github.com/nodejs/node/commit/83c47b6079)] - **src**: introduce node\_sockaddr (James M Snell) [#32070](https://github.com/nodejs/node/pull/32070) +* [[`c979aeaf26`](https://github.com/nodejs/node/commit/c979aeaf26)] - **src**: improve handling of internal field counting (James M Snell) [#31960](https://github.com/nodejs/node/pull/31960) +* [[`38de40ac50`](https://github.com/nodejs/node/commit/38de40ac50)] - **src**: do not unnecessarily re-assign uv handle data (Anna Henningsen) [#31696](https://github.com/nodejs/node/pull/31696) +* [[`e204dba3f3`](https://github.com/nodejs/node/commit/e204dba3f3)] - **src**: pass resource object along with InternalMakeCallback (Anna Henningsen) [#32063](https://github.com/nodejs/node/pull/32063) +* [[`ffefb059e2`](https://github.com/nodejs/node/commit/ffefb059e2)] - **src**: move InternalCallbackScope to StartExecution (Shelley Vohr) [#31944](https://github.com/nodejs/node/pull/31944) +* [[`178c682ad1`](https://github.com/nodejs/node/commit/178c682ad1)] - **src**: start the .text section with an asm symbol (Gabriel Schulhof) [#31981](https://github.com/nodejs/node/pull/31981) +* [[`809d8b5036`](https://github.com/nodejs/node/commit/809d8b5036)] - **src**: include large pages source unconditionally (Gabriel Schulhof) [#31904](https://github.com/nodejs/node/pull/31904) +* [[`5ea3d60db1`](https://github.com/nodejs/node/commit/5ea3d60db1)] - **src**: use \_\_executable\_start for linux hugepages (Ben Noordhuis) [#31547](https://github.com/nodejs/node/pull/31547) +* [[`1e95bb85a9`](https://github.com/nodejs/node/commit/1e95bb85a9)] - **src**: make large\_pages node.cc include conditional (Denys Otrishko) [#31078](https://github.com/nodejs/node/pull/31078) +* [[`6dcb868a0a`](https://github.com/nodejs/node/commit/6dcb868a0a)] - **src**: make --use-largepages a runtime option (Gabriel Schulhof) [#30954](https://github.com/nodejs/node/pull/30954) +* [[`f3fb6a11fe`](https://github.com/nodejs/node/commit/f3fb6a11fe)] - **src**: change GetStringWidth's expand\_emoji\_sequence option default (Ruben Bridgewater) [#31112](https://github.com/nodejs/node/pull/31112) +* [[`4f6300f804`](https://github.com/nodejs/node/commit/4f6300f804)] - **src**: improve GetColumnWidth performance (Ruben Bridgewater) [#31112](https://github.com/nodejs/node/pull/31112) +* [[`98297b92f5`](https://github.com/nodejs/node/commit/98297b92f5)] - **src**: inline SetSNICallback (Anna Henningsen) [#30548](https://github.com/nodejs/node/pull/30548) +* [[`ce8d8c06ac`](https://github.com/nodejs/node/commit/ce8d8c06ac)] - **src**: use BaseObjectPtr to store SNI context (Anna Henningsen) [#30548](https://github.com/nodejs/node/pull/30548) +* [[`c86883e4fe`](https://github.com/nodejs/node/commit/c86883e4fe)] - **stream**: add null check in Readable.from (Pranshu Srivastava) [#32873](https://github.com/nodejs/node/pull/32873) +* [[`5df8ab16f2`](https://github.com/nodejs/node/commit/5df8ab16f2)] - **stream**: close iterator in Readable.from (Vadzim Zieńka) [#32844](https://github.com/nodejs/node/pull/32844) +* [[`c8b4ab0978`](https://github.com/nodejs/node/commit/c8b4ab0978)] - **stream**: fix readable state `awaitDrain` increase in recursion (ran) [#27572](https://github.com/nodejs/node/pull/27572) +* [[`becbe9e246`](https://github.com/nodejs/node/commit/becbe9e246)] - **tls**: move getAllowUnauthorized to internal/options (James M Snell) [#32917](https://github.com/nodejs/node/pull/32917) +* [[`dec8a21cc8`](https://github.com/nodejs/node/commit/dec8a21cc8)] - **tls**: provide default cipher list from command line (Anna Henningsen) [#32760](https://github.com/nodejs/node/pull/32760) +* [[`8961d33aff`](https://github.com/nodejs/node/commit/8961d33aff)] - **tls**: add memory tracking support to SSLWrap (Anna Henningsen) [#30548](https://github.com/nodejs/node/pull/30548) +* [[`1b41829828`](https://github.com/nodejs/node/commit/1b41829828)] - **util**: improve unicode support (Ruben Bridgewater) [#31319](https://github.com/nodejs/node/pull/31319) +* [[`a0b1a06fff`](https://github.com/nodejs/node/commit/a0b1a06fff)] - **util**: add todo comments for inspect to add unicode support (Ruben Bridgewater) [#31112](https://github.com/nodejs/node/pull/31112) +* [[`e0e8a9af6f`](https://github.com/nodejs/node/commit/e0e8a9af6f)] - **util,readline**: NFC-normalize strings before getStringWidth (Anna Henningsen) [#33052](https://github.com/nodejs/node/pull/33052) +* [[`6a9f867e56`](https://github.com/nodejs/node/commit/6a9f867e56)] - **vm**: throw error when duplicated exportNames in SyntheticModule (himself65) [#32810](https://github.com/nodejs/node/pull/32810) +* [[`02de66a110`](https://github.com/nodejs/node/commit/02de66a110)] - **vm**: lazily initialize primordials for vm contexts (Joyee Cheung) [#31738](https://github.com/nodejs/node/pull/31738) +* [[`843a54fd33`](https://github.com/nodejs/node/commit/843a54fd33)] - **wasi**: use free() to release preopen array (Anna Henningsen) [#33110](https://github.com/nodejs/node/pull/33110) +* [[`7f845e614b`](https://github.com/nodejs/node/commit/7f845e614b)] - **wasi**: update start() behavior to match spec (Colin Ihrig) [#33073](https://github.com/nodejs/node/pull/33073) +* [[`e1fe0b66b5`](https://github.com/nodejs/node/commit/e1fe0b66b5)] - **wasi**: rename \_\_wasi\_unstable\_reactor\_start() (Colin Ihrig) [#33073](https://github.com/nodejs/node/pull/33073) +* [[`7c723af3ae`](https://github.com/nodejs/node/commit/7c723af3ae)] - **wasi**: clean up options validation (Denys Otrishko) [#31797](https://github.com/nodejs/node/pull/31797) +* [[`9ce6e363f4`](https://github.com/nodejs/node/commit/9ce6e363f4)] - **worker**: fix process.env var empty key access (Christopher Beeson) [#32921](https://github.com/nodejs/node/pull/32921) +* [[`57cd7d2faa`](https://github.com/nodejs/node/commit/57cd7d2faa)] - **worker**: fix type check in receiveMessageOnPort (Anna Henningsen) [#32745](https://github.com/nodejs/node/pull/32745) +* [[`ade4ec6f9a`](https://github.com/nodejs/node/commit/ade4ec6f9a)] - **worker**: runtime error on pthread creation (Harshitha KP) [#32344](https://github.com/nodejs/node/pull/32344) + +#### Documentation commits + +* [[`51c3c8d1e8`](https://github.com/nodejs/node/commit/51c3c8d1e8)] - **doc**: fix a typo in crypto.generateKeyPairSync() (himself65) [#33187](https://github.com/nodejs/node/pull/33187) +* [[`62143b5cb9`](https://github.com/nodejs/node/commit/62143b5cb9)] - **doc**: add util.types.isArrayBufferView() (Kevin Locke) [#33092](https://github.com/nodejs/node/pull/33092) +* [[`f127ae3102`](https://github.com/nodejs/node/commit/f127ae3102)] - **doc**: clarify when not to run CI on docs (Juan José Arboleda) [#33101](https://github.com/nodejs/node/pull/33101) +* [[`7c8b0d27eb`](https://github.com/nodejs/node/commit/7c8b0d27eb)] - **doc**: fix the spelling error in stream.md (白一梓) [#31561](https://github.com/nodejs/node/pull/31561) +* [[`31b143ccf1`](https://github.com/nodejs/node/commit/31b143ccf1)] - **doc**: correct Nodejs to Node.js spelling (Nick Schonning) [#33088](https://github.com/nodejs/node/pull/33088) +* [[`2ac0f20019`](https://github.com/nodejs/node/commit/2ac0f20019)] - **doc**: improve worker pool example (Ranjan Purbey) [#33082](https://github.com/nodejs/node/pull/33082) +* [[`90cf88614e`](https://github.com/nodejs/node/commit/90cf88614e)] - **doc**: some grammar fixes (Chris Holland) [#33081](https://github.com/nodejs/node/pull/33081) +* [[`8a9be1d071`](https://github.com/nodejs/node/commit/8a9be1d071)] - **doc**: don't check links in tmp dirs (Ben Noordhuis) [#32996](https://github.com/nodejs/node/pull/32996) +* [[`5ea5c26442`](https://github.com/nodejs/node/commit/5ea5c26442)] - **doc**: improve WHATWG url constructor code example (Liran Tal) [#32782](https://github.com/nodejs/node/pull/32782) +* [[`c90a070735`](https://github.com/nodejs/node/commit/c90a070735)] - **doc**: make openssl maintenance position independent (Sam Roberts) [#32977](https://github.com/nodejs/node/pull/32977) +* [[`d75f644dc2`](https://github.com/nodejs/node/commit/d75f644dc2)] - **doc**: improve release documentation (Michaël Zasso) [#33042](https://github.com/nodejs/node/pull/33042) +* [[`98c3c427fc`](https://github.com/nodejs/node/commit/98c3c427fc)] - **doc**: add documentation for transferList arg at worker threads (Juan José Arboleda) [#32881](https://github.com/nodejs/node/pull/32881) +* [[`9038e64619`](https://github.com/nodejs/node/commit/9038e64619)] - **doc**: avoid tautology in README (Ishaan Jain) [#33005](https://github.com/nodejs/node/pull/33005) +* [[`cb7dae3385`](https://github.com/nodejs/node/commit/cb7dae3385)] - **doc**: updated directory entry information (Eileen) [#32791](https://github.com/nodejs/node/pull/32791) +* [[`7397f80dc2`](https://github.com/nodejs/node/commit/7397f80dc2)] - **doc**: ignore no-literal-urls in README (Nick Schonning) [#32676](https://github.com/nodejs/node/pull/32676) +* [[`d8bb226c0d`](https://github.com/nodejs/node/commit/d8bb226c0d)] - **doc**: convert bare email addresses to mailto links (Nick Schonning) [#32676](https://github.com/nodejs/node/pull/32676) +* [[`b057175893`](https://github.com/nodejs/node/commit/b057175893)] - **doc**: ignore no-literal-urls in changelogs (Nick Schonning) [#32676](https://github.com/nodejs/node/pull/32676) +* [[`92d91d1e78`](https://github.com/nodejs/node/commit/92d91d1e78)] - **doc**: add angle brackets around implicit links (Nick Schonning) [#32676](https://github.com/nodejs/node/pull/32676) +* [[`e5a24507f2`](https://github.com/nodejs/node/commit/e5a24507f2)] - **doc**: remove repeated word in modules.md (Prosper Opara) [#32931](https://github.com/nodejs/node/pull/32931) +* [[`a7ec1ea38d`](https://github.com/nodejs/node/commit/a7ec1ea38d)] - **doc**: elevate diagnostic report to tier1 (Gireesh Punathil) [#32732](https://github.com/nodejs/node/pull/32732) +* [[`931c0c74b0`](https://github.com/nodejs/node/commit/931c0c74b0)] - **doc**: fix typo in security-release-process.md (Edward Elric) [#32926](https://github.com/nodejs/node/pull/32926) +* [[`26cf6a3752`](https://github.com/nodejs/node/commit/26cf6a3752)] - **doc**: fix usage of folder and directory terms in fs.md (karan singh virdi) [#32919](https://github.com/nodejs/node/pull/32919) +* [[`1472a39819`](https://github.com/nodejs/node/commit/1472a39819)] - **doc**: fix typo in zlib.md (雨夜带刀) [#32901](https://github.com/nodejs/node/pull/32901) +* [[`26fdc64d96`](https://github.com/nodejs/node/commit/26fdc64d96)] - **doc**: synch SECURITY.md with website (Rich Trott) [#32903](https://github.com/nodejs/node/pull/32903) +* [[`6ddf37cbfd`](https://github.com/nodejs/node/commit/6ddf37cbfd)] - **doc**: add `tsc-agenda` to onboarding labels list (Rich Trott) [#32832](https://github.com/nodejs/node/pull/32832) +* [[`f7b78f221d`](https://github.com/nodejs/node/commit/f7b78f221d)] - **doc**: add N-API version 6 to table (Michael Dawson) [#32829](https://github.com/nodejs/node/pull/32829) +* [[`aed5112889`](https://github.com/nodejs/node/commit/aed5112889)] - **doc**: add juanarbol as collaborator (Juan José Arboleda) [#32906](https://github.com/nodejs/node/pull/32906) +* [[`68a1cec37f`](https://github.com/nodejs/node/commit/68a1cec37f)] - **doc**: missing brackets (William Bonawentura) [#32657](https://github.com/nodejs/node/pull/32657) +* [[`8d53024889`](https://github.com/nodejs/node/commit/8d53024889)] - **doc**: improve consistency in usage of NULL (Michael Dawson) [#32726](https://github.com/nodejs/node/pull/32726) +* [[`e9927e5587`](https://github.com/nodejs/node/commit/e9927e5587)] - **doc**: improve net docs (Robert Nagy) [#32811](https://github.com/nodejs/node/pull/32811) +* [[`8e7c41ee55`](https://github.com/nodejs/node/commit/8e7c41ee55)] - **doc**: note that signatures of binary may be from subkeys (Reşat SABIQ) [#32591](https://github.com/nodejs/node/pull/32591) +* [[`873d4aaaa2`](https://github.com/nodejs/node/commit/873d4aaaa2)] - **doc**: add transform stream destroy() return value (Colin Ihrig) [#32788](https://github.com/nodejs/node/pull/32788) +* [[`39da5bfca7`](https://github.com/nodejs/node/commit/39da5bfca7)] - **doc**: updated guidance for n-api changes (Michael Dawson) [#32721](https://github.com/nodejs/node/pull/32721) +* [[`38e51d335d`](https://github.com/nodejs/node/commit/38e51d335d)] - **doc**: remove warning from `response.writeHead` (Cecchi MacNaughton) [#32700](https://github.com/nodejs/node/pull/32700) +* [[`fa51d859b5`](https://github.com/nodejs/node/commit/fa51d859b5)] - **doc**: document `buffer.from` returns internal pool buffer (Harshitha KP) [#32703](https://github.com/nodejs/node/pull/32703) +* [[`47d2a9604b`](https://github.com/nodejs/node/commit/47d2a9604b)] - **doc**: add puzpuzpuz to collaborators (Andrey Pechkurov) [#32817](https://github.com/nodejs/node/pull/32817) +* [[`ad2fdd5142`](https://github.com/nodejs/node/commit/ad2fdd5142)] - **doc**: make openssl commit messages be valid (Sam Roberts) [#32602](https://github.com/nodejs/node/pull/32602) +* [[`a55d215b08`](https://github.com/nodejs/node/commit/a55d215b08)] - **doc**: add missing changes: entry for dns.ALL (Anna Henningsen) [#32617](https://github.com/nodejs/node/pull/32617) +* [[`13342f884b`](https://github.com/nodejs/node/commit/13342f884b)] - **doc**: fix typo in maintaining-openssl guide (Nitin Kumar) [#32292](https://github.com/nodejs/node/pull/32292) +* [[`d7e4bb20a7`](https://github.com/nodejs/node/commit/d7e4bb20a7)] - **doc**: add missing changes: entry for mkdir (Anna Henningsen) [#32490](https://github.com/nodejs/node/pull/32490) +* [[`742a032775`](https://github.com/nodejs/node/commit/742a032775)] - **doc**: complete n-api version matrix (Gabriel Schulhof) [#32304](https://github.com/nodejs/node/pull/32304) +* [[`f5b60ec8dd`](https://github.com/nodejs/node/commit/f5b60ec8dd)] - **doc**: change worker.takeHeapSnapshot to getHeapSnapshot (Gerhard Stoebich) [#32061](https://github.com/nodejs/node/pull/32061) +* [[`c0cf234da9`](https://github.com/nodejs/node/commit/c0cf234da9)] - **doc**: remove personal pronoun usage in policy.md (Rich Trott) [#32142](https://github.com/nodejs/node/pull/32142) +* [[`97689e05fd`](https://github.com/nodejs/node/commit/97689e05fd)] - **doc**: remove personal pronoun usage in fs.md (Rich Trott) [#32142](https://github.com/nodejs/node/pull/32142) +* [[`9a7f89245d`](https://github.com/nodejs/node/commit/9a7f89245d)] - **doc**: remove personal pronoun usage in errors.md (Rich Trott) [#32142](https://github.com/nodejs/node/pull/32142) +* [[`c98ba9537b`](https://github.com/nodejs/node/commit/c98ba9537b)] - **doc**: remove personal pronoun usage in addons.md (Rich Trott) [#32142](https://github.com/nodejs/node/pull/32142) +* [[`e8985c2e87`](https://github.com/nodejs/node/commit/e8985c2e87)] - **doc**: improve AsyncLocalStorage sample (Andrey Pechkurov) [#32757](https://github.com/nodejs/node/pull/32757) +* [[`9d9e185e3a`](https://github.com/nodejs/node/commit/9d9e185e3a)] - **doc**: list largepage values in --help (Colin Ihrig) [#31537](https://github.com/nodejs/node/pull/31537) +* [[`f13ecd801e`](https://github.com/nodejs/node/commit/f13ecd801e)] - **doc**: fix typo in maintaining-zlib guide (Nitin Kumar) [#32292](https://github.com/nodejs/node/pull/32292) +* [[`3e939ffb5e`](https://github.com/nodejs/node/commit/3e939ffb5e)] - **doc**: describe how to update zlib (Sam Roberts) [#31800](https://github.com/nodejs/node/pull/31800) +* [[`1d2565b8b6`](https://github.com/nodejs/node/commit/1d2565b8b6)] - **doc**: document readline key bindings (Harshitha KP) [#31256](https://github.com/nodejs/node/pull/31256) +* [[`8e829d4a56`](https://github.com/nodejs/node/commit/8e829d4a56)] - ***Revert*** "**doc**: fix default server timeout description for https" (Michaël Zasso) [#33069](https://github.com/nodejs/node/pull/33069) + +#### Other commits + +* [[`cdf4f4875d`](https://github.com/nodejs/node/commit/cdf4f4875d)] - **benchmark**: use let instead of var in worker (Daniele Belardi) [#31794](https://github.com/nodejs/node/pull/31794) +* [[`c572218552`](https://github.com/nodejs/node/commit/c572218552)] - **benchmark**: use let instead of var in util (Daniele Belardi) [#31794](https://github.com/nodejs/node/pull/31794) +* [[`862aeae238`](https://github.com/nodejs/node/commit/862aeae238)] - **benchmark**: use let instead of var in url (Daniele Belardi) [#31794](https://github.com/nodejs/node/pull/31794) +* [[`e68c21f079`](https://github.com/nodejs/node/commit/e68c21f079)] - **benchmark**: use let instead of var in tls (Daniele Belardi) [#31794](https://github.com/nodejs/node/pull/31794) +* [[`f3ef8946d0`](https://github.com/nodejs/node/commit/f3ef8946d0)] - **benchmark**: use let instead of var in timers (Daniele Belardi) [#31794](https://github.com/nodejs/node/pull/31794) +* [[`33858fa917`](https://github.com/nodejs/node/commit/33858fa917)] - **benchmark**: use let instead of var in run.js (Daniele Belardi) [#31794](https://github.com/nodejs/node/pull/31794) +* [[`a05f22647a`](https://github.com/nodejs/node/commit/a05f22647a)] - **benchmark**: use let instead of var in dns (Daniele Belardi) [#31794](https://github.com/nodejs/node/pull/31794) +* [[`2d7c52d729`](https://github.com/nodejs/node/commit/2d7c52d729)] - **benchmark**: use let instead of var in common.js (Daniele Belardi) [#31794](https://github.com/nodejs/node/pull/31794) +* [[`d205bc91d4`](https://github.com/nodejs/node/commit/d205bc91d4)] - **benchmark**: use const instead of var in async\_hooks (Daniele Belardi) [#31794](https://github.com/nodejs/node/pull/31794) +* [[`d7f1add038`](https://github.com/nodejs/node/commit/d7f1add038)] - **benchmark**: add `no-var` rule in .eslintrc.yaml (Daniele Belardi) [#31794](https://github.com/nodejs/node/pull/31794) +* [[`b4a6351634`](https://github.com/nodejs/node/commit/b4a6351634)] - **benchmark**: remove special test entries (Ruben Bridgewater) [#31755](https://github.com/nodejs/node/pull/31755) +* [[`71397885b2`](https://github.com/nodejs/node/commit/71397885b2)] - **benchmark**: add `test` and `all` options and improve errors" (Ruben Bridgewater) [#31755](https://github.com/nodejs/node/pull/31755) +* [[`011e3dec00`](https://github.com/nodejs/node/commit/011e3dec00)] - **benchmark**: refactor helper into a class (Ruben Bridgewater) [#31755](https://github.com/nodejs/node/pull/31755) +* [[`cf2ca11828`](https://github.com/nodejs/node/commit/cf2ca11828)] - ***Revert*** "**benchmark**: refactor helper into a class" (Anna Henningsen) [#31722](https://github.com/nodejs/node/pull/31722) +* [[`ef80c02794`](https://github.com/nodejs/node/commit/ef80c02794)] - ***Revert*** "**benchmark**: remove special test entries" (Anna Henningsen) [#31722](https://github.com/nodejs/node/pull/31722) +* [[`3861c69b02`](https://github.com/nodejs/node/commit/3861c69b02)] - **benchmark**: fix error on server close in AsyncLocalStorage benchmark (Andrey Pechkurov) [#32503](https://github.com/nodejs/node/pull/32503) +* [[`daf6e1702f`](https://github.com/nodejs/node/commit/daf6e1702f)] - **benchmark**: use let instead of var in zlib (Daniele Belardi) [#31794](https://github.com/nodejs/node/pull/31794) +* [[`6b02359dbf`](https://github.com/nodejs/node/commit/6b02359dbf)] - **test**: update c8 ignore comment (Benjamin Coe) [#33151](https://github.com/nodejs/node/pull/33151) +* [[`d7b13abbf8`](https://github.com/nodejs/node/commit/d7b13abbf8)] - **test**: skip memory usage tests when ASAN is enabled (Anna Henningsen) [#33129](https://github.com/nodejs/node/pull/33129) +* [[`238353839c`](https://github.com/nodejs/node/commit/238353839c)] - **test**: move test-process-title to sequential (Anna Henningsen) [#33150](https://github.com/nodejs/node/pull/33150) +* [[`13cae34484`](https://github.com/nodejs/node/commit/13cae34484)] - **test**: fix out-of-bound reads from invalid sizeof usage (Anna Henningsen) [#33115](https://github.com/nodejs/node/pull/33115) +* [[`08e01a12d0`](https://github.com/nodejs/node/commit/08e01a12d0)] - **test**: add missing calls to napi\_async\_destroy (Anna Henningsen) [#33114](https://github.com/nodejs/node/pull/33114) +* [[`3015887019`](https://github.com/nodejs/node/commit/3015887019)] - **test**: check args on SourceTextModule cachedData (Juan José Arboleda) [#32956](https://github.com/nodejs/node/pull/32956) +* [[`dad82173cd`](https://github.com/nodejs/node/commit/dad82173cd)] - **test**: mark test flaky on freebsd (Sam Roberts) [#32849](https://github.com/nodejs/node/pull/32849) +* [[`4ab6643abb`](https://github.com/nodejs/node/commit/4ab6643abb)] - **test**: flaky test-stdout-close-catch on freebsd (Sam Roberts) [#32849](https://github.com/nodejs/node/pull/32849) +* [[`60550f35ac`](https://github.com/nodejs/node/commit/60550f35ac)] - **test**: refactor test-async-hooks-constructor (himself65) [#33063](https://github.com/nodejs/node/pull/33063) +* [[`83520451cc`](https://github.com/nodejs/node/commit/83520451cc)] - **test**: remove timers-blocking-callback (Jeremiah Senkpiel) [#32870](https://github.com/nodejs/node/pull/32870) +* [[`579f68c5fd`](https://github.com/nodejs/node/commit/579f68c5fd)] - **test**: better error validations for event-capture (Adrian Estrada) [#32771](https://github.com/nodejs/node/pull/32771) +* [[`dacd27927a`](https://github.com/nodejs/node/commit/dacd27927a)] - **test**: refactor events tests for invalid listeners (Adrian Estrada) [#32769](https://github.com/nodejs/node/pull/32769) +* [[`4c67568148`](https://github.com/nodejs/node/commit/4c67568148)] - **test**: test-async-wrap-constructor prefer forEach (Daniel Estiven Rico Posada) [#32631](https://github.com/nodejs/node/pull/32631) +* [[`0bae243438`](https://github.com/nodejs/node/commit/0bae243438)] - **test**: mark test-child-process-fork-args as flaky on Windows (Andrey Pechkurov) [#32950](https://github.com/nodejs/node/pull/32950) +* [[`f181b5996a`](https://github.com/nodejs/node/commit/f181b5996a)] - **test**: changed function to arrow function (Nimit) [#32875](https://github.com/nodejs/node/pull/32875) +* [[`68e3954d1a`](https://github.com/nodejs/node/commit/68e3954d1a)] - **test**: replace console.log/error() with debuglog (daemon1024) [#32692](https://github.com/nodejs/node/pull/32692) +* [[`c566906789`](https://github.com/nodejs/node/commit/c566906789)] - **test**: only detect uname on supported os (Xu Meng) [#32833](https://github.com/nodejs/node/pull/32833) +* [[`50130f0e23`](https://github.com/nodejs/node/commit/50130f0e23)] - **test**: mark cpu-prof-dir-worker flaky on all (Sam Roberts) [#32828](https://github.com/nodejs/node/pull/32828) +* [[`96c93113a8`](https://github.com/nodejs/node/commit/96c93113a8)] - **test**: replace equal with strictEqual (Jesus Hernandez) [#32727](https://github.com/nodejs/node/pull/32727) +* [[`e839a71ca8`](https://github.com/nodejs/node/commit/e839a71ca8)] - **test**: mark test-worker-prof flaky on arm (Sam Roberts) [#32826](https://github.com/nodejs/node/pull/32826) +* [[`44ca47904d`](https://github.com/nodejs/node/commit/44ca47904d)] - **test**: mark test-http2-reset-flood flaky on all (Sam Roberts) [#32825](https://github.com/nodejs/node/pull/32825) +* [[`271b309c91`](https://github.com/nodejs/node/commit/271b309c91)] - **test**: cover node entry type in perf\_hooks (Julian Duque) [#32751](https://github.com/nodejs/node/pull/32751) +* [[`769ac24eba`](https://github.com/nodejs/node/commit/769ac24eba)] - **test**: use symlinks to copy shells (John Kleinschmidt) [#32129](https://github.com/nodejs/node/pull/32129) +* [[`b3ac840b97`](https://github.com/nodejs/node/commit/b3ac840b97)] - **test**: save test file in temporary directory (Luigi Pinca) [#32670](https://github.com/nodejs/node/pull/32670) +* [[`c5e0615942`](https://github.com/nodejs/node/commit/c5e0615942)] - **test**: refactor test-worker (himself65) [#32509](https://github.com/nodejs/node/pull/32509) +* [[`8eb6807dfe`](https://github.com/nodejs/node/commit/8eb6807dfe)] - **test**: replace flag expose\_internals to expose-internals (Juan José Arboleda) [#32542](https://github.com/nodejs/node/pull/32542) +* [[`5598dd14df`](https://github.com/nodejs/node/commit/5598dd14df)] - **test**: fix a typo on test-fs-read-optional-params (himself65) [#32461](https://github.com/nodejs/node/pull/32461) +* [[`30207985cc`](https://github.com/nodejs/node/commit/30207985cc)] - **test**: als variant of test-timers-clearImmediate (Harshitha KP) [#32303](https://github.com/nodejs/node/pull/32303) +* [[`e3baee6c3d`](https://github.com/nodejs/node/commit/e3baee6c3d)] - **test**: refactoring / cleanup on child-process tests (James M Snell) [#32078](https://github.com/nodejs/node/pull/32078) +* [[`6a0bc83370`](https://github.com/nodejs/node/commit/6a0bc83370)] - **test**: remove common.skipIfReportDisabled() (Colin Ihrig) [#32242](https://github.com/nodejs/node/pull/32242) +* [[`4a08b85fc8`](https://github.com/nodejs/node/commit/4a08b85fc8)] - **test**: make test-memory-usage predictable (Matheus Marchini) [#32239](https://github.com/nodejs/node/pull/32239) +* [[`efc844d00d`](https://github.com/nodejs/node/commit/efc844d00d)] - **test**: verify that WASI errors are rethrown (Colin Ihrig) [#32157](https://github.com/nodejs/node/pull/32157) +* [[`10ee89a8d5`](https://github.com/nodejs/node/commit/10ee89a8d5)] - **test**: refactor and simplify test-repl-preview (Ruben Bridgewater) [#32154](https://github.com/nodejs/node/pull/32154) +* [[`5a8e54b6de`](https://github.com/nodejs/node/commit/5a8e54b6de)] - **test**: refactor all benchmark tests to use the new test option (Ruben Bridgewater) [#31755](https://github.com/nodejs/node/pull/31755) +* [[`d1d22fa86e`](https://github.com/nodejs/node/commit/d1d22fa86e)] - **test**: add secp224k1 check in crypto-dh-stateless (Daniel Bevenius) [#31715](https://github.com/nodejs/node/pull/31715) +* [[`8a044cb9ae`](https://github.com/nodejs/node/commit/8a044cb9ae)] - **test**: fix flaky parallel/test-repl-history-navigation test (Ruben Bridgewater) [#31708](https://github.com/nodejs/node/pull/31708) +* [[`2fc72cac97`](https://github.com/nodejs/node/commit/2fc72cac97)] - **test**: fix flaky test-trace-sigint-on-idle (Anna Henningsen) [#31645](https://github.com/nodejs/node/pull/31645) +* [[`a4ee930d71`](https://github.com/nodejs/node/commit/a4ee930d71)] - **test**: improve logged errors (Ruben Bridgewater) [#31425](https://github.com/nodejs/node/pull/31425) +* [[`4aaf4075e9`](https://github.com/nodejs/node/commit/4aaf4075e9)] - **test**: show child stderr output in largepages test (Ben Noordhuis) [#31612](https://github.com/nodejs/node/pull/31612) +* [[`2508e1321f`](https://github.com/nodejs/node/commit/2508e1321f)] - **test**: add new scenario for async-local storage (Harshitha KP) [#32082](https://github.com/nodejs/node/pull/32082) +* [[`52a11544cf`](https://github.com/nodejs/node/commit/52a11544cf)] - **test**: add GC test for disabled AsyncLocalStorage (Andrey Pechkurov) [#31995](https://github.com/nodejs/node/pull/31995) +* [[`98ece74dc7`](https://github.com/nodejs/node/commit/98ece74dc7)] - **test**: improve disable AsyncLocalStorage test (Andrey Pechkurov) [#31998](https://github.com/nodejs/node/pull/31998) +* [[`e5a64e5def`](https://github.com/nodejs/node/commit/e5a64e5def)] - **test**: fix flaky test-memory-usage (Anna Henningsen) [#31602](https://github.com/nodejs/node/pull/31602) +* [[`02ec03ce27`](https://github.com/nodejs/node/commit/02ec03ce27)] - **test**: cover property n-api null cases (Gabriel Schulhof) [#31488](https://github.com/nodejs/node/pull/31488) +* [[`733002b081`](https://github.com/nodejs/node/commit/733002b081)] - **test**: skip keygen tests on arm systems (Tobias Nießen) [#31178](https://github.com/nodejs/node/pull/31178) +* [[`5e5d053585`](https://github.com/nodejs/node/commit/5e5d053585)] - **test**: add repl tests to verify unicode support in previews (Ruben Bridgewater) [#31112](https://github.com/nodejs/node/pull/31112) +* [[`f1624bbafa`](https://github.com/nodejs/node/commit/f1624bbafa)] - **test**: add multiple repl preview tests (Ruben Bridgewater) [#30907](https://github.com/nodejs/node/pull/30907) +* [[`9dcf137623`](https://github.com/nodejs/node/commit/9dcf137623)] - **test,benchmark**: fix test-benchmark-zlib (Rich Trott) [#31538](https://github.com/nodejs/node/pull/31538) +* [[`94e4847142`](https://github.com/nodejs/node/commit/94e4847142)] - **tools**: bump remark-preset-lint-node to 1.15.0 (Rich Trott) [#33157](https://github.com/nodejs/node/pull/33157) +* [[`58bd92aa26`](https://github.com/nodejs/node/commit/58bd92aa26)] - **tools**: update remark-preset-lint-node@1.14.0 (Rich Trott) [#33072](https://github.com/nodejs/node/pull/33072) +* [[`b9d9c24cfc`](https://github.com/nodejs/node/commit/b9d9c24cfc)] - **tools**: update broken types in type parser (Colin Ihrig) [#33068](https://github.com/nodejs/node/pull/33068) +* [[`3dafc1460d`](https://github.com/nodejs/node/commit/3dafc1460d)] - **tools**: fix mkcodecache when run with ASAN (Anna Henningsen) [#32850](https://github.com/nodejs/node/pull/32850) +* [[`1c010b41a1`](https://github.com/nodejs/node/commit/1c010b41a1)] - **tools**: update ESLint to 7.0.0-rc.0 (himself65) [#33062](https://github.com/nodejs/node/pull/33062) +* [[`5f79ab2239`](https://github.com/nodejs/node/commit/5f79ab2239)] - **tools**: remove unused code in doc generation tool (Rich Trott) [#32913](https://github.com/nodejs/node/pull/32913) +* [[`576a62688f`](https://github.com/nodejs/node/commit/576a62688f)] - **tools**: decrease timeout in test.py (Anna Henningsen) [#32868](https://github.com/nodejs/node/pull/32868) +* [[`9cf9cb436b`](https://github.com/nodejs/node/commit/9cf9cb436b)] - **tools**: remove prefer-common-expectserror lint rule (Colin Ihrig) [#31147](https://github.com/nodejs/node/pull/31147) + ## 2020-04-28, Version 12.16.3 'Erbium' (LTS), @targos diff --git a/doc/changelogs/CHANGELOG_V4.md b/doc/changelogs/CHANGELOG_V4.md index 7861b5b752fb77..06d8b90a598f1a 100644 --- a/doc/changelogs/CHANGELOG_V4.md +++ b/doc/changelogs/CHANGELOG_V4.md @@ -2,6 +2,7 @@ + diff --git a/doc/changelogs/CHANGELOG_V5.md b/doc/changelogs/CHANGELOG_V5.md index e7ae65ef37893f..7c290223be4b3a 100644 --- a/doc/changelogs/CHANGELOG_V5.md +++ b/doc/changelogs/CHANGELOG_V5.md @@ -2,6 +2,7 @@ +
diff --git a/doc/changelogs/CHANGELOG_V6.md b/doc/changelogs/CHANGELOG_V6.md index 2e84d741b8848f..7f8ea30191c190 100644 --- a/doc/changelogs/CHANGELOG_V6.md +++ b/doc/changelogs/CHANGELOG_V6.md @@ -2,6 +2,7 @@ +
diff --git a/doc/changelogs/CHANGELOG_V7.md b/doc/changelogs/CHANGELOG_V7.md index 3ce23bf6fa0fe4..ad42d662828d85 100644 --- a/doc/changelogs/CHANGELOG_V7.md +++ b/doc/changelogs/CHANGELOG_V7.md @@ -2,6 +2,7 @@ +
diff --git a/doc/changelogs/CHANGELOG_V8.md b/doc/changelogs/CHANGELOG_V8.md index 91f22f5b18f9bc..4ac6e71abf3fc7 100644 --- a/doc/changelogs/CHANGELOG_V8.md +++ b/doc/changelogs/CHANGELOG_V8.md @@ -2,6 +2,7 @@ +
diff --git a/doc/changelogs/CHANGELOG_V9.md b/doc/changelogs/CHANGELOG_V9.md index 6e82d6a3cc6cdd..859e654f63bf7a 100644 --- a/doc/changelogs/CHANGELOG_V9.md +++ b/doc/changelogs/CHANGELOG_V9.md @@ -2,6 +2,7 @@ +
diff --git a/doc/guides/backporting-to-release-lines.md b/doc/guides/backporting-to-release-lines.md index 55fbcb7e5bc344..6fcbdc43f72396 100644 --- a/doc/guides/backporting-to-release-lines.md +++ b/doc/guides/backporting-to-release-lines.md @@ -31,9 +31,9 @@ release line. All commands will use the `v10.x-staging` branch as the target branch. In order to submit a backport pull request to another branch, simply replace that with the staging branch for the targeted release line. -1. Checkout the staging branch for the targeted release line -2. Make sure that the local staging branch is up to date with the remote -3. Create a new branch off of the staging branch +1. Checkout the staging branch for the targeted release line. +2. Make sure that the local staging branch is up to date with the remote. +3. Create a new branch off of the staging branch, as shown below. ```shell # Assuming your fork of Node.js is checked out in $NODE_DIR, @@ -68,17 +68,17 @@ replace that with the staging branch for the targeted release line. using `git add`, and then commit the changes. That can be done with `git cherry-pick --continue`. 6. Leave the commit message as is. If you think it should be modified, comment - in the Pull Request. The `Backport-PR-URL` metadata does need to be added to + in the pull request. The `Backport-PR-URL` metadata does need to be added to the commit, but this will be done later. 7. Make sure `make -j4 test` passes. -8. Push the changes to your fork +8. Push the changes to your fork. 9. Open a pull request: 1. Be sure to target the `v10.x-staging` branch in the pull request. 1. Include the backport target in the pull request title in the following format: `[v10.x backport] `. Example: `[v10.x backport] process: improve performance of nextTick` 1. Check the checkbox labeled "Allow edits from maintainers". - 1. In the description add a reference to the original PR. + 1. In the description add a reference to the original pull request. 1. Amend the commit message and include a `Backport-PR-URL:` metadata and re-push the change to your fork. 1. Run a [`node-test-pull-request`][] CI job (with `REBASE_ONTO` set to the @@ -86,8 +86,8 @@ replace that with the staging branch for the targeted release line. 10. If during the review process conflicts arise, use the following to rebase: `git pull --rebase upstream v10.x-staging` -After the PR lands replace the `backport-requested-v10.x` label on the original -PR with `backported-to-v10.x`. +After the pull request lands, replace the `backport-requested-v10.x` label +on the original pull request with `backported-to-v10.x`. [Release Schedule]: https://github.com/nodejs/Release#release-schedule1 [Release Plan]: https://github.com/nodejs/Release#release-plan diff --git a/doc/guides/collaborator-guide.md b/doc/guides/collaborator-guide.md index 5a105b6cee8137..128f06857b8f0a 100644 --- a/doc/guides/collaborator-guide.md +++ b/doc/guides/collaborator-guide.md @@ -177,8 +177,10 @@ All pull requests must pass continuous integration tests. Code changes must pass on [project CI server](https://ci.nodejs.org/). Pull requests that only change documentation and comments can use GitHub Actions results. -Do not land any pull requests without passing (green or yellow) CI runs. If -there are CI failures unrelated to the change in the pull request, try "Resume +Do not land any pull requests without a passing (green or yellow) CI run. +For documentation-only changes, GitHub Actions CI is sufficient. +For all other code changes, Jenkins CI must pass as well. If there are +Jenkins CI failures unrelated to the change in the pull request, try "Resume Build". It is in the left navigation of the relevant `node-test-pull-request` job. It will preserve all the green results from the current job but re-run everything else. Start a fresh CI if more than seven days have elapsed since @@ -332,8 +334,8 @@ For pull requests introducing new core modules: ### Additions to N-API N-API provides an ABI-stable API guaranteed for future Node.js versions. N-API -additions call for unusual care and scrutiny. If a change adds to `node_api.h` -or `node_api_types.h`, consult [the relevant +additions call for unusual care and scrutiny. If a change adds to `node_api.h`, +`js_native_api.h`, `node_api_types.h`, or `js_native_api_types.h`, consult [the relevant guide](https://github.com/nodejs/node/blob/master/doc/guides/adding-new-napi-api.md). ### Deprecations diff --git a/doc/guides/cve-management-process.md b/doc/guides/cve-management-process.md index 1b87215ac722f2..eba94484b53877 100644 --- a/doc/guides/cve-management-process.md +++ b/doc/guides/cve-management-process.md @@ -3,7 +3,7 @@ The Node.js project acts as a [Common Vulnerabilities and Exposures (CVE) Numbering Authority (CNA)](https://cve.mitre.org/cve/cna.html). The current scope is for all actively developed versions of software -developed under the Node.js project (ie. https://github.com/nodejs). +developed under the Node.js project (ie. ). This means that the Node.js team reviews CVE requests and if appropriate assigns CVE numbers to vulnerabilities. The scope currently **does not** include third party modules. @@ -18,17 +18,17 @@ of contact points. Email aliases have been setup for these as follows: * **Public contact points**. Email address to which people will be directed by Mitre when they are asked for a way to contact the Node.js team about - CVE-related issues. **cve-request@iojs.org** + CVE-related issues. **[cve-request@iojs.org][]** * **Private contact points**. Administrative contacts that Mitre can reach out to directly in case there are issues that require immediate attention. - **cve-mitre-contact@iojs.org** + **[cve-mitre-contact@iojs.org][]** * **Email addresses to add to the CNA email discussion list**. This address has been added to a closed mailing list that is used for announcements, sharing documents, or discussion relevant to the CNA community. The list rarely has more than ten messages a week. - **cna-discussion-list@iojs.org** + **[cna-discussion-list@iojs.org][]** ## CNA management processes @@ -56,7 +56,7 @@ as outlined in the section titled `CVE Management process`. In addition, when moving a CVE from Available such that there are less than two remaining CVEs a new block must be requested as follows: -* Use the Mitre request form https://cveform.mitre.org/ with the +* Use the Mitre request form with the option `Request a Block of IDs` to request a new block. * The new block will be sent to the requester through email. * Once the new block has been received, the requester will add them @@ -72,7 +72,7 @@ of CVEs should then be requested using the steps listed above. ### External CVE request process -When a request for a CVE is received via the cve-request@iojs.org +When a request for a CVE is received via the [cve-request@iojs.org][] email alias the following process will be followed (likely updated after we get HackerOne up and running). @@ -135,3 +135,7 @@ following steps are used to assign, announce and report a CVE. * Move the CVE from the Pending section to the Announced section along with a link to the Node.js blog post announcing that releases are available. + +[cve-request@iojs.org]: mailto:cve-request@iojs.org +[cve-mitre-contact@iojs.org]: mailto:cve-mitre-contact@iojs.org +[cna-discussion-list@iojs.org]: mailto:cna-discussion-list@iojs.org diff --git a/doc/guides/diagnostic-tooling-support-tiers.md b/doc/guides/diagnostic-tooling-support-tiers.md index 62bca48e1b7af7..5d935a29369a88 100644 --- a/doc/guides/diagnostic-tooling-support-tiers.md +++ b/doc/guides/diagnostic-tooling-support-tiers.md @@ -25,7 +25,7 @@ the following tiers. * The tool must have a guide or other documentation in the Node.js GitHub organization or website; * The tool must be working on all supported platforms; - * The tool must only be using APIs exposed by Nodejs as opposed to + * The tool must only be using APIs exposed by Node.js as opposed to its dependencies; and * The tool must be open source. @@ -95,7 +95,8 @@ The tools are currently assigned to Tiers as follows: | Tool Type | Tool/API Name | Regular Testing in Node.js CI | Integrated with Node.js | Target Tier | |-----------|---------------------------|-------------------------------|-------------------------|-------------| - | | | | | | + | FFDC | diagnostic report | Yes | Yes | 1 | + | | | | | | ## Tier 2 diff --git a/doc/guides/maintaining-openssl.md b/doc/guides/maintaining-openssl.md index dfa5c7150d6148..af59486b0f3219 100644 --- a/doc/guides/maintaining-openssl.md +++ b/doc/guides/maintaining-openssl.md @@ -5,7 +5,7 @@ This document describes how to update `deps/openssl/`. ## Requirements * Linux environment * `perl` Only Perl version 5 is tested. -* `nasm` (http://www.nasm.us/) The version of 2.11 or higher is needed. +* `nasm` () The version of 2.11 or higher is needed. * GNU `as` in binutils. The version of 2.26 or higher is needed. ## 0. Check Requirements @@ -27,7 +27,7 @@ NASM version 2.11.08 ## 1. Obtain and extract new OpenSSL sources -Get a new source from https://www.openssl.org/source/ and extract +Get a new source from and extract all files into `deps/openssl/openssl`. Then add all files and commit them. ```sh @@ -57,7 +57,7 @@ This updates all sources in deps/openssl/openssl by: Use `make` to regenerate all platform dependent files in `deps/openssl/config/archs/`: ```sh -% cd deps/openssl/config; make +% make -C deps/openssl/config ``` ## 3. Check diffs @@ -66,8 +66,7 @@ Check diffs if updates are right. Even if no updates in openssl sources, `buildinf.h` files will be updated for they have a timestamp data in them. ```sh -% cd deps/openssl/config -% git diff +% git diff -- deps/openssl ``` *Note*: On Windows, OpenSSL Configure generates `makefile` that can be @@ -93,10 +92,9 @@ The commit message can be (with the openssl version set to the relevant value): ```text deps: update archs files for OpenSSL-1.1.0 - After an OpenSSL source update, all the config files need to be regenerated and - comitted by: - $ cd deps/openssl/config - $ make + After an OpenSSL source update, all the config files need to be + regenerated and committed by: + $ make -C deps/openssl/config $ git add deps/openssl/config/archs $ git add deps/openssl/openssl/include/crypto/bn_conf.h $ git add deps/openssl/openssl/include/crypto/dso_conf.h diff --git a/doc/guides/maintaining-zlib.md b/doc/guides/maintaining-zlib.md new file mode 100644 index 00000000000000..f60ba4614962ba --- /dev/null +++ b/doc/guides/maintaining-zlib.md @@ -0,0 +1,34 @@ +# Maintaining zlib + +This copy of zlib comes from the Chromium team's zlib fork which incorporated +performance improvements not currently available in standard zlib. + +## Updating zlib + +Update zlib: +```shell +git clone https://chromium.googlesource.com/chromium/src/third_party/zlib +cp deps/zlib/zlib.gyp deps/zlib/win32/zlib.def deps +rm -rf deps/zlib zlib/.git +mv zlib deps/ +mv deps/zlib.gyp deps/zlib/ +mkdir deps/zlib/win32 +mv deps/zlib.def deps/zlib/win32 +sed -i -- 's_^#include "chromeconf.h"_//#include "chromeconf.h"_' deps/zlib/zconf.h +``` + +Check that Node.js still builds and tests. + +It may be necessary to update deps/zlib/zlib.gyp if any significant changes have +occurred upstream. + +## Committing zlib + +Add zlib: `git add --all deps/zlib` + +Commit the changes with a message like +```text +deps: update zlib to upstream d7f3ca9 + +Updated as described in doc/guides/maintaining-zlib.md. +``` diff --git a/doc/guides/offboarding.md b/doc/guides/offboarding.md index 3db892b0f3de3d..13f602bb0f8286 100644 --- a/doc/guides/offboarding.md +++ b/doc/guides/offboarding.md @@ -13,4 +13,4 @@ Emeritus or leaves the project. * Some teams may also require a pull request to remove the Collaborator from a team listing. For example, if someone is removed from @nodejs/build, they should also be removed from the Build WG README.md file in the - https://github.com/nodejs/build repository. + repository. diff --git a/doc/guides/onboarding-extras.md b/doc/guides/onboarding-extras.md index a44a55987fc50a..26060a48022221 100644 --- a/doc/guides/onboarding-extras.md +++ b/doc/guides/onboarding-extras.md @@ -21,6 +21,8 @@ request. * `feature request` - Any issue that requests a new feature (usually not PRs) * `good first issue` - Issues suitable for newcomers to process * `meta` - For issues whose topic is governance, policies, procedures, etc. +* `tsc-agenda` - Open issues and pull requests with this label will be added to + the Technical Steering Committee meeting agenda -- diff --git a/doc/guides/releases.md b/doc/guides/releases.md index 2068a46dc111e4..68f4d0b8bacc6f 100644 --- a/doc/guides/releases.md +++ b/doc/guides/releases.md @@ -25,13 +25,15 @@ official release builds for Node.js, hosted on . * [10. Test the Build](#10-test-the-build) * [11. Tag and Sign the Release Commit](#11-tag-and-sign-the-release-commit) * [12. Set Up For the Next Release](#12-set-up-for-the-next-release) - * [13. Promote and Sign the Release Builds](#13-promote-and-sign-the-release-builds) - * [14. Check the Release](#14-check-the-release) - * [15. Create a Blog Post](#15-create-a-blog-post) - * [16. Create the release on GitHub](#16-create-the-release-on-github) - * [17. Cleanup](#17-cleanup) - * [18. Announce](#18-announce) - * [19. Celebrate](#19-celebrate) + * [13. Cherry-pick the Release Commit to `master`](#13-cherry-pick-the-release-commit-to-master) + * [14. Push the release tag](#14-push-the-release-tag) + * [15. Promote and Sign the Release Builds](#15-promote-and-sign-the-release-builds) + * [16. Check the Release](#16-check-the-release) + * [17. Create a Blog Post](#17-create-a-blog-post) + * [18. Create the release on GitHub](#18-create-the-release-on-github) + * [19. Cleanup](#19-cleanup) + * [20. Announce](#20-announce) + * [21. Celebrate](#21-celebrate) * [LTS Releases](#lts-releases) * [Major Releases](#major-releases) @@ -528,15 +530,31 @@ $ git rebase v1.x $ git push upstream v1.x-staging ``` -Cherry-pick the release commit to `master`. After cherry-picking, edit -`src/node_version.h` to ensure the version macros contain whatever values were -previously on `master`. `NODE_VERSION_IS_RELEASE` should be `0`. **Do not** -cherry-pick the "Working on vx.y.z" commit to `master`. +### 13. Cherry-pick the Release Commit to `master` -Run `make lint` before pushing to `master`, to make sure the Changelog -formatting passes the lint rules on `master`. +```console +$ git checkout master +$ git cherry-pick v1.x^ +``` + +Git should stop to let you fix conflicts. Revert all changes that were made to +`src/node_version.h`. If there are conflicts in `doc` due to updated `REPLACEME` +placeholders (that happens when a change previously landed on another release +branch), keep both version numbers. Convert the YAML field to an array if it is +not already one. + +Then finish cherry-picking and push the commit upstream: + +```console +$ git add src/node_version.h doc +$ git cherry-pick --continue +$ make lint +$ git push upstream master +``` + +**Do not** cherry-pick the "Working on vx.y.z" commit to `master`. -### 13. Push the release tag +### 14. Push the release tag Push the tag to the repo before you promote the builds. If you haven't pushed your tag first, then build promotion won't work properly. Push the tag using the @@ -549,7 +567,7 @@ $ git push *Note*: Please do not push the tag unless you are ready to complete the remainder of the release steps. -### 14. Promote and Sign the Release Builds +### 15. Promote and Sign the Release Builds **The same individual who signed the release tag must be the one to promote the builds as the `SHASUMS256.txt` file needs to be signed with the @@ -622,7 +640,7 @@ be prompted to re-sign `SHASUMS256.txt`. **It is possible to only sign a release by running `./tools/release.sh -s vX.Y.Z`.** -### 15. Check the Release +### 16. Check the Release Your release should be available at `https://nodejs.org/dist/vx.y.z/` and . Check that the appropriate files are in @@ -631,7 +649,7 @@ have the right internal version strings. Check that the API docs are available at . Check that the release catalog files are correct at and . -### 16. Create a Blog Post +### 17. Create a Blog Post There is an automatic build that is kicked off when you promote new builds, so within a few minutes nodejs.org will be listing your new version as the latest @@ -664,7 +682,7 @@ This script will use the promoted builds and changelog to generate the post. Run * Changes to `master` on the [nodejs.org repository][] will trigger a new build of nodejs.org so your changes should appear a few minutes after pushing. -### 17. Create the release on GitHub +### 18. Create the release on GitHub * Go to the [New release page](https://github.com/nodejs/node/releases/new). * Select the tag version you pushed earlier. @@ -672,17 +690,17 @@ This script will use the promoted builds and changelog to generate the post. Run * For the description, copy the rest of the changelog entry. * Click on the "Publish release" button. -### 18. Cleanup +### 19. Cleanup Close your release proposal PR and delete the proposal branch. -### 19. Announce +### 20. Announce The nodejs.org website will automatically rebuild and include the new version. To announce the build on Twitter through the official @nodejs account, email [pr@nodejs.org](mailto:pr@nodejs.org) with a message such as: -> v5.8.0 of @nodejs is out: https://nodejs.org/en/blog/release/v5.8.0/ +> v5.8.0 of @nodejs is out: > … > something here about notable changes @@ -693,7 +711,7 @@ announcements. Ping the IRC ops and the other [Partner Communities][] liaisons. -### 20. Celebrate +### 21. Celebrate _In whatever form you do this..._ diff --git a/doc/guides/security-release-process.md b/doc/guides/security-release-process.md index 55951f94d4ae1f..acf6b56558e3ae 100644 --- a/doc/guides/security-release-process.md +++ b/doc/guides/security-release-process.md @@ -2,7 +2,7 @@ The security release process covers the steps required to plan/implement a security release. This document is copied into the description of the Next -Security Release, and used to track progess on the release. It contains ***TEXT +Security Release, and used to track progress on the release. It contains ***TEXT LIKE THIS*** which will be replaced during the release process with the information described. @@ -88,6 +88,6 @@ information described. * [ ] Make sure the PRs for the vulnerabilities are closed. [H1 CVE requests]: https://hackerone.com/nodejs/cve_requests -[docker-node]: https://github.com/nodejs/docker-node/issues) -[nodejs/build]: https://github.com/nodejs/build/issues) +[docker-node]: https://github.com/nodejs/docker-node/issues +[nodejs/build]: https://github.com/nodejs/build/issues [email]: https://groups.google.com/forum/#!forum/nodejs-sec diff --git a/doc/guides/using-symbols.md b/doc/guides/using-symbols.md index b4bf9cd67f4081..2bc32862b7169e 100644 --- a/doc/guides/using-symbols.md +++ b/doc/guides/using-symbols.md @@ -9,7 +9,7 @@ Symbol-keyed properties of an object are not included in the output of default. Learn more about symbols at -https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Symbol. +. ## `Symbol(string)` diff --git a/doc/guides/writing-and-running-benchmarks.md b/doc/guides/writing-and-running-benchmarks.md index 1db72d22de5324..eca55bf4edf2ea 100644 --- a/doc/guides/writing-and-running-benchmarks.md +++ b/doc/guides/writing-and-running-benchmarks.md @@ -54,7 +54,7 @@ from [nghttp2.org][] or built from source. ### Benchmark Analysis Requirements To analyze the results, `R` should be installed. Use one of the available -package managers or download it from https://www.r-project.org/. +package managers or download it from . The R packages `ggplot2` and `plyr` are also used and can be installed using the R REPL. @@ -68,7 +68,7 @@ install.packages("plyr") In the event that a message is reported stating that a CRAN mirror must be selected first, specify a mirror by adding in the repo parameter. -If we used the "http://cran.us.r-project.org" mirror, it could look something +If we used the "" mirror, it could look something like this: ```R @@ -519,7 +519,8 @@ const common = require('../common.js'); const bench = common.createBenchmark(main, { kb: [64, 128, 256, 1024], - connections: [100, 500] + connections: [100, 500], + duration: 5 }); function main(conf) { @@ -546,8 +547,8 @@ Supported options keys are: * `path` - defaults to `/` * `connections` - number of concurrent connections to use, defaults to 100 * `duration` - duration of the benchmark in seconds, defaults to 10 -* `benchmarker` - benchmarker to use, defaults to -`common.default_http_benchmarker` +* `benchmarker` - benchmarker to use, defaults to the first available http + benchmarker [autocannon]: https://github.com/mcollina/autocannon [wrk]: https://github.com/wg/wrk diff --git a/doc/guides/writing-tests.md b/doc/guides/writing-tests.md index 7022bf8f938f78..385e3813fdbd69 100644 --- a/doc/guides/writing-tests.md +++ b/doc/guides/writing-tests.md @@ -430,7 +430,7 @@ To generate a test coverage report, see the [Test Coverage section of the Building guide][]. Nightly coverage reports for the Node.js master branch are available at -https://coverage.nodejs.org/. +. [ASCII]: http://man7.org/linux/man-pages/man7/ascii.7.html [Google Test]: https://github.com/google/googletest diff --git a/doc/node.1 b/doc/node.1 index ad82f466f86d45..be92e7319ed94e 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -100,6 +100,14 @@ The default is File name of the V8 CPU profile generated with .Fl -cpu-prof . +.It Fl -disable-proto Ns = Ns Ar mode +Disable the `Object.prototype.__proto__` property. If +.Ar mode +is `delete`, the property will be removed entirely. If +.Ar mode +is `throw`, accesses to the property will throw an exception with the code +`ERR_PROTO_ACCESS`. +. .It Fl -disallow-code-generation-from-strings Make built-in language features like `eval` and `new Function` that generate code from strings throw an exception instead. This does not affect the Node.js @@ -124,9 +132,6 @@ Specify the .Ar module to use as a custom module loader. . -.It Fl -experimental-modules -Enable experimental ES module support and caching modules. -. .It Fl -experimental-policy Use the specified file as a security policy. . @@ -138,11 +143,6 @@ keyword support in REPL. .It Fl -experimental-specifier-resolution Select extension resolution algorithm for ES Modules; either 'explicit' (default) or 'node' . -.It Fl -experimental-report -Enable experimental -.Sy diagnostic report -feature. -. .It Fl -experimental-vm-modules Enable experimental ES module support in VM module. . @@ -295,6 +295,11 @@ Write process warnings to the given .Ar file instead of printing to stderr. . +.It Fl -report-compact +Write +.Sy diagnostic reports +in a compact format, single-line JSON. +. .It Fl -report-directory Location at which the .Sy diagnostic report @@ -308,16 +313,16 @@ will be written. .It Fl -report-on-fatalerror Enables the .Sy diagnostic report -to be triggered on fatal errors (internal errors within the Node.js runtime such as out of memory) that leads to termination of the application, if -.Sy --experimental-report -is enabled. Useful to inspect various diagnostic data elements such as heap, stack, event loop state, resource consumption etc. to reason about the fatal error. +to be triggered on fatal errors (internal errors within the Node.js runtime such +as out of memory) that leads to termination of the application. Useful to +inspect various diagnostic data elements such as heap, stack, event loop state, +resource consumption etc. to reason about the fatal error. . .It Fl -report-on-signal Enables .Sy diagnostic report -to be generated upon receiving the specified (or predefined) signal to the running Node.js process, if -.Sy --experimental-report -is enabled. Default signal is SIGUSR2. +to be generated upon receiving the specified (or predefined) signal to the +running Node.js process. Default signal is SIGUSR2. . .It Fl -report-signal Sets or resets the signal for @@ -327,9 +332,8 @@ generation (not supported on Windows). Default signal is SIGUSR2. .It Fl -report-uncaught-exception Enables .Sy diagnostic report -to be generated on un-caught exceptions, if -.Sy --experimental-report -is enabled. Useful when inspecting JavaScript stack in conjunction with native stack and other runtime environment data. +to be generated on un-caught exceptions. Useful when inspecting JavaScript +stack in conjunction with native stack and other runtime environment data. . .It Fl -throw-deprecation Throw errors for deprecations. @@ -388,6 +392,8 @@ Enable the collection of trace event tracing information. .It Fl -trace-exit Prints a stack trace whenever an environment is exited proactively, i.e. invoking `process.exit()`. +.It Fl -trace-sigint +Prints a stack trace on SIGINT. . .It Fl -trace-sync-io Print a stack trace whenever synchronous I/O is detected after the first turn of the event loop. @@ -432,6 +438,16 @@ See and .Ev SSL_CERT_FILE . . +.It Fl -use-largepages Ns = Ns Ar mode +Re-map the Node.js static code to large memory pages at startup. If supported on +the target system, this will cause the Node.js static code to be moved onto 2 +MiB pages instead of 4 KiB pages. +.Pp +.Ar mode +must have one of the following values: +`off` (the default value, meaning do not map), `on` (map and ignore failure, +reporting it to stderr), or `silent` (map and silently ignore failure). +. .It Fl -v8-options Print V8 command-line options. . diff --git a/glossary.md b/glossary.md index a48fd6083b407f..a2954635a5ce93 100644 --- a/glossary.md +++ b/glossary.md @@ -1,4 +1,4 @@ -You may also need to check https://chromium.googlesource.com/chromiumos/docs/+/master/glossary.md. +You may also need to check . * LGTM: "Looks good to me", commonly used to approve a code review. * PTAL: Please take a look. diff --git a/lib/_http_agent.js b/lib/_http_agent.js index 40eb2a352b8e70..7fb4a4929c35f5 100644 --- a/lib/_http_agent.js +++ b/lib/_http_agent.js @@ -45,18 +45,10 @@ const kOnKeylog = Symbol('onkeylog'); // ClientRequest.onSocket(). The Agent is now *strictly* // concerned with managing a connection pool. -const kReusedHandle = Symbol('kReusedHandle'); class ReusedHandle { constructor(type, handle) { this.type = type; this.handle = handle; - // We need keep the resource object alive from this object, because - // domains rely on GC of the resource object for lifetime tracking. - // TODO(addaleax): This should really apply to all uses of - // AsyncWrap::AsyncReset() when the resource is not the AsyncWrap object - // itself. However, HTTPClientAsyncResource and HTTPServerAsyncResource - // hold on to other objects, inhibiting GC. - handle[kReusedHandle] = this; } } diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index 49f6e57fb1c6fd..606c3da9bd75fc 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -289,19 +289,11 @@ OutgoingMessage.prototype._send = function _send(data, encoding, callback) { data = this._header + data; } else { const header = this._header; - if (this.outputData.length === 0) { - this.outputData = [{ - data: header, - encoding: 'latin1', - callback: null - }]; - } else { - this.outputData.unshift({ - data: header, - encoding: 'latin1', - callback: null - }); - } + this.outputData.unshift({ + data: header, + encoding: 'latin1', + callback: null + }); this.outputSize += header.length; this._onPendingData(header.length); } diff --git a/lib/_http_server.js b/lib/_http_server.js index d43c1bfb63d67b..86340e78877a04 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -356,7 +356,7 @@ function Server(options, requestListener) { this.timeout = kDefaultHttpServerTimeout; this.keepAliveTimeout = 5000; this.maxHeadersCount = null; - this.headersTimeout = 40 * 1000; // 40 seconds + this.headersTimeout = 60 * 1000; // 60 seconds } ObjectSetPrototypeOf(Server.prototype, net.Server.prototype); ObjectSetPrototypeOf(Server, net.Server); @@ -571,8 +571,12 @@ function onParserExecute(server, socket, parser, state, ret) { // If we have not parsed the headers, destroy the socket // after server.headersTimeout to protect from DoS attacks. - // start === 0 means that we have parsed headers. - if (start !== 0 && nowDate() - start > server.headersTimeout) { + // start === 0 means that we have parsed headers, while + // server.headersTimeout === 0 means user disabled this check. + if ( + start !== 0 && server.headersTimeout && + nowDate() - start > server.headersTimeout + ) { const serverTimeout = server.emit('timeout', socket); if (!serverTimeout) diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index 9f53da30b8ad72..669521e9a568d4 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -27,6 +27,7 @@ const { NumberIsNaN, ObjectDefineProperties, ObjectSetPrototypeOf, + Set, SymbolAsyncIterator, Symbol } = primordials; @@ -146,8 +147,10 @@ function ReadableState(options, stream, isDuplex) { // Everything else in the universe uses 'utf8', though. this.defaultEncoding = (options && options.defaultEncoding) || 'utf8'; - // The number of writers that are awaiting a drain event in .pipe()s - this.awaitDrain = 0; + // Ref the piped dest which we need a drain event on it + // type: null | Writable | Set + this.awaitDrainWriters = null; + this.multiAwaitDrain = false; // If true, a maybeReadMore has been scheduled this.readingMore = false; @@ -282,7 +285,13 @@ function readableAddChunk(stream, chunk, encoding, addToFront) { function addChunk(stream, state, chunk, addToFront) { if (state.flowing && state.length === 0 && !state.sync) { - state.awaitDrain = 0; + // Use the guard to avoid creating `Set()` repeatedly + // when we have multiple pipes. + if (state.multiAwaitDrain) { + state.awaitDrainWriters.clear(); + } else { + state.awaitDrainWriters = null; + } stream.emit('data', chunk); } else { // Update the buffer info. @@ -475,7 +484,11 @@ Readable.prototype.read = function(n) { n = 0; } else { state.length -= n; - state.awaitDrain = 0; + if (state.multiAwaitDrain) { + state.awaitDrainWriters.clear(); + } else { + state.awaitDrainWriters = null; + } } if (state.length === 0) { @@ -620,6 +633,15 @@ Readable.prototype.pipe = function(dest, pipeOpts) { const src = this; const state = this._readableState; + if (state.pipesCount === 1) { + if (!state.multiAwaitDrain) { + state.multiAwaitDrain = true; + state.awaitDrainWriters = new Set( + state.awaitDrainWriters ? [state.awaitDrainWriters] : [] + ); + } + } + switch (state.pipesCount) { case 0: state.pipes = dest; @@ -684,7 +706,7 @@ Readable.prototype.pipe = function(dest, pipeOpts) { // flowing again. // So, if this is awaiting a drain, then we just call it now. // If we don't know, then assume that we are waiting for one. - if (ondrain && state.awaitDrain && + if (ondrain && state.awaitDrainWriters && (!dest._writableState || dest._writableState.needDrain)) ondrain(); } @@ -699,13 +721,15 @@ Readable.prototype.pipe = function(dest, pipeOpts) { // to get stuck in a permanently paused state if that write // also returned false. // => Check whether `dest` is still a piping destination. - if (((state.pipesCount === 1 && state.pipes === dest) || - (state.pipesCount > 1 && state.pipes.includes(dest))) && - !cleanedUp) { - debug('false write response, pause', state.awaitDrain); - state.awaitDrain++; - } if (!cleanedUp) { + if (state.pipesCount === 1 && state.pipes === dest) { + debug('false write response, pause', 0); + state.awaitDrainWriters = dest; + state.multiAwaitDrain = false; + } else if (state.pipesCount > 1 && state.pipes.includes(dest)) { + debug('false write response, pause', state.awaitDrainWriters.size); + state.awaitDrainWriters.add(dest); + } src.pause(); } if (!ondrain) { @@ -713,7 +737,7 @@ Readable.prototype.pipe = function(dest, pipeOpts) { // on the source. This would be more elegant with a .once() // handler in flow(), but adding and removing repeatedly is // too slow. - ondrain = pipeOnDrain(src); + ondrain = pipeOnDrain(src, dest); dest.on('drain', ondrain); } } @@ -762,13 +786,23 @@ Readable.prototype.pipe = function(dest, pipeOpts) { return dest; }; -function pipeOnDrain(src) { +function pipeOnDrain(src, dest) { return function pipeOnDrainFunctionResult() { const state = src._readableState; - debug('pipeOnDrain', state.awaitDrain); - if (state.awaitDrain) - state.awaitDrain--; - if (state.awaitDrain === 0 && EE.listenerCount(src, 'data')) { + + // `ondrain` will call directly, + // `this` maybe not a reference to dest, + // so we use the real dest here. + if (state.awaitDrainWriters === dest) { + debug('pipeOnDrain', 1); + state.awaitDrainWriters = null; + } else if (state.multiAwaitDrain) { + debug('pipeOnDrain', state.awaitDrainWriters.size); + state.awaitDrainWriters.delete(dest); + } + + if ((!state.awaitDrainWriters || state.awaitDrainWriters.size === 0) && + EE.listenerCount(src, 'data')) { state.flowing = true; flow(src); } diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index c8ccbdb84286a4..ea83c371bfa395 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -65,11 +65,19 @@ const { ERR_TLS_RENEGOTIATION_DISABLED, ERR_TLS_REQUIRED_SERVER_NAME, ERR_TLS_SESSION_ATTACK, - ERR_TLS_SNI_FROM_SERVER + ERR_TLS_SNI_FROM_SERVER, + ERR_TLS_INVALID_STATE } = codes; const { onpskexchange: kOnPskExchange } = internalBinding('symbols'); -const { getOptionValue } = require('internal/options'); -const { validateString, validateBuffer } = require('internal/validators'); +const { + getOptionValue, + getAllowUnauthorized, +} = require('internal/options'); +const { + validateString, + validateBuffer, + validateUint32 +} = require('internal/validators'); const traceTls = getOptionValue('--trace-tls'); const tlsKeylog = getOptionValue('--tls-keylog'); const { appendFile } = require('fs'); @@ -458,6 +466,7 @@ function TLSSocket(socket, opts) { this._securePending = false; this._newSessionPending = false; this._controlReleased = false; + this.secureConnecting = true; this._SNICallback = null; this.servername = null; this.alpnProtocol = null; @@ -859,6 +868,18 @@ TLSSocket.prototype.renegotiate = function(options, callback) { return true; }; +TLSSocket.prototype.exportKeyingMaterial = function(length, label, context) { + validateUint32(length, 'length', true); + validateString(label, 'label'); + if (context !== undefined) + validateBuffer(context, 'context'); + + if (!this._secureEstablished) + throw new ERR_TLS_INVALID_STATE(); + + return this._handle.exportKeyingMaterial(length, label, context); +}; + TLSSocket.prototype.setMaxSendFragment = function setMaxSendFragment(size) { return this._handle.setMaxSendFragment(size) === 1; }; @@ -1015,6 +1036,7 @@ function onServerSocketSecure() { if (!this.destroyed && this._releaseControl()) { debug('server emit secureConnection'); + this.secureConnecting = false; this._tlsOptions.server.emit('secureConnection', this); } } @@ -1522,22 +1544,12 @@ function onConnectEnd() { } } -let warnOnAllowUnauthorized = true; - // Arguments: [port,] [host,] [options,] [cb] exports.connect = function connect(...args) { args = normalizeConnectArgs(args); let options = args[0]; const cb = args[1]; - const allowUnauthorized = process.env.NODE_TLS_REJECT_UNAUTHORIZED === '0'; - - if (allowUnauthorized && warnOnAllowUnauthorized) { - warnOnAllowUnauthorized = false; - process.emitWarning('Setting the NODE_TLS_REJECT_UNAUTHORIZED ' + - 'environment variable to \'0\' makes TLS connections ' + - 'and HTTPS requests insecure by disabling ' + - 'certificate verification.'); - } + const allowUnauthorized = getAllowUnauthorized(); options = { rejectUnauthorized: !allowUnauthorized, diff --git a/lib/async_hooks.js b/lib/async_hooks.js index 0e77e7402b5282..0943534790550c 100644 --- a/lib/async_hooks.js +++ b/lib/async_hooks.js @@ -26,6 +26,7 @@ const { getHookArrays, enableHooks, disableHooks, + executionAsyncResource, // Internal Embedder API newAsyncId, getDefaultTriggerAsyncId, @@ -178,7 +179,7 @@ class AsyncResource { runInAsyncScope(fn, thisArg, ...args) { const asyncId = this[async_id_symbol]; - emitBefore(asyncId, this[trigger_async_id_symbol]); + emitBefore(asyncId, this[trigger_async_id_symbol], this); try { const ret = thisArg === undefined ? @@ -209,14 +210,89 @@ class AsyncResource { } } +const storageList = []; +const storageHook = createHook({ + init(asyncId, type, triggerAsyncId, resource) { + const currentResource = executionAsyncResource(); + // Value of currentResource is always a non null object + for (let i = 0; i < storageList.length; ++i) { + storageList[i]._propagate(resource, currentResource); + } + } +}); + +class AsyncLocalStorage { + constructor() { + this.kResourceStore = Symbol('kResourceStore'); + this.enabled = false; + } + + disable() { + if (this.enabled) { + this.enabled = false; + // If this.enabled, the instance must be in storageList + storageList.splice(storageList.indexOf(this), 1); + if (storageList.length === 0) { + storageHook.disable(); + } + } + } + + // Propagate the context from a parent resource to a child one + _propagate(resource, triggerResource) { + const store = triggerResource[this.kResourceStore]; + if (this.enabled) { + resource[this.kResourceStore] = store; + } + } + + enterWith(store) { + if (!this.enabled) { + this.enabled = true; + storageList.push(this); + storageHook.enable(); + } + const resource = executionAsyncResource(); + resource[this.kResourceStore] = store; + } + + run(store, callback, ...args) { + const resource = new AsyncResource('AsyncLocalStorage'); + return resource.runInAsyncScope(() => { + this.enterWith(store); + return callback(...args); + }); + } + + exit(callback, ...args) { + if (!this.enabled) { + return callback(...args); + } + this.enabled = false; + try { + return callback(...args); + } finally { + this.enabled = true; + } + } + + getStore() { + const resource = executionAsyncResource(); + if (this.enabled) { + return resource[this.kResourceStore]; + } + } +} // Placing all exports down here because the exported classes won't export // otherwise. module.exports = { // Public API + AsyncLocalStorage, createHook, executionAsyncId, triggerAsyncId, + executionAsyncResource, // Embedder API AsyncResource, }; diff --git a/lib/buffer.js b/lib/buffer.js index d83a5a30d9e1b8..874227f0d44051 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -59,11 +59,13 @@ const { zeroFill: bindingZeroFill } = internalBinding('buffer'); const { + arraybuffer_untransferable_private_symbol, getOwnNonIndexProperties, propertyFilter: { ALL_PROPERTIES, ONLY_ENUMERABLE - } + }, + setHiddenValue, } = internalBinding('util'); const { customInspectSymbol, @@ -95,6 +97,7 @@ const { hideStackFrames } = require('internal/errors'); const { + validateBuffer, validateInt32, validateString } = require('internal/validators'); @@ -153,6 +156,7 @@ function createUnsafeBuffer(size) { function createPool() { poolSize = Buffer.poolSize; allocPool = createUnsafeBuffer(poolSize).buffer; + setHiddenValue(allocPool, arraybuffer_untransferable_private_symbol, true); poolOffset = 0; } createPool(); @@ -899,6 +903,8 @@ Buffer.prototype.compare = function compare(target, // - encoding - an optional encoding, relevant if val is a string // - dir - true for indexOf, false for lastIndexOf function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) { + validateBuffer(buffer); + if (typeof byteOffset === 'string') { encoding = byteOffset; byteOffset = undefined; @@ -911,7 +917,7 @@ function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) { byteOffset = +byteOffset; // If the offset is undefined, "foo", {}, coerces to NaN, search whole buffer. if (NumberIsNaN(byteOffset)) { - byteOffset = dir ? 0 : buffer.length; + byteOffset = dir ? 0 : (buffer.length || buffer.byteLength); } dir = !!dir; // Cast to bool. diff --git a/lib/crypto.js b/lib/crypto.js index e2d1875d8d0c8b..5e45a1cd987260 100644 --- a/lib/crypto.js +++ b/lib/crypto.js @@ -25,6 +25,7 @@ 'use strict'; const { + ObjectDefineProperty, ObjectDefineProperties, } = primordials; @@ -70,7 +71,8 @@ const { const { DiffieHellman, DiffieHellmanGroup, - ECDH + ECDH, + diffieHellman } = require('internal/crypto/diffiehellman'); const { Cipher, @@ -163,6 +165,7 @@ module.exports = { createSecretKey, createSign, createVerify, + diffieHellman, getCiphers, getCurves, getDiffieHellman: createDiffieHellmanGroup, @@ -222,6 +225,10 @@ function getFipsForced() { return 1; } +ObjectDefineProperty(constants, 'defaultCipherList', { + value: getOptionValue('--tls-cipher-list') +}); + ObjectDefineProperties(module.exports, { createCipher: { enumerable: false, diff --git a/lib/dgram.js b/lib/dgram.js index 26d1e1d11a0e76..f032d3025d9efc 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -35,15 +35,11 @@ const { newHandle, } = require('internal/dgram'); const { guessHandleType } = internalBinding('util'); -const { - isLegalPort, -} = require('internal/net'); const { ERR_INVALID_ARG_TYPE, ERR_MISSING_ARGS, ERR_SOCKET_ALREADY_BOUND, ERR_SOCKET_BAD_BUFFER_SIZE, - ERR_SOCKET_BAD_PORT, ERR_SOCKET_BUFFER_SIZE, ERR_SOCKET_CANNOT_SEND, ERR_SOCKET_DGRAM_IS_CONNECTED, @@ -54,7 +50,8 @@ const { const { isInt32, validateString, - validateNumber + validateNumber, + validatePort, } = require('internal/validators'); const { Buffer } = require('buffer'); const { deprecate } = require('internal/util'); @@ -232,7 +229,9 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) { this.on('listening', onListening); } - if (port instanceof UDP) { + if (port !== null && + typeof port === 'object' && + typeof port.recvStart === 'function') { replaceHandle(this, port); startListening(this); return this; @@ -350,21 +349,8 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) { return this; }; - -function validatePort(port) { - const legal = isLegalPort(port); - if (legal) - port = port | 0; - - if (!legal || port === 0) - throw new ERR_SOCKET_BAD_PORT(port); - - return port; -} - - Socket.prototype.connect = function(port, address, callback) { - port = validatePort(port); + port = validatePort(port, 'Port', { allowZero: false }); if (typeof address === 'function') { callback = address; address = ''; @@ -610,7 +596,7 @@ Socket.prototype.send = function(buffer, } if (!connected) - port = validatePort(port); + port = validatePort(port, 'Port', { allowZero: false }); // Normalize callback so it's either a function or undefined but not anything // else. diff --git a/lib/dns.js b/lib/dns.js index df593a5255af87..4243a05e179b88 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -29,7 +29,7 @@ const { const cares = internalBinding('cares_wrap'); const { toASCII } = require('internal/idna'); -const { isIP, isLegalPort } = require('internal/net'); +const { isIP } = require('internal/net'); const { customPromisifyArgs } = require('internal/util'); const errors = require('internal/errors'); const { @@ -45,9 +45,11 @@ const { ERR_INVALID_CALLBACK, ERR_INVALID_OPT_VALUE, ERR_MISSING_ARGS, - ERR_SOCKET_BAD_PORT } = errors.codes; -const { validateString } = require('internal/validators'); +const { + validatePort, + validateString, +} = require('internal/validators'); const { GetAddrInfoReqWrap, @@ -171,8 +173,7 @@ function lookupService(address, port, callback) { if (isIP(address) === 0) throw new ERR_INVALID_OPT_VALUE('address', address); - if (!isLegalPort(port)) - throw new ERR_SOCKET_BAD_PORT(port); + validatePort(port); if (typeof callback !== 'function') throw new ERR_INVALID_CALLBACK(callback); @@ -285,6 +286,7 @@ module.exports = { // uv_getaddrinfo flags ADDRCONFIG: cares.AI_ADDRCONFIG, + ALL: cares.AI_ALL, V4MAPPED: cares.AI_V4MAPPED, // ERROR CODES diff --git a/lib/events.js b/lib/events.js index 4b16f9fa3c52a5..b138979e138fdf 100644 --- a/lib/events.js +++ b/lib/events.js @@ -59,6 +59,7 @@ const { } = require('internal/util/inspect'); const kCapture = Symbol('kCapture'); +const kErrorMonitor = Symbol('events.errorMonitor'); function EventEmitter(opts) { EventEmitter.init.call(this, opts); @@ -88,6 +89,8 @@ ObjectDefineProperty(EventEmitter, 'captureRejections', { enumerable: true }); +EventEmitter.errorMonitor = kErrorMonitor; + // The default for captureRejections is false ObjectDefineProperty(EventEmitter.prototype, kCapture, { value: false, @@ -261,9 +264,11 @@ EventEmitter.prototype.emit = function emit(type, ...args) { let doError = (type === 'error'); const events = this._events; - if (events !== undefined) + if (events !== undefined) { + if (doError && events[kErrorMonitor] !== undefined) + this.emit(kErrorMonitor, ...args); doError = (doError && events.error === undefined); - else if (!doError) + } else if (!doError) return false; // If there is no 'error' event listener then throw. diff --git a/lib/fs.js b/lib/fs.js index 5fb1784605700e..4a19e3b6033711 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -459,8 +459,36 @@ function openSync(path, flags, mode) { return result; } +// usage: +// fs.read(fd, buffer, offset, length, position, callback); +// OR +// fs.read(fd, {}, callback) function read(fd, buffer, offset, length, position, callback) { validateInt32(fd, 'fd', 0); + + if (arguments.length <= 3) { + // Assume fs.read(fd, options, callback) + let options = {}; + if (arguments.length < 3) { + // This is fs.read(fd, callback) + // buffer will be the callback + callback = buffer; + } else { + // This is fs.read(fd, {}, callback) + // buffer will be the options object + // offset is the callback + options = buffer; + callback = offset; + } + + ({ + buffer = Buffer.alloc(16384), + offset = 0, + length = buffer.length, + position + } = options); + } + validateBuffer(buffer); callback = maybeCallback(callback); @@ -497,8 +525,20 @@ function read(fd, buffer, offset, length, position, callback) { ObjectDefineProperty(read, internalUtil.customPromisifyArgs, { value: ['bytesRead', 'buffer'], enumerable: false }); +// usage: +// fs.readSync(fd, buffer, offset, length, position); +// OR +// fs.readSync(fd, buffer, {}) or fs.readSync(fd, buffer) function readSync(fd, buffer, offset, length, position) { validateInt32(fd, 'fd', 0); + + if (arguments.length <= 3) { + // Assume fs.read(fd, buffer, options) + const options = offset || {}; + + ({ offset = 0, length = buffer.length, position } = options); + } + validateBuffer(buffer); offset |= 0; @@ -525,6 +565,39 @@ function readSync(fd, buffer, offset, length, position) { return result; } +function readv(fd, buffers, position, callback) { + function wrapper(err, read) { + callback(err, read || 0, buffers); + } + + validateInt32(fd, 'fd', /* min */ 0); + validateBufferArray(buffers); + + const req = new FSReqCallback(); + req.oncomplete = wrapper; + + callback = maybeCallback(callback || position); + + if (typeof position !== 'number') + position = null; + + return binding.readBuffers(fd, buffers, position, req); +} + +function readvSync(fd, buffers, position) { + validateInt32(fd, 'fd', 0); + validateBufferArray(buffers); + + const ctx = {}; + + if (typeof position !== 'number') + position = null; + + const result = binding.readBuffers(fd, buffers, position, undefined, ctx); + handleErrorFromBinding(ctx); + return result; +} + // usage: // fs.write(fd, buffer[, offset[, length[, position]]], callback); // OR @@ -835,10 +908,13 @@ function mkdirSync(path, options) { throw new ERR_INVALID_ARG_TYPE('options.recursive', 'boolean', recursive); const ctx = { path }; - binding.mkdir(pathModule.toNamespacedPath(path), - parseMode(mode, 'mode', 0o777), recursive, undefined, - ctx); + const result = binding.mkdir(pathModule.toNamespacedPath(path), + parseMode(mode, 'mode', 0o777), recursive, + undefined, ctx); handleErrorFromBinding(ctx); + if (recursive) { + return result; + } } function readdir(path, options, callback) { @@ -1868,6 +1944,8 @@ module.exports = fs = { readdirSync, read, readSync, + readv, + readvSync, readFile, readFileSync, readlink, diff --git a/lib/https.js b/lib/https.js index cc118669e8f517..2253024f92e213 100644 --- a/lib/https.js +++ b/lib/https.js @@ -81,7 +81,7 @@ function Server(opts, requestListener) { this.timeout = kDefaultHttpServerTimeout; this.keepAliveTimeout = 5000; this.maxHeadersCount = null; - this.headersTimeout = 40 * 1000; // 40 seconds + this.headersTimeout = 60 * 1000; // 60 seconds } ObjectSetPrototypeOf(Server.prototype, tls.Server.prototype); ObjectSetPrototypeOf(Server, tls.Server); diff --git a/lib/internal/async_hooks.js b/lib/internal/async_hooks.js index 2cb81ca44f795d..8439260f1af1a6 100644 --- a/lib/internal/async_hooks.js +++ b/lib/internal/async_hooks.js @@ -28,18 +28,26 @@ const async_wrap = internalBinding('async_wrap'); * 3. executionAsyncId of the current resource. * * async_ids_stack is a Float64Array that contains part of the async ID - * stack. Each pushAsyncIds() call adds two doubles to it, and each - * popAsyncIds() call removes two doubles from it. + * stack. Each pushAsyncContext() call adds two doubles to it, and each + * popAsyncContext() call removes two doubles from it. * It has a fixed size, so if that is exceeded, calls to the native - * side are used instead in pushAsyncIds() and popAsyncIds(). + * side are used instead in pushAsyncContext() and popAsyncContext(). */ -const { async_hook_fields, async_id_fields, owner_symbol } = async_wrap; +const { + async_hook_fields, + async_id_fields, + execution_async_resources, + owner_symbol +} = async_wrap; // Store the pair executionAsyncId and triggerAsyncId in a std::stack on // Environment::AsyncHooks::async_ids_stack_ tracks the resource responsible for // the current execution stack. This is unwound as each resource exits. In the // case of a fatal exception this stack is emptied after calling each hook's // after() callback. -const { pushAsyncIds: pushAsyncIds_, popAsyncIds: popAsyncIds_ } = async_wrap; +const { + pushAsyncContext: pushAsyncContext_, + popAsyncContext: popAsyncContext_ +} = async_wrap; // For performance reasons, only track Promises when a hook is enabled. const { enablePromiseHook, disablePromiseHook } = async_wrap; // Properties in active_hooks are used to keep track of the set of hooks being @@ -92,6 +100,15 @@ const emitDestroyNative = emitHookFactory(destroy_symbol, 'emitDestroyNative'); const emitPromiseResolveNative = emitHookFactory(promise_resolve_symbol, 'emitPromiseResolveNative'); +const topLevelResource = {}; + +function executionAsyncResource() { + const index = async_hook_fields[kStackLength] - 1; + if (index === -1) return topLevelResource; + const resource = execution_async_resources[index]; + return resource; +} + // Used to fatally abort the process if a callback throws. function fatalError(e) { if (typeof e.stack === 'string') { @@ -334,8 +351,8 @@ function emitInitScript(asyncId, type, triggerAsyncId, resource) { } -function emitBeforeScript(asyncId, triggerAsyncId) { - pushAsyncIds(asyncId, triggerAsyncId); +function emitBeforeScript(asyncId, triggerAsyncId, resource) { + pushAsyncContext(asyncId, triggerAsyncId, resource); if (hasHooks(kBefore)) emitBeforeNative(asyncId); @@ -346,7 +363,7 @@ function emitAfterScript(asyncId) { if (hasHooks(kAfter)) emitAfterNative(asyncId); - popAsyncIds(asyncId); + popAsyncContext(asyncId); } @@ -364,6 +381,7 @@ function clearAsyncIdStack() { async_id_fields[kExecutionAsyncId] = 0; async_id_fields[kTriggerAsyncId] = 0; async_hook_fields[kStackLength] = 0; + execution_async_resources.splice(0, execution_async_resources.length); } @@ -373,12 +391,13 @@ function hasAsyncIdStack() { // This is the equivalent of the native push_async_ids() call. -function pushAsyncIds(asyncId, triggerAsyncId) { +function pushAsyncContext(asyncId, triggerAsyncId, resource) { const offset = async_hook_fields[kStackLength]; if (offset * 2 >= async_wrap.async_ids_stack.length) - return pushAsyncIds_(asyncId, triggerAsyncId); + return pushAsyncContext_(asyncId, triggerAsyncId, resource); async_wrap.async_ids_stack[offset * 2] = async_id_fields[kExecutionAsyncId]; async_wrap.async_ids_stack[offset * 2 + 1] = async_id_fields[kTriggerAsyncId]; + execution_async_resources[offset] = resource; async_hook_fields[kStackLength]++; async_id_fields[kExecutionAsyncId] = asyncId; async_id_fields[kTriggerAsyncId] = triggerAsyncId; @@ -386,18 +405,19 @@ function pushAsyncIds(asyncId, triggerAsyncId) { // This is the equivalent of the native pop_async_ids() call. -function popAsyncIds(asyncId) { +function popAsyncContext(asyncId) { const stackLength = async_hook_fields[kStackLength]; if (stackLength === 0) return false; if (enabledHooksExist() && async_id_fields[kExecutionAsyncId] !== asyncId) { // Do the same thing as the native code (i.e. crash hard). - return popAsyncIds_(asyncId); + return popAsyncContext_(asyncId); } const offset = stackLength - 1; async_id_fields[kExecutionAsyncId] = async_wrap.async_ids_stack[2 * offset]; async_id_fields[kTriggerAsyncId] = async_wrap.async_ids_stack[2 * offset + 1]; + execution_async_resources.pop(); async_hook_fields[kStackLength] = offset; return offset > 0; } @@ -430,6 +450,7 @@ module.exports = { clearDefaultTriggerAsyncId, clearAsyncIdStack, hasAsyncIdStack, + executionAsyncResource, // Internal Embedder API newAsyncId, getOrSetAsyncId, diff --git a/lib/internal/bootstrap/loaders.js b/lib/internal/bootstrap/loaders.js index 5422f1335dec33..fd8a4327a426ec 100644 --- a/lib/internal/bootstrap/loaders.js +++ b/lib/internal/bootstrap/loaders.js @@ -210,23 +210,21 @@ class NativeModule { } // Used by user-land module loaders to compile and load builtins. - compileForPublicLoader(needToSyncExports) { + compileForPublicLoader() { if (!this.canBeRequiredByUsers) { // No code because this is an assertion against bugs // eslint-disable-next-line no-restricted-syntax throw new Error(`Should not compile ${this.id} for public use`); } this.compileForInternalLoader(); - if (needToSyncExports) { - if (!this.exportKeys) { - // When using --expose-internals, we do not want to reflect the named - // exports from core modules as this can trigger unnecessary getters. - const internal = this.id.startsWith('internal/'); - this.exportKeys = internal ? [] : ObjectKeys(this.exports); - } - this.getESMFacade(); - this.syncExports(); + if (!this.exportKeys) { + // When using --expose-internals, we do not want to reflect the named + // exports from core modules as this can trigger unnecessary getters. + const internal = this.id.startsWith('internal/'); + this.exportKeys = internal ? [] : ObjectKeys(this.exports); } + this.getESMFacade(); + this.syncExports(); return this.exports; } diff --git a/lib/internal/bootstrap/pre_execution.js b/lib/internal/bootstrap/pre_execution.js index 1b05d6e30a0ba0..3d5e0061daa8d1 100644 --- a/lib/internal/bootstrap/pre_execution.js +++ b/lib/internal/bootstrap/pre_execution.js @@ -37,6 +37,9 @@ function prepareMainThreadExecution(expandArgv1 = false) { setupDebugEnv(); + // Print stack trace on `SIGINT` if option `--trace-sigint` presents. + setupStacktracePrinterOnSigint(); + // Process initial diagnostic reporting configuration, if present. initializeReport(); initializeReportSignalHandlers(); // Main-thread-only. @@ -149,17 +152,22 @@ function setupCoverageHooks(dir) { return coverageDirectory; } -function initializeReport() { - if (!getOptionValue('--experimental-report')) { +function setupStacktracePrinterOnSigint() { + if (!getOptionValue('--trace-sigint')) { return; } + const { SigintWatchdog } = require('internal/watchdog'); + + const watchdog = new SigintWatchdog(); + watchdog.start(); +} + +function initializeReport() { const { report } = require('internal/process/report'); - const { emitExperimentalWarning } = require('internal/util'); ObjectDefineProperty(process, 'report', { enumerable: false, configurable: true, get() { - emitExperimentalWarning('report'); return report; } }); @@ -174,10 +182,6 @@ function setupDebugEnv() { // This has to be called after initializeReport() is called function initializeReportSignalHandlers() { - if (!getOptionValue('--experimental-report')) { - return; - } - const { addSignalHandler } = require('internal/process/report'); addSignalHandler(); @@ -404,24 +408,15 @@ function initializeESMLoader() { // Create this WeakMap in js-land because V8 has no C++ API for WeakMap. internalBinding('module_wrap').callbackMap = new SafeWeakMap(); - const experimentalModules = getOptionValue('--experimental-modules'); - const experimentalVMModules = getOptionValue('--experimental-vm-modules'); - if (experimentalModules || experimentalVMModules) { - if (experimentalModules) { - process.emitWarning( - 'The ESM module loader is experimental.', - 'ExperimentalWarning', undefined); - } - const { - setImportModuleDynamicallyCallback, - setInitializeImportMetaObjectCallback - } = internalBinding('module_wrap'); - const esm = require('internal/process/esm_loader'); - // Setup per-isolate callbacks that locate data or callbacks that we keep - // track of for different ESM modules. - setInitializeImportMetaObjectCallback(esm.initializeImportMetaObject); - setImportModuleDynamicallyCallback(esm.importModuleDynamicallyCallback); - } + const { + setImportModuleDynamicallyCallback, + setInitializeImportMetaObjectCallback + } = internalBinding('module_wrap'); + const esm = require('internal/process/esm_loader'); + // Setup per-isolate callbacks that locate data or callbacks that we keep + // track of for different ESM modules. + setInitializeImportMetaObjectCallback(esm.initializeImportMetaObject); + setImportModuleDynamicallyCallback(esm.importModuleDynamicallyCallback); } function initializeFrozenIntrinsics() { diff --git a/lib/internal/child_process/serialization.js b/lib/internal/child_process/serialization.js index 9f03a8e8446c43..df8a6ca67236c5 100644 --- a/lib/internal/child_process/serialization.js +++ b/lib/internal/child_process/serialization.js @@ -25,10 +25,9 @@ class ChildProcessSerializer extends v8.DefaultSerializer { if (isArrayBufferView(object)) { this.writeUint32(kArrayBufferViewTag); return super._writeHostObject(object); - } else { - this.writeUint32(kNotArrayBufferViewTag); - this.writeValue({ ...object }); } + this.writeUint32(kNotArrayBufferViewTag); + this.writeValue({ ...object }); } } diff --git a/lib/internal/cli_table.js b/lib/internal/cli_table.js index f0f09b4f8fe870..853f02797fce41 100644 --- a/lib/internal/cli_table.js +++ b/lib/internal/cli_table.js @@ -6,7 +6,7 @@ const { ObjectPrototypeHasOwnProperty, } = primordials; -const { getStringWidth } = require('internal/readline/utils'); +const { getStringWidth } = require('internal/util/inspect'); // The use of Unicode characters below is the only non-comment use of non-ASCII // Unicode characters in Node.js built-in modules. If they are ever removed or diff --git a/lib/internal/cluster/child.js b/lib/internal/cluster/child.js index 250a82ecabaa34..74f30c0d2ece90 100644 --- a/lib/internal/cluster/child.js +++ b/lib/internal/cluster/child.js @@ -228,16 +228,23 @@ function _disconnect(masterInitiated) { // Extend generic Worker with methods specific to worker processes. Worker.prototype.disconnect = function() { - _disconnect.call(this); + if (![ 'disconnecting', 'destroying' ].includes(this.state)) { + this.state = 'disconnecting'; + _disconnect.call(this); + } + return this; }; Worker.prototype.destroy = function() { - this.exitedAfterDisconnect = true; + if (this.state === 'destroying') + return; + this.exitedAfterDisconnect = true; if (!this.isConnected()) { process.exit(0); } else { + this.state = 'destroying'; send({ act: 'exitedAfterDisconnect' }, () => process.disconnect()); process.once('disconnect', () => process.exit(0)); } diff --git a/lib/internal/cluster/master.js b/lib/internal/cluster/master.js index 70707e359f4997..9d6d4df6316956 100644 --- a/lib/internal/cluster/master.js +++ b/lib/internal/cluster/master.js @@ -14,13 +14,12 @@ const RoundRobinHandle = require('internal/cluster/round_robin_handle'); const SharedHandle = require('internal/cluster/shared_handle'); const Worker = require('internal/cluster/worker'); const { internal, sendHelper } = require('internal/cluster/utils'); -const { ERR_SOCKET_BAD_PORT } = require('internal/errors').codes; const cluster = new EventEmitter(); const intercom = new EventEmitter(); const SCHED_NONE = 1; const SCHED_RR = 2; -const { isLegalPort } = require('internal/net'); const [ minPort, maxPort ] = [ 1024, 65535 ]; +const { validatePort } = require('internal/validators'); module.exports = cluster; @@ -118,9 +117,7 @@ function createWorkerProcess(id, env) { else inspectPort = cluster.settings.inspectPort; - if (!isLegalPort(inspectPort)) { - throw new ERR_SOCKET_BAD_PORT(inspectPort); - } + validatePort(inspectPort); } else { inspectPort = process.debugPort + debugPortOffset; if (inspectPort > maxPort) @@ -300,12 +297,7 @@ function queryServer(worker, message) { constructor = SharedHandle; } - handle = new constructor(key, - address, - message.port, - message.addressType, - message.fd, - message.flags); + handle = new constructor(key, address, message); handles.set(key, handle); } diff --git a/lib/internal/cluster/round_robin_handle.js b/lib/internal/cluster/round_robin_handle.js index 5fcd43d4200f7a..636bdcc8898216 100644 --- a/lib/internal/cluster/round_robin_handle.js +++ b/lib/internal/cluster/round_robin_handle.js @@ -14,7 +14,7 @@ const { constants } = internalBinding('tcp_wrap'); module.exports = RoundRobinHandle; -function RoundRobinHandle(key, address, port, addressType, fd, flags) { +function RoundRobinHandle(key, address, { port, fd, flags }) { this.key = key; this.all = new Map(); this.free = new Map(); diff --git a/lib/internal/cluster/shared_handle.js b/lib/internal/cluster/shared_handle.js index 20c028ce313d40..656b1292988948 100644 --- a/lib/internal/cluster/shared_handle.js +++ b/lib/internal/cluster/shared_handle.js @@ -6,7 +6,7 @@ const net = require('net'); module.exports = SharedHandle; -function SharedHandle(key, address, port, addressType, fd, flags) { +function SharedHandle(key, address, { port, addressType, fd, flags }) { this.key = key; this.workers = new Map(); this.handle = null; diff --git a/lib/internal/console/constructor.js b/lib/internal/console/constructor.js index 360c8acbbfd4e3..167f5528de9975 100644 --- a/lib/internal/console/constructor.js +++ b/lib/internal/console/constructor.js @@ -30,6 +30,7 @@ const { ERR_INCOMPATIBLE_OPTION_PAIR, }, } = require('internal/errors'); +const { validateInteger } = require('internal/validators'); const { previewEntries } = internalBinding('util'); const { Buffer: { isBuffer } } = require('buffer'); const { @@ -47,11 +48,14 @@ const kTraceBegin = 'b'.charCodeAt(0); const kTraceEnd = 'e'.charCodeAt(0); const kTraceInstant = 'n'.charCodeAt(0); +const kMaxGroupIndentation = 1000; + // Lazy loaded for startup performance. let cliTable; // Track amount of indentation required via `console.group()`. const kGroupIndent = Symbol('kGroupIndent'); +const kGroupIndentationWidth = Symbol('kGroupIndentWidth'); const kFormatForStderr = Symbol('kFormatForStderr'); const kFormatForStdout = Symbol('kFormatForStdout'); const kGetInspectOptions = Symbol('kGetInspectOptions'); @@ -87,7 +91,8 @@ function Console(options /* or: stdout, stderr, ignoreErrors = true */) { stderr = stdout, ignoreErrors = true, colorMode = 'auto', - inspectOptions + inspectOptions, + groupIndentation, } = options; if (!stdout || typeof stdout.write !== 'function') { @@ -100,6 +105,11 @@ function Console(options /* or: stdout, stderr, ignoreErrors = true */) { if (typeof colorMode !== 'boolean' && colorMode !== 'auto') throw new ERR_INVALID_ARG_VALUE('colorMode', colorMode); + if (groupIndentation !== undefined) { + validateInteger(groupIndentation, 'groupIndentation', + 0, kMaxGroupIndentation); + } + if (typeof inspectOptions === 'object' && inspectOptions !== null) { if (inspectOptions.colors !== undefined && options.colorMode !== undefined) { @@ -124,7 +134,7 @@ function Console(options /* or: stdout, stderr, ignoreErrors = true */) { } this[kBindStreamsEager](stdout, stderr); - this[kBindProperties](ignoreErrors, colorMode); + this[kBindProperties](ignoreErrors, colorMode, groupIndentation); } const consolePropAttributes = { @@ -175,7 +185,8 @@ Console.prototype[kBindStreamsLazy] = function(object) { }); }; -Console.prototype[kBindProperties] = function(ignoreErrors, colorMode) { +Console.prototype[kBindProperties] = function(ignoreErrors, colorMode, + groupIndentation = 2) { ObjectDefineProperties(this, { '_stdoutErrorHandler': { ...consolePropAttributes, @@ -194,7 +205,11 @@ Console.prototype[kBindProperties] = function(ignoreErrors, colorMode) { [kCounts]: { ...consolePropAttributes, value: new Map() }, [kColorMode]: { ...consolePropAttributes, value: colorMode }, [kIsConsole]: { ...consolePropAttributes, value: true }, - [kGroupIndent]: { ...consolePropAttributes, value: '' } + [kGroupIndent]: { ...consolePropAttributes, value: '' }, + [kGroupIndentationWidth]: { + ...consolePropAttributes, + value: groupIndentation + }, }); }; @@ -397,12 +412,13 @@ const consoleMethods = { if (data.length > 0) { this.log(...data); } - this[kGroupIndent] += ' '; + this[kGroupIndent] += ' '.repeat(this[kGroupIndentationWidth]); }, groupEnd() { this[kGroupIndent] = - this[kGroupIndent].slice(0, this[kGroupIndent].length - 2); + this[kGroupIndent].slice(0, this[kGroupIndent].length - + this[kGroupIndentationWidth]); }, // https://console.spec.whatwg.org/#table diff --git a/lib/internal/crypto/diffiehellman.js b/lib/internal/crypto/diffiehellman.js index da8f87bf16d4f6..8f86911757fe1f 100644 --- a/lib/internal/crypto/diffiehellman.js +++ b/lib/internal/crypto/diffiehellman.js @@ -2,16 +2,24 @@ const { ObjectDefineProperty, + Set } = primordials; const { Buffer } = require('buffer'); const { ERR_CRYPTO_ECDH_INVALID_FORMAT, ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY, - ERR_INVALID_ARG_TYPE + ERR_CRYPTO_INCOMPATIBLE_KEY, + ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE, + ERR_INVALID_ARG_TYPE, + ERR_INVALID_OPT_VALUE } = require('internal/errors').codes; -const { validateString } = require('internal/validators'); +const { + validateString, + validateInt32, +} = require('internal/validators'); const { isArrayBufferView } = require('internal/util/types'); +const { KeyObject } = require('internal/crypto/keys'); const { getDefaultEncoding, kHandle, @@ -21,7 +29,8 @@ const { DiffieHellman: _DiffieHellman, DiffieHellmanGroup: _DiffieHellmanGroup, ECDH: _ECDH, - ECDHConvertKey: _ECDHConvertKey + ECDHConvertKey: _ECDHConvertKey, + statelessDH } = internalBinding('crypto'); const { POINT_CONVERSION_COMPRESSED, @@ -45,6 +54,13 @@ function DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding) { ); } + // Sizes < 0 don't make sense but they _are_ accepted (and subsequently + // rejected with ERR_OSSL_BN_BITS_TOO_SMALL) by OpenSSL. The glue code + // in node_crypto.cc accepts values that are IsInt32() for that reason + // and that's why we do that here too. + if (typeof sizeOrKey === 'number') + validateInt32(sizeOrKey, 'sizeOrKey'); + if (keyEncoding && !Buffer.isEncoding(keyEncoding) && keyEncoding !== 'buffer') { genEncoding = generator; @@ -61,7 +77,9 @@ function DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding) { if (!generator) generator = DH_GENERATOR; - else if (typeof generator !== 'number') + else if (typeof generator === 'number') + validateInt32(generator, 'generator'); + else generator = toBuf(generator, genEncoding); this[kHandle] = new _DiffieHellman(sizeOrKey, generator); @@ -232,8 +250,40 @@ function getFormat(format) { return POINT_CONVERSION_UNCOMPRESSED; } +const dhEnabledKeyTypes = new Set(['dh', 'ec', 'x448', 'x25519']); + +function diffieHellman(options) { + if (typeof options !== 'object') + throw new ERR_INVALID_ARG_TYPE('options', 'object', options); + + const { privateKey, publicKey } = options; + if (!(privateKey instanceof KeyObject)) + throw new ERR_INVALID_OPT_VALUE('privateKey', privateKey); + + if (!(publicKey instanceof KeyObject)) + throw new ERR_INVALID_OPT_VALUE('publicKey', publicKey); + + if (privateKey.type !== 'private') + throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(privateKey.type, 'private'); + + if (publicKey.type !== 'public' && publicKey.type !== 'private') { + throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(publicKey.type, + 'private or public'); + } + + const privateType = privateKey.asymmetricKeyType; + const publicType = publicKey.asymmetricKeyType; + if (privateType !== publicType || !dhEnabledKeyTypes.has(privateType)) { + throw new ERR_CRYPTO_INCOMPATIBLE_KEY('key types for Diffie-Hellman', + `${privateType} and ${publicType}`); + } + + return statelessDH(privateKey[kHandle], publicKey[kHandle]); +} + module.exports = { DiffieHellman, DiffieHellmanGroup, - ECDH + ECDH, + diffieHellman }; diff --git a/lib/internal/crypto/keygen.js b/lib/internal/crypto/keygen.js index 88d2822fa6fad0..ced1a0608fa4aa 100644 --- a/lib/internal/crypto/keygen.js +++ b/lib/internal/crypto/keygen.js @@ -11,6 +11,7 @@ const { generateKeyPairDSA, generateKeyPairEC, generateKeyPairNid, + generateKeyPairDH, EVP_PKEY_ED25519, EVP_PKEY_ED448, EVP_PKEY_X25519, @@ -28,10 +29,12 @@ const { const { customPromisifyArgs } = require('internal/util'); const { isUint32, validateString } = require('internal/validators'); const { + ERR_INCOMPATIBLE_OPTION_PAIR, ERR_INVALID_ARG_TYPE, ERR_INVALID_ARG_VALUE, ERR_INVALID_CALLBACK, - ERR_INVALID_OPT_VALUE + ERR_INVALID_OPT_VALUE, + ERR_MISSING_OPTION } = require('internal/errors').codes; const { isArrayBufferView } = require('internal/util/types'); @@ -245,6 +248,49 @@ function check(type, options, callback) { cipher, passphrase, wrap); } break; + case 'dh': + { + const { group, primeLength, prime, generator } = needOptions(); + let args; + if (group != null) { + if (prime != null) + throw new ERR_INCOMPATIBLE_OPTION_PAIR('group', 'prime'); + if (primeLength != null) + throw new ERR_INCOMPATIBLE_OPTION_PAIR('group', 'primeLength'); + if (generator != null) + throw new ERR_INCOMPATIBLE_OPTION_PAIR('group', 'generator'); + if (typeof group !== 'string') + throw new ERR_INVALID_OPT_VALUE('group', group); + args = [group]; + } else { + if (prime != null) { + if (primeLength != null) + throw new ERR_INCOMPATIBLE_OPTION_PAIR('prime', 'primeLength'); + if (!isArrayBufferView(prime)) + throw new ERR_INVALID_OPT_VALUE('prime', prime); + } else if (primeLength != null) { + if (!isUint32(primeLength)) + throw new ERR_INVALID_OPT_VALUE('primeLength', primeLength); + } else { + throw new ERR_MISSING_OPTION( + 'At least one of the group, prime, or primeLength options'); + } + + if (generator != null) { + if (!isUint32(generator)) + throw new ERR_INVALID_OPT_VALUE('generator', generator); + } + + args = [prime != null ? prime : primeLength, + generator == null ? 2 : generator]; + } + + impl = (wrap) => generateKeyPairDH(...args, + publicFormat, publicType, + privateFormat, privateType, + cipher, passphrase, wrap); + } + break; default: throw new ERR_INVALID_ARG_VALUE('type', type, 'must be a supported key type'); diff --git a/lib/internal/dns/promises.js b/lib/internal/dns/promises.js index ae007fd31934e2..6ade8854964c2e 100644 --- a/lib/internal/dns/promises.js +++ b/lib/internal/dns/promises.js @@ -14,7 +14,7 @@ const { } = require('internal/dns/utils'); const { codes, dnsException } = require('internal/errors'); const { toASCII } = require('internal/idna'); -const { isIP, isLegalPort } = require('internal/net'); +const { isIP } = require('internal/net'); const { getaddrinfo, getnameinfo, @@ -27,10 +27,11 @@ const { ERR_INVALID_ARG_TYPE, ERR_INVALID_OPT_VALUE, ERR_MISSING_ARGS, - ERR_SOCKET_BAD_PORT } = codes; -const { validateString } = require('internal/validators'); - +const { + validatePort, + validateString +} = require('internal/validators'); function onlookup(err, addresses) { if (err) { @@ -162,8 +163,7 @@ function lookupService(address, port) { if (isIP(address) === 0) throw new ERR_INVALID_OPT_VALUE('address', address); - if (!isLegalPort(port)) - throw new ERR_SOCKET_BAD_PORT(port); + validatePort(port); return createLookupServicePromise(address, +port); } diff --git a/lib/internal/dns/utils.js b/lib/internal/dns/utils.js index 18ad6bfad7a192..93aa529a733a89 100644 --- a/lib/internal/dns/utils.js +++ b/lib/internal/dns/utils.js @@ -10,7 +10,8 @@ const { ChannelWrap, strerror, AI_ADDRCONFIG, - AI_V4MAPPED + AI_ALL, + AI_V4MAPPED, } = internalBinding('cares_wrap'); const IANA_DNS_PORT = 53; const IPv6RE = /^\[([^[\]]*)\]/; @@ -136,10 +137,7 @@ function bindDefaultResolver(target, source) { } function validateHints(hints) { - if (hints !== 0 && - hints !== AI_ADDRCONFIG && - hints !== AI_V4MAPPED && - hints !== (AI_ADDRCONFIG | AI_V4MAPPED)) { + if ((hints & ~(AI_ADDRCONFIG | AI_ALL | AI_V4MAPPED)) !== 0) { throw new ERR_INVALID_OPT_VALUE('hints', hints); } } diff --git a/lib/internal/errors.js b/lib/internal/errors.js index b69ab5658d27f6..bfb2dd556073b6 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -20,6 +20,7 @@ const { ObjectDefineProperty, ObjectKeys, StringPrototypeSlice, + StringPrototypeStartsWith, Symbol, SymbolFor, WeakMap, @@ -766,6 +767,7 @@ E('ERR_CRYPTO_FIPS_UNAVAILABLE', 'Cannot set FIPS mode in a non-FIPS build.', Error); E('ERR_CRYPTO_HASH_FINALIZED', 'Digest already called', Error); E('ERR_CRYPTO_HASH_UPDATE_FAILED', 'Hash update failed', Error); +E('ERR_CRYPTO_INCOMPATIBLE_KEY', 'Incompatible %s: %s', Error); E('ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS', 'The selected key encoding %s %s.', Error); E('ERR_CRYPTO_INVALID_DIGEST', 'Invalid digest: %s', TypeError); @@ -1069,10 +1071,17 @@ E('ERR_INVALID_FILE_URL_PATH', 'File URL path %s', TypeError); E('ERR_INVALID_HANDLE_TYPE', 'This handle type cannot be sent', TypeError); E('ERR_INVALID_HTTP_TOKEN', '%s must be a valid HTTP token ["%s"]', TypeError); E('ERR_INVALID_IP_ADDRESS', 'Invalid IP address: %s', TypeError); -E('ERR_INVALID_MODULE_SPECIFIER', (pkgPath, subpath) => { - assert(subpath !== '.'); - return `Package subpath '${subpath}' is not a valid module request for the ` + - `"exports" resolution of ${pkgPath}${sep}package.json`; +E('ERR_INVALID_MODULE_SPECIFIER', (pkgPath, subpath, base = undefined) => { + if (subpath === undefined) { + return `Invalid package name '${pkgPath}' imported from ${base}`; + } else if (base === undefined) { + assert(subpath !== '.'); + return `Package subpath '${subpath}' is not a valid module request for ` + + `the "exports" resolution of ${pkgPath}${sep}package.json`; + } else { + return `Package subpath '${subpath}' is not a valid module request for ` + + `the "exports" resolution of ${pkgPath} imported from ${base}`; + } }, TypeError); E('ERR_INVALID_OPT_VALUE', (name, value) => `The value "${String(value)}" is invalid for option "${name}"`, @@ -1080,18 +1089,41 @@ E('ERR_INVALID_OPT_VALUE', (name, value) => RangeError); E('ERR_INVALID_OPT_VALUE_ENCODING', 'The value "%s" is invalid for option "encoding"', TypeError); -E('ERR_INVALID_PACKAGE_CONFIG', - `Invalid package config %s${sep}package.json, %s`, Error); -E('ERR_INVALID_PACKAGE_TARGET', (pkgPath, key, subpath, target) => { - if (key === '.') { - return `Invalid "exports" main target ${JSONStringify(target)} defined ` + - `in the package config ${pkgPath}${sep}package.json`; - } else { - return `Invalid "exports" target ${JSONStringify(target)} defined for '${ - StringPrototypeSlice(key, 0, -subpath.length || key.length)}' in the ` + - `package config ${pkgPath}${sep}package.json`; - } +E('ERR_INVALID_PACKAGE_CONFIG', (path, message, hasMessage = true) => { + if (hasMessage) + return `Invalid package config ${path}${sep}package.json, ${message}`; + else + return `Invalid JSON in ${path} imported from ${message}`; }, Error); +E('ERR_INVALID_PACKAGE_TARGET', + (pkgPath, key, subpath, target, base = undefined) => { + const relError = typeof target === 'string' && + target.length && !StringPrototypeStartsWith(target, './'); + if (key === null) { + if (subpath !== '') { + return `Invalid "exports" target ${JSONStringify(target)} defined ` + + `for '${subpath}' in the package config ${pkgPath} imported from ` + + `${base}.${relError ? '; targets must start with "./"' : ''}`; + } else { + return `Invalid "exports" main target ${target} defined in the ` + + `package config ${pkgPath} imported from ${base}${relError ? + '; targets must start with "./"' : ''}`; + } + } else if (key === '.') { + return `Invalid "exports" main target ${JSONStringify(target)} defined ` + + `in the package config ${pkgPath}${sep}package.json${relError ? + '; targets must start with "./"' : ''}`; + } else if (relError) { + return `Invalid "exports" target ${JSONStringify(target)} defined for '${ + StringPrototypeSlice(key, 0, -subpath.length || key.length)}' in the ` + + `package config ${pkgPath}${sep}package.json; ` + + 'targets must start with "./"'; + } else { + return `Invalid "exports" target ${JSONStringify(target)} defined for '${ + StringPrototypeSlice(key, 0, -subpath.length || key.length)}' in the ` + + `package config ${pkgPath}${sep}package.json`; + } + }, Error); E('ERR_INVALID_PERFORMANCE_MARK', 'The "%s" performance mark has not been set', Error); E('ERR_INVALID_PROTOCOL', @@ -1201,6 +1233,10 @@ E('ERR_MISSING_ARGS', E('ERR_MISSING_DYNAMIC_INSTANTIATE_HOOK', 'The ES Module loader may not return a format of \'dynamic\' when no ' + 'dynamicInstantiate function was provided', Error); +E('ERR_MISSING_OPTION', '%s is required', TypeError); +E('ERR_MODULE_NOT_FOUND', (path, base, type = 'package') => { + return `Cannot find ${type} '${path}' imported from ${base}`; +}, Error); E('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times', Error); E('ERR_NAPI_CONS_FUNCTION', 'Constructor must be a function', TypeError); E('ERR_NAPI_INVALID_DATAVIEW_ARGS', @@ -1235,12 +1271,15 @@ E('ERR_OUT_OF_RANGE', msg += ` It must be ${range}. Received ${received}`; return msg; }, RangeError); -E('ERR_PACKAGE_PATH_NOT_EXPORTED', (pkgPath, subpath) => { +E('ERR_PACKAGE_PATH_NOT_EXPORTED', (pkgPath, subpath, base = undefined) => { if (subpath === '.') { return `No "exports" main resolved in ${pkgPath}${sep}package.json`; - } else { + } else if (base === undefined) { return `Package subpath '${subpath}' is not defined by "exports" in ${ pkgPath}${sep}package.json`; + } else { + return `Package subpath '${subpath}' is not defined by "exports" in ${ + pkgPath} imported from ${base}`; } }, Error); E('ERR_REQUIRE_ESM', @@ -1271,8 +1310,12 @@ E('ERR_SERVER_NOT_RUNNING', 'Server is not running.', Error); E('ERR_SOCKET_ALREADY_BOUND', 'Socket is already bound', Error); E('ERR_SOCKET_BAD_BUFFER_SIZE', 'Buffer size must be a positive integer', TypeError); -E('ERR_SOCKET_BAD_PORT', - 'Port should be >= 0 and < 65536. Received %s.', RangeError); +E('ERR_SOCKET_BAD_PORT', (name, port, allowZero = true) => { + assert(typeof allowZero === 'boolean', + "The 'allowZero' argument must be of type boolean."); + const operator = allowZero ? '>=' : '>'; + return `${name} should be ${operator} 0 and < 65536. Received ${port}.`; +}, RangeError); E('ERR_SOCKET_BAD_TYPE', 'Bad socket type specified. Valid types are: udp4, udp6', TypeError); E('ERR_SOCKET_BUFFER_SIZE', @@ -1306,6 +1349,8 @@ E('ERR_TLS_CERT_ALTNAME_INVALID', function(reason, host, cert) { E('ERR_TLS_DH_PARAM_SIZE', 'DH parameter size %s is less than 2048', Error); E('ERR_TLS_HANDSHAKE_TIMEOUT', 'TLS handshake timeout', Error); E('ERR_TLS_INVALID_CONTEXT', '%s must be a SecureContext', TypeError), +E('ERR_TLS_INVALID_STATE', 'TLS socket connection must be securely established', + Error), E('ERR_TLS_INVALID_PROTOCOL_VERSION', '%j is not a valid %s TLS protocol version', TypeError); E('ERR_TLS_PROTOCOL_VERSION_CONFLICT', @@ -1363,6 +1408,8 @@ E('ERR_VALID_PERFORMANCE_ENTRY_TYPE', E('ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING', 'A dynamic import callback was not specified.', TypeError); E('ERR_VM_MODULE_ALREADY_LINKED', 'Module has already been linked', Error); +E('ERR_VM_MODULE_CANNOT_CREATE_CACHED_DATA', + 'Cached data cannot be created for a module which has been evaluated', Error); E('ERR_VM_MODULE_DIFFERENT_CONTEXT', 'Linked modules must use the same context', Error); E('ERR_VM_MODULE_LINKING_ERRORED', @@ -1375,11 +1422,16 @@ E('ERR_WORKER_INIT_FAILED', 'Worker initialization failure: %s', Error); E('ERR_WORKER_INVALID_EXEC_ARGV', (errors, msg = 'invalid execArgv flags') => `Initiated Worker with ${msg}: ${errors.join(', ')}`, Error); +E('ERR_WORKER_NOT_RUNNING', 'Worker instance not running', Error); E('ERR_WORKER_OUT_OF_MEMORY', 'Worker terminated due to reaching memory limit: %s', Error); -E('ERR_WORKER_PATH', - 'The worker script filename must be an absolute path or a relative ' + - 'path starting with \'./\' or \'../\'. Received "%s"', +E('ERR_WORKER_PATH', (filename) => + 'The worker script or module filename must be an absolute path or a ' + + 'relative path starting with \'./\' or \'../\'.' + + (filename.startsWith('file://') ? + ' Wrap file:// URLs with `new URL`.' : '' + ) + + ` Received "${filename}"`, TypeError); E('ERR_WORKER_UNSERIALIZABLE_ERROR', 'Serializing an uncaught exception failed', Error); diff --git a/lib/internal/fixed_queue.js b/lib/internal/fixed_queue.js index d3ffbc2a1e154e..f6f3110d8ec5d4 100644 --- a/lib/internal/fixed_queue.js +++ b/lib/internal/fixed_queue.js @@ -56,7 +56,7 @@ const kMask = kSize - 1; // `top + 1 === bottom` it's full. This wastes a single space of storage // but allows much quicker checks. -const FixedCircularBuffer = class FixedCircularBuffer { +class FixedCircularBuffer { constructor() { this.bottom = 0; this.top = 0; @@ -85,7 +85,7 @@ const FixedCircularBuffer = class FixedCircularBuffer { this.bottom = (this.bottom + 1) & kMask; return nextItem; } -}; +} module.exports = class FixedQueue { constructor() { diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index 927bf739e79763..d653724474f314 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -95,6 +95,10 @@ class FileHandle { return read(this, buffer, offset, length, position); } + readv(buffers, position) { + return readv(this, buffers, position); + } + readFile(options) { return readFile(this, options); } @@ -180,11 +184,8 @@ async function readFileHandle(filehandle, options) { } while (!endOfFile); const result = Buffer.concat(chunks); - if (options.encoding) { - return result.toString(options.encoding); - } else { - return result; - } + + return options.encoding ? result.toString(options.encoding) : result; } // All of the functions are defined as async in order to ensure that errors @@ -244,6 +245,18 @@ async function read(handle, buffer, offset, length, position) { return { bytesRead, buffer }; } +async function readv(handle, buffers, position) { + validateFileHandle(handle); + validateBufferArray(buffers); + + if (typeof position !== 'number') + position = null; + + const bytesRead = (await binding.readBuffers(handle.fd, buffers, position, + kUsePromises)) || 0; + return { bytesRead, buffers }; +} + async function write(handle, buffer, offset, length, position) { validateFileHandle(handle); diff --git a/lib/internal/fs/streams.js b/lib/internal/fs/streams.js index 9522d966673982..343e09d7bc271b 100644 --- a/lib/internal/fs/streams.js +++ b/lib/internal/fs/streams.js @@ -11,6 +11,7 @@ const { } = primordials; const { + ERR_INVALID_ARG_TYPE, ERR_OUT_OF_RANGE, ERR_STREAM_DESTROYED } = require('internal/errors').codes; @@ -21,12 +22,13 @@ const { copyObject, getOptions, } = require('internal/fs/utils'); -const { Readable, Writable } = require('stream'); +const { Readable, Writable, finished } = require('stream'); const { toPathIfFileURL } = require('internal/url'); const kIoDone = Symbol('kIoDone'); const kIsPerformingIO = Symbol('kIsPerformingIO'); const kMinPoolSpace = 128; +const kFs = Symbol('kFs'); let pool; // It can happen that we expect to read a large chunk of data, and reserve @@ -75,6 +77,23 @@ function ReadStream(path, options) { options.emitClose = false; } + this[kFs] = options.fs || fs; + + if (typeof this[kFs].open !== 'function') { + throw new ERR_INVALID_ARG_TYPE('options.fs.open', 'function', + this[kFs].open); + } + + if (typeof this[kFs].read !== 'function') { + throw new ERR_INVALID_ARG_TYPE('options.fs.read', 'function', + this[kFs].read); + } + + if (typeof this[kFs].close !== 'function') { + throw new ERR_INVALID_ARG_TYPE('options.fs.close', 'function', + this[kFs].close); + } + Readable.call(this, options); // Path will be ignored when fd is specified, so it can be falsy @@ -124,7 +143,7 @@ ObjectSetPrototypeOf(ReadStream.prototype, Readable.prototype); ObjectSetPrototypeOf(ReadStream, Readable); ReadStream.prototype.open = function() { - fs.open(this.path, this.flags, this.mode, (er, fd) => { + this[kFs].open(this.path, this.flags, this.mode, (er, fd) => { if (er) { if (this.autoClose) { this.destroy(); @@ -174,42 +193,43 @@ ReadStream.prototype._read = function(n) { // the actual read. this[kIsPerformingIO] = true; - fs.read(this.fd, pool, pool.used, toRead, this.pos, (er, bytesRead) => { - this[kIsPerformingIO] = false; - // Tell ._destroy() that it's safe to close the fd now. - if (this.destroyed) return this.emit(kIoDone, er); - - if (er) { - if (this.autoClose) { - this.destroy(); - } - this.emit('error', er); - } else { - let b = null; - // Now that we know how much data we have actually read, re-wind the - // 'used' field if we can, and otherwise allow the remainder of our - // reservation to be used as a new pool later. - if (start + toRead === thisPool.used && thisPool === pool) { - const newUsed = thisPool.used + bytesRead - toRead; - thisPool.used = roundUpToMultipleOf8(newUsed); + this[kFs].read( + this.fd, pool, pool.used, toRead, this.pos, (er, bytesRead) => { + this[kIsPerformingIO] = false; + // Tell ._destroy() that it's safe to close the fd now. + if (this.destroyed) return this.emit(kIoDone, er); + + if (er) { + if (this.autoClose) { + this.destroy(); + } + this.emit('error', er); } else { - // Round down to the next lowest multiple of 8 to ensure the new pool - // fragment start and end positions are aligned to an 8 byte boundary. - const alignedEnd = (start + toRead) & ~7; - const alignedStart = roundUpToMultipleOf8(start + bytesRead); - if (alignedEnd - alignedStart >= kMinPoolSpace) { - poolFragments.push(thisPool.slice(alignedStart, alignedEnd)); + let b = null; + // Now that we know how much data we have actually read, re-wind the + // 'used' field if we can, and otherwise allow the remainder of our + // reservation to be used as a new pool later. + if (start + toRead === thisPool.used && thisPool === pool) { + const newUsed = thisPool.used + bytesRead - toRead; + thisPool.used = roundUpToMultipleOf8(newUsed); + } else { + // Round down to the next lowest multiple of 8 to ensure the new pool + // fragment start and end positions are aligned to an 8 byte boundary. + const alignedEnd = (start + toRead) & ~7; + const alignedStart = roundUpToMultipleOf8(start + bytesRead); + if (alignedEnd - alignedStart >= kMinPoolSpace) { + poolFragments.push(thisPool.slice(alignedStart, alignedEnd)); + } } - } - if (bytesRead > 0) { - this.bytesRead += bytesRead; - b = thisPool.slice(start, start + bytesRead); - } + if (bytesRead > 0) { + this.bytesRead += bytesRead; + b = thisPool.slice(start, start + bytesRead); + } - this.push(b); - } - }); + this.push(b); + } + }); // Move the pool positions, and internal position for reading. if (this.pos !== undefined) @@ -233,7 +253,7 @@ ReadStream.prototype._destroy = function(err, cb) { }; function closeFsStream(stream, cb, err) { - fs.close(stream.fd, (er) => { + stream[kFs].close(stream.fd, (er) => { er = er || err; cb(er); stream.closed = true; @@ -246,7 +266,8 @@ function closeFsStream(stream, cb, err) { } ReadStream.prototype.close = function(cb) { - this.destroy(null, cb); + if (typeof cb === 'function') finished(this, cb); + this.destroy(); }; ObjectDefineProperty(ReadStream.prototype, 'pending', { @@ -268,6 +289,40 @@ function WriteStream(path, options) { options.emitClose = false; } + this[kFs] = options.fs || fs; + if (typeof this[kFs].open !== 'function') { + throw new ERR_INVALID_ARG_TYPE('options.fs.open', 'function', + this[kFs].open); + } + + if (!this[kFs].write && !this[kFs].writev) { + throw new ERR_INVALID_ARG_TYPE('options.fs.write', 'function', + this[kFs].write); + } + + if (this[kFs].write && typeof this[kFs].write !== 'function') { + throw new ERR_INVALID_ARG_TYPE('options.fs.write', 'function', + this[kFs].write); + } + + if (this[kFs].writev && typeof this[kFs].writev !== 'function') { + throw new ERR_INVALID_ARG_TYPE('options.fs.writev', 'function', + this[kFs].writev); + } + + if (typeof this[kFs].close !== 'function') { + throw new ERR_INVALID_ARG_TYPE('options.fs.close', 'function', + this[kFs].close); + } + + // It's enough to override either, in which case only one will be used. + if (!this[kFs].write) { + this._write = null; + } + if (!this[kFs].writev) { + this._writev = null; + } + Writable.call(this, options); // Path will be ignored when fd is specified, so it can be falsy @@ -313,7 +368,7 @@ WriteStream.prototype._final = function(callback) { }; WriteStream.prototype.open = function() { - fs.open(this.path, this.flags, this.mode, (er, fd) => { + this[kFs].open(this.path, this.flags, this.mode, (er, fd) => { if (er) { if (this.autoClose) { this.destroy(); @@ -339,7 +394,7 @@ WriteStream.prototype._write = function(data, encoding, cb) { if (this.destroyed) return cb(new ERR_STREAM_DESTROYED('write')); this[kIsPerformingIO] = true; - fs.write(this.fd, data, 0, data.length, this.pos, (er, bytes) => { + this[kFs].write(this.fd, data, 0, data.length, this.pos, (er, bytes) => { this[kIsPerformingIO] = false; // Tell ._destroy() that it's safe to close the fd now. if (this.destroyed) { @@ -383,7 +438,7 @@ WriteStream.prototype._writev = function(data, cb) { } this[kIsPerformingIO] = true; - fs.writev(this.fd, chunks, this.pos, (er, bytes) => { + this[kFs].writev(this.fd, chunks, this.pos, (er, bytes) => { this[kIsPerformingIO] = false; // Tell ._destroy() that it's safe to close the fd now. if (this.destroyed) { diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index e143f985a4da99..6f096336f20e10 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -506,13 +506,15 @@ function toUnixTimestamp(time, name = 'time') { const validateOffsetLengthRead = hideStackFrames( (offset, length, bufferLength) => { - if (offset < 0 || offset >= bufferLength) { - throw new ERR_OUT_OF_RANGE('offset', - `>= 0 && <= ${bufferLength}`, offset); + if (offset < 0) { + throw new ERR_OUT_OF_RANGE('offset', '>= 0', offset); } - if (length < 0 || offset + length > bufferLength) { + if (length < 0) { + throw new ERR_OUT_OF_RANGE('length', '>= 0', length); + } + if (offset + length > bufferLength) { throw new ERR_OUT_OF_RANGE('length', - `>= 0 && <= ${bufferLength - offset}`, length); + `<= ${bufferLength - offset}`, length); } } ); diff --git a/lib/internal/heap_utils.js b/lib/internal/heap_utils.js new file mode 100644 index 00000000000000..126fe3f7e46a0c --- /dev/null +++ b/lib/internal/heap_utils.js @@ -0,0 +1,41 @@ +'use strict'; +const { + Symbol +} = primordials; +const { + kUpdateTimer, + onStreamRead, +} = require('internal/stream_base_commons'); +const { owner_symbol } = require('internal/async_hooks').symbols; +const { Readable } = require('stream'); + +const kHandle = Symbol('kHandle'); + +class HeapSnapshotStream extends Readable { + constructor(handle) { + super({ autoDestroy: true }); + this[kHandle] = handle; + handle[owner_symbol] = this; + handle.onread = onStreamRead; + } + + _read() { + if (this[kHandle]) + this[kHandle].readStart(); + } + + _destroy() { + // Release the references on the handle so that + // it can be garbage collected. + this[kHandle][owner_symbol] = undefined; + this[kHandle] = undefined; + } + + [kUpdateTimer]() { + // Does nothing + } +} + +module.exports = { + HeapSnapshotStream +}; diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 2b790c6ece3d19..1031e6dc42474b 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -1115,7 +1115,7 @@ class Http2Session extends EventEmitter { socket.disableRenegotiation(); const setupFn = setupHandle.bind(this, socket, type, options); - if (socket.connecting) { + if (socket.connecting || socket.secureConnecting) { const connectEvent = socket instanceof tls.TLSSocket ? 'secureConnect' : 'connect'; socket.once(connectEvent, () => { diff --git a/lib/internal/main/check_syntax.js b/lib/internal/main/check_syntax.js index f69e7b6ba5f38f..a3b9bf2923769e 100644 --- a/lib/internal/main/check_syntax.js +++ b/lib/internal/main/check_syntax.js @@ -47,23 +47,20 @@ if (process.argv[1] && process.argv[1] !== '-') { function checkSyntax(source, filename) { const { getOptionValue } = require('internal/options'); - const experimentalModules = getOptionValue('--experimental-modules'); - if (experimentalModules) { - let isModule = false; - if (filename === '[stdin]' || filename === '[eval]') { - isModule = getOptionValue('--input-type') === 'module'; - } else { - const { defaultResolve } = require('internal/modules/esm/resolve'); - const { defaultGetFormat } = require('internal/modules/esm/get_format'); - const { url } = defaultResolve(pathToFileURL(filename).toString()); - const { format } = defaultGetFormat(url); - isModule = format === 'module'; - } - if (isModule) { - const { ModuleWrap } = internalBinding('module_wrap'); - new ModuleWrap(filename, undefined, source, 0, 0); - return; - } + let isModule = false; + if (filename === '[stdin]' || filename === '[eval]') { + isModule = getOptionValue('--input-type') === 'module'; + } else { + const { defaultResolve } = require('internal/modules/esm/resolve'); + const { defaultGetFormat } = require('internal/modules/esm/get_format'); + const { url } = defaultResolve(pathToFileURL(filename).toString()); + const { format } = defaultGetFormat(url); + isModule = format === 'module'; + } + if (isModule) { + const { ModuleWrap } = internalBinding('module_wrap'); + new ModuleWrap(filename, undefined, source, 0, 0); + return; } wrapSafe(filename, source); diff --git a/lib/internal/main/run_main_module.js b/lib/internal/main/run_main_module.js index b085f2fd1cd9f3..ca5d1122c59d94 100644 --- a/lib/internal/main/run_main_module.js +++ b/lib/internal/main/run_main_module.js @@ -8,11 +8,10 @@ prepareMainThreadExecution(true); markBootstrapComplete(); -// Note: this loads the module through the ESM loader if -// --experimental-loader is provided or --experimental-modules is on -// and the module is determined to be an ES module. This hangs from the CJS -// module loader because we currently allow monkey-patching of the module -// loaders in the preloaded scripts through require('module'). +// Note: this loads the module through the ESM loader if the module is +// determined to be an ES module. This hangs from the CJS module loader +// because we currently allow monkey-patching of the module loaders +// in the preloaded scripts through require('module'). // runMain here might be monkey-patched by users in --require. // XXX: the monkey-patchability here should probably be deprecated. require('internal/modules/cjs/loader').Module.runMain(process.argv[1]); diff --git a/lib/internal/modules/cjs/helpers.js b/lib/internal/modules/cjs/helpers.js index df41f15ff58610..2f62c8623e27be 100644 --- a/lib/internal/modules/cjs/helpers.js +++ b/lib/internal/modules/cjs/helpers.js @@ -9,8 +9,6 @@ const { ERR_UNKNOWN_BUILTIN_MODULE } = require('internal/errors').codes; const { NativeModule } = require('internal/bootstrap/loaders'); -const { getOptionValue } = require('internal/options'); -const experimentalModules = getOptionValue('--experimental-modules'); const { validateString } = require('internal/validators'); const path = require('path'); @@ -19,11 +17,11 @@ const { URL } = require('url'); const debug = require('internal/util/debuglog').debuglog('module'); -function loadNativeModule(filename, request, experimentalModules) { +function loadNativeModule(filename, request) { const mod = NativeModule.map.get(filename); if (mod) { debug('load native module %s', request); - mod.compileForPublicLoader(experimentalModules); + mod.compileForPublicLoader(); return mod; } } @@ -48,10 +46,7 @@ function makeRequireFunction(mod, redirects) { const href = destination.href; if (destination.protocol === 'node:') { const specifier = destination.pathname; - const mod = loadNativeModule( - specifier, - href, - experimentalModules); + const mod = loadNativeModule(specifier, href); if (mod && mod.canBeRequiredByUsers) { return mod.exports; } @@ -115,11 +110,39 @@ function stripBOM(content) { } const builtinLibs = [ - 'assert', 'async_hooks', 'buffer', 'child_process', 'cluster', 'crypto', - 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'http2', 'https', 'net', - 'os', 'path', 'perf_hooks', 'punycode', 'querystring', 'readline', 'repl', - 'stream', 'string_decoder', 'tls', 'trace_events', 'tty', 'url', 'util', - 'v8', 'vm', 'worker_threads', 'zlib' + 'assert', + 'async_hooks', + 'buffer', + 'child_process', + 'cluster', + 'crypto', + 'dgram', + 'dns', + 'domain', + 'events', + 'fs', + 'http', + 'http2', + 'https', + 'net', + 'os', + 'path', + 'perf_hooks', + 'punycode', + 'querystring', + 'readline', + 'repl', + 'stream', + 'string_decoder', + 'tls', + 'trace_events', + 'tty', + 'url', + 'util', + 'v8', + 'vm', + 'worker_threads', + 'zlib', ]; if (internalBinding('config').experimentalWasi) { diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 0a359a3d8973bc..fc42eb033c923f 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -70,7 +70,6 @@ const { getOptionValue } = require('internal/options'); const enableSourceMaps = getOptionValue('--enable-source-maps'); const preserveSymlinks = getOptionValue('--preserve-symlinks'); const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main'); -const experimentalModules = getOptionValue('--experimental-modules'); const manifest = getOptionValue('--experimental-policy') ? require('internal/process/policy').manifest : null; @@ -395,7 +394,6 @@ function findLongestRegisteredExtension(filename) { } function trySelf(parentPath, request) { - if (!experimentalModules) return false; const { data: pkg, path: basePath } = readPackageScope(parentPath) || {}; if (!pkg || pkg.exports === undefined) return false; if (typeof pkg.name !== 'string') return false; @@ -444,7 +442,7 @@ function applyExports(basePath, expansion) { const mappingKey = `.${expansion}`; let pkgExports = readPackageExports(basePath); - if (pkgExports === undefined || pkgExports === null || !experimentalModules) + if (pkgExports === undefined || pkgExports === null) return false; if (isConditionalDotExportSugar(pkgExports, basePath)) @@ -553,21 +551,22 @@ function resolveExportsTarget(baseUrl, target, subpath, mappingKey) { , 0, -1), mappingKey); } else if (ArrayIsArray(target)) { if (target.length === 0) - throw new ERR_INVALID_PACKAGE_TARGET(StringPrototypeSlice(baseUrl.pathname - , 0, -1), mappingKey, subpath, target); + throw new ERR_PACKAGE_PATH_NOT_EXPORTED( + StringPrototypeSlice(baseUrl.pathname, 0, -1), mappingKey + subpath); + let lastException; for (const targetValue of target) { try { return resolveExportsTarget(baseUrl, targetValue, subpath, mappingKey); } catch (e) { + lastException = e; if (e.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED' && e.code !== 'ERR_INVALID_PACKAGE_TARGET') throw e; } } // Throw last fallback error - resolveExportsTarget(baseUrl, target[target.length - 1], subpath, - mappingKey); - assert(false); + assert(lastException !== undefined); + throw lastException; } else if (typeof target === 'object' && target !== null) { const keys = ObjectKeys(target); if (keys.some(isArrayIndex)) { @@ -596,6 +595,9 @@ function resolveExportsTarget(baseUrl, target, subpath, mappingKey) { } throw new ERR_PACKAGE_PATH_NOT_EXPORTED( StringPrototypeSlice(baseUrl.pathname, 0, -1), mappingKey + subpath); + } else if (target === null) { + throw new ERR_PACKAGE_PATH_NOT_EXPORTED( + StringPrototypeSlice(baseUrl.pathname, 0, -1), mappingKey + subpath); } throw new ERR_INVALID_PACKAGE_TARGET( StringPrototypeSlice(baseUrl.pathname, 0, -1), mappingKey, subpath, target); @@ -845,7 +847,7 @@ Module._load = function(request, parent, isMain) { return cachedModule.exports; } - const mod = loadNativeModule(filename, request, experimentalModules); + const mod = loadNativeModule(filename, request); if (mod && mod.canBeRequiredByUsers) return mod.exports; // Don't call updateChildren(), Module constructor already does. @@ -882,6 +884,13 @@ Module._load = function(request, parent, isMain) { delete Module._cache[filename]; if (parent !== undefined) { delete relativeResolveCache[relResolveCacheIdentifier]; + const children = parent && parent.children; + if (ArrayIsArray(children)) { + const index = children.indexOf(module); + if (index !== -1) { + children.splice(index, 1); + } + } } } } @@ -977,31 +986,29 @@ Module.prototype.load = function(filename) { Module._extensions[extension](this, filename); this.loaded = true; - if (experimentalModules) { - const ESMLoader = asyncESM.ESMLoader; - const url = `${pathToFileURL(filename)}`; - const module = ESMLoader.moduleMap.get(url); - // Create module entry at load time to snapshot exports correctly - const exports = this.exports; - // Called from cjs translator - if (module !== undefined && module.module !== undefined) { - if (module.module.getStatus() >= kInstantiated) - module.module.setExport('default', exports); - } else { - // Preemptively cache - // We use a function to defer promise creation for async hooks. - ESMLoader.moduleMap.set( - url, - // Module job creation will start promises. - // We make it a function to lazily trigger those promises - // for async hooks compatibility. - () => new ModuleJob(ESMLoader, url, () => - new ModuleWrap(url, undefined, ['default'], function() { - this.setExport('default', exports); - }) - , false /* isMain */, false /* inspectBrk */) - ); - } + const ESMLoader = asyncESM.ESMLoader; + const url = `${pathToFileURL(filename)}`; + const module = ESMLoader.moduleMap.get(url); + // Create module entry at load time to snapshot exports correctly + const exports = this.exports; + // Called from cjs translator + if (module !== undefined && module.module !== undefined) { + if (module.module.getStatus() >= kInstantiated) + module.module.setExport('default', exports); + } else { + // Preemptively cache + // We use a function to defer promise creation for async hooks. + ESMLoader.moduleMap.set( + url, + // Module job creation will start promises. + // We make it a function to lazily trigger those promises + // for async hooks compatibility. + () => new ModuleJob(ESMLoader, url, () => + new ModuleWrap(url, undefined, ['default'], function() { + this.setExport('default', exports); + }) + , false /* isMain */, false /* inspectBrk */) + ); } }; @@ -1035,10 +1042,10 @@ function wrapSafe(filename, content, cjsModuleInstance) { filename, lineOffset: 0, displayErrors: true, - importModuleDynamically: experimentalModules ? async (specifier) => { + importModuleDynamically: async (specifier) => { const loader = asyncESM.ESMLoader; return loader.import(specifier, normalizeReferrerURL(filename)); - } : undefined, + }, }); } @@ -1062,20 +1069,18 @@ function wrapSafe(filename, content, cjsModuleInstance) { ] ); } catch (err) { - if (experimentalModules && process.mainModule === cjsModuleInstance) + if (process.mainModule === cjsModuleInstance) enrichCJSError(err); throw err; } - if (experimentalModules) { - const { callbackMap } = internalBinding('module_wrap'); - callbackMap.set(compiled.cacheKey, { - importModuleDynamically: async (specifier) => { - const loader = asyncESM.ESMLoader; - return loader.import(specifier, normalizeReferrerURL(filename)); - } - }); - } + const { callbackMap } = internalBinding('module_wrap'); + callbackMap.set(compiled.cacheKey, { + importModuleDynamically: async (specifier) => { + const loader = asyncESM.ESMLoader; + return loader.import(specifier, normalizeReferrerURL(filename)); + } + }); return compiled.function; } @@ -1285,8 +1290,6 @@ Module.syncBuiltinESMExports = function syncBuiltinESMExports() { Module.Module = Module; // We have to load the esm things after module.exports! -if (experimentalModules) { - ModuleJob = require('internal/modules/esm/module_job'); - asyncESM = require('internal/process/esm_loader'); - ({ ModuleWrap, kInstantiated } = internalBinding('module_wrap')); -} +asyncESM = require('internal/process/esm_loader'); +ModuleJob = require('internal/modules/esm/module_job'); +({ ModuleWrap, kInstantiated } = internalBinding('module_wrap')); diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js index 9815077c3a6dcb..616b2cf52309ea 100644 --- a/lib/internal/modules/esm/get_format.js +++ b/lib/internal/modules/esm/get_format.js @@ -1,5 +1,5 @@ 'use strict'; - +const { StringPrototypeStartsWith } = primordials; const { extname } = require('path'); const { getOptionValue } = require('internal/options'); @@ -7,14 +7,10 @@ const experimentalJsonModules = getOptionValue('--experimental-json-modules'); const experimentalSpeciferResolution = getOptionValue('--experimental-specifier-resolution'); const experimentalWasmModules = getOptionValue('--experimental-wasm-modules'); -const { getPackageType } = internalBinding('module_wrap'); +const { getPackageType } = require('internal/modules/esm/resolve'); const { URL, fileURLToPath } = require('internal/url'); const { ERR_UNKNOWN_FILE_EXTENSION } = require('internal/errors').codes; -// const TYPE_NONE = 0; -// const TYPE_COMMONJS = 1; -const TYPE_MODULE = 2; - const extensionFormatMap = { '__proto__': null, '.cjs': 'commonjs', @@ -37,8 +33,8 @@ if (experimentalWasmModules) if (experimentalJsonModules) extensionFormatMap['.json'] = legacyExtensionFormatMap['.json'] = 'json'; -function defaultGetFormat(url, context, defaultGetFormat) { - if (url.startsWith('nodejs:')) { +function defaultGetFormat(url, context, defaultGetFormatUnused) { + if (StringPrototypeStartsWith(url, 'nodejs:')) { return { format: 'builtin' }; } const parsed = new URL(url); @@ -55,8 +51,7 @@ function defaultGetFormat(url, context, defaultGetFormat) { const ext = extname(parsed.pathname); let format; if (ext === '.js') { - format = getPackageType(parsed.href) === TYPE_MODULE ? - 'module' : 'commonjs'; + format = getPackageType(parsed.href) === 'module' ? 'module' : 'commonjs'; } else { format = extensionFormatMap[ext]; } diff --git a/lib/internal/modules/esm/loader.js b/lib/internal/modules/esm/loader.js index 285f656fa99b11..be5868553fa8df 100644 --- a/lib/internal/modules/esm/loader.js +++ b/lib/internal/modules/esm/loader.js @@ -19,7 +19,10 @@ const { validateString } = require('internal/validators'); const ModuleMap = require('internal/modules/esm/module_map'); const ModuleJob = require('internal/modules/esm/module_job'); -const { defaultResolve } = require('internal/modules/esm/resolve'); +const { + defaultResolve, + DEFAULT_CONDITIONS, +} = require('internal/modules/esm/resolve'); const { defaultGetFormat } = require('internal/modules/esm/get_format'); const { defaultGetSource } = require( 'internal/modules/esm/get_source'); @@ -92,7 +95,7 @@ class Loader { validateString(parentURL, 'parentURL'); const resolveResponse = await this._resolve( - specifier, { parentURL }, defaultResolve); + specifier, { parentURL, conditions: DEFAULT_CONDITIONS }, defaultResolve); if (typeof resolveResponse !== 'object') { throw new ERR_INVALID_RETURN_VALUE( 'object', 'loader resolve', resolveResponse); diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js index ec2e681e621d0d..c66e0554ad2746 100644 --- a/lib/internal/modules/esm/resolve.js +++ b/lib/internal/modules/esm/resolve.js @@ -1,26 +1,710 @@ 'use strict'; const { + ArrayIsArray, + ArrayPrototypeJoin, + ArrayPrototypeShift, + JSONParse, + JSONStringify, + ObjectFreeze, + ObjectGetOwnPropertyNames, + ObjectPrototypeHasOwnProperty, + RegExp, SafeMap, + SafeSet, + StringPrototypeEndsWith, + StringPrototypeIncludes, + StringPrototypeIndexOf, + StringPrototypeReplace, + StringPrototypeSlice, + StringPrototypeSplit, + StringPrototypeStartsWith, + StringPrototypeSubstr, } = primordials; - +const assert = require('internal/assert'); const internalFS = require('internal/fs/utils'); const { NativeModule } = require('internal/bootstrap/loaders'); -const { realpathSync } = require('fs'); +const { + closeSync, + fstatSync, + openSync, + readFileSync, + realpathSync, + statSync, + Stats, +} = require('fs'); const { getOptionValue } = require('internal/options'); -const { sep } = require('path'); - +const { sep, relative } = require('path'); +const { Module: CJSModule } = require('internal/modules/cjs/loader'); const preserveSymlinks = getOptionValue('--preserve-symlinks'); const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main'); const typeFlag = getOptionValue('--input-type'); -const { resolve: moduleWrapResolve } = internalBinding('module_wrap'); const { URL, pathToFileURL, fileURLToPath } = require('internal/url'); -const { ERR_INPUT_TYPE_NOT_ALLOWED, - ERR_UNSUPPORTED_ESM_URL_SCHEME } = require('internal/errors').codes; +const { + ERR_INPUT_TYPE_NOT_ALLOWED, + ERR_INVALID_ARG_VALUE, + ERR_INVALID_MODULE_SPECIFIER, + ERR_INVALID_PACKAGE_CONFIG, + ERR_INVALID_PACKAGE_TARGET, + ERR_MODULE_NOT_FOUND, + ERR_PACKAGE_PATH_NOT_EXPORTED, + ERR_UNSUPPORTED_ESM_URL_SCHEME, +} = require('internal/errors').codes; + +const DEFAULT_CONDITIONS = ObjectFreeze(['node', 'import']); +const DEFAULT_CONDITIONS_SET = new SafeSet(DEFAULT_CONDITIONS); + +function getConditionsSet(conditions) { + if (conditions !== undefined && conditions !== DEFAULT_CONDITIONS) { + if (!ArrayIsArray(conditions)) { + throw new ERR_INVALID_ARG_VALUE('conditions', conditions, + 'expected an array'); + } + return new SafeSet(conditions); + } + return DEFAULT_CONDITIONS_SET; +} const realpathCache = new SafeMap(); +const packageJSONCache = new SafeMap(); /* string -> PackageConfig */ + +function tryStatSync(path) { + try { + return statSync(path); + } catch { + return new Stats(); + } +} + +function readIfFile(path) { + let fd; + try { + fd = openSync(path, 'r'); + } catch { + return undefined; + } + try { + if (!fstatSync(fd).isFile()) return undefined; + return readFileSync(fd, 'utf8'); + } finally { + closeSync(fd); + } +} + +function getPackageConfig(path, base) { + const existing = packageJSONCache.get(path); + if (existing !== undefined) { + if (!existing.isValid) { + throw new ERR_INVALID_PACKAGE_CONFIG(path, fileURLToPath(base), false); + } + return existing; + } + + const source = readIfFile(path); + if (source === undefined) { + const packageConfig = { + exists: false, + main: undefined, + name: undefined, + isValid: true, + type: 'none', + exports: undefined + }; + packageJSONCache.set(path, packageConfig); + return packageConfig; + } + + let packageJSON; + try { + packageJSON = JSONParse(source); + } catch { + const packageConfig = { + exists: true, + main: undefined, + name: undefined, + isValid: false, + type: 'none', + exports: undefined + }; + packageJSONCache.set(path, packageConfig); + return packageConfig; + } + + let { main, name, type } = packageJSON; + const { exports } = packageJSON; + if (typeof main !== 'string') main = undefined; + if (typeof name !== 'string') name = undefined; + // Ignore unknown types for forwards compatibility + if (type !== 'module' && type !== 'commonjs') type = 'none'; + + const packageConfig = { + exists: true, + main, + name, + isValid: true, + type, + exports + }; + packageJSONCache.set(path, packageConfig); + return packageConfig; +} + +function getPackageScopeConfig(resolved, base) { + let packageJSONUrl = new URL('./package.json', resolved); + while (true) { + const packageJSONPath = packageJSONUrl.pathname; + if (StringPrototypeEndsWith(packageJSONPath, 'node_modules/package.json')) + break; + const packageConfig = getPackageConfig(fileURLToPath(packageJSONUrl), base); + if (packageConfig.exists) return packageConfig; + + const lastPackageJSONUrl = packageJSONUrl; + packageJSONUrl = new URL('../package.json', packageJSONUrl); + + // Terminates at root where ../package.json equals ../../package.json + // (can't just check "/package.json" for Windows support). + if (packageJSONUrl.pathname === lastPackageJSONUrl.pathname) break; + } + const packageConfig = { + exists: false, + main: undefined, + name: undefined, + isValid: true, + type: 'none', + exports: undefined + }; + packageJSONCache.set(fileURLToPath(packageJSONUrl), packageConfig); + return packageConfig; +} + +/* + * Legacy CommonJS main resolution: + * 1. let M = pkg_url + (json main field) + * 2. TRY(M, M.js, M.json, M.node) + * 3. TRY(M/index.js, M/index.json, M/index.node) + * 4. TRY(pkg_url/index.js, pkg_url/index.json, pkg_url/index.node) + * 5. NOT_FOUND + */ +function fileExists(url) { + return tryStatSync(fileURLToPath(url)).isFile(); +} + +function legacyMainResolve(packageJSONUrl, packageConfig) { + let guess; + if (packageConfig.main !== undefined) { + // Note: fs check redundances will be handled by Descriptor cache here. + if (fileExists(guess = new URL(`./${packageConfig.main}`, + packageJSONUrl))) { + return guess; + } + if (fileExists(guess = new URL(`./${packageConfig.main}.js`, + packageJSONUrl))) { + return guess; + } + if (fileExists(guess = new URL(`./${packageConfig.main}.json`, + packageJSONUrl))) { + return guess; + } + if (fileExists(guess = new URL(`./${packageConfig.main}.node`, + packageJSONUrl))) { + return guess; + } + if (fileExists(guess = new URL(`./${packageConfig.main}/index.js`, + packageJSONUrl))) { + return guess; + } + if (fileExists(guess = new URL(`./${packageConfig.main}/index.json`, + packageJSONUrl))) { + return guess; + } + if (fileExists(guess = new URL(`./${packageConfig.main}/index.node`, + packageJSONUrl))) { + return guess; + } + // Fallthrough. + } + if (fileExists(guess = new URL('./index.js', packageJSONUrl))) { + return guess; + } + // So fs. + if (fileExists(guess = new URL('./index.json', packageJSONUrl))) { + return guess; + } + if (fileExists(guess = new URL('./index.node', packageJSONUrl))) { + return guess; + } + // Not found. + return undefined; +} + +function resolveExtensionsWithTryExactName(search) { + if (fileExists(search)) return search; + return resolveExtensions(search); +} + +const extensions = ['.js', '.json', '.node', '.mjs']; +function resolveExtensions(search) { + for (let i = 0; i < extensions.length; i++) { + const extension = extensions[i]; + const guess = new URL(`${search.pathname}${extension}`, search); + if (fileExists(guess)) return guess; + } + return undefined; +} + +function resolveIndex(search) { + return resolveExtensions(new URL('index', search)); +} + +function finalizeResolution(resolved, base) { + if (getOptionValue('--experimental-specifier-resolution') === 'node') { + let file = resolveExtensionsWithTryExactName(resolved); + if (file !== undefined) return file; + if (!StringPrototypeEndsWith(resolved.pathname, '/')) { + file = resolveIndex(new URL(`${resolved.pathname}/`, base)); + } else { + file = resolveIndex(resolved); + } + if (file !== undefined) return file; + throw new ERR_MODULE_NOT_FOUND( + resolved.pathname, fileURLToPath(base), 'module'); + } + + if (StringPrototypeEndsWith(resolved.pathname, '/')) return resolved; + const path = fileURLToPath(resolved); + + if (!tryStatSync(path).isFile()) { + throw new ERR_MODULE_NOT_FOUND( + path || resolved.pathname, fileURLToPath(base), 'module'); + } + + return resolved; +} + +function throwExportsNotFound(subpath, packageJSONUrl, base) { + throw new ERR_PACKAGE_PATH_NOT_EXPORTED( + fileURLToPath(packageJSONUrl), subpath, fileURLToPath(base)); +} + +function throwSubpathInvalid(subpath, packageJSONUrl, base) { + throw new ERR_INVALID_MODULE_SPECIFIER( + fileURLToPath(packageJSONUrl), subpath, fileURLToPath(base)); +} + +function throwExportsInvalid( + subpath, target, packageJSONUrl, base) { + if (typeof target === 'object' && target !== null) { + target = JSONStringify(target, null, ''); + } else if (ArrayIsArray(target)) { + target = `[${target}]`; + } else { + target = `${target}`; + } + throw new ERR_INVALID_PACKAGE_TARGET( + fileURLToPath(packageJSONUrl), null, subpath, target, fileURLToPath(base)); +} + +function resolveExportsTargetString( + target, subpath, match, packageJSONUrl, base) { + if (target[0] !== '.' || target[1] !== '/' || + (subpath !== '' && target[target.length - 1] !== '/')) { + throwExportsInvalid(match, target, packageJSONUrl, base); + } + + const resolved = new URL(target, packageJSONUrl); + const resolvedPath = resolved.pathname; + const packagePath = new URL('.', packageJSONUrl).pathname; + + if (!StringPrototypeStartsWith(resolvedPath, packagePath) || + StringPrototypeIncludes( + resolvedPath, '/node_modules/', packagePath.length - 1)) { + throwExportsInvalid(match, target, packageJSONUrl, base); + } + + if (subpath === '') return resolved; + const subpathResolved = new URL(subpath, resolved); + const subpathResolvedPath = subpathResolved.pathname; + if (!StringPrototypeStartsWith(subpathResolvedPath, resolvedPath) || + StringPrototypeIncludes(subpathResolvedPath, + '/node_modules/', packagePath.length - 1)) { + throwSubpathInvalid(match + subpath, packageJSONUrl, base); + } + return subpathResolved; +} -function defaultResolve(specifier, { parentURL } = {}, defaultResolve) { +/** + * @param {string} key + * @returns {boolean} + */ +function isArrayIndex(key) { + const keyNum = +key; + if (`${keyNum}` !== key) return false; + return keyNum >= 0 && keyNum < 0xFFFF_FFFF; +} + +function resolveExportsTarget( + packageJSONUrl, target, subpath, packageSubpath, base, conditions) { + if (typeof target === 'string') { + const resolved = resolveExportsTargetString( + target, subpath, packageSubpath, packageJSONUrl, base); + return finalizeResolution(resolved, base); + } else if (ArrayIsArray(target)) { + if (target.length === 0) + throwExportsNotFound(packageSubpath, packageJSONUrl, base); + + let lastException; + for (let i = 0; i < target.length; i++) { + const targetItem = target[i]; + let resolved; + try { + resolved = resolveExportsTarget( + packageJSONUrl, targetItem, subpath, packageSubpath, base, + conditions); + } catch (e) { + lastException = e; + if (e.code === 'ERR_PACKAGE_PATH_NOT_EXPORTED' || + e.code === 'ERR_INVALID_PACKAGE_TARGET') { + continue; + } + throw e; + } + + return finalizeResolution(resolved, base); + } + assert(lastException !== undefined); + throw lastException; + } else if (typeof target === 'object' && target !== null) { + const keys = ObjectGetOwnPropertyNames(target); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if (isArrayIndex(key)) { + throw new ERR_INVALID_PACKAGE_CONFIG( + fileURLToPath(packageJSONUrl), + '"exports" cannot contain numeric property keys'); + } + } + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if (key === 'default' || conditions.has(key)) { + const conditionalTarget = target[key]; + try { + return resolveExportsTarget( + packageJSONUrl, conditionalTarget, subpath, packageSubpath, base, + conditions); + } catch (e) { + if (e.code === 'ERR_PACKAGE_PATH_NOT_EXPORTED') continue; + throw e; + } + } + } + throwExportsNotFound(packageSubpath, packageJSONUrl, base); + } else if (target === null) { + throwExportsNotFound(packageSubpath, packageJSONUrl, base); + } + throwExportsInvalid(packageSubpath, target, packageJSONUrl, base); +} + +function isConditionalExportsMainSugar(exports, packageJSONUrl, base) { + if (typeof exports === 'string' || ArrayIsArray(exports)) return true; + if (typeof exports !== 'object' || exports === null) return false; + + const keys = ObjectGetOwnPropertyNames(exports); + let isConditionalSugar = false; + let i = 0; + for (let j = 0; j < keys.length; j++) { + const key = keys[j]; + const curIsConditionalSugar = key === '' || key[0] !== '.'; + if (i++ === 0) { + isConditionalSugar = curIsConditionalSugar; + } else if (isConditionalSugar !== curIsConditionalSugar) { + throw new ERR_INVALID_PACKAGE_CONFIG( + fileURLToPath(packageJSONUrl), + '"exports" cannot contain some keys starting with \'.\' and some not.' + + ' The exports object must either be an object of package subpath keys' + + ' or an object of main entry condition name keys only.'); + } + } + return isConditionalSugar; +} + + +function packageMainResolve(packageJSONUrl, packageConfig, base, conditions) { + if (packageConfig.exists) { + const exports = packageConfig.exports; + if (exports !== undefined) { + if (isConditionalExportsMainSugar(exports, packageJSONUrl, base)) { + return resolveExportsTarget(packageJSONUrl, exports, '', '', base, + conditions); + } else if (typeof exports === 'object' && exports !== null) { + const target = exports['.']; + if (target !== undefined) + return resolveExportsTarget(packageJSONUrl, target, '', '', base, + conditions); + } + + throw new ERR_PACKAGE_PATH_NOT_EXPORTED(packageJSONUrl, '.'); + } + if (getOptionValue('--experimental-specifier-resolution') === 'node') { + if (packageConfig.main !== undefined) { + return finalizeResolution( + new URL(packageConfig.main, packageJSONUrl), base); + } else { + return finalizeResolution( + new URL('index', packageJSONUrl), base); + } + } + return legacyMainResolve(packageJSONUrl, packageConfig); + } + + throw new ERR_MODULE_NOT_FOUND( + fileURLToPath(new URL('.', packageJSONUrl)), fileURLToPath(base)); +} + +/** + * @param {URL} packageJSONUrl + * @param {string} packageSubpath + * @param {object} packageConfig + * @param {string} base + * @param {Set} conditions + * @returns {URL} + */ +function packageExportsResolve( + packageJSONUrl, packageSubpath, packageConfig, base, conditions) { + const exports = packageConfig.exports; + if (exports === undefined || + isConditionalExportsMainSugar(exports, packageJSONUrl, base)) { + throwExportsNotFound(packageSubpath, packageJSONUrl, base); + } + + + if (ObjectPrototypeHasOwnProperty(exports, packageSubpath)) { + const target = exports[packageSubpath]; + const resolved = resolveExportsTarget( + packageJSONUrl, target, '', packageSubpath, base, conditions); + return finalizeResolution(resolved, base); + } + + let bestMatch = ''; + const keys = ObjectGetOwnPropertyNames(exports); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if (key[key.length - 1] !== '/') continue; + if (StringPrototypeStartsWith(packageSubpath, key) && + key.length > bestMatch.length) { + bestMatch = key; + } + } + + if (bestMatch) { + const target = exports[bestMatch]; + const subpath = StringPrototypeSubstr(packageSubpath, bestMatch.length); + const resolved = resolveExportsTarget( + packageJSONUrl, target, subpath, packageSubpath, base, conditions); + return finalizeResolution(resolved, base); + } + + throwExportsNotFound(packageSubpath, packageJSONUrl, base); +} + +function getPackageType(url) { + const packageConfig = getPackageScopeConfig(url, url); + return packageConfig.type; +} + +/** + * @param {string} specifier + * @param {URL} base + * @param {Set} conditions + * @returns {URL} + */ +function packageResolve(specifier, base, conditions) { + let separatorIndex = StringPrototypeIndexOf(specifier, '/'); + let validPackageName = true; + let isScoped = false; + if (specifier[0] === '@') { + isScoped = true; + if (separatorIndex === -1 || specifier.length === 0) { + validPackageName = false; + } else { + separatorIndex = StringPrototypeIndexOf( + specifier, '/', separatorIndex + 1); + } + } + + const packageName = separatorIndex === -1 ? + specifier : StringPrototypeSlice(specifier, 0, separatorIndex); + + // Package name cannot have leading . and cannot have percent-encoding or + // separators. + for (let i = 0; i < packageName.length; i++) { + if (packageName[i] === '%' || packageName[i] === '\\') { + validPackageName = false; + break; + } + } + + if (!validPackageName) { + throw new ERR_INVALID_MODULE_SPECIFIER( + specifier, undefined, fileURLToPath(base)); + } + + const packageSubpath = separatorIndex === -1 ? + '' : '.' + StringPrototypeSlice(specifier, separatorIndex); + + // ResolveSelf + const packageConfig = getPackageScopeConfig(base, base); + if (packageConfig.exists) { + // TODO(jkrems): Find a way to forward the pair/iterator already generated + // while executing GetPackageScopeConfig + let packageJSONUrl; + for (const [ filename, packageConfigCandidate ] of packageJSONCache) { + if (packageConfig === packageConfigCandidate) { + packageJSONUrl = pathToFileURL(filename); + break; + } + } + if (packageJSONUrl !== undefined && + packageConfig.name === packageName && + packageConfig.exports !== undefined) { + if (packageSubpath === './') { + return new URL('./', packageJSONUrl); + } else if (packageSubpath === '') { + return packageMainResolve(packageJSONUrl, packageConfig, base, + conditions); + } else { + return packageExportsResolve( + packageJSONUrl, packageSubpath, packageConfig, base, conditions); + } + } + } + + let packageJSONUrl = + new URL('./node_modules/' + packageName + '/package.json', base); + let packageJSONPath = fileURLToPath(packageJSONUrl); + let lastPath; + do { + const stat = tryStatSync( + StringPrototypeSlice(packageJSONPath, 0, packageJSONPath.length - 13)); + if (!stat.isDirectory()) { + lastPath = packageJSONPath; + packageJSONUrl = new URL((isScoped ? + '../../../../node_modules/' : '../../../node_modules/') + + packageName + '/package.json', packageJSONUrl); + packageJSONPath = fileURLToPath(packageJSONUrl); + continue; + } + + // Package match. + const packageConfig = getPackageConfig(packageJSONPath, base); + if (packageSubpath === './') { + return new URL('./', packageJSONUrl); + } else if (packageSubpath === '') { + return packageMainResolve(packageJSONUrl, packageConfig, base, + conditions); + } else if (packageConfig.exports !== undefined) { + return packageExportsResolve( + packageJSONUrl, packageSubpath, packageConfig, base, conditions); + } else { + return finalizeResolution( + new URL(packageSubpath, packageJSONUrl), base); + } + // Cross-platform root check. + } while (packageJSONPath.length !== lastPath.length); + + // eslint can't handle the above code. + // eslint-disable-next-line no-unreachable + throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base)); +} + +function isBareSpecifier(specifier) { + return specifier[0] && specifier[0] !== '/' && specifier[0] !== '.'; +} + +function isRelativeSpecifier(specifier) { + if (specifier[0] === '.') { + if (specifier.length === 1 || specifier[1] === '/') return true; + if (specifier[1] === '.') { + if (specifier.length === 2 || specifier[2] === '/') return true; + } + } + return false; +} + +function shouldBeTreatedAsRelativeOrAbsolutePath(specifier) { + if (specifier === '') return false; + if (specifier[0] === '/') return true; + return isRelativeSpecifier(specifier); +} + +/** + * @param {string} specifier + * @param {URL} base + * @param {Set} conditions + * @returns {URL} + */ +function moduleResolve(specifier, base, conditions) { + // Order swapped from spec for minor perf gain. + // Ok since relative URLs cannot parse as URLs. + let resolved; + if (shouldBeTreatedAsRelativeOrAbsolutePath(specifier)) { + resolved = new URL(specifier, base); + } else { + try { + resolved = new URL(specifier); + } catch { + return packageResolve(specifier, base, conditions); + } + } + return finalizeResolution(resolved, base); +} + +/** + * Try to resolve an import as a CommonJS module + * @param {string} specifier + * @param {string} parentURL + * @returns {boolean|string} + */ +function resolveAsCommonJS(specifier, parentURL) { + try { + const parent = fileURLToPath(parentURL); + const tmpModule = new CJSModule(parent, null); + tmpModule.paths = CJSModule._nodeModulePaths(parent); + + let found = CJSModule._resolveFilename(specifier, tmpModule, false); + + // If it is a relative specifier return the relative path + // to the parent + if (isRelativeSpecifier(specifier)) { + found = relative(parent, found); + // Add '.separator if the path does not start with '..separator' + // This should be a safe assumption because when loading + // esm modules there should be always a file specified so + // there should not be a specifier like '..' or '.' + if (!StringPrototypeStartsWith(found, `..${sep}`)) { + found = `.${sep}${found}`; + } + } else if (isBareSpecifier(specifier)) { + // If it is a bare specifier return the relative path within the + // module + const pkg = StringPrototypeSplit(specifier, '/')[0]; + const index = StringPrototypeIndexOf(found, pkg); + if (index !== -1) { + found = StringPrototypeSlice(found, index); + } + } + // Normalize the path separator to give a valid suggestion + // on Windows + if (process.platform === 'win32') { + found = StringPrototypeReplace(found, new RegExp(`\\${sep}`, 'g'), '/'); + } + return found; + } catch { + return false; + } +} + +function defaultResolve(specifier, context = {}, defaultResolveUnused) { + let { parentURL, conditions } = context; let parsed; try { parsed = new URL(specifier); @@ -39,7 +723,7 @@ function defaultResolve(specifier, { parentURL } = {}, defaultResolve) { url: 'nodejs:' + specifier }; } - if (parentURL && parentURL.startsWith('data:')) { + if (parentURL && StringPrototypeStartsWith(parentURL, 'data:')) { // This is gonna blow up, we want the error new URL(specifier, parentURL); } @@ -58,7 +742,28 @@ function defaultResolve(specifier, { parentURL } = {}, defaultResolve) { throw new ERR_INPUT_TYPE_NOT_ALLOWED(); } - let url = moduleWrapResolve(specifier, parentURL); + conditions = getConditionsSet(conditions); + let url; + try { + url = moduleResolve(specifier, parentURL, conditions); + } catch (error) { + // Try to give the user a hint of what would have been the + // resolved CommonJS module + if (error.code === 'ERR_MODULE_NOT_FOUND') { + const found = resolveAsCommonJS(specifier, parentURL); + if (found) { + // Modify the stack and message string to include the hint + const lines = StringPrototypeSplit(error.stack, '\n'); + const hint = `Did you mean to import ${found}?`; + error.stack = + ArrayPrototypeShift(lines) + '\n' + + hint + '\n' + + ArrayPrototypeJoin(lines, '\n'); + error.message += `\n${hint}`; + } + } + throw error; + } if (isMain ? !preserveSymlinksMain : !preserveSymlinks) { const urlPath = fileURLToPath(url); @@ -73,4 +778,9 @@ function defaultResolve(specifier, { parentURL } = {}, defaultResolve) { return { url: `${url}` }; } -exports.defaultResolve = defaultResolve; + +module.exports = { + DEFAULT_CONDITIONS, + defaultResolve, + getPackageType +}; diff --git a/lib/internal/modules/run_main.js b/lib/internal/modules/run_main.js index 48d0e8eee2bc6f..d18a1a295714b8 100644 --- a/lib/internal/modules/run_main.js +++ b/lib/internal/modules/run_main.js @@ -21,9 +21,6 @@ function resolveMainPath(main) { } function shouldUseESMLoader(mainPath) { - const experimentalModules = getOptionValue('--experimental-modules'); - if (!experimentalModules) - return false; const userLoader = getOptionValue('--experimental-loader'); if (userLoader) return true; diff --git a/lib/internal/net.js b/lib/internal/net.js index 73acaa5efee654..17b754999bbf10 100644 --- a/lib/internal/net.js +++ b/lib/internal/net.js @@ -41,15 +41,6 @@ function isIP(s) { return 0; } -// Check that the port number is not NaN when coerced to a number, -// is an integer and that it falls within the legal range of port numbers. -function isLegalPort(port) { - if ((typeof port !== 'number' && typeof port !== 'string') || - (typeof port === 'string' && port.trim().length === 0)) - return false; - return +port === (+port >>> 0) && port <= 0xFFFF; -} - function makeSyncWrite(fd) { return function(chunk, enc, cb) { if (enc !== 'buffer') @@ -74,7 +65,6 @@ module.exports = { isIP, isIPv4, isIPv6, - isLegalPort, makeSyncWrite, normalizedArgsSymbol: Symbol('normalizedArgs') }; diff --git a/lib/internal/options.js b/lib/internal/options.js index e494787b96c088..03586f9dae6d76 100644 --- a/lib/internal/options.js +++ b/lib/internal/options.js @@ -3,6 +3,8 @@ const { getOptions } = internalBinding('options'); const { options, aliases } = getOptions(); +let warnOnAllowUnauthorized = true; + function getOptionValue(option) { const result = options.get(option); if (!result) { @@ -11,8 +13,23 @@ function getOptionValue(option) { return result.value; } +function getAllowUnauthorized() { + const allowUnauthorized = process.env.NODE_TLS_REJECT_UNAUTHORIZED === '0'; + + if (allowUnauthorized && warnOnAllowUnauthorized) { + warnOnAllowUnauthorized = false; + process.emitWarning( + 'Setting the NODE_TLS_REJECT_UNAUTHORIZED ' + + 'environment variable to \'0\' makes TLS connections ' + + 'and HTTPS requests insecure by disabling ' + + 'certificate verification.'); + } + return allowUnauthorized; +} + module.exports = { options, aliases, - getOptionValue + getOptionValue, + getAllowUnauthorized, }; diff --git a/lib/internal/process/esm_loader.js b/lib/internal/process/esm_loader.js index ce6a7e756263c1..cca1e3e07956a1 100644 --- a/lib/internal/process/esm_loader.js +++ b/lib/internal/process/esm_loader.js @@ -24,6 +24,12 @@ exports.initializeImportMetaObject = function(wrap, meta) { exports.importModuleDynamicallyCallback = async function(wrap, specifier) { assert(calledInitialize === true || !userLoader); + if (!calledInitialize) { + process.emitWarning( + 'The ESM module loader is experimental.', + 'ExperimentalWarning', undefined); + calledInitialize = true; + } const { callbackMap } = internalBinding('module_wrap'); if (callbackMap.has(wrap)) { const { importModuleDynamically } = callbackMap.get(wrap); @@ -42,6 +48,9 @@ let calledInitialize = false; exports.initializeLoader = initializeLoader; async function initializeLoader() { assert(calledInitialize === false); + process.emitWarning( + 'The ESM module loader is experimental.', + 'ExperimentalWarning', undefined); calledInitialize = true; if (!userLoader) return; diff --git a/lib/internal/process/execution.js b/lib/internal/process/execution.js index d9567e643d7c85..a6d6d2325a7f79 100644 --- a/lib/internal/process/execution.js +++ b/lib/internal/process/execution.js @@ -159,6 +159,7 @@ function createOnGlobalUncaughtException() { } const type = fromPromise ? 'unhandledRejection' : 'uncaughtException'; + process.emit('uncaughtExceptionMonitor', er, type); if (exceptionHandlerState.captureFn !== null) { exceptionHandlerState.captureFn(er); } else if (!process.emit('uncaughtException', er, type)) { diff --git a/lib/internal/process/per_thread.js b/lib/internal/process/per_thread.js index 5cb55d74939302..d219cd7298fc15 100644 --- a/lib/internal/process/per_thread.js +++ b/lib/internal/process/per_thread.js @@ -146,14 +146,15 @@ function wrapProcessMethods(binding) { return hrBigintValues[0]; } - const memValues = new Float64Array(4); + const memValues = new Float64Array(5); function memoryUsage() { _memoryUsage(memValues); return { rss: memValues[0], heapTotal: memValues[1], heapUsed: memValues[2], - external: memValues[3] + external: memValues[3], + arrayBuffers: memValues[4] }; } diff --git a/lib/internal/process/report.js b/lib/internal/process/report.js index 407cc12cb04f76..72a8b0c1ebe337 100644 --- a/lib/internal/process/report.js +++ b/lib/internal/process/report.js @@ -3,7 +3,11 @@ const { ERR_INVALID_ARG_TYPE, ERR_SYNTHETIC } = require('internal/errors').codes; -const { validateSignalName, validateString } = require('internal/validators'); +const { + validateSignalName, + validateString, + validateBoolean, +} = require('internal/validators'); const nr = internalBinding('report'); const { JSONParse, @@ -45,6 +49,13 @@ const report = { validateString(name, 'filename'); nr.setFilename(name); }, + get compact() { + return nr.getCompact(); + }, + set compact(b) { + validateBoolean(b, 'compact'); + nr.setCompact(b); + }, get signal() { return nr.getSignal(); }, diff --git a/lib/internal/process/task_queues.js b/lib/internal/process/task_queues.js index 8b2d2d808af854..c07942587ca9c2 100644 --- a/lib/internal/process/task_queues.js +++ b/lib/internal/process/task_queues.js @@ -71,7 +71,7 @@ function processTicksAndRejections() { do { while (tock = queue.shift()) { const asyncId = tock[async_id_symbol]; - emitBefore(asyncId, tock[trigger_async_id_symbol]); + emitBefore(asyncId, tock[trigger_async_id_symbol], tock); try { const callback = tock.callback; diff --git a/lib/internal/readline/utils.js b/lib/internal/readline/utils.js index 510acf221831a0..0b9fe8cde4f5ce 100644 --- a/lib/internal/readline/utils.js +++ b/lib/internal/readline/utils.js @@ -1,23 +1,12 @@ 'use strict'; const { - Boolean, - NumberIsInteger, + Symbol, } = primordials; -// Regex used for ansi escape code splitting -// Adopted from https://github.com/chalk/ansi-regex/blob/master/index.js -// License: MIT, authors: @sindresorhus, Qix-, and arjunmehta -// Matches all ansi escape code sequences in a string -/* eslint-disable no-control-regex */ -const ansi = - /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; -/* eslint-enable no-control-regex */ const kUTF16SurrogateThreshold = 0x10000; // 2 ** 16 const kEscape = '\x1b'; - -let getStringWidth; -let isFullWidthCodePoint; +const kSubstringSearch = Symbol('kSubstringSearch'); function CSI(strings, ...args) { let ret = `${kEscape}[`; @@ -30,126 +19,34 @@ function CSI(strings, ...args) { } CSI.kEscape = kEscape; -CSI.kClearToBeginning = CSI`1K`; -CSI.kClearToEnd = CSI`0K`; +CSI.kClearToLineBeginning = CSI`1K`; +CSI.kClearToLineEnd = CSI`0K`; CSI.kClearLine = CSI`2K`; CSI.kClearScreenDown = CSI`0J`; -if (internalBinding('config').hasIntl) { - const icu = internalBinding('icu'); - getStringWidth = function getStringWidth(str, options) { - options = options || {}; - if (NumberIsInteger(str)) { - // Provide information about the character with code point 'str'. - return icu.getStringWidth( - str, - Boolean(options.ambiguousAsFullWidth), - false - ); - } - str = stripVTControlCharacters(String(str)); - let width = 0; - for (let i = 0; i < str.length; i++) { - // Try to avoid calling into C++ by first handling the ASCII portion of - // the string. If it is fully ASCII, we skip the C++ part. - const code = str.charCodeAt(i); - if (code < 127) { - width += code >= 32; - continue; - } - width += icu.getStringWidth( - str.slice(i), - Boolean(options.ambiguousAsFullWidth), - Boolean(options.expandEmojiSequence) - ); - break; - } - return width; - }; - isFullWidthCodePoint = - function isFullWidthCodePoint(code, options) { - if (typeof code !== 'number') - return false; - return icu.getStringWidth(code, options) === 2; - }; -} else { - /** - * Returns the number of columns required to display the given string. - */ - getStringWidth = function getStringWidth(str) { - if (NumberIsInteger(str)) - return isFullWidthCodePoint(str) ? 2 : 1; - - let width = 0; - - str = stripVTControlCharacters(String(str)); - - for (let i = 0; i < str.length; i++) { - const code = str.codePointAt(i); - - if (code >= kUTF16SurrogateThreshold) { // Surrogates. - i++; - } - - if (isFullWidthCodePoint(code)) { - width += 2; - } else { - width++; - } - } - - return width; - }; - - /** - * Returns true if the character represented by a given - * Unicode code point is full-width. Otherwise returns false. - */ - isFullWidthCodePoint = function isFullWidthCodePoint(code) { - // Code points are derived from: - // http://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt - return NumberIsInteger(code) && code >= 0x1100 && ( - code <= 0x115f || // Hangul Jamo - code === 0x2329 || // LEFT-POINTING ANGLE BRACKET - code === 0x232a || // RIGHT-POINTING ANGLE BRACKET - // CJK Radicals Supplement .. Enclosed CJK Letters and Months - (code >= 0x2e80 && code <= 0x3247 && code !== 0x303f) || - // Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A - (code >= 0x3250 && code <= 0x4dbf) || - // CJK Unified Ideographs .. Yi Radicals - (code >= 0x4e00 && code <= 0xa4c6) || - // Hangul Jamo Extended-A - (code >= 0xa960 && code <= 0xa97c) || - // Hangul Syllables - (code >= 0xac00 && code <= 0xd7a3) || - // CJK Compatibility Ideographs - (code >= 0xf900 && code <= 0xfaff) || - // Vertical Forms - (code >= 0xfe10 && code <= 0xfe19) || - // CJK Compatibility Forms .. Small Form Variants - (code >= 0xfe30 && code <= 0xfe6b) || - // Halfwidth and Fullwidth Forms - (code >= 0xff01 && code <= 0xff60) || - (code >= 0xffe0 && code <= 0xffe6) || - // Kana Supplement - (code >= 0x1b000 && code <= 0x1b001) || - // Enclosed Ideographic Supplement - (code >= 0x1f200 && code <= 0x1f251) || - // CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane - (code >= 0x20000 && code <= 0x3fffd) - ); - }; +// TODO(BridgeAR): Treat combined characters as single character, i.e, +// 'a\u0301' and '\u0301a' (both have the same visual output). +// Check Canonical_Combining_Class in +// http://userguide.icu-project.org/strings/properties +function charLengthLeft(str, i) { + if (i <= 0) + return 0; + if ((i > 1 && str.codePointAt(i - 2) >= kUTF16SurrogateThreshold) || + str.codePointAt(i - 1) >= kUTF16SurrogateThreshold) { + return 2; + } + return 1; } -/** - * Tries to remove all VT control characters. Use to estimate displayed - * string width. May be buggy due to not running a real state machine - */ -function stripVTControlCharacters(str) { - return str.replace(ansi, ''); +function charLengthAt(str, i) { + if (str.length <= i) { + // Pretend to move to the right. This is necessary to autocomplete while + // moving to the right. + return 1; + } + return str.codePointAt(i) >= kUTF16SurrogateThreshold ? 2 : 1; } - /* Some patterns seen in terminal key escape codes, derived from combos seen at http://www.midnight-commander.org/browser/lib/tty/key.c @@ -436,7 +333,7 @@ function* emitKeys(stream) { if (s.length !== 0 && (key.name !== undefined || escaped)) { /* Named character or sequence */ stream.emit('keypress', escaped ? undefined : s, key); - } else if (s.length === 1) { + } else if (charLengthAt(s, 0) === s.length) { /* Single unnamed character, e.g. "." */ stream.emit('keypress', s, key); } @@ -444,11 +341,27 @@ function* emitKeys(stream) { } } +// This runs in O(n log n). +function commonPrefix(strings) { + if (strings.length === 1) { + return strings[0]; + } + const sorted = strings.slice().sort(); + const min = sorted[0]; + const max = sorted[sorted.length - 1]; + for (let i = 0; i < min.length; i++) { + if (min[i] !== max[i]) { + return min.slice(0, i); + } + } + return min; +} + module.exports = { + charLengthAt, + charLengthLeft, + commonPrefix, emitKeys, - getStringWidth, - isFullWidthCodePoint, - kUTF16SurrogateThreshold, - stripVTControlCharacters, + kSubstringSearch, CSI }; diff --git a/lib/internal/repl/utils.js b/lib/internal/repl/utils.js index 6c011e8533f8c3..476760a08d5934 100644 --- a/lib/internal/repl/utils.js +++ b/lib/internal/repl/utils.js @@ -1,10 +1,13 @@ 'use strict'; const { + MathMin, + Set, Symbol, } = primordials; -const acorn = require('internal/deps/acorn/acorn/dist/acorn'); +const { tokTypes: tt, Parser: AcornParser } = + require('internal/deps/acorn/acorn/dist/acorn'); const privateMethods = require('internal/deps/acorn-plugins/acorn-private-methods/index'); const classFields = @@ -13,7 +16,37 @@ const numericSeparator = require('internal/deps/acorn-plugins/acorn-numeric-separator/index'); const staticClassFeatures = require('internal/deps/acorn-plugins/acorn-static-class-features/index'); -const { tokTypes: tt, Parser: AcornParser } = acorn; + +const { sendInspectorCommand } = require('internal/util/inspector'); + +const { + ERR_INSPECTOR_NOT_AVAILABLE +} = require('internal/errors').codes; + +const { + clearLine, + clearScreenDown, + cursorTo, + moveCursor, +} = require('readline'); + +const { + commonPrefix, + kSubstringSearch, +} = require('internal/readline/utils'); + +const { + getStringWidth, + inspect, +} = require('internal/util/inspect'); + +const debug = require('internal/util/debuglog').debuglog('repl'); + +const previewOptions = { + colors: false, + depth: 1, + showHidden: false +}; // If the error is that we've unexpectedly ended the input, // then let the user try to recover by adding more input. @@ -91,7 +124,563 @@ function isRecoverableError(e, code) { } } +function setupPreview(repl, contextSymbol, bufferSymbol, active) { + // Simple terminals can't handle previews. + if (process.env.TERM === 'dumb' || !active) { + return { showPreview() {}, clearPreview() {} }; + } + + let inputPreview = null; + let lastInputPreview = ''; + + let previewCompletionCounter = 0; + let completionPreview = null; + + let wrapped = false; + + function getPreviewPos() { + const displayPos = repl._getDisplayPos(`${repl._prompt}${repl.line}`); + const cursorPos = repl.line.length !== repl.cursor ? + repl.getCursorPos() : + displayPos; + return { displayPos, cursorPos }; + } + + const clearPreview = () => { + if (inputPreview !== null) { + const { displayPos, cursorPos } = getPreviewPos(); + const rows = displayPos.rows - cursorPos.rows + 1; + moveCursor(repl.output, 0, rows); + clearLine(repl.output); + moveCursor(repl.output, 0, -rows); + lastInputPreview = inputPreview; + inputPreview = null; + } + if (completionPreview !== null) { + // Prevent cursor moves if not necessary! + const move = repl.line.length !== repl.cursor; + let pos, rows; + if (move) { + pos = getPreviewPos(); + cursorTo(repl.output, pos.displayPos.cols); + rows = pos.displayPos.rows - pos.cursorPos.rows; + moveCursor(repl.output, 0, rows); + } + const totalLine = `${repl._prompt}${repl.line}${completionPreview}`; + const newPos = repl._getDisplayPos(totalLine); + // Minimize work for the terminal. It is enough to clear the right part of + // the current line in case the preview is visible on a single line. + if (newPos.rows === 0 || (pos && pos.displayPos.rows === newPos.rows)) { + clearLine(repl.output, 1); + } else { + clearScreenDown(repl.output); + } + if (move) { + cursorTo(repl.output, pos.cursorPos.cols); + moveCursor(repl.output, 0, -rows); + } + completionPreview = null; + } + }; + + function showCompletionPreview(line, insertPreview) { + previewCompletionCounter++; + + const count = previewCompletionCounter; + + repl.completer(line, (error, data) => { + // Tab completion might be async and the result might already be outdated. + if (count !== previewCompletionCounter) { + return; + } + + if (error) { + debug('Error while generating completion preview', error); + return; + } + + // Result and the text that was completed. + const [rawCompletions, completeOn] = data; + + if (!rawCompletions || rawCompletions.length === 0) { + return; + } + + // If there is a common prefix to all matches, then apply that portion. + const completions = rawCompletions.filter((e) => e); + const prefix = commonPrefix(completions); + + // No common prefix found. + if (prefix.length <= completeOn.length) { + return; + } + + const suffix = prefix.slice(completeOn.length); + + if (insertPreview) { + repl._insertString(suffix); + return; + } + + completionPreview = suffix; + + const result = repl.useColors ? + `\u001b[90m${suffix}\u001b[39m` : + ` // ${suffix}`; + + const { cursorPos, displayPos } = getPreviewPos(); + if (repl.line.length !== repl.cursor) { + cursorTo(repl.output, displayPos.cols); + moveCursor(repl.output, 0, displayPos.rows - cursorPos.rows); + } + repl.output.write(result); + cursorTo(repl.output, cursorPos.cols); + const totalLine = `${repl._prompt}${repl.line}${suffix}`; + const newPos = repl._getDisplayPos(totalLine); + const rows = newPos.rows - cursorPos.rows - (newPos.cols === 0 ? 1 : 0); + moveCursor(repl.output, 0, -rows); + }); + } + + // This returns a code preview for arbitrary input code. + function getInputPreview(input, callback) { + // For similar reasons as `defaultEval`, wrap expressions starting with a + // curly brace with parenthesis. + if (input.startsWith('{') && !input.endsWith(';') && !wrapped) { + input = `(${input})`; + wrapped = true; + } + sendInspectorCommand((session) => { + session.post('Runtime.evaluate', { + expression: input, + throwOnSideEffect: true, + timeout: 333, + contextId: repl[contextSymbol], + }, (error, preview) => { + if (error) { + callback(error); + return; + } + const { result } = preview; + if (result.value !== undefined) { + callback(null, inspect(result.value, previewOptions)); + // Ignore EvalErrors, SyntaxErrors and ReferenceErrors. It is not clear + // where they came from and if they are recoverable or not. Other errors + // may be inspected. + } else if (preview.exceptionDetails && + (result.className === 'EvalError' || + result.className === 'SyntaxError' || + result.className === 'ReferenceError')) { + callback(null, null); + } else if (result.objectId) { + // The writer options might change and have influence on the inspect + // output. The user might change e.g., `showProxy`, `getters` or + // `showHidden`. Use `inspect` instead of `JSON.stringify` to keep + // `Infinity` and similar intact. + const inspectOptions = inspect({ + ...repl.writer.options, + colors: false, + depth: 1, + compact: true, + breakLength: Infinity + }, previewOptions); + session.post('Runtime.callFunctionOn', { + functionDeclaration: `(v) => util.inspect(v, ${inspectOptions})`, + objectId: result.objectId, + arguments: [result] + }, (error, preview) => { + if (error) { + callback(error); + } else { + callback(null, preview.result.value); + } + }); + } else { + // Either not serializable or undefined. + callback(null, result.unserializableValue || result.type); + } + }); + }, () => callback(new ERR_INSPECTOR_NOT_AVAILABLE())); + } + + const showPreview = () => { + // Prevent duplicated previews after a refresh. + if (inputPreview !== null || !repl.isCompletionEnabled) { + return; + } + + const line = repl.line.trim(); + + // Do not preview in case the line only contains whitespace. + if (line === '') { + return; + } + + // Add the autocompletion preview. + // TODO(BridgeAR): Trigger the input preview after the completion preview. + // That way it's possible to trigger the input prefix including the + // potential completion suffix. To do so, we also have to change the + // behavior of `enter` and `escape`: + // Enter should automatically add the suffix to the current line as long as + // escape was not pressed. We might even remove the preview in case any + // cursor movement is triggered. + const insertPreview = false; + showCompletionPreview(repl.line, insertPreview); + + // Do not preview if the command is buffered. + if (repl[bufferSymbol]) { + return; + } + + const inputPreviewCallback = (error, inspected) => { + if (inspected === null) { + return; + } + + wrapped = false; + + // Ignore the output if the value is identical to the current line and the + // former preview is not identical to this preview. + if (line === inspected && lastInputPreview !== inspected) { + return; + } + + if (error) { + debug('Error while generating preview', error); + return; + } + // Do not preview `undefined` if colors are deactivated or explicitly + // requested. + if (inspected === 'undefined' && + (!repl.useColors || repl.ignoreUndefined)) { + return; + } + + inputPreview = inspected; + + // Limit the output to maximum 250 characters. Otherwise it becomes a) + // difficult to read and b) non terminal REPLs would visualize the whole + // output. + let maxColumns = MathMin(repl.columns, 250); + + // Support unicode characters of width other than one by checking the + // actual width. + if (inspected.length * 2 >= maxColumns && + getStringWidth(inspected) > maxColumns) { + maxColumns -= 4 + (repl.useColors ? 0 : 3); + let res = ''; + for (const char of inspected) { + maxColumns -= getStringWidth(char); + if (maxColumns < 0) + break; + res += char; + } + inspected = `${res}...`; + } + + // Line breaks are very rare and probably only occur in case of error + // messages with line breaks. + const lineBreakPos = inspected.indexOf('\n'); + if (lineBreakPos !== -1) { + inspected = `${inspected.slice(0, lineBreakPos)}`; + } + + const result = repl.useColors ? + `\u001b[90m${inspected}\u001b[39m` : + `// ${inspected}`; + + const { cursorPos, displayPos } = getPreviewPos(); + const rows = displayPos.rows - cursorPos.rows; + moveCursor(repl.output, 0, rows); + repl.output.write(`\n${result}`); + cursorTo(repl.output, cursorPos.cols); + moveCursor(repl.output, 0, -rows - 1); + }; + + getInputPreview(line, inputPreviewCallback); + if (wrapped) { + getInputPreview(line, inputPreviewCallback); + } + wrapped = false; + }; + + // -------------------------------------------------------------------------// + // Replace multiple interface functions. This is required to fully support // + // previews without changing readlines behavior. // + // -------------------------------------------------------------------------// + + // Refresh prints the whole screen again and the preview will be removed + // during that procedure. Print the preview again. This also makes sure + // the preview is always correct after resizing the terminal window. + const originalRefresh = repl._refreshLine.bind(repl); + repl._refreshLine = () => { + inputPreview = null; + originalRefresh(); + showPreview(); + }; + + let insertCompletionPreview = true; + // Insert the longest common suffix of the current input in case the user + // moves to the right while already being at the current input end. + const originalMoveCursor = repl._moveCursor.bind(repl); + repl._moveCursor = (dx) => { + const currentCursor = repl.cursor; + originalMoveCursor(dx); + if (currentCursor + dx > repl.line.length && + typeof repl.completer === 'function' && + insertCompletionPreview) { + const insertPreview = true; + showCompletionPreview(repl.line, insertPreview); + } + }; + + // This is the only function that interferes with the completion insertion. + // Monkey patch it to prevent inserting the completion when it shouldn't be. + const originalClearLine = repl.clearLine.bind(repl); + repl.clearLine = () => { + insertCompletionPreview = false; + originalClearLine(); + insertCompletionPreview = true; + }; + + return { showPreview, clearPreview }; +} + +function setupReverseSearch(repl) { + // Simple terminals can't use reverse search. + if (process.env.TERM === 'dumb') { + return { reverseSearch() { return false; } }; + } + + const alreadyMatched = new Set(); + const labels = { + r: 'bck-i-search: ', + s: 'fwd-i-search: ' + }; + let isInReverseSearch = false; + let historyIndex = -1; + let input = ''; + let cursor = -1; + let dir = 'r'; + let lastMatch = -1; + let lastCursor = -1; + let promptPos; + + function checkAndSetDirectionKey(keyName) { + if (!labels[keyName]) { + return false; + } + if (dir !== keyName) { + // Reset the already matched set in case the direction is changed. That + // way it's possible to find those entries again. + alreadyMatched.clear(); + dir = keyName; + } + return true; + } + + function goToNextHistoryIndex() { + // Ignore this entry for further searches and continue to the next + // history entry. + alreadyMatched.add(repl.history[historyIndex]); + historyIndex += dir === 'r' ? 1 : -1; + cursor = -1; + } + + function search() { + // Just print an empty line in case the user removed the search parameter. + if (input === '') { + print(repl.line, `${labels[dir]}_`); + return; + } + // Fix the bounds in case the direction has changed in the meanwhile. + if (dir === 'r') { + if (historyIndex < 0) { + historyIndex = 0; + } + } else if (historyIndex >= repl.history.length) { + historyIndex = repl.history.length - 1; + } + // Check the history entries until a match is found. + while (historyIndex >= 0 && historyIndex < repl.history.length) { + let entry = repl.history[historyIndex]; + // Visualize all potential matches only once. + if (alreadyMatched.has(entry)) { + historyIndex += dir === 'r' ? 1 : -1; + continue; + } + // Match the next entry either from the start or from the end, depending + // on the current direction. + if (dir === 'r') { + // Update the cursor in case it's necessary. + if (cursor === -1) { + cursor = entry.length; + } + cursor = entry.lastIndexOf(input, cursor - 1); + } else { + cursor = entry.indexOf(input, cursor + 1); + } + // Match not found. + if (cursor === -1) { + goToNextHistoryIndex(); + // Match found. + } else { + if (repl.useColors) { + const start = entry.slice(0, cursor); + const end = entry.slice(cursor + input.length); + entry = `${start}\x1B[4m${input}\x1B[24m${end}`; + } + print(entry, `${labels[dir]}${input}_`, cursor); + lastMatch = historyIndex; + lastCursor = cursor; + // Explicitly go to the next history item in case no further matches are + // possible with the current entry. + if ((dir === 'r' && cursor === 0) || + (dir === 's' && entry.length === cursor + input.length)) { + goToNextHistoryIndex(); + } + return; + } + } + print(repl.line, `failed-${labels[dir]}${input}_`); + } + + function print(outputLine, inputLine, cursor = repl.cursor) { + // TODO(BridgeAR): Resizing the terminal window hides the overlay. To fix + // that, readline must be aware of this information. It's probably best to + // add a couple of properties to readline that allow to do the following: + // 1. Add arbitrary data to the end of the current line while not counting + // towards the line. This would be useful for the completion previews. + // 2. Add arbitrary extra lines that do not count towards the regular line. + // This would be useful for both, the input preview and the reverse + // search. It might be combined with the first part? + // 3. Add arbitrary input that is "on top" of the current line. That is + // useful for the reverse search. + // 4. To trigger the line refresh, functions should be used to pass through + // the information. Alternatively, getters and setters could be used. + // That might even be more elegant. + // The data would then be accounted for when calling `_refreshLine()`. + // This function would then look similar to: + // repl.overlay(outputLine); + // repl.addTrailingLine(inputLine); + // repl.setCursor(cursor); + // More potential improvements: use something similar to stream.cork(). + // Multiple cursor moves on the same tick could be prevented in case all + // writes from the same tick are combined and the cursor is moved at the + // tick end instead of after each operation. + let rows = 0; + if (lastMatch !== -1) { + const line = repl.history[lastMatch].slice(0, lastCursor); + rows = repl._getDisplayPos(`${repl._prompt}${line}`).rows; + cursorTo(repl.output, promptPos.cols); + } else if (isInReverseSearch && repl.line !== '') { + rows = repl.getCursorPos().rows; + cursorTo(repl.output, promptPos.cols); + } + if (rows !== 0) + moveCursor(repl.output, 0, -rows); + + if (isInReverseSearch) { + clearScreenDown(repl.output); + repl.output.write(`${outputLine}\n${inputLine}`); + } else { + repl.output.write(`\n${inputLine}`); + } + + lastMatch = -1; + + // To know exactly how many rows we have to move the cursor back we need the + // cursor rows, the output rows and the input rows. + const prompt = repl._prompt; + const cursorLine = `${prompt}${outputLine.slice(0, cursor)}`; + const cursorPos = repl._getDisplayPos(cursorLine); + const outputPos = repl._getDisplayPos(`${prompt}${outputLine}`); + const inputPos = repl._getDisplayPos(inputLine); + const inputRows = inputPos.rows - (inputPos.cols === 0 ? 1 : 0); + + rows = -1 - inputRows - (outputPos.rows - cursorPos.rows); + + moveCursor(repl.output, 0, rows); + cursorTo(repl.output, cursorPos.cols); + } + + function reset(string) { + isInReverseSearch = string !== undefined; + + // In case the reverse search ends and a history entry is found, reset the + // line to the found entry. + if (!isInReverseSearch) { + if (lastMatch !== -1) { + repl.line = repl.history[lastMatch]; + repl.cursor = lastCursor; + repl.historyIndex = lastMatch; + } + + lastMatch = -1; + + // Clear screen and write the current repl.line before exiting. + cursorTo(repl.output, promptPos.cols); + moveCursor(repl.output, 0, promptPos.rows); + clearScreenDown(repl.output); + if (repl.line !== '') { + repl.output.write(repl.line); + if (repl.line.length !== repl.cursor) { + const { cols, rows } = repl.getCursorPos(); + cursorTo(repl.output, cols); + moveCursor(repl.output, 0, rows); + } + } + } + + input = string || ''; + cursor = -1; + historyIndex = repl.historyIndex; + alreadyMatched.clear(); + } + + function reverseSearch(string, key) { + if (!isInReverseSearch) { + if (key.ctrl && checkAndSetDirectionKey(key.name)) { + historyIndex = repl.historyIndex; + promptPos = repl._getDisplayPos(`${repl._prompt}`); + print(repl.line, `${labels[dir]}_`); + isInReverseSearch = true; + } + } else if (key.ctrl && checkAndSetDirectionKey(key.name)) { + search(); + } else if (key.name === 'backspace' || + (key.ctrl && (key.name === 'h' || key.name === 'w'))) { + reset(input.slice(0, input.length - 1)); + search(); + // Special handle + c and escape. Those should only cancel the + // reverse search. The original line is visible afterwards again. + } else if ((key.ctrl && key.name === 'c') || key.name === 'escape') { + lastMatch = -1; + reset(); + return true; + // End search in case either enter is pressed or if any non-reverse-search + // key (combination) is pressed. + } else if (key.ctrl || + key.meta || + key.name === 'return' || + key.name === 'enter' || + typeof string !== 'string' || + string === '') { + reset(); + repl[kSubstringSearch] = ''; + } else { + reset(`${input}${string}`); + search(); + } + return isInReverseSearch; + } + + return { reverseSearch }; +} + module.exports = { isRecoverableError, - kStandaloneREPL: Symbol('kStandaloneREPL') + kStandaloneREPL: Symbol('kStandaloneREPL'), + setupPreview, + setupReverseSearch }; diff --git a/lib/internal/source_map/prepare_stack_trace.js b/lib/internal/source_map/prepare_stack_trace.js index df559b2cdfe581..037a8dc53e0855 100644 --- a/lib/internal/source_map/prepare_stack_trace.js +++ b/lib/internal/source_map/prepare_stack_trace.js @@ -29,7 +29,6 @@ const prepareStackTrace = (globalThis, error, trace) => { maybeOverridePrepareStackTrace(globalThis, error, trace); if (globalOverride !== kNoOverride) return globalOverride; - const { SourceMap } = require('internal/source_map/source_map'); const errorString = ErrorToString.call(error); if (trace.length === 0) { @@ -39,16 +38,19 @@ const prepareStackTrace = (globalThis, error, trace) => { let str = i !== 0 ? '\n at ' : ''; str = `${str}${t}`; try { - const sourceMap = findSourceMap(t.getFileName(), error); - if (sourceMap && sourceMap.data) { - const sm = new SourceMap(sourceMap.data); + const sm = findSourceMap(t.getFileName(), error); + if (sm) { // Source Map V3 lines/columns use zero-based offsets whereas, in // stack traces, they start at 1/1. - const [, , url, line, col] = - sm.findEntry(t.getLineNumber() - 1, t.getColumnNumber() - 1); - if (url && line !== undefined && col !== undefined) { + const { + originalLine, + originalColumn, + originalSource + } = sm.findEntry(t.getLineNumber() - 1, t.getColumnNumber() - 1); + if (originalSource && originalLine !== undefined && + originalColumn !== undefined) { str += - `\n -> ${url.replace('file://', '')}:${line + 1}:${col + 1}`; +`\n -> ${originalSource.replace('file://', '')}:${originalLine + 1}:${originalColumn + 1}`; } } } catch (err) { diff --git a/lib/internal/source_map/source_map.js b/lib/internal/source_map/source_map.js index 9044521b6d62d0..35ec3ae740e887 100644 --- a/lib/internal/source_map/source_map.js +++ b/lib/internal/source_map/source_map.js @@ -66,6 +66,14 @@ 'use strict'; +const { + ArrayIsArray +} = primordials; + +const { + ERR_INVALID_ARG_TYPE +} = require('internal/errors').codes; + let base64Map; const VLQ_BASE_SHIFT = 5; @@ -112,7 +120,7 @@ class StringCharIterator { * @param {SourceMapV3} payload */ class SourceMap { - #reverseMappingsBySourceURL = []; + #payload; #mappings = []; #sources = {}; #sourceContentByURL = {}; @@ -129,17 +137,27 @@ class SourceMap { for (let i = 0; i < base64Digits.length; ++i) base64Map[base64Digits[i]] = i; } - this.#parseMappingPayload(payload); + this.#payload = cloneSourceMapV3(payload); + this.#parseMappingPayload(); + } + + /** + * @return {Object} raw source map v3 payload. + */ + get payload() { + return cloneSourceMapV3(this.#payload); } /** * @param {SourceMapV3} mappingPayload */ - #parseMappingPayload = (mappingPayload) => { - if (mappingPayload.sections) - this.#parseSections(mappingPayload.sections); - else - this.#parseMap(mappingPayload, 0, 0); + #parseMappingPayload = () => { + if (this.#payload.sections) { + this.#parseSections(this.#payload.sections); + } else { + this.#parseMap(this.#payload, 0, 0); + } + this.#mappings.sort(compareSourceMapEntry); } /** @@ -175,24 +193,18 @@ class SourceMap { const entry = this.#mappings[first]; if (!first && entry && (lineNumber < entry[0] || (lineNumber === entry[0] && columnNumber < entry[1]))) { - return null; - } - return entry; - } - - /** - * @param {string} sourceURL of the originating resource - * @param {number} lineNumber in the originating resource - * @return {Array} - */ - findEntryReversed(sourceURL, lineNumber) { - const mappings = this.#reverseMappingsBySourceURL[sourceURL]; - for (; lineNumber < mappings.length; ++lineNumber) { - const mapping = mappings[lineNumber]; - if (mapping) - return mapping; + return {}; + } else if (!entry) { + return {}; + } else { + return { + generatedLine: entry[0], + generatedColumn: entry[1], + originalSource: entry[2], + originalLine: entry[3], + originalColumn: entry[4] + }; } - return this.#mappings[0]; } /** @@ -251,19 +263,6 @@ class SourceMap { this.#mappings.push([lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber]); } - - for (let i = 0; i < this.#mappings.length; ++i) { - const mapping = this.#mappings[i]; - const url = mapping[2]; - if (!url) - continue; - if (!this.#reverseMappingsBySourceURL[url]) - this.#reverseMappingsBySourceURL[url] = []; - const reverseMappings = this.#reverseMappingsBySourceURL[url]; - const sourceLine = mapping[3]; - if (!reverseMappings[sourceLine]) - reverseMappings[sourceLine] = [mapping[0], mapping[1]]; - } }; } @@ -292,8 +291,51 @@ function decodeVLQ(stringCharIterator) { // Fix the sign. const negative = result & 1; - result >>= 1; - return negative ? -result : result; + // Use unsigned right shift, so that the 32nd bit is properly shifted to the + // 31st, and the 32nd becomes unset. + result >>>= 1; + if (!negative) { + return result; + } + + // We need to OR here to ensure the 32nd bit (the sign bit in an Int32) is + // always set for negative numbers. If `result` were 1, (meaning `negate` is + // true and all other bits were zeros), `result` would now be 0. But -0 + // doesn't flip the 32nd bit as intended. All other numbers will successfully + // set the 32nd bit without issue, so doing this is a noop for them. + return -result | (1 << 31); +} + +/** + * @param {SourceMapV3} payload + * @return {SourceMapV3} + */ +function cloneSourceMapV3(payload) { + if (typeof payload !== 'object') { + throw new ERR_INVALID_ARG_TYPE('payload', ['Object'], payload); + } + payload = { ...payload }; + for (const key in payload) { + if (payload.hasOwnProperty(key) && ArrayIsArray(payload[key])) { + payload[key] = payload[key].slice(0); + } + } + return payload; +} + +/** + * @param {Array} entry1 source map entry [lineNumber, columnNumber, sourceURL, + * sourceLineNumber, sourceColumnNumber] + * @param {Array} entry2 source map entry. + * @return {number} + */ +function compareSourceMapEntry(entry1, entry2) { + const [lineNumber1, columnNumber1] = entry1; + const [lineNumber2, columnNumber2] = entry2; + if (lineNumber1 !== lineNumber2) { + return lineNumber1 - lineNumber2; + } + return columnNumber1 - columnNumber2; } module.exports = { diff --git a/lib/internal/source_map/source_map_cache.js b/lib/internal/source_map/source_map_cache.js index 593c2c8277f224..b64af7eed6e097 100644 --- a/lib/internal/source_map/source_map_cache.js +++ b/lib/internal/source_map/source_map_cache.js @@ -37,6 +37,7 @@ const cjsSourceMapCache = new WeakMap(); const esmSourceMapCache = new Map(); const { fileURLToPath, URL } = require('url'); let Module; +let SourceMap; let experimentalSourceMaps; function maybeCacheSourceMap(filename, content, cjsModuleInstance) { @@ -222,8 +223,13 @@ function appendCJSCache(obj) { // Attempt to lookup a source map, which is either attached to a file URI, or // keyed on an error instance. +// TODO(bcoe): once WeakRefs are available in Node.js, refactor to drop +// requirement of error parameter. function findSourceMap(uri, error) { if (!Module) Module = require('internal/modules/cjs/loader').Module; + if (!SourceMap) { + SourceMap = require('internal/source_map/source_map').SourceMap; + } let sourceMap = cjsSourceMapCache.get(Module._cache[uri]); if (!uri.startsWith('file://')) uri = normalizeReferrerURL(uri); if (sourceMap === undefined) { @@ -235,7 +241,11 @@ function findSourceMap(uri, error) { sourceMap = candidateSourceMap; } } - return sourceMap; + if (sourceMap && sourceMap.data) { + return new SourceMap(sourceMap.data); + } else { + return undefined; + } } module.exports = { diff --git a/lib/internal/streams/from.js b/lib/internal/streams/from.js index ab6db00a125a0b..6752679ae3bc2b 100644 --- a/lib/internal/streams/from.js +++ b/lib/internal/streams/from.js @@ -7,7 +7,8 @@ const { const { Buffer } = require('buffer'); const { - ERR_INVALID_ARG_TYPE + ERR_INVALID_ARG_TYPE, + ERR_STREAM_NULL_VALUES } = require('internal/errors').codes; function from(Readable, iterable, opts) { @@ -34,24 +35,59 @@ function from(Readable, iterable, opts) { objectMode: true, ...opts }); + // Reading boolean to protect against _read // being called before last iteration completion. let reading = false; + + // needToClose boolean if iterator needs to be explicitly closed + let needToClose = false; + readable._read = function() { if (!reading) { reading = true; next(); } }; + + readable._destroy = function(error, cb) { + if (needToClose) { + needToClose = false; + close().then( + () => process.nextTick(cb, error), + (e) => process.nextTick(cb, error || e), + ); + } else { + cb(error); + } + }; + + async function close() { + if (typeof iterator.return === 'function') { + const { value } = await iterator.return(); + await value; + } + } + async function next() { try { + needToClose = false; const { value, done } = await iterator.next(); + needToClose = !done; if (done) { readable.push(null); - } else if (readable.push(await value)) { - next(); + } else if (readable.destroyed) { + await close(); } else { - reading = false; + const res = await value; + if (res === null) { + reading = false; + throw new ERR_STREAM_NULL_VALUES(); + } else if (readable.push(res)) { + next(); + } else { + reading = false; + } } } catch (err) { readable.destroy(err); diff --git a/lib/internal/timers.js b/lib/internal/timers.js index b62ab9499c8fff..bb80f57ee295c5 100644 --- a/lib/internal/timers.js +++ b/lib/internal/timers.js @@ -96,7 +96,7 @@ const { emitInit, emitBefore, emitAfter, - emitDestroy + emitDestroy, } = require('internal/async_hooks'); // Symbols for storing async id state. @@ -448,7 +448,7 @@ function getTimerCallbacks(runNextTicks) { prevImmediate = immediate; const asyncId = immediate[async_id_symbol]; - emitBefore(asyncId, immediate[trigger_async_id_symbol]); + emitBefore(asyncId, immediate[trigger_async_id_symbol], immediate); try { const argv = immediate._argv; @@ -537,7 +537,7 @@ function getTimerCallbacks(runNextTicks) { continue; } - emitBefore(asyncId, timer[trigger_async_id_symbol]); + emitBefore(asyncId, timer[trigger_async_id_symbol], timer); let start; if (timer._repeat) diff --git a/lib/internal/url.js b/lib/internal/url.js index 09fa9f2cf47d50..efb842a074d750 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -1348,8 +1348,7 @@ function getPathFromURLPosix(url) { function fileURLToPath(path) { if (typeof path === 'string') path = new URL(path); - else if (path == null || !path[searchParams] || - !path[searchParams][searchParams]) + else if (!isURLInstance(path)) throw new ERR_INVALID_ARG_TYPE('path', ['string', 'URL'], path); if (path.protocol !== 'file:') throw new ERR_INVALID_URL_SCHEME('file'); @@ -1396,9 +1395,13 @@ function pathToFileURL(filepath) { return outURL; } +function isURLInstance(fileURLOrPath) { + return fileURLOrPath != null && fileURLOrPath[searchParams] && + fileURLOrPath[searchParams][searchParams]; +} + function toPathIfFileURL(fileURLOrPath) { - if (fileURLOrPath == null || !fileURLOrPath[searchParams] || - !fileURLOrPath[searchParams][searchParams]) + if (!isURLInstance(fileURLOrPath)) return fileURLOrPath; return fileURLToPath(fileURLOrPath); } @@ -1431,6 +1434,7 @@ module.exports = { fileURLToPath, pathToFileURL, toPathIfFileURL, + isURLInstance, URL, URLSearchParams, domainToASCII, diff --git a/lib/internal/util/comparisons.js b/lib/internal/util/comparisons.js index 1598e7f9136ace..c8e277abb747ee 100644 --- a/lib/internal/util/comparisons.js +++ b/lib/internal/util/comparisons.js @@ -147,7 +147,7 @@ function isIdenticalTypedArrayType(a, b) { return check(b); } } - /* c8 ignore next */ + /* c8 ignore next 4 */ assert.fail( `Unknown TypedArray type checking ${a[SymbolToStringTag]} ${a}\n` + `and ${b[SymbolToStringTag]} ${b}` diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index 1059ac4209e0eb..600bdd2b888f24 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -146,6 +146,7 @@ const inspectDefaultOptions = ObjectSeal({ customInspect: true, showProxy: false, maxArrayLength: 100, + maxStringLength: Infinity, breakLength: 80, compact: 3, sorted: false, @@ -193,6 +194,17 @@ const meta = [ '', '', '', '', '', '', '', '\\\\' ]; +// Regex used for ansi escape code splitting +// Adopted from https://github.com/chalk/ansi-regex/blob/master/index.js +// License: MIT, authors: @sindresorhus, Qix-, arjunmehta and LitoMore +// Matches all ansi escape code sequences in a string +const ansiPattern = '[\\u001B\\u009B][[\\]()#;?]*' + + '(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)' + + '|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'; +const ansi = new RegExp(ansiPattern, 'g'); + +let getStringWidth; + function getUserOptions(ctx) { return { stylize: ctx.stylize, @@ -202,6 +214,7 @@ function getUserOptions(ctx) { customInspect: ctx.customInspect, showProxy: ctx.showProxy, maxArrayLength: ctx.maxArrayLength, + maxStringLength: ctx.maxStringLength, breakLength: ctx.breakLength, compact: ctx.compact, sorted: ctx.sorted, @@ -232,6 +245,7 @@ function inspect(value, opts) { customInspect: inspectDefaultOptions.customInspect, showProxy: inspectDefaultOptions.showProxy, maxArrayLength: inspectDefaultOptions.maxArrayLength, + maxStringLength: inspectDefaultOptions.maxStringLength, breakLength: inspectDefaultOptions.breakLength, compact: inspectDefaultOptions.compact, sorted: inspectDefaultOptions.sorted, @@ -269,6 +283,7 @@ function inspect(value, opts) { } if (ctx.colors) ctx.stylize = stylizeWithColor; if (ctx.maxArrayLength === null) ctx.maxArrayLength = Infinity; + if (ctx.maxStringLength === null) ctx.maxStringLength = Infinity; return formatValue(ctx, value, 0); } inspect.custom = customInspectSymbol; @@ -1163,7 +1178,7 @@ function groupArrayElements(ctx, output, value) { // entries length of all output entries. We have to remove colors first, // otherwise the length would not be calculated properly. for (; i < outputLength; i++) { - const len = ctx.colors ? removeColors(output[i]).length : output[i].length; + const len = getStringWidth(output[i], ctx.colors); dataLen[i] = len; totalLength += len + separatorSpace; if (maxLength < len) @@ -1282,15 +1297,23 @@ function formatBigInt(fn, value) { function formatPrimitive(fn, value, ctx) { if (typeof value === 'string') { + let trailer = ''; + if (value.length > ctx.maxStringLength) { + const remaining = value.length - ctx.maxStringLength; + value = value.slice(0, ctx.maxStringLength); + trailer = `... ${remaining} more character${remaining > 1 ? 's' : ''}`; + } if (ctx.compact !== true && + // TODO(BridgeAR): Add unicode support. Use the readline getStringWidth + // function. value.length > kMinLineLength && value.length > ctx.breakLength - ctx.indentationLvl - 4) { return value .split(/(?<=\n)/) .map((line) => fn(strEscape(line), 'string')) - .join(` +\n${' '.repeat(ctx.indentationLvl + 2)}`); + .join(` +\n${' '.repeat(ctx.indentationLvl + 2)}`) + trailer; } - return fn(strEscape(value), 'string'); + return fn(strEscape(value), 'string') + trailer; } if (typeof value === 'number') return formatNumber(fn, value); @@ -1578,11 +1601,8 @@ function formatProperty(ctx, value, recurseTimes, key, type, desc) { const diff = (ctx.compact !== true || type !== kObjectType) ? 2 : 3; ctx.indentationLvl += diff; str = formatValue(ctx, desc.value, recurseTimes); - if (diff === 3) { - const len = ctx.colors ? removeColors(str).length : str.length; - if (ctx.breakLength < len) { - extra = `\n${' '.repeat(ctx.indentationLvl)}`; - } + if (diff === 3 && ctx.breakLength < getStringWidth(str, ctx.colors)) { + extra = `\n${' '.repeat(ctx.indentationLvl)}`; } ctx.indentationLvl -= diff; } else if (desc.get !== undefined) { @@ -1636,6 +1656,9 @@ function isBelowBreakLength(ctx, output, start, base) { // Each entry is separated by at least a comma. Thus, we start with a total // length of at least `output.length`. In addition, some cases have a // whitespace in-between each other that is added to the total as well. + // TODO(BridgeAR): Add unicode support. Use the readline getStringWidth + // function. Check the performance overhead and make it an opt-in in case it's + // significant. let totalLength = output.length + start; if (totalLength + output.length > ctx.breakLength) return false; @@ -1891,9 +1914,121 @@ function formatWithOptions(inspectOptions, ...args) { return str; } +function prepareStringForGetStringWidth(str, removeControlChars) { + str = str.normalize('NFC'); + if (removeControlChars) + str = stripVTControlCharacters(str); + return str; +} + +if (internalBinding('config').hasIntl) { + const icu = internalBinding('icu'); + // icu.getStringWidth(string, ambiguousAsFullWidth, expandEmojiSequence) + // Defaults: ambiguousAsFullWidth = false; expandEmojiSequence = true; + // TODO(BridgeAR): Expose the options to the user. That is probably the + // best thing possible at the moment, since it's difficult to know what + // the receiving end supports. + getStringWidth = function getStringWidth(str, removeControlChars = true) { + let width = 0; + + str = prepareStringForGetStringWidth(str, removeControlChars); + for (let i = 0; i < str.length; i++) { + // Try to avoid calling into C++ by first handling the ASCII portion of + // the string. If it is fully ASCII, we skip the C++ part. + const code = str.charCodeAt(i); + if (code >= 127) { + width += icu.getStringWidth(str.slice(i)); + break; + } + width += code >= 32 ? 1 : 0; + } + return width; + }; +} else { + /** + * Returns the number of columns required to display the given string. + */ + getStringWidth = function getStringWidth(str, removeControlChars = true) { + let width = 0; + + str = prepareStringForGetStringWidth(str, removeControlChars); + for (const char of str) { + const code = char.codePointAt(0); + if (isFullWidthCodePoint(code)) { + width += 2; + } else if (!isZeroWidthCodePoint(code)) { + width++; + } + } + + return width; + }; + + /** + * Returns true if the character represented by a given + * Unicode code point is full-width. Otherwise returns false. + */ + const isFullWidthCodePoint = (code) => { + // Code points are partially derived from: + // http://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt + return code >= 0x1100 && ( + code <= 0x115f || // Hangul Jamo + code === 0x2329 || // LEFT-POINTING ANGLE BRACKET + code === 0x232a || // RIGHT-POINTING ANGLE BRACKET + // CJK Radicals Supplement .. Enclosed CJK Letters and Months + (code >= 0x2e80 && code <= 0x3247 && code !== 0x303f) || + // Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A + (code >= 0x3250 && code <= 0x4dbf) || + // CJK Unified Ideographs .. Yi Radicals + (code >= 0x4e00 && code <= 0xa4c6) || + // Hangul Jamo Extended-A + (code >= 0xa960 && code <= 0xa97c) || + // Hangul Syllables + (code >= 0xac00 && code <= 0xd7a3) || + // CJK Compatibility Ideographs + (code >= 0xf900 && code <= 0xfaff) || + // Vertical Forms + (code >= 0xfe10 && code <= 0xfe19) || + // CJK Compatibility Forms .. Small Form Variants + (code >= 0xfe30 && code <= 0xfe6b) || + // Halfwidth and Fullwidth Forms + (code >= 0xff01 && code <= 0xff60) || + (code >= 0xffe0 && code <= 0xffe6) || + // Kana Supplement + (code >= 0x1b000 && code <= 0x1b001) || + // Enclosed Ideographic Supplement + (code >= 0x1f200 && code <= 0x1f251) || + // Miscellaneous Symbols and Pictographs 0x1f300 - 0x1f5ff + // Emoticons 0x1f600 - 0x1f64f + (code >= 0x1f300 && code <= 0x1f64f) || + // CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane + (code >= 0x20000 && code <= 0x3fffd) + ); + }; + + const isZeroWidthCodePoint = (code) => { + return code <= 0x1F || // C0 control codes + (code > 0x7F && code <= 0x9F) || // C1 control codes + (code >= 0x300 && code <= 0x36F) || // Combining Diacritical Marks + (code >= 0x200B && code <= 0x200F) || // Modifying Invisible Characters + (code >= 0xFE00 && code <= 0xFE0F) || // Variation Selectors + (code >= 0xFE20 && code <= 0xFE2F) || // Combining Half Marks + (code >= 0xE0100 && code <= 0xE01EF); // Variation Selectors + }; +} + +/** + * Remove all VT control characters. Use to estimate displayed string width. + */ +function stripVTControlCharacters(str) { + return str.replace(ansi, ''); +} + module.exports = { inspect, format, formatWithOptions, - inspectDefaultOptions + getStringWidth, + inspectDefaultOptions, + stripVTControlCharacters }; diff --git a/lib/internal/validators.js b/lib/internal/validators.js index c768f7cef06c92..1d7bf1baa19fa1 100644 --- a/lib/internal/validators.js +++ b/lib/internal/validators.js @@ -1,6 +1,7 @@ 'use strict'; const { + ArrayIsArray, NumberIsInteger, NumberMAX_SAFE_INTEGER, NumberMIN_SAFE_INTEGER, @@ -9,10 +10,12 @@ const { const { hideStackFrames, codes: { + ERR_SOCKET_BAD_PORT, ERR_INVALID_ARG_TYPE, ERR_INVALID_ARG_VALUE, ERR_OUT_OF_RANGE, - ERR_UNKNOWN_SIGNAL + ERR_UNKNOWN_SIGNAL, + ERR_INVALID_CALLBACK, } } = require('internal/errors'); const { @@ -122,6 +125,30 @@ function validateNumber(value, name) { throw new ERR_INVALID_ARG_TYPE(name, 'number', value); } +function validateBoolean(value, name) { + if (typeof value !== 'boolean') + throw new ERR_INVALID_ARG_TYPE(name, 'boolean', value); +} + +const validateObject = hideStackFrames( + (value, name, { nullable = false } = {}) => { + if ((!nullable && value === null) || + ArrayIsArray(value) || + typeof value !== 'object') { + throw new ERR_INVALID_ARG_TYPE(name, 'Object', value); + } + }); + +const validateArray = hideStackFrames((value, name, { minLength = 0 } = {}) => { + if (!ArrayIsArray(value)) { + throw new ERR_INVALID_ARG_TYPE(name, 'Array', value); + } + if (value.length < minLength) { + const reason = `must be longer than ${minLength}`; + throw new ERR_INVALID_ARG_VALUE(name, value, reason); + } +}); + function validateSignalName(signal, name = 'signal') { if (typeof signal !== 'string') throw new ERR_INVALID_ARG_TYPE(name, 'string', signal); @@ -144,15 +171,38 @@ const validateBuffer = hideStackFrames((buffer, name = 'buffer') => { } }); +// Check that the port number is not NaN when coerced to a number, +// is an integer and that it falls within the legal range of port numbers. +function validatePort(port, name = 'Port', { allowZero = true } = {}) { + if ((typeof port !== 'number' && typeof port !== 'string') || + (typeof port === 'string' && port.trim().length === 0) || + +port !== (+port >>> 0) || + port > 0xFFFF || + (port === 0 && !allowZero)) { + throw new ERR_SOCKET_BAD_PORT(name, port, allowZero); + } + return port | 0; +} + +const validateCallback = hideStackFrames((callback) => { + if (typeof callback !== 'function') + throw new ERR_INVALID_CALLBACK(callback); +}); + module.exports = { isInt32, isUint32, parseMode, + validateArray, + validateBoolean, validateBuffer, - validateInteger, validateInt32, - validateUint32, - validateString, + validateInteger, validateNumber, - validateSignalName + validateObject, + validatePort, + validateSignalName, + validateString, + validateUint32, + validateCallback, }; diff --git a/lib/internal/vm/module.js b/lib/internal/vm/module.js index d12362184a5051..992753ef680dbb 100644 --- a/lib/internal/vm/module.js +++ b/lib/internal/vm/module.js @@ -11,7 +11,10 @@ const { } = primordials; const { isContext } = internalBinding('contextify'); -const { isModuleNamespaceObject } = require('internal/util/types'); +const { + isModuleNamespaceObject, + isArrayBufferView, +} = require('internal/util/types'); const { getConstructorOf, customInspectSymbol, @@ -19,8 +22,10 @@ const { } = require('internal/util'); const { ERR_INVALID_ARG_TYPE, + ERR_INVALID_ARG_VALUE, ERR_VM_MODULE_ALREADY_LINKED, ERR_VM_MODULE_DIFFERENT_CONTEXT, + ERR_VM_MODULE_CANNOT_CREATE_CACHED_DATA, ERR_VM_MODULE_LINKING_ERRORED, ERR_VM_MODULE_NOT_MODULE, ERR_VM_MODULE_STATUS, @@ -107,7 +112,8 @@ class Module { if (sourceText !== undefined) { this[kWrap] = new ModuleWrap(identifier, context, sourceText, - options.lineOffset, options.columnOffset); + options.lineOffset, options.columnOffset, + options.cachedData); binding.callbackMap.set(this[kWrap], { initializeImportMeta: options.initializeImportMeta, @@ -253,6 +259,7 @@ class SourceTextModule extends Module { importModuleDynamically, context, identifier, + cachedData, } = options; validateInt32(lineOffset, 'options.lineOffset'); @@ -271,12 +278,21 @@ class SourceTextModule extends Module { importModuleDynamically); } + if (cachedData !== undefined && !isArrayBufferView(cachedData)) { + throw new ERR_INVALID_ARG_TYPE( + 'options.cachedData', + ['Buffer', 'TypedArray', 'DataView'], + cachedData + ); + } + super({ sourceText, context, identifier, lineOffset, columnOffset, + cachedData, initializeImportMeta, importModuleDynamically, }); @@ -348,14 +364,33 @@ class SourceTextModule extends Module { } return super.error; } + + createCachedData() { + const { status } = this; + if (status === 'evaluating' || + status === 'evaluated' || + status === 'errored') { + throw new ERR_VM_MODULE_CANNOT_CREATE_CACHED_DATA(); + } + return this[kWrap].createCachedData(); + } } class SyntheticModule extends Module { constructor(exportNames, evaluateCallback, options = {}) { if (!ArrayIsArray(exportNames) || exportNames.some((e) => typeof e !== 'string')) { - throw new ERR_INVALID_ARG_TYPE('exportNames', 'Array of strings', + throw new ERR_INVALID_ARG_TYPE('exportNames', + 'Array of unique strings', exportNames); + } else { + exportNames.forEach((name, i) => { + if (exportNames.indexOf(name, i + 1) !== -1) { + throw new ERR_INVALID_ARG_VALUE(`exportNames.${name}`, + name, + 'is duplicated'); + } + }); } if (typeof evaluateCallback !== 'function') { throw new ERR_INVALID_ARG_TYPE('evaluateCallback', 'function', diff --git a/lib/internal/watchdog.js b/lib/internal/watchdog.js new file mode 100644 index 00000000000000..6a5b772111f4d6 --- /dev/null +++ b/lib/internal/watchdog.js @@ -0,0 +1,59 @@ +'use strict'; + +const { + TraceSigintWatchdog +} = internalBinding('watchdog'); + +class SigintWatchdog extends TraceSigintWatchdog { + _started = false; + _effective = false; + _onNewListener = (eve) => { + if (eve === 'SIGINT' && this._effective) { + super.stop(); + this._effective = false; + } + }; + _onRemoveListener = (eve) => { + if (eve === 'SIGINT' && process.listenerCount('SIGINT') === 0 && + !this._effective) { + super.start(); + this._effective = true; + } + } + + start() { + if (this._started) { + return; + } + this._started = true; + // Prepend sigint newListener to remove stop watchdog before signal wrap + // been activated. Also make sigint removeListener been ran after signal + // wrap been stopped. + process.prependListener('newListener', this._onNewListener); + process.addListener('removeListener', this._onRemoveListener); + + if (process.listenerCount('SIGINT') === 0) { + super.start(); + this._effective = true; + } + } + + stop() { + if (!this._started) { + return; + } + this._started = false; + process.removeListener('newListener', this._onNewListener); + process.removeListener('removeListener', this._onRemoveListener); + + if (this._effective) { + super.stop(); + this._effective = false; + } + } +} + + +module.exports = { + SigintWatchdog +}; diff --git a/lib/internal/worker.js b/lib/internal/worker.js index 9924554ff96c8d..5f92a7898e93a9 100644 --- a/lib/internal/worker.js +++ b/lib/internal/worker.js @@ -19,15 +19,14 @@ const path = require('path'); const errorCodes = require('internal/errors').codes; const { + ERR_WORKER_NOT_RUNNING, ERR_WORKER_PATH, ERR_WORKER_UNSERIALIZABLE_ERROR, ERR_WORKER_UNSUPPORTED_EXTENSION, ERR_WORKER_INVALID_EXEC_ARGV, ERR_INVALID_ARG_TYPE, - // eslint-disable-next-line no-unused-vars - ERR_WORKER_INIT_FAILED, + ERR_INVALID_ARG_VALUE, } = errorCodes; -const { validateString } = require('internal/validators'); const { getOptionValue } = require('internal/options'); const workerIo = require('internal/worker/io'); @@ -44,7 +43,7 @@ const { WritableWorkerStdio } = workerIo; const { deserializeError } = require('internal/error-serdes'); -const { pathToFileURL } = require('url'); +const { fileURLToPath, isURLInstance, pathToFileURL } = require('internal/url'); const { ownsProcessState, @@ -85,7 +84,6 @@ class Worker extends EventEmitter { constructor(filename, options = {}) { super(); debug(`[${threadId}] create new worker`, filename, options); - validateString(filename, 'filename'); if (options.execArgv && !ArrayIsArray(options.execArgv)) { throw new ERR_INVALID_ARG_TYPE('options.execArgv', 'Array', @@ -98,11 +96,33 @@ class Worker extends EventEmitter { } argv = options.argv.map(String); } - if (!options.eval) { - if (!path.isAbsolute(filename) && !/^\.\.?[\\/]/.test(filename)) { + + let url; + if (options.eval) { + if (typeof filename !== 'string') { + throw new ERR_INVALID_ARG_VALUE( + 'options.eval', + options.eval, + 'must be false when \'filename\' is not a string' + ); + } + url = null; + } else { + if (isURLInstance(filename)) { + url = filename; + filename = fileURLToPath(filename); + } else if (typeof filename !== 'string') { + throw new ERR_INVALID_ARG_TYPE( + 'filename', + ['string', 'URL'], + filename + ); + } else if (path.isAbsolute(filename) || /^\.\.?[\\/]/.test(filename)) { + filename = path.resolve(filename); + url = pathToFileURL(filename); + } else { throw new ERR_WORKER_PATH(filename); } - filename = path.resolve(filename); const ext = path.extname(filename); if (ext !== '.js' && ext !== '.mjs' && ext !== '.cjs') { @@ -124,7 +144,6 @@ class Worker extends EventEmitter { options.env); } - const url = options.eval ? null : pathToFileURL(filename); // Set up the C++ handle for the worker, as well as some internal wiring. this[kHandle] = new WorkerImpl(url, env === process.env ? null : env, @@ -164,6 +183,11 @@ class Worker extends EventEmitter { this[kParentSideStdio] = { stdin, stdout, stderr }; const { port1, port2 } = new MessageChannel(); + const transferList = [port2]; + // If transferList is provided. + if (options.transferList) + transferList.push(...options.transferList); + this[kPublicPort] = port1; this[kPublicPort].on('message', (message) => this.emit('message', message)); setupPortReferencing(this[kPublicPort], this, 'message'); @@ -179,7 +203,7 @@ class Worker extends EventEmitter { require('internal/process/policy').src : null, hasStdin: !!options.stdin - }, [port2]); + }, transferList); // Actually start the new thread now that everything is in place. this[kHandle].startThread(); } @@ -318,6 +342,17 @@ class Worker extends EventEmitter { return makeResourceLimits(this[kHandle].getResourceLimits()); } + + getHeapSnapshot() { + const heapSnapshotTaker = this[kHandle] && this[kHandle].takeHeapSnapshot(); + return new Promise((resolve, reject) => { + if (!heapSnapshotTaker) return reject(new ERR_WORKER_NOT_RUNNING()); + heapSnapshotTaker.ondone = (handle) => { + const { HeapSnapshotStream } = require('internal/heap_utils'); + resolve(new HeapSnapshotStream(handle)); + }; + }); + } } function pipeWithoutWarning(source, dest) { diff --git a/lib/module.js b/lib/module.js index a767330f5e3d6e..b4a6dd7d18de56 100644 --- a/lib/module.js +++ b/lib/module.js @@ -1,3 +1,9 @@ 'use strict'; -module.exports = require('internal/modules/cjs/loader').Module; +const { findSourceMap } = require('internal/source_map/source_map_cache'); +const { Module } = require('internal/modules/cjs/loader'); +const { SourceMap } = require('internal/source_map/source_map'); + +Module.findSourceMap = findSourceMap; +Module.SourceMap = SourceMap; +module.exports = Module; diff --git a/lib/net.js b/lib/net.js index 39dc526641e216..fa6574c183e48e 100644 --- a/lib/net.js +++ b/lib/net.js @@ -41,7 +41,6 @@ const { isIP, isIPv4, isIPv6, - isLegalPort, normalizedArgsSymbol, makeSyncWrite } = require('internal/net'); @@ -92,7 +91,6 @@ const { ERR_INVALID_OPT_VALUE, ERR_SERVER_ALREADY_LISTEN, ERR_SERVER_NOT_RUNNING, - ERR_SOCKET_BAD_PORT, ERR_SOCKET_CLOSED }, errnoException, @@ -100,7 +98,11 @@ const { uvExceptionWithHostPort } = require('internal/errors'); const { isUint8Array } = require('internal/util/types'); -const { validateInt32, validateString } = require('internal/validators'); +const { + validateInt32, + validatePort, + validateString +} = require('internal/validators'); const kLastWriteQueueSize = Symbol('lastWriteQueueSize'); const { DTRACE_NET_SERVER_CONNECTION, @@ -997,9 +999,7 @@ function lookupAndConnect(self, options) { throw new ERR_INVALID_ARG_TYPE('options.port', ['number', 'string'], port); } - if (!isLegalPort(port)) { - throw new ERR_SOCKET_BAD_PORT(port); - } + validatePort(port); } port |= 0; @@ -1436,9 +1436,7 @@ Server.prototype.listen = function(...args) { // or if options.port is normalized as 0 before let backlog; if (typeof options.port === 'number' || typeof options.port === 'string') { - if (!isLegalPort(options.port)) { - throw new ERR_SOCKET_BAD_PORT(options.port); - } + validatePort(options.port, 'options.port'); backlog = options.backlog || backlogFromArgs; // start TCP server listening on host:port if (options.host) { diff --git a/lib/os.js b/lib/os.js index 2cce09211c3fe8..f533c3f18f13fd 100644 --- a/lib/os.js +++ b/lib/os.js @@ -46,8 +46,7 @@ const { getHostname: _getHostname, getInterfaceAddresses: _getInterfaceAddresses, getLoadAvg, - getOSRelease: _getOSRelease, - getOSType: _getOSType, + getOSInformation: _getOSInformation, getPriority: _getPriority, getTotalMem, getUserInfo, @@ -67,17 +66,25 @@ function getCheckedFunction(fn) { }); } +const [ + type, + version, + release +] = _getOSInformation(); + const getHomeDirectory = getCheckedFunction(_getHomeDirectory); const getHostname = getCheckedFunction(_getHostname); const getInterfaceAddresses = getCheckedFunction(_getInterfaceAddresses); -const getOSRelease = getCheckedFunction(_getOSRelease); -const getOSType = getCheckedFunction(_getOSType); +const getOSRelease = () => release; +const getOSType = () => type; +const getOSVersion = () => version; getFreeMem[SymbolToPrimitive] = () => getFreeMem(); getHostname[SymbolToPrimitive] = () => getHostname(); getHomeDirectory[SymbolToPrimitive] = () => getHomeDirectory(); getOSRelease[SymbolToPrimitive] = () => getOSRelease(); getOSType[SymbolToPrimitive] = () => getOSType(); +getOSVersion[SymbolToPrimitive] = () => getOSVersion(); getTotalMem[SymbolToPrimitive] = () => getTotalMem(); getUptime[SymbolToPrimitive] = () => getUptime(); @@ -283,6 +290,7 @@ module.exports = { tmpdir, totalmem: getTotalMem, type: getOSType, + version: getOSVersion, userInfo, uptime: getUptime, diff --git a/lib/path.js b/lib/path.js index c5db4437a52408..7532b795bf63f7 100644 --- a/lib/path.js +++ b/lib/path.js @@ -385,14 +385,14 @@ const win32 = { return '.'; // Make sure that the joined path doesn't start with two slashes, because - // normalize() will mistake it for an UNC path then. + // normalize() will mistake it for a UNC path then. // // This step is skipped when it is very clear that the user actually - // intended to point at an UNC path. This is assumed when the first + // intended to point at a UNC path. This is assumed when the first // non-empty string arguments starts with exactly two slashes followed by // at least one more non-slash character. // - // Note that for normalize() to treat a path as an UNC path it needs to + // Note that for normalize() to treat a path as a UNC path it needs to // have at least 2 components, so we don't filter for that here. // This means that the user can use join to construct UNC paths from // a server name and a share name; for example: diff --git a/lib/perf_hooks.js b/lib/perf_hooks.js index 11a9b5eba6a343..efc92ca8c4aee4 100644 --- a/lib/perf_hooks.js +++ b/lib/perf_hooks.js @@ -407,8 +407,8 @@ class Performance { } clearMarks(name) { - name = name !== undefined ? `${name}` : name; if (name !== undefined) { + name = `${name}`; this[kIndex][kMarks].delete(name); _clearMark(name); } else { diff --git a/lib/readline.js b/lib/readline.js index 3e4f3cf42d3d96..e86fb50b22cec4 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -46,22 +46,26 @@ const { ERR_INVALID_OPT_VALUE } = require('internal/errors').codes; const { validateString } = require('internal/validators'); -const { inspect } = require('internal/util/inspect'); +const { + inspect, + getStringWidth, + stripVTControlCharacters, +} = require('internal/util/inspect'); const EventEmitter = require('events'); const { + charLengthAt, + charLengthLeft, + commonPrefix, CSI, emitKeys, - getStringWidth, - isFullWidthCodePoint, - kUTF16SurrogateThreshold, - stripVTControlCharacters + kSubstringSearch, } = require('internal/readline/utils'); const { clearTimeout, setTimeout } = require('timers'); const { kEscape, - kClearToBeginning, - kClearToEnd, + kClearToLineBeginning, + kClearToLineEnd, kClearLine, kClearScreenDown } = CSI; @@ -95,6 +99,8 @@ function Interface(input, output, completer, terminal) { } this._sawReturnAt = 0; + // TODO(BridgeAR): Document this property. The name is not ideal, so we might + // want to expose an alias and document that instead. this.isCompletionEnabled = true; this._sawKeyPress = false; this._previousKey = null; @@ -152,6 +158,7 @@ function Interface(input, output, completer, terminal) { const self = this; + this[kSubstringSearch] = null; this.output = output; this.input = input; this.historySize = historySize; @@ -487,103 +494,71 @@ Interface.prototype._insertString = function(c) { } else { this._writeToOutput(c); } - - // A hack to get the line refreshed if it's needed - this._moveCursor(0); } }; Interface.prototype._tabComplete = function(lastKeypressWasTab) { - const self = this; - - self.pause(); - self.completer(self.line.slice(0, self.cursor), function onComplete(err, rv) { - self.resume(); + this.pause(); + this.completer(this.line.slice(0, this.cursor), (err, value) => { + this.resume(); if (err) { - self._writeToOutput(`tab completion error ${inspect(err)}`); + this._writeToOutput(`Tab completion error: ${inspect(err)}`); return; } - const completions = rv[0]; - const completeOn = rv[1]; // The text that was completed - if (completions && completions.length) { - // Apply/show completions. - if (lastKeypressWasTab) { - self._writeToOutput('\r\n'); - const width = completions.reduce(function completionReducer(a, b) { - return a.length > b.length ? a : b; - }).length + 2; // 2 space padding - let maxColumns = MathFloor(self.columns / width); - if (!maxColumns || maxColumns === Infinity) { - maxColumns = 1; - } - let group = []; - for (let i = 0; i < completions.length; i++) { - const c = completions[i]; - if (c === '') { - handleGroup(self, group, width, maxColumns); - group = []; - } else { - group.push(c); - } - } - handleGroup(self, group, width, maxColumns); - } + // Result and the text that was completed. + const [completions, completeOn] = value; - // If there is a common prefix to all matches, then apply that portion. - const f = completions.filter((e) => e); - const prefix = commonPrefix(f); - if (prefix.length > completeOn.length) { - self._insertString(prefix.slice(completeOn.length)); - } + if (!completions || completions.length === 0) { + return; + } - self._refreshLine(); + // If there is a common prefix to all matches, then apply that portion. + const prefix = commonPrefix(completions.filter((e) => e !== '')); + if (prefix.length > completeOn.length) { + this._insertString(prefix.slice(completeOn.length)); + return; } - }); -}; -// this = Interface instance -function handleGroup(self, group, width, maxColumns) { - if (group.length === 0) { - return; - } - const minRows = MathCeil(group.length / maxColumns); - for (let row = 0; row < minRows; row++) { - for (let col = 0; col < maxColumns; col++) { - const idx = row * maxColumns + col; - if (idx >= group.length) { - break; + if (!lastKeypressWasTab) { + return; + } + + // Apply/show completions. + const completionsWidth = completions.map((e) => getStringWidth(e)); + const width = MathMax(...completionsWidth) + 2; // 2 space padding + let maxColumns = MathFloor(this.columns / width) || 1; + if (maxColumns === Infinity) { + maxColumns = 1; + } + let output = '\r\n'; + let lineIndex = 0; + let whitespace = 0; + for (let i = 0; i < completions.length; i++) { + const completion = completions[i]; + if (completion === '' || lineIndex === maxColumns) { + output += '\r\n'; + lineIndex = 0; + whitespace = 0; + } else { + output += ' '.repeat(whitespace); } - const item = group[idx]; - self._writeToOutput(item); - if (col < maxColumns - 1) { - for (let s = 0; s < width - item.length; s++) { - self._writeToOutput(' '); - } + if (completion !== '') { + output += completion; + whitespace = width - completionsWidth[i]; + lineIndex++; + } else { + output += '\r\n'; } } - self._writeToOutput('\r\n'); - } - self._writeToOutput('\r\n'); -} - -function commonPrefix(strings) { - if (!strings || strings.length === 0) { - return ''; - } - if (strings.length === 1) return strings[0]; - const sorted = strings.slice().sort(); - const min = sorted[0]; - const max = sorted[sorted.length - 1]; - for (let i = 0, len = min.length; i < len; i++) { - if (min[i] !== max[i]) { - return min.slice(0, i); + if (lineIndex !== 0) { + output += '\r\n\r\n'; } - } - return min; -} - + this._writeToOutput(output); + this._refreshLine(); + }); +}; Interface.prototype._wordLeft = function() { if (this.cursor > 0) { @@ -605,22 +580,6 @@ Interface.prototype._wordRight = function() { } }; -function charLengthLeft(str, i) { - if (i <= 0) - return 0; - if ((i > 1 && str.codePointAt(i - 2) >= kUTF16SurrogateThreshold) || - str.codePointAt(i - 1) >= kUTF16SurrogateThreshold) { - return 2; - } - return 1; -} - -function charLengthAt(str, i) { - if (str.length <= i) - return 0; - return str.codePointAt(i) >= kUTF16SurrogateThreshold ? 2 : 1; -} - Interface.prototype._deleteLeft = function() { if (this.cursor > 0 && this.line.length > 0) { // The number of UTF-16 units comprising the character to the left @@ -699,52 +658,73 @@ Interface.prototype._line = function() { this._onLine(line); }; - +// TODO(BridgeAR): Add underscores to the search part and a red background in +// case no match is found. This should only be the visual part and not the +// actual line content! +// TODO(BridgeAR): In case the substring based search is active and the end is +// reached, show a comment how to search the history as before. E.g., using +// + N. Only show this after two/three UPs or DOWNs, not on the first +// one. Interface.prototype._historyNext = function() { - if (this.historyIndex > 0) { - this.historyIndex--; - this.line = this.history[this.historyIndex]; + if (this.historyIndex >= 0) { + const search = this[kSubstringSearch] || ''; + let index = this.historyIndex - 1; + while (index >= 0 && + (!this.history[index].startsWith(search) || + this.line === this.history[index])) { + index--; + } + if (index === -1) { + this.line = search; + } else { + this.line = this.history[index]; + } + this.historyIndex = index; this.cursor = this.line.length; // Set cursor to end of line. this._refreshLine(); - - } else if (this.historyIndex === 0) { - this.historyIndex = -1; - this.cursor = 0; - this.line = ''; - this._refreshLine(); } }; - Interface.prototype._historyPrev = function() { - if (this.historyIndex + 1 < this.history.length) { - this.historyIndex++; - this.line = this.history[this.historyIndex]; + if (this.historyIndex < this.history.length && this.history.length) { + const search = this[kSubstringSearch] || ''; + let index = this.historyIndex + 1; + while (index < this.history.length && + (!this.history[index].startsWith(search) || + this.line === this.history[index])) { + index++; + } + if (index === this.history.length) { + this.line = search; + } else { + this.line = this.history[index]; + } + this.historyIndex = index; this.cursor = this.line.length; // Set cursor to end of line. - this._refreshLine(); } }; - // Returns the last character's display position of the given string Interface.prototype._getDisplayPos = function(str) { let offset = 0; const col = this.columns; - let row = 0; + let rows = 0; str = stripVTControlCharacters(str); - for (let i = 0, len = str.length; i < len; i++) { - const code = str.codePointAt(i); - if (code >= kUTF16SurrogateThreshold) { // Surrogates. - i++; - } - if (code === 0x0a) { // new line \n - // row must be incremented by 1 even if offset = 0 or col = +Infinity - row += MathCeil(offset / col) || 1; + for (const char of str) { + if (char === '\n') { + // Rows must be incremented by 1 even if offset = 0 or col = +Infinity. + rows += MathCeil(offset / col) || 1; offset = 0; continue; } - const width = getStringWidth(code); + // Tabs must be aligned by an offset of 8. + // TODO(BridgeAR): Make the tab size configurable. + if (char === '\t') { + offset += 8 - (offset % 8); + continue; + } + const width = getStringWidth(char); if (width === 0 || width === 1) { offset += width; } else { // width === 2 @@ -755,60 +735,39 @@ Interface.prototype._getDisplayPos = function(str) { } } const cols = offset % col; - const rows = row + (offset - cols) / col; - return { cols: cols, rows: rows }; + rows += (offset - cols) / col; + return { cols, rows }; }; - // Returns current cursor's position and line Interface.prototype.getCursorPos = function() { - const columns = this.columns; const strBeforeCursor = this._prompt + this.line.substring(0, this.cursor); - const dispPos = this._getDisplayPos( - stripVTControlCharacters(strBeforeCursor)); - let cols = dispPos.cols; - let rows = dispPos.rows; - // If the cursor is on a full-width character which steps over the line, - // move the cursor to the beginning of the next line. - if (cols + 1 === columns && - this.cursor < this.line.length && - isFullWidthCodePoint(this.line.codePointAt(this.cursor))) { - rows++; - cols = 0; - } - return { cols: cols, rows: rows }; + return this._getDisplayPos(strBeforeCursor); }; Interface.prototype._getCursorPos = Interface.prototype.getCursorPos; - // This function moves cursor dx places to the right -// (-dx for left) and refreshes the line if it is needed +// (-dx for left) and refreshes the line if it is needed. Interface.prototype._moveCursor = function(dx) { - const oldcursor = this.cursor; + if (dx === 0) { + return; + } const oldPos = this.getCursorPos(); this.cursor += dx; - // bounds check - if (this.cursor < 0) this.cursor = 0; - else if (this.cursor > this.line.length) this.cursor = this.line.length; + // Bounds check + if (this.cursor < 0) { + this.cursor = 0; + } else if (this.cursor > this.line.length) { + this.cursor = this.line.length; + } const newPos = this.getCursorPos(); - // Check if cursors are in the same line + // Check if cursor stayed on the line. if (oldPos.rows === newPos.rows) { - const diffCursor = this.cursor - oldcursor; - let diffWidth; - if (diffCursor < 0) { - diffWidth = -getStringWidth( - this.line.substring(this.cursor, oldcursor) - ); - } else if (diffCursor > 0) { - diffWidth = getStringWidth( - this.line.substring(this.cursor, oldcursor) - ); - } + const diffWidth = newPos.cols - oldPos.cols; moveCursor(this.output, diffWidth, 0); - this.prevRows = newPos.rows; } else { this._refreshLine(); } @@ -868,6 +827,20 @@ Interface.prototype._ttyWrite = function(s, key) { key = key || {}; this._previousKey = key; + // Activate or deactivate substring search. + if ((key.name === 'up' || key.name === 'down') && + !key.ctrl && !key.meta && !key.shift) { + if (this[kSubstringSearch] === null) { + this[kSubstringSearch] = this.line.slice(0, this.cursor); + } + } else if (this[kSubstringSearch] !== null) { + this[kSubstringSearch] = null; + // Reset the index in case there's no match. + if (this.history.length === this.historyIndex) { + this.historyIndex = -1; + } + } + // Ignore escape key, fixes // https://github.com/nodejs/node-v0.x-archive/issues/2876. if (key.name === 'escape') return; @@ -972,6 +945,7 @@ Interface.prototype._ttyWrite = function(s, key) { } break; + // TODO(BridgeAR): This seems broken? case 'w': // Delete backwards to a word boundary case 'backspace': this._deleteWordLeft(); @@ -1074,8 +1048,7 @@ Interface.prototype._ttyWrite = function(s, key) { this._tabComplete(lastKeypressWasTab); break; } - // falls through - + // falls through default: if (typeof s === 'string' && s) { const lines = s.split(/\r\n|\n|\r/); @@ -1127,7 +1100,7 @@ Interface.prototype[SymbolAsyncIterator] = function() { * accepts a readable Stream instance and makes it emit "keypress" events */ -function emitKeypressEvents(stream, iface) { +function emitKeypressEvents(stream, iface = {}) { if (stream[KEYPRESS_DECODER]) return; stream[KEYPRESS_DECODER] = new StringDecoder('utf8'); @@ -1135,32 +1108,32 @@ function emitKeypressEvents(stream, iface) { stream[ESCAPE_DECODER] = emitKeys(stream); stream[ESCAPE_DECODER].next(); - const escapeCodeTimeout = () => stream[ESCAPE_DECODER].next(''); + const triggerEscape = () => stream[ESCAPE_DECODER].next(''); + const { escapeCodeTimeout = ESCAPE_CODE_TIMEOUT } = iface; let timeoutId; - function onData(b) { + function onData(input) { if (stream.listenerCount('keypress') > 0) { - const r = stream[KEYPRESS_DECODER].write(b); - if (r) { + const string = stream[KEYPRESS_DECODER].write(input); + if (string) { clearTimeout(timeoutId); - let escapeTimeout = ESCAPE_CODE_TIMEOUT; - - if (iface) { - iface._sawKeyPress = r.length === 1; - escapeTimeout = iface.escapeCodeTimeout; - } + // This supports characters of length 2. + iface._sawKeyPress = charLengthAt(string, 0) === string.length; + iface.isCompletionEnabled = false; - for (let i = 0; i < r.length; i++) { - if (r[i] === '\t' && typeof r[i + 1] === 'string' && iface) { - iface.isCompletionEnabled = false; + let length = 0; + for (const character of string) { + length += character.length; + if (length === string.length) { + iface.isCompletionEnabled = true; } try { - stream[ESCAPE_DECODER].next(r[i]); + stream[ESCAPE_DECODER].next(character); // Escape letter at the tail position - if (r[i] === kEscape && i + 1 === r.length) { - timeoutId = setTimeout(escapeCodeTimeout, escapeTimeout); + if (length === string.length && character === kEscape) { + timeoutId = setTimeout(triggerEscape, escapeCodeTimeout); } } catch (err) { // If the generator throws (it could happen in the `keypress` @@ -1168,10 +1141,6 @@ function emitKeypressEvents(stream, iface) { stream[ESCAPE_DECODER] = emitKeys(stream); stream[ESCAPE_DECODER].next(); throw err; - } finally { - if (iface) { - iface.isCompletionEnabled = true; - } } } } @@ -1211,7 +1180,7 @@ function cursorTo(stream, x, y, callback) { if (stream == null || (typeof x !== 'number' && typeof y !== 'number')) { if (typeof callback === 'function') - process.nextTick(callback); + process.nextTick(callback, null); return true; } @@ -1232,7 +1201,7 @@ function moveCursor(stream, dx, dy, callback) { if (stream == null || !(dx || dy)) { if (typeof callback === 'function') - process.nextTick(callback); + process.nextTick(callback, null); return true; } @@ -1266,11 +1235,15 @@ function clearLine(stream, dir, callback) { if (stream === null || stream === undefined) { if (typeof callback === 'function') - process.nextTick(callback); + process.nextTick(callback, null); return true; } - const type = dir < 0 ? kClearToBeginning : dir > 0 ? kClearToEnd : kClearLine; + const type = dir < 0 ? + kClearToLineBeginning : + dir > 0 ? + kClearToLineEnd : + kClearLine; return stream.write(type, callback); } @@ -1284,7 +1257,7 @@ function clearScreenDown(stream, callback) { if (stream === null || stream === undefined) { if (typeof callback === 'function') - process.nextTick(callback); + process.nextTick(callback, null); return true; } diff --git a/lib/repl.js b/lib/repl.js index 19272f2229c702..5fdf4ffb9de8db 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -43,7 +43,6 @@ 'use strict'; const { - ArrayIsArray, Error, MathMax, NumberIsNaN, @@ -54,14 +53,12 @@ const { ObjectGetOwnPropertyNames, ObjectGetPrototypeOf, ObjectKeys, - ObjectPrototypeHasOwnProperty, ObjectSetPrototypeOf, Promise, PromiseRace, RegExp, Set, Symbol, - WeakMap, WeakSet, } = primordials; @@ -80,11 +77,13 @@ const { deprecate } = require('internal/util'); const { inspect } = require('internal/util/inspect'); -const Stream = require('stream'); const vm = require('vm'); const path = require('path'); const fs = require('fs'); const { Interface } = require('readline'); +const { + commonPrefix +} = require('internal/readline/utils'); const { Console } = require('console'); const cjsLoader = require('internal/modules/cjs/loader'); const { Module: CJSModule } = cjsLoader; @@ -106,7 +105,9 @@ const experimentalREPLAwait = require('internal/options').getOptionValue( ); const { isRecoverableError, - kStandaloneREPL + kStandaloneREPL, + setupPreview, + setupReverseSearch, } = require('internal/repl/utils'); const { getOwnNonIndexProperties, @@ -121,7 +122,6 @@ const { } = internalBinding('contextify'); const history = require('internal/repl/history'); -const { setImmediate } = require('timers'); // Lazy-loaded. let processTopLevelAwait; @@ -130,7 +130,6 @@ const globalBuiltins = new Set(vm.runInNewContext('Object.getOwnPropertyNames(globalThis)')); const parentModule = module; -const replMap = new WeakMap(); const domainSet = new WeakSet(); const kBufferedCommandSymbol = Symbol('bufferedCommand'); @@ -215,6 +214,10 @@ function REPLServer(prompt, } } + // TODO(devsnek): Add a test case for custom eval functions. + const preview = options.terminal && + (options.preview !== undefined ? !!options.preview : !eval_); + this.inputStream = options.input; this.outputStream = options.output; this.useColors = !!options.useColors; @@ -290,11 +293,13 @@ function REPLServer(prompt, if (!paused) return; paused = false; let entry; + const tmpCompletionEnabled = self.isCompletionEnabled; while (entry = pausedBuffer.shift()) { - const [type, payload] = entry; + const [type, payload, isCompletionEnabled] = entry; switch (type) { case 'key': { const [d, key] = payload; + self.isCompletionEnabled = isCompletionEnabled; self._ttyWrite(d, key); break; } @@ -306,14 +311,11 @@ function REPLServer(prompt, break; } } + self.isCompletionEnabled = tmpCompletionEnabled; } function defaultEval(code, context, file, cb) { - const { getOptionValue } = require('internal/options'); - const experimentalModules = getOptionValue('--experimental-modules'); - const asyncESM = experimentalModules ? - require('internal/process/esm_loader') : - null; + const asyncESM = require('internal/process/esm_loader'); let result, script, wrappedErr; let err = null; @@ -321,12 +323,12 @@ function REPLServer(prompt, let awaitPromise = false; const input = code; - if (/^\s*{/.test(code) && /}\s*$/.test(code)) { - // It's confusing for `{ a : 1 }` to be interpreted as a block - // statement rather than an object literal. So, we first try - // to wrap it in parentheses, so that it will be interpreted as - // an expression. Note that if the above condition changes, - // lib/internal/repl/utils.js needs to be changed to match. + // It's confusing for `{ a : 1 }` to be interpreted as a block + // statement rather than an object literal. So, we first try + // to wrap it in parentheses, so that it will be interpreted as + // an expression. Note that if the above condition changes, + // lib/internal/repl/utils.js needs to be changed to match. + if (/^\s*{/.test(code) && !/;\s*$/.test(code)) { code = `(${code.trim()})\n`; wrappedCmd = true; } @@ -367,9 +369,9 @@ function REPLServer(prompt, script = vm.createScript(code, { filename: file, displayErrors: true, - importModuleDynamically: experimentalModules ? async (specifier) => { + importModuleDynamically: async (specifier) => { return asyncESM.ESMLoader.import(specifier, parentURL); - } : undefined + } }); } catch (e) { debug('parse error %j', code, e); @@ -557,14 +559,13 @@ function REPLServer(prompt, self.lastError = e; } - const top = replMap.get(self); if (options[kStandaloneREPL] && process.listenerCount('uncaughtException') !== 0) { process.nextTick(() => { process.emit('uncaughtException', e); - top.clearBufferedCommand(); - top.lines.level = []; - top.displayPrompt(); + self.clearBufferedCommand(); + self.lines.level = []; + self.displayPrompt(); }); } else { if (errStack === '') { @@ -590,10 +591,10 @@ function REPLServer(prompt, } // Normalize line endings. errStack += errStack.endsWith('\n') ? '' : '\n'; - top.outputStream.write(errStack); - top.clearBufferedCommand(); - top.lines.level = []; - top.displayPrompt(); + self.outputStream.write(errStack); + self.clearBufferedCommand(); + self.lines.level = []; + self.displayPrompt(); } }); @@ -819,12 +820,24 @@ function REPLServer(prompt, } }); + const { reverseSearch } = setupReverseSearch(this); + + const { + clearPreview, + showPreview + } = setupPreview( + this, + kContextId, + kBufferedCommandSymbol, + preview + ); + // Wrap readline tty to enable editor mode and pausing. const ttyWrite = self._ttyWrite.bind(self); self._ttyWrite = (d, key) => { key = key || {}; if (paused && !(self.breakEvalOnSigint && key.ctrl && key.name === 'c')) { - pausedBuffer.push(['key', [d, key]]); + pausedBuffer.push(['key', [d, key], self.isCompletionEnabled]); return; } if (!self.editorMode || !self.terminal) { @@ -833,13 +846,19 @@ function REPLServer(prompt, self.cursor === 0 && self.line.length === 0) { self.clearLine(); } - ttyWrite(d, key); + clearPreview(); + if (!reverseSearch(d, key)) { + ttyWrite(d, key); + showPreview(); + } return; } // Editor mode if (key.ctrl && !key.shift) { switch (key.name) { + // TODO(BridgeAR): There should not be a special mode necessary for full + // multiline support. case 'd': // End editor mode _turnOffEditorMode(self); sawCtrlD = true; @@ -892,7 +911,6 @@ exports.start = function(prompt, ignoreUndefined, replMode); if (!exports.repl) exports.repl = repl; - replMap.set(repl, repl); return repl; }; @@ -950,7 +968,7 @@ REPLServer.prototype.createContext = function() { } const module = new CJSModule(''); - module.paths = CJSModule._resolveLookupPaths('', parentModule) || []; + module.paths = CJSModule._resolveLookupPaths('', parentModule); ObjectDefineProperty(context, 'module', { configurable: true, @@ -1029,23 +1047,6 @@ REPLServer.prototype.turnOffEditorMode = deprecate( 'REPLServer.turnOffEditorMode() is deprecated', 'DEP0078'); -// A stream to push an array into a REPL -// used in REPLServer.complete -function ArrayStream() { - Stream.call(this); - - this.run = function(data) { - for (let n = 0; n < data.length; n++) - this.emit('data', `${data[n]}\n`); - }; -} -ObjectSetPrototypeOf(ArrayStream.prototype, Stream.prototype); -ObjectSetPrototypeOf(ArrayStream, Stream); -ArrayStream.prototype.readable = true; -ArrayStream.prototype.writable = true; -ArrayStream.prototype.resume = function() {}; -ArrayStream.prototype.write = function() {}; - const requireRE = /\brequire\s*\(['"](([\w@./-]+\/)?(?:[\w@./-]*))/; const fsAutoCompleteRE = /fs(?:\.promises)?\.\s*[a-z][a-zA-Z]+\(\s*["'](.*)/; const simpleExpressionRE = @@ -1094,6 +1095,9 @@ REPLServer.prototype.complete = function() { this.completer.apply(this, arguments); }; +// TODO: Native module names should be auto-resolved. +// That improves the auto completion. + // Provide a list of completions for the given leading text. This is // given to the readline interface for handling tab completion. // @@ -1105,40 +1109,13 @@ REPLServer.prototype.complete = function() { // Warning: This eval's code like "foo.bar.baz", so it will run property // getter code. function complete(line, callback) { - // There may be local variables to evaluate, try a nested REPL - if (this[kBufferedCommandSymbol] !== undefined && - this[kBufferedCommandSymbol].length) { - // Get a new array of inputted lines - const tmp = this.lines.slice(); - // Kill off all function declarations to push all local variables into - // global scope - for (let n = 0; n < this.lines.level.length; n++) { - const kill = this.lines.level[n]; - if (kill.isFunction) - tmp[kill.line] = ''; - } - const flat = new ArrayStream(); // Make a new "input" stream. - const magic = new REPLServer('', flat); // Make a nested REPL. - replMap.set(magic, replMap.get(this)); - flat.run(tmp); // `eval` the flattened code. - // All this is only profitable if the nested REPL does not have a - // bufferedCommand. - if (!magic[kBufferedCommandSymbol]) { - magic._domain.on('error', (err) => { - if (!cjsLoader.asyncRunMain) - throw err; - setImmediate(() => { - throw err; - }); - }); - return magic.complete(line, callback); - } - } - // List of completion lists, one for each inheritance "level" let completionGroups = []; let completeOn, group; + // Ignore right whitespace. It could change the outcome. + line = line.trimLeft(); + // REPL commands (e.g. ".break"). let filter; let match = line.match(/^\s*\.(\w*)$/); @@ -1160,7 +1137,7 @@ function complete(line, callback) { completeOn = match[1]; const subdir = match[2] || ''; filter = match[1]; - let dir, files, name, base, ext, abs, subfiles, isDirectory; + let dir, files, subfiles, isDirectory; group = []; let paths = []; @@ -1182,14 +1159,14 @@ function complete(line, callback) { continue; } for (let f = 0; f < files.length; f++) { - name = files[f]; - ext = path.extname(name); - base = name.slice(0, -ext.length); + const name = files[f]; + const ext = path.extname(name); + const base = name.slice(0, -ext.length); if (versionedFileNamesRe.test(base) || name === '.npm') { // Exclude versioned names that 'npm' installs. continue; } - abs = path.resolve(dir, name); + const abs = path.resolve(dir, name); try { isDirectory = fs.statSync(abs).isDirectory(); } catch { @@ -1257,109 +1234,87 @@ function complete(line, callback) { // foo.<|> # completions for 'foo' with filter '' } else if (line.length === 0 || /\w|\.|\$/.test(line[line.length - 1])) { match = simpleExpressionRE.exec(line); - if (line.length === 0 || match) { - let expr; - completeOn = (match ? match[0] : ''); - if (line.length === 0) { - filter = ''; - expr = ''; - } else if (line[line.length - 1] === '.') { - filter = ''; - expr = match[0].slice(0, match[0].length - 1); - } else { - const bits = match[0].split('.'); - filter = bits.pop(); - expr = bits.join('.'); + if (line.length !== 0 && !match) { + completionGroupsLoaded(); + return; + } + let expr; + completeOn = (match ? match[0] : ''); + if (line.length === 0) { + filter = ''; + expr = ''; + } else if (line[line.length - 1] === '.') { + filter = ''; + expr = match[0].slice(0, match[0].length - 1); + } else { + const bits = match[0].split('.'); + filter = bits.pop(); + expr = bits.join('.'); + } + + // Resolve expr and get its completions. + const memberGroups = []; + if (!expr) { + // Get global vars synchronously + completionGroups.push(getGlobalLexicalScopeNames(this[kContextId])); + let contextProto = this.context; + while (contextProto = ObjectGetPrototypeOf(contextProto)) { + completionGroups.push(filteredOwnPropertyNames(contextProto)); + } + const contextOwnNames = filteredOwnPropertyNames(this.context); + if (!this.useGlobal) { + // When the context is not `global`, builtins are not own + // properties of it. + contextOwnNames.push(...globalBuiltins); } + completionGroups.push(contextOwnNames); + if (filter !== '') addCommonWords(completionGroups); + completionGroupsLoaded(); + return; + } - // Resolve expr and get its completions. - const memberGroups = []; - if (!expr) { - // If context is instance of vm.ScriptContext - // Get global vars synchronously - if (this.useGlobal || vm.isContext(this.context)) { - completionGroups.push(getGlobalLexicalScopeNames(this[kContextId])); - let contextProto = this.context; - while (contextProto = ObjectGetPrototypeOf(contextProto)) { - completionGroups.push( - filteredOwnPropertyNames.call(this, contextProto)); - } - const contextOwnNames = - filteredOwnPropertyNames.call(this, this.context); - if (!this.useGlobal) { - // When the context is not `global`, builtins are not own - // properties of it. - contextOwnNames.push(...globalBuiltins); + const evalExpr = `try { ${expr} } catch {}`; + this.eval(evalExpr, this.context, 'repl', (e, obj) => { + if (obj != null) { + if (typeof obj === 'object' || typeof obj === 'function') { + try { + memberGroups.push(filteredOwnPropertyNames(obj)); + } catch { + // Probably a Proxy object without `getOwnPropertyNames` trap. + // We simply ignore it here, as we don't want to break the + // autocompletion. Fixes the bug + // https://github.com/nodejs/node/issues/2119 } - completionGroups.push(contextOwnNames); - if (filter !== '') addCommonWords(completionGroups); - completionGroupsLoaded(); - } else { - this.eval('.scope', this.context, 'repl', function ev(err, globals) { - if (err || !ArrayIsArray(globals)) { - if (filter !== '') addCommonWords(completionGroups); - } else if (ArrayIsArray(globals[0])) { - // Add grouped globals - for (let n = 0; n < globals.length; n++) - completionGroups.push(globals[n]); - } else { - completionGroups.push(globals); - if (filter !== '') addCommonWords(completionGroups); - } - completionGroupsLoaded(); - }); } - } else { - const evalExpr = `try { ${expr} } catch {}`; - this.eval(evalExpr, this.context, 'repl', (e, obj) => { - if (obj != null) { - if (typeof obj === 'object' || typeof obj === 'function') { - try { - memberGroups.push(filteredOwnPropertyNames.call(this, obj)); - } catch { - // Probably a Proxy object without `getOwnPropertyNames` trap. - // We simply ignore it here, as we don't want to break the - // autocompletion. Fixes the bug - // https://github.com/nodejs/node/issues/2119 - } - } - // Works for non-objects - try { - let sentinel = 5; - let p; - if (typeof obj === 'object' || typeof obj === 'function') { - p = ObjectGetPrototypeOf(obj); - } else { - p = obj.constructor ? obj.constructor.prototype : null; - } - while (p !== null) { - memberGroups.push(filteredOwnPropertyNames.call(this, p)); - p = ObjectGetPrototypeOf(p); - // Circular refs possible? Let's guard against that. - sentinel--; - if (sentinel <= 0) { - break; - } - } - } catch {} + // Works for non-objects + try { + let p; + if (typeof obj === 'object' || typeof obj === 'function') { + p = ObjectGetPrototypeOf(obj); + } else { + p = obj.constructor ? obj.constructor.prototype : null; } - - if (memberGroups.length) { - for (let i = 0; i < memberGroups.length; i++) { - completionGroups.push( - memberGroups[i].map((member) => `${expr}.${member}`)); - } - if (filter) { - filter = `${expr}.${filter}`; - } + // Circular refs possible? Let's guard against that. + let sentinel = 5; + while (p !== null && sentinel-- !== 0) { + memberGroups.push(filteredOwnPropertyNames(p)); + p = ObjectGetPrototypeOf(p); } + } catch {} + } - completionGroupsLoaded(); - }); + if (memberGroups.length) { + for (let i = 0; i < memberGroups.length; i++) { + completionGroups.push( + memberGroups[i].map((member) => `${expr}.${member}`)); + } + if (filter) { + filter = `${expr}.${filter}`; + } } - } else { + completionGroupsLoaded(); - } + }); } else { completionGroupsLoaded(); } @@ -1380,67 +1335,46 @@ function complete(line, callback) { completionGroups = newCompletionGroups; } - let completions; - - if (completionGroups.length) { - const uniq = {}; // Unique completions across all groups - completions = []; - // Completion group 0 is the "closest" - // (least far up the inheritance chain) - // so we put its completions last: to be closest in the REPL. - for (let i = 0; i < completionGroups.length; i++) { - group = completionGroups[i]; - group.sort(); - for (let j = group.length - 1; j >= 0; j--) { - const c = group[j]; - if (!ObjectPrototypeHasOwnProperty(uniq, c)) { - completions.unshift(c); - uniq[c] = true; - } + const completions = []; + // Unique completions across all groups. + const uniqueSet = new Set(['']); + // Completion group 0 is the "closest" (least far up the inheritance + // chain) so we put its completions last: to be closest in the REPL. + for (const group of completionGroups) { + group.sort((a, b) => (b > a ? 1 : -1)); + const setSize = uniqueSet.size; + for (const entry of group) { + if (!uniqueSet.has(entry)) { + completions.unshift(entry); + uniqueSet.add(entry); } - completions.unshift(''); // Separator btwn groups } - while (completions.length && completions[0] === '') { - completions.shift(); + // Add a separator between groups. + if (uniqueSet.size !== setSize) { + completions.unshift(''); } } - callback(null, [completions || [], completeOn]); - } -} - -function longestCommonPrefix(arr = []) { - const cnt = arr.length; - if (cnt === 0) return ''; - if (cnt === 1) return arr[0]; - - const first = arr[0]; - // complexity: O(m * n) - for (let m = 0; m < first.length; m++) { - const c = first[m]; - for (let n = 1; n < cnt; n++) { - const entry = arr[n]; - if (m >= entry.length || c !== entry[m]) { - return first.substring(0, m); - } + // Remove obsolete group entry, if present. + if (completions[0] === '') { + completions.shift(); } + + callback(null, [completions, completeOn]); } - return first; } REPLServer.prototype.completeOnEditorMode = (callback) => (err, results) => { if (err) return callback(err); const [completions, completeOn = ''] = results; - const prefixLength = completeOn.length; + let result = completions.filter((v) => v); - if (prefixLength === 0) return callback(null, [[], completeOn]); - - const isNotEmpty = (v) => v.length > 0; - const trimCompleteOnPrefix = (v) => v.substring(prefixLength); - const data = completions.filter(isNotEmpty).map(trimCompleteOnPrefix); + if (completeOn && result.length !== 0) { + result = [commonPrefix(result)]; + } - callback(null, [[`${completeOn}${longestCommonPrefix(data)}`], completeOn]); + callback(null, [result, completeOn]); }; REPLServer.prototype.defineCommand = function(keyword, cmd) { @@ -1457,6 +1391,9 @@ REPLServer.prototype.memory = deprecate( 'REPLServer.memory() is deprecated', 'DEP0082'); +// TODO(BridgeAR): This should be replaced with acorn to build an AST. The +// language became more complex and using a simple approach like this is not +// sufficient anymore. function _memory(cmd) { const self = this; self.lines = self.lines || []; @@ -1464,7 +1401,6 @@ function _memory(cmd) { // Save the line so I can do magic later if (cmd) { - // TODO should I tab the level? const len = self.lines.level.length ? self.lines.level.length - 1 : 0; self.lines.push(' '.repeat(len) + cmd); } else { @@ -1472,61 +1408,54 @@ function _memory(cmd) { self.lines.push(''); } + if (!cmd) { + self.lines.level = []; + return; + } + // I need to know "depth." // Because I can not tell the difference between a } that // closes an object literal and a } that closes a function - if (cmd) { - // Going down is { and ( e.g. function() { - // going up is } and ) - let dw = cmd.match(/[{(]/g); - let up = cmd.match(/[})]/g); - up = up ? up.length : 0; - dw = dw ? dw.length : 0; - let depth = dw - up; - - if (depth) { - (function workIt() { - if (depth > 0) { - // Going... down. - // Push the line#, depth count, and if the line is a function. - // Since JS only has functional scope I only need to remove - // "function() {" lines, clearly this will not work for - // "function() - // {" but nothing should break, only tab completion for local - // scope will not work for this function. - self.lines.level.push({ - line: self.lines.length - 1, - depth: depth, - isFunction: /\bfunction\b/.test(cmd) - }); - } else if (depth < 0) { - // Going... up. - const curr = self.lines.level.pop(); - if (curr) { - const tmp = curr.depth + depth; - if (tmp < 0) { - // More to go, recurse - depth += curr.depth; - workIt(); - } else if (tmp > 0) { - // Remove and push back - curr.depth += depth; - self.lines.level.push(curr); - } + + // Going down is { and ( e.g. function() { + // going up is } and ) + let dw = cmd.match(/[{(]/g); + let up = cmd.match(/[})]/g); + up = up ? up.length : 0; + dw = dw ? dw.length : 0; + let depth = dw - up; + + if (depth) { + (function workIt() { + if (depth > 0) { + // Going... down. + // Push the line#, depth count, and if the line is a function. + // Since JS only has functional scope I only need to remove + // "function() {" lines, clearly this will not work for + // "function() + // {" but nothing should break, only tab completion for local + // scope will not work for this function. + self.lines.level.push({ + line: self.lines.length - 1, + depth: depth + }); + } else if (depth < 0) { + // Going... up. + const curr = self.lines.level.pop(); + if (curr) { + const tmp = curr.depth + depth; + if (tmp < 0) { + // More to go, recurse + depth += curr.depth; + workIt(); + } else if (tmp > 0) { + // Remove and push back + curr.depth += depth; + self.lines.level.push(curr); } } - }()); - } - - // It is possible to determine a syntax error at this point. - // if the REPL still has a bufferedCommand and - // self.lines.level.length === 0 - // TODO? keep a log of level so that any syntax breaking lines can - // be cleared on .break and in the case of a syntax error? - // TODO? if a log was kept, then I could clear the bufferedCommand and - // eval these lines and throw the syntax error - } else { - self.lines.level = []; + } + }()); } } diff --git a/lib/timers.js b/lib/timers.js index 5904ec9bd3b533..324752506c7a86 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -53,8 +53,8 @@ const { promisify: { custom: customPromisify }, deprecate } = require('internal/util'); -const { ERR_INVALID_CALLBACK } = require('internal/errors').codes; const debug = require('internal/util/debuglog').debuglog('timer'); +const { validateCallback } = require('internal/validators'); const { destroyHooksExist, @@ -118,9 +118,7 @@ function enroll(item, msecs) { function setTimeout(callback, after, arg1, arg2, arg3) { - if (typeof callback !== 'function') { - throw new ERR_INVALID_CALLBACK(callback); - } + validateCallback(callback); let i, args; switch (arguments.length) { @@ -165,9 +163,7 @@ function clearTimeout(timer) { } function setInterval(callback, repeat, arg1, arg2, arg3) { - if (typeof callback !== 'function') { - throw new ERR_INVALID_CALLBACK(callback); - } + validateCallback(callback); let i, args; switch (arguments.length) { @@ -249,9 +245,7 @@ const Immediate = class Immediate { }; function setImmediate(callback, arg1, arg2, arg3) { - if (typeof callback !== 'function') { - throw new ERR_INVALID_CALLBACK(callback); - } + validateCallback(callback); let i, args; switch (arguments.length) { diff --git a/lib/tls.js b/lib/tls.js index 281de073c49574..2ccbe409c96c2d 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -56,8 +56,7 @@ const _tls_wrap = require('_tls_wrap'); exports.CLIENT_RENEG_LIMIT = 3; exports.CLIENT_RENEG_WINDOW = 600; -exports.DEFAULT_CIPHERS = - internalBinding('constants').crypto.defaultCipherList; +exports.DEFAULT_CIPHERS = getOptionValue('--tls-cipher-list'); exports.DEFAULT_ECDH_CURVE = 'auto'; diff --git a/lib/v8.js b/lib/v8.js index a648d995404836..5841f204986fd7 100644 --- a/lib/v8.js +++ b/lib/v8.js @@ -25,7 +25,6 @@ const { Int8Array, Map, ObjectPrototypeToString, - Symbol, Uint16Array, Uint32Array, Uint8Array, @@ -48,14 +47,7 @@ const { createHeapSnapshotStream, triggerHeapSnapshot } = internalBinding('heap_utils'); -const { Readable } = require('stream'); -const { owner_symbol } = require('internal/async_hooks').symbols; -const { - kUpdateTimer, - onStreamRead, -} = require('internal/stream_base_commons'); -const kHandle = Symbol('kHandle'); - +const { HeapSnapshotStream } = require('internal/heap_utils'); function writeHeapSnapshot(filename) { if (filename !== undefined) { @@ -65,31 +57,6 @@ function writeHeapSnapshot(filename) { return triggerHeapSnapshot(filename); } -class HeapSnapshotStream extends Readable { - constructor(handle) { - super({ autoDestroy: true }); - this[kHandle] = handle; - handle[owner_symbol] = this; - handle.onread = onStreamRead; - } - - _read() { - if (this[kHandle]) - this[kHandle].readStart(); - } - - _destroy() { - // Release the references on the handle so that - // it can be garbage collected. - this[kHandle][owner_symbol] = undefined; - this[kHandle] = undefined; - } - - [kUpdateTimer]() { - // Does nothing - } -} - function getHeapSnapshot() { const handle = createHeapSnapshotStream(); assert(handle); @@ -321,5 +288,5 @@ module.exports = { DefaultDeserializer, deserialize, serialize, - writeHeapSnapshot + writeHeapSnapshot, }; diff --git a/lib/wasi.js b/lib/wasi.js index ea2e2b794b22d7..a6dee9498463dc 100644 --- a/lib/wasi.js +++ b/lib/wasi.js @@ -1,7 +1,6 @@ 'use strict'; /* global WebAssembly */ const { - ArrayIsArray, ArrayPrototypeMap, ArrayPrototypePush, FunctionPrototypeBind, @@ -13,7 +12,13 @@ const { ERR_WASI_ALREADY_STARTED } = require('internal/errors').codes; const { emitExperimentalWarning } = require('internal/util'); +const { + validateArray, + validateBoolean, + validateObject, +} = require('internal/validators'); const { WASI: _WASI } = internalBinding('wasi'); +const kExitCode = Symbol('exitCode'); const kSetMemory = Symbol('setMemory'); const kStarted = Symbol('started'); @@ -22,49 +27,46 @@ emitExperimentalWarning('WASI'); class WASI { constructor(options = {}) { - if (options === null || typeof options !== 'object') - throw new ERR_INVALID_ARG_TYPE('options', 'object', options); - - const { env, preopens } = options; - let { args = [] } = options; - - if (ArrayIsArray(args)) - args = ArrayPrototypeMap(args, (arg) => { return String(arg); }); - else - throw new ERR_INVALID_ARG_TYPE('options.args', 'Array', args); + validateObject(options, 'options'); - const envPairs = []; + if (options.args !== undefined) + validateArray(options.args, 'options.args'); + const args = ArrayPrototypeMap(options.args || [], String); - if (env !== null && typeof env === 'object') { - for (const key in env) { - const value = env[key]; + const env = []; + if (options.env !== undefined) { + validateObject(options.env, 'options.env'); + for (const [key, value] of ObjectEntries(options.env)) { if (value !== undefined) - ArrayPrototypePush(envPairs, `${key}=${value}`); + ArrayPrototypePush(env, `${key}=${value}`); } - } else if (env !== undefined) { - throw new ERR_INVALID_ARG_TYPE('options.env', 'Object', env); } - const preopenArray = []; - - if (typeof preopens === 'object' && preopens !== null) { - for (const [key, value] of ObjectEntries(preopens)) { - ArrayPrototypePush(preopenArray, String(key), String(value)); + const preopens = []; + if (options.preopens !== undefined) { + validateObject(options.preopens, 'options.preopens'); + for (const [key, value] of ObjectEntries(options.preopens)) { + ArrayPrototypePush(preopens, String(key), String(value)); } - } else if (preopens !== undefined) { - throw new ERR_INVALID_ARG_TYPE('options.preopens', 'Object', preopens); } - const wrap = new _WASI(args, envPairs, preopenArray); + const wrap = new _WASI(args, env, preopens); for (const prop in wrap) { wrap[prop] = FunctionPrototypeBind(wrap[prop], wrap); } + if (options.returnOnExit !== undefined) { + validateBoolean(options.returnOnExit, 'options.returnOnExit'); + if (options.returnOnExit) + wrap.proc_exit = FunctionPrototypeBind(wasiReturnOnProcExit, this); + } + this[kSetMemory] = wrap._setMemory; delete wrap._setMemory; this.wasiImport = wrap; this[kStarted] = false; + this[kExitCode] = 0; } start(instance) { @@ -75,10 +77,19 @@ class WASI { const exports = instance.exports; - if (exports === null || typeof exports !== 'object') - throw new ERR_INVALID_ARG_TYPE('instance.exports', 'Object', exports); + validateObject(exports, 'instance.exports'); + + const { _initialize, _start, memory } = exports; + + if (typeof _start !== 'function') { + throw new ERR_INVALID_ARG_TYPE( + 'instance.exports._start', 'function', _start); + } - const { memory } = exports; + if (_initialize !== undefined) { + throw new ERR_INVALID_ARG_TYPE( + 'instance.exports._initialize', 'undefined', _initialize); + } if (!(memory instanceof WebAssembly.Memory)) { throw new ERR_INVALID_ARG_TYPE( @@ -92,12 +103,27 @@ class WASI { this[kStarted] = true; this[kSetMemory](memory); - if (exports._start) + try { exports._start(); - else if (exports.__wasi_unstable_reactor_start) - exports.__wasi_unstable_reactor_start(); + } catch (err) { + if (err !== kExitCode) { + throw err; + } + } + + return this[kExitCode]; } } module.exports = { WASI }; + + +function wasiReturnOnProcExit(rval) { + // If __wasi_proc_exit() does not terminate the process, an assertion is + // triggered in the wasm runtime. Node can sidestep the assertion and return + // an exit code by recording the exit code, and throwing a JavaScript + // exception that WebAssembly cannot catch. + this[kExitCode] = rval; + throw kExitCode; +} diff --git a/node.gyp b/node.gyp index 784ce677c3d081..c0e2dbe908ecb6 100644 --- a/node.gyp +++ b/node.gyp @@ -24,6 +24,7 @@ 'node_core_target_name%': 'node', 'node_lib_target_name%': 'libnode', 'node_intermediate_lib_type%': 'static_library', + 'node_builtin_modules_path%': '', 'library_files': [ 'lib/internal/bootstrap/environment.js', 'lib/internal/bootstrap/loaders.js', @@ -137,6 +138,7 @@ 'lib/internal/fs/utils.js', 'lib/internal/fs/watchers.js', 'lib/internal/http.js', + 'lib/internal/heap_utils.js', 'lib/internal/histogram.js', 'lib/internal/idna.js', 'lib/internal/inspector_async_hook.js', @@ -211,6 +213,7 @@ 'lib/internal/vm/module.js', 'lib/internal/worker.js', 'lib/internal/worker/io.js', + 'lib/internal/watchdog.js', 'lib/internal/streams/lazy_transform.js', 'lib/internal/streams/async_iterator.js', 'lib/internal/streams/buffer_list.js', @@ -246,6 +249,11 @@ 'node_mksnapshot_exec': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)node_mksnapshot<(EXECUTABLE_SUFFIX)', 'mkcodecache_exec': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)mkcodecache<(EXECUTABLE_SUFFIX)', 'conditions': [ + ['GENERATOR == "ninja"', { + 'node_text_start_object_path': 'src/large_pages/node_text_start.node_text_start.o' + }, { + 'node_text_start_object_path': 'node_text_start/src/large_pages/node_text_start.o' + }], [ 'node_shared=="true"', { 'node_target_type%': 'shared_library', 'conditions': [ @@ -309,11 +317,26 @@ }, 'targets': [ + { + 'target_name': 'node_text_start', + 'type': 'none', + 'conditions': [ + [ 'OS in "linux freebsd" and ' + 'target_arch=="x64"', { + 'type': 'static_library', + 'sources': [ + 'src/large_pages/node_text_start.S' + ] + }], + ] + }, { 'target_name': '<(node_core_target_name)', 'type': 'executable', 'defines': [ + 'NODE_ARCH="<(target_arch)"', + 'NODE_PLATFORM="<(OS)"', 'NODE_WANT_INTERNALS=1', ], @@ -401,13 +424,6 @@ 'OTHER_LDFLAGS': [ '-Wl,-rpath,@loader_path', ], }, }], - [ 'node_report=="true"', { - 'defines': [ - 'NODE_REPORT', - 'NODE_ARCH="<(target_arch)"', - 'NODE_PLATFORM="<(OS)"', - ], - }], ['OS=="win"', { 'libraries': [ 'Dbghelp.lib', @@ -494,6 +510,13 @@ 'src/node_snapshot_stub.cc' ], }], + [ 'OS in "linux freebsd" and ' + 'target_arch=="x64"', { + 'dependencies': [ 'node_text_start' ], + 'ldflags+': [ + '<(obj_dir)/<(node_text_start_object_path)' + ] + }], ], }, # node_core_target_name { @@ -536,6 +559,7 @@ 'src/js_native_api_v8.h', 'src/js_native_api_v8_internals.h', 'src/js_stream.cc', + 'src/json_utils.cc', 'src/module_wrap.cc', 'src/node.cc', 'src/node_api.cc', @@ -567,7 +591,11 @@ 'src/node_process_events.cc', 'src/node_process_methods.cc', 'src/node_process_object.cc', + 'src/node_report.cc', + 'src/node_report_module.cc', + 'src/node_report_utils.cc', 'src/node_serdes.cc', + 'src/node_sockaddr.cc', 'src/node_stat_watcher.cc', 'src/node_symbols.cc', 'src/node_task_queue.cc', @@ -619,6 +647,9 @@ 'src/histogram-inl.h', 'src/http_parser_adaptor.h', 'src/js_stream.h', + 'src/json_utils.h', + 'src/large_pages/node_large_page.cc', + 'src/large_pages/node_large_page.h', 'src/memory_tracker.h', 'src/memory_tracker-inl.h', 'src/module_wrap.h', @@ -654,8 +685,11 @@ 'src/node_perf_common.h', 'src/node_platform.h', 'src/node_process.h', + 'src/node_report.h', 'src/node_revert.h', 'src/node_root_certs.h', + 'src/node_sockaddr.h', + 'src/node_sockaddr-inl.h', 'src/node_stat_watcher.h', 'src/node_union_bytes.h', 'src/node_url.h', @@ -715,6 +749,9 @@ 'msvs_disabled_warnings!': [4244], 'conditions': [ + [ 'node_builtin_modules_path!=""', { + 'defines': [ 'NODE_BUILTIN_MODULES_PATH="<(node_builtin_modules_path)"' ] + }], [ 'node_shared=="true"', { 'sources': [ 'src/node_snapshot_stub.cc', @@ -747,6 +784,7 @@ 'libraries': [ 'Dbghelp', 'Psapi', + 'Ws2_32', ], }], [ 'node_use_etw=="true"', { @@ -831,31 +869,10 @@ 'src/tls_wrap.h' ], }], - [ 'node_report=="true"', { - 'sources': [ - 'src/node_report.cc', - 'src/node_report_module.cc', - 'src/node_report_utils.cc', - ], - 'defines': [ - 'NODE_REPORT', - 'NODE_ARCH="<(target_arch)"', - 'NODE_PLATFORM="<(OS)"', - ], - 'conditions': [ - ['OS=="win"', { - 'libraries': [ 'Ws2_32' ], - }], - ], - }], - [ 'node_use_large_pages=="true" and OS in "linux freebsd mac"', { + [ 'OS in "linux freebsd mac" and ' + 'target_arch=="x64" and ' + 'node_target_type=="executable"', { 'defines': [ 'NODE_ENABLE_LARGE_CODE_PAGES=1' ], - # The current implementation of Large Pages is under Linux. - # Other implementations are possible but not currently supported. - 'sources': [ - 'src/large_pages/node_large_page.cc', - 'src/large_pages/node_large_page.h' - ], }], [ 'use_openssl_def==1', { # TODO(bnoordhuis) Make all platforms export the same list of symbols. @@ -1108,7 +1125,11 @@ 'test/cctest', ], - 'defines': [ 'NODE_WANT_INTERNALS=1' ], + 'defines': [ + 'NODE_ARCH="<(target_arch)"', + 'NODE_PLATFORM="<(OS)"', + 'NODE_WANT_INTERNALS=1', + ], 'sources': [ 'src/node_snapshot_stub.cc', @@ -1125,6 +1146,8 @@ 'test/cctest/test_linked_binding.cc', 'test/cctest/test_per_process.cc', 'test/cctest/test_platform.cc', + 'test/cctest/test_json_utils.cc', + 'test/cctest/test_sockaddr.cc', 'test/cctest/test_traced_value.cc', 'test/cctest/test_util.cc', 'test/cctest/test_url.cc', @@ -1161,21 +1184,6 @@ 'OTHER_LDFLAGS': [ '-Wl,-rpath,@loader_path', ], }, }], - [ 'node_report=="true"', { - 'sources': [ - 'test/cctest/test_report_util.cc', - ], - 'defines': [ - 'NODE_REPORT', - 'NODE_ARCH="<(target_arch)"', - 'NODE_PLATFORM="<(OS)"', - ], - 'conditions': [ - ['OS=="win"', { - 'libraries': [ 'Ws2_32' ], - }], - ], - }], ['OS=="win"', { 'libraries': [ 'Dbghelp.lib', diff --git a/node.gypi b/node.gypi index ff6c36c4b82ea9..116c1c7149425b 100644 --- a/node.gypi +++ b/node.gypi @@ -317,24 +317,6 @@ 'ldflags': [ '-Wl,-z,relro', '-Wl,-z,now' ] }], - [ 'OS=="linux" and ' - 'target_arch=="x64" and ' - 'node_use_large_pages=="true" and ' - 'node_use_large_pages_script_lld=="false"', { - 'ldflags': [ - '-Wl,-T', - ' * To get to the form to start a job, click on `Build with Parameters`. (If you don't see it, that probably means you are not logged in!) Click it now! * To start CI testing from this screen, you need to fill in two elements on @@ -200,7 +200,7 @@ needs to be pointed out separately during the onboarding. ## Exercise: Make a PR adding yourself to the README * Example: - https://github.com/nodejs/node/commit/ce986de829457c39257cd205067602e765768fb0 + * For raw commit message: `git log ce986de829457c39257cd205067602e765768fb0 -1` * Collaborators are in alphabetical order by GitHub username. diff --git a/src/api/callback.cc b/src/api/callback.cc index 5e3fd6590332ec..f7e7ddedfae377 100644 --- a/src/api/callback.cc +++ b/src/api/callback.cc @@ -36,7 +36,7 @@ CallbackScope::~CallbackScope() { InternalCallbackScope::InternalCallbackScope(AsyncWrap* async_wrap, int flags) : InternalCallbackScope(async_wrap->env(), - async_wrap->object(), + async_wrap->GetResource(), { async_wrap->get_async_id(), async_wrap->get_trigger_async_id() }, flags) {} @@ -50,7 +50,6 @@ InternalCallbackScope::InternalCallbackScope(Environment* env, object_(object), skip_hooks_(flags & kSkipAsyncHooks), skip_task_queues_(flags & kSkipTaskQueues) { - CHECK_IMPLIES(!(flags & kAllowEmptyResource), !object.IsEmpty()); CHECK_NOT_NULL(env); env->PushAsyncCallbackScope(); @@ -63,15 +62,16 @@ InternalCallbackScope::InternalCallbackScope(Environment* env, // If you hit this assertion, you forgot to enter the v8::Context first. CHECK_EQ(Environment::GetCurrent(env->isolate()), env); + env->async_hooks()->push_async_context( + async_context_.async_id, async_context_.trigger_async_id, object); + + pushed_ids_ = true; + if (asyncContext.async_id != 0 && !skip_hooks_) { // No need to check a return value because the application will exit if // an exception occurs. AsyncWrap::EmitBefore(env, asyncContext.async_id); } - - env->async_hooks()->push_async_ids(async_context_.async_id, - async_context_.trigger_async_id); - pushed_ids_ = true; } InternalCallbackScope::~InternalCallbackScope() { @@ -88,15 +88,15 @@ void InternalCallbackScope::Close() { env_->async_hooks()->clear_async_id_stack(); } + if (!failed_ && async_context_.async_id != 0 && !skip_hooks_) { + AsyncWrap::EmitAfter(env_, async_context_.async_id); + } + if (pushed_ids_) - env_->async_hooks()->pop_async_id(async_context_.async_id); + env_->async_hooks()->pop_async_context(async_context_.async_id); if (failed_) return; - if (async_context_.async_id != 0 && !skip_hooks_) { - AsyncWrap::EmitAfter(env_, async_context_.async_id); - } - if (env_->async_callback_scope_depth() > 1 || skip_task_queues_) { return; } @@ -139,6 +139,7 @@ void InternalCallbackScope::Close() { } MaybeLocal InternalMakeCallback(Environment* env, + Local resource, Local recv, const Local callback, int argc, @@ -150,7 +151,7 @@ MaybeLocal InternalMakeCallback(Environment* env, CHECK(!argv[i].IsEmpty()); #endif - InternalCallbackScope scope(env, recv, asyncContext); + InternalCallbackScope scope(env, resource, asyncContext); if (scope.Failed()) { return MaybeLocal(); } @@ -224,7 +225,7 @@ MaybeLocal MakeCallback(Isolate* isolate, CHECK_NOT_NULL(env); Context::Scope context_scope(env->context()); MaybeLocal ret = - InternalMakeCallback(env, recv, callback, argc, argv, asyncContext); + InternalMakeCallback(env, recv, recv, callback, argc, argv, asyncContext); if (ret.IsEmpty() && env->async_callback_scope_depth() == 0) { // This is only for legacy compatibility and we may want to look into // removing/adjusting it. diff --git a/src/api/environment.cc b/src/api/environment.cc index 1df70cf6a6d44d..09d71b34581268 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -14,15 +14,16 @@ using v8::Context; using v8::EscapableHandleScope; using v8::FinalizationGroup; using v8::Function; +using v8::FunctionCallbackInfo; using v8::HandleScope; using v8::Isolate; using v8::Local; using v8::MaybeLocal; -using v8::MicrotasksPolicy; using v8::Null; using v8::Object; using v8::ObjectTemplate; using v8::Private; +using v8::PropertyDescriptor; using v8::String; using v8::Value; @@ -87,10 +88,34 @@ static void HostCleanupFinalizationGroupCallback( } void* NodeArrayBufferAllocator::Allocate(size_t size) { + void* ret; if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers) - return UncheckedCalloc(size); + ret = UncheckedCalloc(size); else - return UncheckedMalloc(size); + ret = UncheckedMalloc(size); + if (LIKELY(ret != nullptr)) + total_mem_usage_.fetch_add(size, std::memory_order_relaxed); + return ret; +} + +void* NodeArrayBufferAllocator::AllocateUninitialized(size_t size) { + void* ret = node::UncheckedMalloc(size); + if (LIKELY(ret != nullptr)) + total_mem_usage_.fetch_add(size, std::memory_order_relaxed); + return ret; +} + +void* NodeArrayBufferAllocator::Reallocate( + void* data, size_t old_size, size_t size) { + void* ret = UncheckedRealloc(static_cast(data), size); + if (LIKELY(ret != nullptr) || UNLIKELY(size == 0)) + total_mem_usage_.fetch_add(size - old_size, std::memory_order_relaxed); + return ret; +} + +void NodeArrayBufferAllocator::Free(void* data, size_t size) { + total_mem_usage_.fetch_sub(size, std::memory_order_relaxed); + free(data); } DebuggingArrayBufferAllocator::~DebuggingArrayBufferAllocator() { @@ -140,11 +165,13 @@ void* DebuggingArrayBufferAllocator::Reallocate(void* data, void DebuggingArrayBufferAllocator::RegisterPointer(void* data, size_t size) { Mutex::ScopedLock lock(mutex_); + NodeArrayBufferAllocator::RegisterPointer(data, size); RegisterPointerInternal(data, size); } void DebuggingArrayBufferAllocator::UnregisterPointer(void* data, size_t size) { Mutex::ScopedLock lock(mutex_); + NodeArrayBufferAllocator::UnregisterPointer(data, size); UnregisterPointerInternal(data, size); } @@ -356,7 +383,8 @@ MaybeLocal GetPerContextExports(Local context) { return handle_scope.Escape(existing_value.As()); Local exports = Object::New(isolate); - if (context->Global()->SetPrivate(context, key, exports).IsNothing()) + if (context->Global()->SetPrivate(context, key, exports).IsNothing() || + !InitializePrimordials(context)) return MaybeLocal(); return handle_scope.Escape(exports); } @@ -376,6 +404,10 @@ Local NewContext(Isolate* isolate, return context; } +void ProtoThrower(const FunctionCallbackInfo& info) { + THROW_ERR_PROTO_ACCESS(info.GetIsolate()); +} + // This runs at runtime, regardless of whether the context // is created from a snapshot. void InitializeContextRuntime(Local context) { @@ -404,6 +436,32 @@ void InitializeContextRuntime(Local context) { Local atomics = atomics_v.As(); atomics->Delete(context, wake_string).FromJust(); } + + // Remove __proto__ + // https://github.com/nodejs/node/issues/31951 + Local object_string = FIXED_ONE_BYTE_STRING(isolate, "Object"); + Local prototype_string = FIXED_ONE_BYTE_STRING(isolate, "prototype"); + Local prototype = context->Global() + ->Get(context, object_string) + .ToLocalChecked() + .As() + ->Get(context, prototype_string) + .ToLocalChecked() + .As(); + Local proto_string = FIXED_ONE_BYTE_STRING(isolate, "__proto__"); + if (per_process::cli_options->disable_proto == "delete") { + prototype->Delete(context, proto_string).ToChecked(); + } else if (per_process::cli_options->disable_proto == "throw") { + Local thrower = + Function::New(context, ProtoThrower).ToLocalChecked(); + PropertyDescriptor descriptor(thrower, thrower); + descriptor.set_enumerable(false); + descriptor.set_configurable(true); + prototype->DefineProperty(context, proto_string, descriptor).ToChecked(); + } else if (per_process::cli_options->disable_proto != "") { + // Validated in ProcessGlobalArgs + FatalError("InitializeContextRuntime()", "invalid --disable-proto mode"); + } } bool InitializeContextForSnapshot(Local context) { @@ -412,49 +470,50 @@ bool InitializeContextForSnapshot(Local context) { context->SetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration, True(isolate)); + return InitializePrimordials(context); +} + +bool InitializePrimordials(Local context) { + // Run per-context JS files. + Isolate* isolate = context->GetIsolate(); + Context::Scope context_scope(context); + Local exports; + + Local primordials_string = + FIXED_ONE_BYTE_STRING(isolate, "primordials"); + Local global_string = FIXED_ONE_BYTE_STRING(isolate, "global"); + Local exports_string = FIXED_ONE_BYTE_STRING(isolate, "exports"); + + // Create primordials first and make it available to per-context scripts. + Local primordials = Object::New(isolate); + if (!primordials->SetPrototype(context, Null(isolate)).FromJust() || + !GetPerContextExports(context).ToLocal(&exports) || + !exports->Set(context, primordials_string, primordials).FromJust()) { + return false; + } - { - // Run per-context JS files. - Context::Scope context_scope(context); - Local exports; - - Local primordials_string = - FIXED_ONE_BYTE_STRING(isolate, "primordials"); - Local global_string = FIXED_ONE_BYTE_STRING(isolate, "global"); - Local exports_string = FIXED_ONE_BYTE_STRING(isolate, "exports"); - - // Create primordials first and make it available to per-context scripts. - Local primordials = Object::New(isolate); - if (!primordials->SetPrototype(context, Null(isolate)).FromJust() || - !GetPerContextExports(context).ToLocal(&exports) || - !exports->Set(context, primordials_string, primordials).FromJust()) { + static const char* context_files[] = {"internal/per_context/primordials", + "internal/per_context/domexception", + "internal/per_context/messageport", + nullptr}; + + for (const char** module = context_files; *module != nullptr; module++) { + std::vector> parameters = { + global_string, exports_string, primordials_string}; + Local arguments[] = {context->Global(), exports, primordials}; + MaybeLocal maybe_fn = + native_module::NativeModuleEnv::LookupAndCompile( + context, *module, ¶meters, nullptr); + if (maybe_fn.IsEmpty()) { return false; } - - static const char* context_files[] = {"internal/per_context/primordials", - "internal/per_context/domexception", - "internal/per_context/messageport", - nullptr}; - - for (const char** module = context_files; *module != nullptr; module++) { - std::vector> parameters = { - global_string, exports_string, primordials_string}; - Local arguments[] = {context->Global(), exports, primordials}; - MaybeLocal maybe_fn = - native_module::NativeModuleEnv::LookupAndCompile( - context, *module, ¶meters, nullptr); - if (maybe_fn.IsEmpty()) { - return false; - } - Local fn = maybe_fn.ToLocalChecked(); - MaybeLocal result = - fn->Call(context, Undefined(isolate), - arraysize(arguments), arguments); - // Execution failed during context creation. - // TODO(joyeecheung): deprecate this signature and return a MaybeLocal. - if (result.IsEmpty()) { - return false; - } + Local fn = maybe_fn.ToLocalChecked(); + MaybeLocal result = + fn->Call(context, Undefined(isolate), arraysize(arguments), arguments); + // Execution failed during context creation. + // TODO(joyeecheung): deprecate this signature and return a MaybeLocal. + if (result.IsEmpty()) { + return false; } } diff --git a/src/async_wrap.cc b/src/async_wrap.cc index 784493fe4ed734..42837e09818ec2 100644 --- a/src/async_wrap.cc +++ b/src/async_wrap.cc @@ -80,6 +80,20 @@ struct AsyncWrapObject : public AsyncWrap { inline AsyncWrapObject(Environment* env, Local object, ProviderType type) : AsyncWrap(env, object, type) {} + static Local GetConstructorTemplate(Environment* env) { + Local tmpl = env->async_wrap_object_ctor_template(); + if (tmpl.IsEmpty()) { + tmpl = env->NewFunctionTemplate(AsyncWrapObject::New); + tmpl->SetClassName( + FIXED_ONE_BYTE_STRING(env->isolate(), "AsyncWrap")); + tmpl->Inherit(AsyncWrap::GetConstructorTemplate(env)); + tmpl->InstanceTemplate()->SetInternalFieldCount( + AsyncWrapObject::kInternalFieldCount); + env->set_async_wrap_object_ctor_template(tmpl); + } + return tmpl; + } + SET_NO_MEMORY_INFO() SET_MEMORY_INFO_NAME(AsyncWrapObject) SET_SELF_SIZE(AsyncWrapObject) @@ -175,6 +189,10 @@ void AsyncWrap::EmitAfter(Environment* env, double async_id) { class PromiseWrap : public AsyncWrap { public: + enum InternalFields { + kIsChainedPromiseField = AsyncWrap::kInternalFieldCount, + kInternalFieldCount + }; PromiseWrap(Environment* env, Local object, bool silent) : AsyncWrap(env, object, PROVIDER_PROMISE, kInvalidAsyncId, silent) { MakeWeak(); @@ -184,9 +202,6 @@ class PromiseWrap : public AsyncWrap { SET_MEMORY_INFO_NAME(PromiseWrap) SET_SELF_SIZE(PromiseWrap) - static constexpr int kIsChainedPromiseField = 1; - static constexpr int kInternalFieldCount = 2; - static PromiseWrap* New(Environment* env, Local promise, PromiseWrap* parent_wrap, @@ -213,15 +228,16 @@ PromiseWrap* PromiseWrap::New(Environment* env, void PromiseWrap::getIsChainedPromise(Local property, const PropertyCallbackInfo& info) { info.GetReturnValue().Set( - info.Holder()->GetInternalField(kIsChainedPromiseField)); + info.Holder()->GetInternalField(PromiseWrap::kIsChainedPromiseField)); } static PromiseWrap* extractPromiseWrap(Local promise) { - Local resource_object_value = promise->GetInternalField(0); - if (resource_object_value->IsObject()) { - return Unwrap(resource_object_value.As()); - } - return nullptr; + // This check is imperfect. If the internal field is set, it should + // be an object. If it's not, we just ignore it. Ideally v8 would + // have had GetInternalField returning a MaybeLocal but this works + // for now. + Local obj = promise->GetInternalField(0); + return obj->IsObject() ? Unwrap(obj.As()) : nullptr; } static void PromiseHook(PromiseHookType type, Local promise, @@ -259,8 +275,8 @@ static void PromiseHook(PromiseHookType type, Local promise, if (wrap == nullptr) return; if (type == PromiseHookType::kBefore) { - env->async_hooks()->push_async_ids( - wrap->get_async_id(), wrap->get_trigger_async_id()); + env->async_hooks()->push_async_context(wrap->get_async_id(), + wrap->get_trigger_async_id(), wrap->object()); wrap->EmitTraceEventBefore(); AsyncWrap::EmitBefore(wrap->env(), wrap->get_async_id()); } else if (type == PromiseHookType::kAfter) { @@ -272,7 +288,7 @@ static void PromiseHook(PromiseHookType type, Local promise, // Popping it off the stack can be skipped in that case, because it is // known that it would correspond to exactly one call with // PromiseHookType::kBefore that was not witnessed by the PromiseHook. - env->async_hooks()->pop_async_id(wrap->get_async_id()); + env->async_hooks()->pop_async_context(wrap->get_async_id()); } } else if (type == PromiseHookType::kResolve) { AsyncWrap::EmitPromiseResolve(wrap->env(), wrap->get_async_id()); @@ -388,7 +404,6 @@ static void RegisterDestroyHook(const FunctionCallbackInfo& args) { p->env->AddCleanupHook(DestroyParamCleanupHook, p); } - void AsyncWrap::GetAsyncId(const FunctionCallbackInfo& args) { AsyncWrap* wrap; args.GetReturnValue().Set(kInvalidAsyncId); @@ -397,20 +412,20 @@ void AsyncWrap::GetAsyncId(const FunctionCallbackInfo& args) { } -void AsyncWrap::PushAsyncIds(const FunctionCallbackInfo& args) { +void AsyncWrap::PushAsyncContext(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); // No need for CHECK(IsNumber()) on args because if FromJust() doesn't fail // then the checks in push_async_ids() and pop_async_id() will. double async_id = args[0]->NumberValue(env->context()).FromJust(); double trigger_async_id = args[1]->NumberValue(env->context()).FromJust(); - env->async_hooks()->push_async_ids(async_id, trigger_async_id); + env->async_hooks()->push_async_context(async_id, trigger_async_id, args[2]); } -void AsyncWrap::PopAsyncIds(const FunctionCallbackInfo& args) { +void AsyncWrap::PopAsyncContext(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); double async_id = args[0]->NumberValue(env->context()).FromJust(); - args.GetReturnValue().Set(env->async_hooks()->pop_async_id(async_id)); + args.GetReturnValue().Set(env->async_hooks()->pop_async_context(async_id)); } @@ -439,6 +454,7 @@ void AsyncWrap::EmitDestroy() { AsyncWrap::EmitDestroy(env(), async_id_); // Ensure no double destroy is emitted via AsyncReset(). async_id_ = kInvalidAsyncId; + resource_.Reset(); } void AsyncWrap::QueueDestroyAsyncId(const FunctionCallbackInfo& args) { @@ -470,8 +486,8 @@ void AsyncWrap::Initialize(Local target, HandleScope scope(isolate); env->SetMethod(target, "setupHooks", SetupHooks); - env->SetMethod(target, "pushAsyncIds", PushAsyncIds); - env->SetMethod(target, "popAsyncIds", PopAsyncIds); + env->SetMethod(target, "pushAsyncContext", PushAsyncContext); + env->SetMethod(target, "popAsyncContext", PopAsyncContext); env->SetMethod(target, "queueDestroyAsyncId", QueueDestroyAsyncId); env->SetMethod(target, "enablePromiseHook", EnablePromiseHook); env->SetMethod(target, "disablePromiseHook", DisablePromiseHook); @@ -508,6 +524,10 @@ void AsyncWrap::Initialize(Local target, "async_id_fields", env->async_hooks()->async_id_fields().GetJSArray()); + FORCE_SET_TARGET_FIELD(target, + "execution_async_resources", + env->async_hooks()->execution_async_resources()); + target->Set(context, env->async_ids_stack_string(), env->async_hooks()->async_ids_stack().GetJSArray()).Check(); @@ -553,21 +573,10 @@ void AsyncWrap::Initialize(Local target, env->set_async_hooks_promise_resolve_function(Local()); env->set_async_hooks_binding(target); - // TODO(addaleax): This block might better work as a - // AsyncWrapObject::Initialize() or AsyncWrapObject::GetConstructorTemplate() - // function. - { - auto class_name = FIXED_ONE_BYTE_STRING(env->isolate(), "AsyncWrap"); - auto function_template = env->NewFunctionTemplate(AsyncWrapObject::New); - function_template->SetClassName(class_name); - function_template->Inherit(AsyncWrap::GetConstructorTemplate(env)); - auto instance_template = function_template->InstanceTemplate(); - instance_template->SetInternalFieldCount(1); - auto function = - function_template->GetFunction(env->context()).ToLocalChecked(); - target->Set(env->context(), class_name, function).Check(); - env->set_async_wrap_object_ctor_template(function_template); - } + target->Set(env->context(), + FIXED_ONE_BYTE_STRING(env->isolate(), "AsyncWrap"), + AsyncWrapObject::GetConstructorTemplate(env) + ->GetFunction(env->context()).ToLocalChecked()).Check(); } @@ -672,6 +681,12 @@ void AsyncWrap::AsyncReset(Local resource, double execution_async_id, : execution_async_id; trigger_async_id_ = env()->get_default_trigger_async_id(); + if (resource != object()) { + // TODO(addaleax): Using a strong reference here makes it very easy to + // introduce memory leaks. Move away from using a strong reference. + resource_.Reset(env()->isolate(), resource); + } + switch (provider_type()) { #define V(PROVIDER) \ case PROVIDER_ ## PROVIDER: \ @@ -739,7 +754,7 @@ MaybeLocal AsyncWrap::MakeCallback(const Local cb, ProviderType provider = provider_type(); async_context context { get_async_id(), get_trigger_async_id() }; MaybeLocal ret = InternalMakeCallback( - env(), object(), cb, argc, argv, context); + env(), GetResource(), object(), cb, argc, argv, context); // This is a static call with cached values because the `this` object may // no longer be alive at this point. @@ -778,6 +793,14 @@ Local AsyncWrap::GetOwner(Environment* env, Local obj) { } } +Local AsyncWrap::GetResource() { + if (resource_.IsEmpty()) { + return object(); + } + + return resource_.Get(env()->isolate()); +} + } // namespace node NODE_MODULE_CONTEXT_AWARE_INTERNAL(async_wrap, node::AsyncWrap::Initialize) diff --git a/src/async_wrap.h b/src/async_wrap.h index 521560c795768e..34e84fde6d4823 100644 --- a/src/async_wrap.h +++ b/src/async_wrap.h @@ -68,7 +68,9 @@ namespace node { V(TTYWRAP) \ V(UDPSENDWRAP) \ V(UDPWRAP) \ + V(SIGINTWATCHDOG) \ V(WORKER) \ + V(WORKERHEAPSNAPSHOT) \ V(WRITEWRAP) \ V(ZLIB) @@ -132,8 +134,8 @@ class AsyncWrap : public BaseObject { void* priv); static void GetAsyncId(const v8::FunctionCallbackInfo& args); - static void PushAsyncIds(const v8::FunctionCallbackInfo& args); - static void PopAsyncIds(const v8::FunctionCallbackInfo& args); + static void PushAsyncContext(const v8::FunctionCallbackInfo& args); + static void PopAsyncContext(const v8::FunctionCallbackInfo& args); static void AsyncReset(const v8::FunctionCallbackInfo& args); static void GetProviderType(const v8::FunctionCallbackInfo& args); static void QueueDestroyAsyncId( @@ -197,6 +199,7 @@ class AsyncWrap : public BaseObject { v8::Local obj); bool IsDoneInitializing() const override; + v8::Local GetResource(); private: friend class PromiseWrap; @@ -211,6 +214,7 @@ class AsyncWrap : public BaseObject { // Because the values may be Reset(), cannot be made const. double async_id_ = kInvalidAsyncId; double trigger_async_id_; + v8::Global resource_; }; } // namespace node diff --git a/src/base_object-inl.h b/src/base_object-inl.h index efd8f17e9db5bb..fc2611444c1af4 100644 --- a/src/base_object-inl.h +++ b/src/base_object-inl.h @@ -43,7 +43,9 @@ BaseObject::BaseObject(Environment* env, v8::Local object) : persistent_handle_(env->isolate(), object), env_(env) { CHECK_EQ(false, object.IsEmpty()); CHECK_GT(object->InternalFieldCount(), 0); - object->SetAlignedPointerInInternalField(0, static_cast(this)); + object->SetAlignedPointerInInternalField( + BaseObject::kSlot, + static_cast(this)); env->AddCleanupHook(DeleteMe, static_cast(this)); env->modify_base_object_count(1); } @@ -67,7 +69,7 @@ BaseObject::~BaseObject() { { v8::HandleScope handle_scope(env()->isolate()); - object()->SetAlignedPointerInInternalField(0, nullptr); + object()->SetAlignedPointerInInternalField(BaseObject::kSlot, nullptr); } } @@ -100,7 +102,8 @@ Environment* BaseObject::env() const { BaseObject* BaseObject::FromJSObject(v8::Local obj) { CHECK_GT(obj->InternalFieldCount(), 0); - return static_cast(obj->GetAlignedPointerFromInternalField(0)); + return static_cast( + obj->GetAlignedPointerFromInternalField(BaseObject::kSlot)); } @@ -148,11 +151,12 @@ BaseObject::MakeLazilyInitializedJSTemplate(Environment* env) { auto constructor = [](const v8::FunctionCallbackInfo& args) { DCHECK(args.IsConstructCall()); DCHECK_GT(args.This()->InternalFieldCount(), 0); - args.This()->SetAlignedPointerInInternalField(0, nullptr); + args.This()->SetAlignedPointerInInternalField(BaseObject::kSlot, nullptr); }; v8::Local t = env->NewFunctionTemplate(constructor); - t->InstanceTemplate()->SetInternalFieldCount(1); + t->InstanceTemplate()->SetInternalFieldCount( + BaseObject::kInternalFieldCount); return t; } diff --git a/src/base_object.h b/src/base_object.h index e7ef029995f1cf..2c67445c31fbb6 100644 --- a/src/base_object.h +++ b/src/base_object.h @@ -36,6 +36,8 @@ class BaseObjectPtrImpl; class BaseObject : public MemoryRetainer { public: + enum InternalFields { kSlot, kInternalFieldCount }; + // Associates this object with `object`. It uses the 0th internal field for // that, and in particular aborts if there is no such field. inline BaseObject(Environment* env, v8::Local object); diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index 082f86ff41d673..8d1e3bc8794dfe 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -66,6 +66,7 @@ using v8::Int32; using v8::Integer; using v8::Isolate; using v8::Local; +using v8::NewStringType; using v8::Null; using v8::Object; using v8::String; @@ -1929,7 +1930,7 @@ void CanonicalizeIP(const FunctionCallbackInfo& args) { const int af = (rc == 4 ? AF_INET : AF_INET6); CHECK_EQ(0, uv_inet_ntop(af, &result, canonical_ip, sizeof(canonical_ip))); Local val = String::NewFromUtf8(isolate, canonical_ip, - v8::NewStringType::kNormal).ToLocalChecked(); + NewStringType::kNormal).ToLocalChecked(); args.GetReturnValue().Set(val); } @@ -2188,6 +2189,9 @@ void Initialize(Local target, target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AI_ADDRCONFIG"), Integer::New(env->isolate(), AI_ADDRCONFIG)).Check(); + target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), + "AI_ALL"), + Integer::New(env->isolate(), AI_ALL)).Check(); target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AI_V4MAPPED"), Integer::New(env->isolate(), AI_V4MAPPED)).Check(); @@ -2224,7 +2228,8 @@ void Initialize(Local target, Local channel_wrap = env->NewFunctionTemplate(ChannelWrap::New); - channel_wrap->InstanceTemplate()->SetInternalFieldCount(1); + channel_wrap->InstanceTemplate()->SetInternalFieldCount( + ChannelWrap::kInternalFieldCount); channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env)); env->SetProtoMethod(channel_wrap, "queryAny", Query); diff --git a/src/debug_utils.h b/src/debug_utils.h index 3ecbdea90e2c22..ecc53b0c2b0aa0 100644 --- a/src/debug_utils.h +++ b/src/debug_utils.h @@ -41,6 +41,7 @@ void FWrite(FILE* file, const std::string& str); // from a provider type to a debug category. #define DEBUG_CATEGORY_NAMES(V) \ NODE_ASYNC_PROVIDER_TYPES(V) \ + V(HUGEPAGES) \ V(INSPECTOR_SERVER) \ V(INSPECTOR_PROFILER) \ V(CODE_CACHE) \ diff --git a/src/env-inl.h b/src/env-inl.h index 5248e7062354c1..fcb58dc6709d13 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -64,11 +64,15 @@ inline MultiIsolatePlatform* IsolateData::platform() const { return platform_; } +inline v8::Local IsolateData::async_wrap_provider(int index) const { + return async_wrap_providers_[index].Get(isolate_); +} + inline AsyncHooks::AsyncHooks() : async_ids_stack_(env()->isolate(), 16 * 2), fields_(env()->isolate(), kFieldsCount), async_id_fields_(env()->isolate(), kUidFieldsCount) { - v8::HandleScope handle_scope(env()->isolate()); + clear_async_id_stack(); // Always perform async_hooks checks, not just when async_hooks is enabled. // TODO(AndreasMadsen): Consider removing this for LTS releases. @@ -86,20 +90,6 @@ inline AsyncHooks::AsyncHooks() // kAsyncIdCounter should start at 1 because that'll be the id the execution // context during bootstrap (code that runs before entering uv_run()). async_id_fields_[AsyncHooks::kAsyncIdCounter] = 1; - - // Create all the provider strings that will be passed to JS. Place them in - // an array so the array index matches the PROVIDER id offset. This way the - // strings can be retrieved quickly. -#define V(Provider) \ - providers_[AsyncWrap::PROVIDER_ ## Provider].Set( \ - env()->isolate(), \ - v8::String::NewFromOneByte( \ - env()->isolate(), \ - reinterpret_cast(#Provider), \ - v8::NewStringType::kInternalized, \ - sizeof(#Provider) - 1).ToLocalChecked()); - NODE_ASYNC_PROVIDER_TYPES(V) -#undef V } inline AliasedUint32Array& AsyncHooks::fields() { return fields_; @@ -113,8 +103,12 @@ inline AliasedFloat64Array& AsyncHooks::async_ids_stack() { return async_ids_stack_; } +inline v8::Local AsyncHooks::execution_async_resources() { + return PersistentToLocal::Strong(execution_async_resources_); +} + inline v8::Local AsyncHooks::provider_string(int idx) { - return providers_[idx].Get(env()->isolate()); + return env()->isolate_data()->async_wrap_provider(idx); } inline void AsyncHooks::no_force_checks() { @@ -125,9 +119,12 @@ inline Environment* AsyncHooks::env() { return Environment::ForAsyncHooks(this); } -// Remember to keep this code aligned with pushAsyncIds() in JS. -inline void AsyncHooks::push_async_ids(double async_id, - double trigger_async_id) { +// Remember to keep this code aligned with pushAsyncContext() in JS. +inline void AsyncHooks::push_async_context(double async_id, + double trigger_async_id, + v8::Local resource) { + v8::HandleScope handle_scope(env()->isolate()); + // Since async_hooks is experimental, do only perform the check // when async_hooks is enabled. if (fields_[kCheck] > 0) { @@ -143,10 +140,13 @@ inline void AsyncHooks::push_async_ids(double async_id, fields_[kStackLength] += 1; async_id_fields_[kExecutionAsyncId] = async_id; async_id_fields_[kTriggerAsyncId] = trigger_async_id; + + auto resources = execution_async_resources(); + USE(resources->Set(env()->context(), offset, resource)); } -// Remember to keep this code aligned with popAsyncIds() in JS. -inline bool AsyncHooks::pop_async_id(double async_id) { +// Remember to keep this code aligned with popAsyncContext() in JS. +inline bool AsyncHooks::pop_async_context(double async_id) { // In case of an exception then this may have already been reset, if the // stack was multiple MakeCallback()'s deep. if (fields_[kStackLength] == 0) return false; @@ -175,11 +175,18 @@ inline bool AsyncHooks::pop_async_id(double async_id) { async_id_fields_[kTriggerAsyncId] = async_ids_stack_[2 * offset + 1]; fields_[kStackLength] = offset; + auto resources = execution_async_resources(); + USE(resources->Delete(env()->context(), offset)); + return fields_[kStackLength] > 0; } // Keep in sync with clearAsyncIdStack in lib/internal/async_hooks.js. inline void AsyncHooks::clear_async_id_stack() { + auto isolate = env()->isolate(); + v8::HandleScope handle_scope(isolate); + execution_async_resources_.Reset(isolate, v8::Array::New(isolate)); + async_id_fields_[kExecutionAsyncId] = 0; async_id_fields_[kTriggerAsyncId] = 0; fields_[kStackLength] = 0; @@ -206,7 +213,6 @@ inline AsyncHooks::DefaultTriggerAsyncIdScope ::~DefaultTriggerAsyncIdScope() { old_default_trigger_async_id_; } - Environment* Environment::ForAsyncHooks(AsyncHooks* hooks) { return ContainerOf(&Environment::async_hooks_, hooks); } @@ -1013,7 +1019,10 @@ inline AllocatedBuffer::~AllocatedBuffer() { inline void AllocatedBuffer::clear() { uv_buf_t buf = release(); - env_->Free(buf.base, buf.len); + if (buf.base != nullptr) { + CHECK_NOT_NULL(env_); + env_->Free(buf.base, buf.len); + } } // It's a bit awkward to define this Buffer::New() overload here, but it diff --git a/src/env.cc b/src/env.cc index ec50d8841ac1e3..5b8a63a0017c4f 100644 --- a/src/env.cc +++ b/src/env.cc @@ -76,6 +76,8 @@ std::vector IsolateData::Serialize(SnapshotCreator* creator) { #undef VY #undef VS #undef VP + for (size_t i = 0; i < AsyncWrap::PROVIDERS_LENGTH; i++) + indexes.push_back(creator->AddData(async_wrap_provider(i))); return indexes; } @@ -103,6 +105,15 @@ void IsolateData::DeserializeProperties(const std::vector* indexes) { #undef VY #undef VS #undef VP + + for (size_t j = 0; j < AsyncWrap::PROVIDERS_LENGTH; j++) { + MaybeLocal field = + isolate_->GetDataFromSnapshotOnce((*indexes)[i++]); + if (field.IsEmpty()) { + fprintf(stderr, "Failed to deserialize AsyncWrap provider %zu\n", j); + } + async_wrap_providers_[j].Set(isolate_, field.ToLocalChecked()); + } } void IsolateData::CreateProperties() { @@ -153,6 +164,20 @@ void IsolateData::CreateProperties() { .ToLocalChecked()); PER_ISOLATE_STRING_PROPERTIES(V) #undef V + + // Create all the provider strings that will be passed to JS. Place them in + // an array so the array index matches the PROVIDER id offset. This way the + // strings can be retrieved quickly. +#define V(Provider) \ + async_wrap_providers_[AsyncWrap::PROVIDER_ ## Provider].Set( \ + isolate_, \ + String::NewFromOneByte( \ + isolate_, \ + reinterpret_cast(#Provider), \ + NewStringType::kInternalized, \ + sizeof(#Provider) - 1).ToLocalChecked()); + NODE_ASYNC_PROVIDER_TYPES(V) +#undef V } IsolateData::IsolateData(Isolate* isolate, @@ -190,6 +215,8 @@ void IsolateData::MemoryInfo(MemoryTracker* tracker) const { PER_ISOLATE_STRING_PROPERTIES(V) #undef V + tracker->TrackField("async_wrap_providers", async_wrap_providers_); + if (node_allocator_ != nullptr) { tracker->TrackFieldWithSize( "node_allocator", sizeof(*node_allocator_), "NodeArrayBufferAllocator"); @@ -933,7 +960,6 @@ void TickInfo::MemoryInfo(MemoryTracker* tracker) const { } void AsyncHooks::MemoryInfo(MemoryTracker* tracker) const { - tracker->TrackField("providers", providers_); tracker->TrackField("async_ids_stack", async_ids_stack_); tracker->TrackField("fields", fields_); tracker->TrackField("async_id_fields", async_id_fields_); diff --git a/src/env.h b/src/env.h index cdcb8f5cf3b923..deeeb2a385ab75 100644 --- a/src/env.h +++ b/src/env.h @@ -194,6 +194,7 @@ constexpr size_t kFsStatsBufferLength = V(commonjs_string, "commonjs") \ V(config_string, "config") \ V(constants_string, "constants") \ + V(crypto_dh_string, "dh") \ V(crypto_dsa_string, "dsa") \ V(crypto_ec_string, "ec") \ V(crypto_ed25519_string, "ed25519") \ @@ -219,7 +220,6 @@ constexpr size_t kFsStatsBufferLength = V(dns_srv_string, "SRV") \ V(dns_txt_string, "TXT") \ V(done_string, "done") \ - V(dot_string, ".") \ V(duration_string, "duration") \ V(ecdh_string, "ECDH") \ V(emit_warning_string, "emitWarning") \ @@ -274,7 +274,6 @@ constexpr size_t kFsStatsBufferLength = V(kind_string, "kind") \ V(library_string, "library") \ V(mac_string, "mac") \ - V(main_string, "main") \ V(max_buffer_string, "maxBuffer") \ V(message_port_constructor_string, "MessagePort") \ V(message_port_string, "messagePort") \ @@ -413,6 +412,7 @@ constexpr size_t kFsStatsBufferLength = V(http2settings_constructor_template, v8::ObjectTemplate) \ V(http2stream_constructor_template, v8::ObjectTemplate) \ V(http2ping_constructor_template, v8::ObjectTemplate) \ + V(i18n_converter_template, v8::ObjectTemplate) \ V(libuv_stream_wrap_ctor_template, v8::FunctionTemplate) \ V(message_port_constructor_template, v8::FunctionTemplate) \ V(pipe_constructor_template, v8::FunctionTemplate) \ @@ -424,7 +424,8 @@ constexpr size_t kFsStatsBufferLength = V(streambaseoutputstream_constructor_template, v8::ObjectTemplate) \ V(tcp_constructor_template, v8::FunctionTemplate) \ V(tty_constructor_template, v8::FunctionTemplate) \ - V(write_wrap_template, v8::ObjectTemplate) + V(write_wrap_template, v8::ObjectTemplate) \ + V(worker_heap_snapshot_taker_template, v8::ObjectTemplate) #define ENVIRONMENT_STRONG_PERSISTENT_VALUES(V) \ V(as_callback_data, v8::Object) \ @@ -510,6 +511,7 @@ class IsolateData : public MemoryRetainer { #undef VY #undef VS #undef VP + inline v8::Local async_wrap_provider(int index) const; std::unordered_map> http2_static_strs; inline v8::Isolate* isolate() const; @@ -534,6 +536,9 @@ class IsolateData : public MemoryRetainer { #undef VY #undef VS #undef VP + // Keep a list of all Persistent strings used for AsyncWrap Provider types. + std::array, AsyncWrap::PROVIDERS_LENGTH> + async_wrap_providers_; v8::Isolate* const isolate_; uv_loop_t* const event_loop_; @@ -648,14 +653,16 @@ class AsyncHooks : public MemoryRetainer { inline AliasedUint32Array& fields(); inline AliasedFloat64Array& async_id_fields(); inline AliasedFloat64Array& async_ids_stack(); + inline v8::Local execution_async_resources(); inline v8::Local provider_string(int idx); inline void no_force_checks(); inline Environment* env(); - inline void push_async_ids(double async_id, double trigger_async_id); - inline bool pop_async_id(double async_id); + inline void push_async_context(double async_id, double trigger_async_id, + v8::Local execution_async_resource_); + inline bool pop_async_context(double async_id); inline void clear_async_id_stack(); // Used in fatal exceptions. AsyncHooks(const AsyncHooks&) = delete; @@ -689,8 +696,6 @@ class AsyncHooks : public MemoryRetainer { private: friend class Environment; // So we can call the constructor. inline AsyncHooks(); - // Keep a list of all Persistent strings used for Provider types. - std::array, AsyncWrap::PROVIDERS_LENGTH> providers_; // Stores the ids of the current execution context stack. AliasedFloat64Array async_ids_stack_; // Attached to a Uint32Array that tracks the number of active hooks for @@ -700,6 +705,8 @@ class AsyncHooks : public MemoryRetainer { AliasedFloat64Array async_id_fields_; void grow_async_ids_stack(); + + v8::Global execution_async_resources_; }; class ImmediateInfo : public MemoryRetainer { @@ -988,9 +995,6 @@ class Environment : public MemoryRetainer { inline uint32_t get_next_script_id(); inline uint32_t get_next_function_id(); - std::unordered_map - package_json_cache; - inline double* heap_statistics_buffer() const; inline void set_heap_statistics_buffer(double* pointer); diff --git a/src/fs_event_wrap.cc b/src/fs_event_wrap.cc index d38556b1bf8011..858455bff2d42d 100644 --- a/src/fs_event_wrap.cc +++ b/src/fs_event_wrap.cc @@ -97,7 +97,8 @@ void FSEventWrap::Initialize(Local target, auto fsevent_string = FIXED_ONE_BYTE_STRING(env->isolate(), "FSEvent"); Local t = env->NewFunctionTemplate(New); - t->InstanceTemplate()->SetInternalFieldCount(1); + t->InstanceTemplate()->SetInternalFieldCount( + FSEventWrap::kInternalFieldCount); t->SetClassName(fsevent_string); t->Inherit(AsyncWrap::GetConstructorTemplate(env)); diff --git a/src/handle_wrap.cc b/src/handle_wrap.cc index f5d622fc255cdf..4e039d5dbf2d37 100644 --- a/src/handle_wrap.cc +++ b/src/handle_wrap.cc @@ -115,6 +115,7 @@ HandleWrap::HandleWrap(Environment* env, void HandleWrap::OnClose(uv_handle_t* handle) { + CHECK_NOT_NULL(handle->data); BaseObjectPtr wrap { static_cast(handle->data) }; wrap->Detach(); diff --git a/src/heap_utils.cc b/src/heap_utils.cc index b6c8c75c159846..2e979e49e87922 100644 --- a/src/heap_utils.cc +++ b/src/heap_utils.cc @@ -236,18 +236,16 @@ class HeapSnapshotStream : public AsyncWrap, public: HeapSnapshotStream( Environment* env, - const HeapSnapshot* snapshot, - v8::Local obj) : + HeapSnapshotPointer&& snapshot, + Local obj) : AsyncWrap(env, obj, AsyncWrap::PROVIDER_HEAPSNAPSHOT), StreamBase(env), - snapshot_(snapshot) { + snapshot_(std::move(snapshot)) { MakeWeak(); StreamBase::AttachToObject(GetObject()); } - ~HeapSnapshotStream() override { - Cleanup(); - } + ~HeapSnapshotStream() override {} int GetChunkSize() override { return 65536; // big chunks == faster @@ -255,7 +253,7 @@ class HeapSnapshotStream : public AsyncWrap, void EndOfStream() override { EmitRead(UV_EOF); - Cleanup(); + snapshot_.reset(); } WriteResult WriteAsciiChunk(char* data, int size) override { @@ -309,22 +307,13 @@ class HeapSnapshotStream : public AsyncWrap, SET_SELF_SIZE(HeapSnapshotStream) private: - void Cleanup() { - if (snapshot_ != nullptr) { - const_cast(snapshot_)->Delete(); - snapshot_ = nullptr; - } - } - - - const HeapSnapshot* snapshot_; + HeapSnapshotPointer snapshot_; }; inline void TakeSnapshot(Isolate* isolate, v8::OutputStream* out) { - const HeapSnapshot* const snapshot = - isolate->GetHeapProfiler()->TakeHeapSnapshot(); + HeapSnapshotPointer snapshot { + isolate->GetHeapProfiler()->TakeHeapSnapshot() }; snapshot->Serialize(out, HeapSnapshot::kJSON); - const_cast(snapshot)->Delete(); } inline bool WriteSnapshot(Isolate* isolate, const char* filename) { @@ -339,20 +328,44 @@ inline bool WriteSnapshot(Isolate* isolate, const char* filename) { } // namespace -void CreateHeapSnapshotStream(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); +void DeleteHeapSnapshot(const HeapSnapshot* snapshot) { + const_cast(snapshot)->Delete(); +} + +BaseObjectPtr CreateHeapSnapshotStream( + Environment* env, HeapSnapshotPointer&& snapshot) { HandleScope scope(env->isolate()); - const HeapSnapshot* const snapshot = - env->isolate()->GetHeapProfiler()->TakeHeapSnapshot(); - CHECK_NOT_NULL(snapshot); + + if (env->streambaseoutputstream_constructor_template().IsEmpty()) { + // Create FunctionTemplate for HeapSnapshotStream + Local os = FunctionTemplate::New(env->isolate()); + os->Inherit(AsyncWrap::GetConstructorTemplate(env)); + Local ost = os->InstanceTemplate(); + ost->SetInternalFieldCount(StreamBase::kInternalFieldCount); + os->SetClassName( + FIXED_ONE_BYTE_STRING(env->isolate(), "HeapSnapshotStream")); + StreamBase::AddMethods(env, os); + env->set_streambaseoutputstream_constructor_template(ost); + } + Local obj; if (!env->streambaseoutputstream_constructor_template() ->NewInstance(env->context()) .ToLocal(&obj)) { - return; + return {}; } - HeapSnapshotStream* out = new HeapSnapshotStream(env, snapshot, obj); - args.GetReturnValue().Set(out->object()); + return MakeBaseObject(env, std::move(snapshot), obj); +} + +void CreateHeapSnapshotStream(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + HeapSnapshotPointer snapshot { + env->isolate()->GetHeapProfiler()->TakeHeapSnapshot() }; + CHECK(snapshot); + BaseObjectPtr stream = + CreateHeapSnapshotStream(env, std::move(snapshot)); + if (stream) + args.GetReturnValue().Set(stream->object()); } void TriggerHeapSnapshot(const FunctionCallbackInfo& args) { @@ -388,15 +401,6 @@ void Initialize(Local target, env->SetMethod(target, "buildEmbedderGraph", BuildEmbedderGraph); env->SetMethod(target, "triggerHeapSnapshot", TriggerHeapSnapshot); env->SetMethod(target, "createHeapSnapshotStream", CreateHeapSnapshotStream); - - // Create FunctionTemplate for HeapSnapshotStream - Local os = FunctionTemplate::New(env->isolate()); - os->Inherit(AsyncWrap::GetConstructorTemplate(env)); - Local ost = os->InstanceTemplate(); - ost->SetInternalFieldCount(StreamBase::kStreamBaseFieldCount); - os->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "HeapSnapshotStream")); - StreamBase::AddMethods(env, os); - env->set_streambaseoutputstream_constructor_template(ost); } } // namespace heap diff --git a/src/inspector_js_api.cc b/src/inspector_js_api.cc index 703c9ff598fdf2..ed3b36ad5ca80e 100644 --- a/src/inspector_js_api.cc +++ b/src/inspector_js_api.cc @@ -105,7 +105,8 @@ class JSBindingsConnection : public AsyncWrap { Local class_name = ConnectionType::GetClassName(env); Local tmpl = env->NewFunctionTemplate(JSBindingsConnection::New); - tmpl->InstanceTemplate()->SetInternalFieldCount(1); + tmpl->InstanceTemplate()->SetInternalFieldCount( + JSBindingsConnection::kInternalFieldCount); tmpl->SetClassName(class_name); tmpl->Inherit(AsyncWrap::GetConstructorTemplate(env)); env->SetProtoMethod(tmpl, "dispatch", JSBindingsConnection::Dispatch); diff --git a/src/inspector_profiler.cc b/src/inspector_profiler.cc index f9d3c2b512f1c1..03cf2f6e5ca76b 100644 --- a/src/inspector_profiler.cc +++ b/src/inspector_profiler.cc @@ -107,9 +107,9 @@ void V8ProfilerConnection::V8ProfilerSessionDelegate::SendMessageToFrontend( } static bool EnsureDirectory(const std::string& directory, const char* type) { - uv_fs_t req; - int ret = fs::MKDirpSync(nullptr, &req, directory, 0777, nullptr); - uv_fs_req_cleanup(&req); + fs::FSReqWrapSync req_wrap_sync; + int ret = fs::MKDirpSync(nullptr, &req_wrap_sync.req, directory, 0777, + nullptr); if (ret < 0 && ret != UV_EEXIST) { char err_buf[128]; uv_err_name_r(ret, err_buf, sizeof(err_buf)); @@ -209,6 +209,16 @@ void V8CoverageConnection::WriteProfile(Local message) { HandleScope handle_scope(isolate); Context::Scope context_scope(context); + // This is only set up during pre-execution (when the environment variables + // becomes available in the JS land). If it's empty, we don't have coverage + // directory path (which is resolved in JS land at the moment) either, so + // the best we could to is to just discard the profile and do nothing. + // This should only happen in half-baked Environments created using the + // embedder API. + if (env_->source_map_cache_getter().IsEmpty()) { + return; + } + // Get message.result from the response. Local result; if (!ParseProfile(env_, message, type()).ToLocal(&result)) { diff --git a/src/js_native_api.h b/src/js_native_api.h index 489549190b663e..2675da505c2368 100644 --- a/src/js_native_api.h +++ b/src/js_native_api.h @@ -4,7 +4,6 @@ // This file needs to be compatible with C compilers. #include // NOLINT(modernize-deprecated-headers) #include // NOLINT(modernize-deprecated-headers) -#include "js_native_api_types.h" // Use INT_MAX, this should only be consumed by the pre-processor anyway. #define NAPI_VERSION_EXPERIMENTAL 2147483647 @@ -18,10 +17,12 @@ // functions available in a new version of N-API that is not yet ported in all // LTS versions, they can set NAPI_VERSION knowing that they have specifically // depended on that version. -#define NAPI_VERSION 5 +#define NAPI_VERSION 6 #endif #endif +#include "js_native_api_types.h" + // If you need __declspec(dllimport), either include instead, or // define NAPI_EXTERN as __declspec(dllimport) on the compiler's command line. #ifndef NAPI_EXTERN @@ -478,7 +479,7 @@ NAPI_EXTERN napi_status napi_add_finalizer(napi_env env, #endif // NAPI_VERSION >= 5 -#ifdef NAPI_EXPERIMENTAL +#if NAPI_VERSION >= 6 // BigInt NAPI_EXTERN napi_status napi_create_bigint_int64(napi_env env, @@ -506,6 +507,15 @@ NAPI_EXTERN napi_status napi_get_value_bigint_words(napi_env env, size_t* word_count, uint64_t* words); +// Object +NAPI_EXTERN napi_status +napi_get_all_property_names(napi_env env, + napi_value object, + napi_key_collection_mode key_mode, + napi_key_filter key_filter, + napi_key_conversion key_conversion, + napi_value* result); + // Instance data NAPI_EXTERN napi_status napi_set_instance_data(napi_env env, void* data, @@ -514,7 +524,9 @@ NAPI_EXTERN napi_status napi_set_instance_data(napi_env env, NAPI_EXTERN napi_status napi_get_instance_data(napi_env env, void** data); +#endif // NAPI_VERSION >= 6 +#ifdef NAPI_EXPERIMENTAL // ArrayBuffer detaching NAPI_EXTERN napi_status napi_detach_arraybuffer(napi_env env, napi_value arraybuffer); diff --git a/src/js_native_api_types.h b/src/js_native_api_types.h index a81e76a64934de..7a49fc9f719b30 100644 --- a/src/js_native_api_types.h +++ b/src/js_native_api_types.h @@ -115,4 +115,25 @@ typedef struct { napi_status error_code; } napi_extended_error_info; +#if NAPI_VERSION >= 6 +typedef enum { + napi_key_include_prototypes, + napi_key_own_only +} napi_key_collection_mode; + +typedef enum { + napi_key_all_properties = 0, + napi_key_writable = 1, + napi_key_enumerable = 1 << 1, + napi_key_configurable = 1 << 2, + napi_key_skip_strings = 1 << 3, + napi_key_skip_symbols = 1 << 4 +} napi_key_filter; + +typedef enum { + napi_key_keep_numbers, + napi_key_numbers_to_strings +} napi_key_conversion; +#endif // NAPI_VERSION >= 6 + #endif // SRC_JS_NATIVE_API_TYPES_H_ diff --git a/src/js_native_api_v8.cc b/src/js_native_api_v8.cc index f232248c4e12d3..dfffa2bcead8a1 100644 --- a/src/js_native_api_v8.cc +++ b/src/js_native_api_v8.cc @@ -935,6 +935,22 @@ napi_status napi_define_class(napi_env env, napi_status napi_get_property_names(napi_env env, napi_value object, napi_value* result) { + return napi_get_all_property_names( + env, + object, + napi_key_include_prototypes, + static_cast(napi_key_enumerable | + napi_key_skip_symbols), + napi_key_numbers_to_strings, + result); +} + +napi_status napi_get_all_property_names(napi_env env, + napi_value object, + napi_key_collection_mode key_mode, + napi_key_filter key_filter, + napi_key_conversion key_conversion, + napi_value* result) { NAPI_PREAMBLE(env); CHECK_ARG(env, result); @@ -942,19 +958,69 @@ napi_status napi_get_property_names(napi_env env, v8::Local obj; CHECK_TO_OBJECT(env, context, obj, object); - v8::MaybeLocal maybe_propertynames = obj->GetPropertyNames( - context, - v8::KeyCollectionMode::kIncludePrototypes, - static_cast( - v8::PropertyFilter::ONLY_ENUMERABLE | - v8::PropertyFilter::SKIP_SYMBOLS), - v8::IndexFilter::kIncludeIndices, - v8::KeyConversionMode::kConvertToString); + v8::PropertyFilter filter = v8::PropertyFilter::ALL_PROPERTIES; + if (key_filter & napi_key_writable) { + filter = + static_cast(filter | + v8::PropertyFilter::ONLY_WRITABLE); + } + if (key_filter & napi_key_enumerable) { + filter = + static_cast(filter | + v8::PropertyFilter::ONLY_ENUMERABLE); + } + if (key_filter & napi_key_configurable) { + filter = + static_cast(filter | + v8::PropertyFilter::ONLY_WRITABLE); + } + if (key_filter & napi_key_skip_strings) { + filter = + static_cast(filter | + v8::PropertyFilter::SKIP_STRINGS); + } + if (key_filter & napi_key_skip_symbols) { + filter = + static_cast(filter | + v8::PropertyFilter::SKIP_SYMBOLS); + } + v8::KeyCollectionMode collection_mode; + v8::KeyConversionMode conversion_mode; + + switch (key_mode) { + case napi_key_include_prototypes: + collection_mode = v8::KeyCollectionMode::kIncludePrototypes; + break; + case napi_key_own_only: + collection_mode = v8::KeyCollectionMode::kOwnOnly; + break; + default: + return napi_set_last_error(env, napi_invalid_arg); + } - CHECK_MAYBE_EMPTY(env, maybe_propertynames, napi_generic_failure); + switch (key_conversion) { + case napi_key_keep_numbers: + conversion_mode = v8::KeyConversionMode::kKeepNumbers; + break; + case napi_key_numbers_to_strings: + conversion_mode = v8::KeyConversionMode::kConvertToString; + break; + default: + return napi_set_last_error(env, napi_invalid_arg); + } - *result = v8impl::JsValueFromV8LocalValue( - maybe_propertynames.ToLocalChecked()); + v8::MaybeLocal maybe_all_propertynames = + obj->GetPropertyNames(context, + collection_mode, + filter, + v8::IndexFilter::kIncludeIndices, + conversion_mode); + + CHECK_MAYBE_EMPTY_WITH_PREAMBLE( + env, maybe_all_propertynames, napi_generic_failure); + + *result = + v8impl::JsValueFromV8LocalValue(maybe_all_propertynames.ToLocalChecked()); return GET_RETURN_STATUS(env); } diff --git a/src/js_native_api_v8.h b/src/js_native_api_v8.h index ec397275164c8d..32fc16f155a7fe 100644 --- a/src/js_native_api_v8.h +++ b/src/js_native_api_v8.h @@ -199,6 +199,17 @@ napi_status napi_set_last_error(napi_env env, napi_status error_code, } \ } while (0) +#define RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env, condition, status) \ + do { \ + if (!(condition)) { \ + return napi_set_last_error( \ + (env), try_catch.HasCaught() ? napi_pending_exception : (status)); \ + } \ + } while (0) + +#define CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, maybe, status) \ + RETURN_STATUS_IF_FALSE_WITH_PREAMBLE((env), !((maybe).IsEmpty()), (status)) + namespace v8impl { //=== Conversion between V8 Handles and napi_value ======================== diff --git a/src/js_stream.cc b/src/js_stream.cc index 64941b1c4e4fb7..e4da0ce747e3a0 100644 --- a/src/js_stream.cc +++ b/src/js_stream.cc @@ -204,7 +204,7 @@ void JSStream::Initialize(Local target, FIXED_ONE_BYTE_STRING(env->isolate(), "JSStream"); t->SetClassName(jsStreamString); t->InstanceTemplate() - ->SetInternalFieldCount(StreamBase::kStreamBaseFieldCount); + ->SetInternalFieldCount(StreamBase::kInternalFieldCount); t->Inherit(AsyncWrap::GetConstructorTemplate(env)); env->SetProtoMethod(t, "finishWrite", Finish); diff --git a/src/json_utils.cc b/src/json_utils.cc new file mode 100644 index 00000000000000..aa03a6d7305d75 --- /dev/null +++ b/src/json_utils.cc @@ -0,0 +1,67 @@ +#include "json_utils.h" + +namespace node { + +std::string EscapeJsonChars(const std::string& str) { + const std::string control_symbols[0x20] = { + "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", + "\\u0006", "\\u0007", "\\b", "\\t", "\\n", "\\v", "\\f", "\\r", + "\\u000e", "\\u000f", "\\u0010", "\\u0011", "\\u0012", "\\u0013", + "\\u0014", "\\u0015", "\\u0016", "\\u0017", "\\u0018", "\\u0019", + "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f" + }; + + std::string ret; + size_t last_pos = 0; + size_t pos = 0; + for (; pos < str.size(); ++pos) { + std::string replace; + char ch = str[pos]; + if (ch == '\\') { + replace = "\\\\"; + } else if (ch == '\"') { + replace = "\\\""; + } else { + size_t num = static_cast(ch); + if (num < 0x20) replace = control_symbols[num]; + } + if (!replace.empty()) { + if (pos > last_pos) { + ret += str.substr(last_pos, pos - last_pos); + } + last_pos = pos + 1; + ret += replace; + } + } + // Append any remaining symbols. + if (last_pos < str.size()) { + ret += str.substr(last_pos, pos - last_pos); + } + return ret; +} + +std::string Reindent(const std::string& str, int indent_depth) { + std::string indent; + for (int i = 0; i < indent_depth; i++) indent += ' '; + + std::string out; + std::string::size_type pos = 0; + do { + std::string::size_type prev_pos = pos; + pos = str.find('\n', pos); + + out.append(indent); + + if (pos == std::string::npos) { + out.append(str, prev_pos, std::string::npos); + break; + } else { + pos++; + out.append(str, prev_pos, pos - prev_pos); + } + } while (true); + + return out; +} + +} // namespace node diff --git a/src/json_utils.h b/src/json_utils.h new file mode 100644 index 00000000000000..21e204328058ee --- /dev/null +++ b/src/json_utils.h @@ -0,0 +1,160 @@ +#ifndef SRC_JSON_UTILS_H_ +#define SRC_JSON_UTILS_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include +#include +#include + +namespace node { + +std::string EscapeJsonChars(const std::string& str); +std::string Reindent(const std::string& str, int indentation); + +// JSON compiler definitions. +class JSONWriter { + public: + JSONWriter(std::ostream& out, bool compact) + : out_(out), compact_(compact) {} + + private: + inline void indent() { indent_ += 2; } + inline void deindent() { indent_ -= 2; } + inline void advance() { + if (compact_) return; + for (int i = 0; i < indent_; i++) out_ << ' '; + } + inline void write_one_space() { + if (compact_) return; + out_ << ' '; + } + inline void write_new_line() { + if (compact_) return; + out_ << '\n'; + } + + public: + inline void json_start() { + if (state_ == kAfterValue) out_ << ','; + write_new_line(); + advance(); + out_ << '{'; + indent(); + state_ = kObjectStart; + } + + inline void json_end() { + write_new_line(); + deindent(); + advance(); + out_ << '}'; + state_ = kAfterValue; + } + template + inline void json_objectstart(T key) { + if (state_ == kAfterValue) out_ << ','; + write_new_line(); + advance(); + write_string(key); + out_ << ':'; + write_one_space(); + out_ << '{'; + indent(); + state_ = kObjectStart; + } + + template + inline void json_arraystart(T key) { + if (state_ == kAfterValue) out_ << ','; + write_new_line(); + advance(); + write_string(key); + out_ << ':'; + write_one_space(); + out_ << '['; + indent(); + state_ = kObjectStart; + } + inline void json_objectend() { + write_new_line(); + deindent(); + advance(); + out_ << '}'; + if (indent_ == 0) { + // Top-level object is complete, so end the line. + out_ << '\n'; + } + state_ = kAfterValue; + } + + inline void json_arrayend() { + write_new_line(); + deindent(); + advance(); + out_ << ']'; + state_ = kAfterValue; + } + template + inline void json_keyvalue(const T& key, const U& value) { + if (state_ == kAfterValue) out_ << ','; + write_new_line(); + advance(); + write_string(key); + out_ << ':'; + write_one_space(); + write_value(value); + state_ = kAfterValue; + } + + template + inline void json_element(const U& value) { + if (state_ == kAfterValue) out_ << ','; + write_new_line(); + advance(); + write_value(value); + state_ = kAfterValue; + } + + struct Null {}; // Usable as a JSON value. + + struct ForeignJSON { + std::string as_string; + }; + + private: + template ::is_specialized, bool>::type> + inline void write_value(T number) { + if (std::is_same::value) + out_ << (number ? "true" : "false"); + else + out_ << number; + } + + inline void write_value(Null null) { out_ << "null"; } + inline void write_value(const char* str) { write_string(str); } + inline void write_value(const std::string& str) { write_string(str); } + + inline void write_value(const ForeignJSON& json) { + out_ << Reindent(json.as_string, indent_); + } + + inline void write_string(const std::string& str) { + out_ << '"' << EscapeJsonChars(str) << '"'; + } + inline void write_string(const char* str) { write_string(std::string(str)); } + + enum JSONState { kObjectStart, kAfterValue }; + std::ostream& out_; + bool compact_; + int indent_ = 0; + int state_ = kObjectStart; +}; + +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_JSON_UTILS_H_ diff --git a/src/large_pages/ld.implicit.script b/src/large_pages/ld.implicit.script deleted file mode 100644 index 7f12e4bd7df9e5..00000000000000 --- a/src/large_pages/ld.implicit.script +++ /dev/null @@ -1,10 +0,0 @@ - SECTIONS { - .lpstub : { - *libc.a:*(.text .text.*) - *(.lpstub) - } - } - PROVIDE (__nodetext = .); - PROVIDE (_nodetext = .); - PROVIDE (nodetext = .); - INSERT BEFORE .text; diff --git a/src/large_pages/ld.implicit.script.lld b/src/large_pages/ld.implicit.script.lld deleted file mode 100644 index b85510bcf07eeb..00000000000000 --- a/src/large_pages/ld.implicit.script.lld +++ /dev/null @@ -1,3 +0,0 @@ - PROVIDE (__nodetext = .); - PROVIDE (_nodetext = .); - PROVIDE (nodetext = .); diff --git a/src/large_pages/node_large_page.cc b/src/large_pages/node_large_page.cc index f636c9f3142376..853a56f5bd5e4c 100644 --- a/src/large_pages/node_large_page.cc +++ b/src/large_pages/node_large_page.cc @@ -20,54 +20,90 @@ // // SPDX-License-Identifier: MIT +// The functions in this file map the .text section of Node.js into 2MB pages. +// They perform the following steps: +// +// 1: Find the Node.js binary's `.text` section in memory. This is done below in +// `FindNodeTextRegion`. It is accomplished in a platform-specific way. On +// Linux and FreeBSD, `dl_iterate_phdr(3)` is used. When the region is found, +// it is "trimmed" as follows: +// * Modify the start to point to the very beginning of the Node.js `.text` +// section (from symbol `__node_text_start` declared in node_text_start.S). +// * Possibly modify the end to account for the `lpstub` section which +// contains `MoveTextRegionToLargePages`, the function we do not wish to +// move (see below). +// * Align the address of the start to its nearest higher large page +// boundary. +// * Align the address of the end to its nearest lower large page boundary. +// +// 2: Move the text region to large pages. This is done below in +// `MoveTextRegionToLargePages`. We need to be very careful: +// a) `MoveTextRegionToLargePages` itself should not be moved. +// We use gcc attributes +// (__section__) to put it outside the `.text` section, +// (__aligned__) to align it at the 2M boundary, and +// (__noline__) to not inline this function. +// b) `MoveTextRegionToLargePages` should not call any function(s) that might +// be moved. +// To move the .text section, perform the following steps: +// * Map a new, temporary area and copy the original code there. +// * Use mmap using the start address with MAP_FIXED so we get exactly the +// same virtual address (except on OSX). On platforms other than Linux, +// use mmap flags to request hugepages. +// * On Linux use madvise with MADV_HUGEPAGE to use anonymous 2MB pages. +// * If successful copy the code to the newly mapped area and protect it to +// be readable and executable. +// * Unmap the temporary area. + #include "node_large_page.h" -#include "util.h" -#include "uv.h" -#include // _O_RDWR +#include // NOLINT(build/include) + +// Besides returning ENOTSUP at runtime we do nothing if this define is missing. +#if defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES +#include "debug_utils-inl.h" + +#if defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux__) +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif // ifndef _GNU_SOURCE +#elif defined(__FreeBSD__) +#include "uv.h" // uv_exepath +#endif // defined(__linux__) +#include +#endif // defined(__linux__) || defined(__FreeBSD__) + #include #include #if defined(__FreeBSD__) #include -#include #elif defined(__APPLE__) #include #endif -#include // readlink -#include // NOLINT(build/include) #include // PATH_MAX -#include -#include -#include #include #include #include #include #include -#include -#include -#include - -// The functions in this file map the text segment of node into 2M pages. -// The algorithm is simple -// Find the text region of node binary in memory -// 1: Examine the /proc/self/maps to determine the currently mapped text -// region and obtain the start and end -// Modify the start to point to the very beginning of node text segment -// (from variable nodetext setup in ld.script) -// Align the address of start and end to Large Page Boundaries -// -// 2: Move the text region to large pages -// Map a new area and copy the original code there -// Use mmap using the start address with MAP_FIXED so we get exactly the -// same virtual address -// Use madvise with MADV_HUGE_PAGE to use Anonymous 2M Pages -// If successful copy the code there and unmap the original region. - -extern char __nodetext; +#if defined(__linux__) || defined(__FreeBSD__) +extern "C" { +// This symbol must be declared weak because this file becomes part of all +// Node.js targets (like node_mksnapshot, node_mkcodecache, and cctest) and +// those files do not supply the symbol. +extern char __attribute__((weak)) __node_text_start; +extern char __start_lpstub; +} // extern "C" +#endif // defined(__linux__) || defined(__FreeBSD__) + +#endif // defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES namespace node { +#if defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES + +namespace { struct text_region { char* from; @@ -78,11 +114,18 @@ struct text_region { static const size_t hps = 2L * 1024 * 1024; -static void PrintWarning(const char* warn) { +template +inline void Debug(Args&&... args) { + node::Debug(&per_process::enabled_debug_list, + DebugCategory::HUGEPAGES, + std::forward(args)...); +} + +inline void PrintWarning(const char* warn) { fprintf(stderr, "Hugepages WARNING: %s\n", warn); } -static void PrintSystemError(int error) { +inline void PrintSystemError(int error) { PrintWarning(strerror(error)); } @@ -94,126 +137,91 @@ inline uintptr_t hugepage_align_down(uintptr_t addr) { return ((addr) & ~((hps) - 1)); } -// The format of the maps file is the following -// address perms offset dev inode pathname -// 00400000-00452000 r-xp 00000000 08:02 173521 /usr/bin/dbus-daemon -// This is also handling the case where the first line is not the binary. - -static struct text_region FindNodeTextRegion() { - struct text_region nregion; - nregion.found_text_region = false; -#if defined(__linux__) - std::ifstream ifs; - std::string map_line; - std::string permission; - std::string dev; - char dash; - uintptr_t start, end, offset, inode; - - ifs.open("/proc/self/maps"); - if (!ifs) { - PrintWarning("could not open /proc/self/maps"); - return nregion; - } - +#if defined(__linux__) || defined(__FreeBSD__) +#if defined(__FreeBSD__) +#ifndef ElfW +#define ElfW(name) Elf_##name +#endif // ifndef ElfW +#endif // defined(__FreeBSD__) + +struct dl_iterate_params { + uintptr_t start; + uintptr_t end; + uintptr_t reference_sym; std::string exename; - { - char selfexe[PATH_MAX]; - - size_t size = sizeof(selfexe); - if (uv_exepath(selfexe, &size)) - return nregion; - - exename = std::string(selfexe, size); - } +}; - while (std::getline(ifs, map_line)) { - std::istringstream iss(map_line); - iss >> std::hex >> start; - iss >> dash; - iss >> std::hex >> end; - iss >> permission; - iss >> offset; - iss >> dev; - iss >> inode; - if (inode != 0) { - std::string pathname; - iss >> pathname; - if (pathname == exename && permission == "r-xp") { - uintptr_t ntext = reinterpret_cast(&__nodetext); - if (ntext >= start && ntext < end) { - char* from = reinterpret_cast(hugepage_align_up(ntext)); - char* to = reinterpret_cast(hugepage_align_down(end)); - - if (from < to) { - size_t size = to - from; - nregion.found_text_region = true; - nregion.from = from; - nregion.to = to; - nregion.total_hugepages = size / hps; - } - break; +int FindMapping(struct dl_phdr_info* info, size_t, void* data) { + auto dl_params = static_cast(data); + if (dl_params->exename == std::string(info->dlpi_name)) { + for (int idx = 0; idx < info->dlpi_phnum; idx++) { + const ElfW(Phdr)* phdr = &info->dlpi_phdr[idx]; + if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X)) { + uintptr_t start = info->dlpi_addr + phdr->p_vaddr; + uintptr_t end = start + phdr->p_memsz; + + if (dl_params->reference_sym >= start && + dl_params->reference_sym <= end) { + dl_params->start = start; + dl_params->end = end; + return 1; } } } } + return 0; +} +#endif // defined(__linux__) || defined(__FreeBSD__) - ifs.close(); -#elif defined(__FreeBSD__) - std::string exename; +struct text_region FindNodeTextRegion() { + struct text_region nregion; + nregion.found_text_region = false; +#if defined(__linux__) || defined(__FreeBSD__) + dl_iterate_params dl_params = { + 0, 0, reinterpret_cast(&__node_text_start), "" + }; + uintptr_t lpstub_start = reinterpret_cast(&__start_lpstub); + +#if defined(__FreeBSD__) + // On FreeBSD we need the name of the binary, because `dl_iterate_phdr` does + // not pass in an empty string as the `dlpi_name` of the binary but rather its + // absolute path. { char selfexe[PATH_MAX]; size_t count = sizeof(selfexe); if (uv_exepath(selfexe, &count)) return nregion; - - exename = std::string(selfexe, count); - } - - size_t numpg; - int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()}; - const size_t miblen = arraysize(mib); - if (sysctl(mib, miblen, nullptr, &numpg, nullptr, 0) == -1) { - return nregion; - } - - // Enough for struct kinfo_vmentry. - numpg = numpg * 4 / 3; - auto alg = std::vector(numpg); - - if (sysctl(mib, miblen, alg.data(), &numpg, nullptr, 0) == -1) { - return nregion; + dl_params.exename = std::string(selfexe, count); } - - char* start = alg.data(); - char* end = start + numpg; - - while (start < end) { - kinfo_vmentry* entry = reinterpret_cast(start); - const size_t cursz = entry->kve_structsize; - if (cursz == 0) { - break; +#endif // defined(__FreeBSD__) + + if (dl_iterate_phdr(FindMapping, &dl_params) == 1) { + Debug("Hugepages info: start: %p - sym: %p - end: %p\n", + reinterpret_cast(dl_params.start), + reinterpret_cast(dl_params.reference_sym), + reinterpret_cast(dl_params.end)); + + dl_params.start = dl_params.reference_sym; + if (lpstub_start > dl_params.start && lpstub_start <= dl_params.end) { + Debug("Hugepages info: Trimming end for lpstub: %p\n", + reinterpret_cast(lpstub_start)); + dl_params.end = lpstub_start; } - if (entry->kve_path[0] == '\0') { - continue; - } - bool excmapping = ((entry->kve_protection & KVME_PROT_READ) && - (entry->kve_protection & KVME_PROT_EXEC)); - - if (!strcmp(exename.c_str(), entry->kve_path) && excmapping) { - char* estart = - reinterpret_cast(hugepage_align_up(entry->kve_start)); - char* eend = - reinterpret_cast(hugepage_align_down(entry->kve_end)); - size_t size = eend - estart; - nregion.found_text_region = true; - nregion.from = estart; - nregion.to = eend; - nregion.total_hugepages = size / hps; - break; + if (dl_params.start < dl_params.end) { + char* from = reinterpret_cast(hugepage_align_up(dl_params.start)); + char* to = reinterpret_cast(hugepage_align_down(dl_params.end)); + Debug("Hugepages info: Aligned range is %p - %p\n", from, to); + if (from < to) { + size_t pagecount = (to - from) / hps; + if (pagecount > 0) { + nregion.found_text_region = true; + nregion.from = from; + nregion.to = to; + nregion.total_hugepages = pagecount; + } + } } - start += cursz; } #elif defined(__APPLE__) struct vm_region_submap_info_64 map; @@ -250,11 +258,12 @@ static struct text_region FindNodeTextRegion() { } } #endif + Debug("Hugepages info: Found %d huge pages\n", nregion.total_hugepages); return nregion; } #if defined(__linux__) -static bool IsTransparentHugePagesEnabled() { +bool IsTransparentHugePagesEnabled() { std::ifstream ifs; ifs.open("/sys/kernel/mm/transparent_hugepage/enabled"); @@ -272,7 +281,7 @@ static bool IsTransparentHugePagesEnabled() { return always == "[always]" || madvise == "[madvise]"; } #elif defined(__FreeBSD__) -static bool IsSuperPagesEnabled() { +bool IsSuperPagesEnabled() { // It is enabled by default on amd64. unsigned int super_pages = 0; size_t super_pages_length = sizeof(super_pages); @@ -285,145 +294,156 @@ static bool IsSuperPagesEnabled() { } #endif -// Moving the text region to large pages. We need to be very careful. -// 1: This function itself should not be moved. -// We use a gcc attributes -// (__section__) to put it outside the ".text" section -// (__aligned__) to align it at 2M boundary -// (__noline__) to not inline this function -// 2: This function should not call any function(s) that might be moved. -// a. map a new area and copy the original code there -// b. mmap using the start address with MAP_FIXED so we get exactly -// the same virtual address (except on macOS). -// c. madvise with MADV_HUGE_PAGE -// d. If successful copy the code there and unmap the original region +// Functions in this class must always be inlined because they must end up in +// the `lpstub` section rather than the `.text` section. +class MemoryMapPointer { + public: + FORCE_INLINE explicit MemoryMapPointer() {} + FORCE_INLINE bool operator==(void* rhs) const { return mem_ == rhs; } + FORCE_INLINE void* mem() const { return mem_; } + MemoryMapPointer(const MemoryMapPointer&) = delete; + MemoryMapPointer(MemoryMapPointer&&) = delete; + void operator= (const MemoryMapPointer&) = delete; + void operator= (const MemoryMapPointer&&) = delete; + FORCE_INLINE void Reset(void* start, + size_t size, + int prot, + int flags, + int fd = -1, + size_t offset = 0) { + mem_ = mmap(start, size, prot, flags, fd, offset); + size_ = size; + } + FORCE_INLINE void Reset() { + mem_ = nullptr; + size_ = 0; + } + FORCE_INLINE ~MemoryMapPointer() { + if (mem_ == nullptr) return; + if (mem_ == MAP_FAILED) return; + if (munmap(mem_, size_) == 0) return; + PrintSystemError(errno); + } + + private: + size_t size_ = 0; + void* mem_ = nullptr; +}; + +} // End of anonymous namespace + int #if !defined(__APPLE__) -__attribute__((__section__(".lpstub"))) +__attribute__((__section__("lpstub"))) #else __attribute__((__section__("__TEXT,__lpstub"))) #endif __attribute__((__aligned__(hps))) __attribute__((__noinline__)) MoveTextRegionToLargePages(const text_region& r) { - void* nmem = nullptr; - void* tmem = nullptr; - int ret = 0; - - size_t size = r.to - r.from; + MemoryMapPointer nmem; + MemoryMapPointer tmem; void* start = r.from; + size_t size = r.to - r.from; - // Allocate temporary region preparing for copy. - nmem = mmap(nullptr, size, - PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (nmem == MAP_FAILED) { - PrintSystemError(errno); - return -1; - } - OnScopeLeave munmap_on_return([nmem, size]() { - if (-1 == munmap(nmem, size)) PrintSystemError(errno); - }); - - memcpy(nmem, r.from, size); + // Allocate a temporary region and back up the code we will re-map. + nmem.Reset(nullptr, size, + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS); + if (nmem.mem() == MAP_FAILED) goto fail; + memcpy(nmem.mem(), r.from, size); #if defined(__linux__) // We already know the original page is r-xp // (PROT_READ, PROT_EXEC, MAP_PRIVATE) // We want PROT_WRITE because we are writing into it. // We want it at the fixed address and we use MAP_FIXED. - tmem = mmap(start, size, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1 , 0); - if (tmem == MAP_FAILED) { - PrintSystemError(errno); - return -1; - } - - ret = madvise(tmem, size, MADV_HUGEPAGE); - if (ret == -1) { - PrintSystemError(errno); - ret = munmap(tmem, size); - if (ret == -1) { - PrintSystemError(errno); - } - return -1; - } - memcpy(start, nmem, size); + tmem.Reset(start, size, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED); + if (tmem.mem() == MAP_FAILED) goto fail; + if (madvise(tmem.mem(), size, 14 /* MADV_HUGEPAGE */) == -1) goto fail; + memcpy(start, nmem.mem(), size); #elif defined(__FreeBSD__) - tmem = mmap(start, size, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | - MAP_ALIGNED_SUPER, -1 , 0); - if (tmem == MAP_FAILED) { - PrintSystemError(errno); - return -1; - } + tmem.Reset(start, size, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | + MAP_ALIGNED_SUPER); + if (tmem.mem() == MAP_FAILED) goto fail; + memcpy(start, nmem.mem(), size); #elif defined(__APPLE__) // There is not enough room to reserve the mapping close // to the region address so we content to give a hint // without forcing the new address being closed to. // We explicitally gives all permission since we plan // to write into it. - tmem = mmap(start, size, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, - VM_FLAGS_SUPERPAGE_SIZE_2MB, 0); - if (tmem == MAP_FAILED) { - PrintSystemError(errno); - return -1; - } - memcpy(tmem, nmem, size); - ret = mprotect(start, size, PROT_READ | PROT_WRITE | PROT_EXEC); - if (ret == -1) { - PrintSystemError(errno); - ret = munmap(tmem, size); - if (ret == -1) { - PrintSystemError(errno); - } - return -1; - } - memcpy(start, tmem, size); + tmem.Reset(start, size, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, + VM_FLAGS_SUPERPAGE_SIZE_2MB); + if (tmem.mem() == MAP_FAILED) goto fail; + memcpy(tmem.mem(), nmem.mem(), size); + if (mprotect(start, size, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) + goto fail; + memcpy(start, tmem.mem(), size); #endif - ret = mprotect(start, size, PROT_READ | PROT_EXEC); - if (ret == -1) { - PrintSystemError(errno); - ret = munmap(tmem, size); - if (ret == -1) { - PrintSystemError(errno); - } - return -1; - } - return ret; + if (mprotect(start, size, PROT_READ | PROT_EXEC) == -1) goto fail; + + // We need not `munmap(tmem, size)` on success. + tmem.Reset(); + return 0; +fail: + PrintSystemError(errno); + return -1; } +#endif // defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES // This is the primary API called from main. int MapStaticCodeToLargePages() { - struct text_region r = FindNodeTextRegion(); - if (r.found_text_region == false) { - PrintWarning("failed to find text region"); - return -1; - } - +#if defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES + bool have_thp = false; #if defined(__linux__) - if (r.from > reinterpret_cast(&MoveTextRegionToLargePages)) - return MoveTextRegionToLargePages(r); + have_thp = IsTransparentHugePagesEnabled(); +#elif defined(__FreeBSD__) + have_thp = IsSuperPagesEnabled(); +#elif defined(__APPLE__) + // pse-36 flag is present in recent mac x64 products. + have_thp = true; +#endif + if (!have_thp) + return EACCES; + + struct text_region r = FindNodeTextRegion(); + if (r.found_text_region == false) + return ENOENT; - return -1; -#elif defined(__FreeBSD__) || defined(__APPLE__) return MoveTextRegionToLargePages(r); +#else + return ENOTSUP; #endif } -bool IsLargePagesEnabled() { -#if defined(__linux__) - return IsTransparentHugePagesEnabled(); -#elif defined(__FreeBSD__) - return IsSuperPagesEnabled(); -#elif defined(__APPLE__) - // pse-36 flag is present in recent mac x64 products. - return true; -#endif +const char* LargePagesError(int status) { + switch (status) { + case ENOTSUP: + return "Mapping to large pages is not supported."; + + case EACCES: + return "Large pages are not enabled."; + + case ENOENT: + return "failed to find text region"; + + case -1: + return "Mapping code to large pages failed. Reverting to default page " + "size."; + + case 0: + return "OK"; + + default: + return "Unknown error"; + } } } // namespace node diff --git a/src/large_pages/node_large_page.h b/src/large_pages/node_large_page.h index bce505585cf0d0..622cf09ede4e1c 100644 --- a/src/large_pages/node_large_page.h +++ b/src/large_pages/node_large_page.h @@ -25,10 +25,9 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS - namespace node { -bool IsLargePagesEnabled(); int MapStaticCodeToLargePages(); +const char* LargePagesError(int status); } // namespace node #endif // NODE_WANT_INTERNALS diff --git a/src/large_pages/node_text_start.S b/src/large_pages/node_text_start.S new file mode 100644 index 00000000000000..1609b254f0495a --- /dev/null +++ b/src/large_pages/node_text_start.S @@ -0,0 +1,5 @@ +.text +.align 0x2000 +.global __node_text_start +.hidden __node_text_start +__node_text_start: diff --git a/src/memory_tracker-inl.h b/src/memory_tracker-inl.h index 2e39fa21a944d8..97be794bb86ba5 100644 --- a/src/memory_tracker-inl.h +++ b/src/memory_tracker-inl.h @@ -81,6 +81,14 @@ void MemoryTracker::TrackFieldWithSize(const char* edge_name, if (size > 0) AddNode(GetNodeName(node_name, edge_name), size, edge_name); } +void MemoryTracker::TrackInlineFieldWithSize(const char* edge_name, + size_t size, + const char* node_name) { + if (size > 0) AddNode(GetNodeName(node_name, edge_name), size, edge_name); + CHECK(CurrentNode()); + CurrentNode()->size_ -= size; +} + void MemoryTracker::TrackField(const char* edge_name, const MemoryRetainer& value, const char* node_name) { @@ -232,6 +240,12 @@ void MemoryTracker::TrackField(const char* name, TrackFieldWithSize(name, sizeof(value), "uv_async_t"); } +void MemoryTracker::TrackInlineField(const char* name, + const uv_async_t& value, + const char* node_name) { + TrackInlineFieldWithSize(name, sizeof(value), "uv_async_t"); +} + template void MemoryTracker::TrackField(const char* name, const AliasedBufferBase& value, diff --git a/src/memory_tracker.h b/src/memory_tracker.h index a400009aad6728..6cd372f493c41d 100644 --- a/src/memory_tracker.h +++ b/src/memory_tracker.h @@ -135,6 +135,10 @@ class MemoryTracker { inline void TrackFieldWithSize(const char* edge_name, size_t size, const char* node_name = nullptr); + inline void TrackInlineFieldWithSize(const char* edge_name, + size_t size, + const char* node_name = nullptr); + // Shortcut to extract the underlying object out of the smart pointer template inline void TrackField(const char* edge_name, @@ -220,6 +224,9 @@ class MemoryTracker { inline void TrackField(const char* edge_name, const uv_async_t& value, const char* node_name = nullptr); + inline void TrackInlineField(const char* edge_name, + const uv_async_t& value, + const char* node_name = nullptr); template inline void TrackField(const char* edge_name, const AliasedBufferBase& value, diff --git a/src/module_wrap.cc b/src/module_wrap.cc index 29078bf6e58ce1..f578f752b02d8b 100644 --- a/src/module_wrap.cc +++ b/src/module_wrap.cc @@ -2,12 +2,13 @@ #include "env.h" #include "memory_tracker-inl.h" +#include "node_contextify.h" #include "node_errors.h" +#include "node_internals.h" +#include "node_process.h" #include "node_url.h" -#include "util-inl.h" -#include "node_contextify.h" #include "node_watchdog.h" -#include "node_process.h" +#include "util-inl.h" #include // S_IFDIR @@ -22,12 +23,13 @@ using node::contextify::ContextifyContext; using node::url::URL; using node::url::URL_FLAGS_FAILED; using v8::Array; +using v8::ArrayBuffer; +using v8::ArrayBufferView; using v8::Context; using v8::EscapableHandleScope; using v8::Function; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; -using v8::Global; using v8::HandleScope; using v8::Integer; using v8::IntegrityLevel; @@ -37,7 +39,6 @@ using v8::Local; using v8::Maybe; using v8::MaybeLocal; using v8::Module; -using v8::Nothing; using v8::Number; using v8::Object; using v8::PrimitiveArray; @@ -46,24 +47,18 @@ using v8::ScriptCompiler; using v8::ScriptOrigin; using v8::ScriptOrModule; using v8::String; +using v8::UnboundModuleScript; using v8::Undefined; using v8::Value; -static const char* const EXTENSIONS[] = { - ".js", - ".json", - ".node", - ".mjs" -}; - ModuleWrap::ModuleWrap(Environment* env, Local object, Local module, - Local url) : - BaseObject(env, object), - id_(env->get_next_module_id()) { - module_.Reset(env->isolate(), module); - url_.Reset(env->isolate(), url); + Local url) + : BaseObject(env, object), + module_(env->isolate(), module), + url_(env->isolate(), url), + id_(env->get_next_module_id()) { env->id_to_module_map.emplace(id_, this); } @@ -133,7 +128,7 @@ void ModuleWrap::New(const FunctionCallbackInfo& args) { // new ModuleWrap(url, context, exportNames, syntheticExecutionFunction) CHECK(args[3]->IsFunction()); } else { - // new ModuleWrap(url, context, source, lineOffset, columOffset) + // new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData) CHECK(args[2]->IsString()); CHECK(args[3]->IsNumber()); line_offset = args[3].As(); @@ -169,6 +164,18 @@ void ModuleWrap::New(const FunctionCallbackInfo& args) { module = Module::CreateSyntheticModule(isolate, url, export_names, SyntheticModuleEvaluationStepsCallback); } else { + ScriptCompiler::CachedData* cached_data = nullptr; + if (!args[5]->IsUndefined()) { + CHECK(args[5]->IsArrayBufferView()); + Local cached_data_buf = args[5].As(); + ArrayBuffer::Contents contents = + cached_data_buf->Buffer()->GetContents(); + uint8_t* data = static_cast(contents.Data()); + cached_data = + new ScriptCompiler::CachedData(data + cached_data_buf->ByteOffset(), + cached_data_buf->ByteLength()); + } + Local source_text = args[2].As(); ScriptOrigin origin(url, line_offset, // line offset @@ -180,8 +187,15 @@ void ModuleWrap::New(const FunctionCallbackInfo& args) { False(isolate), // is WASM True(isolate), // is ES Module host_defined_options); - ScriptCompiler::Source source(source_text, origin); - if (!ScriptCompiler::CompileModule(isolate, &source).ToLocal(&module)) { + ScriptCompiler::Source source(source_text, origin, cached_data); + ScriptCompiler::CompileOptions options; + if (source.GetCachedData() == nullptr) { + options = ScriptCompiler::kNoCompileOptions; + } else { + options = ScriptCompiler::kConsumeCodeCache; + } + if (!ScriptCompiler::CompileModule(isolate, &source, options) + .ToLocal(&module)) { if (try_catch.HasCaught() && !try_catch.HasTerminated()) { CHECK(!try_catch.Message().IsEmpty()); CHECK(!try_catch.Exception().IsEmpty()); @@ -191,6 +205,13 @@ void ModuleWrap::New(const FunctionCallbackInfo& args) { } return; } + if (options == ScriptCompiler::kConsumeCodeCache && + source.GetCachedData()->rejected) { + THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED( + env, "cachedData buffer was rejected"); + try_catch.ReThrow(); + return; + } } } @@ -252,7 +273,7 @@ void ModuleWrap::Link(const FunctionCallbackInfo& args) { }; MaybeLocal maybe_resolve_return_value = - resolver_arg->Call(mod_context, that, 1, argv); + resolver_arg->Call(mod_context, that, arraysize(argv), argv); if (maybe_resolve_return_value.IsEmpty()) { return; } @@ -423,7 +444,12 @@ MaybeLocal ModuleWrap::ResolveCallback(Local context, Local specifier, Local referrer) { Environment* env = Environment::GetCurrent(context); - CHECK_NOT_NULL(env); // TODO(addaleax): Handle nullptr here. + if (env == nullptr) { + Isolate* isolate = context->GetIsolate(); + THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(isolate); + return MaybeLocal(); + } + Isolate* isolate = env->isolate(); ModuleWrap* dependent = GetFromModule(env, referrer); @@ -461,961 +487,17 @@ MaybeLocal ModuleWrap::ResolveCallback(Local context, return module->module_.Get(isolate); } -namespace { - -// Tests whether a path starts with /, ./ or ../ -// In WhatWG terminology, the alternative case is called a "bare" specifier -// (e.g. in `import "jquery"`). -inline bool ShouldBeTreatedAsRelativeOrAbsolutePath( - const std::string& specifier) { - size_t len = specifier.length(); - if (len == 0) - return false; - if (specifier[0] == '/') { - return true; - } else if (specifier[0] == '.') { - if (len == 1 || specifier[1] == '/') - return true; - if (specifier[1] == '.') { - if (len == 2 || specifier[2] == '/') - return true; - } - } - return false; -} - -std::string ReadFile(uv_file file) { - std::string contents; - uv_fs_t req; - char buffer_memory[4096]; - uv_buf_t buf = uv_buf_init(buffer_memory, sizeof(buffer_memory)); - - do { - const int r = uv_fs_read(nullptr, - &req, - file, - &buf, - 1, - contents.length(), // offset - nullptr); - uv_fs_req_cleanup(&req); - - if (r <= 0) - break; - contents.append(buf.base, r); - } while (true); - return contents; -} - -enum DescriptorType { - FILE, - DIRECTORY, - NONE -}; - -// When DescriptorType cache is added, this can also return -// Nothing for the "null" cache entries. -inline Maybe OpenDescriptor(const std::string& path) { - uv_fs_t fs_req; -#ifdef _WIN32 - std::string pth = "\\\\.\\" + path; - uv_file fd = uv_fs_open(nullptr, &fs_req, pth.c_str(), O_RDONLY, 0, nullptr); -#else - uv_file fd = uv_fs_open(nullptr, &fs_req, path.c_str(), O_RDONLY, 0, nullptr); -#endif - uv_fs_req_cleanup(&fs_req); - if (fd < 0) return Nothing(); - return Just(fd); -} - -inline void CloseDescriptor(uv_file fd) { - uv_fs_t fs_req; - CHECK_EQ(0, uv_fs_close(nullptr, &fs_req, fd, nullptr)); - uv_fs_req_cleanup(&fs_req); -} - -inline DescriptorType CheckDescriptorAtFile(uv_file fd) { - uv_fs_t fs_req; - int rc = uv_fs_fstat(nullptr, &fs_req, fd, nullptr); - if (rc == 0) { - uint64_t is_directory = fs_req.statbuf.st_mode & S_IFDIR; - uv_fs_req_cleanup(&fs_req); - return is_directory ? DIRECTORY : FILE; - } - uv_fs_req_cleanup(&fs_req); - return NONE; -} - -// TODO(@guybedford): Add a DescriptorType cache layer here. -// Should be directory based -> if path/to/dir doesn't exist -// then the cache should early-fail any path/to/dir/file check. -DescriptorType CheckDescriptorAtPath(const std::string& path) { - Maybe fd = OpenDescriptor(path); - if (fd.IsNothing()) return NONE; - DescriptorType type = CheckDescriptorAtFile(fd.FromJust()); - CloseDescriptor(fd.FromJust()); - return type; -} - -Maybe ReadIfFile(const std::string& path) { - Maybe fd = OpenDescriptor(path); - if (fd.IsNothing()) return Nothing(); - DescriptorType type = CheckDescriptorAtFile(fd.FromJust()); - if (type != FILE) return Nothing(); - std::string source = ReadFile(fd.FromJust()); - CloseDescriptor(fd.FromJust()); - return Just(source); -} - -using Exists = PackageConfig::Exists; -using IsValid = PackageConfig::IsValid; -using HasMain = PackageConfig::HasMain; -using HasName = PackageConfig::HasName; -using PackageType = PackageConfig::PackageType; - -Maybe GetPackageConfig(Environment* env, - const std::string& path, - const URL& base) { - auto existing = env->package_json_cache.find(path); - if (existing != env->package_json_cache.end()) { - const PackageConfig* pcfg = &existing->second; - if (pcfg->is_valid == IsValid::No) { - std::string msg = "Invalid JSON in " + path + - " imported from " + base.ToFilePath(); - node::THROW_ERR_INVALID_PACKAGE_CONFIG(env, msg.c_str()); - return Nothing(); - } - return Just(pcfg); - } - - Maybe source = ReadIfFile(path); - - if (source.IsNothing()) { - auto entry = env->package_json_cache.emplace(path, - PackageConfig { Exists::No, IsValid::Yes, HasMain::No, "", - HasName::No, "", - PackageType::None, Global() }); - return Just(&entry.first->second); - } - - std::string pkg_src = source.FromJust(); - - Isolate* isolate = env->isolate(); - HandleScope handle_scope(isolate); - - Local pkg_json; - { - Local src; - Local pkg_json_v; - Local context = env->context(); - - if (!ToV8Value(context, pkg_src).ToLocal(&src) || - !v8::JSON::Parse(context, src.As()).ToLocal(&pkg_json_v) || - !pkg_json_v->ToObject(context).ToLocal(&pkg_json)) { - env->package_json_cache.emplace(path, - PackageConfig { Exists::Yes, IsValid::No, HasMain::No, "", - HasName::No, "", - PackageType::None, Global() }); - std::string msg = "Invalid JSON in " + path + - " imported from " + base.ToFilePath(); - node::THROW_ERR_INVALID_PACKAGE_CONFIG(env, msg.c_str()); - return Nothing(); - } - } - - Local pkg_main; - HasMain has_main = HasMain::No; - std::string main_std; - if (pkg_json->Get(env->context(), env->main_string()).ToLocal(&pkg_main)) { - if (pkg_main->IsString()) { - has_main = HasMain::Yes; - } - Utf8Value main_utf8(isolate, pkg_main); - main_std.assign(std::string(*main_utf8, main_utf8.length())); - } - - Local pkg_name; - HasName has_name = HasName::No; - std::string name_std; - if (pkg_json->Get(env->context(), env->name_string()).ToLocal(&pkg_name)) { - if (pkg_name->IsString()) { - has_name = HasName::Yes; - - Utf8Value name_utf8(isolate, pkg_name); - name_std.assign(std::string(*name_utf8, name_utf8.length())); - } - } - - PackageType pkg_type = PackageType::None; - Local type_v; - if (pkg_json->Get(env->context(), env->type_string()).ToLocal(&type_v)) { - if (type_v->StrictEquals(env->module_string())) { - pkg_type = PackageType::Module; - } else if (type_v->StrictEquals(env->commonjs_string())) { - pkg_type = PackageType::CommonJS; - } - // ignore unknown types for forwards compatibility - } - - Local exports_v; - if (pkg_json->Get(env->context(), - env->exports_string()).ToLocal(&exports_v) && - !exports_v->IsNullOrUndefined()) { - Global exports; - exports.Reset(env->isolate(), exports_v); - - auto entry = env->package_json_cache.emplace(path, - PackageConfig { Exists::Yes, IsValid::Yes, has_main, main_std, - has_name, name_std, - pkg_type, std::move(exports) }); - return Just(&entry.first->second); - } - - auto entry = env->package_json_cache.emplace(path, - PackageConfig { Exists::Yes, IsValid::Yes, has_main, main_std, - has_name, name_std, - pkg_type, Global() }); - return Just(&entry.first->second); -} - -Maybe GetPackageScopeConfig(Environment* env, - const URL& resolved, - const URL& base) { - URL pjson_url("./package.json", &resolved); - while (true) { - std::string pjson_url_path = pjson_url.path(); - if (pjson_url_path.length() > 25 && - pjson_url_path.substr(pjson_url_path.length() - 25, 25) == - "node_modules/package.json") { - break; - } - Maybe pkg_cfg = - GetPackageConfig(env, pjson_url.ToFilePath(), base); - if (pkg_cfg.IsNothing()) return pkg_cfg; - if (pkg_cfg.FromJust()->exists == Exists::Yes) return pkg_cfg; - - URL last_pjson_url = pjson_url; - pjson_url = URL("../package.json", pjson_url); - - // Terminates at root where ../package.json equals ../../package.json - // (can't just check "/package.json" for Windows support). - if (pjson_url.path() == last_pjson_url.path()) break; - } - auto entry = env->package_json_cache.emplace(pjson_url.ToFilePath(), - PackageConfig { Exists::No, IsValid::Yes, HasMain::No, "", - HasName::No, "", - PackageType::None, Global() }); - const PackageConfig* pcfg = &entry.first->second; - return Just(pcfg); -} - -/* - * Legacy CommonJS main resolution: - * 1. let M = pkg_url + (json main field) - * 2. TRY(M, M.js, M.json, M.node) - * 3. TRY(M/index.js, M/index.json, M/index.node) - * 4. TRY(pkg_url/index.js, pkg_url/index.json, pkg_url/index.node) - * 5. NOT_FOUND - */ -inline bool FileExists(const URL& url) { - return CheckDescriptorAtPath(url.ToFilePath()) == FILE; -} -Maybe LegacyMainResolve(const URL& pjson_url, - const PackageConfig& pcfg) { - URL guess; - if (pcfg.has_main == HasMain::Yes) { - // Note: fs check redundances will be handled by Descriptor cache here. - if (FileExists(guess = URL("./" + pcfg.main, pjson_url))) { - return Just(guess); - } - if (FileExists(guess = URL("./" + pcfg.main + ".js", pjson_url))) { - return Just(guess); - } - if (FileExists(guess = URL("./" + pcfg.main + ".json", pjson_url))) { - return Just(guess); - } - if (FileExists(guess = URL("./" + pcfg.main + ".node", pjson_url))) { - return Just(guess); - } - if (FileExists(guess = URL("./" + pcfg.main + "/index.js", pjson_url))) { - return Just(guess); - } - // Such stat. - if (FileExists(guess = URL("./" + pcfg.main + "/index.json", pjson_url))) { - return Just(guess); - } - if (FileExists(guess = URL("./" + pcfg.main + "/index.node", pjson_url))) { - return Just(guess); - } - // Fallthrough. - } - if (FileExists(guess = URL("./index.js", pjson_url))) { - return Just(guess); - } - // So fs. - if (FileExists(guess = URL("./index.json", pjson_url))) { - return Just(guess); - } - if (FileExists(guess = URL("./index.node", pjson_url))) { - return Just(guess); - } - // Not found. - return Nothing(); -} - -enum ResolveExtensionsOptions { - TRY_EXACT_NAME, - ONLY_VIA_EXTENSIONS -}; - -template -Maybe ResolveExtensions(const URL& search) { - if (options == TRY_EXACT_NAME) { - if (FileExists(search)) { - return Just(search); - } - } - - for (const char* extension : EXTENSIONS) { - URL guess(search.path() + extension, &search); - if (FileExists(guess)) { - return Just(guess); - } - } - - return Nothing(); -} - -inline Maybe ResolveIndex(const URL& search) { - return ResolveExtensions(URL("index", search)); -} - -Maybe FinalizeResolution(Environment* env, - const URL& resolved, - const URL& base) { - if (env->options()->experimental_specifier_resolution == "node") { - Maybe file = ResolveExtensions(resolved); - if (!file.IsNothing()) { - return file; - } - if (resolved.path().back() != '/') { - file = ResolveIndex(URL(resolved.path() + "/", &base)); - } else { - file = ResolveIndex(resolved); - } - if (!file.IsNothing()) { - return file; - } - std::string msg = "Cannot find module " + resolved.path() + - " imported from " + base.ToFilePath(); - node::THROW_ERR_MODULE_NOT_FOUND(env, msg.c_str()); - return Nothing(); - } - - if (resolved.path().back() == '/') { - return Just(resolved); - } - - const std::string& path = resolved.ToFilePath(); - if (CheckDescriptorAtPath(path) != FILE) { - std::string msg = "Cannot find module " + - (path.length() != 0 ? path : resolved.path()) + - " imported from " + base.ToFilePath(); - node::THROW_ERR_MODULE_NOT_FOUND(env, msg.c_str()); - return Nothing(); - } - - return Just(resolved); -} - -void ThrowExportsNotFound(Environment* env, - const std::string& subpath, - const URL& pjson_url, - const URL& base) { - const std::string msg = "Package subpath '" + subpath + "' is not defined" + - " by \"exports\" in " + pjson_url.ToFilePath() + " imported from " + - base.ToFilePath(); - node::THROW_ERR_PACKAGE_PATH_NOT_EXPORTED(env, msg.c_str()); -} - -void ThrowSubpathInvalid(Environment* env, - const std::string& subpath, - const URL& pjson_url, - const URL& base) { - const std::string msg = "Package subpath '" + subpath + "' is not a valid " + - "module request for the \"exports\" resolution of " + - pjson_url.ToFilePath() + " imported from " + base.ToFilePath(); - node::THROW_ERR_INVALID_MODULE_SPECIFIER(env, msg.c_str()); -} - -void ThrowExportsInvalid(Environment* env, - const std::string& subpath, - const std::string& target, - const URL& pjson_url, - const URL& base) { - if (subpath.length()) { - const std::string msg = "Invalid \"exports\" target \"" + target + - "\" defined for '" + subpath + "' in the package config " + - pjson_url.ToFilePath() + " imported from " + base.ToFilePath(); - node::THROW_ERR_INVALID_PACKAGE_TARGET(env, msg.c_str()); - } else { - const std::string msg = "Invalid \"exports\" main target " + target + - " defined in the package config " + pjson_url.ToFilePath() + - " imported from " + base.ToFilePath(); - node::THROW_ERR_INVALID_PACKAGE_TARGET(env, msg.c_str()); - } -} - -void ThrowExportsInvalid(Environment* env, - const std::string& subpath, - Local target, - const URL& pjson_url, - const URL& base) { - Local target_string; - if (target->IsObject()) { - if (!v8::JSON::Stringify(env->context(), target.As(), - v8::String::Empty(env->isolate())).ToLocal(&target_string)) - return; - } else { - if (!target->ToString(env->context()).ToLocal(&target_string)) - return; - } - Utf8Value target_utf8(env->isolate(), target_string); - std::string target_str(*target_utf8, target_utf8.length()); - if (target->IsArray()) { - target_str = '[' + target_str + ']'; - } - ThrowExportsInvalid(env, subpath, target_str, pjson_url, base); -} - -Maybe ResolveExportsTargetString(Environment* env, - const std::string& target, - const std::string& subpath, - const std::string& match, - const URL& pjson_url, - const URL& base) { - if (target.substr(0, 2) != "./") { - ThrowExportsInvalid(env, match, target, pjson_url, base); - return Nothing(); - } - if (subpath.length() > 0 && target.back() != '/') { - ThrowExportsInvalid(env, match, target, pjson_url, base); - return Nothing(); - } - URL resolved(target, pjson_url); - std::string resolved_path = resolved.path(); - std::string pkg_path = URL(".", pjson_url).path(); - if (resolved_path.find(pkg_path) != 0 || - resolved_path.find("/node_modules/", pkg_path.length() - 1) != - std::string::npos) { - ThrowExportsInvalid(env, match, target, pjson_url, base); - return Nothing(); - } - if (subpath.length() == 0) return Just(resolved); - URL subpath_resolved(subpath, resolved); - std::string subpath_resolved_path = subpath_resolved.path(); - if (subpath_resolved_path.find(resolved_path) != 0 || - subpath_resolved_path.find("/node_modules/", pkg_path.length() - 1) - != std::string::npos) { - ThrowSubpathInvalid(env, match + subpath, pjson_url, base); - return Nothing(); - } - return Just(subpath_resolved); -} - -bool IsArrayIndex(Environment* env, Local p) { - Local context = env->context(); - Local p_str = p->ToString(context).ToLocalChecked(); - double n_dbl = static_cast(p_str->NumberValue(context).FromJust()); - Local n = Number::New(env->isolate(), n_dbl); - Local cmp_str = n->ToString(context).ToLocalChecked(); - if (!p_str->Equals(context, cmp_str).FromJust()) { - return false; - } - if (n_dbl == 0 && std::signbit(n_dbl) == false) { - return true; - } - Local cmp_integer; - if (!n->ToInteger(context).ToLocal(&cmp_integer)) { - return false; - } - return n_dbl > 0 && n_dbl < (1LL << 32) - 1; -} - -Maybe ResolveExportsTarget(Environment* env, - const URL& pjson_url, - Local target, - const std::string& subpath, - const std::string& pkg_subpath, - const URL& base) { - Isolate* isolate = env->isolate(); - Local context = env->context(); - if (target->IsString()) { - Utf8Value target_utf8(isolate, target.As()); - std::string target_str(*target_utf8, target_utf8.length()); - Maybe resolved = ResolveExportsTargetString(env, target_str, subpath, - pkg_subpath, pjson_url, base); - if (resolved.IsNothing()) { - return Nothing(); - } - return FinalizeResolution(env, resolved.FromJust(), base); - } else if (target->IsArray()) { - Local target_arr = target.As(); - const uint32_t length = target_arr->Length(); - if (length == 0) { - ThrowExportsInvalid(env, pkg_subpath, target, pjson_url, base); - return Nothing(); - } - for (uint32_t i = 0; i < length; i++) { - auto target_item = target_arr->Get(context, i).ToLocalChecked(); - { - TryCatchScope try_catch(env); - Maybe resolved = ResolveExportsTarget(env, pjson_url, - target_item, subpath, pkg_subpath, base); - if (resolved.IsNothing()) { - CHECK(try_catch.HasCaught()); - if (try_catch.Exception().IsEmpty()) return Nothing(); - Local e; - if (!try_catch.Exception()->ToObject(context).ToLocal(&e)) - return Nothing(); - Local code; - if (!e->Get(context, env->code_string()).ToLocal(&code)) - return Nothing(); - Local code_string; - if (!code->ToString(context).ToLocal(&code_string)) - return Nothing(); - Utf8Value code_utf8(env->isolate(), code_string); - if (strcmp(*code_utf8, "ERR_PACKAGE_PATH_NOT_EXPORTED") == 0 || - strcmp(*code_utf8, "ERR_INVALID_PACKAGE_TARGET") == 0) { - continue; - } - try_catch.ReThrow(); - return Nothing(); - } - CHECK(!try_catch.HasCaught()); - return FinalizeResolution(env, resolved.FromJust(), base); - } - } - auto invalid = target_arr->Get(context, length - 1).ToLocalChecked(); - Maybe resolved = ResolveExportsTarget(env, pjson_url, invalid, - subpath, pkg_subpath, base); - CHECK(resolved.IsNothing()); - return Nothing(); - } else if (target->IsObject()) { - Local target_obj = target.As(); - Local target_obj_keys = - target_obj->GetOwnPropertyNames(context).ToLocalChecked(); - Local conditionalTarget; - for (uint32_t i = 0; i < target_obj_keys->Length(); ++i) { - Local key = - target_obj_keys->Get(context, i).ToLocalChecked(); - if (IsArrayIndex(env, key)) { - const std::string msg = "Invalid package config " + - pjson_url.ToFilePath() + " imported from " + base.ToFilePath() + - ". \"exports\" cannot contain numeric property keys."; - node::THROW_ERR_INVALID_PACKAGE_CONFIG(env, msg.c_str()); - return Nothing(); - } - } - for (uint32_t i = 0; i < target_obj_keys->Length(); ++i) { - Local key = target_obj_keys->Get(context, i).ToLocalChecked(); - Utf8Value key_utf8(env->isolate(), - key->ToString(context).ToLocalChecked()); - std::string key_str(*key_utf8, key_utf8.length()); - if (key_str == "node" || key_str == "import") { - conditionalTarget = target_obj->Get(context, key).ToLocalChecked(); - { - TryCatchScope try_catch(env); - Maybe resolved = ResolveExportsTarget(env, pjson_url, - conditionalTarget, subpath, pkg_subpath, base); - if (resolved.IsNothing()) { - CHECK(try_catch.HasCaught()); - if (try_catch.Exception().IsEmpty()) return Nothing(); - Local e; - if (!try_catch.Exception()->ToObject(context).ToLocal(&e)) - return Nothing(); - Local code; - if (!e->Get(context, env->code_string()).ToLocal(&code)) - return Nothing(); - Local code_string; - if (!code->ToString(context).ToLocal(&code_string)) - return Nothing(); - Utf8Value code_utf8(env->isolate(), code_string); - if (strcmp(*code_utf8, "ERR_PACKAGE_PATH_NOT_EXPORTED") == 0) - continue; - try_catch.ReThrow(); - return Nothing(); - } - CHECK(!try_catch.HasCaught()); - return resolved; - } - } else if (key_str == "default") { - conditionalTarget = target_obj->Get(context, key).ToLocalChecked(); - { - TryCatchScope try_catch(env); - Maybe resolved = ResolveExportsTarget(env, pjson_url, - conditionalTarget, subpath, pkg_subpath, base); - if (resolved.IsNothing()) { - CHECK(try_catch.HasCaught() && !try_catch.Exception().IsEmpty()); - auto e = try_catch.Exception()->ToObject(context).ToLocalChecked(); - auto code = e->Get(context, env->code_string()).ToLocalChecked(); - Utf8Value code_utf8(env->isolate(), - code->ToString(context).ToLocalChecked()); - std::string code_str(*code_utf8, code_utf8.length()); - if (code_str == "ERR_PACKAGE_PATH_NOT_EXPORTED") continue; - try_catch.ReThrow(); - return Nothing(); - } - CHECK(!try_catch.HasCaught()); - return resolved; - } - } - } - ThrowExportsNotFound(env, pkg_subpath, pjson_url, base); - return Nothing(); - } - ThrowExportsInvalid(env, pkg_subpath, target, pjson_url, base); - return Nothing(); -} - -Maybe IsConditionalExportsMainSugar(Environment* env, - Local exports, - const URL& pjson_url, - const URL& base) { - if (exports->IsString() || exports->IsArray()) return Just(true); - if (!exports->IsObject()) return Just(false); - Local context = env->context(); - Local exports_obj = exports.As(); - Local keys = - exports_obj->GetOwnPropertyNames(context).ToLocalChecked(); - bool isConditionalSugar = false; - for (uint32_t i = 0; i < keys->Length(); ++i) { - Local key = keys->Get(context, i).ToLocalChecked(); - Utf8Value key_utf8(env->isolate(), key->ToString(context).ToLocalChecked()); - bool curIsConditionalSugar = key_utf8.length() == 0 || key_utf8[0] != '.'; - if (i == 0) { - isConditionalSugar = curIsConditionalSugar; - } else if (isConditionalSugar != curIsConditionalSugar) { - const std::string msg = "Invalid package config " + pjson_url.ToFilePath() - + " imported from " + base.ToFilePath() + ". " + - "\"exports\" cannot contain some keys starting with '.' and some not." + - " The exports object must either be an object of package subpath keys" + - " or an object of main entry condition name keys only."; - node::THROW_ERR_INVALID_PACKAGE_CONFIG(env, msg.c_str()); - return Nothing(); - } - } - return Just(isConditionalSugar); -} - -Maybe PackageMainResolve(Environment* env, - const URL& pjson_url, - const PackageConfig& pcfg, - const URL& base) { - if (pcfg.exists == Exists::Yes) { - Isolate* isolate = env->isolate(); - - if (!pcfg.exports.IsEmpty()) { - Local exports = pcfg.exports.Get(isolate); - Maybe isConditionalExportsMainSugar = - IsConditionalExportsMainSugar(env, exports, pjson_url, base); - if (isConditionalExportsMainSugar.IsNothing()) - return Nothing(); - if (isConditionalExportsMainSugar.FromJust()) { - return ResolveExportsTarget(env, pjson_url, exports, "", "", base); - } else if (exports->IsObject()) { - Local exports_obj = exports.As(); - if (exports_obj->HasOwnProperty(env->context(), env->dot_string()) - .FromJust()) { - Local target = - exports_obj->Get(env->context(), env->dot_string()) - .ToLocalChecked(); - return ResolveExportsTarget(env, pjson_url, target, "", "", base); - } - } - std::string msg = "No \"exports\" main resolved in " + - pjson_url.ToFilePath(); - node::THROW_ERR_PACKAGE_PATH_NOT_EXPORTED(env, msg.c_str()); - } - if (pcfg.has_main == HasMain::Yes) { - URL resolved(pcfg.main, pjson_url); - const std::string& path = resolved.ToFilePath(); - if (CheckDescriptorAtPath(path) == FILE) { - return Just(resolved); - } - } - if (env->options()->experimental_specifier_resolution == "node") { - if (pcfg.has_main == HasMain::Yes) { - return FinalizeResolution(env, URL(pcfg.main, pjson_url), base); - } else { - return FinalizeResolution(env, URL("index", pjson_url), base); - } - } - if (pcfg.type != PackageType::Module) { - Maybe resolved = LegacyMainResolve(pjson_url, pcfg); - if (!resolved.IsNothing()) { - return resolved; - } - } - } - std::string msg = "Cannot find main entry point for " + - URL(".", pjson_url).ToFilePath() + " imported from " + - base.ToFilePath(); - node::THROW_ERR_MODULE_NOT_FOUND(env, msg.c_str()); - return Nothing(); -} - -Maybe PackageExportsResolve(Environment* env, - const URL& pjson_url, - const std::string& pkg_subpath, - const PackageConfig& pcfg, - const URL& base) { - Isolate* isolate = env->isolate(); - Local context = env->context(); - Local exports = pcfg.exports.Get(isolate); - Maybe isConditionalExportsMainSugar = - IsConditionalExportsMainSugar(env, exports, pjson_url, base); - if (isConditionalExportsMainSugar.IsNothing()) - return Nothing(); - if (!exports->IsObject() || isConditionalExportsMainSugar.FromJust()) { - ThrowExportsNotFound(env, pkg_subpath, pjson_url, base); - return Nothing(); - } - Local exports_obj = exports.As(); - Local subpath = String::NewFromUtf8(isolate, - pkg_subpath.c_str(), v8::NewStringType::kNormal).ToLocalChecked(); - - if (exports_obj->HasOwnProperty(context, subpath).FromJust()) { - Local target = exports_obj->Get(context, subpath).ToLocalChecked(); - Maybe resolved = ResolveExportsTarget(env, pjson_url, target, "", - pkg_subpath, base); - if (resolved.IsNothing()) { - return Nothing(); - } - return FinalizeResolution(env, resolved.FromJust(), base); - } - - Local best_match; - std::string best_match_str = ""; - Local keys = - exports_obj->GetOwnPropertyNames(context).ToLocalChecked(); - for (uint32_t i = 0; i < keys->Length(); ++i) { - Local key = keys->Get(context, i).ToLocalChecked(); - Utf8Value key_utf8(isolate, key->ToString(context).ToLocalChecked()); - std::string key_str(*key_utf8, key_utf8.length()); - if (key_str.back() != '/') continue; - if (pkg_subpath.substr(0, key_str.length()) == key_str && - key_str.length() > best_match_str.length()) { - best_match = key->ToString(context).ToLocalChecked(); - best_match_str = key_str; - } - } - - if (best_match_str.length() > 0) { - auto target = exports_obj->Get(context, best_match).ToLocalChecked(); - std::string subpath = pkg_subpath.substr(best_match_str.length()); - - Maybe resolved = ResolveExportsTarget(env, pjson_url, target, subpath, - pkg_subpath, base); - if (resolved.IsNothing()) { - return Nothing(); - } - return FinalizeResolution(env, resolved.FromJust(), base); - } - - ThrowExportsNotFound(env, pkg_subpath, pjson_url, base); - return Nothing(); -} - -Maybe PackageResolve(Environment* env, - const std::string& specifier, - const URL& base) { - size_t sep_index = specifier.find('/'); - bool valid_package_name = true; - bool scope = false; - if (specifier[0] == '@') { - scope = true; - if (sep_index == std::string::npos || specifier.length() == 0) { - valid_package_name = false; - } else { - sep_index = specifier.find('/', sep_index + 1); - } - } else if (specifier[0] == '.') { - valid_package_name = false; - } - std::string pkg_name = specifier.substr(0, - sep_index == std::string::npos ? std::string::npos : sep_index); - // Package name cannot have leading . and cannot have percent-encoding or - // separators. - for (size_t i = 0; i < pkg_name.length(); i++) { - char c = pkg_name[i]; - if (c == '%' || c == '\\') { - valid_package_name = false; - break; - } - } - if (!valid_package_name) { - std::string msg = "Invalid package name '" + specifier + - "' imported from " + base.ToFilePath(); - node::THROW_ERR_INVALID_MODULE_SPECIFIER(env, msg.c_str()); - return Nothing(); - } - std::string pkg_subpath; - if (sep_index == std::string::npos) { - pkg_subpath = ""; - } else { - pkg_subpath = "." + specifier.substr(sep_index); - } - - // ResolveSelf - const PackageConfig* pcfg; - if (GetPackageScopeConfig(env, base, base).To(&pcfg) && - pcfg->exists == Exists::Yes) { - // TODO(jkrems): Find a way to forward the pair/iterator already generated - // while executing GetPackageScopeConfig - URL pjson_url(""); - bool found_pjson = false; - for (const auto& it : env->package_json_cache) { - if (&it.second == pcfg) { - pjson_url = URL::FromFilePath(it.first); - found_pjson = true; - } - } - if (found_pjson && pcfg->name == pkg_name && !pcfg->exports.IsEmpty()) { - if (pkg_subpath == "./") { - return Just(URL("./", pjson_url)); - } else if (!pkg_subpath.length()) { - return PackageMainResolve(env, pjson_url, *pcfg, base); - } else { - return PackageExportsResolve(env, pjson_url, pkg_subpath, *pcfg, base); - } - } - } - - URL pjson_url("./node_modules/" + pkg_name + "/package.json", &base); - std::string pjson_path = pjson_url.ToFilePath(); - std::string last_path; - do { - DescriptorType check = - CheckDescriptorAtPath(pjson_path.substr(0, pjson_path.length() - 13)); - if (check != DIRECTORY) { - last_path = pjson_path; - pjson_url = URL((scope ? - "../../../../node_modules/" : "../../../node_modules/") + - pkg_name + "/package.json", &pjson_url); - pjson_path = pjson_url.ToFilePath(); - continue; - } - - // Package match. - Maybe pcfg = GetPackageConfig(env, pjson_path, base); - // Invalid package configuration error. - if (pcfg.IsNothing()) return Nothing(); - if (pkg_subpath == "./") { - return Just(URL("./", pjson_url)); - } else if (!pkg_subpath.length()) { - return PackageMainResolve(env, pjson_url, *pcfg.FromJust(), base); - } else { - if (!pcfg.FromJust()->exports.IsEmpty()) { - return PackageExportsResolve(env, pjson_url, pkg_subpath, - *pcfg.FromJust(), base); - } else { - return FinalizeResolution(env, URL(pkg_subpath, pjson_url), base); - } - } - CHECK(false); - // Cross-platform root check. - } while (pjson_path.length() != last_path.length()); - - std::string msg = "Cannot find package '" + pkg_name + - "' imported from " + base.ToFilePath(); - node::THROW_ERR_MODULE_NOT_FOUND(env, msg.c_str()); - return Nothing(); -} - -} // anonymous namespace - -Maybe Resolve(Environment* env, - const std::string& specifier, - const URL& base) { - // Order swapped from spec for minor perf gain. - // Ok since relative URLs cannot parse as URLs. - URL resolved; - if (ShouldBeTreatedAsRelativeOrAbsolutePath(specifier)) { - resolved = URL(specifier, base); - } else { - URL pure_url(specifier); - if (!(pure_url.flags() & URL_FLAGS_FAILED)) { - resolved = pure_url; - } else { - return PackageResolve(env, specifier, base); - } - } - return FinalizeResolution(env, resolved, base); -} - -void ModuleWrap::Resolve(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - - // module.resolve(specifier, url) - CHECK_EQ(args.Length(), 2); - - CHECK(args[0]->IsString()); - Utf8Value specifier_utf8(env->isolate(), args[0]); - std::string specifier_std(*specifier_utf8, specifier_utf8.length()); - - CHECK(args[1]->IsString()); - Utf8Value url_utf8(env->isolate(), args[1]); - URL url(*url_utf8, url_utf8.length()); - - if (url.flags() & URL_FLAGS_FAILED) { - return node::THROW_ERR_INVALID_ARG_TYPE( - env, "second argument is not a URL string"); - } - - Maybe result = - node::loader::Resolve(env, - specifier_std, - url); - if (result.IsNothing()) { - return; - } - - URL resolution = result.FromJust(); - CHECK(!(resolution.flags() & URL_FLAGS_FAILED)); - - Local resolution_obj; - if (resolution.ToObject(env).ToLocal(&resolution_obj)) - args.GetReturnValue().Set(resolution_obj); -} - -void ModuleWrap::GetPackageType(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - - // module.getPackageType(url) - CHECK_EQ(args.Length(), 1); - - CHECK(args[0]->IsString()); - Utf8Value url_utf8(env->isolate(), args[0]); - URL url(*url_utf8, url_utf8.length()); - - PackageType pkg_type = PackageType::None; - Maybe pcfg = - GetPackageScopeConfig(env, url, url); - if (!pcfg.IsNothing()) { - pkg_type = pcfg.FromJust()->type; - } - - args.GetReturnValue().Set(Integer::New(env->isolate(), pkg_type)); -} - static MaybeLocal ImportModuleDynamically( Local context, Local referrer, Local specifier) { Isolate* iso = context->GetIsolate(); Environment* env = Environment::GetCurrent(context); - CHECK_NOT_NULL(env); // TODO(addaleax): Handle nullptr here. + if (env == nullptr) { + THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(iso); + return MaybeLocal(); + } + EscapableHandleScope handle_scope(iso); Local import_callback = @@ -1551,8 +633,7 @@ MaybeLocal ModuleWrap::SyntheticModuleEvaluationStepsCallback( return ret; } -void ModuleWrap::SetSyntheticExport( - const v8::FunctionCallbackInfo& args) { +void ModuleWrap::SetSyntheticExport(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); Local that = args.This(); @@ -1572,6 +653,35 @@ void ModuleWrap::SetSyntheticExport( USE(module->SetSyntheticModuleExport(isolate, export_name, export_value)); } +void ModuleWrap::CreateCachedData(const FunctionCallbackInfo& args) { + Isolate* isolate = args.GetIsolate(); + Local that = args.This(); + + ModuleWrap* obj; + ASSIGN_OR_RETURN_UNWRAP(&obj, that); + + CHECK(!obj->synthetic_); + + Local module = obj->module_.Get(isolate); + + CHECK_LT(module->GetStatus(), v8::Module::Status::kEvaluating); + + Local unbound_module_script = + module->GetUnboundModuleScript(); + std::unique_ptr cached_data( + ScriptCompiler::CreateCodeCache(unbound_module_script)); + Environment* env = Environment::GetCurrent(args); + if (!cached_data) { + args.GetReturnValue().Set(Buffer::New(env, 0).ToLocalChecked()); + } else { + MaybeLocal buf = + Buffer::Copy(env, + reinterpret_cast(cached_data->data), + cached_data->length); + args.GetReturnValue().Set(buf.ToLocalChecked()); + } +} + void ModuleWrap::Initialize(Local target, Local unused, Local context, @@ -1581,12 +691,14 @@ void ModuleWrap::Initialize(Local target, Local tpl = env->NewFunctionTemplate(New); tpl->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "ModuleWrap")); - tpl->InstanceTemplate()->SetInternalFieldCount(1); + tpl->InstanceTemplate()->SetInternalFieldCount( + ModuleWrap::kInternalFieldCount); env->SetProtoMethod(tpl, "link", Link); env->SetProtoMethod(tpl, "instantiate", Instantiate); env->SetProtoMethod(tpl, "evaluate", Evaluate); env->SetProtoMethod(tpl, "setExport", SetSyntheticExport); + env->SetProtoMethodNoSideEffect(tpl, "createCachedData", CreateCachedData); env->SetProtoMethodNoSideEffect(tpl, "getNamespace", GetNamespace); env->SetProtoMethodNoSideEffect(tpl, "getStatus", GetStatus); env->SetProtoMethodNoSideEffect(tpl, "getError", GetError); @@ -1595,8 +707,6 @@ void ModuleWrap::Initialize(Local target, target->Set(env->context(), FIXED_ONE_BYTE_STRING(isolate, "ModuleWrap"), tpl->GetFunction(context).ToLocalChecked()).Check(); - env->SetMethod(target, "resolve", Resolve); - env->SetMethod(target, "getPackageType", GetPackageType); env->SetMethod(target, "setImportModuleDynamicallyCallback", SetImportModuleDynamicallyCallback); diff --git a/src/module_wrap.h b/src/module_wrap.h index bee4000d168062..cd51a497acd87e 100644 --- a/src/module_wrap.h +++ b/src/module_wrap.h @@ -65,8 +65,6 @@ class ModuleWrap : public BaseObject { static void GetStaticDependencySpecifiers( const v8::FunctionCallbackInfo& args); - static void Resolve(const v8::FunctionCallbackInfo& args); - static void GetPackageType(const v8::FunctionCallbackInfo& args); static void SetImportModuleDynamicallyCallback( const v8::FunctionCallbackInfo& args); static void SetInitializeImportMetaObjectCallback( @@ -75,6 +73,7 @@ class ModuleWrap : public BaseObject { v8::Local context, v8::Local module); static void SetSyntheticExport( const v8::FunctionCallbackInfo& args); + static void CreateCachedData(const v8::FunctionCallbackInfo& args); static v8::MaybeLocal ResolveCallback( v8::Local context, diff --git a/src/node.cc b/src/node.cc index fee485f86e17f1..da6aebf7178cf6 100644 --- a/src/node.cc +++ b/src/node.cc @@ -27,6 +27,7 @@ #include "env-inl.h" #include "memory_tracker-inl.h" #include "node_binding.h" +#include "node_errors.h" #include "node_internals.h" #include "node_main_instance.h" #include "node_metadata.h" @@ -34,6 +35,7 @@ #include "node_options-inl.h" #include "node_perf.h" #include "node_process.h" +#include "node_report.h" #include "node_revert.h" #include "node_v8_platform-inl.h" #include "node_version.h" @@ -64,13 +66,7 @@ #include "inspector/worker_inspector.h" // ParentInspectorHandle #endif -#ifdef NODE_ENABLE_LARGE_CODE_PAGES #include "large_pages/node_large_page.h" -#endif - -#ifdef NODE_REPORT -#include "node_report.h" -#endif // ========== global C headers ========== @@ -390,6 +386,12 @@ MaybeLocal StartExecution(Environment* env, const char* main_script_id) { ->GetFunction(env->context()) .ToLocalChecked()}; + InternalCallbackScope callback_scope( + env, + Object::New(env->isolate()), + { 1, 0 }, + InternalCallbackScope::kSkipAsyncHooks); + return scope.EscapeMaybe( ExecuteBootstrapper(env, main_script_id, ¶meters, &arguments)); } @@ -668,6 +670,13 @@ int ProcessGlobalArgs(std::vector* args, } } + if (per_process::cli_options->disable_proto != "delete" && + per_process::cli_options->disable_proto != "throw" && + per_process::cli_options->disable_proto != "") { + errors->emplace_back("invalid mode passed to --disable-proto"); + return 12; + } + auto env_opts = per_process::cli_options->per_isolate->per_env; if (std::find(v8_args.begin(), v8_args.end(), "--abort-on-uncaught-exception") != v8_args.end() || @@ -728,11 +737,9 @@ int InitializeNodeWithArgs(std::vector* argv, // Make inherited handles noninheritable. uv_disable_stdio_inheritance(); -#ifdef NODE_REPORT // Cache the original command line to be // used in diagnostic reports. per_process::cli_options->cmdline = *argv; -#endif // NODE_REPORT #if defined(NODE_V8_OPTIONS) // Should come before the call to V8::SetFlagsFromCommandLine() @@ -871,14 +878,6 @@ InitializationResult InitializeOncePerProcess(int argc, char** argv) { CHECK_GT(argc, 0); -#ifdef NODE_ENABLE_LARGE_CODE_PAGES - if (node::IsLargePagesEnabled()) { - if (node::MapStaticCodeToLargePages() != 0) { - fprintf(stderr, "Reverting to default page size\n"); - } - } -#endif - // Hack around with the argv pointer. Used for process.title = "blah". argv = uv_setup_args(argc, argv); @@ -898,6 +897,14 @@ InitializationResult InitializeOncePerProcess(int argc, char** argv) { } } + if (per_process::cli_options->use_largepages == "on" || + per_process::cli_options->use_largepages == "silent") { + int result = node::MapStaticCodeToLargePages(); + if (per_process::cli_options->use_largepages == "on" && result != 0) { + fprintf(stderr, "%s\n", node::LargePagesError(result)); + } + } + if (per_process::cli_options->print_version) { printf("%s\n", NODE_VERSION); result.exit_code = 0; diff --git a/src/node_api.cc b/src/node_api.cc index fad9cf72a972c2..b87690752b3d9a 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -227,8 +227,8 @@ class ThreadSafeFunction : public node::AsyncResource { if (max_queue_size > 0) { cond = std::make_unique(); } - if ((max_queue_size == 0 || cond) && - uv_idle_init(loop, &idle) == 0) { + if (max_queue_size == 0 || cond) { + CHECK_EQ(0, uv_idle_init(loop, &idle)); return napi_ok; } @@ -268,7 +268,6 @@ class ThreadSafeFunction : public node::AsyncResource { void DispatchOne() { void* data = nullptr; bool popped_value = false; - bool idle_stop_failed = false; { node::Mutex::ScopedLock lock(this->mutex); @@ -294,43 +293,24 @@ class ThreadSafeFunction : public node::AsyncResource { } CloseHandlesAndMaybeDelete(); } else { - if (uv_idle_stop(&idle) != 0) { - idle_stop_failed = true; - } + CHECK_EQ(0, uv_idle_stop(&idle)); } } } } - if (popped_value || idle_stop_failed) { + if (popped_value) { v8::HandleScope scope(env->isolate); CallbackScope cb_scope(this); - - if (idle_stop_failed) { - CHECK(napi_throw_error(env, - "ERR_NAPI_TSFN_STOP_IDLE_LOOP", - "Failed to stop the idle loop") == napi_ok); - } else { - napi_value js_callback = nullptr; - if (!ref.IsEmpty()) { - v8::Local js_cb = - v8::Local::New(env->isolate, ref); - js_callback = v8impl::JsValueFromV8LocalValue(js_cb); - } - env->CallIntoModuleThrow([&](napi_env env) { - call_js_cb(env, js_callback, context, data); - }); + napi_value js_callback = nullptr; + if (!ref.IsEmpty()) { + v8::Local js_cb = + v8::Local::New(env->isolate, ref); + js_callback = v8impl::JsValueFromV8LocalValue(js_cb); } - } - } - - void MaybeStartIdle() { - if (uv_idle_start(&idle, IdleCb) != 0) { - v8::HandleScope scope(env->isolate); - CallbackScope cb_scope(this); - CHECK(napi_throw_error(env, - "ERR_NAPI_TSFN_START_IDLE_LOOP", - "Failed to start the idle loop") == napi_ok); + env->CallIntoModuleThrow([&](napi_env env) { + call_js_cb(env, js_callback, context, data); + }); } } @@ -412,7 +392,7 @@ class ThreadSafeFunction : public node::AsyncResource { static void AsyncCb(uv_async_t* async) { ThreadSafeFunction* ts_fn = node::ContainerOf(&ThreadSafeFunction::async, async); - ts_fn->MaybeStartIdle(); + CHECK_EQ(0, uv_idle_start(&ts_fn->idle, IdleCb)); } static void Cleanup(void* data) { diff --git a/src/node_binding.cc b/src/node_binding.cc index 0facfc36cbcb78..91ae3530d09b16 100644 --- a/src/node_binding.cc +++ b/src/node_binding.cc @@ -17,12 +17,6 @@ #define NODE_BUILTIN_ICU_MODULES(V) #endif -#if NODE_REPORT -#define NODE_BUILTIN_REPORT_MODULES(V) V(report) -#else -#define NODE_BUILTIN_REPORT_MODULES(V) -#endif - #if HAVE_INSPECTOR #define NODE_BUILTIN_PROFILER_MODULES(V) V(profiler) #else @@ -68,6 +62,7 @@ V(pipe_wrap) \ V(process_wrap) \ V(process_methods) \ + V(report) \ V(serdes) \ V(signal_wrap) \ V(spawn_sync) \ @@ -88,13 +83,13 @@ V(v8) \ V(wasi) \ V(worker) \ + V(watchdog) \ V(zlib) #define NODE_BUILTIN_MODULES(V) \ NODE_BUILTIN_STANDARD_MODULES(V) \ NODE_BUILTIN_OPENSSL_MODULES(V) \ NODE_BUILTIN_ICU_MODULES(V) \ - NODE_BUILTIN_REPORT_MODULES(V) \ NODE_BUILTIN_PROFILER_MODULES(V) \ NODE_BUILTIN_DTRACE_MODULES(V) diff --git a/src/node_constants.cc b/src/node_constants.cc index 68af221b60aa65..5d99fa181a0472 100644 --- a/src/node_constants.cc +++ b/src/node_constants.cc @@ -1072,12 +1072,6 @@ void DefineCryptoConstants(Local target) { NODE_DEFINE_CONSTANT(target, POINT_CONVERSION_UNCOMPRESSED); NODE_DEFINE_CONSTANT(target, POINT_CONVERSION_HYBRID); - - NODE_DEFINE_STRING_CONSTANT( - target, - "defaultCipherList", - per_process::cli_options->tls_cipher_list.c_str()); - #endif } diff --git a/src/node_contextify.cc b/src/node_contextify.cc index 2d30e0b8038ce4..3072dc8a7bb50f 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -142,7 +142,7 @@ MaybeLocal ContextifyContext::CreateDataWrapper(Environment* env) { return MaybeLocal(); } - wrapper->SetAlignedPointerInInternalField(0, this); + wrapper->SetAlignedPointerInInternalField(ContextifyContext::kSlot, this); return wrapper; } @@ -185,8 +185,11 @@ MaybeLocal ContextifyContext::CreateV8Context( object_template->SetHandler(config); object_template->SetHandler(indexed_config); - - Local ctx = NewContext(env->isolate(), object_template); + Local ctx = Context::New(env->isolate(), nullptr, object_template); + if (ctx.IsEmpty()) return MaybeLocal(); + // Only partially initialize the context - the primordials are left out + // and only initialized when necessary. + InitializeContextRuntime(ctx); if (ctx.IsEmpty()) { return MaybeLocal(); @@ -226,7 +229,8 @@ MaybeLocal ContextifyContext::CreateV8Context( void ContextifyContext::Init(Environment* env, Local target) { Local function_template = FunctionTemplate::New(env->isolate()); - function_template->InstanceTemplate()->SetInternalFieldCount(1); + function_template->InstanceTemplate()->SetInternalFieldCount( + ContextifyContext::kInternalFieldCount); env->set_script_data_constructor_function( function_template->GetFunction(env->context()).ToLocalChecked()); @@ -325,7 +329,8 @@ template ContextifyContext* ContextifyContext::Get(const PropertyCallbackInfo& args) { Local data = args.Data(); return static_cast( - data.As()->GetAlignedPointerFromInternalField(0)); + data.As()->GetAlignedPointerFromInternalField( + ContextifyContext::kSlot)); } // static @@ -622,7 +627,8 @@ void ContextifyScript::Init(Environment* env, Local target) { FIXED_ONE_BYTE_STRING(env->isolate(), "ContextifyScript"); Local script_tmpl = env->NewFunctionTemplate(New); - script_tmpl->InstanceTemplate()->SetInternalFieldCount(1); + script_tmpl->InstanceTemplate()->SetInternalFieldCount( + ContextifyScript::kInternalFieldCount); script_tmpl->SetClassName(class_name); env->SetProtoMethod(script_tmpl, "createCachedData", CreateCachedData); env->SetProtoMethod(script_tmpl, "runInContext", RunInContext); @@ -755,8 +761,8 @@ void ContextifyScript::New(const FunctionCallbackInfo& args) { env->cached_data_rejected_string(), Boolean::New(isolate, source.GetCachedData()->rejected)).Check(); } else if (produce_cached_data) { - const ScriptCompiler::CachedData* cached_data = - ScriptCompiler::CreateCodeCache(v8_script.ToLocalChecked()); + std::unique_ptr cached_data { + ScriptCompiler::CreateCodeCache(v8_script.ToLocalChecked()) }; bool cached_data_produced = cached_data != nullptr; if (cached_data_produced) { MaybeLocal buf = Buffer::Copy( @@ -1217,7 +1223,8 @@ void Initialize(Local target, { Local tpl = FunctionTemplate::New(env->isolate()); tpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "CompiledFnEntry")); - tpl->InstanceTemplate()->SetInternalFieldCount(1); + tpl->InstanceTemplate()->SetInternalFieldCount( + CompiledFnEntry::kInternalFieldCount); env->set_compiled_fn_entry_template(tpl->InstanceTemplate()); } diff --git a/src/node_contextify.h b/src/node_contextify.h index cf1e8475075fcb..f04ea86f41abac 100644 --- a/src/node_contextify.h +++ b/src/node_contextify.h @@ -19,6 +19,7 @@ struct ContextOptions { class ContextifyContext { public: + enum InternalFields { kSlot, kInternalFieldCount }; ContextifyContext(Environment* env, v8::Local sandbox_obj, const ContextOptions& options); diff --git a/src/node_crypto.cc b/src/node_crypto.cc index ee42630ad06da9..9e3c63b5ec9245 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -119,8 +119,8 @@ static bool extra_root_certs_loaded = false; template void SSLWrap::AddMethods(Environment* env, Local t); template void SSLWrap::ConfigureSecureContext(SecureContext* sc); -template void SSLWrap::SetSNIContext(SecureContext* sc); template int SSLWrap::SetCACerts(SecureContext* sc); +template void SSLWrap::MemoryInfo(MemoryTracker* tracker) const; template SSL_SESSION* SSLWrap::GetSessionCallback( SSL* s, const unsigned char* key, @@ -432,7 +432,8 @@ bool EntropySource(unsigned char* buffer, size_t length) { void SecureContext::Initialize(Environment* env, Local target) { Local t = env->NewFunctionTemplate(New); - t->InstanceTemplate()->SetInternalFieldCount(1); + t->InstanceTemplate()->SetInternalFieldCount( + SecureContext::kInternalFieldCount); Local secureContextString = FIXED_ONE_BYTE_STRING(env->isolate(), "SecureContext"); t->SetClassName(secureContextString); @@ -972,6 +973,8 @@ static X509_STORE* NewRootCertStore() { if (*system_cert_path != '\0') { X509_STORE_load_locations(store, system_cert_path, nullptr); } + + Mutex::ScopedLock cli_lock(node::per_process::cli_options_mutex); if (per_process::cli_options->ssl_openssl_cert_store) { X509_STORE_set_default_paths(store); } else { @@ -1701,6 +1704,8 @@ void SSLWrap::AddMethods(Environment* env, Local t) { env->SetProtoMethodNoSideEffect(t, "verifyError", VerifyError); env->SetProtoMethodNoSideEffect(t, "getCipher", GetCipher); env->SetProtoMethodNoSideEffect(t, "getSharedSigalgs", GetSharedSigalgs); + env->SetProtoMethodNoSideEffect( + t, "exportKeyingMaterial", ExportKeyingMaterial); env->SetProtoMethod(t, "endParser", EndParser); env->SetProtoMethod(t, "certCbDone", CertCbDone); env->SetProtoMethod(t, "renegotiate", Renegotiate); @@ -2216,6 +2221,40 @@ void SSLWrap::GetSharedSigalgs(const FunctionCallbackInfo& args) { Array::New(env->isolate(), ret_arr.out(), ret_arr.length())); } +template +void SSLWrap::ExportKeyingMaterial( + const FunctionCallbackInfo& args) { + CHECK(args[0]->IsInt32()); + CHECK(args[1]->IsString()); + + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); + Environment* env = w->ssl_env(); + + uint32_t olen = args[0].As()->Value(); + node::Utf8Value label(env->isolate(), args[1]); + + AllocatedBuffer out = env->AllocateManaged(olen); + + ByteSource context; + bool use_context = !args[2]->IsUndefined(); + if (use_context) + context = ByteSource::FromBuffer(args[2]); + + if (SSL_export_keying_material(w->ssl_.get(), + reinterpret_cast(out.data()), + olen, + *label, + label.length(), + reinterpret_cast( + context.get()), + context.size(), + use_context) != 1) { + return ThrowCryptoError(env, ERR_get_error(), "SSL_export_keying_material"); + } + + args.GetReturnValue().Set(out.ToBuffer().ToLocalChecked()); +} template void SSLWrap::GetProtocol(const FunctionCallbackInfo& args) { @@ -2422,11 +2461,12 @@ void SSLWrap::CertCbDone(const FunctionCallbackInfo& args) { goto fire_cb; if (cons->HasInstance(ctx)) { - SecureContext* sc; - ASSIGN_OR_RETURN_UNWRAP(&sc, ctx.As()); - w->sni_context_.Reset(env->isolate(), ctx); + SecureContext* sc = Unwrap(ctx.As()); + CHECK_NOT_NULL(sc); + // Store the SNI context for later use. + w->sni_context_ = BaseObjectPtr(sc); - if (UseSNIContext(w->ssl_, sc) && !w->SetCACerts(sc)) { + if (UseSNIContext(w->ssl_, w->sni_context_) && !w->SetCACerts(sc)) { // Not clear why sometimes we throw error, and sometimes we call // onerror(). Both cause .destroy(), but onerror does a bit more. unsigned long err = ERR_get_error(); // NOLINT(runtime/int) @@ -2464,15 +2504,6 @@ void SSLWrap::DestroySSL() { } -template -void SSLWrap::SetSNIContext(SecureContext* sc) { - ConfigureSecureContext(sc); - CHECK_EQ(SSL_set_SSL_CTX(ssl_.get(), sc->ctx_.get()), sc->ctx_.get()); - - SetCACerts(sc); -} - - template int SSLWrap::SetCACerts(SecureContext* sc) { int err = SSL_set1_verify_cert_store(ssl_.get(), @@ -2488,6 +2519,12 @@ int SSLWrap::SetCACerts(SecureContext* sc) { return 1; } +template +void SSLWrap::MemoryInfo(MemoryTracker* tracker) const { + tracker->TrackField("ocsp_response", ocsp_response_); + tracker->TrackField("sni_context", sni_context_); +} + int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx) { // From https://www.openssl.org/docs/man1.1.1/man3/SSL_verify_cb: // @@ -2968,7 +3005,7 @@ static NonCopyableMaybe GetPrivateKeyEncodingFromJs( args[*offset].As()); result.cipher_ = EVP_get_cipherbyname(*cipher_name); if (result.cipher_ == nullptr) { - env->ThrowError("Unknown cipher"); + THROW_ERR_CRYPTO_UNKNOWN_CIPHER(env); return NonCopyableMaybe(); } needs_passphrase = true; @@ -3183,7 +3220,8 @@ EVP_PKEY* ManagedEVPPKey::get() const { Local KeyObject::Initialize(Environment* env, Local target) { Local t = env->NewFunctionTemplate(New); - t->InstanceTemplate()->SetInternalFieldCount(1); + t->InstanceTemplate()->SetInternalFieldCount( + KeyObject::kInternalFieldCount); env->SetProtoMethod(t, "init", Init); env->SetProtoMethodNoSideEffect(t, "getSymmetricKeySize", @@ -3328,6 +3366,8 @@ Local KeyObject::GetAsymmetricKeyType() const { return env()->crypto_rsa_pss_string(); case EVP_PKEY_DSA: return env()->crypto_dsa_string(); + case EVP_PKEY_DH: + return env()->crypto_dh_string(); case EVP_PKEY_EC: return env()->crypto_ec_string(); case EVP_PKEY_ED25519: @@ -3414,7 +3454,8 @@ CipherBase::CipherBase(Environment* env, void CipherBase::Initialize(Environment* env, Local target) { Local t = env->NewFunctionTemplate(New); - t->InstanceTemplate()->SetInternalFieldCount(1); + t->InstanceTemplate()->SetInternalFieldCount( + CipherBase::kInternalFieldCount); env->SetProtoMethod(t, "init", Init); env->SetProtoMethod(t, "initiv", InitIv); @@ -3492,7 +3533,7 @@ void CipherBase::Init(const char* cipher_type, const EVP_CIPHER* const cipher = EVP_get_cipherbyname(cipher_type); if (cipher == nullptr) - return env()->ThrowError("Unknown cipher"); + return THROW_ERR_CRYPTO_UNKNOWN_CIPHER(env()); unsigned char key[EVP_MAX_KEY_LENGTH]; unsigned char iv[EVP_MAX_IV_LENGTH]; @@ -3556,7 +3597,7 @@ void CipherBase::InitIv(const char* cipher_type, const EVP_CIPHER* const cipher = EVP_get_cipherbyname(cipher_type); if (cipher == nullptr) { - return env()->ThrowError("Unknown cipher"); + return THROW_ERR_CRYPTO_UNKNOWN_CIPHER(env()); } const int expected_iv_len = EVP_CIPHER_iv_length(cipher); @@ -4040,7 +4081,8 @@ Hmac::Hmac(Environment* env, Local wrap) void Hmac::Initialize(Environment* env, Local target) { Local t = env->NewFunctionTemplate(New); - t->InstanceTemplate()->SetInternalFieldCount(1); + t->InstanceTemplate()->SetInternalFieldCount( + Hmac::kInternalFieldCount); env->SetProtoMethod(t, "init", HmacInit); env->SetProtoMethod(t, "update", HmacUpdate); @@ -4165,7 +4207,8 @@ Hash::Hash(Environment* env, Local wrap) void Hash::Initialize(Environment* env, Local target) { Local t = env->NewFunctionTemplate(New); - t->InstanceTemplate()->SetInternalFieldCount(1); + t->InstanceTemplate()->SetInternalFieldCount( + Hash::kInternalFieldCount); env->SetProtoMethod(t, "update", HashUpdate); env->SetProtoMethod(t, "digest", HashDigest); @@ -4436,7 +4479,8 @@ Sign::Sign(Environment* env, Local wrap) : SignBase(env, wrap) { void Sign::Initialize(Environment* env, Local target) { Local t = env->NewFunctionTemplate(New); - t->InstanceTemplate()->SetInternalFieldCount(1); + t->InstanceTemplate()->SetInternalFieldCount( + SignBase::kInternalFieldCount); env->SetProtoMethod(t, "init", SignInit); env->SetProtoMethod(t, "update", SignUpdate); @@ -4760,7 +4804,8 @@ Verify::Verify(Environment* env, Local wrap) void Verify::Initialize(Environment* env, Local target) { Local t = env->NewFunctionTemplate(New); - t->InstanceTemplate()->SetInternalFieldCount(1); + t->InstanceTemplate()->SetInternalFieldCount( + SignBase::kInternalFieldCount); env->SetProtoMethod(t, "init", VerifyInit); env->SetProtoMethod(t, "update", VerifyUpdate); @@ -5071,7 +5116,8 @@ void DiffieHellman::Initialize(Environment* env, Local target) { const PropertyAttribute attributes = static_cast(ReadOnly | DontDelete); - t->InstanceTemplate()->SetInternalFieldCount(1); + t->InstanceTemplate()->SetInternalFieldCount( + DiffieHellman::kInternalFieldCount); env->SetProtoMethod(t, "generateKeys", GenerateKeys); env->SetProtoMethod(t, "computeSecret", ComputeSecret); @@ -5118,6 +5164,14 @@ bool DiffieHellman::Init(int primeLength, int g) { bool DiffieHellman::Init(const char* p, int p_len, int g) { dh_.reset(DH_new()); + if (p_len <= 0) { + BNerr(BN_F_BN_GENERATE_PRIME_EX, BN_R_BITS_TOO_SMALL); + return false; + } + if (g <= 1) { + DHerr(DH_F_DH_BUILTIN_GENPARAMS, DH_R_BAD_GENERATOR); + return false; + } BIGNUM* bn_p = BN_bin2bn(reinterpret_cast(p), p_len, nullptr); BIGNUM* bn_g = BN_new(); @@ -5133,10 +5187,23 @@ bool DiffieHellman::Init(const char* p, int p_len, int g) { bool DiffieHellman::Init(const char* p, int p_len, const char* g, int g_len) { dh_.reset(DH_new()); - BIGNUM* bn_p = - BN_bin2bn(reinterpret_cast(p), p_len, nullptr); + if (p_len <= 0) { + BNerr(BN_F_BN_GENERATE_PRIME_EX, BN_R_BITS_TOO_SMALL); + return false; + } + if (g_len <= 0) { + DHerr(DH_F_DH_BUILTIN_GENPARAMS, DH_R_BAD_GENERATOR); + return false; + } BIGNUM* bn_g = BN_bin2bn(reinterpret_cast(g), g_len, nullptr); + if (BN_is_zero(bn_g) || BN_is_one(bn_g)) { + BN_free(bn_g); + DHerr(DH_F_DH_BUILTIN_GENPARAMS, DH_R_BAD_GENERATOR); + return false; + } + BIGNUM* bn_p = + BN_bin2bn(reinterpret_cast(p), p_len, nullptr); if (!DH_set0_pqg(dh_.get(), bn_p, nullptr, bn_g)) { BN_free(bn_p); BN_free(bn_g); @@ -5145,37 +5212,34 @@ bool DiffieHellman::Init(const char* p, int p_len, const char* g, int g_len) { return VerifyContext(); } +inline const modp_group* FindDiffieHellmanGroup(const char* name) { + for (const modp_group& group : modp_groups) { + if (StringEqualNoCase(name, group.name)) + return &group; + } + return nullptr; +} void DiffieHellman::DiffieHellmanGroup( const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); DiffieHellman* diffieHellman = new DiffieHellman(env, args.This()); - if (args.Length() != 1) { - return THROW_ERR_MISSING_ARGS(env, "Group name argument is mandatory"); - } - + CHECK_EQ(args.Length(), 1); THROW_AND_RETURN_IF_NOT_STRING(env, args[0], "Group name"); bool initialized = false; const node::Utf8Value group_name(env->isolate(), args[0]); - for (size_t i = 0; i < arraysize(modp_groups); ++i) { - const modp_group* it = modp_groups + i; - - if (!StringEqualNoCase(*group_name, it->name)) - continue; - - initialized = diffieHellman->Init(it->prime, - it->prime_size, - it->gen, - it->gen_size); - if (!initialized) - env->ThrowError("Initialization failed"); - return; - } + const modp_group* group = FindDiffieHellmanGroup(*group_name); + if (group == nullptr) + return THROW_ERR_CRYPTO_UNKNOWN_DH_GROUP(env, "Unknown group"); - env->ThrowError("Unknown group"); + initialized = diffieHellman->Init(group->prime, + group->prime_size, + group->gen); + if (!initialized) + env->ThrowError("Initialization failed"); } @@ -5288,6 +5352,20 @@ void DiffieHellman::GetPrivateKey(const FunctionCallbackInfo& args) { }, "No private key - did you forget to generate one?"); } +static void ZeroPadDiffieHellmanSecret(size_t remainder_size, + AllocatedBuffer* ret) { + // DH_size returns number of bytes in a prime number. + // DH_compute_key returns number of bytes in a remainder of exponent, which + // may have less bytes than a prime number. Therefore add 0-padding to the + // allocated buffer. + const size_t prime_size = ret->size(); + if (remainder_size != prime_size) { + CHECK_LT(remainder_size, prime_size); + const size_t padding = prime_size - remainder_size; + memmove(ret->data() + padding, ret->data(), remainder_size); + memset(ret->data(), 0, padding); + } +} void DiffieHellman::ComputeSecret(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -5334,16 +5412,7 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo& args) { } CHECK_GE(size, 0); - - // DH_size returns number of bytes in a prime number - // DH_compute_key returns number of bytes in a remainder of exponent, which - // may have less bytes than a prime number. Therefore add 0-padding to the - // allocated buffer. - if (static_cast(size) != ret.size()) { - CHECK_GT(ret.size(), static_cast(size)); - memmove(ret.data() + ret.size() - size, ret.data(), size); - memset(ret.data(), 0, ret.size() - size); - } + ZeroPadDiffieHellmanSecret(static_cast(size), &ret); args.GetReturnValue().Set(ret.ToBuffer().ToLocalChecked()); } @@ -5408,7 +5477,7 @@ void ECDH::Initialize(Environment* env, Local target) { Local t = env->NewFunctionTemplate(New); - t->InstanceTemplate()->SetInternalFieldCount(1); + t->InstanceTemplate()->SetInternalFieldCount(ECDH::kInternalFieldCount); env->SetProtoMethod(t, "generateKeys", GenerateKeys); env->SetProtoMethod(t, "computeSecret", ComputeSecret); @@ -6086,6 +6155,71 @@ class NidKeyPairGenerationConfig : public KeyPairGenerationConfig { const int id_; }; +// TODO(tniessen): Use std::variant instead. +// Diffie-Hellman can either generate keys using a fixed prime, or by first +// generating a random prime of a given size (in bits). Only one of both options +// may be specified. +struct PrimeInfo { + BignumPointer fixed_value_; + unsigned int prime_size_; +}; + +class DHKeyPairGenerationConfig : public KeyPairGenerationConfig { + public: + explicit DHKeyPairGenerationConfig(PrimeInfo&& prime_info, + unsigned int generator) + : prime_info_(std::move(prime_info)), + generator_(generator) {} + + EVPKeyCtxPointer Setup() override { + EVPKeyPointer params; + if (prime_info_.fixed_value_) { + DHPointer dh(DH_new()); + if (!dh) + return nullptr; + + BIGNUM* prime = prime_info_.fixed_value_.get(); + BignumPointer bn_g(BN_new()); + if (!BN_set_word(bn_g.get(), generator_) || + !DH_set0_pqg(dh.get(), prime, nullptr, bn_g.get())) + return nullptr; + + prime_info_.fixed_value_.release(); + bn_g.release(); + + params = EVPKeyPointer(EVP_PKEY_new()); + CHECK(params); + EVP_PKEY_assign_DH(params.get(), dh.release()); + } else { + EVPKeyCtxPointer param_ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_DH, nullptr)); + if (!param_ctx) + return nullptr; + + if (EVP_PKEY_paramgen_init(param_ctx.get()) <= 0) + return nullptr; + + if (EVP_PKEY_CTX_set_dh_paramgen_prime_len(param_ctx.get(), + prime_info_.prime_size_) <= 0) + return nullptr; + + if (EVP_PKEY_CTX_set_dh_paramgen_generator(param_ctx.get(), + generator_) <= 0) + return nullptr; + + EVP_PKEY* raw_params = nullptr; + if (EVP_PKEY_paramgen(param_ctx.get(), &raw_params) <= 0) + return nullptr; + params = EVPKeyPointer(raw_params); + } + + return EVPKeyCtxPointer(EVP_PKEY_CTX_new(params.get(), nullptr)); + } + + private: + PrimeInfo prime_info_; + unsigned int generator_; +}; + class GenerateKeyPairJob : public CryptoJob { public: GenerateKeyPairJob(Environment* env, @@ -6299,6 +6433,39 @@ void GenerateKeyPairNid(const FunctionCallbackInfo& args) { GenerateKeyPair(args, 1, std::move(config)); } +void GenerateKeyPairDH(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + + PrimeInfo prime_info = {}; + unsigned int generator; + if (args[0]->IsString()) { + String::Utf8Value group_name(args.GetIsolate(), args[0].As()); + const modp_group* group = FindDiffieHellmanGroup(*group_name); + if (group == nullptr) + return THROW_ERR_CRYPTO_UNKNOWN_DH_GROUP(env); + + prime_info.fixed_value_ = BignumPointer( + BN_bin2bn(reinterpret_cast(group->prime), + group->prime_size, nullptr)); + generator = group->gen; + } else { + if (args[0]->IsInt32()) { + prime_info.prime_size_ = args[0].As()->Value(); + } else { + ArrayBufferViewContents input(args[0]); + prime_info.fixed_value_ = BignumPointer( + BN_bin2bn(input.data(), input.length(), nullptr)); + } + + CHECK(args[1]->IsInt32()); + generator = args[1].As()->Value(); + } + + std::unique_ptr config( + new DHKeyPairGenerationConfig(std::move(prime_info), generator)); + GenerateKeyPair(args, 2, std::move(config)); +} + void GetSSLCiphers(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -6581,6 +6748,49 @@ void ConvertKey(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(buf); } +AllocatedBuffer StatelessDiffieHellman(Environment* env, ManagedEVPPKey our_key, + ManagedEVPPKey their_key) { + size_t out_size; + + EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(our_key.get(), nullptr)); + if (!ctx || + EVP_PKEY_derive_init(ctx.get()) <= 0 || + EVP_PKEY_derive_set_peer(ctx.get(), their_key.get()) <= 0 || + EVP_PKEY_derive(ctx.get(), nullptr, &out_size) <= 0) + return AllocatedBuffer(); + + AllocatedBuffer result = env->AllocateManaged(out_size); + CHECK_NOT_NULL(result.data()); + + unsigned char* data = reinterpret_cast(result.data()); + if (EVP_PKEY_derive(ctx.get(), data, &out_size) <= 0) + return AllocatedBuffer(); + + ZeroPadDiffieHellmanSecret(out_size, &result); + return result; +} + +void StatelessDiffieHellman(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + + CHECK(args[0]->IsObject() && args[1]->IsObject()); + KeyObject* our_key_object; + ASSIGN_OR_RETURN_UNWRAP(&our_key_object, args[0].As()); + CHECK_EQ(our_key_object->GetKeyType(), kKeyTypePrivate); + KeyObject* their_key_object; + ASSIGN_OR_RETURN_UNWRAP(&their_key_object, args[1].As()); + CHECK_NE(their_key_object->GetKeyType(), kKeyTypeSecret); + + ManagedEVPPKey our_key = our_key_object->GetAsymmetricKey(); + ManagedEVPPKey their_key = their_key_object->GetAsymmetricKey(); + + AllocatedBuffer out = StatelessDiffieHellman(env, our_key, their_key); + if (out.size() == 0) + return ThrowCryptoError(env, ERR_get_error(), "diffieHellman failed"); + + args.GetReturnValue().Set(out.ToBuffer().ToLocalChecked()); +} + void TimingSafeEqual(const FunctionCallbackInfo& args) { ArrayBufferViewContents buf1(args[0]); @@ -6732,6 +6942,7 @@ void Initialize(Local target, env->SetMethod(target, "generateKeyPairDSA", GenerateKeyPairDSA); env->SetMethod(target, "generateKeyPairEC", GenerateKeyPairEC); env->SetMethod(target, "generateKeyPairNid", GenerateKeyPairNid); + env->SetMethod(target, "generateKeyPairDH", GenerateKeyPairDH); NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED25519); NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED448); NODE_DEFINE_CONSTANT(target, EVP_PKEY_X25519); @@ -6749,6 +6960,7 @@ void Initialize(Local target, NODE_DEFINE_CONSTANT(target, kKeyTypePrivate); NODE_DEFINE_CONSTANT(target, kSigEncDER); NODE_DEFINE_CONSTANT(target, kSigEncP1363); + env->SetMethodNoSideEffect(target, "statelessDH", StatelessDiffieHellman); env->SetMethod(target, "randomBytes", RandomBytes); env->SetMethod(target, "signOneShot", SignOneShot); env->SetMethod(target, "verifyOneShot", VerifyOneShot); diff --git a/src/node_crypto.h b/src/node_crypto.h index 74ae4025da9f33..772a34a7da7699 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -215,6 +215,8 @@ class SSLWrap { inline bool is_awaiting_new_session() const { return awaiting_new_session_; } inline bool is_waiting_cert_cb() const { return cert_cb_ != nullptr; } + void MemoryInfo(MemoryTracker* tracker) const; + protected: typedef void (*CertCb)(void* arg); @@ -249,6 +251,8 @@ class SSLWrap { static void VerifyError(const v8::FunctionCallbackInfo& args); static void GetCipher(const v8::FunctionCallbackInfo& args); static void GetSharedSigalgs(const v8::FunctionCallbackInfo& args); + static void ExportKeyingMaterial( + const v8::FunctionCallbackInfo& args); static void EndParser(const v8::FunctionCallbackInfo& args); static void CertCbDone(const v8::FunctionCallbackInfo& args); static void Renegotiate(const v8::FunctionCallbackInfo& args); @@ -279,7 +283,6 @@ class SSLWrap { void DestroySSL(); void WaitForCertCb(CertCb cb, void* arg); - void SetSNIContext(SecureContext* sc); int SetCACerts(SecureContext* sc); inline Environment* ssl_env() const { @@ -301,7 +304,7 @@ class SSLWrap { ClientHelloParser hello_parser_; v8::Global ocsp_response_; - v8::Global sni_context_; + BaseObjectPtr sni_context_; friend class SecureContext; }; diff --git a/src/node_crypto_common.cc b/src/node_crypto_common.cc index 197bc5cd5913a4..3b35ee1ff7ba8a 100644 --- a/src/node_crypto_common.cc +++ b/src/node_crypto_common.cc @@ -1,3 +1,4 @@ +#include "base_object-inl.h" #include "env-inl.h" #include "node_buffer.h" #include "node_crypto.h" @@ -33,6 +34,7 @@ using v8::NewStringType; using v8::Null; using v8::Object; using v8::String; +using v8::Undefined; using v8::Value; namespace crypto { @@ -223,7 +225,7 @@ long VerifyPeerCertificate( // NOLINT(runtime/int) return err; } -int UseSNIContext(const SSLPointer& ssl, SecureContext* context) { +int UseSNIContext(const SSLPointer& ssl, BaseObjectPtr context) { SSL_CTX* ctx = context->ctx_.get(); X509* x509 = SSL_CTX_get0_certificate(ctx); EVP_PKEY* pkey = SSL_CTX_get0_privatekey(ctx); @@ -329,11 +331,15 @@ const char* X509ErrorCode(long err) { // NOLINT(runtime/int) } MaybeLocal GetValidationErrorReason(Environment* env, int err) { + if (err == 0) + return Undefined(env->isolate()); const char* reason = X509_verify_cert_error_string(err); return OneByteString(env->isolate(), reason); } MaybeLocal GetValidationErrorCode(Environment* env, int err) { + if (err == 0) + return Undefined(env->isolate()); return OneByteString(env->isolate(), X509ErrorCode(err)); } diff --git a/src/node_crypto_common.h b/src/node_crypto_common.h index e42e249ef2ba2e..c373a97e4763a4 100644 --- a/src/node_crypto_common.h +++ b/src/node_crypto_common.h @@ -3,7 +3,6 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS -#include "env.h" #include "node_crypto.h" #include "v8.h" #include @@ -72,7 +71,7 @@ long VerifyPeerCertificate( // NOLINT(runtime/int) const SSLPointer& ssl, long def = X509_V_ERR_UNSPECIFIED); // NOLINT(runtime/int) -int UseSNIContext(const SSLPointer& ssl, SecureContext* context); +int UseSNIContext(const SSLPointer& ssl, BaseObjectPtr context); const char* GetClientHelloALPN(const SSLPointer& ssl); diff --git a/src/node_crypto_groups.h b/src/node_crypto_groups.h index d22fdc7f966f9a..108edda01bb4eb 100644 --- a/src/node_crypto_groups.h +++ b/src/node_crypto_groups.h @@ -32,7 +32,7 @@ */ -static const unsigned char two_generator[] = { 2 }; +static const unsigned int two_generator = 2; static const unsigned char group_modp1[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, @@ -394,20 +394,19 @@ typedef struct { const char* name; const char* prime; unsigned int prime_size; - const char* gen; - unsigned int gen_size; + unsigned int gen; } modp_group; static const modp_group modp_groups[] = { #define V(var) reinterpret_cast(var) - { "modp1", V(group_modp1), sizeof(group_modp1), V(two_generator), 1 }, - { "modp2", V(group_modp2), sizeof(group_modp2), V(two_generator), 1 }, - { "modp5", V(group_modp5), sizeof(group_modp5), V(two_generator), 1 }, - { "modp14", V(group_modp14), sizeof(group_modp14), V(two_generator), 1 }, - { "modp15", V(group_modp15), sizeof(group_modp15), V(two_generator), 1 }, - { "modp16", V(group_modp16), sizeof(group_modp16), V(two_generator), 1 }, - { "modp17", V(group_modp17), sizeof(group_modp17), V(two_generator), 1 }, - { "modp18", V(group_modp18), sizeof(group_modp18), V(two_generator), 1 } + { "modp1", V(group_modp1), sizeof(group_modp1), two_generator }, + { "modp2", V(group_modp2), sizeof(group_modp2), two_generator }, + { "modp5", V(group_modp5), sizeof(group_modp5), two_generator }, + { "modp14", V(group_modp14), sizeof(group_modp14), two_generator }, + { "modp15", V(group_modp15), sizeof(group_modp15), two_generator }, + { "modp16", V(group_modp16), sizeof(group_modp16), two_generator }, + { "modp17", V(group_modp17), sizeof(group_modp17), two_generator }, + { "modp18", V(group_modp18), sizeof(group_modp18), two_generator } #undef V }; diff --git a/src/node_dir.cc b/src/node_dir.cc index ec53d8216bcba0..9923f042779f2e 100644 --- a/src/node_dir.cc +++ b/src/node_dir.cc @@ -358,7 +358,7 @@ void Initialize(Local target, env->SetProtoMethod(dir, "read", DirHandle::Read); env->SetProtoMethod(dir, "close", DirHandle::Close); Local dirt = dir->InstanceTemplate(); - dirt->SetInternalFieldCount(DirHandle::kDirHandleFieldCount); + dirt->SetInternalFieldCount(DirHandle::kInternalFieldCount); Local handleString = FIXED_ONE_BYTE_STRING(isolate, "DirHandle"); dir->SetClassName(handleString); diff --git a/src/node_dir.h b/src/node_dir.h index b55245d5b89a2e..5fcc36326b7ba2 100644 --- a/src/node_dir.h +++ b/src/node_dir.h @@ -12,8 +12,6 @@ namespace fs_dir { // Needed to propagate `uv_dir_t`. class DirHandle : public AsyncWrap { public: - static constexpr int kDirHandleFieldCount = 1; - static DirHandle* New(Environment* env, uv_dir_t* dir); ~DirHandle() override; diff --git a/src/node_env_var.cc b/src/node_env_var.cc index d6440ba403cad4..9b634337043cef 100644 --- a/src/node_env_var.cc +++ b/src/node_env_var.cc @@ -106,7 +106,7 @@ void RealEnvStore::Set(Isolate* isolate, node::Utf8Value val(isolate, value); #ifdef _WIN32 - if (key[0] == L'=') return; + if (key.length() > 0 && key[0] == '=') return; #endif uv_os_setenv(*key, *val); } @@ -123,7 +123,7 @@ int32_t RealEnvStore::Query(const char* key) const { } #ifdef _WIN32 - if (key[0] == L'=') { + if (key[0] == '=') { return static_cast(v8::ReadOnly) | static_cast(v8::DontDelete) | static_cast(v8::DontEnum); @@ -210,7 +210,7 @@ void MapKVStore::Set(Isolate* isolate, Local key, Local value) { Mutex::ScopedLock lock(mutex_); Utf8Value key_str(isolate, key); Utf8Value value_str(isolate, value); - if (*key_str != nullptr && *value_str != nullptr) { + if (*key_str != nullptr && key_str.length() > 0 && *value_str != nullptr) { map_[std::string(*key_str, key_str.length())] = std::string(*value_str, value_str.length()); } diff --git a/src/node_errors.cc b/src/node_errors.cc index 9d038e3d1683e7..9bae27550cec1b 100644 --- a/src/node_errors.cc +++ b/src/node_errors.cc @@ -4,9 +4,7 @@ #include "debug_utils-inl.h" #include "node_errors.h" #include "node_internals.h" -#ifdef NODE_REPORT #include "node_report.h" -#endif #include "node_process.h" #include "node_v8_platform-inl.h" #include "util-inl.h" @@ -405,14 +403,20 @@ void OnFatalError(const char* location, const char* message) { } else { FPrintF(stderr, "FATAL ERROR: %s\n", message); } -#ifdef NODE_REPORT + Isolate* isolate = Isolate::GetCurrent(); Environment* env = Environment::GetCurrent(isolate); - if (env == nullptr || env->isolate_data()->options()->report_on_fatalerror) { + bool report_on_fatalerror; + { + Mutex::ScopedLock lock(node::per_process::cli_options_mutex); + report_on_fatalerror = per_process::cli_options->report_on_fatalerror; + } + + if (report_on_fatalerror) { report::TriggerNodeReport( isolate, env, message, "FatalError", "", Local()); } -#endif // NODE_REPORT + fflush(stderr); ABORT(); } diff --git a/src/node_errors.h b/src/node_errors.h index 2da952ad29d499..3c57f4b8b02fee 100644 --- a/src/node_errors.h +++ b/src/node_errors.h @@ -12,14 +12,10 @@ namespace node { -using v8::Local; -using v8::Message; -using v8::Value; - enum ErrorHandlingMode { CONTEXTIFY_ERROR, FATAL_ERROR, MODULE_ERROR }; void AppendExceptionLine(Environment* env, - Local er, - Local message, + v8::Local er, + v8::Local message, enum ErrorHandlingMode mode); [[noreturn]] void FatalError(const char* location, const char* message); @@ -31,34 +27,35 @@ void OnFatalError(const char* location, const char* message); // `node::ERR_INVALID_ARG_TYPE(isolate, "message")` returning // a `Local` containing the TypeError with proper code and message -#define ERRORS_WITH_CODE(V) \ - V(ERR_BUFFER_CONTEXT_NOT_AVAILABLE, Error) \ - V(ERR_BUFFER_OUT_OF_BOUNDS, RangeError) \ - V(ERR_BUFFER_TOO_LARGE, Error) \ - V(ERR_CONSTRUCT_CALL_REQUIRED, TypeError) \ - V(ERR_CONSTRUCT_CALL_INVALID, TypeError) \ - V(ERR_INVALID_ARG_VALUE, TypeError) \ - V(ERR_OSSL_EVP_INVALID_DIGEST, Error) \ - V(ERR_INVALID_ARG_TYPE, TypeError) \ - V(ERR_INVALID_MODULE_SPECIFIER, TypeError) \ - V(ERR_INVALID_PACKAGE_CONFIG, Error) \ - V(ERR_INVALID_PACKAGE_TARGET, Error) \ - V(ERR_INVALID_TRANSFER_OBJECT, TypeError) \ - V(ERR_MEMORY_ALLOCATION_FAILED, Error) \ - V(ERR_MISSING_ARGS, TypeError) \ - V(ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST, TypeError) \ - V(ERR_MISSING_PASSPHRASE, TypeError) \ - V(ERR_MISSING_PLATFORM_FOR_WORKER, Error) \ - V(ERR_NON_CONTEXT_AWARE_DISABLED, Error) \ - V(ERR_MODULE_NOT_FOUND, Error) \ - V(ERR_OUT_OF_RANGE, RangeError) \ - V(ERR_PACKAGE_PATH_NOT_EXPORTED, Error) \ - V(ERR_SCRIPT_EXECUTION_INTERRUPTED, Error) \ - V(ERR_SCRIPT_EXECUTION_TIMEOUT, Error) \ - V(ERR_STRING_TOO_LONG, Error) \ - V(ERR_TLS_INVALID_PROTOCOL_METHOD, TypeError) \ - V(ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER, TypeError) \ - V(ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED, Error) \ +#define ERRORS_WITH_CODE(V) \ + V(ERR_BUFFER_CONTEXT_NOT_AVAILABLE, Error) \ + V(ERR_BUFFER_OUT_OF_BOUNDS, RangeError) \ + V(ERR_BUFFER_TOO_LARGE, Error) \ + V(ERR_CONSTRUCT_CALL_REQUIRED, TypeError) \ + V(ERR_CONSTRUCT_CALL_INVALID, TypeError) \ + V(ERR_CRYPTO_UNKNOWN_CIPHER, Error) \ + V(ERR_CRYPTO_UNKNOWN_DH_GROUP, Error) \ + V(ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE, Error) \ + V(ERR_INVALID_ARG_VALUE, TypeError) \ + V(ERR_OSSL_EVP_INVALID_DIGEST, Error) \ + V(ERR_INVALID_ARG_TYPE, TypeError) \ + V(ERR_INVALID_TRANSFER_OBJECT, TypeError) \ + V(ERR_MEMORY_ALLOCATION_FAILED, Error) \ + V(ERR_MISSING_ARGS, TypeError) \ + V(ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST, TypeError) \ + V(ERR_MISSING_PASSPHRASE, TypeError) \ + V(ERR_MISSING_PLATFORM_FOR_WORKER, Error) \ + V(ERR_NON_CONTEXT_AWARE_DISABLED, Error) \ + V(ERR_OUT_OF_RANGE, RangeError) \ + V(ERR_SCRIPT_EXECUTION_INTERRUPTED, Error) \ + V(ERR_SCRIPT_EXECUTION_TIMEOUT, Error) \ + V(ERR_STRING_TOO_LONG, Error) \ + V(ERR_TLS_INVALID_PROTOCOL_METHOD, TypeError) \ + V(ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER, TypeError) \ + V(ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED, Error) \ + V(ERR_VM_MODULE_CACHED_DATA_REJECTED, Error) \ + V(ERR_WORKER_INIT_FAILED, Error) \ + V(ERR_PROTO_ACCESS, Error) #define V(code, type) \ inline v8::Local code(v8::Isolate* isolate, \ @@ -83,26 +80,34 @@ void OnFatalError(const char* location, const char* message); // Errors with predefined static messages -#define PREDEFINED_ERROR_MESSAGES(V) \ - V(ERR_BUFFER_CONTEXT_NOT_AVAILABLE, \ - "Buffer is not available for the current Context") \ - V(ERR_CONSTRUCT_CALL_INVALID, "Constructor cannot be called") \ - V(ERR_CONSTRUCT_CALL_REQUIRED, "Cannot call constructor without `new`") \ - V(ERR_INVALID_TRANSFER_OBJECT, "Found invalid object in transferList") \ - V(ERR_MEMORY_ALLOCATION_FAILED, "Failed to allocate memory") \ - V(ERR_OSSL_EVP_INVALID_DIGEST, "Invalid digest used") \ - V(ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST, \ - "MessagePort was found in message but not listed in transferList") \ - V(ERR_MISSING_PLATFORM_FOR_WORKER, \ - "The V8 platform used by this instance of Node does not support " \ - "creating Workers") \ - V(ERR_NON_CONTEXT_AWARE_DISABLED, \ - "Loading non context-aware native modules has been disabled") \ - V(ERR_SCRIPT_EXECUTION_INTERRUPTED, \ - "Script execution was interrupted by `SIGINT`") \ - V(ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER, \ - "Cannot serialize externalized SharedArrayBuffer") \ - V(ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED, "Failed to set PSK identity hint") \ +#define PREDEFINED_ERROR_MESSAGES(V) \ + V(ERR_BUFFER_CONTEXT_NOT_AVAILABLE, \ + "Buffer is not available for the current Context") \ + V(ERR_CONSTRUCT_CALL_INVALID, "Constructor cannot be called") \ + V(ERR_CONSTRUCT_CALL_REQUIRED, "Cannot call constructor without `new`") \ + V(ERR_CRYPTO_UNKNOWN_CIPHER, "Unknown cipher") \ + V(ERR_CRYPTO_UNKNOWN_DH_GROUP, "Unknown DH group") \ + V(ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE, \ + "Context not associated with Node.js environment") \ + V(ERR_INVALID_TRANSFER_OBJECT, "Found invalid object in transferList") \ + V(ERR_MEMORY_ALLOCATION_FAILED, "Failed to allocate memory") \ + V(ERR_OSSL_EVP_INVALID_DIGEST, "Invalid digest used") \ + V(ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST, \ + "MessagePort was found in message but not listed in transferList") \ + V(ERR_MISSING_PLATFORM_FOR_WORKER, \ + "The V8 platform used by this instance of Node does not support " \ + "creating Workers") \ + V(ERR_NON_CONTEXT_AWARE_DISABLED, \ + "Loading non context-aware native modules has been disabled") \ + V(ERR_SCRIPT_EXECUTION_INTERRUPTED, \ + "Script execution was interrupted by `SIGINT`") \ + V(ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER, \ + "Cannot serialize externalized SharedArrayBuffer") \ + V(ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED, "Failed to set PSK identity hint") \ + V(ERR_WORKER_INIT_FAILED, "Worker initialization failure") \ + V(ERR_PROTO_ACCESS, \ + "Accessing Object.prototype.__proto__ has been " \ + "disallowed with --disable-proto=throw") #define V(code, message) \ inline v8::Local code(v8::Isolate* isolate) { \ @@ -186,8 +191,8 @@ class TryCatchScope : public v8::TryCatch { void TriggerUncaughtException(v8::Isolate* isolate, const v8::TryCatch& try_catch); void TriggerUncaughtException(v8::Isolate* isolate, - Local error, - Local message, + v8::Local error, + v8::Local message, bool from_promise = false); const char* errno_string(int errorno); diff --git a/src/node_file-inl.h b/src/node_file-inl.h index 390f6c7415770f..e9ed18a75fa48b 100644 --- a/src/node_file-inl.h +++ b/src/node_file-inl.h @@ -21,6 +21,12 @@ void FSContinuationData::PushPath(const std::string& path) { paths_.push_back(path); } +void FSContinuationData::MaybeSetFirstPath(const std::string& path) { + if (first_path_.empty()) { + first_path_ = path; + } +} + std::string FSContinuationData::PopPath() { CHECK_GT(paths_.size(), 0); std::string path = std::move(paths_.back()); diff --git a/src/node_file.cc b/src/node_file.cc index bfdc73c9371ad1..97497132570c5f 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -590,6 +590,43 @@ void AfterOpenFileHandle(uv_fs_t* req) { } } +// Reverse the logic applied by path.toNamespacedPath() to create a +// namespace-prefixed path. +void FromNamespacedPath(std::string* path) { +#ifdef _WIN32 + if (path->compare(0, 8, "\\\\?\\UNC\\", 8) == 0) { + *path = path->substr(8); + path->insert(0, "\\\\"); + } else if (path->compare(0, 4, "\\\\?\\", 4) == 0) { + *path = path->substr(4); + } +#endif +} + +void AfterMkdirp(uv_fs_t* req) { + FSReqBase* req_wrap = FSReqBase::from_req(req); + FSReqAfterScope after(req_wrap, req); + + MaybeLocal path; + Local error; + + if (after.Proceed()) { + if (!req_wrap->continuation_data()->first_path().empty()) { + std::string first_path(req_wrap->continuation_data()->first_path()); + FromNamespacedPath(&first_path); + path = StringBytes::Encode(req_wrap->env()->isolate(), first_path.c_str(), + req_wrap->encoding(), + &error); + if (path.IsEmpty()) + req_wrap->Reject(error); + else + req_wrap->Resolve(path.ToLocalChecked()); + } else { + req_wrap->Resolve(Undefined(req_wrap->env()->isolate())); + } + } +} + void AfterStringPath(uv_fs_t* req) { FSReqBase* req_wrap = FSReqBase::from_req(req); FSReqAfterScope after(req_wrap, req); @@ -784,7 +821,7 @@ static void InternalModuleReadJSON(const FunctionCallbackInfo& args) { return; } - std::shared_ptr defer_close(nullptr, [fd, loop] (...) { + auto defer_close = OnScopeLeave([fd, loop]() { uv_fs_t close_req; CHECK_EQ(0, uv_fs_close(loop, &close_req, fd, nullptr)); uv_fs_req_cleanup(&close_req); @@ -1215,18 +1252,25 @@ int MKDirpSync(uv_loop_t* loop, const std::string& path, int mode, uv_fs_cb cb) { - FSContinuationData continuation_data(req, mode, cb); - continuation_data.PushPath(std::move(path)); + FSReqWrapSync* req_wrap = ContainerOf(&FSReqWrapSync::req, req); - while (continuation_data.paths().size() > 0) { - std::string next_path = continuation_data.PopPath(); + // on the first iteration of algorithm, stash state information. + if (req_wrap->continuation_data() == nullptr) { + req_wrap->set_continuation_data( + std::make_unique(req, mode, cb)); + req_wrap->continuation_data()->PushPath(std::move(path)); + } + + while (req_wrap->continuation_data()->paths().size() > 0) { + std::string next_path = req_wrap->continuation_data()->PopPath(); int err = uv_fs_mkdir(loop, req, next_path.c_str(), mode, nullptr); while (true) { switch (err) { // Note: uv_fs_req_cleanup in terminal paths will be called by // ~FSReqWrapSync(): case 0: - if (continuation_data.paths().size() == 0) { + req_wrap->continuation_data()->MaybeSetFirstPath(next_path); + if (req_wrap->continuation_data()->paths().size() == 0) { return 0; } break; @@ -1239,9 +1283,9 @@ int MKDirpSync(uv_loop_t* loop, std::string dirname = next_path.substr(0, next_path.find_last_of(kPathSeparator)); if (dirname != next_path) { - continuation_data.PushPath(std::move(next_path)); - continuation_data.PushPath(std::move(dirname)); - } else if (continuation_data.paths().size() == 0) { + req_wrap->continuation_data()->PushPath(std::move(next_path)); + req_wrap->continuation_data()->PushPath(std::move(dirname)); + } else if (req_wrap->continuation_data()->paths().size() == 0) { err = UV_EEXIST; continue; } @@ -1253,7 +1297,8 @@ int MKDirpSync(uv_loop_t* loop, err = uv_fs_stat(loop, req, next_path.c_str(), nullptr); if (err == 0 && !S_ISDIR(req->statbuf.st_mode)) { uv_fs_req_cleanup(req); - if (orig_err == UV_EEXIST && continuation_data.paths().size() > 0) { + if (orig_err == UV_EEXIST && + req_wrap->continuation_data()->paths().size() > 0) { return UV_ENOTDIR; } return UV_EEXIST; @@ -1298,8 +1343,10 @@ int MKDirpAsync(uv_loop_t* loop, // FSReqAfterScope::~FSReqAfterScope() case 0: { if (req_wrap->continuation_data()->paths().size() == 0) { + req_wrap->continuation_data()->MaybeSetFirstPath(path); req_wrap->continuation_data()->Done(0); } else { + req_wrap->continuation_data()->MaybeSetFirstPath(path); uv_fs_req_cleanup(req); MKDirpAsync(loop, req, path.c_str(), req_wrap->continuation_data()->mode(), nullptr); @@ -1362,6 +1409,25 @@ int MKDirpAsync(uv_loop_t* loop, return err; } +int CallMKDirpSync(Environment* env, const FunctionCallbackInfo& args, + FSReqWrapSync* req_wrap, const char* path, int mode) { + env->PrintSyncTrace(); + int err = MKDirpSync(env->event_loop(), &req_wrap->req, path, mode, + nullptr); + if (err < 0) { + v8::Local context = env->context(); + v8::Local ctx_obj = args[4].As(); + v8::Isolate* isolate = env->isolate(); + ctx_obj->Set(context, + env->errno_string(), + v8::Integer::New(isolate, err)).Check(); + ctx_obj->Set(context, + env->syscall_string(), + OneByteString(isolate, "mkdir")).Check(); + } + return err; +} + static void MKDir(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -1380,14 +1446,29 @@ static void MKDir(const FunctionCallbackInfo& args) { FSReqBase* req_wrap_async = GetReqWrap(env, args[3]); if (req_wrap_async != nullptr) { // mkdir(path, mode, req) AsyncCall(env, req_wrap_async, args, "mkdir", UTF8, - AfterNoArgs, mkdirp ? MKDirpAsync : uv_fs_mkdir, *path, mode); + mkdirp ? AfterMkdirp : AfterNoArgs, + mkdirp ? MKDirpAsync : uv_fs_mkdir, *path, mode); } else { // mkdir(path, mode, undefined, ctx) CHECK_EQ(argc, 5); FSReqWrapSync req_wrap_sync; FS_SYNC_TRACE_BEGIN(mkdir); if (mkdirp) { - SyncCall(env, args[4], &req_wrap_sync, "mkdir", - MKDirpSync, *path, mode); + int err = CallMKDirpSync(env, args, &req_wrap_sync, *path, mode); + if (err == 0 && + !req_wrap_sync.continuation_data()->first_path().empty()) { + Local error; + std::string first_path(req_wrap_sync.continuation_data()->first_path()); + FromNamespacedPath(&first_path); + MaybeLocal path = StringBytes::Encode(env->isolate(), + first_path.c_str(), + UTF8, &error); + if (path.IsEmpty()) { + Local ctx = args[4].As(); + ctx->Set(env->context(), env->error_string(), error).Check(); + return; + } + args.GetReturnValue().Set(path.ToLocalChecked()); + } } else { SyncCall(env, args[4], &req_wrap_sync, "mkdir", uv_fs_mkdir, *path, mode); @@ -1878,6 +1959,52 @@ static void Read(const FunctionCallbackInfo& args) { } +// Wrapper for readv(2). +// +// bytesRead = fs.readv(fd, buffers[, position], callback) +// 0 fd integer. file descriptor +// 1 buffers array of buffers to read +// 2 position if integer, position to read at in the file. +// if null, read from the current position +static void ReadBuffers(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + + const int argc = args.Length(); + CHECK_GE(argc, 3); + + CHECK(args[0]->IsInt32()); + const int fd = args[0].As()->Value(); + + CHECK(args[1]->IsArray()); + Local buffers = args[1].As(); + + int64_t pos = GetOffset(args[2]); // -1 if not a valid JS int + + MaybeStackBuffer iovs(buffers->Length()); + + // Init uv buffers from ArrayBufferViews + for (uint32_t i = 0; i < iovs.length(); i++) { + Local buffer = buffers->Get(env->context(), i).ToLocalChecked(); + CHECK(Buffer::HasInstance(buffer)); + iovs[i] = uv_buf_init(Buffer::Data(buffer), Buffer::Length(buffer)); + } + + FSReqBase* req_wrap_async = GetReqWrap(env, args[3]); + if (req_wrap_async != nullptr) { // readBuffers(fd, buffers, pos, req) + AsyncCall(env, req_wrap_async, args, "read", UTF8, AfterInteger, + uv_fs_read, fd, *iovs, iovs.length(), pos); + } else { // readBuffers(fd, buffers, undefined, ctx) + CHECK_EQ(argc, 5); + FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(read); + int bytesRead = SyncCall(env, /* ctx */ args[4], &req_wrap_sync, "read", + uv_fs_read, fd, *iovs, iovs.length(), pos); + FS_SYNC_TRACE_END(read, "bytesRead", bytesRead); + args.GetReturnValue().Set(bytesRead); + } +} + + /* fs.chmod(path, mode); * Wrapper for chmod(1) / EIO_CHMOD */ @@ -2141,6 +2268,7 @@ void Initialize(Local target, env->SetMethod(target, "open", Open); env->SetMethod(target, "openFileHandle", OpenFileHandle); env->SetMethod(target, "read", Read); + env->SetMethod(target, "readBuffers", ReadBuffers); env->SetMethod(target, "fdatasync", Fdatasync); env->SetMethod(target, "fsync", Fsync); env->SetMethod(target, "rename", Rename); @@ -2196,7 +2324,8 @@ void Initialize(Local target, // Create FunctionTemplate for FSReqCallback Local fst = env->NewFunctionTemplate(NewFSReqCallback); - fst->InstanceTemplate()->SetInternalFieldCount(1); + fst->InstanceTemplate()->SetInternalFieldCount( + FSReqBase::kInternalFieldCount); fst->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local wrapString = FIXED_ONE_BYTE_STRING(isolate, "FSReqCallback"); @@ -2209,7 +2338,8 @@ void Initialize(Local target, // Create FunctionTemplate for FileHandleReadWrap. There’s no need // to do anything in the constructor, so we only store the instance template. Local fh_rw = FunctionTemplate::New(isolate); - fh_rw->InstanceTemplate()->SetInternalFieldCount(1); + fh_rw->InstanceTemplate()->SetInternalFieldCount( + FSReqBase::kInternalFieldCount); fh_rw->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local fhWrapString = FIXED_ONE_BYTE_STRING(isolate, "FileHandleReqWrap"); @@ -2224,7 +2354,7 @@ void Initialize(Local target, FIXED_ONE_BYTE_STRING(isolate, "FSReqPromise"); fpt->SetClassName(promiseString); Local fpo = fpt->InstanceTemplate(); - fpo->SetInternalFieldCount(1); + fpo->SetInternalFieldCount(FSReqBase::kInternalFieldCount); env->set_fsreqpromise_constructor_template(fpo); // Create FunctionTemplate for FileHandle @@ -2233,7 +2363,7 @@ void Initialize(Local target, env->SetProtoMethod(fd, "close", FileHandle::Close); env->SetProtoMethod(fd, "releaseFD", FileHandle::ReleaseFD); Local fdt = fd->InstanceTemplate(); - fdt->SetInternalFieldCount(StreamBase::kStreamBaseFieldCount); + fdt->SetInternalFieldCount(StreamBase::kInternalFieldCount); Local handleString = FIXED_ONE_BYTE_STRING(isolate, "FileHandle"); fd->SetClassName(handleString); @@ -2250,7 +2380,7 @@ void Initialize(Local target, "FileHandleCloseReq")); fdclose->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local fdcloset = fdclose->InstanceTemplate(); - fdcloset->SetInternalFieldCount(1); + fdcloset->SetInternalFieldCount(FSReqBase::kInternalFieldCount); env->set_fdclose_constructor_template(fdcloset); Local use_promises_symbol = diff --git a/src/node_file.h b/src/node_file.h index 0574aa8f6c079d..1ebfe06c1fbdbf 100644 --- a/src/node_file.h +++ b/src/node_file.h @@ -19,10 +19,13 @@ class FSContinuationData : public MemoryRetainer { inline void PushPath(std::string&& path); inline void PushPath(const std::string& path); inline std::string PopPath(); + // Used by mkdirp to track the first path created: + inline void MaybeSetFirstPath(const std::string& path); inline void Done(int result); int mode() const { return mode_; } const std::vector& paths() const { return paths_; } + const std::string& first_path() const { return first_path_; } void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(FSContinuationData) @@ -33,6 +36,7 @@ class FSContinuationData : public MemoryRetainer { uv_fs_t* req_; int mode_; std::vector paths_; + std::string first_path_; }; class FSReqBase : public ReqWrap { @@ -306,8 +310,18 @@ class FSReqWrapSync { ~FSReqWrapSync() { uv_fs_req_cleanup(&req); } uv_fs_t req; + FSContinuationData* continuation_data() const { + return continuation_data_.get(); + } + void set_continuation_data(std::unique_ptr data) { + continuation_data_ = std::move(data); + } + FSReqWrapSync(const FSReqWrapSync&) = delete; FSReqWrapSync& operator=(const FSReqWrapSync&) = delete; + + private: + std::unique_ptr continuation_data_; }; // TODO(addaleax): Currently, callers check the return value and assume diff --git a/src/node_http2.cc b/src/node_http2.cc index 0eebe2935e248b..655cd97a9532c1 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -3059,14 +3059,14 @@ void Initialize(Local target, ping->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "Http2Ping")); ping->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local pingt = ping->InstanceTemplate(); - pingt->SetInternalFieldCount(1); + pingt->SetInternalFieldCount(Http2Session::Http2Ping::kInternalFieldCount); env->set_http2ping_constructor_template(pingt); Local setting = FunctionTemplate::New(env->isolate()); setting->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "Http2Setting")); setting->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local settingt = setting->InstanceTemplate(); - settingt->SetInternalFieldCount(1); + settingt->SetInternalFieldCount(AsyncWrap::kInternalFieldCount); env->set_http2settings_constructor_template(settingt); Local stream = FunctionTemplate::New(env->isolate()); @@ -3083,7 +3083,7 @@ void Initialize(Local target, stream->Inherit(AsyncWrap::GetConstructorTemplate(env)); StreamBase::AddMethods(env, stream); Local streamt = stream->InstanceTemplate(); - streamt->SetInternalFieldCount(StreamBase::kStreamBaseFieldCount); + streamt->SetInternalFieldCount(StreamBase::kInternalFieldCount); env->set_http2stream_constructor_template(streamt); target->Set(context, FIXED_ONE_BYTE_STRING(env->isolate(), "Http2Stream"), @@ -3092,7 +3092,8 @@ void Initialize(Local target, Local session = env->NewFunctionTemplate(Http2Session::New); session->SetClassName(http2SessionClassName); - session->InstanceTemplate()->SetInternalFieldCount(1); + session->InstanceTemplate()->SetInternalFieldCount( + Http2Session::kInternalFieldCount); session->Inherit(AsyncWrap::GetConstructorTemplate(env)); env->SetProtoMethod(session, "origin", Http2Session::Origin); env->SetProtoMethod(session, "altsvc", Http2Session::AltSvc); diff --git a/src/node_http_parser_impl.h b/src/node_http_parser_impl.h index 23f2eaf66d1d27..e1a99db316a060 100644 --- a/src/node_http_parser_impl.h +++ b/src/node_http_parser_impl.h @@ -940,7 +940,7 @@ void InitializeHttpParser(Local target, void* priv) { Environment* env = Environment::GetCurrent(context); Local t = env->NewFunctionTemplate(Parser::New); - t->InstanceTemplate()->SetInternalFieldCount(1); + t->InstanceTemplate()->SetInternalFieldCount(Parser::kInternalFieldCount); t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "HTTPParser")); t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "REQUEST"), diff --git a/src/node_i18n.cc b/src/node_i18n.cc index c68e01e1074a4a..169374aa5de441 100644 --- a/src/node_i18n.cc +++ b/src/node_i18n.cc @@ -86,7 +86,7 @@ namespace node { using v8::Context; using v8::FunctionCallbackInfo; -using v8::HandleScope; +using v8::FunctionTemplate; using v8::Int32; using v8::Isolate; using v8::Local; @@ -117,190 +117,6 @@ MaybeLocal ToBufferEndian(Environment* env, MaybeStackBuffer* buf) { return ret; } -struct Converter { - explicit Converter(const char* name, const char* sub = nullptr) - : conv(nullptr) { - UErrorCode status = U_ZERO_ERROR; - conv = ucnv_open(name, &status); - CHECK(U_SUCCESS(status)); - if (sub != nullptr) { - ucnv_setSubstChars(conv, sub, strlen(sub), &status); - } - } - - explicit Converter(UConverter* converter, - const char* sub = nullptr) : conv(converter) { - CHECK_NOT_NULL(conv); - UErrorCode status = U_ZERO_ERROR; - if (sub != nullptr) { - ucnv_setSubstChars(conv, sub, strlen(sub), &status); - } - } - - ~Converter() { - ucnv_close(conv); - } - - UConverter* conv; -}; - -class ConverterObject : public BaseObject, Converter { - public: - enum ConverterFlags { - CONVERTER_FLAGS_FLUSH = 0x1, - CONVERTER_FLAGS_FATAL = 0x2, - CONVERTER_FLAGS_IGNORE_BOM = 0x4 - }; - - ~ConverterObject() override = default; - - static void Has(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - HandleScope scope(env->isolate()); - - CHECK_GE(args.Length(), 1); - Utf8Value label(env->isolate(), args[0]); - - UErrorCode status = U_ZERO_ERROR; - UConverter* conv = ucnv_open(*label, &status); - args.GetReturnValue().Set(!!U_SUCCESS(status)); - ucnv_close(conv); - } - - static void Create(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - HandleScope scope(env->isolate()); - - Local t = ObjectTemplate::New(env->isolate()); - t->SetInternalFieldCount(1); - Local obj; - if (!t->NewInstance(env->context()).ToLocal(&obj)) return; - - CHECK_GE(args.Length(), 2); - Utf8Value label(env->isolate(), args[0]); - int flags = args[1]->Uint32Value(env->context()).ToChecked(); - bool fatal = - (flags & CONVERTER_FLAGS_FATAL) == CONVERTER_FLAGS_FATAL; - bool ignoreBOM = - (flags & CONVERTER_FLAGS_IGNORE_BOM) == CONVERTER_FLAGS_IGNORE_BOM; - - UErrorCode status = U_ZERO_ERROR; - UConverter* conv = ucnv_open(*label, &status); - if (U_FAILURE(status)) - return; - - if (fatal) { - status = U_ZERO_ERROR; - ucnv_setToUCallBack(conv, UCNV_TO_U_CALLBACK_STOP, - nullptr, nullptr, nullptr, &status); - } - - new ConverterObject(env, obj, conv, ignoreBOM); - args.GetReturnValue().Set(obj); - } - - static void Decode(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - - CHECK_GE(args.Length(), 3); // Converter, Buffer, Flags - - ConverterObject* converter; - ASSIGN_OR_RETURN_UNWRAP(&converter, args[0].As()); - ArrayBufferViewContents input(args[1]); - int flags = args[2]->Uint32Value(env->context()).ToChecked(); - - UErrorCode status = U_ZERO_ERROR; - MaybeStackBuffer result; - MaybeLocal ret; - size_t limit = ucnv_getMinCharSize(converter->conv) * input.length(); - if (limit > 0) - result.AllocateSufficientStorage(limit); - - UBool flush = (flags & CONVERTER_FLAGS_FLUSH) == CONVERTER_FLAGS_FLUSH; - auto cleanup = OnScopeLeave([&]() { - if (flush) { - // Reset the converter state. - converter->bomSeen_ = false; - ucnv_reset(converter->conv); - } - }); - - const char* source = input.data(); - size_t source_length = input.length(); - - UChar* target = *result; - ucnv_toUnicode(converter->conv, - &target, target + (limit * sizeof(UChar)), - &source, source + source_length, - nullptr, flush, &status); - - if (U_SUCCESS(status)) { - bool omit_initial_bom = false; - if (limit > 0) { - result.SetLength(target - &result[0]); - if (result.length() > 0 && - converter->unicode_ && - !converter->ignoreBOM_ && - !converter->bomSeen_) { - // If the very first result in the stream is a BOM, and we are not - // explicitly told to ignore it, then we mark it for discarding. - if (result[0] == 0xFEFF) { - omit_initial_bom = true; - } - converter->bomSeen_ = true; - } - } - ret = ToBufferEndian(env, &result); - if (omit_initial_bom && !ret.IsEmpty()) { - // Peform `ret = ret.slice(2)`. - CHECK(ret.ToLocalChecked()->IsUint8Array()); - Local orig_ret = ret.ToLocalChecked().As(); - ret = Buffer::New(env, - orig_ret->Buffer(), - orig_ret->ByteOffset() + 2, - orig_ret->ByteLength() - 2) - .FromMaybe(Local()); - } - if (!ret.IsEmpty()) - args.GetReturnValue().Set(ret.ToLocalChecked()); - return; - } - - args.GetReturnValue().Set(status); - } - - SET_NO_MEMORY_INFO() - SET_MEMORY_INFO_NAME(ConverterObject) - SET_SELF_SIZE(ConverterObject) - - protected: - ConverterObject(Environment* env, - Local wrap, - UConverter* converter, - bool ignoreBOM, - const char* sub = nullptr) : - BaseObject(env, wrap), - Converter(converter, sub), - ignoreBOM_(ignoreBOM) { - MakeWeak(); - - switch (ucnv_getType(converter)) { - case UCNV_UTF8: - case UCNV_UTF16_BigEndian: - case UCNV_UTF16_LittleEndian: - unicode_ = true; - break; - default: - unicode_ = false; - } - } - - private: - bool unicode_ = false; // True if this is a Unicode converter - bool ignoreBOM_ = false; // True if the BOM should be ignored on Unicode - bool bomSeen_ = false; // True if the BOM has been seen -}; - // One-Shot Converters void CopySourceBuffer(MaybeStackBuffer* dest, @@ -333,10 +149,10 @@ MaybeLocal Transcode(Environment* env, MaybeStackBuffer result; Converter to(toEncoding, "?"); Converter from(fromEncoding); - const uint32_t limit = source_length * ucnv_getMaxCharSize(to.conv); + const uint32_t limit = source_length * to.max_char_size(); result.AllocateSufficientStorage(limit); char* target = *result; - ucnv_convertEx(to.conv, from.conv, &target, target + limit, + ucnv_convertEx(to.conv(), from.conv(), &target, target + limit, &source, source + source_length, nullptr, nullptr, nullptr, nullptr, true, true, status); if (U_SUCCESS(*status)) { @@ -357,7 +173,7 @@ MaybeLocal TranscodeToUcs2(Environment* env, MaybeStackBuffer destbuf(source_length); Converter from(fromEncoding); const size_t length_in_chars = source_length * sizeof(UChar); - ucnv_toUChars(from.conv, *destbuf, length_in_chars, + ucnv_toUChars(from.conv(), *destbuf, length_in_chars, source, source_length, status); if (U_SUCCESS(*status)) ret = ToBufferEndian(env, &destbuf); @@ -377,7 +193,7 @@ MaybeLocal TranscodeFromUcs2(Environment* env, const size_t length_in_chars = source_length / sizeof(UChar); CopySourceBuffer(&sourcebuf, source, source_length, length_in_chars); MaybeStackBuffer destbuf(length_in_chars); - const uint32_t len = ucnv_fromUChars(to.conv, *destbuf, length_in_chars, + const uint32_t len = ucnv_fromUChars(to.conv(), *destbuf, length_in_chars, *sourcebuf, length_in_chars, status); if (U_SUCCESS(*status)) { destbuf.SetLength(len); @@ -528,6 +344,178 @@ void ICUErrorName(const FunctionCallbackInfo& args) { } // anonymous namespace +Converter::Converter(const char* name, const char* sub) { + UErrorCode status = U_ZERO_ERROR; + UConverter* conv = ucnv_open(name, &status); + CHECK(U_SUCCESS(status)); + conv_.reset(conv); + set_subst_chars(sub); +} + +Converter::Converter(UConverter* converter, const char* sub) + : conv_(converter) { + set_subst_chars(sub); +} + +void Converter::set_subst_chars(const char* sub) { + CHECK(conv_); + UErrorCode status = U_ZERO_ERROR; + if (sub != nullptr) { + ucnv_setSubstChars(conv_.get(), sub, strlen(sub), &status); + CHECK(U_SUCCESS(status)); + } +} + +void Converter::reset() { + ucnv_reset(conv_.get()); +} + +size_t Converter::min_char_size() const { + CHECK(conv_); + return ucnv_getMinCharSize(conv_.get()); +} + +size_t Converter::max_char_size() const { + CHECK(conv_); + return ucnv_getMaxCharSize(conv_.get()); +} + +void ConverterObject::Has(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + + CHECK_GE(args.Length(), 1); + Utf8Value label(env->isolate(), args[0]); + + UErrorCode status = U_ZERO_ERROR; + ConverterPointer conv(ucnv_open(*label, &status)); + args.GetReturnValue().Set(!!U_SUCCESS(status)); +} + +void ConverterObject::Create(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + + Local t = env->i18n_converter_template(); + Local obj; + if (!t->NewInstance(env->context()).ToLocal(&obj)) return; + + CHECK_GE(args.Length(), 2); + Utf8Value label(env->isolate(), args[0]); + int flags = args[1]->Uint32Value(env->context()).ToChecked(); + bool fatal = + (flags & CONVERTER_FLAGS_FATAL) == CONVERTER_FLAGS_FATAL; + + UErrorCode status = U_ZERO_ERROR; + UConverter* conv = ucnv_open(*label, &status); + if (U_FAILURE(status)) + return; + + if (fatal) { + status = U_ZERO_ERROR; + ucnv_setToUCallBack(conv, UCNV_TO_U_CALLBACK_STOP, + nullptr, nullptr, nullptr, &status); + } + + new ConverterObject(env, obj, conv, flags); + args.GetReturnValue().Set(obj); +} + +void ConverterObject::Decode(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + + CHECK_GE(args.Length(), 3); // Converter, Buffer, Flags + + ConverterObject* converter; + ASSIGN_OR_RETURN_UNWRAP(&converter, args[0].As()); + ArrayBufferViewContents input(args[1]); + int flags = args[2]->Uint32Value(env->context()).ToChecked(); + + UErrorCode status = U_ZERO_ERROR; + MaybeStackBuffer result; + MaybeLocal ret; + size_t limit = converter->min_char_size() * input.length(); + if (limit > 0) + result.AllocateSufficientStorage(limit); + + UBool flush = (flags & CONVERTER_FLAGS_FLUSH) == CONVERTER_FLAGS_FLUSH; + auto cleanup = OnScopeLeave([&]() { + if (flush) { + // Reset the converter state. + converter->set_bom_seen(false); + converter->reset(); + } + }); + + const char* source = input.data(); + size_t source_length = input.length(); + + UChar* target = *result; + ucnv_toUnicode(converter->conv(), + &target, + target + (limit * sizeof(UChar)), + &source, + source + source_length, + nullptr, + flush, + &status); + + if (U_SUCCESS(status)) { + bool omit_initial_bom = false; + if (limit > 0) { + result.SetLength(target - &result[0]); + if (result.length() > 0 && + converter->unicode() && + !converter->ignore_bom() && + !converter->bom_seen()) { + // If the very first result in the stream is a BOM, and we are not + // explicitly told to ignore it, then we mark it for discarding. + if (result[0] == 0xFEFF) + omit_initial_bom = true; + converter->set_bom_seen(true); + } + } + ret = ToBufferEndian(env, &result); + if (omit_initial_bom && !ret.IsEmpty()) { + // Peform `ret = ret.slice(2)`. + CHECK(ret.ToLocalChecked()->IsUint8Array()); + Local orig_ret = ret.ToLocalChecked().As(); + ret = Buffer::New(env, + orig_ret->Buffer(), + orig_ret->ByteOffset() + 2, + orig_ret->ByteLength() - 2) + .FromMaybe(Local()); + } + if (!ret.IsEmpty()) + args.GetReturnValue().Set(ret.ToLocalChecked()); + return; + } + + args.GetReturnValue().Set(status); +} + +ConverterObject::ConverterObject( + Environment* env, + Local wrap, + UConverter* converter, + int flags, + const char* sub) + : BaseObject(env, wrap), + Converter(converter, sub), + flags_(flags) { + MakeWeak(); + + switch (ucnv_getType(converter)) { + case UCNV_UTF8: + case UCNV_UTF16_BigEndian: + case UCNV_UTF16_LittleEndian: + flags_ |= CONVERTER_FLAGS_UNICODE; + break; + default: { + // Fall through + } + } +} + + bool InitializeICUDirectory(const std::string& path) { UErrorCode status = U_ZERO_ERROR; if (path.empty()) { @@ -728,16 +716,6 @@ static void ToASCII(const FunctionCallbackInfo& args) { // Refs: https://github.com/KDE/konsole/blob/8c6a5d13c0/src/konsole_wcwidth.cpp#L101-L223 static int GetColumnWidth(UChar32 codepoint, bool ambiguous_as_full_width = false) { - const auto zero_width_mask = U_GC_CC_MASK | // C0/C1 control code - U_GC_CF_MASK | // Format control character - U_GC_ME_MASK | // Enclosing mark - U_GC_MN_MASK; // Nonspacing mark - if (codepoint != 0x00AD && // SOFT HYPHEN is Cf but not zero-width - ((U_MASK(u_charType(codepoint)) & zero_width_mask) || - u_hasBinaryProperty(codepoint, UCHAR_EMOJI_MODIFIER))) { - return 0; - } - // UCHAR_EAST_ASIAN_WIDTH is the Unicode property that identifies a // codepoint as being full width, wide, ambiguous, neutral, narrow, // or halfwidth. @@ -761,6 +739,15 @@ static int GetColumnWidth(UChar32 codepoint, case U_EA_HALFWIDTH: case U_EA_NARROW: default: + const auto zero_width_mask = U_GC_CC_MASK | // C0/C1 control code + U_GC_CF_MASK | // Format control character + U_GC_ME_MASK | // Enclosing mark + U_GC_MN_MASK; // Nonspacing mark + if (codepoint != 0x00AD && // SOFT HYPHEN is Cf but not zero-width + ((U_MASK(u_charType(codepoint)) & zero_width_mask) || + u_hasBinaryProperty(codepoint, UCHAR_EMOJI_MODIFIER))) { + return 0; + } return 1; } } @@ -768,18 +755,10 @@ static int GetColumnWidth(UChar32 codepoint, // Returns the column width for the given String. static void GetStringWidth(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - if (args.Length() < 1) - return; + CHECK(args[0]->IsString()); bool ambiguous_as_full_width = args[1]->IsTrue(); - bool expand_emoji_sequence = args[2]->IsTrue(); - - if (args[0]->IsNumber()) { - uint32_t val; - if (!args[0]->Uint32Value(env->context()).To(&val)) return; - args.GetReturnValue().Set(GetColumnWidth(val, ambiguous_as_full_width)); - return; - } + bool expand_emoji_sequence = !args[2]->IsBoolean() || args[2]->IsTrue(); TwoByteValue value(env->isolate(), args[0]); // reinterpret_cast is required by windows to compile @@ -804,6 +783,7 @@ static void GetStringWidth(const FunctionCallbackInfo& args) { // in advance if a particular sequence is going to be supported. // The expand_emoji_sequence option allows the caller to skip this // check and count each code within an emoji sequence separately. + // https://www.unicode.org/reports/tr51/tr51-16.html#Emoji_ZWJ_Sequences if (!expand_emoji_sequence && n > 0 && p == 0x200d && // 0x200d == ZWJ (zero width joiner) (u_hasBinaryProperty(c, UCHAR_EMOJI_PRESENTATION) || @@ -829,6 +809,16 @@ void Initialize(Local target, env->SetMethod(target, "transcode", Transcode); // ConverterObject + { + Local t = FunctionTemplate::New(env->isolate()); + t->InstanceTemplate()->SetInternalFieldCount( + ConverterObject::kInternalFieldCount); + Local converter_string = + FIXED_ONE_BYTE_STRING(env->isolate(), "Converter"); + t->SetClassName(converter_string); + env->set_i18n_converter_template(t->InstanceTemplate()); + } + env->SetMethod(target, "getConverter", ConverterObject::Create); env->SetMethod(target, "decode", ConverterObject::Decode); env->SetMethod(target, "hasConverter", ConverterObject::Has); diff --git a/src/node_i18n.h b/src/node_i18n.h index a0a398ac818736..5c1501ea1908e0 100644 --- a/src/node_i18n.h +++ b/src/node_i18n.h @@ -24,11 +24,16 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS +#if defined(NODE_HAVE_I18N_SUPPORT) + +#include "base_object.h" +#include "env.h" #include "util.h" +#include "v8.h" -#include +#include -#if defined(NODE_HAVE_I18N_SUPPORT) +#include namespace node { @@ -60,6 +65,75 @@ int32_t ToUnicode(MaybeStackBuffer* buf, const char* input, size_t length); +struct ConverterDeleter { + void operator()(UConverter* pointer) const { ucnv_close(pointer); } +}; +using ConverterPointer = std::unique_ptr; + +class Converter { + public: + explicit Converter(const char* name, const char* sub = nullptr); + explicit Converter(UConverter* converter, const char* sub = nullptr); + + UConverter* conv() const { return conv_.get(); } + + size_t max_char_size() const; + size_t min_char_size() const; + void reset(); + void set_subst_chars(const char* sub = nullptr); + + private: + ConverterPointer conv_; +}; + +class ConverterObject : public BaseObject, Converter { + public: + enum ConverterFlags { + CONVERTER_FLAGS_FLUSH = 0x1, + CONVERTER_FLAGS_FATAL = 0x2, + CONVERTER_FLAGS_IGNORE_BOM = 0x4, + CONVERTER_FLAGS_UNICODE = 0x8, + CONVERTER_FLAGS_BOM_SEEN = 0x10, + }; + + static void Create(const v8::FunctionCallbackInfo& args); + static void Decode(const v8::FunctionCallbackInfo& args); + static void Has(const v8::FunctionCallbackInfo& args); + + SET_NO_MEMORY_INFO() + SET_MEMORY_INFO_NAME(ConverterObject) + SET_SELF_SIZE(ConverterObject) + + protected: + ConverterObject(Environment* env, + v8::Local wrap, + UConverter* converter, + int flags, + const char* sub = nullptr); + + void set_bom_seen(bool seen) { + if (seen) + flags_ |= CONVERTER_FLAGS_BOM_SEEN; + else + flags_ &= ~CONVERTER_FLAGS_BOM_SEEN; + } + + bool bom_seen() const { + return (flags_ & CONVERTER_FLAGS_BOM_SEEN) == CONVERTER_FLAGS_BOM_SEEN; + } + + bool unicode() const { + return (flags_ & CONVERTER_FLAGS_UNICODE) == CONVERTER_FLAGS_UNICODE; + } + + bool ignore_bom() const { + return (flags_ & CONVERTER_FLAGS_IGNORE_BOM) == CONVERTER_FLAGS_IGNORE_BOM; + } + + private: + int flags_ = 0; +}; + } // namespace i18n } // namespace node diff --git a/src/node_internals.h b/src/node_internals.h index 0ba13ceaea2ea2..7ec3eac697e4b7 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -102,6 +102,7 @@ std::string GetProcessTitle(const char* default_title); std::string GetHumanReadableProcessName(); void InitializeContextRuntime(v8::Local); +bool InitializePrimordials(v8::Local context); namespace task_queue { void PromiseRejectCallback(v8::PromiseRejectMessage message); @@ -112,20 +113,24 @@ class NodeArrayBufferAllocator : public ArrayBufferAllocator { inline uint32_t* zero_fill_field() { return &zero_fill_field_; } void* Allocate(size_t size) override; // Defined in src/node.cc - void* AllocateUninitialized(size_t size) override - { return node::UncheckedMalloc(size); } - void Free(void* data, size_t) override { free(data); } - virtual void* Reallocate(void* data, size_t old_size, size_t size) { - return static_cast( - UncheckedRealloc(static_cast(data), size)); + void* AllocateUninitialized(size_t size) override; + void Free(void* data, size_t size) override; + virtual void* Reallocate(void* data, size_t old_size, size_t size); + virtual void RegisterPointer(void* data, size_t size) { + total_mem_usage_.fetch_add(size, std::memory_order_relaxed); + } + virtual void UnregisterPointer(void* data, size_t size) { + total_mem_usage_.fetch_sub(size, std::memory_order_relaxed); } - virtual void RegisterPointer(void* data, size_t size) {} - virtual void UnregisterPointer(void* data, size_t size) {} NodeArrayBufferAllocator* GetImpl() final { return this; } + inline uint64_t total_mem_usage() const { + return total_mem_usage_.load(std::memory_order_relaxed); + } private: uint32_t zero_fill_field_ = 1; // Boolean but exposed as uint32 to JS land. + std::atomic total_mem_usage_ {0}; }; class DebuggingArrayBufferAllocator final : public NodeArrayBufferAllocator { @@ -197,6 +202,7 @@ static v8::MaybeLocal New(Environment* env, v8::MaybeLocal InternalMakeCallback( Environment* env, + v8::Local resource, v8::Local recv, const v8::Local callback, int argc, @@ -207,15 +213,13 @@ class InternalCallbackScope { public: enum Flags { kNoFlags = 0, - // Tell the constructor whether its `object` parameter may be empty or not. - kAllowEmptyResource = 1, // Indicates whether 'before' and 'after' hooks should be skipped. - kSkipAsyncHooks = 2, + kSkipAsyncHooks = 1, // Indicates whether nextTick and microtask queues should be skipped. // This should only be used when there is no call into JS in this scope. // (The HTTP parser also uses it for some weird backwards // compatibility issues, but it shouldn't.) - kSkipTaskQueues = 4 + kSkipTaskQueues = 2 }; InternalCallbackScope(Environment* env, v8::Local object, @@ -383,6 +387,16 @@ class TraceEventScope { void* id_; }; +namespace heap { + +void DeleteHeapSnapshot(const v8::HeapSnapshot* snapshot); +using HeapSnapshotPointer = + DeleteFnPtr; + +BaseObjectPtr CreateHeapSnapshotStream( + Environment* env, HeapSnapshotPointer&& snapshot); +} // namespace heap + } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS diff --git a/src/node_main_instance.cc b/src/node_main_instance.cc index 23ede8e0b819c1..998cf260de2a62 100644 --- a/src/node_main_instance.cc +++ b/src/node_main_instance.cc @@ -102,12 +102,8 @@ NodeMainInstance::~NodeMainInstance() { if (!owns_isolate_) { return; } - // TODO(addaleax): Reverse the order of these calls. The fact that we first - // dispose the Isolate is a temporary workaround for - // https://github.com/nodejs/node/issues/31752 -- V8 should not be posting - // platform tasks during Dispose(), but it does in some WASM edge cases. - isolate_->Dispose(); platform_->UnregisterIsolate(isolate_); + isolate_->Dispose(); } int NodeMainInstance::Run() { @@ -122,15 +118,7 @@ int NodeMainInstance::Run() { Context::Scope context_scope(env->context()); if (exit_code == 0) { - { - InternalCallbackScope callback_scope( - env.get(), - Local(), - { 1, 0 }, - InternalCallbackScope::kAllowEmptyResource | - InternalCallbackScope::kSkipAsyncHooks); - LoadEnvironment(env.get()); - } + LoadEnvironment(env.get()); env->set_trace_sync_io(env->options()->trace_sync_io); diff --git a/src/node_mem.h b/src/node_mem.h index 0d3388ad4766bb..f8cdc20848f82e 100644 --- a/src/node_mem.h +++ b/src/node_mem.h @@ -13,8 +13,12 @@ namespace mem { // use different struct names. To allow for code re-use, // the NgLibMemoryManager template class can be used for both. +struct NgLibMemoryManagerBase { + virtual void StopTrackingMemory(void* ptr) = 0; +}; + template -class NgLibMemoryManager { +class NgLibMemoryManager : public NgLibMemoryManagerBase { public: // Class needs to provide these methods: // void CheckAllocatedSize(size_t previous_size) const; @@ -24,7 +28,7 @@ class NgLibMemoryManager { AllocatorStructName MakeAllocator(); - void StopTrackingMemory(void* ptr); + void StopTrackingMemory(void* ptr) override; private: static void* ReallocImpl(void* ptr, size_t size, void* user_data); diff --git a/src/node_messaging.cc b/src/node_messaging.cc index c7c46063731a5b..fa7132d7b43a3d 100644 --- a/src/node_messaging.cc +++ b/src/node_messaging.cc @@ -515,10 +515,9 @@ MessagePort::MessagePort(Environment* env, CHECK_EQ(uv_async_init(env->event_loop(), &async_, onmessage), 0); - async_.data = nullptr; // Reset later to indicate success of the constructor. - auto cleanup = OnScopeLeave([&]() { - if (async_.data == nullptr) Close(); - }); + // Reset later to indicate success of the constructor. + bool succeeded = false; + auto cleanup = OnScopeLeave([&]() { if (!succeeded) Close(); }); Local fn; if (!wrap->Get(context, env->oninit_symbol()).ToLocal(&fn)) @@ -535,7 +534,7 @@ MessagePort::MessagePort(Environment* env, return; emit_message_fn_.Reset(env->isolate(), emit_message_fn); - async_.data = static_cast(this); + succeeded = true; Debug(this, "Created message port"); } @@ -896,7 +895,12 @@ void MessagePort::Drain(const FunctionCallbackInfo& args) { } void MessagePort::ReceiveMessage(const FunctionCallbackInfo& args) { - CHECK(args[0]->IsObject()); + Environment* env = Environment::GetCurrent(args); + if (!args[0]->IsObject() || + !env->message_port_constructor_template()->HasInstance(args[0])) { + return THROW_ERR_INVALID_ARG_TYPE(env, + "First argument needs to be a MessagePort instance"); + } MessagePort* port = Unwrap(args[0].As()); if (port == nullptr) { // Return 'no messages' for a closed port. @@ -963,7 +967,8 @@ Local GetMessagePortConstructorTemplate(Environment* env) { { Local m = env->NewFunctionTemplate(MessagePort::New); m->SetClassName(env->message_port_constructor_string()); - m->InstanceTemplate()->SetInternalFieldCount(1); + m->InstanceTemplate()->SetInternalFieldCount( + MessagePort::kInternalFieldCount); m->Inherit(HandleWrap::GetConstructorTemplate(env)); env->SetProtoMethod(m, "postMessage", MessagePort::PostMessage); diff --git a/src/node_native_module.cc b/src/node_native_module.cc index 43c13ea30a0dc5..1b916d645d8639 100644 --- a/src/node_native_module.cc +++ b/src/node_native_module.cc @@ -174,6 +174,64 @@ MaybeLocal NativeModuleLoader::CompileAsModule( return LookupAndCompile(context, id, ¶meters, result); } +#ifdef NODE_BUILTIN_MODULES_PATH +static std::string OnDiskFileName(const char* id) { + std::string filename = NODE_BUILTIN_MODULES_PATH; + filename += "/"; + + if (strncmp(id, "internal/deps", strlen("internal/deps")) == 0) { + id += strlen("internal/"); + } else { + filename += "lib/"; + } + filename += id; + filename += ".js"; + + return filename; +} +#endif // NODE_BUILTIN_MODULES_PATH + +MaybeLocal NativeModuleLoader::LoadBuiltinModuleSource(Isolate* isolate, + const char* id) { +#ifdef NODE_BUILTIN_MODULES_PATH + std::string filename = OnDiskFileName(id); + + uv_fs_t req; + uv_file file = + uv_fs_open(nullptr, &req, filename.c_str(), O_RDONLY, 0, nullptr); + CHECK_GE(req.result, 0); + uv_fs_req_cleanup(&req); + + auto defer_close = OnScopeLeave([file]() { + uv_fs_t close_req; + CHECK_EQ(0, uv_fs_close(nullptr, &close_req, file, nullptr)); + uv_fs_req_cleanup(&close_req); + }); + + std::string contents; + char buffer[4096]; + uv_buf_t buf = uv_buf_init(buffer, sizeof(buffer)); + + while (true) { + const int r = + uv_fs_read(nullptr, &req, file, &buf, 1, contents.length(), nullptr); + CHECK_GE(req.result, 0); + uv_fs_req_cleanup(&req); + if (r <= 0) { + break; + } + contents.append(buf.base, r); + } + + return String::NewFromUtf8( + isolate, contents.c_str(), v8::NewStringType::kNormal, contents.length()); +#else + const auto source_it = source_.find(id); + CHECK_NE(source_it, source_.end()); + return source_it->second.ToStringChecked(isolate); +#endif // NODE_BUILTIN_MODULES_PATH +} + // Returns Local of the compiled module if return_code_cache // is false (we are only compiling the function). // Otherwise return a Local containing the cache. @@ -185,9 +243,10 @@ MaybeLocal NativeModuleLoader::LookupAndCompile( Isolate* isolate = context->GetIsolate(); EscapableHandleScope scope(isolate); - const auto source_it = source_.find(id); - CHECK_NE(source_it, source_.end()); - Local source = source_it->second.ToStringChecked(isolate); + Local source; + if (!LoadBuiltinModuleSource(isolate, id).ToLocal(&source)) { + return {}; + } std::string filename_s = id + std::string(".js"); Local filename = diff --git a/src/node_native_module.h b/src/node_native_module.h index fabaea75686161..c0bce3bce42c84 100644 --- a/src/node_native_module.h +++ b/src/node_native_module.h @@ -66,6 +66,8 @@ class NativeModuleLoader { NativeModuleCacheMap* code_cache(); v8::ScriptCompiler::CachedData* GetCodeCache(const char* id) const; enum class Result { kWithCache, kWithoutCache }; + v8::MaybeLocal LoadBuiltinModuleSource(v8::Isolate* isolate, + const char* id); // If an exception is encountered (e.g. source code contains // syntax error), the returned value is empty. v8::MaybeLocal LookupAndCompile( diff --git a/src/node_options.cc b/src/node_options.cc index 9985a6e405895b..8b3a161c2d2f83 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -66,64 +66,19 @@ void PerProcessOptions::CheckOptions(std::vector* errors) { "used, not both"); } #endif + if (use_largepages != "off" && + use_largepages != "on" && + use_largepages != "silent") { + errors->push_back("invalid value for --use-largepages"); + } per_isolate->CheckOptions(errors); } void PerIsolateOptions::CheckOptions(std::vector* errors) { per_env->CheckOptions(errors); -#ifdef NODE_REPORT - if (per_env->experimental_report) { - // Assign the report_signal default value here. Once the - // --experimental-report flag is dropped, move this initialization to - // node_options.h, where report_signal is declared. - if (report_signal.empty()) - report_signal = "SIGUSR2"; - return; - } - - if (!report_directory.empty()) { - errors->push_back("--report-directory option is valid only when " - "--experimental-report is set"); - } - - if (!report_filename.empty()) { - errors->push_back("--report-filename option is valid only when " - "--experimental-report is set"); - } - - if (!report_signal.empty()) { - errors->push_back("--report-signal option is valid only when " - "--experimental-report is set"); - } - - if (report_on_fatalerror) { - errors->push_back( - "--report-on-fatalerror option is valid only when " - "--experimental-report is set"); - } - - if (report_on_signal) { - errors->push_back("--report-on-signal option is valid only when " - "--experimental-report is set"); - } - - if (report_uncaught_exception) { - errors->push_back( - "--report-uncaught-exception option is valid only when " - "--experimental-report is set"); - } -#endif // NODE_REPORT } void EnvironmentOptions::CheckOptions(std::vector* errors) { - if (experimental_import_meta_resolve && !experimental_modules) { - errors->push_back("--experimental-meta-resolve requires " - "--experimental-modules be enabled"); - } - if (!userland_loader.empty() && !experimental_modules) { - errors->push_back("--experimental-loader requires " - "--experimental-modules be enabled"); - } if (has_policy_integrity_string && experimental_policy.empty()) { errors->push_back("--policy-integrity requires " "--experimental-policy be enabled"); @@ -133,30 +88,12 @@ void EnvironmentOptions::CheckOptions(std::vector* errors) { } if (!module_type.empty()) { - if (!experimental_modules) { - errors->push_back("--input-type requires " - "--experimental-modules to be enabled"); - } if (module_type != "commonjs" && module_type != "module") { errors->push_back("--input-type must be \"module\" or \"commonjs\""); } } - if (experimental_json_modules && !experimental_modules) { - errors->push_back("--experimental-json-modules requires " - "--experimental-modules be enabled"); - } - - if (experimental_wasm_modules && !experimental_modules) { - errors->push_back("--experimental-wasm-modules requires " - "--experimental-modules be enabled"); - } - if (!es_module_specifier_resolution.empty()) { - if (!experimental_modules) { - errors->push_back("--es-module-specifier-resolution requires " - "--experimental-modules be enabled"); - } if (!experimental_specifier_resolution.empty()) { errors->push_back( "bad option: cannot use --es-module-specifier-resolution" @@ -170,10 +107,6 @@ void EnvironmentOptions::CheckOptions(std::vector* errors) { } } } else if (!experimental_specifier_resolution.empty()) { - if (!experimental_modules) { - errors->push_back("--experimental-specifier-resolution requires " - "--experimental-modules be enabled"); - } if (experimental_specifier_resolution != "node" && experimental_specifier_resolution != "explicit") { errors->push_back( @@ -351,13 +284,12 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { &EnvironmentOptions::experimental_json_modules, kAllowedInEnvironment); AddOption("--experimental-loader", - "(with --experimental-modules) use the specified file as a " - "custom loader", + "use the specified module as a custom loader", &EnvironmentOptions::userland_loader, kAllowedInEnvironment); AddAlias("--loader", "--experimental-loader"); AddOption("--experimental-modules", - "experimental ES Module support and caching modules", + "", &EnvironmentOptions::experimental_modules, kAllowedInEnvironment); AddOption("--experimental-wasm-modules", @@ -391,12 +323,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { &EnvironmentOptions::experimental_vm_modules, kAllowedInEnvironment); AddOption("--experimental-worker", "", NoOp{}, kAllowedInEnvironment); -#ifdef NODE_REPORT - AddOption("--experimental-report", - "enable report generation", - &EnvironmentOptions::experimental_report, - kAllowedInEnvironment); -#endif // NODE_REPORT + AddOption("--experimental-report", "", NoOp{}, kAllowedInEnvironment); AddOption("--experimental-wasi-unstable-preview1", "experimental WASI support", &EnvironmentOptions::experimental_wasi, @@ -651,12 +578,15 @@ PerIsolateOptionsParser::PerIsolateOptionsParser( "disallow eval and friends", V8Option{}, kAllowedInEnvironment); + AddOption("--huge-max-old-generation-size", + "increase default maximum heap size on machines with 16GB memory " + "or more", + V8Option{}, + kAllowedInEnvironment); AddOption("--jitless", "disable runtime allocation of executable memory", V8Option{}, kAllowedInEnvironment); - -#ifdef NODE_REPORT AddOption("--report-uncaught-exception", "generate diagnostic report on uncaught exceptions", &PerIsolateOptions::report_uncaught_exception, @@ -665,27 +595,12 @@ PerIsolateOptionsParser::PerIsolateOptionsParser( "generate diagnostic report upon receiving signals", &PerIsolateOptions::report_on_signal, kAllowedInEnvironment); - AddOption("--report-on-fatalerror", - "generate diagnostic report on fatal (internal) errors", - &PerIsolateOptions::report_on_fatalerror, - kAllowedInEnvironment); AddOption("--report-signal", "causes diagnostic report to be produced on provided signal," " unsupported in Windows. (default: SIGUSR2)", &PerIsolateOptions::report_signal, kAllowedInEnvironment); Implies("--report-signal", "--report-on-signal"); - AddOption("--report-filename", - "define custom report file name." - " (default: YYYYMMDD.HHMMSS.PID.SEQUENCE#.txt)", - &PerIsolateOptions::report_filename, - kAllowedInEnvironment); - AddOption("--report-directory", - "define custom report pathname." - " (default: current working directory of Node.js process)", - &PerIsolateOptions::report_directory, - kAllowedInEnvironment); -#endif // NODE_REPORT Insert(eop, &PerIsolateOptions::get_per_env_options); } @@ -724,7 +639,10 @@ PerProcessOptionsParser::PerProcessOptionsParser( "", /* undocumented, only for debugging */ &PerProcessOptions::debug_arraybuffer_allocations, kAllowedInEnvironment); - + AddOption("--disable-proto", + "disable Object.prototype.__proto__", + &PerProcessOptions::disable_proto, + kAllowedInEnvironment); // 12.x renamed this inadvertently, so alias it for consistency within the // release line, while using the original name for consistency with older @@ -744,6 +662,24 @@ PerProcessOptionsParser::PerProcessOptionsParser( AddOption("--v8-options", "print V8 command line options", &PerProcessOptions::print_v8_help); + AddOption("--report-compact", + "output compact single-line JSON", + &PerProcessOptions::report_compact, + kAllowedInEnvironment); + AddOption("--report-directory", + "define custom report pathname." + " (default: current working directory of Node.js process)", + &PerProcessOptions::report_directory, + kAllowedInEnvironment); + AddOption("--report-filename", + "define custom report file name." + " (default: YYYYMMDD.HHMMSS.PID.SEQUENCE#.txt)", + &PerProcessOptions::report_filename, + kAllowedInEnvironment); + AddOption("--report-on-fatalerror", + "generate diagnostic report on fatal (internal) errors", + &PerProcessOptions::report_on_fatalerror, + kAllowedInEnvironment); #ifdef NODE_HAVE_I18N_SUPPORT AddOption("--icu-data-dir", @@ -801,11 +737,23 @@ PerProcessOptionsParser::PerProcessOptionsParser( kAllowedInEnvironment); #endif #endif + AddOption("--use-largepages", + "Map the Node.js static code to large pages. Options are " + "'off' (the default value, meaning do not map), " + "'on' (map and ignore failure, reporting it to stderr), " + "or 'silent' (map and silently ignore failure)", + &PerProcessOptions::use_largepages, + kAllowedInEnvironment); // v12.x backwards compat flags removed in V8 7.9. AddOption("--fast_calls_with_arguments_mismatches", "", NoOp{}); AddOption("--harmony_numeric_separator", "", NoOp{}); + AddOption("--trace-sigint", + "enable printing JavaScript stacktrace on SIGINT", + &PerProcessOptions::trace_sigint, + kAllowedInEnvironment); + Insert(iop, &PerProcessOptions::get_per_isolate_options); } diff --git a/src/node_options.h b/src/node_options.h index 571ac305f9990c..be577703740548 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -152,9 +152,6 @@ class EnvironmentOptions : public Options { bool syntax_check_only = false; bool has_eval_string = false; -#ifdef NODE_REPORT - bool experimental_report = false; -#endif // NODE_REPORT bool experimental_wasi = false; std::string eval_string; bool print_eval = false; @@ -188,21 +185,23 @@ class PerIsolateOptions : public Options { std::shared_ptr per_env { new EnvironmentOptions() }; bool track_heap_objects = false; bool no_node_snapshot = false; - -#ifdef NODE_REPORT bool report_uncaught_exception = false; bool report_on_signal = false; - bool report_on_fatalerror = false; - std::string report_signal; - std::string report_filename; - std::string report_directory; -#endif // NODE_REPORT + std::string report_signal = "SIGUSR2"; inline EnvironmentOptions* get_per_env_options(); void CheckOptions(std::vector* errors) override; }; class PerProcessOptions : public Options { public: + // Options shouldn't be here unless they affect the entire process scope, and + // that should avoided when possible. + // + // When an option is used during process initialization, it does not need + // protection, but any use after that will likely require synchronization + // using the node::per_process::cli_options_mutex, typically: + // + // Mutex::ScopedLock lock(node::per_process::cli_options_mutex); std::shared_ptr per_isolate { new PerIsolateOptions() }; std::string title; @@ -212,6 +211,7 @@ class PerProcessOptions : public Options { int64_t v8_thread_pool_size = 4; bool zero_fill_all_buffers = false; bool debug_arraybuffer_allocations = false; + std::string disable_proto; std::vector security_reverts; bool print_bash_completion = false; @@ -223,7 +223,8 @@ class PerProcessOptions : public Options { std::string icu_data_dir; #endif - // TODO(addaleax): Some of these could probably be per-Environment. + // Per-process because they affect singleton OpenSSL shared library state, + // or are used once during process intialization. #if HAVE_OPENSSL std::string openssl_config; std::string tls_cipher_list = DEFAULT_CIPHER_LIST_CORE; @@ -240,9 +241,16 @@ class PerProcessOptions : public Options { #endif #endif -#ifdef NODE_REPORT + // Per-process because reports can be triggered outside a known V8 context. + bool report_on_fatalerror = false; + bool report_compact = false; + std::string report_directory; + std::string report_filename; + + // TODO(addaleax): Some of these could probably be per-Environment. + std::string use_largepages = "off"; + bool trace_sigint = false; std::vector cmdline; -#endif // NODE_REPORT inline PerIsolateOptions* get_per_isolate_options(); void CheckOptions(std::vector* errors) override; diff --git a/src/node_os.cc b/src/node_os.cc index 131e38055685c2..6d52c2e44d0aec 100644 --- a/src/node_os.cc +++ b/src/node_os.cc @@ -76,7 +76,7 @@ static void GetHostname(const FunctionCallbackInfo& args) { } -static void GetOSType(const FunctionCallbackInfo& args) { +static void GetOSInformation(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); uv_utsname_t info; int err = uv_os_uname(&info); @@ -87,26 +87,19 @@ static void GetOSType(const FunctionCallbackInfo& args) { return args.GetReturnValue().SetUndefined(); } - args.GetReturnValue().Set( - String::NewFromUtf8(env->isolate(), info.sysname, NewStringType::kNormal) - .ToLocalChecked()); -} - - -static void GetOSRelease(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - uv_utsname_t info; - int err = uv_os_uname(&info); - - if (err != 0) { - CHECK_GE(args.Length(), 1); - env->CollectUVExceptionInfo(args[args.Length() - 1], err, "uv_os_uname"); - return args.GetReturnValue().SetUndefined(); - } - - args.GetReturnValue().Set( - String::NewFromUtf8(env->isolate(), info.release, NewStringType::kNormal) - .ToLocalChecked()); + // [sysname, version, release] + Local osInformation[] = { + String::NewFromUtf8( + env->isolate(), info.sysname, NewStringType::kNormal).ToLocalChecked(), + String::NewFromUtf8( + env->isolate(), info.version, NewStringType::kNormal).ToLocalChecked(), + String::NewFromUtf8( + env->isolate(), info.release, NewStringType::kNormal).ToLocalChecked() + }; + + args.GetReturnValue().Set(Array::New(env->isolate(), + osInformation, + arraysize(osInformation))); } @@ -144,16 +137,12 @@ static void GetCPUInfo(const FunctionCallbackInfo& args) { static void GetFreeMemory(const FunctionCallbackInfo& args) { double amount = uv_get_free_memory(); - if (amount < 0) - return; args.GetReturnValue().Set(amount); } static void GetTotalMemory(const FunctionCallbackInfo& args) { double amount = uv_get_total_memory(); - if (amount < 0) - return; args.GetReturnValue().Set(amount); } @@ -209,7 +198,7 @@ static void GetInterfaceAddresses(const FunctionCallbackInfo& args) { // they name the interface from any input that uses UTF-8, which should be // the most frequent case by far these days.) name = String::NewFromUtf8(isolate, raw_name, - v8::NewStringType::kNormal).ToLocalChecked(); + NewStringType::kNormal).ToLocalChecked(); snprintf(mac.data(), mac.size(), @@ -269,7 +258,7 @@ static void GetHomeDirectory(const FunctionCallbackInfo& args) { Local home = String::NewFromUtf8(env->isolate(), buf, - v8::NewStringType::kNormal, + NewStringType::kNormal, len).ToLocalChecked(); args.GetReturnValue().Set(home); } @@ -398,8 +387,7 @@ void Initialize(Local target, env->SetMethod(target, "getTotalMem", GetTotalMemory); env->SetMethod(target, "getFreeMem", GetFreeMemory); env->SetMethod(target, "getCPUs", GetCPUInfo); - env->SetMethod(target, "getOSType", GetOSType); - env->SetMethod(target, "getOSRelease", GetOSRelease); + env->SetMethod(target, "getOSInformation", GetOSInformation); env->SetMethod(target, "getInterfaceAddresses", GetInterfaceAddresses); env->SetMethod(target, "getHomeDirectory", GetHomeDirectory); env->SetMethod(target, "getUserInfo", GetUserInfo); diff --git a/src/node_perf.cc b/src/node_perf.cc index 67eedf7b30032f..4b8bf2a8a7c913 100644 --- a/src/node_perf.cc +++ b/src/node_perf.cc @@ -249,6 +249,10 @@ void PerformanceGCCallback(Environment* env, env->kind_string(), Integer::New(env->isolate(), entry->gckind()), attr).Check(); + obj->DefineOwnProperty(context, + env->flags_string(), + Integer::New(env->isolate(), entry->gcflags()), + attr).Check(); PerformanceEntry::Notify(env, entry->kind(), obj); } } @@ -275,6 +279,7 @@ void MarkGarbageCollectionEnd(Isolate* isolate, auto entry = std::make_unique( env, static_cast(type), + static_cast(flags), state->performance_last_gc_start_mark, PERFORMANCE_NOW()); env->SetUnrefImmediate([entry = std::move(entry)](Environment* env) mutable { @@ -592,6 +597,21 @@ void Initialize(Local target, NODE_DEFINE_CONSTANT(constants, NODE_PERFORMANCE_GC_INCREMENTAL); NODE_DEFINE_CONSTANT(constants, NODE_PERFORMANCE_GC_WEAKCB); + NODE_DEFINE_CONSTANT( + constants, NODE_PERFORMANCE_GC_FLAGS_NO); + NODE_DEFINE_CONSTANT( + constants, NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED); + NODE_DEFINE_CONSTANT( + constants, NODE_PERFORMANCE_GC_FLAGS_FORCED); + NODE_DEFINE_CONSTANT( + constants, NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING); + NODE_DEFINE_CONSTANT( + constants, NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE); + NODE_DEFINE_CONSTANT( + constants, NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY); + NODE_DEFINE_CONSTANT( + constants, NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE); + #define V(name, _) \ NODE_DEFINE_HIDDEN_CONSTANT(constants, NODE_PERFORMANCE_ENTRY_TYPE_##name); NODE_PERFORMANCE_ENTRY_TYPES(V) @@ -625,7 +645,8 @@ void Initialize(Local target, Local eldh = env->NewFunctionTemplate(ELDHistogramNew); eldh->SetClassName(eldh_classname); - eldh->InstanceTemplate()->SetInternalFieldCount(1); + eldh->InstanceTemplate()->SetInternalFieldCount( + ELDHistogram::kInternalFieldCount); env->SetProtoMethod(eldh, "exceeds", ELDHistogramExceeds); env->SetProtoMethod(eldh, "min", ELDHistogramMin); env->SetProtoMethod(eldh, "max", ELDHistogramMax); diff --git a/src/node_perf.h b/src/node_perf.h index d7f593e5303542..a8a913bddeaad0 100644 --- a/src/node_perf.h +++ b/src/node_perf.h @@ -19,12 +19,6 @@ class Environment; namespace performance { -using v8::FunctionCallbackInfo; -using v8::GCType; -using v8::Local; -using v8::Object; -using v8::Value; - extern const uint64_t timeOrigin; static inline const char* GetPerformanceMilestoneName( @@ -59,9 +53,9 @@ class PerformanceEntry { public: static void Notify(Environment* env, PerformanceEntryType type, - Local object); + v8::Local object); - static void New(const FunctionCallbackInfo& args); + static void New(const v8::FunctionCallbackInfo& args); PerformanceEntry(Environment* env, const char* name, @@ -75,7 +69,7 @@ class PerformanceEntry { virtual ~PerformanceEntry() = default; - virtual v8::MaybeLocal ToObject() const; + virtual v8::MaybeLocal ToObject() const; Environment* env() const { return env_; } @@ -104,31 +98,52 @@ class PerformanceEntry { }; enum PerformanceGCKind { - NODE_PERFORMANCE_GC_MAJOR = GCType::kGCTypeMarkSweepCompact, - NODE_PERFORMANCE_GC_MINOR = GCType::kGCTypeScavenge, - NODE_PERFORMANCE_GC_INCREMENTAL = GCType::kGCTypeIncrementalMarking, - NODE_PERFORMANCE_GC_WEAKCB = GCType::kGCTypeProcessWeakCallbacks + NODE_PERFORMANCE_GC_MAJOR = v8::GCType::kGCTypeMarkSweepCompact, + NODE_PERFORMANCE_GC_MINOR = v8::GCType::kGCTypeScavenge, + NODE_PERFORMANCE_GC_INCREMENTAL = v8::GCType::kGCTypeIncrementalMarking, + NODE_PERFORMANCE_GC_WEAKCB = v8::GCType::kGCTypeProcessWeakCallbacks +}; + +enum PerformanceGCFlags { + NODE_PERFORMANCE_GC_FLAGS_NO = + v8::GCCallbackFlags::kNoGCCallbackFlags, + NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED = + v8::GCCallbackFlags::kGCCallbackFlagConstructRetainedObjectInfos, + NODE_PERFORMANCE_GC_FLAGS_FORCED = + v8::GCCallbackFlags::kGCCallbackFlagForced, + NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING = + v8::GCCallbackFlags::kGCCallbackFlagSynchronousPhantomCallbackProcessing, + NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE = + v8::GCCallbackFlags::kGCCallbackFlagCollectAllAvailableGarbage, + NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY = + v8::GCCallbackFlags::kGCCallbackFlagCollectAllExternalMemory, + NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE = + v8::GCCallbackFlags::kGCCallbackScheduleIdleGarbageCollection }; class GCPerformanceEntry : public PerformanceEntry { public: GCPerformanceEntry(Environment* env, PerformanceGCKind gckind, + PerformanceGCFlags gcflags, uint64_t startTime, uint64_t endTime) : PerformanceEntry(env, "gc", "gc", startTime, endTime), - gckind_(gckind) { } + gckind_(gckind), + gcflags_(gcflags) { } PerformanceGCKind gckind() const { return gckind_; } + PerformanceGCFlags gcflags() const { return gcflags_; } private: PerformanceGCKind gckind_; + PerformanceGCFlags gcflags_; }; class ELDHistogram : public HandleWrap, public Histogram { public: ELDHistogram(Environment* env, - Local wrap, + v8::Local wrap, int32_t resolution); bool RecordDelta(); diff --git a/src/node_platform.cc b/src/node_platform.cc index d3d68f12fab73a..3f6786d6dda162 100644 --- a/src/node_platform.cc +++ b/src/node_platform.cc @@ -10,7 +10,6 @@ namespace node { using v8::Isolate; -using v8::Local; using v8::Object; using v8::Platform; using v8::Task; @@ -223,7 +222,7 @@ int WorkerThreadsTaskRunner::NumberOfWorkerThreads() const { PerIsolatePlatformData::PerIsolatePlatformData( Isolate* isolate, uv_loop_t* loop) - : loop_(loop) { + : isolate_(isolate), loop_(loop) { flush_tasks_ = new uv_async_t(); CHECK_EQ(0, uv_async_init(loop, flush_tasks_, FlushTasks)); flush_tasks_->data = static_cast(this); @@ -373,12 +372,12 @@ int NodePlatform::NumberOfWorkerThreads() { } void PerIsolatePlatformData::RunForegroundTask(std::unique_ptr task) { - Isolate* isolate = Isolate::GetCurrent(); - DebugSealHandleScope scope(isolate); - Environment* env = Environment::GetCurrent(isolate); + DebugSealHandleScope scope(isolate_); + Environment* env = Environment::GetCurrent(isolate_); if (env != nullptr) { - InternalCallbackScope cb_scope(env, Local(), { 0, 0 }, - InternalCallbackScope::kAllowEmptyResource); + v8::HandleScope scope(isolate_); + InternalCallbackScope cb_scope(env, Object::New(isolate_), { 0, 0 }, + InternalCallbackScope::kNoFlags); task->Run(); } else { task->Run(); @@ -396,8 +395,8 @@ void PerIsolatePlatformData::DeleteFromScheduledTasks(DelayedTask* task) { } void PerIsolatePlatformData::RunForegroundTask(uv_timer_t* handle) { - DelayedTask* delayed = static_cast(handle->data); - RunForegroundTask(std::move(delayed->task)); + DelayedTask* delayed = ContainerOf(&DelayedTask::timer, handle); + delayed->platform_data->RunForegroundTask(std::move(delayed->task)); delayed->platform_data->DeleteFromScheduledTasks(delayed); } diff --git a/src/node_platform.h b/src/node_platform.h index bebd61b0c22644..533ae1bcca8248 100644 --- a/src/node_platform.h +++ b/src/node_platform.h @@ -86,7 +86,7 @@ class PerIsolatePlatformData : void DecreaseHandleCount(); static void FlushTasks(uv_async_t* handle); - static void RunForegroundTask(std::unique_ptr task); + void RunForegroundTask(std::unique_ptr task); static void RunForegroundTask(uv_timer_t* timer); struct ShutdownCallback { @@ -99,6 +99,7 @@ class PerIsolatePlatformData : std::shared_ptr self_reference_; uint32_t uv_handle_count_ = 1; // 1 = flush_tasks_ + v8::Isolate* const isolate_; uv_loop_t* const loop_; uv_async_t* flush_tasks_ = nullptr; TaskQueue foreground_tasks_; diff --git a/src/node_process_methods.cc b/src/node_process_methods.cc index ee17f28f1f4b0c..15e2e1b39b67c4 100644 --- a/src/node_process_methods.cc +++ b/src/node_process_methods.cc @@ -193,10 +193,13 @@ static void MemoryUsage(const FunctionCallbackInfo& args) { HeapStatistics v8_heap_stats; isolate->GetHeapStatistics(&v8_heap_stats); + NodeArrayBufferAllocator* array_buffer_allocator = + env->isolate_data()->node_allocator(); + // Get the double array pointer from the Float64Array argument. CHECK(args[0]->IsFloat64Array()); Local array = args[0].As(); - CHECK_EQ(array->Length(), 4); + CHECK_EQ(array->Length(), 5); Local ab = array->Buffer(); double* fields = static_cast(ab->GetContents().Data()); @@ -204,6 +207,8 @@ static void MemoryUsage(const FunctionCallbackInfo& args) { fields[1] = v8_heap_stats.total_heap_size(); fields[2] = v8_heap_stats.used_heap_size(); fields[3] = v8_heap_stats.external_memory(); + fields[4] = array_buffer_allocator == nullptr ? + 0 : array_buffer_allocator->total_mem_usage(); } void RawDebug(const FunctionCallbackInfo& args) { diff --git a/src/node_report.cc b/src/node_report.cc index c29f866f4a8dad..98da24c9567a28 100644 --- a/src/node_report.cc +++ b/src/node_report.cc @@ -1,4 +1,5 @@ #include "env-inl.h" +#include "json_utils.h" #include "node_report.h" #include "debug_utils-inl.h" #include "diagnosticfilename-inl.h" @@ -16,6 +17,7 @@ #include #endif +#include #include #include #include @@ -30,9 +32,9 @@ using node::arraysize; using node::ConditionVariable; using node::DiagnosticFilename; using node::Environment; +using node::JSONWriter; using node::Mutex; using node::NativeSymbolDebuggingContext; -using node::PerIsolateOptions; using node::TIME_TYPE; using node::worker::Worker; using v8::HeapSpaceStatistics; @@ -45,6 +47,8 @@ using v8::String; using v8::V8; using v8::Value; +namespace per_process = node::per_process; + // Internal/static function declarations static void WriteNodeReport(Isolate* isolate, Environment* env, @@ -52,7 +56,8 @@ static void WriteNodeReport(Isolate* isolate, const char* trigger, const std::string& filename, std::ostream& out, - Local stackstr); + Local stackstr, + bool compact); static void PrintVersionInformation(JSONWriter* writer); static void PrintJavaScriptStack(JSONWriter* writer, Isolate* isolate, @@ -69,8 +74,6 @@ static void PrintCpuInfo(JSONWriter* writer); static void PrintNetworkInterfaceInfo(JSONWriter* writer); // External function to trigger a report, writing to file. -// The 'name' parameter is in/out: an input filename is used -// if supplied, and the actual filename is returned. std::string TriggerNodeReport(Isolate* isolate, Environment* env, const char* message, @@ -78,20 +81,25 @@ std::string TriggerNodeReport(Isolate* isolate, const std::string& name, Local stackstr) { std::string filename; - std::shared_ptr options; - if (env != nullptr) options = env->isolate_data()->options(); // Determine the required report filename. In order of priority: // 1) supplied on API 2) configured on startup 3) default generated if (!name.empty()) { // Filename was specified as API parameter. filename = name; - } else if (env != nullptr && options->report_filename.length() > 0) { - // File name was supplied via start-up option. - filename = options->report_filename; } else { - filename = *DiagnosticFilename(env != nullptr ? env->thread_id() : 0, - "report", "json"); + std::string report_filename; + { + Mutex::ScopedLock lock(per_process::cli_options_mutex); + report_filename = per_process::cli_options->report_filename; + } + if (report_filename.length() > 0) { + // File name was supplied via start-up option. + filename = report_filename; + } else { + filename = *DiagnosticFilename(env != nullptr ? env->thread_id() : 0, + "report", "json"); + } } // Open the report file stream for writing. Supports stdout/err, @@ -103,9 +111,14 @@ std::string TriggerNodeReport(Isolate* isolate, } else if (filename == "stderr") { outstream = &std::cerr; } else { + std::string report_directory; + { + Mutex::ScopedLock lock(per_process::cli_options_mutex); + report_directory = per_process::cli_options->report_directory; + } // Regular file. Append filename to directory path if one was specified - if (env != nullptr && options->report_directory.length() > 0) { - std::string pathname = options->report_directory; + if (report_directory.length() > 0) { + std::string pathname = report_directory; pathname += node::kPathSeparator; pathname += filename; outfile.open(pathname, std::ios::out | std::ios::binary); @@ -116,8 +129,8 @@ std::string TriggerNodeReport(Isolate* isolate, if (!outfile.is_open()) { std::cerr << "\nFailed to open Node.js report file: " << filename; - if (env != nullptr && options->report_directory.length() > 0) - std::cerr << " directory: " << options->report_directory; + if (report_directory.length() > 0) + std::cerr << " directory: " << report_directory; std::cerr << " (errno: " << errno << ")" << std::endl; return ""; @@ -126,15 +139,23 @@ std::string TriggerNodeReport(Isolate* isolate, std::cerr << "\nWriting Node.js report to file: " << filename; } + bool compact; + { + Mutex::ScopedLock lock(per_process::cli_options_mutex); + compact = per_process::cli_options->report_compact; + } WriteNodeReport(isolate, env, message, trigger, filename, *outstream, - stackstr); + stackstr, compact); // Do not close stdout/stderr, only close files we opened. if (outfile.is_open()) { outfile.close(); } - std::cerr << "\nNode.js report completed" << std::endl; + // Do not mix JSON and free-form text on stderr. + if (filename != "stderr") { + std::cerr << "\nNode.js report completed" << std::endl; + } return filename; } @@ -145,7 +166,7 @@ void GetNodeReport(Isolate* isolate, const char* trigger, Local stackstr, std::ostream& out) { - WriteNodeReport(isolate, env, message, trigger, "", out, stackstr); + WriteNodeReport(isolate, env, message, trigger, "", out, stackstr, false); } // Internal function to coordinate and write the various @@ -156,7 +177,8 @@ static void WriteNodeReport(Isolate* isolate, const char* trigger, const std::string& filename, std::ostream& out, - Local stackstr) { + Local stackstr, + bool compact) { // Obtain the current time and the pid. TIME_TYPE tm_struct; DiagnosticFilename::LocalTime(&tm_struct); @@ -169,7 +191,7 @@ static void WriteNodeReport(Isolate* isolate, // File stream opened OK, now start printing the report content: // the title and header information (event, filename, timestamp and pid) - JSONWriter writer(out); + JSONWriter writer(out, compact); writer.json_start(); writer.json_objectstart("header"); writer.json_keyvalue("reportVersion", NODE_REPORT_VERSION); diff --git a/src/node_report.h b/src/node_report.h index 46b69b9681db51..98490784dd6e70 100644 --- a/src/node_report.h +++ b/src/node_report.h @@ -3,7 +3,6 @@ #include "node.h" #include "node_buffer.h" #include "uv.h" -#include "v8.h" #include "util.h" #ifndef _WIN32 @@ -11,19 +10,7 @@ #include #endif -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include namespace report { @@ -43,8 +30,6 @@ void GetNodeReport(v8::Isolate* isolate, // Function declarations - utility functions in src/node_report_utils.cc void WalkHandle(uv_handle_t* h, void* arg); -std::string EscapeJsonChars(const std::string& str); -std::string Reindent(const std::string& str, int indentation); template std::string ValueToHexString(T value) { @@ -59,126 +44,4 @@ std::string ValueToHexString(T value) { void WriteReport(const v8::FunctionCallbackInfo& info); void GetReport(const v8::FunctionCallbackInfo& info); -// Node.js boot time - defined in src/node.cc -extern double prog_start_time; - -// JSON compiler definitions. -class JSONWriter { - public: - explicit JSONWriter(std::ostream& out) : out_(out) {} - - inline void indent() { indent_ += 2; } - inline void deindent() { indent_ -= 2; } - inline void advance() { - for (int i = 0; i < indent_; i++) out_ << ' '; - } - - inline void json_start() { - if (state_ == kAfterValue) out_ << ','; - out_ << '\n'; - advance(); - out_ << '{'; - indent(); - state_ = kObjectStart; - } - - inline void json_end() { - out_ << '\n'; - deindent(); - advance(); - out_ << '}'; - state_ = kAfterValue; - } - template - inline void json_objectstart(T key) { - if (state_ == kAfterValue) out_ << ','; - out_ << '\n'; - advance(); - write_string(key); - out_ << ": {"; - indent(); - state_ = kObjectStart; - } - - template - inline void json_arraystart(T key) { - if (state_ == kAfterValue) out_ << ','; - out_ << '\n'; - advance(); - write_string(key); - out_ << ": ["; - indent(); - state_ = kObjectStart; - } - inline void json_objectend() { - out_ << '\n'; - deindent(); - advance(); - out_ << '}'; - state_ = kAfterValue; - } - - inline void json_arrayend() { - out_ << '\n'; - deindent(); - advance(); - out_ << ']'; - state_ = kAfterValue; - } - template - inline void json_keyvalue(const T& key, const U& value) { - if (state_ == kAfterValue) out_ << ','; - out_ << '\n'; - advance(); - write_string(key); - out_ << ": "; - write_value(value); - state_ = kAfterValue; - } - - template - inline void json_element(const U& value) { - if (state_ == kAfterValue) out_ << ','; - out_ << '\n'; - advance(); - write_value(value); - state_ = kAfterValue; - } - - struct Null {}; // Usable as a JSON value. - - struct ForeignJSON { - std::string as_string; - }; - - private: - template ::is_specialized, bool>::type> - inline void write_value(T number) { - if (std::is_same::value) - out_ << (number ? "true" : "false"); - else - out_ << number; - } - - inline void write_value(Null null) { out_ << "null"; } - inline void write_value(const char* str) { write_string(str); } - inline void write_value(const std::string& str) { write_string(str); } - - inline void write_value(const ForeignJSON& json) { - out_ << Reindent(json.as_string, indent_); - } - - inline void write_string(const std::string& str) { - out_ << '"' << EscapeJsonChars(str) << '"'; - } - inline void write_string(const char* str) { write_string(std::string(str)); } - - enum JSONState { kObjectStart, kAfterValue }; - std::ostream& out_; - int indent_ = 0; - int state_ = kObjectStart; -}; - } // namespace report diff --git a/src/node_report_module.cc b/src/node_report_module.cc index f35d23a06e3232..700dd88aba645e 100644 --- a/src/node_report_module.cc +++ b/src/node_report_module.cc @@ -16,6 +16,7 @@ namespace report { using node::Environment; +using node::Mutex; using node::Utf8Value; using v8::Boolean; using v8::Context; @@ -68,9 +69,23 @@ void GetReport(const FunctionCallbackInfo& info) { .ToLocalChecked()); } +static void GetCompact(const FunctionCallbackInfo& info) { + node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex); + info.GetReturnValue().Set(node::per_process::cli_options->report_compact); +} + +static void SetCompact(const FunctionCallbackInfo& info) { + node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex); + Environment* env = Environment::GetCurrent(info); + Isolate* isolate = env->isolate(); + bool compact = info[0]->ToBoolean(isolate)->Value(); + node::per_process::cli_options->report_compact = compact; +} + static void GetDirectory(const FunctionCallbackInfo& info) { + node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex); Environment* env = Environment::GetCurrent(info); - std::string directory = env->isolate_data()->options()->report_directory; + std::string directory = node::per_process::cli_options->report_directory; auto result = String::NewFromUtf8(env->isolate(), directory.c_str(), v8::NewStringType::kNormal); @@ -78,15 +93,17 @@ static void GetDirectory(const FunctionCallbackInfo& info) { } static void SetDirectory(const FunctionCallbackInfo& info) { + node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex); Environment* env = Environment::GetCurrent(info); CHECK(info[0]->IsString()); Utf8Value dir(env->isolate(), info[0].As()); - env->isolate_data()->options()->report_directory = *dir; + node::per_process::cli_options->report_directory = *dir; } static void GetFilename(const FunctionCallbackInfo& info) { + node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex); Environment* env = Environment::GetCurrent(info); - std::string filename = env->isolate_data()->options()->report_filename; + std::string filename = node::per_process::cli_options->report_filename; auto result = String::NewFromUtf8(env->isolate(), filename.c_str(), v8::NewStringType::kNormal); @@ -94,10 +111,11 @@ static void GetFilename(const FunctionCallbackInfo& info) { } static void SetFilename(const FunctionCallbackInfo& info) { + node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex); Environment* env = Environment::GetCurrent(info); CHECK(info[0]->IsString()); Utf8Value name(env->isolate(), info[0].As()); - env->isolate_data()->options()->report_filename = *name; + node::per_process::cli_options->report_filename = *name; } static void GetSignal(const FunctionCallbackInfo& info) { @@ -117,15 +135,15 @@ static void SetSignal(const FunctionCallbackInfo& info) { } static void ShouldReportOnFatalError(const FunctionCallbackInfo& info) { - Environment* env = Environment::GetCurrent(info); + Mutex::ScopedLock lock(node::per_process::cli_options_mutex); info.GetReturnValue().Set( - env->isolate_data()->options()->report_on_fatalerror); + node::per_process::cli_options->report_on_fatalerror); } static void SetReportOnFatalError(const FunctionCallbackInfo& info) { - Environment* env = Environment::GetCurrent(info); CHECK(info[0]->IsBoolean()); - env->isolate_data()->options()->report_on_fatalerror = info[0]->IsTrue(); + Mutex::ScopedLock lock(node::per_process::cli_options_mutex); + node::per_process::cli_options->report_on_fatalerror = info[0]->IsTrue(); } static void ShouldReportOnSignal(const FunctionCallbackInfo& info) { @@ -161,6 +179,8 @@ static void Initialize(Local exports, env->SetMethod(exports, "writeReport", WriteReport); env->SetMethod(exports, "getReport", GetReport); + env->SetMethod(exports, "getCompact", GetCompact); + env->SetMethod(exports, "setCompact", SetCompact); env->SetMethod(exports, "getDirectory", GetDirectory); env->SetMethod(exports, "setDirectory", SetDirectory); env->SetMethod(exports, "getFilename", GetFilename); diff --git a/src/node_report_utils.cc b/src/node_report_utils.cc index efa15790b9bc96..abbf6d529d0ef7 100644 --- a/src/node_report_utils.cc +++ b/src/node_report_utils.cc @@ -1,9 +1,11 @@ +#include "json_utils.h" #include "node_internals.h" #include "node_report.h" #include "util-inl.h" namespace report { +using node::JSONWriter; using node::MallocedBuffer; static constexpr auto null = JSONWriter::Null{}; @@ -225,66 +227,4 @@ void WalkHandle(uv_handle_t* h, void* arg) { writer->json_end(); } -std::string EscapeJsonChars(const std::string& str) { - const std::string control_symbols[0x20] = { - "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", - "\\u0006", "\\u0007", "\\b", "\\t", "\\n", "\\v", "\\f", "\\r", - "\\u000e", "\\u000f", "\\u0010", "\\u0011", "\\u0012", "\\u0013", - "\\u0014", "\\u0015", "\\u0016", "\\u0017", "\\u0018", "\\u0019", - "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f" - }; - - std::string ret; - size_t last_pos = 0; - size_t pos = 0; - for (; pos < str.size(); ++pos) { - std::string replace; - char ch = str[pos]; - if (ch == '\\') { - replace = "\\\\"; - } else if (ch == '\"') { - replace = "\\\""; - } else { - size_t num = static_cast(ch); - if (num < 0x20) replace = control_symbols[num]; - } - if (!replace.empty()) { - if (pos > last_pos) { - ret += str.substr(last_pos, pos - last_pos); - } - last_pos = pos + 1; - ret += replace; - } - } - // Append any remaining symbols. - if (last_pos < str.size()) { - ret += str.substr(last_pos, pos - last_pos); - } - return ret; -} - -std::string Reindent(const std::string& str, int indent_depth) { - std::string indent; - for (int i = 0; i < indent_depth; i++) indent += ' '; - - std::string out; - std::string::size_type pos = 0; - do { - std::string::size_type prev_pos = pos; - pos = str.find('\n', pos); - - out.append(indent); - - if (pos == std::string::npos) { - out.append(str, prev_pos, std::string::npos); - break; - } else { - pos++; - out.append(str, prev_pos, pos - prev_pos); - } - } while (true); - - return out; -} - } // namespace report diff --git a/src/node_serdes.cc b/src/node_serdes.cc index a2d185c4167a75..bcdcd19b261e88 100644 --- a/src/node_serdes.cc +++ b/src/node_serdes.cc @@ -451,7 +451,8 @@ void Initialize(Local target, Local ser = env->NewFunctionTemplate(SerializerContext::New); - ser->InstanceTemplate()->SetInternalFieldCount(1); + ser->InstanceTemplate()->SetInternalFieldCount( + SerializerContext::kInternalFieldCount); env->SetProtoMethod(ser, "writeHeader", SerializerContext::WriteHeader); env->SetProtoMethod(ser, "writeValue", SerializerContext::WriteValue); @@ -477,7 +478,8 @@ void Initialize(Local target, Local des = env->NewFunctionTemplate(DeserializerContext::New); - des->InstanceTemplate()->SetInternalFieldCount(1); + des->InstanceTemplate()->SetInternalFieldCount( + DeserializerContext::kInternalFieldCount); env->SetProtoMethod(des, "readHeader", DeserializerContext::ReadHeader); env->SetProtoMethod(des, "readValue", DeserializerContext::ReadValue); diff --git a/src/node_sockaddr-inl.h b/src/node_sockaddr-inl.h new file mode 100644 index 00000000000000..a9d0ed061a126c --- /dev/null +++ b/src/node_sockaddr-inl.h @@ -0,0 +1,170 @@ +#ifndef SRC_NODE_SOCKADDR_INL_H_ +#define SRC_NODE_SOCKADDR_INL_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "node.h" +#include "node_internals.h" +#include "node_sockaddr.h" +#include "util-inl.h" + +#include + +namespace node { + +static constexpr uint32_t kLabelMask = 0xFFFFF; + +inline void hash_combine(size_t* seed) { } + +template +inline void hash_combine(size_t* seed, const T& value, Args... rest) { + *seed ^= std::hash{}(value) + 0x9e3779b9 + (*seed << 6) + (*seed >> 2); + hash_combine(seed, rest...); +} + +bool SocketAddress::is_numeric_host(const char* hostname) { + return is_numeric_host(hostname, AF_INET) || + is_numeric_host(hostname, AF_INET6); +} + +bool SocketAddress::is_numeric_host(const char* hostname, int family) { + in6_addr dst; + return inet_pton(family, hostname, &dst) == 1; +} + +int SocketAddress::GetPort(const sockaddr* addr) { + CHECK(addr->sa_family == AF_INET || addr->sa_family == AF_INET6); + return ntohs(addr->sa_family == AF_INET ? + reinterpret_cast(addr)->sin_port : + reinterpret_cast(addr)->sin6_port); +} + +int SocketAddress::GetPort(const sockaddr_storage* addr) { + return GetPort(reinterpret_cast(addr)); +} + +std::string SocketAddress::GetAddress(const sockaddr* addr) { + CHECK(addr->sa_family == AF_INET || addr->sa_family == AF_INET6); + char host[INET6_ADDRSTRLEN]; + const void* src = addr->sa_family == AF_INET ? + static_cast( + &(reinterpret_cast(addr)->sin_addr)) : + static_cast( + &(reinterpret_cast(addr)->sin6_addr)); + uv_inet_ntop(addr->sa_family, src, host, INET6_ADDRSTRLEN); + return std::string(host); +} + +std::string SocketAddress::GetAddress(const sockaddr_storage* addr) { + return GetAddress(reinterpret_cast(addr)); +} + +size_t SocketAddress::GetLength(const sockaddr* addr) { + return addr->sa_family == AF_INET ? + sizeof(sockaddr_in) : sizeof(sockaddr_in6); +} + +size_t SocketAddress::GetLength(const sockaddr_storage* addr) { + return GetLength(reinterpret_cast(addr)); +} + +SocketAddress::SocketAddress(const sockaddr* addr) { + memcpy(&address_, addr, GetLength(addr)); +} + +SocketAddress::SocketAddress(const SocketAddress& addr) { + memcpy(&address_, &addr.address_, addr.length()); +} + +SocketAddress& SocketAddress::operator=(const sockaddr* addr) { + memcpy(&address_, addr, GetLength(addr)); + return *this; +} + +SocketAddress& SocketAddress::operator=(const SocketAddress& addr) { + memcpy(&address_, &addr.address_, addr.length()); + return *this; +} + +const sockaddr& SocketAddress::operator*() const { + return *this->data(); +} + +const sockaddr* SocketAddress::operator->() const { + return this->data(); +} + +size_t SocketAddress::length() const { + return GetLength(&address_); +} + +const sockaddr* SocketAddress::data() const { + return reinterpret_cast(&address_); +} + +const uint8_t* SocketAddress::raw() const { + return reinterpret_cast(&address_); +} + +sockaddr* SocketAddress::storage() { + return reinterpret_cast(&address_); +} + +int SocketAddress::family() const { + return address_.ss_family; +} + +std::string SocketAddress::address() const { + return GetAddress(&address_); +} + +int SocketAddress::port() const { + return GetPort(&address_); +} + +uint32_t SocketAddress::flow_label() const { + if (family() != AF_INET6) + return 0; + const sockaddr_in6* in = reinterpret_cast(data()); + return in->sin6_flowinfo; +} + +void SocketAddress::set_flow_label(uint32_t label) { + if (family() != AF_INET6) + return; + CHECK_LE(label, kLabelMask); + sockaddr_in6* in = reinterpret_cast(&address_); + in->sin6_flowinfo = label; +} + +std::string SocketAddress::ToString() const { + if (family() != AF_INET && family() != AF_INET6) return ""; + return (family() == AF_INET6 ? + std::string("[") + address() + "]:" : + address() + ":") + + std::to_string(port()); +} + +void SocketAddress::Update(uint8_t* data, size_t len) { + CHECK_LE(len, sizeof(address_)); + memcpy(&address_, data, len); +} + +v8::Local SocketAddress::ToJS( + Environment* env, + v8::Local info) const { + return AddressToJS(env, data(), info); +} + +bool SocketAddress::operator==(const SocketAddress& other) const { + if (family() != other.family()) return false; + return memcmp(raw(), other.raw(), length()) == 0; +} + +bool SocketAddress::operator!=(const SocketAddress& other) const { + return !(*this == other); +} +} // namespace node + +#endif // NODE_WANT_INTERNALS +#endif // SRC_NODE_SOCKADDR_INL_H_ diff --git a/src/node_sockaddr.cc b/src/node_sockaddr.cc new file mode 100644 index 00000000000000..74fe123529abbd --- /dev/null +++ b/src/node_sockaddr.cc @@ -0,0 +1,95 @@ +#include "node_sockaddr-inl.h" // NOLINT(build/include) +#include "uv.h" + +namespace node { + +namespace { +template +SocketAddress FromUVHandle(F fn, const T& handle) { + SocketAddress addr; + int len = sizeof(sockaddr_storage); + if (fn(&handle, addr.storage(), &len) == 0) + CHECK_EQ(static_cast(len), addr.length()); + else + addr.storage()->sa_family = 0; + return addr; +} +} // namespace + +bool SocketAddress::ToSockAddr( + int32_t family, + const char* host, + uint32_t port, + sockaddr_storage* addr) { + switch (family) { + case AF_INET: + return uv_ip4_addr( + host, + port, + reinterpret_cast(addr)) == 0; + case AF_INET6: + return uv_ip6_addr( + host, + port, + reinterpret_cast(addr)) == 0; + default: + UNREACHABLE(); + } +} + +bool SocketAddress::New( + const char* host, + uint32_t port, + SocketAddress* addr) { + return New(AF_INET, host, port, addr) || New(AF_INET6, host, port, addr); +} + +bool SocketAddress::New( + int32_t family, + const char* host, + uint32_t port, + SocketAddress* addr) { + return ToSockAddr(family, host, port, + reinterpret_cast(addr->storage())); +} + +size_t SocketAddress::Hash::operator()(const SocketAddress& addr) const { + size_t hash = 0; + switch (addr.family()) { + case AF_INET: { + const sockaddr_in* ipv4 = + reinterpret_cast(addr.raw()); + hash_combine(&hash, ipv4->sin_port, ipv4->sin_addr.s_addr); + break; + } + case AF_INET6: { + const sockaddr_in6* ipv6 = + reinterpret_cast(addr.raw()); + const uint64_t* a = + reinterpret_cast(&ipv6->sin6_addr); + hash_combine(&hash, ipv6->sin6_port, a[0], a[1]); + break; + } + default: + UNREACHABLE(); + } + return hash; +} + +SocketAddress SocketAddress::FromSockName(const uv_tcp_t& handle) { + return FromUVHandle(uv_tcp_getsockname, handle); +} + +SocketAddress SocketAddress::FromSockName(const uv_udp_t& handle) { + return FromUVHandle(uv_udp_getsockname, handle); +} + +SocketAddress SocketAddress::FromPeerName(const uv_tcp_t& handle) { + return FromUVHandle(uv_tcp_getpeername, handle); +} + +SocketAddress SocketAddress::FromPeerName(const uv_udp_t& handle) { + return FromUVHandle(uv_udp_getpeername, handle); +} + +} // namespace node diff --git a/src/node_sockaddr.h b/src/node_sockaddr.h new file mode 100644 index 00000000000000..c0d006a4d6e681 --- /dev/null +++ b/src/node_sockaddr.h @@ -0,0 +1,123 @@ +#ifndef SRC_NODE_SOCKADDR_H_ +#define SRC_NODE_SOCKADDR_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "memory_tracker.h" +#include "node.h" +#include "uv.h" +#include "v8.h" + +#include +#include + +namespace node { + +class Environment; + +class SocketAddress : public MemoryRetainer { + public: + struct Hash { + size_t operator()(const SocketAddress& addr) const; + }; + + inline bool operator==(const SocketAddress& other) const; + inline bool operator!=(const SocketAddress& other) const; + + inline static bool is_numeric_host(const char* hostname); + inline static bool is_numeric_host(const char* hostname, int family); + + // Returns true if converting {family, host, port} to *addr succeeded. + static bool ToSockAddr( + int32_t family, + const char* host, + uint32_t port, + sockaddr_storage* addr); + + // Returns true if converting {family, host, port} to *addr succeeded. + static bool New( + int32_t family, + const char* host, + uint32_t port, + SocketAddress* addr); + + static bool New( + const char* host, + uint32_t port, + SocketAddress* addr); + + // Returns the port for an IPv4 or IPv6 address. + inline static int GetPort(const sockaddr* addr); + inline static int GetPort(const sockaddr_storage* addr); + + // Returns the numeric host as a string for an IPv4 or IPv6 address. + inline static std::string GetAddress(const sockaddr* addr); + inline static std::string GetAddress(const sockaddr_storage* addr); + + // Returns the struct length for an IPv4, IPv6 or UNIX domain. + inline static size_t GetLength(const sockaddr* addr); + inline static size_t GetLength(const sockaddr_storage* addr); + + SocketAddress() = default; + + inline explicit SocketAddress(const sockaddr* addr); + inline SocketAddress(const SocketAddress& addr); + inline SocketAddress& operator=(const sockaddr* other); + inline SocketAddress& operator=(const SocketAddress& other); + + inline const sockaddr& operator*() const; + inline const sockaddr* operator->() const; + + inline const sockaddr* data() const; + inline const uint8_t* raw() const; + inline sockaddr* storage(); + inline size_t length() const; + + inline int family() const; + inline std::string address() const; + inline int port() const; + + // If the SocketAddress is an IPv6 address, returns the + // current value of the IPv6 flow label, if set. Otherwise + // returns 0. + inline uint32_t flow_label() const; + + // If the SocketAddress is an IPv6 address, sets the + // current value of the IPv6 flow label. If not an + // IPv6 address, set_flow_label is a non-op. It + // is important to note that the flow label, + // while represented as an uint32_t, the flow + // label is strictly limited to 20 bits, and + // this will assert if any value larger than + // 20-bits is specified. + inline void set_flow_label(uint32_t label = 0); + + inline void Update(uint8_t* data, size_t len); + + static SocketAddress FromSockName(const uv_udp_t& handle); + static SocketAddress FromSockName(const uv_tcp_t& handle); + static SocketAddress FromPeerName(const uv_udp_t& handle); + static SocketAddress FromPeerName(const uv_tcp_t& handle); + + inline v8::Local ToJS( + Environment* env, + v8::Local obj = v8::Local()) const; + + inline std::string ToString() const; + + SET_NO_MEMORY_INFO() + SET_MEMORY_INFO_NAME(SocketAddress) + SET_SELF_SIZE(SocketAddress) + + template + using Map = std::unordered_map; + + private: + sockaddr_storage address_; +}; + +} // namespace node + +#endif // NOE_WANT_INTERNALS + +#endif // SRC_NODE_SOCKADDR_H_ diff --git a/src/node_stat_watcher.cc b/src/node_stat_watcher.cc index 0d67eceed54931..05c540bbff17cc 100644 --- a/src/node_stat_watcher.cc +++ b/src/node_stat_watcher.cc @@ -47,7 +47,8 @@ void StatWatcher::Initialize(Environment* env, Local target) { HandleScope scope(env->isolate()); Local t = env->NewFunctionTemplate(StatWatcher::New); - t->InstanceTemplate()->SetInternalFieldCount(1); + t->InstanceTemplate()->SetInternalFieldCount( + StatWatcher::kInternalFieldCount); Local statWatcherString = FIXED_ONE_BYTE_STRING(env->isolate(), "StatWatcher"); t->SetClassName(statWatcherString); diff --git a/src/node_task_queue.cc b/src/node_task_queue.cc index f418a272470e2b..3c7d9bae0884c5 100644 --- a/src/node_task_queue.cc +++ b/src/node_task_queue.cc @@ -11,7 +11,6 @@ namespace node { using errors::TryCatchScope; -using v8::Array; using v8::Context; using v8::Function; using v8::FunctionCallbackInfo; @@ -21,7 +20,6 @@ using v8::kPromiseRejectAfterResolved; using v8::kPromiseRejectWithNoHandler; using v8::kPromiseResolveAfterResolved; using v8::Local; -using v8::Message; using v8::MicrotasksScope; using v8::Number; using v8::Object; diff --git a/src/node_trace_events.cc b/src/node_trace_events.cc index f5852076b4ec68..9adee9e458ccc0 100644 --- a/src/node_trace_events.cc +++ b/src/node_trace_events.cc @@ -129,7 +129,8 @@ void NodeCategorySet::Initialize(Local target, Local category_set = env->NewFunctionTemplate(NodeCategorySet::New); - category_set->InstanceTemplate()->SetInternalFieldCount(1); + category_set->InstanceTemplate()->SetInternalFieldCount( + NodeCategorySet::kInternalFieldCount); env->SetProtoMethod(category_set, "enable", NodeCategorySet::Enable); env->SetProtoMethod(category_set, "disable", NodeCategorySet::Disable); diff --git a/src/node_util.cc b/src/node_util.cc index e0ef7d421ff24a..db9b8ec8d65f51 100644 --- a/src/node_util.cc +++ b/src/node_util.cc @@ -323,7 +323,8 @@ void Initialize(Local target, FIXED_ONE_BYTE_STRING(env->isolate(), "WeakReference"); Local weak_ref = env->NewFunctionTemplate(WeakReference::New); - weak_ref->InstanceTemplate()->SetInternalFieldCount(1); + weak_ref->InstanceTemplate()->SetInternalFieldCount( + WeakReference::kInternalFieldCount); weak_ref->SetClassName(weak_ref_string); env->SetProtoMethod(weak_ref, "get", WeakReference::Get); env->SetProtoMethod(weak_ref, "incRef", WeakReference::IncRef); diff --git a/src/node_version.h b/src/node_version.h index ab9c0ce0e9b3cb..fe913ca803f9ce 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -23,13 +23,13 @@ #define SRC_NODE_VERSION_H_ #define NODE_MAJOR_VERSION 12 -#define NODE_MINOR_VERSION 16 -#define NODE_PATCH_VERSION 4 +#define NODE_MINOR_VERSION 17 +#define NODE_PATCH_VERSION 0 #define NODE_VERSION_IS_LTS 1 #define NODE_VERSION_LTS_CODENAME "Erbium" -#define NODE_VERSION_IS_RELEASE 0 +#define NODE_VERSION_IS_RELEASE 1 #ifndef NODE_STRINGIFY #define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n) @@ -93,6 +93,6 @@ // The NAPI_VERSION provided by this version of the runtime. This is the version // which the Node binary being built supports. -#define NAPI_VERSION 5 +#define NAPI_VERSION 6 #endif // SRC_NODE_VERSION_H_ diff --git a/src/node_wasi.cc b/src/node_wasi.cc index ab4dd69b823300..a2f0cbced5ed0c 100644 --- a/src/node_wasi.cc +++ b/src/node_wasi.cc @@ -235,7 +235,7 @@ void WASI::New(const FunctionCallbackInfo& args) { free(options.preopens[i].real_path); } - delete[] options.preopens; + free(options.preopens); } } @@ -1812,7 +1812,7 @@ static void Initialize(Local target, Local tmpl = env->NewFunctionTemplate(WASI::New); auto wasi_wrap_string = FIXED_ONE_BYTE_STRING(env->isolate(), "WASI"); - tmpl->InstanceTemplate()->SetInternalFieldCount(1); + tmpl->InstanceTemplate()->SetInternalFieldCount(WASI::kInternalFieldCount); tmpl->SetClassName(wasi_wrap_string); env->SetProtoMethod(tmpl, "args_get", WASI::ArgsGet); diff --git a/src/node_watchdog.cc b/src/node_watchdog.cc index f11902a1fa44bc..107a25bc977bd3 100644 --- a/src/node_watchdog.cc +++ b/src/node_watchdog.cc @@ -21,6 +21,7 @@ #include +#include "async_wrap-inl.h" #include "debug_utils-inl.h" #include "env-inl.h" #include "node_errors.h" @@ -30,6 +31,13 @@ namespace node { +using v8::Context; +using v8::FunctionCallbackInfo; +using v8::FunctionTemplate; +using v8::Local; +using v8::Object; +using v8::Value; + Watchdog::Watchdog(v8::Isolate* isolate, uint64_t ms, bool* timed_out) : isolate_(isolate), timed_out_(timed_out) { @@ -106,10 +114,117 @@ SigintWatchdog::~SigintWatchdog() { SigintWatchdogHelper::GetInstance()->Stop(); } - -void SigintWatchdog::HandleSigint() { +SignalPropagation SigintWatchdog::HandleSigint() { *received_signal_ = true; isolate_->TerminateExecution(); + return SignalPropagation::kStopPropagation; +} + +void TraceSigintWatchdog::Init(Environment* env, Local target) { + Local constructor = env->NewFunctionTemplate(New); + constructor->InstanceTemplate()->SetInternalFieldCount( + TraceSigintWatchdog::kInternalFieldCount); + Local js_sigint_watch_dog = + FIXED_ONE_BYTE_STRING(env->isolate(), "TraceSigintWatchdog"); + constructor->SetClassName(js_sigint_watch_dog); + constructor->Inherit(HandleWrap::GetConstructorTemplate(env)); + + env->SetProtoMethod(constructor, "start", Start); + env->SetProtoMethod(constructor, "stop", Stop); + + target + ->Set(env->context(), + js_sigint_watch_dog, + constructor->GetFunction(env->context()).ToLocalChecked()) + .Check(); +} + +void TraceSigintWatchdog::New(const FunctionCallbackInfo& args) { + // This constructor should not be exposed to public javascript. + // Therefore we assert that we are not trying to call this as a + // normal function. + CHECK(args.IsConstructCall()); + Environment* env = Environment::GetCurrent(args); + new TraceSigintWatchdog(env, args.This()); +} + +void TraceSigintWatchdog::Start(const FunctionCallbackInfo& args) { + TraceSigintWatchdog* watchdog; + ASSIGN_OR_RETURN_UNWRAP(&watchdog, args.Holder()); + // Register this watchdog with the global SIGINT/Ctrl+C listener. + SigintWatchdogHelper::GetInstance()->Register(watchdog); + // Start the helper thread, if that has not already happened. + int r = SigintWatchdogHelper::GetInstance()->Start(); + CHECK_EQ(r, 0); +} + +void TraceSigintWatchdog::Stop(const FunctionCallbackInfo& args) { + TraceSigintWatchdog* watchdog; + ASSIGN_OR_RETURN_UNWRAP(&watchdog, args.Holder()); + SigintWatchdogHelper::GetInstance()->Unregister(watchdog); + SigintWatchdogHelper::GetInstance()->Stop(); +} + +TraceSigintWatchdog::TraceSigintWatchdog(Environment* env, Local object) + : HandleWrap(env, + object, + reinterpret_cast(&handle_), + AsyncWrap::PROVIDER_SIGINTWATCHDOG) { + int r = uv_async_init(env->event_loop(), &handle_, [](uv_async_t* handle) { + TraceSigintWatchdog* watchdog = + ContainerOf(&TraceSigintWatchdog::handle_, handle); + watchdog->signal_flag_ = SignalFlags::FromIdle; + watchdog->HandleInterrupt(); + }); + CHECK_EQ(r, 0); + uv_unref(reinterpret_cast(&handle_)); +} + +SignalPropagation TraceSigintWatchdog::HandleSigint() { + /** + * In case of uv loop polling, i.e. no JS currently running, activate the + * loop to run a piece of JS code to trigger interruption. + */ + CHECK_EQ(uv_async_send(&handle_), 0); + env()->isolate()->RequestInterrupt( + [](v8::Isolate* isolate, void* data) { + TraceSigintWatchdog* self = static_cast(data); + if (self->signal_flag_ == SignalFlags::None) { + self->signal_flag_ = SignalFlags::FromInterrupt; + } + self->HandleInterrupt(); + }, + this); + return SignalPropagation::kContinuePropagation; +} + +void TraceSigintWatchdog::HandleInterrupt() { + // Do not nest interrupts. + if (interrupting) { + return; + } + interrupting = true; + if (signal_flag_ == SignalFlags::None) { + return; + } + Environment* env_ = env(); + // FIXME: Before + // https://github.com/nodejs/node/pull/29207#issuecomment-527667993 get + // fixed, additional JavaScript code evaluation shall be prevented from + // running during interruption. + FPrintF(stderr, + "KEYBOARD_INTERRUPT: Script execution was interrupted by `SIGINT`\n"); + if (signal_flag_ == SignalFlags::FromInterrupt) { + PrintStackTrace(env_->isolate(), + v8::StackTrace::CurrentStackTrace( + env_->isolate(), 10, v8::StackTrace::kDetailed)); + } + signal_flag_ = SignalFlags::None; + interrupting = false; + + SigintWatchdogHelper::GetInstance()->Unregister(this); + SigintWatchdogHelper::GetInstance()->Stop(); + raise(SIGINT); } #ifdef __POSIX__ @@ -162,8 +277,13 @@ bool SigintWatchdogHelper::InformWatchdogsAboutSignal() { instance.has_pending_signal_ = true; } - for (auto it : instance.watchdogs_) - it->HandleSigint(); + for (auto it = instance.watchdogs_.rbegin(); it != instance.watchdogs_.rend(); + it++) { + SignalPropagation wp = (*it)->HandleSigint(); + if (wp == SignalPropagation::kStopPropagation) { + break; + } + } return is_stopping; } @@ -259,15 +379,13 @@ bool SigintWatchdogHelper::HasPendingSignal() { return has_pending_signal_; } - -void SigintWatchdogHelper::Register(SigintWatchdog* wd) { +void SigintWatchdogHelper::Register(SigintWatchdogBase* wd) { Mutex::ScopedLock lock(list_mutex_); watchdogs_.push_back(wd); } - -void SigintWatchdogHelper::Unregister(SigintWatchdog* wd) { +void SigintWatchdogHelper::Unregister(SigintWatchdogBase* wd) { Mutex::ScopedLock lock(list_mutex_); auto it = std::find(watchdogs_.begin(), watchdogs_.end(), wd); @@ -302,4 +420,16 @@ SigintWatchdogHelper::~SigintWatchdogHelper() { SigintWatchdogHelper SigintWatchdogHelper::instance; +namespace watchdog { +static void Initialize(Local target, + Local unused, + Local context, + void* priv) { + Environment* env = Environment::GetCurrent(context); + TraceSigintWatchdog::Init(env, target); +} +} // namespace watchdog + } // namespace node + +NODE_MODULE_CONTEXT_AWARE_INTERNAL(watchdog, node::watchdog::Initialize); diff --git a/src/node_watchdog.h b/src/node_watchdog.h index 14c5e19cca5c9a..eb99c3b72a516b 100644 --- a/src/node_watchdog.h +++ b/src/node_watchdog.h @@ -24,9 +24,12 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS -#include "uv.h" -#include "node_mutex.h" #include +#include "handle_wrap.h" +#include "memory_tracker-inl.h" +#include "node_mutex.h" +#include "uv.h" +#include "v8.h" #ifdef __POSIX__ #include @@ -34,6 +37,11 @@ namespace node { +enum class SignalPropagation { + kContinuePropagation, + kStopPropagation, +}; + class Watchdog { public: explicit Watchdog(v8::Isolate* isolate, @@ -54,24 +62,56 @@ class Watchdog { bool* timed_out_; }; -class SigintWatchdog { +class SigintWatchdogBase { + public: + virtual ~SigintWatchdogBase() = default; + virtual SignalPropagation HandleSigint() = 0; +}; + +class SigintWatchdog : public SigintWatchdogBase { public: explicit SigintWatchdog(v8::Isolate* isolate, bool* received_signal = nullptr); ~SigintWatchdog(); v8::Isolate* isolate() { return isolate_; } - void HandleSigint(); + SignalPropagation HandleSigint() override; private: v8::Isolate* isolate_; bool* received_signal_; }; +class TraceSigintWatchdog : public HandleWrap, public SigintWatchdogBase { + public: + static void Init(Environment* env, v8::Local target); + static void New(const v8::FunctionCallbackInfo& args); + static void Start(const v8::FunctionCallbackInfo& args); + static void Stop(const v8::FunctionCallbackInfo& args); + + SignalPropagation HandleSigint() override; + + inline void MemoryInfo(node::MemoryTracker* tracker) const override { + tracker->TrackInlineField("handle_", handle_); + } + SET_MEMORY_INFO_NAME(TraceSigintWatchdog) + SET_SELF_SIZE(TraceSigintWatchdog) + + private: + enum class SignalFlags { None, FromIdle, FromInterrupt }; + + TraceSigintWatchdog(Environment* env, v8::Local object); + void HandleInterrupt(); + + bool interrupting = false; + uv_async_t handle_; + SignalFlags signal_flag_ = SignalFlags::None; +}; + class SigintWatchdogHelper { public: static SigintWatchdogHelper* GetInstance() { return &instance; } - void Register(SigintWatchdog* watchdog); - void Unregister(SigintWatchdog* watchdog); + void Register(SigintWatchdogBase* watchdog); + void Unregister(SigintWatchdogBase* watchdog); bool HasPendingSignal(); int Start(); @@ -88,7 +128,7 @@ class SigintWatchdogHelper { Mutex mutex_; Mutex list_mutex_; - std::vector watchdogs_; + std::vector watchdogs_; bool has_pending_signal_; #ifdef __POSIX__ diff --git a/src/node_worker.cc b/src/node_worker.cc index d6028af1ead07e..1172dd7e9a8b5e 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -30,7 +30,6 @@ using v8::Integer; using v8::Isolate; using v8::Local; using v8::Locker; -using v8::Maybe; using v8::MaybeLocal; using v8::Null; using v8::Number; @@ -145,10 +144,10 @@ class WorkerThreadData { uv_err_name_r(ret, err_buf, sizeof(err_buf)); w->custom_error_ = "ERR_WORKER_INIT_FAILED"; w->custom_error_str_ = err_buf; - w->loop_init_failed_ = true; w->stopped_ = true; return; } + loop_init_failed_ = false; Isolate::CreateParams params; SetIsolateCreateParamsForNode(¶ms); @@ -201,6 +200,7 @@ class WorkerThreadData { } if (isolate != nullptr) { + CHECK(!loop_init_failed_); bool platform_finished = false; isolate_data_.reset(); @@ -219,18 +219,20 @@ class WorkerThreadData { // Wait until the platform has cleaned up all relevant resources. while (!platform_finished) { - CHECK(!w_->loop_init_failed_); uv_run(&loop_, UV_RUN_ONCE); } } - if (!w_->loop_init_failed_) { + if (!loop_init_failed_) { CheckedUvLoopClose(&loop_); } } + bool loop_is_usable() const { return !loop_init_failed_; } + private: Worker* const w_; uv_loop_t loop_; + bool loop_init_failed_ = true; DeleteFnPtr isolate_data_; friend class Worker; @@ -260,7 +262,7 @@ void Worker::Run() { WorkerThreadData data(this); if (isolate_ == nullptr) return; - CHECK(!data.w_->loop_init_failed_); + CHECK(data.loop_is_usable()); Debug(this, "Starting worker with id %llu", thread_id_); { @@ -344,12 +346,6 @@ void Worker::Run() { env_->InitializeInspector(std::move(inspector_parent_handle_)); #endif HandleScope handle_scope(isolate_); - InternalCallbackScope callback_scope( - env_.get(), - Local(), - { 1, 0 }, - InternalCallbackScope::kAllowEmptyResource | - InternalCallbackScope::kSkipAsyncHooks); if (!env_->RunBootstrapping().IsEmpty()) { CreateEnvMessagePort(env_.get()); @@ -617,21 +613,12 @@ void Worker::StartThread(const FunctionCallbackInfo& args) { ASSIGN_OR_RETURN_UNWRAP(&w, args.This()); Mutex::ScopedLock lock(w->mutex_); - // The object now owns the created thread and should not be garbage collected - // until that finishes. - w->ClearWeak(); - - w->env()->add_sub_worker_context(w); w->stopped_ = false; - w->thread_joined_ = false; - - if (w->has_ref_) - w->env()->add_refs(1); uv_thread_options_t thread_options; thread_options.flags = UV_THREAD_HAS_STACK_SIZE; thread_options.stack_size = kStackSize; - CHECK_EQ(uv_thread_create_ex(&w->tid_, &thread_options, [](void* arg) { + int ret = uv_thread_create_ex(&w->tid_, &thread_options, [](void* arg) { // XXX: This could become a std::unique_ptr, but that makes at least // gcc 6.3 detect undefined behaviour when there shouldn't be any. // gcc 7+ handles this well. @@ -652,7 +639,29 @@ void Worker::StartThread(const FunctionCallbackInfo& args) { w->JoinThread(); // implicitly delete w }); - }, static_cast(w)), 0); + }, static_cast(w)); + + if (ret == 0) { + // The object now owns the created thread and should not be garbage + // collected until that finishes. + w->ClearWeak(); + w->thread_joined_ = false; + + if (w->has_ref_) + w->env()->add_refs(1); + + w->env()->add_sub_worker_context(w); + } else { + w->stopped_ = true; + + char err_buf[128]; + uv_err_name_r(ret, err_buf, sizeof(err_buf)); + { + Isolate* isolate = w->env()->isolate(); + HandleScope handle_scope(isolate); + THROW_ERR_WORKER_INIT_FAILED(isolate, err_buf); + } + } } void Worker::StopThread(const FunctionCallbackInfo& args) { @@ -708,6 +717,53 @@ void Worker::MemoryInfo(MemoryTracker* tracker) const { tracker->TrackField("parent_port", parent_port_); } +class WorkerHeapSnapshotTaker : public AsyncWrap { + public: + WorkerHeapSnapshotTaker(Environment* env, Local obj) + : AsyncWrap(env, obj, AsyncWrap::PROVIDER_WORKERHEAPSNAPSHOT) {} + + SET_NO_MEMORY_INFO() + SET_MEMORY_INFO_NAME(WorkerHeapSnapshotTaker) + SET_SELF_SIZE(WorkerHeapSnapshotTaker) +}; + +void Worker::TakeHeapSnapshot(const FunctionCallbackInfo& args) { + Worker* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.This()); + + Debug(w, "Worker %llu taking heap snapshot", w->thread_id_); + + Environment* env = w->env(); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_id_scope(w); + Local wrap; + if (!env->worker_heap_snapshot_taker_template() + ->NewInstance(env->context()).ToLocal(&wrap)) { + return; + } + BaseObjectPtr taker = + MakeDetachedBaseObject(env, wrap); + + // Interrupt the worker thread and take a snapshot, then schedule a call + // on the parent thread that turns that snapshot into a readable stream. + bool scheduled = w->RequestInterrupt([taker, env](Environment* worker_env) { + heap::HeapSnapshotPointer snapshot { + worker_env->isolate()->GetHeapProfiler()->TakeHeapSnapshot() }; + CHECK(snapshot); + env->SetImmediateThreadsafe( + [taker, snapshot = std::move(snapshot)](Environment* env) mutable { + HandleScope handle_scope(env->isolate()); + Context::Scope context_scope(env->context()); + + AsyncHooks::DefaultTriggerAsyncIdScope trigger_id_scope(taker.get()); + BaseObjectPtr stream = heap::CreateHeapSnapshotStream( + env, std::move(snapshot)); + Local args[] = { stream->object() }; + taker->MakeCallback(env->ondone_string(), arraysize(args), args); + }); + }); + args.GetReturnValue().Set(scheduled ? taker->object() : Local()); +} + namespace { // Return the MessagePort that is global for this Environment and communicates @@ -730,7 +786,8 @@ void InitWorker(Local target, { Local w = env->NewFunctionTemplate(Worker::New); - w->InstanceTemplate()->SetInternalFieldCount(1); + w->InstanceTemplate()->SetInternalFieldCount( + Worker::kInternalFieldCount); w->Inherit(AsyncWrap::GetConstructorTemplate(env)); env->SetProtoMethod(w, "startThread", Worker::StartThread); @@ -738,6 +795,7 @@ void InitWorker(Local target, env->SetProtoMethod(w, "ref", Worker::Ref); env->SetProtoMethod(w, "unref", Worker::Unref); env->SetProtoMethod(w, "getResourceLimits", Worker::GetResourceLimits); + env->SetProtoMethod(w, "takeHeapSnapshot", Worker::TakeHeapSnapshot); Local workerString = FIXED_ONE_BYTE_STRING(env->isolate(), "Worker"); @@ -747,6 +805,19 @@ void InitWorker(Local target, w->GetFunction(env->context()).ToLocalChecked()).Check(); } + { + Local wst = FunctionTemplate::New(env->isolate()); + + wst->InstanceTemplate()->SetInternalFieldCount( + WorkerHeapSnapshotTaker::kInternalFieldCount); + wst->Inherit(AsyncWrap::GetConstructorTemplate(env)); + + Local wst_string = + FIXED_ONE_BYTE_STRING(env->isolate(), "WorkerHeapSnapshotTaker"); + wst->SetClassName(wst_string); + env->set_worker_heap_snapshot_taker_template(wst->InstanceTemplate()); + } + env->SetMethod(target, "getEnvMessagePort", GetEnvMessagePort); target diff --git a/src/node_worker.h b/src/node_worker.h index 863e2cffde0f36..3611a8536fe040 100644 --- a/src/node_worker.h +++ b/src/node_worker.h @@ -61,6 +61,7 @@ class Worker : public AsyncWrap { static void GetResourceLimits( const v8::FunctionCallbackInfo& args); v8::Local GetResourceLimits(v8::Isolate* isolate) const; + static void TakeHeapSnapshot(const v8::FunctionCallbackInfo& args); private: void CreateEnvMessagePort(Environment* env); @@ -87,7 +88,6 @@ class Worker : public AsyncWrap { bool thread_joined_ = true; const char* custom_error_ = nullptr; std::string custom_error_str_; - bool loop_init_failed_ = false; int exit_code_ = 0; uint64_t thread_id_ = -1; uintptr_t stack_base_ = 0; diff --git a/src/node_zlib.cc b/src/node_zlib.cc index 9c734c17d792f7..18f548cc31ad66 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -1215,7 +1215,8 @@ struct MakeClass { static void Make(Environment* env, Local target, const char* name) { Local z = env->NewFunctionTemplate(Stream::New); - z->InstanceTemplate()->SetInternalFieldCount(1); + z->InstanceTemplate()->SetInternalFieldCount( + Stream::kInternalFieldCount); z->Inherit(AsyncWrap::GetConstructorTemplate(env)); env->SetProtoMethod(z, "write", Stream::template Write); diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index c2be4320387549..c4a5b7cd62e1b4 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -74,7 +74,7 @@ void PipeWrap::Initialize(Local target, Local pipeString = FIXED_ONE_BYTE_STRING(env->isolate(), "Pipe"); t->SetClassName(pipeString); t->InstanceTemplate() - ->SetInternalFieldCount(StreamBase::kStreamBaseFieldCount); + ->SetInternalFieldCount(StreamBase::kInternalFieldCount); t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env)); diff --git a/src/process_wrap.cc b/src/process_wrap.cc index e294c6464f2a11..3d1065c9922183 100644 --- a/src/process_wrap.cc +++ b/src/process_wrap.cc @@ -52,7 +52,8 @@ class ProcessWrap : public HandleWrap { void* priv) { Environment* env = Environment::GetCurrent(context); Local constructor = env->NewFunctionTemplate(New); - constructor->InstanceTemplate()->SetInternalFieldCount(1); + constructor->InstanceTemplate()->SetInternalFieldCount( + ProcessWrap::kInternalFieldCount); Local processString = FIXED_ONE_BYTE_STRING(env->isolate(), "Process"); constructor->SetClassName(processString); diff --git a/src/signal_wrap.cc b/src/signal_wrap.cc index bc2d9f1e355efd..2be7ac9834100b 100644 --- a/src/signal_wrap.cc +++ b/src/signal_wrap.cc @@ -53,7 +53,8 @@ class SignalWrap : public HandleWrap { void* priv) { Environment* env = Environment::GetCurrent(context); Local constructor = env->NewFunctionTemplate(New); - constructor->InstanceTemplate()->SetInternalFieldCount(1); + constructor->InstanceTemplate()->SetInternalFieldCount( + SignalWrap::kInternalFieldCount); Local signalString = FIXED_ONE_BYTE_STRING(env->isolate(), "Signal"); constructor->SetClassName(signalString); diff --git a/src/stream_base-inl.h b/src/stream_base-inl.h index f89eb3a5287939..41eeb1e0ef5710 100644 --- a/src/stream_base-inl.h +++ b/src/stream_base-inl.h @@ -3,10 +3,9 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS -#include "stream_base.h" - +#include "async_wrap-inl.h" #include "node.h" -#include "env-inl.h" +#include "stream_base.h" #include "v8.h" namespace node { @@ -23,18 +22,22 @@ using v8::String; using v8::Value; inline void StreamReq::AttachToObject(v8::Local req_wrap_obj) { - CHECK_EQ(req_wrap_obj->GetAlignedPointerFromInternalField(kStreamReqField), + CHECK_EQ(req_wrap_obj->GetAlignedPointerFromInternalField( + StreamReq::kStreamReqField), nullptr); - req_wrap_obj->SetAlignedPointerInInternalField(kStreamReqField, this); + req_wrap_obj->SetAlignedPointerInInternalField( + StreamReq::kStreamReqField, this); } inline StreamReq* StreamReq::FromObject(v8::Local req_wrap_obj) { return static_cast( - req_wrap_obj->GetAlignedPointerFromInternalField(kStreamReqField)); + req_wrap_obj->GetAlignedPointerFromInternalField( + StreamReq::kStreamReqField)); } inline void StreamReq::Dispose() { - object()->SetAlignedPointerInInternalField(kStreamReqField, nullptr); + object()->SetAlignedPointerInInternalField( + StreamReq::kStreamReqField, nullptr); delete this; } @@ -261,15 +264,17 @@ inline WriteWrap* StreamBase::CreateWriteWrap( } inline void StreamBase::AttachToObject(v8::Local obj) { - obj->SetAlignedPointerInInternalField(kStreamBaseField, this); + obj->SetAlignedPointerInInternalField( + StreamBase::kStreamBaseField, this); } inline StreamBase* StreamBase::FromObject(v8::Local obj) { - if (obj->GetAlignedPointerFromInternalField(0) == nullptr) + if (obj->GetAlignedPointerFromInternalField(StreamBase::kSlot) == nullptr) return nullptr; return static_cast( - obj->GetAlignedPointerFromInternalField(kStreamBaseField)); + obj->GetAlignedPointerFromInternalField( + StreamBase::kStreamBaseField)); } @@ -304,7 +309,7 @@ inline void StreamReq::Done(int status, const char* error_str) { inline void StreamReq::ResetObject(v8::Local obj) { DCHECK_GT(obj->InternalFieldCount(), StreamReq::kStreamReqField); - obj->SetAlignedPointerInInternalField(0, nullptr); // BaseObject field. + obj->SetAlignedPointerInInternalField(StreamReq::kSlot, nullptr); obj->SetAlignedPointerInInternalField(StreamReq::kStreamReqField, nullptr); } diff --git a/src/stream_base.cc b/src/stream_base.cc index 3f313aaeff3a44..516f57e40bfbe0 100644 --- a/src/stream_base.cc +++ b/src/stream_base.cc @@ -340,7 +340,8 @@ MaybeLocal StreamBase::CallJSOnreadMethod(ssize_t nread, AsyncWrap* wrap = GetAsyncWrap(); CHECK_NOT_NULL(wrap); - Local onread = wrap->object()->GetInternalField(kOnReadFunctionField); + Local onread = wrap->object()->GetInternalField( + StreamBase::kOnReadFunctionField); CHECK(onread->IsFunction()); return wrap->MakeCallback(onread.As(), arraysize(argv), argv); } @@ -409,8 +410,11 @@ void StreamBase::AddMethods(Environment* env, Local t) { True(env->isolate())); t->PrototypeTemplate()->SetAccessor( FIXED_ONE_BYTE_STRING(env->isolate(), "onread"), - BaseObject::InternalFieldGet, - BaseObject::InternalFieldSet); + BaseObject::InternalFieldGet< + StreamBase::kOnReadFunctionField>, + BaseObject::InternalFieldSet< + StreamBase::kOnReadFunctionField, + &Value::IsFunction>); } void StreamBase::GetFD(const FunctionCallbackInfo& args) { diff --git a/src/stream_base.h b/src/stream_base.h index 3df9e99f6e438e..eb75fdc8339ab8 100644 --- a/src/stream_base.h +++ b/src/stream_base.h @@ -3,7 +3,8 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS -#include "async_wrap-inl.h" +#include "env.h" +#include "async_wrap.h" #include "node.h" #include "util.h" @@ -29,7 +30,14 @@ using JSMethodFunction = void(const v8::FunctionCallbackInfo& args); class StreamReq { public: - static constexpr int kStreamReqField = 1; + // The kSlot internal field here mirrors BaseObject::InternalFields::kSlot + // here because instances derived from StreamReq will also derive from + // BaseObject, and the slots are used for the identical purpose. + enum InternalFields { + kSlot = BaseObject::kSlot, + kStreamReqField = BaseObject::kInternalFieldCount, + kInternalFieldCount + }; explicit StreamReq(StreamBase* stream, v8::Local req_wrap_obj) : stream_(stream) { @@ -275,10 +283,15 @@ class StreamResource { class StreamBase : public StreamResource { public: - // 0 is reserved for the BaseObject pointer. - static constexpr int kStreamBaseField = 1; - static constexpr int kOnReadFunctionField = 2; - static constexpr int kStreamBaseFieldCount = 3; + // The kSlot field here mirrors that of BaseObject::InternalFields::kSlot + // because instances deriving from StreamBase generally also derived from + // BaseObject (it's possible for it not to, however). + enum InternalFields { + kSlot = BaseObject::kSlot, + kStreamBaseField = BaseObject::kInternalFieldCount, + kOnReadFunctionField, + kInternalFieldCount + }; static void AddMethods(Environment* env, v8::Local target); diff --git a/src/stream_pipe.cc b/src/stream_pipe.cc index 5f7514b1b84790..40b094ab5930a5 100644 --- a/src/stream_pipe.cc +++ b/src/stream_pipe.cc @@ -298,7 +298,8 @@ void InitializeStreamPipe(Local target, env->SetProtoMethod(pipe, "pendingWrites", StreamPipe::PendingWrites); pipe->Inherit(AsyncWrap::GetConstructorTemplate(env)); pipe->SetClassName(stream_pipe_string); - pipe->InstanceTemplate()->SetInternalFieldCount(1); + pipe->InstanceTemplate()->SetInternalFieldCount( + StreamPipe::kInternalFieldCount); target ->Set(context, stream_pipe_string, pipe->GetFunction(context).ToLocalChecked()) diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc index 21b775401e4571..7548516e477a36 100644 --- a/src/stream_wrap.cc +++ b/src/stream_wrap.cc @@ -64,8 +64,7 @@ void LibuvStreamWrap::Initialize(Local target, }; Local sw = FunctionTemplate::New(env->isolate(), is_construct_call_callback); - sw->InstanceTemplate()->SetInternalFieldCount( - StreamReq::kStreamReqField + 1 + 3); + sw->InstanceTemplate()->SetInternalFieldCount(StreamReq::kInternalFieldCount); Local wrapString = FIXED_ONE_BYTE_STRING(env->isolate(), "ShutdownWrap"); sw->SetClassName(wrapString); @@ -94,7 +93,8 @@ void LibuvStreamWrap::Initialize(Local target, Local ww = FunctionTemplate::New(env->isolate(), is_construct_call_callback); - ww->InstanceTemplate()->SetInternalFieldCount(StreamReq::kStreamReqField + 1); + ww->InstanceTemplate()->SetInternalFieldCount( + StreamReq::kInternalFieldCount); Local writeWrapString = FIXED_ONE_BYTE_STRING(env->isolate(), "WriteWrap"); ww->SetClassName(writeWrapString); @@ -136,7 +136,7 @@ Local LibuvStreamWrap::GetConstructorTemplate( FIXED_ONE_BYTE_STRING(env->isolate(), "LibuvStreamWrap")); tmpl->Inherit(HandleWrap::GetConstructorTemplate(env)); tmpl->InstanceTemplate()->SetInternalFieldCount( - StreamBase::kStreamBaseFieldCount); + StreamBase::kInternalFieldCount); Local get_write_queue_size = FunctionTemplate::New(env->isolate(), GetWriteQueueSize, diff --git a/src/string_bytes.h b/src/string_bytes.h index 451c39955f7ef7..7902bf0b618255 100644 --- a/src/string_bytes.h +++ b/src/string_bytes.h @@ -26,7 +26,14 @@ // Decodes a v8::Local or Buffer to a raw char* +#if (__GNUC__ >= 8) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif #include "v8.h" +#if (__GNUC__ >= 8) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif #include "env-inl.h" #include diff --git a/src/tcp_wrap.cc b/src/tcp_wrap.cc index 89c4e215bbe6ae..619c9ef6196373 100644 --- a/src/tcp_wrap.cc +++ b/src/tcp_wrap.cc @@ -77,8 +77,7 @@ void TCPWrap::Initialize(Local target, Local t = env->NewFunctionTemplate(New); Local tcpString = FIXED_ONE_BYTE_STRING(env->isolate(), "TCP"); t->SetClassName(tcpString); - t->InstanceTemplate() - ->SetInternalFieldCount(StreamBase::kStreamBaseFieldCount); + t->InstanceTemplate()->SetInternalFieldCount(StreamBase::kInternalFieldCount); // Init properties t->InstanceTemplate()->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "reading"), @@ -186,7 +185,7 @@ void TCPWrap::SetKeepAlive(const FunctionCallbackInfo& args) { Environment* env = wrap->env(); int enable; if (!args[0]->Int32Value(env->context()).To(&enable)) return; - unsigned int delay = args[1].As()->Value(); + unsigned int delay = static_cast(args[1].As()->Value()); int err = uv_tcp_keepalive(&wrap->handle_, enable, delay); args.GetReturnValue().Set(err); } @@ -279,7 +278,8 @@ void TCPWrap::Listen(const FunctionCallbackInfo& args) { void TCPWrap::Connect(const FunctionCallbackInfo& args) { CHECK(args[2]->IsUint32()); - int port = args[2].As()->Value(); + // explicit cast to fit to libuv's type expectation + int port = static_cast(args[2].As()->Value()); Connect(args, [port](const char* ip_address, sockaddr_in* addr) { return uv_ip4_addr(ip_address, port, addr); diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc index 36877424216ed4..39dcf532a9fb7a 100644 --- a/src/tls_wrap.cc +++ b/src/tls_wrap.cc @@ -1091,11 +1091,14 @@ int TLSWrap::SelectSNIContextCallback(SSL* s, int* ad, void* arg) { return SSL_TLSEXT_ERR_NOACK; } - p->sni_context_.Reset(env->isolate(), ctx); - SecureContext* sc = Unwrap(ctx.As()); CHECK_NOT_NULL(sc); - p->SetSNIContext(sc); + p->sni_context_ = BaseObjectPtr(sc); + + p->ConfigureSecureContext(sc); + CHECK_EQ(SSL_set_SSL_CTX(p->ssl_.get(), sc->ctx_.get()), sc->ctx_.get()); + p->SetCACerts(sc); + return SSL_TLSEXT_ERR_OK; } @@ -1240,6 +1243,7 @@ void TLSWrap::GetWriteQueueSize(const FunctionCallbackInfo& info) { void TLSWrap::MemoryInfo(MemoryTracker* tracker) const { + SSLWrap::MemoryInfo(tracker); tracker->TrackField("error", error_); tracker->TrackFieldWithSize("pending_cleartext_input", pending_cleartext_input_.size(), @@ -1265,8 +1269,7 @@ void TLSWrap::Initialize(Local target, Local tlsWrapString = FIXED_ONE_BYTE_STRING(env->isolate(), "TLSWrap"); t->SetClassName(tlsWrapString); - t->InstanceTemplate() - ->SetInternalFieldCount(StreamBase::kStreamBaseFieldCount); + t->InstanceTemplate()->SetInternalFieldCount(StreamBase::kInternalFieldCount); Local get_write_queue_size = FunctionTemplate::New(env->isolate(), diff --git a/src/tty_wrap.cc b/src/tty_wrap.cc index 7dface926e4349..8536fae3ed7383 100644 --- a/src/tty_wrap.cc +++ b/src/tty_wrap.cc @@ -51,8 +51,7 @@ void TTYWrap::Initialize(Local target, Local t = env->NewFunctionTemplate(New); t->SetClassName(ttyString); - t->InstanceTemplate() - ->SetInternalFieldCount(StreamBase::kStreamBaseFieldCount); + t->InstanceTemplate()->SetInternalFieldCount(StreamBase::kInternalFieldCount); t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env)); env->SetProtoMethodNoSideEffect(t, "getWindowSize", TTYWrap::GetWindowSize); diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index a1f70a58e4bb03..770782ee9cf38e 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -22,6 +22,7 @@ #include "udp_wrap.h" #include "env-inl.h" #include "node_buffer.h" +#include "node_sockaddr-inl.h" #include "handle_wrap.h" #include "req_wrap-inl.h" #include "util-inl.h" @@ -69,18 +70,57 @@ SendWrap::SendWrap(Environment* env, } -inline bool SendWrap::have_callback() const { +bool SendWrap::have_callback() const { return have_callback_; } +UDPListener::~UDPListener() { + if (wrap_ != nullptr) + wrap_->set_listener(nullptr); +} + +UDPWrapBase::~UDPWrapBase() { + set_listener(nullptr); +} + +UDPListener* UDPWrapBase::listener() const { + CHECK_NOT_NULL(listener_); + return listener_; +} + +void UDPWrapBase::set_listener(UDPListener* listener) { + if (listener_ != nullptr) + listener_->wrap_ = nullptr; + listener_ = listener; + if (listener_ != nullptr) { + CHECK_NULL(listener_->wrap_); + listener_->wrap_ = this; + } +} + +UDPWrapBase* UDPWrapBase::FromObject(Local obj) { + CHECK_GT(obj->InternalFieldCount(), UDPWrapBase::kUDPWrapBaseField); + return static_cast( + obj->GetAlignedPointerFromInternalField(UDPWrapBase::kUDPWrapBaseField)); +} + +void UDPWrapBase::AddMethods(Environment* env, Local t) { + env->SetProtoMethod(t, "recvStart", RecvStart); + env->SetProtoMethod(t, "recvStop", RecvStop); +} UDPWrap::UDPWrap(Environment* env, Local object) : HandleWrap(env, object, reinterpret_cast(&handle_), AsyncWrap::PROVIDER_UDPWRAP) { + object->SetAlignedPointerInInternalField( + UDPWrapBase::kUDPWrapBaseField, static_cast(this)); + int r = uv_udp_init(env->event_loop(), &handle_); CHECK_EQ(r, 0); // can't fail anyway + + set_listener(this); } @@ -91,7 +131,8 @@ void UDPWrap::Initialize(Local target, Environment* env = Environment::GetCurrent(context); Local t = env->NewFunctionTemplate(New); - t->InstanceTemplate()->SetInternalFieldCount(1); + t->InstanceTemplate()->SetInternalFieldCount( + UDPWrapBase::kInternalFieldCount); Local udpString = FIXED_ONE_BYTE_STRING(env->isolate(), "UDP"); t->SetClassName(udpString); @@ -112,6 +153,7 @@ void UDPWrap::Initialize(Local target, Local(), attributes); + UDPWrapBase::AddMethods(env, t); env->SetProtoMethod(t, "open", Open); env->SetProtoMethod(t, "bind", Bind); env->SetProtoMethod(t, "connect", Connect); @@ -120,8 +162,6 @@ void UDPWrap::Initialize(Local target, env->SetProtoMethod(t, "connect6", Connect6); env->SetProtoMethod(t, "send6", Send6); env->SetProtoMethod(t, "disconnect", Disconnect); - env->SetProtoMethod(t, "recvStart", RecvStart); - env->SetProtoMethod(t, "recvStop", RecvStop); env->SetProtoMethod(t, "getpeername", GetSockOrPeerName); env->SetProtoMethod(t, "getsockname", @@ -220,6 +260,9 @@ void UDPWrap::DoBind(const FunctionCallbackInfo& args, int family) { flags); } + if (err == 0) + wrap->listener()->OnAfterBind(); + args.GetReturnValue().Set(err); } @@ -464,14 +507,10 @@ void UDPWrap::DoSend(const FunctionCallbackInfo& args, int family) { CHECK(args[3]->IsBoolean()); } - Local req_wrap_obj = args[0].As(); Local chunks = args[1].As(); // it is faster to fetch the length of the // array in js-land size_t count = args[2].As()->Value(); - const bool have_callback = sendto ? args[5]->IsTrue() : args[3]->IsTrue(); - - size_t msg_size = 0; MaybeStackBuffer bufs(count); @@ -483,7 +522,6 @@ void UDPWrap::DoSend(const FunctionCallbackInfo& args, int family) { size_t length = Buffer::Length(chunk); bufs[i] = uv_buf_init(Buffer::Data(chunk), length); - msg_size += length; } int err = 0; @@ -493,14 +531,36 @@ void UDPWrap::DoSend(const FunctionCallbackInfo& args, int family) { const unsigned short port = args[3].As()->Value(); node::Utf8Value address(env->isolate(), args[4]); err = sockaddr_for_family(family, address.out(), port, &addr_storage); - if (err == 0) { + if (err == 0) addr = reinterpret_cast(&addr_storage); - } } - uv_buf_t* bufs_ptr = *bufs; - if (err == 0 && !UNLIKELY(env->options()->test_udp_no_try_send)) { - err = uv_udp_try_send(&wrap->handle_, bufs_ptr, count, addr); + if (err == 0) { + wrap->current_send_req_wrap_ = args[0].As(); + wrap->current_send_has_callback_ = + sendto ? args[5]->IsTrue() : args[3]->IsTrue(); + + err = wrap->Send(*bufs, count, addr); + + wrap->current_send_req_wrap_.Clear(); + wrap->current_send_has_callback_ = false; + } + + args.GetReturnValue().Set(err); +} + +ssize_t UDPWrap::Send(uv_buf_t* bufs_ptr, + size_t count, + const sockaddr* addr) { + if (IsHandleClosing()) return UV_EBADF; + + size_t msg_size = 0; + for (size_t i = 0; i < count; i++) + msg_size += bufs_ptr[i].len; + + int err = 0; + if (!UNLIKELY(env()->options()->test_udp_no_try_send)) { + err = uv_udp_try_send(&handle_, bufs_ptr, count, addr); if (err == UV_ENOSYS || err == UV_EAGAIN) { err = 0; } else if (err >= 0) { @@ -518,28 +578,41 @@ void UDPWrap::DoSend(const FunctionCallbackInfo& args, int family) { CHECK_EQ(static_cast(err), msg_size); // + 1 so that the JS side can distinguish 0-length async sends from // 0-length sync sends. - args.GetReturnValue().Set(static_cast(msg_size) + 1); - return; + return msg_size + 1; } } } if (err == 0) { - AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(wrap); - SendWrap* req_wrap = new SendWrap(env, req_wrap_obj, have_callback); - req_wrap->msg_size = msg_size; - - err = req_wrap->Dispatch(uv_udp_send, - &wrap->handle_, - bufs_ptr, - count, - addr, - OnSend); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(this); + ReqWrap* req_wrap = listener()->CreateSendWrap(msg_size); + if (req_wrap == nullptr) return UV_ENOSYS; + + err = req_wrap->Dispatch( + uv_udp_send, + &handle_, + bufs_ptr, + count, + addr, + uv_udp_send_cb{[](uv_udp_send_t* req, int status) { + UDPWrap* self = ContainerOf(&UDPWrap::handle_, req->handle); + self->listener()->OnSendDone( + ReqWrap::from_req(req), status); + }}); if (err) delete req_wrap; } - args.GetReturnValue().Set(err); + return err; +} + + +ReqWrap* UDPWrap::CreateSendWrap(size_t msg_size) { + SendWrap* req_wrap = new SendWrap(env(), + current_send_req_wrap_, + current_send_has_callback_); + req_wrap->msg_size = msg_size; + return req_wrap; } @@ -553,31 +626,46 @@ void UDPWrap::Send6(const FunctionCallbackInfo& args) { } -void UDPWrap::RecvStart(const FunctionCallbackInfo& args) { - UDPWrap* wrap; - ASSIGN_OR_RETURN_UNWRAP(&wrap, - args.Holder(), - args.GetReturnValue().Set(UV_EBADF)); - int err = uv_udp_recv_start(&wrap->handle_, OnAlloc, OnRecv); +AsyncWrap* UDPWrap::GetAsyncWrap() { + return this; +} + +SocketAddress UDPWrap::GetPeerName() { + return SocketAddress::FromPeerName(handle_); +} + +SocketAddress UDPWrap::GetSockName() { + return SocketAddress::FromSockName(handle_); +} + +void UDPWrapBase::RecvStart(const FunctionCallbackInfo& args) { + UDPWrapBase* wrap = UDPWrapBase::FromObject(args.Holder()); + args.GetReturnValue().Set(wrap == nullptr ? UV_EBADF : wrap->RecvStart()); +} + +int UDPWrap::RecvStart() { + if (IsHandleClosing()) return UV_EBADF; + int err = uv_udp_recv_start(&handle_, OnAlloc, OnRecv); // UV_EALREADY means that the socket is already bound but that's okay if (err == UV_EALREADY) err = 0; - args.GetReturnValue().Set(err); + return err; } -void UDPWrap::RecvStop(const FunctionCallbackInfo& args) { - UDPWrap* wrap; - ASSIGN_OR_RETURN_UNWRAP(&wrap, - args.Holder(), - args.GetReturnValue().Set(UV_EBADF)); - int r = uv_udp_recv_stop(&wrap->handle_); - args.GetReturnValue().Set(r); +void UDPWrapBase::RecvStop(const FunctionCallbackInfo& args) { + UDPWrapBase* wrap = UDPWrapBase::FromObject(args.Holder()); + args.GetReturnValue().Set(wrap == nullptr ? UV_EBADF : wrap->RecvStop()); +} + +int UDPWrap::RecvStop() { + if (IsHandleClosing()) return UV_EBADF; + return uv_udp_recv_stop(&handle_); } -void UDPWrap::OnSend(uv_udp_send_t* req, int status) { - std::unique_ptr req_wrap{static_cast(req->data)}; +void UDPWrap::OnSendDone(ReqWrap* req, int status) { + std::unique_ptr req_wrap{static_cast(req)}; if (req_wrap->have_callback()) { Environment* env = req_wrap->env(); HandleScope handle_scope(env->isolate()); @@ -594,19 +682,30 @@ void UDPWrap::OnSend(uv_udp_send_t* req, int status) { void UDPWrap::OnAlloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - UDPWrap* wrap = static_cast(handle->data); - *buf = wrap->env()->AllocateManaged(suggested_size).release(); + UDPWrap* wrap = ContainerOf(&UDPWrap::handle_, + reinterpret_cast(handle)); + *buf = wrap->listener()->OnAlloc(suggested_size); +} + +uv_buf_t UDPWrap::OnAlloc(size_t suggested_size) { + return env()->AllocateManaged(suggested_size).release(); } void UDPWrap::OnRecv(uv_udp_t* handle, ssize_t nread, - const uv_buf_t* buf_, - const struct sockaddr* addr, + const uv_buf_t* buf, + const sockaddr* addr, unsigned int flags) { - UDPWrap* wrap = static_cast(handle->data); - Environment* env = wrap->env(); + UDPWrap* wrap = ContainerOf(&UDPWrap::handle_, handle); + wrap->listener()->OnRecv(nread, *buf, addr, flags); +} - AllocatedBuffer buf(env, *buf_); +void UDPWrap::OnRecv(ssize_t nread, + const uv_buf_t& buf_, + const sockaddr* addr, + unsigned int flags) { + Environment* env = this->env(); + AllocatedBuffer buf(env, buf_); if (nread == 0 && addr == nullptr) { return; } @@ -614,23 +713,22 @@ void UDPWrap::OnRecv(uv_udp_t* handle, HandleScope handle_scope(env->isolate()); Context::Scope context_scope(env->context()); - Local wrap_obj = wrap->object(); Local argv[] = { Integer::New(env->isolate(), nread), - wrap_obj, + object(), Undefined(env->isolate()), Undefined(env->isolate()) }; if (nread < 0) { - wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv); + MakeCallback(env->onmessage_string(), arraysize(argv), argv); return; } buf.Resize(nread); argv[2] = buf.ToBuffer().ToLocalChecked(); argv[3] = AddressToJS(env, addr); - wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv); + MakeCallback(env->onmessage_string(), arraysize(argv), argv); } MaybeLocal UDPWrap::Instantiate(Environment* env, diff --git a/src/udp_wrap.h b/src/udp_wrap.h index 2026dd1dee1eb1..6fed1d2dfea810 100644 --- a/src/udp_wrap.h +++ b/src/udp_wrap.h @@ -25,14 +25,99 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "handle_wrap.h" +#include "req_wrap.h" +#include "node_sockaddr.h" #include "uv.h" #include "v8.h" namespace node { -class Environment; +class UDPWrapBase; -class UDPWrap: public HandleWrap { +// A listener that can be attached to an `UDPWrapBase` object and generally +// manages its I/O activity. This is similar to `StreamListener`. +class UDPListener { + public: + virtual ~UDPListener(); + + // Called right before data is received from the socket. Must return a + // buffer suitable for reading data into, that is then passed to OnRecv. + virtual uv_buf_t OnAlloc(size_t suggested_size) = 0; + + // Called right after data is received from the socket, and includes + // information about the source address. If `nread` is negative, an error + // has occurred, and it represents a libuv error code. + virtual void OnRecv(ssize_t nread, + const uv_buf_t& buf, + const sockaddr* addr, + unsigned int flags) = 0; + + // Called when an asynchronous request for writing data is created. + // The `msg_size` value contains the total size of the data to be sent, + // but may be ignored by the implementation of this Method. + // The return value is later passed to OnSendDone. + virtual ReqWrap* CreateSendWrap(size_t msg_size) = 0; + + // Called when an asynchronous request for writing data has finished. + // If status is negative, an error has occurred, and it represents a libuv + // error code. + virtual void OnSendDone(ReqWrap* wrap, int status) = 0; + + // Optional callback that is called after the socket has been bound. + virtual void OnAfterBind() {} + + inline UDPWrapBase* udp() const { return wrap_; } + + protected: + UDPWrapBase* wrap_ = nullptr; + + friend class UDPWrapBase; +}; + +class UDPWrapBase { + public: + // While UDPWrapBase itself does not extend from HandleWrap, classes + // derived from it will (like UDPWrap) + enum InternalFields { + kUDPWrapBaseField = HandleWrap::kInternalFieldCount, + kInternalFieldCount + }; + virtual ~UDPWrapBase(); + + // Start emitting OnAlloc() + OnRecv() events on the listener. + virtual int RecvStart() = 0; + + // Stop emitting OnAlloc() + OnRecv() events on the listener. + virtual int RecvStop() = 0; + + // Send a chunk of data over this socket. This may call CreateSendWrap() + // on the listener if an async transmission is necessary. + virtual ssize_t Send(uv_buf_t* bufs, + size_t nbufs, + const sockaddr* addr) = 0; + + virtual SocketAddress GetPeerName() = 0; + virtual SocketAddress GetSockName() = 0; + + // Returns an AsyncWrap object with the same lifetime as this object. + virtual AsyncWrap* GetAsyncWrap() = 0; + + void set_listener(UDPListener* listener); + UDPListener* listener() const; + + static UDPWrapBase* FromObject(v8::Local obj); + + static void RecvStart(const v8::FunctionCallbackInfo& args); + static void RecvStop(const v8::FunctionCallbackInfo& args); + static void AddMethods(Environment* env, v8::Local t); + + private: + UDPListener* listener_ = nullptr; +}; + +class UDPWrap final : public HandleWrap, + public UDPWrapBase, + public UDPListener { public: enum SocketType { SOCKET @@ -51,8 +136,6 @@ class UDPWrap: public HandleWrap { static void Connect6(const v8::FunctionCallbackInfo& args); static void Send6(const v8::FunctionCallbackInfo& args); static void Disconnect(const v8::FunctionCallbackInfo& args); - static void RecvStart(const v8::FunctionCallbackInfo& args); - static void RecvStop(const v8::FunctionCallbackInfo& args); static void AddMembership(const v8::FunctionCallbackInfo& args); static void DropMembership(const v8::FunctionCallbackInfo& args); static void AddSourceSpecificMembership( @@ -68,6 +151,27 @@ class UDPWrap: public HandleWrap { static void SetTTL(const v8::FunctionCallbackInfo& args); static void BufferSize(const v8::FunctionCallbackInfo& args); + // UDPListener implementation + uv_buf_t OnAlloc(size_t suggested_size) override; + void OnRecv(ssize_t nread, + const uv_buf_t& buf, + const sockaddr* addr, + unsigned int flags) override; + ReqWrap* CreateSendWrap(size_t msg_size) override; + void OnSendDone(ReqWrap* wrap, int status) override; + + // UDPWrapBase implementation + int RecvStart() override; + int RecvStop() override; + ssize_t Send(uv_buf_t* bufs, + size_t nbufs, + const sockaddr* addr) override; + + SocketAddress GetPeerName() override; + SocketAddress GetSockName() override; + + AsyncWrap* GetAsyncWrap() override; + static v8::MaybeLocal Instantiate(Environment* env, AsyncWrap* parent, SocketType type); @@ -99,7 +203,6 @@ class UDPWrap: public HandleWrap { static void OnAlloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); - static void OnSend(uv_udp_send_t* req, int status); static void OnRecv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, @@ -107,6 +210,9 @@ class UDPWrap: public HandleWrap { unsigned int flags); uv_udp_t handle_; + + bool current_send_has_callback_; + v8::Local current_send_req_wrap_; }; } // namespace node diff --git a/test/addons/openssl-binding/binding.gyp b/test/addons/openssl-binding/binding.gyp index 06c5d15057f586..c9ce9f1b2a6f6a 100644 --- a/test/addons/openssl-binding/binding.gyp +++ b/test/addons/openssl-binding/binding.gyp @@ -3,15 +3,25 @@ { 'target_name': 'binding', 'includes': ['../common.gypi'], - 'variables': { - # Skip this building on IBM i. - 'aix_variant_name': ' exports, node::Buffer::New( isolate, data, - sizeof(data), + sizeof(char), [](char* data, void* hint) { free_call_count++; }, diff --git a/test/addons/zlib-binding/binding.gyp b/test/addons/zlib-binding/binding.gyp index 8c559cd715f779..f0f6d62a5f248c 100644 --- a/test/addons/zlib-binding/binding.gyp +++ b/test/addons/zlib-binding/binding.gyp @@ -2,12 +2,19 @@ 'targets': [ { 'target_name': 'binding', - 'variables': { - # Skip this building on IBM i. - 'aix_variant_name': ' { + res.write('hello'); + setTimeout(() => { + res.end(' world!'); + }, 1000); +}); + +server.listen(0, () => { + assert.strictEqual(executionAsyncResource(), hooked[executionAsyncId()]); + http.get({ port: server.address().port }, (res) => { + assert.strictEqual(executionAsyncResource(), hooked[executionAsyncId()]); + res.on('data', () => { + assert.strictEqual(executionAsyncResource(), hooked[executionAsyncId()]); + }); + res.on('end', () => { + assert.strictEqual(executionAsyncResource(), hooked[executionAsyncId()]); + server.close(); + }); + }); +}); diff --git a/test/async-hooks/test-async-exec-resource-http.js b/test/async-hooks/test-async-exec-resource-http.js new file mode 100644 index 00000000000000..ecc654bea0ab79 --- /dev/null +++ b/test/async-hooks/test-async-exec-resource-http.js @@ -0,0 +1,30 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const { + executionAsyncResource, + executionAsyncId, + createHook, +} = require('async_hooks'); +const http = require('http'); + +const hooked = {}; +createHook({ + init(asyncId, type, triggerAsyncId, resource) { + hooked[asyncId] = resource; + } +}).enable(); + +const server = http.createServer((req, res) => { + res.end('ok'); +}); + +server.listen(0, () => { + assert.strictEqual(executionAsyncResource(), hooked[executionAsyncId()]); + + http.get({ port: server.address().port }, () => { + assert.strictEqual(executionAsyncResource(), hooked[executionAsyncId()]); + server.close(); + }); +}); diff --git a/test/async-hooks/test-async-exec-resource-match.js b/test/async-hooks/test-async-exec-resource-match.js new file mode 100644 index 00000000000000..f5ea2c2b13965a --- /dev/null +++ b/test/async-hooks/test-async-exec-resource-match.js @@ -0,0 +1,62 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { readFile } = require('fs'); +const { + createHook, + executionAsyncResource, + AsyncResource +} = require('async_hooks'); + +// Ignore any asyncIds created before our hook is active. +let firstSeenAsyncId = -1; +const idResMap = new Map(); +const numExpectedCalls = 5; + +createHook({ + init: common.mustCallAtLeast( + (asyncId, type, triggerId, resource) => { + if (firstSeenAsyncId === -1) { + firstSeenAsyncId = asyncId; + } + assert.ok(idResMap.get(asyncId) === undefined); + idResMap.set(asyncId, resource); + }, numExpectedCalls), + before(asyncId) { + if (asyncId >= firstSeenAsyncId) { + beforeHook(asyncId); + } + }, + after(asyncId) { + if (asyncId >= firstSeenAsyncId) { + afterHook(asyncId); + } + } +}).enable(); + +const beforeHook = common.mustCallAtLeast( + (asyncId) => { + const res = idResMap.get(asyncId); + assert.ok(res !== undefined); + const execRes = executionAsyncResource(); + assert.ok(execRes === res, 'resource mismatch in before'); + }, numExpectedCalls); + +const afterHook = common.mustCallAtLeast( + (asyncId) => { + const res = idResMap.get(asyncId); + assert.ok(res !== undefined); + const execRes = executionAsyncResource(); + assert.ok(execRes === res, 'resource mismatch in after'); + }, numExpectedCalls); + +const res = new AsyncResource('TheResource'); +const initRes = idResMap.get(res.asyncId()); +assert.ok(initRes === res, 'resource mismatch in init'); +res.runInAsyncScope(common.mustCall(() => { + const execRes = executionAsyncResource(); + assert.ok(execRes === res, 'resource mismatch in cb'); +})); + +readFile(__filename, common.mustCall()); diff --git a/test/async-hooks/test-async-local-storage-args.js b/test/async-hooks/test-async-local-storage-args.js new file mode 100644 index 00000000000000..71853ecc4af0eb --- /dev/null +++ b/test/async-hooks/test-async-local-storage-args.js @@ -0,0 +1,13 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { AsyncLocalStorage } = require('async_hooks'); + +const asyncLocalStorage = new AsyncLocalStorage(); + +asyncLocalStorage.run({}, (runArg) => { + assert.strictEqual(runArg, 'foo'); + asyncLocalStorage.exit((exitArg) => { + assert.strictEqual(exitArg, 'bar'); + }, 'bar'); +}, 'foo'); diff --git a/test/async-hooks/test-async-local-storage-async-await.js b/test/async-hooks/test-async-local-storage-async-await.js new file mode 100644 index 00000000000000..64333eee938f3d --- /dev/null +++ b/test/async-hooks/test-async-local-storage-async-await.js @@ -0,0 +1,19 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { AsyncLocalStorage } = require('async_hooks'); + +const asyncLocalStorage = new AsyncLocalStorage(); + +async function test() { + asyncLocalStorage.getStore().set('foo', 'bar'); + await Promise.resolve(); + assert.strictEqual(asyncLocalStorage.getStore().get('foo'), 'bar'); +} + +async function main() { + await asyncLocalStorage.run(new Map(), test); + assert.strictEqual(asyncLocalStorage.getStore(), undefined); +} + +main(); diff --git a/test/async-hooks/test-async-local-storage-async-functions.js b/test/async-hooks/test-async-local-storage-async-functions.js new file mode 100644 index 00000000000000..ea186e9f68da4e --- /dev/null +++ b/test/async-hooks/test-async-local-storage-async-functions.js @@ -0,0 +1,27 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { AsyncLocalStorage } = require('async_hooks'); + +async function foo() {} + +const asyncLocalStorage = new AsyncLocalStorage(); + +async function testOut() { + await foo(); + assert.strictEqual(asyncLocalStorage.getStore(), undefined); +} + +async function testAwait() { + await foo(); + assert.notStrictEqual(asyncLocalStorage.getStore(), undefined); + assert.strictEqual(asyncLocalStorage.getStore().get('key'), 'value'); + await asyncLocalStorage.exit(testOut); +} + +asyncLocalStorage.run(new Map(), () => { + const store = asyncLocalStorage.getStore(); + store.set('key', 'value'); + testAwait(); // should not reject +}); +assert.strictEqual(asyncLocalStorage.getStore(), undefined); diff --git a/test/async-hooks/test-async-local-storage-enable-disable.js b/test/async-hooks/test-async-local-storage-enable-disable.js new file mode 100644 index 00000000000000..15ab2f5d9ebbb2 --- /dev/null +++ b/test/async-hooks/test-async-local-storage-enable-disable.js @@ -0,0 +1,32 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { AsyncLocalStorage } = require('async_hooks'); + +const asyncLocalStorage = new AsyncLocalStorage(); + +asyncLocalStorage.run(new Map(), () => { + asyncLocalStorage.getStore().set('foo', 'bar'); + process.nextTick(() => { + assert.strictEqual(asyncLocalStorage.getStore().get('foo'), 'bar'); + process.nextTick(() => { + assert.strictEqual(asyncLocalStorage.getStore(), undefined); + }); + + asyncLocalStorage.disable(); + assert.strictEqual(asyncLocalStorage.getStore(), undefined); + + // Calls to exit() should not mess with enabled status + asyncLocalStorage.exit(() => { + assert.strictEqual(asyncLocalStorage.getStore(), undefined); + }); + assert.strictEqual(asyncLocalStorage.getStore(), undefined); + + process.nextTick(() => { + assert.strictEqual(asyncLocalStorage.getStore(), undefined); + asyncLocalStorage.run(new Map(), () => { + assert.notStrictEqual(asyncLocalStorage.getStore(), undefined); + }); + }); + }); +}); diff --git a/test/async-hooks/test-async-local-storage-enter-with.js b/test/async-hooks/test-async-local-storage-enter-with.js new file mode 100644 index 00000000000000..736dd83f853763 --- /dev/null +++ b/test/async-hooks/test-async-local-storage-enter-with.js @@ -0,0 +1,20 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { AsyncLocalStorage } = require('async_hooks'); + +const asyncLocalStorage = new AsyncLocalStorage(); + +setImmediate(() => { + const store = { foo: 'bar' }; + asyncLocalStorage.enterWith(store); + + assert.strictEqual(asyncLocalStorage.getStore(), store); + setTimeout(() => { + assert.strictEqual(asyncLocalStorage.getStore(), store); + }, 10); +}); + +setTimeout(() => { + assert.strictEqual(asyncLocalStorage.getStore(), undefined); +}, 10); diff --git a/test/async-hooks/test-async-local-storage-errors.js b/test/async-hooks/test-async-local-storage-errors.js new file mode 100644 index 00000000000000..0dd5754e02cbd9 --- /dev/null +++ b/test/async-hooks/test-async-local-storage-errors.js @@ -0,0 +1,31 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { AsyncLocalStorage } = require('async_hooks'); + +// case 2 using *AndReturn calls (dual behaviors) +const asyncLocalStorage = new AsyncLocalStorage(); + +let i = 0; +process.setUncaughtExceptionCaptureCallback((err) => { + ++i; + assert.strictEqual(err.message, 'err2'); + assert.strictEqual(asyncLocalStorage.getStore().get('hello'), 'node'); +}); + +try { + asyncLocalStorage.run(new Map(), () => { + const store = asyncLocalStorage.getStore(); + store.set('hello', 'node'); + setTimeout(() => { + process.nextTick(() => { + assert.strictEqual(i, 1); + }); + throw new Error('err2'); + }, 0); + throw new Error('err1'); + }); +} catch (e) { + assert.strictEqual(e.message, 'err1'); + assert.strictEqual(asyncLocalStorage.getStore(), undefined); +} diff --git a/test/async-hooks/test-async-local-storage-gcable.js b/test/async-hooks/test-async-local-storage-gcable.js new file mode 100644 index 00000000000000..f0d23a0d22793b --- /dev/null +++ b/test/async-hooks/test-async-local-storage-gcable.js @@ -0,0 +1,20 @@ +'use strict'; +// Flags: --expose_gc + +// This test ensures that AsyncLocalStorage gets gced once it was disabled +// and no strong references remain in userland. + +const common = require('../common'); +const { AsyncLocalStorage } = require('async_hooks'); +const onGC = require('../common/ongc'); + +let asyncLocalStorage = new AsyncLocalStorage(); + +asyncLocalStorage.run({}, () => { + asyncLocalStorage.disable(); + + onGC(asyncLocalStorage, { ongc: common.mustCall() }); +}); + +asyncLocalStorage = null; +global.gc(); diff --git a/test/async-hooks/test-async-local-storage-http.js b/test/async-hooks/test-async-local-storage-http.js new file mode 100644 index 00000000000000..c7514d8280df35 --- /dev/null +++ b/test/async-hooks/test-async-local-storage-http.js @@ -0,0 +1,21 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { AsyncLocalStorage } = require('async_hooks'); +const http = require('http'); + +const asyncLocalStorage = new AsyncLocalStorage(); +const server = http.createServer((req, res) => { + res.end('ok'); +}); + +server.listen(0, () => { + asyncLocalStorage.run(new Map(), () => { + const store = asyncLocalStorage.getStore(); + store.set('hello', 'world'); + http.get({ host: 'localhost', port: server.address().port }, () => { + assert.strictEqual(asyncLocalStorage.getStore().get('hello'), 'world'); + server.close(); + }); + }); +}); diff --git a/test/async-hooks/test-async-local-storage-misc-stores.js b/test/async-hooks/test-async-local-storage-misc-stores.js new file mode 100644 index 00000000000000..fbbbb52a5d7a6b --- /dev/null +++ b/test/async-hooks/test-async-local-storage-misc-stores.js @@ -0,0 +1,15 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { AsyncLocalStorage } = require('async_hooks'); + +const asyncLocalStorage = new AsyncLocalStorage(); + +asyncLocalStorage.run('hello node', () => { + assert.strictEqual(asyncLocalStorage.getStore(), 'hello node'); +}); + +const runStore = { hello: 'node' }; +asyncLocalStorage.run(runStore, () => { + assert.strictEqual(asyncLocalStorage.getStore(), runStore); +}); diff --git a/test/async-hooks/test-async-local-storage-nested.js b/test/async-hooks/test-async-local-storage-nested.js new file mode 100644 index 00000000000000..870c294b74d22a --- /dev/null +++ b/test/async-hooks/test-async-local-storage-nested.js @@ -0,0 +1,25 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { AsyncLocalStorage } = require('async_hooks'); + +const asyncLocalStorage = new AsyncLocalStorage(); +const outer = {}; +const inner = {}; + +function testInner() { + assert.strictEqual(asyncLocalStorage.getStore(), outer); + + asyncLocalStorage.run(inner, () => { + assert.strictEqual(asyncLocalStorage.getStore(), inner); + }); + assert.strictEqual(asyncLocalStorage.getStore(), outer); + + asyncLocalStorage.exit(() => { + assert.strictEqual(asyncLocalStorage.getStore(), undefined); + }); + assert.strictEqual(asyncLocalStorage.getStore(), outer); +} + +asyncLocalStorage.run(outer, testInner); +assert.strictEqual(asyncLocalStorage.getStore(), undefined); diff --git a/test/async-hooks/test-async-local-storage-no-mix-contexts.js b/test/async-hooks/test-async-local-storage-no-mix-contexts.js new file mode 100644 index 00000000000000..3a6b352c94ceee --- /dev/null +++ b/test/async-hooks/test-async-local-storage-no-mix-contexts.js @@ -0,0 +1,38 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { AsyncLocalStorage } = require('async_hooks'); + +const asyncLocalStorage = new AsyncLocalStorage(); +const asyncLocalStorage2 = new AsyncLocalStorage(); + +setTimeout(() => { + asyncLocalStorage.run(new Map(), () => { + asyncLocalStorage2.run(new Map(), () => { + const store = asyncLocalStorage.getStore(); + const store2 = asyncLocalStorage2.getStore(); + store.set('hello', 'world'); + store2.set('hello', 'foo'); + setTimeout(() => { + assert.strictEqual(asyncLocalStorage.getStore().get('hello'), 'world'); + assert.strictEqual(asyncLocalStorage2.getStore().get('hello'), 'foo'); + asyncLocalStorage.exit(() => { + assert.strictEqual(asyncLocalStorage.getStore(), undefined); + assert.strictEqual(asyncLocalStorage2.getStore().get('hello'), 'foo'); + }); + assert.strictEqual(asyncLocalStorage.getStore().get('hello'), 'world'); + assert.strictEqual(asyncLocalStorage2.getStore().get('hello'), 'foo'); + }, 200); + }); + }); +}, 100); + +setTimeout(() => { + asyncLocalStorage.run(new Map(), () => { + const store = asyncLocalStorage.getStore(); + store.set('hello', 'earth'); + setTimeout(() => { + assert.strictEqual(asyncLocalStorage.getStore().get('hello'), 'earth'); + }, 100); + }); +}, 100); diff --git a/test/async-hooks/test-async-local-storage-promises.js b/test/async-hooks/test-async-local-storage-promises.js new file mode 100644 index 00000000000000..0e4968534bc3e2 --- /dev/null +++ b/test/async-hooks/test-async-local-storage-promises.js @@ -0,0 +1,28 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { AsyncLocalStorage } = require('async_hooks'); + +async function main() { + const asyncLocalStorage = new AsyncLocalStorage(); + const err = new Error(); + const next = () => Promise.resolve() + .then(() => { + assert.strictEqual(asyncLocalStorage.getStore().get('a'), 1); + throw err; + }); + await new Promise((resolve, reject) => { + asyncLocalStorage.run(new Map(), () => { + const store = asyncLocalStorage.getStore(); + store.set('a', 1); + next().then(resolve, reject); + }); + }) + .catch((e) => { + assert.strictEqual(asyncLocalStorage.getStore(), undefined); + assert.strictEqual(e, err); + }); + assert.strictEqual(asyncLocalStorage.getStore(), undefined); +} + +main(); diff --git a/test/async-hooks/test-async-local-storage-run-resource.js b/test/async-hooks/test-async-local-storage-run-resource.js new file mode 100644 index 00000000000000..9a7479f699246c --- /dev/null +++ b/test/async-hooks/test-async-local-storage-run-resource.js @@ -0,0 +1,17 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { + AsyncLocalStorage, + executionAsyncResource +} = require('async_hooks'); + +const asyncLocalStorage = new AsyncLocalStorage(); + +const outerResource = executionAsyncResource(); + +asyncLocalStorage.run(new Map(), () => { + assert.notStrictEqual(executionAsyncResource(), outerResource); +}); + +assert.strictEqual(executionAsyncResource(), outerResource); diff --git a/test/benchmark/test-benchmark-assert.js b/test/benchmark/test-benchmark-assert.js index 8a8ba0244489e5..5ec2319c28a15d 100644 --- a/test/benchmark/test-benchmark-assert.js +++ b/test/benchmark/test-benchmark-assert.js @@ -7,15 +7,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark( - 'assert', - [ - 'strict=1', - 'len=1', - 'method=', - 'n=1', - 'primitive=null', - 'size=1', - 'type=Int8Array' - ] -); +runBenchmark('assert'); diff --git a/test/benchmark/test-benchmark-async-hooks.js b/test/benchmark/test-benchmark-async-hooks.js index 9951d8c9330804..c9ea2c1e86dbdf 100644 --- a/test/benchmark/test-benchmark-async-hooks.js +++ b/test/benchmark/test-benchmark-async-hooks.js @@ -10,11 +10,4 @@ if (!common.enoughTestMem) const runBenchmark = require('../common/benchmark'); -runBenchmark('async_hooks', - [ - 'asyncHooks=all', - 'connections=50', - 'method=trackingDisabled', - 'n=10' - ], - {}); +runBenchmark('async_hooks'); diff --git a/test/benchmark/test-benchmark-buffer.js b/test/benchmark/test-benchmark-buffer.js index 57130ffb08ba3d..af93842b0b92dd 100644 --- a/test/benchmark/test-benchmark-buffer.js +++ b/test/benchmark/test-benchmark-buffer.js @@ -4,30 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('buffers', - [ - 'aligned=true', - 'args=1', - 'buffer=fast', - 'bytes=0', - 'byteLength=1', - 'charsPerLine=6', - 'difflen=false', - 'encoding=utf8', - 'endian=BE', - 'extraSize=1', - 'len=256', - 'linesCount=1', - 'method=', - 'n=1', - 'partial=true', - 'pieces=1', - 'pieceSize=1', - 'search=@', - 'size=1', - 'source=array', - 'type=', - 'value=0', - 'withTotalLength=0' - ], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('buffers', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-child-process.js b/test/benchmark/test-benchmark-child-process.js index 365777069bc4cf..043620de12f165 100644 --- a/test/benchmark/test-benchmark-child-process.js +++ b/test/benchmark/test-benchmark-child-process.js @@ -4,12 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('child_process', - [ - 'dur=0', - 'n=1', - 'len=1', - 'params=1', - 'methodName=execSync', - ], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('child_process', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-cluster.js b/test/benchmark/test-benchmark-cluster.js index 26df7ec239a221..b24aced5d58dc3 100644 --- a/test/benchmark/test-benchmark-cluster.js +++ b/test/benchmark/test-benchmark-cluster.js @@ -4,9 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('cluster', [ - 'n=1', - 'payload=string', - 'sendsPerBroadcast=1', - 'serialization=json', -]); +runBenchmark('cluster'); diff --git a/test/benchmark/test-benchmark-crypto.js b/test/benchmark/test-benchmark-crypto.js index 6ba71471cf4be2..7f6988acf234d8 100644 --- a/test/benchmark/test-benchmark-crypto.js +++ b/test/benchmark/test-benchmark-crypto.js @@ -10,18 +10,4 @@ if (common.hasFipsCrypto) const runBenchmark = require('../common/benchmark'); -runBenchmark('crypto', - [ - 'algo=sha256', - 'api=stream', - 'cipher=', - 'keylen=1024', - 'len=1', - 'n=1', - 'out=buffer', - 'size=1', - 'type=buf', - 'v=crypto', - 'writes=1', - ], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('crypto', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-dgram.js b/test/benchmark/test-benchmark-dgram.js index 8c93cd5a0c9239..ceafdd77a2aa80 100644 --- a/test/benchmark/test-benchmark-dgram.js +++ b/test/benchmark/test-benchmark-dgram.js @@ -4,14 +4,7 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -// Because the dgram benchmarks use hardcoded ports, this should be in -// sequential rather than parallel to make sure it does not conflict with -// tests that choose random available ports. +// Dgram benchmarks use hardcoded ports. Thus, this test can not be run in +// parallel with tests that choose random ports. -runBenchmark('dgram', ['address=true', - 'chunks=2', - 'dur=0.1', - 'len=1', - 'n=1', - 'num=1', - 'type=send']); +runBenchmark('dgram'); diff --git a/test/benchmark/test-benchmark-dns.js b/test/benchmark/test-benchmark-dns.js index 811e9a44b9e358..331a4c8ff0d85d 100644 --- a/test/benchmark/test-benchmark-dns.js +++ b/test/benchmark/test-benchmark-dns.js @@ -4,6 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -const env = { ...process.env, NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }; - -runBenchmark('dns', ['n=1', 'all=false', 'name=127.0.0.1'], env); +runBenchmark('dns', { ...process.env, NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-domain.js b/test/benchmark/test-benchmark-domain.js index e7d8b60b716441..5ebbfc5ea3b4db 100644 --- a/test/benchmark/test-benchmark-domain.js +++ b/test/benchmark/test-benchmark-domain.js @@ -4,4 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('domain', ['n=1', 'args=0']); +runBenchmark('domain'); diff --git a/test/benchmark/test-benchmark-es.js b/test/benchmark/test-benchmark-es.js index 47fe4ab3f91a63..6886b3ce925746 100644 --- a/test/benchmark/test-benchmark-es.js +++ b/test/benchmark/test-benchmark-es.js @@ -4,15 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('es', - [ - 'method=', - 'count=1', - 'context=null', - 'rest=0', - 'mode=', - 'n=1', - 'encoding=ascii', - 'size=1e1' - ], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('es', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-events.js b/test/benchmark/test-benchmark-events.js index 06be60a84abb5b..53de4897dd75d2 100644 --- a/test/benchmark/test-benchmark-events.js +++ b/test/benchmark/test-benchmark-events.js @@ -4,6 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('events', - ['argc=0', 'listeners=1', 'n=1'], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('events', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-fs.js b/test/benchmark/test-benchmark-fs.js index a072124ef85bee..4b9fde8b6620d6 100644 --- a/test/benchmark/test-benchmark-fs.js +++ b/test/benchmark/test-benchmark-fs.js @@ -6,19 +6,7 @@ const runBenchmark = require('../common/benchmark'); const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); -runBenchmark('fs', [ - 'bufferSize=32', - 'concurrent=1', - 'dir=.github', - 'dur=0.1', - 'encodingType=buf', - 'filesize=1024', - 'len=1024', - 'mode=callback', - 'n=1', - 'pathType=relative', - 'size=1', - 'statSyncType=fstatSync', - 'statType=fstat', - 'withFileTypes=false', -], { NODE_TMPDIR: tmpdir.path, NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('fs', { + NODE_TMPDIR: tmpdir.path, + NODEJS_BENCHMARK_ZERO_ALLOWED: 1 +}); diff --git a/test/benchmark/test-benchmark-http.js b/test/benchmark/test-benchmark-http.js index 43531ec51cced7..a3d92c7e987f58 100644 --- a/test/benchmark/test-benchmark-http.js +++ b/test/benchmark/test-benchmark-http.js @@ -11,27 +11,4 @@ if (!common.enoughTestMem) const runBenchmark = require('../common/benchmark'); -runBenchmark('http', - [ - 'benchmarker=test-double-http', - 'arg=string', - 'c=1', - 'chunkedEnc=true', - 'chunks=0', - 'dur=0.1', - 'e=0', - 'input=keep-alive', - 'key=""', - 'len=1', - 'method=write', - 'n=1', - 'res=normal', - 'type=asc', - 'url=long', - 'value=X-Powered-By', - 'w=0', - ], - { - NODEJS_BENCHMARK_ZERO_ALLOWED: 1, - duration: 0 - }); +runBenchmark('http', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-http2.js b/test/benchmark/test-benchmark-http2.js index 1668a7b87fe643..25dd771076e758 100644 --- a/test/benchmark/test-benchmark-http2.js +++ b/test/benchmark/test-benchmark-http2.js @@ -13,17 +13,4 @@ if (!common.enoughTestMem) const runBenchmark = require('../common/benchmark'); -runBenchmark('http2', - [ - 'benchmarker=test-double-http2', - 'clients=1', - 'length=65536', - 'n=1', - 'nheaders=0', - 'requests=1', - 'streams=1' - ], - { - NODEJS_BENCHMARK_ZERO_ALLOWED: 1, - duration: 0 - }); +runBenchmark('http2', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-misc.js b/test/benchmark/test-benchmark-misc.js index 13bd41e54016f5..30707bfaf7366e 100644 --- a/test/benchmark/test-benchmark-misc.js +++ b/test/benchmark/test-benchmark-misc.js @@ -4,14 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('misc', [ - 'concat=0', - 'dur=0.1', - 'method=', - 'n=1', - 'type=', - 'code=1', - 'val=magyarország.icom.museum', - 'script=test/fixtures/semicolon', - 'mode=worker' -], { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('misc', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-module.js b/test/benchmark/test-benchmark-module.js index 4d49ed249c392f..da8e108d53e19f 100644 --- a/test/benchmark/test-benchmark-module.js +++ b/test/benchmark/test-benchmark-module.js @@ -4,12 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('module', [ - 'cache=true', - 'dir=rel', - 'ext=', - 'fullPath=true', - 'n=1', - 'name=/', - 'useCache=true', -]); +runBenchmark('module'); diff --git a/test/benchmark/test-benchmark-napi.js b/test/benchmark/test-benchmark-napi.js index 1a1ff23d60c5c0..5c6a8aa01187ea 100644 --- a/test/benchmark/test-benchmark-napi.js +++ b/test/benchmark/test-benchmark-napi.js @@ -15,10 +15,4 @@ if (process.features.debug) { } const runBenchmark = require('../common/benchmark'); -runBenchmark('napi', - [ - 'n=1', - 'engine=v8', - 'type=String' - ], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('napi', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-net.js b/test/benchmark/test-benchmark-net.js index f51c615b5df4f0..df8ea8011693ee 100644 --- a/test/benchmark/test-benchmark-net.js +++ b/test/benchmark/test-benchmark-net.js @@ -8,13 +8,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('net', - [ - 'dur=0', - 'len=1024', - 'recvbufgenfn=false', - 'recvbuflen=0', - 'sendchunklen=256', - 'type=buf' - ], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('net', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-os.js b/test/benchmark/test-benchmark-os.js index 836e0e650483f1..dbedd7f582d90b 100644 --- a/test/benchmark/test-benchmark-os.js +++ b/test/benchmark/test-benchmark-os.js @@ -4,4 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('os', ['n=1']); +runBenchmark('os'); diff --git a/test/benchmark/test-benchmark-path.js b/test/benchmark/test-benchmark-path.js index 890fd7ae41f548..3bca4f2a11bd9d 100644 --- a/test/benchmark/test-benchmark-path.js +++ b/test/benchmark/test-benchmark-path.js @@ -4,11 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('path', - [ - 'n=1', - 'path=', - 'pathext=', - 'paths=', - 'props=' - ], { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('path', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-process.js b/test/benchmark/test-benchmark-process.js index a73fc075bfcfa6..c6687f3023412b 100644 --- a/test/benchmark/test-benchmark-process.js +++ b/test/benchmark/test-benchmark-process.js @@ -4,9 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('process', - [ - 'n=1', - 'type=raw', - 'operation=enumerate', - ], { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('process', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-querystring.js b/test/benchmark/test-benchmark-querystring.js index 77d0ac99ff97d8..6fee9bb39143ab 100644 --- a/test/benchmark/test-benchmark-querystring.js +++ b/test/benchmark/test-benchmark-querystring.js @@ -4,9 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('querystring', - [ 'n=1', - 'input="there is nothing to unescape here"', - 'type=noencode' - ], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('querystring', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-streams.js b/test/benchmark/test-benchmark-streams.js index fa61b8dc4e0ae7..68c8478a7398c5 100644 --- a/test/benchmark/test-benchmark-streams.js +++ b/test/benchmark/test-benchmark-streams.js @@ -4,13 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('streams', - [ - 'kind=duplex', - 'n=1', - 'sync=no', - 'writev=no', - 'callback=no', - 'type=buffer', - ], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('streams', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-string_decoder.js b/test/benchmark/test-benchmark-string_decoder.js index f2fd6abe4b8f5f..721529e5ae64b1 100644 --- a/test/benchmark/test-benchmark-string_decoder.js +++ b/test/benchmark/test-benchmark-string_decoder.js @@ -4,7 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('string_decoder', ['chunkLen=16', - 'encoding=utf8', - 'inLen=32', - 'n=1']); +runBenchmark('string_decoder'); diff --git a/test/benchmark/test-benchmark-timers.js b/test/benchmark/test-benchmark-timers.js index af3c49bd714742..db4927ab32ea19 100644 --- a/test/benchmark/test-benchmark-timers.js +++ b/test/benchmark/test-benchmark-timers.js @@ -4,10 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('timers', - [ - 'direction=start', - 'n=1', - 'type=depth', - ], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('timers', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-tls.js b/test/benchmark/test-benchmark-tls.js index 264fa08d396be7..c9a87c15770d63 100644 --- a/test/benchmark/test-benchmark-tls.js +++ b/test/benchmark/test-benchmark-tls.js @@ -14,16 +14,4 @@ if (!common.enoughTestMem) const runBenchmark = require('../common/benchmark'); -runBenchmark('tls', - [ - 'concurrency=1', - 'dur=0.1', - 'n=1', - 'size=1024', - 'securing=SecurePair', - 'type=buf' - ], - { - NODEJS_BENCHMARK_ZERO_ALLOWED: 1, - duration: 0 - }); +runBenchmark('tls', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-url.js b/test/benchmark/test-benchmark-url.js index 8560c918fd1c69..664e7c4d8dc827 100644 --- a/test/benchmark/test-benchmark-url.js +++ b/test/benchmark/test-benchmark-url.js @@ -4,22 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('url', - [ - 'method=legacy', - 'e=0', - 'loopMethod=forEach', - 'accessMethod=get', - 'type=short', - 'searchParam=noencode', - 'href=short', - 'input=short', - 'domain=empty', - 'path=up', - 'to=ascii', - 'prop=href', - 'n=1', - 'param=one', - 'withBase=false' - ], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('url', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-util.js b/test/benchmark/test-benchmark-util.js index b66d4fdb9b4cf6..d0c16c623268a6 100644 --- a/test/benchmark/test-benchmark-util.js +++ b/test/benchmark/test-benchmark-util.js @@ -4,17 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('util', - ['argument=false', - 'input=', - 'method=Array', - 'n=1', - 'option=none', - 'pos=start', - 'size=1', - 'type=', - 'len=1', - 'version=native', - 'isProxy=1', - 'showProxy=1'], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('util', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-v8.js b/test/benchmark/test-benchmark-v8.js index 22861785db9c05..efeaac8328c76d 100644 --- a/test/benchmark/test-benchmark-v8.js +++ b/test/benchmark/test-benchmark-v8.js @@ -4,9 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('v8', - [ - 'method=getHeapStatistics', - 'n=1' - ], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('v8', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-vm.js b/test/benchmark/test-benchmark-vm.js index 79ab6a03402522..e9c4e3f1389f69 100644 --- a/test/benchmark/test-benchmark-vm.js +++ b/test/benchmark/test-benchmark-vm.js @@ -4,10 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('vm', - [ - 'breakOnSigint=0', - 'withSigintListener=0', - 'n=1' - ], - { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +runBenchmark('vm', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-worker.js b/test/benchmark/test-benchmark-worker.js index ae9a8a6701ae4a..a4319d4face623 100644 --- a/test/benchmark/test-benchmark-worker.js +++ b/test/benchmark/test-benchmark-worker.js @@ -11,13 +11,4 @@ if (!common.enoughTestMem) const runBenchmark = require('../common/benchmark'); -runBenchmark('worker', - [ - 'n=1', - 'sendsPerBroadcast=1', - 'workers=1', - 'payload=string' - ], - { - NODEJS_BENCHMARK_ZERO_ALLOWED: 1 - }); +runBenchmark('worker', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/benchmark/test-benchmark-zlib.js b/test/benchmark/test-benchmark-zlib.js index 6f8579b324b03c..e3c4723aa9722f 100644 --- a/test/benchmark/test-benchmark-zlib.js +++ b/test/benchmark/test-benchmark-zlib.js @@ -4,16 +4,4 @@ require('../common'); const runBenchmark = require('../common/benchmark'); -runBenchmark('zlib', - [ - 'algorithm=brotli', - 'method=deflate', - 'n=1', - 'options=true', - 'type=Deflate', - 'inputLen=1024', - 'duration=0.001' - ], - { - 'NODEJS_BENCHMARK_ZERO_ALLOWED': 1 - }); +runBenchmark('zlib', { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/cctest/test_aliased_buffer.cc b/test/cctest/test_aliased_buffer.cc index ba947700c1bf27..4dab70d0b576cb 100644 --- a/test/cctest/test_aliased_buffer.cc +++ b/test/cctest/test_aliased_buffer.cc @@ -1,4 +1,11 @@ +#if (__GNUC__ >= 8) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif #include "v8.h" +#if (__GNUC__ >= 8) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif #include "aliased_buffer.h" #include "node_test_fixture.h" diff --git a/test/cctest/test_report_util.cc b/test/cctest/test_json_utils.cc similarity index 90% rename from test/cctest/test_report_util.cc rename to test/cctest/test_json_utils.cc index e32558ef75b5e8..06a9074a61baf1 100644 --- a/test/cctest/test_report_util.cc +++ b/test/cctest/test_json_utils.cc @@ -1,9 +1,9 @@ -#include "node_report.h" +#include "json_utils.h" #include "gtest/gtest.h" -TEST(ReportUtilTest, EscapeJsonChars) { - using report::EscapeJsonChars; +TEST(JSONUtilsTest, EscapeJsonChars) { + using node::EscapeJsonChars; EXPECT_EQ("abc", EscapeJsonChars("abc")); EXPECT_EQ("abc\\n", EscapeJsonChars("abc\n")); EXPECT_EQ("abc\\nabc", EscapeJsonChars("abc\nabc")); diff --git a/test/cctest/test_sockaddr.cc b/test/cctest/test_sockaddr.cc new file mode 100644 index 00000000000000..8c23463f11d2d1 --- /dev/null +++ b/test/cctest/test_sockaddr.cc @@ -0,0 +1,57 @@ +#include "node_sockaddr-inl.h" +#include "gtest/gtest.h" + +using node::SocketAddress; + +TEST(SocketAddress, SocketAddress) { + CHECK(SocketAddress::is_numeric_host("123.123.123.123")); + CHECK(!SocketAddress::is_numeric_host("localhost")); + + sockaddr_storage storage; + sockaddr_storage storage2; + SocketAddress::ToSockAddr(AF_INET, "123.123.123.123", 443, &storage); + SocketAddress::ToSockAddr(AF_INET, "1.1.1.1", 80, &storage2); + + SocketAddress addr(reinterpret_cast(&storage)); + SocketAddress addr2(reinterpret_cast(&storage2)); + + CHECK_EQ(addr.length(), sizeof(sockaddr_in)); + CHECK_EQ(addr.family(), AF_INET); + CHECK_EQ(addr.address(), "123.123.123.123"); + CHECK_EQ(addr.port(), 443); + + addr.set_flow_label(12345); + CHECK_EQ(addr.flow_label(), 0); + + CHECK_NE(addr, addr2); + CHECK_EQ(addr, addr); + + CHECK_EQ(SocketAddress::Hash()(addr), SocketAddress::Hash()(addr)); + CHECK_NE(SocketAddress::Hash()(addr), SocketAddress::Hash()(addr2)); + + addr.Update(reinterpret_cast(&storage2), sizeof(sockaddr_in)); + CHECK_EQ(addr.length(), sizeof(sockaddr_in)); + CHECK_EQ(addr.family(), AF_INET); + CHECK_EQ(addr.address(), "1.1.1.1"); + CHECK_EQ(addr.port(), 80); + + SocketAddress::Map map; + map[addr]++; + map[addr]++; + CHECK_EQ(map[addr], 2); +} + +TEST(SocketAddress, SocketAddressIPv6) { + sockaddr_storage storage; + SocketAddress::ToSockAddr(AF_INET6, "::1", 443, &storage); + + SocketAddress addr(reinterpret_cast(&storage)); + + CHECK_EQ(addr.length(), sizeof(sockaddr_in6)); + CHECK_EQ(addr.family(), AF_INET6); + CHECK_EQ(addr.address(), "::1"); + CHECK_EQ(addr.port(), 443); + + addr.set_flow_label(12345); + CHECK_EQ(addr.flow_label(), 12345); +} diff --git a/test/common/benchmark.js b/test/common/benchmark.js index f630bb9d0e6fd8..56351c92505efa 100644 --- a/test/common/benchmark.js +++ b/test/common/benchmark.js @@ -8,13 +8,8 @@ const path = require('path'); const runjs = path.join(__dirname, '..', '..', 'benchmark', 'run.js'); -function runBenchmark(name, args, env) { - const argv = []; - - for (let i = 0; i < args.length; i++) { - argv.push('--set'); - argv.push(args[i]); - } +function runBenchmark(name, env) { + const argv = ['test']; argv.push(name); diff --git a/test/common/heap.js b/test/common/heap.js index 030ea773404d14..a6232177ba9fd3 100644 --- a/test/common/heap.js +++ b/test/common/heap.js @@ -14,8 +14,7 @@ try { const { buildEmbedderGraph } = internalBinding('heap_utils'); const { getHeapSnapshot } = require('v8'); -function createJSHeapSnapshot() { - const stream = getHeapSnapshot(); +function createJSHeapSnapshot(stream = getHeapSnapshot()) { stream.pause(); const dump = JSON.parse(stream.read()); const meta = dump.snapshot.meta; @@ -106,8 +105,8 @@ function isEdge(edge, { node_name, edge_name }) { } class State { - constructor() { - this.snapshot = createJSHeapSnapshot(); + constructor(stream) { + this.snapshot = createJSHeapSnapshot(stream); this.embedderGraph = buildEmbedderGraph(); } @@ -189,8 +188,8 @@ class State { } } -function recordState() { - return new State(); +function recordState(stream = undefined) { + return new State(stream); } function validateSnapshotNodes(...args) { diff --git a/test/common/index.js b/test/common/index.js index e527ec5971ac29..06042e260fb30e 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -139,19 +139,22 @@ if (process.env.NODE_TEST_WITH_ASYNC_HOOKS) { process._rawDebug(); throw new Error(`same id added to destroy list twice (${id})`); } - destroyListList[id] = new Error().stack; + destroyListList[id] = util.inspect(new Error()); _queueDestroyAsyncId(id); }; require('async_hooks').createHook({ - init(id, ty, tr, r) { + init(id, ty, tr, resource) { if (initHandles[id]) { process._rawDebug( - `Is same resource: ${r === initHandles[id].resource}`); + `Is same resource: ${resource === initHandles[id].resource}`); process._rawDebug(`Previous stack:\n${initHandles[id].stack}\n`); throw new Error(`init called twice for same id (${id})`); } - initHandles[id] = { resource: r, stack: new Error().stack.substr(6) }; + initHandles[id] = { + resource, + stack: util.inspect(new Error()).substr(6) + }; }, before() { }, after() { }, @@ -161,7 +164,7 @@ if (process.env.NODE_TEST_WITH_ASYNC_HOOKS) { process._rawDebug(); throw new Error(`destroy called for same id (${id})`); } - destroydIdsList[id] = new Error().stack; + destroydIdsList[id] = util.inspect(new Error()); }, }).enable(); } @@ -345,7 +348,7 @@ function _mustCallInner(fn, criteria = 1, field) { const context = { [field]: criteria, actual: 0, - stack: (new Error()).stack, + stack: util.inspect(new Error()), name: fn.name || '' }; @@ -530,7 +533,7 @@ function expectWarning(nameOrMap, expected, code) { function expectsError(validator, exact) { return mustCall((...args) => { if (args.length !== 1) { - // Do not use `assert.strictEqual()` to prevent `util.inspect` from + // Do not use `assert.strictEqual()` to prevent `inspect` from // always being called. assert.fail(`Expected one argument, got ${util.inspect(args)}`); } @@ -563,12 +566,6 @@ function skipIfInspectorDisabled() { } } -function skipIfReportDisabled() { - if (!process.config.variables.node_report) { - skip('Diagnostic reporting is disabled'); - } -} - function skipIf32Bits() { if (bits < 64) { skip('The tested feature is not available in 32bit builds'); @@ -711,7 +708,6 @@ const common = { skipIf32Bits, skipIfEslintMissing, skipIfInspectorDisabled, - skipIfReportDisabled, skipIfWorker, get enoughTestCpu() { diff --git a/test/common/index.mjs b/test/common/index.mjs index e9227ebff7def9..96e6699e3c6f99 100644 --- a/test/common/index.mjs +++ b/test/common/index.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules /* eslint-disable node-core/require-common-first, node-core/required-modules */ import { createRequire } from 'module'; diff --git a/test/common/report.js b/test/common/report.js index c117d7b76459bc..3b6b46eeec0f8d 100644 --- a/test/common/report.js +++ b/test/common/report.js @@ -25,7 +25,12 @@ function findReports(pid, dir) { } function validate(filepath) { - validateContent(JSON.parse(fs.readFileSync(filepath, 'utf8'))); + const report = fs.readFileSync(filepath, 'utf8'); + if (process.report.compact) { + const end = report.indexOf('\n'); + assert.strictEqual(end, report.length - 1); + } + validateContent(JSON.parse(report)); } function validateContent(report) { diff --git a/test/common/wpt.js b/test/common/wpt.js index c227f2e6fa3529..f6ac07bdfd296c 100644 --- a/test/common/wpt.js +++ b/test/common/wpt.js @@ -7,6 +7,7 @@ const fs = require('fs'); const fsPromises = fs.promises; const path = require('path'); const vm = require('vm'); +const { inspect } = require('util'); // https://github.com/w3c/testharness.js/blob/master/testharness.js // TODO: get rid of this half-baked harness in favor of the one @@ -354,7 +355,7 @@ class WPTRunner { this.fail(filename, { name: '', message: err.message, - stack: err.stack + stack: inspect(err) }, 'UNCAUGHT'); this.inProgress.delete(filename); } diff --git a/test/es-module/test-esm-basic-imports.mjs b/test/es-module/test-esm-basic-imports.mjs index c21804d78b292b..5009fbadb39657 100644 --- a/test/es-module/test-esm-basic-imports.mjs +++ b/test/es-module/test-esm-basic-imports.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import assert from 'assert'; import ok from '../fixtures/es-modules/test-esm-ok.mjs'; diff --git a/test/es-module/test-esm-cjs-load-error-note.mjs b/test/es-module/test-esm-cjs-load-error-note.mjs index ce0d1d796969d7..c0ac9393a8ddd5 100644 --- a/test/es-module/test-esm-cjs-load-error-note.mjs +++ b/test/es-module/test-esm-cjs-load-error-note.mjs @@ -1,5 +1,3 @@ -// Flags: --experimental-modules - import { mustCall } from '../common/index.mjs'; import assert from 'assert'; import fixtures from '../common/fixtures.js'; @@ -20,7 +18,7 @@ const expectedNote = 'To load an ES module, ' + const expectedCode = 1; -const pExport1 = spawn(process.execPath, ['--experimental-modules', Export1]); +const pExport1 = spawn(process.execPath, [Export1]); let pExport1Stderr = ''; pExport1.stderr.setEncoding('utf8'); pExport1.stderr.on('data', (data) => { @@ -33,7 +31,7 @@ pExport1.on('close', mustCall((code) => { })); -const pExport2 = spawn(process.execPath, ['--experimental-modules', Export2]); +const pExport2 = spawn(process.execPath, [Export2]); let pExport2Stderr = ''; pExport2.stderr.setEncoding('utf8'); pExport2.stderr.on('data', (data) => { @@ -44,21 +42,8 @@ pExport2.on('close', mustCall((code) => { assert.ok(pExport2Stderr.includes(expectedNote), `${expectedNote} not found in ${pExport2Stderr}`); })); -// The flag --experimental-modules is not used here -// the note must not be included in the output -const pExport3 = spawn(process.execPath, [Export1]); -let pExport3Stderr = ''; -pExport3.stderr.setEncoding('utf8'); -pExport3.stderr.on('data', (data) => { - pExport3Stderr += data; -}); -pExport3.on('close', mustCall((code) => { - assert.strictEqual(code, expectedCode); - assert.ok(!pExport3Stderr.includes(expectedNote), - `${expectedNote} must not be included in ${pExport3Stderr}`); -})); -const pImport1 = spawn(process.execPath, ['--experimental-modules', Import1]); +const pImport1 = spawn(process.execPath, [Import1]); let pImport1Stderr = ''; pImport1.stderr.setEncoding('utf8'); pImport1.stderr.on('data', (data) => { @@ -71,7 +56,7 @@ pImport1.on('close', mustCall((code) => { })); // Note this test shouldn't include the note -const pImport2 = spawn(process.execPath, ['--experimental-modules', Import2]); +const pImport2 = spawn(process.execPath, [Import2]); let pImport2Stderr = ''; pImport2.stderr.setEncoding('utf8'); pImport2.stderr.on('data', (data) => { @@ -84,7 +69,7 @@ pImport2.on('close', mustCall((code) => { `${expectedNote} must not be included in ${pImport2Stderr}`); })); -const pImport3 = spawn(process.execPath, ['--experimental-modules', Import3]); +const pImport3 = spawn(process.execPath, [Import3]); let pImport3Stderr = ''; pImport3.stderr.setEncoding('utf8'); pImport3.stderr.on('data', (data) => { @@ -97,7 +82,7 @@ pImport3.on('close', mustCall((code) => { })); -const pImport4 = spawn(process.execPath, ['--experimental-modules', Import4]); +const pImport4 = spawn(process.execPath, [Import4]); let pImport4Stderr = ''; pImport4.stderr.setEncoding('utf8'); pImport4.stderr.on('data', (data) => { @@ -110,7 +95,7 @@ pImport4.on('close', mustCall((code) => { })); // Must exit with zero and show note -const pImport5 = spawn(process.execPath, ['--experimental-modules', Import5]); +const pImport5 = spawn(process.execPath, [Import5]); let pImport5Stderr = ''; pImport5.stderr.setEncoding('utf8'); pImport5.stderr.on('data', (data) => { @@ -121,16 +106,3 @@ pImport5.on('close', mustCall((code) => { assert.ok(!pImport5Stderr.includes(expectedNote), `${expectedNote} must not be included in ${pImport5Stderr}`); })); - -// Must exit with zero and not show note -const pImport6 = spawn(process.execPath, [Import1]); -let pImport6Stderr = ''; -pImport6.stderr.setEncoding('utf8'); -pImport6.stderr.on('data', (data) => { - pImport6Stderr += data; -}); -pImport6.on('close', mustCall((code) => { - assert.strictEqual(code, expectedCode); - assert.ok(!pImport6Stderr.includes(expectedNote), - `${expectedNote} must not be included in ${pImport6Stderr}`); -})); diff --git a/test/es-module/test-esm-cjs-main.js b/test/es-module/test-esm-cjs-main.js index 8308308a2dce72..92f4124ccaab8a 100644 --- a/test/es-module/test-esm-cjs-main.js +++ b/test/es-module/test-esm-cjs-main.js @@ -7,12 +7,8 @@ const assert = require('assert'); const entry = fixtures.path('/es-modules/cjs.js'); -const child = spawn(process.execPath, ['--experimental-modules', entry]); -let stderr = ''; +const child = spawn(process.execPath, [entry]); child.stderr.setEncoding('utf8'); -child.stderr.on('data', (data) => { - stderr += data; -}); let stdout = ''; child.stdout.setEncoding('utf8'); child.stdout.on('data', (data) => { @@ -22,6 +18,4 @@ child.on('close', common.mustCall((code, signal) => { assert.strictEqual(code, 0); assert.strictEqual(signal, null); assert.strictEqual(stdout, 'executed\n'); - assert.strictEqual(stderr, `(node:${child.pid}) ` + - 'ExperimentalWarning: The ESM module loader is experimental.\n'); })); diff --git a/test/es-module/test-esm-cyclic-dynamic-import.mjs b/test/es-module/test-esm-cyclic-dynamic-import.mjs index 03d405baf3ce9c..6f831470b71853 100644 --- a/test/es-module/test-esm-cyclic-dynamic-import.mjs +++ b/test/es-module/test-esm-cyclic-dynamic-import.mjs @@ -1,3 +1,2 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import('./test-esm-cyclic-dynamic-import.mjs'); diff --git a/test/es-module/test-esm-data-urls.js b/test/es-module/test-esm-data-urls.js index a7b917ec74e297..61da442c9e081c 100644 --- a/test/es-module/test-esm-data-urls.js +++ b/test/es-module/test-esm-data-urls.js @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-json-modules +// Flags: --experimental-json-modules 'use strict'; const common = require('../common'); const assert = require('assert'); diff --git a/test/es-module/test-esm-default-type.mjs b/test/es-module/test-esm-default-type.mjs index 7e63dab3490d04..4b758df9166986 100644 --- a/test/es-module/test-esm-default-type.mjs +++ b/test/es-module/test-esm-default-type.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import { strictEqual } from 'assert'; diff --git a/test/es-module/test-esm-double-encoding.mjs b/test/es-module/test-esm-double-encoding.mjs index 2edfc8add5d2db..e46249f128203c 100644 --- a/test/es-module/test-esm-double-encoding.mjs +++ b/test/es-module/test-esm-double-encoding.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import '../common/index.mjs'; // Assert we can import files with `%` in their pathname. diff --git a/test/es-module/test-esm-dynamic-import.js b/test/es-module/test-esm-dynamic-import.js index a08e66dad3f820..e01b86eed143ed 100644 --- a/test/es-module/test-esm-dynamic-import.js +++ b/test/es-module/test-esm-dynamic-import.js @@ -1,5 +1,3 @@ -// Flags: --experimental-modules - 'use strict'; const common = require('../common'); const assert = require('assert'); @@ -44,6 +42,9 @@ function expectFsNamespace(result) { // For direct use of import expressions inside of CJS or ES modules, including // via eval, all kinds of specifiers should work without issue. (function testScriptOrModuleImport() { + common.expectWarning('ExperimentalWarning', + 'The ESM module loader is experimental.'); + // Importing another file, both direct & via eval // expectOkNamespace(import(relativePath)); expectOkNamespace(eval(`import("${relativePath}")`)); diff --git a/test/es-module/test-esm-encoded-path-native.js b/test/es-module/test-esm-encoded-path-native.js index a3106742d9ee8e..b8f5719b6089ee 100644 --- a/test/es-module/test-esm-encoded-path-native.js +++ b/test/es-module/test-esm-encoded-path-native.js @@ -5,7 +5,7 @@ const assert = require('assert'); const { spawn } = require('child_process'); const native = fixtures.path('es-module-url/native.mjs'); -const child = spawn(process.execPath, ['--experimental-modules', native]); +const child = spawn(process.execPath, [native]); child.on('exit', (code) => { assert.strictEqual(code, 1); }); diff --git a/test/es-module/test-esm-encoded-path.mjs b/test/es-module/test-esm-encoded-path.mjs index efb681ef0b4dfe..351cb7eab887b4 100644 --- a/test/es-module/test-esm-encoded-path.mjs +++ b/test/es-module/test-esm-encoded-path.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import assert from 'assert'; // ./test-esm-ok.mjs diff --git a/test/es-module/test-esm-error-cache.js b/test/es-module/test-esm-error-cache.js index 26e0d170ac2e1b..b13e793626876a 100644 --- a/test/es-module/test-esm-error-cache.js +++ b/test/es-module/test-esm-error-cache.js @@ -1,5 +1,3 @@ -// Flags: --experimental-modules - 'use strict'; require('../common'); diff --git a/test/es-module/test-esm-example-loader.js b/test/es-module/test-esm-example-loader.js index 0da1d34d2ad6fc..b85de4e64c4abc 100644 --- a/test/es-module/test-esm-example-loader.js +++ b/test/es-module/test-esm-example-loader.js @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/example-loader.mjs +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/example-loader.mjs /* eslint-disable node-core/require-common-first, node-core/required-modules */ import assert from 'assert'; import ok from '../fixtures/es-modules/test-esm-ok.mjs'; diff --git a/test/es-module/test-esm-exports.mjs b/test/es-module/test-esm-exports.mjs index 8aaa66aae47d19..bf702345c24207 100644 --- a/test/es-module/test-esm-exports.mjs +++ b/test/es-module/test-esm-exports.mjs @@ -1,5 +1,3 @@ -// Flags: --experimental-modules - import { mustCall } from '../common/index.mjs'; import { ok, deepStrictEqual, strictEqual } from 'assert'; @@ -65,6 +63,11 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js'; // Conditional exports with no match are "not exported" errors ['pkgexports/invalid1', './invalid1'], ['pkgexports/invalid4', './invalid4'], + // Null mapping + ['pkgexports/null', './null'], + ['pkgexports/null/subpath', './null/subpath'], + // Empty fallback + ['pkgexports/nofallback1', './nofallback1'], ]); const invalidExports = new Map([ @@ -75,12 +78,11 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js'; ['pkgexports/belowdir/pkgexports/asdf.js', './belowdir/'], // This target file steps below the package ['pkgexports/belowfile', './belowfile'], - // Invalid target handling - ['pkgexports/null', './null'], + // Invalid targets ['pkgexports/invalid2', './invalid2'], ['pkgexports/invalid3', './invalid3'], + ['pkgexports/invalid5', 'invalid5'], // Missing / invalid fallbacks - ['pkgexports/nofallback1', './nofallback1'], ['pkgexports/nofallback2', './nofallback2'], // Reaching into nested node_modules ['pkgexports/nodemodules', './nodemodules'], @@ -107,6 +109,9 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js'; strictEqual(err.code, 'ERR_INVALID_PACKAGE_TARGET'); assertStartsWith(err.message, 'Invalid "exports"'); assertIncludes(err.message, subpath); + if (!subpath.startsWith('./')) { + assertIncludes(err.message, 'targets must start with'); + } })); } @@ -152,8 +157,7 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js'; // The use of %2F escapes in paths fails loading loadFixture('pkgexports/sub/..%2F..%2Fbar.js').catch(mustCall((err) => { - strictEqual(err.code, isRequire ? 'ERR_INVALID_FILE_URL_PATH' : - 'ERR_MODULE_NOT_FOUND'); + strictEqual(err.code, 'ERR_INVALID_FILE_URL_PATH'); })); // Package export with numeric index properties must throw a validation error diff --git a/test/es-module/test-esm-flagged-self.js b/test/es-module/test-esm-flagged-self.js deleted file mode 100644 index 43a0c4f9684bf0..00000000000000 --- a/test/es-module/test-esm-flagged-self.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -require('../common'); -const assert = require('assert'); -const path = require('path'); -const { createRequireFromPath } = require('module'); - -const fixturesRequire = - createRequireFromPath(path.resolve(__dirname, '../fixtures/_')); - -try { - fixturesRequire('pkgexports/resolve-self'); - assert(false); -} catch (e) { - assert.strictEqual(e.code, 'MODULE_NOT_FOUND'); -} diff --git a/test/es-module/test-esm-forbidden-globals.mjs b/test/es-module/test-esm-forbidden-globals.mjs index b66f278a8a9bb8..2f1914e48631b5 100644 --- a/test/es-module/test-esm-forbidden-globals.mjs +++ b/test/es-module/test-esm-forbidden-globals.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import '../common/index.mjs'; // eslint-disable-next-line no-undef diff --git a/test/es-module/test-esm-get-source-loader.mjs b/test/es-module/test-esm-get-source-loader.mjs index 12ec5d0173db9e..66bac969a47d8f 100644 --- a/test/es-module/test-esm-get-source-loader.mjs +++ b/test/es-module/test-esm-get-source-loader.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/get-source.mjs +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/get-source.mjs /* eslint-disable node-core/require-common-first, node-core/required-modules */ import assert from 'assert'; import { message } from '../fixtures/es-modules/message.mjs'; diff --git a/test/es-module/test-esm-import-meta-resolve.mjs b/test/es-module/test-esm-import-meta-resolve.mjs index 3d9dae48676c50..faf9320a82745a 100644 --- a/test/es-module/test-esm-import-meta-resolve.mjs +++ b/test/es-module/test-esm-import-meta-resolve.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-import-meta-resolve +// Flags: --experimental-import-meta-resolve import '../common/index.mjs'; import assert from 'assert'; diff --git a/test/es-module/test-esm-import-meta.mjs b/test/es-module/test-esm-import-meta.mjs index 54c14a44f5e281..0151177b21c302 100644 --- a/test/es-module/test-esm-import-meta.mjs +++ b/test/es-module/test-esm-import-meta.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import assert from 'assert'; diff --git a/test/es-module/test-esm-invalid-extension.js b/test/es-module/test-esm-invalid-extension.js index 414b68776278ac..cca7704f7994f0 100644 --- a/test/es-module/test-esm-invalid-extension.js +++ b/test/es-module/test-esm-invalid-extension.js @@ -4,7 +4,7 @@ const fixtures = require('../common/fixtures'); const assert = require('assert'); const { spawnSync } = require('child_process'); const fixture = fixtures.path('/es-modules/import-invalid-ext.mjs'); -const child = spawnSync(process.execPath, ['--experimental-modules', fixture]); +const child = spawnSync(process.execPath, [fixture]); const errMsg = 'TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension'; assert.strictEqual(child.status, 1); diff --git a/test/es-module/test-esm-json-cache.mjs b/test/es-module/test-esm-json-cache.mjs index d1fee4f444c2c0..d08f852e255a78 100644 --- a/test/es-module/test-esm-json-cache.mjs +++ b/test/es-module/test-esm-json-cache.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-json-modules +// Flags: --experimental-json-modules import '../common/index.mjs'; import { strictEqual, deepStrictEqual } from 'assert'; diff --git a/test/es-module/test-esm-json.mjs b/test/es-module/test-esm-json.mjs index 3f4608d09d9604..ddcc7cb33e709f 100644 --- a/test/es-module/test-esm-json.mjs +++ b/test/es-module/test-esm-json.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-json-modules +// Flags: --experimental-json-modules import '../common/index.mjs'; import { path } from '../common/fixtures.mjs'; import { strictEqual, ok } from 'assert'; @@ -10,7 +10,6 @@ strictEqual(secret.ofLife, 42); // Test warning message const child = spawn(process.execPath, [ - '--experimental-modules', '--experimental-json-modules', path('/es-modules/json-modules.mjs') ]); diff --git a/test/es-module/test-esm-live-binding.mjs b/test/es-module/test-esm-live-binding.mjs index 4000a621a2bd04..ff58db31f144a3 100644 --- a/test/es-module/test-esm-live-binding.mjs +++ b/test/es-module/test-esm-live-binding.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import assert from 'assert'; import { syncBuiltinESMExports } from 'module'; diff --git a/test/es-module/test-esm-loader-cache-clearing.js b/test/es-module/test-esm-loader-cache-clearing.js index ec22b6a6bb871e..4b5f36cf37ec3b 100644 --- a/test/es-module/test-esm-loader-cache-clearing.js +++ b/test/es-module/test-esm-loader-cache-clearing.js @@ -1,4 +1,3 @@ -// Flags: --experimental-modules 'use strict'; require('../common'); diff --git a/test/es-module/test-esm-loader-custom-condition.mjs b/test/es-module/test-esm-loader-custom-condition.mjs new file mode 100644 index 00000000000000..26d1db4842f621 --- /dev/null +++ b/test/es-module/test-esm-loader-custom-condition.mjs @@ -0,0 +1,7 @@ +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/loader-with-custom-condition.mjs +import '../common/index.mjs'; +import assert from 'assert'; + +import * as ns from '../fixtures/es-modules/conditional-exports.mjs'; + +assert.deepStrictEqual({ ...ns }, { default: 'from custom condition' }); diff --git a/test/es-module/test-esm-loader-dependency.mjs b/test/es-module/test-esm-loader-dependency.mjs index dadc3bd84ae1d3..54327b478bf462 100644 --- a/test/es-module/test-esm-loader-dependency.mjs +++ b/test/es-module/test-esm-loader-dependency.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/loader-with-dep.mjs +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/loader-with-dep.mjs /* eslint-disable node-core/require-common-first, node-core/required-modules */ import '../fixtures/es-modules/test-esm-ok.mjs'; diff --git a/test/es-module/test-esm-loader-get-format.mjs b/test/es-module/test-esm-loader-get-format.mjs index 4fb40db39f75dd..2a252439f91ce4 100644 --- a/test/es-module/test-esm-loader-get-format.mjs +++ b/test/es-module/test-esm-loader-get-format.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/loader-get-format.mjs +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/loader-get-format.mjs import { mustCall, mustNotCall } from '../common/index.mjs'; import assert from 'assert'; diff --git a/test/es-module/test-esm-loader-invalid-format.mjs b/test/es-module/test-esm-loader-invalid-format.mjs index d7a91aaa38b8e3..64237f7af243af 100644 --- a/test/es-module/test-esm-loader-invalid-format.mjs +++ b/test/es-module/test-esm-loader-invalid-format.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/loader-invalid-format.mjs +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/loader-invalid-format.mjs import { expectsError, mustCall } from '../common/index.mjs'; import assert from 'assert'; diff --git a/test/es-module/test-esm-loader-invalid-url.mjs b/test/es-module/test-esm-loader-invalid-url.mjs index 74dba3485bb2ab..e9f04d0af4d4fe 100644 --- a/test/es-module/test-esm-loader-invalid-url.mjs +++ b/test/es-module/test-esm-loader-invalid-url.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/loader-invalid-url.mjs +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/loader-invalid-url.mjs import { expectsError, mustCall } from '../common/index.mjs'; import assert from 'assert'; diff --git a/test/es-module/test-esm-loader-missing-dynamic-instantiate-hook.mjs b/test/es-module/test-esm-loader-missing-dynamic-instantiate-hook.mjs index 5767af7affe1fa..62781c37d48240 100644 --- a/test/es-module/test-esm-loader-missing-dynamic-instantiate-hook.mjs +++ b/test/es-module/test-esm-loader-missing-dynamic-instantiate-hook.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/missing-dynamic-instantiate-hook.mjs +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/missing-dynamic-instantiate-hook.mjs import { expectsError } from '../common/index.mjs'; import('test').catch(expectsError({ diff --git a/test/es-module/test-esm-loader-modulemap.js b/test/es-module/test-esm-loader-modulemap.js index 2d601cd99f1b4b..a4d56a2c2fda1c 100644 --- a/test/es-module/test-esm-loader-modulemap.js +++ b/test/es-module/test-esm-loader-modulemap.js @@ -1,5 +1,5 @@ 'use strict'; -// Flags: --expose-internals --experimental-modules +// Flags: --expose-internals // This test ensures that the type checking of ModuleMap throws // errors appropriately diff --git a/test/es-module/test-esm-loader-side-effect.mjs b/test/es-module/test-esm-loader-side-effect.mjs index 3ac71448252e97..f76b10700ddc8f 100644 --- a/test/es-module/test-esm-loader-side-effect.mjs +++ b/test/es-module/test-esm-loader-side-effect.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/loader-side-effect.mjs --require ./test/fixtures/es-module-loaders/loader-side-effect-require-preload.js +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/loader-side-effect.mjs --require ./test/fixtures/es-module-loaders/loader-side-effect-require-preload.js import { allowGlobals, mustCall } from '../common/index.mjs'; import assert from 'assert'; import { fileURLToPath } from 'url'; diff --git a/test/es-module/test-esm-main-lookup.mjs b/test/es-module/test-esm-main-lookup.mjs index cbc6424dd2ff1c..2023a105e4dc42 100644 --- a/test/es-module/test-esm-main-lookup.mjs +++ b/test/es-module/test-esm-main-lookup.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import assert from 'assert'; diff --git a/test/es-module/test-esm-named-exports.mjs b/test/es-module/test-esm-named-exports.mjs index 6c8030826970a8..7d8d1080082401 100644 --- a/test/es-module/test-esm-named-exports.mjs +++ b/test/es-module/test-esm-named-exports.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs import '../common/index.mjs'; import { readFile } from 'fs'; import assert from 'assert'; diff --git a/test/es-module/test-esm-namespace.mjs b/test/es-module/test-esm-namespace.mjs index 094a9e972cbbad..9ce0f9686d1668 100644 --- a/test/es-module/test-esm-namespace.mjs +++ b/test/es-module/test-esm-namespace.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import * as fs from 'fs'; import assert from 'assert'; diff --git a/test/es-module/test-esm-non-js.js b/test/es-module/test-esm-non-js.js index 3a41b7228ca81b..3e572809bbdf35 100644 --- a/test/es-module/test-esm-non-js.js +++ b/test/es-module/test-esm-non-js.js @@ -7,7 +7,7 @@ const assert = require('assert'); const entry = require.resolve('./test-esm-json.mjs'); // Verify non-js extensions fail for ESM -const child = spawn(process.execPath, ['--experimental-modules', entry]); +const child = spawn(process.execPath, [entry]); let stderr = ''; child.stderr.setEncoding('utf8'); diff --git a/test/es-module/test-esm-nowarn-exports.mjs b/test/es-module/test-esm-nowarn-exports.mjs index 0c5ae17e764797..13bfaf9b4f3527 100644 --- a/test/es-module/test-esm-nowarn-exports.mjs +++ b/test/es-module/test-esm-nowarn-exports.mjs @@ -1,11 +1,9 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import { path } from '../common/fixtures.mjs'; import { strictEqual, ok } from 'assert'; import { spawn } from 'child_process'; const child = spawn(process.execPath, [ - '--experimental-modules', '--experimental-import-meta-resolve', path('/es-modules/import-resolve-exports.mjs') ]); diff --git a/test/es-module/test-esm-pkgname.mjs b/test/es-module/test-esm-pkgname.mjs index 046a12dd1a12da..06b5d2d104df63 100644 --- a/test/es-module/test-esm-pkgname.mjs +++ b/test/es-module/test-esm-pkgname.mjs @@ -1,5 +1,3 @@ -// Flags: --experimental-modules - import { mustCall } from '../common/index.mjs'; import { strictEqual } from 'assert'; diff --git a/test/es-module/test-esm-preserve-symlinks-main.js b/test/es-module/test-esm-preserve-symlinks-main.js index 239fdddc2e8d79..877066a6a4548e 100644 --- a/test/es-module/test-esm-preserve-symlinks-main.js +++ b/test/es-module/test-esm-preserve-symlinks-main.js @@ -53,5 +53,5 @@ function doTest(flags, done) { // First test the commonjs module loader doTest([], () => { // Now test the new loader - doTest(['--experimental-modules'], () => {}); + doTest([], () => {}); }); diff --git a/test/es-module/test-esm-preserve-symlinks-not-found-plain.mjs b/test/es-module/test-esm-preserve-symlinks-not-found-plain.mjs index 1dcae4b8aef4a8..7a538e44c072e0 100644 --- a/test/es-module/test-esm-preserve-symlinks-not-found-plain.mjs +++ b/test/es-module/test-esm-preserve-symlinks-not-found-plain.mjs @@ -1,3 +1,3 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/not-found-assert-loader.mjs +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/not-found-assert-loader.mjs /* eslint-disable node-core/require-common-first, node-core/required-modules */ import './not-found.js'; diff --git a/test/es-module/test-esm-preserve-symlinks-not-found.mjs b/test/es-module/test-esm-preserve-symlinks-not-found.mjs index 68e1b53eeb1d75..722dc467d19273 100644 --- a/test/es-module/test-esm-preserve-symlinks-not-found.mjs +++ b/test/es-module/test-esm-preserve-symlinks-not-found.mjs @@ -1,3 +1,3 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/not-found-assert-loader.mjs +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/not-found-assert-loader.mjs /* eslint-disable node-core/require-common-first, node-core/required-modules */ import './not-found.mjs'; diff --git a/test/es-module/test-esm-preserve-symlinks.js b/test/es-module/test-esm-preserve-symlinks.js index 28cba3e7022c1a..a91373b0c05b93 100644 --- a/test/es-module/test-esm-preserve-symlinks.js +++ b/test/es-module/test-esm-preserve-symlinks.js @@ -32,7 +32,7 @@ try { } spawn(process.execPath, - ['--experimental-modules', '--preserve-symlinks', entry], + ['--preserve-symlinks', entry], { stdio: 'inherit' }).on('exit', (code) => { assert.strictEqual(code, 0); }); diff --git a/test/es-module/test-esm-process.mjs b/test/es-module/test-esm-process.mjs index a2b0d31f1efa27..8fa006a304ed2f 100644 --- a/test/es-module/test-esm-process.mjs +++ b/test/es-module/test-esm-process.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import assert from 'assert'; import process from 'process'; diff --git a/test/es-module/test-esm-repl.js b/test/es-module/test-esm-repl.js index daef48d8e1f58b..653927b241694e 100644 --- a/test/es-module/test-esm-repl.js +++ b/test/es-module/test-esm-repl.js @@ -4,7 +4,6 @@ const assert = require('assert'); const { spawn } = require('child_process'); const child = spawn(process.execPath, [ - '--experimental-modules', '--interactive' ]); child.stdin.end(` diff --git a/test/es-module/test-esm-require-cache.mjs b/test/es-module/test-esm-require-cache.mjs index 8c126c39e0eefe..1cfcf8e2a4b416 100644 --- a/test/es-module/test-esm-require-cache.mjs +++ b/test/es-module/test-esm-require-cache.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import { createRequire } from '../common/index.mjs'; import assert from 'assert'; // diff --git a/test/es-module/test-esm-resolve-hook.mjs b/test/es-module/test-esm-resolve-hook.mjs index 00c8e440f42964..39b11e02739d4b 100644 --- a/test/es-module/test-esm-resolve-hook.mjs +++ b/test/es-module/test-esm-resolve-hook.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/js-loader.mjs +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/js-loader.mjs /* eslint-disable node-core/require-common-first, node-core/required-modules */ import { namedExport } from '../fixtures/es-module-loaders/js-as-esm.js'; import assert from 'assert'; diff --git a/test/es-module/test-esm-scope-node-modules.mjs b/test/es-module/test-esm-scope-node-modules.mjs index 8358da5c765288..0be4194aeb9b4d 100644 --- a/test/es-module/test-esm-scope-node-modules.mjs +++ b/test/es-module/test-esm-scope-node-modules.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import cjs from '../fixtures/baz.js'; import { message } from '../fixtures/es-modules/message.mjs'; diff --git a/test/es-module/test-esm-shared-loader-dep.mjs b/test/es-module/test-esm-shared-loader-dep.mjs index b02e557d34bc29..e0015bd0c755d7 100644 --- a/test/es-module/test-esm-shared-loader-dep.mjs +++ b/test/es-module/test-esm-shared-loader-dep.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/loader-shared-dep.mjs +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/loader-shared-dep.mjs import { createRequire } from '../common/index.mjs'; import assert from 'assert'; diff --git a/test/es-module/test-esm-shebang.mjs b/test/es-module/test-esm-shebang.mjs index 1d22551bd7a4be..6b77151dd78406 100644 --- a/test/es-module/test-esm-shebang.mjs +++ b/test/es-module/test-esm-shebang.mjs @@ -1,5 +1,4 @@ #! }]) // isn't js -// Flags: --experimental-modules import '../common/index.mjs'; const isJs = true; diff --git a/test/es-module/test-esm-snapshot.mjs b/test/es-module/test-esm-snapshot.mjs index 99767f10e2846e..e2695d20a81747 100644 --- a/test/es-module/test-esm-snapshot.mjs +++ b/test/es-module/test-esm-snapshot.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import '../fixtures/es-modules/esm-snapshot-mutator.js'; import one from '../fixtures/es-modules/esm-snapshot.js'; diff --git a/test/es-module/test-esm-specifiers-both-flags.mjs b/test/es-module/test-esm-specifiers-both-flags.mjs index 5cdeed0c82a888..a434684589dc07 100644 --- a/test/es-module/test-esm-specifiers-both-flags.mjs +++ b/test/es-module/test-esm-specifiers-both-flags.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import { mustCall } from '../common/index.mjs'; import { exec } from 'child_process'; import assert from 'assert'; @@ -7,8 +6,7 @@ const expectedError = 'cannot use --es-module-specifier-resolution ' + 'and --experimental-specifier-resolution at the same time'; -const flags = '--experimental-modules ' + - '--es-module-specifier-resolution=node ' + +const flags = '--es-module-specifier-resolution=node ' + '--experimental-specifier-resolution=node'; exec(`${process.execPath} ${flags}`, mustCall((error) => { diff --git a/test/es-module/test-esm-specifiers-legacy-flag.mjs b/test/es-module/test-esm-specifiers-legacy-flag.mjs index 03388493f0b8cb..fcf0c915b649f0 100644 --- a/test/es-module/test-esm-specifiers-legacy-flag.mjs +++ b/test/es-module/test-esm-specifiers-legacy-flag.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --es-module-specifier-resolution=node +// Flags: --es-module-specifier-resolution=node import '../common/index.mjs'; import assert from 'assert'; diff --git a/test/es-module/test-esm-specifiers.mjs b/test/es-module/test-esm-specifiers.mjs index cf9a50353878de..5e436f21b74cc6 100644 --- a/test/es-module/test-esm-specifiers.mjs +++ b/test/es-module/test-esm-specifiers.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-specifier-resolution=node +// Flags: --experimental-specifier-resolution=node import { mustNotCall } from '../common/index.mjs'; import assert from 'assert'; import path from 'path'; @@ -49,11 +49,9 @@ main().catch(mustNotCall); '../../fixtures/es-module-specifiers', item, ); - spawn(process.execPath, [ - '--experimental-modules', - '--es-module-specifier-resolution=node', - modulePath - ], { stdio: 'inherit' }).on('exit', (code) => { + spawn(process.execPath, + ['--es-module-specifier-resolution=node', modulePath], + { stdio: 'inherit' }).on('exit', (code) => { assert.strictEqual(code, 0); }); }); diff --git a/test/es-module/test-esm-symlink-main.js b/test/es-module/test-esm-symlink-main.js index 871180f5ccf4bb..48b4d8bbe65daf 100644 --- a/test/es-module/test-esm-symlink-main.js +++ b/test/es-module/test-esm-symlink-main.js @@ -19,7 +19,7 @@ try { } spawn(process.execPath, - ['--experimental-modules', '--preserve-symlinks', symlinkPath], + ['--preserve-symlinks', symlinkPath], { stdio: 'inherit' }).on('exit', (code) => { assert.strictEqual(code, 0); }); diff --git a/test/es-module/test-esm-symlink-type.js b/test/es-module/test-esm-symlink-type.js index 6159ebecd18be4..1f46dce17f2e46 100644 --- a/test/es-module/test-esm-symlink-type.js +++ b/test/es-module/test-esm-symlink-type.js @@ -48,8 +48,8 @@ symlinks.forEach((symlink) => { fs.symlinkSync(symlink.target, mainPath); const flags = [ - '--experimental-modules', - '--experimental-modules --preserve-symlinks-main' + '', + '--preserve-symlinks-main' ]; flags.forEach((nodeOptions) => { const opts = { diff --git a/test/es-module/test-esm-symlink.js b/test/es-module/test-esm-symlink.js index 9b9eb98cd98406..139e6820ed5354 100644 --- a/test/es-module/test-esm-symlink.js +++ b/test/es-module/test-esm-symlink.js @@ -41,7 +41,7 @@ try { common.skip('insufficient privileges for symlinks'); } -spawn(process.execPath, ['--experimental-modules', entry], +spawn(process.execPath, [entry], { stdio: 'inherit' }).on('exit', (code) => { assert.strictEqual(code, 0); }); diff --git a/test/es-module/test-esm-throw-undefined.mjs b/test/es-module/test-esm-throw-undefined.mjs index 4c091e61532640..c4c25fd12d675c 100644 --- a/test/es-module/test-esm-throw-undefined.mjs +++ b/test/es-module/test-esm-throw-undefined.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import assert from 'assert'; diff --git a/test/es-module/test-esm-transform-source-loader.mjs b/test/es-module/test-esm-transform-source-loader.mjs index 03c7f67431c888..e6d4affea495de 100644 --- a/test/es-module/test-esm-transform-source-loader.mjs +++ b/test/es-module/test-esm-transform-source-loader.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/transform-source.mjs +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/transform-source.mjs /* eslint-disable node-core/require-common-first, node-core/required-modules */ import assert from 'assert'; import { message } from '../fixtures/es-modules/message.mjs'; diff --git a/test/es-module/test-esm-type-flag-errors.js b/test/es-module/test-esm-type-flag-errors.js index fd09edc4648b75..e0dedc16cabf8c 100644 --- a/test/es-module/test-esm-type-flag-errors.js +++ b/test/es-module/test-esm-type-flag-errors.js @@ -1,4 +1,3 @@ -// Flags: --experimental-modules 'use strict'; const common = require('../common'); const assert = require('assert'); @@ -35,8 +34,6 @@ try { } function expect(opt = '', inputFile, want, wantsError = false) { - // TODO: Remove when --experimental-modules is unflagged - opt = `--experimental-modules ${opt}`; const argv = [inputFile]; const opts = { env: Object.assign({}, process.env, { NODE_OPTIONS: opt }), diff --git a/test/es-module/test-esm-type-flag.mjs b/test/es-module/test-esm-type-flag.mjs index 8358da5c765288..0be4194aeb9b4d 100644 --- a/test/es-module/test-esm-type-flag.mjs +++ b/test/es-module/test-esm-type-flag.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import cjs from '../fixtures/baz.js'; import { message } from '../fixtures/es-modules/message.mjs'; diff --git a/test/es-module/test-esm-type-main.mjs b/test/es-module/test-esm-type-main.mjs new file mode 100644 index 00000000000000..012cf4f35fc959 --- /dev/null +++ b/test/es-module/test-esm-type-main.mjs @@ -0,0 +1,9 @@ +import { mustNotCall } from '../common/index.mjs'; +import assert from 'assert'; +import { importFixture } from '../fixtures/pkgexports.mjs'; + +(async () => { + const m = await importFixture('type-main'); + assert.strictEqual(m.default, 'asdf'); +})() +.catch(mustNotCall); diff --git a/test/es-module/test-esm-unknown-or-no-extension.js b/test/es-module/test-esm-unknown-or-no-extension.js index c1cafbe8886413..3b1802a4dcedbd 100644 --- a/test/es-module/test-esm-unknown-or-no-extension.js +++ b/test/es-module/test-esm-unknown-or-no-extension.js @@ -16,7 +16,7 @@ const assert = require('assert'); '/es-modules/package-type-module/imports-unknownext.mjs', ].forEach((fixturePath) => { const entry = fixtures.path(fixturePath); - const child = spawn(process.execPath, ['--experimental-modules', entry]); + const child = spawn(process.execPath, [entry]); let stdout = ''; let stderr = ''; child.stderr.setEncoding('utf8'); diff --git a/test/es-module/test-esm-wasm.mjs b/test/es-module/test-esm-wasm.mjs index 4a9180199c95e7..b2218ce2f09893 100644 --- a/test/es-module/test-esm-wasm.mjs +++ b/test/es-module/test-esm-wasm.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-wasm-modules +// Flags: --experimental-wasm-modules import '../common/index.mjs'; import { path } from '../common/fixtures.mjs'; import { add, addImported } from '../fixtures/es-modules/simple.wasm'; @@ -18,7 +18,6 @@ strictEqual(addImported(1), 43); // Test warning message const child = spawn(process.execPath, [ - '--experimental-modules', '--experimental-wasm-modules', path('/es-modules/wasm-modules.mjs') ]); diff --git a/test/es-module/test-esm-windows.js b/test/es-module/test-esm-windows.js index 44af65d6a4e031..76e016217b3ef8 100644 --- a/test/es-module/test-esm-windows.js +++ b/test/es-module/test-esm-windows.js @@ -1,6 +1,5 @@ 'use strict'; -// Flags: --experimental-modules // This test ensures that JavaScript file that includes // a reserved Windows word can be loaded as ESM module diff --git a/test/fixtures/child-process-spawn-node.js b/test/fixtures/child-process-spawn-node.js index f93fd998fe0e37..2bf4582ea03b41 100644 --- a/test/fixtures/child-process-spawn-node.js +++ b/test/fixtures/child-process-spawn-node.js @@ -1,7 +1,8 @@ const assert = require('assert'); +const debug = require('util').debuglog('test'); function onmessage(m) { - console.log('CHILD got message:', m); + debug('CHILD got message:', m); assert.ok(m.hello); process.removeListener('message', onmessage); } diff --git a/test/fixtures/es-module-loaders/loader-with-custom-condition.mjs b/test/fixtures/es-module-loaders/loader-with-custom-condition.mjs new file mode 100644 index 00000000000000..78ffd75e6be27b --- /dev/null +++ b/test/fixtures/es-module-loaders/loader-with-custom-condition.mjs @@ -0,0 +1,10 @@ +import {ok, deepStrictEqual} from 'assert'; + +export async function resolve(specifier, context, defaultResolve) { + ok(Array.isArray(context.conditions), 'loader receives conditions array'); + deepStrictEqual([...context.conditions].sort(), ['import', 'node']); + return defaultResolve(specifier, { + ...context, + conditions: ['custom-condition', ...context.conditions], + }); +} diff --git a/test/fixtures/es-modules/conditional-exports.mjs b/test/fixtures/es-modules/conditional-exports.mjs new file mode 100644 index 00000000000000..cf06ac004ce883 --- /dev/null +++ b/test/fixtures/es-modules/conditional-exports.mjs @@ -0,0 +1 @@ +export { default } from 'pkgexports/condition'; diff --git a/test/fixtures/esm_loader_not_found_cjs_hint_bare.mjs b/test/fixtures/esm_loader_not_found_cjs_hint_bare.mjs new file mode 100644 index 00000000000000..4eb5f190af43e4 --- /dev/null +++ b/test/fixtures/esm_loader_not_found_cjs_hint_bare.mjs @@ -0,0 +1,5 @@ +'use strict'; + +import obj from 'some_module/obj'; + +throw new Error('Should have errored'); diff --git a/test/fixtures/node_modules/pkgexports/custom-condition.mjs b/test/fixtures/node_modules/pkgexports/custom-condition.mjs new file mode 100644 index 00000000000000..87d8b8a8faca9a --- /dev/null +++ b/test/fixtures/node_modules/pkgexports/custom-condition.mjs @@ -0,0 +1 @@ +export default 'from custom condition'; diff --git a/test/fixtures/node_modules/pkgexports/package.json b/test/fixtures/node_modules/pkgexports/package.json index 200c028f88c9d3..b99e5c7b79f6a8 100644 --- a/test/fixtures/node_modules/pkgexports/package.json +++ b/test/fixtures/node_modules/pkgexports/package.json @@ -9,16 +9,19 @@ "./belowfile": "../belowfile", "./missingtrailer/": ".", "./null": null, + "./null/": null, "./invalid1": {}, "./invalid2": 1234, "./invalid3": "", "./invalid4": {}, + "./invalid5": "invalid5.js", "./fallbackdir/": [[], null, {}, "builtin:x/", "./fallbackfile", "./"], "./fallbackfile": [[], null, {}, "builtin:x", "./asdf.js"], "./nofallback1": [], "./nofallback2": [null, {}, "builtin:x"], "./nodemodules": "./node_modules/internalpkg/x.js", "./condition": [{ + "custom-condition": "./custom-condition.mjs", "import": "///overridden", "require": { "require": { diff --git a/test/fixtures/node_modules/some_module/index.js b/test/fixtures/node_modules/some_module/index.js new file mode 100644 index 00000000000000..a2d739266cdca4 --- /dev/null +++ b/test/fixtures/node_modules/some_module/index.js @@ -0,0 +1,3 @@ +'use strict' + +module.exports = { main: true } diff --git a/test/fixtures/node_modules/some_module/obj.js b/test/fixtures/node_modules/some_module/obj.js new file mode 100644 index 00000000000000..249478e5ca506f --- /dev/null +++ b/test/fixtures/node_modules/some_module/obj.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = { obj: 'module' } diff --git a/test/fixtures/node_modules/some_module/package.json b/test/fixtures/node_modules/some_module/package.json new file mode 100644 index 00000000000000..95a52cc61071a5 --- /dev/null +++ b/test/fixtures/node_modules/some_module/package.json @@ -0,0 +1,12 @@ +{ + "name": "some_module", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/test/fixtures/node_modules/type-main/index.js b/test/fixtures/node_modules/type-main/index.js new file mode 100644 index 00000000000000..a4cb53964349f5 --- /dev/null +++ b/test/fixtures/node_modules/type-main/index.js @@ -0,0 +1 @@ +export default 'asdf'; diff --git a/test/fixtures/node_modules/type-main/package.json b/test/fixtures/node_modules/type-main/package.json new file mode 100644 index 00000000000000..7665d7a8037428 --- /dev/null +++ b/test/fixtures/node_modules/type-main/package.json @@ -0,0 +1,4 @@ +{ + "main": "index", + "type": "module" +} diff --git a/test/fixtures/repl-tab-completion-nested-repls.js b/test/fixtures/repl-tab-completion-nested-repls.js index ceff6e79453705..1d2b154f2b3341 100644 --- a/test/fixtures/repl-tab-completion-nested-repls.js +++ b/test/fixtures/repl-tab-completion-nested-repls.js @@ -31,7 +31,7 @@ const repl = require('repl'); const putIn = new ArrayStream(); const testMe = repl.start('', putIn); -// Some errors are passed to the domain, but do not callback +// Some errors are passed to the domain, but do not callback. testMe._domain.on('error', function(err) { throw err; }); diff --git a/test/fixtures/uncaught-exceptions/domain.js b/test/fixtures/uncaught-exceptions/domain.js index 9ede6993a7331b..8b69f52f14e9da 100644 --- a/test/fixtures/uncaught-exceptions/domain.js +++ b/test/fixtures/uncaught-exceptions/domain.js @@ -2,7 +2,7 @@ const domain = require('domain'); var d = domain.create(); d.on('error', function(err) { - console.log('[ignored]', err.stack); + console.log('[ignored]', err); }); d.run(function() { diff --git a/test/fixtures/uncaught-exceptions/uncaught-monitor1.js b/test/fixtures/uncaught-exceptions/uncaught-monitor1.js new file mode 100644 index 00000000000000..9724539a253bc1 --- /dev/null +++ b/test/fixtures/uncaught-exceptions/uncaught-monitor1.js @@ -0,0 +1,10 @@ +'use strict'; + +// Keep the event loop alive. +setTimeout(() => {}, 1e6); + +process.on('uncaughtExceptionMonitor', (err) => { + console.log(`Monitored: ${err.message}`); +}); + +throw new Error('Shall exit'); diff --git a/test/fixtures/uncaught-exceptions/uncaught-monitor2.js b/test/fixtures/uncaught-exceptions/uncaught-monitor2.js new file mode 100644 index 00000000000000..743a5611008ba2 --- /dev/null +++ b/test/fixtures/uncaught-exceptions/uncaught-monitor2.js @@ -0,0 +1,11 @@ +'use strict'; + +// Keep the event loop alive. +setTimeout(() => {}, 1e6); + +process.on('uncaughtExceptionMonitor', (err) => { + console.log(`Monitored: ${err.message}, will throw now`); + missingFunction(); +}); + +throw new Error('Shall exit'); diff --git a/test/internet/test-http2-issue-32922.js b/test/internet/test-http2-issue-32922.js new file mode 100644 index 00000000000000..e11de0286eb7a4 --- /dev/null +++ b/test/internet/test-http2-issue-32922.js @@ -0,0 +1,80 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); + +if (!common.hasCrypto) + common.skip('missing crypto'); + +const http2 = require('http2'); +const net = require('net'); + +const { + HTTP2_HEADER_PATH, +} = http2.constants; + +// Create a normal session, as a control case +function normalSession(cb) { + http2.connect('https://google.com', (clientSession) => { + let error = null; + const req = clientSession.request({ [HTTP2_HEADER_PATH]: '/' }); + req.on('error', (err) => { + error = err; + }); + req.on('response', (_headers) => { + req.on('data', (_chunk) => { }); + req.on('end', () => { + clientSession.close(); + return cb(error); + }); + }); + }); +} +normalSession(common.mustCall(function(err) { + assert.ifError(err); +})); + +// Create a session using a socket that has not yet finished connecting +function socketNotFinished(done) { + const socket2 = net.connect(443, 'google.com'); + http2.connect('https://google.com', { socket2 }, (clientSession) => { + let error = null; + const req = clientSession.request({ [HTTP2_HEADER_PATH]: '/' }); + req.on('error', (err) => { + error = err; + }); + req.on('response', (_headers) => { + req.on('data', (_chunk) => { }); + req.on('end', () => { + clientSession.close(); + socket2.destroy(); + return done(error); + }); + }); + }); +} +socketNotFinished(common.mustCall(function(err) { + assert.ifError(err); +})); + +// Create a session using a socket that has finished connecting +function socketFinished(done) { + const socket = net.connect(443, 'google.com', () => { + http2.connect('https://google.com', { socket }, (clientSession) => { + let error = null; + const req = clientSession.request({ [HTTP2_HEADER_PATH]: '/' }); + req.on('error', (err) => { + error = err; + }); + req.on('response', (_headers) => { + req.on('data', (_chunk) => { }); + req.on('end', () => { + clientSession.close(); + return done(error); + }); + }); + }); + }); +} +socketFinished(common.mustCall(function(err) { + assert.ifError(err); +})); diff --git a/test/js-native-api/test_bigint/test_bigint.c b/test/js-native-api/test_bigint/test_bigint.c index 4befc171baa5da..c62a0a6a6c2bbc 100644 --- a/test/js-native-api/test_bigint/test_bigint.c +++ b/test/js-native-api/test_bigint/test_bigint.c @@ -1,5 +1,3 @@ -#define NAPI_EXPERIMENTAL - #include #include #include diff --git a/test/js-native-api/test_general/test.js b/test/js-native-api/test_general/test.js index 9b847f4f339e49..aa3a4eedc56634 100644 --- a/test/js-native-api/test_general/test.js +++ b/test/js-native-api/test_general/test.js @@ -32,8 +32,8 @@ assert.strictEqual(test_general.testGetPrototype(extendedObject), assert.notStrictEqual(test_general.testGetPrototype(baseObject), test_general.testGetPrototype(extendedObject)); -// Test version management functions. The expected version is currently 4. -assert.strictEqual(test_general.testGetVersion(), 5); +// Test version management functions +assert.strictEqual(test_general.testGetVersion(), 6); [ 123, diff --git a/test/js-native-api/test_instance_data/test_instance_data.c b/test/js-native-api/test_instance_data/test_instance_data.c index a64ebec0c1aba9..5255c3e4a02b94 100644 --- a/test/js-native-api/test_instance_data/test_instance_data.c +++ b/test/js-native-api/test_instance_data/test_instance_data.c @@ -1,6 +1,5 @@ #include #include -#define NAPI_EXPERIMENTAL #include #include "../common.h" diff --git a/test/js-native-api/test_object/binding.gyp b/test/js-native-api/test_object/binding.gyp index 1cb35d974dece9..e681f98f73ace6 100644 --- a/test/js-native-api/test_object/binding.gyp +++ b/test/js-native-api/test_object/binding.gyp @@ -5,6 +5,7 @@ "sources": [ "../common.c", "../entry_point.c", + "test_null.c", "test_object.c" ] } diff --git a/test/js-native-api/test_object/test.js b/test/js-native-api/test_object/test.js index 33ab49bb6fb5c5..2cd65af6b34de6 100644 --- a/test/js-native-api/test_object/test.js +++ b/test/js-native-api/test_object/test.js @@ -212,8 +212,10 @@ assert.strictEqual(newObject.test_string, 'test string'); inherited: 1 }); + const fooSymbol = Symbol('foo'); + object.normal = 2; - object[Symbol('foo')] = 3; + object[fooSymbol] = 3; Object.defineProperty(object, 'unenumerable', { value: 4, enumerable: false, @@ -224,6 +226,9 @@ assert.strictEqual(newObject.test_string, 'test string'); assert.deepStrictEqual(test_object.GetPropertyNames(object), ['5', 'normal', 'inherited']); + + assert.deepStrictEqual(test_object.GetSymbolNames(object), + [fooSymbol]); } // Verify that passing NULL to napi_set_property() results in the correct diff --git a/test/js-native-api/test_object/test_null.c b/test/js-native-api/test_object/test_null.c new file mode 100644 index 00000000000000..b6bf4df31cc918 --- /dev/null +++ b/test/js-native-api/test_object/test_null.c @@ -0,0 +1,400 @@ +#include + +#include "../common.h" +#include "test_null.h" + +static napi_value SetProperty(napi_env env, napi_callback_info info) { + napi_value return_value, object, key; + + NAPI_CALL(env, napi_create_object(env, &return_value)); + NAPI_CALL(env, napi_create_object(env, &object)); + NAPI_CALL(env, + napi_create_string_utf8(env, "someString", NAPI_AUTO_LENGTH, &key)); + + add_returned_status(env, + "envIsNull", + return_value, + "Invalid argument", + napi_invalid_arg, + napi_set_property(NULL, object, key, object)); + + napi_set_property(env, NULL, key, object); + add_last_status(env, "objectIsNull", return_value); + + napi_set_property(env, object, NULL, object); + add_last_status(env, "keyIsNull", return_value); + + napi_set_property(env, object, key, NULL); + add_last_status(env, "valueIsNull", return_value); + + return return_value; +} + +static napi_value GetProperty(napi_env env, napi_callback_info info) { + napi_value return_value, object, key, prop; + + NAPI_CALL(env, napi_create_object(env, &return_value)); + NAPI_CALL(env, napi_create_object(env, &object)); + NAPI_CALL(env, + napi_create_string_utf8(env, "someString", NAPI_AUTO_LENGTH, &key)); + + add_returned_status(env, + "envIsNull", + return_value, + "Invalid argument", + napi_invalid_arg, + napi_get_property(NULL, object, key, &prop)); + + napi_get_property(env, NULL, key, &prop); + add_last_status(env, "objectIsNull", return_value); + + napi_get_property(env, object, NULL, &prop); + add_last_status(env, "keyIsNull", return_value); + + napi_get_property(env, object, key, NULL); + add_last_status(env, "valueIsNull", return_value); + + return return_value; +} + +static napi_value TestBoolValuedPropApi(napi_env env, + napi_status (*api)(napi_env, napi_value, napi_value, bool*)) { + napi_value return_value, object, key; + bool result; + + NAPI_CALL(env, napi_create_object(env, &return_value)); + NAPI_CALL(env, napi_create_object(env, &object)); + NAPI_CALL(env, + napi_create_string_utf8(env, "someString", NAPI_AUTO_LENGTH, &key)); + + add_returned_status(env, + "envIsNull", + return_value, + "Invalid argument", + napi_invalid_arg, + api(NULL, object, key, &result)); + + api(env, NULL, key, &result); + add_last_status(env, "objectIsNull", return_value); + + api(env, object, NULL, &result); + add_last_status(env, "keyIsNull", return_value); + + api(env, object, key, NULL); + add_last_status(env, "valueIsNull", return_value); + + return return_value; +} + +static napi_value HasProperty(napi_env env, napi_callback_info info) { + return TestBoolValuedPropApi(env, napi_has_property); +} + +static napi_value HasOwnProperty(napi_env env, napi_callback_info info) { + return TestBoolValuedPropApi(env, napi_has_own_property); +} + +static napi_value DeleteProperty(napi_env env, napi_callback_info info) { + return TestBoolValuedPropApi(env, napi_delete_property); +} + +static napi_value SetNamedProperty(napi_env env, napi_callback_info info) { + napi_value return_value, object; + + NAPI_CALL(env, napi_create_object(env, &return_value)); + NAPI_CALL(env, napi_create_object(env, &object)); + + add_returned_status(env, + "envIsNull", + return_value, + "Invalid argument", + napi_invalid_arg, + napi_set_named_property(NULL, object, "key", object)); + + napi_set_named_property(env, NULL, "key", object); + add_last_status(env, "objectIsNull", return_value); + + napi_set_named_property(env, object, NULL, object); + add_last_status(env, "keyIsNull", return_value); + + napi_set_named_property(env, object, "key", NULL); + add_last_status(env, "valueIsNull", return_value); + + return return_value; +} + +static napi_value GetNamedProperty(napi_env env, napi_callback_info info) { + napi_value return_value, object, prop; + + NAPI_CALL(env, napi_create_object(env, &return_value)); + NAPI_CALL(env, napi_create_object(env, &object)); + + add_returned_status(env, + "envIsNull", + return_value, + "Invalid argument", + napi_invalid_arg, + napi_get_named_property(NULL, object, "key", &prop)); + + napi_get_named_property(env, NULL, "key", &prop); + add_last_status(env, "objectIsNull", return_value); + + napi_get_named_property(env, object, NULL, &prop); + add_last_status(env, "keyIsNull", return_value); + + napi_get_named_property(env, object, "key", NULL); + add_last_status(env, "valueIsNull", return_value); + + return return_value; +} + +static napi_value HasNamedProperty(napi_env env, napi_callback_info info) { + napi_value return_value, object; + bool result; + + NAPI_CALL(env, napi_create_object(env, &return_value)); + NAPI_CALL(env, napi_create_object(env, &object)); + + add_returned_status(env, + "envIsNull", + return_value, + "Invalid argument", + napi_invalid_arg, + napi_has_named_property(NULL, object, "key", &result)); + + napi_has_named_property(env, NULL, "key", &result); + add_last_status(env, "objectIsNull", return_value); + + napi_has_named_property(env, object, NULL, &result); + add_last_status(env, "keyIsNull", return_value); + + napi_has_named_property(env, object, "key", NULL); + add_last_status(env, "valueIsNull", return_value); + + return return_value; +} + +static napi_value SetElement(napi_env env, napi_callback_info info) { + napi_value return_value, object; + + NAPI_CALL(env, napi_create_object(env, &return_value)); + NAPI_CALL(env, napi_create_object(env, &object)); + + add_returned_status(env, + "envIsNull", + return_value, + "Invalid argument", + napi_invalid_arg, + napi_set_element(NULL, object, 0, object)); + + napi_set_element(env, NULL, 0, object); + add_last_status(env, "objectIsNull", return_value); + + napi_set_property(env, object, 0, NULL); + add_last_status(env, "valueIsNull", return_value); + + return return_value; +} + +static napi_value GetElement(napi_env env, napi_callback_info info) { + napi_value return_value, object, prop; + + NAPI_CALL(env, napi_create_object(env, &return_value)); + NAPI_CALL(env, napi_create_object(env, &object)); + + add_returned_status(env, + "envIsNull", + return_value, + "Invalid argument", + napi_invalid_arg, + napi_get_element(NULL, object, 0, &prop)); + + napi_get_property(env, NULL, 0, &prop); + add_last_status(env, "objectIsNull", return_value); + + napi_get_property(env, object, 0, NULL); + add_last_status(env, "valueIsNull", return_value); + + return return_value; +} + +static napi_value TestBoolValuedElementApi(napi_env env, + napi_status (*api)(napi_env, napi_value, uint32_t, bool*)) { + napi_value return_value, object; + bool result; + + NAPI_CALL(env, napi_create_object(env, &return_value)); + NAPI_CALL(env, napi_create_object(env, &object)); + + add_returned_status(env, + "envIsNull", + return_value, + "Invalid argument", + napi_invalid_arg, + api(NULL, object, 0, &result)); + + api(env, NULL, 0, &result); + add_last_status(env, "objectIsNull", return_value); + + api(env, object, 0, NULL); + add_last_status(env, "valueIsNull", return_value); + + return return_value; +} + +static napi_value HasElement(napi_env env, napi_callback_info info) { + return TestBoolValuedElementApi(env, napi_has_element); +} + +static napi_value DeleteElement(napi_env env, napi_callback_info info) { + return TestBoolValuedElementApi(env, napi_delete_element); +} + +static napi_value DefineProperties(napi_env env, napi_callback_info info) { + napi_value object, return_value; + + napi_property_descriptor desc = { + "prop", NULL, DefineProperties, NULL, NULL, NULL, napi_enumerable, NULL + }; + + NAPI_CALL(env, napi_create_object(env, &object)); + NAPI_CALL(env, napi_create_object(env, &return_value)); + + add_returned_status(env, + "envIsNull", + return_value, + "Invalid argument", + napi_invalid_arg, + napi_define_properties(NULL, object, 1, &desc)); + + napi_define_properties(env, NULL, 1, &desc); + add_last_status(env, "objectIsNull", return_value); + + napi_define_properties(env, object, 1, NULL); + add_last_status(env, "descriptorListIsNull", return_value); + + desc.utf8name = NULL; + napi_define_properties(env, object, 1, NULL); + add_last_status(env, "utf8nameIsNull", return_value); + desc.utf8name = "prop"; + + desc.method = NULL; + napi_define_properties(env, object, 1, NULL); + add_last_status(env, "methodIsNull", return_value); + desc.method = DefineProperties; + + return return_value; +} + +static napi_value GetPropertyNames(napi_env env, napi_callback_info info) { + napi_value return_value, props; + + NAPI_CALL(env, napi_create_object(env, &return_value)); + + add_returned_status(env, + "envIsNull", + return_value, + "Invalid argument", + napi_invalid_arg, + napi_get_property_names(NULL, return_value, &props)); + + napi_get_property_names(env, NULL, &props); + add_last_status(env, "objectIsNull", return_value); + + napi_get_property_names(env, return_value, NULL); + add_last_status(env, "valueIsNull", return_value); + + return return_value; +} + +static napi_value GetAllPropertyNames(napi_env env, napi_callback_info info) { + napi_value return_value, props; + + NAPI_CALL(env, napi_create_object(env, &return_value)); + + add_returned_status(env, + "envIsNull", + return_value, + "Invalid argument", + napi_invalid_arg, + napi_get_all_property_names(NULL, + return_value, + napi_key_own_only, + napi_key_writable, + napi_key_keep_numbers, + &props)); + + napi_get_all_property_names(env, + NULL, + napi_key_own_only, + napi_key_writable, + napi_key_keep_numbers, + &props); + add_last_status(env, "objectIsNull", return_value); + + napi_get_all_property_names(env, + return_value, + napi_key_own_only, + napi_key_writable, + napi_key_keep_numbers, + NULL); + add_last_status(env, "valueIsNull", return_value); + + return return_value; +} + +static napi_value GetPrototype(napi_env env, napi_callback_info info) { + napi_value return_value, proto; + + NAPI_CALL(env, napi_create_object(env, &return_value)); + + add_returned_status(env, + "envIsNull", + return_value, + "Invalid argument", + napi_invalid_arg, + napi_get_prototype(NULL, return_value, &proto)); + + napi_get_prototype(env, NULL, &proto); + add_last_status(env, "objectIsNull", return_value); + + napi_get_prototype(env, return_value, NULL); + add_last_status(env, "valueIsNull", return_value); + + return return_value; +} + +void init_test_null(napi_env env, napi_value exports) { + napi_value test_null; + + const napi_property_descriptor test_null_props[] = { + DECLARE_NAPI_PROPERTY("setProperty", SetProperty), + DECLARE_NAPI_PROPERTY("getProperty", GetProperty), + DECLARE_NAPI_PROPERTY("hasProperty", HasProperty), + DECLARE_NAPI_PROPERTY("hasOwnProperty", HasOwnProperty), + DECLARE_NAPI_PROPERTY("deleteProperty", DeleteProperty), + DECLARE_NAPI_PROPERTY("setNamedProperty", SetNamedProperty), + DECLARE_NAPI_PROPERTY("getNamedProperty", GetNamedProperty), + DECLARE_NAPI_PROPERTY("hasNamedProperty", HasNamedProperty), + DECLARE_NAPI_PROPERTY("setElement", SetElement), + DECLARE_NAPI_PROPERTY("getElement", GetElement), + DECLARE_NAPI_PROPERTY("hasElement", HasElement), + DECLARE_NAPI_PROPERTY("deleteElement", DeleteElement), + DECLARE_NAPI_PROPERTY("defineProperties", DefineProperties), + DECLARE_NAPI_PROPERTY("getPropertyNames", GetPropertyNames), + DECLARE_NAPI_PROPERTY("getAllPropertyNames", GetAllPropertyNames), + DECLARE_NAPI_PROPERTY("getPrototype", GetPrototype), + }; + + NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &test_null)); + NAPI_CALL_RETURN_VOID(env, napi_define_properties( + env, test_null, sizeof(test_null_props) / sizeof(*test_null_props), + test_null_props)); + + const napi_property_descriptor test_null_set = { + "testNull", NULL, NULL, NULL, NULL, test_null, napi_enumerable, NULL + }; + + NAPI_CALL_RETURN_VOID(env, + napi_define_properties(env, exports, 1, &test_null_set)); +} diff --git a/test/js-native-api/test_object/test_null.h b/test/js-native-api/test_object/test_null.h new file mode 100644 index 00000000000000..e10b708372c3b1 --- /dev/null +++ b/test/js-native-api/test_object/test_null.h @@ -0,0 +1,8 @@ +#ifndef TEST_JS_NATIVE_API_TEST_OBJECT_TEST_NULL_H_ +#define TEST_JS_NATIVE_API_TEST_OBJECT_TEST_NULL_H_ + +#include + +void init_test_null(napi_env env, napi_value exports); + +#endif // TEST_JS_NATIVE_API_TEST_OBJECT_TEST_NULL_H_ diff --git a/test/js-native-api/test_object/test_null.js b/test/js-native-api/test_object/test_null.js new file mode 100644 index 00000000000000..c94aa0fc84f19d --- /dev/null +++ b/test/js-native-api/test_object/test_null.js @@ -0,0 +1,52 @@ +'use strict'; +const common = require('../../common'); +const assert = require('assert'); + +// Test passing NULL to object-related N-APIs. +const { testNull } = require(`./build/${common.buildType}/test_object`); + +const expectedForProperty = { + envIsNull: 'Invalid argument', + objectIsNull: 'Invalid argument', + keyIsNull: 'Invalid argument', + valueIsNull: 'Invalid argument' +}; +assert.deepStrictEqual(testNull.setProperty(), expectedForProperty); +assert.deepStrictEqual(testNull.getProperty(), expectedForProperty); +assert.deepStrictEqual(testNull.hasProperty(), expectedForProperty); +assert.deepStrictEqual(testNull.hasOwnProperty(), expectedForProperty); +// It's OK not to want the result of a deletion. +assert.deepStrictEqual(testNull.deleteProperty(), + Object.assign({}, + expectedForProperty, + { valueIsNull: 'napi_ok' })); +assert.deepStrictEqual(testNull.setNamedProperty(), expectedForProperty); +assert.deepStrictEqual(testNull.getNamedProperty(), expectedForProperty); +assert.deepStrictEqual(testNull.hasNamedProperty(), expectedForProperty); + +const expectedForElement = { + envIsNull: 'Invalid argument', + objectIsNull: 'Invalid argument', + valueIsNull: 'Invalid argument' +}; +assert.deepStrictEqual(testNull.setElement(), expectedForElement); +assert.deepStrictEqual(testNull.getElement(), expectedForElement); +assert.deepStrictEqual(testNull.hasElement(), expectedForElement); +// It's OK not to want the result of a deletion. +assert.deepStrictEqual(testNull.deleteElement(), + Object.assign({}, + expectedForElement, + { valueIsNull: 'napi_ok' })); + +assert.deepStrictEqual(testNull.defineProperties(), { + envIsNull: 'Invalid argument', + objectIsNull: 'Invalid argument', + descriptorListIsNull: 'Invalid argument', + utf8nameIsNull: 'Invalid argument', + methodIsNull: 'Invalid argument', +}); + +// `expectedForElement` also works for the APIs below. +assert.deepStrictEqual(testNull.getPropertyNames(), expectedForElement); +assert.deepStrictEqual(testNull.getAllPropertyNames(), expectedForElement); +assert.deepStrictEqual(testNull.getPrototype(), expectedForElement); diff --git a/test/js-native-api/test_object/test_object.c b/test/js-native-api/test_object/test_object.c index db2d30c64a7cf4..08f619bf7ffc88 100644 --- a/test/js-native-api/test_object/test_object.c +++ b/test/js-native-api/test_object/test_object.c @@ -1,6 +1,7 @@ #include #include "../common.h" #include +#include "test_null.h" static int test_value = 3; @@ -82,6 +83,33 @@ static napi_value GetPropertyNames(napi_env env, napi_callback_info info) { return output; } +static napi_value GetSymbolNames(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value args[1]; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + + NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + + napi_valuetype value_type0; + NAPI_CALL(env, napi_typeof(env, args[0], &value_type0)); + + NAPI_ASSERT(env, + value_type0 == napi_object, + "Wrong type of arguments. Expects an object as first argument."); + + napi_value output; + NAPI_CALL(env, + napi_get_all_property_names( + env, + args[0], + napi_key_include_prototypes, + napi_key_skip_strings, + napi_key_numbers_to_strings, + &output)); + + return output; +} + static napi_value Set(napi_env env, napi_callback_info info) { size_t argc = 3; napi_value args[3]; @@ -449,6 +477,7 @@ napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_PROPERTY("Get", Get), DECLARE_NAPI_PROPERTY("GetNamed", GetNamed), DECLARE_NAPI_PROPERTY("GetPropertyNames", GetPropertyNames), + DECLARE_NAPI_PROPERTY("GetSymbolNames", GetSymbolNames), DECLARE_NAPI_PROPERTY("Set", Set), DECLARE_NAPI_PROPERTY("SetNamed", SetNamed), DECLARE_NAPI_PROPERTY("Has", Has), @@ -464,6 +493,8 @@ napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_PROPERTY("TestGetProperty", TestGetProperty), }; + init_test_null(env, exports); + NAPI_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); diff --git a/test/message/async_error_eval_esm.js b/test/message/async_error_eval_esm.js index 33675b5a9db286..0c9b7378d54729 100644 --- a/test/message/async_error_eval_esm.js +++ b/test/message/async_error_eval_esm.js @@ -26,7 +26,6 @@ main(); // --eval ESM { const child = spawnSync(process.execPath, [ - '--experimental-modules', '--input-type', 'module', '-e', diff --git a/test/message/async_error_eval_esm.out b/test/message/async_error_eval_esm.out index 578a9f5c26160e..769fac7a0d408e 100644 --- a/test/message/async_error_eval_esm.out +++ b/test/message/async_error_eval_esm.out @@ -1,7 +1,6 @@ Error: test at one (file:*/[eval1]:2:9) at two (file:*/[eval1]:15:9) - at processTicksAndRejections (internal/process/task_queues.js:*:*) at async three (file:*/[eval1]:18:3) at async four (file:*/[eval1]:22:3) at async main (file:*/[eval1]:28:5) diff --git a/test/message/async_error_sync_esm.mjs b/test/message/async_error_sync_esm.mjs index f16256d7778b81..fdb6a260d1284b 100644 --- a/test/message/async_error_sync_esm.mjs +++ b/test/message/async_error_sync_esm.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import four from '../fixtures/async-error.js'; diff --git a/test/message/async_error_sync_esm.out b/test/message/async_error_sync_esm.out index f34628ef44e52a..6577fff6944723 100644 --- a/test/message/async_error_sync_esm.out +++ b/test/message/async_error_sync_esm.out @@ -4,4 +4,4 @@ Error: test at two (*fixtures*async-error.js:17:9) at async three (*fixtures*async-error.js:20:3) at async four (*fixtures*async-error.js:24:3) - at async main (*message*async_error_sync_esm.mjs:7:5) + at async main (*message*async_error_sync_esm.mjs:6:5) diff --git a/test/message/esm_display_syntax_error.mjs b/test/message/esm_display_syntax_error.mjs index 829186725554bf..bda4a7e6ebe3a3 100644 --- a/test/message/esm_display_syntax_error.mjs +++ b/test/message/esm_display_syntax_error.mjs @@ -1,3 +1,2 @@ -// Flags: --experimental-modules 'use strict'; await async () => 0; diff --git a/test/message/esm_display_syntax_error.out b/test/message/esm_display_syntax_error.out index 5e82a1e1ee8f87..778d901129fa95 100644 --- a/test/message/esm_display_syntax_error.out +++ b/test/message/esm_display_syntax_error.out @@ -1,5 +1,5 @@ (node:*) ExperimentalWarning: The ESM module loader is experimental. -file:///*/test/message/esm_display_syntax_error.mjs:3 +file:///*/test/message/esm_display_syntax_error.mjs:2 await async () => 0; ^^^^^ diff --git a/test/message/esm_display_syntax_error_import.mjs b/test/message/esm_display_syntax_error_import.mjs index 4c41b292efd4d6..2173cb2b2e3a71 100644 --- a/test/message/esm_display_syntax_error_import.mjs +++ b/test/message/esm_display_syntax_error_import.mjs @@ -1,4 +1,3 @@ -// Flags: --experimental-modules /* eslint-disable no-unused-vars */ import '../common/index.mjs'; import { diff --git a/test/message/esm_display_syntax_error_import.out b/test/message/esm_display_syntax_error_import.out index a3601d6cb46fab..e39744a049b59b 100644 --- a/test/message/esm_display_syntax_error_import.out +++ b/test/message/esm_display_syntax_error_import.out @@ -1,5 +1,5 @@ (node:*) ExperimentalWarning: The ESM module loader is experimental. -file:///*/test/message/esm_display_syntax_error_import.mjs:6 +file:///*/test/message/esm_display_syntax_error_import.mjs:5 notfound ^^^^^^^^ SyntaxError: The requested module '../fixtures/es-module-loaders/module-named-exports.mjs' does not provide an export named 'notfound' diff --git a/test/message/esm_display_syntax_error_import_module.mjs b/test/message/esm_display_syntax_error_import_module.mjs index 346b3489fd920d..c0345c44fb3fda 100644 --- a/test/message/esm_display_syntax_error_import_module.mjs +++ b/test/message/esm_display_syntax_error_import_module.mjs @@ -1,3 +1,2 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import '../fixtures/es-module-loaders/syntax-error-import.mjs'; diff --git a/test/message/esm_display_syntax_error_module.mjs b/test/message/esm_display_syntax_error_module.mjs index 1f2b87ecd0cb1a..da40a4ead8d3c1 100644 --- a/test/message/esm_display_syntax_error_module.mjs +++ b/test/message/esm_display_syntax_error_module.mjs @@ -1,3 +1,2 @@ -// Flags: --experimental-modules import '../common/index.mjs'; import '../fixtures/es-module-loaders/syntax-error.mjs'; diff --git a/test/message/esm_loader_not_found.mjs b/test/message/esm_loader_not_found.mjs index fd6f29ac531507..2b47e5a03ec9e6 100644 --- a/test/message/esm_loader_not_found.mjs +++ b/test/message/esm_loader_not_found.mjs @@ -1,3 +1,3 @@ -// Flags: --experimental-modules --experimental-loader i-dont-exist +// Flags: --experimental-loader i-dont-exist import '../common/index.mjs'; console.log('This should not be printed'); diff --git a/test/message/esm_loader_not_found.out b/test/message/esm_loader_not_found.out index 770ffdc1cb3559..a054dacf2f930a 100644 --- a/test/message/esm_loader_not_found.out +++ b/test/message/esm_loader_not_found.out @@ -1,10 +1,11 @@ (node:*) ExperimentalWarning: The ESM module loader is experimental. (node:*) ExperimentalWarning: --experimental-loader is an experimental feature. This feature could change at any time -internal/modules/esm/resolve.js:* - let url = moduleWrapResolve(specifier, parentURL); - ^ - -Error: Cannot find package 'i-dont-exist' imported from * +internal/modules/run_main.js:* + internalBinding('errors').triggerUncaughtException( + ^ +Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'i-dont-exist' imported from * + at packageResolve (internal/modules/esm/resolve.js:*:*) + at moduleResolve (internal/modules/esm/resolve.js:*:*) at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:*:*) at Loader.resolve (internal/modules/esm/loader.js:*:*) at Loader.getModuleJob (internal/modules/esm/loader.js:*:*) @@ -12,7 +13,6 @@ Error: Cannot find package 'i-dont-exist' imported from * at internal/process/esm_loader.js:*:* at Object.initializeLoader (internal/process/esm_loader.js:*:*) at runMainESM (internal/modules/run_main.js:*:*) - at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:*:*) - at internal/main/run_main_module.js:*:* { + at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:*:*) { code: 'ERR_MODULE_NOT_FOUND' } diff --git a/test/message/esm_loader_not_found_cjs_hint_bare.js b/test/message/esm_loader_not_found_cjs_hint_bare.js new file mode 100644 index 00000000000000..b049fd203fef06 --- /dev/null +++ b/test/message/esm_loader_not_found_cjs_hint_bare.js @@ -0,0 +1,17 @@ +'use strict'; + +require('../common'); +const { spawn } = require('child_process'); +const { join } = require('path'); +const { fixturesDir } = require('../common/fixtures'); + +spawn( + process.execPath, + [ + join(fixturesDir, 'esm_loader_not_found_cjs_hint_bare.mjs') + ], + { + cwd: fixturesDir, + stdio: 'inherit' + } +); diff --git a/test/message/esm_loader_not_found_cjs_hint_bare.out b/test/message/esm_loader_not_found_cjs_hint_bare.out new file mode 100644 index 00000000000000..77c5248bb59423 --- /dev/null +++ b/test/message/esm_loader_not_found_cjs_hint_bare.out @@ -0,0 +1,17 @@ +(node:*) ExperimentalWarning: The ESM module loader is experimental. +internal/modules/run_main.js:* + internalBinding('errors').triggerUncaughtException( + ^ + +Error [ERR_MODULE_NOT_FOUND]: Cannot find module '*test*fixtures*node_modules*some_module*obj' imported from *test*fixtures*esm_loader_not_found_cjs_hint_bare.mjs +Did you mean to import some_module/obj.js? + at finalizeResolution (internal/modules/esm/resolve.js:*:*) + at packageResolve (internal/modules/esm/resolve.js:*:*) + at moduleResolve (internal/modules/esm/resolve.js:*:*) + at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:*:*) + at Loader.resolve (internal/modules/esm/loader.js:*:*) + at Loader.getModuleJob (internal/modules/esm/loader.js:*:*) + at ModuleWrap. (internal/modules/esm/module_job.js:*:*) + at link (internal/modules/esm/module_job.js:*:*) { + code: 'ERR_MODULE_NOT_FOUND' +} diff --git a/test/message/esm_loader_not_found_cjs_hint_relative.mjs b/test/message/esm_loader_not_found_cjs_hint_relative.mjs new file mode 100644 index 00000000000000..928186318bb09a --- /dev/null +++ b/test/message/esm_loader_not_found_cjs_hint_relative.mjs @@ -0,0 +1,3 @@ +// Flags: --experimental-loader ./test/common/fixtures +import '../common/index.mjs'; +console.log('This should not be printed'); diff --git a/test/message/esm_loader_not_found_cjs_hint_relative.out b/test/message/esm_loader_not_found_cjs_hint_relative.out new file mode 100644 index 00000000000000..82ede3ab9b9ec9 --- /dev/null +++ b/test/message/esm_loader_not_found_cjs_hint_relative.out @@ -0,0 +1,20 @@ +(node:*) ExperimentalWarning: The ESM module loader is experimental. +(node:*) ExperimentalWarning: --experimental-loader is an experimental feature. This feature could change at any time +internal/modules/run_main.js:* + internalBinding('errors').triggerUncaughtException( + ^ + +Error [ERR_MODULE_NOT_FOUND]: Cannot find module '*test*common*fixtures' imported from * +Did you mean to import ./test/common/fixtures.js? + at finalizeResolution (internal/modules/esm/resolve.js:*:*) + at moduleResolve (internal/modules/esm/resolve.js:*:*) + at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:*:*) + at Loader.resolve (internal/modules/esm/loader.js:*:*) + at Loader.getModuleJob (internal/modules/esm/loader.js:*:*) + at Loader.import (internal/modules/esm/loader.js:*:*) + at internal/process/esm_loader.js:*:* + at Object.initializeLoader (internal/process/esm_loader.js:*:*) + at runMainESM (internal/modules/run_main.js:*:*) + at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:*:*) { + code: 'ERR_MODULE_NOT_FOUND' +} diff --git a/test/message/esm_loader_syntax_error.mjs b/test/message/esm_loader_syntax_error.mjs index 7caad4056e08d2..68cde42e585644 100644 --- a/test/message/esm_loader_syntax_error.mjs +++ b/test/message/esm_loader_syntax_error.mjs @@ -1,3 +1,3 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/syntax-error.mjs +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/syntax-error.mjs import '../common/index.mjs'; console.log('This should not be printed'); diff --git a/test/message/vm_display_runtime_error.js b/test/message/vm_display_runtime_error.js index 230c45feab19a7..3ebbb1464d135d 100644 --- a/test/message/vm_display_runtime_error.js +++ b/test/message/vm_display_runtime_error.js @@ -28,7 +28,7 @@ console.error('beginning'); try { vm.runInThisContext('throw new Error("boo!")', { filename: 'test.vm' }); } catch (err) { - console.error(err.stack); + console.error(err); } vm.runInThisContext('throw new Error("spooky!")', { filename: 'test.vm' }); diff --git a/test/message/vm_display_syntax_error.js b/test/message/vm_display_syntax_error.js index 097b8e368c1249..ac9b4d17bd147b 100644 --- a/test/message/vm_display_syntax_error.js +++ b/test/message/vm_display_syntax_error.js @@ -28,7 +28,7 @@ console.error('beginning'); try { vm.runInThisContext('var 4;', { filename: 'foo.vm', displayErrors: true }); } catch (err) { - console.error(err.stack); + console.error(err); } vm.runInThisContext('var 5;', { filename: 'test.vm' }); diff --git a/test/node-api/test_callback_scope/binding.cc b/test/node-api/test_callback_scope/binding.cc index 1a06d04fce53e3..a8a755a016a7ee 100644 --- a/test/node-api/test_callback_scope/binding.cc +++ b/test/node-api/test_callback_scope/binding.cc @@ -4,21 +4,12 @@ namespace { -// the test needs to fake out the async structure, so we need to use -// the raw structure here and then cast as done behind the scenes -// in napi calls. -struct async_context { - double async_id; - double trigger_async_id; -}; - - napi_value RunInCallbackScope(napi_env env, napi_callback_info info) { size_t argc; - napi_value args[4]; + napi_value args[3]; NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr)); - NAPI_ASSERT(env, argc == 4 , "Wrong number of arguments"); + NAPI_ASSERT(env, argc == 3 , "Wrong number of arguments"); NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); @@ -28,40 +19,35 @@ napi_value RunInCallbackScope(napi_env env, napi_callback_info info) { "Wrong type of arguments. Expects an object as first argument."); NAPI_CALL(env, napi_typeof(env, args[1], &valuetype)); - NAPI_ASSERT(env, valuetype == napi_number, - "Wrong type of arguments. Expects a number as second argument."); + NAPI_ASSERT(env, valuetype == napi_string, + "Wrong type of arguments. Expects a string as second argument."); NAPI_CALL(env, napi_typeof(env, args[2], &valuetype)); - NAPI_ASSERT(env, valuetype == napi_number, - "Wrong type of arguments. Expects a number as third argument."); - - NAPI_CALL(env, napi_typeof(env, args[3], &valuetype)); NAPI_ASSERT(env, valuetype == napi_function, "Wrong type of arguments. Expects a function as third argument."); - struct async_context context; - NAPI_CALL(env, napi_get_value_double(env, args[1], &context.async_id)); - NAPI_CALL(env, - napi_get_value_double(env, args[2], &context.trigger_async_id)); + napi_async_context context; + NAPI_CALL(env, napi_async_init(env, args[0], args[1], &context)); napi_callback_scope scope = nullptr; NAPI_CALL( env, napi_open_callback_scope(env, args[0], - reinterpret_cast(&context), + context, &scope)); // if the function has an exception pending after the call that is ok // so we don't use NAPI_CALL as we must close the callback scope regardless napi_value result = nullptr; napi_status function_call_result = - napi_call_function(env, args[0], args[3], 0, nullptr, &result); + napi_call_function(env, args[0], args[2], 0, nullptr, &result); if (function_call_result != napi_ok) { GET_AND_THROW_LAST_ERROR((env)); } NAPI_CALL(env, napi_close_callback_scope(env, scope)); + NAPI_CALL(env, napi_async_destroy(env, context)); return result; } @@ -100,6 +86,7 @@ static void Callback(uv_work_t* req, int ignored) { NAPI_CALL_RETURN_VOID(env, napi_close_callback_scope(env, scope)); NAPI_CALL_RETURN_VOID(env, napi_close_handle_scope(env, handle_scope)); + NAPI_CALL_RETURN_VOID(env, napi_async_destroy(env, context)); delete req; } diff --git a/test/node-api/test_callback_scope/test-async-hooks.js b/test/node-api/test_callback_scope/test-async-hooks.js index 1a11bf60398f9b..22074428883d6b 100644 --- a/test/node-api/test_callback_scope/test-async-hooks.js +++ b/test/node-api/test_callback_scope/test-async-hooks.js @@ -12,18 +12,28 @@ process.emitWarning = () => {}; const { runInCallbackScope } = require(`./build/${common.buildType}/binding`); +const expectedResource = {}; +const expectedResourceType = 'test-resource'; let insideHook = false; +let expectedId; async_hooks.createHook({ + init: common.mustCall((id, type, triggerAsyncId, resource) => { + if (type !== expectedResourceType) { + return; + } + assert.strictEqual(resource, expectedResource); + expectedId = id; + }), before: common.mustCall((id) => { - assert.strictEqual(id, 1000); + assert.strictEqual(id, expectedId); insideHook = true; }), after: common.mustCall((id) => { - assert.strictEqual(id, 1000); + assert.strictEqual(id, expectedId); insideHook = false; }) }).enable(); -runInCallbackScope({}, 1000, 1000, () => { +runInCallbackScope(expectedResource, expectedResourceType, () => { assert(insideHook); }); diff --git a/test/node-api/test_callback_scope/test.js b/test/node-api/test_callback_scope/test.js index 2f2efe5f47b98a..abf9e41b8f5028 100644 --- a/test/node-api/test_callback_scope/test.js +++ b/test/node-api/test_callback_scope/test.js @@ -4,14 +4,14 @@ const common = require('../../common'); const assert = require('assert'); const { runInCallbackScope } = require(`./build/${common.buildType}/binding`); -assert.strictEqual(runInCallbackScope({}, 0, 0, () => 42), 42); +assert.strictEqual(runInCallbackScope({}, 'test-resource', () => 42), 42); { process.once('uncaughtException', common.mustCall((err) => { assert.strictEqual(err.message, 'foo'); })); - runInCallbackScope({}, 0, 0, () => { + runInCallbackScope({}, 'test-resource', () => { throw new Error('foo'); }); } diff --git a/test/node-api/test_general/test_general.c b/test/node-api/test_general/test_general.c index 05bccaf5c2cf4f..be805f782be8d5 100644 --- a/test/node-api/test_general/test_general.c +++ b/test/node-api/test_general/test_general.c @@ -1,4 +1,3 @@ -#define NAPI_EXPERIMENTAL #include #include #include "../../js-native-api/common.h" diff --git a/test/node-api/test_instance_data/addon.c b/test/node-api/test_instance_data/addon.c index 928b4dfaf8e11e..7cf27bf28ab7eb 100644 --- a/test/node-api/test_instance_data/addon.c +++ b/test/node-api/test_instance_data/addon.c @@ -1,6 +1,5 @@ #include #include -#define NAPI_EXPERIMENTAL #include static void addon_free(napi_env env, void* data, void* hint) { diff --git a/test/node-api/test_instance_data/test_instance_data.c b/test/node-api/test_instance_data/test_instance_data.c index 1a814e91c0665b..24fd502e836176 100644 --- a/test/node-api/test_instance_data/test_instance_data.c +++ b/test/node-api/test_instance_data/test_instance_data.c @@ -1,6 +1,5 @@ #include #include -#define NAPI_EXPERIMENTAL #include #include "../../js-native-api/common.h" diff --git a/test/node-api/test_instance_data/test_ref_then_set.c b/test/node-api/test_instance_data/test_ref_then_set.c index a0df1e5b9f8a64..10c779d3241e0e 100644 --- a/test/node-api/test_instance_data/test_ref_then_set.c +++ b/test/node-api/test_instance_data/test_ref_then_set.c @@ -1,6 +1,5 @@ #include #include -#define NAPI_EXPERIMENTAL #include napi_value addon_new(napi_env env, napi_value exports, bool ref_first); diff --git a/test/node-api/test_instance_data/test_set_then_ref.c b/test/node-api/test_instance_data/test_set_then_ref.c index 6ebed2d1e86871..9a1b31aeed390b 100644 --- a/test/node-api/test_instance_data/test_set_then_ref.c +++ b/test/node-api/test_instance_data/test_set_then_ref.c @@ -1,6 +1,5 @@ #include #include -#define NAPI_EXPERIMENTAL #include napi_value addon_new(napi_env env, napi_value exports, bool ref_first); diff --git a/test/node-api/test_worker_buffer_callback/test_worker_buffer_callback.c b/test/node-api/test_worker_buffer_callback/test_worker_buffer_callback.c index b911fd86380644..b327feaeb28878 100644 --- a/test/node-api/test_worker_buffer_callback/test_worker_buffer_callback.c +++ b/test/node-api/test_worker_buffer_callback/test_worker_buffer_callback.c @@ -32,7 +32,7 @@ NAPI_MODULE_INIT() { NAPI_CALL(env, napi_create_external_arraybuffer( env, data, - sizeof(data), + sizeof(char), finalize_cb, NULL, &buffer)); diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status index 0d11851bbd82e8..193cd820ac9683 100644 --- a/test/parallel/parallel.status +++ b/test/parallel/parallel.status @@ -5,8 +5,12 @@ prefix parallel # sample-test : PASS,FLAKY [true] # This section applies to all platforms +# https://github.com/nodejs/node/issues/29802 +test-http2-reset-flood: PASS,FLAKY [$system==win32] +# https://github.com/nodejs/node/issues/32863 +test-child-process-fork-args: PASS,FLAKY # https://github.com/nodejs/node/issues/20750 test-http2-client-upload: PASS,FLAKY # https://github.com/nodejs/node/issues/20750 @@ -33,6 +37,9 @@ test-worker-message-port-transfer-terminate: PASS,FLAKY [$arch==arm || $arch==arm64] # https://github.com/nodejs/node/issues/26610 test-async-hooks-http-parser-destroy: PASS,FLAKY +# https://github.com/nodejs/node/pull/31178 +test-crypto-dh-stateless: SKIP +test-crypto-keygen: SKIP [$system==solaris] # Also applies to SmartOS @@ -41,6 +48,10 @@ test-async-hooks-http-parser-destroy: PASS,FLAKY test-fs-stat-bigint: PASS,FLAKY # https://github.com/nodejs/node/issues/29802 test-http2-reset-flood: PASS,FLAKY +# https://github.com/nodejs/node/issues/28803 +test-stdout-close-catch: PASS,FLAKY +# https://github.com/nodejs/node/issues/31280 +test-worker-message-port-message-before-close: PASS,FLAKY [$system==aix] diff --git a/test/parallel/test-assert-if-error.js b/test/parallel/test-assert-if-error.js index cd6f99dfa43ea7..76539bb69b44f0 100644 --- a/test/parallel/test-assert-if-error.js +++ b/test/parallel/test-assert-if-error.js @@ -1,8 +1,7 @@ 'use strict'; require('../common'); -const assert = require('assert').strict; -/* eslint-disable no-restricted-properties */ +const assert = require('assert'); // Test that assert.ifError has the correct stack trace of both stacks. @@ -26,12 +25,13 @@ const stack = err.stack; try { assert.ifError(err); } catch (e) { - assert.equal(e.message, 'ifError got unwanted exception: test error'); - assert.equal(err.message, msg); - assert.equal(e.actual, err); - assert.equal(e.actual.stack, stack); - assert.equal(e.expected, null); - assert.equal(e.operator, 'ifError'); + assert.strictEqual(e.message, + 'ifError got unwanted exception: test error'); + assert.strictEqual(err.message, msg); + assert.strictEqual(e.actual, err); + assert.strictEqual(e.actual.stack, stack); + assert.strictEqual(e.expected, null); + assert.strictEqual(e.operator, 'ifError'); threw = true; } assert(threw); @@ -83,7 +83,7 @@ assert.ifError(undefined); } catch (e) { threw = true; assert.strictEqual(e.message, 'Missing expected exception.'); - assert(!e.stack.includes('throws'), e.stack); + assert(!e.stack.includes('throws'), e); } assert(threw); } diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index 6bdefee5d3d5b4..95351a1c930439 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -390,7 +390,7 @@ assert.throws( threw = true; assert.ok(e.message.includes(rangeError.message)); assert.ok(e instanceof assert.AssertionError); - assert.ok(!e.stack.includes('doesNotThrow'), e.stack); + assert.ok(!e.stack.includes('doesNotThrow'), e); } assert.ok(threw); } diff --git a/test/parallel/test-async-hooks-constructor.js b/test/parallel/test-async-hooks-constructor.js index f6f5c45607fc48..62ec854108e9dc 100644 --- a/test/parallel/test-async-hooks-constructor.js +++ b/test/parallel/test-async-hooks-constructor.js @@ -5,20 +5,17 @@ require('../common'); const assert = require('assert'); const async_hooks = require('async_hooks'); -const non_function = 10; +const nonFunctionArray = [null, -1, 1, {}, []]; -typeErrorForFunction('init'); -typeErrorForFunction('before'); -typeErrorForFunction('after'); -typeErrorForFunction('destroy'); -typeErrorForFunction('promiseResolve'); - -function typeErrorForFunction(functionName) { - assert.throws(() => { - async_hooks.createHook({ [functionName]: non_function }); - }, { - code: 'ERR_ASYNC_CALLBACK', - name: 'TypeError', - message: `hook.${functionName} must be a function` +['init', 'before', 'after', 'destroy', 'promiseResolve'].forEach( + (functionName) => { + nonFunctionArray.forEach((nonFunction) => { + assert.throws(() => { + async_hooks.createHook({ [functionName]: nonFunction }); + }, { + code: 'ERR_ASYNC_CALLBACK', + name: 'TypeError', + message: `hook.${functionName} must be a function`, + }); + }); }); -} diff --git a/test/parallel/test-async-hooks-execution-async-resource-await.js b/test/parallel/test-async-hooks-execution-async-resource-await.js new file mode 100644 index 00000000000000..8dc04c83d73103 --- /dev/null +++ b/test/parallel/test-async-hooks-execution-async-resource-await.js @@ -0,0 +1,54 @@ +'use strict'; + +const common = require('../common'); +const sleep = require('util').promisify(setTimeout); +const assert = require('assert'); +const { executionAsyncResource, createHook } = require('async_hooks'); +const { createServer, get } = require('http'); +const sym = Symbol('cls'); + +// Tests continuation local storage with the currentResource API +// through an async function + +assert.ok(executionAsyncResource()); + +createHook({ + init(asyncId, type, triggerAsyncId, resource) { + const cr = executionAsyncResource(); + resource[sym] = cr[sym]; + } +}).enable(); + +async function handler(req, res) { + executionAsyncResource()[sym] = { state: req.url }; + await sleep(10); + const { state } = executionAsyncResource()[sym]; + res.setHeader('content-type', 'application/json'); + res.end(JSON.stringify({ state })); +} + +const server = createServer(function(req, res) { + handler(req, res); +}); + +function test(n) { + get(`http://localhost:${server.address().port}/${n}`, common.mustCall(function(res) { + res.setEncoding('utf8'); + + let body = ''; + res.on('data', function(chunk) { + body += chunk; + }); + + res.on('end', common.mustCall(function() { + assert.deepStrictEqual(JSON.parse(body), { state: `/${n}` }); + })); + })); +} + +server.listen(0, common.mustCall(function() { + server.unref(); + for (let i = 0; i < 10; i++) { + test(i); + } +})); diff --git a/test/parallel/test-async-hooks-execution-async-resource.js b/test/parallel/test-async-hooks-execution-async-resource.js new file mode 100644 index 00000000000000..b3a9f76ef4ec3f --- /dev/null +++ b/test/parallel/test-async-hooks-execution-async-resource.js @@ -0,0 +1,49 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { executionAsyncResource, createHook } = require('async_hooks'); +const { createServer, get } = require('http'); +const sym = Symbol('cls'); + +// Tests continuation local storage with the executionAsyncResource API + +assert.ok(executionAsyncResource()); + +createHook({ + init(asyncId, type, triggerAsyncId, resource) { + const cr = executionAsyncResource(); + resource[sym] = cr[sym]; + } +}).enable(); + +const server = createServer(function(req, res) { + executionAsyncResource()[sym] = { state: req.url }; + setTimeout(function() { + const { state } = executionAsyncResource()[sym]; + res.setHeader('content-type', 'application/json'); + res.end(JSON.stringify({ state })); + }, 10); +}); + +function test(n) { + get(`http://localhost:${server.address().port}/${n}`, common.mustCall(function(res) { + res.setEncoding('utf8'); + + let body = ''; + res.on('data', function(chunk) { + body += chunk; + }); + + res.on('end', common.mustCall(function() { + assert.deepStrictEqual(JSON.parse(body), { state: `/${n}` }); + })); + })); +} + +server.listen(0, common.mustCall(function() { + server.unref(); + for (let i = 0; i < 10; i++) { + test(i); + } +})); diff --git a/test/parallel/test-async-local-storage-http-multiclients.js b/test/parallel/test-async-local-storage-http-multiclients.js new file mode 100644 index 00000000000000..1903d5825d75ba --- /dev/null +++ b/test/parallel/test-async-local-storage-http-multiclients.js @@ -0,0 +1,65 @@ +'use strict'; +const common = require('../common'); +const Countdown = require('../common/countdown'); +const assert = require('assert'); +const { AsyncLocalStorage } = require('async_hooks'); +const http = require('http'); +const cls = new AsyncLocalStorage(); +const NUM_CLIENTS = 10; + +// Run multiple clients that receive data from a server +// in multiple chunks, in a single non-closure function. +// Use the AsyncLocalStorage (ALS) APIs to maintain the context +// and data download. Make sure that individual clients +// receive their respective data, with no conflicts. + +// Set up a server that sends large buffers of data, filled +// with cardinal numbers, increasing per request +let index = 0; +const server = http.createServer((q, r) => { + // Send a large chunk as response, otherwise the data + // may be sent in a single chunk, and the callback in the + // client may be called only once, defeating the purpose of test + r.end((index++ % 10).toString().repeat(1024 * 1024)); +}); + +const countdown = new Countdown(NUM_CLIENTS, () => { + server.close(); +}); + +server.listen(0, common.mustCall(() => { + for (let i = 0; i < NUM_CLIENTS; i++) { + cls.run(new Map(), common.mustCall(() => { + const options = { port: server.address().port }; + const req = http.get(options, common.mustCall((res) => { + const store = cls.getStore(); + store.set('data', ''); + + // Make ondata and onend non-closure + // functions and fully dependent on ALS + res.setEncoding('utf8'); + res.on('data', ondata); + res.on('end', common.mustCall(onend)); + })); + req.end(); + })); + } +})); + +// Accumulate the current data chunk with the store data +function ondata(d) { + const store = cls.getStore(); + assert.notStrictEqual(store, undefined); + let chunk = store.get('data'); + chunk += d; + store.set('data', chunk); +} + +// Retrieve the store data, and test for homogeneity +function onend() { + const store = cls.getStore(); + assert.notStrictEqual(store, undefined); + const data = store.get('data'); + assert.strictEqual(data, data[0].repeat(data.length)); + countdown.dec(); +} diff --git a/test/parallel/test-async-wrap-constructor.js b/test/parallel/test-async-wrap-constructor.js index 8e96e9ce3021ef..e89bc49df02333 100644 --- a/test/parallel/test-async-wrap-constructor.js +++ b/test/parallel/test-async-wrap-constructor.js @@ -6,14 +6,15 @@ require('../common'); const assert = require('assert'); const async_hooks = require('async_hooks'); -for (const badArg of [0, 1, false, true, null, 'hello']) { +[0, 1, false, true, null, 'hello'].forEach((badArg) => { const hookNames = ['init', 'before', 'after', 'destroy', 'promiseResolve']; - for (const field of hookNames) { + hookNames.forEach((field) => { assert.throws(() => { async_hooks.createHook({ [field]: badArg }); }, { code: 'ERR_ASYNC_CALLBACK', name: 'TypeError', + message: `hook.${field} must be a function` }); - } -} + }); +}); diff --git a/test/parallel/test-bash-completion.js b/test/parallel/test-bash-completion.js index f6a1cc405eb02c..4492c2f85c470f 100644 --- a/test/parallel/test-bash-completion.js +++ b/test/parallel/test-bash-completion.js @@ -2,14 +2,15 @@ require('../common'); const assert = require('assert'); const child_process = require('child_process'); -const { inspect } = require('util'); +const { debuglog, inspect } = require('util'); +const debug = debuglog('test'); const p = child_process.spawnSync( process.execPath, [ '--completion-bash' ]); assert.ifError(p.error); const output = p.stdout.toString().trim().replace(/\r/g, ''); -console.log(output); +debug(output); const prefix = `_node_complete() { local cur_word options diff --git a/test/parallel/test-bootstrap-modules.js b/test/parallel/test-bootstrap-modules.js index 9b075d981a7e5c..e07ca03e807b5d 100644 --- a/test/parallel/test-bootstrap-modules.js +++ b/test/parallel/test-bootstrap-modules.js @@ -22,6 +22,7 @@ const expectedModules = new Set([ 'Internal Binding native_module', 'Internal Binding options', 'Internal Binding process_methods', + 'Internal Binding report', 'Internal Binding string_decoder', 'Internal Binding task_queue', 'Internal Binding timers', @@ -49,11 +50,22 @@ const expectedModules = new Set([ 'NativeModule internal/modules/run_main', 'NativeModule internal/modules/cjs/helpers', 'NativeModule internal/modules/cjs/loader', + 'NativeModule internal/modules/esm/create_dynamic_module', + 'NativeModule internal/modules/esm/get_format', + 'NativeModule internal/modules/esm/get_source', + 'NativeModule internal/modules/esm/loader', + 'NativeModule internal/modules/esm/module_job', + 'NativeModule internal/modules/esm/module_map', + 'NativeModule internal/modules/esm/resolve', + 'NativeModule internal/modules/esm/transform_source', + 'NativeModule internal/modules/esm/translators', + 'NativeModule internal/process/esm_loader', 'NativeModule internal/options', 'NativeModule internal/priority_queue', 'NativeModule internal/process/execution', 'NativeModule internal/process/per_thread', 'NativeModule internal/process/promises', + 'NativeModule internal/process/report', 'NativeModule internal/process/signal', 'NativeModule internal/process/task_queues', 'NativeModule internal/process/warning', @@ -66,6 +78,7 @@ const expectedModules = new Set([ 'NativeModule internal/util/inspect', 'NativeModule internal/util/types', 'NativeModule internal/validators', + 'NativeModule internal/vm/module', 'NativeModule path', 'NativeModule timers', 'NativeModule url', diff --git a/test/parallel/test-buffer-indexof.js b/test/parallel/test-buffer-indexof.js index d789c9b46cf868..b17520366e506a 100644 --- a/test/parallel/test-buffer-indexof.js +++ b/test/parallel/test-buffer-indexof.js @@ -606,3 +606,18 @@ assert.strictEqual(reallyLong.lastIndexOf(pattern), 0); assert.strictEqual(haystack.indexOf(needle), 2); assert.strictEqual(haystack.lastIndexOf(needle), haystack.length - 3); } + +// Avoid abort because of invalid usage +// see https://github.com/nodejs/node/issues/32753 +{ + assert.throws(() => { + const buffer = require('buffer'); + new buffer.Buffer.prototype.lastIndexOf(1, 'str'); + }, { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + message: 'The "buffer" argument must be an instance of Buffer, ' + + 'TypedArray, or DataView. ' + + 'Received an instance of lastIndexOf' + }); +} diff --git a/test/parallel/test-buffer-pool-untransferable.js b/test/parallel/test-buffer-pool-untransferable.js new file mode 100644 index 00000000000000..96e109c113fee8 --- /dev/null +++ b/test/parallel/test-buffer-pool-untransferable.js @@ -0,0 +1,20 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { MessageChannel } = require('worker_threads'); + +// Make sure that the pools used by the Buffer implementation are not +// transferable. +// Refs: https://github.com/nodejs/node/issues/32752 + +const a = Buffer.from('hello world'); +const b = Buffer.from('hello world'); +assert.strictEqual(a.buffer, b.buffer); +const length = a.length; + +const { port1 } = new MessageChannel(); +port1.postMessage(a, [ a.buffer ]); + +// Verify that the pool ArrayBuffer has not actually been transfered: +assert.strictEqual(a.buffer, b.buffer); +assert.strictEqual(a.length, length); diff --git a/test/parallel/test-child-process-bad-stdio.js b/test/parallel/test-child-process-bad-stdio.js index 45294d7d82d4f6..1f382e2966043d 100644 --- a/test/parallel/test-child-process-bad-stdio.js +++ b/test/parallel/test-child-process-bad-stdio.js @@ -1,5 +1,5 @@ 'use strict'; -// Flags: --expose_internals +// Flags: --expose-internals const common = require('../common'); const assert = require('assert'); const cp = require('child_process'); diff --git a/test/parallel/test-child-process-default-options.js b/test/parallel/test-child-process-default-options.js index a0ab2bfd4d98e9..39f90deaebb7aa 100644 --- a/test/parallel/test-child-process-default-options.js +++ b/test/parallel/test-child-process-default-options.js @@ -20,15 +20,16 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +const { isWindows } = require('../common'); const assert = require('assert'); const spawn = require('child_process').spawn; +const debug = require('util').debuglog('test'); process.env.HELLO = 'WORLD'; let child; -if (common.isWindows) { +if (isWindows) { child = spawn('cmd.exe', ['/c', 'set'], {}); } else { child = spawn('/usr/bin/env', [], {}); @@ -39,7 +40,7 @@ let response = ''; child.stdout.setEncoding('utf8'); child.stdout.on('data', function(chunk) { - console.log(`stdout: ${chunk}`); + debug(`stdout: ${chunk}`); response += chunk; }); diff --git a/test/parallel/test-child-process-double-pipe.js b/test/parallel/test-child-process-double-pipe.js index 135993f7df450c..11e9ce1cb532a6 100644 --- a/test/parallel/test-child-process-double-pipe.js +++ b/test/parallel/test-child-process-double-pipe.js @@ -20,17 +20,22 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +const { + isWindows, + mustCall, + mustCallAtLeast, +} = require('../common'); const assert = require('assert'); const os = require('os'); const spawn = require('child_process').spawn; +const debug = require('util').debuglog('test'); // We're trying to reproduce: // $ echo "hello\nnode\nand\nworld" | grep o | sed s/o/a/ let grep, sed, echo; -if (common.isWindows) { +if (isWindows) { grep = spawn('grep', ['--binary', 'o']); sed = spawn('sed', ['--binary', 's/o/O/']); echo = spawn('cmd.exe', @@ -54,62 +59,66 @@ if (common.isWindows) { // pipe echo | grep -echo.stdout.on('data', function(data) { - console.error(`grep stdin write ${data.length}`); +echo.stdout.on('data', mustCallAtLeast((data) => { + debug(`grep stdin write ${data.length}`); if (!grep.stdin.write(data)) { echo.stdout.pause(); } -}); +})); -grep.stdin.on('drain', function(data) { +// TODO(@jasnell): This does not appear to ever be +// emitted. It's not clear if it is necessary. +grep.stdin.on('drain', (data) => { echo.stdout.resume(); }); // Propagate end from echo to grep -echo.stdout.on('end', function(code) { +echo.stdout.on('end', mustCall((code) => { grep.stdin.end(); -}); +})); -echo.on('exit', function() { - console.error('echo exit'); -}); +echo.on('exit', mustCall(() => { + debug('echo exit'); +})); -grep.on('exit', function() { - console.error('grep exit'); -}); +grep.on('exit', mustCall(() => { + debug('grep exit'); +})); -sed.on('exit', function() { - console.error('sed exit'); -}); +sed.on('exit', mustCall(() => { + debug('sed exit'); +})); // pipe grep | sed -grep.stdout.on('data', function(data) { - console.error(`grep stdout ${data.length}`); +grep.stdout.on('data', mustCallAtLeast((data) => { + debug(`grep stdout ${data.length}`); if (!sed.stdin.write(data)) { grep.stdout.pause(); } -}); +})); -sed.stdin.on('drain', function(data) { +// TODO(@jasnell): This does not appear to ever be +// emitted. It's not clear if it is necessary. +sed.stdin.on('drain', (data) => { grep.stdout.resume(); }); // Propagate end from grep to sed -grep.stdout.on('end', function(code) { - console.error('grep stdout end'); +grep.stdout.on('end', mustCall((code) => { + debug('grep stdout end'); sed.stdin.end(); -}); +})); let result = ''; // print sed's output -sed.stdout.on('data', function(data) { +sed.stdout.on('data', mustCallAtLeast((data) => { result += data.toString('utf8', 0, data.length); - console.log(data); -}); + debug(data); +})); -sed.stdout.on('end', function(code) { +sed.stdout.on('end', mustCall((code) => { assert.strictEqual(result, `hellO${os.EOL}nOde${os.EOL}wOrld${os.EOL}`); -}); +})); diff --git a/test/parallel/test-child-process-env.js b/test/parallel/test-child-process-env.js index 0a20ee232f7c32..783e392c3e42a8 100644 --- a/test/parallel/test-child-process-env.js +++ b/test/parallel/test-child-process-env.js @@ -20,9 +20,14 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +const { + isWindows, + mustCall, + mustCallAtLeast, +} = require('../common'); const assert = require('assert'); const os = require('os'); +const debug = require('util').debuglog('test'); const spawn = require('child_process').spawn; @@ -38,7 +43,7 @@ Object.setPrototypeOf(env, { }); let child; -if (common.isWindows) { +if (isWindows) { child = spawn('cmd.exe', ['/c', 'set'], { env }); } else { child = spawn('/usr/bin/env', [], { env }); @@ -49,15 +54,15 @@ let response = ''; child.stdout.setEncoding('utf8'); -child.stdout.on('data', (chunk) => { - console.log(`stdout: ${chunk}`); +child.stdout.on('data', mustCallAtLeast((chunk) => { + debug(`stdout: ${chunk}`); response += chunk; -}); +})); -process.on('exit', () => { +child.stdout.on('end', mustCall(() => { assert.ok(response.includes('HELLO=WORLD')); assert.ok(response.includes('FOO=BAR')); assert.ok(!response.includes('UNDEFINED=undefined')); assert.ok(response.includes('NULL=null')); assert.ok(response.includes(`EMPTY=${os.EOL}`)); -}); +})); diff --git a/test/parallel/test-child-process-exec-any-shells-windows.js b/test/parallel/test-child-process-exec-any-shells-windows.js index 8cdd03d7e510d5..0e78b665689720 100644 --- a/test/parallel/test-child-process-exec-any-shells-windows.js +++ b/test/parallel/test-child-process-exec-any-shells-windows.js @@ -23,10 +23,10 @@ const test = (shell) => { })); }; const testCopy = (shellName, shellPath) => { - // Copy the executable to a path with spaces, to ensure there are no issues + // Symlink the executable to a path with spaces, to ensure there are no issues // related to quoting of argv0 const copyPath = `${tmpPath}\\${shellName}`; - fs.copyFileSync(shellPath, copyPath); + fs.symlinkSync(shellPath, copyPath); test(copyPath); }; diff --git a/test/parallel/test-child-process-exec-env.js b/test/parallel/test-child-process-exec-env.js index eac07bce88b204..f5156436199ff6 100644 --- a/test/parallel/test-child-process-exec-env.js +++ b/test/parallel/test-child-process-exec-env.js @@ -20,9 +20,11 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +const { isWindows } = require('../common'); const assert = require('assert'); const exec = require('child_process').exec; +const debug = require('util').debuglog('test'); + let success_count = 0; let error_count = 0; let response = ''; @@ -31,9 +33,9 @@ let child; function after(err, stdout, stderr) { if (err) { error_count++; - console.log(`error!: ${err.code}`); - console.log(`stdout: ${JSON.stringify(stdout)}`); - console.log(`stderr: ${JSON.stringify(stderr)}`); + debug(`error!: ${err.code}`); + debug(`stdout: ${JSON.stringify(stdout)}`); + debug(`stderr: ${JSON.stringify(stderr)}`); assert.strictEqual(err.killed, false); } else { success_count++; @@ -41,7 +43,7 @@ function after(err, stdout, stderr) { } } -if (!common.isWindows) { +if (!isWindows) { child = exec('/usr/bin/env', { env: { 'HELLO': 'WORLD' } }, after); } else { child = exec('set', @@ -55,7 +57,7 @@ child.stdout.on('data', function(chunk) { }); process.on('exit', function() { - console.log('response: ', response); + debug('response: ', response); assert.strictEqual(success_count, 1); assert.strictEqual(error_count, 0); assert.ok(response.includes('HELLO=WORLD')); diff --git a/test/parallel/test-child-process-exec-kill-throws.js b/test/parallel/test-child-process-exec-kill-throws.js index d6a0d4da19eae7..fbc9677f531068 100644 --- a/test/parallel/test-child-process-exec-kill-throws.js +++ b/test/parallel/test-child-process-exec-kill-throws.js @@ -1,5 +1,5 @@ 'use strict'; -// Flags: --expose_internals +// Flags: --expose-internals const common = require('../common'); const assert = require('assert'); const cp = require('child_process'); diff --git a/test/parallel/test-child-process-fork-getconnections.js b/test/parallel/test-child-process-fork-getconnections.js index b96d61238a0dd8..a6843ea64ba41f 100644 --- a/test/parallel/test-child-process-fork-getconnections.js +++ b/test/parallel/test-child-process-fork-getconnections.js @@ -20,7 +20,7 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const fork = require('child_process').fork; const net = require('net'); @@ -29,7 +29,7 @@ const count = 12; if (process.argv[2] === 'child') { const sockets = []; - process.on('message', function(m, socket) { + process.on('message', common.mustCall((m, socket) => { function sendClosed(id) { process.send({ id: id, status: 'closed' }); } @@ -52,41 +52,39 @@ if (process.argv[2] === 'child') { sockets[m.id].destroy(); } } - }); + })); } else { const child = fork(process.argv[1], ['child']); - child.on('exit', function(code, signal) { + child.on('exit', common.mustCall((code, signal) => { if (!subprocessKilled) { assert.fail('subprocess died unexpectedly! ' + `code: ${code} signal: ${signal}`); } - }); + })); const server = net.createServer(); const sockets = []; - let sent = 0; - server.on('connection', function(socket) { + server.on('connection', common.mustCall((socket) => { child.send({ cmd: 'new' }, socket); sockets.push(socket); if (sockets.length === count) { closeSockets(0); } - }); + }, count)); - let disconnected = 0; - server.on('listening', function() { + const onClose = common.mustCall(count); + + server.on('listening', common.mustCall(() => { let j = count; while (j--) { const client = net.connect(server.address().port, '127.0.0.1'); - client.on('close', function() { - disconnected += 1; - }); + client.on('close', onClose); } - }); + })); let subprocessKilled = false; function closeSockets(i) { @@ -97,29 +95,18 @@ if (process.argv[2] === 'child') { return; } - child.once('message', function(m) { + child.once('message', common.mustCall((m) => { assert.strictEqual(m.status, 'closed'); - server.getConnections(function(err, num) { + server.getConnections(common.mustCall((err, num) => { assert.ifError(err); assert.strictEqual(num, count - (i + 1)); closeSockets(i + 1); - }); - }); - sent++; + })); + })); child.send({ id: i, cmd: 'close' }); } - let closeEmitted = false; - server.on('close', function() { - closeEmitted = true; - }); + server.on('close', common.mustCall()); server.listen(0, '127.0.0.1'); - - process.on('exit', function() { - assert.strictEqual(sent, count); - assert.strictEqual(disconnected, count); - assert.ok(closeEmitted); - console.log('ok'); - }); } diff --git a/test/parallel/test-child-process-fork-net-server.js b/test/parallel/test-child-process-fork-net-server.js index 9d39e149af26f7..3a3f01c6d664cb 100644 --- a/test/parallel/test-child-process-fork-net-server.js +++ b/test/parallel/test-child-process-fork-net-server.js @@ -24,56 +24,60 @@ const common = require('../common'); const assert = require('assert'); const fork = require('child_process').fork; const net = require('net'); +const debug = require('util').debuglog('test'); -function ProgressTracker(missing, callback) { - this.missing = missing; - this.callback = callback; -} -ProgressTracker.prototype.done = function() { - this.missing -= 1; - this.check(); -}; -ProgressTracker.prototype.check = function() { - if (this.missing === 0) this.callback(); -}; +const Countdown = require('../common/countdown'); if (process.argv[2] === 'child') { let serverScope; - process.on('message', function onServer(msg, server) { + // TODO(@jasnell): The message event is not called consistently + // across platforms. Need to investigate if it can be made + // more consistent. + const onServer = (msg, server) => { if (msg.what !== 'server') return; process.removeListener('message', onServer); serverScope = server; - server.on('connection', function(socket) { - console.log('CHILD: got connection'); + // TODO(@jasnell): This is apparently not called consistently + // across platforms. Need to investigate if it can be made + // more consistent. + server.on('connection', (socket) => { + debug('CHILD: got connection'); process.send({ what: 'connection' }); socket.destroy(); }); // Start making connection from parent. - console.log('CHILD: server listening'); + debug('CHILD: server listening'); process.send({ what: 'listening' }); - }); + }; - process.on('message', function onClose(msg) { + process.on('message', onServer); + + // TODO(@jasnell): The close event is not called consistently + // across platforms. Need to investigate if it can be made + // more consistent. + const onClose = (msg) => { if (msg.what !== 'close') return; process.removeListener('message', onClose); - serverScope.on('close', function() { + serverScope.on('close', common.mustCall(() => { process.send({ what: 'close' }); - }); + })); serverScope.close(); - }); + }; + + process.on('message', onClose); process.send({ what: 'ready' }); } else { const child = fork(process.argv[1], ['child']); - child.on('exit', common.mustCall(function(code, signal) { + child.on('exit', common.mustCall((code, signal) => { const message = `CHILD: died with ${code}, ${signal}`; assert.strictEqual(code, 0, message); })); @@ -82,64 +86,74 @@ if (process.argv[2] === 'child') { function testServer(callback) { // Destroy server execute callback when done. - const progress = new ProgressTracker(2, function() { - server.on('close', function() { - console.log('PARENT: server closed'); + const countdown = new Countdown(2, () => { + server.on('close', common.mustCall(() => { + debug('PARENT: server closed'); child.send({ what: 'close' }); - }); + })); server.close(); }); // We expect 4 connections and close events. - const connections = new ProgressTracker(4, progress.done.bind(progress)); - const closed = new ProgressTracker(4, progress.done.bind(progress)); + const connections = new Countdown(4, () => countdown.dec()); + const closed = new Countdown(4, () => countdown.dec()); // Create server and send it to child. const server = net.createServer(); - server.on('connection', function(socket) { - console.log('PARENT: got connection'); + + // TODO(@jasnell): The specific number of times the connection + // event is emitted appears to be variable across platforms. + // Need to investigate why and whether it can be made + // more consistent. + server.on('connection', (socket) => { + debug('PARENT: got connection'); socket.destroy(); - connections.done(); + connections.dec(); }); - server.on('listening', function() { - console.log('PARENT: server listening'); + + server.on('listening', common.mustCall(() => { + debug('PARENT: server listening'); child.send({ what: 'server' }, server); - }); + })); server.listen(0); // Handle client messages. - function messageHandlers(msg) { - + // TODO(@jasnell): The specific number of times the message + // event is emitted appears to be variable across platforms. + // Need to investigate why and whether it can be made + // more consistent. + const messageHandlers = (msg) => { if (msg.what === 'listening') { // Make connections. let socket; for (let i = 0; i < 4; i++) { - socket = net.connect(server.address().port, function() { - console.log('CLIENT: connected'); - }); - socket.on('close', function() { - closed.done(); - console.log('CLIENT: closed'); - }); + socket = net.connect(server.address().port, common.mustCall(() => { + debug('CLIENT: connected'); + })); + socket.on('close', common.mustCall(() => { + closed.dec(); + debug('CLIENT: closed'); + })); } } else if (msg.what === 'connection') { // Child got connection - connections.done(); + connections.dec(); } else if (msg.what === 'close') { child.removeListener('message', messageHandlers); callback(); } - } + }; child.on('message', messageHandlers); } - // Create server and send it to child. - child.on('message', function onReady(msg) { + const onReady = common.mustCall((msg) => { if (msg.what !== 'ready') return; child.removeListener('message', onReady); - testServer(common.mustCall()); }); + + // Create server and send it to child. + child.on('message', onReady); } diff --git a/test/parallel/test-child-process-fork-net-socket.js b/test/parallel/test-child-process-fork-net-socket.js index 8e3d9ee16e2e56..28da94f4ef566b 100644 --- a/test/parallel/test-child-process-fork-net-socket.js +++ b/test/parallel/test-child-process-fork-net-socket.js @@ -20,68 +20,77 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +const { + mustCall, + mustCallAtLeast, +} = require('../common'); const assert = require('assert'); const fork = require('child_process').fork; const net = require('net'); +const debug = require('util').debuglog('test'); if (process.argv[2] === 'child') { - process.on('message', function onSocket(msg, socket) { + const onSocket = mustCall((msg, socket) => { if (msg.what !== 'socket') return; process.removeListener('message', onSocket); socket.end('echo'); - console.log('CHILD: got socket'); + debug('CHILD: got socket'); }); + process.on('message', onSocket); + process.send({ what: 'ready' }); } else { const child = fork(process.argv[1], ['child']); - child.on('exit', common.mustCall(function(code, signal) { + child.on('exit', mustCall((code, signal) => { const message = `CHILD: died with ${code}, ${signal}`; assert.strictEqual(code, 0, message); })); // Send net.Socket to child. - function testSocket(callback) { + function testSocket() { // Create a new server and connect to it, // but the socket will be handled by the child. const server = net.createServer(); - server.on('connection', function(socket) { - socket.on('close', function() { - console.log('CLIENT: socket closed'); + server.on('connection', mustCall((socket) => { + // TODO(@jasnell): Close does not seem to actually be called. + // It is not clear if it is needed. + socket.on('close', () => { + debug('CLIENT: socket closed'); }); child.send({ what: 'socket' }, socket); - }); - server.on('close', function() { - console.log('PARENT: server closed'); - callback(); - }); + })); + server.on('close', mustCall(() => { + debug('PARENT: server closed'); + })); - server.listen(0, function() { - console.log('testSocket, listening'); + server.listen(0, mustCall(() => { + debug('testSocket, listening'); const connect = net.connect(server.address().port); let store = ''; - connect.on('data', function(chunk) { + connect.on('data', mustCallAtLeast((chunk) => { store += chunk; - console.log('CLIENT: got data'); - }); - connect.on('close', function() { - console.log('CLIENT: closed'); + debug('CLIENT: got data'); + })); + connect.on('close', mustCall(() => { + debug('CLIENT: closed'); assert.strictEqual(store, 'echo'); server.close(); - }); - }); + })); + })); } - // Create socket and send it to child. - child.on('message', function onReady(msg) { + const onReady = mustCall((msg) => { if (msg.what !== 'ready') return; child.removeListener('message', onReady); - testSocket(common.mustCall()); + testSocket(); }); + + // Create socket and send it to child. + child.on('message', onReady); } diff --git a/test/parallel/test-child-process-fork-net.js b/test/parallel/test-child-process-fork-net.js index 6607d7981666de..0760ca44adc3c7 100644 --- a/test/parallel/test-child-process-fork-net.js +++ b/test/parallel/test-child-process-fork-net.js @@ -20,64 +20,69 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +const { + mustCall, + mustCallAtLeast, + platformTimeout, +} = require('../common'); const assert = require('assert'); const fork = require('child_process').fork; const net = require('net'); +const debug = require('util').debuglog('test'); const count = 12; if (process.argv[2] === 'child') { const needEnd = []; const id = process.argv[3]; - process.on('message', function(m, socket) { + process.on('message', mustCall((m, socket) => { if (!socket) return; - console.error(`[${id}] got socket ${m}`); + debug(`[${id}] got socket ${m}`); // Will call .end('end') or .write('write'); socket[m](m); socket.resume(); - socket.on('data', function() { - console.error(`[${id}] socket.data ${m}`); - }); + socket.on('data', mustCallAtLeast(() => { + debug(`[${id}] socket.data ${m}`); + })); - socket.on('end', function() { - console.error(`[${id}] socket.end ${m}`); - }); + socket.on('end', mustCall(() => { + debug(`[${id}] socket.end ${m}`); + })); // Store the unfinished socket if (m === 'write') { needEnd.push(socket); } - socket.on('close', function(had_error) { - console.error(`[${id}] socket.close ${had_error} ${m}`); - }); + socket.on('close', mustCall((had_error) => { + debug(`[${id}] socket.close ${had_error} ${m}`); + })); - socket.on('finish', function() { - console.error(`[${id}] socket finished ${m}`); - }); - }); + socket.on('finish', mustCall(() => { + debug(`[${id}] socket finished ${m}`); + })); + })); - process.on('message', function(m) { + process.on('message', mustCall((m) => { if (m !== 'close') return; - console.error(`[${id}] got close message`); - needEnd.forEach(function(endMe, i) { - console.error(`[${id}] ending ${i}/${needEnd.length}`); + debug(`[${id}] got close message`); + needEnd.forEach((endMe, i) => { + debug(`[${id}] ending ${i}/${needEnd.length}`); endMe.end('end'); }); - }); + })); - process.on('disconnect', function() { - console.error(`[${id}] process disconnect, ending`); - needEnd.forEach(function(endMe, i) { - console.error(`[${id}] ending ${i}/${needEnd.length}`); + process.on('disconnect', mustCall(() => { + debug(`[${id}] process disconnect, ending`); + needEnd.forEach((endMe, i) => { + debug(`[${id}] ending ${i}/${needEnd.length}`); endMe.end('end'); }); - }); + })); } else { @@ -106,8 +111,10 @@ if (process.argv[2] === 'child') { } connected += 1; - socket.once('close', function() { - console.log(`[m] socket closed, total ${++closed}`); + // TODO(@jasnell): This is not actually being called. + // It is not clear if it is needed. + socket.once('close', () => { + debug(`[m] socket closed, total ${++closed}`); }); if (connected === count) { @@ -116,26 +123,27 @@ if (process.argv[2] === 'child') { }); let disconnected = 0; - server.on('listening', function() { + server.on('listening', mustCall(() => { let j = count; while (j--) { - const client = net.connect(this.address().port, '127.0.0.1'); - client.on('error', function() { + const client = net.connect(server.address().port, '127.0.0.1'); + client.on('error', () => { // This can happen if we kill the subprocess too early. // The client should still get a close event afterwards. - console.error('[m] CLIENT: error event'); + // It likely won't so don't wrap in a mustCall. + debug('[m] CLIENT: error event'); }); - client.on('close', function() { - console.error('[m] CLIENT: close event'); + client.on('close', mustCall(() => { + debug('[m] CLIENT: close event'); disconnected += 1; - }); + })); client.resume(); } - }); + })); let closeEmitted = false; - server.on('close', common.mustCall(function() { + server.on('close', mustCall(function() { closeEmitted = true; child1.kill(); @@ -148,12 +156,12 @@ if (process.argv[2] === 'child') { function closeServer() { server.close(); - setTimeout(function() { + setTimeout(() => { assert(!closeEmitted); child1.send('close'); child2.send('close'); child3.disconnect(); - }, 200); + }, platformTimeout(200)); } process.on('exit', function() { diff --git a/test/parallel/test-child-process-fork-ref2.js b/test/parallel/test-child-process-fork-ref2.js index f34d67ee17fcec..8f27e58fb0c831 100644 --- a/test/parallel/test-child-process-fork-ref2.js +++ b/test/parallel/test-child-process-fork-ref2.js @@ -20,26 +20,31 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +const { + mustCall, + mustNotCall, + platformTimeout, +} = require('../common'); const fork = require('child_process').fork; +const debug = require('util').debuglog('test'); if (process.argv[2] === 'child') { - console.log('child -> call disconnect'); + debug('child -> call disconnect'); process.disconnect(); - setTimeout(function() { - console.log('child -> will this keep it alive?'); - process.on('message', common.mustNotCall()); - }, 400); + setTimeout(() => { + debug('child -> will this keep it alive?'); + process.on('message', mustNotCall()); + }, platformTimeout(400)); } else { const child = fork(__filename, ['child']); - child.on('disconnect', function() { - console.log('parent -> disconnect'); - }); + child.on('disconnect', mustCall(() => { + debug('parent -> disconnect'); + })); - child.once('exit', function() { - console.log('parent -> exit'); - }); + child.once('exit', mustCall(() => { + debug('parent -> exit'); + })); } diff --git a/test/parallel/test-child-process-fork.js b/test/parallel/test-child-process-fork.js index a771f84e681fd9..a357f4fbc192ef 100644 --- a/test/parallel/test-child-process-fork.js +++ b/test/parallel/test-child-process-fork.js @@ -18,13 +18,14 @@ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. - +// Flags: --no-warnings 'use strict'; const common = require('../common'); const assert = require('assert'); -const fork = require('child_process').fork; +const { fork } = require('child_process'); const args = ['foo', 'bar']; const fixtures = require('../common/fixtures'); +const debug = require('util').debuglog('test'); const n = fork(fixtures.path('child-process-spawn-node.js'), args); @@ -32,7 +33,7 @@ assert.strictEqual(n.channel, n._channel); assert.deepStrictEqual(args, ['foo', 'bar']); n.on('message', (m) => { - console.log('PARENT got message:', m); + debug('PARENT got message:', m); assert.ok(m.foo); }); diff --git a/test/parallel/test-child-process-http-socket-leak.js b/test/parallel/test-child-process-http-socket-leak.js index 553a3277532b04..07cc0ebbf95e76 100644 --- a/test/parallel/test-child-process-http-socket-leak.js +++ b/test/parallel/test-child-process-http-socket-leak.js @@ -1,4 +1,4 @@ -// Flags: --expose_internals +// Flags: --expose-internals 'use strict'; diff --git a/test/parallel/test-child-process-ipc.js b/test/parallel/test-child-process-ipc.js index f1652a91e6968e..d776f9594bb40b 100644 --- a/test/parallel/test-child-process-ipc.js +++ b/test/parallel/test-child-process-ipc.js @@ -21,47 +21,43 @@ 'use strict'; -require('../common'); +const { + mustCall, + mustNotCall, +} = require('../common'); const assert = require('assert'); +const debug = require('util').debuglog('test'); const { spawn } = require('child_process'); const fixtures = require('../common/fixtures'); const sub = fixtures.path('echo.js'); -let gotHelloWorld = false; -let gotEcho = false; - const child = spawn(process.argv[0], [sub]); -child.stderr.on('data', function(data) { - console.log(`parent stderr: ${data}`); -}); +child.stderr.on('data', mustNotCall()); child.stdout.setEncoding('utf8'); -child.stdout.on('data', function(data) { - console.log(`child said: ${JSON.stringify(data)}`); - if (!gotHelloWorld) { - console.error('testing for hello world'); - assert.strictEqual(data, 'hello world\r\n'); - gotHelloWorld = true; - console.error('writing echo me'); - child.stdin.write('echo me\r\n'); +const messages = [ + 'hello world\r\n', + 'echo me\r\n', +]; + +child.stdout.on('data', mustCall((data) => { + debug(`child said: ${JSON.stringify(data)}`); + const test = messages.shift(); + debug(`testing for '${test}'`); + assert.strictEqual(data, test); + if (messages.length) { + debug(`writing '${messages[0]}'`); + child.stdin.write(messages[0]); } else { - console.error('testing for echo me'); - assert.strictEqual(data, 'echo me\r\n'); - gotEcho = true; + assert.strictEqual(messages.length, 0); child.stdin.end(); } -}); - -child.stdout.on('end', function(data) { - console.log('child end'); -}); - +}, messages.length)); -process.on('exit', function() { - assert.ok(gotHelloWorld); - assert.ok(gotEcho); -}); +child.stdout.on('end', mustCall((data) => { + debug('child end'); +})); diff --git a/test/parallel/test-child-process-spawnsync-kill-signal.js b/test/parallel/test-child-process-spawnsync-kill-signal.js index 61f9b63b3d7e57..d31d629c503e22 100644 --- a/test/parallel/test-child-process-spawnsync-kill-signal.js +++ b/test/parallel/test-child-process-spawnsync-kill-signal.js @@ -1,4 +1,4 @@ -// Flags: --expose_internals +// Flags: --expose-internals 'use strict'; const common = require('../common'); const assert = require('assert'); diff --git a/test/parallel/test-child-process-spawnsync-shell.js b/test/parallel/test-child-process-spawnsync-shell.js index f94a67a804b82d..feb329e2ae6323 100644 --- a/test/parallel/test-child-process-spawnsync-shell.js +++ b/test/parallel/test-child-process-spawnsync-shell.js @@ -1,4 +1,4 @@ -// Flags: --expose_internals +// Flags: --expose-internals 'use strict'; const common = require('../common'); const assert = require('assert'); diff --git a/test/parallel/test-child-process-spawnsync-timeout.js b/test/parallel/test-child-process-spawnsync-timeout.js index 35df6cee22f5f2..5991f5d626411a 100644 --- a/test/parallel/test-child-process-spawnsync-timeout.js +++ b/test/parallel/test-child-process-spawnsync-timeout.js @@ -24,14 +24,16 @@ const common = require('../common'); const assert = require('assert'); const spawnSync = require('child_process').spawnSync; +const { debuglog } = require('util'); +const debug = debuglog('test'); const TIMER = 200; const SLEEP = common.platformTimeout(5000); switch (process.argv[2]) { case 'child': - setTimeout(function() { - console.log('child fired'); + setTimeout(() => { + debug('child fired'); process.exit(1); }, SLEEP); break; diff --git a/test/parallel/test-child-process-stdin.js b/test/parallel/test-child-process-stdin.js index 29f78df7d0ae88..24a79d623813a1 100644 --- a/test/parallel/test-child-process-stdin.js +++ b/test/parallel/test-child-process-stdin.js @@ -20,9 +20,13 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +const { + mustCall, + mustCallAtLeast, + mustNotCall, +} = require('../common'); const assert = require('assert'); - +const debug = require('util').debuglog('test'); const spawn = require('child_process').spawn; const cat = spawn('cat'); @@ -38,21 +42,21 @@ cat.stdin.end(); let response = ''; cat.stdout.setEncoding('utf8'); -cat.stdout.on('data', function(chunk) { - console.log(`stdout: ${chunk}`); +cat.stdout.on('data', mustCallAtLeast((chunk) => { + debug(`stdout: ${chunk}`); response += chunk; -}); +})); -cat.stdout.on('end', common.mustCall()); +cat.stdout.on('end', mustCall()); -cat.stderr.on('data', common.mustNotCall()); +cat.stderr.on('data', mustNotCall()); -cat.stderr.on('end', common.mustCall()); +cat.stderr.on('end', mustCall()); -cat.on('exit', common.mustCall(function(status) { +cat.on('exit', mustCall((status) => { assert.strictEqual(status, 0); })); -cat.on('close', common.mustCall(function() { +cat.on('close', mustCall(() => { assert.strictEqual(response, 'hello world'); })); diff --git a/test/parallel/test-child-process-stdio-big-write-end.js b/test/parallel/test-child-process-stdio-big-write-end.js index 07656c04ca936d..85e6a8b321088f 100644 --- a/test/parallel/test-child-process-stdio-big-write-end.js +++ b/test/parallel/test-child-process-stdio-big-write-end.js @@ -20,8 +20,13 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +const { + mustCall, + mustCallAtLeast, +} = require('../common'); const assert = require('assert'); +const debug = require('util').debuglog('test'); + let bufsize = 0; switch (process.argv[2]) { @@ -40,12 +45,12 @@ function parent() { let n = ''; child.stdout.setEncoding('ascii'); - child.stdout.on('data', function(c) { + child.stdout.on('data', mustCallAtLeast((c) => { n += c; - }); - child.stdout.on('end', common.mustCall(function() { + })); + child.stdout.on('end', mustCall(() => { assert.strictEqual(+n, sent); - console.log('ok'); + debug('ok'); })); // Write until the buffer fills up. @@ -71,10 +76,11 @@ function parent() { function child() { let received = 0; - process.stdin.on('data', function(c) { + process.stdin.on('data', mustCallAtLeast((c) => { received += c.length; - }); - process.stdin.on('end', function() { + })); + process.stdin.on('end', mustCall(() => { + // This console.log is part of the test. console.log(received); - }); + })); } diff --git a/test/parallel/test-child-process-stdout-flush-exit.js b/test/parallel/test-child-process-stdout-flush-exit.js index cc1fa83fa9aaec..3c5f00d9bb2b13 100644 --- a/test/parallel/test-child-process-stdout-flush-exit.js +++ b/test/parallel/test-child-process-stdout-flush-exit.js @@ -24,6 +24,7 @@ const common = require('../common'); const assert = require('assert'); // If child process output to console and exit +// The console.log statements here are part of the test. if (process.argv[2] === 'child') { console.log('hello'); for (let i = 0; i < 200; i++) { @@ -40,18 +41,15 @@ if (process.argv[2] === 'child') { let stdout = ''; - child.stderr.setEncoding('utf8'); - child.stderr.on('data', function(data) { - assert.fail(`Unexpected parent stderr: ${data}`); - }); + child.stderr.on('data', common.mustNotCall()); // Check if we receive both 'hello' at start and 'goodbye' at end child.stdout.setEncoding('utf8'); - child.stdout.on('data', function(data) { + child.stdout.on('data', common.mustCallAtLeast((data) => { stdout += data; - }); + })); - child.on('close', common.mustCall(function() { + child.on('close', common.mustCall(() => { assert.strictEqual(stdout.slice(0, 6), 'hello\n'); assert.strictEqual(stdout.slice(stdout.length - 8), 'goodbye\n'); })); diff --git a/test/parallel/test-child-process-validate-stdio.js b/test/parallel/test-child-process-validate-stdio.js index 5b0259f19bbd1f..ff214ee2d78262 100644 --- a/test/parallel/test-child-process-validate-stdio.js +++ b/test/parallel/test-child-process-validate-stdio.js @@ -1,5 +1,5 @@ 'use strict'; -// Flags: --expose_internals +// Flags: --expose-internals const common = require('../common'); const assert = require('assert'); diff --git a/test/parallel/test-child-process-windows-hide.js b/test/parallel/test-child-process-windows-hide.js index 67ed18d7338d83..ec00978408bb16 100644 --- a/test/parallel/test-child-process-windows-hide.js +++ b/test/parallel/test-child-process-windows-hide.js @@ -1,4 +1,4 @@ -// Flags: --expose_internals +// Flags: --expose-internals 'use strict'; const common = require('../common'); const assert = require('assert'); diff --git a/test/parallel/test-cli-eval.js b/test/parallel/test-cli-eval.js index 71482205932a27..be063b79fad320 100644 --- a/test/parallel/test-cli-eval.js +++ b/test/parallel/test-cli-eval.js @@ -234,7 +234,7 @@ child.exec(`${nodejs} --use-strict -p process.execArgv`, // Assert that "42\n" is written to stdout on module eval. -const execOptions = '--experimental-modules --input-type module'; +const execOptions = '--input-type module'; child.exec( `${nodejs} ${execOptions} --eval "console.log(42)"`, common.mustCall((err, stdout) => { diff --git a/test/parallel/test-cli-node-options.js b/test/parallel/test-cli-node-options.js index 0bbe4c9eae1ba2..2fc22ca477ce94 100644 --- a/test/parallel/test-cli-node-options.js +++ b/test/parallel/test-cli-node-options.js @@ -67,6 +67,7 @@ if (common.hasCrypto) { // V8 options expect('--abort_on-uncaught_exception', 'B\n'); expect('--disallow-code-generation-from-strings', 'B\n'); +expect('--huge-max-old-generation-size', 'B\n'); expect('--jitless', 'B\n'); expect('--max-old-space-size=0', 'B\n'); expect('--stack-trace-limit=100', diff --git a/test/parallel/test-cli-syntax-piped-bad.js b/test/parallel/test-cli-syntax-piped-bad.js index 5da5f07e57d0ad..abd924848fc417 100644 --- a/test/parallel/test-cli-syntax-piped-bad.js +++ b/test/parallel/test-cli-syntax-piped-bad.js @@ -39,7 +39,7 @@ syntaxArgs.forEach(function(arg) { const stdin = 'export var p = 5; var foo bar;'; const c = spawnSync( node, - ['--experimental-modules', '--input-type=module', '--no-warnings', arg], + ['--input-type=module', '--no-warnings', arg], { encoding: 'utf8', input: stdin } ); diff --git a/test/parallel/test-cli-syntax-piped-good.js b/test/parallel/test-cli-syntax-piped-good.js index 5df5eb1c51d105..43de5d32f40d40 100644 --- a/test/parallel/test-cli-syntax-piped-good.js +++ b/test/parallel/test-cli-syntax-piped-good.js @@ -30,7 +30,7 @@ syntaxArgs.forEach(function(arg) { const stdin = 'export var p = 5; throw new Error("should not get run");'; const c = spawnSync( node, - ['--experimental-modules', '--no-warnings', '--input-type=module', arg], + ['--no-warnings', '--input-type=module', arg], { encoding: 'utf8', input: stdin } ); diff --git a/test/parallel/test-cluster-concurrent-disconnect.js b/test/parallel/test-cluster-concurrent-disconnect.js new file mode 100644 index 00000000000000..22f72040263027 --- /dev/null +++ b/test/parallel/test-cluster-concurrent-disconnect.js @@ -0,0 +1,48 @@ +'use strict'; + +// Ref: https://github.com/nodejs/node/issues/32106 + +const common = require('../common'); + +const assert = require('assert'); +const cluster = require('cluster'); +const os = require('os'); + +if (cluster.isMaster) { + const workers = []; + const numCPUs = os.cpus().length; + let waitOnline = numCPUs; + for (let i = 0; i < numCPUs; i++) { + const worker = cluster.fork(); + workers[i] = worker; + worker.once('online', common.mustCall(() => { + if (--waitOnline === 0) + for (const worker of workers) + if (worker.isConnected()) + worker.send(i % 2 ? 'disconnect' : 'destroy'); + })); + + // These errors can occur due to the nature of the test, we might be trying + // to send messages when the worker is disconnecting. + worker.on('error', (err) => { + assert.strictEqual(err.syscall, 'write'); + assert.strictEqual(err.code, 'EPIPE'); + }); + + worker.once('disconnect', common.mustCall(() => { + for (const worker of workers) + if (worker.isConnected()) + worker.send('disconnect'); + })); + + worker.once('exit', common.mustCall((code, signal) => { + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + })); + } +} else { + process.on('message', (msg) => { + if (cluster.worker.isConnected()) + cluster.worker[msg](); + }); +} diff --git a/test/parallel/test-console-group.js b/test/parallel/test-console-group.js index 99c01fc36ea469..9b7e836a436add 100644 --- a/test/parallel/test-console-group.js +++ b/test/parallel/test-console-group.js @@ -12,7 +12,7 @@ const Console = require('console').Console; let c, stdout, stderr; -function setup() { +function setup(groupIndentation) { stdout = ''; hijackStdout(function(data) { stdout += data; @@ -25,7 +25,8 @@ function setup() { c = new Console({ stdout: process.stdout, stderr: process.stderr, - colorMode: false }); + colorMode: false, + groupIndentation: groupIndentation }); } function teardown() { @@ -155,3 +156,86 @@ function teardown() { assert(!keys.includes('Symbol(groupIndent)'), 'groupIndent should not be enumerable'); } + +// Check custom groupIndentation. +{ + setup(3); + const expectedOut = 'Set the groupIndentation parameter to 3\n' + + 'This is the outer level\n' + + ' Level 2\n' + + ' Level 3\n' + + ' Back to level 2\n' + + 'Back to the outer level\n' + + 'Still at the outer level\n'; + + + const expectedErr = ' More of level 3\n'; + + c.log('Set the groupIndentation parameter to 3'); + c.log('This is the outer level'); + c.group(); + c.log('Level 2'); + c.group(); + c.log('Level 3'); + c.warn('More of level 3'); + c.groupEnd(); + c.log('Back to level 2'); + c.groupEnd(); + c.log('Back to the outer level'); + c.groupEnd(); + c.log('Still at the outer level'); + + assert.strictEqual(stdout, expectedOut); + assert.strictEqual(stderr, expectedErr); + teardown(); +} + +// Check the correctness of the groupIndentation parameter. +{ + // TypeError + [null, 'str', [], false, true, {}].forEach((e) => { + assert.throws( + () => { + new Console({ stdout: process.stdout, + stderr: process.stderr, + groupIndentation: e }); + }, + { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError' + } + ); + }); + + // RangeError for integer + [NaN, 1.01].forEach((e) => { + assert.throws( + () => { + new Console({ stdout: process.stdout, + stderr: process.stderr, + groupIndentation: e }); + }, + { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + message: /an integer/, + } + ); + }); + + // RangeError + [-1, 1001].forEach((e) => { + assert.throws( + () => { + new Console({ stdout: process.stdout, + stderr: process.stderr, + groupIndentation: e }); + }, + { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + message: />= 0 && <= 1000/, + } + ); + }); +} diff --git a/test/parallel/test-constants.js b/test/parallel/test-constants.js index 62c62b101a10a8..08d1f1dbcdd0ab 100644 --- a/test/parallel/test-constants.js +++ b/test/parallel/test-constants.js @@ -1,4 +1,4 @@ -// Flags: --expose_internals +// Flags: --expose-internals 'use strict'; require('../common'); diff --git a/test/parallel/test-crypto-cipheriv-decipheriv.js b/test/parallel/test-crypto-cipheriv-decipheriv.js index e2279a689c05ec..07591fdfffd072 100644 --- a/test/parallel/test-crypto-cipheriv-decipheriv.js +++ b/test/parallel/test-crypto-cipheriv-decipheriv.js @@ -210,7 +210,11 @@ for (let n = 1; n < 256; n += 1) { // Passing an invalid cipher name should throw. assert.throws( () => crypto.createCipheriv('aes-127', Buffer.alloc(16), null), - /Unknown cipher/); + { + name: 'Error', + code: 'ERR_CRYPTO_UNKNOWN_CIPHER', + message: 'Unknown cipher' + }); // Passing a key with an invalid length should throw. assert.throws( diff --git a/test/parallel/test-crypto-dh-leak.js b/test/parallel/test-crypto-dh-leak.js index 9ba8d29e155dc6..65486dbd80cb64 100644 --- a/test/parallel/test-crypto-dh-leak.js +++ b/test/parallel/test-crypto-dh-leak.js @@ -4,6 +4,8 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.config.variables.asan) + common.skip('ASAN messes with memory measurements'); const assert = require('assert'); const crypto = require('crypto'); diff --git a/test/parallel/test-crypto-dh-stateless.js b/test/parallel/test-crypto-dh-stateless.js new file mode 100644 index 00000000000000..b01cea76b221c1 --- /dev/null +++ b/test/parallel/test-crypto-dh-stateless.js @@ -0,0 +1,223 @@ +'use strict'; +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const crypto = require('crypto'); + +assert.throws(() => crypto.diffieHellman(), { + name: 'TypeError', + code: 'ERR_INVALID_ARG_TYPE', + message: 'The "options" argument must be of type object. Received undefined' +}); + +function test({ publicKey: alicePublicKey, privateKey: alicePrivateKey }, + { publicKey: bobPublicKey, privateKey: bobPrivateKey }, + expectedValue) { + const buf1 = crypto.diffieHellman({ + privateKey: alicePrivateKey, + publicKey: bobPublicKey + }); + const buf2 = crypto.diffieHellman({ + privateKey: bobPrivateKey, + publicKey: alicePublicKey + }); + assert.deepStrictEqual(buf1, buf2); + + if (expectedValue !== undefined) + assert.deepStrictEqual(buf1, expectedValue); +} + +const alicePrivateKey = crypto.createPrivateKey({ + key: '-----BEGIN PRIVATE KEY-----\n' + + 'MIIBoQIBADCB1QYJKoZIhvcNAQMBMIHHAoHBAP//////////yQ/aoiFowjTExmKL\n' + + 'gNwc0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVt\n' + + 'bVHCReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR\n' + + '7ORbPcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkH\n' + + 'cJaWbWcMNU5KvJgE8XRsCMojcyf//////////wIBAgSBwwKBwEh82IAVnYNf0Kjb\n' + + 'qYSImDFyg9sH6CJ0GzRK05e6hM3dOSClFYi4kbA7Pr7zyfdn2SH6wSlNS14Jyrtt\n' + + 'HePrRSeYl1T+tk0AfrvaLmyM56F+9B3jwt/nzqr5YxmfVdXb2aQV53VS/mm3pB2H\n' + + 'iIt9FmvFaaOVe2DupqSr6xzbf/zyON+WF5B5HNVOWXswgpgdUsCyygs98hKy/Xje\n' + + 'TGzJUoWInW39t0YgMXenJrkS0m6wol8Rhxx81AGgELNV7EHZqg==\n' + + '-----END PRIVATE KEY-----', + format: 'pem' +}); + +const alicePublicKey = crypto.createPublicKey({ + key: '-----BEGIN PUBLIC KEY-----\n' + + 'MIIBnzCB1QYJKoZIhvcNAQMBMIHHAoHBAP//////////yQ/aoiFowjTExmKLgNwc\n' + + '0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHC\n' + + 'ReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7ORb\n' + + 'PcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkHcJaW\n' + + 'bWcMNU5KvJgE8XRsCMojcyf//////////wIBAgOBxAACgcBR7+iL5qx7aOb9K+aZ\n' + + 'y2oLt7ST33sDKT+nxpag6cWDDWzPBKFDCJ8fr0v7yW453px8N4qi4R7SYYxFBaYN\n' + + 'Y3JvgDg1ct2JC9sxSuUOLqSFn3hpmAjW7cS0kExIVGfdLlYtIqbhhuo45cTEbVIM\n' + + 'rDEz8mjIlnvbWpKB9+uYmbjfVoc3leFvUBqfG2In2m23Md1swsPxr3n7g68H66JX\n' + + 'iBJKZLQMqNdbY14G9rdKmhhTJrQjC+i7Q/wI8JPhOFzHIGA=\n' + + '-----END PUBLIC KEY-----', + format: 'pem' +}); + +const bobPrivateKey = crypto.createPrivateKey({ + key: '-----BEGIN PRIVATE KEY-----\n' + + 'MIIBoQIBADCB1QYJKoZIhvcNAQMBMIHHAoHBAP//////////yQ/aoiFowjTExmKL\n' + + 'gNwc0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVt\n' + + 'bVHCReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR\n' + + '7ORbPcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkH\n' + + 'cJaWbWcMNU5KvJgE8XRsCMojcyf//////////wIBAgSBwwKBwHxnT7Zw2Ehh1vyw\n' + + 'eolzQFHQzyuT0y+3BF+FxK2Ox7VPguTp57wQfGHbORJ2cwCdLx2mFM7gk4tZ6COS\n' + + 'E3Vta85a/PuhKXNLRdP79JgLnNtVtKXB+ePDS5C2GgXH1RHvqEdJh7JYnMy7Zj4P\n' + + 'GagGtIy3dV5f4FA0B/2C97jQ1pO16ah8gSLQRKsNpTCw2rqsZusE0rK6RaYAef7H\n' + + 'y/0tmLIsHxLIn+WK9CANqMbCWoP4I178BQaqhiOBkNyNZ0ndqA==\n' + + '-----END PRIVATE KEY-----', + format: 'pem' +}); + +const bobPublicKey = crypto.createPublicKey({ + key: '-----BEGIN PUBLIC KEY-----\n' + + 'MIIBoDCB1QYJKoZIhvcNAQMBMIHHAoHBAP//////////yQ/aoiFowjTExmKLgNwc\n' + + '0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHC\n' + + 'ReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7ORb\n' + + 'PcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkHcJaW\n' + + 'bWcMNU5KvJgE8XRsCMojcyf//////////wIBAgOBxQACgcEAi26oq8z/GNSBm3zi\n' + + 'gNt7SA7cArUBbTxINa9iLYWp6bxrvCKwDQwISN36/QUw8nUAe8aRyMt0oYn+y6vW\n' + + 'Pw5OlO+TLrUelMVFaADEzoYomH0zVGb0sW4aBN8haC0mbrPt9QshgCvjr1hEPEna\n' + + 'QFKfjzNaJRNMFFd4f2Dn8MSB4yu1xpA1T2i0JSk24vS2H55jx24xhUYtfhT2LJgK\n' + + 'JvnaODey/xtY4Kql10ZKf43Lw6gdQC3G8opC9OxVxt9oNR7Z\n' + + '-----END PUBLIC KEY-----', + format: 'pem' +}); + +assert.throws(() => crypto.diffieHellman({ privateKey: alicePrivateKey }), { + name: 'TypeError', + code: 'ERR_INVALID_OPT_VALUE', + message: 'The value "undefined" is invalid for option "publicKey"' +}); + +assert.throws(() => crypto.diffieHellman({ publicKey: alicePublicKey }), { + name: 'TypeError', + code: 'ERR_INVALID_OPT_VALUE', + message: 'The value "undefined" is invalid for option "privateKey"' +}); + +const privateKey = Buffer.from( + '487CD880159D835FD0A8DBA9848898317283DB07E822741B344AD397BA84CDDD3920A51588' + + 'B891B03B3EBEF3C9F767D921FAC1294D4B5E09CABB6D1DE3EB4527989754FEB64D007EBBDA' + + '2E6C8CE7A17EF41DE3C2DFE7CEAAF963199F55D5DBD9A415E77552FE69B7A41D87888B7D16' + + '6BC569A3957B60EEA6A4ABEB1CDB7FFCF238DF961790791CD54E597B3082981D52C0B2CA0B' + + '3DF212B2FD78DE4C6CC95285889D6DFDB746203177A726B912D26EB0A25F11871C7CD401A0' + + '10B355EC41D9AA', 'hex'); +const publicKey = Buffer.from( + '8b6ea8abccff18d4819b7ce280db7b480edc02b5016d3c4835af622d85a9e9bc6bbc22b00d' + + '0c0848ddfafd0530f275007bc691c8cb74a189fecbabd63f0e4e94ef932eb51e94c5456800' + + 'c4ce8628987d335466f4b16e1a04df21682d266eb3edf50b21802be3af58443c49da40529f' + + '8f335a25134c1457787f60e7f0c481e32bb5c690354f68b4252936e2f4b61f9e63c76e3185' + + '462d7e14f62c980a26f9da3837b2ff1b58e0aaa5d7464a7f8dcbc3a81d402dc6f28a42f4ec' + + '55c6df68351ed9', 'hex'); + +const group = crypto.getDiffieHellman('modp5'); +const dh = crypto.createDiffieHellman(group.getPrime(), group.getGenerator()); +dh.setPrivateKey(privateKey); + +// Test simple Diffie-Hellman, no curves involved. + +test({ publicKey: alicePublicKey, privateKey: alicePrivateKey }, + { publicKey: bobPublicKey, privateKey: bobPrivateKey }, + dh.computeSecret(publicKey)); + +test(crypto.generateKeyPairSync('dh', { group: 'modp5' }), + crypto.generateKeyPairSync('dh', { group: 'modp5' })); + +test(crypto.generateKeyPairSync('dh', { group: 'modp5' }), + crypto.generateKeyPairSync('dh', { prime: group.getPrime() })); + +for (const [params1, params2] of [ + // Same generator, but different primes. + [{ group: 'modp5' }, { group: 'modp18' }], + // Same primes, but different generator. + [{ group: 'modp5' }, { prime: group.getPrime(), generator: 5 }], + // Same generator, but different primes. + [{ primeLength: 1024 }, { primeLength: 1024 }] +]) { + assert.throws(() => { + test(crypto.generateKeyPairSync('dh', params1), + crypto.generateKeyPairSync('dh', params2)); + }, { + name: 'Error', + code: 'ERR_OSSL_EVP_DIFFERENT_PARAMETERS' + }); +} + +{ + const privateKey = crypto.createPrivateKey({ + key: '-----BEGIN PRIVATE KEY-----\n' + + 'MIIBoQIBADCB1QYJKoZIhvcNAQMBMIHHAoHBAP//////////yQ/aoiFowjTExmKL\n' + + 'gNwc0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVt\n' + + 'bVHCReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR\n' + + '7ORbPcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkH\n' + + 'cJaWbWcMNU5KvJgE8XRsCMojcyf//////////wIBAgSBwwKBwHu9fpiqrfJJ+tl9\n' + + 'ujFtEWv4afub6A/1/7sgishOYN3YQ+nmWQlmPpveIY34an5dG82CTrixHwUzQTMF\n' + + 'JaiCW3ax9+qk31f2jTNKrQznmKgopVKXF0FEJC6H79W/8Y0U14gsI9sHpovKhfou\n' + + 'RQD0QogW7ejSwMG8hCYibfrvMm0b5PHlwimISyEKh7VtDQ1frYN/Wr9ZbiV+FePJ\n' + + '2j6RUKYNj1Pv+B4zdMgiLLjILAs8WUfbHciU21KSJh1izVQaUQ==\n' + + '-----END PRIVATE KEY-----' + }); + const publicKey = crypto.createPublicKey({ + key: '-----BEGIN PUBLIC KEY-----\n' + + 'MIIBoDCB1QYJKoZIhvcNAQMBMIHHAoHBAP//////////yQ/aoiFowjTExmKLgNwc\n' + + '0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHC\n' + + 'ReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7ORb\n' + + 'PcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkHcJaW\n' + + 'bWcMNU5KvJgE8XRsCMojcyf//////////wIBAgOBxQACgcEAmG9LpD8SAA6/W7oK\n' + + 'E4MCuuQtf5E8bqtcEAfYTOOvKyCS+eiX3TtZRsvHJjUBEyeO99PR/KrGVlkSuW52\n' + + 'ZOSXUOFu1L/0tqHrvRVHo+QEq3OvZ3EAyJkdtSEUTztxuUrMOyJXHDc1OUdNSnk0\n' + + 'taGX4mP3247golVx2DS4viDYs7UtaMdx03dWaP6y5StNUZQlgCIUzL7MYpC16V5y\n' + + 'KkFrE+Kp/Z77gEjivaG6YuxVj4GPLxJYbNFVTel42oSVeKuq\n' + + '-----END PUBLIC KEY-----', + format: 'pem' + }); + + // This key combination will result in an unusually short secret, and should + // not cause an assertion failure. + const secret = crypto.diffieHellman({ publicKey, privateKey }); + assert.strictEqual(secret.toString('hex'), + '0099d0fa242af5db9ea7330e23937a27db041f79c581500fc7f9976' + + '554d59d5b9ced934778d72e19a1fefc81e9d981013198748c0b5c6c' + + '762985eec687dc5bec5c9367b05837daee9d0bcc29024ed7f3abba1' + + '2794b65a745117fb0d87bc5b1b2b68c296c3f686cc29e450e4e1239' + + '21f56a5733fe58aabf71f14582954059c2185d342b9b0fa10c2598a' + + '5426c2baee7f9a686fc1e16cd4757c852bf7225a2732250548efe28' + + 'debc26f1acdec51efe23d20786a6f8a14d360803bbc71972e87fd3'); +} + +// Test ECDH. + +test(crypto.generateKeyPairSync('ec', { namedCurve: 'secp256k1' }), + crypto.generateKeyPairSync('ec', { namedCurve: 'secp256k1' })); + +const not256k1 = crypto.getCurves().find((c) => /^sec.*(224|384|512)/.test(c)); +assert.throws(() => { + test(crypto.generateKeyPairSync('ec', { namedCurve: 'secp256k1' }), + crypto.generateKeyPairSync('ec', { namedCurve: not256k1 })); +}, { + name: 'Error', + code: 'ERR_OSSL_EVP_DIFFERENT_PARAMETERS' +}); + +// Test ECDH-ES. + +test(crypto.generateKeyPairSync('x448'), + crypto.generateKeyPairSync('x448')); + +test(crypto.generateKeyPairSync('x25519'), + crypto.generateKeyPairSync('x25519')); + +assert.throws(() => { + test(crypto.generateKeyPairSync('x448'), + crypto.generateKeyPairSync('x25519')); +}, { + name: 'Error', + code: 'ERR_CRYPTO_INCOMPATIBLE_KEY', + message: 'Incompatible key types for Diffie-Hellman: x448 and x25519' +}); diff --git a/test/parallel/test-crypto-dh.js b/test/parallel/test-crypto-dh.js index 855244a70b1b93..6db0d9543f057b 100644 --- a/test/parallel/test-crypto-dh.js +++ b/test/parallel/test-crypto-dh.js @@ -20,6 +20,62 @@ assert.strictEqual(secret2.toString('base64'), secret1); assert.strictEqual(dh1.verifyError, 0); assert.strictEqual(dh2.verifyError, 0); +// https://github.com/nodejs/node/issues/32738 +// XXX(bnoordhuis) validateInt32() throwing ERR_OUT_OF_RANGE and RangeError +// instead of ERR_INVALID_ARG_TYPE and TypeError is questionable, IMO. +assert.throws(() => crypto.createDiffieHellman(13.37), { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + message: 'The value of "sizeOrKey" is out of range. ' + + 'It must be an integer. Received 13.37', +}); + +assert.throws(() => crypto.createDiffieHellman('abcdef', 13.37), { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + message: 'The value of "generator" is out of range. ' + + 'It must be an integer. Received 13.37', +}); + +for (const bits of [-1, 0, 1]) { + assert.throws(() => crypto.createDiffieHellman(bits), { + code: 'ERR_OSSL_BN_BITS_TOO_SMALL', + name: 'Error', + message: /bits too small/, + }); +} + +// Through a fluke of history, g=0 defaults to DH_GENERATOR (2). +{ + const g = 0; + crypto.createDiffieHellman('abcdef', g); + crypto.createDiffieHellman('abcdef', 'hex', g); +} + +for (const g of [-1, 1]) { + const ex = { + code: 'ERR_OSSL_DH_BAD_GENERATOR', + name: 'Error', + message: /bad generator/, + }; + assert.throws(() => crypto.createDiffieHellman('abcdef', g), ex); + assert.throws(() => crypto.createDiffieHellman('abcdef', 'hex', g), ex); +} + +crypto.createDiffieHellman('abcdef', Buffer.from([2])); // OK + +for (const g of [Buffer.from([]), + Buffer.from([0]), + Buffer.from([1])]) { + const ex = { + code: 'ERR_OSSL_DH_BAD_GENERATOR', + name: 'Error', + message: /bad generator/, + }; + assert.throws(() => crypto.createDiffieHellman('abcdef', g), ex); + assert.throws(() => crypto.createDiffieHellman('abcdef', 'hex', g), ex); +} + { const DiffieHellman = crypto.DiffieHellman; const dh = DiffieHellman(p1, 'buffer'); @@ -389,7 +445,11 @@ assert.throws( function() { crypto.getDiffieHellman('unknown-group'); }, - /^Error: Unknown group$/, + { + name: 'Error', + code: 'ERR_CRYPTO_UNKNOWN_DH_GROUP', + message: 'Unknown group' + }, 'crypto.getDiffieHellman(\'unknown-group\') ' + 'failed to throw the expected error.' ); diff --git a/test/parallel/test-crypto-keygen.js b/test/parallel/test-crypto-keygen.js index 30b04e34d6ec36..1f059c469419fc 100644 --- a/test/parallel/test-crypto-keygen.js +++ b/test/parallel/test-crypto-keygen.js @@ -822,6 +822,7 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher); } }), { name: 'Error', + code: 'ERR_CRYPTO_UNKNOWN_CIPHER', message: 'Unknown cipher' }); @@ -981,6 +982,75 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher); } } +// Test classic Diffie-Hellman key generation. +{ + generateKeyPair('dh', { + primeLength: 1024 + }, common.mustCall((err, publicKey, privateKey) => { + assert.ifError(err); + + assert.strictEqual(publicKey.type, 'public'); + assert.strictEqual(publicKey.asymmetricKeyType, 'dh'); + + assert.strictEqual(privateKey.type, 'private'); + assert.strictEqual(privateKey.asymmetricKeyType, 'dh'); + })); + + assert.throws(() => { + generateKeyPair('dh', common.mustNotCall()); + }, { + name: 'TypeError', + code: 'ERR_INVALID_ARG_TYPE', + message: 'The "options" argument must be of type object. Received undefined' + }); + + assert.throws(() => { + generateKeyPair('dh', {}, common.mustNotCall()); + }, { + name: 'TypeError', + code: 'ERR_MISSING_OPTION', + message: 'At least one of the group, prime, or primeLength options is ' + + 'required' + }); + + assert.throws(() => { + generateKeyPair('dh', { + group: 'modp0' + }, common.mustNotCall()); + }, { + name: 'Error', + code: 'ERR_CRYPTO_UNKNOWN_DH_GROUP', + message: 'Unknown DH group' + }); + + // Test incompatible options. + const allOpts = { + group: 'modp5', + prime: Buffer.alloc(0), + primeLength: 1024, + generator: 2 + }; + const incompatible = [ + ['group', 'prime'], + ['group', 'primeLength'], + ['group', 'generator'], + ['prime', 'primeLength'] + ]; + for (const [opt1, opt2] of incompatible) { + assert.throws(() => { + generateKeyPairSync('dh', { + [opt1]: allOpts[opt1], + [opt2]: allOpts[opt2] + }); + }, { + name: 'TypeError', + code: 'ERR_INCOMPATIBLE_OPTION_PAIR', + message: `Option "${opt1}" cannot be used in combination with option ` + + `"${opt2}"` + }); + } +} + // Test invalid key encoding types. { // Invalid public key type. diff --git a/test/parallel/test-dgram-connect.js b/test/parallel/test-dgram-connect.js index a9815f439a731a..30e817f344a42c 100644 --- a/test/parallel/test-dgram-connect.js +++ b/test/parallel/test-dgram-connect.js @@ -60,7 +60,7 @@ assert.throws(() => { client.connect(port); }, { name: 'RangeError', - message: /^Port should be >= 0 and < 65536/, + message: /^Port should be > 0 and < 65536/, code: 'ERR_SOCKET_BAD_PORT' }); }); diff --git a/test/parallel/test-disable-proto-delete.js b/test/parallel/test-disable-proto-delete.js new file mode 100644 index 00000000000000..90cf9287bb9fc5 --- /dev/null +++ b/test/parallel/test-disable-proto-delete.js @@ -0,0 +1,25 @@ +// Flags: --disable-proto=delete + +'use strict'; + +require('../common'); +const assert = require('assert'); +const vm = require('vm'); +const { Worker, isMainThread } = require('worker_threads'); + +// eslint-disable-next-line no-proto +assert.strictEqual(Object.prototype.__proto__, undefined); +assert(!Object.prototype.hasOwnProperty('__proto__')); + +const ctx = vm.createContext(); +const ctxGlobal = vm.runInContext('this', ctx); + +// eslint-disable-next-line no-proto +assert.strictEqual(ctxGlobal.Object.prototype.__proto__, undefined); +assert(!ctxGlobal.Object.prototype.hasOwnProperty('__proto__')); + +if (isMainThread) { + new Worker(__filename); +} else { + process.exit(); +} diff --git a/test/parallel/test-disable-proto-throw.js b/test/parallel/test-disable-proto-throw.js new file mode 100644 index 00000000000000..e7a1f679765235 --- /dev/null +++ b/test/parallel/test-disable-proto-throw.js @@ -0,0 +1,44 @@ +// Flags: --disable-proto=throw + +'use strict'; + +require('../common'); +const assert = require('assert'); +const vm = require('vm'); +const { Worker, isMainThread } = require('worker_threads'); + +assert(Object.prototype.hasOwnProperty('__proto__')); + +assert.throws(() => { + // eslint-disable-next-line no-proto + ({}).__proto__; +}, { + code: 'ERR_PROTO_ACCESS' +}); + +assert.throws(() => { + // eslint-disable-next-line no-proto + ({}).__proto__ = {}; +}, { + code: 'ERR_PROTO_ACCESS', +}); + +const ctx = vm.createContext(); + +assert.throws(() => { + vm.runInContext('({}).__proto__;', ctx); +}, { + code: 'ERR_PROTO_ACCESS' +}); + +assert.throws(() => { + vm.runInContext('({}).__proto__ = {};', ctx); +}, { + code: 'ERR_PROTO_ACCESS', +}); + +if (isMainThread) { + new Worker(__filename); +} else { + process.exit(); +} diff --git a/test/parallel/test-dns-lookupService.js b/test/parallel/test-dns-lookupService.js index f78e98766063f7..dc04893c28f9fd 100644 --- a/test/parallel/test-dns-lookupService.js +++ b/test/parallel/test-dns-lookupService.js @@ -5,11 +5,17 @@ const assert = require('assert'); const { internalBinding } = require('internal/test/binding'); const cares = internalBinding('cares_wrap'); const { UV_ENOENT } = internalBinding('uv'); -const dns = require('dns'); // Stub `getnameinfo` to *always* error. cares.getnameinfo = () => UV_ENOENT; +// Because dns promises is attached lazily, +// and turn accesses getnameinfo on init +// but this lazy access is triggered by ES named +// instead of lazily itself, we must require +// dns after hooking cares +const dns = require('dns'); + assert.throws( () => dns.lookupService('127.0.0.1', 80, common.mustNotCall()), { diff --git a/test/parallel/test-dns.js b/test/parallel/test-dns.js index f0f94aefbbd241..bf49b66370dc93 100644 --- a/test/parallel/test-dns.js +++ b/test/parallel/test-dns.js @@ -209,14 +209,14 @@ assert.deepStrictEqual(dns.getServers(), []); { /* * Make sure that dns.lookup throws if hints does not represent a valid flag. - * (dns.V4MAPPED | dns.ADDRCONFIG) + 1 is invalid because: - * - it's different from dns.V4MAPPED and dns.ADDRCONFIG. - * - it's different from them bitwise ored. + * (dns.V4MAPPED | dns.ADDRCONFIG | dns.ALL) + 1 is invalid because: + * - it's different from dns.V4MAPPED and dns.ADDRCONFIG and dns.ALL. + * - it's different from any subset of them bitwise ored. * - it's different from 0. * - it's an odd number different than 1, and thus is invalid, because * flags are either === 1 or even. */ - const hints = (dns.V4MAPPED | dns.ADDRCONFIG) + 1; + const hints = (dns.V4MAPPED | dns.ADDRCONFIG | dns.ALL) + 1; const err = { code: 'ERR_INVALID_OPT_VALUE', name: 'TypeError', @@ -254,11 +254,28 @@ dns.lookup('', { hints: dns.ADDRCONFIG | dns.V4MAPPED }, common.mustCall()); +dns.lookup('', { + hints: dns.ALL +}, common.mustCall()); + +dns.lookup('', { + hints: dns.V4MAPPED | dns.ALL +}, common.mustCall()); + +dns.lookup('', { + hints: dns.ADDRCONFIG | dns.V4MAPPED | dns.ALL +}, common.mustCall()); + (async function() { await dnsPromises.lookup('', { family: 4, hints: 0 }); await dnsPromises.lookup('', { family: 6, hints: dns.ADDRCONFIG }); await dnsPromises.lookup('', { hints: dns.V4MAPPED }); await dnsPromises.lookup('', { hints: dns.ADDRCONFIG | dns.V4MAPPED }); + await dnsPromises.lookup('', { hints: dns.ALL }); + await dnsPromises.lookup('', { hints: dns.V4MAPPED | dns.ALL }); + await dnsPromises.lookup('', { + hints: dns.ADDRCONFIG | dns.V4MAPPED | dns.ALL + }); })(); { diff --git a/test/parallel/test-domain-http-server.js b/test/parallel/test-domain-http-server.js index 5b1ef68106cfda..6168566334a11d 100644 --- a/test/parallel/test-domain-http-server.js +++ b/test/parallel/test-domain-http-server.js @@ -24,6 +24,7 @@ require('../common'); const domain = require('domain'); const http = require('http'); const assert = require('assert'); +const debug = require('util').debuglog('test'); const objects = { foo: 'bar', baz: {}, num: 42, arr: [1, 2, 3] }; objects.baz.asdf = objects; @@ -39,7 +40,7 @@ const server = http.createServer(function(req, res) { dom.on('error', function(er) { serverCaught++; - console.log('horray! got a server error', er); + debug('horray! got a server error', er); // Try to send a 500. If that fails, oh well. res.writeHead(500, { 'content-type': 'text/plain' }); res.end(er.stack || er.message || 'Unknown error'); @@ -62,7 +63,7 @@ server.listen(0, next); function next() { const port = this.address().port; - console.log(`listening on localhost:${port}`); + debug(`listening on localhost:${port}`); let requests = 0; let responses = 0; @@ -79,7 +80,7 @@ function next() { const dom = domain.create(); dom.on('error', function(er) { clientCaught++; - console.log('client error', er); + debug('client error', er); req.socket.destroy(); }); @@ -87,9 +88,9 @@ function next() { dom.add(req); req.on('response', function(res) { responses++; - console.error(`requests=${requests} responses=${responses}`); + debug(`requests=${requests} responses=${responses}`); if (responses === requests) { - console.error('done, closing server'); + debug('done, closing server'); // no more coming. server.close(); } @@ -100,9 +101,9 @@ function next() { d += c; }); res.on('end', function() { - console.error('trying to parse json', d); + debug('trying to parse json', d); d = JSON.parse(d); - console.log('json!', d); + debug('json!', d); }); }); } @@ -111,5 +112,5 @@ function next() { process.on('exit', function() { assert.strictEqual(serverCaught, 2); assert.strictEqual(clientCaught, 2); - console.log('ok'); + debug('ok'); }); diff --git a/test/parallel/test-event-capture-rejections.js b/test/parallel/test-event-capture-rejections.js index dbe5deeefade99..233b6b35d55072 100644 --- a/test/parallel/test-event-capture-rejections.js +++ b/test/parallel/test-event-capture-rejections.js @@ -278,14 +278,22 @@ function resetCaptureOnThrowInError() { function argValidation() { function testType(obj) { + const received = obj.constructor.name !== 'Number' ? + `an instance of ${obj.constructor.name}` : + `type number (${obj})`; + assert.throws(() => new EventEmitter({ captureRejections: obj }), { code: 'ERR_INVALID_ARG_TYPE', - name: 'TypeError' + name: 'TypeError', + message: 'The "options.captureRejections" property must be of type ' + + `boolean. Received ${received}` }); assert.throws(() => EventEmitter.captureRejections = obj, { code: 'ERR_INVALID_ARG_TYPE', - name: 'TypeError' + name: 'TypeError', + message: 'The "EventEmitter.captureRejections" property must be of ' + + `type boolean. Received ${received}` }); } diff --git a/test/parallel/test-event-emitter-add-listeners.js b/test/parallel/test-event-emitter-add-listeners.js index 4b0305c176bd14..f42d1f24878483 100644 --- a/test/parallel/test-event-emitter-add-listeners.js +++ b/test/parallel/test-event-emitter-add-listeners.js @@ -84,14 +84,3 @@ const EventEmitter = require('events'); // listeners were added. assert.deepStrictEqual(ee.listeners('hello'), [listen2, listen1]); } - -// Verify that the listener must be a function -assert.throws(() => { - const ee = new EventEmitter(); - ee.on('foo', null); -}, { - code: 'ERR_INVALID_ARG_TYPE', - name: 'TypeError', - message: 'The "listener" argument must be of type function. ' + - 'Received null' -}); diff --git a/test/parallel/test-event-emitter-error-monitor.js b/test/parallel/test-event-emitter-error-monitor.js new file mode 100644 index 00000000000000..2b22b425b29194 --- /dev/null +++ b/test/parallel/test-event-emitter-error-monitor.js @@ -0,0 +1,32 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const EventEmitter = require('events'); + +const EE = new EventEmitter(); +const theErr = new Error('MyError'); + +EE.on( + EventEmitter.errorMonitor, + common.mustCall(function onErrorMonitor(e) { + assert.strictEqual(e, theErr); + }, 3) +); + +// Verify with no error listener +assert.throws( + () => EE.emit('error', theErr), theErr +); + +// Verify with error listener +EE.once('error', common.mustCall((e) => assert.strictEqual(e, theErr))); +EE.emit('error', theErr); + + +// Verify it works with once +process.nextTick(() => EE.emit('error', theErr)); +assert.rejects(EventEmitter.once(EE, 'notTriggered'), theErr); + +// Only error events trigger error monitor +EE.on('aEvent', common.mustCall()); +EE.emit('aEvent'); diff --git a/test/parallel/test-event-emitter-invalid-listener.js b/test/parallel/test-event-emitter-invalid-listener.js new file mode 100644 index 00000000000000..3070d4ed7517de --- /dev/null +++ b/test/parallel/test-event-emitter-invalid-listener.js @@ -0,0 +1,20 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const EventEmitter = require('events'); + +const eventsMethods = ['on', 'once', 'removeListener', 'prependOnceListener']; + +// Verify that the listener must be a function for events methods +for (const method of eventsMethods) { + assert.throws(() => { + const ee = new EventEmitter(); + ee[method]('foo', null); + }, { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + message: 'The "listener" argument must be of type function. ' + + 'Received null' + }, `event.${method}('foo', null) should throw the proper error`); +} diff --git a/test/parallel/test-event-emitter-once.js b/test/parallel/test-event-emitter-once.js index 1ad2de1da556bf..983f6141b9dc4c 100644 --- a/test/parallel/test-event-emitter-once.js +++ b/test/parallel/test-event-emitter-once.js @@ -49,17 +49,6 @@ e.once('e', common.mustCall()); e.emit('e'); -// Verify that the listener must be a function -assert.throws(() => { - const ee = new EventEmitter(); - ee.once('foo', null); -}, { - code: 'ERR_INVALID_ARG_TYPE', - name: 'TypeError', - message: 'The "listener" argument must be of type function. ' + - 'Received null' -}); - { // once() has different code paths based on the number of arguments being // emitted. Verify that all of the cases are covered. diff --git a/test/parallel/test-event-emitter-prepend.js b/test/parallel/test-event-emitter-prepend.js index c65b6b8f780f5c..ffe8544911365c 100644 --- a/test/parallel/test-event-emitter-prepend.js +++ b/test/parallel/test-event-emitter-prepend.js @@ -18,17 +18,6 @@ myEE.prependOnceListener('foo', myEE.emit('foo'); -// Verify that the listener must be a function -assert.throws(() => { - const ee = new EventEmitter(); - ee.prependOnceListener('foo', null); -}, { - code: 'ERR_INVALID_ARG_TYPE', - name: 'TypeError', - message: 'The "listener" argument must be of type function. ' + - 'Received null' -}); - // Test fallback if prependListener is undefined. const stream = require('stream'); diff --git a/test/parallel/test-event-emitter-remove-listeners.js b/test/parallel/test-event-emitter-remove-listeners.js index 91e1f071046ac1..f37d26eb258c23 100644 --- a/test/parallel/test-event-emitter-remove-listeners.js +++ b/test/parallel/test-event-emitter-remove-listeners.js @@ -144,17 +144,6 @@ function listener2() {} assert.deepStrictEqual(ee, ee.removeListener('foo', () => {})); } -// Verify that the removed listener must be a function -assert.throws(() => { - const ee = new EventEmitter(); - ee.removeListener('foo', null); -}, { - code: 'ERR_INVALID_ARG_TYPE', - name: 'TypeError', - message: 'The "listener" argument must be of type function. ' + - 'Received null' -}); - { const ee = new EventEmitter(); const listener = () => {}; diff --git a/test/parallel/test-fs-mkdir.js b/test/parallel/test-fs-mkdir.js index 417f5c7e06b8b5..5e28d6b944b6e0 100644 --- a/test/parallel/test-fs-mkdir.js +++ b/test/parallel/test-fs-mkdir.js @@ -245,6 +245,100 @@ if (common.isMainThread && (common.isLinux || common.isOSX)) { }); } +// `mkdirp` returns first folder created, when all folders are new. +{ + const dir1 = nextdir(); + const dir2 = nextdir(); + const firstPathCreated = path.join(tmpdir.path, dir1); + const pathname = path.join(tmpdir.path, dir1, dir2); + + fs.mkdir(pathname, { recursive: true }, common.mustCall(function(err, path) { + assert.strictEqual(err, null); + assert.strictEqual(fs.existsSync(pathname), true); + assert.strictEqual(fs.statSync(pathname).isDirectory(), true); + assert.strictEqual(path, firstPathCreated); + })); +} + +// `mkdirp` returns first folder created, when last folder is new. +{ + const dir1 = nextdir(); + const dir2 = nextdir(); + const pathname = path.join(tmpdir.path, dir1, dir2); + fs.mkdirSync(path.join(tmpdir.path, dir1)); + fs.mkdir(pathname, { recursive: true }, common.mustCall(function(err, path) { + assert.strictEqual(err, null); + assert.strictEqual(fs.existsSync(pathname), true); + assert.strictEqual(fs.statSync(pathname).isDirectory(), true); + assert.strictEqual(path, pathname); + })); +} + +// `mkdirp` returns undefined, when no new folders are created. +{ + const dir1 = nextdir(); + const dir2 = nextdir(); + const pathname = path.join(tmpdir.path, dir1, dir2); + fs.mkdirSync(path.join(tmpdir.path, dir1, dir2), { recursive: true }); + fs.mkdir(pathname, { recursive: true }, common.mustCall(function(err, path) { + assert.strictEqual(err, null); + assert.strictEqual(fs.existsSync(pathname), true); + assert.strictEqual(fs.statSync(pathname).isDirectory(), true); + assert.strictEqual(path, undefined); + })); +} + +// `mkdirp.sync` returns first folder created, when all folders are new. +{ + const dir1 = nextdir(); + const dir2 = nextdir(); + const firstPathCreated = path.join(tmpdir.path, dir1); + const pathname = path.join(tmpdir.path, dir1, dir2); + const p = fs.mkdirSync(pathname, { recursive: true }); + assert.strictEqual(fs.existsSync(pathname), true); + assert.strictEqual(fs.statSync(pathname).isDirectory(), true); + assert.strictEqual(p, firstPathCreated); +} + +// `mkdirp.sync` returns first folder created, when last folder is new. +{ + const dir1 = nextdir(); + const dir2 = nextdir(); + const pathname = path.join(tmpdir.path, dir1, dir2); + fs.mkdirSync(path.join(tmpdir.path, dir1), { recursive: true }); + const p = fs.mkdirSync(pathname, { recursive: true }); + assert.strictEqual(fs.existsSync(pathname), true); + assert.strictEqual(fs.statSync(pathname).isDirectory(), true); + assert.strictEqual(p, pathname); +} + +// `mkdirp.sync` returns undefined, when no new folders are created. +{ + const dir1 = nextdir(); + const dir2 = nextdir(); + const pathname = path.join(tmpdir.path, dir1, dir2); + fs.mkdirSync(path.join(tmpdir.path, dir1, dir2), { recursive: true }); + const p = fs.mkdirSync(pathname, { recursive: true }); + assert.strictEqual(fs.existsSync(pathname), true); + assert.strictEqual(fs.statSync(pathname).isDirectory(), true); + assert.strictEqual(p, undefined); +} + +// `mkdirp.promises` returns first folder created, when all folders are new. +{ + const dir1 = nextdir(); + const dir2 = nextdir(); + const firstPathCreated = path.join(tmpdir.path, dir1); + const pathname = path.join(tmpdir.path, dir1, dir2); + async function testCase() { + const p = await fs.promises.mkdir(pathname, { recursive: true }); + assert.strictEqual(fs.existsSync(pathname), true); + assert.strictEqual(fs.statSync(pathname).isDirectory(), true); + assert.strictEqual(p, firstPathCreated); + } + testCase(); +} + // Keep the event loop alive so the async mkdir() requests // have a chance to run (since they don't ref the event loop). process.nextTick(() => {}); diff --git a/test/parallel/test-fs-open-flags.js b/test/parallel/test-fs-open-flags.js index 6daaef817bff66..bb5b7c6020c062 100644 --- a/test/parallel/test-fs-open-flags.js +++ b/test/parallel/test-fs-open-flags.js @@ -19,7 +19,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -// Flags: --expose_internals +// Flags: --expose-internals 'use strict'; const common = require('../common'); diff --git a/test/parallel/test-fs-read-optional-params.js b/test/parallel/test-fs-read-optional-params.js new file mode 100644 index 00000000000000..bae99da3c0ebd0 --- /dev/null +++ b/test/parallel/test-fs-read-optional-params.js @@ -0,0 +1,36 @@ +'use strict'; + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +const fs = require('fs'); +const assert = require('assert'); +const filepath = fixtures.path('x.txt'); +const fd = fs.openSync(filepath, 'r'); + +const expected = Buffer.from('xyz\n'); +const defaultBufferAsync = Buffer.alloc(16384); +const bufferAsOption = Buffer.allocUnsafe(expected.length); + +// Test passing in an empty options object +fs.read(fd, { position: 0 }, common.mustCall((err, bytesRead, buffer) => { + assert.strictEqual(bytesRead, expected.length); + assert.deepStrictEqual(defaultBufferAsync.length, buffer.length); +})); + +// Test not passing in any options object +fs.read(fd, common.mustCall((err, bytesRead, buffer) => { + assert.strictEqual(bytesRead, expected.length); + assert.deepStrictEqual(defaultBufferAsync.length, buffer.length); +})); + +// Test passing in options +fs.read(fd, { + buffer: bufferAsOption, + offset: 0, + length: bufferAsOption.length, + position: 0 +}, + common.mustCall((err, bytesRead, buffer) => { + assert.strictEqual(bytesRead, expected.length); + assert.deepStrictEqual(bufferAsOption.length, buffer.length); + })); diff --git a/test/parallel/test-fs-read-promises-optional-params.js b/test/parallel/test-fs-read-promises-optional-params.js new file mode 100644 index 00000000000000..9d19eaa41151a8 --- /dev/null +++ b/test/parallel/test-fs-read-promises-optional-params.js @@ -0,0 +1,19 @@ +'use strict'; + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +const fs = require('fs'); +const read = require('util').promisify(fs.read); +const assert = require('assert'); +const filepath = fixtures.path('x.txt'); +const fd = fs.openSync(filepath, 'r'); + +const expected = Buffer.from('xyz\n'); +const defaultBufferAsync = Buffer.alloc(16384); + +read(fd, {}) + .then(function({ bytesRead, buffer }) { + assert.strictEqual(bytesRead, expected.length); + assert.deepStrictEqual(defaultBufferAsync.length, buffer.length); + }) + .then(common.mustCall()); diff --git a/test/parallel/test-fs-read-stream.js b/test/parallel/test-fs-read-stream.js index bec675737cc317..243fc78afcda89 100644 --- a/test/parallel/test-fs-read-stream.js +++ b/test/parallel/test-fs-read-stream.js @@ -31,11 +31,11 @@ const fixtures = require('../common/fixtures'); const fn = fixtures.path('elipses.txt'); const rangeFile = fixtures.path('x.txt'); -{ +function test1(options) { let paused = false; let bytesRead = 0; - const file = fs.createReadStream(fn); + const file = fs.createReadStream(fn, options); const fileSize = fs.statSync(fn).size; assert.strictEqual(file.bytesRead, 0); @@ -88,6 +88,15 @@ const rangeFile = fixtures.path('x.txt'); }); } +test1({}); +test1({ + fs: { + open: common.mustCall(fs.open), + read: common.mustCallAtLeast(fs.read, 1), + close: common.mustCall(fs.close), + } +}); + { const file = fs.createReadStream(fn, { encoding: 'utf8' }); file.length = 0; diff --git a/test/parallel/test-fs-read-type.js b/test/parallel/test-fs-read-type.js index 850715c2ce0952..d95c88c47e7c26 100644 --- a/test/parallel/test-fs-read-type.js +++ b/test/parallel/test-fs-read-type.js @@ -44,7 +44,7 @@ assert.throws(() => { }, { code: 'ERR_OUT_OF_RANGE', name: 'RangeError', - message: 'The value of "offset" is out of range. It must be >= 0 && <= 4. ' + + message: 'The value of "offset" is out of range. It must be >= 0. ' + 'Received -1' }); @@ -59,7 +59,7 @@ assert.throws(() => { code: 'ERR_OUT_OF_RANGE', name: 'RangeError', message: 'The value of "length" is out of range. ' + - 'It must be >= 0 && <= 4. Received -1' + 'It must be >= 0. Received -1' }); @@ -96,7 +96,7 @@ assert.throws(() => { code: 'ERR_OUT_OF_RANGE', name: 'RangeError', message: 'The value of "offset" is out of range. ' + - 'It must be >= 0 && <= 4. Received -1' + 'It must be >= 0. Received -1' }); assert.throws(() => { @@ -109,5 +109,18 @@ assert.throws(() => { code: 'ERR_OUT_OF_RANGE', name: 'RangeError', message: 'The value of "length" is out of range. ' + - 'It must be >= 0 && <= 4. Received -1' + 'It must be >= 0. Received -1' +}); + +assert.throws(() => { + fs.readSync(fd, + Buffer.allocUnsafe(expected.length), + 0, + expected.length + 1, + 0); +}, { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + message: 'The value of "length" is out of range. ' + + 'It must be <= 4. Received 5' }); diff --git a/test/parallel/test-fs-read.js b/test/parallel/test-fs-read.js index 03ddf7f36d1f98..2b665d8eb96ebb 100644 --- a/test/parallel/test-fs-read.js +++ b/test/parallel/test-fs-read.js @@ -80,6 +80,14 @@ assert.throws( } ); +['buffer', 'offset', 'length'].forEach((option) => + assert.throws( + () => fs.read(fd, { + [option]: null + }), + `not throws when options.${option} is null` + )); + assert.throws( () => fs.read(null, Buffer.alloc(1), 0, 1, 0), { diff --git a/test/parallel/test-fs-readSync-optional-params.js b/test/parallel/test-fs-readSync-optional-params.js new file mode 100644 index 00000000000000..37d3d24911db51 --- /dev/null +++ b/test/parallel/test-fs-readSync-optional-params.js @@ -0,0 +1,27 @@ +'use strict'; + +require('../common'); +const fixtures = require('../common/fixtures'); +const fs = require('fs'); +const assert = require('assert'); +const filepath = fixtures.path('x.txt'); +const fd = fs.openSync(filepath, 'r'); + +const expected = Buffer.from('xyz\n'); + +function runTest(defaultBuffer, options) { + const result = fs.readSync(fd, defaultBuffer, options); + assert.strictEqual(result, expected.length); + assert.deepStrictEqual(defaultBuffer, expected); +} + +// Test passing in an empty options object +runTest(Buffer.allocUnsafe(expected.length), { position: 0 }); + +// Test not passing in any options object +runTest(Buffer.allocUnsafe(expected.length)); + +// Test passing in options +runTest(Buffer.allocUnsafe(expected.length), { offset: 0, + length: expected.length, + position: 0 }); diff --git a/test/parallel/test-fs-readv-promises.js b/test/parallel/test-fs-readv-promises.js new file mode 100644 index 00000000000000..e0536505c91291 --- /dev/null +++ b/test/parallel/test-fs-readv-promises.js @@ -0,0 +1,67 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const path = require('path'); +const fs = require('fs').promises; +const tmpdir = require('../common/tmpdir'); + +tmpdir.refresh(); + +const expected = 'ümlaut. Лорем 運務ホソモ指及 आपको करने विकास 紙読決多密所 أضف'; +const exptectedBuff = Buffer.from(expected); + +let cnt = 0; +function getFileName() { + return path.join(tmpdir.path, `readv_promises_${++cnt}.txt`); +} + +const allocateEmptyBuffers = (combinedLength) => { + const bufferArr = []; + // Allocate two buffers, each half the size of exptectedBuff + bufferArr[0] = Buffer.alloc(Math.floor(combinedLength / 2)), + bufferArr[1] = Buffer.alloc(combinedLength - bufferArr[0].length); + + return bufferArr; +}; + +(async () => { + { + const filename = getFileName(); + await fs.writeFile(filename, exptectedBuff); + const handle = await fs.open(filename, 'r'); + // const buffer = Buffer.from(expected); + const bufferArr = allocateEmptyBuffers(exptectedBuff.length); + const expectedLength = exptectedBuff.length; + + let { bytesRead, buffers } = await handle.readv([Buffer.from('')], + null); + assert.deepStrictEqual(bytesRead, 0); + assert.deepStrictEqual(buffers, [Buffer.from('')]); + + ({ bytesRead, buffers } = await handle.readv(bufferArr, null)); + assert.deepStrictEqual(bytesRead, expectedLength); + assert.deepStrictEqual(buffers, bufferArr); + assert(Buffer.concat(bufferArr).equals(await fs.readFile(filename))); + handle.close(); + } + + { + const filename = getFileName(); + await fs.writeFile(filename, exptectedBuff); + const handle = await fs.open(filename, 'r'); + // const buffer = Buffer.from(expected); + const bufferArr = allocateEmptyBuffers(exptectedBuff.length); + const expectedLength = exptectedBuff.length; + + let { bytesRead, buffers } = await handle.readv([Buffer.from('')]); + assert.deepStrictEqual(bytesRead, 0); + assert.deepStrictEqual(buffers, [Buffer.from('')]); + + ({ bytesRead, buffers } = await handle.readv(bufferArr)); + assert.deepStrictEqual(bytesRead, expectedLength); + assert.deepStrictEqual(buffers, bufferArr); + assert(Buffer.concat(bufferArr).equals(await fs.readFile(filename))); + handle.close(); + } +})(); diff --git a/test/parallel/test-fs-readv-sync.js b/test/parallel/test-fs-readv-sync.js new file mode 100644 index 00000000000000..92aa2fb6816752 --- /dev/null +++ b/test/parallel/test-fs-readv-sync.js @@ -0,0 +1,93 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); +const tmpdir = require('../common/tmpdir'); + +tmpdir.refresh(); + +const expected = 'ümlaut. Лорем 運務ホソモ指及 आपको करने विकास 紙読決多密所 أضف'; + +const exptectedBuff = Buffer.from(expected); +const expectedLength = exptectedBuff.length; + +const filename = path.join(tmpdir.path, 'readv_sync.txt'); +fs.writeFileSync(filename, exptectedBuff); + +const allocateEmptyBuffers = (combinedLength) => { + const bufferArr = []; + // Allocate two buffers, each half the size of exptectedBuff + bufferArr[0] = Buffer.alloc(Math.floor(combinedLength / 2)), + bufferArr[1] = Buffer.alloc(combinedLength - bufferArr[0].length); + + return bufferArr; +}; + +// fs.readvSync with array of buffers with all parameters +{ + const fd = fs.openSync(filename, 'r'); + + const bufferArr = allocateEmptyBuffers(exptectedBuff.length); + + let read = fs.readvSync(fd, [Buffer.from('')], 0); + assert.deepStrictEqual(read, 0); + + read = fs.readvSync(fd, bufferArr, 0); + assert.deepStrictEqual(read, expectedLength); + + fs.closeSync(fd); + + assert(Buffer.concat(bufferArr).equals(fs.readFileSync(filename))); +} + +// fs.readvSync with array of buffers without position +{ + const fd = fs.openSync(filename, 'r'); + + const bufferArr = allocateEmptyBuffers(exptectedBuff.length); + + let read = fs.readvSync(fd, [Buffer.from('')]); + assert.deepStrictEqual(read, 0); + + read = fs.readvSync(fd, bufferArr); + assert.deepStrictEqual(read, expectedLength); + + fs.closeSync(fd); + + assert(Buffer.concat(bufferArr).equals(fs.readFileSync(filename))); +} + +/** + * Testing with incorrect arguments + */ +const wrongInputs = [false, 'test', {}, [{}], ['sdf'], null, undefined]; + +{ + const fd = fs.openSync(filename, 'r'); + + wrongInputs.forEach((wrongInput) => { + assert.throws( + () => fs.readvSync(fd, wrongInput, null), { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError' + } + ); + }); + + fs.closeSync(fd); +} + +{ + // fs.readv with wrong fd argument + wrongInputs.forEach((wrongInput) => { + assert.throws( + () => fs.readvSync(wrongInput), + { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError' + } + ); + }); +} diff --git a/test/parallel/test-fs-readv.js b/test/parallel/test-fs-readv.js new file mode 100644 index 00000000000000..1fa9d80f9f2328 --- /dev/null +++ b/test/parallel/test-fs-readv.js @@ -0,0 +1,97 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const path = require('path'); +const fs = require('fs'); +const tmpdir = require('../common/tmpdir'); + +tmpdir.refresh(); + +const expected = 'ümlaut. Лорем 運務ホソモ指及 आपको करने विकास 紙読決多密所 أضف'; + +let cnt = 0; +const getFileName = () => path.join(tmpdir.path, `readv_${++cnt}.txt`); +const exptectedBuff = Buffer.from(expected); + +const allocateEmptyBuffers = (combinedLength) => { + const bufferArr = []; + // Allocate two buffers, each half the size of exptectedBuff + bufferArr[0] = Buffer.alloc(Math.floor(combinedLength / 2)), + bufferArr[1] = Buffer.alloc(combinedLength - bufferArr[0].length); + + return bufferArr; +}; + +const getCallback = (fd, bufferArr) => { + return common.mustCall((err, bytesRead, buffers) => { + assert.ifError(err); + + assert.deepStrictEqual(bufferArr, buffers); + const expectedLength = exptectedBuff.length; + assert.deepStrictEqual(bytesRead, expectedLength); + fs.closeSync(fd); + + assert(Buffer.concat(bufferArr).equals(exptectedBuff)); + }); +}; + +// fs.readv with array of buffers with all parameters +{ + const filename = getFileName(); + const fd = fs.openSync(filename, 'w+'); + fs.writeSync(fd, exptectedBuff); + + const bufferArr = allocateEmptyBuffers(exptectedBuff.length); + const callback = getCallback(fd, bufferArr); + + fs.readv(fd, bufferArr, 0, callback); +} + +// fs.readv with array of buffers without position +{ + const filename = getFileName(); + fs.writeFileSync(filename, exptectedBuff); + const fd = fs.openSync(filename, 'r'); + + const bufferArr = allocateEmptyBuffers(exptectedBuff.length); + const callback = getCallback(fd, bufferArr); + + fs.readv(fd, bufferArr, callback); +} + +/** + * Testing with incorrect arguments + */ +const wrongInputs = [false, 'test', {}, [{}], ['sdf'], null, undefined]; + +{ + const filename = getFileName(2); + fs.writeFileSync(filename, exptectedBuff); + const fd = fs.openSync(filename, 'r'); + + + wrongInputs.forEach((wrongInput) => { + assert.throws( + () => fs.readv(fd, wrongInput, null, common.mustNotCall()), { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError' + } + ); + }); + + fs.closeSync(fd); +} + +{ + // fs.readv with wrong fd argument + wrongInputs.forEach((wrongInput) => { + assert.throws( + () => fs.readv(wrongInput, common.mustNotCall()), + { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError' + } + ); + }); +} diff --git a/test/parallel/test-fs-write-stream-fs.js b/test/parallel/test-fs-write-stream-fs.js new file mode 100644 index 00000000000000..2e15f57c764838 --- /dev/null +++ b/test/parallel/test-fs-write-stream-fs.js @@ -0,0 +1,38 @@ +'use strict'; +const common = require('../common'); +const path = require('path'); +const fs = require('fs'); + +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); + +{ + const file = path.join(tmpdir.path, 'write-end-test0.txt'); + const stream = fs.createWriteStream(file, { + fs: { + open: common.mustCall(fs.open), + write: common.mustCallAtLeast(fs.write, 1), + close: common.mustCall(fs.close), + } + }); + stream.end('asd'); + stream.on('close', common.mustCall()); +} + + +{ + const file = path.join(tmpdir.path, 'write-end-test1.txt'); + const stream = fs.createWriteStream(file, { + fs: { + open: common.mustCall(fs.open), + write: fs.write, + writev: common.mustCallAtLeast(fs.writev, 1), + close: common.mustCall(fs.close), + } + }); + stream.write('asd'); + stream.write('asd'); + stream.write('asd'); + stream.end(); + stream.on('close', common.mustCall()); +} diff --git a/test/parallel/test-http-request-agent.js b/test/parallel/test-http-request-agent.js index a1f3077ed2820f..453ac380d0908f 100644 --- a/test/parallel/test-http-request-agent.js +++ b/test/parallel/test-http-request-agent.js @@ -34,7 +34,7 @@ server.listen(0, common.mustCall(function() { res.resume(); server.close(); })).on('error', function(e) { - console.error(e.stack); + console.error(e); process.exit(1); }); })); diff --git a/test/parallel/test-http-server-disabled-headers-timeout.js b/test/parallel/test-http-server-disabled-headers-timeout.js new file mode 100644 index 00000000000000..905e589cbe71eb --- /dev/null +++ b/test/parallel/test-http-server-disabled-headers-timeout.js @@ -0,0 +1,49 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { createServer } = require('http'); +const { connect } = require('net'); + +// This test verifies that it is possible to disable +// headersTimeout by setting it to zero. + +const server = createServer(common.mustCall((req, res) => { + res.writeHead(200); + res.end('OK'); +})); + +server.headersTimeout = 0; + +server.once('timeout', common.mustNotCall((socket) => { + socket.destroy(); +})); + +server.listen(0, common.mustCall(() => { + const client = connect(server.address().port); + let response = ''; + + client.resume(); + client.write('GET / HTTP/1.1\r\nConnection: close\r\n'); + + // All the timeouts below must be greater than a second, otherwise + // headersTimeout won't be triggered anyway as the current date is cached + // for a second in HTTP internals. + setTimeout(() => { + client.write('X-Crash: Ab: 456\r\n'); + }, common.platformTimeout(1100)).unref(); + + setTimeout(() => { + client.write('\r\n'); + }, common.platformTimeout(1200)).unref(); + + client.on('data', (chunk) => { + response += chunk.toString('utf-8'); + }); + + client.on('end', common.mustCall(() => { + assert.strictEqual(response.split('\r\n').shift(), 'HTTP/1.1 200 OK'); + client.end(); + server.close(); + })); +})); diff --git a/test/parallel/test-http-slow-headers.js b/test/parallel/test-http-slow-headers.js index 6da11465dac17b..25ee5b63e8c0e2 100644 --- a/test/parallel/test-http-slow-headers.js +++ b/test/parallel/test-http-slow-headers.js @@ -17,8 +17,8 @@ const headers = const server = createServer(common.mustNotCall()); let sendCharEvery = 1000; -// 40 seconds is the default -assert.strictEqual(server.headersTimeout, 40 * 1000); +// 60 seconds is the default +assert.strictEqual(server.headersTimeout, 60 * 1000); // Pass a REAL env variable to shortening up the default // value which is 40s otherwise this is useful for manual diff --git a/test/parallel/test-http-unix-socket.js b/test/parallel/test-http-unix-socket.js index d6ce23bb19f4b1..f8362d6183d8e1 100644 --- a/test/parallel/test-http-unix-socket.js +++ b/test/parallel/test-http-unix-socket.js @@ -69,7 +69,7 @@ server.listen(common.PIPE, common.mustCall(function() { })); req.on('error', function(e) { - assert.fail(e.stack); + assert.fail(e); }); req.end(); diff --git a/test/parallel/test-http2-compat-socket.js b/test/parallel/test-http2-compat-socket.js index 0db2876738c766..95bc42180ef8e9 100644 --- a/test/parallel/test-http2-compat-socket.js +++ b/test/parallel/test-http2-compat-socket.js @@ -1,4 +1,4 @@ -// Flags: --expose_internals +// Flags: --expose-internals 'use strict'; diff --git a/test/parallel/test-http2-socket-proxy.js b/test/parallel/test-http2-socket-proxy.js index 745006831759d1..067909069e9d86 100644 --- a/test/parallel/test-http2-socket-proxy.js +++ b/test/parallel/test-http2-socket-proxy.js @@ -1,4 +1,4 @@ -// Flags: --expose_internals +// Flags: --expose-internals 'use strict'; diff --git a/test/parallel/test-https-slow-headers.js b/test/parallel/test-https-slow-headers.js index 531d9ad318fa03..95f0caa9878c5e 100644 --- a/test/parallel/test-https-slow-headers.js +++ b/test/parallel/test-https-slow-headers.js @@ -27,8 +27,8 @@ const server = createServer({ let sendCharEvery = 1000; -// 40 seconds is the default -assert.strictEqual(server.headersTimeout, 40 * 1000); +// 60 seconds is the default +assert.strictEqual(server.headersTimeout, 60 * 1000); // Pass a REAL env variable to shortening up the default // value which is 40s otherwise diff --git a/test/parallel/test-icu-stringwidth.js b/test/parallel/test-icu-stringwidth.js index 48384f916d9126..4e8389961d0d6d 100644 --- a/test/parallel/test-icu-stringwidth.js +++ b/test/parallel/test-icu-stringwidth.js @@ -1,4 +1,4 @@ -// Flags: --expose_internals +// Flags: --expose-internals 'use strict'; const common = require('../common'); @@ -6,88 +6,93 @@ if (!common.hasIntl) common.skip('missing Intl'); const assert = require('assert'); -const readline = require('internal/readline/utils'); +const { getStringWidth } = require('internal/util/inspect'); // Test column width // Ll (Lowercase Letter): LATIN SMALL LETTER A -assert.strictEqual(readline.getStringWidth('a'), 1); -assert.strictEqual(readline.getStringWidth(0x0061), 1); +assert.strictEqual(getStringWidth('a'), 1); +assert.strictEqual(getStringWidth(String.fromCharCode(0x0061)), 1); // Lo (Other Letter) -assert.strictEqual(readline.getStringWidth('丁'), 2); -assert.strictEqual(readline.getStringWidth(0x4E01), 2); +assert.strictEqual(getStringWidth('丁'), 2); +assert.strictEqual(getStringWidth(String.fromCharCode(0x4E01)), 2); // Surrogate pairs -assert.strictEqual(readline.getStringWidth('\ud83d\udc78\ud83c\udfff'), 2); -assert.strictEqual(readline.getStringWidth('👅'), 2); +assert.strictEqual(getStringWidth('\ud83d\udc78\ud83c\udfff'), 4); +assert.strictEqual(getStringWidth('👅'), 2); // Cs (Surrogate): High Surrogate -assert.strictEqual(readline.getStringWidth('\ud83d'), 1); +assert.strictEqual(getStringWidth('\ud83d'), 1); // Cs (Surrogate): Low Surrogate -assert.strictEqual(readline.getStringWidth('\udc78'), 1); +assert.strictEqual(getStringWidth('\udc78'), 1); // Cc (Control): NULL -assert.strictEqual(readline.getStringWidth(0), 0); +assert.strictEqual(getStringWidth('\u0000'), 0); // Cc (Control): BELL -assert.strictEqual(readline.getStringWidth(0x0007), 0); +assert.strictEqual(getStringWidth(String.fromCharCode(0x0007)), 0); // Cc (Control): LINE FEED -assert.strictEqual(readline.getStringWidth('\n'), 0); +assert.strictEqual(getStringWidth('\n'), 0); // Cf (Format): SOFT HYPHEN -assert.strictEqual(readline.getStringWidth(0x00AD), 1); +assert.strictEqual(getStringWidth(String.fromCharCode(0x00AD)), 1); // Cf (Format): LEFT-TO-RIGHT MARK // Cf (Format): RIGHT-TO-LEFT MARK -assert.strictEqual(readline.getStringWidth('\u200Ef\u200F'), 1); +assert.strictEqual(getStringWidth('\u200Ef\u200F'), 1); // Cn (Unassigned): Not a character -assert.strictEqual(readline.getStringWidth(0x10FFEF), 1); +assert.strictEqual(getStringWidth(String.fromCharCode(0x10FFEF)), 1); // Cn (Unassigned): Not a character (but in a CJK range) -assert.strictEqual(readline.getStringWidth(0x3FFEF), 2); +assert.strictEqual(getStringWidth(String.fromCharCode(0x3FFEF)), 1); // Mn (Nonspacing Mark): COMBINING ACUTE ACCENT -assert.strictEqual(readline.getStringWidth(0x0301), 0); +assert.strictEqual(getStringWidth(String.fromCharCode(0x0301)), 0); // Mc (Spacing Mark): BALINESE ADEG ADEG // Chosen as its Canonical_Combining_Class is not 0, but is not a 0-width // character. -assert.strictEqual(readline.getStringWidth(0x1B44), 1); +assert.strictEqual(getStringWidth(String.fromCharCode(0x1B44)), 1); // Me (Enclosing Mark): COMBINING ENCLOSING CIRCLE -assert.strictEqual(readline.getStringWidth(0x20DD), 0); +assert.strictEqual(getStringWidth(String.fromCharCode(0x20DD)), 0); -// The following is an emoji sequence. In some implementations, it is -// represented as a single glyph, in other implementations as a sequence -// of individual glyphs. By default, the algorithm will assume the single -// glyph interpretation and return a value of 2. By passing the -// expandEmojiSequence: true option, each component will be counted -// individually. -assert.strictEqual(readline.getStringWidth('👩‍👩‍👧‍👧'), 2); -assert.strictEqual( - readline.getStringWidth('👩‍👩‍👧‍👧', { expandEmojiSequence: true }), 8); +// The following is an emoji sequence with ZWJ (zero-width-joiner). In some +// implementations, it is represented as a single glyph, in other +// implementations as a sequence of individual glyphs. By default, each +// component will be counted individually, since not a lot of systems support +// these fully. +// See https://www.unicode.org/reports/tr51/tr51-16.html#Emoji_ZWJ_Sequences +assert.strictEqual(getStringWidth('👩‍👩‍👧‍👧'), 8); +// TODO(BridgeAR): This should have a width of two and six. The heart contains +// the \uFE0F variation selector that indicates that it should be displayed as +// emoji instead of as text. Emojis are all full width characters when not being +// rendered as text. +// https://en.wikipedia.org/wiki/Variation_Selectors_(Unicode_block) +assert.strictEqual(getStringWidth('❤️'), 1); +assert.strictEqual(getStringWidth('👩‍❤️‍👩'), 5); +// The length of one is correct. It is an emoji treated as text. +assert.strictEqual(getStringWidth('❤'), 1); // By default, unicode characters whose width is considered ambiguous will // be considered half-width. For these characters, getStringWidth will return // 1. In some contexts, however, it is more appropriate to consider them full -// width. By default, the algorithm will assume half width. By passing -// the ambiguousAsFullWidth: true option, ambiguous characters will be counted -// as 2 columns. -assert.strictEqual(readline.getStringWidth('\u01d4'), 1); -assert.strictEqual( - readline.getStringWidth('\u01d4', { ambiguousAsFullWidth: true }), 2); +// width. By default, the algorithm will assume half width. +assert.strictEqual(getStringWidth('\u01d4'), 1); // Control chars and combining chars are zero -assert.strictEqual(readline.getStringWidth('\u200E\n\u220A\u20D2'), 1); +assert.strictEqual(getStringWidth('\u200E\n\u220A\u20D2'), 1); // Test that the fast path for ASCII characters yields results consistent // with the 'slow' path. -for (const ambiguousAsFullWidth of [ false, true ]) { - for (let i = 0; i < 256; i++) { - const char = String.fromCharCode(i); - assert.strictEqual( - readline.getStringWidth(i, { ambiguousAsFullWidth }), - readline.getStringWidth(char, { ambiguousAsFullWidth })); - assert.strictEqual( - readline.getStringWidth(char + '🎉', { ambiguousAsFullWidth }), - readline.getStringWidth(char, { ambiguousAsFullWidth }) + 2); +for (let i = 0; i < 256; i++) { + const char = String.fromCharCode(i); + assert.strictEqual( + getStringWidth(char + '🎉'), + getStringWidth(char) + 2); - if (i < 32 || (i >= 127 && i < 160)) { // Control character - assert.strictEqual( - readline.getStringWidth(i, { ambiguousAsFullWidth }), 0); - } else if (i < 127) { // Regular ASCII character - assert.strictEqual( - readline.getStringWidth(i, { ambiguousAsFullWidth }), 1); - } + if (i < 32 || (i >= 127 && i < 160)) { // Control character + assert.strictEqual(getStringWidth(char), 0); + } else { // Regular ASCII character + assert.strictEqual(getStringWidth(char), 1); } } + +{ + const a = '한글'.normalize('NFD'); // 한글 + const b = '한글'.normalize('NFC'); // 한글 + assert.strictEqual(a.length, 6); + assert.strictEqual(b.length, 2); + assert.strictEqual(getStringWidth(a), 4); + assert.strictEqual(getStringWidth(b), 4); +} diff --git a/test/parallel/test-inspector-esm.js b/test/parallel/test-inspector-esm.js index 19d493c519b5e3..707fa7bb56f9e5 100644 --- a/test/parallel/test-inspector-esm.js +++ b/test/parallel/test-inspector-esm.js @@ -99,8 +99,8 @@ async function testBreakpoint(session) { } async function runTest() { - const child = new NodeInstance(['--inspect-brk=0', '--experimental-modules'], - '', fixtures.path('es-modules/loop.mjs')); + const child = new NodeInstance(['--inspect-brk=0'], '', + fixtures.path('es-modules/loop.mjs')); const session = await child.connectInspectorSession(); await testBreakpointOnStart(session); diff --git a/test/parallel/test-internal-util-decorate-error-stack.js b/test/parallel/test-internal-util-decorate-error-stack.js index 40fbf1d48caf20..b12d50bee79abc 100644 --- a/test/parallel/test-internal-util-decorate-error-stack.js +++ b/test/parallel/test-internal-util-decorate-error-stack.js @@ -1,4 +1,4 @@ -// Flags: --expose_internals +// Flags: --expose-internals 'use strict'; require('../common'); const fixtures = require('../common/fixtures'); diff --git a/test/parallel/test-internal-validators-validateport.js b/test/parallel/test-internal-validators-validateport.js new file mode 100644 index 00000000000000..ea9c3a7b58b692 --- /dev/null +++ b/test/parallel/test-internal-validators-validateport.js @@ -0,0 +1,23 @@ +// Flags: --expose-internals +'use strict'; + +require('../common'); +const assert = require('assert'); +const { validatePort } = require('internal/validators'); + +for (let n = 0; n <= 0xFFFF; n++) { + validatePort(n); + validatePort(`${n}`); + validatePort(`0x${n.toString(16)}`); + validatePort(`0o${n.toString(8)}`); + validatePort(`0b${n.toString(2)}`); +} + +[ + -1, 'a', {}, [], false, true, + 0xFFFF + 1, Infinity, -Infinity, NaN, + undefined, null, '', ' ', 1.1, '0x', + '-0x1', '-0o1', '-0b1', '0o', '0b' +].forEach((i) => assert.throws(() => validatePort(i), { + code: 'ERR_SOCKET_BAD_PORT' +})); diff --git a/test/parallel/test-loaders-unknown-builtin-module.mjs b/test/parallel/test-loaders-unknown-builtin-module.mjs index b0b1d400e6904e..464dbeb22a9b31 100644 --- a/test/parallel/test-loaders-unknown-builtin-module.mjs +++ b/test/parallel/test-loaders-unknown-builtin-module.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-modules --experimental-loader ./test/fixtures/es-module-loaders/loader-unknown-builtin-module.mjs +// Flags: --experimental-loader ./test/fixtures/es-module-loaders/loader-unknown-builtin-module.mjs import { expectsError, mustCall } from '../common/index.mjs'; import assert from 'assert'; diff --git a/test/parallel/test-memory-usage.js b/test/parallel/test-memory-usage.js index 08ef07a34627ca..e8743c47d235c0 100644 --- a/test/parallel/test-memory-usage.js +++ b/test/parallel/test-memory-usage.js @@ -19,6 +19,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. +// Flags: --predictable-gc-schedule 'use strict'; const common = require('../common'); const assert = require('assert'); @@ -30,3 +31,16 @@ if (!common.isIBMi) assert.ok(r.heapTotal > 0); assert.ok(r.heapUsed > 0); assert.ok(r.external > 0); + +assert.strictEqual(typeof r.arrayBuffers, 'number'); +if (r.arrayBuffers > 0) { + const size = 10 * 1024 * 1024; + // eslint-disable-next-line no-unused-vars + const ab = new ArrayBuffer(size); + + const after = process.memoryUsage(); + assert(after.external - r.external >= size, + `${after.external} - ${r.external} >= ${size}`); + assert.strictEqual(after.arrayBuffers - r.arrayBuffers, size, + `${after.arrayBuffers} - ${r.arrayBuffers} === ${size}`); +} diff --git a/test/parallel/test-module-main-extension-lookup.js b/test/parallel/test-module-main-extension-lookup.js index 9e7eab295e8795..58d78e09b1199e 100644 --- a/test/parallel/test-module-main-extension-lookup.js +++ b/test/parallel/test-module-main-extension-lookup.js @@ -5,7 +5,5 @@ const { execFileSync } = require('child_process'); const node = process.argv[0]; -execFileSync(node, ['--experimental-modules', - fixtures.path('es-modules', 'test-esm-ok.mjs')]); -execFileSync(node, ['--experimental-modules', - fixtures.path('es-modules', 'noext')]); +execFileSync(node, [fixtures.path('es-modules', 'test-esm-ok.mjs')]); +execFileSync(node, [fixtures.path('es-modules', 'noext')]); diff --git a/test/parallel/test-module-main-fail.js b/test/parallel/test-module-main-fail.js index a6457f33b659dd..c66b6f2f7a843f 100644 --- a/test/parallel/test-module-main-fail.js +++ b/test/parallel/test-module-main-fail.js @@ -4,18 +4,15 @@ const assert = require('assert'); const { execFileSync } = require('child_process'); const entryPoints = ['iDoNotExist', 'iDoNotExist.js', 'iDoNotExist.mjs']; -const flags = [[], ['--experimental-modules']]; const node = process.argv[0]; -for (const args of flags) { - for (const entryPoint of entryPoints) { - try { - execFileSync(node, args.concat(entryPoint), { stdio: 'pipe' }); - } catch (e) { - assert(e.toString().match(/Error: Cannot find module/)); - continue; - } - assert.fail('Executing node with inexistent entry point should ' + - `fail. Entry point: ${entryPoint}, Flags: [${args}]`); +for (const entryPoint of entryPoints) { + try { + execFileSync(node, [entryPoint], { stdio: 'pipe' }); + } catch (e) { + assert(e.toString().match(/Error: Cannot find module/)); + continue; } + assert.fail('Executing node with inexistent entry point should ' + + `fail. Entry point: ${entryPoint}`); } diff --git a/test/parallel/test-module-main-preserve-symlinks-fail.js b/test/parallel/test-module-main-preserve-symlinks-fail.js index b46497b625261f..bbaf451c3ce539 100644 --- a/test/parallel/test-module-main-preserve-symlinks-fail.js +++ b/test/parallel/test-module-main-preserve-symlinks-fail.js @@ -4,7 +4,7 @@ const assert = require('assert'); const { execFileSync } = require('child_process'); const entryPoints = ['iDoNotExist', 'iDoNotExist.js', 'iDoNotExist.mjs']; -const flags = [[], ['--experimental-modules', '--preserve-symlinks']]; +const flags = [[], ['--preserve-symlinks']]; const node = process.argv[0]; for (const args of flags) { diff --git a/test/parallel/test-net-after-close.js b/test/parallel/test-net-after-close.js index 641e61bd04c5d0..7d49780d001d6e 100644 --- a/test/parallel/test-net-after-close.js +++ b/test/parallel/test-net-after-close.js @@ -24,14 +24,14 @@ const common = require('../common'); const assert = require('assert'); const net = require('net'); -const server = net.createServer(common.mustCall(function(s) { +const server = net.createServer(common.mustCall((s) => { console.error('SERVER: got connection'); s.end(); })); -server.listen(0, common.mustCall(function() { - const c = net.createConnection(this.address().port); - c.on('close', common.mustCall(function() { +server.listen(0, common.mustCall(() => { + const c = net.createConnection(server.address().port); + c.on('close', common.mustCall(() => { console.error('connection closed'); assert.strictEqual(c._handle, null); // Calling functions / accessing properties of a closed socket should not diff --git a/test/parallel/test-net-connect-options-port.js b/test/parallel/test-net-connect-options-port.js index 88e626354ed520..91598f5f15af2f 100644 --- a/test/parallel/test-net-connect-options-port.js +++ b/test/parallel/test-net-connect-options-port.js @@ -59,7 +59,7 @@ const net = require('net'); // Test invalid hints { // connect({hint}, cb) and connect({hint}) - const hints = (dns.ADDRCONFIG | dns.V4MAPPED) + 42; + const hints = (dns.ADDRCONFIG | dns.V4MAPPED | dns.ALL) + 42; const hintOptBlocks = doConnect([{ hints }], () => common.mustNotCall()); for (const fn of hintOptBlocks) { diff --git a/test/parallel/test-net-internal.js b/test/parallel/test-net-internal.js deleted file mode 100644 index 309b56d4d9aafc..00000000000000 --- a/test/parallel/test-net-internal.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -// Flags: --expose-internals - -require('../common'); -const assert = require('assert'); -const isLegalPort = require('internal/net').isLegalPort; - -for (let n = 0; n <= 0xFFFF; n++) { - assert(isLegalPort(n)); - assert(isLegalPort(String(n))); - assert(`0x${n.toString(16)}`); - assert(`0o${n.toString(8)}`); - assert(`0b${n.toString(2)}`); -} - -const bad = [-1, 'a', {}, [], false, true, 0xFFFF + 1, Infinity, - -Infinity, NaN, undefined, null, '', ' ', 1.1, '0x', - '-0x1', '-0o1', '-0b1', '0o', '0b']; -bad.forEach((i) => assert(!isLegalPort(i))); diff --git a/test/parallel/test-os-checked-function.js b/test/parallel/test-os-checked-function.js index e0758437fe873f..819cdf1794155f 100644 --- a/test/parallel/test-os-checked-function.js +++ b/test/parallel/test-os-checked-function.js @@ -1,5 +1,5 @@ 'use strict'; -// Flags: --expose_internals +// Flags: --expose-internals require('../common'); const { internalBinding } = require('internal/test/binding'); diff --git a/test/parallel/test-os.js b/test/parallel/test-os.js index 57b68ff8dea9ac..5ee0fb9ca8dadb 100644 --- a/test/parallel/test-os.js +++ b/test/parallel/test-os.js @@ -194,6 +194,10 @@ const home = os.homedir(); is.string(home); assert.ok(home.includes(path.sep)); +const version = os.version(); +assert.strictEqual(typeof version, 'string'); +assert(version); + if (common.isWindows && process.env.USERPROFILE) { assert.strictEqual(home, process.env.USERPROFILE); delete process.env.USERPROFILE; diff --git a/test/parallel/test-performance-gc.js b/test/parallel/test-performance-gc.js index d071cddbcf0b51..aef0ee14254146 100644 --- a/test/parallel/test-performance-gc.js +++ b/test/parallel/test-performance-gc.js @@ -12,7 +12,8 @@ const { NODE_PERFORMANCE_GC_MAJOR, NODE_PERFORMANCE_GC_MINOR, NODE_PERFORMANCE_GC_INCREMENTAL, - NODE_PERFORMANCE_GC_WEAKCB + NODE_PERFORMANCE_GC_WEAKCB, + NODE_PERFORMANCE_GC_FLAGS_FORCED } = constants; const kinds = [ @@ -30,6 +31,7 @@ const kinds = [ assert.strictEqual(entry.name, 'gc'); assert.strictEqual(entry.entryType, 'gc'); assert(kinds.includes(entry.kind)); + assert.strictEqual(entry.flags, NODE_PERFORMANCE_GC_FLAGS_FORCED); assert.strictEqual(typeof entry.startTime, 'number'); assert.strictEqual(typeof entry.duration, 'number'); obs.disconnect(); diff --git a/test/parallel/test-performanceobserver.js b/test/parallel/test-performanceobserver.js index 01afbdc6aaf4b2..c68de859b6b654 100644 --- a/test/parallel/test-performanceobserver.js +++ b/test/parallel/test-performanceobserver.js @@ -88,8 +88,10 @@ assert.strictEqual(counts[NODE_PERFORMANCE_ENTRY_TYPE_FUNCTION], 0); countdown.dec(); } assert.strictEqual(counts[NODE_PERFORMANCE_ENTRY_TYPE_MARK], 0); - observer.observe({ entryTypes: ['mark'] }); + assert.strictEqual(counts[NODE_PERFORMANCE_ENTRY_TYPE_NODE], 0); + observer.observe({ entryTypes: ['mark', 'node'] }); assert.strictEqual(counts[NODE_PERFORMANCE_ENTRY_TYPE_MARK], 1); + assert.strictEqual(counts[NODE_PERFORMANCE_ENTRY_TYPE_NODE], 1); performance.mark('test1'); performance.mark('test2'); performance.mark('test3'); diff --git a/test/parallel/test-process-env-allowed-flags-are-documented.js b/test/parallel/test-process-env-allowed-flags-are-documented.js index f356f88fe9c740..0e0af9471ce84e 100644 --- a/test/parallel/test-process-env-allowed-flags-are-documented.js +++ b/test/parallel/test-process-env-allowed-flags-are-documented.js @@ -59,8 +59,6 @@ const conditionalOpts = [ filter: (opt) => opt === '--icu-data-dir' }, { include: process.features.inspector, filter: (opt) => opt.startsWith('--inspect') || opt === '--debug-port' }, - { include: process.config.variables.node_report, - filter: (opt) => opt.includes('-report') }, ]; documented.forEach((opt) => { conditionalOpts.forEach(({ include, filter }) => { @@ -86,6 +84,7 @@ const undocumented = difference(process.allowedNodeEnvironmentFlags, // Remove intentionally undocumented options. assert(undocumented.delete('--debug-arraybuffer-allocations')); assert(undocumented.delete('--es-module-specifier-resolution')); +assert(undocumented.delete('--experimental-report')); assert(undocumented.delete('--experimental-worker')); assert(undocumented.delete('--no-node-snapshot')); assert(undocumented.delete('--loader')); diff --git a/test/parallel/test-process-env.js b/test/parallel/test-process-env.js index 0e06306634c3e2..4ece826e8b938f 100644 --- a/test/parallel/test-process-env.js +++ b/test/parallel/test-process-env.js @@ -106,3 +106,11 @@ if (common.isWindows) { const keys = Object.keys(process.env); assert.ok(keys.length > 0); } + +// Setting environment variables on Windows with empty names should not cause +// an assertion failure. +// https://github.com/nodejs/node/issues/32920 +{ + process.env[''] = ''; + assert.strictEqual(process.env[''], undefined); +} diff --git a/test/parallel/test-process-uncaught-exception-monitor.js b/test/parallel/test-process-uncaught-exception-monitor.js new file mode 100644 index 00000000000000..fc6c2637f6978e --- /dev/null +++ b/test/parallel/test-process-uncaught-exception-monitor.js @@ -0,0 +1,69 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { execFile } = require('child_process'); +const fixtures = require('../common/fixtures'); + +{ + // Verify exit behavior is unchanged + const fixture = fixtures.path('uncaught-exceptions', 'uncaught-monitor1.js'); + execFile( + process.execPath, + [fixture], + common.mustCall((err, stdout, stderr) => { + assert.strictEqual(err.code, 1); + assert.strictEqual(Object.getPrototypeOf(err).name, 'Error'); + assert.strictEqual(stdout, 'Monitored: Shall exit\n'); + const errLines = stderr.trim().split(/[\r\n]+/); + const errLine = errLines.find((l) => /^Error/.exec(l)); + assert.strictEqual(errLine, 'Error: Shall exit'); + }) + ); +} + +{ + // Verify exit behavior is unchanged + const fixture = fixtures.path('uncaught-exceptions', 'uncaught-monitor2.js'); + execFile( + process.execPath, + [fixture], + common.mustCall((err, stdout, stderr) => { + assert.strictEqual(err.code, 7); + assert.strictEqual(Object.getPrototypeOf(err).name, 'Error'); + assert.strictEqual(stdout, 'Monitored: Shall exit, will throw now\n'); + const errLines = stderr.trim().split(/[\r\n]+/); + const errLine = errLines.find((l) => /^ReferenceError/.exec(l)); + assert.strictEqual( + errLine, + 'ReferenceError: missingFunction is not defined' + ); + }) + ); +} + +const theErr = new Error('MyError'); + +process.on( + 'uncaughtExceptionMonitor', + common.mustCall((err, origin) => { + assert.strictEqual(err, theErr); + assert.strictEqual(origin, 'uncaughtException'); + }, 2) +); + +process.on('uncaughtException', common.mustCall((err, origin) => { + assert.strictEqual(origin, 'uncaughtException'); + assert.strictEqual(err, theErr); +})); + +process.nextTick(common.mustCall(() => { + // Test with uncaughtExceptionCaptureCallback installed + process.setUncaughtExceptionCaptureCallback(common.mustCall( + (err) => assert.strictEqual(err, theErr)) + ); + + throw theErr; +})); + +throw theErr; diff --git a/test/parallel/test-promises-unhandled-rejections.js b/test/parallel/test-promises-unhandled-rejections.js index f4294800fa9dab..86a4370c518c56 100644 --- a/test/parallel/test-promises-unhandled-rejections.js +++ b/test/parallel/test-promises-unhandled-rejections.js @@ -2,6 +2,7 @@ const common = require('../common'); const assert = require('assert'); const domain = require('domain'); +const { inspect } = require('util'); common.disableCrashOnUnhandledRejection(); @@ -14,8 +15,8 @@ const asyncTest = (function() { function fail(error) { const stack = currentTest ? - `${error.stack}\nFrom previous event:\n${currentTest.stack}` : - error.stack; + `${inspect(error)}\nFrom previous event:\n${currentTest.stack}` : + inspect(error); if (currentTest) process.stderr.write(`'${currentTest.description}' failed\n\n`); @@ -44,11 +45,11 @@ const asyncTest = (function() { } return function asyncTest(description, fn) { - const stack = new Error().stack.split('\n').slice(1).join('\n'); + const stack = inspect(new Error()).split('\n').slice(1).join('\n'); asyncTestQueue.push({ action: fn, - stack: stack, - description: description + stack, + description }); if (!asyncTestsEnabled) { asyncTestsEnabled = true; diff --git a/test/parallel/test-readable-from-iterator-closing.js b/test/parallel/test-readable-from-iterator-closing.js new file mode 100644 index 00000000000000..02252ffe56854c --- /dev/null +++ b/test/parallel/test-readable-from-iterator-closing.js @@ -0,0 +1,197 @@ +'use strict'; + +const { mustCall, mustNotCall } = require('../common'); +const { Readable } = require('stream'); +const { strictEqual } = require('assert'); + +async function asyncSupport() { + const finallyMustCall = mustCall(); + const bodyMustCall = mustCall(); + + async function* infiniteGenerate() { + try { + while (true) yield 'a'; + } finally { + finallyMustCall(); + } + } + + const stream = Readable.from(infiniteGenerate()); + + for await (const chunk of stream) { + bodyMustCall(); + strictEqual(chunk, 'a'); + break; + } +} + +async function syncSupport() { + const finallyMustCall = mustCall(); + const bodyMustCall = mustCall(); + + function* infiniteGenerate() { + try { + while (true) yield 'a'; + } finally { + finallyMustCall(); + } + } + + const stream = Readable.from(infiniteGenerate()); + + for await (const chunk of stream) { + bodyMustCall(); + strictEqual(chunk, 'a'); + break; + } +} + +async function syncPromiseSupport() { + const returnMustBeAwaited = mustCall(); + const bodyMustCall = mustCall(); + + function* infiniteGenerate() { + try { + while (true) yield Promise.resolve('a'); + } finally { + // eslint-disable-next-line no-unsafe-finally + return { then(cb) { + returnMustBeAwaited(); + cb(); + } }; + } + } + + const stream = Readable.from(infiniteGenerate()); + + for await (const chunk of stream) { + bodyMustCall(); + strictEqual(chunk, 'a'); + break; + } +} + +async function syncRejectedSupport() { + const returnMustBeAwaited = mustCall(); + const bodyMustNotCall = mustNotCall(); + const catchMustCall = mustCall(); + const secondNextMustNotCall = mustNotCall(); + + function* generate() { + try { + yield Promise.reject('a'); + secondNextMustNotCall(); + } finally { + // eslint-disable-next-line no-unsafe-finally + return { then(cb) { + returnMustBeAwaited(); + cb(); + } }; + } + } + + const stream = Readable.from(generate()); + + try { + for await (const chunk of stream) { + bodyMustNotCall(chunk); + } + } catch { + catchMustCall(); + } +} + +async function noReturnAfterThrow() { + const returnMustNotCall = mustNotCall(); + const bodyMustNotCall = mustNotCall(); + const catchMustCall = mustCall(); + const nextMustCall = mustCall(); + + const stream = Readable.from({ + [Symbol.asyncIterator]() { return this; }, + async next() { + nextMustCall(); + throw new Error('a'); + }, + async return() { + returnMustNotCall(); + return { done: true }; + }, + }); + + try { + for await (const chunk of stream) { + bodyMustNotCall(chunk); + } + } catch { + catchMustCall(); + } +} + +async function closeStreamWhileNextIsPending() { + const finallyMustCall = mustCall(); + const dataMustCall = mustCall(); + + let resolveDestroy; + const destroyed = + new Promise((resolve) => { resolveDestroy = mustCall(resolve); }); + let resolveYielded; + const yielded = + new Promise((resolve) => { resolveYielded = mustCall(resolve); }); + + async function* infiniteGenerate() { + try { + while (true) { + yield 'a'; + resolveYielded(); + await destroyed; + } + } finally { + finallyMustCall(); + } + } + + const stream = Readable.from(infiniteGenerate()); + + stream.on('data', (data) => { + dataMustCall(); + strictEqual(data, 'a'); + }); + + yielded.then(() => { + stream.destroy(); + resolveDestroy(); + }); +} + +async function closeAfterNullYielded() { + const finallyMustCall = mustCall(); + const dataMustCall = mustCall(3); + + function* generate() { + try { + yield 'a'; + yield 'a'; + yield 'a'; + } finally { + finallyMustCall(); + } + } + + const stream = Readable.from(generate()); + + stream.on('data', (chunk) => { + dataMustCall(); + strictEqual(chunk, 'a'); + }); +} + +Promise.all([ + asyncSupport(), + syncSupport(), + syncPromiseSupport(), + syncRejectedSupport(), + noReturnAfterThrow(), + closeStreamWhileNextIsPending(), + closeAfterNullYielded(), +]).then(mustCall()); diff --git a/test/parallel/test-readline-csi.js b/test/parallel/test-readline-csi.js index 51b95c06b74897..5c0080d3d41910 100644 --- a/test/parallel/test-readline-csi.js +++ b/test/parallel/test-readline-csi.js @@ -9,8 +9,8 @@ const { CSI } = require('internal/readline/utils'); { assert(CSI); - assert.strictEqual(CSI.kClearToBeginning, '\x1b[1K'); - assert.strictEqual(CSI.kClearToEnd, '\x1b[0K'); + assert.strictEqual(CSI.kClearToLineBeginning, '\x1b[1K'); + assert.strictEqual(CSI.kClearToLineEnd, '\x1b[0K'); assert.strictEqual(CSI.kClearLine, '\x1b[2K'); assert.strictEqual(CSI.kClearScreenDown, '\x1b[0J'); assert.strictEqual(CSI`1${2}3`, '\x1b[123'); @@ -39,17 +39,19 @@ assert.throws(() => { }, /ERR_INVALID_CALLBACK/); // Verify that clearScreenDown() does not throw on null or undefined stream. -assert.strictEqual(readline.clearScreenDown(null, common.mustCall()), true); +assert.strictEqual(readline.clearScreenDown(null, common.mustCall((err) => { + assert.strictEqual(err, null); +})), true); assert.strictEqual(readline.clearScreenDown(undefined, common.mustCall()), true); writable.data = ''; assert.strictEqual(readline.clearLine(writable, -1), true); -assert.deepStrictEqual(writable.data, CSI.kClearToBeginning); +assert.deepStrictEqual(writable.data, CSI.kClearToLineBeginning); writable.data = ''; assert.strictEqual(readline.clearLine(writable, 1), true); -assert.deepStrictEqual(writable.data, CSI.kClearToEnd); +assert.deepStrictEqual(writable.data, CSI.kClearToLineEnd); writable.data = ''; assert.strictEqual(readline.clearLine(writable, 0), true); @@ -57,7 +59,7 @@ assert.deepStrictEqual(writable.data, CSI.kClearLine); writable.data = ''; assert.strictEqual(readline.clearLine(writable, -1, common.mustCall()), true); -assert.deepStrictEqual(writable.data, CSI.kClearToBeginning); +assert.deepStrictEqual(writable.data, CSI.kClearToLineBeginning); // Verify that clearLine() throws on invalid callback. assert.throws(() => { @@ -67,7 +69,9 @@ assert.throws(() => { // Verify that clearLine() does not throw on null or undefined stream. assert.strictEqual(readline.clearLine(null, 0), true); assert.strictEqual(readline.clearLine(undefined, 0), true); -assert.strictEqual(readline.clearLine(null, 0, common.mustCall()), true); +assert.strictEqual(readline.clearLine(null, 0, common.mustCall((err) => { + assert.strictEqual(err, null); +})), true); assert.strictEqual(readline.clearLine(undefined, 0, common.mustCall()), true); // Nothing is written when moveCursor 0, 0 @@ -101,7 +105,9 @@ assert.throws(() => { // Verify that moveCursor() does not throw on null or undefined stream. assert.strictEqual(readline.moveCursor(null, 1, 1), true); assert.strictEqual(readline.moveCursor(undefined, 1, 1), true); -assert.strictEqual(readline.moveCursor(null, 1, 1, common.mustCall()), true); +assert.strictEqual(readline.moveCursor(null, 1, 1, common.mustCall((err) => { + assert.strictEqual(err, null); +})), true); assert.strictEqual(readline.moveCursor(undefined, 1, 1, common.mustCall()), true); @@ -109,7 +115,9 @@ assert.strictEqual(readline.moveCursor(undefined, 1, 1, common.mustCall()), assert.strictEqual(readline.cursorTo(null), true); assert.strictEqual(readline.cursorTo(), true); assert.strictEqual(readline.cursorTo(null, 1, 1, common.mustCall()), true); -assert.strictEqual(readline.cursorTo(undefined, 1, 1, common.mustCall()), true); +assert.strictEqual(readline.cursorTo(undefined, 1, 1, common.mustCall((err) => { + assert.strictEqual(err, null); +})), true); writable.data = ''; assert.strictEqual(readline.cursorTo(writable, 'a'), true); diff --git a/test/parallel/test-readline-interface.js b/test/parallel/test-readline-interface.js index 2355676015b39a..2b0dcb0c383520 100644 --- a/test/parallel/test-readline-interface.js +++ b/test/parallel/test-readline-interface.js @@ -19,13 +19,16 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -// Flags: --expose_internals +// Flags: --expose-internals 'use strict'; const common = require('../common'); const assert = require('assert'); const readline = require('readline'); -const internalReadline = require('internal/readline/utils'); +const { + getStringWidth, + stripVTControlCharacters +} = require('internal/util/inspect'); const EventEmitter = require('events').EventEmitter; const { Writable, Readable } = require('stream'); @@ -410,6 +413,7 @@ function isWarned(emitter) { removeHistoryDuplicates: true }); const expectedLines = ['foo', 'bar', 'baz', 'bar', 'bat', 'bat']; + // ['foo', 'baz', 'bar', bat']; let callCount = 0; rli.on('line', function(line) { assert.strictEqual(line, expectedLines[callCount]); @@ -430,12 +434,51 @@ function isWarned(emitter) { assert.strictEqual(callCount, 0); fi.emit('keypress', '.', { name: 'down' }); // 'baz' assert.strictEqual(rli.line, 'baz'); + assert.strictEqual(rli.historyIndex, 2); fi.emit('keypress', '.', { name: 'n', ctrl: true }); // 'bar' assert.strictEqual(rli.line, 'bar'); + assert.strictEqual(rli.historyIndex, 1); + fi.emit('keypress', '.', { name: 'n', ctrl: true }); + assert.strictEqual(rli.line, 'bat'); + assert.strictEqual(rli.historyIndex, 0); + // Activate the substring history search. fi.emit('keypress', '.', { name: 'down' }); // 'bat' assert.strictEqual(rli.line, 'bat'); - fi.emit('keypress', '.', { name: 'down' }); // '' - assert.strictEqual(rli.line, ''); + assert.strictEqual(rli.historyIndex, -1); + // Deactivate substring history search. + fi.emit('keypress', '.', { name: 'backspace' }); // 'ba' + assert.strictEqual(rli.historyIndex, -1); + assert.strictEqual(rli.line, 'ba'); + // Activate the substring history search. + fi.emit('keypress', '.', { name: 'down' }); // 'ba' + assert.strictEqual(rli.historyIndex, -1); + assert.strictEqual(rli.line, 'ba'); + fi.emit('keypress', '.', { name: 'down' }); // 'ba' + assert.strictEqual(rli.historyIndex, -1); + assert.strictEqual(rli.line, 'ba'); + fi.emit('keypress', '.', { name: 'up' }); // 'bat' + assert.strictEqual(rli.historyIndex, 0); + assert.strictEqual(rli.line, 'bat'); + fi.emit('keypress', '.', { name: 'up' }); // 'bar' + assert.strictEqual(rli.historyIndex, 1); + assert.strictEqual(rli.line, 'bar'); + fi.emit('keypress', '.', { name: 'up' }); // 'baz' + assert.strictEqual(rli.historyIndex, 2); + assert.strictEqual(rli.line, 'baz'); + fi.emit('keypress', '.', { name: 'up' }); // 'ba' + assert.strictEqual(rli.historyIndex, 4); + assert.strictEqual(rli.line, 'ba'); + fi.emit('keypress', '.', { name: 'up' }); // 'ba' + assert.strictEqual(rli.historyIndex, 4); + assert.strictEqual(rli.line, 'ba'); + // Deactivate substring history search and reset history index. + fi.emit('keypress', '.', { name: 'right' }); // 'ba' + assert.strictEqual(rli.historyIndex, -1); + assert.strictEqual(rli.line, 'ba'); + // Substring history search activated. + fi.emit('keypress', '.', { name: 'up' }); // 'ba' + assert.strictEqual(rli.historyIndex, 0); + assert.strictEqual(rli.line, 'bat'); rli.close(); } @@ -676,11 +719,7 @@ function isWarned(emitter) { fi.emit('keypress', '.', { name: 'right' }); cursorPos = rli.getCursorPos(); assert.strictEqual(cursorPos.rows, 0); - if (common.hasIntl) { - assert.strictEqual(cursorPos.cols, 2); - } else { - assert.strictEqual(cursorPos.cols, 1); - } + assert.strictEqual(cursorPos.cols, 2); rli.on('line', common.mustCall((line) => { assert.strictEqual(line, '💻'); @@ -709,14 +748,7 @@ function isWarned(emitter) { fi.emit('data', '🐕'); cursorPos = rli.getCursorPos(); assert.strictEqual(cursorPos.rows, 0); - - if (common.hasIntl) { - assert.strictEqual(cursorPos.cols, 2); - } else { - assert.strictEqual(cursorPos.cols, 1); - // Fix cursor position without internationalization - fi.emit('keypress', '.', { name: 'left' }); - } + assert.strictEqual(cursorPos.cols, 2); rli.on('line', common.mustCall((line) => { assert.strictEqual(line, '🐕💻'); @@ -740,22 +772,12 @@ function isWarned(emitter) { fi.emit('keypress', '.', { name: 'right' }); let cursorPos = rli.getCursorPos(); assert.strictEqual(cursorPos.rows, 0); - if (common.hasIntl) { - assert.strictEqual(cursorPos.cols, 2); - } else { - assert.strictEqual(cursorPos.cols, 1); - // Fix cursor position without internationalization - fi.emit('keypress', '.', { name: 'right' }); - } + assert.strictEqual(cursorPos.cols, 2); fi.emit('data', '🐕'); cursorPos = rli.getCursorPos(); assert.strictEqual(cursorPos.rows, 0); - if (common.hasIntl) { - assert.strictEqual(cursorPos.cols, 4); - } else { - assert.strictEqual(cursorPos.cols, 2); - } + assert.strictEqual(cursorPos.cols, 4); rli.on('line', common.mustCall((line) => { assert.strictEqual(line, '💻🐕'); @@ -917,11 +939,7 @@ function isWarned(emitter) { fi.emit('data', '💻'); let cursorPos = rli.getCursorPos(); assert.strictEqual(cursorPos.rows, 0); - if (common.hasIntl) { - assert.strictEqual(cursorPos.cols, 2); - } else { - assert.strictEqual(cursorPos.cols, 1); - } + assert.strictEqual(cursorPos.cols, 2); // Delete left character fi.emit('keypress', '.', { ctrl: true, name: 'h' }); cursorPos = rli.getCursorPos(); @@ -1104,52 +1122,45 @@ function isWarned(emitter) { } } - // isFullWidthCodePoint() should return false for non-numeric values - [true, false, null, undefined, {}, [], 'あ'].forEach((v) => { - assert.strictEqual(internalReadline.isFullWidthCodePoint('あ'), false); - }); - // Wide characters should be treated as two columns. - assert.strictEqual(internalReadline.isFullWidthCodePoint('a'.charCodeAt(0)), - false); - assert.strictEqual(internalReadline.isFullWidthCodePoint('あ'.charCodeAt(0)), - true); - assert.strictEqual(internalReadline.isFullWidthCodePoint('谢'.charCodeAt(0)), - true); - assert.strictEqual(internalReadline.isFullWidthCodePoint('고'.charCodeAt(0)), - true); - assert.strictEqual(internalReadline.isFullWidthCodePoint(0x1f251), true); - assert.strictEqual(internalReadline.getStringWidth('abcde'), 5); - assert.strictEqual(internalReadline.getStringWidth('古池や'), 6); - assert.strictEqual(internalReadline.getStringWidth('ノード.js'), 9); - assert.strictEqual(internalReadline.getStringWidth('你好'), 4); - assert.strictEqual(internalReadline.getStringWidth('안녕하세요'), 10); - assert.strictEqual(internalReadline.getStringWidth('A\ud83c\ude00BC'), 5); + assert.strictEqual(getStringWidth('a'), 1); + assert.strictEqual(getStringWidth('あ'), 2); + assert.strictEqual(getStringWidth('谢'), 2); + assert.strictEqual(getStringWidth('고'), 2); + assert.strictEqual(getStringWidth(String.fromCodePoint(0x1f251)), 2); + assert.strictEqual(getStringWidth('abcde'), 5); + assert.strictEqual(getStringWidth('古池や'), 6); + assert.strictEqual(getStringWidth('ノード.js'), 9); + assert.strictEqual(getStringWidth('你好'), 4); + assert.strictEqual(getStringWidth('안녕하세요'), 10); + assert.strictEqual(getStringWidth('A\ud83c\ude00BC'), 5); + assert.strictEqual(getStringWidth('👨‍👩‍👦‍👦'), 8); + assert.strictEqual(getStringWidth('🐕𐐷あ💻😀'), 9); + // TODO(BridgeAR): This should have a width of 4. + assert.strictEqual(getStringWidth('⓬⓪'), 2); + assert.strictEqual(getStringWidth('\u0301\u200D\u200E'), 0); // Check if vt control chars are stripped assert.strictEqual( - internalReadline.stripVTControlCharacters('\u001b[31m> \u001b[39m'), + stripVTControlCharacters('\u001b[31m> \u001b[39m'), '> ' ); assert.strictEqual( - internalReadline.stripVTControlCharacters('\u001b[31m> \u001b[39m> '), + stripVTControlCharacters('\u001b[31m> \u001b[39m> '), '> > ' ); assert.strictEqual( - internalReadline.stripVTControlCharacters('\u001b[31m\u001b[39m'), + stripVTControlCharacters('\u001b[31m\u001b[39m'), '' ); assert.strictEqual( - internalReadline.stripVTControlCharacters('> '), + stripVTControlCharacters('> '), '> ' ); - assert.strictEqual(internalReadline - .getStringWidth('\u001b[31m> \u001b[39m'), 2); - assert.strictEqual(internalReadline - .getStringWidth('\u001b[31m> \u001b[39m> '), 4); - assert.strictEqual(internalReadline - .getStringWidth('\u001b[31m\u001b[39m'), 0); - assert.strictEqual(internalReadline.getStringWidth('> '), 2); + assert.strictEqual(getStringWidth('\u001b[31m> \u001b[39m'), 2); + assert.strictEqual(getStringWidth('\u001b[31m> \u001b[39m> '), 4); + assert.strictEqual(getStringWidth('\u001b[31m\u001b[39m'), 0); + assert.strictEqual(getStringWidth('> '), 2); { const fi = new FakeInput(); diff --git a/test/parallel/test-readline-tab-complete.js b/test/parallel/test-readline-tab-complete.js new file mode 100644 index 00000000000000..d7a4bb7a9a0690 --- /dev/null +++ b/test/parallel/test-readline-tab-complete.js @@ -0,0 +1,68 @@ +'use strict'; + +// Flags: --expose-internals + +const common = require('../common'); +const readline = require('readline'); +const assert = require('assert'); +const EventEmitter = require('events').EventEmitter; +const { getStringWidth } = require('internal/util/inspect'); + +// This test verifies that the tab completion supports unicode and the writes +// are limited to the minimum. +[ + 'あ', + '𐐷', + '🐕' +].forEach((char) => { + [true, false].forEach((lineBreak) => { + const completer = (line) => [ + [ + 'First group', + '', + `${char}${'a'.repeat(10)}`, `${char}${'b'.repeat(10)}`, char.repeat(11), + ], + line + ]; + + let output = ''; + const width = getStringWidth(char) - 1; + + class FakeInput extends EventEmitter { + columns = ((width + 1) * 10 + (lineBreak ? 0 : 10)) * 3 + + write = common.mustCall((data) => { + output += data; + }, 6) + + resume() {} + pause() {} + end() {} + } + + const fi = new FakeInput(); + const rli = new readline.Interface({ + input: fi, + output: fi, + terminal: true, + completer: completer + }); + + const last = '\r\nFirst group\r\n\r\n' + + `${char}${'a'.repeat(10)}${' '.repeat(2 + width * 10)}` + + `${char}${'b'.repeat(10)}` + + (lineBreak ? '\r\n' : ' '.repeat(2 + width * 10)) + + `${char.repeat(11)}\r\n` + + `\r\n\u001b[1G\u001b[0J> ${char}\u001b[${4 + width}G`; + + const expectations = [char, '', last]; + + rli.on('line', common.mustNotCall()); + for (const character of `${char}\t\t`) { + fi.emit('data', character); + assert.strictEqual(output, expectations.shift()); + output = ''; + } + rli.close(); + }); +}); diff --git a/test/parallel/test-repl-editor.js b/test/parallel/test-repl-editor.js index 969f6172b3fb70..6871fbdcb1a882 100644 --- a/test/parallel/test-repl-editor.js +++ b/test/parallel/test-repl-editor.js @@ -5,9 +5,9 @@ const assert = require('assert'); const repl = require('repl'); const ArrayStream = require('../common/arraystream'); -// \u001b[1G - Moves the cursor to 1st column +// \u001b[nG - Moves the cursor to n st column // \u001b[0J - Clear screen -// \u001b[3G - Moves the cursor to 3rd column +// \u001b[0K - Clear to line end const terminalCode = '\u001b[1G\u001b[0J> \u001b[3G'; const terminalCodeRegex = new RegExp(terminalCode.replace(/\[/g, '\\['), 'g'); diff --git a/test/parallel/test-repl-eval-scope.js b/test/parallel/test-repl-eval-scope.js deleted file mode 100644 index 702b6056f101a5..00000000000000 --- a/test/parallel/test-repl-eval-scope.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; -const common = require('../common'); -const ArrayStream = require('../common/arraystream'); -const assert = require('assert'); -const repl = require('repl'); - -{ - const stream = new ArrayStream(); - const options = { - eval: common.mustCall((cmd, context) => { - assert.strictEqual(cmd, '.scope\n'); - assert.deepStrictEqual(context, { animal: 'Sterrance' }); - }), - input: stream, - output: stream, - terminal: true - }; - - const r = repl.start(options); - r.context = { animal: 'Sterrance' }; - - stream.emit('data', '\t'); - stream.emit('.exit\n'); -} diff --git a/test/parallel/test-repl-history-navigation.js b/test/parallel/test-repl-history-navigation.js index b00f932aa9a253..8eda8e3ceceeef 100644 --- a/test/parallel/test-repl-history-navigation.js +++ b/test/parallel/test-repl-history-navigation.js @@ -8,6 +8,7 @@ const REPL = require('internal/repl'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); +const { inspect } = require('util'); const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); @@ -34,40 +35,436 @@ class ActionStream extends stream.Stream { } setImmediate(doAction); }; - setImmediate(doAction); + doAction(); } resume() {} pause() {} } ActionStream.prototype.readable = true; - // Mock keys const ENTER = { name: 'enter' }; const UP = { name: 'up' }; const DOWN = { name: 'down' }; +const LEFT = { name: 'left' }; +const RIGHT = { name: 'right' }; +const DELETE = { name: 'delete' }; +const BACKSPACE = { name: 'backspace' }; +const WORD_LEFT = { name: 'left', ctrl: true }; +const WORD_RIGHT = { name: 'right', ctrl: true }; +const GO_TO_END = { name: 'end' }; +const DELETE_WORD_LEFT = { name: 'backspace', ctrl: true }; +const SIGINT = { name: 'c', ctrl: true }; const prompt = '> '; +const WAIT = '€'; + +const prev = process.features.inspector; + +let completions = 0; const tests = [ { // Creates few history to navigate for env: { NODE_REPL_HISTORY: defaultHistoryPath }, test: [ 'let ab = 45', ENTER, '555 + 909', ENTER, - '{key : {key2 :[] }}', ENTER], + '{key : {key2 :[] }}', ENTER, + 'Array(100).fill(1).map((e, i) => i ** i)', LEFT, LEFT, DELETE, + '2', ENTER], expected: [], clean: false }, { env: { NODE_REPL_HISTORY: defaultHistoryPath }, - test: [UP, UP, UP, UP, DOWN, DOWN, DOWN], + test: [UP, UP, UP, UP, UP, DOWN, DOWN, DOWN, DOWN, DOWN], expected: [prompt, + `${prompt}Array(100).fill(1).map((e, i) => i ** 2)`, + prev && '\n// [ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, ' + + '144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529,' + + ' 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, ' + + '1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936,' + + ' 2025, 2116, 2209,...', `${prompt}{key : {key2 :[] }}`, + prev && '\n// { key: { key2: [] } }', `${prompt}555 + 909`, + prev && '\n// 1464', + `${prompt}let ab = 45`, + prompt, `${prompt}let ab = 45`, `${prompt}555 + 909`, + prev && '\n// 1464', `${prompt}{key : {key2 :[] }}`, - prompt], + prev && '\n// { key: { key2: [] } }', + `${prompt}Array(100).fill(1).map((e, i) => i ** 2)`, + prev && '\n// [ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, ' + + '144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529,' + + ' 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, ' + + '1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936,' + + ' 2025, 2116, 2209,...', + prompt].filter((e) => typeof e === 'string'), + clean: false + }, + { // Creates more history entries to navigate through. + env: { NODE_REPL_HISTORY: defaultHistoryPath }, + test: [ + '555 + 909', ENTER, // Add a duplicate to the history set. + 'const foo = true', ENTER, + '555n + 111n', ENTER, + '5 + 5', ENTER, + '55 - 13 === 42', ENTER + ], + expected: [], + clean: false + }, + { + env: { NODE_REPL_HISTORY: defaultHistoryPath }, + checkTotal: true, + preview: false, + showEscapeCodes: true, + test: [ + '55', UP, UP, UP, UP, UP, UP, ENTER + ], + expected: [ + '\x1B[1G', '\x1B[0J', prompt, '\x1B[3G', + // '55' + '5', '5', + // UP + '\x1B[1G', '\x1B[0J', + '> 55 - 13 === 42', '\x1B[17G', + // UP - skipping 5 + 5 + '\x1B[1G', '\x1B[0J', + '> 555n + 111n', '\x1B[14G', + // UP - skipping const foo = true + '\x1B[1G', '\x1B[0J', + '> 555 + 909', '\x1B[12G', + // UP, UP + // UPs at the end of the history reset the line to the original input. + '\x1B[1G', '\x1B[0J', + '> 55', '\x1B[5G', + // ENTER + '\r\n', '55\n', + '\x1B[1G', '\x1B[0J', + '> ', '\x1B[3G', + '\r\n' + ], + clean: true + }, + { + env: { NODE_REPL_HISTORY: defaultHistoryPath }, + skip: !process.features.inspector, + test: [ + // あ is a full width character with a length of one. + // 🐕 is a full width character with a length of two. + // 𐐷 is a half width character with the length of two. + // '\u0301', '0x200D', '\u200E' are zero width characters. + `const x1 = '${'あ'.repeat(124)}'`, ENTER, // Fully visible + ENTER, + `const y1 = '${'あ'.repeat(125)}'`, ENTER, // Cut off + ENTER, + `const x2 = '${'🐕'.repeat(124)}'`, ENTER, // Fully visible + ENTER, + `const y2 = '${'🐕'.repeat(125)}'`, ENTER, // Cut off + ENTER, + `const x3 = '${'𐐷'.repeat(248)}'`, ENTER, // Fully visible + ENTER, + `const y3 = '${'𐐷'.repeat(249)}'`, ENTER, // Cut off + ENTER, + `const x4 = 'a${'\u0301'.repeat(1000)}'`, ENTER, // á + ENTER, + `const ${'veryLongName'.repeat(30)} = 'I should be previewed'`, + ENTER, + 'const e = new RangeError("visible\\ninvisible")', + ENTER, + 'e', + ENTER, + 'veryLongName'.repeat(30), + ENTER, + `${'\x1B[90m \x1B[39m'.repeat(235)} fun`, + ENTER, + `${' '.repeat(236)} fun`, + ENTER + ], + expected: [], + clean: false + }, + { + env: { NODE_REPL_HISTORY: defaultHistoryPath }, + columns: 250, + checkTotal: true, + showEscapeCodes: true, + skip: !process.features.inspector, + test: [ + UP, + UP, + UP, + WORD_LEFT, + UP, + BACKSPACE, + 'x1', + BACKSPACE, + '2', + BACKSPACE, + '3', + BACKSPACE, + '4', + DELETE_WORD_LEFT, + 'y1', + BACKSPACE, + '2', + BACKSPACE, + '3', + SIGINT + ], + // A = Cursor n up + // B = Cursor n down + // C = Cursor n forward + // D = Cursor n back + // G = Cursor to column n + // J = Erase in screen; 0 = right; 1 = left; 2 = total + // K = Erase in line; 0 = right; 1 = left; 2 = total + expected: [ + // 0. Start + '\x1B[1G', '\x1B[0J', + prompt, '\x1B[3G', + // 1. UP + // This exceeds the maximum columns (250): + // Whitespace + prompt + ' // '.length + 'function'.length + // 236 + 2 + 4 + 8 + '\x1B[1G', '\x1B[0J', + `${prompt}${' '.repeat(236)} fun`, '\x1B[243G', + ' // ction', '\x1B[243G', + ' // ction', '\x1B[243G', + '\x1B[0K', + // 2. UP + '\x1B[1G', '\x1B[0J', + `${prompt}${' '.repeat(235)} fun`, '\x1B[242G', + // TODO(BridgeAR): Investigate why the preview is generated twice. + ' // ction', '\x1B[242G', + ' // ction', '\x1B[242G', + // Preview cleanup + '\x1B[0K', + // 3. UP + '\x1B[1G', '\x1B[0J', + // 'veryLongName'.repeat(30).length === 360 + // prompt.length === 2 + // 360 % 250 + 2 === 112 (+1) + `${prompt}${'veryLongName'.repeat(30)}`, '\x1B[113G', + // "// 'I should be previewed'".length + 86 === 112 (+1) + "\n// 'I should be previewed'", '\x1B[113G', '\x1B[1A', + // Preview cleanup + '\x1B[1B', '\x1B[2K', '\x1B[1A', + // 4. WORD LEFT + // Almost identical as above. Just one extra line. + // Math.floor(360 / 250) === 1 + '\x1B[1A', + '\x1B[1G', '\x1B[0J', + `${prompt}${'veryLongName'.repeat(30)}`, '\x1B[3G', '\x1B[1A', + '\x1B[1B', "\n// 'I should be previewed'", '\x1B[3G', '\x1B[2A', + // Preview cleanup + '\x1B[2B', '\x1B[2K', '\x1B[2A', + // 5. UP + '\x1B[1G', '\x1B[0J', + `${prompt}e`, '\x1B[4G', + // '// RangeError: visible'.length - 19 === 3 (+1) + '\n// RangeError: visible', '\x1B[4G', '\x1B[1A', + // Preview cleanup + '\x1B[1B', '\x1B[2K', '\x1B[1A', + // 6. Backspace + '\x1B[1G', '\x1B[0J', + '> ', '\x1B[3G', 'x', '1', + `\n// '${'あ'.repeat(124)}'`, + '\x1B[5G', '\x1B[1A', + '\x1B[1B', '\x1B[2K', '\x1B[1A', + '\x1B[1G', '\x1B[0J', + '> x', '\x1B[4G', '2', + `\n// '${'🐕'.repeat(124)}'`, + '\x1B[5G', '\x1B[1A', + '\x1B[1B', '\x1B[2K', '\x1B[1A', + '\x1B[1G', '\x1B[0J', + '> x', '\x1B[4G', '3', + `\n// '${'𐐷'.repeat(248)}'`, + '\x1B[5G', '\x1B[1A', + '\x1B[1B', '\x1B[2K', '\x1B[1A', + '\x1B[1G', '\x1B[0J', + '> x', '\x1B[4G', '4', + `\n// 'a${'\u0301'.repeat(1000)}'`, + '\x1B[5G', '\x1B[1A', + '\x1B[1B', '\x1B[2K', '\x1B[1A', + '\x1B[1G', '\x1B[0J', + '> ', '\x1B[3G', 'y', '1', + `\n// '${'あ'.repeat(121)}...`, + '\x1B[5G', '\x1B[1A', + '\x1B[1B', '\x1B[2K', '\x1B[1A', + '\x1B[1G', '\x1B[0J', + '> y', '\x1B[4G', '2', + `\n// '${'🐕'.repeat(121)}...`, + '\x1B[5G', '\x1B[1A', + '\x1B[1B', '\x1B[2K', '\x1B[1A', + '\x1B[1G', '\x1B[0J', + '> y', '\x1B[4G', '3', + `\n// '${'𐐷'.repeat(242)}...`, + '\x1B[5G', '\x1B[1A', + '\x1B[1B', '\x1B[2K', '\x1B[1A', + '\r\n', + '\x1B[1G', '\x1B[0J', + '> ', '\x1B[3G', + '\r\n' + ], + clean: true + }, + { + env: { NODE_REPL_HISTORY: defaultHistoryPath }, + showEscapeCodes: true, + skip: !process.features.inspector, + test: [ + 'fu', + 'n', + RIGHT, + BACKSPACE, + LEFT, + LEFT, + 'A', + BACKSPACE, + GO_TO_END, + BACKSPACE, + WORD_LEFT, + WORD_RIGHT, + ENTER + ], + // C = Cursor n forward + // D = Cursor n back + // G = Cursor to column n + // J = Erase in screen; 0 = right; 1 = left; 2 = total + // K = Erase in line; 0 = right; 1 = left; 2 = total + expected: [ + // 0. + // 'f' + '\x1B[1G', '\x1B[0J', prompt, '\x1B[3G', 'f', + // 'u' + 'u', ' // nction', '\x1B[5G', + // 'n' - Cleanup + '\x1B[0K', + 'n', ' // ction', '\x1B[6G', + // 1. Right. Cleanup + '\x1B[0K', + 'ction', + // 2. Backspace. Refresh + '\x1B[1G', '\x1B[0J', `${prompt}functio`, '\x1B[10G', + // Autocomplete and refresh? + ' // n', '\x1B[10G', ' // n', '\x1B[10G', + // 3. Left. Cleanup + '\x1B[0K', + '\x1B[1D', '\x1B[10G', ' // n', '\x1B[9G', + // 4. Left. Cleanup + '\x1B[10G', '\x1B[0K', '\x1B[9G', + '\x1B[1D', '\x1B[10G', ' // n', '\x1B[8G', + // 5. 'A' - Cleanup + '\x1B[10G', '\x1B[0K', '\x1B[8G', + // Refresh + '\x1B[1G', '\x1B[0J', `${prompt}functAio`, '\x1B[9G', + // 6. Backspace. Refresh + '\x1B[1G', '\x1B[0J', `${prompt}functio`, '\x1B[8G', '\x1B[10G', ' // n', + '\x1B[8G', '\x1B[10G', ' // n', + '\x1B[8G', '\x1B[10G', + // 7. Go to end. Cleanup + '\x1B[0K', '\x1B[8G', '\x1B[2C', + 'n', + // 8. Backspace. Refresh + '\x1B[1G', '\x1B[0J', `${prompt}functio`, '\x1B[10G', + // Autocomplete + ' // n', '\x1B[10G', ' // n', '\x1B[10G', + // 9. Word left. Cleanup + '\x1B[0K', '\x1B[7D', '\x1B[10G', ' // n', '\x1B[3G', '\x1B[10G', + // 10. Word right. Cleanup + '\x1B[0K', '\x1B[3G', '\x1B[7C', ' // n', '\x1B[10G', + '\x1B[0K', + // 11. ENTER + '\r\n', + 'Uncaught ReferenceError: functio is not defined\n', + '\x1B[1G', '\x1B[0J', + prompt, '\x1B[3G', '\r\n' + ], + clean: true + }, + { + // Check changed inspection defaults. + env: { NODE_REPL_HISTORY: defaultHistoryPath }, + skip: !process.features.inspector, + test: [ + 'util.inspect.replDefaults.showHidden', + ENTER + ], + expected: [], + clean: false + }, + { + env: { NODE_REPL_HISTORY: defaultHistoryPath }, + skip: !process.features.inspector, + checkTotal: true, + test: [ + '[ ]', + WORD_LEFT, + WORD_LEFT, + UP, + ' = true', + ENTER, + '[ ]', + ENTER + ], + expected: [ + prompt, + '[', ' ', ']', + '\n// []', '\n// []', '\n// []', + '> util.inspect.replDefaults.showHidden', + '\n// false', + ' ', '=', ' ', 't', 'r', 'u', 'e', + 'true\n', + '> ', '[', ' ', ']', + '\n// [ [length]: 0 ]', + '[ [length]: 0 ]\n', + '> ', + ], + clean: true + }, + { + // Check that the completer ignores completions that are outdated. + env: { NODE_REPL_HISTORY: defaultHistoryPath }, + completer(line, callback) { + if (line.endsWith(WAIT)) { + if (completions++ === 0) { + callback(null, [[`${WAIT}WOW`], line]); + } else { + setTimeout(callback, 1000, null, [[`${WAIT}WOW`], line]).unref(); + } + } else { + callback(null, [[' Always visible'], line]); + } + }, + skip: !process.features.inspector, + test: [ + WAIT, // The first call is awaited before new input is triggered! + BACKSPACE, + 's', + BACKSPACE, + WAIT, // The second call is not awaited. It won't trigger the preview. + BACKSPACE, + 's', + BACKSPACE + ], + expected: [ + prompt, + WAIT, + ' // WOW', + prompt, + 's', + ' // Always visible', + prompt, + WAIT, + prompt, + 's', + ' // Always visible', + prompt, + ], clean: true } ]; @@ -90,30 +487,50 @@ function runTest() { const opts = tests.shift(); if (!opts) return; // All done - const env = opts.env; - const test = opts.test; - const expected = opts.expected; + const { expected, skip } = opts; - REPL.createInternalRepl(env, { + // Test unsupported on platform. + if (skip) { + setImmediate(runTestWrap, true); + return; + } + const lastChunks = []; + let i = 0; + + REPL.createInternalRepl(opts.env, { input: new ActionStream(), output: new stream.Writable({ write(chunk, _, next) { const output = chunk.toString(); - if (output.charCodeAt(0) === 27 || /^[\r\n]+$/.test(output)) { + if (!opts.showEscapeCodes && + (output[0] === '\x1B' || /^[\r\n]+$/.test(output))) { return next(); } - if (expected.length) { - assert.strictEqual(output, expected[0]); - expected.shift(); + lastChunks.push(output); + + if (expected.length && !opts.checkTotal) { + try { + assert.strictEqual(output, expected[i]); + } catch (e) { + console.error(`Failed test # ${numtests - tests.length}`); + console.error('Last outputs: ' + inspect(lastChunks, { + breakLength: 5, colors: true + })); + throw e; + } + // TODO(BridgeAR): Auto close on last chunk! + i++; } next(); } }), - prompt: prompt, + completer: opts.completer, + prompt, useColors: false, + preview: opts.preview, terminal: true }, function(err, repl) { if (err) { @@ -125,13 +542,23 @@ function runTest() { if (opts.clean) cleanupTmpFile(); - if (expected.length !== 0) { + if (opts.checkTotal) { + assert.deepStrictEqual(lastChunks, expected); + } else if (expected.length !== i) { + console.error(tests[numtests - tests.length - 1]); throw new Error(`Failed test # ${numtests - tests.length}`); } + setImmediate(runTestWrap, true); }); - repl.inputStream.run(test); + if (opts.columns) { + Object.defineProperty(repl, 'columns', { + value: opts.columns, + enumerable: true + }); + } + repl.inputStream.run(opts.test); }); } diff --git a/test/parallel/test-repl-history-perm.js b/test/parallel/test-repl-history-perm.js index 03ce1435d9ba4e..a6317d7c02181b 100644 --- a/test/parallel/test-repl-history-perm.js +++ b/test/parallel/test-repl-history-perm.js @@ -2,7 +2,7 @@ // Verifies that the REPL history file is created with mode 0600 -// Flags: --expose_internals +// Flags: --expose-internals const common = require('../common'); diff --git a/test/parallel/test-repl-import-referrer.js b/test/parallel/test-repl-import-referrer.js index 400015ced07f59..19b3fe721b5c43 100644 --- a/test/parallel/test-repl-import-referrer.js +++ b/test/parallel/test-repl-import-referrer.js @@ -4,11 +4,7 @@ const assert = require('assert'); const cp = require('child_process'); const fixtures = require('../common/fixtures'); -const args = [ - '--interactive', - '--experimental-repl-await', - '--experimental-modules' -]; +const args = ['--interactive', '--experimental-repl-await']; const opts = { cwd: fixtures.path('es-modules') }; const child = cp.spawn(process.execPath, args, opts); diff --git a/test/parallel/test-repl-multiline.js b/test/parallel/test-repl-multiline.js index 454d5b10192fa5..e458555cd87f76 100644 --- a/test/parallel/test-repl-multiline.js +++ b/test/parallel/test-repl-multiline.js @@ -3,34 +3,39 @@ const common = require('../common'); const ArrayStream = require('../common/arraystream'); const assert = require('assert'); const repl = require('repl'); -const inputStream = new ArrayStream(); -const outputStream = new ArrayStream(); -const input = ['const foo = {', '};', 'foo;']; -let output = ''; +const input = ['const foo = {', '};', 'foo']; -outputStream.write = (data) => { output += data.replace('\r', ''); }; +function run({ useColors }) { + const inputStream = new ArrayStream(); + const outputStream = new ArrayStream(); + let output = ''; -const r = repl.start({ - prompt: '', - input: inputStream, - output: outputStream, - terminal: true, - useColors: false -}); + outputStream.write = (data) => { output += data.replace('\r', ''); }; -r.on('exit', common.mustCall(() => { - const actual = output.split('\n'); + const r = repl.start({ + prompt: '', + input: inputStream, + output: outputStream, + terminal: true, + useColors + }); - // Validate the output, which contains terminal escape codes. - assert.strictEqual(actual.length, 6); - assert.ok(actual[0].endsWith(input[0])); - assert.ok(actual[1].includes('... ')); - assert.ok(actual[1].endsWith(input[1])); - assert.strictEqual(actual[2], 'undefined'); - assert.ok(actual[3].endsWith(input[2])); - assert.strictEqual(actual[4], '{}'); - // Ignore the last line, which is nothing but escape codes. -})); + r.on('exit', common.mustCall(() => { + const actual = output.split('\n'); -inputStream.run(input); -r.close(); + // Validate the output, which contains terminal escape codes. + assert.strictEqual(actual.length, 6); + assert.ok(actual[0].endsWith(input[0])); + assert.ok(actual[1].includes('... ')); + assert.ok(actual[1].endsWith(input[1])); + assert.ok(actual[2].includes('undefined')); + assert.ok(actual[3].endsWith(input[2])); + assert.strictEqual(actual[4], '{}'); + })); + + inputStream.run(input); + r.close(); +} + +run({ useColors: true }); +run({ useColors: false }); diff --git a/test/parallel/test-repl-persistent-history.js b/test/parallel/test-repl-persistent-history.js index bb10085eccfcf6..1d1261a3752365 100644 --- a/test/parallel/test-repl-persistent-history.js +++ b/test/parallel/test-repl-persistent-history.js @@ -10,6 +10,7 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); const os = require('os'); +const util = require('util'); const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); @@ -51,6 +52,7 @@ ActionStream.prototype.readable = true; // Mock keys const UP = { name: 'up' }; +const DOWN = { name: 'down' }; const ENTER = { name: 'enter' }; const CLEAR = { ctrl: true, name: 'u' }; @@ -90,20 +92,42 @@ const tests = [ }, { env: {}, - test: [UP, '\'42\'', ENTER], - expected: [prompt, '\'', '4', '2', '\'', '\'42\'\n', prompt, prompt], + test: [UP, '21', ENTER, "'42'", ENTER], + expected: [ + prompt, + '2', '1', '21\n', prompt, prompt, + "'", '4', '2', "'", "'42'\n", prompt, prompt + ], clean: false }, { // Requires the above test case env: {}, - test: [UP, UP, ENTER], - expected: [prompt, `${prompt}'42'`, '\'42\'\n', prompt] + test: [UP, UP, CLEAR, ENTER, DOWN, CLEAR, ENTER, UP, ENTER], + expected: [ + prompt, + `${prompt}'42'`, + `${prompt}21`, + prompt, + prompt, + `${prompt}'42'`, + prompt, + prompt, + `${prompt}21`, + '21\n', + prompt, + ] }, { env: { NODE_REPL_HISTORY: historyPath, NODE_REPL_HISTORY_SIZE: 1 }, - test: [UP, UP, CLEAR], - expected: [prompt, `${prompt}'you look fabulous today'`, prompt] + test: [UP, UP, DOWN, CLEAR], + expected: [ + prompt, + `${prompt}'you look fabulous today'`, + prompt, + `${prompt}'you look fabulous today'`, + prompt + ] }, { env: { NODE_REPL_HISTORY: historyPathFail, @@ -169,6 +193,8 @@ function runTest(assertCleaned) { const opts = tests.shift(); if (!opts) return; // All done + console.log('NEW'); + if (assertCleaned) { try { assert.strictEqual(fs.readFileSync(defaultHistoryPath, 'utf8'), ''); @@ -193,6 +219,7 @@ function runTest(assertCleaned) { output: new stream.Writable({ write(chunk, _, next) { const output = chunk.toString(); + console.log('INPUT', util.inspect(output)); // Ignore escapes and blank lines if (output.charCodeAt(0) === 27 || /^[\r\n]+$/.test(output)) @@ -207,7 +234,7 @@ function runTest(assertCleaned) { next(); } }), - prompt: prompt, + prompt, useColors: false, terminal: true }, function(err, repl) { diff --git a/test/parallel/test-repl-preview.js b/test/parallel/test-repl-preview.js new file mode 100644 index 00000000000000..b8dbbf3f9a993d --- /dev/null +++ b/test/parallel/test-repl-preview.js @@ -0,0 +1,193 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { REPLServer } = require('repl'); +const { Stream } = require('stream'); +const { inspect } = require('util'); + +common.skipIfInspectorDisabled(); + +const PROMPT = 'repl > '; + +class REPLStream extends Stream { + readable = true; + writable = true; + + constructor() { + super(); + this.lines = ['']; + } + run(data) { + for (const entry of data) { + this.emit('data', entry); + } + this.emit('data', '\n'); + } + write(chunk) { + const chunkLines = chunk.toString('utf8').split('\n'); + this.lines[this.lines.length - 1] += chunkLines[0]; + if (chunkLines.length > 1) { + this.lines.push(...chunkLines.slice(1)); + } + this.emit('line'); + return true; + } + wait() { + this.lines = ['']; + return new Promise((resolve, reject) => { + const onError = (err) => { + this.removeListener('line', onLine); + reject(err); + }; + const onLine = () => { + if (this.lines[this.lines.length - 1].includes(PROMPT)) { + this.removeListener('error', onError); + this.removeListener('line', onLine); + resolve(this.lines); + } + }; + this.once('error', onError); + this.on('line', onLine); + }); + } + pause() {} + resume() {} +} + +function runAndWait(cmds, repl) { + const promise = repl.inputStream.wait(); + for (const cmd of cmds) { + repl.inputStream.run(cmd); + } + return promise; +} + +async function tests(options) { + const repl = REPLServer({ + prompt: PROMPT, + stream: new REPLStream(), + ignoreUndefined: true, + useColors: true, + ...options + }); + + repl.inputStream.run([ + 'function foo(x) { return x; }', + 'function koo() { console.log("abc"); }', + 'a = undefined;' + ]); + + const testCases = [{ + input: 'foo', + noPreview: '[Function: foo]', + preview: [ + 'foo', + '\x1B[90m[Function: foo]\x1B[39m\x1B[11G\x1B[1A\x1B[1B\x1B[2K\x1B[1A\r', + '\x1B[36m[Function: foo]\x1B[39m' + ] + }, { + input: 'koo', + noPreview: '[Function: koo]', + preview: [ + 'k\x1B[90moo\x1B[39m\x1B[9G\x1B[0Ko\x1B[90mo\x1B[39m\x1B[10G\x1B[0Ko', + '\x1B[90m[Function: koo]\x1B[39m\x1B[11G\x1B[1A\x1B[1B\x1B[2K\x1B[1A\r', + '\x1B[36m[Function: koo]\x1B[39m' + ] + }, { + input: 'a', + noPreview: 'repl > ', // No "undefined" output. + preview: ['a\r'] // No "undefined" preview. + }, { + input: " { b: 1 }['b'] === 1", + noPreview: '\x1B[33mtrue\x1B[39m', + preview: [ + " { b: 1 }['b']", + '\x1B[90m1\x1B[39m\x1B[22G\x1B[1A\x1B[1B\x1B[2K\x1B[1A ', + '\x1B[90m1\x1B[39m\x1B[23G\x1B[1A\x1B[1B\x1B[2K\x1B[1A=== 1', + '\x1B[90mtrue\x1B[39m\x1B[28G\x1B[1A\x1B[1B\x1B[2K\x1B[1A\r', + '\x1B[33mtrue\x1B[39m' + ] + }, { + input: "{ b: 1 }['b'] === 1;", + noPreview: '\x1B[33mfalse\x1B[39m', + preview: [ + "{ b: 1 }['b']", + '\x1B[90m1\x1B[39m\x1B[21G\x1B[1A\x1B[1B\x1B[2K\x1B[1A ', + '\x1B[90m1\x1B[39m\x1B[22G\x1B[1A\x1B[1B\x1B[2K\x1B[1A=== 1', + '\x1B[90mtrue\x1B[39m\x1B[27G\x1B[1A\x1B[1B\x1B[2K\x1B[1A;', + '\x1B[90mfalse\x1B[39m\x1B[28G\x1B[1A\x1B[1B\x1B[2K\x1B[1A\r', + '\x1B[33mfalse\x1B[39m' + ] + }, { + input: '{ a: true }', + noPreview: '{ a: \x1B[33mtrue\x1B[39m }', + preview: [ + '{ a: tru\x1B[90me\x1B[39m\x1B[16G\x1B[0Ke }\r', + '{ a: \x1B[33mtrue\x1B[39m }' + ] + }, { + input: '{ a: true };', + noPreview: '\x1B[33mtrue\x1B[39m', + preview: [ + '{ a: tru\x1B[90me\x1B[39m\x1B[16G\x1B[0Ke };', + '\x1B[90mtrue\x1B[39m\x1B[20G\x1B[1A\x1B[1B\x1B[2K\x1B[1A\r', + '\x1B[33mtrue\x1B[39m' + ] + }, { + input: ' \t { a: true};', + noPreview: '\x1B[33mtrue\x1B[39m', + preview: [ + ' { a: tru\x1B[90me\x1B[39m\x1B[18G\x1B[0Ke}', + '\x1B[90m{ a: true }\x1B[39m\x1B[20G\x1B[1A\x1B[1B\x1B[2K\x1B[1A;', + '\x1B[90mtrue\x1B[39m\x1B[21G\x1B[1A\x1B[1B\x1B[2K\x1B[1A\r', + '\x1B[33mtrue\x1B[39m' + ] + }, { + input: '1n + 2n', + noPreview: '\x1B[33m3n\x1B[39m', + preview: [ + '1n + 2', + '\x1B[90mType[39m\x1B[14G\x1B[1A\x1B[1B\x1B[2K\x1B[1An', + '\x1B[90m3n\x1B[39m\x1B[15G\x1B[1A\x1B[1B\x1B[2K\x1B[1A\r', + '\x1B[33m3n\x1B[39m' + ] + }, { + input: '{};1', + noPreview: '\x1B[33m1\x1B[39m', + preview: [ + '{};1', + '\x1B[90m1\x1B[39m\x1B[12G\x1B[1A\x1B[1B\x1B[2K\x1B[1A\r', + '\x1B[33m1\x1B[39m' + ] + }]; + + const hasPreview = repl.terminal && + (options.preview !== undefined ? !!options.preview : true); + + for (const { input, noPreview, preview } of testCases) { + console.log(`Testing ${input}`); + + const toBeRun = input.split('\n'); + let lines = await runAndWait(toBeRun, repl); + + if (hasPreview) { + // Remove error messages. That allows the code to run in different + // engines. + // eslint-disable-next-line no-control-regex + lines = lines.map((line) => line.replace(/Error: .+?\x1B/, '')); + assert.strictEqual(lines.pop(), '\x1B[1G\x1B[0Jrepl > \x1B[8G'); + assert.deepStrictEqual(lines, preview); + } else { + assert.ok(lines[0].includes(noPreview), lines.map(inspect)); + if (preview.length !== 1 || preview[0] !== `${input}\r`) + assert.strictEqual(lines.length, 2); + } + } +} + +tests({ terminal: false }); // No preview +tests({ terminal: true }); // Preview +tests({ terminal: false, preview: false }); // No preview +tests({ terminal: false, preview: true }); // No preview +tests({ terminal: true, preview: true }); // Preview diff --git a/test/parallel/test-repl-programmatic-history.js b/test/parallel/test-repl-programmatic-history.js index 7eda401a7c386b..5307ae0556ae74 100644 --- a/test/parallel/test-repl-programmatic-history.js +++ b/test/parallel/test-repl-programmatic-history.js @@ -8,6 +8,7 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); const os = require('os'); +const util = require('util'); const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); @@ -49,6 +50,7 @@ ActionStream.prototype.readable = true; // Mock keys const UP = { name: 'up' }; +const DOWN = { name: 'down' }; const ENTER = { name: 'enter' }; const CLEAR = { ctrl: true, name: 'u' }; @@ -88,20 +90,40 @@ const tests = [ }, { env: {}, - test: [UP, '\'42\'', ENTER], - expected: [prompt, '\'', '4', '2', '\'', '\'42\'\n', prompt, prompt], + test: [UP, '21', ENTER, "'42'", ENTER], + expected: [ + prompt, + // TODO(BridgeAR): The line is refreshed too many times. The double prompt + // is redundant and can be optimized away. + '2', '1', '21\n', prompt, prompt, + "'", '4', '2', "'", "'42'\n", prompt, prompt + ], clean: false }, { // Requires the above test case env: {}, - test: [UP, UP, ENTER], - expected: [prompt, `${prompt}'42'`, '\'42\'\n', prompt] + test: [UP, UP, UP, DOWN, ENTER], + expected: [ + prompt, + `${prompt}'42'`, + `${prompt}21`, + prompt, + `${prompt}21`, + '21\n', + prompt + ] }, { env: { NODE_REPL_HISTORY: historyPath, NODE_REPL_HISTORY_SIZE: 1 }, - test: [UP, UP, CLEAR], - expected: [prompt, `${prompt}'you look fabulous today'`, prompt] + test: [UP, UP, DOWN, CLEAR], + expected: [ + prompt, + `${prompt}'you look fabulous today'`, + prompt, + `${prompt}'you look fabulous today'`, + prompt + ] }, { env: { NODE_REPL_HISTORY: historyPathFail, @@ -167,6 +189,8 @@ function runTest(assertCleaned) { const opts = tests.shift(); if (!opts) return; // All done + console.log('NEW'); + if (assertCleaned) { try { assert.strictEqual(fs.readFileSync(defaultHistoryPath, 'utf8'), ''); @@ -192,6 +216,7 @@ function runTest(assertCleaned) { output: new stream.Writable({ write(chunk, _, next) { const output = chunk.toString(); + console.log('INPUT', util.inspect(output)); // Ignore escapes and blank lines if (output.charCodeAt(0) === 27 || /^[\r\n]+$/.test(output)) diff --git a/test/parallel/test-repl-reverse-search.js b/test/parallel/test-repl-reverse-search.js new file mode 100644 index 00000000000000..e507dc285fa3a3 --- /dev/null +++ b/test/parallel/test-repl-reverse-search.js @@ -0,0 +1,363 @@ +'use strict'; + +// Flags: --expose-internals + +const common = require('../common'); +const stream = require('stream'); +const REPL = require('internal/repl'); +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); +const { inspect } = require('util'); + +common.allowGlobals('aaaa'); + +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); + +const defaultHistoryPath = path.join(tmpdir.path, '.node_repl_history'); + +// Create an input stream specialized for testing an array of actions +class ActionStream extends stream.Stream { + run(data) { + const _iter = data[Symbol.iterator](); + const doAction = () => { + const next = _iter.next(); + if (next.done) { + // Close the repl. Note that it must have a clean prompt to do so. + this.emit('keypress', '', { ctrl: true, name: 'd' }); + return; + } + const action = next.value; + + if (typeof action === 'object') { + this.emit('keypress', '', action); + } else { + this.emit('data', `${action}`); + } + setImmediate(doAction); + }; + doAction(); + } + resume() {} + pause() {} +} +ActionStream.prototype.readable = true; + +// Mock keys +const ENTER = { name: 'enter' }; +const UP = { name: 'up' }; +const DOWN = { name: 'down' }; +const BACKSPACE = { name: 'backspace' }; +const SEARCH_BACKWARDS = { name: 'r', ctrl: true }; +const SEARCH_FORWARDS = { name: 's', ctrl: true }; +const ESCAPE = { name: 'escape' }; +const CTRL_C = { name: 'c', ctrl: true }; +const DELETE_WORD_LEFT = { name: 'w', ctrl: true }; + +const prompt = '> '; + +// TODO(BridgeAR): Add tests for lines that exceed the maximum columns. +const tests = [ + { // Creates few history to navigate for + env: { NODE_REPL_HISTORY: defaultHistoryPath }, + test: [ + 'console.log("foo")', ENTER, + 'ab = "aaaa"', ENTER, + 'repl.repl.historyIndex', ENTER, + 'console.log("foo")', ENTER, + 'let ba = 9', ENTER, + 'ab = "aaaa"', ENTER, + '555 - 909', ENTER, + '{key : {key2 :[] }}', ENTER, + 'Array(100).fill(1)', ENTER + ], + expected: [], + clean: false + }, + { + env: { NODE_REPL_HISTORY: defaultHistoryPath }, + showEscapeCodes: true, + checkTotal: true, + useColors: true, + test: [ + '7', // 1 + SEARCH_FORWARDS, + SEARCH_FORWARDS, // 3 + 'a', + SEARCH_BACKWARDS, // 5 + SEARCH_FORWARDS, + SEARCH_BACKWARDS, // 7 + 'a', + BACKSPACE, // 9 + DELETE_WORD_LEFT, + 'aa', // 11 + SEARCH_BACKWARDS, + SEARCH_BACKWARDS, // 13 + SEARCH_BACKWARDS, + SEARCH_BACKWARDS, // 15 + SEARCH_FORWARDS, + ESCAPE, // 17 + ENTER + ], + // A = Cursor n up + // B = Cursor n down + // C = Cursor n forward + // D = Cursor n back + // G = Cursor to column n + // J = Erase in screen; 0 = right; 1 = left; 2 = total + // K = Erase in line; 0 = right; 1 = left; 2 = total + expected: [ + // 0. Start + '\x1B[1G', '\x1B[0J', + prompt, '\x1B[3G', + // 1. '7' + '7', + // 2. SEARCH FORWARDS + '\nfwd-i-search: _', '\x1B[1A', '\x1B[4G', + // 3. SEARCH FORWARDS + '\x1B[3G', '\x1B[0J', + '7\nfwd-i-search: _', '\x1B[1A', '\x1B[4G', + // 4. 'a' + '\x1B[3G', '\x1B[0J', + '7\nfailed-fwd-i-search: a_', '\x1B[1A', '\x1B[4G', + // 5. SEARCH BACKWARDS + '\x1B[3G', '\x1B[0J', + 'Arr\x1B[4ma\x1B[24my(100).fill(1)\nbck-i-search: a_', + '\x1B[1A', '\x1B[6G', + // 6. SEARCH FORWARDS + '\x1B[3G', '\x1B[0J', + '7\nfailed-fwd-i-search: a_', '\x1B[1A', '\x1B[4G', + // 7. SEARCH BACKWARDS + '\x1B[3G', '\x1B[0J', + 'Arr\x1B[4ma\x1B[24my(100).fill(1)\nbck-i-search: a_', + '\x1B[1A', '\x1B[6G', + // 8. 'a' + '\x1B[3G', '\x1B[0J', + 'ab = "aa\x1B[4maa\x1B[24m"\nbck-i-search: aa_', + '\x1B[1A', '\x1B[11G', + // 9. BACKSPACE + '\x1B[3G', '\x1B[0J', + 'Arr\x1B[4ma\x1B[24my(100).fill(1)\nbck-i-search: a_', + '\x1B[1A', '\x1B[6G', + // 10. DELETE WORD LEFT (works as backspace) + '\x1B[3G', '\x1B[0J', + '7\nbck-i-search: _', '\x1B[1A', '\x1B[4G', + // 11. 'a' + '\x1B[3G', '\x1B[0J', + 'Arr\x1B[4ma\x1B[24my(100).fill(1)\nbck-i-search: a_', + '\x1B[1A', '\x1B[6G', + // 11. 'aa' - continued + '\x1B[3G', '\x1B[0J', + 'ab = "aa\x1B[4maa\x1B[24m"\nbck-i-search: aa_', + '\x1B[1A', '\x1B[11G', + // 12. SEARCH BACKWARDS + '\x1B[3G', '\x1B[0J', + 'ab = "a\x1B[4maa\x1B[24ma"\nbck-i-search: aa_', + '\x1B[1A', '\x1B[10G', + // 13. SEARCH BACKWARDS + '\x1B[3G', '\x1B[0J', + 'ab = "\x1B[4maa\x1B[24maa"\nbck-i-search: aa_', + '\x1B[1A', '\x1B[9G', + // 14. SEARCH BACKWARDS + '\x1B[3G', '\x1B[0J', + '7\nfailed-bck-i-search: aa_', '\x1B[1A', '\x1B[4G', + // 15. SEARCH BACKWARDS + '\x1B[3G', '\x1B[0J', + '7\nfailed-bck-i-search: aa_', '\x1B[1A', '\x1B[4G', + // 16. SEARCH FORWARDS + '\x1B[3G', '\x1B[0J', + 'ab = "\x1B[4maa\x1B[24maa"\nfwd-i-search: aa_', + '\x1B[1A', '\x1B[9G', + // 17. ESCAPE + '\x1B[3G', '\x1B[0J', + '7', + // 18. ENTER + '\r\n', + '\x1B[33m7\x1B[39m\n', + '\x1B[1G', '\x1B[0J', + prompt, + '\x1B[3G', + '\r\n' + ], + clean: false + }, + { + env: { NODE_REPL_HISTORY: defaultHistoryPath }, + showEscapeCodes: true, + skip: !process.features.inspector, + checkTotal: true, + useColors: false, + test: [ + 'fu', // 1 + SEARCH_BACKWARDS, + '}', // 3 + SEARCH_BACKWARDS, + CTRL_C, // 5 + CTRL_C, + '1+1', // 7 + ENTER, + SEARCH_BACKWARDS, // 9 + '+', + '\r', // 11 + '2', + SEARCH_BACKWARDS, // 13 + 're', + UP, // 15 + DOWN, + SEARCH_FORWARDS, // 17 + '\n' + ], + expected: [ + '\x1B[1G', '\x1B[0J', + prompt, '\x1B[3G', + 'f', 'u', ' // nction', + '\x1B[5G', '\x1B[0K', + '\nbck-i-search: _', '\x1B[1A', '\x1B[5G', + '\x1B[3G', '\x1B[0J', + '{key : {key2 :[] }}\nbck-i-search: }_', '\x1B[1A', '\x1B[21G', + '\x1B[3G', '\x1B[0J', + '{key : {key2 :[] }}\nbck-i-search: }_', '\x1B[1A', '\x1B[20G', + '\x1B[3G', '\x1B[0J', + 'fu', + '\r\n', + '\x1B[1G', '\x1B[0J', + prompt, '\x1B[3G', + '1', '+', '1', '\n// 2', '\x1B[6G', '\x1B[1A', + '\x1B[1B', '\x1B[2K', '\x1B[1A', + '\r\n', + '2\n', + '\x1B[1G', '\x1B[0J', + prompt, '\x1B[3G', + '\nbck-i-search: _', '\x1B[1A', + '\x1B[3G', '\x1B[0J', + '1+1\nbck-i-search: +_', '\x1B[1A', '\x1B[4G', + '\x1B[3G', '\x1B[0J', + '1+1', '\x1B[4G', + '\x1B[2C', + '\r\n', + '2\n', + '\x1B[1G', '\x1B[0J', + prompt, '\x1B[3G', + '2', '\n// 2', '\x1B[4G', '\x1B[1A', + '\x1B[1B', '\x1B[2K', '\x1B[1A', + '\nbck-i-search: _', '\x1B[1A', '\x1B[4G', + '\x1B[3G', '\x1B[0J', + 'Array(100).fill(1)\nbck-i-search: r_', '\x1B[1A', '\x1B[5G', + '\x1B[3G', '\x1B[0J', + 'repl.repl.historyIndex\nbck-i-search: re_', '\x1B[1A', '\x1B[8G', + '\x1B[3G', '\x1B[0J', + 'repl.repl.historyIndex', '\x1B[8G', + '\x1B[1G', '\x1B[0J', + `${prompt}ab = "aaaa"`, '\x1B[14G', + '\x1B[1G', '\x1B[0J', + `${prompt}repl.repl.historyIndex`, '\x1B[25G', '\n// -1', + '\x1B[25G', '\x1B[1A', + '\x1B[1B', '\x1B[2K', '\x1B[1A', + '\nfwd-i-search: _', '\x1B[1A', '\x1B[25G', + '\x1B[3G', '\x1B[0J', + 'repl.repl.historyIndex', + '\r\n', + '-1\n', + '\x1B[1G', '\x1B[0J', + prompt, '\x1B[3G', + '\r\n' + ], + clean: false + } +]; +const numtests = tests.length; + +const runTestWrap = common.mustCall(runTest, numtests); + +function cleanupTmpFile() { + try { + // Write over the file, clearing any history + fs.writeFileSync(defaultHistoryPath, ''); + } catch (err) { + if (err.code === 'ENOENT') return true; + throw err; + } + return true; +} + +function runTest() { + const opts = tests.shift(); + if (!opts) return; // All done + + const { expected, skip } = opts; + + // Test unsupported on platform. + if (skip) { + setImmediate(runTestWrap, true); + return; + } + + const lastChunks = []; + let i = 0; + + REPL.createInternalRepl(opts.env, { + input: new ActionStream(), + output: new stream.Writable({ + write(chunk, _, next) { + const output = chunk.toString(); + + if (!opts.showEscapeCodes && + (output[0] === '\x1B' || /^[\r\n]+$/.test(output))) { + return next(); + } + + lastChunks.push(output); + + if (expected.length && !opts.checkTotal) { + try { + assert.strictEqual(output, expected[i]); + } catch (e) { + console.error(`Failed test # ${numtests - tests.length}`); + console.error('Last outputs: ' + inspect(lastChunks, { + breakLength: 5, colors: true + })); + throw e; + } + i++; + } + + next(); + } + }), + completer: opts.completer, + prompt, + useColors: opts.useColors || false, + terminal: true + }, function(err, repl) { + if (err) { + console.error(`Failed test # ${numtests - tests.length}`); + throw err; + } + + repl.once('close', () => { + if (opts.clean) + cleanupTmpFile(); + + if (opts.checkTotal) { + assert.deepStrictEqual(lastChunks, expected); + } else if (expected.length !== i) { + console.error(tests[numtests - tests.length - 1]); + throw new Error(`Failed test # ${numtests - tests.length}`); + } + + setImmediate(runTestWrap, true); + }); + + if (opts.columns) { + Object.defineProperty(repl, 'columns', { + value: opts.columns, + enumerable: true + }); + } + repl.inputStream.run(opts.test); + }); +} + +// run the tests +runTest(); diff --git a/test/parallel/test-repl-save-load.js b/test/parallel/test-repl-save-load.js index ef9ff8f6498877..f6ecc8d4ab67e9 100644 --- a/test/parallel/test-repl-save-load.js +++ b/test/parallel/test-repl-save-load.js @@ -44,8 +44,9 @@ testMe._domain.on('error', function(reason) { }); const testFile = [ - 'let top = function() {', - 'let inner = {one:1};' + 'let inner = (function() {', + ' return {one:1};', + '})()' ]; const saveFileName = join(tmpdir.path, 'test.save.js'); diff --git a/test/parallel/test-repl-tab-complete-nested-repls.js b/test/parallel/test-repl-tab-complete-nested-repls.js index 36547e8d9fb5be..3cac02f20562bc 100644 --- a/test/parallel/test-repl-tab-complete-nested-repls.js +++ b/test/parallel/test-repl-tab-complete-nested-repls.js @@ -19,3 +19,5 @@ const result = spawnSync(process.execPath, [testFile]); // test here is to make sure that the error information bubbles up to the // calling process. assert.ok(result.status, 'testFile swallowed its error'); +const err = result.stderr.toString(); +assert.ok(err.includes('fhqwhgads'), err); diff --git a/test/parallel/test-repl-tab-complete.js b/test/parallel/test-repl-tab-complete.js index 1c66f9a3238230..6cf689c4b11074 100644 --- a/test/parallel/test-repl-tab-complete.js +++ b/test/parallel/test-repl-tab-complete.js @@ -54,12 +54,9 @@ const putIn = new ArrayStream(); const testMe = repl.start('', putIn); // Some errors are passed to the domain, but do not callback -testMe._domain.on('error', function(err) { - assert.ifError(err); -}); +testMe._domain.on('error', assert.ifError); // Tab Complete will not break in an object literal -putIn.run(['.clear']); putIn.run([ 'var inner = {', 'one:1' @@ -93,9 +90,7 @@ putIn.run([ 'var top = function() {', 'var inner = {one:1};' ]); -testMe.complete('inner.o', common.mustCall(function(error, data) { - assert.deepStrictEqual(data, works); -})); +testMe.complete('inner.o', getNoResultsFunction()); // When you close the function scope tab complete will not return the // locally scoped variable @@ -111,9 +106,7 @@ putIn.run([ ' one:1', '};' ]); -testMe.complete('inner.o', common.mustCall(function(error, data) { - assert.deepStrictEqual(data, works); -})); +testMe.complete('inner.o', getNoResultsFunction()); putIn.run(['.clear']); @@ -125,9 +118,7 @@ putIn.run([ ' one:1', '};' ]); -testMe.complete('inner.o', common.mustCall(function(error, data) { - assert.deepStrictEqual(data, works); -})); +testMe.complete('inner.o', getNoResultsFunction()); putIn.run(['.clear']); @@ -140,9 +131,7 @@ putIn.run([ ' one:1', '};' ]); -testMe.complete('inner.o', common.mustCall(function(error, data) { - assert.deepStrictEqual(data, works); -})); +testMe.complete('inner.o', getNoResultsFunction()); putIn.run(['.clear']); @@ -155,9 +144,7 @@ putIn.run([ ' one:1', '};' ]); -testMe.complete('inner.o', common.mustCall(function(error, data) { - assert.deepStrictEqual(data, works); -})); +testMe.complete('inner.o', getNoResultsFunction()); putIn.run(['.clear']); @@ -204,7 +191,9 @@ const spaceTimeout = setTimeout(function() { }, 1000); testMe.complete(' ', common.mustCall(function(error, data) { - assert.deepStrictEqual(data, [[], undefined]); + assert.ifError(error); + assert.strictEqual(data[1], ''); + assert.ok(data[0].includes('globalThis')); clearTimeout(spaceTimeout); })); diff --git a/test/parallel/test-repl-top-level-await.js b/test/parallel/test-repl-top-level-await.js index 5c8aa95d40ec05..48e9e37605a085 100644 --- a/test/parallel/test-repl-top-level-await.js +++ b/test/parallel/test-repl-top-level-await.js @@ -1,11 +1,13 @@ 'use strict'; -require('../common'); +const common = require('../common'); const ArrayStream = require('../common/arraystream'); const assert = require('assert'); -const { stripVTControlCharacters } = require('internal/readline/utils'); +const { stripVTControlCharacters } = require('internal/util/inspect'); const repl = require('repl'); +common.skipIfInspectorDisabled(); + // Flags: --expose-internals --experimental-repl-await const PROMPT = 'await repl > '; @@ -30,7 +32,7 @@ class REPLStream extends ArrayStream { return true; } - wait(lookFor = PROMPT) { + wait() { if (this.waitingForResponse) { throw new Error('Currently waiting for response to another command'); } @@ -41,7 +43,7 @@ class REPLStream extends ArrayStream { reject(err); }; const onLine = () => { - if (this.lines[this.lines.length - 1].includes(lookFor)) { + if (this.lines[this.lines.length - 1].includes(PROMPT)) { this.removeListener('error', onError); this.removeListener('line', onLine); resolve(this.lines); @@ -58,12 +60,12 @@ const testMe = repl.start({ prompt: PROMPT, stream: putIn, terminal: true, - useColors: false, + useColors: true, breakEvalOnSigint: true }); -function runAndWait(cmds, lookFor) { - const promise = putIn.wait(lookFor); +function runAndWait(cmds) { + const promise = putIn.wait(); for (const cmd of cmds) { if (typeof cmd === 'string') { putIn.run([cmd]); @@ -82,63 +84,77 @@ async function ordinaryTests() { 'function koo() { return Promise.resolve(4); }' ]); const testCases = [ - [ 'await Promise.resolve(0)', '0' ], - [ '{ a: await Promise.resolve(1) }', '{ a: 1 }' ], - [ '_', '{ a: 1 }' ], - [ 'let { a, b } = await Promise.resolve({ a: 1, b: 2 }), f = 5;', - 'undefined' ], - [ 'a', '1' ], - [ 'b', '2' ], - [ 'f', '5' ], - [ 'let c = await Promise.resolve(2)', 'undefined' ], - [ 'c', '2' ], - [ 'let d;', 'undefined' ], - [ 'd', 'undefined' ], - [ 'let [i, { abc: { k } }] = [0, { abc: { k: 1 } }];', 'undefined' ], - [ 'i', '0' ], - [ 'k', '1' ], - [ 'var l = await Promise.resolve(2);', 'undefined' ], - [ 'l', '2' ], - [ 'foo(await koo())', '4' ], - [ '_', '4' ], - [ 'const m = foo(await koo());', 'undefined' ], - [ 'm', '4' ], - [ 'const n = foo(await\nkoo());', 'undefined' ], - [ 'n', '4' ], + ['await Promise.resolve(0)', '0'], + ['{ a: await Promise.resolve(1) }', '{ a: 1 }'], + ['_', '{ a: 1 }'], + ['let { aa, bb } = await Promise.resolve({ aa: 1, bb: 2 }), f = 5;'], + ['aa', '1'], + ['bb', '2'], + ['f', '5'], + ['let cc = await Promise.resolve(2)'], + ['cc', '2'], + ['let dd;'], + ['dd'], + ['let [ii, { abc: { kk } }] = [0, { abc: { kk: 1 } }];'], + ['ii', '0'], + ['kk', '1'], + ['var ll = await Promise.resolve(2);'], + ['ll', '2'], + ['foo(await koo())', '4'], + ['_', '4'], + ['const m = foo(await koo());'], + ['m', '4'], + ['const n = foo(await\nkoo());', + ['const n = foo(await\r', '... koo());\r', 'undefined']], + ['n', '4'], // eslint-disable-next-line no-template-curly-in-string - [ '`status: ${(await Promise.resolve({ status: 200 })).status}`', - "'status: 200'"], - [ 'for (let i = 0; i < 2; ++i) await i', 'undefined' ], - [ 'for (let i = 0; i < 2; ++i) { await i }', 'undefined' ], - [ 'await 0', '0' ], - [ 'await 0; function foo() {}', 'undefined' ], - [ 'foo', '[Function: foo]' ], - [ 'class Foo {}; await 1;', '1' ], - [ 'Foo', '[Function: Foo]' ], - [ 'if (await true) { function bar() {}; }', 'undefined' ], - [ 'bar', '[Function: bar]' ], - [ 'if (await true) { class Bar {}; }', 'undefined' ], - [ 'Bar', 'Uncaught ReferenceError: Bar is not defined' ], - [ 'await 0; function* gen(){}', 'undefined' ], - [ 'for (var i = 0; i < 10; ++i) { await i; }', 'undefined' ], - [ 'i', '10' ], - [ 'for (let j = 0; j < 5; ++j) { await j; }', 'undefined' ], - [ 'j', 'Uncaught ReferenceError: j is not defined' ], - [ 'gen', '[GeneratorFunction: gen]' ], - [ 'return 42; await 5;', 'Uncaught SyntaxError: Illegal return statement', - { line: 3 } ], - [ 'let o = await 1, p', 'undefined' ], - [ 'p', 'undefined' ], - [ 'let q = 1, s = await 2', 'undefined' ], - [ 's', '2' ], - [ 'for await (let i of [1,2,3]) console.log(i)', 'undefined', { line: 3 } ] + ['`status: ${(await Promise.resolve({ status: 200 })).status}`', + "'status: 200'"], + ['for (let i = 0; i < 2; ++i) await i'], + ['for (let i = 0; i < 2; ++i) { await i }'], + ['await 0', '0'], + ['await 0; function foo() {}'], + ['foo', '[Function: foo]'], + ['class Foo {}; await 1;', '1'], + ['Foo', '[Function: Foo]'], + ['if (await true) { function bar() {}; }'], + ['bar', '[Function: bar]'], + ['if (await true) { class Bar {}; }'], + ['Bar', 'Uncaught ReferenceError: Bar is not defined'], + ['await 0; function* gen(){}'], + ['for (var i = 0; i < 10; ++i) { await i; }'], + ['i', '10'], + ['for (let j = 0; j < 5; ++j) { await j; }'], + ['j', 'Uncaught ReferenceError: j is not defined', { line: 0 }], + ['gen', '[GeneratorFunction: gen]'], + ['return 42; await 5;', 'Uncaught SyntaxError: Illegal return statement', + { line: 3 }], + ['let o = await 1, p'], + ['p'], + ['let q = 1, s = await 2'], + ['s', '2'], + ['for await (let i of [1,2,3]) console.log(i)', + [ + 'for await (let i of [1,2,3]) console.log(i)\r', + '1', + '2', + '3', + 'undefined' + ] + ] ]; - for (const [input, expected, options = {}] of testCases) { + for (const [input, expected = [`${input}\r`], options = {}] of testCases) { console.log(`Testing ${input}`); const toBeRun = input.split('\n'); const lines = await runAndWait(toBeRun); - if ('line' in options) { + if (Array.isArray(expected)) { + if (expected.length === 1) + expected.push('undefined'); + if (lines[0] === input) + lines.shift(); + assert.deepStrictEqual(lines, [...expected, PROMPT]); + } else if ('line' in options) { assert.strictEqual(lines[toBeRun.length + options.line], expected); } else { const echoed = toBeRun.map((a, i) => `${i > 0 ? '... ' : ''}${a}\r`); diff --git a/test/parallel/test-repl.js b/test/parallel/test-repl.js index b8498db4b9041a..9b8578293d9e52 100644 --- a/test/parallel/test-repl.js +++ b/test/parallel/test-repl.js @@ -457,6 +457,28 @@ const errorTests = [ /'thefourtheye'/ ] }, + // Check for wrapped objects. + { + send: '{ a: 1 }.a', // ({ a: 1 }.a); + expect: '1' + }, + { + send: '{ a: 1 }.a;', // { a: 1 }.a; + expect: [ + kSource, + kArrow, + '', + /^Uncaught SyntaxError: / + ] + }, + { + send: '{ a: 1 }["a"] === 1', // ({ a: 1 }['a'] === 1); + expect: 'true' + }, + { + send: '{ a: 1 }["a"] === 1;', // { a: 1 }; ['a'] === 1; + expect: 'false' + }, // Empty lines in the REPL should be allowed { send: '\n\r\n\r\n', @@ -538,7 +560,7 @@ const errorTests = [ expect: '... ... ... undefined' }, // REPL should get a normal require() function, not one that allows - // access to internal modules without the --expose_internals flag. + // access to internal modules without the --expose-internals flag. { send: 'require("internal/repl")', expect: [ diff --git a/test/parallel/test-safe-get-env.js b/test/parallel/test-safe-get-env.js index 0bee9971dbb3eb..f57dcb566d672d 100644 --- a/test/parallel/test-safe-get-env.js +++ b/test/parallel/test-safe-get-env.js @@ -1,5 +1,5 @@ 'use strict'; -// Flags: --expose_internals +// Flags: --expose-internals require('../common'); const assert = require('assert'); diff --git a/test/parallel/test-source-map-api.js b/test/parallel/test-source-map-api.js new file mode 100644 index 00000000000000..60bbb661e1c801 --- /dev/null +++ b/test/parallel/test-source-map-api.js @@ -0,0 +1,151 @@ +// Flags: --enable-source-maps +'use strict'; + +require('../common'); +const assert = require('assert'); +const { findSourceMap, SourceMap } = require('module'); +const { readFileSync } = require('fs'); + +// findSourceMap() can lookup source-maps based on URIs, in the +// non-exceptional case. +{ + require('../fixtures/source-map/disk-relative-path.js'); + const sourceMap = findSourceMap( + require.resolve('../fixtures/source-map/disk-relative-path.js') + ); + const { + originalLine, + originalColumn, + originalSource + } = sourceMap.findEntry(0, 29); + assert.strictEqual(originalLine, 2); + assert.strictEqual(originalColumn, 4); + assert(originalSource.endsWith('disk.js')); +} + +// findSourceMap() can be used in Error.prepareStackTrace() to lookup +// source-map attached to error. +{ + let callSite; + let sourceMap; + Error.prepareStackTrace = (error, trace) => { + const throwingRequireCallSite = trace[0]; + if (throwingRequireCallSite.getFileName().endsWith('typescript-throw.js')) { + sourceMap = findSourceMap(throwingRequireCallSite.getFileName(), error); + callSite = throwingRequireCallSite; + } + }; + try { + // Require a file that throws an exception, and has a source map. + require('../fixtures/source-map/typescript-throw.js'); + } catch (err) { + err.stack; // Force prepareStackTrace() to be called. + } + assert(callSite); + assert(sourceMap); + const { + generatedLine, + generatedColumn, + originalLine, + originalColumn, + originalSource + } = sourceMap.findEntry( + callSite.getLineNumber() - 1, + callSite.getColumnNumber() - 1 + ); + + assert.strictEqual(generatedLine, 19); + assert.strictEqual(generatedColumn, 14); + + assert.strictEqual(originalLine, 17); + assert.strictEqual(originalColumn, 10); + assert(originalSource.endsWith('typescript-throw.ts')); +} + +// SourceMap can be instantiated with Source Map V3 object as payload. +{ + const payload = JSON.parse(readFileSync( + require.resolve('../fixtures/source-map/disk.map'), 'utf8' + )); + const sourceMap = new SourceMap(payload); + const { + originalLine, + originalColumn, + originalSource + } = sourceMap.findEntry(0, 29); + assert.strictEqual(originalLine, 2); + assert.strictEqual(originalColumn, 4); + assert(originalSource.endsWith('disk.js')); + // The stored payload should be a clone: + assert.strictEqual(payload.mappings, sourceMap.payload.mappings); + assert.notStrictEqual(payload, sourceMap.payload); + assert.strictEqual(payload.sources[0], sourceMap.payload.sources[0]); + assert.notStrictEqual(payload.sources, sourceMap.payload.sources); +} + +// Test various known decodings to ensure decodeVLQ works correctly. +{ + function makeMinimalMap(column) { + return { + sources: ['test.js'], + // Mapping from the 0th line, 0th column of the output file to the 0th + // source file, 0th line, ${column}th column. + mappings: `AAA${column}`, + }; + } + const knownDecodings = { + 'A': 0, + 'B': -2147483648, + 'C': 1, + 'D': -1, + 'E': 2, + 'F': -2, + + // 2^31 - 1, maximum values + '+/////D': 2147483647, + '8/////D': 2147483646, + '6/////D': 2147483645, + '4/////D': 2147483644, + '2/////D': 2147483643, + '0/////D': 2147483642, + + // -2^31 + 1, minimum values + '//////D': -2147483647, + '9/////D': -2147483646, + '7/////D': -2147483645, + '5/////D': -2147483644, + '3/////D': -2147483643, + '1/////D': -2147483642, + }; + + for (const column in knownDecodings) { + const sourceMap = new SourceMap(makeMinimalMap(column)); + const { originalColumn } = sourceMap.findEntry(0, 0); + assert.strictEqual(originalColumn, knownDecodings[column]); + } +} + +// Test that generated columns are sorted when a negative offset is +// observed, see: https://github.com/mozilla/source-map/pull/92 +{ + function makeMinimalMap(generatedColumns, originalColumns) { + return { + sources: ['test.js'], + // Mapping from the 0th line, ${g}th column of the output file to the 0th + // source file, 0th line, ${column}th column. + mappings: generatedColumns.map((g, i) => `${g}AA${originalColumns[i]}`) + .join(',') + }; + } + // U = 10 + // F = -2 + // A = 0 + // E = 2 + const sourceMap = new SourceMap(makeMinimalMap( + ['U', 'F', 'F'], + ['A', 'E', 'E'] + )); + assert.strictEqual(sourceMap.findEntry(0, 6).originalColumn, 4); + assert.strictEqual(sourceMap.findEntry(0, 8).originalColumn, 2); + assert.strictEqual(sourceMap.findEntry(0, 10).originalColumn, 0); +} diff --git a/test/parallel/test-source-map.js b/test/parallel/test-source-map-enable.js similarity index 99% rename from test/parallel/test-source-map.js rename to test/parallel/test-source-map-enable.js index ec2241f985281d..71130441438dcc 100644 --- a/test/parallel/test-source-map.js +++ b/test/parallel/test-source-map-enable.js @@ -66,7 +66,6 @@ function nextdir() { const coverageDirectory = nextdir(); const output = spawnSync(process.execPath, [ '--no-warnings', - '--experimental-modules', require.resolve('../fixtures/source-map/esm-basic.mjs') ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); assert.strictEqual(output.stderr.toString(), ''); @@ -217,7 +216,6 @@ function nextdir() { { const output = spawnSync(process.execPath, [ '--enable-source-maps', - '--experimental-modules', require.resolve('../fixtures/source-map/babel-esm.mjs') ]); assert.ok( diff --git a/test/parallel/test-startup-large-pages.js b/test/parallel/test-startup-large-pages.js new file mode 100644 index 00000000000000..ed0542b6c6dc68 --- /dev/null +++ b/test/parallel/test-startup-large-pages.js @@ -0,0 +1,30 @@ +'use strict'; + +// Make sure that Node.js runs correctly with the --use-largepages option. + +require('../common'); +const assert = require('assert'); +const { spawnSync } = require('child_process'); + +{ + const child = spawnSync(process.execPath, + [ '--use-largepages=on', '-p', '42' ], + { stdio: ['inherit', 'pipe', 'inherit'] }); + const stdout = child.stdout.toString().match(/\S+/g); + assert.strictEqual(child.status, 0); + assert.strictEqual(child.signal, null); + assert.strictEqual(stdout.length, 1); + assert.strictEqual(stdout[0], '42'); +} + +{ + const child = spawnSync(process.execPath, + [ '--use-largepages=xyzzy', '-p', '42' ]); + assert.strictEqual(child.status, 9); + assert.strictEqual(child.signal, null); + assert.strictEqual(child.stderr.toString().match(/\S+/g).slice(1).join(' '), + 'invalid value for --use-largepages'); +} + +// TODO(gabrielschulhof): Make assertions about the stderr, which may or may not +// contain a message indicating that mapping to large pages has failed. diff --git a/test/parallel/test-stream-await-drain-writers-in-synchronously-recursion-write.js b/test/parallel/test-stream-await-drain-writers-in-synchronously-recursion-write.js new file mode 100644 index 00000000000000..110d46bb9f23cc --- /dev/null +++ b/test/parallel/test-stream-await-drain-writers-in-synchronously-recursion-write.js @@ -0,0 +1,28 @@ +'use strict'; +const common = require('../common'); +const { PassThrough } = require('stream'); + +const encode = new PassThrough({ + highWaterMark: 1 +}); + +const decode = new PassThrough({ + highWaterMark: 1 +}); + +const send = common.mustCall((buf) => { + encode.write(buf); +}, 4); + +let i = 0; +const onData = common.mustCall(() => { + if (++i === 2) { + send(Buffer.from([0x3])); + send(Buffer.from([0x4])); + } +}, 4); + +encode.pipe(decode).on('data', onData); + +send(Buffer.from([0x1])); +send(Buffer.from([0x2])); diff --git a/test/parallel/test-stream-buffer-list.js b/test/parallel/test-stream-buffer-list.js index c78efeea24bf6b..5b495a41e08545 100644 --- a/test/parallel/test-stream-buffer-list.js +++ b/test/parallel/test-stream-buffer-list.js @@ -1,4 +1,4 @@ -// Flags: --expose_internals +// Flags: --expose-internals 'use strict'; require('../common'); const assert = require('assert'); diff --git a/test/parallel/test-stream-pipe-await-drain-manual-resume.js b/test/parallel/test-stream-pipe-await-drain-manual-resume.js index 37acead9969443..a95a5e05aea9ef 100644 --- a/test/parallel/test-stream-pipe-await-drain-manual-resume.js +++ b/test/parallel/test-stream-pipe-await-drain-manual-resume.js @@ -28,10 +28,10 @@ readable.pipe(writable); readable.once('pause', common.mustCall(() => { assert.strictEqual( - readable._readableState.awaitDrain, - 1, - 'Expected awaitDrain to equal 1 but instead got ' + - `${readable._readableState.awaitDrain}` + readable._readableState.awaitDrainWriters, + writable, + 'Expected awaitDrainWriters to be a Writable but instead got ' + + `${readable._readableState.awaitDrainWriters}` ); // First pause, resume manually. The next write() to writable will still // return false, because chunks are still being buffered, so it will increase @@ -43,10 +43,10 @@ readable.once('pause', common.mustCall(() => { readable.once('pause', common.mustCall(() => { assert.strictEqual( - readable._readableState.awaitDrain, - 1, - '.resume() should not reset the counter but instead got ' + - `${readable._readableState.awaitDrain}` + readable._readableState.awaitDrainWriters, + writable, + '.resume() should not reset the awaitDrainWriters, but instead got ' + + `${readable._readableState.awaitDrainWriters}` ); // Second pause, handle all chunks from now on. Once all callbacks that // are currently queued up are handled, the awaitDrain drain counter should @@ -65,10 +65,11 @@ readable.push(null); writable.on('finish', common.mustCall(() => { assert.strictEqual( - readable._readableState.awaitDrain, - 0, - 'awaitDrain should equal 0 after all chunks are written but instead got' + - `${readable._readableState.awaitDrain}` + readable._readableState.awaitDrainWriters, + null, + `awaitDrainWriters should be reset to null + after all chunks are written but instead got + ${readable._readableState.awaitDrainWriters}` ); // Everything okay, all chunks were written. })); diff --git a/test/parallel/test-stream-pipe-await-drain-push-while-write.js b/test/parallel/test-stream-pipe-await-drain-push-while-write.js index d14ad46cb066ec..6dbf3c669bc177 100644 --- a/test/parallel/test-stream-pipe-await-drain-push-while-write.js +++ b/test/parallel/test-stream-pipe-await-drain-push-while-write.js @@ -6,8 +6,8 @@ const assert = require('assert'); const writable = new stream.Writable({ write: common.mustCall(function(chunk, encoding, cb) { assert.strictEqual( - readable._readableState.awaitDrain, - 0 + readable._readableState.awaitDrainWriters, + null, ); if (chunk.length === 32 * 1024) { // first chunk @@ -15,7 +15,7 @@ const writable = new stream.Writable({ // We should check if awaitDrain counter is increased in the next // tick, because awaitDrain is incremented after this method finished process.nextTick(() => { - assert.strictEqual(readable._readableState.awaitDrain, 1); + assert.strictEqual(readable._readableState.awaitDrainWriters, writable); }); } diff --git a/test/parallel/test-stream-pipe-await-drain.js b/test/parallel/test-stream-pipe-await-drain.js index 9286ceb791ce5f..3ae248e08b854f 100644 --- a/test/parallel/test-stream-pipe-await-drain.js +++ b/test/parallel/test-stream-pipe-await-drain.js @@ -24,10 +24,10 @@ writer1._write = common.mustCall(function(chunk, encoding, cb) { writer1.once('chunk-received', () => { assert.strictEqual( - reader._readableState.awaitDrain, + reader._readableState.awaitDrainWriters.size, 0, 'awaitDrain initial value should be 0, actual is ' + - reader._readableState.awaitDrain + reader._readableState.awaitDrainWriters ); setImmediate(() => { // This one should *not* get through to writer1 because writer2 is not @@ -39,10 +39,10 @@ writer1.once('chunk-received', () => { // A "slow" consumer: writer2._write = common.mustCall((chunk, encoding, cb) => { assert.strictEqual( - reader._readableState.awaitDrain, + reader._readableState.awaitDrainWriters.size, 1, 'awaitDrain should be 1 after first push, actual is ' + - reader._readableState.awaitDrain + reader._readableState.awaitDrainWriters ); // Not calling cb here to "simulate" slow stream. // This should be called exactly once, since the first .write() call @@ -51,10 +51,10 @@ writer2._write = common.mustCall((chunk, encoding, cb) => { writer3._write = common.mustCall((chunk, encoding, cb) => { assert.strictEqual( - reader._readableState.awaitDrain, + reader._readableState.awaitDrainWriters.size, 2, 'awaitDrain should be 2 after second push, actual is ' + - reader._readableState.awaitDrain + reader._readableState.awaitDrainWriters ); // Not calling cb here to "simulate" slow stream. // This should be called exactly once, since the first .write() call diff --git a/test/parallel/test-stream-readable-next-no-null.js b/test/parallel/test-stream-readable-next-no-null.js new file mode 100644 index 00000000000000..64ca40be11ed03 --- /dev/null +++ b/test/parallel/test-stream-readable-next-no-null.js @@ -0,0 +1,19 @@ +'use strict'; +const { mustNotCall, expectsError } = require('../common'); +const { Readable } = require('stream'); + +async function* generate() { + yield null; +} + +const stream = Readable.from(generate()); + +stream.on('error', expectsError({ + code: 'ERR_STREAM_NULL_VALUES', + name: 'TypeError', + message: 'May not write null values to stream' +})); + +stream.on('data', mustNotCall((chunk) => {})); + +stream.on('end', mustNotCall()); diff --git a/test/parallel/test-stream2-basic.js b/test/parallel/test-stream2-basic.js index 501f81e7e36526..08e3b29d532660 100644 --- a/test/parallel/test-stream2-basic.js +++ b/test/parallel/test-stream2-basic.js @@ -355,7 +355,6 @@ class TestWriter extends EE { assert.strictEqual(v, null); const w = new R(); - w.write = function(buffer) { written = true; assert.strictEqual(ended, false); diff --git a/test/parallel/test-stream2-readable-from-list.js b/test/parallel/test-stream2-readable-from-list.js index 0ab7c059d66a85..6564a01691f09e 100644 --- a/test/parallel/test-stream2-readable-from-list.js +++ b/test/parallel/test-stream2-readable-from-list.js @@ -19,7 +19,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -// Flags: --expose_internals +// Flags: --expose-internals 'use strict'; require('../common'); const assert = require('assert'); diff --git a/test/parallel/test-timers-clearImmediate-als.js b/test/parallel/test-timers-clearImmediate-als.js new file mode 100644 index 00000000000000..bf2bc6b8d5a175 --- /dev/null +++ b/test/parallel/test-timers-clearImmediate-als.js @@ -0,0 +1,28 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const { AsyncLocalStorage } = require('async_hooks'); + +// This is an asynclocalstorage variant of test-timers-clearImmediate.js +const asyncLocalStorage = new AsyncLocalStorage(); +const N = 3; + +function next() { + const fn = common.mustCall(onImmediate); + asyncLocalStorage.run(new Map(), common.mustCall(() => { + const immediate = setImmediate(fn); + const store = asyncLocalStorage.getStore(); + store.set('immediate', immediate); + })); +} + +function onImmediate() { + const store = asyncLocalStorage.getStore(); + const immediate = store.get('immediate'); + assert.strictEqual(immediate.constructor.name, 'Immediate'); + clearImmediate(immediate); +} + +for (let i = 0; i < N; i++) { + next(); +} diff --git a/test/parallel/test-tls-cipher-list.js b/test/parallel/test-tls-cipher-list.js index ddbe6a33f6409d..b3c34a74bf4ee0 100644 --- a/test/parallel/test-tls-cipher-list.js +++ b/test/parallel/test-tls-cipher-list.js @@ -8,11 +8,11 @@ const assert = require('assert'); const spawn = require('child_process').spawn; const defaultCoreList = require('crypto').constants.defaultCoreCipherList; -function doCheck(arg, check) { +function doCheck(arg, expression, check) { let out = ''; arg = arg.concat([ '-pe', - 'require("crypto").constants.defaultCipherList' + expression ]); spawn(process.execPath, arg, {}) .on('error', common.mustNotCall()) @@ -24,7 +24,9 @@ function doCheck(arg, check) { } // Test the default unmodified version -doCheck([], defaultCoreList); +doCheck([], 'crypto.constants.defaultCipherList', defaultCoreList); +doCheck([], 'tls.DEFAULT_CIPHERS', defaultCoreList); // Test the command line switch by itself -doCheck(['--tls-cipher-list=ABC'], 'ABC'); +doCheck(['--tls-cipher-list=ABC'], 'crypto.constants.defaultCipherList', 'ABC'); +doCheck(['--tls-cipher-list=ABC'], 'tls.DEFAULT_CIPHERS', 'ABC'); diff --git a/test/parallel/test-tls-connect-hints-option.js b/test/parallel/test-tls-connect-hints-option.js index fd155c9659ad0c..3f58266ac88263 100644 --- a/test/parallel/test-tls-connect-hints-option.js +++ b/test/parallel/test-tls-connect-hints-option.js @@ -15,7 +15,11 @@ const hints = 512; assert.notStrictEqual(hints, dns.ADDRCONFIG); assert.notStrictEqual(hints, dns.V4MAPPED); +assert.notStrictEqual(hints, dns.ALL); assert.notStrictEqual(hints, dns.ADDRCONFIG | dns.V4MAPPED); +assert.notStrictEqual(hints, dns.ADDRCONFIG | dns.ALL); +assert.notStrictEqual(hints, dns.V4MAPPED | dns.ALL); +assert.notStrictEqual(hints, dns.ADDRCONFIG | dns.V4MAPPED | dns.ALL); tls.connect({ lookup: common.mustCall((host, options) => { diff --git a/test/parallel/test-tls-exportkeyingmaterial.js b/test/parallel/test-tls-exportkeyingmaterial.js new file mode 100644 index 00000000000000..b3173f94001194 --- /dev/null +++ b/test/parallel/test-tls-exportkeyingmaterial.js @@ -0,0 +1,102 @@ +'use strict'; + +// Test return value of tlsSocket.exportKeyingMaterial + +const common = require('../common'); + +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const net = require('net'); +const tls = require('tls'); +const fixtures = require('../common/fixtures'); + +const key = fixtures.readKey('agent1-key.pem'); +const cert = fixtures.readKey('agent1-cert.pem'); + +const server = net.createServer(common.mustCall((s) => { + const tlsSocket = new tls.TLSSocket(s, { + isServer: true, + server: server, + secureContext: tls.createSecureContext({ key, cert }) + }); + + assert.throws(() => { + tlsSocket.exportKeyingMaterial(128, 'label'); + }, { + name: 'Error', + message: 'TLS socket connection must be securely established', + code: 'ERR_TLS_INVALID_STATE' + }); + + tlsSocket.on('secure', common.mustCall(() => { + const label = 'client finished'; + + const validKeyingMaterial = tlsSocket.exportKeyingMaterial(128, label); + assert.strictEqual(validKeyingMaterial.length, 128); + + const validKeyingMaterialWithContext = tlsSocket + .exportKeyingMaterial(128, label, Buffer.from([0, 1, 2, 3])); + assert.strictEqual(validKeyingMaterialWithContext.length, 128); + + // Ensure providing a context results in a different key than without + assert.notStrictEqual(validKeyingMaterial, validKeyingMaterialWithContext); + + const validKeyingMaterialWithEmptyContext = tlsSocket + .exportKeyingMaterial(128, label, Buffer.from([])); + assert.strictEqual(validKeyingMaterialWithEmptyContext.length, 128); + + assert.throws(() => { + tlsSocket.exportKeyingMaterial(128, label, 'stringAsContextNotSupported'); + }, { + name: 'TypeError', + code: 'ERR_INVALID_ARG_TYPE' + }); + + assert.throws(() => { + tlsSocket.exportKeyingMaterial(128, label, 1234); + }, { + name: 'TypeError', + code: 'ERR_INVALID_ARG_TYPE' + }); + + assert.throws(() => { + tlsSocket.exportKeyingMaterial(10, null); + }, { + name: 'TypeError', + code: 'ERR_INVALID_ARG_TYPE' + }); + + assert.throws(() => { + tlsSocket.exportKeyingMaterial('length', 1234); + }, { + name: 'TypeError', + code: 'ERR_INVALID_ARG_TYPE' + }); + + assert.throws(() => { + tlsSocket.exportKeyingMaterial(-3, 'a'); + }, { + name: 'RangeError', + code: 'ERR_OUT_OF_RANGE' + }); + + assert.throws(() => { + tlsSocket.exportKeyingMaterial(0, 'a'); + }, { + name: 'RangeError', + code: 'ERR_OUT_OF_RANGE' + }); + + tlsSocket.end(); + server.close(); + })); +})).listen(0, () => { + const opts = { + port: server.address().port, + rejectUnauthorized: false + }; + + tls.connect(opts, common.mustCall(function() { this.end(); })); +}); diff --git a/test/parallel/test-tls-min-max-version.js b/test/parallel/test-tls-min-max-version.js index 179ae1fa637d92..7ef0f12426537c 100644 --- a/test/parallel/test-tls-min-max-version.js +++ b/test/parallel/test-tls-min-max-version.js @@ -1,6 +1,7 @@ 'use strict'; const common = require('../common'); const fixtures = require('../common/fixtures'); +const { inspect } = require('util'); // Check min/max protocol versions. @@ -16,7 +17,7 @@ function test(cmin, cmax, cprot, smin, smax, sprot, proto, cerr, serr) { // Report where test was called from. Strip leading garbage from // at Object. (file:line) // from the stack location, we only want the file:line part. - const where = (new Error()).stack.split('\n')[2].replace(/[^(]*/, ''); + const where = inspect(new Error()).split('\n')[2].replace(/[^(]*/, ''); connect({ client: { checkServerIdentity: (servername, cert) => { }, diff --git a/test/parallel/test-tls-parse-cert-string.js b/test/parallel/test-tls-parse-cert-string.js index a3062c227e6fd1..f5412cad4074c4 100644 --- a/test/parallel/test-tls-parse-cert-string.js +++ b/test/parallel/test-tls-parse-cert-string.js @@ -10,7 +10,7 @@ const { restoreStderr } = require('../common/hijackstdio'); const assert = require('assert'); -// Flags: --expose_internals +// Flags: --expose-internals const internalTLS = require('internal/tls'); const tls = require('tls'); diff --git a/test/parallel/test-tls-securepair-server.js b/test/parallel/test-tls-securepair-server.js index 5e3cd4130cba9f..78cd9f725401ed 100644 --- a/test/parallel/test-tls-securepair-server.js +++ b/test/parallel/test-tls-securepair-server.js @@ -37,7 +37,7 @@ const key = fixtures.readKey('rsa_private.pem'); const cert = fixtures.readKey('rsa_cert.crt'); function log(a) { - console.error(`***server*** ${a}`); + console.error('***server***', a); } const server = net.createServer(common.mustCall(function(socket) { @@ -74,21 +74,18 @@ const server = net.createServer(common.mustCall(function(socket) { pair.cleartext.on('error', function(err) { log('got error: '); log(err); - log(err.stack); socket.destroy(); }); pair.encrypted.on('error', function(err) { log('encrypted error: '); log(err); - log(err.stack); socket.destroy(); }); socket.on('error', function(err) { log('socket error: '); log(err); - log(err.stack); socket.destroy(); }); @@ -99,7 +96,6 @@ const server = net.createServer(common.mustCall(function(socket) { pair.on('error', function(err) { log('secure error: '); log(err); - log(err.stack); socket.destroy(); }); })); diff --git a/test/parallel/test-tls-set-ciphers.js b/test/parallel/test-tls-set-ciphers.js index fbca83b3d5d286..50fb6edc3a2431 100644 --- a/test/parallel/test-tls-set-ciphers.js +++ b/test/parallel/test-tls-set-ciphers.js @@ -1,7 +1,10 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) common.skip('missing crypto'); +if (!common.hasCrypto) + common.skip('missing crypto'); + const fixtures = require('../common/fixtures'); +const { inspect } = require('util'); // Test cipher: option for TLS. @@ -12,7 +15,7 @@ const { function test(cciphers, sciphers, cipher, cerr, serr) { assert(cipher || cerr || serr, 'test missing any expectations'); - const where = (new Error()).stack.split('\n')[2].replace(/[^(]*/, ''); + const where = inspect(new Error()).split('\n')[2].replace(/[^(]*/, ''); connect({ client: { checkServerIdentity: (servername, cert) => { }, diff --git a/test/parallel/test-tls-wrap-timeout.js b/test/parallel/test-tls-wrap-timeout.js index 6ae2c39c59b8d9..7b9cb4170c888f 100644 --- a/test/parallel/test-tls-wrap-timeout.js +++ b/test/parallel/test-tls-wrap-timeout.js @@ -1,4 +1,4 @@ -// Flags: --expose_internals +// Flags: --expose-internals 'use strict'; const common = require('../common'); diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 5df203e6d33be0..7bb0464335e82f 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -2441,6 +2441,26 @@ assert.strictEqual( assert.strictEqual(out, expected); + // Unicode support. あ has a length of one and a width of two. + obj = [ + '123', '123', '123', '123', 'あああ', + '123', '123', '123', '123', 'あああ' + ]; + + out = util.inspect(obj, { compact: 3 }); + + expected = [ + '[', + " '123', '123',", + " '123', '123',", + " 'あああ', '123',", + " '123', '123',", + " '123', 'あああ'", + ']', + ].join('\n'); + + assert.strictEqual(out, expected); + // Verify that array grouping and line consolidation does not happen together. obj = { a: { @@ -2758,3 +2778,11 @@ assert.strictEqual( v8.setFlagsFromString('--no-allow-natives-syntax'); assert.strictEqual(inspect(undetectable), '{}'); } + +{ + const x = 'a'.repeat(1e6); + assert.strictEqual( + util.inspect(x, { maxStringLength: 4 }), + "'aaaa'... 999996 more characters" + ); +} diff --git a/test/parallel/test-util-internal.js b/test/parallel/test-util-internal.js index f16ccfdbdc534f..cd38f3e7c57f44 100644 --- a/test/parallel/test-util-internal.js +++ b/test/parallel/test-util-internal.js @@ -1,5 +1,5 @@ 'use strict'; -// Flags: --expose_internals +// Flags: --expose-internals require('../common'); const assert = require('assert'); diff --git a/test/parallel/test-vm-context.js b/test/parallel/test-vm-context.js index 247b8a17cc675e..5226f0e6ac0ea2 100644 --- a/test/parallel/test-vm-context.js +++ b/test/parallel/test-vm-context.js @@ -22,7 +22,7 @@ 'use strict'; require('../common'); const assert = require('assert'); - +const { inspect } = require('util'); const vm = require('vm'); const Script = vm.Script; let script = new Script('"passed";'); @@ -59,7 +59,7 @@ try { } catch (e) { gh1140Exception = e; assert.ok(/expected-filename/.test(e.stack), - `expected appearance of filename in Error stack: ${e.stack}`); + `expected appearance of filename in Error stack: ${inspect(e)}`); } // This is outside of catch block to confirm catch block ran. assert.strictEqual(gh1140Exception.toString(), 'Error'); diff --git a/test/parallel/test-vm-module-basic.js b/test/parallel/test-vm-module-basic.js index 86e13f8b12bfa8..27b7f0476d502d 100644 --- a/test/parallel/test-vm-module-basic.js +++ b/test/parallel/test-vm-module-basic.js @@ -124,12 +124,22 @@ const util = require('util'); // Check to throws invalid exportNames { assert.throws(() => new SyntheticModule(undefined, () => {}, {}), { - message: 'The "exportNames" argument must be an Array of strings.' + - ' Received undefined', + message: 'The "exportNames" argument must be an ' + + 'Array of unique strings.' + + ' Received undefined', name: 'TypeError' }); } +// Check to throws duplicated exportNames +// https://github.com/nodejs/node/issues/32806 +{ + assert.throws(() => new SyntheticModule(['x', 'x'], () => {}, {}), { + message: 'The argument \'exportNames.x\' is duplicated. Received \'x\'', + name: 'TypeError', + }); +} + // Check to throws invalid evaluateCallback { assert.throws(() => new SyntheticModule([], undefined, {}), { diff --git a/test/parallel/test-vm-module-cached-data.js b/test/parallel/test-vm-module-cached-data.js new file mode 100644 index 00000000000000..f91d9e62688dc5 --- /dev/null +++ b/test/parallel/test-vm-module-cached-data.js @@ -0,0 +1,30 @@ +'use strict'; + +// Flags: --experimental-vm-modules + +require('../common'); + +const assert = require('assert'); +const { SourceTextModule } = require('vm'); + +{ + const m = new SourceTextModule('const a = 1'); + const cachedData = m.createCachedData(); + + new SourceTextModule('const a = 1', { cachedData }); + + assert.throws(() => { + new SourceTextModule('differentSource', { cachedData }); + }, { + code: 'ERR_VM_MODULE_CACHED_DATA_REJECTED', + }); +} + +assert.rejects(async () => { + const m = new SourceTextModule('const a = 1'); + await m.link(() => {}); + m.evaluate(); + m.createCachedData(); +}, { + code: 'ERR_VM_MODULE_CANNOT_CREATE_CACHED_DATA', +}); diff --git a/test/parallel/test-vm-module-dynamic-import.js b/test/parallel/test-vm-module-dynamic-import.js index 897d9f27d73376..70229b3897874b 100644 --- a/test/parallel/test-vm-module-dynamic-import.js +++ b/test/parallel/test-vm-module-dynamic-import.js @@ -1,6 +1,6 @@ 'use strict'; -// Flags: --experimental-vm-modules --experimental-modules +// Flags: --experimental-vm-modules const common = require('../common'); diff --git a/test/parallel/test-vm-module-errors.js b/test/parallel/test-vm-module-errors.js index 5f36f9339fe41a..d14296b1e9ebde 100644 --- a/test/parallel/test-vm-module-errors.js +++ b/test/parallel/test-vm-module-errors.js @@ -209,6 +209,22 @@ async function checkInvalidOptionForEvaluate() { }); } +function checkInvalidCachedData() { + [true, false, 'foo', {}, Array, function() {}].forEach((invalidArg) => { + const message = 'The "options.cachedData" property must be an ' + + 'instance of Buffer, TypedArray, or DataView.' + + common.invalidArgTypeHelper(invalidArg); + assert.throws( + () => new SourceTextModule('import "foo";', { cachedData: invalidArg }), + { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + message, + } + ); + }); +} + const finished = common.mustCall(); (async function main() { @@ -217,5 +233,6 @@ const finished = common.mustCall(); await checkLinking(); await checkExecution(); await checkInvalidOptionForEvaluate(); + checkInvalidCachedData(); finished(); })(); diff --git a/test/parallel/test-whatwg-encoding-custom-textdecoder.js b/test/parallel/test-whatwg-encoding-custom-textdecoder.js index 1430a0daa8eabb..d16fd24bcd3739 100644 --- a/test/parallel/test-whatwg-encoding-custom-textdecoder.js +++ b/test/parallel/test-whatwg-encoding-custom-textdecoder.js @@ -107,8 +107,13 @@ if (common.hasIntl) { if (common.hasIntl) { assert.strictEqual( util.inspect(dec, { showHidden: true }), - 'TextDecoder {\n encoding: \'utf-8\',\n fatal: false,\n ' + - 'ignoreBOM: true,\n [Symbol(flags)]: 4,\n [Symbol(handle)]: {}\n}' + 'TextDecoder {\n' + + ' encoding: \'utf-8\',\n' + + ' fatal: false,\n' + + ' ignoreBOM: true,\n' + + ' [Symbol(flags)]: 4,\n' + + ' [Symbol(handle)]: Converter {}\n' + + '}' ); } else { assert.strictEqual( diff --git a/test/parallel/test-worker-esm-exit.js b/test/parallel/test-worker-esm-exit.js index aebb17edda0baf..8c38faf3b72f8d 100644 --- a/test/parallel/test-worker-esm-exit.js +++ b/test/parallel/test-worker-esm-exit.js @@ -4,8 +4,7 @@ const fixtures = require('../common/fixtures'); const assert = require('assert'); const { Worker } = require('worker_threads'); -const w = new Worker(fixtures.path('es-modules/import-process-exit.mjs'), - { execArgv: ['--experimental-modules'] }); +const w = new Worker(fixtures.path('es-modules/import-process-exit.mjs')); w.on('error', common.mustNotCall()); w.on('exit', common.mustCall((code) => assert.strictEqual(code, 42)) diff --git a/test/parallel/test-worker-esm-missing-main.js b/test/parallel/test-worker-esm-missing-main.js index 8f4cfb0fe7fa9b..07bfb6a0276cd5 100644 --- a/test/parallel/test-worker-esm-missing-main.js +++ b/test/parallel/test-worker-esm-missing-main.js @@ -8,7 +8,7 @@ const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); const missing = path.join(tmpdir.path, 'does-not-exist.js'); -const worker = new Worker(missing, { execArgv: ['--experimental-modules'] }); +const worker = new Worker(missing); worker.on('error', common.mustCall((err) => { // eslint-disable-next-line node-core/no-unescaped-regexp-dot diff --git a/test/parallel/test-worker-esmodule.js b/test/parallel/test-worker-esmodule.js index 33788c1422ce84..e7f9bd7aea6c8a 100644 --- a/test/parallel/test-worker-esmodule.js +++ b/test/parallel/test-worker-esmodule.js @@ -1,4 +1,3 @@ -// Flags: --experimental-modules 'use strict'; const common = require('../common'); const fixtures = require('../common/fixtures'); diff --git a/test/parallel/test-worker-heapdump-failure.js b/test/parallel/test-worker-heapdump-failure.js new file mode 100644 index 00000000000000..06e260374cd3a4 --- /dev/null +++ b/test/parallel/test-worker-heapdump-failure.js @@ -0,0 +1,15 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const { Worker } = require('worker_threads'); +const { once } = require('events'); + +(async function() { + const w = new Worker('', { eval: true }); + + await once(w, 'exit'); + await assert.rejects(() => w.getHeapSnapshot(), { + name: 'Error', + code: 'ERR_WORKER_NOT_RUNNING' + }); +})().then(common.mustCall()); diff --git a/test/parallel/test-worker-message-port-receive-message.js b/test/parallel/test-worker-message-port-receive-message.js index 9bd8e7ed644aa3..e7078ea1e67ee5 100644 --- a/test/parallel/test-worker-message-port-receive-message.js +++ b/test/parallel/test-worker-message-port-receive-message.js @@ -23,3 +23,11 @@ port2.on('message', common.mustNotCall()); port1.postMessage(message1); assert.deepStrictEqual(receiveMessageOnPort(port2), { message: message1 }); port1.close(); + +for (const value of [null, 0, -1, {}, []]) { + assert.throws(() => receiveMessageOnPort(value), { + name: 'TypeError', + code: 'ERR_INVALID_ARG_TYPE', + message: 'First argument needs to be a MessagePort instance' + }); +} diff --git a/test/parallel/test-worker-mjs-workerdata.js b/test/parallel/test-worker-mjs-workerdata.js index c107730ea4bba2..b0a65e2e805c1e 100644 --- a/test/parallel/test-worker-mjs-workerdata.js +++ b/test/parallel/test-worker-mjs-workerdata.js @@ -7,8 +7,7 @@ const { Worker } = require('worker_threads'); const workerData = 'Hello from main thread'; const worker = new Worker(fixtures.path('worker-data.mjs'), { - workerData, - execArgv: ['--experimental-modules'] + workerData }); worker.on('message', common.mustCall((message) => { diff --git a/test/parallel/test-worker-type-check.js b/test/parallel/test-worker-type-check.js index 2a67bfec405af2..88965f4be4c62d 100644 --- a/test/parallel/test-worker-type-check.js +++ b/test/parallel/test-worker-type-check.js @@ -20,7 +20,8 @@ const { Worker } = require('worker_threads'); { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError', - message: 'The "filename" argument must be of type string.' + + message: 'The "filename" argument must be of type string ' + + 'or an instance of URL.' + common.invalidArgTypeHelper(val) } ); diff --git a/test/parallel/test-worker-unsupported-eval-on-url.mjs b/test/parallel/test-worker-unsupported-eval-on-url.mjs new file mode 100644 index 00000000000000..c3d2050ec5f2da --- /dev/null +++ b/test/parallel/test-worker-unsupported-eval-on-url.mjs @@ -0,0 +1,6 @@ +import '../common/index.mjs'; +import assert from 'assert'; +import { Worker } from 'worker_threads'; + +const re = /The argument 'options\.eval' must be false when 'filename' is not a string\./; +assert.throws(() => new Worker(new URL(import.meta.url), { eval: true }), re); diff --git a/test/parallel/test-worker-unsupported-path.js b/test/parallel/test-worker-unsupported-path.js index 21ff40671965e5..1a5f53c821ee6c 100644 --- a/test/parallel/test-worker-unsupported-path.js +++ b/test/parallel/test-worker-unsupported-path.js @@ -13,6 +13,7 @@ const { Worker } = require('worker_threads'); assert.throws(() => { new Worker('/b'); }, expectedErr); assert.throws(() => { new Worker('/c.wasm'); }, expectedErr); assert.throws(() => { new Worker('/d.txt'); }, expectedErr); + assert.throws(() => { new Worker(new URL('file:///C:/e.wasm')); }, expectedErr); } { @@ -26,3 +27,26 @@ const { Worker } = require('worker_threads'); assert.throws(() => { new Worker('file:///file_url'); }, expectedErr); assert.throws(() => { new Worker('https://www.url.com'); }, expectedErr); } + +{ + assert.throws( + () => { new Worker('file:///file_url'); }, + /Wrap file:\/\/ URLs with `new URL`/ + ); + assert.throws( + () => { new Worker('relative_no_dot'); }, + // eslint-disable-next-line node-core/no-unescaped-regexp-dot + /^((?!Wrap file:\/\/ URLs with `new URL`).)*$/s + ); +} + +{ + const expectedErr = { + code: 'ERR_INVALID_URL_SCHEME', + name: 'TypeError' + }; + assert.throws(() => { new Worker(new URL('https://www.url.com')); }, + expectedErr); + assert.throws(() => { new Worker(new URL('data:application/javascript,')); }, + expectedErr); +} diff --git a/test/parallel/test-worker-workerdata-messageport.js b/test/parallel/test-worker-workerdata-messageport.js new file mode 100644 index 00000000000000..352d0729412ddb --- /dev/null +++ b/test/parallel/test-worker-workerdata-messageport.js @@ -0,0 +1,60 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); + +const { + Worker, MessageChannel +} = require('worker_threads'); + +const channel = new MessageChannel(); +const workerData = { mesage: channel.port1 }; +const transferList = [channel.port1]; +const meowScript = () => 'meow'; + +{ + // Should receive the transferList param. + new Worker(`${meowScript}`, { eval: true, workerData, transferList }); +} + +{ + // Should work with more than one MessagePort. + const channel1 = new MessageChannel(); + const channel2 = new MessageChannel(); + const workerData = { message: channel1.port1, message2: channel2.port1 }; + const transferList = [channel1.port1, channel2.port1]; + new Worker(`${meowScript}`, { eval: true, workerData, transferList }); +} + +{ + const uint8Array = new Uint8Array([ 1, 2, 3, 4 ]); + assert.deepStrictEqual(uint8Array.length, 4); + new Worker(` + const { parentPort, workerData } = require('worker_threads'); + parentPort.postMessage(workerData); + `, { + eval: true, + workerData: uint8Array, + transferList: [uint8Array.buffer] + }).on( + 'message', + (message) => + assert.deepStrictEqual(message, Uint8Array.of(1, 2, 3, 4)) + ); + assert.deepStrictEqual(uint8Array.length, 0); +} + +{ + // Should throw on non valid transferList input. + const channel1 = new MessageChannel(); + const channel2 = new MessageChannel(); + const workerData = { message: channel1.port1, message2: channel2.port1 }; + assert.throws(() => new Worker(`${meowScript}`, { + eval: true, + workerData, + transferList: [] + }), { + code: 'ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST', + message: 'MessagePort was found in message but not listed in transferList' + }); +} diff --git a/test/parallel/test-worker.js b/test/parallel/test-worker.js index 9c388955483b94..9154aaa12baee1 100644 --- a/test/parallel/test-worker.js +++ b/test/parallel/test-worker.js @@ -3,15 +3,17 @@ const common = require('../common'); const assert = require('assert'); const { Worker, isMainThread, parentPort } = require('worker_threads'); +const kTestString = 'Hello, world!'; + if (isMainThread) { const w = new Worker(__filename); w.on('message', common.mustCall((message) => { - assert.strictEqual(message, 'Hello, world!'); + assert.strictEqual(message, kTestString); })); } else { setImmediate(() => { process.nextTick(() => { - parentPort.postMessage('Hello, world!'); + parentPort.postMessage(kTestString); }); }); } diff --git a/test/parallel/test-worker.mjs b/test/parallel/test-worker.mjs new file mode 100644 index 00000000000000..4ee3f7dc96fa4c --- /dev/null +++ b/test/parallel/test-worker.mjs @@ -0,0 +1,18 @@ +import { mustCall } from '../common/index.mjs'; +import assert from 'assert'; +import { Worker, isMainThread, parentPort } from 'worker_threads'; + +const kTestString = 'Hello, world!'; + +if (isMainThread) { + const w = new Worker(new URL(import.meta.url)); + w.on('message', mustCall((message) => { + assert.strictEqual(message, kTestString); + })); +} else { + setImmediate(() => { + process.nextTick(() => { + parentPort.postMessage(kTestString); + }); + }); +} diff --git a/test/pseudo-tty/repl-dumb-tty.js b/test/pseudo-tty/repl-dumb-tty.js index 1a3a24299821fe..8c9b93a9f31ccd 100644 --- a/test/pseudo-tty/repl-dumb-tty.js +++ b/test/pseudo-tty/repl-dumb-tty.js @@ -7,25 +7,30 @@ const repl = require('repl'); const ArrayStream = require('../common/arraystream'); repl.start('> '); -process.stdin.push('console.log("foo")\n'); -process.stdin.push('1 + 2\n'); +process.stdin.push('conso'); // No completion preview. +process.stdin.push('le.log("foo")\n'); +process.stdin.push('1 + 2'); // No input preview. +process.stdin.push('\n'); process.stdin.push('"str"\n'); process.stdin.push('console.dir({ a: 1 })\n'); process.stdin.push('{ a: 1 }\n'); process.stdin.push('\n'); process.stdin.push('.exit\n'); -// Verify Control+D support. +// Verify + D support. { const stream = new ArrayStream(); - const replServer = repl.start({ + const replServer = new repl.REPLServer({ prompt: '> ', terminal: true, input: stream, - output: stream, + output: process.stdout, useColors: false }); replServer.on('close', common.mustCall()); + // Verify that + R or + C does not trigger the reverse search. + replServer.write(null, { ctrl: true, name: 'r' }); + replServer.write(null, { ctrl: true, name: 's' }); replServer.write(null, { ctrl: true, name: 'd' }); } diff --git a/test/pseudo-tty/repl-dumb-tty.out b/test/pseudo-tty/repl-dumb-tty.out index 69eb4e5da6313e..3304faff0a4f4f 100644 --- a/test/pseudo-tty/repl-dumb-tty.out +++ b/test/pseudo-tty/repl-dumb-tty.out @@ -12,3 +12,4 @@ undefined { a: 1 } > > .exit +> diff --git a/test/pseudo-tty/test-trace-sigint-disabled.js b/test/pseudo-tty/test-trace-sigint-disabled.js new file mode 100644 index 00000000000000..5dc4dfa9b36afa --- /dev/null +++ b/test/pseudo-tty/test-trace-sigint-disabled.js @@ -0,0 +1,39 @@ +'use strict'; + +const { mustCall } = require('../common'); +const childProcess = require('child_process'); +const assert = require('assert'); + +if (process.env.CHILD === 'true') { + main(); +} else { + // Use inherited stdio child process to prevent test tools from determining + // the case as crashed from SIGINT + const cp = childProcess.spawn( + process.execPath, + ['--trace-sigint', __filename], + { + env: { ...process.env, CHILD: 'true' }, + stdio: 'inherit' + }); + cp.on('exit', mustCall((code, signal) => { + assert.strictEqual(signal, null); + assert.strictEqual(code, 0); + })); +} + +function main() { + // Deactivate colors even if the tty does support colors. + process.env.NODE_DISABLE_COLORS = '1'; + + const noop = mustCall(() => { + process.exit(0); + }); + process.on('SIGINT', noop); + // Try testing re-add 'SIGINT' listeners + process.removeListener('SIGINT', noop); + process.on('SIGINT', noop); + + process.kill(process.pid, 'SIGINT'); + setTimeout(() => { assert.fail('unreachable path'); }, 10 * 1000); +} diff --git a/test/pseudo-tty/test-trace-sigint-disabled.out b/test/pseudo-tty/test-trace-sigint-disabled.out new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/test/pseudo-tty/test-trace-sigint-on-idle.js b/test/pseudo-tty/test-trace-sigint-on-idle.js new file mode 100644 index 00000000000000..5f79cb82fe95db --- /dev/null +++ b/test/pseudo-tty/test-trace-sigint-on-idle.js @@ -0,0 +1,32 @@ +'use strict'; +const { platformTimeout, mustCall } = require('../common'); +const childProcess = require('child_process'); +const assert = require('assert'); + +if (process.env.CHILD === 'true') { + main(); +} else { + // Use inherited stdio child process to prevent test tools from determining + // the case as crashed from SIGINT + const cp = childProcess.spawn( + process.execPath, + ['--trace-sigint', __filename], + { + env: { ...process.env, CHILD: 'true' }, + stdio: ['inherit', 'inherit', 'inherit', 'ipc'] + }); + cp.on('message', mustCall(() => { + setTimeout(() => cp.kill('SIGINT'), platformTimeout(100)); + })); + cp.on('exit', mustCall((code, signal) => { + assert.strictEqual(signal, 'SIGINT'); + assert.strictEqual(code, null); + })); +} + +function main() { + // Deactivate colors even if the tty does support colors. + process.env.NODE_DISABLE_COLORS = '1'; + process.channel.ref(); // Keep event loop alive until the signal is received. + process.send('ready'); +} diff --git a/test/pseudo-tty/test-trace-sigint-on-idle.out b/test/pseudo-tty/test-trace-sigint-on-idle.out new file mode 100644 index 00000000000000..faaef62fc79f70 --- /dev/null +++ b/test/pseudo-tty/test-trace-sigint-on-idle.out @@ -0,0 +1 @@ +KEYBOARD_INTERRUPT: Script execution was interrupted by `SIGINT` diff --git a/test/pseudo-tty/test-trace-sigint.js b/test/pseudo-tty/test-trace-sigint.js new file mode 100644 index 00000000000000..8b539bfc88d7b8 --- /dev/null +++ b/test/pseudo-tty/test-trace-sigint.js @@ -0,0 +1,30 @@ +'use strict'; + +const { mustCall } = require('../common'); +const childProcess = require('child_process'); +const assert = require('assert'); + +if (process.env.CHILD === 'true') { + main(); +} else { + // Use inherited stdio child process to prevent test tools from determining + // the case as crashed from SIGINT + const cp = childProcess.spawn( + process.execPath, + ['--trace-sigint', __filename], + { + env: { ...process.env, CHILD: 'true' }, + stdio: 'inherit' + }); + cp.on('exit', mustCall((code, signal) => { + assert.strictEqual(signal, 'SIGINT'); + assert.strictEqual(code, null); + })); +} + +function main() { + // Deactivate colors even if the tty does support colors. + process.env.NODE_DISABLE_COLORS = '1'; + process.kill(process.pid, 'SIGINT'); + while (true) {} +} diff --git a/test/pseudo-tty/test-trace-sigint.out b/test/pseudo-tty/test-trace-sigint.out new file mode 100644 index 00000000000000..956cbafccc2d19 --- /dev/null +++ b/test/pseudo-tty/test-trace-sigint.out @@ -0,0 +1,9 @@ +KEYBOARD_INTERRUPT: Script execution was interrupted by `SIGINT` + at main (*/test-trace-sigint.js:*) + at */test-trace-sigint.js:* + at * + at * + at * + at * + at * + at * diff --git a/test/pummel/test-worker-take-heapsnapshot.js b/test/pummel/test-worker-take-heapsnapshot.js new file mode 100644 index 00000000000000..b369759d0613e5 --- /dev/null +++ b/test/pummel/test-worker-take-heapsnapshot.js @@ -0,0 +1,22 @@ +// Flags: --expose-internals +'use strict'; +const common = require('../common'); +const { recordState } = require('../common/heap'); +const { Worker } = require('worker_threads'); +const { once } = require('events'); + +(async function() { + const w = new Worker('setInterval(() => {}, 100)', { eval: true }); + + await once(w, 'online'); + const stream = await w.getHeapSnapshot(); + const snapshot = recordState(stream); + snapshot.validateSnapshot('Node / MessagePort', [ + { + children: [ + { node_name: 'Node / MessagePortData', edge_name: 'data' } + ] + } + ], { loose: true }); + await w.terminate(); +})().then(common.mustCall()); diff --git a/test/report/test-report-config.js b/test/report/test-report-config.js index 4f6fdf2a80e111..a8c0f70691e63f 100644 --- a/test/report/test-report-config.js +++ b/test/report/test-report-config.js @@ -1,13 +1,8 @@ -// Flags: --experimental-report --report-on-fatalerror --report-on-signal --report-uncaught-exception +// Flags: --report-on-fatalerror --report-on-signal --report-uncaught-exception --report-compact 'use strict'; const common = require('../common'); -common.skipIfReportDisabled(); const assert = require('assert'); -common.expectWarning('ExperimentalWarning', - 'report is an experimental feature. This feature could ' + - 'change at any time'); - // Verify that process.report.directory behaves properly. assert.strictEqual(process.report.directory, ''); process.report.directory = __dirname; @@ -60,6 +55,17 @@ assert.throws(() => { }, { code: 'ERR_INVALID_ARG_TYPE' }); assert.strictEqual(process.report.reportOnSignal, true); +// Verify that process.report.reportCompact behaves properly. +assert.strictEqual(process.report.compact, true); +process.report.compact = false; +assert.strictEqual(process.report.compact, false); +process.report.compact = true; +assert.strictEqual(process.report.compact, true); +assert.throws(() => { + process.report.compact = {}; +}, { code: 'ERR_INVALID_ARG_TYPE' }); +assert.strictEqual(process.report.compact, true); + if (!common.isWindows) { // Verify that process.report.signal behaves properly. assert.strictEqual(process.report.signal, 'SIGUSR2'); diff --git a/test/report/test-report-fatal-error.js b/test/report/test-report-fatal-error.js index 8ecd058cf8a4de..c166c4b86c384f 100644 --- a/test/report/test-report-fatal-error.js +++ b/test/report/test-report-fatal-error.js @@ -1,9 +1,14 @@ 'use strict'; -const common = require('../common'); -common.skipIfReportDisabled(); +// Testcases for situations involving fatal errors, like Javascript heap OOM + +require('../common'); const assert = require('assert'); -// Testcase to produce report on fatal error (javascript heap OOM) +const fs = require('fs'); +const helper = require('../common/report.js'); +const spawnSync = require('child_process').spawnSync; +const tmpdir = require('../common/tmpdir'); + if (process.argv[2] === 'child') { const list = []; @@ -17,22 +22,100 @@ if (process.argv[2] === 'child') { this.id = 128; this.account = 98454324; } -} else { - const helper = require('../common/report.js'); - const tmpdir = require('../common/tmpdir'); +} + +// Common args that will cause an out-of-memory error for child process. +const ARGS = [ + '--max-old-space-size=20', + __filename, + 'child' +]; + +{ + // Verify that --report-on-fatalerror is respected when set. + tmpdir.refresh(); + const args = ['--report-on-fatalerror', ...ARGS]; + const child = spawnSync(process.execPath, args, { cwd: tmpdir.path }); + assert.notStrictEqual(child.status, 0, 'Process exited unexpectedly'); + + const reports = helper.findReports(child.pid, tmpdir.path); + assert.strictEqual(reports.length, 1); + + const report = reports[0]; + helper.validate(report); + + // Errors occur in a context where env is not available, so thread ID is + // unknown. Assert this, to verify that the underlying env-less situation is + // actually reached. + assert.strictEqual(require(report).header.threadId, null); +} + +{ + // Verify that --report-on-fatalerror is respected when not set. + const args = ARGS; + const child = spawnSync(process.execPath, args, { cwd: tmpdir.path }); + assert.notStrictEqual(child.status, 0, 'Process exited unexpectedly'); + const reports = helper.findReports(child.pid, tmpdir.path); + assert.strictEqual(reports.length, 0); +} + +{ + // Verify that --report-directory is respected when set. + // Verify that --report-compact is respected when not set. tmpdir.refresh(); - const spawn = require('child_process').spawn; - const args = ['--experimental-report', - '--report-on-fatalerror', - '--max-old-space-size=20', - __filename, - 'child']; - const child = spawn(process.execPath, args, { cwd: tmpdir.path }); - child.on('exit', common.mustCall((code) => { - assert.notStrictEqual(code, 0, 'Process exited unexpectedly'); - const reports = helper.findReports(child.pid, tmpdir.path); - assert.strictEqual(reports.length, 1); - const report = reports[0]; - helper.validate(report); - })); + const dir = '--report-directory=' + tmpdir.path; + const args = ['--report-on-fatalerror', dir, ...ARGS]; + const child = spawnSync(process.execPath, args, { }); + assert.notStrictEqual(child.status, 0, 'Process exited unexpectedly'); + + const reports = helper.findReports(child.pid, tmpdir.path); + assert.strictEqual(reports.length, 1); + + const report = reports[0]; + helper.validate(report); + assert.strictEqual(require(report).header.threadId, null); + const lines = fs.readFileSync(report, 'utf8').split('\n').length - 1; + assert(lines > 10); +} + +{ + // Verify that --report-compact is respected when set. + tmpdir.refresh(); + const args = ['--report-on-fatalerror', '--report-compact', ...ARGS]; + const child = spawnSync(process.execPath, args, { cwd: tmpdir.path }); + assert.notStrictEqual(child.status, 0, 'Process exited unexpectedly'); + + const reports = helper.findReports(child.pid, tmpdir.path); + assert.strictEqual(reports.length, 1); + + const report = reports[0]; + helper.validate(report); + assert.strictEqual(require(report).header.threadId, null); + // Subtract 1 because "xx\n".split("\n") => [ 'xx', '' ]. + const lines = fs.readFileSync(report, 'utf8').split('\n').length - 1; + assert.strictEqual(lines, 1); +} + +{ + // Verify that --report-compact is respected when set. + // Verify that --report-filename is respected when set. + tmpdir.refresh(); + const args = [ + '--report-on-fatalerror', + '--report-compact', + '--report-filename=stderr', + ...ARGS + ]; + const child = spawnSync(process.execPath, args, { encoding: 'utf8' }); + assert.notStrictEqual(child.status, 0, 'Process exited unexpectedly'); + + const reports = helper.findReports(child.pid, tmpdir.path); + assert.strictEqual(reports.length, 0); + + const lines = child.stderr.split('\n'); + // Skip over unavoidable free-form output and gc log from V8. + const report = lines.find((i) => i.startsWith('{')); + const json = JSON.parse(report); + + assert.strictEqual(json.header.threadId, null); } diff --git a/test/report/test-report-getreport.js b/test/report/test-report-getreport.js index ba645df69fdd7b..4c68b4ecbb5e48 100644 --- a/test/report/test-report-getreport.js +++ b/test/report/test-report-getreport.js @@ -1,14 +1,8 @@ -// Flags: --experimental-report 'use strict'; -const common = require('../common'); -common.skipIfReportDisabled(); +require('../common'); const assert = require('assert'); const helper = require('../common/report'); -common.expectWarning('ExperimentalWarning', - 'report is an experimental feature. This feature could ' + - 'change at any time'); - { // Test with no arguments. helper.validateContent(process.report.getReport()); diff --git a/test/report/test-report-signal.js b/test/report/test-report-signal.js index 51244fcade2196..cb5efd9fc39fe2 100644 --- a/test/report/test-report-signal.js +++ b/test/report/test-report-signal.js @@ -1,8 +1,8 @@ -// Flags: --experimental-report --report-on-signal +// Flags: --report-on-signal 'use strict'; // Test producing a report via signal. const common = require('../common'); -common.skipIfReportDisabled(); + if (common.isWindows) return common.skip('Unsupported on Windows.'); @@ -13,9 +13,6 @@ const assert = require('assert'); const helper = require('../common/report'); const tmpdir = require('../common/tmpdir'); -common.expectWarning('ExperimentalWarning', - 'report is an experimental feature. This feature could ' + - 'change at any time'); tmpdir.refresh(); process.report.directory = tmpdir.path; diff --git a/test/report/test-report-uncaught-exception-compat.js b/test/report/test-report-uncaught-exception-compat.js new file mode 100644 index 00000000000000..9fe690595e89a0 --- /dev/null +++ b/test/report/test-report-uncaught-exception-compat.js @@ -0,0 +1,5 @@ +// Flags: --experimental-report --report-uncaught-exception --report-compact +'use strict'; +// Test producing a compact report on uncaught exception. +require('../common'); +require('./test-report-uncaught-exception.js'); diff --git a/test/report/test-report-uncaught-exception.js b/test/report/test-report-uncaught-exception.js index 4a2627c13c88ff..10dcccb090019c 100644 --- a/test/report/test-report-uncaught-exception.js +++ b/test/report/test-report-uncaught-exception.js @@ -1,16 +1,12 @@ -// Flags: --experimental-report --report-uncaught-exception +// Flags: --report-uncaught-exception 'use strict'; // Test producing a report on uncaught exception. const common = require('../common'); -common.skipIfReportDisabled(); const assert = require('assert'); const helper = require('../common/report'); const tmpdir = require('../common/tmpdir'); const error = new Error('test error'); -common.expectWarning('ExperimentalWarning', - 'report is an experimental feature. This feature could ' + - 'change at any time'); tmpdir.refresh(); process.report.directory = tmpdir.path; diff --git a/test/report/test-report-uv-handles.js b/test/report/test-report-uv-handles.js index ea0c189b859c1a..3a6a34a8573fe7 100644 --- a/test/report/test-report-uv-handles.js +++ b/test/report/test-report-uv-handles.js @@ -5,7 +5,6 @@ const common = require('../common'); if (common.isIBMi) common.skip('IBMi does not support fs.watch()'); -common.skipIfReportDisabled(); if (process.argv[2] === 'child') { // Exit on loss of parent process const exit = () => process.exit(2); @@ -78,13 +77,12 @@ if (process.argv[2] === 'child') { const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); const options = { encoding: 'utf8', silent: true, cwd: tmpdir.path }; - const child = fork('--experimental-report', [__filename, 'child'], options); + const child = fork(__filename, ['child'], options); let child_data; child.on('message', (data) => { child_data = data; }); let stderr = ''; child.stderr.on('data', (chunk) => { stderr += chunk; }); let stdout = ''; - const std_msg = 'Found messages in stderr unexpectedly: '; const report_msg = 'Report files were written: unexpectedly'; child.stdout.on('data', (chunk) => { stdout += chunk; }); child.on('exit', common.mustCall((code, signal) => { @@ -92,10 +90,7 @@ if (process.argv[2] === 'child') { `${code}`); assert.deepStrictEqual(signal, null, 'Process should have exited cleanly,' + ` but did not: ${signal}`); - assert.ok(stderr.match( - '(node:.*) ExperimentalWarning: report is an experimental' + - ' feature. This feature could change at any time'), - std_msg); + assert.strictEqual(stderr.trim(), ''); const reports = helper.findReports(child.pid, tmpdir.path); assert.deepStrictEqual(reports, [], report_msg, reports); diff --git a/test/report/test-report-worker.js b/test/report/test-report-worker.js index a34c05f08431de..feb83a50643b0f 100644 --- a/test/report/test-report-worker.js +++ b/test/report/test-report-worker.js @@ -1,7 +1,5 @@ -// Flags: --experimental-report 'use strict'; const common = require('../common'); -common.skipIfReportDisabled(); const assert = require('assert'); const { Worker } = require('worker_threads'); const { once } = require('events'); diff --git a/test/report/test-report-writereport.js b/test/report/test-report-writereport.js index a72744fcd4fcb7..50514c68373d15 100644 --- a/test/report/test-report-writereport.js +++ b/test/report/test-report-writereport.js @@ -1,9 +1,7 @@ -// Flags: --experimental-report 'use strict'; // Test producing a report via API call, using the no-hooks/no-signal interface. -const common = require('../common'); -common.skipIfReportDisabled(); +require('../common'); const assert = require('assert'); const { spawnSync } = require('child_process'); const fs = require('fs'); @@ -11,9 +9,6 @@ const path = require('path'); const helper = require('../common/report'); const tmpdir = require('../common/tmpdir'); -common.expectWarning('ExperimentalWarning', - 'report is an experimental feature. This feature could ' + - 'change at any time'); tmpdir.refresh(); process.report.directory = tmpdir.path; @@ -93,8 +88,7 @@ function validate() { { // Test the special "stdout" filename. - const args = ['--experimental-report', '-e', - 'process.report.writeReport("stdout")']; + const args = ['-e', 'process.report.writeReport("stdout")']; const child = spawnSync(process.execPath, args, { cwd: tmpdir.path }); assert.strictEqual(child.status, 0); assert.strictEqual(child.signal, null); @@ -104,8 +98,7 @@ function validate() { { // Test the special "stderr" filename. - const args = ['--experimental-report', '-e', - 'process.report.writeReport("stderr")']; + const args = ['-e', 'process.report.writeReport("stderr")']; const child = spawnSync(process.execPath, args, { cwd: tmpdir.path }); assert.strictEqual(child.status, 0); assert.strictEqual(child.signal, null); @@ -118,8 +111,7 @@ function validate() { { // Test the case where the report file cannot be opened. const reportDir = path.join(tmpdir.path, 'does', 'not', 'exist'); - const args = ['--experimental-report', - `--report-directory=${reportDir}`, + const args = [`--report-directory=${reportDir}`, '-e', 'process.report.writeReport()']; const child = spawnSync(process.execPath, args, { cwd: tmpdir.path }); diff --git a/test/root.status b/test/root.status index e3431ec9465066..85d907b1f9cc07 100644 --- a/test/root.status +++ b/test/root.status @@ -64,6 +64,7 @@ parallel/test-next-tick-fixed-queue-regression: SLOW parallel/test-npm-install: SLOW parallel/test-preload: SLOW parallel/test-repl: SLOW +parallel/test-repl-history-navigation.js: SLOW parallel/test-repl-tab-complete: SLOW parallel/test-repl-top-level-await: SLOW parallel/test-stdio-pipe-access: SLOW diff --git a/test/sequential/sequential.status b/test/sequential/sequential.status index 3d432b7bbb0dd3..fce8bd959f0326 100644 --- a/test/sequential/sequential.status +++ b/test/sequential/sequential.status @@ -5,6 +5,8 @@ prefix sequential # sample-test : PASS,FLAKY [true] # This section applies to all platforms +# https://github.com/nodejs/node/issues/27611#issuecomment-613100468 +test-cpu-prof-dir-worker: PASS, FLAKY [$system==win32] # https://github.com/nodejs/node/issues/22327 @@ -15,8 +17,6 @@ test-worker-prof: PASS, FLAKY [$system==linux] [$system==macos] -# https://github.com/nodejs/node/issues/21781 -test-timers-blocking-callback: PASS, FLAKY [$system==solaris] # Also applies to SmartOS @@ -33,3 +33,5 @@ test-buffer-creation-regression: SKIP test-perf-hooks: SKIP [$arch==arm] +# https://github.com/nodejs/node/issues/26401#issuecomment-613095719 +test-worker-prof: PASS, FLAKY diff --git a/test/sequential/test-async-wrap-getasyncid.js b/test/sequential/test-async-wrap-getasyncid.js index 7e9f77cd7a4cc2..ab1f2110a3debc 100644 --- a/test/sequential/test-async-wrap-getasyncid.js +++ b/test/sequential/test-async-wrap-getasyncid.js @@ -51,6 +51,8 @@ const { getSystemErrorName } = require('util'); delete providers.HTTPCLIENTREQUEST; delete providers.HTTPINCOMINGMESSAGE; delete providers.ELDHISTOGRAM; + delete providers.SIGINTWATCHDOG; + delete providers.WORKERHEAPSNAPSHOT; const objKeys = Object.keys(providers); if (objKeys.length > 0) diff --git a/test/sequential/test-module-loading.js b/test/sequential/test-module-loading.js index 2e55eb29369fcd..2a5cb5edd07f57 100644 --- a/test/sequential/test-module-loading.js +++ b/test/sequential/test-module-loading.js @@ -302,17 +302,14 @@ assert.throws( } }, 'fixtures/path.js': {}, - 'fixtures/throws_error.js': {}, 'fixtures/registerExt.test': {}, 'fixtures/registerExt.hello.world': {}, 'fixtures/registerExt2.test': {}, 'fixtures/module-load-order/file1': {}, 'fixtures/module-load-order/file2.js': {}, - 'fixtures/module-load-order/file3.node': {}, 'fixtures/module-load-order/file4.reg': {}, 'fixtures/module-load-order/file5.reg2': {}, 'fixtures/module-load-order/file6/index.js': {}, - 'fixtures/module-load-order/file7/index.node': {}, 'fixtures/module-load-order/file8/index.reg': {}, 'fixtures/module-load-order/file9/index.reg2': {}, 'fixtures/module-require/parent/index.js': { diff --git a/test/sequential/test-net-bytes-per-incoming-chunk-overhead.js b/test/sequential/test-net-bytes-per-incoming-chunk-overhead.js index c2275b570ca08e..6eec8cc3c6d6c8 100644 --- a/test/sequential/test-net-bytes-per-incoming-chunk-overhead.js +++ b/test/sequential/test-net-bytes-per-incoming-chunk-overhead.js @@ -2,6 +2,9 @@ 'use strict'; const common = require('../common'); +if (process.config.variables.asan) + common.skip('ASAN messes with memory measurements'); + const assert = require('assert'); const net = require('net'); diff --git a/test/parallel/test-process-title.js b/test/sequential/test-process-title.js similarity index 100% rename from test/parallel/test-process-title.js rename to test/sequential/test-process-title.js diff --git a/test/sequential/test-timers-blocking-callback.js b/test/sequential/test-timers-blocking-callback.js deleted file mode 100644 index a5e0f596a34b93..00000000000000 --- a/test/sequential/test-timers-blocking-callback.js +++ /dev/null @@ -1,114 +0,0 @@ -// Flags: --expose-internals -'use strict'; - -/* - * This is a regression test for - * https://github.com/nodejs/node-v0.x-archive/issues/15447 and - * https://github.com/nodejs/node-v0.x-archive/issues/9333. - * - * When a timer is added in another timer's callback, its underlying timer - * handle was started with a timeout that was actually incorrect. - * - * The reason was that the value that represents the current time was not - * updated between the time the original callback was called and the time - * the added timer was processed by timers.listOnTimeout. That led the - * logic in timers.listOnTimeout to do an incorrect computation that made - * the added timer fire with a timeout of scheduledTimeout + - * timeSpentInCallback. - * - * This test makes sure that a timer added by another timer's callback - * fires with the expected timeout. - * - * It makes sure that it works when the timers list for a given timeout is - * empty (see testAddingTimerToEmptyTimersList) and when the timers list - * is not empty (see testAddingTimerToNonEmptyTimersList). - */ - -const common = require('../common'); -const assert = require('assert'); -const { sleep } = require('internal/util'); - -const TIMEOUT = 100; - -let nbBlockingCallbackCalls; -let latestDelay; -let timeCallbackScheduled; - -// These tests are timing dependent so they may fail even when the bug is -// not present (if the host is sufficiently busy that the timers are delayed -// significantly). However, they fail 100% of the time when the bug *is* -// present, so to increase reliability, allow for a small number of retries. -let retries = 2; - -function initTest() { - nbBlockingCallbackCalls = 0; - latestDelay = 0; - timeCallbackScheduled = 0; -} - -function blockingCallback(retry, callback) { - ++nbBlockingCallbackCalls; - - if (nbBlockingCallbackCalls > 1) { - latestDelay = Date.now() - timeCallbackScheduled; - // Even if timers can fire later than when they've been scheduled - // to fire, they shouldn't generally be more than 100% late in this case. - // But they are guaranteed to be at least 100ms late given the bug in - // https://github.com/nodejs/node-v0.x-archive/issues/15447 and - // https://github.com/nodejs/node-v0.x-archive/issues/9333. - if (latestDelay >= TIMEOUT * 2) { - if (retries > 0) { - retries--; - return retry(callback); - } - assert.fail(`timeout delayed by more than 100% (${latestDelay}ms)`); - } - if (callback) - return callback(); - } else { - // Block by busy-looping to trigger the issue - sleep(TIMEOUT); - - timeCallbackScheduled = Date.now(); - setTimeout(blockingCallback.bind(null, retry, callback), TIMEOUT); - } -} - -function testAddingTimerToEmptyTimersList(callback) { - initTest(); - // Call setTimeout just once to make sure the timers list is - // empty when blockingCallback is called. - setTimeout( - blockingCallback.bind(null, testAddingTimerToEmptyTimersList, callback), - TIMEOUT - ); -} - -function testAddingTimerToNonEmptyTimersList() { - // If both timers fail and attempt a retry, only actually do anything for one - // of them. - let retryOK = true; - const retry = () => { - if (retryOK) - testAddingTimerToNonEmptyTimersList(); - retryOK = false; - }; - - initTest(); - // Call setTimeout twice with the same timeout to make - // sure the timers list is not empty when blockingCallback is called. - setTimeout( - blockingCallback.bind(null, retry), - TIMEOUT - ); - setTimeout( - blockingCallback.bind(null, retry), - TIMEOUT - ); -} - -// Run the test for the empty timers list case, and then for the non-empty -// timers list one. -testAddingTimerToEmptyTimersList( - common.mustCall(testAddingTimerToNonEmptyTimersList) -); diff --git a/test/wasi/test-return-on-exit.js b/test/wasi/test-return-on-exit.js new file mode 100644 index 00000000000000..3f5d40c9ba7fb8 --- /dev/null +++ b/test/wasi/test-return-on-exit.js @@ -0,0 +1,31 @@ +// Flags: --experimental-wasi-unstable-preview1 --experimental-wasm-bigint +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); +const { WASI } = require('wasi'); +const wasmDir = path.join(__dirname, 'wasm'); +const modulePath = path.join(wasmDir, 'exitcode.wasm'); +const buffer = fs.readFileSync(modulePath); + +(async () => { + const wasi = new WASI({ returnOnExit: true }); + const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; + const { instance } = await WebAssembly.instantiate(buffer, importObject); + + assert.strictEqual(wasi.start(instance), 120); +})().then(common.mustCall()); + +(async () => { + // Verify that if a WASI application throws an exception, Node rethrows it + // properly. + const wasi = new WASI({ returnOnExit: true }); + wasi.wasiImport.proc_exit = () => { throw new Error('test error'); }; + const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; + const { instance } = await WebAssembly.instantiate(buffer, importObject); + + assert.throws(() => { + wasi.start(instance); + }, /^Error: test error$/); +})().then(common.mustCall()); diff --git a/test/wasi/test-wasi-options-validation.js b/test/wasi/test-wasi-options-validation.js index f0aa6932db4ea7..36411bc179cab8 100644 --- a/test/wasi/test-wasi-options-validation.js +++ b/test/wasi/test-wasi-options-validation.js @@ -21,6 +21,10 @@ assert.throws(() => { new WASI({ env: 'fhqwhgads' }); }, assert.throws(() => { new WASI({ preopens: 'fhqwhgads' }); }, { code: 'ERR_INVALID_ARG_TYPE', message: /\bpreopens\b/ }); +// If returnOnExit is not a boolean and not undefined, it should throw. +assert.throws(() => { new WASI({ returnOnExit: 'fhqwhgads' }); }, + { code: 'ERR_INVALID_ARG_TYPE', message: /\breturnOnExit\b/ }); + // If options is provided, but not an object, the constructor should throw. [null, 'foo', '', 0, NaN, Symbol(), true, false, () => {}].forEach((value) => { assert.throws(() => { new WASI(value); }, diff --git a/test/wasi/test-wasi-start-validation.js b/test/wasi/test-wasi-start-validation.js index a31c5847968491..617738442ee64a 100644 --- a/test/wasi/test-wasi-start-validation.js +++ b/test/wasi/test-wasi-start-validation.js @@ -8,85 +8,111 @@ const { WASI } = require('wasi'); const fixtures = require('../common/fixtures'); const bufferSource = fixtures.readSync('simple.wasm'); -{ - const wasi = new WASI(); - assert.throws( - () => { - wasi.start(); - }, - { code: 'ERR_INVALID_ARG_TYPE', message: /\bWebAssembly\.Instance\b/ } - ); -} - (async () => { - const wasi = new WASI({}); - const wasm = await WebAssembly.compile(bufferSource); - const instance = await WebAssembly.instantiate(wasm); + { + // Verify that a WebAssembly.Instance is passed in. + const wasi = new WASI(); - assert.throws( - () => { wasi.start(instance); }, - { code: 'ERR_INVALID_ARG_TYPE', message: /\bWebAssembly\.Memory\b/ } - ); -})(); + assert.throws( + () => { wasi.start(); }, + { code: 'ERR_INVALID_ARG_TYPE', message: /\bWebAssembly\.Instance\b/ } + ); + } -(async () => { - const wasi = new WASI(); - const wasm = await WebAssembly.compile(bufferSource); - const instance = await WebAssembly.instantiate(wasm); - const values = [undefined, null, 'foo', 42, true, false, () => {}]; - let cnt = 0; + { + // Verify that the passed instance has an exports objects. + const wasi = new WASI({}); + const wasm = await WebAssembly.compile(bufferSource); + const instance = await WebAssembly.instantiate(wasm); + + Object.defineProperty(instance, 'exports', { get() { return null; } }); + assert.throws( + () => { wasi.start(instance); }, + { + code: 'ERR_INVALID_ARG_TYPE', + message: /"instance\.exports" property must be of type object/ + } + ); + } - // Mock instance.exports to trigger start() validation. - Object.defineProperty(instance, 'exports', { - get() { return values[cnt++]; } - }); + { + // Verify that a _start() export was passed. + const wasi = new WASI({}); + const wasm = await WebAssembly.compile(bufferSource); + const instance = await WebAssembly.instantiate(wasm); - values.forEach((val) => { + Object.defineProperty(instance, 'exports', { get() { return {}; } }); assert.throws( () => { wasi.start(instance); }, - { code: 'ERR_INVALID_ARG_TYPE', message: /\binstance\.exports\b/ } + { + code: 'ERR_INVALID_ARG_TYPE', + message: /"instance\.exports\._start" property must be of type function/ + } ); - }); -})(); + } -(async () => { - const wasi = new WASI(); - const wasm = await WebAssembly.compile(bufferSource); - const instance = await WebAssembly.instantiate(wasm); + { + // Verify that an _initialize export was not passed. + const wasi = new WASI({}); + const wasm = await WebAssembly.compile(bufferSource); + const instance = await WebAssembly.instantiate(wasm); - // Mock instance.exports.memory to bypass start() validation. - Object.defineProperty(instance, 'exports', { - get() { - return { - memory: new WebAssembly.Memory({ initial: 1 }) - }; - } - }); + Object.defineProperty(instance, 'exports', { + get() { + return { + _start() {}, + _initialize() {} + }; + } + }); + assert.throws( + () => { wasi.start(instance); }, + { + code: 'ERR_INVALID_ARG_TYPE', + message: /"instance\.exports\._initialize" property must be undefined/ + } + ); + } - wasi.start(instance); - assert.throws( - () => { wasi.start(instance); }, - { - code: 'ERR_WASI_ALREADY_STARTED', - message: /^WASI instance has already started$/ - } - ); -})(); + { + // Verify that a memory export was passed. + const wasi = new WASI({}); + const wasm = await WebAssembly.compile(bufferSource); + const instance = await WebAssembly.instantiate(wasm); -(async () => { - const wasi = new WASI(); - const wasm = await WebAssembly.compile(bufferSource); - const instance = await WebAssembly.instantiate(wasm); + Object.defineProperty(instance, 'exports', { + get() { return { _start() {} }; } + }); + assert.throws( + () => { wasi.start(instance); }, + { + code: 'ERR_INVALID_ARG_TYPE', + message: /"instance\.exports\.memory" property .+ WebAssembly\.Memory/ + } + ); + } - // Mock instance.exports to bypass start() validation. - Object.defineProperty(instance, 'exports', { - get() { - return { - memory: new WebAssembly.Memory({ initial: 1 }), - __wasi_unstable_reactor_start: common.mustCall() - }; - } - }); + { + // Verify that start() can only be called once. + const wasi = new WASI({}); + const wasm = await WebAssembly.compile(bufferSource); + const instance = await WebAssembly.instantiate(wasm); - wasi.start(instance); -})(); + Object.defineProperty(instance, 'exports', { + get() { + return { + _start() {}, + memory: new WebAssembly.Memory({ initial: 1 }) + }; + } + }); + wasi.start(instance); + assert.throws( + () => { wasi.start(instance); }, + { + code: 'ERR_WASI_ALREADY_STARTED', + message: /^WASI instance has already started$/ + } + ); + } +})().then(common.mustCall()); diff --git a/tools/code_cache/mkcodecache.cc b/tools/code_cache/mkcodecache.cc index 34af7bc61ba374..fabb6a1a5d2f4d 100644 --- a/tools/code_cache/mkcodecache.cc +++ b/tools/code_cache/mkcodecache.cc @@ -49,8 +49,9 @@ int main(int argc, char* argv[]) { // Create a new Isolate and make it the current one. Isolate::CreateParams create_params; - create_params.array_buffer_allocator = - ArrayBuffer::Allocator::NewDefaultAllocator(); + std::unique_ptr array_buffer_allocator { + ArrayBuffer::Allocator::NewDefaultAllocator() }; + create_params.array_buffer_allocator = array_buffer_allocator.get(); Isolate* isolate = Isolate::New(create_params); { Isolate::Scope isolate_scope(isolate); @@ -65,6 +66,7 @@ int main(int argc, char* argv[]) { out << cache; out.close(); } + isolate->Dispose(); v8::V8::ShutdownPlatform(); return 0; diff --git a/tools/doc/checkLinks.js b/tools/doc/checkLinks.js index 60a3f65e5ea9f1..00697cc01cf01a 100644 --- a/tools/doc/checkLinks.js +++ b/tools/doc/checkLinks.js @@ -27,6 +27,7 @@ function findMarkdownFilesRecursively(dirPath) { if ( entry.isDirectory() && entry.name !== 'api' && + entry.name !== 'tmp' && entry.name !== 'fixtures' && entry.name !== 'changelogs' && entry.name !== 'deps' && diff --git a/tools/doc/html.js b/tools/doc/html.js index acd62c3e8d0ddb..b58563045def8d 100644 --- a/tools/doc/html.js +++ b/tools/doc/html.js @@ -313,23 +313,11 @@ function versionSort(a, b) { function buildToc({ filename, apilinks }) { return (tree, file) => { - const startIncludeRefRE = /^\s*\s*$/; - const endIncludeRefRE = /^\s*\s*$/; - const realFilenames = [filename]; const idCounters = Object.create(null); let toc = ''; let depth = 0; visit(tree, null, (node) => { - // Keep track of the current filename for comment wrappers of inclusions. - if (node.type === 'html') { - const [, includedFileName] = node.value.match(startIncludeRefRE) || []; - if (includedFileName !== undefined) - realFilenames.unshift(includedFileName); - else if (endIncludeRefRE.test(node.value)) - realFilenames.shift(); - } - if (node.type !== 'heading') return; if (node.depth - depth > 1) { @@ -339,7 +327,7 @@ function buildToc({ filename, apilinks }) { } depth = node.depth; - const realFilename = path.basename(realFilenames[0], '.md'); + const realFilename = path.basename(filename, '.md'); const headingText = file.contents.slice( node.children[0].position.start.offset, node.position.end.offset).trim(); diff --git a/tools/doc/type-parser.js b/tools/doc/type-parser.js index ef4499e50ff35a..7470bac5bfb5c7 100644 --- a/tools/doc/type-parser.js +++ b/tools/doc/type-parser.js @@ -15,10 +15,10 @@ const jsPrimitives = { const jsGlobalObjectsUrl = `${jsDocPrefix}Reference/Global_Objects/`; const jsGlobalTypes = [ - 'Array', 'ArrayBuffer', 'ArrayBufferView', 'DataView', 'Date', 'Error', + 'Array', 'ArrayBuffer', 'DataView', 'Date', 'Error', 'EvalError', 'Function', 'Map', 'Object', 'Promise', 'RangeError', 'ReferenceError', 'RegExp', 'Set', 'SharedArrayBuffer', 'SyntaxError', - 'TypeError', 'TypedArray', 'URIError', 'Uint8Array', 'WebAssembly.Instance', + 'TypeError', 'TypedArray', 'URIError', 'Uint8Array', ]; const customTypesMap = { @@ -26,9 +26,14 @@ const customTypesMap = { 'this': `${jsDocPrefix}Reference/Operators/this`, + 'ArrayBufferView': + 'https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView', + 'AsyncIterator': 'https://tc39.github.io/ecma262/#sec-asynciterator-interface', 'bigint': `${jsDocPrefix}Reference/Global_Objects/BigInt`, + 'WebAssembly.Instance': + `${jsDocPrefix}Reference/Global_Objects/WebAssembly/Instance`, 'Iterable': `${jsDocPrefix}Reference/Iteration_protocols#The_iterable_protocol`, @@ -101,6 +106,10 @@ const customTypesMap = { 'https.Server': 'https.html#https_class_https_server', 'module': 'modules.html#modules_the_module_object', + + 'module.SourceMap': + 'modules.html#modules_class_module_sourcemap', + 'require': 'modules.html#modules_require_id', 'Handle': 'net.html#net_server_listen_handle_backlog_callback', diff --git a/tools/eslint-rules/prefer-common-expectserror.js b/tools/eslint-rules/prefer-common-expectserror.js deleted file mode 100644 index f33241697a68ef..00000000000000 --- a/tools/eslint-rules/prefer-common-expectserror.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; - -//------------------------------------------------------------------------------ -// Rule Definition -//------------------------------------------------------------------------------ - -const msg = 'Please use common.expectsError(fn, err) instead of ' + - 'assert.throws(fn, common.expectsError(err)).'; - -const astSelector = - 'CallExpression[arguments.length=2]' + - '[callee.object.name="assert"]' + - '[callee.property.name="throws"]' + - '[arguments.1.callee.object.name="common"]' + - '[arguments.1.callee.property.name="expectsError"]'; - -module.exports = function(context) { - return { - [astSelector]: (node) => context.report(node, msg) - }; -}; diff --git a/tools/icu/current_ver.dep b/tools/icu/current_ver.dep index 2980335bdd4b3b..f22f158c30bcfd 100644 --- a/tools/icu/current_ver.dep +++ b/tools/icu/current_ver.dep @@ -1,6 +1,6 @@ [ { - "url": "https://github.com/unicode-org/icu/releases/download/release-65-1/icu4c-65_1-src.tgz", - "md5": "d1ff436e26cabcb28e6cb383d32d1339" + "url": "https://github.com/unicode-org/icu/releases/download/release-67-1/icu4c-67_1-src.tgz", + "md5": "c4d62b497cbd89ab2a9ca6b543e57b30" } ] diff --git a/tools/lint-md.js b/tools/lint-md.js index 35df2b11fcb936..a926298f025334 100644 --- a/tools/lint-md.js +++ b/tools/lint-md.js @@ -195,6 +195,8 @@ function trough() { } } +var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + function commonjsRequire () { throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs'); } @@ -5894,7 +5896,7 @@ var deepExtend = module.exports = function (/*obj_1, [obj_2], [obj_N]*/) { var minimist = function (args, opts) { if (!opts) opts = {}; - + var flags = { bools : {}, strings : {}, unknownFn: null }; if (typeof opts['unknown'] === 'function') { @@ -5908,7 +5910,7 @@ var minimist = function (args, opts) { flags.bools[key] = true; }); } - + var aliases = {}; Object.keys(opts.alias || {}).forEach(function (key) { aliases[key] = [].concat(opts.alias[key]); @@ -5927,12 +5929,12 @@ var minimist = function (args, opts) { }); var defaults = opts['default'] || {}; - + var argv = { _ : [] }; Object.keys(flags.bools).forEach(function (key) { setArg(key, defaults[key] === undefined ? false : defaults[key]); }); - + var notFlags = []; if (args.indexOf('--') !== -1) { @@ -5954,7 +5956,7 @@ var minimist = function (args, opts) { ? Number(val) : val ; setKey(argv, key.split('.'), value); - + (aliases[key] || []).forEach(function (x) { setKey(argv, x.split('.'), value); }); @@ -5987,7 +5989,7 @@ var minimist = function (args, opts) { o[key] = [ o[key], value ]; } } - + function aliasIsBoolean(key) { return aliases[key].some(function (x) { return flags.bools[x]; @@ -5996,7 +5998,7 @@ var minimist = function (args, opts) { for (var i = 0; i < args.length; i++) { var arg = args[i]; - + if (/^--.+=/.test(arg)) { // Using [\s\S] instead of . because js doesn't support the // 'dotall' regex modifier. See: @@ -6033,29 +6035,29 @@ var minimist = function (args, opts) { } else if (/^-[^-]+/.test(arg)) { var letters = arg.slice(1,-1).split(''); - + var broken = false; for (var j = 0; j < letters.length; j++) { var next = arg.slice(j+2); - + if (next === '-') { setArg(letters[j], next, arg); continue; } - + if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) { setArg(letters[j], next.split('=')[1], arg); broken = true; break; } - + if (/[A-Za-z]/.test(letters[j]) && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { setArg(letters[j], next, arg); broken = true; break; } - + if (letters[j+1] && letters[j+1].match(/\W/)) { setArg(letters[j], arg.slice(j+2), arg); broken = true; @@ -6065,7 +6067,7 @@ var minimist = function (args, opts) { setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg); } } - + var key = arg.slice(-1)[0]; if (!broken && key !== '-') { if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1]) @@ -6095,17 +6097,17 @@ var minimist = function (args, opts) { } } } - + Object.keys(defaults).forEach(function (key) { if (!hasKey(argv, key.split('.'))) { setKey(argv, key.split('.'), defaults[key]); - + (aliases[key] || []).forEach(function (x) { setKey(argv, x.split('.'), defaults[key]); }); } }); - + if (opts['--']) { argv['--'] = new Array(); notFlags.forEach(function(key) { @@ -14436,155 +14438,155 @@ var escapeStringRegexp = function (str) { return str.replace(matchOperatorsRe, '\\$&'); }; -var colorName = { - "aliceblue": [240, 248, 255], - "antiquewhite": [250, 235, 215], - "aqua": [0, 255, 255], - "aquamarine": [127, 255, 212], - "azure": [240, 255, 255], - "beige": [245, 245, 220], - "bisque": [255, 228, 196], - "black": [0, 0, 0], - "blanchedalmond": [255, 235, 205], - "blue": [0, 0, 255], - "blueviolet": [138, 43, 226], - "brown": [165, 42, 42], - "burlywood": [222, 184, 135], - "cadetblue": [95, 158, 160], - "chartreuse": [127, 255, 0], - "chocolate": [210, 105, 30], - "coral": [255, 127, 80], - "cornflowerblue": [100, 149, 237], - "cornsilk": [255, 248, 220], - "crimson": [220, 20, 60], - "cyan": [0, 255, 255], - "darkblue": [0, 0, 139], - "darkcyan": [0, 139, 139], - "darkgoldenrod": [184, 134, 11], - "darkgray": [169, 169, 169], - "darkgreen": [0, 100, 0], - "darkgrey": [169, 169, 169], - "darkkhaki": [189, 183, 107], - "darkmagenta": [139, 0, 139], - "darkolivegreen": [85, 107, 47], - "darkorange": [255, 140, 0], - "darkorchid": [153, 50, 204], - "darkred": [139, 0, 0], - "darksalmon": [233, 150, 122], - "darkseagreen": [143, 188, 143], - "darkslateblue": [72, 61, 139], - "darkslategray": [47, 79, 79], - "darkslategrey": [47, 79, 79], - "darkturquoise": [0, 206, 209], - "darkviolet": [148, 0, 211], - "deeppink": [255, 20, 147], - "deepskyblue": [0, 191, 255], - "dimgray": [105, 105, 105], - "dimgrey": [105, 105, 105], - "dodgerblue": [30, 144, 255], - "firebrick": [178, 34, 34], - "floralwhite": [255, 250, 240], - "forestgreen": [34, 139, 34], - "fuchsia": [255, 0, 255], - "gainsboro": [220, 220, 220], - "ghostwhite": [248, 248, 255], - "gold": [255, 215, 0], - "goldenrod": [218, 165, 32], - "gray": [128, 128, 128], - "green": [0, 128, 0], - "greenyellow": [173, 255, 47], - "grey": [128, 128, 128], - "honeydew": [240, 255, 240], - "hotpink": [255, 105, 180], - "indianred": [205, 92, 92], - "indigo": [75, 0, 130], - "ivory": [255, 255, 240], - "khaki": [240, 230, 140], - "lavender": [230, 230, 250], - "lavenderblush": [255, 240, 245], - "lawngreen": [124, 252, 0], - "lemonchiffon": [255, 250, 205], - "lightblue": [173, 216, 230], - "lightcoral": [240, 128, 128], - "lightcyan": [224, 255, 255], - "lightgoldenrodyellow": [250, 250, 210], - "lightgray": [211, 211, 211], - "lightgreen": [144, 238, 144], - "lightgrey": [211, 211, 211], - "lightpink": [255, 182, 193], - "lightsalmon": [255, 160, 122], - "lightseagreen": [32, 178, 170], - "lightskyblue": [135, 206, 250], - "lightslategray": [119, 136, 153], - "lightslategrey": [119, 136, 153], - "lightsteelblue": [176, 196, 222], - "lightyellow": [255, 255, 224], - "lime": [0, 255, 0], - "limegreen": [50, 205, 50], - "linen": [250, 240, 230], - "magenta": [255, 0, 255], - "maroon": [128, 0, 0], - "mediumaquamarine": [102, 205, 170], - "mediumblue": [0, 0, 205], - "mediumorchid": [186, 85, 211], - "mediumpurple": [147, 112, 219], - "mediumseagreen": [60, 179, 113], - "mediumslateblue": [123, 104, 238], - "mediumspringgreen": [0, 250, 154], - "mediumturquoise": [72, 209, 204], - "mediumvioletred": [199, 21, 133], - "midnightblue": [25, 25, 112], - "mintcream": [245, 255, 250], - "mistyrose": [255, 228, 225], - "moccasin": [255, 228, 181], - "navajowhite": [255, 222, 173], - "navy": [0, 0, 128], - "oldlace": [253, 245, 230], - "olive": [128, 128, 0], - "olivedrab": [107, 142, 35], - "orange": [255, 165, 0], - "orangered": [255, 69, 0], - "orchid": [218, 112, 214], - "palegoldenrod": [238, 232, 170], - "palegreen": [152, 251, 152], - "paleturquoise": [175, 238, 238], - "palevioletred": [219, 112, 147], - "papayawhip": [255, 239, 213], - "peachpuff": [255, 218, 185], - "peru": [205, 133, 63], - "pink": [255, 192, 203], - "plum": [221, 160, 221], - "powderblue": [176, 224, 230], - "purple": [128, 0, 128], - "rebeccapurple": [102, 51, 153], - "red": [255, 0, 0], - "rosybrown": [188, 143, 143], - "royalblue": [65, 105, 225], - "saddlebrown": [139, 69, 19], - "salmon": [250, 128, 114], - "sandybrown": [244, 164, 96], - "seagreen": [46, 139, 87], - "seashell": [255, 245, 238], - "sienna": [160, 82, 45], - "silver": [192, 192, 192], - "skyblue": [135, 206, 235], - "slateblue": [106, 90, 205], - "slategray": [112, 128, 144], - "slategrey": [112, 128, 144], - "snow": [255, 250, 250], - "springgreen": [0, 255, 127], - "steelblue": [70, 130, 180], - "tan": [210, 180, 140], - "teal": [0, 128, 128], - "thistle": [216, 191, 216], - "tomato": [255, 99, 71], - "turquoise": [64, 224, 208], - "violet": [238, 130, 238], - "wheat": [245, 222, 179], - "white": [255, 255, 255], - "whitesmoke": [245, 245, 245], - "yellow": [255, 255, 0], - "yellowgreen": [154, 205, 50] +var colorName = { + "aliceblue": [240, 248, 255], + "antiquewhite": [250, 235, 215], + "aqua": [0, 255, 255], + "aquamarine": [127, 255, 212], + "azure": [240, 255, 255], + "beige": [245, 245, 220], + "bisque": [255, 228, 196], + "black": [0, 0, 0], + "blanchedalmond": [255, 235, 205], + "blue": [0, 0, 255], + "blueviolet": [138, 43, 226], + "brown": [165, 42, 42], + "burlywood": [222, 184, 135], + "cadetblue": [95, 158, 160], + "chartreuse": [127, 255, 0], + "chocolate": [210, 105, 30], + "coral": [255, 127, 80], + "cornflowerblue": [100, 149, 237], + "cornsilk": [255, 248, 220], + "crimson": [220, 20, 60], + "cyan": [0, 255, 255], + "darkblue": [0, 0, 139], + "darkcyan": [0, 139, 139], + "darkgoldenrod": [184, 134, 11], + "darkgray": [169, 169, 169], + "darkgreen": [0, 100, 0], + "darkgrey": [169, 169, 169], + "darkkhaki": [189, 183, 107], + "darkmagenta": [139, 0, 139], + "darkolivegreen": [85, 107, 47], + "darkorange": [255, 140, 0], + "darkorchid": [153, 50, 204], + "darkred": [139, 0, 0], + "darksalmon": [233, 150, 122], + "darkseagreen": [143, 188, 143], + "darkslateblue": [72, 61, 139], + "darkslategray": [47, 79, 79], + "darkslategrey": [47, 79, 79], + "darkturquoise": [0, 206, 209], + "darkviolet": [148, 0, 211], + "deeppink": [255, 20, 147], + "deepskyblue": [0, 191, 255], + "dimgray": [105, 105, 105], + "dimgrey": [105, 105, 105], + "dodgerblue": [30, 144, 255], + "firebrick": [178, 34, 34], + "floralwhite": [255, 250, 240], + "forestgreen": [34, 139, 34], + "fuchsia": [255, 0, 255], + "gainsboro": [220, 220, 220], + "ghostwhite": [248, 248, 255], + "gold": [255, 215, 0], + "goldenrod": [218, 165, 32], + "gray": [128, 128, 128], + "green": [0, 128, 0], + "greenyellow": [173, 255, 47], + "grey": [128, 128, 128], + "honeydew": [240, 255, 240], + "hotpink": [255, 105, 180], + "indianred": [205, 92, 92], + "indigo": [75, 0, 130], + "ivory": [255, 255, 240], + "khaki": [240, 230, 140], + "lavender": [230, 230, 250], + "lavenderblush": [255, 240, 245], + "lawngreen": [124, 252, 0], + "lemonchiffon": [255, 250, 205], + "lightblue": [173, 216, 230], + "lightcoral": [240, 128, 128], + "lightcyan": [224, 255, 255], + "lightgoldenrodyellow": [250, 250, 210], + "lightgray": [211, 211, 211], + "lightgreen": [144, 238, 144], + "lightgrey": [211, 211, 211], + "lightpink": [255, 182, 193], + "lightsalmon": [255, 160, 122], + "lightseagreen": [32, 178, 170], + "lightskyblue": [135, 206, 250], + "lightslategray": [119, 136, 153], + "lightslategrey": [119, 136, 153], + "lightsteelblue": [176, 196, 222], + "lightyellow": [255, 255, 224], + "lime": [0, 255, 0], + "limegreen": [50, 205, 50], + "linen": [250, 240, 230], + "magenta": [255, 0, 255], + "maroon": [128, 0, 0], + "mediumaquamarine": [102, 205, 170], + "mediumblue": [0, 0, 205], + "mediumorchid": [186, 85, 211], + "mediumpurple": [147, 112, 219], + "mediumseagreen": [60, 179, 113], + "mediumslateblue": [123, 104, 238], + "mediumspringgreen": [0, 250, 154], + "mediumturquoise": [72, 209, 204], + "mediumvioletred": [199, 21, 133], + "midnightblue": [25, 25, 112], + "mintcream": [245, 255, 250], + "mistyrose": [255, 228, 225], + "moccasin": [255, 228, 181], + "navajowhite": [255, 222, 173], + "navy": [0, 0, 128], + "oldlace": [253, 245, 230], + "olive": [128, 128, 0], + "olivedrab": [107, 142, 35], + "orange": [255, 165, 0], + "orangered": [255, 69, 0], + "orchid": [218, 112, 214], + "palegoldenrod": [238, 232, 170], + "palegreen": [152, 251, 152], + "paleturquoise": [175, 238, 238], + "palevioletred": [219, 112, 147], + "papayawhip": [255, 239, 213], + "peachpuff": [255, 218, 185], + "peru": [205, 133, 63], + "pink": [255, 192, 203], + "plum": [221, 160, 221], + "powderblue": [176, 224, 230], + "purple": [128, 0, 128], + "rebeccapurple": [102, 51, 153], + "red": [255, 0, 0], + "rosybrown": [188, 143, 143], + "royalblue": [65, 105, 225], + "saddlebrown": [139, 69, 19], + "salmon": [250, 128, 114], + "sandybrown": [244, 164, 96], + "seagreen": [46, 139, 87], + "seashell": [255, 245, 238], + "sienna": [160, 82, 45], + "silver": [192, 192, 192], + "skyblue": [135, 206, 235], + "slateblue": [106, 90, 205], + "slategray": [112, 128, 144], + "slategrey": [112, 128, 144], + "snow": [255, 250, 250], + "springgreen": [0, 255, 127], + "steelblue": [70, 130, 180], + "tan": [210, 180, 140], + "teal": [0, 128, 128], + "thistle": [216, 191, 216], + "tomato": [255, 99, 71], + "turquoise": [64, 224, 208], + "violet": [238, 130, 238], + "wheat": [245, 222, 179], + "white": [255, 255, 255], + "whitesmoke": [245, 245, 245], + "yellow": [255, 255, 0], + "yellowgreen": [154, 205, 50] }; var conversions = createCommonjsModule(function (module) { @@ -22580,7 +22582,7 @@ var textTable = function (rows_, opts) { var stringLength = opts.stringLength || function (s) { return String(s).length; } ; - + var dotsizes = reduce(rows_, function (acc, row) { forEach(row, function (c, ix) { var n = dotindex(c); @@ -22588,7 +22590,7 @@ var textTable = function (rows_, opts) { }); return acc; }, []); - + var rows = map$1(rows_, function (row) { return map$1(row, function (c_, ix) { var c = String(c_); @@ -22602,7 +22604,7 @@ var textTable = function (rows_, opts) { else return c; }); }); - + var sizes = reduce(rows, function (acc, row) { forEach(row, function (c, ix) { var n = stringLength(c); @@ -22610,7 +22612,7 @@ var textTable = function (rows_, opts) { }); return acc; }, []); - + return map$1(rows, function (row) { return map$1(row, function (c, ix) { var n = (sizes[ix] - stringLength(c)) || 0; @@ -22623,7 +22625,7 @@ var textTable = function (rows_, opts) { + c + Array(Math.floor(n / 2 + 1)).join(' ') ; } - + return c + s; }).join(hsep).replace(/\s+$/, ''); }).join('\n'); @@ -40953,7 +40955,7 @@ const dependencies$1 = { "markdown-extensions": "^1.1.1", remark: "^11.0.2", "remark-lint": "^6.0.5", - "remark-preset-lint-node": "^1.13.0", + "remark-preset-lint-node": "^1.15.0", "unified-args": "^7.1.0" }; const main = "dist/index.js"; @@ -40983,43 +40985,291 @@ var _package$3 = /*#__PURE__*/Object.freeze({ 'default': _package$2 }); -/* Map of allowed verbs. */ -var ALLOWED_VERBS = { - enable: true, - disable: true, - ignore: true -}; +var vfileLocation$1 = factory$7; + +function factory$7(file) { + var contents = indices$1(String(file)); + + return { + toPosition: offsetToPositionFactory$1(contents), + toOffset: positionToOffsetFactory$1(contents) + } +} + +// Factory to get the line and column-based `position` for `offset` in the bound +// indices. +function offsetToPositionFactory$1(indices) { + return offsetToPosition + + // Get the line and column-based `position` for `offset` in the bound indices. + function offsetToPosition(offset) { + var index = -1; + var length = indices.length; + + if (offset < 0) { + return {} + } + + while (++index < length) { + if (indices[index] > offset) { + return { + line: index + 1, + column: offset - (indices[index - 1] || 0) + 1, + offset: offset + } + } + } + + return {} + } +} + +// Factory to get the `offset` for a line and column-based `position` in the +// bound indices. +function positionToOffsetFactory$1(indices) { + return positionToOffset + + // Get the `offset` for a line and column-based `position` in the bound + // indices. + function positionToOffset(position) { + var line = position && position.line; + var column = position && position.column; + + if (!isNaN(line) && !isNaN(column) && line - 1 in indices) { + return (indices[line - 2] || 0) + column - 1 || 0 + } + + return -1 + } +} + +// Get indices of line-breaks in `value`. +function indices$1(value) { + var result = []; + var index = value.indexOf('\n'); + + while (index !== -1) { + result.push(index + 1); + index = value.indexOf('\n', index + 1); + } + + result.push(value.length + 1); + + return result +} + +var convert_1$1 = convert$2; + +function convert$2(test) { + if (typeof test === 'string') { + return typeFactory$1(test) + } + + if (test === null || test === undefined) { + return ok$2 + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$1 : matchesFactory$1)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$1(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$2(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$1(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$1(tests) { + var checks = convertAll$1(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$1(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$2() { + return true +} + +var unistUtilVisitParents$1 = visitParents$1; + + + +var CONTINUE$2 = true; +var SKIP$2 = 'skip'; +var EXIT$2 = false; + +visitParents$1.CONTINUE = CONTINUE$2; +visitParents$1.SKIP = SKIP$2; +visitParents$1.EXIT = EXIT$2; + +function visitParents$1(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$1(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$1(visitor(node, parents)); + + if (result[0] === EXIT$2) { + return result + } + } + + if (node.children && result[0] !== SKIP$2) { + subresult = toResult$1(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$2 ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$2) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$1(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$2, value] + } + + return [value] +} + +var unistUtilVisit$1 = visit$1; + + + +var CONTINUE$3 = unistUtilVisitParents$1.CONTINUE; +var SKIP$3 = unistUtilVisitParents$1.SKIP; +var EXIT$3 = unistUtilVisitParents$1.EXIT; + +visit$1.CONTINUE = CONTINUE$3; +visit$1.SKIP = SKIP$3; +visit$1.EXIT = EXIT$3; + +function visit$1(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$1(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} var unifiedMessageControl = messageControl; function messageControl(options) { - var name = options && options.name; - var marker = options && options.marker; - var test = options && options.test; - var sources; - var known; - var reset; - var enable; - var disable; + var settings = options || {}; + var name = settings.name; + var marker = settings.marker; + var test = settings.test; + var sources = settings.source; + var known = settings.known; + var reset = settings.reset; + var enable = settings.enable || []; + var disable = settings.disable || []; if (!name) { throw new Error('Expected `name` in `options`, got `' + name + '`') } if (!marker) { - throw new Error('Expected `name` in `options`, got `' + name + '`') + throw new Error('Expected `marker` in `options`, got `' + marker + '`') } - if (!test) { - throw new Error('Expected `test` in `options`, got `' + test + '`') - } - - known = options.known; - reset = options.reset; - enable = options.enable || []; - disable = options.disable || []; - sources = options.source; - if (!sources) { sources = [name]; } else if (typeof sources === 'string') { @@ -41029,13 +41279,13 @@ function messageControl(options) { return transformer function transformer(tree, file) { - var toOffset = vfileLocation(file).toOffset; + var toOffset = vfileLocation$1(file).toOffset; var initial = !reset; var gaps = detectGaps(tree, file); var scope = {}; var globals = []; - unistUtilVisit(tree, test, visitor); + unistUtilVisit$1(tree, test, visitor); file.messages = file.messages.filter(filter); @@ -41050,7 +41300,7 @@ function messageControl(options) { var pos; var tail; - if (!mark || mark.name !== options.name) { + if (!mark || mark.name !== name) { return } @@ -41060,7 +41310,7 @@ function messageControl(options) { pos = mark.node.position && mark.node.position.start; tail = next && next.position && next.position.end; - if (!verb || !ALLOWED_VERBS[verb] === true) { + if (verb !== 'enable' && verb !== 'disable' && verb !== 'ignore') { file.fail( 'Unknown keyword `' + verb + @@ -41073,20 +41323,8 @@ function messageControl(options) { length = ruleIds.length; index = -1; - while (++index < length) { - ruleId = ruleIds[index]; - - if (isKnown(ruleId, verb, mark.node)) { - toggle(pos, verb === 'enable', ruleId); - - if (verb === 'ignore') { - toggle(tail, true, ruleId); - } - } - } - - /* Apply to all rules. */ - if (!length) { + // Apply to all rules. + if (length === 0) { if (verb === 'ignore') { toggle(pos, false); toggle(tail, true); @@ -41094,6 +41332,18 @@ function messageControl(options) { toggle(pos, verb === 'enable'); reset = verb !== 'enable'; } + } else { + while (++index < length) { + ruleId = ruleIds[index]; + + if (isKnown(ruleId, verb, mark.node)) { + toggle(pos, verb === 'enable', ruleId); + + if (verb === 'ignore') { + toggle(tail, true, ruleId); + } + } + } } } @@ -41103,13 +41353,13 @@ function messageControl(options) { var ranges = scope[ruleId]; var pos; - /* Keep messages from a different source. */ + // Keep messages from a different source. if (!message.source || sources.indexOf(message.source) === -1) { return true } - /* We only ignore messages if they‘re disabled, - * *not* when they’re not in the document. */ + // We only ignore messages if they‘re disabled, *not* when they’re not in + // the document. if (!message.line) { message.line = 1; } @@ -41118,7 +41368,7 @@ function messageControl(options) { message.column = 1; } - /* Check whether the warning is inside a gap. */ + // Check whether the warning is inside a gap. pos = toOffset(message); while (gapIndex--) { @@ -41127,22 +41377,26 @@ function messageControl(options) { } } - /* Check whether allowed by specific and global states. */ + // Check whether allowed by specific and global states. return check(message, ranges, ruleId) && check(message, globals) } - /* Helper to check (and possibly warn) if a ruleId is unknown. */ + // Helper to check (and possibly warn) if a `ruleId` is unknown. function isKnown(ruleId, verb, pos) { var result = known ? known.indexOf(ruleId) !== -1 : true; if (!result) { - file.warn('Unknown rule: cannot ' + verb + " `'" + ruleId + "'`", pos); + file.message( + 'Unknown rule: cannot ' + verb + " `'" + ruleId + "'`", + pos + ); } return result } - /* Get the latest state of a rule. When without `ruleId`, gets global state. */ + // Get the latest state of a rule. + // When without `ruleId`, gets global state. function getState(ruleId) { var ranges = ruleId ? scope[ruleId] : globals; @@ -41161,10 +41415,9 @@ function messageControl(options) { return disable.indexOf(ruleId) === -1 } - /* Handle a rule. */ + // Handle a rule. function toggle(pos, state, ruleId) { var markers = ruleId ? scope[ruleId] : globals; - var currentState; var previousState; if (!markers) { @@ -41173,13 +41426,12 @@ function messageControl(options) { } previousState = getState(ruleId); - currentState = state; - if (currentState !== previousState) { - markers.push({state: currentState, position: pos}); + if (state !== previousState) { + markers.push({state: state, position: pos}); } - /* Toggle all known rules. */ + // Toggle all known rules. if (!ruleId) { for (ruleId in scope) { toggle(pos, state, ruleId); @@ -41187,9 +41439,9 @@ function messageControl(options) { } } - /* Check all `ranges` for `message`. */ + // Check all `ranges` for `message`. function check(message, ranges, id) { - /* Check the state at the message's position. */ + // Check the state at the message’s position. var index = ranges && ranges.length; var length = -1; var range; @@ -41197,7 +41449,7 @@ function messageControl(options) { while (--index > length) { range = ranges[index]; - /* istanbul ignore if - generated marker. */ + /* istanbul ignore if - Generated marker. */ if (!range.position || !range.position.line || !range.position.column) { continue } @@ -41205,14 +41457,14 @@ function messageControl(options) { if ( range.position.line < message.line || (range.position.line === message.line && - range.position.column < message.column) + range.position.column <= message.column) ) { return range.state === true } } - /* The first marker ocurred after the first - * message, so we check the initial state. */ + // The first marker ocurred after the first message, so we check the + // initial state. if (!id) { return initial || reset } @@ -41222,26 +41474,26 @@ function messageControl(options) { } } -/* Detect gaps in `ast`. */ +// Detect gaps in `tree`. function detectGaps(tree, file) { var lastNode = tree.children[tree.children.length - 1]; var offset = 0; var isGap = false; var gaps = []; - /* Find all gaps. */ - unistUtilVisit(tree, one); + // Find all gaps. + unistUtilVisit$1(tree, one); - /* Get the end of the document. - * This detects if the last node was the last node. - * If not, there’s an extra gap between the last node - * and the end of the document. */ + // Get the end of the document. + // This detects if the last node was the last node. + // If not, there’s an extra gap between the last node and the end of the + // document. if ( lastNode && lastNode.position && lastNode.position.end && offset === lastNode.position.end.offset && - trim_1(file.toString().slice(offset)) !== '' + trim(file.toString().slice(offset)) !== '' ) { update(); @@ -41262,7 +41514,7 @@ function detectGaps(tree, file) { } } - /* Detect a new position. */ + // Detect a new position. function update(latest) { if (latest === null || latest === undefined) { isGap = true; @@ -41282,6 +41534,10 @@ function detectGaps(tree, file) { } } +function trim(value) { + return value.replace(/^\s*|\s*$/g, '') +} + var mdastCommentMarker = marker$1; var whiteSpaceExpression = /\s+/g; @@ -41367,7 +41623,7 @@ var test = [ ]; function messageControl$1(options) { - return unifiedMessageControl(immutable({marker: mdastCommentMarker, test: test}, options)) + return unifiedMessageControl(Object.assign({marker: mdastCommentMarker, test: test}, options)) } var remarkLint = lint; @@ -41383,6 +41639,583 @@ function lintMessageControl() { return remarkMessageControl({name: 'lint', source: 'remark-lint'}) } +var vfileLocation$2 = factory$8; + +function factory$8(file) { + var contents = indices$2(String(file)); + + return { + toPosition: offsetToPositionFactory$2(contents), + toOffset: positionToOffsetFactory$2(contents) + } +} + +// Factory to get the line and column-based `position` for `offset` in the bound +// indices. +function offsetToPositionFactory$2(indices) { + return offsetToPosition + + // Get the line and column-based `position` for `offset` in the bound indices. + function offsetToPosition(offset) { + var index = -1; + var length = indices.length; + + if (offset < 0) { + return {} + } + + while (++index < length) { + if (indices[index] > offset) { + return { + line: index + 1, + column: offset - (indices[index - 1] || 0) + 1, + offset: offset + } + } + } + + return {} + } +} + +// Factory to get the `offset` for a line and column-based `position` in the +// bound indices. +function positionToOffsetFactory$2(indices) { + return positionToOffset + + // Get the `offset` for a line and column-based `position` in the bound + // indices. + function positionToOffset(position) { + var line = position && position.line; + var column = position && position.column; + + if (!isNaN(line) && !isNaN(column) && line - 1 in indices) { + return (indices[line - 2] || 0) + column - 1 || 0 + } + + return -1 + } +} + +// Get indices of line-breaks in `value`. +function indices$2(value) { + var result = []; + var index = value.indexOf('\n'); + + while (index !== -1) { + result.push(index + 1); + index = value.indexOf('\n', index + 1); + } + + result.push(value.length + 1); + + return result +} + +var convert_1$2 = convert$3; + +function convert$3(test) { + if (typeof test === 'string') { + return typeFactory$2(test) + } + + if (test === null || test === undefined) { + return ok$3 + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$2 : matchesFactory$2)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$2(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$3(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$2(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$2(tests) { + var checks = convertAll$2(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$2(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$3() { + return true +} + +var unistUtilVisitParents$2 = visitParents$2; + + + +var CONTINUE$4 = true; +var SKIP$4 = 'skip'; +var EXIT$4 = false; + +visitParents$2.CONTINUE = CONTINUE$4; +visitParents$2.SKIP = SKIP$4; +visitParents$2.EXIT = EXIT$4; + +function visitParents$2(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$2(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$2(visitor(node, parents)); + + if (result[0] === EXIT$4) { + return result + } + } + + if (node.children && result[0] !== SKIP$4) { + subresult = toResult$2(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$4 ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$4) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$2(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$4, value] + } + + return [value] +} + +var unistUtilVisit$2 = visit$2; + + + +var CONTINUE$5 = unistUtilVisitParents$2.CONTINUE; +var SKIP$5 = unistUtilVisitParents$2.SKIP; +var EXIT$5 = unistUtilVisitParents$2.EXIT; + +visit$2.CONTINUE = CONTINUE$5; +visit$2.SKIP = SKIP$5; +visit$2.EXIT = EXIT$5; + +function visit$2(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$2(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var unifiedMessageControl$1 = messageControl$2; + +function messageControl$2(options) { + var settings = options || {}; + var name = settings.name; + var marker = settings.marker; + var test = settings.test; + var sources = settings.source; + var known = settings.known; + var reset = settings.reset; + var enable = settings.enable || []; + var disable = settings.disable || []; + + if (!name) { + throw new Error('Expected `name` in `options`, got `' + name + '`') + } + + if (!marker) { + throw new Error('Expected `marker` in `options`, got `' + marker + '`') + } + + if (!sources) { + sources = [name]; + } else if (typeof sources === 'string') { + sources = [sources]; + } + + return transformer + + function transformer(tree, file) { + var toOffset = vfileLocation$2(file).toOffset; + var initial = !reset; + var gaps = detectGaps$1(tree, file); + var scope = {}; + var globals = []; + + unistUtilVisit$2(tree, test, visitor); + + file.messages = file.messages.filter(filter); + + function visitor(node, position, parent) { + var mark = marker(node); + var ruleIds; + var ruleId; + var verb; + var index; + var length; + var next; + var pos; + var tail; + + if (!mark || mark.name !== name) { + return + } + + ruleIds = mark.attributes.split(/\s/g); + verb = ruleIds.shift(); + next = parent.children[position + 1]; + pos = mark.node.position && mark.node.position.start; + tail = next && next.position && next.position.end; + + if (verb !== 'enable' && verb !== 'disable' && verb !== 'ignore') { + file.fail( + 'Unknown keyword `' + + verb + + '`: expected ' + + "`'enable'`, `'disable'`, or `'ignore'`", + mark.node + ); + } + + length = ruleIds.length; + index = -1; + + // Apply to all rules. + if (length === 0) { + if (verb === 'ignore') { + toggle(pos, false); + toggle(tail, true); + } else { + toggle(pos, verb === 'enable'); + reset = verb !== 'enable'; + } + } else { + while (++index < length) { + ruleId = ruleIds[index]; + + if (isKnown(ruleId, verb, mark.node)) { + toggle(pos, verb === 'enable', ruleId); + + if (verb === 'ignore') { + toggle(tail, true, ruleId); + } + } + } + } + } + + function filter(message) { + var gapIndex = gaps.length; + var ruleId = message.ruleId; + var ranges = scope[ruleId]; + var pos; + + // Keep messages from a different source. + if (!message.source || sources.indexOf(message.source) === -1) { + return true + } + + // We only ignore messages if they‘re disabled, *not* when they’re not in + // the document. + if (!message.line) { + message.line = 1; + } + + if (!message.column) { + message.column = 1; + } + + // Check whether the warning is inside a gap. + pos = toOffset(message); + + while (gapIndex--) { + if (gaps[gapIndex].start <= pos && gaps[gapIndex].end > pos) { + return false + } + } + + // Check whether allowed by specific and global states. + return check(message, ranges, ruleId) && check(message, globals) + } + + // Helper to check (and possibly warn) if a `ruleId` is unknown. + function isKnown(ruleId, verb, pos) { + var result = known ? known.indexOf(ruleId) !== -1 : true; + + if (!result) { + file.message( + 'Unknown rule: cannot ' + verb + " `'" + ruleId + "'`", + pos + ); + } + + return result + } + + // Get the latest state of a rule. + // When without `ruleId`, gets global state. + function getState(ruleId) { + var ranges = ruleId ? scope[ruleId] : globals; + + if (ranges && ranges.length !== 0) { + return ranges[ranges.length - 1].state + } + + if (!ruleId) { + return !reset + } + + if (reset) { + return enable.indexOf(ruleId) !== -1 + } + + return disable.indexOf(ruleId) === -1 + } + + // Handle a rule. + function toggle(pos, state, ruleId) { + var markers = ruleId ? scope[ruleId] : globals; + var previousState; + + if (!markers) { + markers = []; + scope[ruleId] = markers; + } + + previousState = getState(ruleId); + + if (state !== previousState) { + markers.push({state: state, position: pos}); + } + + // Toggle all known rules. + if (!ruleId) { + for (ruleId in scope) { + toggle(pos, state, ruleId); + } + } + } + + // Check all `ranges` for `message`. + function check(message, ranges, id) { + // Check the state at the message’s position. + var index = ranges && ranges.length; + var length = -1; + var range; + + while (--index > length) { + range = ranges[index]; + + /* istanbul ignore if - Generated marker. */ + if (!range.position || !range.position.line || !range.position.column) { + continue + } + + if ( + range.position.line < message.line || + (range.position.line === message.line && + range.position.column <= message.column) + ) { + return range.state === true + } + } + + // The first marker ocurred after the first message, so we check the + // initial state. + if (!id) { + return initial || reset + } + + return reset ? enable.indexOf(id) !== -1 : disable.indexOf(id) === -1 + } + } +} + +// Detect gaps in `tree`. +function detectGaps$1(tree, file) { + var lastNode = tree.children[tree.children.length - 1]; + var offset = 0; + var isGap = false; + var gaps = []; + + // Find all gaps. + unistUtilVisit$2(tree, one); + + // Get the end of the document. + // This detects if the last node was the last node. + // If not, there’s an extra gap between the last node and the end of the + // document. + if ( + lastNode && + lastNode.position && + lastNode.position.end && + offset === lastNode.position.end.offset && + trim$1(file.toString().slice(offset)) !== '' + ) { + update(); + + update( + tree && tree.position && tree.position.end && tree.position.end.offset - 1 + ); + } + + return gaps + + function one(node) { + var pos = node.position; + + update(pos && pos.start && pos.start.offset); + + if (!node.children) { + update(pos && pos.end && pos.end.offset); + } + } + + // Detect a new position. + function update(latest) { + if (latest === null || latest === undefined) { + isGap = true; + return + } + + if (offset >= latest) { + return + } + + if (isGap) { + gaps.push({start: offset, end: latest}); + isGap = false; + } + + offset = latest; + } +} + +function trim$1(value) { + return value.replace(/^\s*|\s*$/g, '') +} + +var remarkMessageControl$1 = messageControl$3; + +var test$1 = [ + 'html', // Comments are `html` nodes in mdast. + 'comment' // In MDX, comments have their own node. +]; + +function messageControl$3(options) { + return unifiedMessageControl$1(Object.assign({marker: mdastCommentMarker, test: test$1}, options)) +} + +var remarkLint$1 = lint$1; + +// `remark-lint`. +// This adds support for ignoring stuff from messages (``). +// All rules are in their own packages and presets. +function lint$1() { + this.use(lintMessageControl$1); +} + +function lintMessageControl$1() { + return remarkMessageControl$1({name: 'lint', source: 'remark-lint'}) +} + /** * An Array.prototype.slice.call(arguments) alternative * @@ -41822,9 +42655,9 @@ function promise(value) { return value && 'function' == typeof value.then; } -var unifiedLintRule = factory$7; +var unifiedLintRule = factory$9; -function factory$7(id, rule) { +function factory$9(id, rule) { var parts = id.split(':'); var source = parts[0]; var ruleId = parts[1]; @@ -41862,7 +42695,7 @@ function factory$7(id, rule) { if (err && messages.indexOf(err) === -1) { try { file.fail(err); - } catch (error) {} + } catch (_) {} } while (index < messages.length) { @@ -41921,7 +42754,7 @@ function coerce(name, value) { if (level < 0 || level > 2) { throw new Error( - 'Invalid severity `' + + 'Incorrect severity `' + level + '` for `' + name + @@ -41946,490 +42779,700 @@ function finalNewline(tree, file) { } } -const addendum = "addenda"; -const aircraft = "aircraft"; -const alga = "algae"; -const alumna = "alumnae"; -const alumnus = "alumni"; -const amoeba = "amoebae"; -const analysis = "analyses"; -const antenna = "antennae"; -const antithesis = "antitheses"; -const apex = "apices"; -const appendix = "appendices"; -const automaton = "automata"; -const axis = "axes"; -const bacillus = "bacilli"; -const bacterium = "bacteria"; -const barracks = "barracks"; -const basis = "bases"; -const beau = "beaux"; -const bison = "bison"; -const buffalo = "buffalo"; -const bureau = "bureaus"; -const cactus = "cacti"; -const calf = "calves"; -const carp = "carp"; -const census = "censuses"; -const chassis = "chassis"; -const cherub = "cherubim"; -const child = "children"; -const cod = "cod"; -const codex = "codices"; -const concerto = "concerti"; -const corpus = "corpora"; -const crisis = "crises"; -const criterion = "criteria"; -const curriculum = "curricula"; -const datum = "data"; -const deer = "deer"; -const diagnosis = "diagnoses"; -const die$1 = "dice"; -const dwarf = "dwarfs"; -const echo = "echoes"; -const elf = "elves"; -const elk = "elk"; -const ellipsis = "ellipses"; -const embargo = "embargoes"; -const emphasis$3 = "emphases"; -const erratum = "errata"; -const fez = "fezes"; -const firmware = "firmware"; -const fish = "fish"; -const focus = "foci"; -const foot = "feet"; -const formula = "formulae"; -const fungus = "fungi"; -const gallows = "gallows"; -const genus = "genera"; -const goose = "geese"; -const graffito = "graffiti"; -const grouse = "grouse"; -const half$1 = "halves"; -const hero = "heroes"; -const hoof = "hooves"; -const hovercraft = "hovercraft"; -const hypothesis = "hypotheses"; -const index$5 = "indices"; -const kakapo = "kakapo"; -const knife = "knives"; -const larva = "larvae"; -const leaf = "leaves"; -const libretto = "libretti"; -const life = "lives"; -const loaf = "loaves"; -const locus = "loci"; -const louse = "lice"; -const man = "men"; -const matrix = "matrices"; -const means = "means"; -const medium = "media"; -const memorandum = "memoranda"; -const millennium = "millennia"; -const minutia = "minutiae"; -const moose = "moose"; -const mouse = "mice"; -const nebula = "nebulae"; -const nemesis = "nemeses"; -const neurosis = "neuroses"; -const news = "news"; -const nucleus = "nuclei"; -const oasis = "oases"; -const offspring = "offspring"; -const opus = "opera"; -const ovum = "ova"; -const ox = "oxen"; -const paralysis = "paralyses"; -const parenthesis = "parentheses"; -const person = "people"; -const phenomenon = "phenomena"; -const phylum = "phyla"; -const pike = "pike"; -const polyhedron = "polyhedra"; -const potato = "potatoes"; -const prognosis = "prognoses"; -const quiz = "quizzes"; -const radius = "radii"; -const referendum = "referenda"; -const salmon = "salmon"; -const scarf = "scarves"; -const self = "selves"; -const series = "series"; -const sheep = "sheep"; -const shelf = "shelves"; -const shrimp = "shrimp"; -const spacecraft = "spacecraft"; -const species = "species"; -const spectrum = "spectra"; -const squid = "squid"; -const stimulus = "stimuli"; -const stratum = "strata"; -const swine = "swine"; -const syllabus = "syllabi"; -const symposium = "symposia"; -const synopsis = "synopses"; -const synthesis = "syntheses"; -const tableau = "tableaus"; -const that = "those"; -const thesis = "theses"; -const thief = "thieves"; -const tomato = "tomatoes"; -const tooth = "teeth"; -const trout = "trout"; -const tuna = "tuna"; -const vertebra = "vertebrae"; -const vertex = "vertices"; -const veto = "vetoes"; -const vita = "vitae"; -const vortex = "vortices"; -const watercraft = "watercraft"; -const wharf = "wharves"; -const wife = "wives"; -const wolf = "wolves"; -const woman = "women"; -var irregularPlurals = { - addendum: addendum, - aircraft: aircraft, - alga: alga, - alumna: alumna, - alumnus: alumnus, - amoeba: amoeba, - analysis: analysis, - antenna: antenna, - antithesis: antithesis, - apex: apex, - appendix: appendix, - automaton: automaton, - axis: axis, - bacillus: bacillus, - bacterium: bacterium, - barracks: barracks, - basis: basis, - beau: beau, - bison: bison, - buffalo: buffalo, - bureau: bureau, - cactus: cactus, - calf: calf, - carp: carp, - census: census, - chassis: chassis, - cherub: cherub, - child: child, - "château": "châteaus", - cod: cod, - codex: codex, - concerto: concerto, - corpus: corpus, - crisis: crisis, - criterion: criterion, - curriculum: curriculum, - datum: datum, - deer: deer, - diagnosis: diagnosis, - die: die$1, - dwarf: dwarf, - echo: echo, - elf: elf, - elk: elk, - ellipsis: ellipsis, - embargo: embargo, - emphasis: emphasis$3, - erratum: erratum, - "faux pas": "faux pas", - fez: fez, - firmware: firmware, - fish: fish, - focus: focus, - foot: foot, - formula: formula, - fungus: fungus, - gallows: gallows, - genus: genus, - goose: goose, - graffito: graffito, - grouse: grouse, - half: half$1, - hero: hero, - hoof: hoof, - hovercraft: hovercraft, - hypothesis: hypothesis, - index: index$5, - kakapo: kakapo, - knife: knife, - larva: larva, - leaf: leaf, - libretto: libretto, - life: life, - loaf: loaf, - locus: locus, - louse: louse, - man: man, - matrix: matrix, - means: means, - medium: medium, - memorandum: memorandum, - millennium: millennium, - minutia: minutia, - moose: moose, - mouse: mouse, - nebula: nebula, - nemesis: nemesis, - neurosis: neurosis, - news: news, - nucleus: nucleus, - oasis: oasis, - offspring: offspring, - opus: opus, - ovum: ovum, - ox: ox, - paralysis: paralysis, - parenthesis: parenthesis, - person: person, - phenomenon: phenomenon, - phylum: phylum, - pike: pike, - polyhedron: polyhedron, - potato: potato, - prognosis: prognosis, - quiz: quiz, - radius: radius, - referendum: referendum, - salmon: salmon, - scarf: scarf, - self: self, - series: series, - sheep: sheep, - shelf: shelf, - shrimp: shrimp, - spacecraft: spacecraft, - species: species, - spectrum: spectrum, - squid: squid, - stimulus: stimulus, - stratum: stratum, - swine: swine, - syllabus: syllabus, - symposium: symposium, - synopsis: synopsis, - synthesis: synthesis, - tableau: tableau, - that: that, - thesis: thesis, - thief: thief, - "this": "these", - tomato: tomato, - tooth: tooth, - trout: trout, - tuna: tuna, - vertebra: vertebra, - vertex: vertex, - veto: veto, - vita: vita, - vortex: vortex, - watercraft: watercraft, - wharf: wharf, - wife: wife, - wolf: wolf, - woman: woman -}; - -var irregularPlurals$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - addendum: addendum, - aircraft: aircraft, - alga: alga, - alumna: alumna, - alumnus: alumnus, - amoeba: amoeba, - analysis: analysis, - antenna: antenna, - antithesis: antithesis, - apex: apex, - appendix: appendix, - automaton: automaton, - axis: axis, - bacillus: bacillus, - bacterium: bacterium, - barracks: barracks, - basis: basis, - beau: beau, - bison: bison, - buffalo: buffalo, - bureau: bureau, - cactus: cactus, - calf: calf, - carp: carp, - census: census, - chassis: chassis, - cherub: cherub, - child: child, - cod: cod, - codex: codex, - concerto: concerto, - corpus: corpus, - crisis: crisis, - criterion: criterion, - curriculum: curriculum, - datum: datum, - deer: deer, - diagnosis: diagnosis, - die: die$1, - dwarf: dwarf, - echo: echo, - elf: elf, - elk: elk, - ellipsis: ellipsis, - embargo: embargo, - emphasis: emphasis$3, - erratum: erratum, - fez: fez, - firmware: firmware, - fish: fish, - focus: focus, - foot: foot, - formula: formula, - fungus: fungus, - gallows: gallows, - genus: genus, - goose: goose, - graffito: graffito, - grouse: grouse, - half: half$1, - hero: hero, - hoof: hoof, - hovercraft: hovercraft, - hypothesis: hypothesis, - index: index$5, - kakapo: kakapo, - knife: knife, - larva: larva, - leaf: leaf, - libretto: libretto, - life: life, - loaf: loaf, - locus: locus, - louse: louse, - man: man, - matrix: matrix, - means: means, - medium: medium, - memorandum: memorandum, - millennium: millennium, - minutia: minutia, - moose: moose, - mouse: mouse, - nebula: nebula, - nemesis: nemesis, - neurosis: neurosis, - news: news, - nucleus: nucleus, - oasis: oasis, - offspring: offspring, - opus: opus, - ovum: ovum, - ox: ox, - paralysis: paralysis, - parenthesis: parenthesis, - person: person, - phenomenon: phenomenon, - phylum: phylum, - pike: pike, - polyhedron: polyhedron, - potato: potato, - prognosis: prognosis, - quiz: quiz, - radius: radius, - referendum: referendum, - salmon: salmon, - scarf: scarf, - self: self, - series: series, - sheep: sheep, - shelf: shelf, - shrimp: shrimp, - spacecraft: spacecraft, - species: species, - spectrum: spectrum, - squid: squid, - stimulus: stimulus, - stratum: stratum, - swine: swine, - syllabus: syllabus, - symposium: symposium, - synopsis: synopsis, - synthesis: synthesis, - tableau: tableau, - that: that, - thesis: thesis, - thief: thief, - tomato: tomato, - tooth: tooth, - trout: trout, - tuna: tuna, - vertebra: vertebra, - vertex: vertex, - veto: veto, - vita: vita, - vortex: vortex, - watercraft: watercraft, - wharf: wharf, - wife: wife, - wolf: wolf, - woman: woman, - 'default': irregularPlurals -}); +var pluralize = createCommonjsModule(function (module, exports) { +/* global define */ -var irregularPlurals$2 = getCjsExportFromNamespace(irregularPlurals$1); +(function (root, pluralize) { + /* istanbul ignore else */ + if (typeof commonjsRequire === 'function' && 'object' === 'object' && 'object' === 'object') { + // Node. + module.exports = pluralize(); + } else { + // Browser global. + root.pluralize = pluralize(); + } +})(commonjsGlobal, function () { + // Rule storage - pluralize and singularize need to be run sequentially, + // while other rules can be optimized using an object for instant lookups. + var pluralRules = []; + var singularRules = []; + var uncountables = {}; + var irregularPlurals = {}; + var irregularSingles = {}; -var irregularPlurals_1 = createCommonjsModule(function (module) { + /** + * Sanitize a pluralization rule to a usable regular expression. + * + * @param {(RegExp|string)} rule + * @return {RegExp} + */ + function sanitizeRule (rule) { + if (typeof rule === 'string') { + return new RegExp('^' + rule + '$', 'i'); + } + return rule; + } -const map = new Map(); -// TODO: Use Object.entries when targeting Node.js 8 -for (const key of Object.keys(irregularPlurals$2)) { - map.set(key, irregularPlurals$2[key]); -} + /** + * Pass in a word token to produce a function that can replicate the case on + * another word. + * + * @param {string} word + * @param {string} token + * @return {Function} + */ + function restoreCase (word, token) { + // Tokens are an exact match. + if (word === token) return token; -// Ensure nobody can modify each others Map -Object.defineProperty(module, 'exports', { - get() { - return map; - } -}); -}); + // Lower cased words. E.g. "hello". + if (word === word.toLowerCase()) return token.toLowerCase(); -var plur = (word, plural, count) => { - if (typeof plural === 'number') { - count = plural; - } + // Upper cased words. E.g. "WHISKY". + if (word === word.toUpperCase()) return token.toUpperCase(); - if (irregularPlurals_1.has(word.toLowerCase())) { - plural = irregularPlurals_1.get(word.toLowerCase()); + // Title cased words. E.g. "Title". + if (word[0] === word[0].toUpperCase()) { + return token.charAt(0).toUpperCase() + token.substr(1).toLowerCase(); + } - const firstLetter = word.charAt(0); - const isFirstLetterUpperCase = firstLetter === firstLetter.toUpperCase(); - if (isFirstLetterUpperCase) { - plural = firstLetter.toUpperCase() + plural.slice(1); - } + // Lower cased words. E.g. "test". + return token.toLowerCase(); + } - const isWholeWordUpperCase = word === word.toUpperCase(); - if (isWholeWordUpperCase) { - plural = plural.toUpperCase(); - } - } else if (typeof plural !== 'string') { - plural = (word.replace(/(?:s|x|z|ch|sh)$/i, '$&e').replace(/([^aeiou])y$/i, '$1ie') + 's') - .replace(/i?e?s$/i, match => { - const isTailLowerCase = word.slice(-1) === word.slice(-1).toLowerCase(); - return isTailLowerCase ? match.toLowerCase() : match.toUpperCase(); - }); - } + /** + * Interpolate a regexp string. + * + * @param {string} str + * @param {Array} args + * @return {string} + */ + function interpolate (str, args) { + return str.replace(/\$(\d{1,2})/g, function (match, index) { + return args[index] || ''; + }); + } - return Math.abs(count) === 1 ? word : plural; -}; + /** + * Replace a word using a rule. + * + * @param {string} word + * @param {Array} rule + * @return {string} + */ + function replace (word, rule) { + return word.replace(rule[0], function (match, index) { + var result = interpolate(rule[1], arguments); + + if (match === '') { + return restoreCase(word[index - 1], result); + } + + return restoreCase(match, result); + }); + } + + /** + * Sanitize a word by passing in the word and sanitization rules. + * + * @param {string} token + * @param {string} word + * @param {Array} rules + * @return {string} + */ + function sanitizeWord (token, word, rules) { + // Empty string or doesn't need fixing. + if (!token.length || uncountables.hasOwnProperty(token)) { + return word; + } + + var len = rules.length; + + // Iterate over the sanitization rules and use the first one to match. + while (len--) { + var rule = rules[len]; + + if (rule[0].test(word)) return replace(word, rule); + } + + return word; + } + + /** + * Replace a word with the updated word. + * + * @param {Object} replaceMap + * @param {Object} keepMap + * @param {Array} rules + * @return {Function} + */ + function replaceWord (replaceMap, keepMap, rules) { + return function (word) { + // Get the correct token and case restoration functions. + var token = word.toLowerCase(); + + // Check against the keep object map. + if (keepMap.hasOwnProperty(token)) { + return restoreCase(word, token); + } + + // Check against the replacement map for a direct word replacement. + if (replaceMap.hasOwnProperty(token)) { + return restoreCase(word, replaceMap[token]); + } + + // Run all the rules against the word. + return sanitizeWord(token, word, rules); + }; + } + + /** + * Check if a word is part of the map. + */ + function checkWord (replaceMap, keepMap, rules, bool) { + return function (word) { + var token = word.toLowerCase(); + + if (keepMap.hasOwnProperty(token)) return true; + if (replaceMap.hasOwnProperty(token)) return false; + + return sanitizeWord(token, token, rules) === token; + }; + } + + /** + * Pluralize or singularize a word based on the passed in count. + * + * @param {string} word The word to pluralize + * @param {number} count How many of the word exist + * @param {boolean} inclusive Whether to prefix with the number (e.g. 3 ducks) + * @return {string} + */ + function pluralize (word, count, inclusive) { + var pluralized = count === 1 + ? pluralize.singular(word) : pluralize.plural(word); + + return (inclusive ? count + ' ' : '') + pluralized; + } + + /** + * Pluralize a word. + * + * @type {Function} + */ + pluralize.plural = replaceWord( + irregularSingles, irregularPlurals, pluralRules + ); + + /** + * Check if a word is plural. + * + * @type {Function} + */ + pluralize.isPlural = checkWord( + irregularSingles, irregularPlurals, pluralRules + ); + + /** + * Singularize a word. + * + * @type {Function} + */ + pluralize.singular = replaceWord( + irregularPlurals, irregularSingles, singularRules + ); + + /** + * Check if a word is singular. + * + * @type {Function} + */ + pluralize.isSingular = checkWord( + irregularPlurals, irregularSingles, singularRules + ); + + /** + * Add a pluralization rule to the collection. + * + * @param {(string|RegExp)} rule + * @param {string} replacement + */ + pluralize.addPluralRule = function (rule, replacement) { + pluralRules.push([sanitizeRule(rule), replacement]); + }; + + /** + * Add a singularization rule to the collection. + * + * @param {(string|RegExp)} rule + * @param {string} replacement + */ + pluralize.addSingularRule = function (rule, replacement) { + singularRules.push([sanitizeRule(rule), replacement]); + }; + + /** + * Add an uncountable word rule. + * + * @param {(string|RegExp)} word + */ + pluralize.addUncountableRule = function (word) { + if (typeof word === 'string') { + uncountables[word.toLowerCase()] = true; + return; + } + + // Set singular and plural references for the word. + pluralize.addPluralRule(word, '$0'); + pluralize.addSingularRule(word, '$0'); + }; + + /** + * Add an irregular word definition. + * + * @param {string} single + * @param {string} plural + */ + pluralize.addIrregularRule = function (single, plural) { + plural = plural.toLowerCase(); + single = single.toLowerCase(); + + irregularSingles[single] = plural; + irregularPlurals[plural] = single; + }; + + /** + * Irregular rules. + */ + [ + // Pronouns. + ['I', 'we'], + ['me', 'us'], + ['he', 'they'], + ['she', 'they'], + ['them', 'them'], + ['myself', 'ourselves'], + ['yourself', 'yourselves'], + ['itself', 'themselves'], + ['herself', 'themselves'], + ['himself', 'themselves'], + ['themself', 'themselves'], + ['is', 'are'], + ['was', 'were'], + ['has', 'have'], + ['this', 'these'], + ['that', 'those'], + // Words ending in with a consonant and `o`. + ['echo', 'echoes'], + ['dingo', 'dingoes'], + ['volcano', 'volcanoes'], + ['tornado', 'tornadoes'], + ['torpedo', 'torpedoes'], + // Ends with `us`. + ['genus', 'genera'], + ['viscus', 'viscera'], + // Ends with `ma`. + ['stigma', 'stigmata'], + ['stoma', 'stomata'], + ['dogma', 'dogmata'], + ['lemma', 'lemmata'], + ['schema', 'schemata'], + ['anathema', 'anathemata'], + // Other irregular rules. + ['ox', 'oxen'], + ['axe', 'axes'], + ['die', 'dice'], + ['yes', 'yeses'], + ['foot', 'feet'], + ['eave', 'eaves'], + ['goose', 'geese'], + ['tooth', 'teeth'], + ['quiz', 'quizzes'], + ['human', 'humans'], + ['proof', 'proofs'], + ['carve', 'carves'], + ['valve', 'valves'], + ['looey', 'looies'], + ['thief', 'thieves'], + ['groove', 'grooves'], + ['pickaxe', 'pickaxes'], + ['passerby', 'passersby'] + ].forEach(function (rule) { + return pluralize.addIrregularRule(rule[0], rule[1]); + }); + + /** + * Pluralization rules. + */ + [ + [/s?$/i, 's'], + [/[^\u0000-\u007F]$/i, '$0'], + [/([^aeiou]ese)$/i, '$1'], + [/(ax|test)is$/i, '$1es'], + [/(alias|[^aou]us|t[lm]as|gas|ris)$/i, '$1es'], + [/(e[mn]u)s?$/i, '$1s'], + [/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i, '$1'], + [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1i'], + [/(alumn|alg|vertebr)(?:a|ae)$/i, '$1ae'], + [/(seraph|cherub)(?:im)?$/i, '$1im'], + [/(her|at|gr)o$/i, '$1oes'], + [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i, '$1a'], + [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i, '$1a'], + [/sis$/i, 'ses'], + [/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i, '$1$2ves'], + [/([^aeiouy]|qu)y$/i, '$1ies'], + [/([^ch][ieo][ln])ey$/i, '$1ies'], + [/(x|ch|ss|sh|zz)$/i, '$1es'], + [/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, '$1ices'], + [/\b((?:tit)?m|l)(?:ice|ouse)$/i, '$1ice'], + [/(pe)(?:rson|ople)$/i, '$1ople'], + [/(child)(?:ren)?$/i, '$1ren'], + [/eaux$/i, '$0'], + [/m[ae]n$/i, 'men'], + ['thou', 'you'] + ].forEach(function (rule) { + return pluralize.addPluralRule(rule[0], rule[1]); + }); + + /** + * Singularization rules. + */ + [ + [/s$/i, ''], + [/(ss)$/i, '$1'], + [/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i, '$1fe'], + [/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, '$1f'], + [/ies$/i, 'y'], + [/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i, '$1ie'], + [/\b(mon|smil)ies$/i, '$1ey'], + [/\b((?:tit)?m|l)ice$/i, '$1ouse'], + [/(seraph|cherub)im$/i, '$1'], + [/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i, '$1'], + [/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i, '$1sis'], + [/(movie|twelve|abuse|e[mn]u)s$/i, '$1'], + [/(test)(?:is|es)$/i, '$1is'], + [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1us'], + [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i, '$1um'], + [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i, '$1on'], + [/(alumn|alg|vertebr)ae$/i, '$1a'], + [/(cod|mur|sil|vert|ind)ices$/i, '$1ex'], + [/(matr|append)ices$/i, '$1ix'], + [/(pe)(rson|ople)$/i, '$1rson'], + [/(child)ren$/i, '$1'], + [/(eau)x?$/i, '$1'], + [/men$/i, 'man'] + ].forEach(function (rule) { + return pluralize.addSingularRule(rule[0], rule[1]); + }); + + /** + * Uncountable rules. + */ + [ + // Singular words with no plurals. + 'adulthood', + 'advice', + 'agenda', + 'aid', + 'aircraft', + 'alcohol', + 'ammo', + 'analytics', + 'anime', + 'athletics', + 'audio', + 'bison', + 'blood', + 'bream', + 'buffalo', + 'butter', + 'carp', + 'cash', + 'chassis', + 'chess', + 'clothing', + 'cod', + 'commerce', + 'cooperation', + 'corps', + 'debris', + 'diabetes', + 'digestion', + 'elk', + 'energy', + 'equipment', + 'excretion', + 'expertise', + 'firmware', + 'flounder', + 'fun', + 'gallows', + 'garbage', + 'graffiti', + 'hardware', + 'headquarters', + 'health', + 'herpes', + 'highjinks', + 'homework', + 'housework', + 'information', + 'jeans', + 'justice', + 'kudos', + 'labour', + 'literature', + 'machinery', + 'mackerel', + 'mail', + 'media', + 'mews', + 'moose', + 'music', + 'mud', + 'manga', + 'news', + 'only', + 'personnel', + 'pike', + 'plankton', + 'pliers', + 'police', + 'pollution', + 'premises', + 'rain', + 'research', + 'rice', + 'salmon', + 'scissors', + 'series', + 'sewage', + 'shambles', + 'shrimp', + 'software', + 'species', + 'staff', + 'swine', + 'tennis', + 'traffic', + 'transportation', + 'trout', + 'tuna', + 'wealth', + 'welfare', + 'whiting', + 'wildebeest', + 'wildlife', + 'you', + /pok[eé]mon$/i, + // Regexes. + /[^aeiou]ese$/i, // "chinese", "japanese" + /deer$/i, // "deer", "reindeer" + /fish$/i, // "fish", "blowfish", "angelfish" + /measles$/i, + /o[iu]s$/i, // "carnivorous" + /pox$/i, // "chickpox", "smallpox" + /sheep$/i + ].forEach(pluralize.addUncountableRule); + + return pluralize; +}); +}); + +var convert_1$3 = convert$4; + +function convert$4(test) { + if (typeof test === 'string') { + return typeFactory$3(test) + } + + if (test === null || test === undefined) { + return ok$4 + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$3 : matchesFactory$3)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$3(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$4(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$3(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$3(tests) { + var checks = convertAll$3(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$3(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$4() { + return true +} + +var unistUtilVisitParents$3 = visitParents$3; + + + +var CONTINUE$6 = true; +var SKIP$6 = 'skip'; +var EXIT$6 = false; + +visitParents$3.CONTINUE = CONTINUE$6; +visitParents$3.SKIP = SKIP$6; +visitParents$3.EXIT = EXIT$6; + +function visitParents$3(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$3(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$3(visitor(node, parents)); + + if (result[0] === EXIT$6) { + return result + } + } + + if (node.children && result[0] !== SKIP$6) { + subresult = toResult$3(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$6 ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$6) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$3(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } -var start$1 = factory$8('start'); -var end = factory$8('end'); + if (typeof value === 'number') { + return [CONTINUE$6, value] + } + + return [value] +} + +var unistUtilVisit$3 = visit$3; + + + +var CONTINUE$7 = unistUtilVisitParents$3.CONTINUE; +var SKIP$7 = unistUtilVisitParents$3.SKIP; +var EXIT$7 = unistUtilVisitParents$3.EXIT; + +visit$3.CONTINUE = CONTINUE$7; +visit$3.SKIP = SKIP$7; +visit$3.EXIT = EXIT$7; + +function visit$3(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$3(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var start$1 = factory$a('start'); +var end = factory$a('end'); var unistUtilPosition = position$1; @@ -42440,7 +43483,7 @@ function position$1(node) { return {start: start$1(node), end: end(node)} } -function factory$8(type) { +function factory$a(type) { point.displayName = type; return point @@ -42480,7 +43523,7 @@ var start$2 = unistUtilPosition.start; function listItemBulletIndent(tree, file) { var contents = String(file); - unistUtilVisit(tree, 'list', visitor); + unistUtilVisit$3(tree, 'list', visitor); function visitor(node) { node.children.forEach(visitItems); @@ -42501,7 +43544,7 @@ function listItemBulletIndent(tree, file) { 'Incorrect indentation before bullet: remove ' + indent + ' ' + - plur('space', indent); + pluralize('space', indent); file.message(reason, { line: final.line, @@ -42512,26 +43555,216 @@ function listItemBulletIndent(tree, file) { } } +var convert_1$4 = convert$5; + +function convert$5(test) { + if (typeof test === 'string') { + return typeFactory$4(test) + } + + if (test === null || test === undefined) { + return ok$5 + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$4 : matchesFactory$4)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$4(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$5(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$4(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$4(tests) { + var checks = convertAll$4(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$4(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$5() { + return true +} + +var unistUtilVisitParents$4 = visitParents$4; + + + +var CONTINUE$8 = true; +var SKIP$8 = 'skip'; +var EXIT$8 = false; + +visitParents$4.CONTINUE = CONTINUE$8; +visitParents$4.SKIP = SKIP$8; +visitParents$4.EXIT = EXIT$8; + +function visitParents$4(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$4(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$4(visitor(node, parents)); + + if (result[0] === EXIT$8) { + return result + } + } + + if (node.children && result[0] !== SKIP$8) { + subresult = toResult$4(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$8 ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$8) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$4(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$8, value] + } + + return [value] +} + +var unistUtilVisit$4 = visit$4; + + + +var CONTINUE$9 = unistUtilVisitParents$4.CONTINUE; +var SKIP$9 = unistUtilVisitParents$4.SKIP; +var EXIT$9 = unistUtilVisitParents$4.EXIT; + +visit$4.CONTINUE = CONTINUE$9; +visit$4.SKIP = SKIP$9; +visit$4.EXIT = EXIT$9; + +function visit$4(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$4(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + var remarkLintListItemIndent = unifiedLintRule('remark-lint:list-item-indent', listItemIndent); var start$3 = unistUtilPosition.start; var styles = {'tab-size': true, mixed: true, space: true}; -function listItemIndent(tree, file, pref) { +function listItemIndent(tree, file, option) { var contents = String(file); + var preferred = typeof option === 'string' ? option : 'tab-size'; - pref = typeof pref === 'string' ? pref : 'tab-size'; - - if (styles[pref] !== true) { + if (styles[preferred] !== true) { file.fail( - 'Invalid list-item indent style `' + - pref + + 'Incorrect list-item indent style `' + + preferred + "`: use either `'tab-size'`, `'space'`, or `'mixed'`" ); } - unistUtilVisit(tree, 'list', visitor); + unistUtilVisit$4(tree, 'list', visitor); function visitor(node) { var spread = node.spread || node.loose; @@ -42548,28 +43781,30 @@ function listItemIndent(tree, file, pref) { var style; var diff; var reason; + var abs; marker = contents .slice(start$3(item).offset, final.offset) .replace(/\[[x ]?]\s*$/i, ''); - bulletSize = marker.trimRight().length; + bulletSize = marker.replace(/\s+$/, '').length; style = - pref === 'tab-size' || (pref === 'mixed' && spread) + preferred === 'tab-size' || (preferred === 'mixed' && spread) ? Math.ceil(bulletSize / 4) * 4 : bulletSize + 1; if (marker.length !== style) { diff = style - marker.length; + abs = Math.abs(diff); reason = 'Incorrect list-item indent: ' + (diff > 0 ? 'add' : 'remove') + ' ' + - Math.abs(diff) + + abs + ' ' + - plur('space', diff); + pluralize('space', abs); file.message(reason, final); } @@ -42577,1385 +43812,7850 @@ function listItemIndent(tree, file, pref) { } } -var mdastUtilToString = toString$4; +var convert_1$5 = convert$6; -// Get the text content of a node. If the node itself does not expose -// plain-text fields, `toString` will recursivly try its children. -function toString$4(node) { - return ( - valueOf$1(node) || - (node.children && node.children.map(toString$4).join('')) || - '' - ) +function convert$6(test) { + if (typeof test === 'string') { + return typeFactory$5(test) + } + + if (test === null || test === undefined) { + return ok$6 + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$5 : matchesFactory$5)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') } -// Get the value of `node`. Checks, `value`, `alt`, and `title`, in that order. -function valueOf$1(node) { - return ( - (node && node.value ? node.value : node.alt ? node.alt : node.title) || '' - ) +function convertAll$5(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$6(tests[index]); + } + + return results } -var remarkLintNoAutoLinkWithoutProtocol = unifiedLintRule( - 'remark-lint:no-auto-link-without-protocol', - noAutoLinkWithoutProtocol -); +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$5(test) { + return matches -var start$4 = unistUtilPosition.start; -var end$1 = unistUtilPosition.end; + function matches(node) { + var key; -// Protocol expression. -// See: . -var protocol$2 = /^[a-z][a-z+.-]+:\/?/i; + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } -var reason = 'All automatic links must start with a protocol'; + return true + } +} -function noAutoLinkWithoutProtocol(tree, file) { - unistUtilVisit(tree, 'link', visitor); +function anyFactory$5(tests) { + var checks = convertAll$5(tests); + var length = checks.length; - function visitor(node) { - var children; + return matches - if (!unistUtilGenerated(node)) { - children = node.children; + function matches() { + var index = -1; - if ( - start$4(node).column === start$4(children[0]).column - 1 && - end$1(node).column === end$1(children[children.length - 1]).column + 1 && - !protocol$2.test(mdastUtilToString(node)) - ) { - file.message(reason, node); + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true } } + + return false } } -var remarkLintNoBlockquoteWithoutMarker = unifiedLintRule( - 'remark-lint:no-blockquote-without-marker', - noBlockquoteWithoutMarker -); +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$5(test) { + return type -var reason$1 = 'Missing marker in blockquote'; + function type(node) { + return Boolean(node && node.type === test) + } +} -function noBlockquoteWithoutMarker(tree, file) { - var contents = String(file); - var location = vfileLocation(file); - var last = contents.length; +// Utility to return true. +function ok$6() { + return true +} - unistUtilVisit(tree, 'blockquote', visitor); +var unistUtilVisitParents$5 = visitParents$5; - function visitor(node) { - var indent = node.position && node.position.indent; - var start; - var length; - var index; - var line; - var offset; - var character; - var pos; - if (unistUtilGenerated(node) || !indent || indent.length === 0) { - return - } - start = unistUtilPosition.start(node).line; - length = indent.length; - index = -1; +var CONTINUE$a = true; +var SKIP$a = 'skip'; +var EXIT$a = false; - while (++index < length) { - line = start + index + 1; - pos = {line: line, column: indent[index]}; - offset = location.toOffset(pos) - 1; +visitParents$5.CONTINUE = CONTINUE$a; +visitParents$5.SKIP = SKIP$a; +visitParents$5.EXIT = EXIT$a; - while (++offset < last) { +function visitParents$5(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$5(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$5(visitor(node, parents)); + + if (result[0] === EXIT$a) { + return result + } + } + + if (node.children && result[0] !== SKIP$a) { + subresult = toResult$5(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$a ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$a) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$5(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$a, value] + } + + return [value] +} + +var unistUtilVisit$5 = visit$5; + + + +var CONTINUE$b = unistUtilVisitParents$5.CONTINUE; +var SKIP$b = unistUtilVisitParents$5.SKIP; +var EXIT$b = unistUtilVisitParents$5.EXIT; + +visit$5.CONTINUE = CONTINUE$b; +visit$5.SKIP = SKIP$b; +visit$5.EXIT = EXIT$b; + +function visit$5(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$5(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var mdastUtilToString = toString$4; + +// Get the text content of a node. +// Prefer the node’s plain-text fields, otherwise serialize its children, +// and if the given value is an array, serialize the nodes in it. +function toString$4(node) { + return ( + (node && + (node.value || + node.alt || + node.title || + ('children' in node && all$1(node.children)) || + ('length' in node && all$1(node)))) || + '' + ) +} + +function all$1(values) { + var result = []; + var length = values.length; + var index = -1; + + while (++index < length) { + result[index] = toString$4(values[index]); + } + + return result.join('') +} + +var remarkLintNoAutoLinkWithoutProtocol = unifiedLintRule( + 'remark-lint:no-auto-link-without-protocol', + noAutoLinkWithoutProtocol +); + +var start$4 = unistUtilPosition.start; +var end$1 = unistUtilPosition.end; + +// Protocol expression. +// See: . +var protocol$2 = /^[a-z][a-z+.-]+:\/?/i; + +var reason = 'All automatic links must start with a protocol'; + +function noAutoLinkWithoutProtocol(tree, file) { + unistUtilVisit$5(tree, 'link', visitor); + + function visitor(node) { + var children; + + if (!unistUtilGenerated(node)) { + children = node.children; + + if ( + start$4(node).column === start$4(children[0]).column - 1 && + end$1(node).column === end$1(children[children.length - 1]).column + 1 && + !protocol$2.test(mdastUtilToString(node)) + ) { + file.message(reason, node); + } + } + } +} + +var vfileLocation$3 = factory$b; + +function factory$b(file) { + var contents = indices$3(String(file)); + + return { + toPosition: offsetToPositionFactory$3(contents), + toOffset: positionToOffsetFactory$3(contents) + } +} + +// Factory to get the line and column-based `position` for `offset` in the bound +// indices. +function offsetToPositionFactory$3(indices) { + return offsetToPosition + + // Get the line and column-based `position` for `offset` in the bound indices. + function offsetToPosition(offset) { + var index = -1; + var length = indices.length; + + if (offset < 0) { + return {} + } + + while (++index < length) { + if (indices[index] > offset) { + return { + line: index + 1, + column: offset - (indices[index - 1] || 0) + 1, + offset: offset + } + } + } + + return {} + } +} + +// Factory to get the `offset` for a line and column-based `position` in the +// bound indices. +function positionToOffsetFactory$3(indices) { + return positionToOffset + + // Get the `offset` for a line and column-based `position` in the bound + // indices. + function positionToOffset(position) { + var line = position && position.line; + var column = position && position.column; + + if (!isNaN(line) && !isNaN(column) && line - 1 in indices) { + return (indices[line - 2] || 0) + column - 1 || 0 + } + + return -1 + } +} + +// Get indices of line-breaks in `value`. +function indices$3(value) { + var result = []; + var index = value.indexOf('\n'); + + while (index !== -1) { + result.push(index + 1); + index = value.indexOf('\n', index + 1); + } + + result.push(value.length + 1); + + return result +} + +var convert_1$6 = convert$7; + +function convert$7(test) { + if (typeof test === 'string') { + return typeFactory$6(test) + } + + if (test === null || test === undefined) { + return ok$7 + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$6 : matchesFactory$6)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$6(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$7(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$6(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$6(tests) { + var checks = convertAll$6(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$6(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$7() { + return true +} + +var unistUtilVisitParents$6 = visitParents$6; + + + +var CONTINUE$c = true; +var SKIP$c = 'skip'; +var EXIT$c = false; + +visitParents$6.CONTINUE = CONTINUE$c; +visitParents$6.SKIP = SKIP$c; +visitParents$6.EXIT = EXIT$c; + +function visitParents$6(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$6(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$6(visitor(node, parents)); + + if (result[0] === EXIT$c) { + return result + } + } + + if (node.children && result[0] !== SKIP$c) { + subresult = toResult$6(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$c ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$c) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$6(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$c, value] + } + + return [value] +} + +var unistUtilVisit$6 = visit$6; + + + +var CONTINUE$d = unistUtilVisitParents$6.CONTINUE; +var SKIP$d = unistUtilVisitParents$6.SKIP; +var EXIT$d = unistUtilVisitParents$6.EXIT; + +visit$6.CONTINUE = CONTINUE$d; +visit$6.SKIP = SKIP$d; +visit$6.EXIT = EXIT$d; + +function visit$6(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$6(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintNoBlockquoteWithoutMarker = unifiedLintRule( + 'remark-lint:no-blockquote-without-marker', + noBlockquoteWithoutMarker +); + +var reason$1 = 'Missing marker in block quote'; + +function noBlockquoteWithoutMarker(tree, file) { + var contents = String(file); + var location = vfileLocation$3(file); + var last = contents.length; + + unistUtilVisit$6(tree, 'blockquote', visitor); + + function visitor(node) { + var indent = node.position && node.position.indent; + var start; + var length; + var index; + var line; + var offset; + var character; + var pos; + + if (unistUtilGenerated(node) || !indent || indent.length === 0) { + return + } + + start = unistUtilPosition.start(node).line; + length = indent.length; + index = -1; + + while (++index < length) { + line = start + index + 1; + pos = {line: line, column: indent[index]}; + offset = location.toOffset(pos) - 1; + + while (++offset < last) { character = contents.charAt(offset); - if (character === '>') { - break - } + if (character === '>') { + break + } + + /* istanbul ignore else - just for safety */ + if (character !== ' ' && character !== '\t') { + file.message(reason$1, pos); + break + } + } + } + } +} + +var convert_1$7 = convert$8; + +function convert$8(test) { + if (typeof test === 'string') { + return typeFactory$7(test) + } + + if (test === null || test === undefined) { + return ok$8 + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$7 : matchesFactory$7)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$7(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$8(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$7(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$7(tests) { + var checks = convertAll$7(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$7(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$8() { + return true +} + +var unistUtilVisitParents$7 = visitParents$7; + + + +var CONTINUE$e = true; +var SKIP$e = 'skip'; +var EXIT$e = false; + +visitParents$7.CONTINUE = CONTINUE$e; +visitParents$7.SKIP = SKIP$e; +visitParents$7.EXIT = EXIT$e; + +function visitParents$7(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$7(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$7(visitor(node, parents)); + + if (result[0] === EXIT$e) { + return result + } + } + + if (node.children && result[0] !== SKIP$e) { + subresult = toResult$7(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$e ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$e) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$7(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$e, value] + } + + return [value] +} + +var unistUtilVisit$7 = visit$7; + + + +var CONTINUE$f = unistUtilVisitParents$7.CONTINUE; +var SKIP$f = unistUtilVisitParents$7.SKIP; +var EXIT$f = unistUtilVisitParents$7.EXIT; + +visit$7.CONTINUE = CONTINUE$f; +visit$7.SKIP = SKIP$f; +visit$7.EXIT = EXIT$f; + +function visit$7(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$7(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintNoLiteralUrls = unifiedLintRule('remark-lint:no-literal-urls', noLiteralURLs); + +var start$5 = unistUtilPosition.start; +var end$2 = unistUtilPosition.end; +var mailto$3 = 'mailto:'; +var reason$2 = 'Don’t use literal URLs without angle brackets'; + +function noLiteralURLs(tree, file) { + unistUtilVisit$7(tree, 'link', visitor); + + function visitor(node) { + var children = node.children; + var value = mdastUtilToString(node); + + if ( + !unistUtilGenerated(node) && + start$5(node).column === start$5(children[0]).column && + end$2(node).column === end$2(children[children.length - 1]).column && + (node.url === mailto$3 + value || node.url === value) + ) { + file.message(reason$2, node); + } + } +} + +var convert_1$8 = convert$9; + +function convert$9(test) { + if (typeof test === 'string') { + return typeFactory$8(test) + } + + if (test === null || test === undefined) { + return ok$9 + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$8 : matchesFactory$8)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$8(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$9(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$8(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$8(tests) { + var checks = convertAll$8(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$8(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$9() { + return true +} + +var unistUtilVisitParents$8 = visitParents$8; + + + +var CONTINUE$g = true; +var SKIP$g = 'skip'; +var EXIT$g = false; + +visitParents$8.CONTINUE = CONTINUE$g; +visitParents$8.SKIP = SKIP$g; +visitParents$8.EXIT = EXIT$g; + +function visitParents$8(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$8(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$8(visitor(node, parents)); + + if (result[0] === EXIT$g) { + return result + } + } + + if (node.children && result[0] !== SKIP$g) { + subresult = toResult$8(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$g ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$g) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$8(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$g, value] + } + + return [value] +} + +var unistUtilVisit$8 = visit$8; + + + +var CONTINUE$h = unistUtilVisitParents$8.CONTINUE; +var SKIP$h = unistUtilVisitParents$8.SKIP; +var EXIT$h = unistUtilVisitParents$8.EXIT; + +visit$8.CONTINUE = CONTINUE$h; +visit$8.SKIP = SKIP$h; +visit$8.EXIT = EXIT$h; + +function visit$8(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$8(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintOrderedListMarkerStyle = unifiedLintRule( + 'remark-lint:ordered-list-marker-style', + orderedListMarkerStyle +); + +var start$6 = unistUtilPosition.start; + +var styles$1 = { + ')': true, + '.': true, + null: true +}; + +function orderedListMarkerStyle(tree, file, option) { + var contents = String(file); + var preferred = + typeof option !== 'string' || option === 'consistent' ? null : option; + + if (styles$1[preferred] !== true) { + file.fail( + 'Incorrect ordered list item marker style `' + + preferred + + "`: use either `'.'` or `')'`" + ); + } + + unistUtilVisit$8(tree, 'list', visitor); + + function visitor(node) { + var children = node.children; + var length = node.ordered ? children.length : 0; + var index = -1; + var marker; + var child; + + while (++index < length) { + child = children[index]; + + if (!unistUtilGenerated(child)) { + marker = contents + .slice(start$6(child).offset, start$6(child.children[0]).offset) + .replace(/\s|\d/g, '') + .replace(/\[[x ]?]\s*$/i, ''); + + if (preferred) { + if (marker !== preferred) { + file.message('Marker style should be `' + preferred + '`', child); + } + } else { + preferred = marker; + } + } + } + } +} + +var convert_1$9 = convert$a; + +function convert$a(test) { + if (typeof test === 'string') { + return typeFactory$9(test) + } + + if (test === null || test === undefined) { + return ok$a + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$9 : matchesFactory$9)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$9(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$a(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$9(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$9(tests) { + var checks = convertAll$9(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$9(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$a() { + return true +} + +var unistUtilVisitParents$9 = visitParents$9; + + + +var CONTINUE$i = true; +var SKIP$i = 'skip'; +var EXIT$i = false; + +visitParents$9.CONTINUE = CONTINUE$i; +visitParents$9.SKIP = SKIP$i; +visitParents$9.EXIT = EXIT$i; + +function visitParents$9(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$9(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$9(visitor(node, parents)); + + if (result[0] === EXIT$i) { + return result + } + } + + if (node.children && result[0] !== SKIP$i) { + subresult = toResult$9(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$i ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$i) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$9(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$i, value] + } + + return [value] +} + +var unistUtilVisit$9 = visit$9; + + + +var CONTINUE$j = unistUtilVisitParents$9.CONTINUE; +var SKIP$j = unistUtilVisitParents$9.SKIP; +var EXIT$j = unistUtilVisitParents$9.EXIT; + +visit$9.CONTINUE = CONTINUE$j; +visit$9.SKIP = SKIP$j; +visit$9.EXIT = EXIT$j; + +function visit$9(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$9(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintHardBreakSpaces = unifiedLintRule('remark-lint:hard-break-spaces', hardBreakSpaces); + +var reason$3 = 'Use two spaces for hard line breaks'; + +function hardBreakSpaces(tree, file) { + var contents = String(file); + + unistUtilVisit$9(tree, 'break', visitor); + + function visitor(node) { + var value; + + if (!unistUtilGenerated(node)) { + value = contents + .slice(unistUtilPosition.start(node).offset, unistUtilPosition.end(node).offset) + .split('\n', 1)[0] + .replace(/\r$/, ''); + + if (value.length > 2) { + file.message(reason$3, node); + } + } + } +} + +var convert_1$a = convert$b; + +function convert$b(test) { + if (typeof test === 'string') { + return typeFactory$a(test) + } + + if (test === null || test === undefined) { + return ok$b + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$a : matchesFactory$a)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$a(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$b(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$a(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$a(tests) { + var checks = convertAll$a(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$a(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$b() { + return true +} + +var unistUtilVisitParents$a = visitParents$a; + + + +var CONTINUE$k = true; +var SKIP$k = 'skip'; +var EXIT$k = false; + +visitParents$a.CONTINUE = CONTINUE$k; +visitParents$a.SKIP = SKIP$k; +visitParents$a.EXIT = EXIT$k; + +function visitParents$a(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$a(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$a(visitor(node, parents)); + + if (result[0] === EXIT$k) { + return result + } + } + + if (node.children && result[0] !== SKIP$k) { + subresult = toResult$a(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$k ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$k) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$a(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$k, value] + } + + return [value] +} + +var unistUtilVisit$a = visit$a; + + + +var CONTINUE$l = unistUtilVisitParents$a.CONTINUE; +var SKIP$l = unistUtilVisitParents$a.SKIP; +var EXIT$l = unistUtilVisitParents$a.EXIT; + +visit$a.CONTINUE = CONTINUE$l; +visit$a.SKIP = SKIP$l; +visit$a.EXIT = EXIT$l; + +function visit$a(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$a(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintNoDuplicateDefinitions = unifiedLintRule( + 'remark-lint:no-duplicate-definitions', + noDuplicateDefinitions +); + +var reason$4 = 'Do not use definitions with the same identifier'; + +function noDuplicateDefinitions(tree, file) { + var map = {}; + + unistUtilVisit$a(tree, ['definition', 'footnoteDefinition'], check); + + function check(node) { + var identifier; + var duplicate; + + if (!unistUtilGenerated(node)) { + identifier = node.identifier; + duplicate = map[identifier]; + + if (duplicate && duplicate.type) { + file.message( + reason$4 + ' (' + unistUtilStringifyPosition(unistUtilPosition.start(duplicate)) + ')', + node + ); + } + + map[identifier] = node; + } + } +} + +var convert_1$b = convert$c; + +function convert$c(test) { + if (typeof test === 'string') { + return typeFactory$b(test) + } + + if (test === null || test === undefined) { + return ok$c + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$b : matchesFactory$b)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$b(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$c(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$b(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$b(tests) { + var checks = convertAll$b(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$b(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$c() { + return true +} + +var unistUtilVisitParents$b = visitParents$b; + + + +var CONTINUE$m = true; +var SKIP$m = 'skip'; +var EXIT$m = false; + +visitParents$b.CONTINUE = CONTINUE$m; +visitParents$b.SKIP = SKIP$m; +visitParents$b.EXIT = EXIT$m; + +function visitParents$b(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$b(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$b(visitor(node, parents)); + + if (result[0] === EXIT$m) { + return result + } + } + + if (node.children && result[0] !== SKIP$m) { + subresult = toResult$b(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$m ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$m) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$b(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$m, value] + } + + return [value] +} + +var unistUtilVisit$b = visit$b; + + + +var CONTINUE$n = unistUtilVisitParents$b.CONTINUE; +var SKIP$n = unistUtilVisitParents$b.SKIP; +var EXIT$n = unistUtilVisitParents$b.EXIT; + +visit$b.CONTINUE = CONTINUE$n; +visit$b.SKIP = SKIP$n; +visit$b.EXIT = EXIT$n; + +function visit$b(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$b(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var mdastUtilHeadingStyle = style; + +function style(node, relative) { + var last = node.children[node.children.length - 1]; + var depth = node.depth; + var pos = node && node.position && node.position.end; + var final = last && last.position && last.position.end; + + if (!pos) { + return null + } + + // This can only occur for `'atx'` and `'atx-closed'` headings. + // This might incorrectly match `'atx'` headings with lots of trailing white + // space as an `'atx-closed'` heading. + if (!last) { + if (pos.column - 1 <= depth * 2) { + return consolidate(depth, relative) + } + + return 'atx-closed' + } + + if (final.line + 1 === pos.line) { + return 'setext' + } + + if (final.column + depth < pos.column) { + return 'atx-closed' + } + + return consolidate(depth, relative) +} + +// Get the probable style of an atx-heading, depending on preferred style. +function consolidate(depth, relative) { + return depth < 3 + ? 'atx' + : relative === 'atx' || relative === 'setext' + ? relative + : null +} + +var remarkLintNoHeadingContentIndent = unifiedLintRule( + 'remark-lint:no-heading-content-indent', + noHeadingContentIndent +); + +var start$7 = unistUtilPosition.start; +var end$3 = unistUtilPosition.end; + +function noHeadingContentIndent(tree, file) { + var contents = String(file); + + unistUtilVisit$b(tree, 'heading', visitor); + + function visitor(node) { + var depth; + var children; + var type; + var head; + var initial; + var final; + var diff; + var index; + var char; + var reason; + var abs; + + if (unistUtilGenerated(node)) { + return + } + + depth = node.depth; + children = node.children; + type = mdastUtilHeadingStyle(node, 'atx'); + + if (type === 'atx' || type === 'atx-closed') { + initial = start$7(node); + index = initial.offset; + char = contents.charAt(index); + + while (char && char !== '#') { + char = contents.charAt(++index); + } + + /* istanbul ignore if - CR/LF bug: remarkjs/remark#195. */ + if (!char) { + return + } + + index = depth + (index - initial.offset); + head = start$7(children[0]).column; + + // Ignore empty headings. + if (!head) { + return + } + + diff = head - initial.column - 1 - index; + + if (diff) { + abs = Math.abs(diff); + + reason = + (diff > 0 ? 'Remove' : 'Add') + + ' ' + + abs + + ' ' + + pluralize('space', abs) + + ' before this heading’s content'; + + file.message(reason, start$7(children[0])); + } + } + + // Closed ATX headings always must have a space between their content and + // the final hashes, thus, there is no `add x spaces`. + if (type === 'atx-closed') { + final = end$3(children[children.length - 1]); + diff = end$3(node).column - final.column - 1 - depth; + + if (diff) { + reason = + 'Remove ' + + diff + + ' ' + + pluralize('space', diff) + + ' after this heading’s content'; + + file.message(reason, final); + } + } + } +} + +var convert_1$c = convert$d; + +function convert$d(test) { + if (typeof test === 'string') { + return typeFactory$c(test) + } + + if (test === null || test === undefined) { + return ok$d + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$c : matchesFactory$c)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$c(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$d(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$c(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$c(tests) { + var checks = convertAll$c(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$c(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$d() { + return true +} + +var unistUtilVisitParents$c = visitParents$c; + + + +var CONTINUE$o = true; +var SKIP$o = 'skip'; +var EXIT$o = false; + +visitParents$c.CONTINUE = CONTINUE$o; +visitParents$c.SKIP = SKIP$o; +visitParents$c.EXIT = EXIT$o; + +function visitParents$c(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$c(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$c(visitor(node, parents)); + + if (result[0] === EXIT$o) { + return result + } + } + + if (node.children && result[0] !== SKIP$o) { + subresult = toResult$c(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$o ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$o) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$c(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$o, value] + } + + return [value] +} + +var unistUtilVisit$c = visit$c; + + + +var CONTINUE$p = unistUtilVisitParents$c.CONTINUE; +var SKIP$p = unistUtilVisitParents$c.SKIP; +var EXIT$p = unistUtilVisitParents$c.EXIT; + +visit$c.CONTINUE = CONTINUE$p; +visit$c.SKIP = SKIP$p; +visit$c.EXIT = EXIT$p; + +function visit$c(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$c(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintNoInlinePadding = unifiedLintRule('remark-lint:no-inline-padding', noInlinePadding); + +function noInlinePadding(tree, file) { + unistUtilVisit$c(tree, ['emphasis', 'strong', 'delete', 'image', 'link'], visitor); + + function visitor(node) { + var contents; + + if (!unistUtilGenerated(node)) { + contents = mdastUtilToString(node); + + if ( + contents.charAt(0) === ' ' || + contents.charAt(contents.length - 1) === ' ' + ) { + file.message('Don’t pad `' + node.type + '` with inner spaces', node); + } + } + } +} + +var convert_1$d = convert$e; + +function convert$e(test) { + if (typeof test === 'string') { + return typeFactory$d(test) + } + + if (test === null || test === undefined) { + return ok$e + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$d : matchesFactory$d)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$d(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$e(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$d(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$d(tests) { + var checks = convertAll$d(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$d(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$e() { + return true +} + +var unistUtilVisitParents$d = visitParents$d; + + + +var CONTINUE$q = true; +var SKIP$q = 'skip'; +var EXIT$q = false; + +visitParents$d.CONTINUE = CONTINUE$q; +visitParents$d.SKIP = SKIP$q; +visitParents$d.EXIT = EXIT$q; + +function visitParents$d(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$d(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$d(visitor(node, parents)); + + if (result[0] === EXIT$q) { + return result + } + } + + if (node.children && result[0] !== SKIP$q) { + subresult = toResult$d(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$q ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$q) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$d(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$q, value] + } + + return [value] +} + +var unistUtilVisit$d = visit$d; + + + +var CONTINUE$r = unistUtilVisitParents$d.CONTINUE; +var SKIP$r = unistUtilVisitParents$d.SKIP; +var EXIT$r = unistUtilVisitParents$d.EXIT; + +visit$d.CONTINUE = CONTINUE$r; +visit$d.SKIP = SKIP$r; +visit$d.EXIT = EXIT$r; + +function visit$d(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$d(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintNoShortcutReferenceImage = unifiedLintRule( + 'remark-lint:no-shortcut-reference-image', + noShortcutReferenceImage +); + +var reason$5 = 'Use the trailing [] on reference images'; + +function noShortcutReferenceImage(tree, file) { + unistUtilVisit$d(tree, 'imageReference', visitor); + + function visitor(node) { + if (!unistUtilGenerated(node) && node.referenceType === 'shortcut') { + file.message(reason$5, node); + } + } +} + +var convert_1$e = convert$f; + +function convert$f(test) { + if (typeof test === 'string') { + return typeFactory$e(test) + } + + if (test === null || test === undefined) { + return ok$f + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$e : matchesFactory$e)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$e(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$f(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$e(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$e(tests) { + var checks = convertAll$e(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$e(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$f() { + return true +} + +var unistUtilVisitParents$e = visitParents$e; + + + +var CONTINUE$s = true; +var SKIP$s = 'skip'; +var EXIT$s = false; + +visitParents$e.CONTINUE = CONTINUE$s; +visitParents$e.SKIP = SKIP$s; +visitParents$e.EXIT = EXIT$s; + +function visitParents$e(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$e(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$e(visitor(node, parents)); + + if (result[0] === EXIT$s) { + return result + } + } + + if (node.children && result[0] !== SKIP$s) { + subresult = toResult$e(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$s ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$s) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$e(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$s, value] + } + + return [value] +} + +var unistUtilVisit$e = visit$e; + + + +var CONTINUE$t = unistUtilVisitParents$e.CONTINUE; +var SKIP$t = unistUtilVisitParents$e.SKIP; +var EXIT$t = unistUtilVisitParents$e.EXIT; + +visit$e.CONTINUE = CONTINUE$t; +visit$e.SKIP = SKIP$t; +visit$e.EXIT = EXIT$t; + +function visit$e(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$e(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintNoShortcutReferenceLink = unifiedLintRule( + 'remark-lint:no-shortcut-reference-link', + noShortcutReferenceLink +); + +var reason$6 = 'Use the trailing `[]` on reference links'; + +function noShortcutReferenceLink(tree, file) { + unistUtilVisit$e(tree, 'linkReference', visitor); + + function visitor(node) { + if (!unistUtilGenerated(node) && node.referenceType === 'shortcut') { + file.message(reason$6, node); + } + } +} + +var convert_1$f = convert$g; + +function convert$g(test) { + if (typeof test === 'string') { + return typeFactory$f(test) + } + + if (test === null || test === undefined) { + return ok$g + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$f : matchesFactory$f)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$f(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$g(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$f(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$f(tests) { + var checks = convertAll$f(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$f(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$g() { + return true +} + +var unistUtilVisitParents$f = visitParents$f; + + + +var CONTINUE$u = true; +var SKIP$u = 'skip'; +var EXIT$u = false; + +visitParents$f.CONTINUE = CONTINUE$u; +visitParents$f.SKIP = SKIP$u; +visitParents$f.EXIT = EXIT$u; + +function visitParents$f(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$f(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$f(visitor(node, parents)); + + if (result[0] === EXIT$u) { + return result + } + } + + if (node.children && result[0] !== SKIP$u) { + subresult = toResult$f(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$u ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$u) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$f(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$u, value] + } + + return [value] +} + +var unistUtilVisit$f = visit$f; + + + +var CONTINUE$v = unistUtilVisitParents$f.CONTINUE; +var SKIP$v = unistUtilVisitParents$f.SKIP; +var EXIT$v = unistUtilVisitParents$f.EXIT; + +visit$f.CONTINUE = CONTINUE$v; +visit$f.SKIP = SKIP$v; +visit$f.EXIT = EXIT$v; + +function visit$f(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$f(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintNoUndefinedReferences = unifiedLintRule( + 'remark-lint:no-undefined-references', + noUndefinedReferences +); + +var reason$7 = 'Found reference to undefined definition'; + +// The identifier is upcased to avoid naming collisions with fields inherited +// from `Object.prototype`. +// If `Object.create(null)` was used in place of `{}`, downcasing would work +// equally well. +function normalize$3(s) { + return collapseWhiteSpace(s.toUpperCase()) +} + +function noUndefinedReferences(tree, file, option) { + var allow = ((option || {}).allow || []).map(normalize$3); + var map = {}; + + unistUtilVisit$f(tree, ['definition', 'footnoteDefinition'], mark); + unistUtilVisit$f(tree, ['imageReference', 'linkReference', 'footnoteReference'], find); + + function mark(node) { + if (!unistUtilGenerated(node)) { + map[normalize$3(node.identifier)] = true; + } + } + + function find(node) { + if ( + !unistUtilGenerated(node) && + !(normalize$3(node.identifier) in map) && + allow.indexOf(normalize$3(node.identifier)) === -1 + ) { + file.message(reason$7, node); + } + } +} + +var convert_1$g = convert$h; + +function convert$h(test) { + if (typeof test === 'string') { + return typeFactory$g(test) + } + + if (test === null || test === undefined) { + return ok$h + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$g : matchesFactory$g)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$g(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$h(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$g(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$g(tests) { + var checks = convertAll$g(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$g(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$h() { + return true +} + +var unistUtilVisitParents$g = visitParents$g; + + + +var CONTINUE$w = true; +var SKIP$w = 'skip'; +var EXIT$w = false; + +visitParents$g.CONTINUE = CONTINUE$w; +visitParents$g.SKIP = SKIP$w; +visitParents$g.EXIT = EXIT$w; + +function visitParents$g(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$g(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$g(visitor(node, parents)); + + if (result[0] === EXIT$w) { + return result + } + } + + if (node.children && result[0] !== SKIP$w) { + subresult = toResult$g(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$w ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$w) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$g(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$w, value] + } + + return [value] +} + +var unistUtilVisit$g = visit$g; + + + +var CONTINUE$x = unistUtilVisitParents$g.CONTINUE; +var SKIP$x = unistUtilVisitParents$g.SKIP; +var EXIT$x = unistUtilVisitParents$g.EXIT; + +visit$g.CONTINUE = CONTINUE$x; +visit$g.SKIP = SKIP$x; +visit$g.EXIT = EXIT$x; + +function visit$g(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$g(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintNoUnusedDefinitions = unifiedLintRule('remark-lint:no-unused-definitions', noUnusedDefinitions); + +var reason$8 = 'Found unused definition'; + +function noUnusedDefinitions(tree, file) { + var map = {}; + var identifier; + var entry; + + unistUtilVisit$g(tree, ['definition', 'footnoteDefinition'], find); + unistUtilVisit$g(tree, ['imageReference', 'linkReference', 'footnoteReference'], mark); + + for (identifier in map) { + entry = map[identifier]; + + if (!entry.used) { + file.message(reason$8, entry.node); + } + } + + function find(node) { + if (!unistUtilGenerated(node)) { + map[node.identifier.toUpperCase()] = {node: node, used: false}; + } + } + + function mark(node) { + var info = map[node.identifier.toUpperCase()]; + + if (!unistUtilGenerated(node) && info) { + info.used = true; + } + } +} + +var plugins$1 = [ + remarkLint$1, + // Unix compatibility. + remarkLintFinalNewline, + // Rendering across vendors differs greatly if using other styles. + remarkLintListItemBulletIndent, + [remarkLintListItemIndent, 'tab-size'], + // Differs or unsupported across vendors. + remarkLintNoAutoLinkWithoutProtocol, + remarkLintNoBlockquoteWithoutMarker, + remarkLintNoLiteralUrls, + [remarkLintOrderedListMarkerStyle, '.'], + // Mistakes. + remarkLintHardBreakSpaces, + remarkLintNoDuplicateDefinitions, + remarkLintNoHeadingContentIndent, + remarkLintNoInlinePadding, + remarkLintNoShortcutReferenceImage, + remarkLintNoShortcutReferenceLink, + remarkLintNoUndefinedReferences, + remarkLintNoUnusedDefinitions +]; + +var remarkPresetLintRecommended = { + plugins: plugins$1 +}; + +var convert_1$h = convert$i; + +function convert$i(test) { + if (typeof test === 'string') { + return typeFactory$h(test) + } + + if (test === null || test === undefined) { + return ok$i + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$h : matchesFactory$h)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$h(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$i(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$h(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$h(tests) { + var checks = convertAll$h(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$h(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$i() { + return true +} + +var unistUtilVisitParents$h = visitParents$h; + + + +var CONTINUE$y = true; +var SKIP$y = 'skip'; +var EXIT$y = false; + +visitParents$h.CONTINUE = CONTINUE$y; +visitParents$h.SKIP = SKIP$y; +visitParents$h.EXIT = EXIT$y; + +function visitParents$h(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$h(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$h(visitor(node, parents)); + + if (result[0] === EXIT$y) { + return result + } + } + + if (node.children && result[0] !== SKIP$y) { + subresult = toResult$h(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$y ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$y) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$h(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$y, value] + } + + return [value] +} + +var unistUtilVisit$h = visit$h; + + + +var CONTINUE$z = unistUtilVisitParents$h.CONTINUE; +var SKIP$z = unistUtilVisitParents$h.SKIP; +var EXIT$z = unistUtilVisitParents$h.EXIT; + +visit$h.CONTINUE = CONTINUE$z; +visit$h.SKIP = SKIP$z; +visit$h.EXIT = EXIT$z; + +function visit$h(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$h(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintBlockquoteIndentation = unifiedLintRule( + 'remark-lint:blockquote-indentation', + blockquoteIndentation +); + +function blockquoteIndentation(tree, file, option) { + var preferred = typeof option === 'number' && !isNaN(option) ? option : null; + + unistUtilVisit$h(tree, 'blockquote', visitor); + + function visitor(node) { + var abs; + var diff; + var reason; + + if (unistUtilGenerated(node) || node.children.length === 0) { + return + } + + if (preferred) { + diff = preferred - check$3(node); + + if (diff !== 0) { + abs = Math.abs(diff); + reason = + (diff > 0 ? 'Add' : 'Remove') + + ' ' + + abs + + ' ' + + pluralize('space', abs) + + ' between block quote and content'; + + file.message(reason, unistUtilPosition.start(node.children[0])); + } + } else { + preferred = check$3(node); + } + } +} + +function check$3(node) { + var head = node.children[0]; + var indentation = unistUtilPosition.start(head).column - unistUtilPosition.start(node).column; + var padding = mdastUtilToString(head).match(/^ +/); + + if (padding) { + indentation += padding[0].length; + } + + return indentation +} + +var vfileLocation$4 = factory$c; + +function factory$c(file) { + var contents = indices$4(String(file)); + + return { + toPosition: offsetToPositionFactory$4(contents), + toOffset: positionToOffsetFactory$4(contents) + } +} + +// Factory to get the line and column-based `position` for `offset` in the bound +// indices. +function offsetToPositionFactory$4(indices) { + return offsetToPosition + + // Get the line and column-based `position` for `offset` in the bound indices. + function offsetToPosition(offset) { + var index = -1; + var length = indices.length; + + if (offset < 0) { + return {} + } + + while (++index < length) { + if (indices[index] > offset) { + return { + line: index + 1, + column: offset - (indices[index - 1] || 0) + 1, + offset: offset + } + } + } + + return {} + } +} + +// Factory to get the `offset` for a line and column-based `position` in the +// bound indices. +function positionToOffsetFactory$4(indices) { + return positionToOffset + + // Get the `offset` for a line and column-based `position` in the bound + // indices. + function positionToOffset(position) { + var line = position && position.line; + var column = position && position.column; + + if (!isNaN(line) && !isNaN(column) && line - 1 in indices) { + return (indices[line - 2] || 0) + column - 1 || 0 + } + + return -1 + } +} + +// Get indices of line-breaks in `value`. +function indices$4(value) { + var result = []; + var index = value.indexOf('\n'); + + while (index !== -1) { + result.push(index + 1); + index = value.indexOf('\n', index + 1); + } + + result.push(value.length + 1); + + return result +} + +var convert_1$i = convert$j; + +function convert$j(test) { + if (typeof test === 'string') { + return typeFactory$i(test) + } + + if (test === null || test === undefined) { + return ok$j + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$i : matchesFactory$i)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$i(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$j(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$i(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$i(tests) { + var checks = convertAll$i(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$i(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$j() { + return true +} + +var unistUtilVisitParents$i = visitParents$i; + + + +var CONTINUE$A = true; +var SKIP$A = 'skip'; +var EXIT$A = false; + +visitParents$i.CONTINUE = CONTINUE$A; +visitParents$i.SKIP = SKIP$A; +visitParents$i.EXIT = EXIT$A; + +function visitParents$i(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$i(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$i(visitor(node, parents)); + + if (result[0] === EXIT$A) { + return result + } + } + + if (node.children && result[0] !== SKIP$A) { + subresult = toResult$i(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$A ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$A) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$i(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$A, value] + } + + return [value] +} + +var unistUtilVisit$i = visit$i; + + + +var CONTINUE$B = unistUtilVisitParents$i.CONTINUE; +var SKIP$B = unistUtilVisitParents$i.SKIP; +var EXIT$B = unistUtilVisitParents$i.EXIT; + +visit$i.CONTINUE = CONTINUE$B; +visit$i.SKIP = SKIP$B; +visit$i.EXIT = EXIT$B; + +function visit$i(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$i(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintCheckboxCharacterStyle = unifiedLintRule( + 'remark-lint:checkbox-character-style', + checkboxCharacterStyle +); + +var start$8 = unistUtilPosition.start; +var end$4 = unistUtilPosition.end; + +var checked = {x: true, X: true}; +var unchecked = {' ': true, '\t': true}; +var types$1 = {true: 'checked', false: 'unchecked'}; + +function checkboxCharacterStyle(tree, file, option) { + var contents = String(file); + var location = vfileLocation$4(file); + var preferred = typeof option === 'object' ? option : {}; + + if (preferred.unchecked && unchecked[preferred.unchecked] !== true) { + file.fail( + 'Incorrect unchecked checkbox marker `' + + preferred.unchecked + + "`: use either `'\\t'`, or `' '`" + ); + } + + if (preferred.checked && checked[preferred.checked] !== true) { + file.fail( + 'Incorrect checked checkbox marker `' + + preferred.checked + + "`: use either `'x'`, or `'X'`" + ); + } + + unistUtilVisit$i(tree, 'listItem', visitor); + + function visitor(node) { + var type; + var initial; + var final; + var value; + var style; + var character; + var reason; + + // Exit early for items without checkbox. + if (typeof node.checked !== 'boolean' || unistUtilGenerated(node)) { + return + } + + type = types$1[node.checked]; + initial = start$8(node).offset; + final = (node.children.length === 0 ? end$4(node) : start$8(node.children[0])) + .offset; + + // For a checkbox to be parsed, it must be followed by a whitespace. + value = contents.slice(initial, final).replace(/\s+$/, '').slice(0, -1); + + // The checkbox character is behind a square bracket. + character = value.charAt(value.length - 1); + style = preferred[type]; + + if (style) { + if (character !== style) { + reason = + type.charAt(0).toUpperCase() + + type.slice(1) + + ' checkboxes should use `' + + style + + '` as a marker'; + + file.message(reason, { + start: location.toPosition(initial + value.length - 1), + end: location.toPosition(initial + value.length) + }); + } + } else { + preferred[type] = character; + } + } +} + +var vfileLocation$5 = factory$d; + +function factory$d(file) { + var contents = indices$5(String(file)); + + return { + toPosition: offsetToPositionFactory$5(contents), + toOffset: positionToOffsetFactory$5(contents) + } +} + +// Factory to get the line and column-based `position` for `offset` in the bound +// indices. +function offsetToPositionFactory$5(indices) { + return offsetToPosition + + // Get the line and column-based `position` for `offset` in the bound indices. + function offsetToPosition(offset) { + var index = -1; + var length = indices.length; + + if (offset < 0) { + return {} + } + + while (++index < length) { + if (indices[index] > offset) { + return { + line: index + 1, + column: offset - (indices[index - 1] || 0) + 1, + offset: offset + } + } + } + + return {} + } +} + +// Factory to get the `offset` for a line and column-based `position` in the +// bound indices. +function positionToOffsetFactory$5(indices) { + return positionToOffset + + // Get the `offset` for a line and column-based `position` in the bound + // indices. + function positionToOffset(position) { + var line = position && position.line; + var column = position && position.column; + + if (!isNaN(line) && !isNaN(column) && line - 1 in indices) { + return (indices[line - 2] || 0) + column - 1 || 0 + } + + return -1 + } +} + +// Get indices of line-breaks in `value`. +function indices$5(value) { + var result = []; + var index = value.indexOf('\n'); + + while (index !== -1) { + result.push(index + 1); + index = value.indexOf('\n', index + 1); + } + + result.push(value.length + 1); + + return result +} + +var convert_1$j = convert$k; + +function convert$k(test) { + if (typeof test === 'string') { + return typeFactory$j(test) + } + + if (test === null || test === undefined) { + return ok$k + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$j : matchesFactory$j)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$j(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$k(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$j(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$j(tests) { + var checks = convertAll$j(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$j(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$k() { + return true +} + +var unistUtilVisitParents$j = visitParents$j; + + + +var CONTINUE$C = true; +var SKIP$C = 'skip'; +var EXIT$C = false; + +visitParents$j.CONTINUE = CONTINUE$C; +visitParents$j.SKIP = SKIP$C; +visitParents$j.EXIT = EXIT$C; + +function visitParents$j(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$j(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$j(visitor(node, parents)); + + if (result[0] === EXIT$C) { + return result + } + } + + if (node.children && result[0] !== SKIP$C) { + subresult = toResult$j(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$C ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$C) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$j(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$C, value] + } + + return [value] +} + +var unistUtilVisit$j = visit$j; + + + +var CONTINUE$D = unistUtilVisitParents$j.CONTINUE; +var SKIP$D = unistUtilVisitParents$j.SKIP; +var EXIT$D = unistUtilVisitParents$j.EXIT; + +visit$j.CONTINUE = CONTINUE$D; +visit$j.SKIP = SKIP$D; +visit$j.EXIT = EXIT$D; + +function visit$j(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$j(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintCheckboxContentIndent = unifiedLintRule( + 'remark-lint:checkbox-content-indent', + checkboxContentIndent +); + +var start$9 = unistUtilPosition.start; +var end$5 = unistUtilPosition.end; + +var reason$9 = 'Checkboxes should be followed by a single character'; + +function checkboxContentIndent(tree, file) { + var contents = String(file); + var location = vfileLocation$5(file); + + unistUtilVisit$j(tree, 'listItem', visitor); + + function visitor(node) { + var initial; + var final; + var value; + + // Exit early for items without checkbox. + if (typeof node.checked !== 'boolean' || unistUtilGenerated(node)) { + return + } + + initial = start$9(node).offset; + /* istanbul ignore next - hard to test, couldn’t find a case. */ + final = (node.children.length === 0 ? end$5(node) : start$9(node.children[0])) + .offset; + + while (/[^\S\n]/.test(contents.charAt(final))) { + final++; + } + + // For a checkbox to be parsed, it must be followed by a whitespace. + value = contents.slice(initial, final); + value = value.slice(value.indexOf(']') + 1); + + if (value.length !== 1) { + file.message(reason$9, { + start: location.toPosition(final - value.length + 1), + end: location.toPosition(final) + }); + } + } +} + +var convert_1$k = convert$l; + +function convert$l(test) { + if (typeof test === 'string') { + return typeFactory$k(test) + } + + if (test === null || test === undefined) { + return ok$l + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$k : matchesFactory$k)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$k(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$l(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$k(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$k(tests) { + var checks = convertAll$k(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$k(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$l() { + return true +} + +var unistUtilVisitParents$k = visitParents$k; + + + +var CONTINUE$E = true; +var SKIP$E = 'skip'; +var EXIT$E = false; + +visitParents$k.CONTINUE = CONTINUE$E; +visitParents$k.SKIP = SKIP$E; +visitParents$k.EXIT = EXIT$E; + +function visitParents$k(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$k(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$k(visitor(node, parents)); + + if (result[0] === EXIT$E) { + return result + } + } + + if (node.children && result[0] !== SKIP$E) { + subresult = toResult$k(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$E ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$E) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$k(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$E, value] + } + + return [value] +} + +var unistUtilVisit$k = visit$k; + + + +var CONTINUE$F = unistUtilVisitParents$k.CONTINUE; +var SKIP$F = unistUtilVisitParents$k.SKIP; +var EXIT$F = unistUtilVisitParents$k.EXIT; + +visit$k.CONTINUE = CONTINUE$F; +visit$k.SKIP = SKIP$F; +visit$k.EXIT = EXIT$F; + +function visit$k(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$k(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintCodeBlockStyle = unifiedLintRule('remark-lint:code-block-style', codeBlockStyle); + +var start$a = unistUtilPosition.start; +var end$6 = unistUtilPosition.end; + +var styles$2 = {null: true, fenced: true, indented: true}; + +function codeBlockStyle(tree, file, option) { + var contents = String(file); + var preferred = + typeof option === 'string' && option !== 'consistent' ? option : null; + + if (styles$2[preferred] !== true) { + file.fail( + 'Incorrect code block style `' + + preferred + + "`: use either `'consistent'`, `'fenced'`, or `'indented'`" + ); + } + + unistUtilVisit$k(tree, 'code', visitor); + + function visitor(node) { + var initial; + var final; + var current; + + if (unistUtilGenerated(node)) { + return null + } + + initial = start$a(node).offset; + final = end$6(node).offset; + + current = + node.lang || /^\s*([~`])\1{2,}/.test(contents.slice(initial, final)) + ? 'fenced' + : 'indented'; + + if (preferred) { + if (preferred !== current) { + file.message('Code blocks should be ' + preferred, node); + } + } else { + preferred = current; + } + } +} + +var convert_1$l = convert$m; + +function convert$m(test) { + if (typeof test === 'string') { + return typeFactory$l(test) + } + + if (test === null || test === undefined) { + return ok$m + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$l : matchesFactory$l)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$l(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$m(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$l(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$l(tests) { + var checks = convertAll$l(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$l(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$m() { + return true +} + +var unistUtilVisitParents$l = visitParents$l; + + + +var CONTINUE$G = true; +var SKIP$G = 'skip'; +var EXIT$G = false; + +visitParents$l.CONTINUE = CONTINUE$G; +visitParents$l.SKIP = SKIP$G; +visitParents$l.EXIT = EXIT$G; + +function visitParents$l(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$l(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$l(visitor(node, parents)); + + if (result[0] === EXIT$G) { + return result + } + } + + if (node.children && result[0] !== SKIP$G) { + subresult = toResult$l(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$G ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$G) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$l(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$G, value] + } + + return [value] +} + +var unistUtilVisit$l = visit$l; + + + +var CONTINUE$H = unistUtilVisitParents$l.CONTINUE; +var SKIP$H = unistUtilVisitParents$l.SKIP; +var EXIT$H = unistUtilVisitParents$l.EXIT; + +visit$l.CONTINUE = CONTINUE$H; +visit$l.SKIP = SKIP$H; +visit$l.EXIT = EXIT$H; + +function visit$l(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$l(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintDefinitionSpacing = unifiedLintRule('remark-lint:definition-spacing', definitionSpacing); + +var label$1 = /^\s*\[((?:\\[\s\S]|[^[\]])+)]/; +var reason$a = 'Do not use consecutive whitespace in definition labels'; + +function definitionSpacing(tree, file) { + var contents = String(file); + + unistUtilVisit$l(tree, ['definition', 'footnoteDefinition'], check); + + function check(node) { + var start = unistUtilPosition.start(node).offset; + var end = unistUtilPosition.end(node).offset; + + if ( + !unistUtilGenerated(node) && + /[ \t\n]{2,}/.test(contents.slice(start, end).match(label$1)[1]) + ) { + file.message(reason$a, node); + } + } +} + +var convert_1$m = convert$n; + +function convert$n(test) { + if (typeof test === 'string') { + return typeFactory$m(test) + } + + if (test === null || test === undefined) { + return ok$n + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$m : matchesFactory$m)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$m(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$n(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$m(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$m(tests) { + var checks = convertAll$m(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$m(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$n() { + return true +} + +var unistUtilVisitParents$m = visitParents$m; + + + +var CONTINUE$I = true; +var SKIP$I = 'skip'; +var EXIT$I = false; + +visitParents$m.CONTINUE = CONTINUE$I; +visitParents$m.SKIP = SKIP$I; +visitParents$m.EXIT = EXIT$I; + +function visitParents$m(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$m(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$m(visitor(node, parents)); + + if (result[0] === EXIT$I) { + return result + } + } + + if (node.children && result[0] !== SKIP$I) { + subresult = toResult$m(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$I ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$I) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$m(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$I, value] + } + + return [value] +} + +var unistUtilVisit$m = visit$m; + + + +var CONTINUE$J = unistUtilVisitParents$m.CONTINUE; +var SKIP$J = unistUtilVisitParents$m.SKIP; +var EXIT$J = unistUtilVisitParents$m.EXIT; + +visit$m.CONTINUE = CONTINUE$J; +visit$m.SKIP = SKIP$J; +visit$m.EXIT = EXIT$J; + +function visit$m(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$m(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintFencedCodeFlag = unifiedLintRule('remark-lint:fenced-code-flag', fencedCodeFlag); + +var start$b = unistUtilPosition.start; +var end$7 = unistUtilPosition.end; + +var fence$2 = /^ {0,3}([~`])\1{2,}/; +var reasonIncorrect = 'Incorrect code language flag'; +var reasonMissing = 'Missing code language flag'; + +function fencedCodeFlag(tree, file, option) { + var contents = String(file); + var allowEmpty = false; + var allowed = []; + var flags = option; + + if (typeof flags === 'object' && !('length' in flags)) { + allowEmpty = Boolean(flags.allowEmpty); + flags = flags.flags; + } + + if (typeof flags === 'object' && 'length' in flags) { + allowed = String(flags).split(','); + } + + unistUtilVisit$m(tree, 'code', visitor); + + function visitor(node) { + var value; + + if (!unistUtilGenerated(node)) { + if (node.lang) { + if (allowed.length !== 0 && allowed.indexOf(node.lang) === -1) { + file.message(reasonIncorrect, node); + } + } else { + value = contents.slice(start$b(node).offset, end$7(node).offset); + + if (!allowEmpty && fence$2.test(value)) { + file.message(reasonMissing, node); + } + } + } + } +} + +var convert_1$n = convert$o; + +function convert$o(test) { + if (typeof test === 'string') { + return typeFactory$n(test) + } + + if (test === null || test === undefined) { + return ok$o + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$n : matchesFactory$n)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$n(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$o(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$n(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$n(tests) { + var checks = convertAll$n(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$n(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$o() { + return true +} + +var unistUtilVisitParents$n = visitParents$n; + + + +var CONTINUE$K = true; +var SKIP$K = 'skip'; +var EXIT$K = false; + +visitParents$n.CONTINUE = CONTINUE$K; +visitParents$n.SKIP = SKIP$K; +visitParents$n.EXIT = EXIT$K; + +function visitParents$n(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$n(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$n(visitor(node, parents)); + + if (result[0] === EXIT$K) { + return result + } + } + + if (node.children && result[0] !== SKIP$K) { + subresult = toResult$n(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$K ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$K) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$n(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$K, value] + } + + return [value] +} + +var unistUtilVisit$n = visit$n; + + + +var CONTINUE$L = unistUtilVisitParents$n.CONTINUE; +var SKIP$L = unistUtilVisitParents$n.SKIP; +var EXIT$L = unistUtilVisitParents$n.EXIT; + +visit$n.CONTINUE = CONTINUE$L; +visit$n.SKIP = SKIP$L; +visit$n.EXIT = EXIT$L; + +function visit$n(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$n(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintFencedCodeMarker = unifiedLintRule('remark-lint:fenced-code-marker', fencedCodeMarker); + +var markers = { + '`': true, + '~': true, + null: true +}; + +function fencedCodeMarker(tree, file, option) { + var contents = String(file); + var preferred = + typeof option === 'string' && option !== 'consistent' ? option : null; + + if (markers[preferred] !== true) { + file.fail( + 'Incorrect fenced code marker `' + + preferred + + "`: use either `'consistent'`, `` '`' ``, or `'~'`" + ); + } + + unistUtilVisit$n(tree, 'code', visitor); + + function visitor(node) { + var start; + var marker; + var label; + + if (!unistUtilGenerated(node)) { + start = unistUtilPosition.start(node).offset; + marker = contents + .slice(start, start + 4) + .replace(/^\s+/, '') + .charAt(0); + + // Ignore unfenced code blocks. + if (markers[marker] === true) { + if (preferred) { + if (marker !== preferred) { + label = preferred === '~' ? preferred : '` ` `'; + file.message( + 'Fenced code should use `' + label + '` as a marker', + node + ); + } + } else { + preferred = marker; + } + } + } + } +} + +var remarkLintFileExtension = unifiedLintRule('remark-lint:file-extension', fileExtension); + +function fileExtension(tree, file, option) { + var ext = file.extname; + var preferred = typeof option === 'string' ? option : 'md'; + + if (ext && ext.slice(1) !== preferred) { + file.message('Incorrect extension: use `' + preferred + '`'); + } +} + +var convert_1$o = convert$p; + +function convert$p(test) { + if (typeof test === 'string') { + return typeFactory$o(test) + } + + if (test === null || test === undefined) { + return ok$p + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$o : matchesFactory$o)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$o(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$p(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$o(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$o(tests) { + var checks = convertAll$o(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$o(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$p() { + return true +} + +var unistUtilVisitParents$o = visitParents$o; + + + +var CONTINUE$M = true; +var SKIP$M = 'skip'; +var EXIT$M = false; + +visitParents$o.CONTINUE = CONTINUE$M; +visitParents$o.SKIP = SKIP$M; +visitParents$o.EXIT = EXIT$M; + +function visitParents$o(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$o(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$o(visitor(node, parents)); + + if (result[0] === EXIT$M) { + return result + } + } + + if (node.children && result[0] !== SKIP$M) { + subresult = toResult$o(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$M ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$M) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$o(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$M, value] + } + + return [value] +} + +var unistUtilVisit$o = visit$o; + + + +var CONTINUE$N = unistUtilVisitParents$o.CONTINUE; +var SKIP$N = unistUtilVisitParents$o.SKIP; +var EXIT$N = unistUtilVisitParents$o.EXIT; + +visit$o.CONTINUE = CONTINUE$N; +visit$o.SKIP = SKIP$N; +visit$o.EXIT = EXIT$N; + +function visit$o(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$o(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintFinalDefinition = unifiedLintRule('remark-lint:final-definition', finalDefinition); + +var start$c = unistUtilPosition.start; + +function finalDefinition(tree, file) { + var last = null; + + unistUtilVisit$o(tree, visitor, true); + + function visitor(node) { + var line = start$c(node).line; + + // Ignore generated nodes. + if (node.type === 'root' || unistUtilGenerated(node)) { + return + } + + if (node.type === 'definition') { + if (last !== null && last > line) { + file.message( + 'Move definitions to the end of the file (after the node at line `' + + last + + '`)', + node + ); + } + } else if (last === null) { + last = line; + } + } +} + +var convert_1$p = convert$q; + +function convert$q(test) { + if (typeof test === 'string') { + return typeFactory$p(test) + } + + if (test === null || test === undefined) { + return ok$q + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$p : matchesFactory$p)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$p(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$q(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$p(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$p(tests) { + var checks = convertAll$p(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$p(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$q() { + return true +} + +var unistUtilVisitParents$p = visitParents$p; + + + +var CONTINUE$O = true; +var SKIP$O = 'skip'; +var EXIT$O = false; + +visitParents$p.CONTINUE = CONTINUE$O; +visitParents$p.SKIP = SKIP$O; +visitParents$p.EXIT = EXIT$O; + +function visitParents$p(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$p(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$p(visitor(node, parents)); + + if (result[0] === EXIT$O) { + return result + } + } + + if (node.children && result[0] !== SKIP$O) { + subresult = toResult$p(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$O ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$O) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$p(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$O, value] + } + + return [value] +} + +var unistUtilVisit$p = visit$p; + + + +var CONTINUE$P = unistUtilVisitParents$p.CONTINUE; +var SKIP$P = unistUtilVisitParents$p.SKIP; +var EXIT$P = unistUtilVisitParents$p.EXIT; + +visit$p.CONTINUE = CONTINUE$P; +visit$p.SKIP = SKIP$P; +visit$p.EXIT = EXIT$P; + +function visit$p(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$p(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintFirstHeadingLevel = unifiedLintRule('remark-lint:first-heading-level', firstHeadingLevel); + +var re$3 = / min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$Q) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$q(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$Q, value] + } + + return [value] +} + +var unistUtilVisit$q = visit$q; + + + +var CONTINUE$R = unistUtilVisitParents$q.CONTINUE; +var SKIP$R = unistUtilVisitParents$q.SKIP; +var EXIT$R = unistUtilVisitParents$q.EXIT; + +visit$q.CONTINUE = CONTINUE$R; +visit$q.SKIP = SKIP$R; +visit$q.EXIT = EXIT$R; + +function visit$q(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$q(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintHeadingStyle = unifiedLintRule('remark-lint:heading-style', headingStyle); + +var types$2 = ['atx', 'atx-closed', 'setext']; + +function headingStyle(tree, file, option) { + var preferred = types$2.indexOf(option) === -1 ? null : option; + + unistUtilVisit$q(tree, 'heading', visitor); + + function visitor(node) { + if (!unistUtilGenerated(node)) { + if (preferred) { + if (mdastUtilHeadingStyle(node, preferred) !== preferred) { + file.message('Headings should use ' + preferred, node); + } + } else { + preferred = mdastUtilHeadingStyle(node, preferred); + } + } + } +} + +var convert_1$r = convert$s; + +function convert$s(test) { + if (typeof test === 'string') { + return typeFactory$r(test) + } + + if (test === null || test === undefined) { + return ok$s + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$r : matchesFactory$r)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$r(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$s(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$r(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$r(tests) { + var checks = convertAll$r(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$r(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$s() { + return true +} + +var unistUtilVisitParents$r = visitParents$r; + + + +var CONTINUE$S = true; +var SKIP$S = 'skip'; +var EXIT$S = false; + +visitParents$r.CONTINUE = CONTINUE$S; +visitParents$r.SKIP = SKIP$S; +visitParents$r.EXIT = EXIT$S; + +function visitParents$r(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$r(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$r(visitor(node, parents)); + + if (result[0] === EXIT$S) { + return result + } + } + + if (node.children && result[0] !== SKIP$S) { + subresult = toResult$r(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$S ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$S) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$r(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$S, value] + } + + return [value] +} + +var unistUtilVisit$r = visit$r; + + + +var CONTINUE$T = unistUtilVisitParents$r.CONTINUE; +var SKIP$T = unistUtilVisitParents$r.SKIP; +var EXIT$T = unistUtilVisitParents$r.EXIT; + +visit$r.CONTINUE = CONTINUE$T; +visit$r.SKIP = SKIP$T; +visit$r.EXIT = EXIT$T; + +function visit$r(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$r(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintMaximumLineLength = unifiedLintRule('remark-lint:maximum-line-length', maximumLineLength); + +var start$d = unistUtilPosition.start; +var end$8 = unistUtilPosition.end; + +function maximumLineLength(tree, file, option) { + var preferred = typeof option === 'number' && !isNaN(option) ? option : 80; + var content = String(file); + var lines = content.split(/\r?\n/); + var length = lines.length; + var index = -1; + var lineLength; + + // Note: JSX is from MDX: . + unistUtilVisit$r(tree, ['heading', 'table', 'code', 'definition', 'html', 'jsx'], ignore); + unistUtilVisit$r(tree, ['link', 'image', 'inlineCode'], inline); + + // Iterate over every line, and warn for violating lines. + while (++index < length) { + lineLength = lines[index].length; + + if (lineLength > preferred) { + file.message('Line must be at most ' + preferred + ' characters', { + line: index + 1, + column: lineLength + 1 + }); + } + } + + // Finally, whitelist some inline spans, but only if they occur at or after + // the wrap. + // However, when they do, and there’s whitespace after it, they are not + // whitelisted. + function inline(node, pos, parent) { + var next = parent.children[pos + 1]; + var initial; + var final; + + /* istanbul ignore if - Nothing to whitelist when generated. */ + if (unistUtilGenerated(node)) { + return + } + + initial = start$d(node); + final = end$8(node); + + // No whitelisting when starting after the border, or ending before it. + if (initial.column > preferred || final.column < preferred) { + return + } + + // No whitelisting when there’s whitespace after the link. + if ( + next && + start$d(next).line === initial.line && + (!next.value || /^(.+?[ \t].+?)/.test(next.value)) + ) { + return + } + + whitelist(initial.line - 1, final.line); + } + + function ignore(node) { + /* istanbul ignore else - Hard to test, as we only run this case on `position: true` */ + if (!unistUtilGenerated(node)) { + whitelist(start$d(node).line - 1, end$8(node).line); + } + } + + // Whitelist from `initial` to `final`, zero-based. + function whitelist(initial, final) { + while (initial < final) { + lines[initial++] = ''; + } + } +} + +var convert_1$s = convert$t; + +function convert$t(test) { + if (typeof test === 'string') { + return typeFactory$s(test) + } + + if (test === null || test === undefined) { + return ok$t + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$s : matchesFactory$s)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$s(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$t(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$s(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$s(tests) { + var checks = convertAll$s(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$s(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$t() { + return true +} + +var unistUtilVisitParents$s = visitParents$s; + + + +var CONTINUE$U = true; +var SKIP$U = 'skip'; +var EXIT$U = false; + +visitParents$s.CONTINUE = CONTINUE$U; +visitParents$s.SKIP = SKIP$U; +visitParents$s.EXIT = EXIT$U; + +function visitParents$s(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$s(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$s(visitor(node, parents)); + + if (result[0] === EXIT$U) { + return result + } + } + + if (node.children && result[0] !== SKIP$U) { + subresult = toResult$s(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$U ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$U) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$s(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$U, value] + } + + return [value] +} + +var unistUtilVisit$s = visit$s; + + + +var CONTINUE$V = unistUtilVisitParents$s.CONTINUE; +var SKIP$V = unistUtilVisitParents$s.SKIP; +var EXIT$V = unistUtilVisitParents$s.EXIT; + +visit$s.CONTINUE = CONTINUE$V; +visit$s.SKIP = SKIP$V; +visit$s.EXIT = EXIT$V; + +function visit$s(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$s(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintNoConsecutiveBlankLines = unifiedLintRule( + 'remark-lint:no-consecutive-blank-lines', + noConsecutiveBlankLines +); + +function noConsecutiveBlankLines(tree, file) { + unistUtilVisit$s(tree, visitor); + + function visitor(node) { + var children = node.children; + var head; + var tail; + + if (!unistUtilGenerated(node) && children) { + head = children[0]; + + if (head && !unistUtilGenerated(head)) { + // Compare parent and first child. + compare(unistUtilPosition.start(node), unistUtilPosition.start(head), 0); + + // Compare between each child. + children.forEach(visitChild); + + tail = children[children.length - 1]; + + // Compare parent and last child. + if (tail !== head && !unistUtilGenerated(tail)) { + compare(unistUtilPosition.end(node), unistUtilPosition.end(tail), 1); + } + } + } + } + + // Compare the difference between `start` and `end`, and warn when that + // difference exceeds `max`. + function compare(start, end, max) { + var diff = end.line - start.line; + var lines = Math.abs(diff) - max; + var reason; + + if (lines > 0) { + reason = + 'Remove ' + + lines + + ' ' + + pluralize('line', Math.abs(lines)) + + ' ' + + (diff > 0 ? 'before' : 'after') + + ' node'; + + file.message(reason, end); + } + } + + function visitChild(child, index, all) { + var previous = all[index - 1]; + var max = 2; + + if (previous && !unistUtilGenerated(previous) && !unistUtilGenerated(child)) { + if ( + (previous.type === 'list' && child.type === 'list') || + (child.type === 'code' && previous.type === 'list' && !child.lang) + ) { + max++; + } + + compare(unistUtilPosition.end(previous), unistUtilPosition.start(child), max); + } + } +} + +var remarkLintNoFileNameArticles = unifiedLintRule('remark-lint:no-file-name-articles', noFileNameArticles); + +function noFileNameArticles(tree, file) { + var match = file.stem && file.stem.match(/^(the|teh|an?)\b/i); + + if (match) { + file.message('Do not start file names with `' + match[0] + '`'); + } +} + +var remarkLintNoFileNameConsecutiveDashes = unifiedLintRule( + 'remark-lint:no-file-name-consecutive-dashes', + noFileNameConsecutiveDashes +); + +var reason$b = 'Do not use consecutive dashes in a file name'; + +function noFileNameConsecutiveDashes(tree, file) { + if (file.stem && /-{2,}/.test(file.stem)) { + file.message(reason$b); + } +} + +var remarkLintNoFileNameOuterDashes = unifiedLintRule( + 'remark-lint:no-file-name-outer-dashes', + noFileNameOuterDashes +); + +var reason$c = 'Do not use initial or final dashes in a file name'; + +function noFileNameOuterDashes(tree, file) { + if (file.stem && /^-|-$/.test(file.stem)) { + file.message(reason$c); + } +} + +var convert_1$t = convert$u; + +function convert$u(test) { + if (typeof test === 'string') { + return typeFactory$t(test) + } + + if (test === null || test === undefined) { + return ok$u + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$t : matchesFactory$t)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$t(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$u(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$t(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$t(tests) { + var checks = convertAll$t(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$t(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$u() { + return true +} + +var unistUtilVisitParents$t = visitParents$t; + + + +var CONTINUE$W = true; +var SKIP$W = 'skip'; +var EXIT$W = false; + +visitParents$t.CONTINUE = CONTINUE$W; +visitParents$t.SKIP = SKIP$W; +visitParents$t.EXIT = EXIT$W; + +function visitParents$t(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$t(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$t(visitor(node, parents)); + + if (result[0] === EXIT$W) { + return result + } + } + + if (node.children && result[0] !== SKIP$W) { + subresult = toResult$t(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$W ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$W) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$t(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$W, value] + } + + return [value] +} + +var unistUtilVisit$t = visit$t; + + + +var CONTINUE$X = unistUtilVisitParents$t.CONTINUE; +var SKIP$X = unistUtilVisitParents$t.SKIP; +var EXIT$X = unistUtilVisitParents$t.EXIT; + +visit$t.CONTINUE = CONTINUE$X; +visit$t.SKIP = SKIP$X; +visit$t.EXIT = EXIT$X; + +function visit$t(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$t(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintNoHeadingIndent = unifiedLintRule('remark-lint:no-heading-indent', noHeadingIndent); + +var start$e = unistUtilPosition.start; + +function noHeadingIndent(tree, file) { + var contents = String(file); + var length = contents.length; + + unistUtilVisit$t(tree, 'heading', visitor); + + function visitor(node) { + var initial; + var begin; + var index; + var character; + var diff; + + if (unistUtilGenerated(node)) { + return + } + + initial = start$e(node); + begin = initial.offset; + index = begin - 1; + + while (++index < length) { + character = contents.charAt(index); + + if (character !== ' ' && character !== '\t') { + break + } + } + + diff = index - begin; + + if (diff) { + file.message( + 'Remove ' + diff + ' ' + pluralize('space', diff) + ' before this heading', + { + line: initial.line, + column: initial.column + diff + } + ); + } + } +} + +var convert_1$u = convert$v; + +function convert$v(test) { + if (typeof test === 'string') { + return typeFactory$u(test) + } + + if (test === null || test === undefined) { + return ok$v + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$u : matchesFactory$u)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$u(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$v(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$u(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$u(tests) { + var checks = convertAll$u(tests); + var length = checks.length; - /* istanbul ignore else - just for safety */ - if (character !== ' ' && character !== '\t') { - file.message(reason$1, pos); - break - } + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true } } + + return false } } -var remarkLintNoLiteralUrls = unifiedLintRule('remark-lint:no-literal-urls', noLiteralURLs); +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$u(test) { + return type -var start$5 = unistUtilPosition.start; -var end$2 = unistUtilPosition.end; -var mailto$3 = 'mailto:'; -var reason$2 = 'Don’t use literal URLs without angle brackets'; + function type(node) { + return Boolean(node && node.type === test) + } +} -function noLiteralURLs(tree, file) { - unistUtilVisit(tree, 'link', visitor); +// Utility to return true. +function ok$v() { + return true +} - function visitor(node) { - var children = node.children; - var value = mdastUtilToString(node); +var unistUtilVisitParents$u = visitParents$u; - if ( - !unistUtilGenerated(node) && - start$5(node).column === start$5(children[0]).column && - end$2(node).column === end$2(children[children.length - 1]).column && - (node.url === mailto$3 + value || node.url === value) - ) { - file.message(reason$2, node); + + +var CONTINUE$Y = true; +var SKIP$Y = 'skip'; +var EXIT$Y = false; + +visitParents$u.CONTINUE = CONTINUE$Y; +visitParents$u.SKIP = SKIP$Y; +visitParents$u.EXIT = EXIT$Y; + +function visitParents$u(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$u(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$u(visitor(node, parents)); + + if (result[0] === EXIT$Y) { + return result + } + } + + if (node.children && result[0] !== SKIP$Y) { + subresult = toResult$u(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$Y ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$Y) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; } } } -var remarkLintOrderedListMarkerStyle = unifiedLintRule( - 'remark-lint:ordered-list-marker-style', - orderedListMarkerStyle -); +function toResult$u(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } -var start$6 = unistUtilPosition.start; + if (typeof value === 'number') { + return [CONTINUE$Y, value] + } -var styles$1 = { - ')': true, - '.': true, - null: true -}; + return [value] +} -function orderedListMarkerStyle(tree, file, pref) { - var contents = String(file); +var unistUtilVisit$u = visit$u; - pref = typeof pref !== 'string' || pref === 'consistent' ? null : pref; - if (styles$1[pref] !== true) { - file.fail( - 'Invalid ordered list-item marker style `' + - pref + - "`: use either `'.'` or `')'`" - ); + +var CONTINUE$Z = unistUtilVisitParents$u.CONTINUE; +var SKIP$Z = unistUtilVisitParents$u.SKIP; +var EXIT$Z = unistUtilVisitParents$u.EXIT; + +visit$u.CONTINUE = CONTINUE$Z; +visit$u.SKIP = SKIP$Z; +visit$u.EXIT = EXIT$Z; + +function visit$u(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$u(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) } +} + +var start$f = unistUtilPosition.start; - unistUtilVisit(tree, 'list', visitor); + + +var remarkLintNoMultipleToplevelHeadings = unifiedLintRule( + 'remark-lint:no-multiple-toplevel-headings', + noMultipleToplevelHeadings +); + +function noMultipleToplevelHeadings(tree, file, option) { + var preferred = option || 1; + var duplicate; + + unistUtilVisit$u(tree, 'heading', visitor); function visitor(node) { - var children = node.children; - var length = node.ordered ? children.length : 0; - var index = -1; - var marker; - var child; + if (!unistUtilGenerated(node) && node.depth === preferred) { + if (duplicate) { + file.message( + 'Don’t use multiple top level headings (' + duplicate + ')', + node + ); + } else { + duplicate = unistUtilStringifyPosition(start$f(node)); + } + } + } +} - while (++index < length) { - child = children[index]; +var convert_1$v = convert$w; - if (!unistUtilGenerated(child)) { - marker = contents - .slice(start$6(child).offset, start$6(child.children[0]).offset) - .replace(/\s|\d/g, '') - .replace(/\[[x ]?]\s*$/i, ''); +function convert$w(test) { + if (typeof test === 'string') { + return typeFactory$v(test) + } - if (pref) { - if (marker !== pref) { - file.message('Marker style should be `' + pref + '`', child); - } - } else { - pref = marker; - } + if (test === null || test === undefined) { + return ok$w + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$v : matchesFactory$v)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$v(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$w(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$v(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false } } + + return true } } -var remarkLintHardBreakSpaces = unifiedLintRule('remark-lint:hard-break-spaces', hardBreakSpaces); +function anyFactory$v(tests) { + var checks = convertAll$v(tests); + var length = checks.length; -var reason$3 = 'Use two spaces for hard line breaks'; + return matches -function hardBreakSpaces(tree, file) { - var contents = String(file); + function matches() { + var index = -1; - unistUtilVisit(tree, 'break', visitor); + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } - function visitor(node) { - var value; + return false + } +} - if (!unistUtilGenerated(node)) { - value = contents - .slice(unistUtilPosition.start(node).offset, unistUtilPosition.end(node).offset) - .split('\n', 1)[0] - .replace(/\r$/, ''); +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$v(test) { + return type - if (value.length > 2) { - file.message(reason$3, node); + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$w() { + return true +} + +var unistUtilVisitParents$v = visitParents$v; + + + +var CONTINUE$_ = true; +var SKIP$_ = 'skip'; +var EXIT$_ = false; + +visitParents$v.CONTINUE = CONTINUE$_; +visitParents$v.SKIP = SKIP$_; +visitParents$v.EXIT = EXIT$_; + +function visitParents$v(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$v(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$v(visitor(node, parents)); + + if (result[0] === EXIT$_) { + return result + } + } + + if (node.children && result[0] !== SKIP$_) { + subresult = toResult$v(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$_ ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$_) { + return result } + + index = typeof result[1] === 'number' ? result[1] : index + step; } } } -var remarkLintNoDuplicateDefinitions = unifiedLintRule( - 'remark-lint:no-duplicate-definitions', - noDuplicateDefinitions -); +function toResult$v(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } -var reason$4 = 'Do not use definitions with the same identifier'; + if (typeof value === 'number') { + return [CONTINUE$_, value] + } -function noDuplicateDefinitions(tree, file) { - var map = {}; + return [value] +} - unistUtilVisit(tree, ['definition', 'footnoteDefinition'], validate); +var unistUtilVisit$v = visit$v; - function validate(node) { - var identifier; - var duplicate; - if (!unistUtilGenerated(node)) { - identifier = node.identifier; - duplicate = map[identifier]; - if (duplicate && duplicate.type) { - file.message( - reason$4 + ' (' + unistUtilStringifyPosition(unistUtilPosition.start(duplicate)) + ')', - node - ); +var CONTINUE$$ = unistUtilVisitParents$v.CONTINUE; +var SKIP$$ = unistUtilVisitParents$v.SKIP; +var EXIT$$ = unistUtilVisitParents$v.EXIT; + +visit$v.CONTINUE = CONTINUE$$; +visit$v.SKIP = SKIP$$; +visit$v.EXIT = EXIT$$; + +function visit$v(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$v(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + +var remarkLintNoShellDollars = unifiedLintRule('remark-lint:no-shell-dollars', noShellDollars); + +var reason$d = 'Do not use dollar signs before shell commands'; + +// List of shell script file extensions (also used as code flags for syntax +// highlighting on GitHub): +// See: +var flags = [ + 'sh', + 'bash', + 'bats', + 'cgi', + 'command', + 'fcgi', + 'ksh', + 'tmux', + 'tool', + 'zsh' +]; + +function noShellDollars(tree, file) { + unistUtilVisit$v(tree, 'code', visitor); + + function visitor(node) { + var lines; + var line; + var length; + var index; + + // Check both known shell code and unknown code. + if (!unistUtilGenerated(node) && node.lang && flags.indexOf(node.lang) !== -1) { + lines = node.value.split('\n'); + length = lines.length; + index = -1; + + if (length <= 1) { + return } - map[identifier] = node; + while (++index < length) { + line = lines[index]; + + if (line.trim() && !line.match(/^\s*\$\s*/)) { + return + } + } + + file.message(reason$d, node); } } } -var mdastUtilHeadingStyle = style; +var convert_1$w = convert$x; -function style(node, relative) { - var last = node.children[node.children.length - 1]; - var depth = node.depth; - var pos = node && node.position && node.position.end; - var final = last && last.position && last.position.end; +function convert$x(test) { + if (typeof test === 'string') { + return typeFactory$w(test) + } - if (!pos) { - return null + if (test === null || test === undefined) { + return ok$x } - // This can only occur for `'atx'` and `'atx-closed'` headings. - // This might incorrectly match `'atx'` headings with lots of trailing white - // space as an `'atx-closed'` heading. - if (!last) { - if (pos.column - 1 <= depth * 2) { - return consolidate(depth, relative) + if (typeof test === 'object') { + return ('length' in test ? anyFactory$w : matchesFactory$w)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$w(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$x(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$w(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } } - return 'atx-closed' + return true } +} - if (final.line + 1 === pos.line) { - return 'setext' +function anyFactory$w(tests) { + var checks = convertAll$w(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false } +} - if (final.column + depth < pos.column) { - return 'atx-closed' +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$w(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) } +} - return consolidate(depth, relative) +// Utility to return true. +function ok$x() { + return true } -// Get the probable style of an atx-heading, depending on preferred style. -function consolidate(depth, relative) { - return depth < 3 - ? 'atx' - : relative === 'atx' || relative === 'setext' - ? relative - : null +var unistUtilVisitParents$w = visitParents$w; + + + +var CONTINUE$10 = true; +var SKIP$10 = 'skip'; +var EXIT$10 = false; + +visitParents$w.CONTINUE = CONTINUE$10; +visitParents$w.SKIP = SKIP$10; +visitParents$w.EXIT = EXIT$10; + +function visitParents$w(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$w(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$w(visitor(node, parents)); + + if (result[0] === EXIT$10) { + return result + } + } + + if (node.children && result[0] !== SKIP$10) { + subresult = toResult$w(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$10 ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$10) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } } -var remarkLintNoHeadingContentIndent = unifiedLintRule( - 'remark-lint:no-heading-content-indent', - noHeadingContentIndent -); +function toResult$w(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } -var start$7 = unistUtilPosition.start; -var end$3 = unistUtilPosition.end; + if (typeof value === 'number') { + return [CONTINUE$10, value] + } -function noHeadingContentIndent(tree, file) { - var contents = String(file); + return [value] +} - unistUtilVisit(tree, 'heading', visitor); +var unistUtilVisit$w = visit$w; - function visitor(node) { - var depth; - var children; - var type; - var head; - var initial; - var final; - var diff; - var index; - var char; - var reason; - if (unistUtilGenerated(node)) { - return - } - depth = node.depth; - children = node.children; - type = mdastUtilHeadingStyle(node, 'atx'); +var CONTINUE$11 = unistUtilVisitParents$w.CONTINUE; +var SKIP$11 = unistUtilVisitParents$w.SKIP; +var EXIT$11 = unistUtilVisitParents$w.EXIT; - if (type === 'atx' || type === 'atx-closed') { - initial = start$7(node); - index = initial.offset; - char = contents.charAt(index); +visit$w.CONTINUE = CONTINUE$11; +visit$w.SKIP = SKIP$11; +visit$w.EXIT = EXIT$11; - while (char && char !== '#') { - char = contents.charAt(++index); - } +function visit$w(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } - /* istanbul ignore if - CR/LF bug: remarkjs/remark#195. */ - if (!char) { - return - } + unistUtilVisitParents$w(tree, test, overload, reverse); - index = depth + (index - initial.offset); - head = start$7(children[0]).column; + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} - // Ignore empty headings. - if (!head) { - return - } +var remarkLintNoTableIndentation = unifiedLintRule('remark-lint:no-table-indentation', noTableIndentation); - diff = head - initial.column - 1 - index; +var reason$e = 'Do not indent table rows'; - if (diff) { - reason = - (diff > 0 ? 'Remove' : 'Add') + - ' ' + - Math.abs(diff) + - ' ' + - plur('space', diff) + - ' before this heading’s content'; +function noTableIndentation(tree, file) { + var contents = String(file); - file.message(reason, start$7(children[0])); - } + unistUtilVisit$w(tree, 'table', visitor); + + function visitor(node) { + if (!unistUtilGenerated(node)) { + node.children.forEach(each); } - // Closed ATX-heading always must have a space between their content and the - // final hashes, thus, there is no `add x spaces`. - if (type === 'atx-closed') { - final = end$3(children[children.length - 1]); - diff = end$3(node).column - final.column - 1 - depth; + return unistUtilVisit$w.SKIP + } - if (diff) { - reason = - 'Remove ' + - diff + - ' ' + - plur('space', diff) + - ' after this heading’s content'; + function each(row) { + var fence = contents.slice( + unistUtilPosition.start(row).offset, + unistUtilPosition.start(row.children[0]).offset + ); - file.message(reason, final); - } + if (fence.indexOf('|') > 1) { + file.message(reason$e, row); } } } -var remarkLintNoInlinePadding = unifiedLintRule('remark-lint:no-inline-padding', noInlinePadding); - -function noInlinePadding(tree, file) { - unistUtilVisit(tree, ['emphasis', 'strong', 'delete', 'image', 'link'], visitor); - - function visitor(node) { - var contents; +var vfileLocation$6 = factory$e; - if (!unistUtilGenerated(node)) { - contents = mdastUtilToString(node); +function factory$e(file) { + var contents = indices$6(String(file)); - if ( - contents.charAt(0) === ' ' || - contents.charAt(contents.length - 1) === ' ' - ) { - file.message('Don’t pad `' + node.type + '` with inner spaces', node); - } - } + return { + toPosition: offsetToPositionFactory$6(contents), + toOffset: positionToOffsetFactory$6(contents) } } -var remarkLintNoShortcutReferenceImage = unifiedLintRule( - 'remark-lint:no-shortcut-reference-image', - noShortcutReferenceImage -); +// Factory to get the line and column-based `position` for `offset` in the bound +// indices. +function offsetToPositionFactory$6(indices) { + return offsetToPosition -var reason$5 = 'Use the trailing [] on reference images'; + // Get the line and column-based `position` for `offset` in the bound indices. + function offsetToPosition(offset) { + var index = -1; + var length = indices.length; -function noShortcutReferenceImage(tree, file) { - unistUtilVisit(tree, 'imageReference', visitor); + if (offset < 0) { + return {} + } - function visitor(node) { - if (!unistUtilGenerated(node) && node.referenceType === 'shortcut') { - file.message(reason$5, node); + while (++index < length) { + if (indices[index] > offset) { + return { + line: index + 1, + column: offset - (indices[index - 1] || 0) + 1, + offset: offset + } + } } + + return {} } } -var remarkLintNoShortcutReferenceLink = unifiedLintRule( - 'remark-lint:no-shortcut-reference-link', - noShortcutReferenceLink -); - -var reason$6 = 'Use the trailing [] on reference links'; +// Factory to get the `offset` for a line and column-based `position` in the +// bound indices. +function positionToOffsetFactory$6(indices) { + return positionToOffset -function noShortcutReferenceLink(tree, file) { - unistUtilVisit(tree, 'linkReference', visitor); + // Get the `offset` for a line and column-based `position` in the bound + // indices. + function positionToOffset(position) { + var line = position && position.line; + var column = position && position.column; - function visitor(node) { - if (!unistUtilGenerated(node) && node.referenceType === 'shortcut') { - file.message(reason$6, node); + if (!isNaN(line) && !isNaN(column) && line - 1 in indices) { + return (indices[line - 2] || 0) + column - 1 || 0 } + + return -1 } } -var remarkLintNoUndefinedReferences = unifiedLintRule( - 'remark-lint:no-undefined-references', - noUndefinedReferences -); +// Get indices of line-breaks in `value`. +function indices$6(value) { + var result = []; + var index = value.indexOf('\n'); -var reason$7 = 'Found reference to undefined definition'; + while (index !== -1) { + result.push(index + 1); + index = value.indexOf('\n', index + 1); + } -// The identifier is upcased to avoid naming collisions with properties -// inherited from `Object.prototype`. Were `Object.create(null)` to be -// used in place of `{}`, downcasing would work equally well. -function normalize$3(s) { - return collapseWhiteSpace(s.toUpperCase()) + result.push(value.length + 1); + + return result } -function noUndefinedReferences(tree, file, pref) { - var allow = - pref != null && Array.isArray(pref.allow) ? pref.allow.map(normalize$3) : []; +var remarkLintNoTabs = unifiedLintRule('remark-lint:no-tabs', noTabs); - var map = {}; +var reason$f = 'Use spaces instead of tabs'; - unistUtilVisit(tree, ['definition', 'footnoteDefinition'], mark); - unistUtilVisit(tree, ['imageReference', 'linkReference', 'footnoteReference'], find); +function noTabs(tree, file) { + var content = String(file); + var position = vfileLocation$6(file).toPosition; + var index = content.indexOf('\t'); - function mark(node) { - if (!unistUtilGenerated(node)) { - map[normalize$3(node.identifier)] = true; - } + while (index !== -1) { + file.message(reason$f, position(index)); + index = content.indexOf('\t', index + 1); } +} - function find(node) { - if ( - !( - unistUtilGenerated(node) || - allow.includes(normalize$3(node.identifier)) || - normalize$3(node.identifier) in map - ) - ) { - file.message(reason$7, node); +var remarkLintNoTrailingSpaces = unifiedLintRule('remark-lint:no-trailing-spaces', noTrailingSpaces); + +/** + * Lines that are just space characters are not present in + * the AST, which is why we loop through lines manually. + */ + +function noTrailingSpaces(ast, file) { + var lines = file.toString().split(/\r?\n/); + for (var i = 0; i < lines.length; i++) { + var currentLine = lines[i]; + var lineIndex = i + 1; + if (/\s$/.test(currentLine)) { + file.message('Remove trailing whitespace', { + position: { + start: { line: lineIndex, column: currentLine.length + 1 }, + end: { line: lineIndex } + } + }); } } } -var remarkLintNoUnusedDefinitions = unifiedLintRule('remark-lint:no-unused-definitions', noUnusedDefinitions); - -var reason$8 = 'Found unused definition'; - -function noUnusedDefinitions(tree, file) { - var map = {}; - var identifier; - var entry; +var escapeStringRegexp$1 = string => { + if (typeof string !== 'string') { + throw new TypeError('Expected a string'); + } - unistUtilVisit(tree, ['definition', 'footnoteDefinition'], find); - unistUtilVisit(tree, ['imageReference', 'linkReference', 'footnoteReference'], mark); + // Escape characters with special meaning either inside or outside character sets. + // Use a simple backslash escape when it’s always valid, and a \unnnn escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar. + return string + .replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') + .replace(/-/g, '\\x2d'); +}; - for (identifier in map) { - entry = map[identifier]; +var convert_1$x = convert$y; - if (!entry.used) { - file.message(reason$8, entry.node); - } +function convert$y(test) { + if (typeof test === 'string') { + return typeFactory$x(test) } - function find(node) { - if (!unistUtilGenerated(node)) { - map[node.identifier.toUpperCase()] = {node: node, used: false}; - } + if (test === null || test === undefined) { + return ok$y } - function mark(node) { - var info = map[node.identifier.toUpperCase()]; + if (typeof test === 'object') { + return ('length' in test ? anyFactory$x : matchesFactory$x)(test) + } - if (!unistUtilGenerated(node) && info) { - info.used = true; - } + if (typeof test === 'function') { + return test } -} -var plugins$1 = [ - remarkLint, - // Unix compatibility. - remarkLintFinalNewline, - // Rendering across vendors differs greatly if using other styles. - remarkLintListItemBulletIndent, - [remarkLintListItemIndent, 'tab-size'], - // Differs or unsupported across vendors. - remarkLintNoAutoLinkWithoutProtocol, - remarkLintNoBlockquoteWithoutMarker, - remarkLintNoLiteralUrls, - [remarkLintOrderedListMarkerStyle, '.'], - // Mistakes. - remarkLintHardBreakSpaces, - remarkLintNoDuplicateDefinitions, - remarkLintNoHeadingContentIndent, - remarkLintNoInlinePadding, - remarkLintNoShortcutReferenceImage, - remarkLintNoShortcutReferenceLink, - remarkLintNoUndefinedReferences, - remarkLintNoUnusedDefinitions -]; + throw new Error('Expected function, string, or object as test') +} -var remarkPresetLintRecommended = { - plugins: plugins$1 -}; +function convertAll$x(tests) { + var results = []; + var length = tests.length; + var index = -1; -var remarkLintBlockquoteIndentation = unifiedLintRule( - 'remark-lint:blockquote-indentation', - blockquoteIndentation -); + while (++index < length) { + results[index] = convert$y(tests[index]); + } -function blockquoteIndentation(tree, file, pref) { - pref = typeof pref === 'number' && !isNaN(pref) ? pref : null; + return results +} - unistUtilVisit(tree, 'blockquote', visitor); +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$x(test) { + return matches - function visitor(node) { - var diff; - var reason; + function matches(node) { + var key; - if (unistUtilGenerated(node) || node.children.length === 0) { - return + for (key in test) { + if (node[key] !== test[key]) { + return false + } } - if (pref) { - diff = pref - check$3(node); + return true + } +} - if (diff !== 0) { - reason = - (diff > 0 ? 'Add' : 'Remove') + - ' ' + - Math.abs(diff) + - ' ' + - plur('space', diff) + - ' between blockquote and content'; +function anyFactory$x(tests) { + var checks = convertAll$x(tests); + var length = checks.length; - file.message(reason, unistUtilPosition.start(node.children[0])); + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true } - } else { - pref = check$3(node); } + + return false } } -function check$3(node) { - var head = node.children[0]; - var indentation = unistUtilPosition.start(head).column - unistUtilPosition.start(node).column; - var padding = mdastUtilToString(head).match(/^ +/); +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$x(test) { + return type - if (padding) { - indentation += padding[0].length; + function type(node) { + return Boolean(node && node.type === test) } +} - return indentation +// Utility to return true. +function ok$y() { + return true } -var remarkLintCheckboxCharacterStyle = unifiedLintRule( - 'remark-lint:checkbox-character-style', - checkboxCharacterStyle -); +var unistUtilVisitParents$x = visitParents$x; -var start$8 = unistUtilPosition.start; -var end$4 = unistUtilPosition.end; -var checked = {x: true, X: true}; -var unchecked = {' ': true, '\t': true}; -var types$1 = {true: 'checked', false: 'unchecked'}; -function checkboxCharacterStyle(tree, file, pref) { - var contents = String(file); - var location = vfileLocation(file); +var CONTINUE$12 = true; +var SKIP$12 = 'skip'; +var EXIT$12 = false; - pref = typeof pref === 'object' ? pref : {}; +visitParents$x.CONTINUE = CONTINUE$12; +visitParents$x.SKIP = SKIP$12; +visitParents$x.EXIT = EXIT$12; - if (pref.unchecked && unchecked[pref.unchecked] !== true) { - file.fail( - 'Invalid unchecked checkbox marker `' + - pref.unchecked + - "`: use either `'\\t'`, or `' '`" - ); - } +function visitParents$x(tree, test, visitor, reverse) { + var is; - if (pref.checked && checked[pref.checked] !== true) { - file.fail( - 'Invalid checked checkbox marker `' + - pref.checked + - "`: use either `'x'`, or `'X'`" - ); + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; } - unistUtilVisit(tree, 'listItem', visitor); + is = convert_1$x(test); - function visitor(node) { - var type; - var initial; - var final; - var value; - var style; - var character; - var reason; + one(tree, null, []); - // Exit early for items without checkbox. - if (typeof node.checked !== 'boolean' || unistUtilGenerated(node)) { - return + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$x(visitor(node, parents)); + + if (result[0] === EXIT$12) { + return result + } } - type = types$1[node.checked]; - initial = start$8(node).offset; - final = (node.children.length === 0 ? end$4(node) : start$8(node.children[0])) - .offset; + if (node.children && result[0] !== SKIP$12) { + subresult = toResult$x(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$12 ? subresult : result + } - // For a checkbox to be parsed, it must be followed by a whitespace. - value = contents - .slice(initial, final) - .trimRight() - .slice(0, -1); + return result + } - // The checkbox character is behind a square bracket. - character = value.charAt(value.length - 1); - style = pref[type]; + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; - if (style) { - if (character !== style) { - reason = - type.charAt(0).toUpperCase() + - type.slice(1) + - ' checkboxes should use `' + - style + - '` as a marker'; + while (index > min && index < children.length) { + result = one(children[index], index, parents); - file.message(reason, { - start: location.toPosition(initial + value.length - 1), - end: location.toPosition(initial + value.length) - }); + if (result[0] === EXIT$12) { + return result } - } else { - pref[type] = character; + + index = typeof result[1] === 'number' ? result[1] : index + step; } } } -var remarkLintCheckboxContentIndent = unifiedLintRule( - 'remark-lint:checkbox-content-indent', - checkboxContentIndent -); +function toResult$x(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } -var start$9 = unistUtilPosition.start; -var end$5 = unistUtilPosition.end; + if (typeof value === 'number') { + return [CONTINUE$12, value] + } -var reason$9 = 'Checkboxes should be followed by a single character'; + return [value] +} -function checkboxContentIndent(tree, file) { - var contents = String(file); - var location = vfileLocation(file); +var unistUtilVisit$x = visit$x; - unistUtilVisit(tree, 'listItem', visitor); - function visitor(node) { - var initial; - var final; - var value; - // Exit early for items without checkbox. - if (typeof node.checked !== 'boolean' || unistUtilGenerated(node)) { - return - } +var CONTINUE$13 = unistUtilVisitParents$x.CONTINUE; +var SKIP$13 = unistUtilVisitParents$x.SKIP; +var EXIT$13 = unistUtilVisitParents$x.EXIT; - initial = start$9(node).offset; - /* istanbul ignore next - hard to test, couldn’t find a case. */ - final = (node.children.length === 0 ? end$5(node) : start$9(node.children[0])) - .offset; +visit$x.CONTINUE = CONTINUE$13; +visit$x.SKIP = SKIP$13; +visit$x.EXIT = EXIT$13; - while (/[^\S\n]/.test(contents.charAt(final))) { - final++; - } +function visit$x(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } - // For a checkbox to be parsed, it must be followed by a whitespace. - value = contents.slice(initial, final); - value = value.slice(value.indexOf(']') + 1); + unistUtilVisitParents$x(tree, test, overload, reverse); - if (value.length !== 1) { - file.message(reason$9, { - start: location.toPosition(final - value.length + 1), - end: location.toPosition(final) - }); - } + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) } } -var remarkLintCodeBlockStyle = unifiedLintRule('remark-lint:code-block-style', codeBlockStyle); - -var start$a = unistUtilPosition.start; -var end$6 = unistUtilPosition.end; - -var styles$2 = {null: true, fenced: true, indented: true}; - -function codeBlockStyle(tree, file, pref) { - var contents = String(file); +var vfileLocation$7 = factory$f; - pref = typeof pref === 'string' && pref !== 'consistent' ? pref : null; +function factory$f(file) { + var contents = indices$7(String(file)); - if (styles$2[pref] !== true) { - file.fail( - 'Invalid code block style `' + - pref + - "`: use either `'consistent'`, `'fenced'`, or `'indented'`" - ); + return { + toPosition: offsetToPositionFactory$7(contents), + toOffset: positionToOffsetFactory$7(contents) } +} - unistUtilVisit(tree, 'code', visitor); +// Factory to get the line and column-based `position` for `offset` in the bound +// indices. +function offsetToPositionFactory$7(indices) { + return offsetToPosition - function visitor(node) { - var current = check(node); + // Get the line and column-based `position` for `offset` in the bound indices. + function offsetToPosition(offset) { + var index = -1; + var length = indices.length; - if (current) { - if (!pref) { - pref = current; - } else if (pref !== current) { - file.message('Code blocks should be ' + pref, node); + if (offset < 0) { + return {} + } + + while (++index < length) { + if (indices[index] > offset) { + return { + line: index + 1, + column: offset - (indices[index - 1] || 0) + 1, + offset: offset + } } } + + return {} } +} - // Get the style of `node`. - function check(node) { - var initial = start$a(node).offset; - var final = end$6(node).offset; +// Factory to get the `offset` for a line and column-based `position` in the +// bound indices. +function positionToOffsetFactory$7(indices) { + return positionToOffset - if (unistUtilGenerated(node)) { - return null + // Get the `offset` for a line and column-based `position` in the bound + // indices. + function positionToOffset(position) { + var line = position && position.line; + var column = position && position.column; + + if (!isNaN(line) && !isNaN(column) && line - 1 in indices) { + return (indices[line - 2] || 0) + column - 1 || 0 } - return node.lang || /^\s*([~`])\1{2,}/.test(contents.slice(initial, final)) - ? 'fenced' - : 'indented' + return -1 } } -var remarkLintDefinitionSpacing = unifiedLintRule('remark-lint:definition-spacing', definitionSpacing); +// Get indices of line-breaks in `value`. +function indices$7(value) { + var result = []; + var index = value.indexOf('\n'); + + while (index !== -1) { + result.push(index + 1); + index = value.indexOf('\n', index + 1); + } + + result.push(value.length + 1); -var label$1 = /^\s*\[((?:\\[\s\S]|[^[\]])+)]/; -var reason$a = 'Do not use consecutive white-space in definition labels'; + return result +} -function definitionSpacing(tree, file) { - var contents = String(file); +const start$g = unistUtilPosition.start; - unistUtilVisit(tree, ['definition', 'footnoteDefinition'], validate); +var remarkLintProhibitedStrings = unifiedLintRule('remark-lint:prohibited-strings', prohibitedStrings); - function validate(node) { - var start = unistUtilPosition.start(node).offset; - var end = unistUtilPosition.end(node).offset; +function testProhibited (val, content) { + let regexpFlags = 'g'; - if ( - !unistUtilGenerated(node) && - /[ \t\n]{2,}/.test(contents.slice(start, end).match(label$1)[1]) - ) { - file.message(reason$a, node); - } + if (!val.no) { + val.no = escapeStringRegexp$1(val.yes); + regexpFlags += 'i'; } -} -var remarkLintFencedCodeFlag = unifiedLintRule('remark-lint:fenced-code-flag', fencedCodeFlag); + let regexpString = '(? { + const results = testProhibited(val, content); + if (results.length) { + results.forEach(({ result, index }) => { + const message = val.yes ? `Use "${val.yes}" instead of "${result}"` : `Do not use "${result}"`; + file.message(message, { + start: location.toPosition(initial + index), + end: location.toPosition(initial + index + [...result].length) + }); + }); } - } + }); } } -var remarkLintFencedCodeMarker = unifiedLintRule('remark-lint:fenced-code-marker', fencedCodeMarker); - -var markers = { - '`': true, - '~': true, - null: true -}; +var convert_1$y = convert$z; -function fencedCodeMarker(tree, file, pref) { - var contents = String(file); +function convert$z(test) { + if (typeof test === 'string') { + return typeFactory$y(test) + } - pref = typeof pref === 'string' && pref !== 'consistent' ? pref : null; + if (test === null || test === undefined) { + return ok$z + } - if (markers[pref] !== true) { - file.fail( - 'Invalid fenced code marker `' + - pref + - "`: use either `'consistent'`, `` '`' ``, or `'~'`" - ); + if (typeof test === 'object') { + return ('length' in test ? anyFactory$y : matchesFactory$y)(test) } - unistUtilVisit(tree, 'code', visitor); + if (typeof test === 'function') { + return test + } - function visitor(node) { - var marker; + throw new Error('Expected function, string, or object as test') +} - if (!unistUtilGenerated(node)) { - marker = contents - .substr(unistUtilPosition.start(node).offset, 4) - .trimLeft() - .charAt(0); +function convertAll$y(tests) { + var results = []; + var length = tests.length; + var index = -1; - // Ignore unfenced code blocks. - if (markers[marker] === true) { - if (pref) { - if (marker !== pref) { - file.message( - 'Fenced code should use ' + pref + ' as a marker', - node - ); - } - } else { - pref = marker; - } - } - } + while (++index < length) { + results[index] = convert$z(tests[index]); } + + return results } -var remarkLintFileExtension = unifiedLintRule('remark-lint:file-extension', fileExtension); +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$y(test) { + return matches -function fileExtension(tree, file, pref) { - var ext = file.extname; + function matches(node) { + var key; - pref = typeof pref === 'string' ? pref : 'md'; + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } - if (ext && ext.slice(1) !== pref) { - file.message('Invalid extension: use `' + pref + '`'); + return true } } -var remarkLintFinalDefinition = unifiedLintRule('remark-lint:final-definition', finalDefinition); +function anyFactory$y(tests) { + var checks = convertAll$y(tests); + var length = checks.length; -var start$c = unistUtilPosition.start; + return matches -function finalDefinition(tree, file) { - var last = null; + function matches() { + var index = -1; - unistUtilVisit(tree, visitor, true); + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } - function visitor(node) { - var line = start$c(node).line; + return false + } +} - // Ignore generated nodes. - if (node.type === 'root' || unistUtilGenerated(node)) { - return - } +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$y(test) { + return type - if (node.type === 'definition') { - if (last !== null && last > line) { - file.message( - 'Move definitions to the end of the file (after the node at line `' + - last + - '`)', - node - ); - } - } else if (last === null) { - last = line; - } + function type(node) { + return Boolean(node && node.type === test) } } -var remarkLintFirstHeadingLevel = unifiedLintRule('remark-lint:first-heading-level', firstHeadingLevel); +// Utility to return true. +function ok$z() { + return true +} -var re$3 = /. - unistUtilVisit(tree, ['heading', 'table', 'code', 'definition', 'html', 'jsx'], ignore); - unistUtilVisit(tree, ['link', 'image', 'inlineCode'], inline); + while (index > min && index < children.length) { + result = one(children[index], index, parents); - // Iterate over every line, and warn for violating lines. - while (++index < length) { - lineLength = lines[index].length; + if (result[0] === EXIT$14) { + return result + } - if (lineLength > style) { - file.message('Line must be at most ' + style + ' characters', { - line: index + 1, - column: lineLength + 1 - }); + index = typeof result[1] === 'number' ? result[1] : index + step; } } +} - // Finally, whitelist some inline spans, but only if they occur at or after - // the wrap. - // However, when they do, and there’s whitespace after it, they are not - // whitelisted. - function inline(node, pos, parent) { - var next = parent.children[pos + 1]; - var initial; - var final; +function toResult$y(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } - /* istanbul ignore if - Nothing to whitelist when generated. */ - if (unistUtilGenerated(node)) { - return - } + if (typeof value === 'number') { + return [CONTINUE$14, value] + } - initial = start$d(node); - final = end$8(node); + return [value] +} - // No whitelisting when starting after the border, or ending before it. - if (initial.column > style || final.column < style) { - return - } +var unistUtilVisit$y = visit$y; - // No whitelisting when there’s whitespace after the link. - if ( - next && - start$d(next).line === initial.line && - (!next.value || /^(.+?[ \t].+?)/.test(next.value)) - ) { - return - } - whitelist(initial.line - 1, final.line); - } - function ignore(node) { - /* istanbul ignore else - Hard to test, as we only run this case on `position: true` */ - if (!unistUtilGenerated(node)) { - whitelist(start$d(node).line - 1, end$8(node).line); - } +var CONTINUE$15 = unistUtilVisitParents$y.CONTINUE; +var SKIP$15 = unistUtilVisitParents$y.SKIP; +var EXIT$15 = unistUtilVisitParents$y.EXIT; + +visit$y.CONTINUE = CONTINUE$15; +visit$y.SKIP = SKIP$15; +visit$y.EXIT = EXIT$15; + +function visit$y(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; } - // Whitelist from `initial` to `final`, zero-based. - function whitelist(initial, final) { - while (initial < final) { - lines[initial++] = ''; - } + unistUtilVisitParents$y(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) } } -var remarkLintNoConsecutiveBlankLines = unifiedLintRule( - 'remark-lint:no-consecutive-blank-lines', - noConsecutiveBlankLines -); +var rule = unifiedLintRule; -function noConsecutiveBlankLines(tree, file) { - unistUtilVisit(tree, visitor); - function visitor(node) { - var children = node.children; - var head; - var tail; - if (!unistUtilGenerated(node) && children) { - head = children[0]; - if (head && !unistUtilGenerated(head)) { - // Compare parent and first child. - compare(unistUtilPosition.start(node), unistUtilPosition.start(head), 0); +var remarkLintRuleStyle = rule('remark-lint:rule-style', ruleStyle); - // Compare between each child. - children.forEach(visitChild); +var start$h = unistUtilPosition.start; +var end$9 = unistUtilPosition.end; - tail = children[children.length - 1]; +function ruleStyle(tree, file, option) { + var contents = String(file); + var preferred = + typeof option === 'string' && option !== 'consistent' ? option : null; - // Compare parent and last child. - if (tail !== head && !unistUtilGenerated(tail)) { - compare(unistUtilPosition.end(node), unistUtilPosition.end(tail), 1); - } - } - } + if (preferred !== null && /[^-_* ]/.test(preferred)) { + file.fail( + "Incorrect preferred rule style: provide a correct markdown rule or `'consistent'`" + ); } - // Compare the difference between `start` and `end`, and warn when that - // difference exceeds `max`. - function compare(start, end, max) { - var diff = end.line - start.line; - var lines = Math.abs(diff) - max; - var reason; - - if (lines > 0) { - reason = - 'Remove ' + - lines + - ' ' + - plur('line', lines) + - ' ' + - (diff > 0 ? 'before' : 'after') + - ' node'; + unistUtilVisit$y(tree, 'thematicBreak', visitor); - file.message(reason, end); - } - } + function visitor(node) { + var initial = start$h(node).offset; + var final = end$9(node).offset; + var rule; - function visitChild(child, index, all) { - var prev = all[index - 1]; - var max = 2; + if (!unistUtilGenerated(node)) { + rule = contents.slice(initial, final); - if (prev && !unistUtilGenerated(prev) && !unistUtilGenerated(child)) { - if ( - (prev.type === 'list' && child.type === 'list') || - (child.type === 'code' && prev.type === 'list' && !child.lang) - ) { - max++; + if (preferred) { + if (rule !== preferred) { + file.message('Rules should use `' + preferred + '`', node); + } + } else { + preferred = rule; } - - compare(unistUtilPosition.end(prev), unistUtilPosition.start(child), max); } } } -var remarkLintNoFileNameArticles = unifiedLintRule('remark-lint:no-file-name-articles', noFileNameArticles); - -function noFileNameArticles(tree, file) { - var match = file.stem && file.stem.match(/^(the|teh|an?)\b/i); +var convert_1$z = convert$A; - if (match) { - file.message('Do not start file names with `' + match[0] + '`'); +function convert$A(test) { + if (typeof test === 'string') { + return typeFactory$z(test) } -} -var remarkLintNoFileNameConsecutiveDashes = unifiedLintRule( - 'remark-lint:no-file-name-consecutive-dashes', - noFileNameConsecutiveDashes -); + if (test === null || test === undefined) { + return ok$A + } -var reason$b = 'Do not use consecutive dashes in a file name'; + if (typeof test === 'object') { + return ('length' in test ? anyFactory$z : matchesFactory$z)(test) + } -function noFileNameConsecutiveDashes(tree, file) { - if (file.stem && /-{2,}/.test(file.stem)) { - file.message(reason$b); + if (typeof test === 'function') { + return test } -} -var remarkLintNoFileNameOuterDashes = unifiedLintRule( - 'remark-lint:no-file-name-outer-dashes', - noFileNameOuterDashes -); + throw new Error('Expected function, string, or object as test') +} -var reason$c = 'Do not use initial or final dashes in a file name'; +function convertAll$z(tests) { + var results = []; + var length = tests.length; + var index = -1; -function noFileNameOuterDashes(tree, file) { - if (file.stem && /^-|-$/.test(file.stem)) { - file.message(reason$c); + while (++index < length) { + results[index] = convert$A(tests[index]); } + + return results } -var remarkLintNoHeadingIndent = unifiedLintRule('remark-lint:no-heading-indent', noHeadingIndent); +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$z(test) { + return matches -var start$e = unistUtilPosition.start; + function matches(node) { + var key; -function noHeadingIndent(tree, file) { - var contents = String(file); - var length = contents.length; + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } - unistUtilVisit(tree, 'heading', visitor); + return true + } +} - function visitor(node) { - var initial; - var begin; - var index; - var character; - var diff; +function anyFactory$z(tests) { + var checks = convertAll$z(tests); + var length = checks.length; - if (unistUtilGenerated(node)) { - return - } + return matches - initial = start$e(node); - begin = initial.offset; - index = begin - 1; + function matches() { + var index = -1; while (++index < length) { - character = contents.charAt(index); - - if (character !== ' ' && character !== '\t') { - break + if (checks[index].apply(this, arguments)) { + return true } } - diff = index - begin; + return false + } +} - if (diff) { - file.message( - 'Remove ' + diff + ' ' + plur('space', diff) + ' before this heading', - { - line: initial.line, - column: initial.column + diff - } - ); - } +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$z(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) } } -var start$f = unistUtilPosition.start; +// Utility to return true. +function ok$A() { + return true +} +var unistUtilVisitParents$z = visitParents$z; -var remarkLintNoMultipleToplevelHeadings = unifiedLintRule( - 'remark-lint:no-multiple-toplevel-headings', - noMultipleToplevelHeadings -); -function noMultipleToplevelHeadings(tree, file, pref) { - var style = pref ? pref : 1; - var duplicate; +var CONTINUE$16 = true; +var SKIP$16 = 'skip'; +var EXIT$16 = false; - unistUtilVisit(tree, 'heading', visitor); +visitParents$z.CONTINUE = CONTINUE$16; +visitParents$z.SKIP = SKIP$16; +visitParents$z.EXIT = EXIT$16; - function visitor(node) { - if (!unistUtilGenerated(node) && node.depth === style) { - if (duplicate) { - file.message( - 'Don’t use multiple top level headings (' + duplicate + ')', - node - ); - } else { - duplicate = unistUtilStringifyPosition(start$f(node)); - } - } +function visitParents$z(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; } -} -var remarkLintNoShellDollars = unifiedLintRule('remark-lint:no-shell-dollars', noShellDollars); + is = convert_1$z(test); -var reason$d = 'Do not use dollar signs before shell-commands'; + one(tree, null, []); -// List of shell script file extensions (also used as code flags for syntax -// highlighting on GitHub): -// See: -var flags = [ - 'sh', - 'bash', - 'bats', - 'cgi', - 'command', - 'fcgi', - 'ksh', - 'tmux', - 'tool', - 'zsh' -]; + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; -function noShellDollars(tree, file) { - unistUtilVisit(tree, 'code', visitor); + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$z(visitor(node, parents)); - function visitor(node) { - var lines; - var line; - var length; - var index; + if (result[0] === EXIT$16) { + return result + } + } - // Check both known shell code and unknown code. - if (!unistUtilGenerated(node) && node.lang && flags.indexOf(node.lang) !== -1) { - lines = node.value.split('\n'); - length = lines.length; - index = -1; + if (node.children && result[0] !== SKIP$16) { + subresult = toResult$z(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$16 ? subresult : result + } - if (length <= 1) { - return - } + return result + } - while (++index < length) { - line = lines[index]; + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; - if (line.trim() && !line.match(/^\s*\$\s*/)) { - return - } + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$16) { + return result } - file.message(reason$d, node); + index = typeof result[1] === 'number' ? result[1] : index + step; } } } -var remarkLintNoTableIndentation = unifiedLintRule('remark-lint:no-table-indentation', noTableIndentation); +function toResult$z(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } -var reason$e = 'Do not indent table rows'; + if (typeof value === 'number') { + return [CONTINUE$16, value] + } -function noTableIndentation(tree, file) { - var contents = String(file); + return [value] +} - unistUtilVisit(tree, 'table', visitor); +var unistUtilVisit$z = visit$z; - function visitor(node) { - if (!unistUtilGenerated(node)) { - node.children.forEach(each); - } - return unistUtilVisit.SKIP + +var CONTINUE$17 = unistUtilVisitParents$z.CONTINUE; +var SKIP$17 = unistUtilVisitParents$z.SKIP; +var EXIT$17 = unistUtilVisitParents$z.EXIT; + +visit$z.CONTINUE = CONTINUE$17; +visit$z.SKIP = SKIP$17; +visit$z.EXIT = EXIT$17; + +function visit$z(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; } - function each(row) { - var fence = contents.slice( - unistUtilPosition.start(row).offset, - unistUtilPosition.start(row.children[0]).offset - ); + unistUtilVisitParents$z(tree, test, overload, reverse); - if (fence.indexOf('|') > 1) { - file.message(reason$e, row); - } + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) } } -var remarkLintNoTabs = unifiedLintRule('remark-lint:no-tabs', noTabs); +var remarkLintStrongMarker = unifiedLintRule('remark-lint:strong-marker', strongMarker); -var reason$f = 'Use spaces instead of hard-tabs'; +var markers$1 = {'*': true, _: true, null: true}; -function noTabs(tree, file) { - var content = String(file); - var position = vfileLocation(file).toPosition; - var index = content.indexOf('\t'); +function strongMarker(tree, file, option) { + var contents = String(file); + var preferred = + typeof option === 'string' && option !== 'consistent' ? option : null; - while (index !== -1) { - file.message(reason$f, position(index)); - index = content.indexOf('\t', index + 1); + if (markers$1[preferred] !== true) { + file.fail( + 'Incorrect strong marker `' + + preferred + + "`: use either `'consistent'`, `'*'`, or `'_'`" + ); } -} -var remarkLintNoTrailingSpaces = unifiedLintRule('remark-lint:no-trailing-spaces', noTrailingSpaces); + unistUtilVisit$z(tree, 'strong', visitor); -/** - * Lines that are just space characters are not present in - * the AST, which is why we loop through lines manually. - */ + function visitor(node) { + var marker = contents.charAt(unistUtilPosition.start(node).offset); -function noTrailingSpaces(ast, file) { - var lines = file.toString().split(/\r?\n/); - for (var i = 0; i < lines.length; i++) { - var currentLine = lines[i]; - var lineIndex = i + 1; - if (/\s$/.test(currentLine)) { - file.message('Remove trailing whitespace', { - position: { - start: { line: lineIndex, column: currentLine.length + 1 }, - end: { line: lineIndex } + if (!unistUtilGenerated(node)) { + if (preferred) { + if (marker !== preferred) { + file.message( + 'Strong should use `' + preferred + '` as a marker', + node + ); } - }); + } else { + preferred = marker; + } } } } -var convert_1$1 = convert$2; +var convert_1$A = convert$B; -function convert$2(test) { +function convert$B(test) { if (typeof test === 'string') { - return typeFactory$1(test) + return typeFactory$A(test) } if (test === null || test === undefined) { - return ok$2 + return ok$B } if (typeof test === 'object') { - return ('length' in test ? anyFactory$1 : matchesFactory$1)(test) + return ('length' in test ? anyFactory$A : matchesFactory$A)(test) } if (typeof test === 'function') { @@ -43965,13 +51665,13 @@ function convert$2(test) { throw new Error('Expected function, string, or object as test') } -function convertAll$1(tests) { +function convertAll$A(tests) { var results = []; var length = tests.length; var index = -1; while (++index < length) { - results[index] = convert$2(tests[index]); + results[index] = convert$B(tests[index]); } return results @@ -43979,7 +51679,7 @@ function convertAll$1(tests) { // Utility assert each property in `test` is represented in `node`, and each // values are strictly equal. -function matchesFactory$1(test) { +function matchesFactory$A(test) { return matches function matches(node) { @@ -43995,8 +51695,8 @@ function matchesFactory$1(test) { } } -function anyFactory$1(tests) { - var checks = convertAll$1(tests); +function anyFactory$A(tests) { + var checks = convertAll$A(tests); var length = checks.length; return matches @@ -44016,7 +51716,7 @@ function anyFactory$1(tests) { // Utility to convert a string into a function which checks a given node’s type // for said string. -function typeFactory$1(test) { +function typeFactory$A(test) { return type function type(node) { @@ -44025,23 +51725,23 @@ function typeFactory$1(test) { } // Utility to return true. -function ok$2() { +function ok$B() { return true } -var unistUtilVisitParents$1 = visitParents$1; +var unistUtilVisitParents$A = visitParents$A; -var CONTINUE$2 = true; -var SKIP$2 = 'skip'; -var EXIT$2 = false; +var CONTINUE$18 = true; +var SKIP$18 = 'skip'; +var EXIT$18 = false; -visitParents$1.CONTINUE = CONTINUE$2; -visitParents$1.SKIP = SKIP$2; -visitParents$1.EXIT = EXIT$2; +visitParents$A.CONTINUE = CONTINUE$18; +visitParents$A.SKIP = SKIP$18; +visitParents$A.EXIT = EXIT$18; -function visitParents$1(tree, test, visitor, reverse) { +function visitParents$A(tree, test, visitor, reverse) { var is; if (typeof test === 'function' && typeof visitor !== 'function') { @@ -44050,7 +51750,7 @@ function visitParents$1(tree, test, visitor, reverse) { test = null; } - is = convert_1$1(test); + is = convert_1$A(test); one(tree, null, []); @@ -44060,16 +51760,16 @@ function visitParents$1(tree, test, visitor, reverse) { var subresult; if (!test || is(node, index, parents[parents.length - 1] || null)) { - result = toResult$1(visitor(node, parents)); + result = toResult$A(visitor(node, parents)); - if (result[0] === EXIT$2) { + if (result[0] === EXIT$18) { return result } } - if (node.children && result[0] !== SKIP$2) { - subresult = toResult$1(all(node.children, parents.concat(node))); - return subresult[0] === EXIT$2 ? subresult : result + if (node.children && result[0] !== SKIP$18) { + subresult = toResult$A(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$18 ? subresult : result } return result @@ -44085,7 +51785,7 @@ function visitParents$1(tree, test, visitor, reverse) { while (index > min && index < children.length) { result = one(children[index], index, parents); - if (result[0] === EXIT$2) { + if (result[0] === EXIT$18) { return result } @@ -44094,38 +51794,38 @@ function visitParents$1(tree, test, visitor, reverse) { } } -function toResult$1(value) { +function toResult$A(value) { if (value !== null && typeof value === 'object' && 'length' in value) { return value } if (typeof value === 'number') { - return [CONTINUE$2, value] + return [CONTINUE$18, value] } return [value] } -var unistUtilVisit$1 = visit$1; +var unistUtilVisit$A = visit$A; -var CONTINUE$3 = unistUtilVisitParents$1.CONTINUE; -var SKIP$3 = unistUtilVisitParents$1.SKIP; -var EXIT$3 = unistUtilVisitParents$1.EXIT; +var CONTINUE$19 = unistUtilVisitParents$A.CONTINUE; +var SKIP$19 = unistUtilVisitParents$A.SKIP; +var EXIT$19 = unistUtilVisitParents$A.EXIT; -visit$1.CONTINUE = CONTINUE$3; -visit$1.SKIP = SKIP$3; -visit$1.EXIT = EXIT$3; +visit$A.CONTINUE = CONTINUE$19; +visit$A.SKIP = SKIP$19; +visit$A.EXIT = EXIT$19; -function visit$1(tree, test, visitor, reverse) { +function visit$A(tree, test, visitor, reverse) { if (typeof test === 'function' && typeof visitor !== 'function') { reverse = visitor; visitor = test; test = null; } - unistUtilVisitParents$1(tree, test, overload, reverse); + unistUtilVisitParents$A(tree, test, overload, reverse); function overload(node, parents) { var parent = parents[parents.length - 1]; @@ -44134,142 +51834,27 @@ function visit$1(tree, test, visitor, reverse) { } } -var remarkLintProhibitedStrings = unifiedLintRule('remark-lint:prohibited-strings', prohibitedStrings); - -function testProhibited(val, content) { - let regexpString = '(\\.|@[a-z0-9/-]*)?'; - - // If it starts with a letter, make sure it is a word break. - if (/^\b/.test(val.no)) { - regexpString += '\\b'; - } - regexpString += `(${val.no})`; - - // If it ends with a letter, make sure it is a word break. - if (/\b$/.test(val.no)) { - regexpString += '\\b'; - } - regexpString += '(\\.\\w)?'; - const re = new RegExp(regexpString, 'g'); - - let result = null; - while (result = re.exec(content)) { - if (!result[1] && !result[3]) { - return result[2]; - } - } - - return false; -} - -function prohibitedStrings(ast, file, strings) { - unistUtilVisit$1(ast, 'text', checkText); - - function checkText(node) { - const content = node.value; - - strings.forEach((val) => { - const result = testProhibited(val, content); - if (result) { - file.message(`Use "${val.yes}" instead of "${result}"`, node); - } - }); - } -} - -var rule = unifiedLintRule; - - - - -var remarkLintRuleStyle = rule('remark-lint:rule-style', ruleStyle); - -var start$g = unistUtilPosition.start; -var end$9 = unistUtilPosition.end; - -function ruleStyle(tree, file, pref) { - var contents = String(file); - - pref = typeof pref === 'string' && pref !== 'consistent' ? pref : null; - - if (pref !== null && /[^-_* ]/.test(pref)) { - file.fail( - "Invalid preferred rule-style: provide a valid markdown rule, or `'consistent'`" - ); - } - - unistUtilVisit(tree, 'thematicBreak', visitor); - - function visitor(node) { - var initial = start$g(node).offset; - var final = end$9(node).offset; - var rule; - - if (!unistUtilGenerated(node)) { - rule = contents.slice(initial, final); - - if (pref) { - if (rule !== pref) { - file.message('Rules should use `' + pref + '`', node); - } - } else { - pref = rule; - } - } - } -} - -var remarkLintStrongMarker = unifiedLintRule('remark-lint:strong-marker', strongMarker); - -var markers$1 = {'*': true, _: true, null: true}; - -function strongMarker(tree, file, pref) { - var contents = String(file); - - pref = typeof pref === 'string' && pref !== 'consistent' ? pref : null; - - if (markers$1[pref] !== true) { - file.fail( - 'Invalid strong marker `' + - pref + - "`: use either `'consistent'`, `'*'`, or `'_'`" - ); - } - - unistUtilVisit(tree, 'strong', visitor); - - function visitor(node) { - var marker = contents.charAt(unistUtilPosition.start(node).offset); - - if (!unistUtilGenerated(node)) { - if (pref) { - if (marker !== pref) { - file.message('Strong should use `' + pref + '` as a marker', node); - } - } else { - pref = marker; - } - } - } -} - var remarkLintTableCellPadding = unifiedLintRule('remark-lint:table-cell-padding', tableCellPadding); -var start$h = unistUtilPosition.start; +var start$i = unistUtilPosition.start; var end$a = unistUtilPosition.end; var styles$3 = {null: true, padded: true, compact: true}; -function tableCellPadding(tree, file, pref) { +function tableCellPadding(tree, file, option) { var contents = String(file); + var preferred = + typeof option === 'string' && option !== 'consistent' ? option : null; - pref = typeof pref === 'string' && pref !== 'consistent' ? pref : null; - - if (styles$3[pref] !== true) { - file.fail('Invalid table-cell-padding style `' + pref + '`'); + if (styles$3[preferred] !== true) { + file.fail( + 'Incorrect table cell padding style `' + + preferred + + "`, expected `'padded'`, `'compact'`, or `'consistent'`" + ); } - unistUtilVisit(tree, 'table', visitor); + unistUtilVisit$A(tree, 'table', visitor); function visitor(node) { var rows = node.children; @@ -44304,8 +51889,8 @@ function tableCellPadding(tree, file, pref) { next = cells[column + 1]; fence = contents.slice( - cell ? end$a(cell).offset : start$h(row).offset, - next ? start$h(next).offset : end$a(row).offset + cell ? end$a(cell).offset : start$i(row).offset, + next ? start$i(next).offset : end$a(row).offset ); pos = fence.indexOf('|'); @@ -44327,8 +51912,8 @@ function tableCellPadding(tree, file, pref) { } } - if (pref) { - style = pref === 'padded' ? 1 : 0; + if (preferred) { + style = preferred === 'padded' ? 1 : 0; } else { style = entries[0] && (!entries[0].start || !entries[0].end) ? 0 : 1; } @@ -44342,7 +51927,7 @@ function tableCellPadding(tree, file, pref) { checkSide('end', entry, style, sizes); } - return unistUtilVisit.SKIP + return unistUtilVisit$A.SKIP } function checkSide(side, entry, style, sizes) { @@ -44382,12 +51967,203 @@ function tableCellPadding(tree, file, pref) { } function size(node) { - return end$a(node).offset - start$h(node).offset + return end$a(node).offset - start$i(node).offset +} + +var convert_1$B = convert$C; + +function convert$C(test) { + if (typeof test === 'string') { + return typeFactory$B(test) + } + + if (test === null || test === undefined) { + return ok$C + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$B : matchesFactory$B)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$B(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$C(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$B(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$B(tests) { + var checks = convertAll$B(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$B(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$C() { + return true +} + +var unistUtilVisitParents$B = visitParents$B; + + + +var CONTINUE$1a = true; +var SKIP$1a = 'skip'; +var EXIT$1a = false; + +visitParents$B.CONTINUE = CONTINUE$1a; +visitParents$B.SKIP = SKIP$1a; +visitParents$B.EXIT = EXIT$1a; + +function visitParents$B(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$B(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$B(visitor(node, parents)); + + if (result[0] === EXIT$1a) { + return result + } + } + + if (node.children && result[0] !== SKIP$1a) { + subresult = toResult$B(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$1a ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$1a) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$B(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$1a, value] + } + + return [value] +} + +var unistUtilVisit$B = visit$B; + + + +var CONTINUE$1b = unistUtilVisitParents$B.CONTINUE; +var SKIP$1b = unistUtilVisitParents$B.SKIP; +var EXIT$1b = unistUtilVisitParents$B.EXIT; + +visit$B.CONTINUE = CONTINUE$1b; +visit$B.SKIP = SKIP$1b; +visit$B.EXIT = EXIT$1b; + +function visit$B(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$B(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } } var remarkLintTablePipes = unifiedLintRule('remark-lint:table-pipes', tablePipes); -var start$i = unistUtilPosition.start; +var start$j = unistUtilPosition.start; var end$b = unistUtilPosition.end; var reasonStart = 'Missing initial pipe in table fence'; @@ -44396,7 +52172,7 @@ var reasonEnd = 'Missing final pipe in table fence'; function tablePipes(tree, file) { var contents = String(file); - unistUtilVisit(tree, 'table', visitor); + unistUtilVisit$B(tree, 'table', visitor); function visitor(node) { var rows = node.children; @@ -44416,11 +52192,11 @@ function tablePipes(tree, file) { cells = row.children; head = cells[0]; tail = cells[cells.length - 1]; - initial = contents.slice(start$i(row).offset, start$i(head).offset); + initial = contents.slice(start$j(row).offset, start$j(head).offset); final = contents.slice(end$b(tail).offset, end$b(row).offset); if (initial.indexOf('|') === -1) { - file.message(reasonStart, start$i(row)); + file.message(reasonStart, start$j(row)); } if (final.indexOf('|') === -1) { @@ -44431,12 +52207,203 @@ function tablePipes(tree, file) { } } +var convert_1$C = convert$D; + +function convert$D(test) { + if (typeof test === 'string') { + return typeFactory$C(test) + } + + if (test === null || test === undefined) { + return ok$D + } + + if (typeof test === 'object') { + return ('length' in test ? anyFactory$C : matchesFactory$C)(test) + } + + if (typeof test === 'function') { + return test + } + + throw new Error('Expected function, string, or object as test') +} + +function convertAll$C(tests) { + var results = []; + var length = tests.length; + var index = -1; + + while (++index < length) { + results[index] = convert$D(tests[index]); + } + + return results +} + +// Utility assert each property in `test` is represented in `node`, and each +// values are strictly equal. +function matchesFactory$C(test) { + return matches + + function matches(node) { + var key; + + for (key in test) { + if (node[key] !== test[key]) { + return false + } + } + + return true + } +} + +function anyFactory$C(tests) { + var checks = convertAll$C(tests); + var length = checks.length; + + return matches + + function matches() { + var index = -1; + + while (++index < length) { + if (checks[index].apply(this, arguments)) { + return true + } + } + + return false + } +} + +// Utility to convert a string into a function which checks a given node’s type +// for said string. +function typeFactory$C(test) { + return type + + function type(node) { + return Boolean(node && node.type === test) + } +} + +// Utility to return true. +function ok$D() { + return true +} + +var unistUtilVisitParents$C = visitParents$C; + + + +var CONTINUE$1c = true; +var SKIP$1c = 'skip'; +var EXIT$1c = false; + +visitParents$C.CONTINUE = CONTINUE$1c; +visitParents$C.SKIP = SKIP$1c; +visitParents$C.EXIT = EXIT$1c; + +function visitParents$C(tree, test, visitor, reverse) { + var is; + + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + is = convert_1$C(test); + + one(tree, null, []); + + // Visit a single node. + function one(node, index, parents) { + var result = []; + var subresult; + + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$C(visitor(node, parents)); + + if (result[0] === EXIT$1c) { + return result + } + } + + if (node.children && result[0] !== SKIP$1c) { + subresult = toResult$C(all(node.children, parents.concat(node))); + return subresult[0] === EXIT$1c ? subresult : result + } + + return result + } + + // Visit children in `parent`. + function all(children, parents) { + var min = -1; + var step = reverse ? -1 : 1; + var index = (reverse ? children.length : min) + step; + var result; + + while (index > min && index < children.length) { + result = one(children[index], index, parents); + + if (result[0] === EXIT$1c) { + return result + } + + index = typeof result[1] === 'number' ? result[1] : index + step; + } + } +} + +function toResult$C(value) { + if (value !== null && typeof value === 'object' && 'length' in value) { + return value + } + + if (typeof value === 'number') { + return [CONTINUE$1c, value] + } + + return [value] +} + +var unistUtilVisit$C = visit$C; + + + +var CONTINUE$1d = unistUtilVisitParents$C.CONTINUE; +var SKIP$1d = unistUtilVisitParents$C.SKIP; +var EXIT$1d = unistUtilVisitParents$C.EXIT; + +visit$C.CONTINUE = CONTINUE$1d; +visit$C.SKIP = SKIP$1d; +visit$C.EXIT = EXIT$1d; + +function visit$C(tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + + unistUtilVisitParents$C(tree, test, overload, reverse); + + function overload(node, parents) { + var parent = parents[parents.length - 1]; + var index = parent ? parent.children.indexOf(node) : null; + return visitor(node, index, parent) + } +} + var remarkLintUnorderedListMarkerStyle = unifiedLintRule( 'remark-lint:unordered-list-marker-style', unorderedListMarkerStyle ); -var start$j = unistUtilPosition.start; +var start$k = unistUtilPosition.start; var styles$4 = { '-': true, @@ -44445,20 +52412,20 @@ var styles$4 = { null: true }; -function unorderedListMarkerStyle(tree, file, pref) { +function unorderedListMarkerStyle(tree, file, option) { var contents = String(file); + var preferred = + typeof option === 'string' && option !== 'consistent' ? option : null; - pref = typeof pref === 'string' && pref !== 'consistent' ? pref : null; - - if (styles$4[pref] !== true) { + if (styles$4[preferred] !== true) { file.fail( - 'Invalid unordered list-item marker style `' + - pref + + 'Incorrect unordered list item marker style `' + + preferred + "`: use either `'-'`, `'*'`, or `'+'`" ); } - unistUtilVisit(tree, 'list', visitor); + unistUtilVisit$C(tree, 'list', visitor); function visitor(node) { var children = node.children; @@ -44472,16 +52439,16 @@ function unorderedListMarkerStyle(tree, file, pref) { if (!unistUtilGenerated(child)) { marker = contents - .slice(start$j(child).offset, start$j(child.children[0]).offset) + .slice(start$k(child).offset, start$k(child.children[0]).offset) .replace(/\[[x ]?]\s*$/i, '') .replace(/\s/g, ''); - if (pref) { - if (marker !== pref) { - file.message('Marker style should be `' + pref + '`', child); + if (preferred) { + if (marker !== preferred) { + file.message('Marker style should be `' + preferred + '`', child); } } else { - pref = marker; + preferred = marker; } } } @@ -44498,8 +52465,8 @@ var plugins$2 = [ remarkLintCheckboxCharacterStyle, { checked: "x", - unchecked: " " - } + unchecked: " ", + }, ], remarkLintCheckboxContentIndent, [remarkLintCodeBlockStyle, "fenced"], @@ -44517,7 +52484,6 @@ var plugins$2 = [ remarkLintNoFileNameConsecutiveDashes, remarkLintNoFileNameOuterDashes, remarkLintNoHeadingIndent, - [remarkLintNoLiteralUrls, false], remarkLintNoMultipleToplevelHeadings, remarkLintNoShellDollars, remarkLintNoTableIndentation, @@ -44526,29 +52492,26 @@ var plugins$2 = [ [ remarkLintProhibitedStrings, [ - { no: "End-Of-Life", yes: "End-of-Life" }, - { no: "End-of-life", yes: "End-of-Life" }, - { no: "Github", yes: "GitHub" }, + { yes: "End-of-Life" }, + { yes: "GitHub" }, { no: "hostname", yes: "host name" }, - { no: "[Jj]avascript", yes: "JavaScript" }, + { yes: "JavaScript" }, { no: "Node", yes: "Node.js" }, - { no: "Node\\.JS", yes: "Node.js" }, - { no: "node\\.js", yes: "Node.js" }, + { yes: "Node.js" }, + { no: "Node[Jj][Ss]", yes: "Node.js" }, { no: "Node\\.js's?", yes: "the Node.js" }, { no: "[Nn]ote that", yes: "" }, - { no: "Rfc", yes: "RFC" }, + { yes: "RFC" }, { no: "[Rr][Ff][Cc]\\d+", yes: "RFC " }, - { no: "rfc", yes: "RFC" }, - { no: "UNIX", yes: "Unix" }, - { no: "unix", yes: "Unix" }, - { no: "v8", yes: "V8" } - ] + { yes: "Unix" }, + { yes: "V8" }, + ], ], remarkLintRuleStyle, [remarkLintStrongMarker, "*"], [remarkLintTableCellPadding, "padded"], remarkLintTablePipes, - [remarkLintUnorderedListMarkerStyle, "*"] + [remarkLintUnorderedListMarkerStyle, "*"], ]; var remarkPresetLintNode = { diff --git a/tools/make-v8.sh b/tools/make-v8.sh index e4024330b169db..68222c1cd8ba9f 100755 --- a/tools/make-v8.sh +++ b/tools/make-v8.sh @@ -4,6 +4,7 @@ BUILD_ARCH_TYPE=$1 V8_BUILD_OPTIONS=$2 cd deps/v8 +find . -type d -name .git | xargs rm -rf tools/node/fetch_deps.py . ARCH="`arch`" diff --git a/tools/node-lint-md-cli-rollup/package-lock.json b/tools/node-lint-md-cli-rollup/package-lock.json index e6597cfdd506fe..f1a8df25bef8c1 100644 --- a/tools/node-lint-md-cli-rollup/package-lock.json +++ b/tools/node-lint-md-cli-rollup/package-lock.json @@ -401,11 +401,6 @@ "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", "dev": true }, - "irregular-plurals": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-2.0.0.tgz", - "integrity": "sha512-Y75zBYLkh0lJ9qxeHlMjQ7bSbyiSqNW/UOPWDmzC7cXskL1hekSITh1Oc6JV0XCWWZ9DE8VYSB71xocLk3gmGw==" - }, "is-alphabetical": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.3.tgz", @@ -595,14 +590,14 @@ } }, "mdast-util-heading-style": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/mdast-util-heading-style/-/mdast-util-heading-style-1.0.5.tgz", - "integrity": "sha512-8zQkb3IUwiwOdUw6jIhnwM6DPyib+mgzQuHAe7j2Hy1rIarU4VUxe472bp9oktqULW3xqZE+Kz6OD4Gi7IA3vw==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/mdast-util-heading-style/-/mdast-util-heading-style-1.0.6.tgz", + "integrity": "sha512-8ZuuegRqS0KESgjAGW8zTx4tJ3VNIiIaGFNEzFpRSAQBavVc7AvOo9I4g3crcZBfYisHs4seYh0rAVimO6HyOw==" }, "mdast-util-to-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.7.tgz", - "integrity": "sha512-P+gdtssCoHOX+eJUrrC30Sixqao86ZPlVjR5NEAoy0U79Pfxb1Y0Gntei0+GrnQD4T04X9xA8tcugp90cSmNow==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz", + "integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==" }, "minimatch": { "version": "3.0.4", @@ -688,13 +683,10 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==" }, - "plur": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/plur/-/plur-3.1.1.tgz", - "integrity": "sha512-t1Ax8KUvV3FFII8ltczPn2tJdjqbd1sIzu6t4JL7nQ3EyeL/lTrj5PWKb06ic5/6XYDr65rQ4uzQEGN70/6X5w==", - "requires": { - "irregular-plurals": "^2.0.0" - } + "pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" }, "rc": { "version": "1.2.8", @@ -753,360 +745,1084 @@ } }, "remark-lint-blockquote-indentation": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-blockquote-indentation/-/remark-lint-blockquote-indentation-1.0.3.tgz", - "integrity": "sha512-qK4C1l2VmeOVWEAkDYP0CaDtSFoaEBEo5l4oyz1kTkY7YB0Jh7llW2KjuhJz5IzMLmloKJzIyGwlu/odcwaHpg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-blockquote-indentation/-/remark-lint-blockquote-indentation-2.0.0.tgz", + "integrity": "sha512-Ma/lk+egYzvzV9+RLxR7iaNcFqwsF02guxY2nFF7gaVFXWDhbRy+hbiRZiTQe3y8AK+smc2yE79I+JRUVL15LQ==", "requires": { "mdast-util-to-string": "^1.0.2", - "plur": "^3.0.0", + "pluralize": "^8.0.0", "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-checkbox-character-style": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-checkbox-character-style/-/remark-lint-checkbox-character-style-1.0.3.tgz", - "integrity": "sha512-bQGrGHLlguTxOzuywHtYxNcg58TYhNgeEAMCTvdAggt5bYZIwmh/otx51JsQ0a96qxd/6/G0Ri2xzgyxf9wB8w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-checkbox-character-style/-/remark-lint-checkbox-character-style-2.0.0.tgz", + "integrity": "sha512-V+eTXFHrHCpFFG2RWaQM6lSetLLvpYC8WEZ9dMYSAUbeS/h0PhA7cB7j5kGH86RUwGCihawfzNAKbRmgGxL+DQ==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1", - "vfile-location": "^2.0.1" + "unist-util-visit": "^2.0.0", + "vfile-location": "^3.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + }, + "vfile-location": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.0.1.tgz", + "integrity": "sha512-yYBO06eeN/Ki6Kh1QAkgzYpWT1d3Qln+ZCtSbJqFExPl1S3y2qqotJQXoh6qEvl/jDlgpUJolBn3PItVnnZRqQ==" + } } }, "remark-lint-checkbox-content-indent": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-checkbox-content-indent/-/remark-lint-checkbox-content-indent-1.0.3.tgz", - "integrity": "sha512-YaM1yy8RdnM0DUaP0r2X8kF+inUTmjkCpj5Xjn7QTOV1T5jqJMJnRRilirAWgOGa1QBZBUew7uj0L1Je9SJIZw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-checkbox-content-indent/-/remark-lint-checkbox-content-indent-2.0.0.tgz", + "integrity": "sha512-02Xytexe8nso1ofPC6wN3FE48302nmteSIwydeIDFhJq7mG14SxF4xgay+Kjbhs/O5NoRIF2ju9qcPNJ5gFsXA==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1", - "vfile-location": "^2.0.1" + "unist-util-visit": "^2.0.0", + "vfile-location": "^3.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + }, + "vfile-location": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.0.1.tgz", + "integrity": "sha512-yYBO06eeN/Ki6Kh1QAkgzYpWT1d3Qln+ZCtSbJqFExPl1S3y2qqotJQXoh6qEvl/jDlgpUJolBn3PItVnnZRqQ==" + } } }, "remark-lint-code-block-style": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-code-block-style/-/remark-lint-code-block-style-1.0.3.tgz", - "integrity": "sha512-DL+rudnd9ILP5YXm74tLpMzfWZLqziX7NwIwUhqRefaOyWwxgPPy7hbT59FJqcFc6E/zvDz+Oq4nR1BSV5kEdw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-code-block-style/-/remark-lint-code-block-style-2.0.0.tgz", + "integrity": "sha512-bXT1b9MvYDxKdLfzWTW3eSXWy7v57LXtU5ySLzlD1g3DWoSA6rSWjJT5l/2mA+iOuswg18ssY3SSjwExmTyWUA==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-definition-spacing": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-definition-spacing/-/remark-lint-definition-spacing-1.0.4.tgz", - "integrity": "sha512-UderghITmru72OXB5ErCFhVsY7up2wK/m1bUD3E2dm/TFn73/7WpykENt5UirCDT/aeyoHYl8QXUVL20rAc3XQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-definition-spacing/-/remark-lint-definition-spacing-2.0.0.tgz", + "integrity": "sha512-kE+ffEGsyxgUDlcKSVrnhqyHjQfH0RtUVN/OdA/iSzKfTy/Yc9VMMaNu6xT14xhwjTnSVPrd38rUOnDt1LZhAw==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.4.0" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-fenced-code-flag": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-fenced-code-flag/-/remark-lint-fenced-code-flag-1.0.3.tgz", - "integrity": "sha512-X8Oi6dhfqV9NI3cVg29myvT/NATDHVgRGCpnNz76w7VXwzhBvQtJr1MxZzuPxfWLox+ARCXF2rY9n9hbYFHYTg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-fenced-code-flag/-/remark-lint-fenced-code-flag-2.0.0.tgz", + "integrity": "sha512-SyQ31cdQlbsS+eBw2DUxkuzNwGIGlWnnCLyHLz3D1nxtZBVUaUOnIAturSA3PsguIrnxH4qD2JYCTp5aPbZhzQ==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-fenced-code-marker": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-fenced-code-marker/-/remark-lint-fenced-code-marker-1.0.3.tgz", - "integrity": "sha512-JKnojSQ8JkwpIpbNm6wtKEfx8iiv8QIwNHFM06iTCHExMhXa4pJ3wb5M5f0wsWNHtoND3lrw6AcVPoZxEPnflg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-fenced-code-marker/-/remark-lint-fenced-code-marker-2.0.0.tgz", + "integrity": "sha512-ZkJ4/o0A34nQefhsu6AU2cftQjCwzXClbZ5TrwgtkQQHG9BSu9/vo3PSLxGGw7XBX63oKcrx5HWGrWXaeLTN2g==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-file-extension": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-file-extension/-/remark-lint-file-extension-1.0.3.tgz", - "integrity": "sha512-P5gzsxKmuAVPN7Kq1W0f8Ss0cFKfu+OlezYJWXf+5qOa+9Y5GqHEUOobPnsmNFZrVMiM7JoqJN2C9ZjrUx3N6Q==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-file-extension/-/remark-lint-file-extension-1.0.4.tgz", + "integrity": "sha512-Zfp1mXNwpg7STjTWynZjL+/JtvIOCrmOAZzL3uK+tYpT0ZDPdQ1EQEl5D92+Eiu5OcYlenzG42jiLcyJjv+Q2g==", "requires": { "unified-lint-rule": "^1.0.0" } }, "remark-lint-final-definition": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-final-definition/-/remark-lint-final-definition-1.0.3.tgz", - "integrity": "sha512-QhbBYy99enfQDeUTElioCHrhgg+SgjMNRlru7/JlOguOufP6wn7AXgn2EVTrLZRoByY0VsNS2jCayXxUTzQ8KA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-final-definition/-/remark-lint-final-definition-2.0.0.tgz", + "integrity": "sha512-oGObGXt/CdQfvnoQHWrFPtpTQK7oHiw5kBGzG5GbPSj3rrv30ohD5K+11ljEle9e3wO048EiWDROO5eKzIeeGw==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-final-newline": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-final-newline/-/remark-lint-final-newline-1.0.3.tgz", - "integrity": "sha512-ETAadktv75EwUS3XDhyZUVstXKxfPAEn7SmfN9kZ4+Jb4qo4hHE9gtTOzhE6HxLUxxl9BBhpC5mMO3JcL8UZ5A==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-final-newline/-/remark-lint-final-newline-1.0.4.tgz", + "integrity": "sha512-pUwqX8TVTTfqX5arMnu9Dr2ufg6wZ6Pk1VeqlnWfK92PBXLG8Zc3yrLpYXOJy1fHdWpqUECRRowG0H/OkZIEbw==", "requires": { "unified-lint-rule": "^1.0.0" } }, "remark-lint-first-heading-level": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/remark-lint-first-heading-level/-/remark-lint-first-heading-level-1.1.4.tgz", - "integrity": "sha512-iU5G4ZmGx8/2p/U2rPc6qhjyQ/BCcOuj07KzI7XxapYfJqZF6Xxz2rC2b/5xsDJAz2vXG74U4iG3c9vmbyH9WQ==", - "requires": { - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.4.0" - } - }, - "remark-lint-hard-break-spaces": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-hard-break-spaces/-/remark-lint-hard-break-spaces-1.0.4.tgz", - "integrity": "sha512-YM82UpgliZCZhGNmFxEe7ArfhqR5CplFf2bc0k0+8w3rKWKx7EJcGMar2NK410tIi40gGeWtH/pIEypPJFCCiA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-first-heading-level/-/remark-lint-first-heading-level-2.0.0.tgz", + "integrity": "sha512-LFjKO6nQAPo0oarhLZqHaGUqCpLvjeVuJTr58yo3jpC4v0Gmb1iG8X53hrLtxPz+MP4J5WVz/83eAXCH+Vh3vA==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" - } + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } + } + }, + "remark-lint-hard-break-spaces": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-hard-break-spaces/-/remark-lint-hard-break-spaces-2.0.0.tgz", + "integrity": "sha512-dmB8GucOSDtEctwa+Y8JlSAWF4q8HcquvLr+OpFOSE1QCrpFoZdb2mcSY+rZuTtfeg4S60orhhzArd2aiHvUPQ==", + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } + } }, "remark-lint-heading-style": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-heading-style/-/remark-lint-heading-style-1.0.3.tgz", - "integrity": "sha512-ZUhMav0HHUxo5gzLqxQsOf2ZpP/I3m6EEK8q25/kqpCYnwm1uRJ5CQ40PDQx46pmKtVibIMzDmraYovxNG3ovw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-heading-style/-/remark-lint-heading-style-2.0.0.tgz", + "integrity": "sha512-LZvnAq5zWh9i/oRAEocth8yajEEH4kRgCrL4dE547Nkv6zaR2SKcym+uXMZ+GF6WEWcjXMiwSxIL7MHaT6XexA==", "requires": { "mdast-util-heading-style": "^1.0.2", "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-list-item-bullet-indent": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-list-item-bullet-indent/-/remark-lint-list-item-bullet-indent-1.0.3.tgz", - "integrity": "sha512-iVxQbrgzLpMHG3C6o6wRta/+Bc96etOiBYJnh2zm/aWz6DJ7cGLDykngblP/C4he7LYSeWOD/8Y57HbXZwM2Og==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-list-item-bullet-indent/-/remark-lint-list-item-bullet-indent-2.0.0.tgz", + "integrity": "sha512-8iK+ht771UBf/Iuj4YBgdLnFFOyEgfXY62jBoywtMuiOLVWXDfPe+jUY7pCrnFjsnxXGEnMaxHJqENgrHd0J/w==", "requires": { - "plur": "^3.0.0", + "pluralize": "^8.0.0", "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-list-item-indent": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-list-item-indent/-/remark-lint-list-item-indent-1.0.4.tgz", - "integrity": "sha512-Sv0gVH6qP1/nFpbJuyyguB9sAD2o42StD2WbEZeUcEexXwRO4u/YaX0Pm5pMtCiEHyN+qyL6ShKBQMtgol9BeA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-list-item-indent/-/remark-lint-list-item-indent-2.0.0.tgz", + "integrity": "sha512-qnKsq2UQpCC8gnI1O23dgoKsd+5RAJrAJuvHXrlkRgzsab7BOMluptxRlyLVXn0P71l4Wo/bfo84Ual7qpOyWw==", "requires": { - "plur": "^3.0.0", + "pluralize": "^8.0.0", "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-maximum-line-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/remark-lint-maximum-line-length/-/remark-lint-maximum-line-length-1.2.1.tgz", - "integrity": "sha512-CSxX1qc+rAqixk8eBrI+yBsUmD8YGfOezFeJWjJRuUaoOvs67oqCIU+I2HbwcUYY8/KnDxF1MCp+uCM0RkjKKw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-maximum-line-length/-/remark-lint-maximum-line-length-2.0.0.tgz", + "integrity": "sha512-Qhe1QwDGisMP/UraUexWIPNBXJO8VQ7LIelz4NdftBQl/FxDVoXn3477Fm+8bGtcTXkMPF+QfllE4L1U7kJQgQ==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.4.0" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-no-auto-link-without-protocol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-auto-link-without-protocol/-/remark-lint-no-auto-link-without-protocol-1.0.3.tgz", - "integrity": "sha512-k+hg2mXnO4Q9WV+UShPLen5oThvFxcRVWkx2hviVd/nu3eiszBKH3o38csBwjeJoMG3l2ZhdUW8dlOBhq8670Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-auto-link-without-protocol/-/remark-lint-no-auto-link-without-protocol-2.0.0.tgz", + "integrity": "sha512-pIntUa+zNiyRxIt2Wvp1soktDbVnk1SEiJXsjcLYYn9GapgXqOQG5ZfFwR6zxTkGV5mZKo9927EvHQkvIV6cLQ==", "requires": { "mdast-util-to-string": "^1.0.2", "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-no-blockquote-without-marker": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-blockquote-without-marker/-/remark-lint-no-blockquote-without-marker-2.0.3.tgz", - "integrity": "sha512-faDzKrA6aKidsRXG6gcIlCO8TexLxIxe+n9B3mdnl8mhZGgE0FfWTkIWVMj0IYps/xVsVMf45KxhXgc1wU9kwg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-blockquote-without-marker/-/remark-lint-no-blockquote-without-marker-3.0.0.tgz", + "integrity": "sha512-auyAxMVDuhvGw29VilqUfUIUnBT7qmByG/kBPqV/GwM1a5rn4fIUJ7p9Je9BlWMRCBMTNQUMsm3ce0dawouVew==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1", - "vfile-location": "^2.0.1" + "unist-util-visit": "^2.0.0", + "vfile-location": "^3.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + }, + "vfile-location": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.0.1.tgz", + "integrity": "sha512-yYBO06eeN/Ki6Kh1QAkgzYpWT1d3Qln+ZCtSbJqFExPl1S3y2qqotJQXoh6qEvl/jDlgpUJolBn3PItVnnZRqQ==" + } } }, "remark-lint-no-consecutive-blank-lines": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-consecutive-blank-lines/-/remark-lint-no-consecutive-blank-lines-1.0.3.tgz", - "integrity": "sha512-2Ef7fPxrfLditA7sTo2Qfqd+xwh/luWl8GzILE5vcWIxLDqKk3dTLJkB5nP+7Cr4kqWJAwXnRkEDd77ehrRV3A==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-consecutive-blank-lines/-/remark-lint-no-consecutive-blank-lines-2.0.0.tgz", + "integrity": "sha512-qIXHW0atHaOmHlu7V+4Krs5IAdIZhcXoeRdOMgqkGNW8CtfL12pP8KnzigAB9D5/X/qxPxZ95Js/KaESFS+3hA==", "requires": { - "plur": "^3.0.0", + "pluralize": "^8.0.0", "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-no-duplicate-definitions": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/remark-lint-no-duplicate-definitions/-/remark-lint-no-duplicate-definitions-1.0.5.tgz", - "integrity": "sha512-zKXmfNUODXhJsGQdqfguMG9Nl9v1sLaDsQgMjUtmOSoQRnNud9ThQAZl62eX5jBn5HKcpOifG80tgkyBvU5eEw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-duplicate-definitions/-/remark-lint-no-duplicate-definitions-2.0.0.tgz", + "integrity": "sha512-Z5DkYKbmS+r4D0ZhaXgK6L72EWzhiklpXNF/TS+KCsffAFgfy5aJfSA3A8GpVNj1wYMP35STXBGBCLW5TckvGw==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", "unist-util-stringify-position": "^2.0.0", - "unist-util-visit": "^1.4.0" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-no-file-name-articles": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-articles/-/remark-lint-no-file-name-articles-1.0.3.tgz", - "integrity": "sha512-YZDJDKUWZEmhrO6tHB0u0K0K2qJKxyg/kryr14OaRMvWLS62RgMn97sXPZ38XOSN7mOcCnl0k7/bClghJXx0sg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-articles/-/remark-lint-no-file-name-articles-1.0.4.tgz", + "integrity": "sha512-Ieqg/2WjYs5M+IoZsFrQUG0niN8zRC6IAYWOVaHi3UK/1P0IdmXKZE6pCFSJrhletawAaPw9Xtl42/45tcccCA==", "requires": { "unified-lint-rule": "^1.0.0" } }, "remark-lint-no-file-name-consecutive-dashes": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-consecutive-dashes/-/remark-lint-no-file-name-consecutive-dashes-1.0.3.tgz", - "integrity": "sha512-7f4vyXn/ca5lAguWWC3eu5hi8oZ7etX7aQlnTSgQZeslnJCbVJm6V6prFJKAzrqbBzMicUXr5pZLBDoXyTvHHw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-consecutive-dashes/-/remark-lint-no-file-name-consecutive-dashes-1.0.4.tgz", + "integrity": "sha512-Fyc8mL+Fyt2b/BVkCc2Y+GjJ4SwafDKQEUaizeuZQDBTiqRK3S4L9YpvLHTAPgTNntZkXLUsHzFDlGyKzW2gBQ==", "requires": { "unified-lint-rule": "^1.0.0" } }, "remark-lint-no-file-name-outer-dashes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-outer-dashes/-/remark-lint-no-file-name-outer-dashes-1.0.4.tgz", - "integrity": "sha512-+bZvvme2Bm3Vp5L2iKuvGHYVmHKrTkkRt8JqJPGepuhvBvT4Q7+CgfKyMtC/hIjyl+IcuJQ2H0qPRzdicjy1wQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-outer-dashes/-/remark-lint-no-file-name-outer-dashes-1.0.5.tgz", + "integrity": "sha512-5CMrCqyJj4ydM2QMhMAc60o08fJDxBgmO62r+RqVs+aIdIK6TtsF+T8oX+aTEtc3y/euKJ681tqEsSeJZh/h0A==", "requires": { "unified-lint-rule": "^1.0.0" } }, "remark-lint-no-heading-content-indent": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-heading-content-indent/-/remark-lint-no-heading-content-indent-1.0.3.tgz", - "integrity": "sha512-7xM6X5E/dt8OXOHdejH+sfYb139a3kMr8ZSSkcp90Ab1y+ZQBNaWsR3mYh8FRKkYPTN5eyd+KjhNpLWyqqCbgg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-heading-content-indent/-/remark-lint-no-heading-content-indent-2.0.0.tgz", + "integrity": "sha512-Zqg0WXG60Nan8j7HZtnBXidMxXhlhc7Q5JrB54I3n7H3vSPCyaqhZJ2/obYVLalEVGND8NOJGvfA1rtchaZyYg==", "requires": { "mdast-util-heading-style": "^1.0.2", - "plur": "^3.0.0", + "pluralize": "^8.0.0", "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-no-heading-indent": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-heading-indent/-/remark-lint-no-heading-indent-1.0.3.tgz", - "integrity": "sha512-RTvsFfiXjHZOxU+t7DtNPk9M9EqGe82MZbo+VOJEUBkQKf17qp4EZkJEvl4h9pn+hJmoKHLb7Vfge8Bxe42gcQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-heading-indent/-/remark-lint-no-heading-indent-2.0.0.tgz", + "integrity": "sha512-dBjSP2QdQVypFpwQdjZ6h/VsyY3CBY+IXY2edSWiITOofZrt7knmwrLFUoxPtvc9k4PIBA7XXpiwPPYBQzuLFg==", "requires": { - "plur": "^3.0.0", + "pluralize": "^8.0.0", "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-no-inline-padding": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-no-inline-padding/-/remark-lint-no-inline-padding-1.0.4.tgz", - "integrity": "sha512-u5rgbDkcfVv645YxxOwoGBBJbsHEwWm/XqnO8EhfKTxkfKOF4ZItG7Ajhj89EDaeXMkvCcB/avBl4bj50eJH3g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-inline-padding/-/remark-lint-no-inline-padding-2.0.0.tgz", + "integrity": "sha512-0YueQ3SBA8zFQYCN0/afRc6ZuSbM4Azx4sPVeVpAfMT0MrYgmi6msswyhUDXaeN2RwVO6bx/ZW6di8dVqRr7UA==", "requires": { "mdast-util-to-string": "^1.0.2", "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.4.0" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-no-literal-urls": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-literal-urls/-/remark-lint-no-literal-urls-1.0.3.tgz", - "integrity": "sha512-H5quyMzl2kaewK+jYD1FI0G1SIinIsIp4DEyOUwIR+vYUoKwo0B4vvW0cmPpD1dgqqxHYx0B2B0JQQKFVWzGiw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-literal-urls/-/remark-lint-no-literal-urls-2.0.0.tgz", + "integrity": "sha512-bZAxr65ftz9joszDkSs2LBeJB2cRE8GydUtxYdA1WRHYmVW1AfM5ilcqLnWhiOmu+XMPH7J0eRvUzbtvu+xerw==", "requires": { "mdast-util-to-string": "^1.0.2", "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-no-multiple-toplevel-headings": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-no-multiple-toplevel-headings/-/remark-lint-no-multiple-toplevel-headings-1.0.4.tgz", - "integrity": "sha512-0wDddx6htN5sL9/rofesiQF0oEgwN5224UmueiDx0ZUlYrn6VS0/SS0X3WWxtXmyeqlExfWF3D/g89tNs7dcjw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-multiple-toplevel-headings/-/remark-lint-no-multiple-toplevel-headings-2.0.0.tgz", + "integrity": "sha512-vpbdnrqUykyqpjaREg4W07J3gHgR0eTapDkz9RjVwyGNmBry7xUnyvaiPavAKqsA+qO/nnpIH8Qyw/2u5hDsJQ==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", "unist-util-stringify-position": "^2.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-no-shell-dollars": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-shell-dollars/-/remark-lint-no-shell-dollars-1.0.3.tgz", - "integrity": "sha512-fT3lQMTjEkPryL+63qDP1NfrohP3tG5i3SkNWSSR4VLU6OSsSSXlHGQGjo0ag//+EPKHB5/9frB/YQ0gDEPRGQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-shell-dollars/-/remark-lint-no-shell-dollars-2.0.0.tgz", + "integrity": "sha512-1uEM0kSGlV6UY7w3PdIeIf/USFFvVuU1352myQdaiw/Wof7+uVXznFFCPnhJDTVlPN4vrgwFnLb32UwXrjkrQw==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-no-shortcut-reference-image": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-image/-/remark-lint-no-shortcut-reference-image-1.0.3.tgz", - "integrity": "sha512-CGm27X54kXp/5ehXejDTsZjqzK4uIhLGcrFzN3k/KjdwunQouEY92AARGrLSEuJ1hQx0bJsmnvr/hvQyWAfNJg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-image/-/remark-lint-no-shortcut-reference-image-2.0.0.tgz", + "integrity": "sha512-kgGCQBHibJ0IFVhWjnfjbqkKC0VeL5+cvyjjwfMJlgZrHEXNOYb2FJE2nvF/l6PSXQ17goRZpznTBfP4mQieUA==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-no-shortcut-reference-link": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-link/-/remark-lint-no-shortcut-reference-link-1.0.4.tgz", - "integrity": "sha512-FXdMJYqspZBhPlxYqfVgVluVXjxStg0RHJzqrk8G9wS8fCS62AE3reoaoiCahwoH1tfKcA+poktbKqDAmZo7Jg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-link/-/remark-lint-no-shortcut-reference-link-2.0.0.tgz", + "integrity": "sha512-rSdGLWpEsHa4b2doUch+B7QtUHH9XuC8Hndb4rAYf8U0d48KfGAIoiicxUho8qZJ4VA3RIaDo4kA/iQ15Al+Vg==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-no-table-indentation": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-no-table-indentation/-/remark-lint-no-table-indentation-1.0.4.tgz", - "integrity": "sha512-H4VGHcg1k8sTIbwazFYLNbDqpPR+M0aHHKDf+93b/xyd27Dp0ODQrMnQbls1Cls5qOAQnwAQbx+75wcpFxP3OQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-table-indentation/-/remark-lint-no-table-indentation-2.0.0.tgz", + "integrity": "sha512-5akpqHl+5r3Xe2WFiZB1I9eAwn6zTYqXNd0CVsiTF3DJo0KyvvgyrFRV1sCf/l/kzyNaFvpWpFDTMoWc8EI0RQ==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.4.0" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-no-tabs": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-tabs/-/remark-lint-no-tabs-1.0.3.tgz", - "integrity": "sha512-GxmG1LLxYoVjKnQ39On4mFEiVwpLfR3BPTXyaC9UCBUj9fnDQ7ANXceeCsPAyxamr0UM4r2tk/hB9mNT4rLskQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-tabs/-/remark-lint-no-tabs-2.0.0.tgz", + "integrity": "sha512-aXbqkgjI0611IN651eXK8NxLQLEjReviU6AjtluMVnvGx1B8Y8mEn5pxznrorXaAjOP4mvX0JYeu8kdhcAaHsw==", "requires": { "unified-lint-rule": "^1.0.0", - "vfile-location": "^2.0.1" + "vfile-location": "^3.0.0" + }, + "dependencies": { + "vfile-location": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.0.1.tgz", + "integrity": "sha512-yYBO06eeN/Ki6Kh1QAkgzYpWT1d3Qln+ZCtSbJqFExPl1S3y2qqotJQXoh6qEvl/jDlgpUJolBn3PItVnnZRqQ==" + } } }, "remark-lint-no-trailing-spaces": { @@ -1118,46 +1834,132 @@ } }, "remark-lint-no-undefined-references": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/remark-lint-no-undefined-references/-/remark-lint-no-undefined-references-1.1.1.tgz", - "integrity": "sha512-b1eIjWFaCu6m16Ax2uG33o1v+eRYqDTQRUqU6UeQ76JXmDmVtVO75ZuyRpqqE7VTZRW8YLVurXfJPDXfIa5Wng==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-undefined-references/-/remark-lint-no-undefined-references-2.0.0.tgz", + "integrity": "sha512-K4k05pmlMRqEMUDYewitRUx8zM+ntJWbG61dILmL7to7uy0JoSbzuDtz1cxC+kKBKzkulPnyE3WOgRZG8RX2Jg==", "requires": { "collapse-white-space": "^1.0.4", "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.4.0" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-no-unused-definitions": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/remark-lint-no-unused-definitions/-/remark-lint-no-unused-definitions-1.0.5.tgz", - "integrity": "sha512-Bo22e0RNzc1QMW317KTuStGFDG7uTDUQhm/TrW6Qzud0WXnNnqUyvts+e7wTYoj8VnwhhjyjyoA9lKA3uXMdAQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-unused-definitions/-/remark-lint-no-unused-definitions-2.0.0.tgz", + "integrity": "sha512-Y8zrulwaf7z6WR1ICfEGjW92iq2SPEN7Zhrs0nloNITHOg22tIPf28TurUz9HSQ3sEd52d9bZCfW9RkdfMq1xw==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.4.0" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-ordered-list-marker-style": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-ordered-list-marker-style/-/remark-lint-ordered-list-marker-style-1.0.3.tgz", - "integrity": "sha512-24TmW1eUa/2JlwprZg9jJ8LKLxNGKnlKiI5YOhN4taUp2yv8daqlV9vR54yfn/ZZQh6EQvbIX0jeVY9NYgQUtw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-ordered-list-marker-style/-/remark-lint-ordered-list-marker-style-2.0.0.tgz", + "integrity": "sha512-zYMZA8tQD/slJYKqsstZv0/Q34Hkdlf4DjC8SOr92PSA60R/xr7JdVd/AHHisbMsFvdnHZrxaB8oIOtbAUJCSw==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-prohibited-strings": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/remark-lint-prohibited-strings/-/remark-lint-prohibited-strings-1.2.1.tgz", - "integrity": "sha512-i3LatoJn/eHkgawdi3eoynikQa5zIEDX+GYcvu4ns5LsOvIrT8WcuvgYQ2kbEFbV0KTy7yBAGLJ9040xs1ssXA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/remark-lint-prohibited-strings/-/remark-lint-prohibited-strings-1.5.1.tgz", + "integrity": "sha512-YZoRWbzIGRIQkngAowwAKG39kUAGSalYvrxqTzUU4LYj1dS37q7i5WDr4m/mnCcc5KwRin08D62Dphs6g9Btnw==", "requires": { + "escape-string-regexp": "^4.0.0", "unified-lint-rule": "^1.0.2", - "unist-util-visit": "^2.0.0" + "unist-util-position": "^3.1.0", + "unist-util-visit": "^2.0.0", + "vfile-location": "^3.0.1" }, "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + }, "unist-util-is": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", @@ -1181,62 +1983,197 @@ "@types/unist": "^2.0.0", "unist-util-is": "^4.0.0" } + }, + "vfile-location": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.0.1.tgz", + "integrity": "sha512-yYBO06eeN/Ki6Kh1QAkgzYpWT1d3Qln+ZCtSbJqFExPl1S3y2qqotJQXoh6qEvl/jDlgpUJolBn3PItVnnZRqQ==" } } }, "remark-lint-rule-style": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-rule-style/-/remark-lint-rule-style-1.0.3.tgz", - "integrity": "sha512-SJe7IFORYRdo8JUhMSdcTktVAUVNVp36YYl1ZD9CfHqQHWlFD+3vWYzJXOZfog/i+CyWf7Yi0WVYmQes+167dA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-rule-style/-/remark-lint-rule-style-2.0.0.tgz", + "integrity": "sha512-fdRfLUE5AJiFEn9rWTQrHwOUG3UcYtIxbWnR7YFvuPlFmzcMRwRHP5ZOcrj4KIpwCdVtlPI3h08m0kfO7a1KlQ==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-strong-marker": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-strong-marker/-/remark-lint-strong-marker-1.0.3.tgz", - "integrity": "sha512-PFkH282dCwfRsVEw9IxbYbaZBY4UcTuT2SN+lA3R0cBeocWnOySVw8YEm4sv9JfV8BLcQA5gc4tj66/U3KCScw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-strong-marker/-/remark-lint-strong-marker-2.0.0.tgz", + "integrity": "sha512-1gl6vZF5BvV4kvS4xxhl8cw90La5Cio9ZFDQuspZMRA2KjzpwoU5RlTUbeHv8OqlKJJ2p7s0MDs8bLZNTzzjHA==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-table-cell-padding": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-table-cell-padding/-/remark-lint-table-cell-padding-1.0.4.tgz", - "integrity": "sha512-AQWWtV1yca1PN27QaFRJbBK6Ro/bopv1XnVKxj/iMebhOU2D2FBJ8rXmMZXVMC3G9OB2WSzGgqH3nP6QY12LoA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-table-cell-padding/-/remark-lint-table-cell-padding-2.0.0.tgz", + "integrity": "sha512-UstIXIaRVRJPKZPv1AXX/p3qCt//RYNsRHIq8KvL5YQPKaKWRkj2cNermCgm0XoUXy0EmRPNiBtUcuAQaP+jXg==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.4.0" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-table-pipes": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-table-pipes/-/remark-lint-table-pipes-1.0.3.tgz", - "integrity": "sha512-K9NnGZp6i0m/CaOH7ZT4Ymt2seyiRPcBIlNMMGXBm6gpy34KJDDxYqsNUrh+j7dR+Zg4rYAQLnr3BiSHvj+rbQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-table-pipes/-/remark-lint-table-pipes-2.0.0.tgz", + "integrity": "sha512-qGIttPFNT+19BEDz2JJWQtJIClFNIpg+XVw6ruX9LSR7xdo5QG9uARG4XS2EGUQQ7fiLIxQYb8g2dHwuXGbfmA==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-lint-unordered-list-marker-style": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-unordered-list-marker-style/-/remark-lint-unordered-list-marker-style-1.0.3.tgz", - "integrity": "sha512-0nn/Yscy5ImO4fqByrk/Ua02UwGx8LRu+0kdCbkVz4IxPO5qxTEfyccUQZR71zTdMJp1d2OeqyD9XtMaO4X7Ww==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-unordered-list-marker-style/-/remark-lint-unordered-list-marker-style-2.0.0.tgz", + "integrity": "sha512-s+ZiBgBDbIiScPPxWG/r2E/4YY+xP6EFLsLXPV/uPx7JqegIP/4+MAPi7Nz2zLmnQ2eekssZrEXma3uDb/dE1Q==", "requires": { "unified-lint-rule": "^1.0.0", "unist-util-generated": "^1.1.0", "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "remark-message-control": { @@ -1272,65 +2209,178 @@ } }, "remark-preset-lint-node": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/remark-preset-lint-node/-/remark-preset-lint-node-1.13.0.tgz", - "integrity": "sha512-UNAoY4wl672d0qE+LM5rA0ILOTJN+siNGj3/qa5Zvl7nMIUwqMcz0G266Ck6OL6GOrpys/e4EOrkXiitEdEqNA==", - "requires": { - "remark-lint": "^6.0.5", - "remark-lint-blockquote-indentation": "^1.0.3", - "remark-lint-checkbox-character-style": "^1.0.3", - "remark-lint-checkbox-content-indent": "^1.0.3", - "remark-lint-code-block-style": "^1.0.3", - "remark-lint-definition-spacing": "^1.0.4", - "remark-lint-fenced-code-flag": "^1.0.3", - "remark-lint-fenced-code-marker": "^1.0.3", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/remark-preset-lint-node/-/remark-preset-lint-node-1.15.0.tgz", + "integrity": "sha512-1G7S2F/u7bk3kc4tZPrUphceP0RfT9AF6e+gzWbNi8URutECe3kl+Ur6ooMI5f1VqJUzcLF/U1YuhnFhkPnKkA==", + "requires": { + "remark-lint": "^7.0.0", + "remark-lint-blockquote-indentation": "^2.0.0", + "remark-lint-checkbox-character-style": "^2.0.0", + "remark-lint-checkbox-content-indent": "^2.0.0", + "remark-lint-code-block-style": "^2.0.0", + "remark-lint-definition-spacing": "^2.0.0", + "remark-lint-fenced-code-flag": "^2.0.0", + "remark-lint-fenced-code-marker": "^2.0.0", "remark-lint-file-extension": "^1.0.3", - "remark-lint-final-definition": "^1.0.3", - "remark-lint-first-heading-level": "^1.1.4", - "remark-lint-heading-style": "^1.0.3", - "remark-lint-list-item-indent": "^1.0.4", - "remark-lint-maximum-line-length": "^1.2.1", - "remark-lint-no-consecutive-blank-lines": "^1.0.3", - "remark-lint-no-file-name-articles": "^1.0.3", - "remark-lint-no-file-name-consecutive-dashes": "^1.0.3", - "remark-lint-no-file-name-outer-dashes": "^1.0.4", - "remark-lint-no-heading-indent": "^1.0.3", - "remark-lint-no-literal-urls": "^1.0.3", - "remark-lint-no-multiple-toplevel-headings": "^1.0.4", - "remark-lint-no-shell-dollars": "^1.0.3", - "remark-lint-no-table-indentation": "^1.0.4", - "remark-lint-no-tabs": "^1.0.3", + "remark-lint-final-definition": "^2.0.0", + "remark-lint-first-heading-level": "^2.0.0", + "remark-lint-heading-style": "^2.0.0", + "remark-lint-list-item-indent": "^2.0.0", + "remark-lint-maximum-line-length": "^2.0.0", + "remark-lint-no-consecutive-blank-lines": "^2.0.0", + "remark-lint-no-file-name-articles": "^1.0.4", + "remark-lint-no-file-name-consecutive-dashes": "^1.0.4", + "remark-lint-no-file-name-outer-dashes": "^1.0.5", + "remark-lint-no-heading-indent": "^2.0.0", + "remark-lint-no-multiple-toplevel-headings": "^2.0.0", + "remark-lint-no-shell-dollars": "^2.0.0", + "remark-lint-no-table-indentation": "^2.0.0", + "remark-lint-no-tabs": "^2.0.0", "remark-lint-no-trailing-spaces": "^2.0.1", - "remark-lint-prohibited-strings": "^1.2.1", - "remark-lint-rule-style": "^1.0.3", - "remark-lint-strong-marker": "^1.0.3", - "remark-lint-table-cell-padding": "^1.0.4", - "remark-lint-table-pipes": "^1.0.3", - "remark-lint-unordered-list-marker-style": "^1.0.3", - "remark-preset-lint-recommended": "^3.0.3" + "remark-lint-prohibited-strings": "^1.5.1", + "remark-lint-rule-style": "^2.0.0", + "remark-lint-strong-marker": "^2.0.0", + "remark-lint-table-cell-padding": "^2.0.0", + "remark-lint-table-pipes": "^2.0.0", + "remark-lint-unordered-list-marker-style": "^2.0.0", + "remark-preset-lint-recommended": "^4.0.0" + }, + "dependencies": { + "remark-lint": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/remark-lint/-/remark-lint-7.0.0.tgz", + "integrity": "sha512-OLrWPYy0MUcGLa/2rjuy1kQILTRRK+JiRtyUzqe4XRoHboGuvFDcy/W2e7sq5hu/0xmD+Eh7cEa1Coiqp7LeaA==", + "requires": { + "remark-message-control": "^6.0.0" + } + }, + "remark-message-control": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/remark-message-control/-/remark-message-control-6.0.0.tgz", + "integrity": "sha512-k9bt7BYc3G7YBdmeAhvd3VavrPa/XlKWR3CyHjr4sLO9xJyly8WHHT3Sp+8HPR8lEUv+/sZaffL7IjMLV0f6BA==", + "requires": { + "mdast-comment-marker": "^1.0.0", + "unified-message-control": "^3.0.0" + } + }, + "unified-message-control": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/unified-message-control/-/unified-message-control-3.0.1.tgz", + "integrity": "sha512-K2Kvvp1DBzeuxYLLsumZh/gDWUTl4e2z/P3VReFirC78cfHKtQifbhnfRrSBtKtd1Uc6cvYTW0/SZIUaMAEcTg==", + "requires": { + "unist-util-visit": "^2.0.0", + "vfile-location": "^3.0.0" + } + }, + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + }, + "vfile-location": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.0.1.tgz", + "integrity": "sha512-yYBO06eeN/Ki6Kh1QAkgzYpWT1d3Qln+ZCtSbJqFExPl1S3y2qqotJQXoh6qEvl/jDlgpUJolBn3PItVnnZRqQ==" + } } }, "remark-preset-lint-recommended": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/remark-preset-lint-recommended/-/remark-preset-lint-recommended-3.0.3.tgz", - "integrity": "sha512-5sQ34j1Irlsj6Tt4WWRylZ7UU+1jD5es/LfDZBZp/LXDwC4ldGqKpMmCCR6Z00x1jYM1phmS4M+eGqTdah0qkQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-preset-lint-recommended/-/remark-preset-lint-recommended-4.0.0.tgz", + "integrity": "sha512-Nroe+4Itvk+AHxkMCMu6iRUptE/5pXWgLoEOGdVO/2JIiMk/+15HEogMZ05vMhPct9+Wp4uVt2zqfuvzNzdcww==", "requires": { - "remark-lint": "^6.0.0", + "remark-lint": "^7.0.0", "remark-lint-final-newline": "^1.0.0", - "remark-lint-hard-break-spaces": "^1.0.0", - "remark-lint-list-item-bullet-indent": "^1.0.0", - "remark-lint-list-item-indent": "^1.0.0", - "remark-lint-no-auto-link-without-protocol": "^1.0.0", - "remark-lint-no-blockquote-without-marker": "^2.0.0", - "remark-lint-no-duplicate-definitions": "^1.0.0", - "remark-lint-no-heading-content-indent": "^1.0.0", - "remark-lint-no-inline-padding": "^1.0.0", - "remark-lint-no-literal-urls": "^1.0.0", - "remark-lint-no-shortcut-reference-image": "^1.0.0", - "remark-lint-no-shortcut-reference-link": "^1.0.0", - "remark-lint-no-undefined-references": "^1.0.0", - "remark-lint-no-unused-definitions": "^1.0.0", - "remark-lint-ordered-list-marker-style": "^1.0.0" + "remark-lint-hard-break-spaces": "^2.0.0", + "remark-lint-list-item-bullet-indent": "^2.0.0", + "remark-lint-list-item-indent": "^2.0.0", + "remark-lint-no-auto-link-without-protocol": "^2.0.0", + "remark-lint-no-blockquote-without-marker": "^3.0.0", + "remark-lint-no-duplicate-definitions": "^2.0.0", + "remark-lint-no-heading-content-indent": "^2.0.0", + "remark-lint-no-inline-padding": "^2.0.0", + "remark-lint-no-literal-urls": "^2.0.0", + "remark-lint-no-shortcut-reference-image": "^2.0.0", + "remark-lint-no-shortcut-reference-link": "^2.0.0", + "remark-lint-no-undefined-references": "^2.0.0", + "remark-lint-no-unused-definitions": "^2.0.0", + "remark-lint-ordered-list-marker-style": "^2.0.0" + }, + "dependencies": { + "remark-lint": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/remark-lint/-/remark-lint-7.0.0.tgz", + "integrity": "sha512-OLrWPYy0MUcGLa/2rjuy1kQILTRRK+JiRtyUzqe4XRoHboGuvFDcy/W2e7sq5hu/0xmD+Eh7cEa1Coiqp7LeaA==", + "requires": { + "remark-message-control": "^6.0.0" + } + }, + "remark-message-control": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/remark-message-control/-/remark-message-control-6.0.0.tgz", + "integrity": "sha512-k9bt7BYc3G7YBdmeAhvd3VavrPa/XlKWR3CyHjr4sLO9xJyly8WHHT3Sp+8HPR8lEUv+/sZaffL7IjMLV0f6BA==", + "requires": { + "mdast-comment-marker": "^1.0.0", + "unified-message-control": "^3.0.0" + } + }, + "unified-message-control": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/unified-message-control/-/unified-message-control-3.0.1.tgz", + "integrity": "sha512-K2Kvvp1DBzeuxYLLsumZh/gDWUTl4e2z/P3VReFirC78cfHKtQifbhnfRrSBtKtd1Uc6cvYTW0/SZIUaMAEcTg==", + "requires": { + "unist-util-visit": "^2.0.0", + "vfile-location": "^3.0.0" + } + }, + "unist-util-is": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz", + "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==" + }, + "unist-util-visit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", + "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", + "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + }, + "vfile-location": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.0.1.tgz", + "integrity": "sha512-yYBO06eeN/Ki6Kh1QAkgzYpWT1d3Qln+ZCtSbJqFExPl1S3y2qqotJQXoh6qEvl/jDlgpUJolBn3PItVnnZRqQ==" + } } }, "remark-stringify": { @@ -1608,9 +2658,9 @@ } }, "unified-lint-rule": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unified-lint-rule/-/unified-lint-rule-1.0.4.tgz", - "integrity": "sha512-q9wY6S+d38xRAuWQVOMjBQYi7zGyKkY23ciNafB8JFVmDroyKjtytXHCg94JnhBCXrNqpfojo3+8D+gmF4zxJQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/unified-lint-rule/-/unified-lint-rule-1.0.5.tgz", + "integrity": "sha512-jOPr/fx8lTzqszEfh46p99jUMqgPlIZ8rNKllEepumISvgfj9lUq1c7BSpVihr0L1df3lkjVHAThRPS7dIyjYg==", "requires": { "wrapped": "^1.0.1" } diff --git a/tools/node-lint-md-cli-rollup/package.json b/tools/node-lint-md-cli-rollup/package.json index be155b49e95fce..58ea5ee80a3dad 100644 --- a/tools/node-lint-md-cli-rollup/package.json +++ b/tools/node-lint-md-cli-rollup/package.json @@ -13,7 +13,7 @@ "markdown-extensions": "^1.1.1", "remark": "^11.0.2", "remark-lint": "^6.0.5", - "remark-preset-lint-node": "^1.13.0", + "remark-preset-lint-node": "^1.15.0", "unified-args": "^7.1.0" }, "main": "dist/index.js", diff --git a/tools/node_modules/eslint/README.md b/tools/node_modules/eslint/README.md index da75b5c149d799..0a802b0c25d0ca 100644 --- a/tools/node_modules/eslint/README.md +++ b/tools/node_modules/eslint/README.md @@ -214,6 +214,11 @@ The people who review and implement new features.
薛定谔的猫 +
+ +
+Milos Djermanovic +
@@ -233,11 +238,6 @@ Pig Fang
YeonJuan -
- -
-Milos Djermanovic -
@@ -250,9 +250,9 @@ The following companies, organizations, and individuals support ESLint's ongoing

Gold Sponsors

-

Shopify Salesforce MagicLab Airbnb

Silver Sponsors

+

Shopify Salesforce Airbnb

Silver Sponsors

AMP Project

Bronze Sponsors

-

Kasinot.fi Pelisivut Nettikasinot.org BonusFinder Deutschland Top Web Design Agencies Bugsnag Stability Monitoring Mixpanel VPS Server Free Icons by Icons8 UI UX Design Agencies clay Discord ThemeIsle TekHattan Marfeel Fire Stick Tricks

+

CasinoTop.com Casino Topp Writers Per Hour Anagram Solver vpn netflix Kasinot.fi Pelisivut Nettikasinot.org BonusFinder Deutschland Top Web Design Agencies Bugsnag Stability Monitoring Mixpanel VPS Server Free Icons by Icons8 UI UX Design Agencies clay Discord ThemeIsle TekHattan Marfeel Fire Stick Tricks

## Technology Sponsors diff --git a/tools/node_modules/eslint/bin/eslint.js b/tools/node_modules/eslint/bin/eslint.js index a9f51f1d7d4c57..75b413148695e5 100755 --- a/tools/node_modules/eslint/bin/eslint.js +++ b/tools/node_modules/eslint/bin/eslint.js @@ -12,97 +12,135 @@ // to use V8's code cache to speed up instantiation time require("v8-compile-cache"); -//------------------------------------------------------------------------------ -// Helpers -//------------------------------------------------------------------------------ - -const useStdIn = process.argv.includes("--stdin"), - init = process.argv.includes("--init"), - debug = process.argv.includes("--debug"); - // must do this initialization *before* other requires in order to work -if (debug) { +if (process.argv.includes("--debug")) { require("debug").enable("eslint:*,-eslint:code-path"); } //------------------------------------------------------------------------------ -// Requirements +// Helpers //------------------------------------------------------------------------------ -// now we can safely include the other modules that use debug -const path = require("path"), - fs = require("fs"), - cli = require("../lib/cli"); - -//------------------------------------------------------------------------------ -// Execution -//------------------------------------------------------------------------------ +/** + * Read data from stdin til the end. + * + * Note: See + * - https://github.com/nodejs/node/blob/master/doc/api/process.md#processstdin + * - https://github.com/nodejs/node/blob/master/doc/api/process.md#a-note-on-process-io + * - https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-01/msg00419.html + * - https://github.com/nodejs/node/issues/7439 (historical) + * + * On Windows using `fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8")` seems + * to read 4096 bytes before blocking and never drains to read further data. + * + * The investigation on the Emacs thread indicates: + * + * > Emacs on MS-Windows uses pipes to communicate with subprocesses; a + * > pipe on Windows has a 4K buffer. So as soon as Emacs writes more than + * > 4096 bytes to the pipe, the pipe becomes full, and Emacs then waits for + * > the subprocess to read its end of the pipe, at which time Emacs will + * > write the rest of the stuff. + * @returns {Promise} The read text. + */ +function readStdin() { + return new Promise((resolve, reject) => { + let content = ""; + let chunk = ""; + + process.stdin + .setEncoding("utf8") + .on("readable", () => { + while ((chunk = process.stdin.read()) !== null) { + content += chunk; + } + }) + .on("end", () => resolve(content)) + .on("error", reject); + }); +} -process.once("uncaughtException", err => { +/** + * Get the error message of a given value. + * @param {any} error The value to get. + * @returns {string} The error message. + */ +function getErrorMessage(error) { - // lazy load + // Lazy loading because those are used only if error happened. + const fs = require("fs"); + const path = require("path"); + const util = require("util"); const lodash = require("lodash"); - if (typeof err.messageTemplate === "string" && err.messageTemplate.length > 0) { - const template = lodash.template(fs.readFileSync(path.resolve(__dirname, `../messages/${err.messageTemplate}.txt`), "utf-8")); - const pkg = require("../package.json"); + // Foolproof -- thirdparty module might throw non-object. + if (typeof error !== "object" || error === null) { + return String(error); + } + + // Use templates if `error.messageTemplate` is present. + if (typeof error.messageTemplate === "string") { + try { + const templateFilePath = path.resolve( + __dirname, + `../messages/${error.messageTemplate}.txt` + ); + + // Use sync API because Node.js should exit at this tick. + const templateText = fs.readFileSync(templateFilePath, "utf-8"); + const template = lodash.template(templateText); + + return template(error.messageData || {}); + } catch { + + // Ignore template error then fallback to use `error.stack`. + } + } - console.error("\nOops! Something went wrong! :("); - console.error(`\nESLint: ${pkg.version}.\n\n${template(err.messageData || {})}`); - } else { - console.error(err.stack); + // Use the stacktrace if it's an error object. + if (typeof error.stack === "string") { + return error.stack; } + // Otherwise, dump the object. + return util.format("%o", error); +} + +/** + * Catch and report unexpected error. + * @param {any} error The thrown error object. + * @returns {void} + */ +function onFatalError(error) { process.exitCode = 2; -}); - -if (useStdIn) { - - /* - * Note: See - * - https://github.com/nodejs/node/blob/master/doc/api/process.md#processstdin - * - https://github.com/nodejs/node/blob/master/doc/api/process.md#a-note-on-process-io - * - https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-01/msg00419.html - * - https://github.com/nodejs/node/issues/7439 (historical) - * - * On Windows using `fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8")` seems - * to read 4096 bytes before blocking and never drains to read further data. - * - * The investigation on the Emacs thread indicates: - * - * > Emacs on MS-Windows uses pipes to communicate with subprocesses; a - * > pipe on Windows has a 4K buffer. So as soon as Emacs writes more than - * > 4096 bytes to the pipe, the pipe becomes full, and Emacs then waits for - * > the subprocess to read its end of the pipe, at which time Emacs will - * > write the rest of the stuff. - * - * Using the nodejs code example for reading from stdin. - */ - let contents = "", - chunk = ""; - - process.stdin.setEncoding("utf8"); - process.stdin.on("readable", () => { - - // Use a loop to make sure we read all available data. - while ((chunk = process.stdin.read()) !== null) { - contents += chunk; - } - }); - process.stdin.on("end", () => { - process.exitCode = cli.execute(process.argv, contents, "utf8"); - }); -} else if (init) { - const configInit = require("../lib/init/config-initializer"); - - configInit.initializeConfig().then(() => { - process.exitCode = 0; - }).catch(err => { - process.exitCode = 1; - console.error(err.message); - console.error(err.stack); - }); -} else { - process.exitCode = cli.execute(process.argv); + const { version } = require("../package.json"); + const message = getErrorMessage(error); + + console.error(` +Oops! Something went wrong! :( + +ESLint: ${version} + +${message}`); } + +//------------------------------------------------------------------------------ +// Execution +//------------------------------------------------------------------------------ + +(async function main() { + process.on("uncaughtException", onFatalError); + process.on("unhandledRejection", onFatalError); + + // Call the config initializer if `--init` is present. + if (process.argv.includes("--init")) { + await require("../lib/init/config-initializer").initializeConfig(); + return; + } + + // Otherwise, call the CLI. + process.exitCode = await require("../lib/cli").execute( + process.argv, + process.argv.includes("--stdin") ? await readStdin() : null + ); +}()).catch(onFatalError); diff --git a/tools/node_modules/eslint/lib/api.js b/tools/node_modules/eslint/lib/api.js index 40a5cc9fa5ccd4..e4b6643b44780a 100644 --- a/tools/node_modules/eslint/lib/api.js +++ b/tools/node_modules/eslint/lib/api.js @@ -6,6 +6,7 @@ "use strict"; const { CLIEngine } = require("./cli-engine"); +const { ESLint } = require("./eslint"); const { Linter } = require("./linter"); const { RuleTester } = require("./rule-tester"); const { SourceCode } = require("./source-code"); @@ -13,6 +14,7 @@ const { SourceCode } = require("./source-code"); module.exports = { Linter, CLIEngine, + ESLint, RuleTester, SourceCode }; diff --git a/tools/node_modules/eslint/lib/cli-engine/cascading-config-array-factory.js b/tools/node_modules/eslint/lib/cli-engine/cascading-config-array-factory.js index b53f67bd9dce6c..f54605c4db991e 100644 --- a/tools/node_modules/eslint/lib/cli-engine/cascading-config-array-factory.js +++ b/tools/node_modules/eslint/lib/cli-engine/cascading-config-array-factory.js @@ -279,6 +279,18 @@ class CascadingConfigArrayFactory { ); } + /** + * Set the config data to override all configs. + * Require to call `clearCache()` method after this method is called. + * @param {ConfigData} configData The config data to override all configs. + * @returns {void} + */ + setOverrideConfig(configData) { + const slots = internalSlotsMap.get(this); + + slots.cliConfigData = configData; + } + /** * Clear config cache. * @returns {void} diff --git a/tools/node_modules/eslint/lib/cli-engine/cli-engine.js b/tools/node_modules/eslint/lib/cli-engine/cli-engine.js index 72d1fa4d5dcd5d..b6aa995beef933 100644 --- a/tools/node_modules/eslint/lib/cli-engine/cli-engine.js +++ b/tools/node_modules/eslint/lib/cli-engine/cli-engine.js @@ -39,6 +39,7 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]); // For VSCode IntelliSense /** @typedef {import("../shared/types").ConfigData} ConfigData */ +/** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */ /** @typedef {import("../shared/types").LintMessage} LintMessage */ /** @typedef {import("../shared/types").ParserOptions} ParserOptions */ /** @typedef {import("../shared/types").Plugin} Plugin */ @@ -50,29 +51,29 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]); /** * The options to configure a CLI engine with. * @typedef {Object} CLIEngineOptions - * @property {boolean} allowInlineConfig Enable or disable inline configuration comments. - * @property {ConfigData} baseConfig Base config object, extended by all configs used with this CLIEngine instance - * @property {boolean} cache Enable result caching. - * @property {string} cacheLocation The cache file to use instead of .eslintcache. - * @property {string} configFile The configuration file to use. - * @property {string} cwd The value to use for the current working directory. - * @property {string[]} envs An array of environments to load. - * @property {string[]|null} extensions An array of file extensions to check. - * @property {boolean|Function} fix Execute in autofix mode. If a function, should return a boolean. - * @property {string[]} fixTypes Array of rule types to apply fixes for. - * @property {string[]} globals An array of global variables to declare. - * @property {boolean} ignore False disables use of .eslintignore. - * @property {string} ignorePath The ignore file to use instead of .eslintignore. - * @property {string|string[]} ignorePattern One or more glob patterns to ignore. - * @property {boolean} useEslintrc False disables looking for .eslintrc - * @property {string} parser The name of the parser to use. - * @property {ParserOptions} parserOptions An object of parserOption settings to use. - * @property {string[]} plugins An array of plugins to load. - * @property {Record} rules An object of rules to use. - * @property {string[]} rulePaths An array of directories to load custom rules from. - * @property {boolean} reportUnusedDisableDirectives `true` adds reports for unused eslint-disable directives - * @property {boolean} globInputPaths Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file. - * @property {string} resolvePluginsRelativeTo The folder where plugins should be resolved from, defaulting to the CWD + * @property {boolean} [allowInlineConfig] Enable or disable inline configuration comments. + * @property {ConfigData} [baseConfig] Base config object, extended by all configs used with this CLIEngine instance + * @property {boolean} [cache] Enable result caching. + * @property {string} [cacheLocation] The cache file to use instead of .eslintcache. + * @property {string} [configFile] The configuration file to use. + * @property {string} [cwd] The value to use for the current working directory. + * @property {string[]} [envs] An array of environments to load. + * @property {string[]|null} [extensions] An array of file extensions to check. + * @property {boolean|Function} [fix] Execute in autofix mode. If a function, should return a boolean. + * @property {string[]} [fixTypes] Array of rule types to apply fixes for. + * @property {string[]} [globals] An array of global variables to declare. + * @property {boolean} [ignore] False disables use of .eslintignore. + * @property {string} [ignorePath] The ignore file to use instead of .eslintignore. + * @property {string|string[]} [ignorePattern] One or more glob patterns to ignore. + * @property {boolean} [useEslintrc] False disables looking for .eslintrc + * @property {string} [parser] The name of the parser to use. + * @property {ParserOptions} [parserOptions] An object of parserOption settings to use. + * @property {string[]} [plugins] An array of plugins to load. + * @property {Record} [rules] An object of rules to use. + * @property {string[]} [rulePaths] An array of directories to load custom rules from. + * @property {boolean} [reportUnusedDisableDirectives] `true` adds reports for unused eslint-disable directives + * @property {boolean} [globInputPaths] Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file. + * @property {string} [resolvePluginsRelativeTo] The folder where plugins should be resolved from, defaulting to the CWD */ /** @@ -88,13 +89,6 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]); * @property {string} [output] The source code of the file that was linted, with as many fixes applied as possible. */ -/** - * Information of deprecated rules. - * @typedef {Object} DeprecatedRuleInfo - * @property {string} ruleId The rule ID. - * @property {string[]} replacedBy The rule IDs that replace this deprecated rule. - */ - /** * Linting results. * @typedef {Object} LintReport @@ -821,16 +815,22 @@ class CLIEngine { lintResultCache.reconcile(); } - // Collect used deprecated rules. - const usedDeprecatedRules = Array.from( - iterateRuleDeprecationWarnings(lastConfigArrays) - ); - debug(`Linting complete in: ${Date.now() - startTime}ms`); + let usedDeprecatedRules; + return { results, ...calculateStatsPerRun(results), - usedDeprecatedRules + + // Initialize it lazily because CLI and `ESLint` API don't use it. + get usedDeprecatedRules() { + if (!usedDeprecatedRules) { + usedDeprecatedRules = Array.from( + iterateRuleDeprecationWarnings(lastConfigArrays) + ); + } + return usedDeprecatedRules; + } }; } @@ -858,9 +858,9 @@ class CLIEngine { const startTime = Date.now(); const resolvedFilename = filename && path.resolve(cwd, filename); + // Clear the last used config arrays. lastConfigArrays.length = 0; - if (resolvedFilename && this.isPathIgnored(resolvedFilename)) { if (warnIgnored) { results.push(createIgnoreResult(resolvedFilename, cwd)); @@ -892,16 +892,22 @@ class CLIEngine { })); } - // Collect used deprecated rules. - const usedDeprecatedRules = Array.from( - iterateRuleDeprecationWarnings(lastConfigArrays) - ); - debug(`Linting complete in: ${Date.now() - startTime}ms`); + let usedDeprecatedRules; + return { results, ...calculateStatsPerRun(results), - usedDeprecatedRules + + // Initialize it lazily because CLI and `ESLint` API don't use it. + get usedDeprecatedRules() { + if (!usedDeprecatedRules) { + usedDeprecatedRules = Array.from( + iterateRuleDeprecationWarnings(lastConfigArrays) + ); + } + return usedDeprecatedRules; + } }; } @@ -955,11 +961,10 @@ class CLIEngine { } /** - * Returns the formatter representing the given format or null if no formatter - * with the given name can be found. + * Returns the formatter representing the given format or null if the `format` is not a string. * @param {string} [format] The name of the format to load or the path to a * custom formatter. - * @returns {Function} The formatter function or null if not found. + * @returns {(Function|null)} The formatter function or null if the `format` is not a string. */ getFormatter(format) { diff --git a/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js b/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js index b1429af6ad95cf..fa3fdb3bedd89b 100644 --- a/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js +++ b/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js @@ -817,7 +817,7 @@ class ConfigArrayFactory { if (configData) { return this._normalizeConfigData(configData, { ...ctx, - filePath: plugin.filePath, + filePath: plugin.filePath || ctx.filePath, name: `${ctx.name} » plugin:${plugin.id}/${configName}` }); } @@ -978,7 +978,7 @@ class ConfigArrayFactory { if (plugin) { return new ConfigDependency({ definition: normalizePlugin(plugin), - filePath: ctx.filePath, + filePath: "", // It's unknown where the plugin came from. id, importerName: ctx.name, importerPath: ctx.filePath diff --git a/tools/node_modules/eslint/lib/cli-engine/config-array/config-array.js b/tools/node_modules/eslint/lib/cli-engine/config-array/config-array.js index b3434198b19201..42a7362737fc7c 100644 --- a/tools/node_modules/eslint/lib/cli-engine/config-array/config-array.js +++ b/tools/node_modules/eslint/lib/cli-engine/config-array/config-array.js @@ -107,7 +107,7 @@ function getMatchedIndices(elements, filePath) { for (let i = elements.length - 1; i >= 0; --i) { const element = elements[i]; - if (!element.criteria || element.criteria.test(filePath)) { + if (!element.criteria || (filePath && element.criteria.test(filePath))) { indices.push(i); } } diff --git a/tools/node_modules/eslint/lib/cli-engine/config-array/ignore-pattern.js b/tools/node_modules/eslint/lib/cli-engine/config-array/ignore-pattern.js index 92690b9f8ae342..6eaec4258e1ae4 100644 --- a/tools/node_modules/eslint/lib/cli-engine/config-array/ignore-pattern.js +++ b/tools/node_modules/eslint/lib/cli-engine/config-array/ignore-pattern.js @@ -71,7 +71,13 @@ function getCommonAncestorPath(sourcePaths) { } } - return result || path.sep; + let resolvedResult = result || path.sep; + + // if Windows common ancestor is root of drive must have trailing slash to be absolute. + if (resolvedResult && resolvedResult.endsWith(":") && process.platform === "win32") { + resolvedResult += path.sep; + } + return resolvedResult; } /** diff --git a/tools/node_modules/eslint/lib/cli.js b/tools/node_modules/eslint/lib/cli.js index 815ce68c22fe2e..ce11878008f108 100644 --- a/tools/node_modules/eslint/lib/cli.js +++ b/tools/node_modules/eslint/lib/cli.js @@ -17,105 +17,176 @@ const fs = require("fs"), path = require("path"), - { CLIEngine } = require("./cli-engine"), - options = require("./options"), + { promisify } = require("util"), + { ESLint } = require("./eslint"), + CLIOptions = require("./options"), log = require("./shared/logging"), RuntimeInfo = require("./shared/runtime-info"); const debug = require("debug")("eslint:cli"); +//------------------------------------------------------------------------------ +// Types +//------------------------------------------------------------------------------ + +/** @typedef {import("./eslint/eslint").ESLintOptions} ESLintOptions */ +/** @typedef {import("./eslint/eslint").LintMessage} LintMessage */ +/** @typedef {import("./eslint/eslint").LintResult} LintResult */ + //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ +const mkdir = promisify(fs.mkdir); +const stat = promisify(fs.stat); +const writeFile = promisify(fs.writeFile); + /** * Predicate function for whether or not to apply fixes in quiet mode. * If a message is a warning, do not apply a fix. - * @param {LintResult} lintResult The lint result. + * @param {LintMessage} message The lint result. * @returns {boolean} True if the lint message is an error (and thus should be * autofixed), false otherwise. */ -function quietFixPredicate(lintResult) { - return lintResult.severity === 2; +function quietFixPredicate(message) { + return message.severity === 2; } /** * Translates the CLI options into the options expected by the CLIEngine. * @param {Object} cliOptions The CLI options to translate. - * @returns {CLIEngineOptions} The options object for the CLIEngine. + * @returns {ESLintOptions} The options object for the CLIEngine. * @private */ -function translateOptions(cliOptions) { +function translateOptions({ + cache, + cacheFile, + cacheLocation, + config, + env, + errorOnUnmatchedPattern, + eslintrc, + ext, + fix, + fixDryRun, + fixType, + global, + ignore, + ignorePath, + ignorePattern, + inlineConfig, + parser, + parserOptions, + plugin, + quiet, + reportUnusedDisableDirectives, + resolvePluginsRelativeTo, + rule, + rulesdir +}) { return { - envs: cliOptions.env, - extensions: cliOptions.ext, - rules: cliOptions.rule, - plugins: cliOptions.plugin, - globals: cliOptions.global, - ignore: cliOptions.ignore, - ignorePath: cliOptions.ignorePath, - ignorePattern: cliOptions.ignorePattern, - configFile: cliOptions.config, - rulePaths: cliOptions.rulesdir, - useEslintrc: cliOptions.eslintrc, - parser: cliOptions.parser, - parserOptions: cliOptions.parserOptions, - cache: cliOptions.cache, - cacheFile: cliOptions.cacheFile, - cacheLocation: cliOptions.cacheLocation, - fix: (cliOptions.fix || cliOptions.fixDryRun) && (cliOptions.quiet ? quietFixPredicate : true), - fixTypes: cliOptions.fixType, - allowInlineConfig: cliOptions.inlineConfig, - reportUnusedDisableDirectives: cliOptions.reportUnusedDisableDirectives, - resolvePluginsRelativeTo: cliOptions.resolvePluginsRelativeTo, - errorOnUnmatchedPattern: cliOptions.errorOnUnmatchedPattern + allowInlineConfig: inlineConfig, + cache, + cacheLocation: cacheLocation || cacheFile, + errorOnUnmatchedPattern, + extensions: ext, + fix: (fix || fixDryRun) && (quiet ? quietFixPredicate : true), + fixTypes: fixType, + ignore, + ignorePath, + overrideConfig: { + env: env && env.reduce((obj, name) => { + obj[name] = true; + return obj; + }, {}), + globals: global && global.reduce((obj, name) => { + if (name.endsWith(":true")) { + obj[name.slice(0, -5)] = "writable"; + } else { + obj[name] = "readonly"; + } + return obj; + }, {}), + ignorePatterns: ignorePattern, + parser, + parserOptions, + plugins: plugin, + rules: rule + }, + overrideConfigFile: config, + reportUnusedDisableDirectives: reportUnusedDisableDirectives ? "error" : void 0, + resolvePluginsRelativeTo, + rulePaths: rulesdir, + useEslintrc: eslintrc }; } +/** + * Count error messages. + * @param {LintResult[]} results The lint results. + * @returns {{errorCount:number;warningCount:number}} The number of error messages. + */ +function countErrors(results) { + let errorCount = 0; + let warningCount = 0; + + for (const result of results) { + errorCount += result.errorCount; + warningCount += result.warningCount; + } + + return { errorCount, warningCount }; +} + +/** + * Check if a given file path is a directory or not. + * @param {string} filePath The path to a file to check. + * @returns {Promise} `true` if the given path is a directory. + */ +async function isDirectory(filePath) { + try { + return (await stat(filePath)).isDirectory(); + } catch (error) { + if (error.code === "ENOENT" || error.code === "ENOTDIR") { + return false; + } + throw error; + } +} + /** * Outputs the results of the linting. - * @param {CLIEngine} engine The CLIEngine to use. + * @param {ESLint} engine The ESLint instance to use. * @param {LintResult[]} results The results to print. * @param {string} format The name of the formatter to use or the path to the formatter. * @param {string} outputFile The path for the output file. - * @returns {boolean} True if the printing succeeds, false if not. + * @returns {Promise} True if the printing succeeds, false if not. * @private */ -function printResults(engine, results, format, outputFile) { +async function printResults(engine, results, format, outputFile) { let formatter; - let rulesMeta; try { - formatter = engine.getFormatter(format); + formatter = await engine.loadFormatter(format); } catch (e) { log.error(e.message); return false; } - const output = formatter(results, { - get rulesMeta() { - if (!rulesMeta) { - rulesMeta = {}; - for (const [ruleId, rule] of engine.getRules()) { - rulesMeta[ruleId] = rule.meta; - } - } - return rulesMeta; - } - }); + const output = formatter.format(results); if (output) { if (outputFile) { const filePath = path.resolve(process.cwd(), outputFile); - if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) { + if (await isDirectory(filePath)) { log.error("Cannot write to output file path, it is a directory: %s", outputFile); return false; } try { - fs.mkdirSync(path.dirname(filePath), { recursive: true }); - fs.writeFileSync(filePath, output); + await mkdir(path.dirname(filePath), { recursive: true }); + await writeFile(filePath, output); } catch (ex) { log.error("There was a problem writing the output file:\n%s", ex); return false; @@ -126,7 +197,6 @@ function printResults(engine, results, format, outputFile) { } return true; - } //------------------------------------------------------------------------------ @@ -143,28 +213,33 @@ const cli = { * Executes the CLI based on an array of arguments that is passed in. * @param {string|Array|Object} args The arguments to process. * @param {string} [text] The text to lint (used for TTY). - * @returns {int} The exit code for the operation. + * @returns {Promise} The exit code for the operation. */ - execute(args, text) { + async execute(args, text) { if (Array.isArray(args)) { debug("CLI args: %o", args.slice(2)); } - - let currentOptions; + let options; try { - currentOptions = options.parse(args); + options = CLIOptions.parse(args); } catch (error) { log.error(error.message); return 2; } - const files = currentOptions._; + const files = options._; const useStdin = typeof text === "string"; - if (currentOptions.version) { + if (options.help) { + log.info(CLIOptions.generateHelp()); + return 0; + } + if (options.version) { log.info(RuntimeInfo.version()); - } else if (currentOptions.envInfo) { + return 0; + } + if (options.envInfo) { try { log.info(RuntimeInfo.environment()); return 0; @@ -172,7 +247,9 @@ const cli = { log.error(err.message); return 2; } - } else if (currentOptions.printConfig) { + } + + if (options.printConfig) { if (files.length) { log.error("The --print-config option must be used with exactly one file name."); return 2; @@ -182,58 +259,67 @@ const cli = { return 2; } - const engine = new CLIEngine(translateOptions(currentOptions)); - const fileConfig = engine.getConfigForFile(currentOptions.printConfig); + const engine = new ESLint(translateOptions(options)); + const fileConfig = + await engine.calculateConfigForFile(options.printConfig); log.info(JSON.stringify(fileConfig, null, " ")); return 0; - } else if (currentOptions.help || (!files.length && !useStdin)) { - log.info(options.generateHelp()); - } else { - debug(`Running on ${useStdin ? "text" : "files"}`); - - if (currentOptions.fix && currentOptions.fixDryRun) { - log.error("The --fix option and the --fix-dry-run option cannot be used together."); - return 2; - } + } - if (useStdin && currentOptions.fix) { - log.error("The --fix option is not available for piped-in code; use --fix-dry-run instead."); - return 2; - } + debug(`Running on ${useStdin ? "text" : "files"}`); - if (currentOptions.fixType && !currentOptions.fix && !currentOptions.fixDryRun) { - log.error("The --fix-type option requires either --fix or --fix-dry-run."); - return 2; - } + if (options.fix && options.fixDryRun) { + log.error("The --fix option and the --fix-dry-run option cannot be used together."); + return 2; + } + if (useStdin && options.fix) { + log.error("The --fix option is not available for piped-in code; use --fix-dry-run instead."); + return 2; + } + if (options.fixType && !options.fix && !options.fixDryRun) { + log.error("The --fix-type option requires either --fix or --fix-dry-run."); + return 2; + } - const engine = new CLIEngine(translateOptions(currentOptions)); - const report = useStdin ? engine.executeOnText(text, currentOptions.stdinFilename, true) : engine.executeOnFiles(files); + const engine = new ESLint(translateOptions(options)); + let results; - if (currentOptions.fix) { - debug("Fix mode enabled - applying fixes"); - CLIEngine.outputFixes(report); - } + if (useStdin) { + results = await engine.lintText(text, { + filePath: options.stdinFilename, + warnIgnored: true + }); + } else { + results = await engine.lintFiles(files); + } - if (currentOptions.quiet) { - debug("Quiet mode enabled - filtering out warnings"); - report.results = CLIEngine.getErrorResults(report.results); - } + if (options.fix) { + debug("Fix mode enabled - applying fixes"); + await ESLint.outputFixes(results); + } - if (printResults(engine, report.results, currentOptions.format, currentOptions.outputFile)) { - const tooManyWarnings = currentOptions.maxWarnings >= 0 && report.warningCount > currentOptions.maxWarnings; + if (options.quiet) { + debug("Quiet mode enabled - filtering out warnings"); + results = ESLint.getErrorResults(results); + } - if (!report.errorCount && tooManyWarnings) { - log.error("ESLint found too many warnings (maximum: %s).", currentOptions.maxWarnings); - } + if (await printResults(engine, results, options.format, options.outputFile)) { + const { errorCount, warningCount } = countErrors(results); + const tooManyWarnings = + options.maxWarnings >= 0 && warningCount > options.maxWarnings; - return (report.errorCount || tooManyWarnings) ? 1 : 0; + if (!errorCount && tooManyWarnings) { + log.error( + "ESLint found too many warnings (maximum: %s).", + options.maxWarnings + ); } - return 2; + return (errorCount || tooManyWarnings) ? 1 : 0; } - return 0; + return 2; } }; diff --git a/tools/node_modules/eslint/lib/eslint/eslint.js b/tools/node_modules/eslint/lib/eslint/eslint.js new file mode 100644 index 00000000000000..d195aab09f1918 --- /dev/null +++ b/tools/node_modules/eslint/lib/eslint/eslint.js @@ -0,0 +1,656 @@ +/** + * @fileoverview Main API Class + * @author Kai Cataldo + * @author Toru Nagashima + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const path = require("path"); +const fs = require("fs"); +const { promisify } = require("util"); +const { CLIEngine, getCLIEngineInternalSlots } = require("../cli-engine/cli-engine"); +const BuiltinRules = require("../rules"); +const { getRuleSeverity } = require("../shared/config-ops"); +const { version } = require("../../package.json"); + +//------------------------------------------------------------------------------ +// Typedefs +//------------------------------------------------------------------------------ + +/** @typedef {import("../cli-engine/cli-engine").LintReport} CLIEngineLintReport */ +/** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */ +/** @typedef {import("../shared/types").ConfigData} ConfigData */ +/** @typedef {import("../shared/types").LintMessage} LintMessage */ +/** @typedef {import("../shared/types").Plugin} Plugin */ +/** @typedef {import("../shared/types").Rule} Rule */ +/** @typedef {import("./load-formatter").Formatter} Formatter */ + +/** + * The options with which to configure the ESLint instance. + * @typedef {Object} ESLintOptions + * @property {boolean} [allowInlineConfig] Enable or disable inline configuration comments. + * @property {ConfigData} [baseConfig] Base config object, extended by all configs used with this instance + * @property {boolean} [cache] Enable result caching. + * @property {string} [cacheLocation] The cache file to use instead of .eslintcache. + * @property {string} [cwd] The value to use for the current working directory. + * @property {boolean} [errorOnUnmatchedPattern] If `false` then `ESLint#lintFiles()` doesn't throw even if no target files found. Defaults to `true`. + * @property {string[]} [extensions] An array of file extensions to check. + * @property {boolean|Function} [fix] Execute in autofix mode. If a function, should return a boolean. + * @property {string[]} [fixTypes] Array of rule types to apply fixes for. + * @property {boolean} [globInputPaths] Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file. + * @property {boolean} [ignore] False disables use of .eslintignore. + * @property {string} [ignorePath] The ignore file to use instead of .eslintignore. + * @property {ConfigData} [overrideConfig] Override config object, overrides all configs used with this instance + * @property {string} [overrideConfigFile] The configuration file to use. + * @property {Record} [plugins] An array of plugin implementations. + * @property {"error" | "warn" | "off"} [reportUnusedDisableDirectives] the severity to report unused eslint-disable directives. + * @property {string} [resolvePluginsRelativeTo] The folder where plugins should be resolved from, defaulting to the CWD. + * @property {string[]} [rulePaths] An array of directories to load custom rules from. + * @property {boolean} [useEslintrc] False disables looking for .eslintrc.* files. + */ + +/** + * A rules metadata object. + * @typedef {Object} RulesMeta + * @property {string} id The plugin ID. + * @property {Object} definition The plugin definition. + */ + +/** + * A linting result. + * @typedef {Object} LintResult + * @property {string} filePath The path to the file that was linted. + * @property {LintMessage[]} messages All of the messages for the result. + * @property {number} errorCount Number of errors for the result. + * @property {number} warningCount Number of warnings for the result. + * @property {number} fixableErrorCount Number of fixable errors for the result. + * @property {number} fixableWarningCount Number of fixable warnings for the result. + * @property {string} [source] The source code of the file that was linted. + * @property {string} [output] The source code of the file that was linted, with as many fixes applied as possible. + * @property {DeprecatedRuleInfo[]} usedDeprecatedRules The list of used deprecated rules. + */ + +/** + * Private members for the `ESLint` instance. + * @typedef {Object} ESLintPrivateMembers + * @property {CLIEngine} cliEngine The wrapped CLIEngine instance. + * @property {ESLintOptions} options The options used to instantiate the ESLint instance. + */ + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +const writeFile = promisify(fs.writeFile); + +/** + * The map with which to store private class members. + * @type {WeakMap} + */ +const privateMembersMap = new WeakMap(); + +/** + * Check if a given value is a non-empty string or not. + * @param {any} x The value to check. + * @returns {boolean} `true` if `x` is a non-empty string. + */ +function isNonEmptyString(x) { + return typeof x === "string" && x.trim() !== ""; +} + +/** + * Check if a given value is an array of non-empty stringss or not. + * @param {any} x The value to check. + * @returns {boolean} `true` if `x` is an array of non-empty stringss. + */ +function isArrayOfNonEmptyString(x) { + return Array.isArray(x) && x.every(isNonEmptyString); +} + +/** + * Check if a given value is a valid fix type or not. + * @param {any} x The value to check. + * @returns {boolean} `true` if `x` is valid fix type. + */ +function isFixType(x) { + return x === "problem" || x === "suggestion" || x === "layout"; +} + +/** + * Check if a given value is an array of fix types or not. + * @param {any} x The value to check. + * @returns {boolean} `true` if `x` is an array of fix types. + */ +function isFixTypeArray(x) { + return Array.isArray(x) && x.every(isFixType); +} + +/** + * The error for invalid options. + */ +class ESLintInvalidOptionsError extends Error { + constructor(messages) { + super(`Invalid Options:\n- ${messages.join("\n- ")}`); + this.code = "ESLINT_INVALID_OPTIONS"; + Error.captureStackTrace(this, ESLintInvalidOptionsError); + } +} + +/** + * Validates and normalizes options for the wrapped CLIEngine instance. + * @param {ESLintOptions} options The options to process. + * @returns {ESLintOptions} The normalized options. + */ +function processOptions({ + allowInlineConfig = true, // ← we cannot use `overrideConfig.noInlineConfig` instead because `allowInlineConfig` has side-effect that suppress warnings that show inline configs are ignored. + baseConfig = null, + cache = false, + cacheLocation = ".eslintcache", + cwd = process.cwd(), + errorOnUnmatchedPattern = true, + extensions = null, // ← should be null by default because if it's an array then it suppresses RFC20 feature. + fix = false, + fixTypes = null, // ← should be null by default because if it's an array then it suppresses rules that don't have the `meta.type` property. + globInputPaths = true, + ignore = true, + ignorePath = null, // ← should be null by default because if it's a string then it may throw ENOENT. + overrideConfig = null, + overrideConfigFile = null, + plugins = {}, + reportUnusedDisableDirectives = null, // ← should be null by default because if it's a string then it overrides the 'reportUnusedDisableDirectives' setting in config files. And we cannot use `overrideConfig.reportUnusedDisableDirectives` instead because we cannot configure the `error` severity with that. + resolvePluginsRelativeTo = null, // ← should be null by default because if it's a string then it suppresses RFC47 feature. + rulePaths = [], + useEslintrc = true, + ...unknownOptions +}) { + const errors = []; + const unknownOptionKeys = Object.keys(unknownOptions); + + if (unknownOptionKeys.length >= 1) { + errors.push(`Unknown options: ${unknownOptionKeys.join(", ")}`); + if (unknownOptionKeys.includes("cacheFile")) { + errors.push("'cacheFile' has been removed. Please use the 'cacheLocation' option instead."); + } + if (unknownOptionKeys.includes("configFile")) { + errors.push("'configFile' has been removed. Please use the 'overrideConfigFile' option instead."); + } + if (unknownOptionKeys.includes("envs")) { + errors.push("'envs' has been removed. Please use the 'overrideConfig.env' option instead."); + } + if (unknownOptionKeys.includes("globals")) { + errors.push("'globals' has been removed. Please use the 'overrideConfig.globals' option instead."); + } + if (unknownOptionKeys.includes("ignorePattern")) { + errors.push("'ignorePattern' has been removed. Please use the 'overrideConfig.ignorePatterns' option instead."); + } + if (unknownOptionKeys.includes("parser")) { + errors.push("'parser' has been removed. Please use the 'overrideConfig.parser' option instead."); + } + if (unknownOptionKeys.includes("parserOptions")) { + errors.push("'parserOptions' has been removed. Please use the 'overrideConfig.parserOptions' option instead."); + } + if (unknownOptionKeys.includes("rules")) { + errors.push("'rules' has been removed. Please use the 'overrideConfig.rules' option instead."); + } + } + if (typeof allowInlineConfig !== "boolean") { + errors.push("'allowInlineConfig' must be a boolean."); + } + if (typeof baseConfig !== "object") { + errors.push("'baseConfig' must be an object or null."); + } + if (typeof cache !== "boolean") { + errors.push("'cache' must be a boolean."); + } + if (!isNonEmptyString(cacheLocation)) { + errors.push("'cacheLocation' must be a non-empty string."); + } + if (!isNonEmptyString(cwd) || !path.isAbsolute(cwd)) { + errors.push("'cwd' must be an absolute path."); + } + if (typeof errorOnUnmatchedPattern !== "boolean") { + errors.push("'errorOnUnmatchedPattern' must be a boolean."); + } + if (!isArrayOfNonEmptyString(extensions) && extensions !== null) { + errors.push("'extensions' must be an array of non-empty strings or null."); + } + if (typeof fix !== "boolean" && typeof fix !== "function") { + errors.push("'fix' must be a boolean or a function."); + } + if (fixTypes !== null && !isFixTypeArray(fixTypes)) { + errors.push("'fixTypes' must be an array of any of \"problem\", \"suggestion\", and \"layout\"."); + } + if (typeof globInputPaths !== "boolean") { + errors.push("'globInputPaths' must be a boolean."); + } + if (typeof ignore !== "boolean") { + errors.push("'ignore' must be a boolean."); + } + if (!isNonEmptyString(ignorePath) && ignorePath !== null) { + errors.push("'ignorePath' must be a non-empty string or null."); + } + if (typeof overrideConfig !== "object") { + errors.push("'overrideConfig' must be an object or null."); + } + if (!isNonEmptyString(overrideConfigFile) && overrideConfigFile !== null) { + errors.push("'overrideConfigFile' must be a non-empty string or null."); + } + if (typeof plugins !== "object") { + errors.push("'plugins' must be an object or null."); + } else if (plugins !== null && Object.keys(plugins).includes("")) { + errors.push("'plugins' must not include an empty string."); + } + if (Array.isArray(plugins)) { + errors.push("'plugins' doesn't add plugins to configuration to load. Please use the 'overrideConfig.plugins' option instead."); + } + if ( + reportUnusedDisableDirectives !== "error" && + reportUnusedDisableDirectives !== "warn" && + reportUnusedDisableDirectives !== "off" && + reportUnusedDisableDirectives !== null + ) { + errors.push("'reportUnusedDisableDirectives' must be any of \"error\", \"warn\", \"off\", and null."); + } + if ( + !isNonEmptyString(resolvePluginsRelativeTo) && + resolvePluginsRelativeTo !== null + ) { + errors.push("'resolvePluginsRelativeTo' must be a non-empty string or null."); + } + if (!isArrayOfNonEmptyString(rulePaths)) { + errors.push("'rulePaths' must be an array of non-empty strings."); + } + if (typeof useEslintrc !== "boolean") { + errors.push("'useElintrc' must be a boolean."); + } + + if (errors.length > 0) { + throw new ESLintInvalidOptionsError(errors); + } + + return { + allowInlineConfig, + baseConfig, + cache, + cacheLocation, + configFile: overrideConfigFile, + cwd, + errorOnUnmatchedPattern, + extensions, + fix, + fixTypes, + globInputPaths, + ignore, + ignorePath, + reportUnusedDisableDirectives, + resolvePluginsRelativeTo, + rulePaths, + useEslintrc + }; +} + +/** + * Check if a value has one or more properties and that value is not undefined. + * @param {any} obj The value to check. + * @returns {boolean} `true` if `obj` has one or more properties that that value is not undefined. + */ +function hasDefinedProperty(obj) { + if (typeof obj === "object" && obj !== null) { + for (const key in obj) { + if (typeof obj[key] !== "undefined") { + return true; + } + } + } + return false; +} + +/** + * Create rulesMeta object. + * @param {Map} rules a map of rules from which to generate the object. + * @returns {Object} metadata for all enabled rules. + */ +function createRulesMeta(rules) { + return Array.from(rules).reduce((retVal, [id, rule]) => { + retVal[id] = rule.meta; + return retVal; + }, {}); +} + +/** @type {WeakMap} */ +const usedDeprecatedRulesCache = new WeakMap(); + +/** + * Create used deprecated rule list. + * @param {CLIEngine} cliEngine The CLIEngine instance. + * @param {string} maybeFilePath The absolute path to a lint target file or `""`. + * @returns {DeprecatedRuleInfo[]} The used deprecated rule list. + */ +function getOrFindUsedDeprecatedRules(cliEngine, maybeFilePath) { + const { + configArrayFactory, + options: { cwd } + } = getCLIEngineInternalSlots(cliEngine); + const filePath = path.isAbsolute(maybeFilePath) + ? maybeFilePath + : path.join(cwd, "__placeholder__.js"); + const configArray = configArrayFactory.getConfigArrayForFile(filePath); + const config = configArray.extractConfig(filePath); + + // Most files use the same config, so cache it. + if (!usedDeprecatedRulesCache.has(config)) { + const pluginRules = configArray.pluginRules; + const retv = []; + + for (const [ruleId, ruleConf] of Object.entries(config.rules)) { + if (getRuleSeverity(ruleConf) === 0) { + continue; + } + const rule = pluginRules.get(ruleId) || BuiltinRules.get(ruleId); + const meta = rule && rule.meta; + + if (meta && meta.deprecated) { + retv.push({ ruleId, replacedBy: meta.replacedBy || [] }); + } + } + + usedDeprecatedRulesCache.set(config, Object.freeze(retv)); + } + + return usedDeprecatedRulesCache.get(config); +} + +/** + * Processes the linting results generated by a CLIEngine linting report to + * match the ESLint class's API. + * @param {CLIEngine} cliEngine The CLIEngine instance. + * @param {CLIEngineLintReport} report The CLIEngine linting report to process. + * @returns {LintResult[]} The processed linting results. + */ +function processCLIEngineLintReport(cliEngine, { results }) { + const descriptor = { + configurable: true, + enumerable: true, + get() { + return getOrFindUsedDeprecatedRules(cliEngine, this.filePath); + } + }; + + for (const result of results) { + Object.defineProperty(result, "usedDeprecatedRules", descriptor); + } + + return results; +} + +/** + * An Array.prototype.sort() compatible compare function to order results by their file path. + * @param {LintResult} a The first lint result. + * @param {LintResult} b The second lint result. + * @returns {number} An integer representing the order in which the two results should occur. + */ +function compareResultsByFilePath(a, b) { + if (a.filePath < b.filePath) { + return -1; + } + + if (a.filePath > b.filePath) { + return 1; + } + + return 0; +} + +class ESLint { + + /** + * Creates a new instance of the main ESLint API. + * @param {ESLintOptions} options The options for this instance. + */ + constructor(options = {}) { + const processedOptions = processOptions(options); + const cliEngine = new CLIEngine(processedOptions); + const { + additionalPluginPool, + configArrayFactory, + lastConfigArrays + } = getCLIEngineInternalSlots(cliEngine); + let updated = false; + + /* + * Address `plugins` to add plugin implementations. + * Operate the `additionalPluginPool` internal slot directly to avoid + * using `addPlugin(id, plugin)` method that resets cache everytime. + */ + if (options.plugins) { + for (const [id, plugin] of Object.entries(options.plugins)) { + additionalPluginPool.set(id, plugin); + updated = true; + } + } + + /* + * Address `overrideConfig` to set override config. + * Operate the `configArrayFactory` internal slot directly because this + * functionality doesn't exist as the public API of CLIEngine. + */ + if (hasDefinedProperty(options.overrideConfig)) { + configArrayFactory.setOverrideConfig(options.overrideConfig); + updated = true; + } + + // Update caches. + if (updated) { + configArrayFactory.clearCache(); + lastConfigArrays[0] = configArrayFactory.getConfigArrayForFile(); + } + + // Initialize private properties. + privateMembersMap.set(this, { + cliEngine, + options: processedOptions + }); + } + + /** + * The version text. + * @type {string} + */ + static get version() { + return version; + } + + /** + * Outputs fixes from the given results to files. + * @param {LintResult[]} results The lint results. + * @returns {Promise} Returns a promise that is used to track side effects. + */ + static async outputFixes(results) { + if (!Array.isArray(results)) { + throw new Error("'results' must be an array"); + } + + await Promise.all( + results + .filter(result => { + if (typeof result !== "object" || result === null) { + throw new Error("'results' must include only objects"); + } + return ( + typeof result.output === "string" && + path.isAbsolute(result.filePath) + ); + }) + .map(r => writeFile(r.filePath, r.output)) + ); + } + + /** + * Returns results that only contains errors. + * @param {LintResult[]} results The results to filter. + * @returns {LintResult[]} The filtered results. + */ + static getErrorResults(results) { + return CLIEngine.getErrorResults(results); + } + + /** + * Executes the current configuration on an array of file and directory names. + * @param {string[]} patterns An array of file and directory names. + * @returns {Promise} The results of linting the file patterns given. + */ + async lintFiles(patterns) { + if (!isNonEmptyString(patterns) && !isArrayOfNonEmptyString(patterns)) { + throw new Error("'patterns' must be a non-empty string or an array of non-empty strings"); + } + const { cliEngine } = privateMembersMap.get(this); + + return processCLIEngineLintReport( + cliEngine, + cliEngine.executeOnFiles(patterns) + ); + } + + /** + * Executes the current configuration on text. + * @param {string} code A string of JavaScript code to lint. + * @param {Object} [options] The options. + * @param {string} [options.filePath] The path to the file of the source code. + * @param {boolean} [options.warnIgnored] When set to true, warn if given filePath is an ignored path. + * @returns {Promise} The results of linting the string of code given. + */ + async lintText(code, options = {}) { + if (typeof code !== "string") { + throw new Error("'code' must be a string"); + } + if (typeof options !== "object") { + throw new Error("'options' must be an object, null, or undefined"); + } + const { + filePath, + warnIgnored = false, + ...unknownOptions + } = options || {}; + + for (const key of Object.keys(unknownOptions)) { + throw new Error(`'options' must not include the unknown option '${key}'`); + } + if (filePath !== void 0 && !isNonEmptyString(filePath)) { + throw new Error("'options.filePath' must be a non-empty string or undefined"); + } + if (typeof warnIgnored !== "boolean") { + throw new Error("'options.warnIgnored' must be a boolean or undefined"); + } + + const { cliEngine } = privateMembersMap.get(this); + + return processCLIEngineLintReport( + cliEngine, + cliEngine.executeOnText(code, filePath, warnIgnored) + ); + } + + /** + * Returns the formatter representing the given formatter name. + * @param {string} [name] The name of the formattter to load. + * The following values are allowed: + * - `undefined` ... Load `stylish` builtin formatter. + * - A builtin formatter name ... Load the builtin formatter. + * - A thirdparty formatter name: + * - `foo` → `eslint-formatter-foo` + * - `@foo` → `@foo/eslint-formatter` + * - `@foo/bar` → `@foo/eslint-formatter-bar` + * - A file path ... Load the file. + * @returns {Promise} A promise resolving to the formatter object. + * This promise will be rejected if the given formatter was not found or not + * a function. + */ + async loadFormatter(name = "stylish") { + if (typeof name !== "string") { + throw new Error("'name' must be a string"); + } + + const { cliEngine } = privateMembersMap.get(this); + const formatter = cliEngine.getFormatter(name); + + if (typeof formatter !== "function") { + throw new Error(`Formatter must be a function, but got a ${typeof formatter}.`); + } + + return { + + /** + * The main formatter method. + * @param {LintResults[]} results The lint results to format. + * @returns {string} The formatted lint results. + */ + format(results) { + let rulesMeta = null; + + results.sort(compareResultsByFilePath); + + return formatter(results, { + get rulesMeta() { + if (!rulesMeta) { + rulesMeta = createRulesMeta(cliEngine.getRules()); + } + + return rulesMeta; + } + }); + } + }; + } + + /** + * Returns a configuration object for the given file based on the CLI options. + * This is the same logic used by the ESLint CLI executable to determine + * configuration for each file it processes. + * @param {string} filePath The path of the file to retrieve a config object for. + * @returns {Promise} A configuration object for the file. + */ + async calculateConfigForFile(filePath) { + if (!isNonEmptyString(filePath)) { + throw new Error("'filePath' must be a non-empty string"); + } + const { cliEngine } = privateMembersMap.get(this); + + return cliEngine.getConfigForFile(filePath); + } + + /** + * Checks if a given path is ignored by ESLint. + * @param {string} filePath The path of the file to check. + * @returns {Promise} Whether or not the given path is ignored. + */ + async isPathIgnored(filePath) { + if (!isNonEmptyString(filePath)) { + throw new Error("'filePath' must be a non-empty string"); + } + const { cliEngine } = privateMembersMap.get(this); + + return cliEngine.isPathIgnored(filePath); + } +} + +//------------------------------------------------------------------------------ +// Public Interface +//------------------------------------------------------------------------------ + +module.exports = { + ESLint, + + /** + * Get the private class members of a given ESLint instance for tests. + * @param {ESLint} instance The ESLint instance to get. + * @returns {ESLintPrivateMembers} The instance's private class members. + */ + getESLintPrivateMembers(instance) { + return privateMembersMap.get(instance); + } +}; diff --git a/tools/node_modules/eslint/lib/eslint/index.js b/tools/node_modules/eslint/lib/eslint/index.js new file mode 100644 index 00000000000000..c9185ee0eba0a5 --- /dev/null +++ b/tools/node_modules/eslint/lib/eslint/index.js @@ -0,0 +1,7 @@ +"use strict"; + +const { ESLint } = require("./eslint"); + +module.exports = { + ESLint +}; diff --git a/tools/node_modules/eslint/lib/init/autoconfig.js b/tools/node_modules/eslint/lib/init/autoconfig.js index 64be3d2a84f49b..2b0aa12ac13df6 100644 --- a/tools/node_modules/eslint/lib/init/autoconfig.js +++ b/tools/node_modules/eslint/lib/init/autoconfig.js @@ -301,7 +301,7 @@ class Registry { ruleSetIdx += 1; if (cb) { - cb(totalFilesLinting); // eslint-disable-line callback-return + cb(totalFilesLinting); // eslint-disable-line node/callback-return } }); @@ -316,10 +316,10 @@ class Registry { /** * Extract rule configuration into eslint:recommended where possible. * - * This will return a new config with `"extends": "eslint:recommended"` and + * This will return a new config with `["extends": [ ..., "eslint:recommended"]` and * only the rules which have configurations different from the recommended config. * @param {Object} config config object - * @returns {Object} config object using `"extends": "eslint:recommended"` + * @returns {Object} config object using `"extends": ["eslint:recommended"]` */ function extendFromRecommended(config) { const newConfig = Object.assign({}, config); @@ -333,7 +333,7 @@ function extendFromRecommended(config) { delete newConfig.rules[ruleId]; } }); - newConfig.extends = RECOMMENDED_CONFIG_NAME; + newConfig.extends.unshift(RECOMMENDED_CONFIG_NAME); return newConfig; } diff --git a/tools/node_modules/eslint/lib/init/config-initializer.js b/tools/node_modules/eslint/lib/init/config-initializer.js index 28dfad194a7e6f..70f0a250ad1dd6 100644 --- a/tools/node_modules/eslint/lib/init/config-initializer.js +++ b/tools/node_modules/eslint/lib/init/config-initializer.js @@ -15,6 +15,7 @@ const util = require("util"), inquirer = require("inquirer"), ProgressBar = require("progress"), semver = require("semver"), + espree = require("espree"), recConfig = require("../../conf/eslint-recommended"), ConfigOps = require("../shared/config-ops"), log = require("../shared/logging"), @@ -31,8 +32,6 @@ const debug = require("debug")("eslint:config-initializer"); // Private //------------------------------------------------------------------------------ -const DEFAULT_ECMA_VERSION = 2018; - /* istanbul ignore next: hard to test fs function */ /** * Create .eslintrc file in the current working directory @@ -265,8 +264,7 @@ function processAnswers(answers) { extends: [] }; - // set the latest ECMAScript version - config.parserOptions.ecmaVersion = DEFAULT_ECMA_VERSION; + config.parserOptions.ecmaVersion = espree.latestEcmaVersion; config.env.es6 = true; config.globals = { Atomics: "readonly", diff --git a/tools/node_modules/eslint/lib/init/source-code-utils.js b/tools/node_modules/eslint/lib/init/source-code-utils.js index dfc170a65cf71b..dca6541d1ed328 100644 --- a/tools/node_modules/eslint/lib/init/source-code-utils.js +++ b/tools/node_modules/eslint/lib/init/source-code-utils.js @@ -23,7 +23,7 @@ const { CLIEngine } = require("../cli-engine"); * TODO1: Expose the API that enumerates target files. * TODO2: Extract the creation logic of `SourceCode` from `Linter` class. */ -const { getCLIEngineInternalSlots } = require("../cli-engine/cli-engine"); // eslint-disable-line no-restricted-modules +const { getCLIEngineInternalSlots } = require("../cli-engine/cli-engine"); // eslint-disable-line node/no-restricted-require const debug = require("debug")("eslint:source-code-utils"); @@ -97,7 +97,7 @@ function getSourceCodeOfFiles(patterns, options, callback) { sourceCodes[filename] = sourceCode; } if (callback) { - callback(filenames.length); // eslint-disable-line callback-return + callback(filenames.length); // eslint-disable-line node/callback-return } }); diff --git a/tools/node_modules/eslint/lib/options.js b/tools/node_modules/eslint/lib/options.js index 98dc04b6eb3968..1681f1dbd1d733 100644 --- a/tools/node_modules/eslint/lib/options.js +++ b/tools/node_modules/eslint/lib/options.js @@ -46,7 +46,6 @@ module.exports = optionator({ { option: "ext", type: "[String]", - default: ".js", description: "Specify JavaScript file extensions" }, { diff --git a/tools/node_modules/eslint/lib/rule-tester/rule-tester.js b/tools/node_modules/eslint/lib/rule-tester/rule-tester.js index 1c1737152c1b19..77df1def893ccc 100644 --- a/tools/node_modules/eslint/lib/rule-tester/rule-tester.js +++ b/tools/node_modules/eslint/lib/rule-tester/rule-tester.js @@ -563,7 +563,12 @@ class RuleTester { output = SourceCodeFixer.applyFixes(code, messages).output; const errorMessageInFix = linter.verify(output, config, filename).find(m => m.fatal); - assert(!errorMessageInFix, `A fatal parsing error occurred in autofix: ${errorMessageInFix && errorMessageInFix.message}`); + assert(!errorMessageInFix, [ + "A fatal parsing error occurred in autofix.", + `Error: ${errorMessageInFix && errorMessageInFix.message}`, + "Autofix output:", + output + ].join("\n")); } else { output = code; } diff --git a/tools/node_modules/eslint/lib/rules/array-callback-return.js b/tools/node_modules/eslint/lib/rules/array-callback-return.js index eb38965024f05d..62ba7b72d87257 100644 --- a/tools/node_modules/eslint/lib/rules/array-callback-return.js +++ b/tools/node_modules/eslint/lib/rules/array-callback-return.js @@ -29,22 +29,6 @@ function isReachable(segment) { return segment.reachable; } -/** - * Gets a readable location. - * - * - FunctionExpression -> the function name or `function` keyword. - * - ArrowFunctionExpression -> `=>` token. - * @param {ASTNode} node A function node to get. - * @param {SourceCode} sourceCode A source code to get tokens. - * @returns {ASTNode|Token} The node or the token of a location. - */ -function getLocation(node, sourceCode) { - if (node.type === "ArrowFunctionExpression") { - return sourceCode.getTokenBefore(node.body); - } - return node.id || node; -} - /** * Checks a given node is a MemberExpression node which has the specified name's * property. @@ -179,6 +163,7 @@ module.exports = { create(context) { const options = context.options[0] || { allowImplicit: false, checkForEach: false }; + const sourceCode = context.getSourceCode(); let funcInfo = { arrayMethodName: null, @@ -217,12 +202,12 @@ module.exports = { } if (messageId) { - let name = astUtils.getFunctionNameWithKind(funcInfo.node); + let name = astUtils.getFunctionNameWithKind(node); name = messageId === "expectedNoReturnValue" ? lodash.upperFirst(name) : name; context.report({ node, - loc: getLocation(node, context.getSourceCode()).loc.start, + loc: astUtils.getFunctionHeadLoc(node, sourceCode), messageId, data: { name } }); diff --git a/tools/node_modules/eslint/lib/rules/callback-return.js b/tools/node_modules/eslint/lib/rules/callback-return.js index c5263cde46b752..5df792d436341e 100644 --- a/tools/node_modules/eslint/lib/rules/callback-return.js +++ b/tools/node_modules/eslint/lib/rules/callback-return.js @@ -10,6 +10,10 @@ module.exports = { meta: { + deprecated: true, + + replacedBy: ["node/callback-return"], + type: "suggestion", docs: { diff --git a/tools/node_modules/eslint/lib/rules/comma-style.js b/tools/node_modules/eslint/lib/rules/comma-style.js index bc22f05dd3892c..f1a23d63b786a0 100644 --- a/tools/node_modules/eslint/lib/rules/comma-style.js +++ b/tools/node_modules/eslint/lib/rules/comma-style.js @@ -146,10 +146,7 @@ module.exports = { // lone comma context.report({ node: reportItem, - loc: { - line: commaToken.loc.end.line, - column: commaToken.loc.start.column - }, + loc: commaToken.loc, messageId: "unexpectedLineBeforeAndAfterComma", fix: getFixerFunction(styleType, previousItemToken, commaToken, currentItemToken) }); @@ -158,6 +155,7 @@ module.exports = { context.report({ node: reportItem, + loc: commaToken.loc, messageId: "expectedCommaFirst", fix: getFixerFunction(style, previousItemToken, commaToken, currentItemToken) }); @@ -166,10 +164,7 @@ module.exports = { context.report({ node: reportItem, - loc: { - line: commaToken.loc.end.line, - column: commaToken.loc.end.column - }, + loc: commaToken.loc, messageId: "expectedCommaLast", fix: getFixerFunction(style, previousItemToken, commaToken, currentItemToken) }); diff --git a/tools/node_modules/eslint/lib/rules/func-call-spacing.js b/tools/node_modules/eslint/lib/rules/func-call-spacing.js index e2edd4282da578..dccdd0a40c6d76 100644 --- a/tools/node_modules/eslint/lib/rules/func-call-spacing.js +++ b/tools/node_modules/eslint/lib/rules/func-call-spacing.js @@ -63,7 +63,8 @@ module.exports = { }, messages: { - unexpected: "Unexpected newline between function name and paren.", + unexpectedWhitespace: "Unexpected whitespace between function name and paren.", + unexpectedNewline: "Unexpected newline between function name and paren.", missing: "Missing space between function name and paren." } }, @@ -116,7 +117,7 @@ module.exports = { context.report({ node, loc: leftToken.loc.start, - messageId: "unexpected", + messageId: "unexpectedWhitespace", fix(fixer) { /* @@ -143,7 +144,7 @@ module.exports = { context.report({ node, loc: leftToken.loc.start, - messageId: "unexpected", + messageId: "unexpectedNewline", fix(fixer) { return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " "); } diff --git a/tools/node_modules/eslint/lib/rules/getter-return.js b/tools/node_modules/eslint/lib/rules/getter-return.js index e1468a5b19f88d..c54ebfb4ffb8cd 100644 --- a/tools/node_modules/eslint/lib/rules/getter-return.js +++ b/tools/node_modules/eslint/lib/rules/getter-return.js @@ -25,17 +25,6 @@ function isReachable(segment) { return segment.reachable; } -/** - * Gets a readable location. - * - * - FunctionExpression -> the function name or `function` keyword. - * @param {ASTNode} node A function node to get. - * @returns {ASTNode|Token} The node or the token of a location. - */ -function getId(node) { - return node.id || node; -} - //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -75,6 +64,7 @@ module.exports = { create(context) { const options = context.options[0] || { allowImplicit: false }; + const sourceCode = context.getSourceCode(); let funcInfo = { upper: null, @@ -99,7 +89,7 @@ module.exports = { ) { context.report({ node, - loc: getId(node).loc.start, + loc: astUtils.getFunctionHeadLoc(node, sourceCode), messageId: funcInfo.hasReturn ? "expectedAlways" : "expected", data: { name: astUtils.getFunctionNameWithKind(funcInfo.node) diff --git a/tools/node_modules/eslint/lib/rules/global-require.js b/tools/node_modules/eslint/lib/rules/global-require.js index 4af3a6a4669a79..9bd073b88546d6 100644 --- a/tools/node_modules/eslint/lib/rules/global-require.js +++ b/tools/node_modules/eslint/lib/rules/global-require.js @@ -48,6 +48,10 @@ function isShadowed(scope, node) { module.exports = { meta: { + deprecated: true, + + replacedBy: ["node/global-require"], + type: "suggestion", docs: { diff --git a/tools/node_modules/eslint/lib/rules/handle-callback-err.js b/tools/node_modules/eslint/lib/rules/handle-callback-err.js index 640946699e7bea..8ad63bbd53a77b 100644 --- a/tools/node_modules/eslint/lib/rules/handle-callback-err.js +++ b/tools/node_modules/eslint/lib/rules/handle-callback-err.js @@ -11,6 +11,10 @@ module.exports = { meta: { + deprecated: true, + + replacedBy: ["node/handle-callback-err"], + type: "suggestion", docs: { diff --git a/tools/node_modules/eslint/lib/rules/key-spacing.js b/tools/node_modules/eslint/lib/rules/key-spacing.js index c405043794c7d1..57abb00b06e8a4 100644 --- a/tools/node_modules/eslint/lib/rules/key-spacing.js +++ b/tools/node_modules/eslint/lib/rules/key-spacing.js @@ -45,7 +45,7 @@ function isSingleLine(node) { /** * Checks whether the properties on a single line. * @param {ASTNode[]} properties List of Property AST nodes. - * @returns {boolean} True if all properies is on a single line. + * @returns {boolean} True if all properties is on a single line. */ function isSingleLineProperties(properties) { const [firstProp] = properties, diff --git a/tools/node_modules/eslint/lib/rules/new-cap.js b/tools/node_modules/eslint/lib/rules/new-cap.js index 7cce968c5aed0e..0faf45efb92daf 100644 --- a/tools/node_modules/eslint/lib/rules/new-cap.js +++ b/tools/node_modules/eslint/lib/rules/new-cap.js @@ -235,7 +235,7 @@ module.exports = { callee = callee.property; } - context.report({ node, loc: callee.loc.start, messageId }); + context.report({ node, loc: callee.loc, messageId }); } //-------------------------------------------------------------------------- diff --git a/tools/node_modules/eslint/lib/rules/newline-per-chained-call.js b/tools/node_modules/eslint/lib/rules/newline-per-chained-call.js index 8ad88386c0f61d..4254fec185ef88 100644 --- a/tools/node_modules/eslint/lib/rules/newline-per-chained-call.js +++ b/tools/node_modules/eslint/lib/rules/newline-per-chained-call.js @@ -90,16 +90,19 @@ module.exports = { } if (depth > ignoreChainWithDepth && astUtils.isTokenOnSameLine(callee.object, callee.property)) { + const firstTokenAfterObject = sourceCode.getTokenAfter(callee.object, astUtils.isNotClosingParenToken); + context.report({ node: callee.property, - loc: callee.property.loc.start, + loc: { + start: firstTokenAfterObject.loc.start, + end: callee.loc.end + }, messageId: "expected", data: { callee: getPropertyText(callee) }, fix(fixer) { - const firstTokenAfterObject = sourceCode.getTokenAfter(callee.object, astUtils.isNotClosingParenToken); - return fixer.insertTextBefore(firstTokenAfterObject, "\n"); } }); diff --git a/tools/node_modules/eslint/lib/rules/no-buffer-constructor.js b/tools/node_modules/eslint/lib/rules/no-buffer-constructor.js index bf4c8891ad1adf..5dce047b92312e 100644 --- a/tools/node_modules/eslint/lib/rules/no-buffer-constructor.js +++ b/tools/node_modules/eslint/lib/rules/no-buffer-constructor.js @@ -10,6 +10,10 @@ module.exports = { meta: { + deprecated: true, + + replacedBy: ["node/no-deprecated-api"], + type: "problem", docs: { diff --git a/tools/node_modules/eslint/lib/rules/no-empty-function.js b/tools/node_modules/eslint/lib/rules/no-empty-function.js index c74321158b3464..c512f8cd5f4500 100644 --- a/tools/node_modules/eslint/lib/rules/no-empty-function.js +++ b/tools/node_modules/eslint/lib/rules/no-empty-function.js @@ -151,7 +151,7 @@ module.exports = { ) { context.report({ node, - loc: node.body.loc.start, + loc: node.body.loc, messageId: "unexpected", data: { name } }); diff --git a/tools/node_modules/eslint/lib/rules/no-extra-parens.js b/tools/node_modules/eslint/lib/rules/no-extra-parens.js index a3dd5bab699da3..7cbb7522ebedfa 100644 --- a/tools/node_modules/eslint/lib/rules/no-extra-parens.js +++ b/tools/node_modules/eslint/lib/rules/no-extra-parens.js @@ -560,7 +560,11 @@ module.exports = { tokensToIgnore.add(secondToken); } - if (hasExcessParens(node)) { + const hasExtraParens = node.parent.type === "ExportDefaultDeclaration" + ? hasExcessParensWithPrecedence(node, PRECEDENCE_OF_ASSIGNMENT_EXPR) + : hasExcessParens(node); + + if (hasExtraParens) { report(node); } } diff --git a/tools/node_modules/eslint/lib/rules/no-inner-declarations.js b/tools/node_modules/eslint/lib/rules/no-inner-declarations.js index e1c29e0a3b4f3f..0768bc61149cec 100644 --- a/tools/node_modules/eslint/lib/rules/no-inner-declarations.js +++ b/tools/node_modules/eslint/lib/rules/no-inner-declarations.js @@ -5,10 +5,19 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("./utils/ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ +const validParent = new Set(["Program", "ExportNamedDeclaration", "ExportDefaultDeclaration"]); +const validBlockStatementParent = new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"]); + module.exports = { meta: { type: "problem", @@ -33,54 +42,37 @@ module.exports = { create(context) { - /** - * Find the nearest Program or Function ancestor node. - * @returns {Object} Ancestor's type and distance from node. - */ - function nearestBody() { - const ancestors = context.getAncestors(); - let ancestor = ancestors.pop(), - generation = 1; - - while (ancestor && ["Program", "FunctionDeclaration", - "FunctionExpression", "ArrowFunctionExpression" - ].indexOf(ancestor.type) < 0) { - generation += 1; - ancestor = ancestors.pop(); - } - - return { - - // Type of containing ancestor - type: ancestor.type, - - // Separation between ancestor and node - distance: generation - }; - } - /** * Ensure that a given node is at a program or function body's root. * @param {ASTNode} node Declaration node to check. * @returns {void} */ function check(node) { - const body = nearestBody(), - valid = ((body.type === "Program" && body.distance === 1) || - body.distance === 2); - - if (!valid) { - context.report({ - node, - messageId: "moveDeclToRoot", - data: { - type: (node.type === "FunctionDeclaration" ? "function" : "variable"), - body: (body.type === "Program" ? "program" : "function body") - } - }); + const parent = node.parent; + + if ( + parent.type === "BlockStatement" && validBlockStatementParent.has(parent.parent.type) + ) { + return; + } + + if (validParent.has(parent.type)) { + return; } + + const upperFunction = astUtils.getUpperFunction(parent); + + context.report({ + node, + messageId: "moveDeclToRoot", + data: { + type: (node.type === "FunctionDeclaration" ? "function" : "variable"), + body: (upperFunction === null ? "program" : "function body") + } + }); } + return { FunctionDeclaration: check, diff --git a/tools/node_modules/eslint/lib/rules/no-lone-blocks.js b/tools/node_modules/eslint/lib/rules/no-lone-blocks.js index d7069887b8e460..290784b82ea2fb 100644 --- a/tools/node_modules/eslint/lib/rules/no-lone-blocks.js +++ b/tools/node_modules/eslint/lib/rules/no-lone-blocks.js @@ -49,7 +49,7 @@ module.exports = { } /** - * Checks for any ocurrence of a BlockStatement in a place where lists of statements can appear + * Checks for any occurrence of a BlockStatement in a place where lists of statements can appear * @param {ASTNode} node The node to check * @returns {boolean} True if the node is a lone block. */ diff --git a/tools/node_modules/eslint/lib/rules/no-mixed-requires.js b/tools/node_modules/eslint/lib/rules/no-mixed-requires.js index 8e988e32c24f84..bfe9b7aa97858a 100644 --- a/tools/node_modules/eslint/lib/rules/no-mixed-requires.js +++ b/tools/node_modules/eslint/lib/rules/no-mixed-requires.js @@ -11,6 +11,10 @@ module.exports = { meta: { + deprecated: true, + + replacedBy: ["node/no-mixed-requires"], + type: "suggestion", docs: { diff --git a/tools/node_modules/eslint/lib/rules/no-new-object.js b/tools/node_modules/eslint/lib/rules/no-new-object.js index f3e99c9bd13502..e9f915db5eaa91 100644 --- a/tools/node_modules/eslint/lib/rules/no-new-object.js +++ b/tools/node_modules/eslint/lib/rules/no-new-object.js @@ -5,6 +5,12 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("./utils/ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -28,10 +34,17 @@ module.exports = { }, create(context) { - return { - NewExpression(node) { + const variable = astUtils.getVariableByName( + context.getScope(), + node.callee.name + ); + + if (variable && variable.identifiers.length > 0) { + return; + } + if (node.callee.name === "Object") { context.report({ node, @@ -40,6 +53,5 @@ module.exports = { } } }; - } }; diff --git a/tools/node_modules/eslint/lib/rules/no-new-require.js b/tools/node_modules/eslint/lib/rules/no-new-require.js index df12a424e3527e..7f81e83fd782c3 100644 --- a/tools/node_modules/eslint/lib/rules/no-new-require.js +++ b/tools/node_modules/eslint/lib/rules/no-new-require.js @@ -11,6 +11,10 @@ module.exports = { meta: { + deprecated: true, + + replacedBy: ["node/no-new-require"], + type: "suggestion", docs: { diff --git a/tools/node_modules/eslint/lib/rules/no-path-concat.js b/tools/node_modules/eslint/lib/rules/no-path-concat.js index 9fa8b852fe8358..77a03a7f952b04 100644 --- a/tools/node_modules/eslint/lib/rules/no-path-concat.js +++ b/tools/node_modules/eslint/lib/rules/no-path-concat.js @@ -10,6 +10,10 @@ module.exports = { meta: { + deprecated: true, + + replacedBy: ["node/no-path-concat"], + type: "suggestion", docs: { diff --git a/tools/node_modules/eslint/lib/rules/no-process-env.js b/tools/node_modules/eslint/lib/rules/no-process-env.js index 0f8d7f8a339d0e..24bb9f9971d5c9 100644 --- a/tools/node_modules/eslint/lib/rules/no-process-env.js +++ b/tools/node_modules/eslint/lib/rules/no-process-env.js @@ -10,6 +10,10 @@ module.exports = { meta: { + deprecated: true, + + replacedBy: ["node/no-process-env"], + type: "suggestion", docs: { diff --git a/tools/node_modules/eslint/lib/rules/no-process-exit.js b/tools/node_modules/eslint/lib/rules/no-process-exit.js index 29871660cc6ee1..9c70ea8808b4c4 100644 --- a/tools/node_modules/eslint/lib/rules/no-process-exit.js +++ b/tools/node_modules/eslint/lib/rules/no-process-exit.js @@ -10,6 +10,10 @@ module.exports = { meta: { + deprecated: true, + + replacedBy: ["node/no-process-exit"], + type: "suggestion", docs: { diff --git a/tools/node_modules/eslint/lib/rules/no-restricted-modules.js b/tools/node_modules/eslint/lib/rules/no-restricted-modules.js index abd8d5cbe29381..61834ceeb444d3 100644 --- a/tools/node_modules/eslint/lib/rules/no-restricted-modules.js +++ b/tools/node_modules/eslint/lib/rules/no-restricted-modules.js @@ -40,6 +40,10 @@ const arrayOfStringsOrObjects = { module.exports = { meta: { + deprecated: true, + + replacedBy: ["node/no-restricted-require"], + type: "suggestion", docs: { diff --git a/tools/node_modules/eslint/lib/rules/no-sync.js b/tools/node_modules/eslint/lib/rules/no-sync.js index d8111059631734..9790d1f94bb20c 100644 --- a/tools/node_modules/eslint/lib/rules/no-sync.js +++ b/tools/node_modules/eslint/lib/rules/no-sync.js @@ -13,6 +13,10 @@ module.exports = { meta: { + deprecated: true, + + replacedBy: ["node/no-sync"], + type: "suggestion", docs: { diff --git a/tools/node_modules/eslint/lib/rules/no-unexpected-multiline.js b/tools/node_modules/eslint/lib/rules/no-unexpected-multiline.js index eb72008a2947e7..b5ec20de4b20a3 100644 --- a/tools/node_modules/eslint/lib/rules/no-unexpected-multiline.js +++ b/tools/node_modules/eslint/lib/rules/no-unexpected-multiline.js @@ -53,7 +53,11 @@ module.exports = { const nodeExpressionEnd = sourceCode.getTokenBefore(openParen); if (openParen.loc.start.line !== nodeExpressionEnd.loc.end.line) { - context.report({ node, loc: openParen.loc.start, messageId, data: { char: openParen.value } }); + context.report({ + node, + loc: openParen.loc, + messageId + }); } } @@ -71,18 +75,24 @@ module.exports = { }, TaggedTemplateExpression(node) { - if (node.tag.loc.end.line === node.quasi.loc.start.line) { - return; - } - - // handle generics type parameters on template tags - const tokenBefore = sourceCode.getTokenBefore(node.quasi); - - if (tokenBefore.loc.end.line === node.quasi.loc.start.line) { - return; + const { quasi } = node; + + // handles common tags, parenthesized tags, and typescript's generic type arguments + const tokenBefore = sourceCode.getTokenBefore(quasi); + + if (tokenBefore.loc.end.line !== quasi.loc.start.line) { + context.report({ + node, + loc: { + start: quasi.loc.start, + end: { + line: quasi.loc.start.line, + column: quasi.loc.start.column + 1 + } + }, + messageId: "taggedTemplate" + }); } - - context.report({ node, loc: node.loc.start, messageId: "taggedTemplate" }); }, CallExpression(node) { diff --git a/tools/node_modules/eslint/lib/rules/no-useless-concat.js b/tools/node_modules/eslint/lib/rules/no-useless-concat.js index aa46742abdd5ca..cfc60c8fb51a24 100644 --- a/tools/node_modules/eslint/lib/rules/no-useless-concat.js +++ b/tools/node_modules/eslint/lib/rules/no-useless-concat.js @@ -105,7 +105,7 @@ module.exports = { context.report({ node, - loc: operatorToken.loc.start, + loc: operatorToken.loc, messageId: "unexpectedConcat" }); } diff --git a/tools/node_modules/eslint/lib/rules/space-before-function-paren.js b/tools/node_modules/eslint/lib/rules/space-before-function-paren.js index af609c2e7c72fa..1021a110cfd3f0 100644 --- a/tools/node_modules/eslint/lib/rules/space-before-function-paren.js +++ b/tools/node_modules/eslint/lib/rules/space-before-function-paren.js @@ -127,7 +127,10 @@ module.exports = { if (hasSpacing && functionConfig === "never") { context.report({ node, - loc: leftToken.loc.end, + loc: { + start: leftToken.loc.end, + end: rightToken.loc.start + }, messageId: "unexpectedSpace", fix(fixer) { const comments = sourceCode.getCommentsBefore(rightToken); @@ -145,7 +148,7 @@ module.exports = { } else if (!hasSpacing && functionConfig === "always") { context.report({ node, - loc: leftToken.loc.end, + loc: rightToken.loc, messageId: "missingSpace", fix: fixer => fixer.insertTextAfter(leftToken, " ") }); diff --git a/tools/node_modules/eslint/lib/rules/yoda.js b/tools/node_modules/eslint/lib/rules/yoda.js index c4ff3f81938595..f1159e5255df79 100644 --- a/tools/node_modules/eslint/lib/rules/yoda.js +++ b/tools/node_modules/eslint/lib/rules/yoda.js @@ -20,7 +20,7 @@ const astUtils = require("./utils/ast-utils"); * @returns {boolean} Whether or not it is a comparison operator. */ function isComparisonOperator(operator) { - return (/^(==|===|!=|!==|<|>|<=|>=)$/u).test(operator); + return /^(==|===|!=|!==|<|>|<=|>=)$/u.test(operator); } /** @@ -29,7 +29,7 @@ function isComparisonOperator(operator) { * @returns {boolean} Whether or not it is an equality operator. */ function isEqualityOperator(operator) { - return (/^(==|===)$/u).test(operator); + return /^(==|===)$/u.test(operator); } /** @@ -50,10 +50,12 @@ function isRangeTestOperator(operator) { * real literal and should be treated as such. */ function isNegativeNumericLiteral(node) { - return (node.type === "UnaryExpression" && + return ( + node.type === "UnaryExpression" && node.operator === "-" && node.prefix && - astUtils.isNumericLiteral(node.argument)); + astUtils.isNumericLiteral(node.argument) + ); } /** @@ -71,25 +73,21 @@ function isStaticTemplateLiteral(node) { * @returns {boolean} True if the node should be treated as a single Literal node. */ function looksLikeLiteral(node) { - return isNegativeNumericLiteral(node) || - isStaticTemplateLiteral(node); + return isNegativeNumericLiteral(node) || isStaticTemplateLiteral(node); } /** * Attempts to derive a Literal node from nodes that are treated like literals. * @param {ASTNode} node Node to normalize. - * @param {number} [defaultValue] The default value to be returned if the node - * is not a Literal. * @returns {ASTNode} One of the following options. * 1. The original node if the node is already a Literal * 2. A normalized Literal node with the negative number as the value if the * node represents a negative number literal. * 3. A normalized Literal node with the string as the value if the node is * a Template Literal without expression. - * 4. The Literal node which has the `defaultValue` argument if it exists. - * 5. Otherwise `null`. + * 4. Otherwise `null`. */ -function getNormalizedLiteral(node, defaultValue) { +function getNormalizedLiteral(node) { if (node.type === "Literal") { return node; } @@ -110,14 +108,6 @@ function getNormalizedLiteral(node, defaultValue) { }; } - if (defaultValue) { - return { - type: "Literal", - value: defaultValue, - raw: String(defaultValue) - }; - } - return null; } @@ -183,7 +173,7 @@ module.exports = { type: "suggestion", docs: { - description: "require or disallow \"Yoda\" conditions", + description: 'require or disallow "Yoda" conditions', category: "Best Practices", recommended: false, url: "https://eslint.org/docs/rules/yoda" @@ -211,16 +201,19 @@ module.exports = { fixable: "code", messages: { - expected: "Expected literal to be on the {{expectedSide}} side of {{operator}}." + expected: + "Expected literal to be on the {{expectedSide}} side of {{operator}}." } }, create(context) { // Default to "never" (!always) if no option - const always = (context.options[0] === "always"); - const exceptRange = (context.options[1] && context.options[1].exceptRange); - const onlyEquality = (context.options[1] && context.options[1].onlyEquality); + const always = context.options[0] === "always"; + const exceptRange = + context.options[1] && context.options[1].exceptRange; + const onlyEquality = + context.options[1] && context.options[1].onlyEquality; const sourceCode = context.getSourceCode(); @@ -243,13 +236,23 @@ module.exports = { * @returns {boolean} Whether node is a "between" range test. */ function isBetweenTest() { - let leftLiteral, rightLiteral; + if (node.operator === "&&" && same(left.right, right.left)) { + const leftLiteral = getNormalizedLiteral(left.left); + const rightLiteral = getNormalizedLiteral(right.right); + + if (leftLiteral === null && rightLiteral === null) { + return false; + } - return (node.operator === "&&" && - (leftLiteral = getNormalizedLiteral(left.left)) && - (rightLiteral = getNormalizedLiteral(right.right, Number.POSITIVE_INFINITY)) && - leftLiteral.value <= rightLiteral.value && - same(left.right, right.left)); + if (rightLiteral === null || leftLiteral === null) { + return true; + } + + if (leftLiteral.value <= rightLiteral.value) { + return true; + } + } + return false; } /** @@ -257,13 +260,24 @@ module.exports = { * @returns {boolean} Whether node is an "outside" range test. */ function isOutsideTest() { - let leftLiteral, rightLiteral; + if (node.operator === "||" && same(left.left, right.right)) { + const leftLiteral = getNormalizedLiteral(left.right); + const rightLiteral = getNormalizedLiteral(right.left); + + if (leftLiteral === null && rightLiteral === null) { + return false; + } + + if (rightLiteral === null || leftLiteral === null) { + return true; + } + + if (leftLiteral.value <= rightLiteral.value) { + return true; + } + } - return (node.operator === "||" && - (leftLiteral = getNormalizedLiteral(left.right, Number.NEGATIVE_INFINITY)) && - (rightLiteral = getNormalizedLiteral(right.left)) && - leftLiteral.value <= rightLiteral.value && - same(left.left, right.right)); + return false; } /** @@ -276,13 +290,15 @@ module.exports = { return astUtils.isParenthesised(sourceCode, node); } - return (node.type === "LogicalExpression" && + return ( + node.type === "LogicalExpression" && left.type === "BinaryExpression" && right.type === "BinaryExpression" && isRangeTestOperator(left.operator) && isRangeTestOperator(right.operator) && (isBetweenTest() || isOutsideTest()) && - isParenWrapped()); + isParenWrapped() + ); } const OPERATOR_FLIP_MAP = { @@ -303,21 +319,52 @@ module.exports = { */ function getFlippedString(node) { const tokenBefore = sourceCode.getTokenBefore(node); - const operatorToken = sourceCode.getFirstTokenBetween(node.left, node.right, token => token.value === node.operator); - const textBeforeOperator = sourceCode.getText().slice(sourceCode.getTokenBefore(operatorToken).range[1], operatorToken.range[0]); - const textAfterOperator = sourceCode.getText().slice(operatorToken.range[1], sourceCode.getTokenAfter(operatorToken).range[0]); - const leftText = sourceCode.getText().slice(node.range[0], sourceCode.getTokenBefore(operatorToken).range[1]); + const operatorToken = sourceCode.getFirstTokenBetween( + node.left, + node.right, + token => token.value === node.operator + ); + const textBeforeOperator = sourceCode + .getText() + .slice( + sourceCode.getTokenBefore(operatorToken).range[1], + operatorToken.range[0] + ); + const textAfterOperator = sourceCode + .getText() + .slice( + operatorToken.range[1], + sourceCode.getTokenAfter(operatorToken).range[0] + ); + const leftText = sourceCode + .getText() + .slice( + node.range[0], + sourceCode.getTokenBefore(operatorToken).range[1] + ); const firstRightToken = sourceCode.getTokenAfter(operatorToken); - const rightText = sourceCode.getText().slice(firstRightToken.range[0], node.range[1]); + const rightText = sourceCode + .getText() + .slice(firstRightToken.range[0], node.range[1]); let prefix = ""; - if (tokenBefore && tokenBefore.range[1] === node.range[0] && - !astUtils.canTokensBeAdjacent(tokenBefore, firstRightToken)) { + if ( + tokenBefore && + tokenBefore.range[1] === node.range[0] && + !astUtils.canTokensBeAdjacent(tokenBefore, firstRightToken) + ) { prefix = " "; } - return prefix + rightText + textBeforeOperator + OPERATOR_FLIP_MAP[operatorToken.value] + textAfterOperator + leftText; + return ( + prefix + + rightText + + textBeforeOperator + + OPERATOR_FLIP_MAP[operatorToken.value] + + textAfterOperator + + leftText + ); } //-------------------------------------------------------------------------- @@ -331,8 +378,12 @@ module.exports = { // If `expectedLiteral` is not a literal, and `expectedNonLiteral` is a literal, raise an error. if ( - (expectedNonLiteral.type === "Literal" || looksLikeLiteral(expectedNonLiteral)) && - !(expectedLiteral.type === "Literal" || looksLikeLiteral(expectedLiteral)) && + (expectedNonLiteral.type === "Literal" || + looksLikeLiteral(expectedNonLiteral)) && + !( + expectedLiteral.type === "Literal" || + looksLikeLiteral(expectedLiteral) + ) && !(!isEqualityOperator(node.operator) && onlyEquality) && isComparisonOperator(node.operator) && !(exceptRange && isRangeTest(context.getAncestors().pop())) @@ -344,12 +395,11 @@ module.exports = { operator: node.operator, expectedSide: always ? "left" : "right" }, - fix: fixer => fixer.replaceText(node, getFlippedString(node)) + fix: fixer => + fixer.replaceText(node, getFlippedString(node)) }); } - } }; - } }; diff --git a/tools/node_modules/eslint/lib/shared/relative-module-resolver.js b/tools/node_modules/eslint/lib/shared/relative-module-resolver.js index fa6cca72361df5..80335c5cfca7c8 100644 --- a/tools/node_modules/eslint/lib/shared/relative-module-resolver.js +++ b/tools/node_modules/eslint/lib/shared/relative-module-resolver.js @@ -11,6 +11,7 @@ const Module = require("module"); * `Module.createRequire` is added in v12.2.0. It supports URL as well. * We only support the case where the argument is a filepath, not a URL. */ +// eslint-disable-next-line node/no-unsupported-features/node-builtins, node/no-deprecated-api const createRequire = Module.createRequire || Module.createRequireFromPath; module.exports = { diff --git a/tools/node_modules/eslint/lib/shared/types.js b/tools/node_modules/eslint/lib/shared/types.js index bf37327fa240ca..bbd95d1b37862f 100644 --- a/tools/node_modules/eslint/lib/shared/types.js +++ b/tools/node_modules/eslint/lib/shared/types.js @@ -141,3 +141,10 @@ module.exports = {}; * @property {Record} [processors] The definition of plugin processors. * @property {Record} [rules] The definition of plugin rules. */ + +/** + * Information of deprecated rules. + * @typedef {Object} DeprecatedRuleInfo + * @property {string} ruleId The rule ID. + * @property {string[]} replacedBy The rule IDs that replace this deprecated rule. + */ diff --git a/tools/node_modules/eslint/node_modules/@babel/helper-validator-identifier/lib/identifier.js b/tools/node_modules/eslint/node_modules/@babel/helper-validator-identifier/lib/identifier.js index 92043ce6630710..51ec76370ccfc6 100644 --- a/tools/node_modules/eslint/node_modules/@babel/helper-validator-identifier/lib/identifier.js +++ b/tools/node_modules/eslint/node_modules/@babel/helper-validator-identifier/lib/identifier.js @@ -73,5 +73,5 @@ function isIdentifierName(name) { } } - return true; + return !isFirst; } \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/@babel/helper-validator-identifier/package.json b/tools/node_modules/eslint/node_modules/@babel/helper-validator-identifier/package.json index bdc69e6c6f8926..da8c4e12d40ff7 100644 --- a/tools/node_modules/eslint/node_modules/@babel/helper-validator-identifier/package.json +++ b/tools/node_modules/eslint/node_modules/@babel/helper-validator-identifier/package.json @@ -7,7 +7,7 @@ "unicode-13.0.0": "^0.8.0" }, "exports": "./lib/index.js", - "gitHead": "8d5e422be27251cfaadf8dd2536b31b4a5024b02", + "gitHead": "5b97e77e030cf3853a147fdff81844ea4026219d", "license": "MIT", "main": "./lib/index.js", "name": "@babel/helper-validator-identifier", @@ -18,5 +18,5 @@ "type": "git", "url": "https://github.com/babel/babel/tree/master/packages/babel-helper-validator-identifier" }, - "version": "7.9.0" + "version": "7.9.5" } \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/ajv/README.md b/tools/node_modules/eslint/node_modules/ajv/README.md index 9bd1f571872a26..e13fdec2939c92 100644 --- a/tools/node_modules/eslint/node_modules/ajv/README.md +++ b/tools/node_modules/eslint/node_modules/ajv/README.md @@ -8,8 +8,49 @@ The fastest JSON Schema validator for Node.js and browser. Supports draft-04/06/ [![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv) [![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv) [![Coverage Status](https://coveralls.io/repos/epoberezkin/ajv/badge.svg?branch=master&service=github)](https://coveralls.io/github/epoberezkin/ajv?branch=master) -[![Greenkeeper badge](https://badges.greenkeeper.io/epoberezkin/ajv.svg)](https://greenkeeper.io/) [![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv) +[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin) + +## Please [sponsor Ajv](https://github.com/sponsors/epoberezkin) + +Dear Ajv users! ❤️ + +I ask you to support the development of Ajv with donations. 🙏 + +Since 2015 Ajv has become widely used, thanks to your help and contributions: + +- **90** contributors 🏗 +- **5,000** dependent npm packages ⚙️ +- **7,000** github stars, from GitHub users [all over the world](https://www.google.com/maps/d/u/0/viewer?mid=1MGRV8ciFUGIbO1l0EKFWNJGYE7iSkDxP&ll=-3.81666561775622e-14%2C4.821737100000007&z=2) ⭐️ +- **5,000,000** dependent repositories on GitHub 🚀 +- **120,000,000** npm downloads per month! 💯 + +Your donations will fund futher development - small and large improvements, support of the next versions of JSON Schema specification, and, possibly, the code should be migrated to TypeScript to make it more maintainable. + +I will greatly appreciate anything you can help with to make it happen: + +- a **personal** donation - from $2 ☕️ +- your **company** donation - from $10 🍔 +- a **sponsorship** to get promoted on Ajv or related packages - from $50 💰 +- an **introduction** to a sponsor who would benefit from the promotion on Ajv page 🤝 + +| Please [make donations via my GitHub sponsors page](https://github.com/sponsors/epoberezkin)
‼️ **GitHub will DOUBLE them** ‼️ | +|---| + +#### Open Collective sponsors + + + + + + + + + + + + + ## Using version 6 @@ -273,7 +314,7 @@ The following formats are implemented for string validation with "format" keywor __Please note__: JSON Schema draft-07 also defines formats `iri`, `iri-reference`, `idn-hostname` and `idn-email` for URLs, hostnames and emails with international characters. Ajv does not implement these formats. If you create Ajv plugin that implements them please make a PR to mention this plugin here. -There are two modes of format validation: `fast` and `full`. This mode affects formats `date`, `time`, `date-time`, `uri`, `uri-reference`, `email`, and `hostname`. See [Options](#options) for details. +There are two modes of format validation: `fast` and `full`. This mode affects formats `date`, `time`, `date-time`, `uri`, `uri-reference`, and `email`. See [Options](#options) for details. You can add additional formats and replace any of the formats above using [addFormat](#api-addformat) method. @@ -1340,7 +1381,7 @@ If you have published a useful plugin please submit a PR to add it to the next s - [ajv-keywords](https://github.com/epoberezkin/ajv-keywords) - plugin with custom validation keywords (select, typeof, etc.) - [ajv-merge-patch](https://github.com/epoberezkin/ajv-merge-patch) - plugin with keywords $merge and $patch - [ajv-pack](https://github.com/epoberezkin/ajv-pack) - produces a compact module exporting validation functions - +- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - format validators for draft2019 that aren't already included in ajv (ie. `idn-hostname`, `idn-email`, `iri`, `iri-reference` and `duration`). ## Some packages using Ajv diff --git a/tools/node_modules/eslint/node_modules/ajv/dist/ajv.min.js b/tools/node_modules/eslint/node_modules/ajv/dist/ajv.min.js index 157af21a92cda5..1c72a75ecfc321 100644 --- a/tools/node_modules/eslint/node_modules/ajv/dist/ajv.min.js +++ b/tools/node_modules/eslint/node_modules/ajv/dist/ajv.min.js @@ -1,3 +1,3 @@ -/* ajv 6.12.0: Another JSON Schema Validator */ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Ajv=e()}}(function(){return function o(i,n,l){function c(r,e){if(!n[r]){if(!i[r]){var t="function"==typeof require&&require;if(!e&&t)return t(r,!0);if(u)return u(r,!0);var a=new Error("Cannot find module '"+r+"'");throw a.code="MODULE_NOT_FOUND",a}var s=n[r]={exports:{}};i[r][0].call(s.exports,function(e){return c(i[r][1][e]||e)},s,s.exports,o,i,n,l)}return n[r].exports}for(var u="function"==typeof require&&require,e=0;e%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i,u=/^(?:(?:http[s\u017F]?|ftp):\/\/)(?:(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+(?::(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?@)?(?:(?!10(?:\.[0-9]{1,3}){3})(?!127(?:\.[0-9]{1,3}){3})(?!169\.254(?:\.[0-9]{1,3}){2})(?!192\.168(?:\.[0-9]{1,3}){2})(?!172\.(?:1[6-9]|2[0-9]|3[01])(?:\.[0-9]{1,3}){2})(?:[1-9][0-9]?|1[0-9][0-9]|2[01][0-9]|22[0-3])(?:\.(?:1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])){2}(?:\.(?:[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-4]))|(?:(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)(?:\.(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)*(?:\.(?:(?:[KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){2,})))(?::[0-9]{2,5})?(?:\/(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?$/i,h=/^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i,d=/^(?:\/(?:[^~/]|~0|~1)*)*$/,f=/^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i,p=/^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/;function m(e){return a.copy(m[e="full"==e?"full":"fast"])}function v(e){var r=e.match(o);if(!r)return!1;var t,a=+r[2],s=+r[3];return 1<=a&&a<=12&&1<=s&&s<=(2!=a||((t=+r[1])%4!=0||t%100==0&&t%400!=0)?i[a]:29)}function y(e,r){var t=e.match(n);if(!t)return!1;var a=t[1],s=t[2],o=t[3];return(a<=23&&s<=59&&o<=59||23==a&&59==s&&60==o)&&(!r||t[5])}(r.exports=m).fast={date:/^\d\d\d\d-[0-1]\d-[0-3]\d$/,time:/^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)?$/i,"date-time":/^\d\d\d\d-[0-1]\d-[0-3]\d[t\s](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)$/i,uri:/^(?:[a-z][a-z0-9+-.]*:)(?:\/?\/)?[^\s]*$/i,"uri-reference":/^(?:(?:[a-z][a-z0-9+-.]*:)?\/?\/)?(?:[^\\\s#][^\s#]*)?(?:#[^\\\s]*)?$/i,"uri-template":c,url:u,email:/^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i,hostname:s,ipv4:/^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,ipv6:/^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,regex:w,uuid:h,"json-pointer":d,"json-pointer-uri-fragment":f,"relative-json-pointer":p},m.full={date:v,time:y,"date-time":function(e){var r=e.split(g);return 2==r.length&&v(r[0])&&y(r[1],!0)},uri:function(e){return P.test(e)&&l.test(e)},"uri-reference":/^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i,"uri-template":c,url:u,email:/^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,hostname:s,ipv4:/^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,ipv6:/^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,regex:w,uuid:h,"json-pointer":d,"json-pointer-uri-fragment":f,"relative-json-pointer":p};var g=/t|\s/i;var P=/\/|:/;var E=/[^\\]\\Z/;function w(e){if(E.test(e))return!1;try{return new RegExp(e),!0}catch(e){return!1}}},{"./util":10}],5:[function(e,r,t){"use strict";var j=e("./resolve"),O=e("./util"),I=e("./error_classes"),A=e("fast-json-stable-stringify"),C=e("../dotjs/validate"),k=O.ucs2length,L=e("fast-deep-equal"),z=I.Validation;function T(e,r,t){var a=s.call(this,e,r,t);return 0<=a?{index:a,compiling:!0}:{index:a=this._compilations.length,compiling:!(this._compilations[a]={schema:e,root:r,baseId:t})}}function q(e,r,t){var a=s.call(this,e,r,t);0<=a&&this._compilations.splice(a,1)}function s(e,r,t){for(var a=0;a",y=d?">":"<",g=void 0;if(m){var P=e.util.getData(p.$data,o,e.dataPathArr),E="exclusive"+s,w="exclType"+s,b="exclIsNumber"+s,S="' + "+(x="op"+s)+" + '";a+=" var schemaExcl"+s+" = "+P+"; ";var _;g=f;(_=_||[]).push(a+=" var "+E+"; var "+w+" = typeof "+(P="schemaExcl"+s)+"; if ("+w+" != 'boolean' && "+w+" != 'undefined' && "+w+" != 'number') { "),a="",!1!==e.createErrors?(a+=" { keyword: '"+(g||"_exclusiveLimit")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: {} ",!1!==e.opts.messages&&(a+=" , message: '"+f+" should be boolean' "),e.opts.verbose&&(a+=" , schema: validate.schema"+n+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),a+=" } "):a+=" {} ";var F=a;a=_.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+F+"]); ":" validate.errors = ["+F+"]; return false; ":" var err = "+F+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+=" } else if ( ",h&&(a+=" ("+t+" !== undefined && typeof "+t+" != 'number') || "),a+=" "+w+" == 'number' ? ( ("+E+" = "+t+" === undefined || "+P+" "+v+"= "+t+") ? "+u+" "+y+"= "+P+" : "+u+" "+y+" "+t+" ) : ( ("+E+" = "+P+" === true) ? "+u+" "+y+"= "+t+" : "+u+" "+y+" "+t+" ) || "+u+" !== "+u+") { var op"+s+" = "+E+" ? '"+v+"' : '"+v+"='; ",void 0===i&&(l=e.errSchemaPath+"/"+(g=f),t=P,h=m)}else{S=v;if((b="number"==typeof p)&&h){var x="'"+S+"'";a+=" if ( ",h&&(a+=" ("+t+" !== undefined && typeof "+t+" != 'number') || "),a+=" ( "+t+" === undefined || "+p+" "+v+"= "+t+" ? "+u+" "+y+"= "+p+" : "+u+" "+y+" "+t+" ) || "+u+" !== "+u+") { "}else{b&&void 0===i?(E=!0,l=e.errSchemaPath+"/"+(g=f),t=p,y+="="):(b&&(t=Math[d?"min":"max"](p,i)),p===(!b||t)?(E=!0,l=e.errSchemaPath+"/"+(g=f),y+="="):(E=!1,S+="="));x="'"+S+"'";a+=" if ( ",h&&(a+=" ("+t+" !== undefined && typeof "+t+" != 'number') || "),a+=" "+u+" "+y+" "+t+" || "+u+" !== "+u+") { "}}g=g||r,(_=_||[]).push(a),a="",!1!==e.createErrors?(a+=" { keyword: '"+(g||"_limit")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { comparison: "+x+", limit: "+t+", exclusive: "+E+" } ",!1!==e.opts.messages&&(a+=" , message: 'should be "+S+" ",a+=h?"' + "+t:t+"'"),e.opts.verbose&&(a+=" , schema: ",a+=h?"validate.schema"+n:""+i,a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),a+=" } "):a+=" {} ";F=a;return a=_.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+F+"]); ":" validate.errors = ["+F+"]; return false; ":" var err = "+F+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+=" } ",c&&(a+=" else { "),a}},{}],14:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a=" ",s=e.level,o=e.dataLevel,i=e.schema[r],n=e.schemaPath+e.util.getProperty(r),l=e.errSchemaPath+"/"+r,c=!e.opts.allErrors,u="data"+(o||""),h=e.opts.$data&&i&&i.$data;t=h?(a+=" var schema"+s+" = "+e.util.getData(i.$data,o,e.dataPathArr)+"; ","schema"+s):i,a+="if ( ",h&&(a+=" ("+t+" !== undefined && typeof "+t+" != 'number') || ");var d=r,f=f||[];f.push(a+=" "+u+".length "+("maxItems"==r?">":"<")+" "+t+") { "),a="",!1!==e.createErrors?(a+=" { keyword: '"+(d||"_limitItems")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { limit: "+t+" } ",!1!==e.opts.messages&&(a+=" , message: 'should NOT have ",a+="maxItems"==r?"more":"fewer",a+=" than ",a+=h?"' + "+t+" + '":""+i,a+=" items' "),e.opts.verbose&&(a+=" , schema: ",a+=h?"validate.schema"+n:""+i,a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),a+=" } "):a+=" {} ";var p=a;return a=f.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+p+"]); ":" validate.errors = ["+p+"]; return false; ":" var err = "+p+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+="} ",c&&(a+=" else { "),a}},{}],15:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a=" ",s=e.level,o=e.dataLevel,i=e.schema[r],n=e.schemaPath+e.util.getProperty(r),l=e.errSchemaPath+"/"+r,c=!e.opts.allErrors,u="data"+(o||""),h=e.opts.$data&&i&&i.$data;t=h?(a+=" var schema"+s+" = "+e.util.getData(i.$data,o,e.dataPathArr)+"; ","schema"+s):i,a+="if ( ",h&&(a+=" ("+t+" !== undefined && typeof "+t+" != 'number') || "),a+=!1===e.opts.unicode?" "+u+".length ":" ucs2length("+u+") ";var d=r,f=f||[];f.push(a+=" "+("maxLength"==r?">":"<")+" "+t+") { "),a="",!1!==e.createErrors?(a+=" { keyword: '"+(d||"_limitLength")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { limit: "+t+" } ",!1!==e.opts.messages&&(a+=" , message: 'should NOT be ",a+="maxLength"==r?"longer":"shorter",a+=" than ",a+=h?"' + "+t+" + '":""+i,a+=" characters' "),e.opts.verbose&&(a+=" , schema: ",a+=h?"validate.schema"+n:""+i,a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),a+=" } "):a+=" {} ";var p=a;return a=f.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+p+"]); ":" validate.errors = ["+p+"]; return false; ":" var err = "+p+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+="} ",c&&(a+=" else { "),a}},{}],16:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a=" ",s=e.level,o=e.dataLevel,i=e.schema[r],n=e.schemaPath+e.util.getProperty(r),l=e.errSchemaPath+"/"+r,c=!e.opts.allErrors,u="data"+(o||""),h=e.opts.$data&&i&&i.$data;t=h?(a+=" var schema"+s+" = "+e.util.getData(i.$data,o,e.dataPathArr)+"; ","schema"+s):i,a+="if ( ",h&&(a+=" ("+t+" !== undefined && typeof "+t+" != 'number') || ");var d=r,f=f||[];f.push(a+=" Object.keys("+u+").length "+("maxProperties"==r?">":"<")+" "+t+") { "),a="",!1!==e.createErrors?(a+=" { keyword: '"+(d||"_limitProperties")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { limit: "+t+" } ",!1!==e.opts.messages&&(a+=" , message: 'should NOT have ",a+="maxProperties"==r?"more":"fewer",a+=" than ",a+=h?"' + "+t+" + '":""+i,a+=" properties' "),e.opts.verbose&&(a+=" , schema: ",a+=h?"validate.schema"+n:""+i,a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),a+=" } "):a+=" {} ";var p=a;return a=f.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+p+"]); ":" validate.errors = ["+p+"]; return false; ":" var err = "+p+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+="} ",c&&(a+=" else { "),a}},{}],17:[function(e,r,t){"use strict";r.exports=function(e,r){var t=" ",a=e.schema[r],s=e.schemaPath+e.util.getProperty(r),o=e.errSchemaPath+"/"+r,i=!e.opts.allErrors,n=e.util.copy(e),l="";n.level++;var c="valid"+n.level,u=n.baseId,h=!0,d=a;if(d)for(var f,p=-1,m=d.length-1;p "+F+") { ";var $=c+"["+F+"]";d.schema=_,d.schemaPath=i+"["+F+"]",d.errSchemaPath=n+"/"+F,d.errorPath=e.util.getPathExpr(e.errorPath,F,e.opts.jsonPointers,!0),d.dataPathArr[v]=F;var R=e.validate(d);d.baseId=g,e.util.varOccurences(R,y)<2?t+=" "+e.util.varReplace(R,y,$)+" ":t+=" var "+y+" = "+$+"; "+R+" ",t+=" } ",l&&(t+=" if ("+p+") { ",f+="}")}if("object"==typeof P&&(e.opts.strictKeywords?"object"==typeof P&&0 "+o.length+") { for (var "+m+" = "+o.length+"; "+m+" < "+c+".length; "+m+"++) { ",d.errorPath=e.util.getPathExpr(e.errorPath,m,e.opts.jsonPointers,!0);$=c+"["+m+"]";d.dataPathArr[v]=m;R=e.validate(d);d.baseId=g,e.util.varOccurences(R,y)<2?t+=" "+e.util.varReplace(R,y,$)+" ":t+=" var "+y+" = "+$+"; "+R+" ",l&&(t+=" if (!"+p+") break; "),t+=" } } ",l&&(t+=" if ("+p+") { ",f+="}")}}else if(e.opts.strictKeywords?"object"==typeof o&&0 1e-"+e.opts.multipleOfPrecision+" ":" division"+s+" !== parseInt(division"+s+") ",a+=" ) ",h&&(a+=" ) ");var d=d||[];d.push(a+=" ) { "),a="",!1!==e.createErrors?(a+=" { keyword: 'multipleOf' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { multipleOf: "+t+" } ",!1!==e.opts.messages&&(a+=" , message: 'should be multiple of ",a+=h?"' + "+t:t+"'"),e.opts.verbose&&(a+=" , schema: ",a+=h?"validate.schema"+n:""+i,a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),a+=" } "):a+=" {} ";var f=a;return a=d.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+f+"]); ":" validate.errors = ["+f+"]; return false; ":" var err = "+f+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+="} ",c&&(a+=" else { "),a}},{}],30:[function(e,r,t){"use strict";r.exports=function(e,r){var t=" ",a=e.level,s=e.dataLevel,o=e.schema[r],i=e.schemaPath+e.util.getProperty(r),n=e.errSchemaPath+"/"+r,l=!e.opts.allErrors,c="data"+(s||""),u="errs__"+a,h=e.util.copy(e);h.level++;var d="valid"+h.level;if(e.opts.strictKeywords?"object"==typeof o&&0 1) { ";var f=e.schema.items&&e.schema.items.type,p=Array.isArray(f);if(!f||"object"==f||"array"==f||p&&(0<=f.indexOf("object")||0<=f.indexOf("array")))a+=" outer: for (;i--;) { for (j = i; j--;) { if (equal("+u+"[i], "+u+"[j])) { "+h+" = false; break outer; } } } ";else a+=" var itemIndices = {}, item; for (;i--;) { var item = "+u+"[i]; ",a+=" if ("+e.util["checkDataType"+(p?"s":"")](f,"item",!0)+") continue; ",p&&(a+=" if (typeof item == 'string') item = '\"' + item; "),a+=" if (typeof itemIndices[item] == 'number') { "+h+" = false; j = itemIndices[item]; break; } itemIndices[item] = i; } ";a+=" } ",d&&(a+=" } ");var m=m||[];m.push(a+=" if (!"+h+") { "),a="",!1!==e.createErrors?(a+=" { keyword: 'uniqueItems' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { i: i, j: j } ",!1!==e.opts.messages&&(a+=" , message: 'should NOT have duplicate items (items ## ' + j + ' and ' + i + ' are identical)' "),e.opts.verbose&&(a+=" , schema: ",a+=d?"validate.schema"+n:""+i,a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),a+=" } "):a+=" {} ";var v=a;a=m.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+v+"]); ":" validate.errors = ["+v+"]; return false; ":" var err = "+v+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+=" } ",c&&(a+=" else { ")}else c&&(a+=" if (true) { ");return a}},{}],38:[function(e,r,t){"use strict";r.exports=function(a,e){var r="",t=!0===a.schema.$async,s=a.util.schemaHasRulesExcept(a.schema,a.RULES.all,"$ref"),o=a.self._getId(a.schema);if(a.opts.strictKeywords){var i=a.util.schemaUnknownRules(a.schema,a.RULES.keywords);if(i){var n="unknown keyword: "+i;if("log"!==a.opts.strictKeywords)throw new Error(n);a.logger.warn(n)}}if(a.isTop&&(r+=" var validate = ",t&&(a.async=!0,r+="async "),r+="function(data, dataPath, parentData, parentDataProperty, rootData) { 'use strict'; ",o&&(a.opts.sourceCode||a.opts.processCode)&&(r+=" /*# sourceURL="+o+" */ ")),"boolean"==typeof a.schema||!s&&!a.schema.$ref){var l=a.level,c=a.dataLevel,u=a.schema[e="false schema"],h=a.schemaPath+a.util.getProperty(e),d=a.errSchemaPath+"/"+e,f=!a.opts.allErrors,p="data"+(c||""),m="valid"+l;if(!1===a.schema){a.isTop?f=!0:r+=" var "+m+" = false; ",(Z=Z||[]).push(r),r="",!1!==a.createErrors?(r+=" { keyword: 'false schema' , dataPath: (dataPath || '') + "+a.errorPath+" , schemaPath: "+a.util.toQuotedString(d)+" , params: {} ",!1!==a.opts.messages&&(r+=" , message: 'boolean schema is false' "),a.opts.verbose&&(r+=" , schema: false , parentSchema: validate.schema"+a.schemaPath+" , data: "+p+" "),r+=" } "):r+=" {} ";var v=r;r=Z.pop(),r+=!a.compositeRule&&f?a.async?" throw new ValidationError(["+v+"]); ":" validate.errors = ["+v+"]; return false; ":" var err = "+v+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; "}else r+=a.isTop?t?" return data; ":" validate.errors = null; return true; ":" var "+m+" = true; ";return a.isTop&&(r+=" }; return validate; "),r}if(a.isTop){var y=a.isTop;l=a.level=0,c=a.dataLevel=0,p="data";if(a.rootId=a.resolve.fullPath(a.self._getId(a.root.schema)),a.baseId=a.baseId||a.rootId,delete a.isTop,a.dataPathArr=[void 0],void 0!==a.schema.default&&a.opts.useDefaults&&a.opts.strictDefaults){var g="default is ignored in the schema root";if("log"!==a.opts.strictDefaults)throw new Error(g);a.logger.warn(g)}r+=" var vErrors = null; ",r+=" var errors = 0; ",r+=" if (rootData === undefined) rootData = data; "}else{l=a.level,p="data"+((c=a.dataLevel)||"");if(o&&(a.baseId=a.resolve.url(a.baseId,o)),t&&!a.async)throw new Error("async schema in sync schema");r+=" var errs_"+l+" = errors;"}m="valid"+l,f=!a.opts.allErrors;var P="",E="",w=a.schema.type,b=Array.isArray(w);if(w&&a.opts.nullable&&!0===a.schema.nullable&&(b?-1==w.indexOf("null")&&(w=w.concat("null")):"null"!=w&&(w=[w,"null"],b=!0)),b&&1==w.length&&(w=w[0],b=!1),a.schema.$ref&&s){if("fail"==a.opts.extendRefs)throw new Error('$ref: validation keywords used in schema at path "'+a.errSchemaPath+'" (see option extendRefs)');!0!==a.opts.extendRefs&&(s=!1,a.logger.warn('$ref: keywords ignored in schema at path "'+a.errSchemaPath+'"'))}if(a.schema.$comment&&a.opts.$comment&&(r+=" "+a.RULES.all.$comment.code(a,"$comment")),w){if(a.opts.coerceTypes)var S=a.util.coerceToTypes(a.opts.coerceTypes,w);var _=a.RULES.types[w];if(S||b||!0===_||_&&!G(_)){h=a.schemaPath+".type",d=a.errSchemaPath+"/type",h=a.schemaPath+".type",d=a.errSchemaPath+"/type";if(r+=" if ("+a.util[b?"checkDataTypes":"checkDataType"](w,p,!0)+") { ",S){var F="dataType"+l,x="coerced"+l;r+=" var "+F+" = typeof "+p+"; ","array"==a.opts.coerceTypes&&(r+=" if ("+F+" == 'object' && Array.isArray("+p+")) "+F+" = 'array'; "),r+=" var "+x+" = undefined; ";var $="",R=S;if(R)for(var D,j=-1,O=R.length-1;j= 0x80 (not a basic code point)","invalid-input":"Invalid input"},C=Math.floor,k=String.fromCharCode;function L(e){throw new RangeError(i[e])}function n(e,r){var t=e.split("@"),a="";return 1>1,e+=C(e/r);455C((A-s)/h))&&L("overflow"),s+=f*h;var p=d<=i?1:i+26<=d?26:d-i;if(fC(A/m)&&L("overflow"),h*=m}var v=t.length+1;i=q(s-u,v,0==u),C(s/v)>A-o&&L("overflow"),o+=C(s/v),s%=v,t.splice(s++,0,o)}return String.fromCodePoint.apply(String,t)}function c(e){var r=[],t=(e=z(e)).length,a=128,s=0,o=72,i=!0,n=!1,l=void 0;try{for(var c,u=e[Symbol.iterator]();!(i=(c=u.next()).done);i=!0){var h=c.value;h<128&&r.push(k(h))}}catch(e){n=!0,l=e}finally{try{!i&&u.return&&u.return()}finally{if(n)throw l}}var d=r.length,f=d;for(d&&r.push("-");fC((A-s)/w)&&L("overflow"),s+=(p-a)*w,a=p;var b=!0,S=!1,_=void 0;try{for(var F,x=e[Symbol.iterator]();!(b=(F=x.next()).done);b=!0){var $=F.value;if($A&&L("overflow"),$==a){for(var R=s,D=36;;D+=36){var j=D<=o?1:o+26<=D?26:D-o;if(R>6|192).toString(16).toUpperCase()+"%"+(63&r|128).toString(16).toUpperCase():"%"+(r>>12|224).toString(16).toUpperCase()+"%"+(r>>6&63|128).toString(16).toUpperCase()+"%"+(63&r|128).toString(16).toUpperCase()}function f(e){for(var r="",t=0,a=e.length;tA-Z\\x5E-\\x7E]",'[\\"\\\\]')),M=new RegExp(V,"g"),B=new RegExp("(?:(?:%[EFef][0-9A-Fa-f]%[0-9A-Fa-f][0-9A-Fa-f]%[0-9A-Fa-f][0-9A-Fa-f])|(?:%[89A-Fa-f][0-9A-Fa-f]%[0-9A-Fa-f][0-9A-Fa-f])|(?:%[0-9A-Fa-f][0-9A-Fa-f]))","g"),G=new RegExp(J("[^]","[A-Za-z0-9\\!\\$\\%\\'\\*\\+\\-\\^\\_\\`\\{\\|\\}\\~]","[\\.]",'[\\"]',K),"g"),Y=new RegExp(J("[^]",V,"[\\!\\$\\'\\(\\)\\*\\+\\,\\;\\:\\@]"),"g"),W=Y;function X(e){var r=f(e);return r.match(M)?r:e}var ee={scheme:"mailto",parse:function(e,r){var t=e,a=t.to=t.path?t.path.split(","):[];if(t.path=void 0,t.query){for(var s=!1,o={},i=t.query.split("&"),n=0,l=i.length;n%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i,u=/^(?:(?:http[s\u017F]?|ftp):\/\/)(?:(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+(?::(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?@)?(?:(?!10(?:\.[0-9]{1,3}){3})(?!127(?:\.[0-9]{1,3}){3})(?!169\.254(?:\.[0-9]{1,3}){2})(?!192\.168(?:\.[0-9]{1,3}){2})(?!172\.(?:1[6-9]|2[0-9]|3[01])(?:\.[0-9]{1,3}){2})(?:[1-9][0-9]?|1[0-9][0-9]|2[01][0-9]|22[0-3])(?:\.(?:1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])){2}(?:\.(?:[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-4]))|(?:(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)(?:\.(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)*(?:\.(?:(?:[KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){2,})))(?::[0-9]{2,5})?(?:\/(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?$/i,h=/^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i,d=/^(?:\/(?:[^~/]|~0|~1)*)*$/,f=/^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i,p=/^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/;function m(e){return a.copy(m[e="full"==e?"full":"fast"])}function v(e){var r=e.match(o);if(!r)return!1;var t,a=+r[2],s=+r[3];return 1<=a&&a<=12&&1<=s&&s<=(2!=a||((t=+r[1])%4!=0||t%100==0&&t%400!=0)?i[a]:29)}function y(e,r){var t=e.match(n);if(!t)return!1;var a=t[1],s=t[2],o=t[3];return(a<=23&&s<=59&&o<=59||23==a&&59==s&&60==o)&&(!r||t[5])}(r.exports=m).fast={date:/^\d\d\d\d-[0-1]\d-[0-3]\d$/,time:/^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)?$/i,"date-time":/^\d\d\d\d-[0-1]\d-[0-3]\d[t\s](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)$/i,uri:/^(?:[a-z][a-z0-9+-.]*:)(?:\/?\/)?[^\s]*$/i,"uri-reference":/^(?:(?:[a-z][a-z0-9+-.]*:)?\/?\/)?(?:[^\\\s#][^\s#]*)?(?:#[^\\\s]*)?$/i,"uri-template":c,url:u,email:/^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i,hostname:s,ipv4:/^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,ipv6:/^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,regex:w,uuid:h,"json-pointer":d,"json-pointer-uri-fragment":f,"relative-json-pointer":p},m.full={date:v,time:y,"date-time":function(e){var r=e.split(g);return 2==r.length&&v(r[0])&&y(r[1],!0)},uri:function(e){return P.test(e)&&l.test(e)},"uri-reference":/^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i,"uri-template":c,url:u,email:/^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,hostname:s,ipv4:/^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,ipv6:/^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,regex:w,uuid:h,"json-pointer":d,"json-pointer-uri-fragment":f,"relative-json-pointer":p};var g=/t|\s/i;var P=/\/|:/;var E=/[^\\]\\Z/;function w(e){if(E.test(e))return!1;try{return new RegExp(e),!0}catch(e){return!1}}},{"./util":10}],5:[function(e,r,t){"use strict";var $=e("./resolve"),R=e("./util"),D=e("./error_classes"),j=e("fast-json-stable-stringify"),O=e("../dotjs/validate"),I=R.ucs2length,A=e("fast-deep-equal"),C=D.Validation;function k(e,c,u,r){var d=this,f=this._opts,h=[void 0],p={},l=[],t={},m=[],a={},v=[],s=function(e,r,t){var a=L.call(this,e,r,t);return 0<=a?{index:a,compiling:!0}:{index:a=this._compilations.length,compiling:!(this._compilations[a]={schema:e,root:r,baseId:t})}}.call(this,e,c=c||{schema:e,refVal:h,refs:p},r),o=this._compilations[s.index];if(s.compiling)return o.callValidate=P;var y=this._formats,g=this.RULES;try{var i=E(e,c,u,r);o.validate=i;var n=o.callValidate;return n&&(n.schema=i.schema,n.errors=null,n.refs=i.refs,n.refVal=i.refVal,n.root=i.root,n.$async=i.$async,f.sourceCode&&(n.source=i.source)),i}finally{(function(e,r,t){var a=L.call(this,e,r,t);0<=a&&this._compilations.splice(a,1)}).call(this,e,c,r)}function P(){var e=o.validate,r=e.apply(this,arguments);return P.errors=e.errors,r}function E(e,r,t,a){var s=!r||r&&r.schema==e;if(r.schema!=c.schema)return k.call(d,e,r,t,a);var o,i=!0===e.$async,n=O({isTop:!0,schema:e,isRoot:s,baseId:a,root:r,schemaPath:"",errSchemaPath:"#",errorPath:'""',MissingRefError:D.MissingRef,RULES:g,validate:O,util:R,resolve:$,resolveRef:w,usePattern:_,useDefault:F,useCustomRule:x,opts:f,formats:y,logger:d.logger,self:d});n=Q(h,q)+Q(l,z)+Q(m,T)+Q(v,N)+n,f.processCode&&(n=f.processCode(n));try{o=new Function("self","RULES","formats","root","refVal","defaults","customRules","equal","ucs2length","ValidationError",n)(d,g,y,c,h,m,v,A,I,C),h[0]=o}catch(e){throw d.logger.error("Error compiling schema, function code:",n),e}return o.schema=e,o.errors=null,o.refs=p,o.refVal=h,o.root=s?o:r,i&&(o.$async=!0),!0===f.sourceCode&&(o.source={code:n,patterns:l,defaults:m}),o}function w(e,r,t){r=$.url(e,r);var a,s,o=p[r];if(void 0!==o)return S(a=h[o],s="refVal["+o+"]");if(!t&&c.refs){var i=c.refs[r];if(void 0!==i)return S(a=c.refVal[i],s=b(r,a))}s=b(r);var n=$.call(d,E,c,r);if(void 0===n){var l=u&&u[r];l&&(n=$.inlineRef(l,f.inlineRefs)?l:k.call(d,l,c,u,e))}if(void 0!==n)return h[p[r]]=n,S(n,s);delete p[r]}function b(e,r){var t=h.length;return h[t]=r,"refVal"+(p[e]=t)}function S(e,r){return"object"==typeof e||"boolean"==typeof e?{code:r,schema:e,inline:!0}:{code:r,$async:e&&!!e.$async}}function _(e){var r=t[e];return void 0===r&&(r=t[e]=l.length,l[r]=e),"pattern"+r}function F(e){switch(typeof e){case"boolean":case"number":return""+e;case"string":return R.toQuotedString(e);case"object":if(null===e)return"null";var r=j(e),t=a[r];return void 0===t&&(t=a[r]=m.length,m[t]=e),"default"+t}}function x(e,r,t,a){if(!1!==d._opts.validateSchema){var s=e.definition.dependencies;if(s&&!s.every(function(e){return Object.prototype.hasOwnProperty.call(t,e)}))throw new Error("parent schema must have all required keywords: "+s.join(","));var o=e.definition.validateSchema;if(o)if(!o(r)){var i="keyword schema is invalid: "+d.errorsText(o.errors);if("log"!=d._opts.validateSchema)throw new Error(i);d.logger.error(i)}}var n,l=e.definition.compile,c=e.definition.inline,u=e.definition.macro;if(l)n=l.call(d,r,t,a);else if(u)n=u.call(d,r,t,a),!1!==f.validateSchema&&d.validateSchema(n,!0);else if(c)n=c.call(d,a,e.keyword,r,t);else if(!(n=e.definition.validate))return;if(void 0===n)throw new Error('custom keyword "'+e.keyword+'"failed to compile');var h=v.length;return{code:"customRule"+h,validate:v[h]=n}}}function L(e,r,t){for(var a=0;a",y=d?">":"<",g=void 0;if(m){var P=e.util.getData(p.$data,o,e.dataPathArr),E="exclusive"+s,w="exclType"+s,b="exclIsNumber"+s,S="' + "+(x="op"+s)+" + '";a+=" var schemaExcl"+s+" = "+P+"; ";var _;g=f;(_=_||[]).push(a+=" var "+E+"; var "+w+" = typeof "+(P="schemaExcl"+s)+"; if ("+w+" != 'boolean' && "+w+" != 'undefined' && "+w+" != 'number') { "),a="",!1!==e.createErrors?(a+=" { keyword: '"+(g||"_exclusiveLimit")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: {} ",!1!==e.opts.messages&&(a+=" , message: '"+f+" should be boolean' "),e.opts.verbose&&(a+=" , schema: validate.schema"+n+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),a+=" } "):a+=" {} ";var F=a;a=_.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+F+"]); ":" validate.errors = ["+F+"]; return false; ":" var err = "+F+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+=" } else if ( ",h&&(a+=" ("+t+" !== undefined && typeof "+t+" != 'number') || "),a+=" "+w+" == 'number' ? ( ("+E+" = "+t+" === undefined || "+P+" "+v+"= "+t+") ? "+u+" "+y+"= "+P+" : "+u+" "+y+" "+t+" ) : ( ("+E+" = "+P+" === true) ? "+u+" "+y+"= "+t+" : "+u+" "+y+" "+t+" ) || "+u+" !== "+u+") { var op"+s+" = "+E+" ? '"+v+"' : '"+v+"='; ",void 0===i&&(l=e.errSchemaPath+"/"+(g=f),t=P,h=m)}else{S=v;if((b="number"==typeof p)&&h){var x="'"+S+"'";a+=" if ( ",h&&(a+=" ("+t+" !== undefined && typeof "+t+" != 'number') || "),a+=" ( "+t+" === undefined || "+p+" "+v+"= "+t+" ? "+u+" "+y+"= "+p+" : "+u+" "+y+" "+t+" ) || "+u+" !== "+u+") { "}else{b&&void 0===i?(E=!0,l=e.errSchemaPath+"/"+(g=f),t=p,y+="="):(b&&(t=Math[d?"min":"max"](p,i)),p===(!b||t)?(E=!0,l=e.errSchemaPath+"/"+(g=f),y+="="):(E=!1,S+="="));x="'"+S+"'";a+=" if ( ",h&&(a+=" ("+t+" !== undefined && typeof "+t+" != 'number') || "),a+=" "+u+" "+y+" "+t+" || "+u+" !== "+u+") { "}}g=g||r,(_=_||[]).push(a),a="",!1!==e.createErrors?(a+=" { keyword: '"+(g||"_limit")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { comparison: "+x+", limit: "+t+", exclusive: "+E+" } ",!1!==e.opts.messages&&(a+=" , message: 'should be "+S+" ",a+=h?"' + "+t:t+"'"),e.opts.verbose&&(a+=" , schema: ",a+=h?"validate.schema"+n:""+i,a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),a+=" } "):a+=" {} ";F=a;return a=_.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+F+"]); ":" validate.errors = ["+F+"]; return false; ":" var err = "+F+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+=" } ",c&&(a+=" else { "),a}},{}],14:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a=" ",s=e.level,o=e.dataLevel,i=e.schema[r],n=e.schemaPath+e.util.getProperty(r),l=e.errSchemaPath+"/"+r,c=!e.opts.allErrors,u="data"+(o||""),h=e.opts.$data&&i&&i.$data;t=h?(a+=" var schema"+s+" = "+e.util.getData(i.$data,o,e.dataPathArr)+"; ","schema"+s):i,a+="if ( ",h&&(a+=" ("+t+" !== undefined && typeof "+t+" != 'number') || ");var d=r,f=f||[];f.push(a+=" "+u+".length "+("maxItems"==r?">":"<")+" "+t+") { "),a="",!1!==e.createErrors?(a+=" { keyword: '"+(d||"_limitItems")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { limit: "+t+" } ",!1!==e.opts.messages&&(a+=" , message: 'should NOT have ",a+="maxItems"==r?"more":"fewer",a+=" than ",a+=h?"' + "+t+" + '":""+i,a+=" items' "),e.opts.verbose&&(a+=" , schema: ",a+=h?"validate.schema"+n:""+i,a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),a+=" } "):a+=" {} ";var p=a;return a=f.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+p+"]); ":" validate.errors = ["+p+"]; return false; ":" var err = "+p+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+="} ",c&&(a+=" else { "),a}},{}],15:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a=" ",s=e.level,o=e.dataLevel,i=e.schema[r],n=e.schemaPath+e.util.getProperty(r),l=e.errSchemaPath+"/"+r,c=!e.opts.allErrors,u="data"+(o||""),h=e.opts.$data&&i&&i.$data;t=h?(a+=" var schema"+s+" = "+e.util.getData(i.$data,o,e.dataPathArr)+"; ","schema"+s):i,a+="if ( ",h&&(a+=" ("+t+" !== undefined && typeof "+t+" != 'number') || "),a+=!1===e.opts.unicode?" "+u+".length ":" ucs2length("+u+") ";var d=r,f=f||[];f.push(a+=" "+("maxLength"==r?">":"<")+" "+t+") { "),a="",!1!==e.createErrors?(a+=" { keyword: '"+(d||"_limitLength")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { limit: "+t+" } ",!1!==e.opts.messages&&(a+=" , message: 'should NOT be ",a+="maxLength"==r?"longer":"shorter",a+=" than ",a+=h?"' + "+t+" + '":""+i,a+=" characters' "),e.opts.verbose&&(a+=" , schema: ",a+=h?"validate.schema"+n:""+i,a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),a+=" } "):a+=" {} ";var p=a;return a=f.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+p+"]); ":" validate.errors = ["+p+"]; return false; ":" var err = "+p+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+="} ",c&&(a+=" else { "),a}},{}],16:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a=" ",s=e.level,o=e.dataLevel,i=e.schema[r],n=e.schemaPath+e.util.getProperty(r),l=e.errSchemaPath+"/"+r,c=!e.opts.allErrors,u="data"+(o||""),h=e.opts.$data&&i&&i.$data;t=h?(a+=" var schema"+s+" = "+e.util.getData(i.$data,o,e.dataPathArr)+"; ","schema"+s):i,a+="if ( ",h&&(a+=" ("+t+" !== undefined && typeof "+t+" != 'number') || ");var d=r,f=f||[];f.push(a+=" Object.keys("+u+").length "+("maxProperties"==r?">":"<")+" "+t+") { "),a="",!1!==e.createErrors?(a+=" { keyword: '"+(d||"_limitProperties")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { limit: "+t+" } ",!1!==e.opts.messages&&(a+=" , message: 'should NOT have ",a+="maxProperties"==r?"more":"fewer",a+=" than ",a+=h?"' + "+t+" + '":""+i,a+=" properties' "),e.opts.verbose&&(a+=" , schema: ",a+=h?"validate.schema"+n:""+i,a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),a+=" } "):a+=" {} ";var p=a;return a=f.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+p+"]); ":" validate.errors = ["+p+"]; return false; ":" var err = "+p+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+="} ",c&&(a+=" else { "),a}},{}],17:[function(e,r,t){"use strict";r.exports=function(e,r){var t=" ",a=e.schema[r],s=e.schemaPath+e.util.getProperty(r),o=e.errSchemaPath+"/"+r,i=!e.opts.allErrors,n=e.util.copy(e),l="";n.level++;var c="valid"+n.level,u=n.baseId,h=!0,d=a;if(d)for(var f,p=-1,m=d.length-1;p "+F+") { ";var $=c+"["+F+"]";d.schema=_,d.schemaPath=i+"["+F+"]",d.errSchemaPath=n+"/"+F,d.errorPath=e.util.getPathExpr(e.errorPath,F,e.opts.jsonPointers,!0),d.dataPathArr[v]=F;var R=e.validate(d);d.baseId=g,e.util.varOccurences(R,y)<2?t+=" "+e.util.varReplace(R,y,$)+" ":t+=" var "+y+" = "+$+"; "+R+" ",t+=" } ",l&&(t+=" if ("+p+") { ",f+="}")}if("object"==typeof P&&(e.opts.strictKeywords?"object"==typeof P&&0 "+o.length+") { for (var "+m+" = "+o.length+"; "+m+" < "+c+".length; "+m+"++) { ",d.errorPath=e.util.getPathExpr(e.errorPath,m,e.opts.jsonPointers,!0);$=c+"["+m+"]";d.dataPathArr[v]=m;R=e.validate(d);d.baseId=g,e.util.varOccurences(R,y)<2?t+=" "+e.util.varReplace(R,y,$)+" ":t+=" var "+y+" = "+$+"; "+R+" ",l&&(t+=" if (!"+p+") break; "),t+=" } } ",l&&(t+=" if ("+p+") { ",f+="}")}}else if(e.opts.strictKeywords?"object"==typeof o&&0 1e-"+e.opts.multipleOfPrecision+" ":" division"+s+" !== parseInt(division"+s+") ",a+=" ) ",h&&(a+=" ) ");var d=d||[];d.push(a+=" ) { "),a="",!1!==e.createErrors?(a+=" { keyword: 'multipleOf' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { multipleOf: "+t+" } ",!1!==e.opts.messages&&(a+=" , message: 'should be multiple of ",a+=h?"' + "+t:t+"'"),e.opts.verbose&&(a+=" , schema: ",a+=h?"validate.schema"+n:""+i,a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),a+=" } "):a+=" {} ";var f=a;return a=d.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+f+"]); ":" validate.errors = ["+f+"]; return false; ":" var err = "+f+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+="} ",c&&(a+=" else { "),a}},{}],30:[function(e,r,t){"use strict";r.exports=function(e,r){var t=" ",a=e.level,s=e.dataLevel,o=e.schema[r],i=e.schemaPath+e.util.getProperty(r),n=e.errSchemaPath+"/"+r,l=!e.opts.allErrors,c="data"+(s||""),u="errs__"+a,h=e.util.copy(e);h.level++;var d="valid"+h.level;if(e.opts.strictKeywords?"object"==typeof o&&0 1) { ";var f=e.schema.items&&e.schema.items.type,p=Array.isArray(f);if(!f||"object"==f||"array"==f||p&&(0<=f.indexOf("object")||0<=f.indexOf("array")))a+=" outer: for (;i--;) { for (j = i; j--;) { if (equal("+u+"[i], "+u+"[j])) { "+h+" = false; break outer; } } } ";else a+=" var itemIndices = {}, item; for (;i--;) { var item = "+u+"[i]; ",a+=" if ("+e.util["checkDataType"+(p?"s":"")](f,"item",!0)+") continue; ",p&&(a+=" if (typeof item == 'string') item = '\"' + item; "),a+=" if (typeof itemIndices[item] == 'number') { "+h+" = false; j = itemIndices[item]; break; } itemIndices[item] = i; } ";a+=" } ",d&&(a+=" } ");var m=m||[];m.push(a+=" if (!"+h+") { "),a="",!1!==e.createErrors?(a+=" { keyword: 'uniqueItems' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { i: i, j: j } ",!1!==e.opts.messages&&(a+=" , message: 'should NOT have duplicate items (items ## ' + j + ' and ' + i + ' are identical)' "),e.opts.verbose&&(a+=" , schema: ",a+=d?"validate.schema"+n:""+i,a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),a+=" } "):a+=" {} ";var v=a;a=m.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+v+"]); ":" validate.errors = ["+v+"]; return false; ":" var err = "+v+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+=" } ",c&&(a+=" else { ")}else c&&(a+=" if (true) { ");return a}},{}],38:[function(e,r,t){"use strict";r.exports=function(a,e){var r="",t=!0===a.schema.$async,s=a.util.schemaHasRulesExcept(a.schema,a.RULES.all,"$ref"),o=a.self._getId(a.schema);if(a.opts.strictKeywords){var i=a.util.schemaUnknownRules(a.schema,a.RULES.keywords);if(i){var n="unknown keyword: "+i;if("log"!==a.opts.strictKeywords)throw new Error(n);a.logger.warn(n)}}if(a.isTop&&(r+=" var validate = ",t&&(a.async=!0,r+="async "),r+="function(data, dataPath, parentData, parentDataProperty, rootData) { 'use strict'; ",o&&(a.opts.sourceCode||a.opts.processCode)&&(r+=" /*# sourceURL="+o+" */ ")),"boolean"==typeof a.schema||!s&&!a.schema.$ref){var l=a.level,c=a.dataLevel,u=a.schema[e="false schema"],h=a.schemaPath+a.util.getProperty(e),d=a.errSchemaPath+"/"+e,f=!a.opts.allErrors,p="data"+(c||""),m="valid"+l;if(!1===a.schema){a.isTop?f=!0:r+=" var "+m+" = false; ",(Z=Z||[]).push(r),r="",!1!==a.createErrors?(r+=" { keyword: 'false schema' , dataPath: (dataPath || '') + "+a.errorPath+" , schemaPath: "+a.util.toQuotedString(d)+" , params: {} ",!1!==a.opts.messages&&(r+=" , message: 'boolean schema is false' "),a.opts.verbose&&(r+=" , schema: false , parentSchema: validate.schema"+a.schemaPath+" , data: "+p+" "),r+=" } "):r+=" {} ";var v=r;r=Z.pop(),r+=!a.compositeRule&&f?a.async?" throw new ValidationError(["+v+"]); ":" validate.errors = ["+v+"]; return false; ":" var err = "+v+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; "}else r+=a.isTop?t?" return data; ":" validate.errors = null; return true; ":" var "+m+" = true; ";return a.isTop&&(r+=" }; return validate; "),r}if(a.isTop){var y=a.isTop;l=a.level=0,c=a.dataLevel=0,p="data";if(a.rootId=a.resolve.fullPath(a.self._getId(a.root.schema)),a.baseId=a.baseId||a.rootId,delete a.isTop,a.dataPathArr=[void 0],void 0!==a.schema.default&&a.opts.useDefaults&&a.opts.strictDefaults){var g="default is ignored in the schema root";if("log"!==a.opts.strictDefaults)throw new Error(g);a.logger.warn(g)}r+=" var vErrors = null; ",r+=" var errors = 0; ",r+=" if (rootData === undefined) rootData = data; "}else{l=a.level,p="data"+((c=a.dataLevel)||"");if(o&&(a.baseId=a.resolve.url(a.baseId,o)),t&&!a.async)throw new Error("async schema in sync schema");r+=" var errs_"+l+" = errors;"}m="valid"+l,f=!a.opts.allErrors;var P="",E="",w=a.schema.type,b=Array.isArray(w);if(w&&a.opts.nullable&&!0===a.schema.nullable&&(b?-1==w.indexOf("null")&&(w=w.concat("null")):"null"!=w&&(w=[w,"null"],b=!0)),b&&1==w.length&&(w=w[0],b=!1),a.schema.$ref&&s){if("fail"==a.opts.extendRefs)throw new Error('$ref: validation keywords used in schema at path "'+a.errSchemaPath+'" (see option extendRefs)');!0!==a.opts.extendRefs&&(s=!1,a.logger.warn('$ref: keywords ignored in schema at path "'+a.errSchemaPath+'"'))}if(a.schema.$comment&&a.opts.$comment&&(r+=" "+a.RULES.all.$comment.code(a,"$comment")),w){if(a.opts.coerceTypes)var S=a.util.coerceToTypes(a.opts.coerceTypes,w);var _=a.RULES.types[w];if(S||b||!0===_||_&&!G(_)){h=a.schemaPath+".type",d=a.errSchemaPath+"/type",h=a.schemaPath+".type",d=a.errSchemaPath+"/type";if(r+=" if ("+a.util[b?"checkDataTypes":"checkDataType"](w,p,!0)+") { ",S){var F="dataType"+l,x="coerced"+l;r+=" var "+F+" = typeof "+p+"; ","array"==a.opts.coerceTypes&&(r+=" if ("+F+" == 'object' && Array.isArray("+p+")) "+F+" = 'array'; "),r+=" var "+x+" = undefined; ";var $="",R=S;if(R)for(var D,j=-1,O=R.length-1;j= 0x80 (not a basic code point)","invalid-input":"Invalid input"},C=Math.floor,k=String.fromCharCode;function L(e){throw new RangeError(i[e])}function n(e,r){var t=e.split("@"),a="";return 1>1,e+=C(e/r);455C((A-s)/h))&&L("overflow"),s+=f*h;var p=d<=i?1:i+26<=d?26:d-i;if(fC(A/m)&&L("overflow"),h*=m}var v=t.length+1;i=q(s-u,v,0==u),C(s/v)>A-o&&L("overflow"),o+=C(s/v),s%=v,t.splice(s++,0,o)}return String.fromCodePoint.apply(String,t)}function c(e){var r=[],t=(e=z(e)).length,a=128,s=0,o=72,i=!0,n=!1,l=void 0;try{for(var c,u=e[Symbol.iterator]();!(i=(c=u.next()).done);i=!0){var h=c.value;h<128&&r.push(k(h))}}catch(e){n=!0,l=e}finally{try{!i&&u.return&&u.return()}finally{if(n)throw l}}var d=r.length,f=d;for(d&&r.push("-");fC((A-s)/w)&&L("overflow"),s+=(p-a)*w,a=p;var b=!0,S=!1,_=void 0;try{for(var F,x=e[Symbol.iterator]();!(b=(F=x.next()).done);b=!0){var $=F.value;if($A&&L("overflow"),$==a){for(var R=s,D=36;;D+=36){var j=D<=o?1:o+26<=D?26:D-o;if(R>6|192).toString(16).toUpperCase()+"%"+(63&r|128).toString(16).toUpperCase():"%"+(r>>12|224).toString(16).toUpperCase()+"%"+(r>>6&63|128).toString(16).toUpperCase()+"%"+(63&r|128).toString(16).toUpperCase()}function f(e){for(var r="",t=0,a=e.length;tA-Z\\x5E-\\x7E]",'[\\"\\\\]')),M=new RegExp(V,"g"),B=new RegExp("(?:(?:%[EFef][0-9A-Fa-f]%[0-9A-Fa-f][0-9A-Fa-f]%[0-9A-Fa-f][0-9A-Fa-f])|(?:%[89A-Fa-f][0-9A-Fa-f]%[0-9A-Fa-f][0-9A-Fa-f])|(?:%[0-9A-Fa-f][0-9A-Fa-f]))","g"),G=new RegExp(J("[^]","[A-Za-z0-9\\!\\$\\%\\'\\*\\+\\-\\^\\_\\`\\{\\|\\}\\~]","[\\.]",'[\\"]',K),"g"),Y=new RegExp(J("[^]",V,"[\\!\\$\\'\\(\\)\\*\\+\\,\\;\\:\\@]"),"g"),W=Y;function X(e){var r=f(e);return r.match(M)?r:e}var ee={scheme:"mailto",parse:function(e,r){var t=e,a=t.to=t.path?t.path.split(","):[];if(t.path=void 0,t.query){for(var s=!1,o={},i=t.query.split("&"),n=0,l=i.length;n=8" + "node": ">=10" }, "files": [ "source", "index.d.ts" ], + "funding": "https://github.com/chalk/chalk?sponsor=1", "homepage": "https://github.com/chalk/chalk#readme", "keywords": [ "color", @@ -62,11 +63,15 @@ "bench": "matcha benchmark.js", "test": "xo && nyc ava && tsd" }, - "version": "3.0.0", + "version": "4.0.0", "xo": { "rules": { "unicorn/prefer-string-slice": "off", - "unicorn/prefer-includes": "off" + "unicorn/prefer-includes": "off", + "@typescript-eslint/member-ordering": "off", + "no-redeclare": "off", + "unicorn/string-content": "off", + "unicorn/better-regex": "off" } } } \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/chalk/readme.md b/tools/node_modules/eslint/node_modules/chalk/readme.md index 877cb93b7861f7..a0ca245604033b 100644 --- a/tools/node_modules/eslint/node_modules/chalk/readme.md +++ b/tools/node_modules/eslint/node_modules/chalk/readme.md @@ -9,11 +9,10 @@ > Terminal string styling done right -[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![npm dependents](https://badgen.net/npm/dependents/chalk)](https://www.npmjs.com/package/chalk?activeTab=dependents) [![Downloads](https://badgen.net/npm/dt/chalk)](https://www.npmjs.com/package/chalk) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) ![TypeScript-ready](https://img.shields.io/npm/types/chalk.svg) +[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![npm dependents](https://badgen.net/npm/dependents/chalk)](https://www.npmjs.com/package/chalk?activeTab=dependents) [![Downloads](https://badgen.net/npm/dt/chalk)](https://www.npmjs.com/package/chalk) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) ![TypeScript-ready](https://img.shields.io/npm/types/chalk.svg) [![run on repl.it](http://repl.it/badge/github/chalk/chalk)](https://repl.it/github/chalk/chalk) - ## Highlights - Expressive API @@ -24,8 +23,7 @@ - Doesn't extend `String.prototype` - Clean and focused - Actively maintained -- [Used by ~46,000 packages](https://www.npmjs.com/browse/depended/chalk) as of October 1, 2019 - +- [Used by ~50,000 packages](https://www.npmjs.com/browse/depended/chalk) as of January 1, 2020 ## Install @@ -33,7 +31,6 @@ $ npm install chalk ``` - ## Usage ```js @@ -107,7 +104,6 @@ console.log(chalk.green('Hello %s'), name); //=> 'Hello Sindre' ``` - ## API ### chalk.`